feat: cockpit

This commit is contained in:
OpenSquared
2026-07-27 08:29:55 +02:00
parent a08e8e1b11
commit ce09159bfb
4 changed files with 48 additions and 12 deletions

View File

@@ -63,7 +63,8 @@ def mark_to_market(pos: Dict[str, Any]) -> Dict[str, Any]:
days_to_expiry = T * 365
r = 0.05
chain, surface = resolve_saxo_chain(underlying, target_days=max(int(days_to_expiry), 1))
chain, surface = resolve_saxo_chain(underlying, target_days=max(int(days_to_expiry), 1),
sanity_reference=pos.get("entry_underlying_price"))
# yfinance fallback inputs — only actually fetched if no usable Saxo chain, so a
# Saxo-linked instrument never pays for a yfinance round-trip it doesn't need.
@@ -276,13 +277,18 @@ def add_pos(req: AddPositionRequest):
# Underlying price — Saxo option chain's own spot first (real, and consistent with
# whatever prices the legs below), yfinance only if this underlying has no
# saxo_option_symbol link at all (Config -> Instruments Watchlist -> "Option").
chain, surface = resolve_saxo_chain(normalized, target_days=data.get("expiry_days", 90))
# saxo_option_symbol link at all (Config -> Instruments Watchlist -> "Option"). The
# yfinance quote is fetched unconditionally (cheap, one-time at creation) to also
# serve as resolve_saxo_chain's sanity_reference — guards against a Saxo chain whose
# spot is on a different scale (observed on COMEX copper, ~100x too large).
q = get_quote(normalized)
yf_spot = q.get("price") if q else None
chain, surface = resolve_saxo_chain(normalized, target_days=data.get("expiry_days", 90),
sanity_reference=yf_spot)
S = chain["spot"] if chain else None
sigma = None
if S is None:
q = get_quote(normalized)
S = q.get("price") if q else None
S = yf_spot
if S is not None:
sigma = compute_historical_iv(req.underlying)
if not S: