绩效分析模块

betalens.analyst 提供从净值序列出发的指标计算与报告导出功能,适用于回测与实时组合。

PortfolioAnalyzer

import pandas as pd
from betalens.analyst import PortfolioAnalyzer

nav = pd.Series(..., index=pd.date_range("2023-01-01", periods=250))
analyzer = PortfolioAnalyzer(
    nav_series=nav,
    risk_free_rate=0.02,  # 年化无风险利率
    annualizer=252,       # 年化因子
    window=30             # 滚动窗口
)

核心指标

# 累计收益率
print(analyzer.total_return())

# 年化收益率
print(analyzer.annualized_return())

# 年化波动率
print(analyzer.annualized_volatility())

# 夏普比率
print(analyzer.sharpe_ratio())

# 最大回撤
print(analyzer.max_drawdown())

# 卡玛比率(年化收益/最大回撤)
print(analyzer.calmar_ratio())

# 恢复天数
print(analyzer.recovery_days())

滚动指标

# 滚动最大回撤
rolling_mdd = analyzer.rolling_max_drawdown()

# 滚动胜率
rolling_wr = analyzer.rolling_win_rate()

关键属性

  • nav:净值序列(按日期排序)

  • returns:日度收益(pct_change 后去 NA)

  • risk_free_rate:年化无风险利率

  • annualizer:年化因子(默认252)

  • window:滚动统计窗口

ReportExporter

from betalens.analyst import ReportExporter

exporter = ReportExporter(analyzer)

分年度报告

exporter.generate_annual_report()
exporter.generate_annual_report(excel_path="annual_report.xlsx")

自定义时段报告

exporter.generate_custom_report("2024-01-01", "2024-06-30")
exporter.generate_custom_report("2024-01-01", "2024-06-30", excel_path="custom.xlsx")

基准对比报告

# 创建基准分析器
benchmark_nav = pd.Series(...)
benchmark = PortfolioAnalyzer(benchmark_nav)

# 带基准的报告导出器
exporter = ReportExporter(analyzer, benchmark_analyzer=benchmark)
exporter.generate_benchmark_report()

# 访问超额收益分析器
excess_analyzer = exporter.excess
print(f"超额收益: {excess_analyzer.total_return():.2%}")

指定分析区间

# 在构造函数中裁剪分析区间
exporter = ReportExporter(
    analyzer,
    benchmark_analyzer=benchmark,
    start_date="2023-01-01",
    end_date="2024-12-31"
)

输出方式

  • CLI 表格:基于 PrettyTable,美观易读

  • Excel:传入 excel_path 即可将结果写入多工作表

高级用法

滚动指标绘图

import matplotlib.pyplot as plt

fig, axes = plt.subplots(2, 1, figsize=(12, 8))

# NAV 与滚动最大回撤
axes[0].plot(analyzer.nav, label='NAV')
axes[0].legend()

axes[1].plot(analyzer.rolling_max_drawdown(), label='Rolling MDD', color='red')
axes[1].legend()

plt.tight_layout()
plt.show()

自定义指标

class CustomAnalyzer(PortfolioAnalyzer):
    def sortino_ratio(self, target_return=0):
        """索提诺比率"""
        excess_returns = self.returns - self.risk_free_rate / self.annualizer
        downside_returns = excess_returns[excess_returns < target_return]
        downside_std = downside_returns.std() * np.sqrt(self.annualizer)
        return excess_returns.mean() * self.annualizer / downside_std

analyzer = CustomAnalyzer(nav)
print(f"Sortino: {analyzer.sortino_ratio():.4f}")

多策略对比

strategies = {
    "Strategy A": nav_a,
    "Strategy B": nav_b,
    "Benchmark": nav_benchmark
}

results = []
for name, nav in strategies.items():
    a = PortfolioAnalyzer(nav)
    results.append({
        "Strategy": name,
        "Return": a.total_return(),
        "Volatility": a.annualized_volatility(),
        "Sharpe": a.sharpe_ratio(),
        "MaxDD": a.max_drawdown()
    })

comparison = pd.DataFrame(results)
print(comparison)

常见问题

  • generate_custom_report 提示「数据不足」,请确认 NAV 序列包含目标日期,并保持频率一致。

  • recovery_days 默认寻找首次回到历史高点的日期,若 NAV 从未恢复,将抛出索引错误,可自行捕获。

  • 基准序列会自动裁剪到与策略NAV相同的日期范围。

更多 API 细节请参阅 Analyst API