Разработка системы Monte Carlo симуляции портфеля

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1Все 1306 услуг
Разработка системы Monte Carlo симуляции портфеля
Сложный
~3-5 дней
Часто задаваемые вопросы

Направления блокчейн-разработки

Этапы блокчейн-разработки

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1288
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1198
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    902
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1122
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    589
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    859

Разработка системы Monte Carlo симуляции портфеля

Monte Carlo симуляция генерирует тысячи возможных будущих траекторий портфеля на основе статистических свойств рыночных данных. Это позволяет оценить распределение возможных исходов, а не просто одно «ожидаемое» значение.

Принцип Monte Carlo симуляции

Вместо «портфель вырастет на X%» говорим: «с вероятностью 70% портфель вырастет на 20–80%, с вероятностью 15% потеряет 10–30%».

Базовый GBM (Geometric Brownian Motion):

import numpy as np

def simulate_gbm(initial_price, mu, sigma, days, n_simulations=10000):
    """
    mu: среднедневная доходность
    sigma: среднедневная волатильность
    """
    dt = 1  # 1 день
    random_returns = np.random.normal(
        mu * dt, 
        sigma * np.sqrt(dt), 
        (n_simulations, days)
    )
    
    # Кумулятивные returns
    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):
    """
    initial_prices: dict {symbol: price}
    means: dict {symbol: daily_mean}
    cov_matrix: ковариационная матрица daily returns
    """
    n_assets = len(initial_prices)
    symbols = list(initial_prices.keys())
    
    # Cholesky decomposition для генерации коррелированных случайных чисел
    L = cholesky(cov_matrix)
    
    portfolio_paths = []
    
    for _ in range(n_sims):
        # Генерируем некоррелированные нормальные случайные числа
        z = np.random.standard_normal((days, n_assets))
        # Применяем корреляционную структуру
        correlated_returns = z @ L.T
        
        # Добавляем drifts (mean returns)
        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 и кластеризация волатильности.

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')
    
    # Симулируем из fitted GARCH модели
    simulations = result.forecast(horizon=horizon, method='simulation', 
                                   simulations=n_sims)
    return simulations.simulations.values

Анализ результатов симуляции

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()
    
    # Expected return и std
    returns = (final_values - initial_value) / initial_value
    
    # VaR из симуляции
    var_95 = np.percentile(final_values - initial_value, 5)
    cvar_95 = (final_values - initial_value)[
        final_values - initial_value <= var_95
    ].mean()
    
    # Max drawdown distribution
    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)
    }

Visualisation результатов

Fan chart: показывает диапазон возможных траекторий портфеля. Центральная линия — медиана (50-й перцентиль). Более тёмные зоны — вероятные диапазоны (25–75%), светлее — редкие (5–95%).

Return distribution histogram: гистограмма финальных returns из всех симуляций. Нормальное vs реальное распределение.

Drawdown distribution: гистограмма максимальных drawdown по симуляциям. Показывает вероятность различных уровней просадки.

Применения в управлении портфелем

Вероятность достижения цели: «какова вероятность что портфель вырастет на 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.

Разрабатываем систему Monte Carlo симуляции с поддержкой GBM, fat-tail distributions и GARCH моделью, мультиактивной симуляцией с корреляциями, анализом результатов (percentiles, VaR, drawdown distribution) и интерактивными visualisations.