Назад к блогу

Как рассчитать волатильность валюты: руководство для разработчиков

V
Vlado Grigirov
September 07, 2026
Currency API Exchange Rates Volatility Historical Data Python Risk Management

Понимать, как рассчитать волатильность валюты, — это разница между мультивалютным приложением, которое спокойно переживает движение на 2% за ночь, и тем, которое будит вас звонком в три часа ночи. Волатильность — единственное число, которое говорит, как далеко способен уйти обменный курс, и почти каждое практическое решение в системе, работающей с FX, зависит от него: как долго котировка остаётся действительной, какой запас закладывать в цену, когда хеджировать и когда слать алерт.

Неприятность в том, что большинство руководств по расчёту волатильности написаны для акций. Они предполагают дневную цену закрытия, торговый год из 252 дней и одну однозначную котировку. На валютном рынке нет ничего из этого. Он торгуется 24 часа в сутки пять дней в неделю на децентрализованном внебиржевом рынке без официального закрытия, а «цена» EUR/USD зависит от того, в какую сторону вы котируете пару.

Это руководство разбирает саму математику, специфические для FX ловушки и рабочий код на Python и JavaScript, который считает реализованную волатильность по историческим данным обменных курсов.

Почему волатильность валют важна прямо сейчас

Сентябрь 2026 года — необычно удачный момент, чтобы задуматься о волатильности: рынок провёл бо́льшую часть года в подозрительно тихом режиме, а потом ненадолго перестал быть тихим.

Всё лето валюты развивающихся рынков были менее волатильны, чем валюты G7, — почти 200 торговых сессий подряд. Bloomberg отмечал, что эта серия стала бы самой длинной с 2000 года, если бы продолжилась. Кэрри-трейды с долларовым фондированием выдали самую длинную выигрышную серию с 2008 года, а популярная корзина из бразильского реала, колумбийского песо и турецкой лиры с фондированием в евро, по сообщениям, прибавила около 19% с начала года — лучший результат с 2005 года. Кэрри-стратегии работают только на спокойных рынках, так что их доходность сама по себе является сигналом о волатильности.

Затем, в начале сентября, иена подскочила более чем на 2% к доллару за одну сессию и достигла 155,28 — самого сильного уровня с начала августа, поскольку трейдеры готовились к новым интервенциям Министерства финансов Японии. Этому предшествовали совместная американо-японская интервенция 31 июля и рекордные ¥11,73 трлн (примерно $73 млрд) интервенций Минфина в апреле и мае, после того как USD/JPY пробил отметку 160.

В этом контрасте — весь урок. Средняя волатильность была низкой. Реализованная волатильность в один конкретный день оказалась огромной. Система, которая рассчитывала бы валютные буферы по скользящему годовому среднему, сильно ошиблась бы ровно в тот день, когда это было важно. Правильное — и непрерывное — измерение волатильности как раз и не даёт этому случиться.

Что на самом деле измеряет волатильность валюты

Волатильность — это стандартное отклонение доходностей, выраженное в годовом исчислении. Это не прогноз направления и не размер движения. Это мера разброса: насколько широко дневные доходности валютной пары рассеяны вокруг своего среднего.

Значение имеют две разновидности:

  • Реализованная (историческая) волатильность — считается назад по фактически наблюдавшимся курсам. Именно её вы можете вычислить сами из временного ряда, и именно о ней это руководство.
  • Подразумеваемая (implied) волатильность — извлекается из цен валютных опционов. Это взгляд рынка в будущее. Из спот-курсов её получить нельзя — нужен фид данных по опционам.

Большинству прикладных разработчиков — ценообразование, биллинг, казначейские дашборды, риск-алерты — реализованной волатильности достаточно, и считается она бесплатно, если исторические курсы у вас уже есть.

Грубая интуиция по числам: основные пары вроде EUR/USD в спокойные периоды обычно держались в диапазоне 5–10% годовых, а в стрессовые — 10–15%. Пары развивающихся рынков стабильно идут в два-три раза выше. Эти коридоры со временем смещаются — именно поэтому стоит измерять, а не предполагать.

Формула: логарифмические доходности, стандартное отклонение, аннуализация

Расчёт состоит из трёх шагов.

Шаг 1 — переведите курсы в логарифмические доходности.

r_t = ln(P_t / P_t-1)

Шаг 2 — возьмите стандартное отклонение этих доходностей по выбранному окну (используйте выборочное стандартное отклонение, деля на n − 1).

