From 2a77007dc328938a277413ed70d54f65139861be Mon Sep 17 00:00:00 2001 From: OpenSquared Date: Sat, 20 Jun 2026 06:47:11 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20jauges=20macro=20+=20signaux=20d=C3=A9c?= =?UTF-8?q?lencheurs=20dans=20card=20R=C3=A9gime=20Macro?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Partie basse de la card : 5 indicateurs clés expliquant le régime (VIX, S&P vs 200j MA, Pente 10Y-3M, Cuivre, Or) avec couleur contextuelle et hint court, puis chips des signaux déclencheurs du régime dominant issus de scenarios.reasons[dominant]. Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/pages/Dashboard.tsx | 73 ++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/frontend/src/pages/Dashboard.tsx b/frontend/src/pages/Dashboard.tsx index c090f57..8b1609e 100644 --- a/frontend/src/pages/Dashboard.tsx +++ b/frontend/src/pages/Dashboard.tsx @@ -620,6 +620,45 @@ export default function Dashboard() { : dom === 'inflation_shock' ? 'text-orange-400' : 'text-slate-400' const ranked = macroInfo?.ranked ?? [] + + // Key gauges from macroData + const gauges = (macroData as any)?.gauges ?? {} + const reasons: string[] = dom ? ((macroData as any)?.scenarios?.reasons?.[dom] ?? []) : [] + + // 5 key indicators that explain the regime + const KEY_GAUGES = [ + { + key: 'vix', label: 'VIX', + color: (v: number) => v < 18 ? 'text-emerald-400' : v < 25 ? 'text-yellow-400' : 'text-red-400', + fmt: (v: number) => v.toFixed(1), + hint: (v: number) => v < 18 ? '↓ risque bas' : v < 25 ? '↑ alerte' : '↑ crise', + }, + { + key: 'spx_vs_200d', label: 'S&P/200j', + color: (v: number) => v >= 0 ? 'text-emerald-400' : 'text-red-400', + fmt: (v: number) => `${v >= 0 ? '+' : ''}${v.toFixed(1)}%`, + hint: (v: number) => v >= 5 ? 'bull fort' : v >= 0 ? 'bull mod.' : 'bear', + }, + { + key: 'slope_10y3m', label: 'Pente 10Y-3M', + color: (v: number) => v >= 0.5 ? 'text-emerald-400' : v >= 0 ? 'text-yellow-400' : 'text-red-400', + fmt: (v: number) => `${v >= 0 ? '+' : ''}${v.toFixed(2)}`, + hint: (v: number) => v >= 0.5 ? 'normale' : v >= 0 ? 'plate' : 'inversée', + }, + { + key: 'copper', label: 'Cuivre', + color: (v: number, chg: number) => chg >= 0 ? 'text-emerald-400' : 'text-red-400', + fmt: (v: number, chg: number) => `${chg >= 0 ? '+' : ''}${chg.toFixed(2)}%`, + hint: (v: number, chg: number) => chg >= 0 ? '↑ croissance' : '↓ ralentis.', + }, + { + key: 'gold', label: 'Or', + color: (v: number, chg: number) => chg >= 1 ? 'text-amber-400' : chg <= -1 ? 'text-emerald-400' : 'text-slate-400', + fmt: (v: number, chg: number) => `${chg >= 0 ? '+' : ''}${chg.toFixed(2)}%`, + hint: (v: number, chg: number) => chg >= 1 ? '↑ refuge' : chg <= -1 ? '↓ risk-on' : '≈ neutre', + }, + ] + return (
@@ -654,6 +693,40 @@ export default function Dashboard() { })}
)} + + {/* Key macro gauges */} + {Object.keys(gauges).length > 0 && ( +
+ {KEY_GAUGES.map(({ key, label, color, fmt, hint }) => { + const g = gauges[key] + if (!g) return null + const val: number = g.value ?? 0 + const chg: number = g.change_pct ?? 0 + const c = color(val, chg) + const h = hint(val, chg) + return ( +
+ {label} + + {fmt(val, chg)} + + {h} +
+ ) + })} +
+ )} + + {/* Trigger signals for dominant regime */} + {reasons.length > 0 && ( +
+ {reasons.slice(0, 4).map((r: string, i: number) => ( + + {r} + + ))} +
+ )} ) })()}