Initial commit — GeoOptions Intelligence Cockpit v2.0
Stack: FastAPI + React/TypeScript + SQLite + GPT-4o Features: Radar géopolitique, Marchés, Régime Macro, Journal de Bord MTM, Rapport IA, Super Contexte (base de raisonnement évolutive), Boucle feedback IA. Deploy: Docker + docker-compose + nginx pour openfin.open-squared.tech Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
77
backend/routers/market_data.py
Normal file
77
backend/routers/market_data.py
Normal file
@@ -0,0 +1,77 @@
|
||||
from fastapi import APIRouter, Query
|
||||
from typing import Optional, Dict, Any
|
||||
from datetime import datetime
|
||||
from services.data_fetcher import get_all_quotes, get_historical, compute_historical_iv, WATCHLIST
|
||||
|
||||
_macro_cache: Dict[str, Any] = {}
|
||||
|
||||
router = APIRouter(prefix="/api/market", tags=["market"])
|
||||
|
||||
|
||||
@router.get("/quotes")
|
||||
def quotes_all():
|
||||
return get_all_quotes()
|
||||
|
||||
|
||||
@router.get("/quote/{symbol}")
|
||||
def quote_single(symbol: str):
|
||||
from services.data_fetcher import get_quote
|
||||
return get_quote(symbol)
|
||||
|
||||
|
||||
@router.get("/history/{symbol}")
|
||||
def history(
|
||||
symbol: str,
|
||||
period: str = Query("1y", description="1d,5d,1mo,3mo,6mo,1y,2y,5y"),
|
||||
interval: str = Query("1d", description="1m,5m,15m,1h,1d,1wk,1mo"),
|
||||
):
|
||||
return get_historical(symbol, period, interval)
|
||||
|
||||
|
||||
@router.get("/iv/{symbol}")
|
||||
def implied_vol(symbol: str, window: int = 30):
|
||||
iv = compute_historical_iv(symbol, window)
|
||||
return {"symbol": symbol, "iv": iv, "window": window}
|
||||
|
||||
|
||||
@router.get("/watchlist")
|
||||
def watchlist():
|
||||
return WATCHLIST
|
||||
|
||||
|
||||
@router.get("/macro-regime")
|
||||
def macro_regime(force: bool = False):
|
||||
"""Macro gauge values + 5-scenario scoring. Cached 15 min."""
|
||||
from services.data_fetcher import get_macro_gauges, score_macro_scenarios
|
||||
now = datetime.utcnow()
|
||||
if not force and _macro_cache.get("data") and _macro_cache.get("ts"):
|
||||
age = (now - _macro_cache["ts"]).total_seconds()
|
||||
if age < 900:
|
||||
return {**_macro_cache["data"], "cached": True, "cache_age_sec": int(age)}
|
||||
gauges = get_macro_gauges()
|
||||
scenarios = score_macro_scenarios(gauges)
|
||||
result: Dict[str, Any] = {
|
||||
"gauges": gauges,
|
||||
"scenarios": scenarios,
|
||||
"fetched_at": now.isoformat(),
|
||||
"cached": False,
|
||||
}
|
||||
_macro_cache["data"] = result
|
||||
_macro_cache["ts"] = now
|
||||
|
||||
if force:
|
||||
# Build a compact gauge summary (key → value + change_pct) for the journal
|
||||
gauges_summary = {
|
||||
k: {"value": v.get("value"), "change_pct": v.get("change_pct"), "label": v.get("label")}
|
||||
for k, v in gauges.items()
|
||||
if v.get("value") is not None or v.get("change_pct") is not None
|
||||
}
|
||||
from services.database import log_macro_regime
|
||||
log_macro_regime(
|
||||
dominant=scenarios.get("dominant", "incertain"),
|
||||
scores=scenarios.get("scores", {}),
|
||||
reasons=scenarios.get("reasons", {}),
|
||||
gauges_summary=gauges_summary,
|
||||
)
|
||||
|
||||
return result
|
||||
Reference in New Issue
Block a user