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

Глава 146: Физически-информированные нейронные сети для модели CIR

Обзор

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

Модель CIR описывает эволюцию короткой ставки r(t) через стохастическое дифференциальное уравнение:

dr = kappa * (theta - r) * dt + sigma * sqrt(r) * dW

где:

  • kappa > 0 — скорость возврата к среднему (насколько быстро ставки притягиваются к долгосрочному среднему)
  • theta > 0 — долгосрочное среднее (равновесная ставка)
  • sigma > 0 — коэффициент волатильности
  • sqrt(r) делает волатильность пропорциональной корню из текущей ставки
  • dW — стандартный винеровский процесс (броуновское движение)

Ключевое наблюдение: множитель sqrt(r) обеспечивает то, что при приближении ставок к нулю волатильность исчезает, предотвращая отрицательные ставки. Это гарантируется при выполнении условия Феллера:

2 * kappa * theta >= sigma^2

Когда это условие выполнено, процесс ставки никогда не достигает нуля.

Почему CIR лучше других моделей короткой ставки?

Сравнение моделей

ХарактеристикаВасичекХалл-УайтCIR
СДУdr = kappa(theta-r)dt + sigma dWdr = [theta(t)-ar]dt + sigma dWdr = kappa(theta-r)dt + sigma*sqrt(r) dW
Отрицательные ставкиВозможныВозможныНевозможны (условие Феллера)
ВолатильностьПостояннаяПостоянная или зависит от tЗависит от ставки: sigma*sqrt(r)
Аналитические цены облигацийДаДаДа (через функции Бесселя)
Плотность переходаНормальнаяНормальнаяНецентральная хи-квадрат
Сложность калибровкиНизкаяСредняяСредняя
Реалистичность для криптоНетЧастичноДа (ставки всегда >= 0)

Почему CIR для криптовалютных рынков?

На криптовалютных рынках несколько “процентно-ставочных” величин естественно неотрицательны:

  1. Ставки фондирования: ставки фондирования бессрочных фьючерсов на биржах вроде Bybit
  2. Ставки DeFi-кредитования: Aave, Compound — всегда неотрицательны
  3. Доходность стейкинга: доходность стейкинга Ethereum строго положительна
  4. Возврат к среднему подразумеваемой волатильности: IV криптовалют демонстрирует возврат к среднему с зависящей от уровня волатильностью

Модель CIR естественно описывает эту динамику.

PDE CIR для ценообразования облигаций

Вывод

Бескупонная облигация с погашением T выплачивает $1 в момент T. Её цена P(r, t) зависит от текущей короткой ставки r и времени t. Используя ценообразование в риск-нейтральной мере и лемму Ито, P удовлетворяет PDE CIR для ценообразования облигаций:

dP/dt + kappa * (theta - r) * dP/dr + 0.5 * sigma^2 * r * d^2P/dr^2 - r * P = 0

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

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

Ключевое отличие от PDE Халл-Уайта: обратите внимание на множитель r при второй производной (0.5 * sigma^2 * r * d^2P/dr^2). В модели Халл-Уайта этот коэффициент равен 0.5 * sigma^2 * d^2P/dr^2 (без множителя r). Этот зависящий от r коэффициент диффузии делает PDE CIR более сложным численно — особенно вблизи r = 0, где коэффициент диффузии обращается в ноль.

Граничные условия

При r = 0:
dP/dt + kappa * theta * dP/dr = 0 (поглощающая/отражающая граница)
При r -> бесконечность:
P(r, t) -> 0 (высокие ставки обесценивают облигации)
При t = T:
P(r, T) = 1 (терминальная выплата)

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

Модель CIR имеет элегантную замкнутую формулу цены облигации:

P(r, t) = A(tau) * exp(-B(tau) * r)
где tau = T - t (время до погашения)
gamma = sqrt(kappa^2 + 2 * sigma^2)
B(tau) = 2 * (exp(gamma * tau) - 1) / ((gamma + kappa) * (exp(gamma * tau) - 1) + 2 * gamma)
A(tau) = [ 2 * gamma * exp((kappa + gamma) * tau / 2) /
((gamma + kappa) * (exp(gamma * tau) - 1) + 2 * gamma) ] ^ (2 * kappa * theta / sigma^2)

Эта аналитическая формула служит эталоном для валидации нашей PINN.

Доходность и форвардная ставка

