Skip to content

feat(backtest): expand benchmark analytics with M^2, Dual-Beta, and Batting Average - #307

Merged
brokermr810 merged 1 commit into
OpenByteInc:mainfrom
huuan26:feat/backtest-m2-dual-beta-and-batting-average
Oct 24, 2026
Merged

brokermr810 merged 1 commit into
OpenByteInc:mainfrom
huuan26:feat/backtest-m2-dual-beta-and-batting-average

Conversation

@huuan26

@huuan26 huuan26 commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Expands the benchmark-relative performance analytics in app/services/backtest/metrics.py and Strategy API V2 with Modigliani–Modigliani ($M^2$), Dual-Beta ($\beta^+$ and $\beta^-$), and Batting Average metrics:

  1. Modigliani–Modigliani Measure ($M^2$) & $M^2 \text{ Alpha}$:
    • Leverages or deleverages the portfolio return to match the benchmark's total volatility level ($\sigma_{p^*} = \sigma_b$), converting the abstract Sharpe ratio into an annualized percentage return directly comparable to the benchmark:
      $$M^2 = R_f + \text{Sharpe}p \times \sigma{b,\text{ann}} = R_f + \left(\frac{R_{p,\text{ann}} - R_f}{\sigma_{p,\text{ann}}}\right) \sigma_{b,\text{ann}}$$
      $$M^2_{\text{alpha}} = M^2 - R_{b,\text{ann}}$$
    • Directly answers: "If this strategy were scaled to carry the exact risk of the benchmark (e.g. SPY or BTC), what annualized return and excess alpha would it produce?"
    • Safely handles flat portfolio variance (zero_portfolio_variance) and flat benchmark variance (zero_benchmark_variance).
  2. Dual-Beta: Up-Market ($\beta^+$) & Down-Market ($\beta^-$) Beta:
    • Asymmetric systematic risk modeling across distinct market regimes:
      $$\beta^+ = \frac{\text{Cov}(R_p, R_b \mid R_b > 0)}{\text{Var}(R_b \mid R_b > 0)}$$
      $$\beta^- = \frac{\text{Cov}(R_p, R_b \mid R_b < 0)}{\text{Var}(R_b \mid R_b < 0)}$$
    • Computes betaSpread = \beta^+ - \beta^-. A positive spread represents a convex payoff structure with high upside participation and defensive downside insulation.
    • Pairs directly with the Up/Down Capture Ratios added in feat(backtest): expand benchmark-relative metrics with Beta, Jensen's Alpha, Treynor, and Capture Ratios #303.
  3. Batting Average & Outperformance Payoff Ratio:
    • battingAverage: Percentage of aligned observation periods where portfolio return strictly outperformed benchmark return:
      $$\text{Batting Average} = \frac{\sum_{t=1}^T \mathbb{I}(R_{p,t} > R_{b,t})}{T}$$
    • outperformancePayoffRatio: Ratio of average active return during winning periods to average active loss during losing periods.
    • Also records outperformancePeriods and underperformancePeriods.
  4. Comprehensive Integration & Full Backward Compatibility:
    • Seamlessly integrated into calculate_benchmark_relative_metrics, populating mSquaredStatus, dualBetaStatus, battingStatus, and associated fields in result["benchmarkRelativeMetrics"].
    • Standalone functions exposed in __all__: calculate_m_squared, calculate_dual_beta, and calculate_batting_average.
    • 100% backward-compatible with existing callers.
  5. Documentation:
    • Updated docs/product/BACKTEST_CENTER.md and docs/product/BACKTEST_CENTER_CN.md with mathematical formulas and explanations.

Related issue

Changes

  • backend_api_python/app/services/backtest/metrics.py:
    • Implement _calculate_m_squared_metrics, _calculate_dual_beta_metrics, and _calculate_batting_metrics.
    • Implement calculate_m_squared, calculate_dual_beta, and calculate_batting_average.
    • Wire new metrics into calculate_benchmark_relative_metrics.
    • Export new functions in __all__.
  • backend_api_python/tests/test_backtest_metrics.py:
    • Add unit tests for $M^2$ (known values, positive risk-free rate, zero portfolio/benchmark variance, input validation).
    • Add unit tests for Dual-Beta (known values, upside/downside regime filtering, single-regime curves).
    • Add unit tests for Batting Average and Outperformance Payoff Ratio (known values, all-win edge case).
    • Add integration test for calculate_benchmark_relative_metrics.
  • docs/product/BACKTEST_CENTER.md & BACKTEST_CENTER_CN.md:
    • Document $M^2$, Dual-Beta, and Batting Average in English and Chinese.

Test plan

  • pytest backend_api_python/tests/test_backtest_metrics.py passes (31/31 tests)
  • pytest backend_api_python/tests/test_strategy_v2_service.py passes (30/30 tests)
  • ruff check app/services/backtest/metrics.py tests/test_backtest_metrics.py passes with zero violations
  • python backend_api_python/scripts/backend_quality_check.py passes
  • git diff --check passes with zero whitespace or line-ending issues

@brokermr810
brokermr810 merged commit 01c1cb8 into OpenByteInc:main Oct 24, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants