feat: strategy builder

This commit is contained in:
OpenSquared
2026-07-30 14:48:20 +02:00
parent d85c0348d8
commit efe29cef53
5 changed files with 412 additions and 44 deletions

View File

@@ -41,6 +41,12 @@ class ScenarioIn(BaseModel):
# options (e.g. dte_min=20, dte_max=60) instead of horizon_days doing double duty.
dte_min: Optional[int] = None
dte_max: Optional[int] = None
# "Dériver d'un historique" mode: reconstruct the chain (and every leg strike drawn
# from it, including in /optimize) as it stood at/before this date instead of live —
# e.g. so the optimizer searches over what was ACTUALLY quoted on the day a realized
# scenario's window starts, not today's chain. None (default) = live, unchanged
# behavior for the normal Construire flow.
as_of: Optional[str] = None
@property
def shocked_rate(self) -> float:
@@ -118,7 +124,7 @@ class StrategySaveRequest(BaseModel):
def _build_surfaces(scenario: ScenarioIn):
chain_slice = get_chain_slice(
scenario.symbol, scenario.horizon_days, scenario.n_expiries,
dte_min=scenario.dte_min, dte_max=scenario.dte_max,
dte_min=scenario.dte_min, dte_max=scenario.dte_max, as_of=scenario.as_of,
)
surface_now = build_surface(chain_slice)
surface_scenario = apply_scenario(
@@ -206,6 +212,20 @@ def price(req: PriceRequest):
return result
@router.get("/realized-scenario")
def realized_scenario(symbol: str = Query(...), start_date: str = Query(...), end_date: str = Query(...)):
""""Dériver d'un historique" mode: turns a real Du→Au window into scenario inputs
(spot_shock_pct/iv_level_shift/horizon_days) computed from what actually happened —
see services.realized_scenario. The frontend copies these into the normal scenario
state (same one Construire/optimize use) rather than this being a separate pricing
path of its own."""
from services.realized_scenario import compute_realized_scenario
try:
return compute_realized_scenario(symbol, start_date, end_date)
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
@router.post("/suggested-profile")
def suggested_profile(scenario: ScenarioIn):
"""Mode 1 of the scenario/profile/constraints split: what Greek behavior this scenario