Перейти к содержимому

Глава 145: Физически-информированные нейронные сети для модели процентных ставок Халла-Уайта

Обзор

Модель Халла-Уайта (также известная как расширенная модель Васичека) является одной из наиболее широко используемых однофакторных моделей коротких ставок в количественных финансах. Она описывает эволюцию мгновенной короткой ставки и может быть точно калибрована к начальной структуре процентных ставок. В этой главе мы строим физически-информированную нейронную сеть (PINN), которая встраивает уравнение в частных производных (PDE) Халла-Уайта непосредственно в функцию потерь нейронной сети, обеспечивая бессеточное, дифференцируемое ценообразование облигаций с автоматической подгонкой к структуре ставок.

Почему Халл-Уайт + PINN?

Модель Халла-Уайта

Модель Халла-Уайта описывает динамику короткой ставки при риск-нейтральной мере:

dr(t) = [theta(t) - a * r(t)] dt + sigma * dW(t)

где:

  • r(t) — мгновенная короткая ставка в момент t
  • a > 0 — скорость возврата к среднему
  • theta(t) — зависящий от времени дрейф (калибруется для соответствия начальной кривой доходности)
  • sigma > 0 — волатильность короткой ставки
  • W(t) — стандартное броуновское движение при риск-нейтральной мере

Ключевые свойства

  1. Возврат к среднему: Процентные ставки притягиваются к долгосрочному уровню theta(t)/a, не позволяя ставкам уходить в экстремальные значения
  2. Аналитическая решаемость: Существуют замкнутые формулы для цен бескупонных облигаций, кэпов, флоров и свопционов
  3. Подгонка к структуре ставок: Функция theta(t) может быть подобрана для точного соответствия любой наблюдаемой кривой доходности
  4. Нормальное распределение: Короткая ставка r(t) имеет нормальное распределение (может принимать отрицательные значения, что реалистично для современных рынков)

Почему PINN?

Традиционные численные методы (конечные разности, триномиальные деревья) требуют:

  • Построения сетки и управления граничными условиями
  • Интерполяции между узлами сетки
  • Отдельных шагов калибровки и ценообразования

Преимущества PINN:

  • Бессеточный метод: не требуется дискретизация
  • Дифференцируемость: греки (чувствительности) получаются бесплатно через автоматическое дифференцирование
  • Гибкость: легко расширяется на многомерные случаи
  • Ускорение на GPU: естественный параллелизм через мини-батчи
  • Единый процесс: калибровка и ценообразование в одной оптимизации

Математические основы

Уравнение ценообразования облигаций

Для бескупонной облигации P(r, t; T) с погашением в момент T модель Халла-Уайта даёт уравнение в частных производных:

dP/dt + [theta(t) - a*r] * dP/dr + (1/2) * sigma^2 * d^2P/dr^2 - r*P = 0

с терминальным условием:

P(r, T; T) = 1 для всех r

Аналитическое решение

Модель Халла-Уайта допускает замкнутую формулу ценообразования:

P(r, t; T) = A(t, T) * exp(-B(t, T) * r)

где:

B(t, T) = (1 - exp(-a*(T-t))) / a
A(t, T) = (P_M(0, T) / P_M(0, t)) * exp(
B(t,T) * f_M(0, t) - (sigma^2 / (4*a)) * (1 - exp(-2*a*t)) * B(t,T)^2
)

Здесь:

  • P_M(0, t) — рыночный коэффициент дисконтирования в момент 0 для срока t
  • f_M(0, t) — рыночная мгновенная форвардная ставка в момент 0 для срока t

Зависящий от времени дрейф

Функция theta(t) определяется начальной структурой ставок:

theta(t) = df_M(0, t)/dt + a * f_M(0, t) + (sigma^2 / (2*a)) * (1 - exp(-2*a*t))

Это гарантирует, что модель точно воспроизводит наблюдаемую кривую доходности в момент 0.

Архитектура PINN

Структура сети

