diff --git a/frontend/src/pages/InstrumentDashboard.tsx b/frontend/src/pages/InstrumentDashboard.tsx index 456498f..e50b483 100644 --- a/frontend/src/pages/InstrumentDashboard.tsx +++ b/frontend/src/pages/InstrumentDashboard.tsx @@ -1014,11 +1014,12 @@ function CausalFrise({ // ── ExplanationScore ────────────────────────────────────────────────────────── function ExplanationScore({ - events, templates, causalInsts, + events, templates, causalInsts, onRefreshDone, }: { events: SnapshotEvent[] templates: CausalTemplate[] causalInsts: string[] + onRefreshDone?: () => void }) { const [refreshing, setRefreshing] = useState(false) const [refreshDone, setRefreshDone] = useState(false) @@ -1059,6 +1060,7 @@ function ExplanationScore({ try { await api.post('/causal-lab/auto-analyze/refresh') setRefreshDone(true) + onRefreshDone?.() setTimeout(() => setRefreshDone(false), 3000) } finally { setRefreshing(false) @@ -1137,16 +1139,8 @@ export default function InstrumentDashboard() { api.get('/causal-lab/templates').then(r => setTemplates(r.data)).catch(() => {}) }, []) - useEffect(() => { + const fetchSnapshot = useCallback(() => { setLoading(true) - setSnapshot(null) - setNarrative('') - setSelectedDate(null) - setMacroAtDate(null) - setTheoryCurve(null) - setShowTheory(false) - chartDateToXRef.current = null - setChartReady(0) api.get(`/instruments/${instrumentId}/snapshot?period=${period}`) .then(r => { setSnapshot(r.data) @@ -1157,6 +1151,18 @@ export default function InstrumentDashboard() { .finally(() => setLoading(false)) }, [instrumentId, period]) + useEffect(() => { + setSnapshot(null) + setNarrative('') + setSelectedDate(null) + setMacroAtDate(null) + setTheoryCurve(null) + setShowTheory(false) + chartDateToXRef.current = null + setChartReady(0) + fetchSnapshot() + }, [instrumentId, period]) + const loadNarrative = useCallback(() => { setLoadingNarr(true) api.post(`/instruments/${instrumentId}/narrative`) @@ -1525,6 +1531,7 @@ export default function InstrumentDashboard() { events={snapshot.events} templates={templates} causalInsts={causalInsts} + onRefreshDone={fetchSnapshot} /> ) diff --git a/frontend/src/pages/MarketEvents.tsx b/frontend/src/pages/MarketEvents.tsx index ec13ddb..4ae12c6 100644 --- a/frontend/src/pages/MarketEvents.tsx +++ b/frontend/src/pages/MarketEvents.tsx @@ -1000,6 +1000,38 @@ function EventDetail({ {outputNodes.length > 0 && (
Prédictions
+ {(() => { + const nodeScores = outputNodes + .map(n => { + const pred = anResult.preds[n.id] + const act = anResult.actuals[n.instrument || n.id] ?? anResult.actuals[n.id] + if (pred == null || act == null) return null + if (pred === 0 && act === 0) return 100 + if (pred === 0) return 40 + const sameDir = pred * act > 0 + if (!sameDir) return 0 + const ratio = Math.min(Math.abs(act), Math.abs(pred)) / Math.max(Math.abs(act), Math.abs(pred)) + return Math.round(50 + ratio * 50) + }) + .filter((s): s is number => s != null) + const graphScore = nodeScores.length > 0 + ? Math.round(nodeScores.reduce((a, b) => a + b, 0) / nodeScores.length) + : null + if (graphScore == null) return null + const barCls = graphScore >= 70 ? 'bg-emerald-500' : graphScore >= 40 ? 'bg-amber-500' : 'bg-red-500' + const txtCls = graphScore >= 70 ? 'text-emerald-400' : graphScore >= 40 ? 'text-amber-400' : 'text-red-400' + return ( +
+
+ Précision + {graphScore}% +
+
+
+
+
+ ) + })()} {outputNodes.map(n => { const pred = anResult.preds[n.id] const actual = anResult.actuals[n.instrument || n.id] ?? anResult.actuals[n.id]