mirror of
https://github.com/caty21/forex-dashboard.git
synced 2026-08-18 06:58:06 +00:00
feat: dashboard v8 — COT, FX Weekly, Report, TvChart, Sentiment, News
Ajout des onglets COT, Weekly Report, TvChart. Refonte Sentiment, News, Calendar, Drivers. Nouvelles API cot-history et fx-weekly. Intégration FinancialJuice. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
e11d61eb4d
commit
1a2ea02b22
+78
-63
@@ -14,7 +14,7 @@ function fmt(v: number | null, dec: number, unit = "") {
|
||||
|
||||
interface TooltipState { x: number; y: number }
|
||||
|
||||
function D({ label, value, dec = 2, unit = "", delta, deltaPct, deltaDec, tooltip }: {
|
||||
function Tile({ label, value, dec = 2, unit = "", delta, deltaPct, deltaDec, tooltip, accent }: {
|
||||
label: string;
|
||||
value: number | null;
|
||||
dec?: number;
|
||||
@@ -23,6 +23,7 @@ function D({ label, value, dec = 2, unit = "", delta, deltaPct, deltaDec, toolti
|
||||
deltaPct?: boolean;
|
||||
deltaDec?: number;
|
||||
tooltip?: string;
|
||||
accent?: "red" | "green" | "amber";
|
||||
}) {
|
||||
const [tip, setTip] = useState<TooltipState | null>(null);
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
@@ -42,28 +43,30 @@ function D({ label, value, dec = 2, unit = "", delta, deltaPct, deltaDec, toolti
|
||||
? `${Math.abs(delta).toFixed(deltaDec ?? dec)}${deltaPct ? "%" : ""}`
|
||||
: null;
|
||||
|
||||
const borderCls = accent === "red" ? "border-red-500/30 bg-red-500/5"
|
||||
: accent === "green" ? "border-emerald-500/30 bg-emerald-500/5"
|
||||
: accent === "amber" ? "border-amber-500/30 bg-amber-500/5"
|
||||
: "border-slate-800/60 bg-slate-900/40";
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
ref={ref}
|
||||
onMouseEnter={tooltip ? show : undefined}
|
||||
onMouseLeave={tooltip ? hide : undefined}
|
||||
className={`flex items-center gap-1.5 shrink-0 ${tooltip ? "cursor-help" : ""}`}
|
||||
className={`flex flex-col gap-0.5 px-3 py-2 rounded-lg border ${borderCls} ${tooltip ? "cursor-help" : ""} min-w-[72px]`}
|
||||
>
|
||||
<span className="text-slate-500 text-[11px]">{label}</span>
|
||||
<span className="text-slate-100 font-semibold tabular-nums text-[11px]">
|
||||
{fmt(value, dec, unit)}
|
||||
</span>
|
||||
{dFmt && (
|
||||
<span className={`text-[10px] font-medium tabular-nums ${dColor}`}>
|
||||
{dArrow}{dFmt}
|
||||
<span className="text-slate-500 text-[10px] font-medium leading-none">{label}</span>
|
||||
<div className="flex items-baseline gap-1">
|
||||
<span className="text-slate-100 font-bold tabular-nums text-[13px] leading-none">
|
||||
{fmt(value, dec, unit)}
|
||||
</span>
|
||||
)}
|
||||
{tooltip && (
|
||||
<span className="w-3 h-3 rounded-full border border-slate-700 text-slate-600 text-[7px] flex items-center justify-center leading-none select-none shrink-0">
|
||||
i
|
||||
</span>
|
||||
)}
|
||||
{dFmt && (
|
||||
<span className={`text-[10px] font-medium tabular-nums leading-none ${dColor}`}>
|
||||
{dArrow}{dFmt}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{tip && typeof document !== "undefined" && createPortal(
|
||||
@@ -80,8 +83,12 @@ function D({ label, value, dec = 2, unit = "", delta, deltaPct, deltaDec, toolti
|
||||
);
|
||||
}
|
||||
|
||||
function VSep() {
|
||||
return <div className="w-px h-3.5 bg-slate-700/60 shrink-0 mx-0.5" />;
|
||||
function GroupLabel({ label }: { label: string }) {
|
||||
return (
|
||||
<span className="text-slate-600 text-[9px] font-semibold uppercase tracking-widest self-center shrink-0 hidden sm:block">
|
||||
{label}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export default function DriversBar({ drivers }: Props) {
|
||||
@@ -102,59 +109,67 @@ export default function DriversBar({ drivers }: Props) {
|
||||
const riskOff = (vix ?? 0) > 25 || (hySpread ?? 0) > 500;
|
||||
|
||||
return (
|
||||
<div className="mb-4 bg-slate-900 border border-slate-800 rounded-xl px-4 py-2.5 flex items-center gap-4 overflow-x-auto scrollbar-hide">
|
||||
<div className="mb-4 bg-slate-950/60 border border-slate-800 rounded-xl p-3 space-y-2">
|
||||
|
||||
<span className="text-slate-500 font-semibold uppercase tracking-widest text-[10px] shrink-0">
|
||||
DRIVERS GLOBAUX
|
||||
</span>
|
||||
{/* Ligne titre + alerte */}
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-slate-500 font-semibold uppercase tracking-widest text-[10px]">
|
||||
Drivers Globaux
|
||||
</span>
|
||||
{riskOff && (
|
||||
<div className="flex items-center gap-1 bg-red-500/10 border border-red-500/20 rounded-full px-2 py-0.5">
|
||||
<AlertTriangle size={10} className="text-red-400" />
|
||||
<span className="text-[9px] font-semibold text-red-400">Risk-Off</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{riskOff && (
|
||||
<div className="flex items-center gap-1 shrink-0 bg-red-500/10 border border-red-500/20 rounded-full px-2 py-0.5">
|
||||
<AlertTriangle size={10} className="text-red-400" />
|
||||
<span className="text-[9px] font-semibold text-red-400">Risk-Off</span>
|
||||
</div>
|
||||
)}
|
||||
{/* Grille responsive — 2 lignes sur desktop, s'adapte sur mobile */}
|
||||
<div className="flex flex-wrap gap-2">
|
||||
|
||||
<VSep />
|
||||
{/* ── Sentiment ─────────────────────────────────────────── */}
|
||||
<GroupLabel label="Sentiment" />
|
||||
<Tile label="VIX" value={vix} dec={1} delta={vixDelta} deltaDec={1}
|
||||
accent={(vix ?? 0) > 25 ? "red" : undefined}
|
||||
tooltip="Clôture actuelle − clôture précédente (Yahoo Finance)." />
|
||||
<Tile label="S&P 500" value={sp500} dec={0} delta={sp500ChangePct} deltaPct deltaDec={2}
|
||||
tooltip="% vs clôture précédente (Yahoo Finance)." />
|
||||
<Tile label="Bitcoin" value={btc} dec={0} unit=" $" delta={btcChange24h} deltaPct deltaDec={2}
|
||||
tooltip="Variation 24h (Binance / CoinGecko)." />
|
||||
|
||||
{/* Sentiment / Risk-On */}
|
||||
<D label="VIX" value={vix} dec={1} delta={vixDelta} deltaDec={1}
|
||||
tooltip="Clôture actuelle − clôture précédente (Yahoo Finance)." />
|
||||
<D label="S&P 500" value={sp500} dec={0} delta={sp500ChangePct} deltaPct deltaDec={2}
|
||||
tooltip="% vs clôture précédente (Yahoo Finance)." />
|
||||
<D label="Bitcoin" value={btc} dec={0} unit=" $" delta={btcChange24h} deltaPct deltaDec={2}
|
||||
tooltip="Variation 24h (Binance / CoinGecko)." />
|
||||
{/* ── Crédit ────────────────────────────────────────────── */}
|
||||
<div className="w-px bg-slate-800 self-stretch mx-0.5 hidden sm:block" />
|
||||
<GroupLabel label="Crédit" />
|
||||
<Tile label="HY Spread" value={hySpread} dec={0} unit=" bps"
|
||||
accent={(hySpread ?? 0) > 500 ? "red" : (hySpread ?? 0) > 400 ? "amber" : undefined}
|
||||
tooltip="High Yield spread vs Treasuries US. >500 bps = risk-off fort." />
|
||||
<Tile label="IG Spread" value={igSpread} dec={0} unit=" bps"
|
||||
tooltip="Investment Grade spread vs Treasuries US." />
|
||||
|
||||
<VSep />
|
||||
{/* ── FX / Taux ─────────────────────────────────────────── */}
|
||||
<div className="w-px bg-slate-800 self-stretch mx-0.5 hidden sm:block" />
|
||||
<GroupLabel label="FX / Taux" />
|
||||
<Tile label="DXY" value={dxy} dec={2} delta={dxyDelta} deltaDec={2}
|
||||
tooltip="ICE Dollar Index Futures (DX=F) — Yahoo Finance, cache 5 min." />
|
||||
<Tile
|
||||
label="Crb 2-10" value={curveSlope} dec={0} unit=" bps"
|
||||
accent={(curveSlope ?? 0) < -50 ? "amber" : undefined}
|
||||
tooltip={`Spread US 10Y − US 2Y. Négatif = courbe inversée.\nUS 10Y: ${us10y != null ? us10y.toFixed(2) + "%" : "N/A"} | US 2Y: ${us2y != null ? us2y.toFixed(2) + "%" : "N/A"}`}
|
||||
/>
|
||||
|
||||
{/* Crédit */}
|
||||
<D label="HY Spread" value={hySpread} dec={0} unit=" bps"
|
||||
tooltip="High Yield spread vs Treasuries US. >500 bps = risk-off fort." />
|
||||
<D label="IG Spread" value={igSpread} dec={0} unit=" bps"
|
||||
tooltip="Investment Grade spread vs Treasuries US." />
|
||||
|
||||
<VSep />
|
||||
|
||||
{/* Taux & FX */}
|
||||
<D label="DXY" value={dxy} dec={2} delta={dxyDelta} deltaDec={2}
|
||||
tooltip="ICE Dollar Index Futures (DX=F) — Yahoo Finance, cache 5 min." />
|
||||
<D
|
||||
label="Crb 2-10" value={curveSlope} dec={0} unit=" bps"
|
||||
tooltip={`Spread US 10Y − US 2Y. Négatif = courbe inversée.\nUS 10Y: ${us10y != null ? us10y.toFixed(2) + "%" : "N/A"} | US 2Y: ${us2y != null ? us2y.toFixed(2) + "%" : "N/A"}`}
|
||||
/>
|
||||
|
||||
<VSep />
|
||||
|
||||
{/* Commodités */}
|
||||
<D label="Or $/oz" value={gold} dec={0} delta={goldDelta} deltaDec={1}
|
||||
tooltip="Delta intraday close−open (Stooq)." />
|
||||
<D label="Argent $/oz" value={silver} dec={2} delta={silverDelta}
|
||||
tooltip="Delta intraday close−open (Stooq)." />
|
||||
<D label="Brent $/b" value={brent} dec={1} delta={brentDelta} deltaDec={1}
|
||||
tooltip="Delta intraday close−open (Stooq)." />
|
||||
<D label="WTI $/b" value={wti} dec={1} delta={wtiDelta} deltaDec={1}
|
||||
tooltip="Delta intraday close−open (Stooq)." />
|
||||
{/* ── Commodités ────────────────────────────────────────── */}
|
||||
<div className="w-px bg-slate-800 self-stretch mx-0.5 hidden sm:block" />
|
||||
<GroupLabel label="Commodités" />
|
||||
<Tile label="Or $/oz" value={gold} dec={0} delta={goldDelta} deltaDec={1}
|
||||
tooltip="Delta intraday close−open (Stooq)." />
|
||||
<Tile label="Argent $/oz" value={silver} dec={2} delta={silverDelta}
|
||||
tooltip="Delta intraday close−open (Stooq)." />
|
||||
<Tile label="Brent $/b" value={brent} dec={1} delta={brentDelta} deltaDec={1}
|
||||
tooltip="Delta intraday close−open (Stooq)." />
|
||||
<Tile label="WTI $/b" value={wti} dec={1} delta={wtiDelta} deltaDec={1}
|
||||
tooltip="Delta intraday close−open (Stooq)." />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user