Из цены облигации выводим:

Доходность:
y(r, tau) = -ln(P(r, t)) / tau = (B(tau) * r - ln(A(tau))) / tau
Мгновенная форвардная ставка:
f(r, t, T) = -d ln(P) / dT = B'(tau) * r - A'(tau) / A(tau)

Плотность перехода: нецентральное хи-квадрат распределение

Процесс CIR имеет известную плотность перехода. При заданном r(s) = r_s распределение r(t) для t > s:

r(t) | r(s) = r_s ~ (sigma^2 * (1 - exp(-kappa*(t-s)))) / (4*kappa) * chi^2(df, lambda)
где:
df = 4 * kappa * theta / sigma^2 (число степеней свободы)
lambda = 4 * kappa * r_s * exp(-kappa*(t-s)) / (sigma^2 * (1 - exp(-kappa*(t-s))))
(параметр нецентральности)

Это нецентральное хи-квадрат распределение критически важно для:

  • Оценки максимального правдоподобия (MLE) параметров CIR
  • Точного моделирования траекторий CIR (без ошибки дискретизации)
  • Аналитического вычисления цен опционов на облигации

Архитектура PINN для CIR

Проектирование сети

PINN принимает короткую ставку r и время t на вход и выдаёт цену облигации P(r, t):

Архитектура PINN для CIR
========================================
ВХОДНОЙ СЛОЙ
+---------------------------+
| (r, t) | 2 нейрона
| r = короткая ставка |
| t = текущее время |
+---------------------------+
|
v
ПРЕОБРАЗОВАНИЕ ВХОДА
+---------------------------+
| r_norm = r / r_max | Нормализация к [0, 1]
| t_norm = t / T |
| sqrt_r = sqrt(r) / sqrt(r_max) <-- учёт структуры sqrt(r)
+---------------------------+
|
v
СКРЫТЫЕ СЛОИ
+---------------------------+
| Слой 1: Linear(3, 128) | 3 входа: r_norm, t_norm, sqrt_r
| + Tanh |
+---------------------------+
|
v
+---------------------------+
| Слой 2: Linear(128, 128) |
| + Tanh |
+---------------------------+
|
v
+---------------------------+
| Слой 3: Linear(128, 128) |
| + Tanh |
+---------------------------+
|
v
+---------------------------+
| Слой 4: Linear(128, 64) |
| + Tanh |
+---------------------------+
|
v
ВЫХОДНОЙ СЛОЙ
+---------------------------+
| Слой 5: Linear(64, 1) |
| + Sigmoid | Гарантирует P в (0, 1)
+---------------------------+

Зачем sqrt(r) как входной признак? PDE CIR имеет сингулярную структуру sqrt(r). Предоставляя sqrt(r) напрямую, сеть не должна обучать это преобразование внутри себя, что значительно улучшает сходимость вблизи r = 0.

Зачем Sigmoid на выходе? Цены бескупонных облигаций всегда в (0, 1], поэтому сигмоидная активация на выходном слое естественно обеспечивает это ограничение.

Обработка сингулярности sqrt(r)

Вблизи r = 0 PDE CIR становится вырожденным: коэффициент диффузии 0.5 * sigma^2 * r обращается в ноль. Это создаёт численные сложности для PINN:

  1. Остаток PDE доминируется членом сноса kappa * theta * dP/dr
  2. Малые ошибки в d^2P/dr^2 усиливаются относительно исчезающей диффузии
  3. Стандартная равномерная коллокация недостаточно покрывает критическую область вблизи нуля

Реализованные решения:

# 1. Коллокация с учётом sqrt(r): больше точек вблизи r = 0
r_collocation = r_max * (torch.rand(N) ** 2) # квадратичная выборка
# 2. Взвешенная потеря PDE: больший вес остаткам вблизи r = 0
weights = 1.0 / (r_collocation + epsilon)
# 3. Вспомогательный вход sqrt(r): подаём sqrt(r) как признак
inputs = torch.stack([r, t, torch.sqrt(r + epsilon)], dim=-1)
# 4. Регуляризованная диффузия: добавляем epsilon
diffusion = 0.5 * sigma**2 * (r + epsilon)

Проектирование функции потерь

Общая потеря для обучения CIR PINN:

L_total = w_pde * L_pde + w_bc * L_bc + w_ic * L_ic + w_analytical * L_analytical

1. Потеря остатка PDE

