88import hashlib
99import json
1010import tempfile
11+ from dataclasses import replace
1112from datetime import date
1213from pathlib import Path
1314from typing import Any
2122 SUPPORTED_PROFILES ,
2223 build_backtest_runner ,
2324)
25+ from crypto_strategies .backtest .live_pool_simulator import _performance_metrics
2426from crypto_strategies .strategies .crypto_equity_combo import PROFILE_NAME as CRYPTO_EQUITY_COMBO_PROFILE
2527
2628DEFAULT_WINDOWS : tuple [tuple [date , date ], ...] = (
@@ -177,6 +179,26 @@ def _write_return_matrix(
177179 frame .reset_index ().to_csv (output_path , index = False )
178180
179181
182+ def _baseline_from_return_tail (full_result : Any , returns : pd .Series ) -> Any :
183+ tail = returns .tail (DRIFT_BASELINE_HORIZON_DAYS )
184+ metrics = _performance_metrics (tail )
185+ max_drawdown = float (metrics ["Max Drawdown" ])
186+ cagr = float (metrics ["CAGR" ])
187+ return replace (
188+ full_result ,
189+ sharpe_ratio = float (metrics ["Sharpe" ]),
190+ calmar_ratio = abs (cagr / max_drawdown ) if max_drawdown else None ,
191+ max_drawdown = max_drawdown ,
192+ cagr = cagr ,
193+ volatility = float (metrics ["Annualized Volatility" ]),
194+ win_rate = float (metrics ["Win Rate" ]),
195+ total_return = float (metrics ["total_return" ]),
196+ start_date = tail .index .min ().date (),
197+ end_date = tail .index .max ().date (),
198+ observation_count = int (metrics ["Trading Days" ]),
199+ )
200+
201+
180202def run_walk_forward (
181203 * ,
182204 profile : str ,
@@ -214,7 +236,7 @@ def run_walk_forward(
214236 )
215237 full_start = min (start for start , _ in windows )
216238 baseline_end = max (end for _ , end in windows )
217- return_matrix_runner .run (
239+ full_window_raw = return_matrix_runner .run (
218240 profile ,
219241 copy .deepcopy (baseline_params ),
220242 start_date = full_start ,
@@ -223,19 +245,7 @@ def run_walk_forward(
223245 full_window_returns = return_matrix_runner .last_daily_returns
224246 if len (full_window_returns ) < DRIFT_BASELINE_HORIZON_DAYS :
225247 raise ValueError ("full-window returns do not cover the 126-day drift baseline" )
226- baseline_start = full_window_returns .index [- DRIFT_BASELINE_HORIZON_DAYS ].date ()
227- baseline_runner = _build_runner (
228- profile = profile ,
229- panel = shared_panel ,
230- market_history = shared_market_history ,
231- synthetic_days = synthetic_days ,
232- )
233- baseline_raw = baseline_runner .run (
234- profile ,
235- copy .deepcopy (baseline_params ),
236- start_date = baseline_start ,
237- end_date = baseline_end ,
238- )
248+ baseline_raw = _baseline_from_return_tail (full_window_raw , full_window_returns )
239249 with tempfile .TemporaryDirectory (prefix = f"{ profile } _wf_" , dir = target_root ) as scratch_dir :
240250 scratch_orchestrator = BacktestOrchestrator (store = PerformanceStore (local_root = Path (scratch_dir )))
241251 scratch_orchestrator .register_runner (
0 commit comments