feat: instrument model
This commit is contained in:
@@ -23,6 +23,26 @@ class BulkOverrideBody(BaseModel):
|
||||
overrides: List[BulkOverrideItem]
|
||||
|
||||
|
||||
class VirtualEvent(BaseModel):
|
||||
date: str
|
||||
category: str = "unclassified"
|
||||
pips: float = 0.0
|
||||
label: str = "Event virtuel"
|
||||
absorption_days: int = 14
|
||||
rise_days: int = 1
|
||||
plateau_days: int = 0
|
||||
decay_type: str = "exp"
|
||||
|
||||
|
||||
class WhatIfBody(BaseModel):
|
||||
period: str = "1y"
|
||||
virtual_events: List[VirtualEvent] = []
|
||||
|
||||
|
||||
class CalibrateBody(BaseModel):
|
||||
ref_date: Optional[str] = None
|
||||
|
||||
|
||||
@router.get("", response_model=List[Dict[str, Any]])
|
||||
def list_instrument_models():
|
||||
from services.database import get_conn
|
||||
@@ -136,6 +156,32 @@ def get_instrument_regime(
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.get("/{instrument}/price-history")
|
||||
def get_price_history(
|
||||
instrument: str,
|
||||
period: str = Query("1y", description="5d|1mo|3mo|6mo|1y|2y"),
|
||||
refresh: bool = Query(False),
|
||||
) -> Dict[str, Any]:
|
||||
"""Cours historiques réels depuis yfinance (cache SQLite 6h)."""
|
||||
from services.database import get_conn
|
||||
from services.price_history import get_price_history as fetch_prices
|
||||
from services.instrument_models import INSTRUMENT_MODELS
|
||||
conn = get_conn()
|
||||
try:
|
||||
inst = instrument.upper()
|
||||
prices = fetch_prices(conn, inst, period, force_refresh=refresh)
|
||||
meta = INSTRUMENT_MODELS.get(inst, {})
|
||||
return {
|
||||
"instrument": inst,
|
||||
"ticker": meta.get("yf_ticker", ""),
|
||||
"period": period,
|
||||
"n_points": len(prices),
|
||||
"prices": prices,
|
||||
}
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.get("/{instrument}/timeline")
|
||||
def get_instrument_timeline(
|
||||
instrument: str,
|
||||
@@ -154,6 +200,56 @@ def get_instrument_timeline(
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.post("/{instrument}/timeline-whatif")
|
||||
def timeline_whatif(
|
||||
instrument: str,
|
||||
body: WhatIfBody,
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Simulation what-if avec events virtuels injectés dans la timeline."""
|
||||
from services.database import get_conn
|
||||
from services.instrument_models import simulate_timeline
|
||||
conn = get_conn()
|
||||
try:
|
||||
ve_list = [ve.dict() for ve in body.virtual_events]
|
||||
data = simulate_timeline(conn, instrument.upper(), body.period, virtual_events=ve_list)
|
||||
if not data:
|
||||
raise HTTPException(status_code=404, detail=f"Modèle introuvable pour {instrument.upper()}")
|
||||
return data
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.post("/{instrument}/calibrate")
|
||||
def calibrate_intercept(
|
||||
instrument: str,
|
||||
body: CalibrateBody,
|
||||
) -> Dict[str, Any]:
|
||||
"""Auto-calcule l'intercept depuis le cours réel à une date de référence."""
|
||||
from services.database import get_conn
|
||||
from services.instrument_models import get_model_state, INSTRUMENT_MODELS
|
||||
from services.price_history import calibrate_intercept as do_calibrate, get_price_history
|
||||
conn = get_conn()
|
||||
try:
|
||||
inst = instrument.upper()
|
||||
state = get_model_state(conn, inst, body.ref_date)
|
||||
if not state:
|
||||
raise HTTPException(status_code=404, detail=f"Modèle introuvable")
|
||||
# Make sure prices are cached
|
||||
get_price_history(conn, inst, "3mo")
|
||||
intercept = do_calibrate(conn, inst, state["structural_pips"], body.ref_date)
|
||||
meta = INSTRUMENT_MODELS.get(inst, {})
|
||||
return {
|
||||
"instrument": inst,
|
||||
"ref_date": body.ref_date,
|
||||
"structural_pips": state["structural_pips"],
|
||||
"pip_to_price": meta.get("pip_to_price", 0.0001),
|
||||
"calibrated_intercept": intercept,
|
||||
"current_intercept": meta.get("price_intercept", 0.0),
|
||||
}
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.get("/{instrument}")
|
||||
def get_instrument_model(
|
||||
instrument: str,
|
||||
|
||||
Reference in New Issue
Block a user