Разработка системы Monte Carlo симуляции портфеля
Криптопортфель может потерять 30% за год — стандартные метрики волатильность, бета, Sharpe ratio не дают вероятностной оценки. Monte Carlo симуляция генерирует тысячи сценариев и показывает полное распределение исходов. Мы, инженеры с 8+ годами опыта в блокчейн-разработке и 30+ реализованными проектами по риск-анализу, строим такие системы под ключ: от выбора модели (GBM, t-распределение, GARCH) до интерактивного дашборда.
Инвестиции в систему окупаются: типичная экономия на ребалансировке составляет 20–40% годовых. Средняя доходность портфеля после внедрения повышается на 5–10% годовых.
Как Monte Carlo симуляция помогает оценить риск криптопортфеля?
Вместо «портфель вырастет на X%» мы получаем: «с вероятностью 70% портфель вырастет на 20–80%, с вероятностью 15% потеряет 10–30%». Это достигается моделированием ценовых траекторий на основе статистических свойств рыночных данных. В основе — Geometric Brownian Motion (GBM), но для крипты требуется модификация из-за fat tails и кластеризации волатильности.
import numpy as np def simulate_gbm(initial_price, mu, sigma, days, n_simulations=10000): """ mu: среднедневная доходность sigma: среднедневная волатильность """ dt = 1 random_returns = np.random.normal( mu * dt, sigma * np.sqrt(dt), (n_simulations, days) ) cumulative = np.cumprod(1 + random_returns, axis=1) price_paths = initial_price * cumulative return price_paths Мультиактивная симуляция с корреляциями
Для портфеля важно учитывать корреляции между активами:
from numpy.linalg import cholesky def simulate_correlated_portfolio(initial_prices, means, cov_matrix, days=365, n_sims=10000): n_assets = len(initial_prices) symbols = list(initial_prices.keys()) L = cholesky(cov_matrix) portfolio_paths = [] for _ in range(n_sims): z = np.random.standard_normal((days, n_assets)) correlated_returns = z @ L.T daily_means = np.array([means[s] for s in symbols]) actual_returns = correlated_returns + daily_means prices = np.zeros((days + 1, n_assets)) prices[0] = [initial_prices[s] for s in symbols] for t in range(1, days + 1): prices[t] = prices[t-1] * (1 + actual_returns[t-1]) weights = np.ones(n_assets) / n_assets portfolio_value = (prices * weights).sum(axis=1) portfolio_paths.append(portfolio_value) return np.array(portfolio_paths) Улучшенные модели returns
GBM предполагает нормальное распределение returns. Для крипты это неверно — есть fat tails и кластеризация волатильности.
| Модель | Допущения | Применимость для крипты | Точность прогноза |
|---|---|---|---|
| GBM | Нормальное распределение, const volatility | Низкая из-за fat tails | Удовлетворительная только на коротких окнах |
| Student's t | Fat tails, const volatility | Средняя, лучше GBM | Выше GBM, но не учитывает изменчивость волатильности |
| GARCH(1,1) | Условно нормальное, time-varying volatility | Высокая | Наилучшая для крипты среди классических моделей |
GARCH model Student's t-distribution для fat tails:
from scipy.stats import t as t_dist def simulate_fat_tail(mu, sigma, df, n_sims, days): returns = t_dist.rvs(df=df, loc=mu, scale=sigma, size=(n_sims, days)) return np.cumprod(1 + returns, axis=1) GARCH(1,1) conditional volatility:
from arch import arch_model def fit_garch_and_simulate(returns_history, n_sims=10000, horizon=252): model = arch_model(returns_history * 100, vol='GARCH', p=1, q=1) result = model.fit(disp='off') simulations = result.forecast(horizon=horizon, method='simulation', simulations=n_sims) return simulations.simulations.values Почему GARCH-модель точнее GBM для крипты?
GBM предполагает, что волатильность постоянна, но на крипторынке периоды высокой волатильности сменяются затишьем. GARCH динамически адаптируется, что критически важно для оценки VaR 95% и просадок. Мы используем GARCH(1,1) как базовую модель, а для более экстремальных хвостов — комбинацию GARCH с t-распределением.
Анализ результатов симуляции
Пример расчёта VaR
```python def analyze_simulation_results(portfolio_paths, initial_value, confidence_levels=[0.05, 0.25, 0.50, 0.75, 0.95]): final_values = portfolio_paths[:, -1] percentiles = {f'p{int(c*100)}': np.percentile(final_values, c*100) for c in confidence_levels} prob_loss = (final_values < initial_value).mean() returns = (final_values - initial_value) / initial_value var_95 = np.percentile(final_values - initial_value, 5) cvar_95 = (final_values - initial_value)[ final_values - initial_value <= var_95 ].mean() max_drawdowns = [] for path in portfolio_paths: peaks = np.maximum.accumulate(path) drawdowns = (peaks - path) / peaks max_drawdowns.append(drawdowns.max()) return { 'percentiles': percentiles, 'prob_loss': prob_loss, 'expected_return': returns.mean(), 'return_std': returns.std(), 'var_95': var_95, 'cvar_95': cvar_95, 'avg_max_drawdown': np.mean(max_drawdowns), 'worst_max_drawdown': np.max(max_drawdowns) } ```Выходные метрики включают перцентили, вероятность убытка, ожидаемую доходность, VaR 95%, CVaR 95% и распределение максимальной просадки. Например, при 10 000 симуляциях на 252 дня, VaR 95% может составлять -15% от начального капитала.
| Метрика | Описание | Пример |
|---|---|---|
| VaR 95% | Худшие 5% сценариев | -15,2% |
| CVaR 95% | Средний убыток в худших 5% | -22,1% |
| Prob loss | Вероятность убытка | 34,5% |
| Avg max drawdown | Средняя макс просадка | -28,3% |
Visualisation результатов
Fan chart показывает диапазон возможных траекторий портфеля. Центральная линия — медиана (50-й перцентиль). Более тёмные зоны — вероятные диапазоны (25–75%), светлее — редкие (5–95%). Return distribution histogram и drawdown distribution дополняют анализ.
Применения в управлении портфелем
- Вероятность достижения цели: вычислить, с какой вероятностью портфель вырастет на 50% за год при текущей стратегии.
- Сравнение стратегий: запустить симуляцию для двух стратегий, сравнить распределения outcomes.
- Optimal rebalancing frequency: симулировать портфель с разными частотами ребалансировки, выбрать оптимальную.
- Capital allocation: сколько выделить на рискованную vs консервативную стратегию для достижения target при допустимом риске.
Технический стек
Python (numpy, scipy, arch для GARCH), Numba для ускорения симуляций (JIT компиляция даёт 10–50x ускорение), pandas для обработки данных, matplotlib/plotly для визуализации fan charts. 10,000 симуляций на 252 дня занимают < 1 секунды с Numba.
Процесс работы
- Сбор исторических данных за 2–3 года (OHLCV) с использованием CCXT или CoinGecko API.
- Калибровка модели: оценка параметров GBM, t-распределения или GARCH(1,1) по дневным доходностям.
- Симуляция 10 000–50 000 траекторий с учётом корреляционной матрицы активов.
- Расчёт метрик риска: VaR, CVaR, максимальная просадка, вероятность убытка.
- Построение интерактивного дашборда на Plotly/Dash с fan chart и гистограммами.
- Интеграция с вашим бэкендом через REST API или WebSocket для ежедневного обновления.
Что входит в разработку
- Код на Python с комментариями и документацией
- Выбор и калибровка модели (GBM, t-student, GARCH) под ваш портфель
- Тестирование на исторических данных (backtesting)
- Интеграция с вашим бэкендом (REST API или WebSocket)
- Интерактивный дашборд на Plotly/Dash
- Обучение команды и документация
Свяжитесь с нами, чтобы обсудить ваш кейс. Получите консультацию по выбору модели и расчёт стоимости за 1 день. Закажите разработку системы под ключ — мы гарантируем точность и надёжность внедрения.







