feat: instrument model
This commit is contained in:
@@ -200,8 +200,11 @@ def get_instrument_timeline(
|
|||||||
"""Simulation jour par jour de tous les nœuds du modèle sur la période."""
|
"""Simulation jour par jour de tous les nœuds du modèle sur la période."""
|
||||||
from services.database import get_conn
|
from services.database import get_conn
|
||||||
from services.instrument_models import simulate_timeline
|
from services.instrument_models import simulate_timeline
|
||||||
|
from services.price_history import get_price_history
|
||||||
conn = get_conn()
|
conn = get_conn()
|
||||||
try:
|
try:
|
||||||
|
# Pré-peupler le cache prix pour que l'auto-anchor ait les données disponibles
|
||||||
|
get_price_history(conn, instrument.upper(), period)
|
||||||
data = simulate_timeline(conn, instrument.upper(), period)
|
data = simulate_timeline(conn, instrument.upper(), period)
|
||||||
if not data:
|
if not data:
|
||||||
raise HTTPException(status_code=404, detail=f"Modèle introuvable pour {instrument.upper()}")
|
raise HTTPException(status_code=404, detail=f"Modèle introuvable pour {instrument.upper()}")
|
||||||
@@ -218,8 +221,11 @@ def timeline_whatif(
|
|||||||
"""Simulation what-if avec events virtuels injectés dans la timeline."""
|
"""Simulation what-if avec events virtuels injectés dans la timeline."""
|
||||||
from services.database import get_conn
|
from services.database import get_conn
|
||||||
from services.instrument_models import simulate_timeline
|
from services.instrument_models import simulate_timeline
|
||||||
|
from services.price_history import get_price_history
|
||||||
conn = get_conn()
|
conn = get_conn()
|
||||||
try:
|
try:
|
||||||
|
# Garantir que le cache prix est disponible pour l'auto-anchor
|
||||||
|
get_price_history(conn, instrument.upper(), body.period)
|
||||||
ve_list = [ve.dict() for ve in body.virtual_events]
|
ve_list = [ve.dict() for ve in body.virtual_events]
|
||||||
data = simulate_timeline(conn, instrument.upper(), body.period, virtual_events=ve_list)
|
data = simulate_timeline(conn, instrument.upper(), body.period, virtual_events=ve_list)
|
||||||
if not data:
|
if not data:
|
||||||
|
|||||||
@@ -1077,6 +1077,28 @@ def simulate_timeline(
|
|||||||
structural_pips = round(float(vals_struct.get(output_id, 0.0)), 1)
|
structural_pips = round(float(vals_struct.get(output_id, 0.0)), 1)
|
||||||
fundamental_level_base = round(price_intercept + structural_pips * pip_to_price, 6)
|
fundamental_level_base = round(price_intercept + structural_pips * pip_to_price, 6)
|
||||||
|
|
||||||
|
# Auto-anchor : caler le niveau fondamental sur le prix réel au début de la fenêtre.
|
||||||
|
# start_offset = prix_réel_début - niveau_fondamental_machine
|
||||||
|
# → synthetic_price(t) = prix_réel_début + event_pips(t) * pip_to_price
|
||||||
|
start_offset = 0.0
|
||||||
|
try:
|
||||||
|
ph_row = conn.execute(
|
||||||
|
"""SELECT close FROM price_history_cache
|
||||||
|
WHERE instrument=? AND date>=? ORDER BY date ASC LIMIT 1""",
|
||||||
|
(inst_upper, str(date_from))
|
||||||
|
).fetchone()
|
||||||
|
if ph_row is None:
|
||||||
|
# Weekends/jours fériés : on remonte jusqu'à 7 jours avant
|
||||||
|
ph_row = conn.execute(
|
||||||
|
"""SELECT close FROM price_history_cache
|
||||||
|
WHERE instrument=? AND date>=? ORDER BY date ASC LIMIT 1""",
|
||||||
|
(inst_upper, str(date_from - timedelta(days=7)))
|
||||||
|
).fetchone()
|
||||||
|
if ph_row:
|
||||||
|
start_offset = round(float(ph_row["close"]) - fundamental_level_base, 6)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
timeline = []
|
timeline = []
|
||||||
cur = date_from
|
cur = date_from
|
||||||
while cur <= today:
|
while cur <= today:
|
||||||
@@ -1111,8 +1133,8 @@ def simulate_timeline(
|
|||||||
"net_pips": net,
|
"net_pips": net,
|
||||||
"structural_pips": structural_pips,
|
"structural_pips": structural_pips,
|
||||||
"event_pips": round(net - structural_pips, 1),
|
"event_pips": round(net - structural_pips, 1),
|
||||||
"fundamental_level": fundamental_level_base,
|
"fundamental_level": round(fundamental_level_base + start_offset, 6),
|
||||||
"synthetic_price": round(price_intercept + net * pip_to_price, 6),
|
"synthetic_price": round(price_intercept + start_offset + net * pip_to_price, 6),
|
||||||
"regime": regime_label,
|
"regime": regime_label,
|
||||||
"nodes": {k: round(float(v), 1) for k, v in vals.items()},
|
"nodes": {k: round(float(v), 1) for k, v in vals.items()},
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user