Шаг 3 — аннуализируйте, умножив на квадратный корень из числа наблюдений в году.

annualised_volatility = stdev(r) * sqrt(N)

Вместе:

σ_annual = stdev( ln(P_t / P_t-1) ) × √N

Почему логарифмические доходности, а не процентное изменение

Простое процентное изменение асимметрично: движение с 1,10 до 1,20 — это +9,09%, а обратный путь с 1,20 до 1,10 — уже −8,33%. Они должны быть равны и противоположны. У логарифмических доходностей так и есть: ln(1.20/1.10) и ln(1.10/1.20) различаются только знаком.

В FX это важнее, чем в акциях, из-за инверсии котировки. EUR/USD и USD/EUR описывают один и тот же рынок. Если считать волатильность по процентным изменениям, вы получите два слегка разных ответа в зависимости от того, в какую сторону котировали пару, — что очевидно неверно. Логарифмические доходности симметричны к инверсии: ln(1/x) = −ln(x), а стандартное отклонение знак игнорирует. Та же пара, та же волатильность, в любом направлении.

Логарифмические доходности к тому же аддитивны во времени, что делает агрегацию за несколько дней тривиальной.

Почему √N — и каким должно быть N для FX

Волатильность масштабируется как квадратный корень из времени, потому что дисперсия растёт линейно по времени (при стандартном предположении о случайном блуждании). Чтобы перевести дневную волатильность в годовую, умножьте на √(days per year).

Руководства по акциям используют 252 — примерное число торговых дней на биржах США. С FX всё иначе. Рынок работает непрерывно с вечера воскресенья до вечера пятницы — это примерно 260 будних сессий в году, минус горстка малоликвидных праздников. Большинство провайдеров данных по FX публикуют курсы каждый будний день, включая дни, когда собственный рынок той или иной страны закрыт.

Практическое правило: N должно соответствовать частоте дискретизации ваших данных, а не соглашению, заимствованному из другого класса активов.

Частота данныхN (коэффициент аннуализации)
Дневная (будни, соглашение FX)260
Дневная (биржевое соглашение, 252 дня)252
Недельная52
Месячная12
Часовая (24×5)~6 240
Разрыв между 252 и 260 меняет результат примерно на 1,6% относительно — несущественно для дашборда, существенно, если вы сравниваете своё число с числом вендора. Что бы вы ни выбрали, задокументируйте это и не меняйте.

Шаг 1: получите чистые исторические данные по обменным курсам

Волатильность хороша ровно настолько, насколько хорош ряд под ней. Загрузите дневной ряд одним вызовом эндпоинта /v1/timeseries:

curl -G "https://api.finexly.com/v1/timeseries" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d base=EUR \
  -d symbols=USD,JPY,GBP \
  -d start_date=2026-06-08 \
  -d end_date=2026-09-05

Ответ — словарь с ключами-датами:

{
  "success": true,
  "base": "EUR",
  "start_date": "2026-06-08",
  "end_date": "2026-09-05",
  "rates": {
    "2026-06-08": { "USD": 1.1421, "JPY": 178.62, "GBP": 0.8447 },
    "2026-06-09": { "USD": 1.1408, "JPY": 178.94, "GBP": 0.8451 }
  }
}

Один запрос, один ряд, никаких циклов пагинации. Полный справочник параметров — в документации Finexly API, а более широкие паттерны работы с диапазонами дат разобраны в нашем руководстве по API исторических обменных курсов.

Четыре проблемы с данными, уникальные для FX

Прежде чем доверять результату, разберитесь с ними. Ни одна не встречается в руководстве по волатильности акций, и все четыре исказят ваше число.

1. Официального закрытия не существует. FX децентрализован, никто не звонит в колокол. Разные провайдеры делают снимок в разные моменты — 22:00 UTC, полночь UTC, референсный фиксинг ЕЦБ в 14:15 CET или лондонский фиксинг WM/Reuters в 16:00. Смешивание времён снимка внутри одного ряда добавляет искусственную дисперсию. Выберите одно соглашение и никогда не смешивайте. Если вы не уверены, как устроен ваш провайдер, наш разбор того, откуда API обменных курсов берут данные, — хорошая отправная точка.

2. Выходные и разрывы. Рынок закрывается вечером в пятницу и открывается вечером в воскресенье. Доходность пятница→понедельник охватывает около 65 часов календарного времени, но в наивном расчёте считается одним «днём». Большинство практиков с этим мирятся и аннуализируют по числу будних дней — это стандартный подход, — но важна последовательность. Не заполняйте выходные протянутыми вперёд курсами: серия одинаковых значений искусственно занизит стандартное отклонение.

