diff --git a/components/CurrencyCard.tsx b/components/CurrencyCard.tsx index aaea10e..6ea69fb 100644 --- a/components/CurrencyCard.tsx +++ b/components/CurrencyCard.tsx @@ -739,94 +739,119 @@ function OISEnhancedBlock({ ratePath, syncChartTab, onChartTabChange }: { )} - {/* Chart 3 — Probabilités : LineChart probMovePct + liste réunions avec taux prévu */} - {chartTab === "scenarios" && ( -
- {/* Graphique probabilité de move par réunion */} - - ({ label: m.label, prob: m.probMovePct, isCut: m.probIsCut, impliedRate: m.impliedRate }))} - margin={{ top: 5, right: 5, left: -20, bottom: 0 }} - > - - `${v}%`} /> - - - { - if (!payload?.length) return null; - const v = payload[0]?.value as number; - const m = chartMeetings.find(m => m.label === label); - return ( -
-

{label}

-

Prob : {v.toFixed(0)}% {m?.probIsCut ? "Cut" : "Hike"}

-

Implicite : {m?.impliedRate.toFixed(2)}%

-
- ); - }} - /> -
-
+ {/* Chart 3 — Probabilités : AreaChart auto-scale + résumé + liste réunions */} + {chartTab === "scenarios" && (() => { + const probValues = chartMeetings.map(m => m.probMovePct); + const pMin = Math.max(0, Math.min(...probValues) - 12); + const pMax = Math.min(100, Math.max(...probValues) + 12); + const maxR2 = Math.max(...scenariosData.map(d => d.rate), currentRate); + const minR2 = Math.min(...scenariosData.map(d => d.rate), currentRate) - 0.05; + const range = maxR2 - minR2 || 0.25; + const peakIsCut = !!ratePath.peakMeeting?.probIsCut; + const gradId = `probGrad_${currency}`; + const gradColor = peakIsCut ? "#38bdf8" : "#f59e0b"; + return ( +
+ {/* Graphique AreaChart auto-scale */} + + ({ label: m.label, prob: m.probMovePct, isCut: m.probIsCut, impliedRate: m.impliedRate }))} + margin={{ top: 4, right: 4, left: -22, bottom: 0 }} + > + + + + + + + + `${v}%`} /> + + + { + if (!payload?.length) return null; + const v = payload[0]?.value as number; + const m = chartMeetings.find(m => m.label === label); + const bpsCum = m ? Math.round((m.impliedRate - currentRate) * 100) : 0; + return ( +
+

{label}

+

Prob : {v.toFixed(0)}% {m?.probIsCut ? "Cut" : "Hike"}

+

+ {m?.impliedRate.toFixed(2)}% {bpsCum !== 0 ? `(${bpsCum > 0 ? "+" : ""}${bpsCum}bps)` : ""} +

+
+ ); + }} + /> +
+
- {/* Résumé : pic + bps fin an + flèches IL vs sem. préc. */} - {ratePath.peakMeeting && ( - <> -
- Pic : {ratePath.peakMeeting.label} - - {ratePath.peakMeeting.probMovePct.toFixed(0)}% {ratePath.peakMeeting.probIsCut ? "Cut" : "Hike"} + {/* Résumé compact : pic · proba · bps fin an · delta IL */} + {ratePath.peakMeeting && ( +
+ Pic : {ratePath.peakMeeting.label} + + {ratePath.peakMeeting.probMovePct.toFixed(0)}% {peakIsCut ? "Cut" : "Hike"} {bpsYE !== null && ( - - {bpsYE > 0 ? "+" : ""}{bpsYE}bps fin an + + {bpsYE > 0 ? "+" : ""}{bpsYE}bps fin an + + )} + {ilDelta && (Math.abs(ilDelta.probDelta) >= 3 || Math.abs(ilDelta.bpsDelta) >= 5) && ( + + vs sem. préc. : + + {ilDelta.bpsDelta !== 0 && ( + + )} )}
- {ilDelta && (Math.abs(ilDelta.probDelta) >= 3 || Math.abs(ilDelta.bpsDelta) >= 5) && ( -
- vs sem. préc. : - - {ilDelta.bpsDelta !== 0 && ( - - )} -
- )} - - )} + )} - {/* Liste des réunions : date | barre taux implicite | taux | proba */} -
- {(() => { - const maxR2 = Math.max(...scenariosData.map(d => d.rate), currentRate); - const minR2 = Math.min(...scenariosData.map(d => d.rate), currentRate) - 0.05; - const range = maxR2 - minR2 || 0.25; - return scenariosData.map(d => { - const barW = Math.max(5, Math.min(100, ((d.rate - minR2) / range) * 100)); - const isDown = d.rate < currentRate - 0.001; - const isUp = d.rate > currentRate + 0.001; - const barCl = isDown ? "bg-sky-500/70" : isUp ? "bg-red-500/70" : "bg-amber-500/60"; - const isPeak = ratePath.peakMeeting?.dateIso === d.dateIso; + {/* Liste des réunions */} +
+ {scenariosData.map(d => { + const isPeak = ratePath.peakMeeting?.dateIso === d.dateIso; + const isDown = d.rate < currentRate - 0.001; + const isUp = d.rate > currentRate + 0.001; + const barColor = isDown ? "#38bdf8" : isUp ? "#f87171" : "#f59e0b"; + const barW = Math.max(4, Math.min(100, ((d.rate - minR2) / range) * 100)); + const cumBps = d.cumulBps; + const cumStr = cumBps === 0 ? null : `${cumBps > 0 ? "+" : ""}${cumBps}`; return ( -
- +
+ {d.label} -
-
+
+
- {d.rate.toFixed(2)}% + + {d.rate.toFixed(2)}% + + {cumStr && ( + + {cumStr}bps + + )} {d.prob > 0 && ( - {d.prob.toFixed(0)}% + {d.prob.toFixed(0)}% )}
); - }); - })()} + })} +
-
- )} + ); + })()}
{/* ── IL footer (analyste InvestingLive) ────────────────────────────── */}