fix: bootstrap IV history with 1y realized vol to unblock IV Rank from 50
IV Rank was stuck at 50 for all tickers because the formula returns 50.0 when iv_max == iv_min (not enough historical snapshots). Added: - bootstrap_iv_history(): downloads 1y of closes per ticker, computes 30d rolling realized vol (annualized), saves each day to iv_history - POST /api/options-vol/bootstrap-history endpoint (runs in background) - OptionsLab: auto-detect when IV Rank needs bootstrapping and show an amber banner with one-click "Initialiser historique" button Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -142,6 +142,24 @@ def refresh_watchlist(background_tasks: BackgroundTasks):
|
||||
return {"status": "refresh started", "tickers": len(__import__("services.iv_engine", fromlist=["IV_WATCHLIST"]).IV_WATCHLIST)}
|
||||
|
||||
|
||||
@router.post("/bootstrap-history")
|
||||
def bootstrap_iv_history_endpoint(background_tasks: BackgroundTasks, min_existing: int = 30):
|
||||
"""
|
||||
Bootstrap iv_history with 1 year of realized volatility for all watchlist tickers.
|
||||
Only fills missing dates — safe to call multiple times.
|
||||
Runs in background (takes ~30-60s for 18 tickers).
|
||||
"""
|
||||
def _run():
|
||||
from services.iv_engine import bootstrap_iv_history, IV_WATCHLIST
|
||||
logger.info(f"[IV Bootstrap] Starting for {len(IV_WATCHLIST)} tickers")
|
||||
result = bootstrap_iv_history(tickers=IV_WATCHLIST, min_existing=min_existing)
|
||||
total = sum(v.get("inserted", 0) for v in result.values() if isinstance(v, dict))
|
||||
logger.info(f"[IV Bootstrap] Done — {total} rows inserted across {len(result)} tickers")
|
||||
|
||||
background_tasks.add_task(_run)
|
||||
return {"status": "bootstrap started", "message": "Chargement historique 1 an réalisé vol — vérifier les logs dans ~60s"}
|
||||
|
||||
|
||||
@router.get("/for-trade/{underlying}")
|
||||
def get_iv_for_trade(underlying: str):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user