3. Асимметрия базовой валюты. Как сказано выше, логарифмические доходности решают проблему инверсии математически. Но вам всё равно нужно решить, в какой базе вы измеряете риск. Волатильность вашей долларовой экспозиции, измеренная в EUR, — это другой бизнес-вопрос, чем та же пара, измеренная в USD, даже если число выходит одинаковым. Явно фиксируйте нумерарий.

4. Триангулированные кросс-курсы. Если ваш провайдер выводит, скажем, SEK/NOK делением SEK/USD на NOK/USD, результат наследует шум обеих ног и любое расхождение по времени между ними. Синтетические кроссы могут показывать заметно более высокую волатильность, чем напрямую котируемый рынок. Наше руководство по кросс-курсам объясняет, когда триангуляция безопасна, а когда нет.

Следите и за точностью. Округление пар с JPY до двух знаков перед расчётом доходностей превращает мелкие движения в нули и смещает волатильность вниз — общее правило описано в материале про округление валют и знаки после запятой. Храните полную точность, округляйте только при отображении.

Шаг 2: расчёт реализованной волатильности на Python

Вот полная реализация с минимумом зависимостей. Она использует requests и стандартную библиотеку — pandas не нужен.

import math
import statistics
import requests

FX_DAYS_PER_YEAR = 260  # weekday sessions; use 252 for the equity convention


def fetch_series(base, symbol, start, end, api_key):
    url = "https://api.finexly.com/v1/timeseries"
    params = {
        "base": base,
        "symbols": symbol,
        "start_date": start,
        "end_date": end,
    }
    headers = {"Authorization": "Bearer " + api_key}
    response = requests.get(url, params=params, headers=headers, timeout=10)
    response.raise_for_status()
    return response.json()["rates"]


def log_returns(rates, symbol):
    """Ordered log returns from a date-keyed rates map."""
    dates = sorted(rates.keys())
    series = [rates[d][symbol] for d in dates]
    return [
        math.log(series[i] / series[i - 1])
        for i in range(1, len(series))
        if series[i] > 0 and series[i - 1] > 0
    ]


def annualised_volatility(returns, periods_per_year=FX_DAYS_PER_YEAR):
    if len(returns) < 2:
        raise ValueError("need at least two returns")
    return statistics.stdev(returns) * math.sqrt(periods_per_year)


rates = fetch_series("EUR", "USD", "2026-06-08", "2026-09-05", "YOUR_API_KEY")
returns = log_returns(rates, "USD")

vol = annualised_volatility(returns)
print("Observations:      {}".format(len(returns)))
print("Daily volatility:  {:.4%}".format(vol / math.sqrt(FX_DAYS_PER_YEAR)))
print("Annual volatility: {:.2%}".format(vol))

statistics.stdev — это выборочное стандартное отклонение (знаменатель n − 1), именно то, что нужно. Если перейдёте на NumPy, помните, что numpy.std по умолчанию считает генеральную версию — передайте ddof=1, чтобы результаты совпали.

Две проверки, которые стоит оставить в продакшен-коде: пропускать неположительные курсы перед взятием логарифма и отказываться возвращать число для окна со слишком малым количеством наблюдений. 30-дневная волатильность, посчитанная по девяти точкам, — это не 30-дневная волатильность.

Шаг 3: тот же расчёт на JavaScript

Численная библиотека здесь тоже не нужна.

const FX_DAYS_PER_YEAR = 260;

async function fetchSeries(base, symbol, start, end, apiKey) {
  const url = new URL('https://api.finexly.com/v1/timeseries');
  url.searchParams.set('base', base);
  url.searchParams.set('symbols', symbol);
  url.searchParams.set('start_date', start);
  url.searchParams.set('end_date', end);

  const res = await fetch(url, {
    headers: { Authorization: `Bearer ${apiKey}` },
  });
  if (!res.ok) throw new Error(`Finexly returned ${res.status}`);
  const body = await res.json();
  return body.rates;
}

function logReturns(rates, symbol) {
  const dates = Object.keys(rates).sort();
  const series = dates.map((d) => rates[d][symbol]);
  const out = [];
  for (let i = 1; i < series.length; i += 1) {
    if (series[i] > 0 && series[i - 1] > 0) {
      out.push(Math.log(series[i] / series[i - 1]));
    }
  }
  return out;
}

