@@ -253,3 +253,58 @@ def test_global_etf_rotation_keeps_default_cash_reserve(strategy_module_factory)
253253 )
254254
255255 assert module .CASH_RESERVE_RATIO == pytest .approx (0.03 )
256+
257+
258+ def test_compute_signals_exposes_dry_run_price_fallbacks (strategy_module_factory , tmp_path ):
259+ pytest .importorskip ("pandas" )
260+
261+ snapshot_path = tmp_path / "snapshot.csv"
262+ config_path = tmp_path / "tech_pullback_cash_buffer.json"
263+ snapshot_path .write_text (
264+ "\n " .join (
265+ [
266+ "as_of,symbol,sector,close,adv20_usd,history_days,mom_6_1,mom_12_1,sma20_gap,sma50_gap,sma200_gap,ma50_over_ma200,vol_63,maxdd_126,breakout_252,dist_63_high,dist_126_high,rebound_20,base_eligible" ,
267+ "2026-03-31,QQQ,benchmark,500,1000000000,400,0.20,0.30,0.03,0.05,0.08,0.04,0.22,-0.12,-0.01,-0.03,-0.05,0.04,false" ,
268+ "2026-03-31,BOXX,defense,101,20000000,400,0.02,0.04,0.00,0.00,0.01,0.00,0.03,-0.01,0.00,-0.01,-0.01,0.00,false" ,
269+ "2026-03-31,AAPL,Information Technology,200,150000000,400,0.20,0.35,0.03,0.05,0.10,0.05,0.18,-0.08,-0.01,-0.03,-0.05,0.05,true" ,
270+ "2026-03-31,MSFT,Information Technology,350,150000000,400,0.18,0.33,0.03,0.05,0.09,0.04,0.17,-0.09,-0.02,-0.04,-0.06,0.04,true" ,
271+ ]
272+ ),
273+ encoding = "utf-8" ,
274+ )
275+ config_path .write_text (
276+ json .dumps (
277+ {
278+ "name" : "tech_pullback_cash_buffer" ,
279+ "family" : "tech_heavy_pullback" ,
280+ "branch_role" : "cash-buffered parallel branch" ,
281+ "benchmark_symbol" : "QQQ" ,
282+ "holdings_count" : 2 ,
283+ "single_name_cap" : 0.5 ,
284+ "sector_cap" : 1.0 ,
285+ "hold_bonus" : 0.0 ,
286+ "min_adv20_usd" : 1.0 ,
287+ "normalization" : "universe_cross_sectional" ,
288+ "score_template" : "balanced_pullback" ,
289+ "sector_whitelist" : ["Information Technology" ],
290+ "breadth_thresholds" : {"soft" : 0.55 , "hard" : 0.35 },
291+ "exposures" : {"risk_on" : 1.0 , "soft_defense" : 1.0 , "hard_defense" : 0.0 },
292+ "execution_cash_reserve_ratio" : 0.0 ,
293+ "residual_proxy" : "simple_excess_return_vs_QQQ" ,
294+ }
295+ ),
296+ encoding = "utf-8" ,
297+ )
298+ _write_cash_buffer_manifest (snapshot_path , config_path , snapshot_as_of = "2026-03-31" )
299+
300+ module = strategy_module_factory (
301+ STRATEGY_PROFILE = "tech_pullback_cash_buffer" ,
302+ IBKR_FEATURE_SNAPSHOT_PATH = str (snapshot_path ),
303+ IBKR_FEATURE_SNAPSHOT_MANIFEST_PATH = str (Path (f"{ snapshot_path } .manifest.json" )),
304+ IBKR_STRATEGY_CONFIG_PATH = str (config_path ),
305+ IBKR_RUN_AS_OF_DATE = "2026-04-01" ,
306+ )
307+ result = module .compute_signals (None , set ())
308+
309+ assert result [4 ]["dry_run_price_fallbacks" ]["BOXX" ] == pytest .approx (101.0 )
310+ assert result [4 ]["dry_run_price_fallbacks" ]["AAPL" ] == pytest .approx (200.0 )
0 commit comments