Входной слой: (r, t, T) -- 2+1 нейрон
|
Скрытый слой 1: 64 нейрона, активация Tanh
|
Скрытый слой 2: 64 нейрона, активация Tanh
|
Скрытый слой 3: 64 нейрона, активация Tanh
|
Скрытый слой 4: 32 нейрона, активация Tanh
|
Выходной слой: P(r, t) -- 1 нейрон (цена облигации)

Компоненты функции потерь

Общая функция потерь — это взвешенная комбинация нескольких компонент:

L_total = w_pde * L_pde + w_ic * L_ic + w_bc * L_bc + w_data * L_data

1. Потери от невязки PDE

# Автоматическое дифференцирование для вычисления частных производных
P = network(r, t)
P_t = d(P)/d(t) # производная по времени
P_r = d(P)/d(r) # производная по ставке
P_rr = d^2(P)/d(r^2) # вторая производная по ставке
# Невязка PDE Халла-Уайта
residual = P_t + (theta_t - a * r) * P_r + 0.5 * sigma**2 * P_rr - r * P
L_pde = mean(residual^2)

2. Потери от терминального условия

# При погашении T цена облигации должна равняться 1
P_T = network(r_samples, T)
L_ic = mean((P_T - 1.0)^2)

3. Потери от граничных условий

# При r -> +inf, P -> 0 (для конечного T)
P_high = network(r_max, t_samples)
L_bc = mean(P_high^2)

4. Потери от подгонки к структуре ставок

# Соответствие наблюдаемым рыночным ценам облигаций при t=0
P_market = market_discount_factors
P_model = network(r0, t_maturities)
L_data = mean((P_model - P_market)^2)

Применение к криптовалютным ставкам кредитования

Ставки финансирования Bybit как прокси для короткой ставки

Криптовалютные бессрочные фьючерсы имеют ставки финансирования, которые служат аналогом краткосрочных процентных ставок:

Ставка финансирования = Индекс премии + clamp(Ставка% - Индекс премии, -0.05%, 0.05%)

Эти ставки финансирования демонстрируют:

  • Возврат к среднему (обусловленный арбитражем)
  • Стохастическую волатильность (зависящую от режима)
  • Зависящий от времени дрейф (сдвиги рыночных настроений)

Это делает модель Халла-Уайта применимой к криптовалютным рынкам.

Получение данных

import requests
def fetch_bybit_funding_rates(symbol="BTCUSDT", limit=200):
"""Получение исторических ставок финансирования с Bybit."""
url = "https://api.bybit.com/v5/market/funding/history"
params = {
"category": "linear",
"symbol": symbol,
"limit": limit
}
response = requests.get(url, params=params)
data = response.json()
rates = []
for item in data["result"]["list"]:
rates.append({
"timestamp": int(item["fundingRateTimestamp"]),
"rate": float(item["fundingRate"])
})
return rates

Процентные деривативы

Кэпы и флоры

Процентный кэп — это серия кэплетов, каждый из которых выплачивает:

max(L(T_i, T_{i+1}) - K, 0) * delta * N

где L — ставка LIBOR/референсная ставка, K — страйк, delta — доля дневного подсчёта, N — номинал.

Свопционы

Свопцион даёт право войти в процентный своп в будущую дату. При модели Халла-Уайта разложение Джамшидиана выражает свопцион как портфель опционов на облигации.

Сравнение с методами деревьев

Триномиальное дерево

ХарактеристикаТриномиальное деревоPINN
СеткаДа (N шагов x M узлов)Нет (бессеточный)
ГрекиКонечные разности (шумные)Автодифф (точные)
ИнтерполяцияНужна между узламиНепрерывность по построению
КалибровкаОтдельный шагИнтегрирована в обучение
МногомерностьПроклятие размерностиМасштабируется лучше
Ускорение GPUОграниченоЕстественное

Примеры кода

Быстрый старт: обучение и ценообразование