function annualisedVolatility(returns, periodsPerYear = FX_DAYS_PER_YEAR) {
  if (returns.length < 2) throw new Error('need at least two returns');
  const mean = returns.reduce((a, b) => a + b, 0) / returns.length;
  const variance =
    returns.reduce((acc, r) => acc + (r - mean) ** 2, 0) / (returns.length - 1);
  return Math.sqrt(variance) * Math.sqrt(periodsPerYear);
}

const rates = await fetchSeries('EUR', 'USD', '2026-06-08', '2026-09-05', 'YOUR_API_KEY');
const vol = annualisedVolatility(logReturns(rates, 'USD'));
console.log(`Annualised volatility: ${(vol * 100).toFixed(2)}%`);

Обратите внимание на знаменатель (returns.length - 1) — та же поправка на выборочную дисперсию, что и в версии на Python.

Скользящая волатильность и выявление смены режима

Одно число по фиксированному окну почти ничего не говорит о том, когда стало шумно. Скользящая волатильность говорит — и именно её вы на самом деле хотите видеть на дашборде.

def rolling_volatility(rates, symbol, window=30,
                       periods_per_year=FX_DAYS_PER_YEAR):
    dates = sorted(rates.keys())
    series = [rates[d][symbol] for d in dates]
    returns = [math.log(series[i] / series[i - 1]) for i in range(1, len(series))]
    return_dates = dates[1:]

    out = []
    for i in range(window - 1, len(returns)):
        chunk = returns[i - window + 1:i + 1]
        out.append((
            return_dates[i],
            statistics.stdev(chunk) * math.sqrt(periods_per_year),
        ))
    return out


for date, vol in rolling_volatility(rates, "USD", window=30)[-5:]:
    print("{}  {:.2%}".format(date, vol))

Выбор окна — это компромисс, а не догма:

  • 10 дней — очень отзывчиво, очень шумно. Хорошо для алертов, плохо для ценообразования.
  • 30 дней — распространённый вариант по умолчанию. Реагирует за несколько сессий, но не дёргается.
  • 90 дней — гладко и стабильно. Хорошо для коэффициентов хеджирования и ценовых буферов.

Практический сигнал о смене режима — отношение волатильностей: разделите 10-дневную волатильность на 90-дневную. Устойчивые значения выше примерно 1,5 означают, что краткосрочный разброс заметно обогнал более длинную базу. Применительно к парам с иеной в описанные выше эпизоды интервенций это отношение резко подскакивает, тогда как 90-дневное число почти не двигается — в чём и суть. Длинные окна прячут события, короткие их находят.

Если планируете гонять это непрерывно по многим парам, сначала прочитайте наши заметки про кэширование и обработку ошибок для валютных API. Исторические дневные курсы неизменны после публикации, поэтому кэшируются бессрочно — пересчитывайте только самое свежее окно, а не выкачивайте год истории при каждой загрузке страницы. На странице тарифных планов видно, как объёмы запросов распределены по уровням.

Как превратить число волатильности в решение

Посчитать волатильность легко. Ценность — в том, как её использовать. Четыре конкретных применения:

  1. Окна действия котировки. Цена, которую вы показываете клиенту, — это короткий опцион, который вы ему выписали. Ожидаемый дрейф за период удержания в t дней составляет примерно σ_annual × √(t / 260). При волатильности 8% годовых суточная котировка несёт около 0,5% ожидаемого дрейфа, при 20% — ближе к 1,2%. Сокращайте TTL при росте волатильности вместо вечных фиксированных 15 минут.
  1. Ценовые буферы. Вместо зашитой валютной маржи в 2% масштабируйте её: buffer = k × σ_annual × √(settlement_days / 260). Буфер автоматически расширяется в стрессовых режимах и сужается, когда рынки успокаиваются, — это позволяет оставаться конкурентоспособным, не принимая скрытый риск.
  1. Триггеры хеджирования. Риск — это не сама экспозиция, а экспозиция, умноженная на волатильность. Экспозиция в $2 млн к паре с волатильностью 4% — меньшая проблема, чем $400 тыс. в паре с волатильностью 30%. Ранжируйте решения о хеджировании по exposure × σ, а не по номиналу. Наше руководство по валютному хеджированию разбирает инструменты, а число волатильности подсказывает, что вообще заслуживает хеджа.
  1. Обнаружение аномалий. Переводите каждое новое дневное движение в z-оценку относительно скользящего 30-дневного стандартного отклонения и подавайте алерт за пределами ±3. Это ловит и настоящие рыночные события, и плохие данные: устаревший фид или неверно триангулированный кросс обычно заявляет о себе неправдоподобным выбросом раньше, чем кто-то заметит его в отчёте.

