Исходный код
Классический метод исторического моделирования или параметрический VaR предполагают постоянную волатильность активов во времени. Однако на реальных рынках волатильность изменчива и имеет свойство группироваться (периоды высокой волатильности сменяются периодами затишья). Для решения этой проблемы в количественных финансах (Quantitative Finance) применяется связка модели GARCH(1,1) и симуляции Монте-Карло.
Перед тем как перейти к расчету рисков, часто требуется предварительно очистить рыночные данные от шума. В этом вам поможет Фильтр Калмана на Python: Сглаживание ценовых рядов с pykalman. Если же вы работаете с терабайтами тиковых данных для построения микроструктурных признаков, ознакомьтесь с руководством Как вычислить профиль объема (VPVR) на 50 ГБ данных с Dask.
Ниже представлен оптимизированный и векторизованный код на Python для расчета GARCH-Monte Carlo VaR. Мы используем библиотеку arch для калибровки модели и numpy для проведения высокоскоростных симуляций.
import numpy as np
import pandas as pd
from arch import arch_model
def calculate_garch_mc_var(returns: pd.Series, confidence_level: float = 0.99, horizon: int = 10, n_simulations: int = 50000) -> float:
# Очистка данных от NaN
clean_returns = returns.dropna()
# Подгонка модели GARCH(1,1)
model = arch_model(clean_returns, vol='Garch', p=1, q=1, dist='normal', rescale=False)
res = model.fit(disp='off')
# Извлечение параметров модели
mu = res.params['mu']
omega = res.params['omega']
alpha = res.params['alpha[1]']
beta = res.params['beta[1]']
# Последнее известное состояние (t = T)
last_var = res.conditional_volatility.iloc[-1] ** 2
last_resid = res.resid.iloc[-1]
# Массивы для симуляции: строки - симуляции, столбцы - шаги по времени (horizon)
sim_vars = np.zeros((n_simulations, horizon))
sim_resids = np.zeros((n_simulations, horizon))
sim_returns = np.zeros((n_simulations, horizon))
# Шаг 1: Симуляция для t + 1
z = np.random.normal(0, 1, n_simulations)
sim_vars[:, 0] = omega + alpha * (last_resid ** 2) + beta * last_var
sim_resids[:, 0] = np.sqrt(sim_vars[:, 0]) * z
sim_returns[:, 0] = mu + sim_resids[:, 0]
# Шаги от 2 до horizon
for t in range(1, horizon):
z = np.random.normal(0, 1, n_simulations)
# Волатильность на шаге t зависит от шока и волатильности на шаге t-1
sim_vars[:, t] = omega + alpha * (sim_resids[:, t-1] ** 2) + beta * sim_vars[:, t-1]
sim_resids[:, t] = np.sqrt(sim_vars[:, t]) * z
sim_returns[:, t] = mu + sim_resids[:, t]
# Суммируем логарифмические доходности по строкам для получения совокупной доходности за весь горизонт
cumulative_returns = np.sum(sim_returns, axis=1)
# Находим квантиль распределения доходностей
var_threshold = np.percentile(cumulative_returns, (1 - confidence_level) * 100)
# Возвращаем VaR как положительную величину возможных потерь
return -var_threshold
# Пример использования
if __name__ == '__main__':
# Генерируем синтетические данные (например, 1000 дней доходностей акций)
np.random.seed(42)
historical_returns = pd.Series(np.random.normal(0.0005, 0.015, 1000))
var_99_10d = calculate_garch_mc_var(historical_returns, confidence_level=0.99, horizon=10, n_simulations=100000)
print(f'10-дневный 99% GARCH-MC VaR: {var_99_10d:.4%}')
Разбор параметров
returns: Временной ряд исторических логарифмических доходностей актива. Важно использовать именно логарифмические доходности, так как они обладают свойством аддитивности во времени.confidence_level: Уровень доверия для расчета VaR. Значение0.99означает, что мы ищем максимальные потери, которые не будут превышены с вероятностью 99%.horizon: Временной горизонт прогнозирования (в торговых днях). Например,10означает оценку риска на 10 дней вперед.n_simulations: Количество генерируемых траекторий Монте-Карло. Чем больше симуляций, тем выше точность оценки «хвостов» распределения, но тем дольше выполняется расчет. Оптимально выбирать от 50 000 до 100 000.
Как запустить
Для запуска скрипта вам понадобятся библиотеки numpy, pandas и arch. Установите их через терминал:
pip install numpy pandas arch После установки импортируйте функцию calculate_garch_mc_var в свой проект, передайте в нее реальные исторические цены акций или индексов (предварительно преобразовав их в логарифмические доходности через np.log(prices / prices.shift(1))) и получите точную оценку рыночного риска.
Для высокочастотного трейдинга (HFT) и мониторинга инфраструктурных рисков в реальном времени расчет VaR часто интегрируют с системами сбора метрик. Подробнее об этом читайте в статье Интеграция InfluxDB и Grafana для HFT: Мониторинг Latency и Slippage.