Выбираем коллокационные точки (r_i, t_i) во внутренней области и вычисляем:

P = network(r, t)
# Автоматическое дифференцирование
dP_dt = autograd(P, t)
dP_dr = autograd(P, r)
d2P_dr2 = autograd(dP_dr, r)
# Остаток PDE CIR
residual = dP_dt + kappa * (theta - r) * dP_dr + 0.5 * sigma**2 * r * d2P_dr2 - r * P
L_pde = mean(weights * residual**2)

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

# Терминальное условие: P(r, T) = 1
P_terminal = network(r_terminal, T)
L_ic = mean((P_terminal - 1.0)**2)
# Нижняя граница: при r = 0, редуцированное PDE
# Верхняя граница: P -> 0 при r -> бесконечность

3. Потеря аналитических ограничений (опционально)

Используем небольшой набор аналитически вычисленных цен CIR как супервизию.

Стратегия обучения

Фаза 1: Тёплый старт с аналитическими решениями (эпохи 1-500)

  • Высокий вес L_analytical, низкий вес L_pde
  • Сеть обучает общую форму поверхности цен облигаций

Фаза 2: Обучение с фокусом на PDE (эпохи 501-3000)

  • Увеличение веса L_pde, уменьшение L_analytical
  • Сеть уточняет решение PDE

Фаза 3: Тонкая настройка (эпохи 3001-5000)

  • Сбалансированные веса всех компонент потерь
  • Адаптивная коллокация

Калибровка параметров CIR через MLE

Перед обучением PINN нужно определить параметры CIR (kappa, theta, sigma). Оценка максимального правдоподобия использует нецентральное хи-квадрат распределение перехода:

def cir_log_likelihood(params, rates, dt):
kappa, theta, sigma = params
c = 2 * kappa / (sigma**2 * (1 - np.exp(-kappa * dt)))
df = 4 * kappa * theta / sigma**2
for i in range(1, len(rates)):
noncentrality = 2 * c * rates[i-1] * np.exp(-kappa * dt)
x = 2 * c * rates[i]
ll += ncx2.logpdf(x, df=df, nc=noncentrality) + np.log(2 * c)
return -ll # минимизируем отрицательное логарифмическое правдоподобие

Кредитный риск: CIR для интенсивности дефолта

Модель CIR широко используется для моделирования интенсивности дефолта (функции опасности) lambda(t) в кредитном риске:

d(lambda) = kappa * (theta - lambda) * dt + sigma * sqrt(lambda) * dW

Вероятность выживания (вероятность отсутствия дефолта до момента T):

Q(t, T) = E[exp(-integral_t^T lambda(s) ds) | lambda(t)]

Замечательно, что она имеет точно такую же форму, как цена облигации CIR:

Q(t, T) = A(T-t) * exp(-B(T-t) * lambda(t))

с теми же функциями A, B! Наша PINN может поэтому также оценивать:

  • Кредитные дефолтные свопы (CDS)
  • Облигации с кредитным риском
  • Кредитные опционы

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

Моделирование ставок фондирования Bybit

Бессрочные фьючерсы на Bybit имеют механизм фондирования каждые 8 часов. Ставка фондирования демонстрирует:

  1. Возврат к среднему: ставки возвращаются к базовому уровню
  2. Зависящую от уровня волатильность: более высокие ставки имеют более высокую волатильность
  3. Неотрицательность: абсолютная ставка |funding| всегда неотрицательна

Торговая стратегия: возврат ставки фондирования к среднему

def funding_rate_strategy(funding_rates, cir_params, threshold=2.0):
kappa, theta, sigma = cir_params
for rate in funding_rates:
expected_rate = theta + (rate - theta) * np.exp(-kappa * dt)
rate_std = sigma * np.sqrt(rate * (1 - np.exp(-2*kappa*dt)) / (2*kappa))
z_score = (rate - theta) / max(rate_std, 1e-8)
if z_score > threshold:
signal = -1 # Шорт: ставка вернётся вниз
elif z_score < -threshold:
signal = 1 # Лонг: ставка вернётся вверх
else:
signal = 0 # Нейтрально

Условие Феллера: 2kappatheta >= sigma^2

