Расчет VaR историческим методом для фьючерсов Binance на Python

Расчет VaR историческим методом для фьючерсов Binance на Python Анализ данных и Бэктесты
Пошаговое руководство по расчету метрики Value at Risk (VaR) и CVaR для фьючерсных контрактов Binance с использованием Python. Исходный код и разбор параметров.
Суть: Исторический метод расчета Value at Risk (VaR) оценивает максимальные ожидаемые убытки по фьючерсному портфелю на основе реальных исторических колебаний цен за заданный период при определенном доверительном интервале. В отличие от параметрического метода, он не требует допущения о нормальном распределении доходностей, что критически важно для крипторынка с его «тяжелыми хвостами» распределения.

Исходный код

Ниже представлен готовый к продакшену скрипт на Python, который загружает исторические данные по фьючерсам с публичного API Binance (USD-M Futures), рассчитывает логарифмические доходности, а также вычисляет метрики VaR и CVaR (Expected Shortfall) с учетом кредитного плеча.

import numpy as np
import pandas as pd
import requests
from typing import Dict, Any

def fetch_binance_futures_data(symbol: str, interval: str = '1d', limit: int = 1000) -> pd.DataFrame:
    """
    Загружает исторические свечи с API Binance USD-M Futures.
    """
    base_url = 'https://fapi.binance.com/fapi/v1/klines'
    params = {
        'symbol': symbol.upper(),
        'interval': interval,
        'limit': limit
    }
    try:
        response = requests.get(base_url, params=params, timeout=10)
        response.raise_for_status()
        data = response.json()
    except Exception as e:
        raise RuntimeError(f'Ошибка при запросе к API Binance: {e}')

    df = pd.DataFrame(data, columns=[
        'open_time', 'open', 'high', 'low', 'close', 'volume',
        'close_time', 'quote_asset_volume', 'number_of_trades',
        'taker_buy_base_asset_volume', 'taker_buy_quote_asset_volume', 'ignore'
    ])
    df['close'] = pd.to_numeric(df['close'])
    df['timestamp'] = pd.to_datetime(df['open_time'], unit='ms')
    return df[['timestamp', 'close']]

def calculate_historical_metrics(
    df: pd.DataFrame, 
    position_size_usd: float, 
    leverage: float = 1.0, 
    confidence_level: float = 0.95
) -> Dict[str, Any]:
    """
    Рассчитывает исторический Value at Risk (VaR) и Conditional VaR (CVaR).
    """
    if df.empty or len(df) < 10:
        raise ValueError('Недостаточно данных для расчета риск-метрик.')

    df = df.copy()
    # Используем логарифмические доходности для лучшей статистической точности
    df['returns'] = np.log(df['close'] / df['close'].shift(1))
    df = df.dropna()

    # Определение альфы (уровня значимости)
    alpha = 1.0 - confidence_level
    var_percentile = np.percentile(df['returns'], alpha * 100)
    
    # Корректировка размера позиции с учетом кредитного плеча
    effective_position = position_size_usd * leverage
    
    # Расчет VaR в USD (абсолютный убыток)
    var_usd = -var_percentile * effective_position
    
    # Расчет Expected Shortfall (CVaR) — средний убыток в хвосте распределения
    tail_losses = df['returns'][df['returns'] <= var_percentile]
    cvar_percentile = tail_losses.mean() if not tail_losses.empty else var_percentile
    cvar_usd = -cvar_percentile * effective_position

    return {
        'symbol_last_price': df['close'].iloc[-1],
        'confidence_level': confidence_level,
        'historical_days': len(df),
        'var_percentage': abs(var_percentile) * 100,
        'var_usd': max(0.0, var_usd),
        'cvar_percentage': abs(cvar_percentile) * 100,
        'cvar_usd': max(0.0, cvar_usd),
        'leverage': leverage,
        'effective_position_usd': effective_position
    }

if __name__ == '__main__':
    # Пример: BTCUSDT с обеспечением $10,000 и плечом 5x (номинал позиции $50,000)
    ticker = 'BTCUSDT'
    margin = 10000.0
    lev = 5.0
    conf = 0.99

    print(f'Загрузка данных для {ticker}...')
    historical_data = fetch_binance_futures_data(symbol=ticker, interval='1d', limit=365)
    
    metrics = calculate_historical_metrics(
        df=historical_data, 
        position_size_usd=margin, 
        leverage=lev, 
        confidence_level=conf
    )
    
    print('\n--- Отчет по рискам (Historical VaR) ---')
    print(f'Инструмент: {ticker} (Текущая цена: {metrics["symbol_last_price"]:.2f} USDT)')
    print(f'Маржа: ${margin:,.2f} | Плечо: {metrics["leverage"]}x')
    print(f'Номинальный объем позиции: ${metrics["effective_position_usd"]:,.2f}')
    print(f'Доверительный интервал: {metrics["confidence_level"] * 100}%')
    print(f'Период анализа: {metrics["historical_days"]} дней')
    print(f'Value at Risk (VaR 1d): {metrics["var_percentage"]:.2f}% (${metrics["var_usd"]:,.2f})')
    print(f'Expected Shortfall (CVaR 1d): {metrics["cvar_percentage"]:.2f}% (${metrics["cvar_usd"]:,.2f})')

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

  • symbol: Идентификатор фьючерсного контракта на Binance (например, 'BTCUSDT' или 'ETHUSDT').
  • position_size_usd: Размер вашего маржинального обеспечения (коллатерала) в USD, выделенного под данную позицию.
  • leverage: Кредитное плечо фьючерсного контракта. Используется для расчета реального рыночного риска через номинальный объем позиции.
  • confidence_level: Доверительный уровень (обычно 0.95 или 0.99). Показывает вероятность, с которой ваши убытки за 1 день не превысят расчетный VaR.
  • limit: Количество исторических дней для анализа. Чем больше выборка, тем точнее оценка экстремальных движений рынка.

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

Для работы скрипта вам понадобятся стандартные библиотеки для анализа данных. Установите их с помощью pip:

pip install pandas numpy requests

Сохраните приведенный выше код в файл var_calculator.py и запустите его из терминала. Скрипт автоматически обратится к публичному API Binance, загрузит дневные свечи за последний год и выведет детальный отчет по рискам.

Для масштабирования расчетов на портфель из сотен инструментов рекомендуем ознакомиться со статьей Оптимизация стратегий на 100+ тикерах: Multiprocessing в Python.

Помимо расчета VaR, для глубокого анализа структуры рынка и поиска ключевых уровней поддержки/сопротивления полезно использовать Кластеризация Volume Profile с DBSCAN для POC уровней | Python scikit-learn.

Если вы интегрируете риск-метрики в торговые системы на базе машинного обучения, обратите внимание на Распределенный бэктестинг RL в FinRL с Ray: Масштабирование и оптимизация.

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