Closes #014 - System-wide handbook sweep, English consolidation & Crypto state persistence

This commit is contained in:
Antigravity Agent
2026-06-13 13:59:29 +02:00
parent f3c549e476
commit dc703e1bb8
18 changed files with 839 additions and 488 deletions

View File

@@ -9,7 +9,7 @@ import CryptoMathModal from './CryptoMathModal';
import {
Cpu, Search, RefreshCw, BarChart2, TrendingUp, AlertCircle, Info,
ChevronDown, ChevronUp, ArrowUpRight, ArrowDownRight, Compass, ShieldAlert, Sparkles,
BookOpen
BookOpen, Check
} from 'lucide-react';
interface CoinData {
@@ -68,8 +68,26 @@ const defaultCoins: Record<string, CoinData> = {
}
};
interface Forecast {
id: string;
ticker: string;
predictedDirection: 'UP' | 'DOWN';
predictedProb: number;
entryPrice: number;
resolved: boolean;
result?: 'SUCCESS' | 'FAILURE';
timestamp: number;
targetTime: number;
}
export default function CryptoDemo() {
const { alphaSuccess, betaFailure, addModelTrial } = useSandboxStore();
const { addModelTrial } = useSandboxStore();
// Local state for alphaSuccess and betaFailure to satisfy SSR hydration safeguarding
const [alphaSuccess, setAlphaSuccess] = useState<number>(394);
const [betaFailure, setBetaFailure] = useState<number>(118);
const [forecasts, setForecasts] = useState<Forecast[]>([]);
const [learningLoopLog, setLearningLoopLog] = useState<string>('');
const [activeTicker, setActiveTicker] = useState<string>('BTC');
const [searchQuery, setSearchQuery] = useState('');
@@ -80,6 +98,166 @@ export default function CryptoDemo() {
const [simulatedTrialLogged, setSimulatedTrialLogged] = useState(false);
const [lastTrialSuccess, setLastTrialSuccess] = useState(false);
// Safely load counters and forecasts from localStorage on client mount
React.useEffect(() => {
const savedAlpha = localStorage.getItem('crypto_bayes_alpha');
const savedBeta = localStorage.getItem('crypto_bayes_beta');
const savedForecasts = localStorage.getItem('crypto_bayes_forecasts');
let loadedAlpha = 394;
let loadedBeta = 118;
if (savedAlpha !== null) {
loadedAlpha = parseInt(savedAlpha, 10);
setAlphaSuccess(loadedAlpha);
} else {
localStorage.setItem('crypto_bayes_alpha', '394');
}
if (savedBeta !== null) {
loadedBeta = parseInt(savedBeta, 10);
setBetaFailure(loadedBeta);
} else {
localStorage.setItem('crypto_bayes_beta', '118');
}
if (savedForecasts !== null) {
setForecasts(JSON.parse(savedForecasts));
} else {
const now = Date.now();
const mockForecasts: Forecast[] = [
{
id: 'mock-1',
ticker: 'BTC',
predictedDirection: 'UP',
predictedProb: 0.68,
entryPrice: 65000,
resolved: true,
result: 'SUCCESS',
timestamp: now - 86400 * 1000 * 3,
targetTime: now - 86400 * 1000 * 2,
},
{
id: 'mock-2',
ticker: 'ETH',
predictedDirection: 'DOWN',
predictedProb: 0.35,
entryPrice: 3950,
resolved: true,
result: 'SUCCESS',
timestamp: now - 86400 * 1000 * 3,
targetTime: now - 86400 * 1000 * 2,
},
{
id: 'mock-3',
ticker: 'SOL',
predictedDirection: 'UP',
predictedProb: 0.72,
entryPrice: 170,
resolved: true,
result: 'SUCCESS',
timestamp: now - 86400 * 1000 * 2,
targetTime: now - 86400 * 1000 * 1,
},
{
id: 'mock-4',
ticker: 'BTC',
predictedDirection: 'UP',
predictedProb: 0.62,
entryPrice: 71000,
resolved: true,
result: 'FAILURE',
timestamp: now - 86400 * 1000 * 2,
targetTime: now - 86400 * 1000 * 1,
},
{
id: 'mock-5',
ticker: 'ETH',
predictedDirection: 'UP',
predictedProb: 0.58,
entryPrice: 3900,
resolved: true,
result: 'FAILURE',
timestamp: now - 86400 * 1000 * 2,
targetTime: now - 86400 * 1000 * 1,
}
];
setForecasts(mockForecasts);
localStorage.setItem('crypto_bayes_forecasts', JSON.stringify(mockForecasts));
}
}, []);
// Client-side background learning loop evaluating forecasts against actual live returns
React.useEffect(() => {
const runLearningLoop = async () => {
try {
const res = await fetch('/api/finance?region=crypto');
if (!res.ok) return;
const data = await res.ok ? await res.json() : { results: [] };
const results = data.results || [];
const pricesMap: Record<string, number> = {};
results.forEach((r: any) => {
pricesMap[r.ticker] = r.currentPrice;
const cleanTicker = r.ticker.replace('-USD', '');
pricesMap[cleanTicker] = r.currentPrice;
});
let updatedAny = false;
let newAlpha = alphaSuccess;
let newBeta = betaFailure;
const updatedForecasts = forecasts.map((f) => {
if (f.resolved) return f;
const currentPrice = pricesMap[f.ticker] || pricesMap[`${f.ticker}-USD`];
if (!currentPrice) return f;
const now = Date.now();
if (now >= f.targetTime) {
const priceWentUp = currentPrice > f.entryPrice;
const success = (f.predictedDirection === 'UP' && priceWentUp) || (f.predictedDirection === 'DOWN' && !priceWentUp);
updatedAny = true;
if (success) {
newAlpha += 1;
} else {
newBeta += 1;
}
addModelTrial(success);
return {
...f,
resolved: true,
result: success ? ('SUCCESS' as const) : ('FAILURE' as const)
};
}
return f;
});
if (updatedAny) {
setAlphaSuccess(newAlpha);
setBetaFailure(newBeta);
setForecasts(updatedForecasts);
localStorage.setItem('crypto_bayes_alpha', String(newAlpha));
localStorage.setItem('crypto_bayes_beta', String(newBeta));
localStorage.setItem('crypto_bayes_forecasts', JSON.stringify(updatedForecasts));
setLearningLoopLog(`Processed active forecasts. New successes: ${newAlpha}, New failures: ${newBeta}`);
setTimeout(() => setLearningLoopLog(''), 6000);
}
} catch (err) {
console.error("Learning loop evaluation error:", err);
}
};
if (forecasts.length > 0) {
runLearningLoop();
}
const interval = setInterval(runLearningLoop, 30000);
return () => clearInterval(interval);
}, [forecasts, alphaSuccess, betaFailure, addModelTrial]);
// Active Coin data retrieval
const activeCoin = useMemo(() => {
return customCoins[activeTicker] || defaultCoins[activeTicker] || defaultCoins['BTC'];
@@ -98,14 +276,12 @@ export default function CryptoDemo() {
// Apply Bayesian online learning error-correction posterior update
const correctedPredictions = useMemo(() => {
// Correct short term probability
const shortTermCorrected = calculateBetaPosterior(
alphaSuccess,
betaFailure,
mlPredictions.shortTermProb,
12 // pseudo weight/confidence scale
12 // confidence scale
);
// Correct medium term probability
const mediumTermCorrected = calculateBetaPosterior(
alphaSuccess,
betaFailure,
@@ -119,7 +295,7 @@ export default function CryptoDemo() {
};
}, [mlPredictions, alphaSuccess, betaFailure]);
// Perform search check for Altcoins
// Search/add new altcoin
const handleAltcoinSearch = (e: React.FormEvent) => {
e.preventDefault();
setSearchError(false);
@@ -138,7 +314,6 @@ export default function CryptoDemo() {
return;
}
// Generate simulated data for Altcoin
const isBull = Math.random() > 0.45;
const simulatedChange = isBull ? 3 + Math.random() * 8 : -2 - Math.random() * 6;
const simulatedPrice = isBull ? 2 + Math.random() * 10 : 0.2 + Math.random() * 3;
@@ -162,8 +337,44 @@ export default function CryptoDemo() {
setSearchQuery('');
};
// Manual logging of active forecast
const handleLogManualForecast = () => {
const entryPrice = parseFloat(activeCoin.price.replace(/[^0-9.]/g, ''));
const predictedDirection = correctedPredictions.shortTerm > 0.5 ? 'UP' : 'DOWN';
const predictedProb = correctedPredictions.shortTerm;
const newForecast: Forecast = {
id: 'fc-' + Date.now(),
ticker: activeCoin.ticker,
predictedDirection,
predictedProb,
entryPrice,
resolved: false,
timestamp: Date.now(),
targetTime: Date.now() + 60 * 1000 // resolves in 60s for direct visual validation
};
const nextForecasts = [newForecast, ...forecasts];
setForecasts(nextForecasts);
localStorage.setItem('crypto_bayes_forecasts', JSON.stringify(nextForecasts));
setLearningLoopLog(`Registered active forecast for ${activeCoin.ticker} at $${entryPrice}. Evaluating returns in 60 seconds.`);
setTimeout(() => setLearningLoopLog(''), 6000);
};
// Simulator for calibration
const handleSimulateTrial = (success: boolean) => {
addModelTrial(success);
setAlphaSuccess(prev => {
const next = success ? prev + 1 : prev;
localStorage.setItem('crypto_bayes_alpha', String(next));
return next;
});
setBetaFailure(prev => {
const next = !success ? prev + 1 : prev;
localStorage.setItem('crypto_bayes_beta', String(next));
return next;
});
setLastTrialSuccess(success);
setSimulatedTrialLogged(true);
setTimeout(() => setSimulatedTrialLogged(false), 2500);
@@ -179,9 +390,9 @@ export default function CryptoDemo() {
{/* Header */}
<div className="flex flex-col lg:flex-row justify-between items-start lg:items-center gap-4 border-b border-slate-800 pb-4 mb-6">
<div>
<span className="text-cyan-400 text-xs font-semibold uppercase tracking-wider">Element 4</span>
<span className="text-cyan-400 text-xs font-semibold uppercase tracking-wider">Level 4</span>
<h2 className="text-2xl font-bold bg-gradient-to-r from-cyan-400 to-sky-200 bg-clip-text text-transparent">
Predictive Krypto-Modelle & Bayes Self-Correction
Predictive Crypto Models & Bayes Self-Correction
</h2>
</div>
<div className="flex flex-wrap items-center gap-3">
@@ -195,13 +406,13 @@ export default function CryptoDemo() {
className="flex items-center gap-1.5 px-4 py-2 rounded-xl bg-slate-950/80 hover:bg-slate-900 border border-slate-800 hover:border-slate-700 transition-all font-semibold text-xs tracking-wider text-cyan-400 justify-center h-11"
>
<BookOpen className="w-3.5 h-3.5" />
<span>📖 Modulerklärung</span>
<span>📖 Quantitative Handbook</span>
</button>
<div className="bg-slate-900 border border-slate-800 rounded-xl px-4 py-2 flex items-center gap-3 h-11">
<Cpu className="text-cyan-400 w-5 h-5 animate-spin-slow" />
<div>
<p className="text-slate-400 text-xs">A-Priori Genauigkeit</p>
<p className="text-slate-400 text-xs">Prior Accuracy</p>
<p className="font-mono text-sm font-bold text-cyan-400">
{priorAccuracy.toFixed(1)}% (n={totalTrials})
</p>
@@ -245,7 +456,7 @@ export default function CryptoDemo() {
<input
type="text"
required
placeholder="Altcoin Ticker (z.B. LINK)"
placeholder="Altcoin Ticker (e.g. LINK)"
className="bg-slate-900 border border-slate-800 rounded-lg p-2 flex-1 text-slate-100 font-mono text-xs uppercase focus:outline-none focus:border-cyan-500"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
@@ -279,14 +490,14 @@ export default function CryptoDemo() {
{/* Left Column: Metrics Widgets */}
<div className="xl:col-span-2 space-y-6">
<h3 className="text-base font-bold text-white flex items-center gap-2 border-b border-slate-800 pb-3">
<BarChart2 className="text-cyan-400 w-5 h-5" /> On-Chain &amp; Derivate-Indikatoren ({activeCoin.ticker})
<BarChart2 className="text-cyan-400 w-5 h-5" /> On-Chain &amp; Derivative Indicators ({activeCoin.ticker})
</h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
{/* Funding & Open Interest Widget */}
<div className="p-4 rounded-xl border border-slate-850 bg-slate-950/40 space-y-3">
<h4 className="text-xs font-semibold text-slate-400 uppercase tracking-wider">Ref-Zinssatz &amp; Kontrakte (OI)</h4>
<h4 className="text-xs font-semibold text-slate-400 uppercase tracking-wider">Funding Rates &amp; Open Interest</h4>
<div className="space-y-2">
<div className="flex justify-between items-center text-sm font-mono">
<span className="text-slate-400 text-xs">Daily Funding Rate:</span>
@@ -305,14 +516,14 @@ export default function CryptoDemo() {
{/* Long/Short & Liquidation Widget */}
<div className="p-4 rounded-xl border border-slate-850 bg-slate-950/40 space-y-3">
<h4 className="text-xs font-semibold text-slate-400 uppercase tracking-wider">Positionierung &amp; Liquidationen</h4>
<h4 className="text-xs font-semibold text-slate-400 uppercase tracking-wider">Positioning &amp; Liquidations</h4>
<div className="space-y-2">
<div className="flex justify-between items-center text-sm font-mono">
<span className="text-slate-400 text-xs">Long / Short Ratio:</span>
<span className="text-slate-200 font-bold">{activeCoin.longShortRatio}</span>
</div>
<div className="flex justify-between items-center text-xs font-mono">
<span className="text-slate-400">Liq-Cluster:</span>
<span className="text-slate-400">Liq Cluster:</span>
<span className="text-rose-400">Long: {activeCoin.liqLong} | Short: {activeCoin.liqShort}</span>
</div>
</div>
@@ -320,32 +531,32 @@ export default function CryptoDemo() {
{/* Whale Flows Widget */}
<div className="p-4 rounded-xl border border-slate-850 bg-slate-950/40 space-y-3">
<h4 className="text-xs font-semibold text-slate-400 uppercase tracking-wider">Whale-Ströme (Nettozufluss)</h4>
<h4 className="text-xs font-semibold text-slate-400 uppercase tracking-wider">Whale Flows (Net Inflow)</h4>
<div className="space-y-2">
<div className="flex justify-between items-center text-sm font-mono">
<span className="text-slate-400 text-xs">Netto Inflow (Wallets):</span>
<span className="text-slate-400 text-xs">Net Inflow (Wallets):</span>
<span className={`font-bold ${activeCoin.whaleInflow >= 0 ? 'text-emerald-400' : 'text-rose-400'}`}>
{activeCoin.whaleInflow > 0 ? '+' : ''}{activeCoin.whaleInflow} {activeCoin.ticker}
</span>
</div>
<div className="text-[10px] text-slate-500 leading-relaxed font-sans">
Positive Werte signalisieren, dass Großinvestoren Bestände von Börsen auf private Wallets (Akkumulation) abziehen.
Positive values signal that large investors are withdrawing assets from exchanges to private wallets (accumulation).
</div>
</div>
</div>
{/* Exchange Reserves Widget */}
<div className="p-4 rounded-xl border border-slate-850 bg-slate-950/40 space-y-3">
<h4 className="text-xs font-semibold text-slate-400 uppercase tracking-wider">Börsenreserven (Spot)</h4>
<h4 className="text-xs font-semibold text-slate-400 uppercase tracking-wider">Exchange Reserves (Spot)</h4>
<div className="space-y-2">
<div className="flex justify-between items-center text-sm font-mono">
<span className="text-slate-400 text-xs">Reservenänderung (7d):</span>
<span className="text-slate-400 text-xs">Reserve Change (7d):</span>
<span className={`font-bold ${activeCoin.exchangeReserves <= 0 ? 'text-emerald-400' : 'text-rose-400'}`}>
{activeCoin.exchangeReserves > 0 ? '+' : ''}{activeCoin.exchangeReserves}%
</span>
</div>
<div className="text-[10px] text-slate-500 leading-relaxed font-sans">
Sinkende Reserven an den Spot-Börsen reduzieren den verfügbaren Verkaufsdruck und begünstigen Squeezes.
Falling reserves at spot exchanges reduce available selling pressure and favor squeezes.
</div>
</div>
</div>
@@ -356,7 +567,7 @@ export default function CryptoDemo() {
{/* Right Column: Predictive Gauges & Correction Calibration */}
<div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-6 text-slate-100 shadow-xl space-y-6">
<h3 className="text-base font-bold text-white flex items-center gap-2 border-b border-slate-800 pb-3">
<Compass className="text-cyan-400 w-5 h-5" /> Vorhersage-Wahrscheinlichkeiten
<Compass className="text-cyan-400 w-5 h-5" /> Prediction Probabilities
</h3>
{/* Gauges / Progress Bars */}
@@ -369,27 +580,25 @@ export default function CryptoDemo() {
<span className="text-cyan-400 font-mono">{(correctedPredictions.shortTerm * 100).toFixed(0)}%</span>
</div>
<div className="w-full bg-slate-950 rounded-full h-3 overflow-hidden border border-slate-850 flex">
{/* ML Baseline Overlay */}
<div
className="bg-cyan-500 h-full rounded-l transition-all duration-500 opacity-30"
style={{ width: `${mlPredictions.shortTermProb * 100}%` }}
/>
{/* Corrected Posterior Marker */}
<div
className="bg-cyan-400 h-full rounded-r transition-all duration-500 -ml-[20%] shadow-[0_0_10px_rgba(34,211,238,0.5)]"
style={{ width: `${correctedPredictions.shortTerm * 100}%` }}
/>
</div>
<div className="flex justify-between text-[9px] text-slate-500 font-mono">
<span>ML-Signal: {(mlPredictions.shortTermProb * 100).toFixed(0)}%</span>
<span className="text-cyan-400">Bayes-Korrigiert: {(correctedPredictions.shortTerm * 100).toFixed(0)}%</span>
<span>ML Signal: {(mlPredictions.shortTermProb * 100).toFixed(0)}%</span>
<span className="text-cyan-400">Bayes Corrected: {(correctedPredictions.shortTerm * 100).toFixed(0)}%</span>
</div>
</div>
{/* 14d Gauge */}
<div className="space-y-2">
<div className="flex justify-between text-xs font-semibold">
<span className="text-slate-300">14d Struktureller Bullish-Trend (Medium-Term)</span>
<span className="text-slate-300">14d Structural Bullish Trend (Medium-Term)</span>
<span className="text-teal-400 font-mono">{(correctedPredictions.mediumTerm * 100).toFixed(0)}%</span>
</div>
<div className="w-full bg-slate-950 rounded-full h-3 overflow-hidden border border-slate-850 flex">
@@ -403,8 +612,8 @@ export default function CryptoDemo() {
/>
</div>
<div className="flex justify-between text-[9px] text-slate-500 font-mono">
<span>ML-Signal: {(mlPredictions.mediumTermProb * 100).toFixed(0)}%</span>
<span className="text-teal-400">Bayes-Korrigiert: {(correctedPredictions.mediumTerm * 100).toFixed(0)}%</span>
<span>ML Signal: {(mlPredictions.mediumTermProb * 100).toFixed(0)}%</span>
<span className="text-teal-400">Bayes Corrected: {(correctedPredictions.mediumTerm * 100).toFixed(0)}%</span>
</div>
</div>
@@ -413,88 +622,161 @@ export default function CryptoDemo() {
{/* Model Calibration Log & Simulation */}
<div className="p-4 rounded-xl border border-slate-850 bg-slate-950/40 space-y-3">
<div className="flex items-center justify-between">
<h4 className="text-xs font-bold text-slate-300 uppercase">Bayes Modell-Kalibrierung</h4>
<h4 className="text-xs font-bold text-slate-300 uppercase">Bayes Model Calibration</h4>
<span className="text-[10px] text-slate-500 font-mono">n = {totalTrials} Trials</span>
</div>
<div className="grid grid-cols-2 gap-2 text-xs font-mono pb-2 border-b border-slate-900">
<div className="text-slate-400">Erfolge (&alpha;):</div>
<div className="text-slate-400">Successes (&alpha;):</div>
<div className="text-emerald-400 font-bold">{alphaSuccess}</div>
<div className="text-slate-400">Fehlalarme (&beta;):</div>
<div className="text-slate-400">False Alarms (&beta;):</div>
<div className="text-rose-400 font-bold">{betaFailure}</div>
</div>
{/* Trial simulator */}
<div className="space-y-2">
<p className="text-[10px] text-slate-400">Modell-Drift simulieren: Fügen Sie richtige/falsche Outcomes hinzu, um die Beta-Verteilung anzupassen.</p>
<p className="text-[10px] text-slate-400">Simulate model drift: Add correct/false outcomes to calibrate the Beta distribution.</p>
<div className="flex gap-2">
<button
onClick={() => handleSimulateTrial(true)}
className="flex-1 bg-emerald-500/10 hover:bg-emerald-500/20 text-emerald-400 border border-emerald-500/20 py-1.5 rounded-lg text-xs font-semibold font-mono"
>
+1 Erfolg
+1 Success
</button>
<button
onClick={() => handleSimulateTrial(false)}
className="flex-1 bg-rose-500/10 hover:bg-rose-500/20 text-rose-400 border border-rose-500/20 py-1.5 rounded-lg text-xs font-semibold font-mono"
>
+1 Fehlalarm
+1 False Alarm
</button>
</div>
{simulatedTrialLogged && (
<div className="text-[10px] text-cyan-400 font-mono text-center animate-pulse">
Trial geloggt! Bayes-Prior wurde auf {lastTrialSuccess ? 'Erfolg' : 'Fehlalarm'} aktualisiert.
Trial logged! Bayes prior updated to {lastTrialSuccess ? 'Success' : 'False Alarm'}.
</div>
)}
</div>
</div>
</div>
</div>
{/* SECTION 3: Mathematical LaTeX Accordion */}
{/* SECTION 3: Active Forecasts (Feedback Loop) */}
<div className="grid grid-cols-1 xl:grid-cols-3 gap-8 mt-6">
<div className="xl:col-span-2 bg-slate-950/30 rounded-xl p-4 border border-slate-850 space-y-4">
<div className="flex justify-between items-center border-b border-slate-800 pb-3">
<h3 className="text-sm font-bold text-white flex items-center gap-2">
<TrendingUp className="text-cyan-400 w-4 h-4" /> Active Learning Feedback Loop
</h3>
<button
onClick={handleLogManualForecast}
className="bg-cyan-500 hover:bg-cyan-600 text-slate-950 font-bold py-1.5 px-3 rounded-lg text-xs transition-all active:scale-[0.96]"
>
Log Forecast to Feedback Loop
</button>
</div>
{learningLoopLog && (
<div className="p-3 bg-cyan-950/20 border border-cyan-900/40 rounded-lg text-xs text-cyan-300 flex items-center gap-2">
<Info className="w-4 h-4 shrink-0" />
<span>{learningLoopLog}</span>
</div>
)}
<div className="overflow-x-auto max-h-56 scrollbar-thin">
<table className="w-full border-collapse text-left text-xs font-mono">
<thead>
<tr className="border-b border-slate-800 text-slate-400 font-semibold bg-slate-900/40">
<th className="p-2">Ticker</th>
<th className="p-2">Direction</th>
<th className="p-2">Probability</th>
<th className="p-2">Entry Price</th>
<th className="p-2">Status</th>
<th className="p-2 text-right">Result</th>
</tr>
</thead>
<tbody>
{forecasts.length === 0 ? (
<tr>
<td colSpan={6} className="p-4 text-center text-slate-500 italic">No forecasts registered yet.</td>
</tr>
) : (
forecasts.map((fc) => (
<tr key={fc.id} className="border-b border-slate-900 hover:bg-slate-850/10">
<td className="p-2 text-slate-200 font-bold">{fc.ticker}</td>
<td className="p-2">
<span className={`px-1.5 py-0.5 rounded text-[10px] font-bold ${fc.predictedDirection === 'UP' ? 'bg-emerald-500/10 text-emerald-400' : 'bg-rose-500/10 text-rose-400'}`}>
{fc.predictedDirection}
</span>
</td>
<td className="p-2 text-slate-350">{(fc.predictedProb * 100).toFixed(0)}%</td>
<td className="p-2 text-slate-300">${fc.entryPrice.toLocaleString()}</td>
<td className="p-2 text-slate-400">{fc.resolved ? 'RESOLVED' : 'PENDING'}</td>
<td className={`p-2 text-right font-bold ${fc.result === 'SUCCESS' ? 'text-emerald-400' : fc.result === 'FAILURE' ? 'text-rose-400' : 'text-slate-500'}`}>
{fc.result || '-'}
</td>
</tr>
))
)}
</tbody>
</table>
</div>
</div>
{/* Informational overlay */}
<div className="bg-slate-950/40 rounded-xl p-4 border border-slate-850 text-xs text-slate-400 space-y-2">
<h4 className="font-bold text-slate-300 uppercase">Econometric Feedback Loop Spec</h4>
<p className="leading-relaxed">
The learning loop automatically evaluates active forecast parameters in the background against actual price histories returned by <code className="text-cyan-400 font-mono">/api/finance?region=crypto</code>.
</p>
<p className="leading-relaxed">
When a logged forecast passes its evaluation target timestamp, it resolves against live market data, updating the Bayesian online calibration metrics <InlineMath math="\alpha" /> and <InlineMath math="\beta" />.
</p>
</div>
</div>
{/* SECTION 4: Mathematical LaTeX Accordion */}
<div className="border-t border-slate-850 pt-4 mt-6">
<button
onClick={() => setShowMathAccordion(!showMathAccordion)}
className="flex items-center gap-1.5 text-xs text-slate-400 hover:text-cyan-400 transition-colors focus:outline-none"
>
<span>{showMathAccordion ? <ChevronUp className="w-4 h-4" /> : <ChevronDown className="w-4 h-4" />}</span>
<span className="font-semibold uppercase tracking-wider">Mathematische Formulierung (Beta-Update &amp; Random Forest)</span>
<span className="font-semibold uppercase tracking-wider">Mathematical Formulation (Beta Update &amp; Random Forest)</span>
</button>
{showMathAccordion && (
<div className="mt-4 p-4 rounded-xl border border-slate-850 bg-slate-950/40 text-xs text-slate-300 space-y-4">
<div>
<h4 className="font-bold text-cyan-400 mb-1">1. Bayesianische Beta-Konjugierte Fehlerkorrektur</h4>
<h4 className="font-bold text-cyan-400 mb-1">1. Bayesian Beta-Conjugate Error Correction</h4>
<p className="mb-2">
Wir modellieren das Vertrauensintervall über die Fehlerraten des Modells mittels einer Beta-Verteilung. Der A-Priori Fehlerzustand wird durch die Parameter <InlineMath math="\alpha" /> (Erfolge) und <InlineMath math="\beta" /> (Fehlalarme) dargestellt:
We model the error rate confidence interval of the model using a Beta distribution. The prior error state is represented by the parameters <InlineMath math="\alpha" /> (Successes) and <InlineMath math="\beta" /> (False Alarms):
</p>
<div className="py-2 overflow-x-auto text-slate-200">
<BlockMath math="P \sim \text{Beta}(\alpha, \beta) \quad \text{mit Erwartungswert } \mathbb{E}[P] = \frac{\alpha}{\alpha + \beta}" />
<BlockMath math="P \\sim \\text{Beta}(\\alpha, \\beta) \\quad \\text{with expected value } \\mathbb{E}[P] = \\frac{\\alpha}{\\alpha + \\beta}" />
</div>
<p className="mb-2">
Bei einem neuen ML-Signal <InlineMath math="P_{\text{ML}}" /> führen wir ein konjugiertes Bayes-Update mit einem Vertrauensgewicht <InlineMath math="w" /> aus:
With a new ML signal <InlineMath math="P_{\\text{ML}}" />, we perform a conjugate Bayes update with a confidence weight <InlineMath math="w" />:
</p>
<div className="py-2 overflow-x-auto text-slate-200">
<BlockMath math="\alpha_{\text{post}} = \alpha + w \cdot P_{\text{ML}}, \quad \beta_{\text{post}} = \beta + w \cdot (1 - P_{\text{ML}})" />
<BlockMath math="\\alpha_{\\text{post}} = \\alpha + w \\cdot P_{\\text{ML}}, \\quad \\beta_{\\text{post}} = \\beta + w \\cdot (1 - P_{\\text{ML}})" />
</div>
<div className="py-2 overflow-x-auto text-slate-200">
<BlockMath math="P_{\text{Posterior}} = \frac{\alpha_{\text{post}}}{\alpha_{\text{post}} + \beta_{\text{post}}}" />
<BlockMath math="P_{\\text{Posterior}} = \\frac{\\alpha_{\\text{post}}}{\\alpha_{\\text{post}} + \\beta_{\\text{post}}}" />
</div>
<p className="text-slate-400">
Ist das Modell historisch sehr instabil (hohes <InlineMath math="\beta" />), korrigiert der Bayesianische Term ein übermütiges ML-Signal nach unten, was die Robustheit des Gesamtsystems schützt.
If the model is historically highly unstable (high <InlineMath math="\\beta" />), the Bayesian term corrects an overconfident ML signal downwards, safeguarding the robustness of the system.
</p>
</div>
<div className="border-t border-slate-900 pt-3">
<h4 className="font-bold text-cyan-400 mb-1">2. Random Forest Nicht-Lineares Signalmapping</h4>
<h4 className="font-bold text-cyan-400 mb-1">2. Random Forest Non-Linear Signal Mapping</h4>
<p className="mb-2">
Der Random Forest simuliert ein Ensemble von 10 schwachen Entscheidungsbäumen. Jeder Baum spaltet die Daten nach Schwellenwerten (z.B. &bdquo;Funding-Rate &lt; -0.04%&ldquo; und &bdquo;Open Interest &gt; 10%&ldquo;) auf:
The Random Forest simulates an ensemble of 10 weak decision trees. Each tree splits the data based on threshold criteria (e.g., 'Funding Rate &lt; -0.04%' and 'Open Interest &gt; 10%'):
</p>
<div className="py-2 overflow-x-auto text-slate-200">
<BlockMath math="\text{ML}_{\text{prob}} = \frac{1}{M} \sum_{m=1}^{M} T_m(\mathbf{x})" />
<BlockMath math="\\text{ML}_{\\text{prob}} = \\frac{1}{M} \\sum_{m=1}^{M} T_m(\\mathbf{x})" />
</div>
<p className="text-slate-400">
wobei <InlineMath math="T_m(\mathbf{x})" /> der prognostizierte Ausgabewert des <InlineMath math="m" />-ten Entscheidungsbaumes r den Featurevektor <InlineMath math="\mathbf{x}" /> ist.
where <InlineMath math="T_m(\\mathbf{x})" /> is the predicted output value of the <InlineMath math="m" />-th decision tree for the feature vector <InlineMath math="\\mathbf{x}" />.
</p>
</div>
</div>