Расчет коэффициента Шарпа и просадки в Python с pandas-ta

Расчет коэффициента Шарпа и просадки в Python с pandas-ta Анализ данных и Бэктесты
Пошаговое руководство по расчету коэффициента Шарпа и максимальной просадки (Max Drawdown) в Python с использованием библиотеки pandas-ta и векторизованных вычислений.
Суть: Быстрый и точный расчет ключевых метрик эффективности торговой стратегии (коэффициента Шарпа и максимальной просадки) с использованием библиотеки pandas-ta для подготовки данных о доходности и векторизованных вычислений на pandas и numpy.

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

Исходный код

Для оценки качества торговой системы недостаточно знать только ее чистую прибыль. Профессиональные кванты всегда оценивают доходность с учетом принятого риска. Ниже представлен готовый production-ready скрипт, который загружает исторические данные по ETF SPY, рассчитывает ежедневную доходность с помощью pandas_ta.percent_return, а затем вычисляет годовой коэффициент Шарпа и максимальную просадку (Maximum Drawdown).

Эти метрики критически важны при проведении таких процедур, как Walk-Forward Оптимизация в Backtrader, а также при оценке результатов, которые дает Байесовская оптимизация с Optuna в Python. Дополнительно, для полной картины системного риска, рекомендуется проводить Расчет Бета-коэффициента Крипто-портфеля.

import numpy as np
import pandas as pd
import pandas_ta as ta
import yfinance as yf

def calculate_metrics(ticker: str, start_date: str, end_date: str, rf_rate: float = 0.02):
    # 1. Загрузка исторических данных
    df = yf.download(ticker, start=start_date, end=end_date)
    if df.empty:
        raise ValueError("Не удалось загрузить данные. Проверьте тикер и даты.")

    # Очистка мультииндексов, если они есть (актуально для новых версий yfinance)
    if isinstance(df.columns, pd.MultiIndex):
        df.columns = df.columns.get_level_values(0)

    # 2. Расчет доходности с использованием pandas-ta
    # Функция percent_return автоматически рассчитывает процентное изменение цены закрытия
    df["Daily_Return"] = df.ta.percent_return(close=df["Close"], append=False)

    # Удаляем первый NaN, появившийся из-за расчета доходности
    df.dropna(subset=["Daily_Return"], inplace=True)

    # 3. Расчет коэффициента Шарпа (Sharpe Ratio)
    # Переводим безрисковую ставку в дневной эквивалент (исходя из 252 торговых дней в году)
    trading_days = 252
    daily_rf = rf_rate / trading_days

    mean_excess_return = df["Daily_Return"].mean() - daily_rf
    std_dev = df["Daily_Return"].std()

    # Годовой коэффициент Шарпа
    sharpe_ratio = (mean_excess_return / std_dev) * np.sqrt(trading_days) if std_dev != 0 else 0.0

    # 4. Расчет максимальной просадки (Maximum Drawdown)
    # Рассчитываем кумулятивную доходность
    cumulative_returns = (1 + df["Daily_Return"]).cumprod()

    # Находим исторический максимум на каждый момент времени
    running_max = cumulative_returns.cummax()

    # Рассчитываем текущую просадку
    drawdowns = (cumulative_returns - running_max) / running_max

    # Максимальная просадка — это минимальное значение просадки (наибольший пик-впадина спад)
    max_drawdown = drawdowns.min()

    return {
        "sharpe_ratio": sharpe_ratio,
        "max_drawdown": max_drawdown,
        "final_return": (cumulative_returns.iloc[-1] - 1) * 100
    }

if __name__ == "__main__":
    ticker_symbol = "SPY"
    metrics = calculate_metrics(ticker=ticker_symbol, start_date="2020-01-01", end_date="2023-12-31")

    print(f"--- Результаты анализа для {ticker_symbol} ---")
    print(f"Годовой коэффициент Шарпа (Sharpe Ratio): {metrics['sharpe_ratio']:.4f}")
    print(f"Максимальная просадка (Max Drawdown): {metrics['max_drawdown'] * 100:.2f}%")
    print(f"Общая доходность за период: {metrics['final_return']:.2f}%")

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

  • close: Ряд цен закрытия (обычно df['Close']), используемый pandas-ta для вычисления процентных изменений.
  • rf_rate: Годовая безрисковая процентная ставка (например, доходность казначейских облигаций США). По умолчанию установлена на уровне 0.02 (2%).
  • trading_days: Количество торговых дней в году (для фондового рынка США стандартно принимается равным 252, для криптовалютного рынка — 365). Используется для годовой нормализации коэффициента Шарпа.
  • cumulative_returns: Накопленная доходность портфеля, рассчитываемая как произведение последовательных дневных доходностей.
  • running_max: Скользящий максимум кумулятивной доходности, необходимый для определения пиковых точек перед началом просадки.

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

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

pip install pandas pandas-ta numpy yfinance

После установки зависимостей скопируйте исходный код в файл metrics_calc.py и запустите его из терминала:

python metrics_calc.py

Скрипт автоматически загрузит данные по индексу S&P 500 (через ETF SPY) за указанный период, рассчитает метрики эффективности и выведет их в консоль.

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