feat: strategy builder

This commit is contained in:
OpenSquared
2026-07-31 12:12:24 +02:00
parent 49ebd75522
commit cc22cbd3e0
6 changed files with 316 additions and 246 deletions

View File

@@ -274,14 +274,23 @@ def optimize(
dte_max: Optional[int] = None,
greek_profile: Optional[Dict[str, Any]] = None,
as_of: Optional[str] = None,
checkpoint_as_of: Optional[str] = None,
) -> List[Dict[str, Any]]:
r = rate + rate_shock_bps / 10000.0
chain_slice = get_chain_slice(symbol, horizon_days, n_expiries, dte_min=dte_min, dte_max=dte_max, as_of=as_of)
surface_now = build_surface(chain_slice)
surface_scenario = apply_scenario(
surface_now, spot_shock_pct=spot_shock_pct, iv_level_shift=iv_level_shift,
skew_tilt=skew_tilt, term_slope_shift=term_slope_shift, manual_grid=manual_grid,
)
if checkpoint_as_of:
# Real smile-of-the-day (same fitting as surface_now) instead of a parametric
# shock — see routers.strategy_builder.ScenarioIn.checkpoint_as_of. Surface and
# ScenarioSurface share the same .spot/.iv_at() interface, so every candidate
# evaluated below (_evaluate/_residual_search) needs no change.
checkpoint_chain = get_chain_slice(symbol, horizon_days, n_expiries, dte_min=dte_min, dte_max=dte_max, as_of=checkpoint_as_of)
surface_scenario = build_surface(checkpoint_chain)
else:
surface_scenario = apply_scenario(
surface_now, spot_shock_pct=spot_shock_pct, iv_level_shift=iv_level_shift,
skew_tilt=skew_tilt, term_slope_shift=term_slope_shift, manual_grid=manual_grid,
)
candidates = generate_all(chain_slice)
scored: List[Dict[str, Any]] = []