| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- from __future__ import annotations
- import json
- import tempfile
- import unittest
- from pathlib import Path
- from src.backtest.compare import build_rows, render_markdown_table
- class CompareTests(unittest.TestCase):
- def test_build_rows_includes_momentum_profile_cost_label_and_relative_columns(self) -> None:
- temp_dir = tempfile.TemporaryDirectory()
- self.addCleanup(temp_dir.cleanup)
- root = Path(temp_dir.name)
- backtests_root = root / "outputs" / "backtests"
- result_dir = backtests_root / "demo_strategy"
- result_dir.mkdir(parents=True, exist_ok=True)
- (result_dir / "summary.json").write_text(
- json.dumps(
- {
- "cumulative_return": 0.20,
- "annual_return": 0.05,
- "max_drawdown": -0.10,
- "annual_volatility": 0.20,
- "sharpe": 0.25,
- "calmar": 0.50,
- "turnover": 12.0,
- "rebalance_count": 8,
- "cash_days_ratio": 0.10,
- }
- ),
- encoding="utf-8",
- )
- (result_dir / "benchmark_summary.json").write_text(
- json.dumps(
- {
- "equal_weight": {"cumulative_return": 0.15},
- "hs300": {"cumulative_return": 0.08},
- "chinext50": {"cumulative_return": 0.30},
- }
- ),
- encoding="utf-8",
- )
- frame = build_rows(
- backtests_root=backtests_root,
- strategy_configs={
- "demo_strategy": {
- "name": "demo_strategy",
- "top_n": 1,
- "rebalance_frequency": "every_5_days",
- "risk_penalty_multiplier": 0.5,
- "commission_bps": 7.5,
- "slippage_bps": 7.5,
- "momentum_weights": {
- "ret_5d": 0.25,
- "ret_10d": 0.25,
- "ret_20d": 0.30,
- "ret_60d": 0.20,
- },
- }
- },
- cost_scenarios={10.0: "optimistic", 15.0: "base", 20.0: "conservative"},
- )
- self.assertEqual(len(frame.index), 1)
- row = frame.iloc[0]
- self.assertEqual(row["cost_scenario"], "base")
- self.assertEqual(row["momentum_profile"], "5d=0.25, 10d=0.25, 20d=0.30, 60d=0.20")
- self.assertAlmostEqual(row["vs_equal_weight_cum"], 0.05)
- self.assertAlmostEqual(row["vs_hs300_cum"], 0.12)
- self.assertAlmostEqual(row["vs_chinext50_cum"], -0.10)
- markdown = render_markdown_table(frame)
- self.assertIn("Top1 Every 5 Days P05 Base 15bp Momentum Experiment", markdown)
- self.assertIn("5d=0.25, 10d=0.25, 20d=0.30, 60d=0.20", markdown)
- if __name__ == "__main__":
- unittest.main()
|