44from __future__ import annotations
55
66import argparse
7+ import copy
8+ import hashlib
79import json
10+ import re
811from datetime import date
912from pathlib import Path
1013from typing import Any
@@ -45,6 +48,40 @@ def _result_payload(item: Any) -> dict[str, Any]:
4548 }
4649
4750
51+ def _baseline_param_set_id (profile : str , params : dict [str , Any ]) -> str :
52+ fingerprint = hashlib .sha256 (json .dumps (params , sort_keys = True , default = str ).encode ("utf-8" )).hexdigest ()[:12 ]
53+ return f"{ profile } _baseline_{ fingerprint } "
54+
55+
56+ def _current_qpk_pin () -> str :
57+ text = (Path (__file__ ).resolve ().parents [1 ] / "qsl.toml" ).read_text (encoding = "utf-8" )
58+ match = re .search (r"QuantPlatformKit\.git@([0-9a-f]{40})" , text )
59+ return match .group (1 ) if match else "unknown"
60+
61+
62+ def _baseline_identity_params (
63+ params : dict [str , Any ],
64+ * ,
65+ synthetic_days : int ,
66+ baseline_result : Any ,
67+ ) -> dict [str , Any ]:
68+ identity = copy .deepcopy (params )
69+ identity ["_baseline_start_date" ] = baseline_result .start_date .isoformat () if baseline_result .start_date else None
70+ identity ["_baseline_end_date" ] = baseline_result .end_date .isoformat () if baseline_result .end_date else None
71+ identity ["_qpk_pin" ] = _current_qpk_pin ()
72+ identity ["_synthetic_days" ] = synthetic_days
73+ return identity
74+
75+
76+ def _build_runner (* , profile : str , synthetic_days : int , panel : Any = None , market_history : Any = None ):
77+ return build_backtest_runner (
78+ profile ,
79+ panel = panel ,
80+ market_history = market_history ,
81+ synthetic_days = synthetic_days ,
82+ )
83+
84+
4885def run_walk_forward (
4986 * ,
5087 profile : str ,
@@ -61,21 +98,43 @@ def run_walk_forward(
6198 raise ValueError (f"unsupported profile={ profile !r} ; supported={ sorted (SUPPORTED_PROFILES )} " )
6299
63100 params = dict (PROFILE_DEFAULTS .get (profile , {"min_history_days" : DEFAULT_MIN_HISTORY_DAYS }))
64- runner = build_backtest_runner (
65- profile ,
101+ store = PerformanceStore (local_root = store_root ) if store_root is not None else PerformanceStore .from_env ()
102+ orchestrator = BacktestOrchestrator (store = store )
103+
104+ baseline_params = copy .deepcopy (params )
105+ runner = _build_runner (
106+ profile = profile ,
66107 panel = panel ,
67108 market_history = market_history ,
68109 synthetic_days = synthetic_days ,
69110 )
70- store = PerformanceStore (local_root = store_root or Path ("/tmp/crypto_wf_store" ))
71- orchestrator = BacktestOrchestrator (store = store )
72111 orchestrator .register_runner ("crypto" , runner )
73-
74- baseline = runner .run (profile , params )
112+ baseline_probe = orchestrator .run (
113+ profile ,
114+ domain = "crypto" ,
115+ params = copy .deepcopy (baseline_params ),
116+ param_set_id = "__discarded__" ,
117+ start_date = None ,
118+ end_date = None ,
119+ )
120+ baseline_store_params = _baseline_identity_params (
121+ baseline_params ,
122+ synthetic_days = synthetic_days ,
123+ baseline_result = baseline_probe ,
124+ )
125+ baseline = orchestrator .run (
126+ profile ,
127+ domain = "crypto" ,
128+ params = baseline_store_params ,
129+ param_set_id = _baseline_param_set_id (profile , baseline_store_params ),
130+ start_date = None ,
131+ end_date = None ,
132+ )
133+ wf_params = copy .deepcopy (params )
75134 wf_results = orchestrator .walk_forward (
76135 profile ,
77136 domain = "crypto" ,
78- params = params ,
137+ params = wf_params ,
79138 windows = windows ,
80139 param_set_id = f"{ profile } _wf" ,
81140 )
0 commit comments