feat: instrument analysis
This commit is contained in:
@@ -762,17 +762,49 @@ function CausalFrise({
|
||||
} | null>(null)
|
||||
const [popupScore, setPopupScore] = useState<number | null | 'loading'>('loading')
|
||||
|
||||
// Fetch activation_score live when popup opens for a specific event
|
||||
// Fetch analysis live when popup opens — compute same precision as MarketEvents expanded view
|
||||
useEffect(() => {
|
||||
const evId = activeChip?.ev.id
|
||||
if (!evId) { setPopupScore(null); return }
|
||||
setPopupScore('loading')
|
||||
api.get(`/causal-lab/analyses?market_event_id=${evId}&limit=1`)
|
||||
.then(r => {
|
||||
const score = r.data?.[0]?.activation_score
|
||||
setPopupScore(score != null ? Math.round(score * 100) : null)
|
||||
const analysis = r.data?.[0]
|
||||
console.log('[CausalFrise] analysis for event', evId, analysis)
|
||||
if (!analysis) { setPopupScore(null); return }
|
||||
|
||||
// Compute magnitude-weighted precision (same formula as MarketEvents expanded panel)
|
||||
const preds: Record<string, number> = analysis.prediction_json || {}
|
||||
const actuals: Record<string, number> = analysis.actual_json || {}
|
||||
const graph = analysis.graph_json || {}
|
||||
const outputNodes: { id: string; instrument?: string }[] = (graph.nodes || [])
|
||||
.filter((n: { type?: string }) => n.type === 'market_asset' || n.type === 'output')
|
||||
|
||||
console.log('[CausalFrise] preds:', preds, 'actuals:', actuals, 'outputNodes:', outputNodes)
|
||||
|
||||
const nodeScores = outputNodes.map((n: { id: string; instrument?: string }) => {
|
||||
const pred = preds[n.id]
|
||||
const act = actuals[n.instrument || n.id] ?? 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)
|
||||
|
||||
console.log('[CausalFrise] nodeScores:', nodeScores)
|
||||
|
||||
if (nodeScores.length > 0) {
|
||||
setPopupScore(Math.round(nodeScores.reduce((a, b) => a + b, 0) / nodeScores.length))
|
||||
} else {
|
||||
// Fallback: use stored activation_score if no prediction data
|
||||
const stored = analysis.activation_score
|
||||
setPopupScore(stored != null ? Math.round(stored * 100) : null)
|
||||
}
|
||||
})
|
||||
.catch(() => setPopupScore(null))
|
||||
.catch(err => { console.error('[CausalFrise] fetch error:', err); setPopupScore(null) })
|
||||
}, [activeChip?.ev.id])
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user