Симуляция Монте-Карло для крипто-портфеля в Python scipy

Симуляция Монте-Карло для крипто-портфеля в Python scipy ЛИЧНЫЙ БЮДЖЕТ и ЭКОНОМИЯ
Пошаговое руководство по оценке риска (VaR и CVaR) криптовалютного портфеля методом Монте-Карло с использованием многомерного распределения Стьюдента в scipy.
Суть: Оценка рыночного риска (VaR и CVaR) криптовалютного портфеля с использованием многомерного распределения Стьюдента (Student-t) в scipy.stats для точного моделирования «тяжелых хвостов» (fat tails) крипторынка.

Видеоинструкция

Исходный код

Классическое геометрическое броуновское движение (GBM) предполагает нормальное распределение доходностей. Однако для криптовалют характерны экстремальные выбросы и тяжелые хвосты. Использование многомерного распределения Стьюдента (multivariate_t) из библиотеки scipy позволяет построить гораздо более реалистичную модель риска.

Перед расчетом ковариационной матрицы критически важно очистить исторические данные от рыночных манипуляций и аномалий. В этом поможет статья про Выявление Аномалий в Торговых Объемах: Isolation Forest в Python.

Для более глубокого анализа структуры портфеля и снижения размерности перед симуляцией полезно использовать PCA для портфеля альткоинов: Уменьшение размерности в Python scikit-learn.

Если вы работаете с деривативами в портфеле, рекомендуем ознакомиться с руководством по Бэктесту опционных стратегий Iron Condor на Python с Implied Volatility.

import numpy as np
import pandas as pd
from scipy.stats import multivariate_t

# Настройка воспроизводимости
np.random.seed(42)

# 1. Генерация синтетических исторических доходностей (BTC, ETH, SOL)
# Используем распределение Стьюдента для симуляции тяжелых хвостов
num_assets = 3
df_historical = 3.0  # Степени свободы для крипты
loc_historical = np.array([0.0012, 0.0018, 0.0025])  # Ожидаемая дневная доходность
shape_historical = np.array([
    [0.0008, 0.0005, 0.0004],
    [0.0005, 0.0012, 0.0006],
    [0.0004, 0.0006, 0.0020]
])

# Генерируем 1000 дней "истории"
hist_returns = multivariate_t.rvs(
    loc=loc_historical,
    shape=shape_historical,
    df=df_historical,
    size=1000
)

# 2. Оценка параметров для Монте-Карло
mean_returns = np.mean(hist_returns, axis=0)
cov_matrix = np.cov(hist_returns, rowvar=False)

# Задаем степени свободы для симуляции (тяжелые хвосты)
nu = 3.0
# Корректируем матрицу формы для распределения Стьюдента
shape_matrix = cov_matrix * (nu - 2) / nu

# 3. Параметры симуляции Монте-Карло
num_simulations = 100000
time_horizon = 10  # Горизонт риска в днях
portfolio_value = 1000000.0  # Размер портфеля в USD
weights = np.array([0.50, 0.30, 0.20])  # BTC: 50%, ETH: 30%, SOL: 20%

# 4. Генерация многомерных случайных величин
# Генерируем доходности для всех симуляций и дней сразу
sim_returns = multivariate_t.rvs(
    loc=mean_returns,
    shape=shape_matrix,
    df=nu,
    size=(num_simulations, time_horizon)
)

# 5. Расчет доходности портфеля по путям
portfolio_sim_returns = np.zeros(num_simulations)
for i in range(num_simulations):
    # Накапливаем доходность активов за time_horizon дней: prod(1 + r) - 1
    cum_asset_returns = np.prod(1 + sim_returns[i], axis=0) - 1
    # Взвешенная доходность портфеля
    portfolio_sim_returns[i] = np.dot(cum_asset_returns, weights)

# Расчет конечной стоимости и убытков
portfolio_end_values = portfolio_value * (1 + portfolio_sim_returns)
portfolio_losses = portfolio_value - portfolio_end_values

# 6. Расчет метрик риска (VaR и CVaR)
confidence_levels = [0.95, 0.99]
risk_metrics = {}

for cl in confidence_levels:
    # Value at Risk (VaR)
    var = np.percentile(portfolio_losses, cl * 100)
    # Conditional Value at Risk (CVaR)
    cvar = portfolio_losses[portfolio_losses >= var].mean()
    risk_metrics[cl] = {'VaR': var, 'CVaR': cvar}

# Вывод результатов
for cl, metrics in risk_metrics.items():
    print(f'Уровень доверия {cl*100}%:')
    print(f'  Value at Risk (VaR): ${metrics["VaR"]:,.2f}')
    print(f'  Conditional Value at Risk (CVaR): ${metrics["CVaR"]:,.2f}')

Разбор параметров

  • multivariate_t: Класс из модуля scipy.stats, используемый для генерации многомерного распределения Стьюдента, которое лучше описывает экстремальные риски криптовалют по сравнению с нормальным распределением.
  • df (degrees of freedom): Число степеней свободы. Чем меньше этот параметр, тем «тяжелее» хвосты распределения. Для крипторынка стандартным выбором является диапазон от 2.5 до 4.0.
  • shape_matrix: Матрица формы (масштаба). В распределении Стьюдента она связана с ковариационной матрицей формулой cov * (nu - 2) / nu для nu > 2.
  • portfolio_losses: Массив смоделированных убытков портфеля в базовой валюте (USD) на конец временного горизонта. Используется для расчета квантилей риска.
  • np.percentile: Функция для расчета Value at Risk (VaR) как определенного квантиля распределения убытков.

Как запустить

Для запуска симуляции вам понадобятся библиотеки numpy, pandas и scipy. Установите их с помощью пакетного менеджера pip:

pip install numpy pandas scipy

Скопируйте исходный код в файл monte_carlo.py и запустите его в терминале или вашей любимой IDE. Скрипт сгенерирует синтетические исторические данные, настроит параметры распределения Стьюдента, проведет 100 000 итераций симуляции для 10-дневного горизонта и выведет значения VaR и CVaR для уровней доверия 95% и 99%.

Оцените статью
FinFluct