feat: instrument model
This commit is contained in:
@@ -1679,6 +1679,23 @@ def simulate_timeline(
|
||||
if v0 is not None:
|
||||
macro_last[node_id] = v0
|
||||
|
||||
# Catégories d'events gérées par les nœuds input_event du graphe
|
||||
# Les catégories sans nœud correspondant sont appliquées comme choc direct sur l'output.
|
||||
graph_event_cats: set[str] = {
|
||||
n.get("event_category", "")
|
||||
for n in graph_def.get("nodes", [])
|
||||
if n.get("node_type") == "input_event"
|
||||
} - {""}
|
||||
|
||||
# Baseline linéaire pour la sensibilité temporelle des nœuds macro
|
||||
# Utilisé uniquement pour calculer le DELTA par rapport au point d'ancrage.
|
||||
# Le linéaire amplifie la sensibilité aux changements de taux/CPI/NFP qui
|
||||
# sinon disparaissent dans la zone de saturation tanh.
|
||||
base_linear_pips = float(evaluate_graph(
|
||||
_graph_json_for_eval(graph_def, {}),
|
||||
_build_inputs(graph_def, overrides, {}, saturation=False)
|
||||
).get(output_id, 0.0)) if has_macro else 0.0
|
||||
|
||||
timeline = []
|
||||
cur = date_from
|
||||
while cur <= today:
|
||||
@@ -1706,6 +1723,10 @@ def simulate_timeline(
|
||||
"category": cat,
|
||||
})
|
||||
|
||||
# Split ev_by_cat : catégories avec nœud dédié vs choc direct
|
||||
routed_ev = {cat: v for cat, v in ev_by_cat.items() if cat in graph_event_cats}
|
||||
direct_shock = sum(v for cat, v in ev_by_cat.items() if cat not in graph_event_cats)
|
||||
|
||||
# ── Overrides pour ce jour (statiques + time-varying macro) ───────────
|
||||
if has_macro:
|
||||
cur_overrides = dict(overrides)
|
||||
@@ -1718,18 +1739,26 @@ def simulate_timeline(
|
||||
if v is not None:
|
||||
cur_overrides[node_id] = {"value": v, "note": "macro_guidance", "set_at": ""}
|
||||
|
||||
# Structural pips time-varying (sans events, avec macro overrides du jour)
|
||||
# Structural pips : baseline saturé + delta linéaire (sensibilité amplifiée)
|
||||
gj_s = _graph_json_for_eval(graph_def, {})
|
||||
in_s = _build_inputs(graph_def, cur_overrides, {}, saturation=True)
|
||||
vs_s = evaluate_graph(gj_s, in_s)
|
||||
structural_pips_t = round(float(vs_s.get(output_id, 0.0)), 1)
|
||||
sat_pips_t = float(vs_s.get(output_id, 0.0))
|
||||
|
||||
# Delta linéaire = (linéaire_courant − linéaire_base) → sensibilité temporelle
|
||||
in_s_lin = _build_inputs(graph_def, cur_overrides, {}, saturation=False)
|
||||
vs_s_lin = evaluate_graph(gj_s, in_s_lin)
|
||||
lin_pips_t = float(vs_s_lin.get(output_id, 0.0))
|
||||
delta_lin = lin_pips_t - base_linear_pips
|
||||
|
||||
structural_pips_t = round(sat_pips_t + delta_lin, 1)
|
||||
|
||||
if ev_by_cat:
|
||||
ri = detect_regime(ev_by_cat)
|
||||
gj_ = _graph_json_for_eval(graph_def, ri["weights"])
|
||||
in_ = _build_inputs(graph_def, cur_overrides, ev_by_cat, saturation=True)
|
||||
in_ = _build_inputs(graph_def, cur_overrides, routed_ev, saturation=True)
|
||||
vals = evaluate_graph(gj_, in_)
|
||||
net = round(float(vals.get(output_id, 0.0)), 1)
|
||||
net = round(float(vals.get(output_id, 0.0)) + delta_lin + direct_shock, 1)
|
||||
regime_label = ri["regime"]
|
||||
else:
|
||||
vals = vs_s
|
||||
@@ -1741,9 +1770,9 @@ def simulate_timeline(
|
||||
if ev_by_cat:
|
||||
ri = detect_regime(ev_by_cat)
|
||||
gj = _graph_json_for_eval(graph_def, ri["weights"])
|
||||
inputs = _build_inputs(graph_def, overrides, ev_by_cat, saturation=True)
|
||||
inputs = _build_inputs(graph_def, overrides, routed_ev, saturation=True)
|
||||
vals = evaluate_graph(gj, inputs)
|
||||
net = round(float(vals.get(output_id, 0.0)), 1)
|
||||
net = round(float(vals.get(output_id, 0.0)) + direct_shock, 1)
|
||||
regime_label = ri["regime"]
|
||||
else:
|
||||
vals = vals_struct
|
||||
|
||||
Reference in New Issue
Block a user