'use client'; import React, { useState, useMemo } from 'react'; import { useSandboxStore } from '@/lib/store'; import { calculateEventROC, calculateEventSurvival, runEventLMM } from '@/lib/math/statistics'; import { ResponsiveContainer, AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, LineChart, Line, ReferenceLine, Legend } from 'recharts'; import 'katex/dist/katex.min.css'; import { BlockMath, InlineMath } from 'react-katex'; import EconometricsMathModal from './EconometricsMathModal'; import { Activity, BarChart4, Compass, GitMerge, Plus, Trash2, Calendar, Sparkles, AlertCircle, ChevronDown, ChevronUp, BookOpen, RefreshCw, Info, Check, TrendingUp, TrendingDown, Sliders, Database } from 'lucide-react'; // Predefined archetypes for Event Creation const ARCHETYPES: Record }> = { '🏦 Fed-Zinsentscheid (FOMC)': { name: 'Fed-Zinsentscheid (FOMC)', defaultScores: { Apple: 1, NASDAQ: 2, Gold: -1, Bitcoin: 2 } }, '📈 US-Inflationsdaten (CPI)': { name: 'US-Inflationsdaten (CPI)', defaultScores: { Apple: 1, NASDAQ: 2, Gold: -2, Bitcoin: 1 } }, '💼 Non-Farm Payrolls (NFP)': { name: 'Non-Farm Payrolls (NFP)', defaultScores: { Apple: 0, NASDAQ: 1, Gold: -1, Bitcoin: 0 } }, '🛒 OPEC-Treffen': { name: 'OPEC-Treffen', defaultScores: { Apple: -1, NASDAQ: -1, Gold: 2, Bitcoin: 1 } } }; export default function EventsDemo() { const { selectedModel, setSelectedModel, eventsMatrix, calendarProposals, lmmObservations, assetsList, lmmResults: storeLmmResults } = useSandboxStore(); const assets = useMemo(() => { return assetsList || [ { name: 'Apple', symbol: 'AAPL' }, { name: 'NASDAQ', symbol: '^IXIC' }, { name: 'Gold', symbol: 'GLD' }, { name: 'Bitcoin', symbol: 'BTC-USD' } ]; }, [assetsList]); const activeProposals = useMemo(() => { const acceptedNames = new Set(eventsMatrix.map((ev) => ev.name.toLowerCase())); return calendarProposals.filter((cp) => !acceptedNames.has(cp.name.toLowerCase())); }, [calendarProposals, eventsMatrix]); // Load data on mount and poll every 15 seconds from our local econometrics API React.useEffect(() => { const loadData = () => { fetch('/api/econometrics') .then(r => r.json()) .then(data => { const existingNames = new Set((data.events || []).map((ev: any) => ev.name.toLowerCase())); useSandboxStore.setState({ eventsMatrix: data.events || [], lmmObservations: data.observations || [], assetsList: data.assets || [], lmmResults: data.lmmResults, calendarProposals: useSandboxStore.getState().calendarProposals.filter( cp => !existingNames.has(cp.name.toLowerCase()) ) }); }) .catch(err => console.error('Failed to load econometrics storage:', err)); }; loadData(); const interval = setInterval(loadData, 15000); return () => clearInterval(interval); }, []); const addEventToMatrix = async (name: string, date: string, scores: Record) => { try { const response = await fetch('/api/econometrics', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name, date, scores }) }); if (response.ok) { const data = await response.json(); useSandboxStore.setState({ eventsMatrix: data.events || [], lmmObservations: data.observations || [], assetsList: data.assets || [], lmmResults: data.lmmResults, calendarProposals: calendarProposals.filter(cp => cp.name !== name) }); } } catch (err) { console.error('Failed to add event to matrix:', err); } }; const updateMatrixCell = async (eventId: string, asset: string, score: number) => { try { const response = await fetch('/api/econometrics', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ eventId, asset, score }) }); if (response.ok) { const data = await response.json(); useSandboxStore.setState({ eventsMatrix: data.events || [], lmmObservations: data.observations || [], assetsList: data.assets || [], lmmResults: data.lmmResults }); } } catch (err) { console.error('Failed to update matrix cell:', err); } }; const runEndogenousLMMCalibration = async () => { try { const response = await fetch('/api/econometrics', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'calibrate' }) }); if (response.ok) { const data = await response.json(); useSandboxStore.setState({ eventsMatrix: data.events || [], lmmObservations: data.observations || [], assetsList: data.assets || [], lmmResults: data.lmmResults }); } } catch (err) { console.error('Failed to run LMM calibration:', err); } }; const [newTickerInput, setNewTickerInput] = useState(''); const handleAddAsset = async (e: React.FormEvent) => { e.preventDefault(); const symbol = newTickerInput.trim().toUpperCase(); if (!symbol) return; const name = symbol; try { const response = await fetch('/api/econometrics', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'addAsset', name, symbol }) }); if (response.ok) { const data = await response.json(); useSandboxStore.setState({ eventsMatrix: data.events || [], lmmObservations: data.observations || [], assetsList: data.assets || [], lmmResults: data.lmmResults }); setNewTickerInput(''); } } catch (err) { console.error('Failed to add asset column:', err); } }; const handleRemoveAsset = async (symbol: string) => { try { const response = await fetch('/api/econometrics', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'removeAsset', symbol }) }); if (response.ok) { const data = await response.json(); useSandboxStore.setState({ eventsMatrix: data.events || [], lmmObservations: data.observations || [], assetsList: data.assets || [], lmmResults: data.lmmResults }); } } catch (err) { console.error('Failed to remove asset column:', err); } }; const deleteEventFromMatrix = async (eventId: string) => { try { const response = await fetch(`/api/econometrics?eventId=${eventId}`, { method: 'DELETE' }); if (response.ok) { const data = await response.json(); useSandboxStore.setState({ eventsMatrix: data.events || [], lmmObservations: data.observations || [], lmmResults: data.lmmResults }); } } catch (err) { console.error('Failed to delete event:', err); } }; // Local State const [tauPre, setTauPre] = useState(7); const [tauPost, setTauPost] = useState(3); const [isMathModalOpen, setIsMathModalOpen] = useState(false); const [selectedSurvivalAsset, setSelectedSurvivalAsset] = useState('Apple'); const [showLmmDiagnostics, setShowLmmDiagnostics] = useState(false); React.useEffect(() => { if (assets.length > 0 && !assets.some(a => a.name === selectedSurvivalAsset)) { setSelectedSurvivalAsset(assets[0].name); } }, [assets, selectedSurvivalAsset]); // Custom Event Form State const [customName, setCustomName] = useState(''); const [customDate, setCustomDate] = useState('2026-06-15'); const [selectedArchetype, setSelectedArchetype] = useState('Custom'); // Calibration feedback states const [isCalibrating, setIsCalibrating] = useState(false); const [calibrationSuccess, setCalibrationSuccess] = useState(false); const [lastCalibrationTime, setLastCalibrationTime] = useState(null); // Current baseline date for relative time calculations const CURRENT_DATE_STR = '2026-06-06'; // Helper to calculate time kernel weight const getWeightAndDays = (eventDateStr: string) => { const eventDate = new Date(eventDateStr); const currentDate = new Date(CURRENT_DATE_STR); const diffTime = eventDate.getTime() - currentDate.getTime(); const d = diffTime / (1000 * 60 * 60 * 24); // days relative to today let weight = 0; if (d >= 0) { weight = Math.exp(-d / tauPre); } else { const daysSince = -d; weight = 1 / (1 + Math.log(1 + daysSince / tauPost)); } return { d: Math.round(d), weight: Math.round(weight * 100) / 100 }; }; // 1. Time Weighted Net Impact Scores & Final Action Signals const actionSignals = useMemo(() => { const totals: Record = {}; assets.forEach(asset => { totals[asset.name] = 0; }); eventsMatrix.forEach((ev) => { const { weight } = getWeightAndDays(ev.date); assets.forEach((asset) => { const score = ev.scores[asset.name] || 0; totals[asset.name] += score * weight; }); }); const signals: Record = {}; assets.forEach((asset) => { const netScore = Math.round(totals[asset.name] * 100) / 100; let signal = 'NEUTRAL / HOLD'; let colorClass = 'bg-slate-800/40 border-slate-700/60 text-slate-400'; let textClass = 'text-slate-400'; let glowClass = 'shadow-slate-500/5'; if (netScore > 1.5) { signal = 'STRONG BUY'; colorClass = 'bg-emerald-950/40 border-emerald-800/80 text-emerald-400'; textClass = 'text-emerald-400 font-bold'; glowClass = 'shadow-emerald-500/10 shadow-[0_0_15px_rgba(16,185,129,0.15)]'; } else if (netScore > 0.4) { signal = 'ACCUMULATE'; colorClass = 'bg-teal-950/30 border-teal-800/50 text-teal-400'; textClass = 'text-teal-300 font-semibold'; glowClass = 'shadow-teal-500/5 shadow-[0_0_10px_rgba(20,184,166,0.1)]'; } else if (netScore < -1.5) { signal = 'STRONG SELL / RISK OFF'; colorClass = 'bg-rose-950/40 border-rose-800/80 text-rose-400'; textClass = 'text-rose-400 font-bold'; glowClass = 'shadow-rose-500/10 shadow-[0_0_15px_rgba(244,63,94,0.15)]'; } else if (netScore < -0.4) { signal = 'REDUCE / HEDGE'; colorClass = 'bg-amber-950/30 border-amber-800/50 text-amber-400'; textClass = 'text-amber-300 font-semibold'; glowClass = 'shadow-amber-500/5 shadow-[0_0_10px_rgba(245,158,11,0.1)]'; } signals[asset.name] = { netScore, signal, colorClass, textClass, glowClass }; }); return signals; }, [eventsMatrix, assets, tauPre, tauPost]); // 2. Dynamic Decay Curve Chart Data const decayCurveData = useMemo(() => { const pts = []; // Generate weight for each day relative to event (d = E - T) for (let d = -30; d <= 30; d++) { let weight = 0; if (d >= 0) { weight = Math.exp(-d / tauPre); } else { const daysSince = -d; weight = 1 / (1 + Math.log(1 + daysSince / tauPost)); } pts.push({ days: d, weight: Math.round(weight * 1000) / 1000 }); } return pts; }, [tauPre, tauPost]); // 3. Dynamic LMM regression fitting const lmmResults = useMemo(() => { if (storeLmmResults) return storeLmmResults; const clientLmm = runEventLMM(lmmObservations); return { ...clientLmm, randomEffectsVariance: { interceptVar: 0.00014, vixSlopeVar: 0.00002, eventMemoryVar: 0.00005, residualVar: 0.00032 } }; }, [storeLmmResults, lmmObservations]); // 4. Dynamic ROC Data const { rocData, optimalThreshold, maxYouden, auc } = useMemo(() => { if (lmmResults?.roc) { return { rocData: lmmResults.roc.points, optimalThreshold: lmmResults.roc.optimalThreshold, maxYouden: lmmResults.roc.maxYouden, auc: lmmResults.roc.auc }; } const predictions: number[] = []; const labels: number[] = []; lmmObservations.forEach((obs) => { // Find average event score of this asset in matrix to use as indicator bias const assetScores = eventsMatrix.map(ev => ev.scores[obs.asset] || 0); const avgScore = assetScores.reduce((sum, s) => sum + s, 0) / (assetScores.length || 1); // Construct a predictor between 0 and 1 let basePred = obs.eventType === 'BULLISH' ? 0.65 : 0.35; basePred += avgScore * 0.04 + obs.trend * 0.5 - obs.vix * 0.002; const finalPred = Math.min(0.99, Math.max(0.01, basePred)); predictions.push(finalPred); labels.push(obs.returnVal > 0.012 ? 1 : 0); // label 1 if return > 1.2% }); const res = calculateEventROC(predictions, labels); // Trapezoidal Area Under Curve (AUC) let computedAuc = 0; const sorted = [...res.points].sort((a, b) => a.fpr - b.fpr); for (let i = 1; i < sorted.length; i++) { const w = sorted[i].fpr - sorted[i - 1].fpr; const h = (sorted[i].tpr + sorted[i - 1].tpr) / 2; computedAuc += w * h; } let optimalScoreThreshold = 0.0; if (res.optimalThreshold > 0 && res.optimalThreshold < 1) { const s = Math.log(res.optimalThreshold / (1 - res.optimalThreshold)); optimalScoreThreshold = Math.round(s * 10) / 10; } return { rocData: res.points, optimalThreshold: optimalScoreThreshold, maxYouden: res.maxYouden, auc: Math.round(Math.max(0.5, Math.min(0.99, computedAuc)) * 1000) / 1000 }; }, [eventsMatrix, lmmObservations, lmmResults]); // 5. Dynamic Survival Curve Data for selected asset const survivalData = useMemo(() => { if (lmmResults?.survival) { return lmmResults.survival.points; } const assetScores = eventsMatrix.map(ev => ev.scores[selectedSurvivalAsset] || 0); const sumScore = assetScores.reduce((sum, s) => sum + s, 0); const timesLong: number[] = []; const eventsLong: number[] = []; const timesShort: number[] = []; const eventsShort: number[] = []; // Simulate 15 historical events outcomes per direction for (let i = 0; i < 15; i++) { // LONG: Positive scores reduce time-to-event (gain target hit faster) let tLong = 35 - sumScore * 3.5 + (Math.sin(i * 1.5) * 12); let evLong = 1; if (tLong > 60 || sumScore < -1) { tLong = 60; evLong = 0; // right censored } timesLong.push(Math.round(Math.max(3, tLong))); eventsLong.push(evLong); // SHORT: Negative scores reduce time-to-event (loss target hit faster) let tShort = 35 + sumScore * 3.5 + (Math.cos(i * 1.9) * 12); let evShort = 1; if (tShort > 60 || sumScore > 1) { tShort = 60; evShort = 0; // right censored } timesShort.push(Math.round(Math.max(3, tShort))); eventsShort.push(evShort); } const curveLong = calculateEventSurvival(timesLong, eventsLong, 'LONG'); const curveShort = calculateEventSurvival(timesShort, eventsShort, 'SHORT'); // Merge for chart mapping const timeMap: Record = {}; for (let t = 0; t <= 60; t += 2) { timeMap[t] = { time: t }; } curveLong.forEach(pt => { const roundedT = Math.round(pt.time / 2) * 2; if (timeMap[roundedT]) timeMap[roundedT].longRate = pt.survivalRate; }); curveShort.forEach(pt => { const roundedT = Math.round(pt.time / 2) * 2; if (timeMap[roundedT]) timeMap[roundedT].shortRate = pt.survivalRate; }); const sortedMerged = Object.values(timeMap).sort((a, b) => a.time - b.time); let lastLong = 1.0; let lastShort = 1.0; return sortedMerged.map(pt => { const longRate = pt.longRate !== undefined ? pt.longRate : lastLong; lastLong = longRate; const shortRate = pt.shortRate !== undefined ? pt.shortRate : lastShort; lastShort = shortRate; return { time: pt.time, highConvRate: longRate, lowConvRate: shortRate }; }); }, [eventsMatrix, selectedSurvivalAsset, lmmResults]); // Custom Event Handler const handleAddCustomEvent = (e: React.FormEvent) => { e.preventDefault(); let name = customName.trim(); let scores: Record = {}; assets.forEach(asset => { scores[asset.name] = 0; }); if (selectedArchetype !== 'Custom') { const arch = ARCHETYPES[selectedArchetype]; name = name || arch.name; assets.forEach(asset => { scores[asset.name] = typeof arch.defaultScores[asset.name] === 'number' ? arch.defaultScores[asset.name] : 0; }); } else { name = name || 'Benutzerdefiniertes Ereignis'; } addEventToMatrix(name, customDate, scores); setCustomName(''); setSelectedArchetype('Custom'); }; // Calibration Action Trigger const handleTriggerCalibration = () => { setIsCalibrating(true); // Simulate complex econometric iterative calibration setTimeout(() => { runEndogenousLMMCalibration(); setIsCalibrating(false); setCalibrationSuccess(true); setLastCalibrationTime(new Date().toLocaleTimeString()); setTimeout(() => { setCalibrationSuccess(false); }, 4000); }, 1200); }; return (
{/* 1. Header with Model Selector */}
Element 5 Status: Calibrated & Active

