feat: instrument model

This commit is contained in:
OpenSquared
2026-07-03 14:48:00 +02:00
parent 05ee909ee4
commit 243375ff07

View File

@@ -1085,25 +1085,29 @@ def simulate_timeline(
structural_pips = round(float(vals_struct.get(output_id, 0.0)), 1)
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
# Guidance EMA : la baseline de la synthétique est l'EMA lissée du prix réel.
# synthetic_price(t) = EMA(t) + event_pips(t) × pip_to_price
# → sans event perturbateur : synthétique colle au lissé historique
# → avec events : déviation proportionnelle à leur contribution
ema_prices: dict[str, float] = {}
last_ema: float = fundamental_level_base # fallback si pas de données prix
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)
# 30j de warmup avant date_from pour que l'EMA soit stabilisée dès le début
warmup_from = str(date_from - timedelta(days=30))
ph_rows = conn.execute(
"""SELECT date, close FROM price_history_cache
WHERE instrument=? AND date>=? ORDER BY date ASC""",
(inst_upper, warmup_from)
).fetchall()
alpha = 0.15 # lissage EMA (~6j de demi-vie)
ema_val: Optional[float] = None
for r in ph_rows:
c = float(r["close"])
ema_val = c if ema_val is None else alpha * c + (1.0 - alpha) * ema_val
if r["date"] >= str(date_from):
ema_prices[r["date"]] = round(ema_val, 6)
if ema_prices:
last_ema = list(ema_prices.values())[-1]
except Exception:
pass
@@ -1150,13 +1154,23 @@ def simulate_timeline(
net = structural_pips
regime_label = "BALANCED"
# Guide price : EMA du prix réel si disponible, sinon dernier EMA connu (futur)
date_str = str(cur)
if date_str in ema_prices:
guide_price = ema_prices[date_str]
last_ema = guide_price
else:
guide_price = last_ema # dates futures : tient le dernier EMA connu
event_pips = round(net - structural_pips, 1)
timeline.append({
"date": str(cur),
"date": date_str,
"net_pips": net,
"structural_pips": structural_pips,
"event_pips": round(net - structural_pips, 1),
"fundamental_level": round(fundamental_level_base + start_offset, 6),
"synthetic_price": round(price_intercept + start_offset + net * pip_to_price, 6),
"event_pips": event_pips,
"fundamental_level": guide_price,
"synthetic_price": round(guide_price + event_pips * pip_to_price, 6),
"regime": regime_label,
"nodes": {k: round(float(v), 1) for k, v in vals.items()},
"active_events": active_events_detail,