DEV Community

drake
drake

Posted on

Sharpe-like Ratio(夏普比率)算法解析

import math
from typing import List, Dict

def calculate_sharpe_ratio(historical_data: Dict) -> float:
    """
    基于JS文件 (Ze 函数) 解析的夏普比率 (Sharpe-like Ratio) 算法。
    计算公式: (每日百分比收益率的平均值) / (每日百分比收益率的标准差) (非年化)

    Args:
        historical_data: 包含 'accountValueHistory''pnlHistory' 的字典,
                         time1, time2... 必须按时间顺序排列,pnlHistory 中的 PnL 是累积的。
                         例如: {"accountValueHistory": [[time1, value1], ...], "pnlHistory": [[time1, pnl1], ...]}

    Returns:
        夏普比率的数值。
    """
    account_value_history = historical_data.get("accountValueHistory", [])
    pnl_history = historical_data.get("pnlHistory", [])

    # 检查基本数据长度
    if len(account_value_history) < 1 or len(pnl_history) < 2:
        return 0.0

    # 1. 计算每日 PnL (Daily PnL)
    daily_pnls = []
    # pnl_history 是累积 PnL: pnl[t] - pnl[t-1]
    for t in range(1, len(pnl_history)):
        try:
            current_pnl = float(pnl_history[t][1])
            previous_pnl = float(pnl_history[t-1][1])
            daily_pnls.append(current_pnl - previous_pnl)
        except (ValueError, TypeError):
            # 忽略数据格式错误的点
            continue

    # 2. 计算平均账户价值 (Average Account Value)
    total_value_sum = sum(float(item[1]) for item in account_value_history if isinstance(item[1], (int, float, str)))
    count = len(account_value_history)

    if count == 0:
        return 0.0

    avg_value = total_value_sum / count

    if avg_value == 0:
        return 0.0

    # 3. 计算每日百分比收益率 (Daily Return %)
    # R_t = 100 * Daily PnL / AvgValue
    returns_percent = []
    for daily_pnl in daily_pnls:
        daily_return_percent = 100 * daily_pnl / avg_value
        returns_percent.append(daily_return_percent)

    # 检查收益率序列长度 (JS: r.length < 2)
    if len(returns_percent) < 2:
        return 0.0

    # 4. 计算均值 (Mean)
    mean_return = sum(returns_percent) / len(returns_percent)

    # 5. 计算样本标准差 (Sample Standard Deviation) (N-1 分母)
    variance_sum = sum(math.pow(r - mean_return, 2) for r in returns_percent)
    # 分母是 N - 1
    sample_stdev = math.sqrt(variance_sum / (len(returns_percent) - 1))

    # 6. 计算比率
    # JS: 0===u?0:o/u
    if sample_stdev == 0:
        return 0.0
    else:
        return mean_return / sample_stdev
Enter fullscreen mode Exit fullscreen mode

Top comments (0)