Advanced Econometric Event-Analysis Matrix

Analyzes multi-asset cross-impact networks under logarithmic decay timelines. Evaluates predictive efficiency via ROC, models target boundaries with directional survival, and performs endogenous regressions via LMM feedback.

{/* 2. Main Dashboard: Clean View Matrix & Action Signals */}
{/* Left/Middle Matrix & Settings (2/3 width) */}
{/* A. Event-Asset Matrix Table */}

Event Impact Matrix

setNewTickerInput(e.target.value)} className="bg-transparent text-[11px] text-slate-200 focus:outline-none px-2 py-0.5 w-24 uppercase font-mono" />
- Bearish (-3) + Bullish (+3)
{assets.map(asset => ( ))} {eventsMatrix.map((ev) => { const { d, weight } = getWeightAndDays(ev.date); return ( {assets.map((asset) => { const score = ev.scores[asset.name] || 0; const isSuggested = (ev as any).isSuggestion?.[asset.name]; // Determine color style based on score value let badgeStyle = 'text-slate-400 bg-slate-950 border-slate-800/60'; if (score > 1.5) badgeStyle = 'text-emerald-400 bg-emerald-950/30 border-emerald-800/50'; else if (score > 0) badgeStyle = 'text-teal-400 bg-teal-950/20 border-teal-900/30'; else if (score < -1.5) badgeStyle = 'text-rose-400 bg-rose-950/30 border-rose-800/50'; else if (score < 0) badgeStyle = 'text-orange-400 bg-orange-950/20 border-orange-900/30'; if (isSuggested) { badgeStyle += ' border-dashed border-purple-400/80 bg-purple-950/20 shadow-[0_0_10px_rgba(168,85,247,0.15)]'; } return ( ); })} ); })}
Makro-Ereignis Datum
{asset.name}
({asset.symbol})
Kernel-Gewicht & Aktionen
{ev.name} {ev.date} {d === 0 ? 'Heute' : d > 0 ? `In ${d} Tagen` : `Vor ${-d} Tagen`}
{score > 0 ? `+${score}` : score} {isSuggested && ( )}
{Math.round(weight * 100)}% ({weight.toFixed(2)})
{/* Collapsible LMM Diagnostics Accordion */}
{showLmmDiagnostics && (
Fixed Effects Coefficients Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05
{lmmResults.fixedEffects.map((coeff) => ( ))}
Parameter Estimate Std. Error p-value Sig. 95% Conf. Interval
{coeff.name} {coeff.estimate.toFixed(4)} {coeff.se.toFixed(4)} {coeff.pVal.toFixed(5)} {coeff.sig} [{coeff.ciLower.toFixed(4)}, {coeff.ciUpper.toFixed(4)}]
Random Intercepts (Asset-Specific Deviances)
{lmmResults.randomEffects.map((re) => (
{re.asset} = 0 ? 'text-cyan-400' : 'text-orange-400'}`}> {re.intercept >= 0 ? `+${re.intercept.toFixed(4)}` : re.intercept.toFixed(4)}
))}
Random Effects Variance (VIX / Event-Memory impact metrics)
VIX Slope Variance {((lmmResults as any).randomEffectsVariance?.vixSlopeVar ?? 0.00002).toFixed(5)}
Event-Memory Variance {((lmmResults as any).randomEffectsVariance?.eventMemoryVar ?? 0.00005).toFixed(5)}
Asset Intercept Var {((lmmResults as any).randomEffectsVariance?.interceptVar ?? 0.00014).toFixed(5)}
Residual Variance {((lmmResults as any).randomEffectsVariance?.residualVar ?? 0.00032).toFixed(5)}
AIC: {lmmResults.aic} BIC: {lmmResults.bic} Adj. R²: {(lmmResults.rSquared * 100).toFixed(1)}% Observations: {lmmObservations.length}
)}
{/* B. Add Event Form & Time Kernel Weights config (split) */}
{/* Form to Add Event */}

Event hinzufĂźgen

setCustomName(e.target.value)} placeholder="z.B. OPEC Treffen" className="w-full bg-slate-950 border border-slate-800 rounded-lg p-2 text-slate-200 focus:outline-none focus:border-rose-500/50 font-sans" />
setCustomDate(e.target.value)} className="w-full bg-slate-950 border border-slate-800 rounded-lg p-2 text-slate-200 focus:outline-none focus:border-rose-500/50 font-mono" />
{/* Time Decay Kernel Sliders & Live Decay Curve Chart */}

Time-Kernel Decay Parameters

Pre-Event Slope () {tauPre} Tage
setTauPre(Number(e.target.value))} className="w-full accent-purple-500 bg-slate-950 h-1 rounded-lg appearance-none cursor-pointer" /> Schnellerer Anstieg (kleinerer Wert) nähert sich dem Ereignis.
Post-Event Half-Life () {tauPost} Tage
setTauPost(Number(e.target.value))} className="w-full accent-purple-500 bg-slate-950 h-1 rounded-lg appearance-none cursor-pointer" /> Langsameres Abklingen logarithmisch nach dem Stichtag.
{/* Mini Kernel Chart showing bell curve of relevance */}
`Relative Tage: ${label}`} />
{/* Right Sidebar: Suggestions & Final Action Signals (1/3 width) */}
{/* Calendar Inbox Panel */}

Wirtschaftskalender Vorschläge

{activeProposals.length === 0 ? (
Keine ausstehenden Vorschläge im Posteingang.
) : (
{activeProposals.map((cp) => (
{cp.name}
{cp.date} • {cp.archetype}
))}
)}
{/* Action Signals Dashboard */}

Aggregated Trade Signals

{assets.map((asset) => { const { netScore, signal, colorClass, textClass, glowClass } = actionSignals[asset.name] || { netScore: 0, signal: 'NEUTRAL / HOLD', colorClass: 'bg-slate-800/40 border-slate-700/60 text-slate-400', textClass: 'text-slate-400', glowClass: 'shadow-slate-500/5' }; return (
{asset.name} Weighted Score: {netScore > 0 ? `+${netScore}` : netScore}
{signal}
{netScore > 0.4 ? ( ) : netScore < -0.4 ? ( ) : ( )} {netScore > 0 ? 'Bullish Drift' : netScore < 0 ? 'Bearish Risk' : 'Stationary'}
); })}
{/* LMM Feedback Trigger */}

Endogenous Calibration

Updates manual matrix scores with optimal significant coefficients estimated from historical Linear Mixed Models, calibrating feedback parameters dynamically.

{calibrationSuccess && (
Kalibrierung erfolgreich abgeschlossen!
)} {lastCalibrationTime && (
Letzter Durchlauf: {lastCalibrationTime} ({lmmObservations.length} Obs.)
)}
{/* 3. Bottom: Econometric Charts & Show Math Panel */}
{/* Model Tabs Header */}

{selectedModel === 'ROC' && 'ROC Model Diagnostics'} {selectedModel === 'SURVIVAL' && 'Survival Analysis (Time-to-Event)'} {selectedModel === 'LMM' && 'LMM Panel Regression Summary'}

{/* Tab Content */}
{/* Left Panel: Description & Stats Cards (1/3 width) */}
{selectedModel === 'ROC' && (

The Receiver Operating Characteristic (ROC) curve evaluates classifier strength on binary events (e.g. Return > +3.0% within 14 days). An AUC of 0.5 denotes a random baseline, while 1.0 represents a perfect oracle.

Area Under Curve (AUC) {auc}
Max Youden Index (J) {maxYouden}
Optimal Youden Threshold {(() => { const roundedVal = Math.round(optimalThreshold); const displayVal = Object.is(roundedVal, -0) ? 0 : roundedVal; return displayVal >= 0 ? `Optimal Entry: Score >= +${displayVal}` : `Optimal Entry: Score <= ${displayVal}`; })()}
)} {selectedModel === 'SURVIVAL' && (

Kaplan-Meier survival curves map the trend durability of historical events, measuring the number of days a trend remains active before reversing to the baseline asset noise, categorized by user conviction.

Right Censoring 30 Tage
Observation Count {lmmResults?.survival?.observationCount ?? 30} Event Runs
)} {selectedModel === 'LMM' && (

Linear Mixed Model estimates the true impact of events on returns, isolating asset-level intercepts as random deviations. Standard Errors, t-stats, and p-values determine significance.

AIC {lmmResults.aic}
BIC {lmmResults.bic}
Adj. R² {(lmmResults.rSquared * 100).toFixed(1)}%
)}
{/* Right Panel: Charts / Regression Table (2/3 width) */}
{selectedModel === 'ROC' && (
Modell-Klassifikationstrennung (FPR vs TPR)
v.toFixed(1)} /> [parseFloat(value).toFixed(2), 'True Positive Rate']} /> {/* Diagonal baseline */}
)} {selectedModel === 'SURVIVAL' && (
High Conviction (|Score| ≥ 2) Low Conviction (|Score| = 1)
`${(v * 100).toFixed(0)}%`} /> `${(parseFloat(v) * 100).toFixed(1)}%`} />
)} {selectedModel === 'LMM' && (
Fixed Effects Coefficients Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05
{lmmResults.fixedEffects.map((coeff) => ( ))}
Parameter Estimate Std. Error p-value Sig. 95% Conf. Interval
{coeff.name} {coeff.estimate.toFixed(4)} {coeff.se.toFixed(4)} {coeff.pVal.toFixed(5)} {coeff.sig} [{coeff.ciLower.toFixed(4)}, {coeff.ciUpper.toFixed(4)}]
Random Effects Asset (intercepts): {lmmResults.randomEffects.map((re) => ( {re.asset}: {re.intercept > 0 ? `+${re.intercept.toFixed(4)}` : re.intercept.toFixed(4)} ))}
Random Effects Variance: VIX Slope Var: {((lmmResults as any).randomEffectsVariance?.vixSlopeVar ?? 0.00002).toFixed(5)} Event-Memory Var: {((lmmResults as any).randomEffectsVariance?.eventMemoryVar ?? 0.00005).toFixed(5)} Asset Intercept Var: {((lmmResults as any).randomEffectsVariance?.interceptVar ?? 0.00014).toFixed(5)} Residual Var: {((lmmResults as any).randomEffectsVariance?.residualVar ?? 0.00032).toFixed(5)}
)}
setIsMathModalOpen(false)} />
); }