diff --git a/backend/services/option_chain.py b/backend/services/option_chain.py index 33ee838..634d9e0 100644 --- a/backend/services/option_chain.py +++ b/backend/services/option_chain.py @@ -48,7 +48,18 @@ def get_chain_slice( " — ajoutez-le à la watchlist (Config → Saxo) et attendez le prochain cycle de snapshot (~5 min)." ) - spot = next((r["spot"] for r in flat_rows if r.get("spot") is not None), None) + # Every accumulated row carries its OWN spot proxy (MidStrikePrice at the moment THAT + # contract's price last changed — see saxo_client.snapshot_options_chain). Rows here + # can span many expiries/strikes with very different last-changed times (dedup skips + # inserting when a contract's price is unchanged, so a quiet far-dated contract can + # sit on a stale row for days) — picking an arbitrary one is picking an arbitrary + # moment, not "the spot for this chain." Sort by created_at first so the freshest + # available proxy wins, deterministically. + spot_rows = sorted( + (r for r in flat_rows if r.get("spot") is not None and r.get("created_at")), + key=lambda r: r["created_at"], reverse=True, + ) + spot = spot_rows[0]["spot"] if spot_rows else next((r["spot"] for r in flat_rows if r.get("spot") is not None), None) snapshot_as_of = max((r["created_at"] for r in flat_rows if r.get("created_at")), default=None) reference_date = datetime.strptime(as_of[:10], "%Y-%m-%d").date() if as_of else date.today()