from python.hull_white_pinn import HullWhitePINN
from python.train import train_pinn
from python.analytical import HullWhiteAnalytical
# Параметры модели
a = 0.1 # скорость возврата к среднему
sigma = 0.01 # волатильность
r0 = 0.03 # текущая короткая ставка
T_max = 10.0 # максимальный срок (лет)
# Создание и обучение PINN
model = HullWhitePINN(a=a, sigma=sigma)
train_pinn(model=model, r0=r0, a=a, sigma=sigma, T_max=T_max, epochs=5000)
# Сравнение с аналитикой
hw = HullWhiteAnalytical(a=a, sigma=sigma)
for T in [0.5, 1.0, 2.0, 5.0, 10.0]:
price_pinn = model.predict(r0, 0.0, T)
price_analytical = hw.bond_price(r0, 0.0, T)
print(f"T={T:.1f} PINN={price_pinn:.6f} Аналитика={price_analytical:.6f}")

Криптовалютные ставки финансирования

from python.data_loader import load_bybit_funding_rates
from python.calibration import calibrate_hull_white
# Загрузка данных ставок финансирования с Bybit
rates = load_bybit_funding_rates(symbol="BTCUSDT", days=90)
# Калибровка параметров Халла-Уайта
params = calibrate_hull_white(rates)
print(f"Возврат к среднему: a={params['a']:.4f}")
print(f"Волатильность: sigma={params['sigma']:.6f}")
print(f"Долгосрочная ставка: theta/a={params['long_run_mean']:.6f}")

Управление рисками

Дюрация и выпуклость из PINN

С автоматическим дифференцированием получаем точные чувствительности:

def compute_greeks(model, r, t, T):
"""Вычисление чувствительностей цены облигации."""
greeks = model.compute_greeks(r, t, T)
# duration -- дюрация (чувствительность к ставке)
# convexity -- выпуклость (вторая производная)
# theta -- временной распад
return greeks

Value at Risk (VaR)

Используя распределение ставок Халла-Уайта и ценообразование PINN:

def compute_var(model, r0, t, T, a, sigma, confidence=0.99):
"""Вычисление Value at Risk для позиции в облигации."""
# При Халле-Уайте r(t+h) имеет нормальное распределение
# VaR = P(r0) - P(r_shock)
pass

Выводы

Ключевые результаты

  1. Модель Халла-Уайта — золотой стандарт однофакторных моделей коротких ставок
  2. PINN встраивает PDE непосредственно в функцию потерь, обеспечивая физическую согласованность
  3. Автоматическое дифференцирование даёт точные греки без конечных разностей
  4. Бессеточный подход избегает артефактов дискретизации
  5. Криптовалютные ставки финансирования демонстрируют возврат к среднему, подходящий для модели Халла-Уайта
  6. Пакетное ценообразование на GPU даёт PINN преимущество в скорости для больших портфелей

Когда использовать этот подход

  • PINN: пакетное ценообразование, гладкие греки, гибкие расширения, ускорение GPU
  • Аналитика: скорость единичной цены, гарантированная сходимость, интерпретируемость
  • Деревья: зависящие от пути продукты, досрочное исполнение, простота

Структура файлов

145_pinn_hull_white_rates/
├── README.md # Английская версия
├── README.ru.md # Этот файл
├── readme.simple.md # Простое объяснение (английский)
├── readme.simple.ru.md # Простое объяснение (русский)
├── python/
│ ├── __init__.py
│ ├── requirements.txt
│ ├── hull_white_pinn.py # Архитектура PINN
│ ├── train.py # Цикл обучения
│ ├── data_loader.py # Данные Treasury + Bybit
│ ├── analytical.py # Аналитическое ценообразование
│ ├── calibration.py # Калибровка модели
│ ├── derivatives.py # Кэпы, флоры, свопционы
│ ├── visualize.py # Визуализация
│ └── backtest.py # Бэктестинг стратегий
└── rust_pinn_hw/
├── Cargo.toml
├── src/
│ ├── lib.rs # Ядро реализации
│ └── bin/
│ ├── train.rs # Обучение
│ ├── price_bonds.rs # Ценообразование
│ └── fetch_data.rs # Получение данных
└── examples/
├── basic_pricing.rs # Базовый пример
└── yield_curve.rs # Кривая доходности