feat: jauges macro + signaux déclencheurs dans card Régime Macro
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 <noreply@anthropic.com>
This commit is contained in:
@@ -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 (
|
||||
<Link to="/macro" className="card block hover:border-slate-600/60 transition-all cursor-pointer">
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
@@ -654,6 +693,40 @@ export default function Dashboard() {
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Key macro gauges */}
|
||||
{Object.keys(gauges).length > 0 && (
|
||||
<div className="mt-2 pt-2 border-t border-slate-700/30 space-y-1">
|
||||
{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 (
|
||||
<div key={key} className="flex items-center gap-1.5">
|
||||
<span className="text-[9px] text-slate-600 w-16 shrink-0">{label}</span>
|
||||
<span className={clsx('text-[9px] font-mono font-semibold shrink-0', c)}>
|
||||
{fmt(val, chg)}
|
||||
</span>
|
||||
<span className="text-[8px] text-slate-700 truncate">{h}</span>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Trigger signals for dominant regime */}
|
||||
{reasons.length > 0 && (
|
||||
<div className="mt-1.5 flex flex-wrap gap-1">
|
||||
{reasons.slice(0, 4).map((r: string, i: number) => (
|
||||
<span key={i} className="text-[8px] bg-blue-900/20 text-blue-400/80 border border-blue-800/30 px-1.5 py-0.5 rounded">
|
||||
{r}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</Link>
|
||||
)
|
||||
})()}
|
||||
|
||||
Reference in New Issue
Block a user