Случай 1: 2*kappa*theta > sigma^2 (сильное условие Феллера)
- r = 0 -- входная граница
- Процесс НИКОГДА не достигает нуля
Случай 2: 2*kappa*theta = sigma^2 (критическое условие Феллера)
- r = 0 достигается, но мгновенно отражается
Случай 3: 2*kappa*theta < sigma^2 (условие Феллера нарушено)
- r = 0 достигается и процесс может застревать в нуле
- Часто встречается в криптовалютах с высокой волатильностью

Примеры кода

Быстрый старт: Python

from python.cir_pinn import CIRPINN
from python.train import train_pinn
from python.analytical import cir_bond_price
# Параметры CIR
kappa, theta, sigma = 0.5, 0.05, 0.1
T = 5.0
# Создание и обучение PINN
pinn = CIRPINN(kappa=kappa, theta=theta, sigma=sigma, T=T)
losses = train_pinn(pinn, epochs=5000, lr=1e-3)
# Сравнение с аналитическим решением
r_test = torch.linspace(0.0, 0.15, 100)
P_pinn = pinn.predict(r_test, torch.zeros(100))
P_analytical = cir_bond_price(r_test.numpy(), 0.0, T, kappa, theta, sigma)

Быстрый старт: Rust

use pinn_cir_model::{CIRParams, cir_bond_price, simulate_cir_paths};
fn main() {
let params = CIRParams {
kappa: 0.5,
theta: 0.05,
sigma: 0.1,
r0: 0.03,
};
let price = cir_bond_price(0.03, 5.0, &params);
println!("Цена облигации CIR (r=0.03, T=5): {:.6}", price);
}

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

146_pinn_cir_model/
|-- README.md # Английская версия
|-- README.ru.md # Этот файл (русская версия)
|-- readme.simple.md # Простое объяснение (англ.)
|-- readme.simple.ru.md # Простое объяснение (рус.)
|-- python/
| |-- __init__.py # Инициализация пакета
| |-- requirements.txt # Зависимости Python
| |-- cir_pinn.py # Архитектура PINN для CIR PDE
| |-- train.py # Цикл обучения с коллокацией sqrt(r)
| |-- data_loader.py # Данные: казначейские + фондирование Bybit
| |-- analytical.py # Аналитическое ценообразование CIR
| |-- calibration.py # MLE-калибровка параметров CIR
| |-- credit_risk.py # CIR для моделирования интенсивности дефолта
| |-- visualize.py # Графики: траектории, поверхности, кривые
| |-- backtest.py # Бэктестинг торговой стратегии
|-- rust_pinn_cir/
| |-- Cargo.toml # Конфигурация Rust проекта
| |-- src/
| | |-- lib.rs # Основная библиотека CIR
| | |-- bin/
| | |-- train.rs # Обучение PINN
| | |-- price_bonds.rs # Ценообразование облигаций
| | |-- fetch_data.rs # Загрузка данных Bybit
| |-- examples/
| |-- basic_pricing.rs # Простой пример ценообразования

Литература

  1. Cox, J.C., Ingersoll, J.E., Ross, S.A. (1985). “A Theory of the Term Structure of Interest Rates.” Econometrica, 53(2), 385-407.
  2. Feller, W. (1951). “Two Singular Diffusion Problems.” Annals of Mathematics, 54(1), 173-182.
  3. Raissi, M., Perdikaris, P., Karniadakis, G.E. (2019). “Physics-Informed Neural Networks.” Journal of Computational Physics, 378, 686-707.
  4. Brigo, D., Mercurio, F. (2006). Interest Rate Models - Theory and Practice. Springer.
  5. Duffie, D., Singleton, K.J. (2003). Credit Risk. Princeton University Press.

Запуск кода

Python

Окно терминала
cd 146_pinn_cir_model/python
pip install -r requirements.txt
# Обучение PINN
python -m python.train --epochs 5000 --kappa 0.5 --theta 0.05 --sigma 0.1
# Загрузка данных Bybit и калибровка
python -m python.data_loader --symbol BTCUSDT --days 180
# Бэктестинг
python -m python.backtest --symbol BTCUSDT --days 90

Rust

Окно терминала
cd 146_pinn_cir_model/rust_pinn_cir
# Сборка
cargo build --release
# Обучение
cargo run --release --bin train
# Ценообразование облигаций
cargo run --release --bin price_bonds
# Загрузка данных Bybit
cargo run --release --bin fetch_data -- --symbol BTCUSDT --days 180
# Запуск примера
cargo run --release --example basic_pricing