Чтобы выражать эти движения в привычных трейдерам единицах, а не в процентах, посмотрите, что такое пункт (pip).

Типичные ошибки

  • Использование процентного изменения вместо логарифмических доходностей. Вносит асимметрию и делает ответ зависимым от направления котировки.
  • Использование генерального стандартного отклонения. numpy.std() без ddof=1 занижает волатильность, особенно сильно на коротких окнах.
  • Протягивание значений на выходные и праздники. Повторяющиеся значения — это дни с нулевой доходностью, которые механически тянут волатильность вниз.
  • Аннуализация с неверным N. Недельные данные, аннуализированные с 260 вместо 52, дают число примерно в 2,2 раза больше нужного.
  • Сравнение волатильностей, посчитанных по разному времени снимка. Два провайдера, два времени фиксинга, два несопоставимых числа.
  • Публикация одной годовой цифры и объявление её риском. Волатильность кластеризуется. Спокойные месяцы и бурные недели усредняются в невнятное число, которое не описывает ни то ни другое. Всегда публикуйте скользящий ряд рядом с заголовочным значением.
  • Предположение, что низкая волатильность означает низкий риск. Тихие, дружелюбные к кэрри-трейду режимы 2026 года были тихими ровно до того момента, как заголовки об интервенциях сдвинули иену на 2% за сессию. Низкая реализованная волатильность — это описание недавнего прошлого, а не обещание на следующую неделю.

Часто задаваемые вопросы

Какой уровень волатильности для валютной пары считается нормальным?

Основные пары, такие как EUR/USD и GBP/USD, исторически держались примерно на 5–10% годовых в спокойных условиях и на 10–15% под стрессом. Пары развивающихся рынков обычно в два-три раза выше. Вместо опоры на эмпирические правила посчитайте 90-дневную скользящую волатильность для интересующих вас пар и используйте собственную базу — уровни смещаются вместе с режимом.

Использовать 252 или 260 торговых дней для аннуализации волатильности FX?

260 подходит лучше, потому что валютный рынок торгуется каждый будний день, а не следует календарю одной биржи. 252 — биржевое соглашение, и его всё равно широко применяют. Разница составляет около 1,6% относительно, так что важнее выбрать одно значение, задокументировать его и последовательно применять везде, где вы сравниваете числа.

Можно ли рассчитать подразумеваемую волатильность через API обменных курсов?

Нет. Подразумеваемая волатильность выводится из цен валютных опционов и требует фида данных по опционам. Из спот-ряда или ряда исторических курсов вы можете посчитать реализованную волатильность. Для ценообразования, порогов хеджирования и алертов в прикладном коде реализованная волатильность обычно и есть подходящая мера.

Сколько исторических данных нужно?

Как минимум на одно наблюдение больше длины окна — но это даст неустойчивую оценку. Практический минимум: 30 наблюдений для 30-дневного окна, и лучше выгрузить хотя бы год истории, чтобы сравнивать текущее значение с более длинной базой. Эндпоинт /v1/timeseries возвращает произвольный диапазон дат одним запросом.

Почему моё число волатильности отличается от числа провайдера данных?

Почти всегда причина одна из четырёх: другой коэффициент аннуализации (252 против 260), генеральное вместо выборочного стандартного отклонения, другое время снимка дневного курса или простые доходности вместо логарифмических. Проверьте эти четыре пункта, прежде чем считать данные неверными.

Предсказывает ли волатильность направление движения валюты?

Нет. Волатильность измеряет разброс, а не направление. От пары с волатильностью 20% годовых ожидается большое движение, но расчёт ничего не говорит о том, вверх оно будет или вниз. Используйте её, чтобы оценивать размер риска, а не чтобы делать ставку на направление.


Готовы считать волатильность на живых данных? Получите бесплатный API-ключ Finexly — кредитная карта не нужна. Вы получаете доступ к текущим и историческим курсам для 170+ валют, 1000 бесплатных запросов в месяц и эндпоинт /v1/timeseries, который возвращает полный диапазон дат за один вызов. Начните с бесплатного API обменных курсов и переходите на старший тариф по мере роста потребностей в данных.

Vlado Grigirov

Senior Currency Markets Analyst & Financial Strategist

Vlado Grigirov is a senior currency markets analyst and financial strategist with over 14 years of experience in foreign exchange markets, cross-border finance, and currency risk management. He has wo...

View full profile →