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

@@ -122,3 +122,21 @@ This document tracks all modifications, npm packages, active compilation states,
### Active Bugs / Compile Status ### Active Bugs / Compile Status
* **Active Bugs**: None. * **Active Bugs**: None.
* **Type Checker Status**: Verified clean compilation (`npx tsc --noEmit` returns exit code 0). * **Type Checker Status**: Verified clean compilation (`npx tsc --noEmit` returns exit code 0).
---
## [2026-06-13] - System-Wide Handbook Sweep, English Consolidation & Crypto State Persistence (#ISSUE-014)
### Added
* **Sandbox Math Handbook**: Created `components/modules/sandbox/SandboxMathModal.tsx` detailing the Kelly Criterion, Half-Kelly safety buffers, percentage weightings (\(w_i\)), and synthetic portfolio returns (\(R_{pt}\)) in double-escaped BlockMath LaTeX.
* **Crypto Online Learning Loop**: Integrated a client-side background evaluation routine inside `components/modules/crypto/CryptoDemo.tsx` that resolves active forecasts against price histories from `/api/finance?region=crypto` and updates the Bayesian online calibration parameters.
### Modified
* **KaTeX Escaping & Close Handler Audit**: Standardized all 8 math handbook modals with Escape key listeners and glassmorphic floating top-right "X" buttons. Repaired all escaping sequences for KaTeX rendering strings across all components.
* **100% Institutional English Translation**: Swapped all remaining German UI texts, buttons (e.g. `📖 Modulerklärung` renamed to `📖 Quantitative Handbook`), table cells, and warnings to professional English across all tabs (`Smart Money`, `Events/Econometrics`, `Macro`, `Tech Silo`, `Sandbox`, `Scanner`).
* **Next.js SSR Hydration Safeguard**: Wrapped `localStorage` operations for `alphaSuccess`, `betaFailure`, and active forecasts inside a React `useEffect` hook in `CryptoDemo.tsx` to prevent hydration mismatches.
* **`QUANT_ROADMAP.md`**: Updated Section 1 and Section 4.VI detailing the Sandbox Portfolio and Kelly sizing formulations.
### Active Bugs / Compile Status
* **Active Bugs**: None.
* **Type Checker Status**: Verified clean compilation (`npx tsc --noEmit` returns exit code 0).

View File

@@ -197,6 +197,29 @@ $$P_{\text{Posterior}} = \frac{\alpha_{\text{prior}} + (P_{\text{ML}} \times w)}
--- ---
### VI. Sandbox Portfolio Cockpit & Kelly Sizing
Integrates fractional betting algorithms and asset weight models inside the active Portfolio Sandbox environment.
#### 1. Active Portfolio Weighting ($w_i$)
Calculates the dynamic percentage value allocation of constituent assets:
$$w_i = \frac{\text{Shares}_i \times P_{\text{current}, i}}{\sum_{j} \text{Shares}_j \times P_{\text{current}, j}}$$
#### 2. Synthetic Portfolio Return ($R_{pt}$)
Simulates active log returns of the combined holdings:
$$R_{pt} = \sum_{i} w_i \times \ln\left(\frac{P_{t, i}}{P_{t-1, i}}\right)$$
#### 3. Theoretical Kelly Sizing ($f^*$)
Calculates the optimal size fraction to maximize the log growth of capital:
$$f^* = \frac{p \cdot b - (1 - p)}{b}$$
Where $p$ is the probability of success, and $b$ is the payout odds ratio (average win/average loss).
#### 4. Half-Kelly Safety Buffer Sizing
Applies a fractional buffer to lower estimation variance and protect against drawdowns:
$$f_{\text{applied}} = \max\left(0, 0.5 \times f^*\right)$$
---
## 5. Multi-Regime Transition Classifier ## 5. Multi-Regime Transition Classifier
The core cognitive brain of the sandbox dynamically adjusts allocation weights across our portfolio modules based on estimated macroeconomic and market states. The core cognitive brain of the sandbox dynamically adjusts allocation weights across our portfolio modules based on estimated macroeconomic and market states.

View File

@@ -30,16 +30,16 @@ export default function Home() {
</div> </div>
<div> <div>
<h1 className="text-xl font-bold bg-gradient-to-r from-teal-400 via-sky-300 to-indigo-400 bg-clip-text text-transparent"> <h1 className="text-xl font-bold bg-gradient-to-r from-teal-400 via-sky-300 to-indigo-400 bg-clip-text text-transparent">
QuantSandbox &Ouml;konometrie QuantSandbox Econometrics
</h1> </h1>
<p className="text-[10px] text-slate-400 uppercase tracking-widest font-mono">KI-gestützte Investment-Sandbox</p> <p className="text-[10px] text-slate-400 uppercase tracking-widest font-mono">AI-Powered Investment Sandbox</p>
</div> </div>
</div> </div>
<div className="hidden md:flex items-center gap-6 text-xs text-slate-400"> <div className="hidden md:flex items-center gap-6 text-xs text-slate-400">
<div className="flex items-center gap-2 border-r border-slate-800 pr-4"> <div className="flex items-center gap-2 border-r border-slate-800 pr-4">
<span className="w-2 h-2 rounded-full bg-emerald-500 animate-pulse" /> <span className="w-2 h-2 rounded-full bg-emerald-500 animate-pulse" />
<span>Verbindung aktiv</span> <span>Connection Active</span>
</div> </div>
<div className="flex items-center gap-1.5 font-mono"> <div className="flex items-center gap-1.5 font-mono">
<span className="text-slate-500">Workspace:</span> <span className="text-slate-500">Workspace:</span>
@@ -58,10 +58,10 @@ export default function Home() {
Scaffolding Version 1.0.0 Scaffolding Version 1.0.0
</span> </span>
<h2 className="text-3xl font-extrabold text-white tracking-tight sm:text-4xl"> <h2 className="text-3xl font-extrabold text-white tracking-tight sm:text-4xl">
Statistische Investment-Analyse & Sandbox Statistical Investment Analysis & Sandbox
</h2> </h2>
<p className="text-slate-400 text-sm leading-relaxed"> <p className="text-slate-400 text-sm leading-relaxed">
Diese modulare Architektur bündelt fortgeschrittene &ouml;konometrische Modelle &ndash; von EWMA und GJR-GARCH Volatilit&auml;tsprognosen über Bayesianisches On-Chain-Lernen bis hin zu Überlebens- und LMM-Regressionsmodellen. This modular architecture pools advanced econometric models &ndash; from EWMA and GJR-GARCH volatility forecasts to Bayesian on-chain learning, survival analysis, and LMM panel regressions.
</p> </p>
</div> </div>
@@ -88,13 +88,13 @@ export default function Home() {
onClick={() => setActiveTab('crypto')} onClick={() => setActiveTab('crypto')}
className={`flex-1 lg:flex-none px-4 py-2.5 rounded-xl text-xs font-semibold flex items-center justify-center gap-2 transition-all ${activeTab === 'crypto' ? 'bg-gradient-to-r from-cyan-500 to-sky-500 text-slate-950 font-bold shadow-lg shadow-cyan-500/25' : 'text-slate-400 hover:text-slate-200 hover:bg-slate-900/50'}`} className={`flex-1 lg:flex-none px-4 py-2.5 rounded-xl text-xs font-semibold flex items-center justify-center gap-2 transition-all ${activeTab === 'crypto' ? 'bg-gradient-to-r from-cyan-500 to-sky-500 text-slate-950 font-bold shadow-lg shadow-cyan-500/25' : 'text-slate-400 hover:text-slate-200 hover:bg-slate-900/50'}`}
> >
<BarChart3 className="w-4 h-4" /> Krypto Bayes <BarChart3 className="w-4 h-4" /> Crypto Bayes
</button> </button>
<button <button
onClick={() => setActiveTab('events')} onClick={() => setActiveTab('events')}
className={`flex-1 lg:flex-none px-4 py-2.5 rounded-xl text-xs font-semibold flex items-center justify-center gap-2 transition-all ${activeTab === 'events' ? 'bg-gradient-to-r from-rose-500 to-pink-500 text-slate-950 font-bold shadow-lg shadow-rose-500/25' : 'text-slate-400 hover:text-slate-200 hover:bg-slate-900/50'}`} className={`flex-1 lg:flex-none px-4 py-2.5 rounded-xl text-xs font-semibold flex items-center justify-center gap-2 transition-all ${activeTab === 'events' ? 'bg-gradient-to-r from-rose-500 to-pink-500 text-slate-950 font-bold shadow-lg shadow-rose-500/25' : 'text-slate-400 hover:text-slate-200 hover:bg-slate-900/50'}`}
> >
<Landmark className="w-4 h-4" /> Ökonometrie <Landmark className="w-4 h-4" /> Econometrics
</button> </button>
<button <button
onClick={() => setActiveTab('macro')} onClick={() => setActiveTab('macro')}
@@ -148,7 +148,7 @@ export default function Home() {
{/* Footer */} {/* Footer */}
<footer className="border-t border-slate-900 bg-slate-950/60 py-6 text-center text-xs text-slate-500 mt-auto"> <footer className="border-t border-slate-900 bg-slate-950/60 py-6 text-center text-xs text-slate-500 mt-auto">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex flex-col sm:flex-row justify-between items-center gap-4"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex flex-col sm:flex-row justify-between items-center gap-4">
<p>&copy; 2026 QuantSandbox Inc. Alle Rechte vorbehalten.</p> <p>&copy; 2026 QuantSandbox Inc. All rights reserved.</p>
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<span className="flex items-center gap-1"><RefreshCw className="w-3.5 h-3.5 text-teal-400 animate-spin-slow" /> Zustand State Engine</span> <span className="flex items-center gap-1"><RefreshCw className="w-3.5 h-3.5 text-teal-400 animate-spin-slow" /> Zustand State Engine</span>
<span>|</span> <span>|</span>

View File

@@ -9,7 +9,7 @@ import CryptoMathModal from './CryptoMathModal';
import { import {
Cpu, Search, RefreshCw, BarChart2, TrendingUp, AlertCircle, Info, Cpu, Search, RefreshCw, BarChart2, TrendingUp, AlertCircle, Info,
ChevronDown, ChevronUp, ArrowUpRight, ArrowDownRight, Compass, ShieldAlert, Sparkles, ChevronDown, ChevronUp, ArrowUpRight, ArrowDownRight, Compass, ShieldAlert, Sparkles,
BookOpen BookOpen, Check
} from 'lucide-react'; } from 'lucide-react';
interface CoinData { 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() { 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 [activeTicker, setActiveTicker] = useState<string>('BTC');
const [searchQuery, setSearchQuery] = useState(''); const [searchQuery, setSearchQuery] = useState('');
@@ -80,6 +98,166 @@ export default function CryptoDemo() {
const [simulatedTrialLogged, setSimulatedTrialLogged] = useState(false); const [simulatedTrialLogged, setSimulatedTrialLogged] = useState(false);
const [lastTrialSuccess, setLastTrialSuccess] = 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 // Active Coin data retrieval
const activeCoin = useMemo(() => { const activeCoin = useMemo(() => {
return customCoins[activeTicker] || defaultCoins[activeTicker] || defaultCoins['BTC']; return customCoins[activeTicker] || defaultCoins[activeTicker] || defaultCoins['BTC'];
@@ -98,14 +276,12 @@ export default function CryptoDemo() {
// Apply Bayesian online learning error-correction posterior update // Apply Bayesian online learning error-correction posterior update
const correctedPredictions = useMemo(() => { const correctedPredictions = useMemo(() => {
// Correct short term probability
const shortTermCorrected = calculateBetaPosterior( const shortTermCorrected = calculateBetaPosterior(
alphaSuccess, alphaSuccess,
betaFailure, betaFailure,
mlPredictions.shortTermProb, mlPredictions.shortTermProb,
12 // pseudo weight/confidence scale 12 // confidence scale
); );
// Correct medium term probability
const mediumTermCorrected = calculateBetaPosterior( const mediumTermCorrected = calculateBetaPosterior(
alphaSuccess, alphaSuccess,
betaFailure, betaFailure,
@@ -119,7 +295,7 @@ export default function CryptoDemo() {
}; };
}, [mlPredictions, alphaSuccess, betaFailure]); }, [mlPredictions, alphaSuccess, betaFailure]);
// Perform search check for Altcoins // Search/add new altcoin
const handleAltcoinSearch = (e: React.FormEvent) => { const handleAltcoinSearch = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
setSearchError(false); setSearchError(false);
@@ -138,7 +314,6 @@ export default function CryptoDemo() {
return; return;
} }
// Generate simulated data for Altcoin
const isBull = Math.random() > 0.45; const isBull = Math.random() > 0.45;
const simulatedChange = isBull ? 3 + Math.random() * 8 : -2 - Math.random() * 6; const simulatedChange = isBull ? 3 + Math.random() * 8 : -2 - Math.random() * 6;
const simulatedPrice = isBull ? 2 + Math.random() * 10 : 0.2 + Math.random() * 3; const simulatedPrice = isBull ? 2 + Math.random() * 10 : 0.2 + Math.random() * 3;
@@ -162,8 +337,44 @@ export default function CryptoDemo() {
setSearchQuery(''); 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) => { const handleSimulateTrial = (success: boolean) => {
addModelTrial(success); 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); setLastTrialSuccess(success);
setSimulatedTrialLogged(true); setSimulatedTrialLogged(true);
setTimeout(() => setSimulatedTrialLogged(false), 2500); setTimeout(() => setSimulatedTrialLogged(false), 2500);
@@ -179,9 +390,9 @@ export default function CryptoDemo() {
{/* Header */} {/* 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 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> <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"> <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> </h2>
</div> </div>
<div className="flex flex-wrap items-center gap-3"> <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" 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" /> <BookOpen className="w-3.5 h-3.5" />
<span>📖 Modulerklärung</span> <span>📖 Quantitative Handbook</span>
</button> </button>
<div className="bg-slate-900 border border-slate-800 rounded-xl px-4 py-2 flex items-center gap-3 h-11"> <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" /> <Cpu className="text-cyan-400 w-5 h-5 animate-spin-slow" />
<div> <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"> <p className="font-mono text-sm font-bold text-cyan-400">
{priorAccuracy.toFixed(1)}% (n={totalTrials}) {priorAccuracy.toFixed(1)}% (n={totalTrials})
</p> </p>
@@ -245,7 +456,7 @@ export default function CryptoDemo() {
<input <input
type="text" type="text"
required 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" 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} value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)} onChange={(e) => setSearchQuery(e.target.value)}
@@ -279,14 +490,14 @@ export default function CryptoDemo() {
{/* Left Column: Metrics Widgets */} {/* Left Column: Metrics Widgets */}
<div className="xl:col-span-2 space-y-6"> <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"> <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> </h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
{/* Funding & Open Interest Widget */} {/* Funding & Open Interest Widget */}
<div className="p-4 rounded-xl border border-slate-850 bg-slate-950/40 space-y-3"> <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="space-y-2">
<div className="flex justify-between items-center text-sm font-mono"> <div className="flex justify-between items-center text-sm font-mono">
<span className="text-slate-400 text-xs">Daily Funding Rate:</span> <span className="text-slate-400 text-xs">Daily Funding Rate:</span>
@@ -305,14 +516,14 @@ export default function CryptoDemo() {
{/* Long/Short & Liquidation Widget */} {/* Long/Short & Liquidation Widget */}
<div className="p-4 rounded-xl border border-slate-850 bg-slate-950/40 space-y-3"> <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="space-y-2">
<div className="flex justify-between items-center text-sm font-mono"> <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-400 text-xs">Long / Short Ratio:</span>
<span className="text-slate-200 font-bold">{activeCoin.longShortRatio}</span> <span className="text-slate-200 font-bold">{activeCoin.longShortRatio}</span>
</div> </div>
<div className="flex justify-between items-center text-xs font-mono"> <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> <span className="text-rose-400">Long: {activeCoin.liqLong} | Short: {activeCoin.liqShort}</span>
</div> </div>
</div> </div>
@@ -320,32 +531,32 @@ export default function CryptoDemo() {
{/* Whale Flows Widget */} {/* Whale Flows Widget */}
<div className="p-4 rounded-xl border border-slate-850 bg-slate-950/40 space-y-3"> <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="space-y-2">
<div className="flex justify-between items-center text-sm font-mono"> <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'}`}> <span className={`font-bold ${activeCoin.whaleInflow >= 0 ? 'text-emerald-400' : 'text-rose-400'}`}>
{activeCoin.whaleInflow > 0 ? '+' : ''}{activeCoin.whaleInflow} {activeCoin.ticker} {activeCoin.whaleInflow > 0 ? '+' : ''}{activeCoin.whaleInflow} {activeCoin.ticker}
</span> </span>
</div> </div>
<div className="text-[10px] text-slate-500 leading-relaxed font-sans"> <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> </div>
</div> </div>
{/* Exchange Reserves Widget */} {/* Exchange Reserves Widget */}
<div className="p-4 rounded-xl border border-slate-850 bg-slate-950/40 space-y-3"> <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="space-y-2">
<div className="flex justify-between items-center text-sm font-mono"> <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'}`}> <span className={`font-bold ${activeCoin.exchangeReserves <= 0 ? 'text-emerald-400' : 'text-rose-400'}`}>
{activeCoin.exchangeReserves > 0 ? '+' : ''}{activeCoin.exchangeReserves}% {activeCoin.exchangeReserves > 0 ? '+' : ''}{activeCoin.exchangeReserves}%
</span> </span>
</div> </div>
<div className="text-[10px] text-slate-500 leading-relaxed font-sans"> <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> </div>
</div> </div>
@@ -356,7 +567,7 @@ export default function CryptoDemo() {
{/* Right Column: Predictive Gauges & Correction Calibration */} {/* 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"> <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"> <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> </h3>
{/* Gauges / Progress Bars */} {/* Gauges / Progress Bars */}
@@ -369,27 +580,25 @@ export default function CryptoDemo() {
<span className="text-cyan-400 font-mono">{(correctedPredictions.shortTerm * 100).toFixed(0)}%</span> <span className="text-cyan-400 font-mono">{(correctedPredictions.shortTerm * 100).toFixed(0)}%</span>
</div> </div>
<div className="w-full bg-slate-950 rounded-full h-3 overflow-hidden border border-slate-850 flex"> <div className="w-full bg-slate-950 rounded-full h-3 overflow-hidden border border-slate-850 flex">
{/* ML Baseline Overlay */}
<div <div
className="bg-cyan-500 h-full rounded-l transition-all duration-500 opacity-30" className="bg-cyan-500 h-full rounded-l transition-all duration-500 opacity-30"
style={{ width: `${mlPredictions.shortTermProb * 100}%` }} style={{ width: `${mlPredictions.shortTermProb * 100}%` }}
/> />
{/* Corrected Posterior Marker */}
<div <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)]" 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}%` }} style={{ width: `${correctedPredictions.shortTerm * 100}%` }}
/> />
</div> </div>
<div className="flex justify-between text-[9px] text-slate-500 font-mono"> <div className="flex justify-between text-[9px] text-slate-500 font-mono">
<span>ML-Signal: {(mlPredictions.shortTermProb * 100).toFixed(0)}%</span> <span>ML Signal: {(mlPredictions.shortTermProb * 100).toFixed(0)}%</span>
<span className="text-cyan-400">Bayes-Korrigiert: {(correctedPredictions.shortTerm * 100).toFixed(0)}%</span> <span className="text-cyan-400">Bayes Corrected: {(correctedPredictions.shortTerm * 100).toFixed(0)}%</span>
</div> </div>
</div> </div>
{/* 14d Gauge */} {/* 14d Gauge */}
<div className="space-y-2"> <div className="space-y-2">
<div className="flex justify-between text-xs font-semibold"> <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> <span className="text-teal-400 font-mono">{(correctedPredictions.mediumTerm * 100).toFixed(0)}%</span>
</div> </div>
<div className="w-full bg-slate-950 rounded-full h-3 overflow-hidden border border-slate-850 flex"> <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>
<div className="flex justify-between text-[9px] text-slate-500 font-mono"> <div className="flex justify-between text-[9px] text-slate-500 font-mono">
<span>ML-Signal: {(mlPredictions.mediumTermProb * 100).toFixed(0)}%</span> <span>ML Signal: {(mlPredictions.mediumTermProb * 100).toFixed(0)}%</span>
<span className="text-teal-400">Bayes-Korrigiert: {(correctedPredictions.mediumTerm * 100).toFixed(0)}%</span> <span className="text-teal-400">Bayes Corrected: {(correctedPredictions.mediumTerm * 100).toFixed(0)}%</span>
</div> </div>
</div> </div>
@@ -413,88 +622,161 @@ export default function CryptoDemo() {
{/* Model Calibration Log & Simulation */} {/* Model Calibration Log & Simulation */}
<div className="p-4 rounded-xl border border-slate-850 bg-slate-950/40 space-y-3"> <div className="p-4 rounded-xl border border-slate-850 bg-slate-950/40 space-y-3">
<div className="flex items-center justify-between"> <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> <span className="text-[10px] text-slate-500 font-mono">n = {totalTrials} Trials</span>
</div> </div>
<div className="grid grid-cols-2 gap-2 text-xs font-mono pb-2 border-b border-slate-900"> <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-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 className="text-rose-400 font-bold">{betaFailure}</div>
</div> </div>
{/* Trial simulator */} {/* Trial simulator */}
<div className="space-y-2"> <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"> <div className="flex gap-2">
<button <button
onClick={() => handleSimulateTrial(true)} 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" 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>
<button <button
onClick={() => handleSimulateTrial(false)} 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" 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> </button>
</div> </div>
{simulatedTrialLogged && ( {simulatedTrialLogged && (
<div className="text-[10px] text-cyan-400 font-mono text-center animate-pulse"> <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> </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"> <div className="border-t border-slate-850 pt-4 mt-6">
<button <button
onClick={() => setShowMathAccordion(!showMathAccordion)} onClick={() => setShowMathAccordion(!showMathAccordion)}
className="flex items-center gap-1.5 text-xs text-slate-400 hover:text-cyan-400 transition-colors focus:outline-none" 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>{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> </button>
{showMathAccordion && ( {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 className="mt-4 p-4 rounded-xl border border-slate-850 bg-slate-950/40 text-xs text-slate-300 space-y-4">
<div> <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"> <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> </p>
<div className="py-2 overflow-x-auto text-slate-200"> <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> </div>
<p className="mb-2"> <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> </p>
<div className="py-2 overflow-x-auto text-slate-200"> <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>
<div className="py-2 overflow-x-auto text-slate-200"> <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> </div>
<p className="text-slate-400"> <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> </p>
</div> </div>
<div className="border-t border-slate-900 pt-3"> <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"> <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> </p>
<div className="py-2 overflow-x-auto text-slate-200"> <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> </div>
<p className="text-slate-400"> <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> </p>
</div> </div>
</div> </div>

View File

@@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { BookOpen } from 'lucide-react'; import { BookOpen, X } from 'lucide-react';
import 'katex/dist/katex.min.css'; import 'katex/dist/katex.min.css';
import { BlockMath, InlineMath } from 'react-katex'; import { BlockMath, InlineMath } from 'react-katex';
@@ -26,8 +26,8 @@ export default function EconometricsMathModal({ isOpen, onClose }: EconometricsM
if (!isOpen) return null; if (!isOpen) return null;
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-slate-950/85 backdrop-blur-md p-4 sm:p-6 md:p-8"> <div className="fixed inset-0 z-50 flex items-center justify-center bg-slate-955/90 backdrop-blur-md p-4 sm:p-6 md:p-8">
<div className="bg-slate-900 border border-slate-800/80 rounded-3xl w-full max-w-4xl h-[80vh] flex flex-col overflow-hidden shadow-2xl relative text-slate-300"> <div className="bg-slate-900 border border-slate-800/80 rounded-3xl w-full max-w-4xl h-[80vh] flex flex-col overflow-hidden shadow-2xl relative text-slate-350">
{/* Modal Header */} {/* Modal Header */}
<div className="flex justify-between items-center px-6 py-4 bg-slate-950/40 border-b border-slate-800/60"> <div className="flex justify-between items-center px-6 py-4 bg-slate-950/40 border-b border-slate-800/60">
@@ -39,9 +39,10 @@ export default function EconometricsMathModal({ isOpen, onClose }: EconometricsM
</div> </div>
<button <button
onClick={onClose} onClick={onClose}
className="text-slate-400 hover:text-slate-200 bg-slate-950/50 border border-slate-800 hover:border-slate-700 px-3 py-1.5 rounded-lg text-xs font-semibold font-mono transition-all cursor-pointer" className="text-slate-400 hover:text-slate-200 bg-slate-950/50 border border-slate-800 hover:border-slate-700 p-2 rounded-xl transition-all cursor-pointer flex items-center justify-center"
aria-label="Close modal"
> >
Schließen (ESC) <X className="w-4 h-4" />
</button> </button>
</div> </div>
@@ -69,10 +70,10 @@ export default function EconometricsMathModal({ isOpen, onClose }: EconometricsM
<div className="space-y-3"> <div className="space-y-3">
<h4 className="text-xs font-bold text-rose-400 uppercase tracking-wider font-mono">B. Endogenous Calibration</h4> <h4 className="text-xs font-bold text-rose-400 uppercase tracking-wider font-mono">B. Endogenous Calibration</h4>
<p className="text-xs leading-relaxed text-slate-400"> <p className="text-xs leading-relaxed text-slate-400">
Active future matrix cells pre-fill suggested scores by looking up the corresponding historical LMM coefficient <InlineMath math="\beta_{asset\_event\_post}" /> and scaling it to our native score scale: Active future matrix cells pre-fill suggested scores by looking up the corresponding historical LMM coefficient <InlineMath math="\\beta_{\\text{asset}\\_\\text{event}\\_\\text{post}}" /> and scaling it to our native score scale:
</p> </p>
<div className="bg-slate-950/40 p-4 rounded-xl border border-slate-800/60 my-2"> <div className="bg-slate-950/40 p-4 rounded-xl border border-slate-800/60 my-2">
<BlockMath math="\text{Score}_{\text{suggested}} = \max\left(-3, \min\left(3, \text{Round}(\beta_{\text{estimate}} \times 100)\right)\right)" /> <BlockMath math="\\text{Score}_{\\text{suggested}} = \\max\\left(-3, \\min\\left(3, \\text{Round}(\\beta_{\\text{estimate}} \\times 100)\\right)\\right)" />
</div> </div>
</div> </div>
@@ -82,13 +83,17 @@ export default function EconometricsMathModal({ isOpen, onClose }: EconometricsM
The engine estimates direct event drift and impact returns, isolating asset-level intercepts as random deviances and purging macro volatility using VIX indices: The engine estimates direct event drift and impact returns, isolating asset-level intercepts as random deviances and purging macro volatility using VIX indices:
</p> </p>
<div className="bg-slate-950/40 p-4 rounded-xl border border-slate-800/60 my-2"> <div className="bg-slate-950/40 p-4 rounded-xl border border-slate-800/60 my-2">
<BlockMath math="Y_{it} = X_{it}\beta + Z_{it}b_i + \varepsilon_{it}" /> <BlockMath math="Y_{it} = X_{it}\\beta + Z_{it}b_i + \\varepsilon_{it}" />
<p className="text-[11px] text-slate-400 mt-2 font-mono leading-relaxed"> <p className="text-[11px] text-slate-400 mt-2 font-mono leading-relaxed">
Where:<br/> {"Where:"}
- <InlineMath math="Y_{it}" /> is the log-return <InlineMath math="\ln(P_t/P_0)" /> of asset <InlineMath math="i" /> at relative index <InlineMath math="t \in [-30, 30]" />.<br/> <br />
- <InlineMath math="X_{it}" /> design matrix elements isolate Pre-Event Drift (<InlineMath math="t < 0" />) and Post-Event Impact (<InlineMath math="t \ge 0" />) while controlling for systemic covariates (VIX).<br/> {"- "}<InlineMath math="Y_{it}" />{" is the log-return "}<InlineMath math="\\ln(P_t/P_0)" />{" of asset "}<InlineMath math="i" />{" at relative index "}<InlineMath math="t \\in [-30, 30]" />{"."}
- <InlineMath math="b_i \sim N(0, \sigma_b^2)" /> random intercept captures unique baseline asset variance.<br/> <br />
- <InlineMath math="\varepsilon_{it} \sim N(0, \sigma^2)" /> residuals noise. {"- "}<InlineMath math="X_{it}" />{" design matrix elements isolate Pre-Event Drift ("}<InlineMath math="t < 0" />{") and Post-Event Impact ("}<InlineMath math="t \\ge 0" />{") while controlling for systemic covariates (VIX)."}
<br />
{"- "}<InlineMath math="b_i \\sim N(0, \\sigma_b^2)" />{" random intercept captures unique baseline asset variance."}
<br />
{"- "}<InlineMath math="\\varepsilon_{it} \\sim N(0, \\sigma^2)" />{" residuals noise."}
</p> </p>
</div> </div>
</div> </div>
@@ -101,15 +106,15 @@ export default function EconometricsMathModal({ isOpen, onClose }: EconometricsM
<div className="bg-slate-950/40 p-4 rounded-xl border border-slate-800/60 my-2 space-y-4"> <div className="bg-slate-950/40 p-4 rounded-xl border border-slate-800/60 my-2 space-y-4">
<div> <div>
<p className="text-xs text-slate-400 mb-1">Logistic Probability Projection:</p> <p className="text-xs text-slate-400 mb-1">Logistic Probability Projection:</p>
<BlockMath math="P(\text{Bullish}) = \frac{1}{1 + e^{-\text{Score}}}" /> <BlockMath math="P(\\text{Bullish}) = \\frac{1}{1 + e^{-\\text{Score}}}" />
</div> </div>
<div> <div>
<p className="text-xs text-slate-400 mb-1">Optimal Youden Index (J):</p> <p className="text-xs text-slate-400 mb-1">Optimal Youden Index (J):</p>
<BlockMath math="J = \text{Sensitivity} + \text{Specificity} - 1 = \text{TPR} + (1 - \text{FPR}) - 1" /> <BlockMath math="J = \\text{Sensitivity} + \\text{Specificity} - 1 = \\text{TPR} + (1 - \\text{FPR}) - 1" />
</div> </div>
<div> <div>
<p className="text-xs text-slate-400 mb-1">Inverting probability optimal threshold <InlineMath math="P^*" /> back to native score <InlineMath math="S^*" /> via Logit:</p> <p className="text-xs text-slate-400 mb-1">{"Inverting probability optimal threshold "}<InlineMath math="P^*" />{" back to native score "}<InlineMath math="S^*" />{" via Logit:"}</p>
<BlockMath math="S^* = \ln\left(\frac{P^*}{1 - P^*}\right)" /> <BlockMath math="S^* = \\ln\\left(\\frac{P^*}{1 - P^*}\\right)" />
</div> </div>
</div> </div>
</div> </div>
@@ -121,16 +126,18 @@ export default function EconometricsMathModal({ isOpen, onClose }: EconometricsM
</p> </p>
<div className="bg-slate-950/40 p-4 rounded-xl border border-slate-800/60 my-2 space-y-4"> <div className="bg-slate-950/40 p-4 rounded-xl border border-slate-800/60 my-2 space-y-4">
<div> <div>
<BlockMath math="\hat{S}(t) = \prod_{t_i \le t} \left(1 - \frac{d_i}{n_i}\right)" /> <BlockMath math="\\hat{S}(t) = \\prod_{t_i \\le t} \\left(1 - \\frac{d_i}{n_i}\\right)" />
<p className="text-[11px] text-slate-400 mt-2 font-mono"> <p className="text-[11px] text-slate-400 mt-2 font-mono leading-relaxed">
Where:<br/> {"Where:"}
- <InlineMath math="n_i" /> is the number of active asset-run observations at risk at day <InlineMath math="t" />.<br/> <br />
- <InlineMath math="d_i" /> is the number of trend-reversal events recorded on day <InlineMath math="t" />. {"- "}<InlineMath math="n_i" />{" is the number of active asset-run observations at risk at day "}<InlineMath math="t" />{"."}
<br />
{"- "}<InlineMath math="d_i" />{" is the number of trend-reversal events recorded on day "}<InlineMath math="t" />{"."}
</p> </p>
</div> </div>
<div> <div>
<p className="text-xs text-slate-400 mb-1">Reversal trigger with 1% Volatility Buffer:</p> <p className="text-xs text-slate-400 mb-1">Reversal trigger with 1% Volatility Buffer:</p>
<BlockMath math="\text{Sign}(\text{Score}) \times \text{Return} \le -0.01" /> <BlockMath math="\\text{Sign}(\\text{Score}) \\times \\text{Return} \\le -0.01" />
</div> </div>
</div> </div>
</div> </div>

View File

@@ -43,20 +43,20 @@ import {
// Predefined archetypes for Event Creation // Predefined archetypes for Event Creation
const ARCHETYPES: Record<string, { name: string; defaultScores: Record<string, number> }> = { const ARCHETYPES: Record<string, { name: string; defaultScores: Record<string, number> }> = {
'🏦 Fed-Zinsentscheid (FOMC)': { '🏦 Fed Rate Decision (FOMC)': {
name: 'Fed-Zinsentscheid (FOMC)', name: 'Fed Rate Decision (FOMC)',
defaultScores: { Apple: 1, NASDAQ: 2, Gold: -1, Bitcoin: 2 } defaultScores: { Apple: 1, NASDAQ: 2, Gold: -1, Bitcoin: 2 }
}, },
'📈 US-Inflationsdaten (CPI)': { '📈 US Inflation Data (CPI)': {
name: 'US-Inflationsdaten (CPI)', name: 'US Inflation Data (CPI)',
defaultScores: { Apple: 1, NASDAQ: 2, Gold: -2, Bitcoin: 1 } defaultScores: { Apple: 1, NASDAQ: 2, Gold: -2, Bitcoin: 1 }
}, },
'💼 Non-Farm Payrolls (NFP)': { '💼 Non-Farm Payrolls (NFP)': {
name: 'Non-Farm Payrolls (NFP)', name: 'Non-Farm Payrolls (NFP)',
defaultScores: { Apple: 0, NASDAQ: 1, Gold: -1, Bitcoin: 0 } defaultScores: { Apple: 0, NASDAQ: 1, Gold: -1, Bitcoin: 0 }
}, },
'🛒 OPEC-Treffen': { '🛒 OPEC Meeting': {
name: 'OPEC-Treffen', name: 'OPEC Meeting',
defaultScores: { Apple: -1, NASDAQ: -1, Gold: 2, Bitcoin: 1 } defaultScores: { Apple: -1, NASDAQ: -1, Gold: 2, Bitcoin: 1 }
} }
}; };
@@ -258,7 +258,6 @@ export default function EventsDemo() {
// Custom Event Form State
const [customName, setCustomName] = useState<string>(''); const [customName, setCustomName] = useState<string>('');
const [customDate, setCustomDate] = useState<string>('2026-06-15'); const [customDate, setCustomDate] = useState<string>('2026-06-15');
const [selectedArchetype, setSelectedArchetype] = useState<string>('Custom'); const [selectedArchetype, setSelectedArchetype] = useState<string>('Custom');
@@ -522,7 +521,7 @@ export default function EventsDemo() {
scores[asset.name] = typeof arch.defaultScores[asset.name] === 'number' ? arch.defaultScores[asset.name] : 0; scores[asset.name] = typeof arch.defaultScores[asset.name] === 'number' ? arch.defaultScores[asset.name] : 0;
}); });
} else { } else {
name = name || 'Benutzerdefiniertes Ereignis'; name = name || 'Custom Event';
} }
addEventToMatrix(name, customDate, scores); addEventToMatrix(name, customDate, scores);
@@ -608,7 +607,7 @@ export default function EventsDemo() {
className="flex items-center gap-1.5 px-3 py-2 rounded-lg bg-slate-950/80 hover:bg-slate-905 border border-slate-800 hover:border-slate-700 transition-all font-semibold text-xs tracking-wider text-rose-400" className="flex items-center gap-1.5 px-3 py-2 rounded-lg bg-slate-950/80 hover:bg-slate-905 border border-slate-800 hover:border-slate-700 transition-all font-semibold text-xs tracking-wider text-rose-400"
> >
<BookOpen className="w-3.5 h-3.5" /> <BookOpen className="w-3.5 h-3.5" />
<span>📖 Modulerklärung</span> <span>📖 Quantitative Handbook</span>
</button> </button>
</div> </div>
</div> </div>
@@ -630,7 +629,7 @@ export default function EventsDemo() {
<form onSubmit={handleAddAsset} className="flex items-center gap-1 bg-slate-950 p-1 rounded-lg border border-slate-800"> <form onSubmit={handleAddAsset} className="flex items-center gap-1 bg-slate-950 p-1 rounded-lg border border-slate-800">
<input <input
type="text" type="text"
placeholder="Ticker (z.B. TSLA)" placeholder="Ticker (e.g. TSLA)"
value={newTickerInput} value={newTickerInput}
onChange={(e) => setNewTickerInput(e.target.value)} onChange={(e) => 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" className="bg-transparent text-[11px] text-slate-200 focus:outline-none px-2 py-0.5 w-24 uppercase font-mono"
@@ -664,7 +663,7 @@ export default function EventsDemo() {
<button <button
onClick={() => handleRemoveAsset(asset.symbol)} onClick={() => handleRemoveAsset(asset.symbol)}
className="text-slate-500 hover:text-rose-400 p-0.5 rounded opacity-0 group-hover/header:opacity-100 transition-opacity" className="text-slate-500 hover:text-rose-400 p-0.5 rounded opacity-0 group-hover/header:opacity-100 transition-opacity"
title={`${asset.name} Spalte löschen`} title={`${asset.name} Column delete`}
> >
<Trash2 className="w-3 h-3" /> <Trash2 className="w-3 h-3" />
</button> </button>
@@ -687,7 +686,7 @@ export default function EventsDemo() {
<td className="py-3 px-3 text-slate-400 font-mono"> <td className="py-3 px-3 text-slate-400 font-mono">
{ev.date} {ev.date}
<span className="block text-[10px] text-slate-500"> <span className="block text-[10px] text-slate-500">
{d === 0 ? 'Heute' : d > 0 ? `In ${d} Tagen` : `Vor ${-d} Tagen`} {d === 0 ? 'Today' : d > 0 ? `In ${d} days` : `${-d} days ago`}
</span> </span>
</td> </td>
@@ -750,7 +749,7 @@ export default function EventsDemo() {
<button <button
onClick={() => deleteEventFromMatrix(ev.id)} onClick={() => deleteEventFromMatrix(ev.id)}
className="text-slate-500 hover:text-rose-400 p-1 hover:bg-slate-800/50 rounded transition-all" className="text-slate-500 hover:text-rose-400 p-1 hover:bg-slate-800/50 rounded transition-all"
title="Event aus Matrix löschen" title="Delete event from matrix"
> >
<Trash2 className="w-3.5 h-3.5" /> <Trash2 className="w-3.5 h-3.5" />
</button> </button>
@@ -1082,7 +1081,7 @@ export default function EventsDemo() {
{calibrationSuccess && ( {calibrationSuccess && (
<div className="bg-emerald-950/30 border border-emerald-800/80 text-emerald-400 text-[10px] rounded-lg p-2 flex items-center gap-1.5 justify-center font-semibold"> <div className="bg-emerald-950/30 border border-emerald-800/80 text-emerald-400 text-[10px] rounded-lg p-2 flex items-center gap-1.5 justify-center font-semibold">
<Check className="w-3.5 h-3.5" /> Kalibrierung erfolgreich abgeschlossen! <Check className="w-3.5 h-3.5" /> Calibration successfully completed!
</div> </div>
)} )}
@@ -1101,7 +1100,7 @@ export default function EventsDemo() {
{lastCalibrationTime && ( {lastCalibrationTime && (
<div className="text-[9px] text-slate-500 font-mono"> <div className="text-[9px] text-slate-500 font-mono">
Letzter Durchlauf: {lastCalibrationTime} ({lmmObservations.length} Obs.) Last run: {lastCalibrationTime} ({lmmObservations.length} Obs.)
</div> </div>
)} )}
</div> </div>
@@ -1169,7 +1168,7 @@ export default function EventsDemo() {
</p> </p>
<div> <div>
<label className="block text-slate-500 mb-1 text-[10px] uppercase font-semibold">Fokus Asset</label> <label className="block text-slate-500 mb-1 text-[10px] uppercase font-semibold">Focus Asset</label>
<select <select
value={selectedSurvivalAsset} value={selectedSurvivalAsset}
onChange={(e) => setSelectedSurvivalAsset(e.target.value)} onChange={(e) => setSelectedSurvivalAsset(e.target.value)}
@@ -1184,7 +1183,7 @@ export default function EventsDemo() {
<div className="grid grid-cols-2 gap-3 mt-2"> <div className="grid grid-cols-2 gap-3 mt-2">
<div className="bg-slate-950/40 border border-slate-805 p-3 rounded-xl"> <div className="bg-slate-950/40 border border-slate-805 p-3 rounded-xl">
<span className="block text-[10px] text-slate-500 uppercase font-semibold">Right Censoring</span> <span className="block text-[10px] text-slate-500 uppercase font-semibold">Right Censoring</span>
<span className="text-sm font-bold text-slate-200 font-mono">30 Tage</span> <span className="text-sm font-bold text-slate-200 font-mono">30 days</span>
</div> </div>
<div className="bg-slate-950/40 border border-slate-805 p-3 rounded-xl"> <div className="bg-slate-950/40 border border-slate-805 p-3 rounded-xl">
<span className="block text-[10px] text-slate-500 uppercase font-semibold">Observation Count</span> <span className="block text-[10px] text-slate-500 uppercase font-semibold">Observation Count</span>
@@ -1226,7 +1225,7 @@ export default function EventsDemo() {
{selectedModel === 'ROC' && ( {selectedModel === 'ROC' && (
<div className="w-full h-full"> <div className="w-full h-full">
<div className="text-[10px] font-mono text-slate-400 mb-2 text-center flex items-center justify-center gap-1.5"> <div className="text-[10px] font-mono text-slate-400 mb-2 text-center flex items-center justify-center gap-1.5">
<span>Modell-Klassifikationstrennung (FPR vs TPR)</span> <span>Model Classification Separation (FPR vs TPR)</span>
</div> </div>
<ResponsiveContainer width="100%" height="90%"> <ResponsiveContainer width="100%" height="90%">
<AreaChart data={rocData} margin={{ top: 10, right: 10, left: -25, bottom: 5 }}> <AreaChart data={rocData} margin={{ top: 10, right: 10, left: -25, bottom: 5 }}>

View File

@@ -113,7 +113,7 @@ export default function InsiderDemo() {
if (whaleRes.liveDataAvailable === false) unavailable.push('Whales (13F Filings)'); if (whaleRes.liveDataAvailable === false) unavailable.push('Whales (13F Filings)');
if (unavailable.length > 0) { if (unavailable.length > 0) {
setErrorMsg(`Echtzeitdaten-Quelle vorübergehend ausgelastet für: ${unavailable.join(', ')}. Bitte später erneut versuchen.`); setErrorMsg(`Real-time data source temporarily busy for: ${unavailable.join(', ')}. Please try again later.`);
} }
useSandboxStore.setState({ useSandboxStore.setState({
@@ -125,7 +125,7 @@ export default function InsiderDemo() {
} catch (err: any) { } catch (err: any) {
console.error('Failed to load live insider data:', err.message); console.error('Failed to load live insider data:', err.message);
if (active) { if (active) {
setErrorMsg(err.message || 'Echtzeitdaten-Quelle vorübergehend nicht erreichbar.'); setErrorMsg(err.message || 'Real-time data source temporarily unreachable.');
} }
} finally { } finally {
if (active) setLoading(false); if (active) setLoading(false);
@@ -237,7 +237,7 @@ export default function InsiderDemo() {
if (!tickerStats || !selectedTicker) return []; if (!tickerStats || !selectedTicker) return [];
return tickerStats.volumes.map((vol, idx) => ({ return tickerStats.volumes.map((vol, idx) => ({
month: `M-${tickerStats.volumes.length - idx - 1}`, month: `M-${tickerStats.volumes.length - idx - 1}`,
'Volumen (Shares)': vol, 'Volume (Shares)': vol,
})); }));
}, [tickerStats, selectedTicker]); }, [tickerStats, selectedTicker]);
@@ -254,12 +254,12 @@ export default function InsiderDemo() {
{isShieldActive ? ( {isShieldActive ? (
<span className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-[10px] font-bold bg-amber-500/10 text-amber-400 border border-amber-500/20 shadow-[0_0_10px_rgba(245,158,11,0.15)] animate-pulse"> <span className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-[10px] font-bold bg-amber-500/10 text-amber-400 border border-amber-500/20 shadow-[0_0_10px_rgba(245,158,11,0.15)] animate-pulse">
<span className="w-1.5 h-1.5 rounded-full bg-amber-500" /> <span className="w-1.5 h-1.5 rounded-full bg-amber-500" />
DEV-ARCHIV AKTIV (0 CALLS) DEV ARCHIVE ACTIVE (0 CALLS)
</span> </span>
) : ( ) : (
<span className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-[10px] font-bold bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 shadow-[0_0_10px_rgba(16,185,129,0.15)]"> <span className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-[10px] font-bold bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 shadow-[0_0_10px_rgba(16,185,129,0.15)]">
<span className="w-1.5 h-1.5 rounded-full bg-emerald-500 animate-ping" /> <span className="w-1.5 h-1.5 rounded-full bg-emerald-500 animate-ping" />
LIVE-API ENDPUNKT (FMP CORPO) LIVE API ENDPOINT (FMP CORPO)
</span> </span>
)} )}
</h2> </h2>
@@ -270,13 +270,13 @@ export default function InsiderDemo() {
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-purple-400 justify-center h-11" 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-purple-400 justify-center h-11"
> >
<BookOpen className="w-3.5 h-3.5" /> <BookOpen className="w-3.5 h-3.5" />
<span>📖 Modulerklärung</span> <span>📖 Quantitative Handbook</span>
</button> </button>
<div className="bg-slate-900 border border-slate-800 rounded-xl px-4 py-2 flex items-center gap-3 h-11"> <div className="bg-slate-900 border border-slate-800 rounded-xl px-4 py-2 flex items-center gap-3 h-11">
<Shield className="text-purple-400 w-5 h-5" /> <Shield className="text-purple-400 w-5 h-5" />
<div> <div>
<p className="text-slate-400 text-xs">Bayesianische Kopplung</p> <p className="text-slate-400 text-xs">Bayesian Coupling</p>
<p className="font-mono text-sm font-bold text-purple-400"> <p className="font-mono text-sm font-bold text-purple-400">
Prior Rebound: {(priorProbability * 100).toFixed(0)}% Prior Rebound: {(priorProbability * 100).toFixed(0)}%
</p> </p>
@@ -290,7 +290,7 @@ export default function InsiderDemo() {
<div className="p-4 rounded-xl border border-slate-800 bg-slate-950/30 flex flex-col justify-between gap-4"> <div className="p-4 rounded-xl border border-slate-800 bg-slate-950/30 flex flex-col justify-between gap-4">
<div className="space-y-1"> <div className="space-y-1">
<h4 className="text-sm font-semibold text-slate-300">Global Flow Outlier Scan</h4> <h4 className="text-sm font-semibold text-slate-300">Global Flow Outlier Scan</h4>
<p className="text-xs text-slate-400">Filtert den Markt nach statistisch signifikanten Kaufvolumina (Z-Score &gt; 2.0) und konzertierten Käufen (Insider-Cluster).</p> <p className="text-xs text-slate-400">Filters the market for statistically significant purchase volumes (Z-Score &gt; 2.0) and concerted buying (insider clusters).</p>
</div> </div>
<button <button
onClick={handleGlobalFlowScan} onClick={handleGlobalFlowScan}
@@ -298,20 +298,20 @@ export default function InsiderDemo() {
className="w-full bg-gradient-to-r from-purple-500 to-indigo-500 hover:from-purple-600 hover:to-indigo-600 disabled:from-purple-900 text-white font-bold py-2.5 px-4 rounded-xl transition-all shadow-lg shadow-purple-500/10 flex items-center justify-center gap-2" className="w-full bg-gradient-to-r from-purple-500 to-indigo-500 hover:from-purple-600 hover:to-indigo-600 disabled:from-purple-900 text-white font-bold py-2.5 px-4 rounded-xl transition-all shadow-lg shadow-purple-500/10 flex items-center justify-center gap-2"
> >
<Radio className={`w-4 h-4 ${scanning ? 'animate-pulse' : ''}`} /> <Radio className={`w-4 h-4 ${scanning ? 'animate-pulse' : ''}`} />
<span>{scanning ? 'Scanne Transaktionen...' : 'Global Flow Scan starten'}</span> <span>{scanning ? 'Scanning Transactions...' : 'Start Global Flow Scan'}</span>
</button> </button>
</div> </div>
<div className="p-4 rounded-xl border border-slate-800 bg-slate-950/30 flex flex-col justify-between gap-4"> <div className="p-4 rounded-xl border border-slate-800 bg-slate-950/30 flex flex-col justify-between gap-4">
<div className="space-y-1"> <div className="space-y-1">
<h4 className="text-sm font-semibold text-slate-300">Ticker Lookup (Einzelauswertung)</h4> <h4 className="text-sm font-semibold text-slate-300">Ticker Lookup (Single Evaluation)</h4>
<p className="text-xs text-slate-400">Gezielte Abfrage von Insider-Z-Scores und Bayesianischen Kopplungs-Updates (z.B. PLTR, RACE, AMZN, AAPL).</p> <p className="text-xs text-slate-400">Targeted query of insider Z-scores and Bayesian coupling updates (e.g., PLTR, RACE, AMZN, AAPL).</p>
</div> </div>
<form onSubmit={handleTickerLookup} className="flex gap-2"> <form onSubmit={handleTickerLookup} className="flex gap-2">
<input <input
type="text" type="text"
required required
placeholder="z.B. PLTR" placeholder="e.g. PLTR"
className="bg-slate-950 border border-slate-800 rounded-lg p-2.5 flex-1 text-slate-100 font-mono text-sm uppercase focus:outline-none focus:border-purple-500" className="bg-slate-950 border border-slate-800 rounded-lg p-2.5 flex-1 text-slate-100 font-mono text-sm uppercase focus:outline-none focus:border-purple-500"
value={searchQuery} value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)} onChange={(e) => setSearchQuery(e.target.value)}
@@ -331,31 +331,31 @@ export default function InsiderDemo() {
<div className="p-5 rounded-2xl border border-purple-500/30 bg-purple-500/5 grid grid-cols-1 lg:grid-cols-3 gap-6 mb-6 animate-fade-in"> <div className="p-5 rounded-2xl border border-purple-500/30 bg-purple-500/5 grid grid-cols-1 lg:grid-cols-3 gap-6 mb-6 animate-fade-in">
<div className="space-y-3"> <div className="space-y-3">
<div className="flex justify-between items-center border-b border-slate-800 pb-2"> <div className="flex justify-between items-center border-b border-slate-800 pb-2">
<h3 className="font-mono font-bold text-lg text-slate-100">{selectedTicker} Einzelauswertung</h3> <h3 className="font-mono font-bold text-lg text-slate-100">{selectedTicker} Single Evaluation</h3>
{tickerStats.isAnomaly && <span className="px-2 py-0.5 rounded bg-purple-500/20 text-purple-300 text-[10px] font-bold border border-purple-500/30 animate-pulse">FLOW OUTLIER</span>} {tickerStats.isAnomaly && <span className="px-2 py-0.5 rounded bg-purple-500/20 text-purple-300 text-[10px] font-bold border border-purple-500/30 animate-pulse">FLOW OUTLIER</span>}
</div> </div>
<div className="space-y-2 text-xs"> <div className="space-y-2 text-xs">
<div className="flex justify-between font-mono"> <div className="flex justify-between font-mono">
<span className="text-slate-400">Volumetrischer Z-Score:</span> <span className="text-slate-400">Volumetric Z-Score:</span>
<span className={`font-bold ${tickerStats.isAnomaly ? 'text-purple-400' : 'text-slate-300'}`}> <span className={`font-bold ${tickerStats.isAnomaly ? 'text-purple-400' : 'text-slate-300'}`}>
Z = {tickerStats.zScore.toFixed(2)} Z = {tickerStats.zScore.toFixed(2)}
</span> </span>
</div> </div>
<div className="flex justify-between font-mono"> <div className="flex justify-between font-mono">
<span className="text-slate-400">Konzertiertes Cluster (14 Tage):</span> <span className="text-slate-400">Concerted Cluster (14 Days):</span>
<span className={`font-bold ${tickerStats.isCluster ? 'text-emerald-400' : 'text-slate-400'}`}> <span className={`font-bold ${tickerStats.isCluster ? 'text-emerald-400' : 'text-slate-400'}`}>
{tickerStats.isCluster ? `JA (${tickerStats.clusterCount} Insiders)` : `NEIN (${tickerStats.clusterCount})`} {tickerStats.isCluster ? `YES (${tickerStats.clusterCount} Insiders)` : `NO (${tickerStats.clusterCount})`}
</span> </span>
</div> </div>
{tickerStats.isCluster && ( {tickerStats.isCluster && (
<div className="flex justify-between font-mono text-emerald-400"> <div className="flex justify-between font-mono text-emerald-400">
<span>Cluster Exponent-Multiplikator:</span> <span>Cluster Exponent Multiplier:</span>
<span>x{tickerStats.multiplier.toFixed(2)}</span> <span>x{tickerStats.multiplier.toFixed(2)}</span>
</div> </div>
)} )}
<div className="flex justify-between font-mono border-t border-slate-800/80 pt-2 text-sm"> <div className="flex justify-between font-mono border-t border-slate-800/80 pt-2 text-sm">
<span className="text-slate-300">Gekoppelte Rebound-Wahrsch.:</span> <span className="text-slate-300">Coupled Rebound Prob.:</span>
<span className="text-purple-400 font-bold flex items-center gap-1"> <span className="text-purple-400 font-bold flex items-center gap-1">
<Percent className="w-3.5 h-3.5" /> <Percent className="w-3.5 h-3.5" />
{(tickerStats.coupledRebound * 100).toFixed(0)}% {(tickerStats.coupledRebound * 100).toFixed(0)}%
@@ -366,14 +366,14 @@ export default function InsiderDemo() {
{/* Volume chart */} {/* Volume chart */}
<div className="lg:col-span-2 h-44 w-full"> <div className="lg:col-span-2 h-44 w-full">
<div className="text-[10px] text-slate-400 mb-1 text-center font-mono font-semibold">Insider Handelsvolumen (24 Monate Baseline)</div> <div className="text-[10px] text-slate-400 mb-1 text-center font-mono font-semibold">Insider Trading Volume (24-Month Baseline)</div>
<ResponsiveContainer width="100%" height="90%"> <ResponsiveContainer width="100%" height="90%">
<BarChart data={volumeChartData}> <BarChart data={volumeChartData}>
<CartesianGrid strokeDasharray="3 3" stroke="#1e293b" /> <CartesianGrid strokeDasharray="3 3" stroke="#1e293b" />
<XAxis dataKey="month" stroke="#64748b" fontSize={9} /> <XAxis dataKey="month" stroke="#64748b" fontSize={9} />
<YAxis stroke="#64748b" fontSize={9} /> <YAxis stroke="#64748b" fontSize={9} />
<Tooltip contentStyle={{ backgroundColor: '#0f172a', borderColor: '#334155', borderRadius: '8px' }} /> <Tooltip contentStyle={{ backgroundColor: '#0f172a', borderColor: '#334155', borderRadius: '8px' }} />
<Bar dataKey="Volumen (Shares)" fill="#8b5cf6" radius={[3, 3, 0, 0]} /> <Bar dataKey="Volume (Shares)" fill="#8b5cf6" radius={[3, 3, 0, 0]} />
</BarChart> </BarChart>
</ResponsiveContainer> </ResponsiveContainer>
</div> </div>
@@ -383,12 +383,12 @@ export default function InsiderDemo() {
{/* Global Scan Outlier List */} {/* Global Scan Outlier List */}
{scanResults && ( {scanResults && (
<div className="p-5 rounded-2xl border border-slate-800 bg-slate-950/20 mb-6 space-y-3 animate-fade-in"> <div className="p-5 rounded-2xl border border-slate-800 bg-slate-950/20 mb-6 space-y-3 animate-fade-in">
<h3 className="text-sm font-bold text-slate-200 uppercase tracking-wider">Ergebnisse des Global Flow Scans</h3> <h3 className="text-sm font-bold text-slate-200 uppercase tracking-wider">Global Flow Scan Results</h3>
{scanResults.length === 0 ? ( {scanResults.length === 0 ? (
<div className="p-6 text-center border border-dashed border-slate-800 rounded-xl text-slate-400 bg-slate-900/10"> <div className="p-6 text-center border border-dashed border-slate-800 rounded-xl text-slate-400 bg-slate-900/10">
<Radio className="w-8 h-8 text-purple-500/50 mx-auto mb-2 animate-pulse" /> <Radio className="w-8 h-8 text-purple-500/50 mx-auto mb-2 animate-pulse" />
<p className="text-xs font-semibold text-slate-300">Keine signifikanten Volumen-Anomalien gefunden</p> <p className="text-xs font-semibold text-slate-300">No Significant Volume Anomalies Found</p>
<p className="text-[10px] text-slate-500 mt-1">Es wurden keine Transaktionen mit einem berechneten volumetric Z-Score &gt; 2.0 in den aktiven Live-Feeds identifiziert.</p> <p className="text-[10px] text-slate-500 mt-1">No transactions with a calculated volumetric Z-Score &gt; 2.0 were identified in the active live feeds.</p>
</div> </div>
) : ( ) : (
<div className="grid grid-cols-2 md:grid-cols-4 gap-4"> <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
@@ -421,13 +421,13 @@ export default function InsiderDemo() {
onClick={() => setActiveSegment('executives')} onClick={() => setActiveSegment('executives')}
className={`flex-1 py-2 rounded-lg text-xs font-semibold font-sans transition-all flex items-center justify-center gap-1.5 ${activeSegment === 'executives' ? 'bg-purple-500 text-white font-bold' : 'text-slate-400 hover:text-slate-200'}`} className={`flex-1 py-2 rounded-lg text-xs font-semibold font-sans transition-all flex items-center justify-center gap-1.5 ${activeSegment === 'executives' ? 'bg-purple-500 text-white font-bold' : 'text-slate-400 hover:text-slate-200'}`}
> >
<User className="w-3.5 h-3.5" /> Vorstände (Form 4) <User className="w-3.5 h-3.5" /> Executives (Form 4)
</button> </button>
<button <button
onClick={() => setActiveSegment('congress')} onClick={() => setActiveSegment('congress')}
className={`flex-1 py-2 rounded-lg text-xs font-semibold font-sans transition-all flex items-center justify-center gap-1.5 ${activeSegment === 'congress' ? 'bg-purple-500 text-white font-bold' : 'text-slate-400 hover:text-slate-200'}`} className={`flex-1 py-2 rounded-lg text-xs font-semibold font-sans transition-all flex items-center justify-center gap-1.5 ${activeSegment === 'congress' ? 'bg-purple-500 text-white font-bold' : 'text-slate-400 hover:text-slate-200'}`}
> >
<Landmark className="w-3.5 h-3.5" /> Kongress (Stock Act) <Landmark className="w-3.5 h-3.5" /> Congress (Stock Act)
</button> </button>
<button <button
onClick={() => setActiveSegment('whales')} onClick={() => setActiveSegment('whales')}
@@ -441,7 +441,7 @@ export default function InsiderDemo() {
<div className="p-4 rounded-xl border border-red-550/30 bg-red-550/10 text-red-400 text-xs flex items-center gap-3 mb-4 animate-fade-in"> <div className="p-4 rounded-xl border border-red-550/30 bg-red-550/10 text-red-400 text-xs flex items-center gap-3 mb-4 animate-fade-in">
<AlertTriangle className="w-5 h-5 shrink-0 animate-pulse" /> <AlertTriangle className="w-5 h-5 shrink-0 animate-pulse" />
<div> <div>
<span className="font-bold">Datenladefehler:</span> {errorMsg} <span className="font-bold">Data Load Error:</span> {errorMsg}
</div> </div>
</div> </div>
)} )}
@@ -455,12 +455,12 @@ export default function InsiderDemo() {
<th className="p-3">Ticker</th> <th className="p-3">Ticker</th>
<th className="p-3">Insider Name</th> <th className="p-3">Insider Name</th>
<th className="p-3">Position</th> <th className="p-3">Position</th>
<th className="p-3">Transaktion</th> <th className="p-3">Transaction</th>
<th className="p-3 font-mono">Stücke</th> <th className="p-3 font-mono">Shares</th>
<th className="p-3 text-right">Wert ($)</th> <th className="p-3 text-right">Value ($)</th>
<th className="p-3 font-mono text-center">Volumetrischer Z-Score</th> <th className="p-3 font-mono text-center">Volumetric Z-Score</th>
<th className="p-3 font-mono text-center">P(R|Z)</th> <th className="p-3 font-mono text-center">P(R|Z)</th>
<th className="p-3">Strategische Einordnung</th> <th className="p-3">Strategic Assessment</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -469,7 +469,7 @@ export default function InsiderDemo() {
<td colSpan={9} className="p-8 text-center text-slate-400"> <td colSpan={9} className="p-8 text-center text-slate-400">
<div className="flex items-center justify-center gap-2"> <div className="flex items-center justify-center gap-2">
<div className="w-4 h-4 border-2 border-purple-500 border-t-transparent rounded-full animate-spin" /> <div className="w-4 h-4 border-2 border-purple-500 border-t-transparent rounded-full animate-spin" />
<span>Lade live Insider-Transaktionen (Form 4)...</span> <span>Loading live insider transactions (Form 4)...</span>
</div> </div>
</td> </td>
</tr> </tr>
@@ -477,7 +477,7 @@ export default function InsiderDemo() {
{!loading && insiderTrades.length === 0 && ( {!loading && insiderTrades.length === 0 && (
<tr> <tr>
<td colSpan={9} className="p-8 text-center text-slate-500"> <td colSpan={9} className="p-8 text-center text-slate-500">
Keine Insider-Transaktionen geladen. No insider transactions loaded.
</td> </td>
</tr> </tr>
)} )}
@@ -496,7 +496,7 @@ export default function InsiderDemo() {
<td className="p-3 text-slate-400">{t.relation}</td> <td className="p-3 text-slate-400">{t.relation}</td>
<td className="p-3"> <td className="p-3">
<span className={`px-1.5 py-0.5 rounded text-[9px] font-bold ${isBuy ? 'bg-emerald-500/10 text-emerald-400 border border-emerald-500/20' : 'bg-rose-500/10 text-rose-400 border border-rose-500/20'}`}> <span className={`px-1.5 py-0.5 rounded text-[9px] font-bold ${isBuy ? 'bg-emerald-500/10 text-emerald-400 border border-emerald-500/20' : 'bg-rose-500/10 text-rose-400 border border-rose-500/20'}`}>
{isBuy ? 'KAUF' : 'VERKAUF'} {isBuy ? 'BUY' : 'SELL'}
</span> </span>
</td> </td>
<td className="p-3 font-mono text-slate-300">{t.shares.toLocaleString()}</td> <td className="p-3 font-mono text-slate-300">{t.shares.toLocaleString()}</td>
@@ -505,7 +505,7 @@ export default function InsiderDemo() {
</td> </td>
<td className={`p-3 font-mono text-center font-bold ${zScore >= 2.0 ? 'text-purple-400' : 'text-slate-350'}`}>{zScore}</td> <td className={`p-3 font-mono text-center font-bold ${zScore >= 2.0 ? 'text-purple-400' : 'text-slate-350'}`}>{zScore}</td>
<td className="p-3 font-mono text-center text-purple-400 font-bold">{(coupledRebound * 100).toFixed(0)}%</td> <td className="p-3 font-mono text-center text-purple-400 font-bold">{(coupledRebound * 100).toFixed(0)}%</td>
<td className="p-3 text-slate-350 whitespace-normal break-words">{t.insight || 'Opportunistische Diversifikation'}</td> <td className="p-3 text-slate-350 whitespace-normal break-words">{t.insight || 'Opportunistic Diversification'}</td>
</tr> </tr>
); );
})} })}
@@ -518,23 +518,23 @@ export default function InsiderDemo() {
<div className="p-3 bg-amber-500/10 border-b border-slate-800 text-xs text-amber-400 flex items-start gap-2.5"> <div className="p-3 bg-amber-500/10 border-b border-slate-800 text-xs text-amber-400 flex items-start gap-2.5">
<AlertTriangle className="w-5 h-5 shrink-0" /> <AlertTriangle className="w-5 h-5 shrink-0" />
<div> <div>
<span className="font-bold">U.S. Congress Stock Act Offenlegungslags:</span> Abgeordnete müssen Käufe innerhalb von 30 bis 45 Tagen offenlegen. Der Alpha-Lag in der Tabelle visualisiert diese Meldeverzögerung. Käufe können verzögert eingepreist sein. <span className="font-bold">U.S. Congress Stock Act Disclosure Lags:</span> Representatives must disclose transactions within 30 to 45 days. The Alpha Lag in the table visualizes this reporting delay. Transactions may be priced in with a delay.
</div> </div>
</div> </div>
<table className="w-full border-collapse text-left text-xs"> <table className="w-full border-collapse text-left text-xs">
<thead> <thead>
<tr className="border-b border-slate-800 text-slate-400 font-semibold bg-slate-900/40"> <tr className="border-b border-slate-800 text-slate-400 font-semibold bg-slate-900/40">
<th className="p-3">Ticker</th> <th className="p-3">Ticker</th>
<th className="p-3">Abgeordneter</th> <th className="p-3">Representative</th>
<th className="p-3">Kammer</th> <th className="p-3">Chamber</th>
<th className="p-3">Transaktion</th> <th className="p-3">Transaction</th>
<th className="p-3">Volumen-Spanne</th> <th className="p-3">Volume Range</th>
<th className="p-3 font-mono">Handelsdatum</th> <th className="p-3 font-mono">Transaction Date</th>
<th className="p-3 font-mono">Meldedatum</th> <th className="p-3 font-mono">Filing Date</th>
<th className="p-3 text-right">Alpha-Lag</th> <th className="p-3 text-right">Alpha Lag</th>
<th className="p-3 font-mono text-center">Volumetrischer Z-Score</th> <th className="p-3 font-mono text-center">Volumetric Z-Score</th>
<th className="p-3 font-mono text-center">P(R|Z)</th> <th className="p-3 font-mono text-center">P(R|Z)</th>
<th className="p-3">Strategische Einordnung</th> <th className="p-3">Strategic Assessment</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -543,7 +543,7 @@ export default function InsiderDemo() {
<td colSpan={11} className="p-8 text-center text-slate-400"> <td colSpan={11} className="p-8 text-center text-slate-400">
<div className="flex items-center justify-center gap-2"> <div className="flex items-center justify-center gap-2">
<div className="w-4 h-4 border-2 border-purple-500 border-t-transparent rounded-full animate-spin" /> <div className="w-4 h-4 border-2 border-purple-500 border-t-transparent rounded-full animate-spin" />
<span>Lade US-Kongress-Transaktionen...</span> <span>Loading US Congress transactions...</span>
</div> </div>
</td> </td>
</tr> </tr>
@@ -551,7 +551,7 @@ export default function InsiderDemo() {
{!loading && congressTrades.length === 0 && ( {!loading && congressTrades.length === 0 && (
<tr> <tr>
<td colSpan={11} className="p-8 text-center text-slate-500"> <td colSpan={11} className="p-8 text-center text-slate-500">
Keine Kongress-Transaktionen geladen. No Congress transactions loaded.
</td> </td>
</tr> </tr>
)} )}
@@ -571,16 +571,16 @@ export default function InsiderDemo() {
<td className="p-3 text-slate-400">{c.chamber}</td> <td className="p-3 text-slate-400">{c.chamber}</td>
<td className="p-3"> <td className="p-3">
<span className={`px-1.5 py-0.5 rounded text-[9px] font-bold ${isBuy ? 'bg-emerald-500/10 text-emerald-400 border border-emerald-500/20' : 'bg-rose-500/10 text-rose-400 border border-rose-500/20'}`}> <span className={`px-1.5 py-0.5 rounded text-[9px] font-bold ${isBuy ? 'bg-emerald-500/10 text-emerald-400 border border-emerald-500/20' : 'bg-rose-500/10 text-rose-400 border border-rose-500/20'}`}>
{isBuy ? 'KAUF' : 'VERKAUF'} {isBuy ? 'BUY' : 'SELL'}
</span> </span>
</td> </td>
<td className="p-3 text-slate-300 font-mono">{c.valueRange}</td> <td className="p-3 text-slate-300 font-mono">{c.valueRange}</td>
<td className="p-3 font-mono text-slate-400">{c.transactionDate}</td> <td className="p-3 font-mono text-slate-400">{c.transactionDate}</td>
<td className="p-3 font-mono text-slate-400">{c.filingDate}</td> <td className="p-3 font-mono text-slate-400">{c.filingDate}</td>
<td className="p-3 font-mono text-right text-amber-400 font-bold">{c.lagDays} Tage</td> <td className="p-3 font-mono text-right text-amber-400 font-bold">{c.lagDays} Days</td>
<td className={`p-3 font-mono text-center font-bold ${zScore >= 2.0 ? 'text-purple-400' : 'text-slate-350'}`}>{zScore}</td> <td className={`p-3 font-mono text-center font-bold ${zScore >= 2.0 ? 'text-purple-400' : 'text-slate-350'}`}>{zScore}</td>
<td className="p-3 font-mono text-center text-purple-400 font-bold">{(coupledRebound * 100).toFixed(0)}%</td> <td className="p-3 font-mono text-center text-purple-400 font-bold">{(coupledRebound * 100).toFixed(0)}%</td>
<td className="p-3 text-slate-350 whitespace-normal break-words">{c.insight || 'Opportunistische Diversifikation'}</td> <td className="p-3 text-slate-350 whitespace-normal break-words">{c.insight || 'Opportunistic Diversification'}</td>
</tr> </tr>
); );
})} })}
@@ -595,14 +595,14 @@ export default function InsiderDemo() {
<tr className="border-b border-slate-800 text-slate-400 font-semibold bg-slate-900/40"> <tr className="border-b border-slate-800 text-slate-400 font-semibold bg-slate-900/40">
<th className="p-3">Ticker</th> <th className="p-3">Ticker</th>
<th className="p-3">Institution (13F Filers)</th> <th className="p-3">Institution (13F Filers)</th>
<th className="p-3">Art</th> <th className="p-3">Type</th>
<th className="p-3 font-mono">Gehandelte Anteile</th> <th className="p-3 font-mono">Shares Traded</th>
<th className="p-3 font-mono">Aktueller Bestand</th> <th className="p-3 font-mono">Shares Held</th>
<th className="p-3 font-mono">Meldedatum</th> <th className="p-3 font-mono">Filing Date</th>
<th className="p-3 text-right">Geschätzter Wert ($)</th> <th className="p-3 text-right">Estimated Value ($)</th>
<th className="p-3 font-mono text-center">Volumetrischer Z-Score</th> <th className="p-3 font-mono text-center">Volumetric Z-Score</th>
<th className="p-3 font-mono text-center">P(R|Z)</th> <th className="p-3 font-mono text-center">P(R|Z)</th>
<th className="p-3">Strategische Einordnung</th> <th className="p-3">Strategic Assessment</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -611,7 +611,7 @@ export default function InsiderDemo() {
<td colSpan={10} className="p-8 text-center text-slate-400"> <td colSpan={10} className="p-8 text-center text-slate-400">
<div className="flex items-center justify-center gap-2"> <div className="flex items-center justify-center gap-2">
<div className="w-4 h-4 border-2 border-purple-500 border-t-transparent rounded-full animate-spin" /> <div className="w-4 h-4 border-2 border-purple-500 border-t-transparent rounded-full animate-spin" />
<span>Lade 13F Whales-Transaktionen...</span> <span>Loading 13F whale transactions...</span>
</div> </div>
</td> </td>
</tr> </tr>
@@ -619,7 +619,7 @@ export default function InsiderDemo() {
{!loading && whaleTrades.length === 0 && ( {!loading && whaleTrades.length === 0 && (
<tr> <tr>
<td colSpan={10} className="p-8 text-center text-slate-500"> <td colSpan={10} className="p-8 text-center text-slate-500">
Keine Institutionen-Transaktionen geladen. No institutional transactions loaded.
</td> </td>
</tr> </tr>
)} )}
@@ -648,7 +648,7 @@ export default function InsiderDemo() {
</td> </td>
<td className={`p-3 font-mono text-center font-bold ${zScore >= 2.0 ? 'text-purple-400' : 'text-slate-350'}`}>{zScore}</td> <td className={`p-3 font-mono text-center font-bold ${zScore >= 2.0 ? 'text-purple-400' : 'text-slate-350'}`}>{zScore}</td>
<td className="p-3 font-mono text-center text-purple-400 font-bold">{(coupledRebound * 100).toFixed(0)}%</td> <td className="p-3 font-mono text-center text-purple-400 font-bold">{(coupledRebound * 100).toFixed(0)}%</td>
<td className="p-3 text-slate-350 whitespace-normal break-words">{w.insight || 'Opportunistisches Rebalancing'}</td> <td className="p-3 text-slate-350 whitespace-normal break-words">{w.insight || 'Opportunistic Rebalancing'}</td>
</tr> </tr>
); );
})} })}
@@ -665,34 +665,34 @@ export default function InsiderDemo() {
className="flex items-center gap-1.5 text-xs text-slate-400 hover:text-purple-400 transition-colors focus:outline-none" className="flex items-center gap-1.5 text-xs text-slate-400 hover:text-purple-400 transition-colors focus:outline-none"
> >
<span>{showMathAccordion ? <ChevronUp className="w-4 h-4" /> : <ChevronDown className="w-4 h-4" />}</span> <span>{showMathAccordion ? <ChevronUp className="w-4 h-4" /> : <ChevronDown className="w-4 h-4" />}</span>
<span className="font-semibold uppercase tracking-wider">Mathematische Formulierung (Z-Score &amp; Bayesianische Kopplung)</span> <span className="font-semibold uppercase tracking-wider">Mathematical Formulation (Z-Score &amp; Bayesian Coupling)</span>
</button> </button>
{showMathAccordion && ( {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 className="mt-4 p-4 rounded-xl border border-slate-850 bg-slate-950/40 text-xs text-slate-300 space-y-4">
<div> <div>
<h4 className="font-bold text-purple-400 mb-1">1. Volumetrischer Z-Score (Statistische Signifikanz)</h4> <h4 className="font-bold text-purple-400 mb-1">1. Volumetric Z-Score (Statistical Significance)</h4>
<p className="mb-2"> <p className="mb-2">
Der Z-Score gibt an, um wie viele Standardabweichungen das aktuelle Transaktionsvolumen <InlineMath math="X_t" /> vom historischen Durchschnitt <InlineMath math="\mu" /> abweicht: The Z-Score indicates how many standard deviations the current transaction volume <InlineMath math="X_t" /> deviates from the historical average <InlineMath math="\\mu" />:
</p> </p>
<div className="py-2 overflow-x-auto text-slate-200"> <div className="py-2 overflow-x-auto text-slate-200">
<BlockMath math="Z = \frac{X_t - \mu}{\sigma}" /> <BlockMath math="Z = \\frac{X_t - \\mu}{\\sigma}" />
</div> </div>
<p className="text-slate-400"> <p className="text-slate-400">
Ein Z-Score &gt; 2.0 wird als Ausreißer (Anomaly Trigger) eingestuft, was einer Wahrscheinlichkeit von unter 2.27% r einen zufälligen Anstieg entspricht (einseitiger Test bei Normalverteilung). A Z-Score &gt; 2.0 is classified as an outlier (anomaly trigger), corresponding to a probability of less than 2.27% for a random spike (one-sided test under a normal distribution).
</p> </p>
</div> </div>
<div className="border-t border-slate-900 pt-3"> <div className="border-t border-slate-900 pt-3">
<h4 className="font-bold text-purple-400 mb-1">2. Bayesianische Kopplung (Rebound-Wahrscheinlichkeit)</h4> <h4 className="font-bold text-purple-400 mb-1">2. Bayesian Coupling (Rebound Probability)</h4>
<p className="mb-2"> <p className="mb-2">
Wir verknüpfen den Preisdrop-Sentiment (Element 2) mit den Insider-Z-Scores (Element 3), um die A-Posteriori-Wahrscheinlichkeit eines echten Rebounds zu ermitteln: We couple price drop sentiment (Element 2) with insider Z-Scores (Element 3) to determine the posterior probability of a true rebound:
</p> </p>
<div className="py-2 overflow-x-auto text-slate-200"> <div className="py-2 overflow-x-auto text-slate-200">
<BlockMath math="P(R|Z) = \frac{P(Z|R) \cdot P(R)}{P(Z|R) \cdot P(R) + P(Z|\neg R) \cdot (1 - P(R))}" /> <BlockMath math="P(R|Z) = \\frac{P(Z|R) \\cdot P(R)}{P(Z|R) \\cdot P(R) + P(Z|\\neg R) \\cdot (1 - P(R))}" />
</div> </div>
<p className="text-slate-400"> <p className="text-slate-400">
wobei <InlineMath math="P(R)" /> die Prior-Wahrscheinlichkeit ist. Ist der Z-Score hoch (Käufe), steigt die Likelihood <InlineMath math="P(Z|R)" /> stark an und maximiert den Rebound-Erwartungswert. where <InlineMath math="P(R)" /> is the prior probability. When the Z-Score is high (buying), the likelihood <InlineMath math="P(Z|R)" /> increases significantly, maximizing the rebound expectation.
</p> </p>
</div> </div>
</div> </div>

View File

@@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { BookOpen } from 'lucide-react'; import { BookOpen, X } from 'lucide-react';
import 'katex/dist/katex.min.css'; import 'katex/dist/katex.min.css';
import { BlockMath, InlineMath } from 'react-katex'; import { BlockMath, InlineMath } from 'react-katex';
@@ -26,7 +26,7 @@ export default function InsiderMathModal({ isOpen, onClose }: InsiderMathModalPr
if (!isOpen) return null; if (!isOpen) return null;
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-slate-950/85 backdrop-blur-md p-4 sm:p-6 md:p-8"> <div className="fixed inset-0 z-50 flex items-center justify-center bg-slate-955/90 backdrop-blur-md p-4 sm:p-6 md:p-8">
<div className="bg-slate-900 border border-slate-800/80 rounded-3xl w-full max-w-4xl h-[80vh] flex flex-col overflow-hidden shadow-2xl relative text-slate-300"> <div className="bg-slate-900 border border-slate-800/80 rounded-3xl w-full max-w-4xl h-[80vh] flex flex-col overflow-hidden shadow-2xl relative text-slate-300">
{/* Modal Header */} {/* Modal Header */}
@@ -39,9 +39,10 @@ export default function InsiderMathModal({ isOpen, onClose }: InsiderMathModalPr
</div> </div>
<button <button
onClick={onClose} onClick={onClose}
className="text-slate-400 hover:text-slate-200 bg-slate-950/50 border border-slate-800 hover:border-slate-700 px-3 py-1.5 rounded-lg text-xs font-semibold font-mono transition-all cursor-pointer" className="text-slate-400 hover:text-slate-200 bg-slate-950/50 border border-slate-800 hover:border-slate-700 p-2 rounded-xl transition-all cursor-pointer flex items-center justify-center"
aria-label="Close modal"
> >
Schließen (ESC) <X className="w-4 h-4" />
</button> </button>
</div> </div>
@@ -69,8 +70,8 @@ export default function InsiderMathModal({ isOpen, onClose }: InsiderMathModalPr
<p className="text-xs leading-relaxed text-slate-400"> <p className="text-xs leading-relaxed text-slate-400">
Insiders have unique company information, but clusters yield highest significance. A cluster is registered if: Insiders have unique company information, but clusters yield highest significance. A cluster is registered if:
</p> </p>
<div className="bg-slate-950/40 p-4 rounded-xl border border-slate-800/60 my-2"> <div className="bg-slate-955/40 p-4 rounded-xl border border-slate-800/60 my-2">
<BlockMath math="\text{Count}_{\text{insiders}} \ge 3 \quad \text{within a rolling 14-day window}" /> <BlockMath math="\\text{Count}_{\\text{insiders}} \\ge 3 \\quad \\text{within a rolling 14-day window}" />
<p className="text-[11px] text-slate-400 font-mono mt-2 text-center"> <p className="text-[11px] text-slate-400 font-mono mt-2 text-center">
Insiders must represent distinct entities (e.g. CEO, CFO, and Directors trading concurrently). Insiders must represent distinct entities (e.g. CEO, CFO, and Directors trading concurrently).
</p> </p>
@@ -82,8 +83,8 @@ export default function InsiderMathModal({ isOpen, onClose }: InsiderMathModalPr
<p className="text-xs leading-relaxed text-slate-400"> <p className="text-xs leading-relaxed text-slate-400">
The Insider Intensity Score scales signals based on size, conviction value, and count of participants: The Insider Intensity Score scales signals based on size, conviction value, and count of participants:
</p> </p>
<div className="bg-slate-950/40 p-4 rounded-xl border border-slate-800/60 my-2"> <div className="bg-slate-955/40 p-4 rounded-xl border border-slate-800/60 my-2">
<BlockMath math="I_{score} = \ln\left(\sum_{k=1}^N \text{Volume}_{shares, k}\right) \times \left(\frac{\sum_{k=1}^N \text{Value}_{USD, k}}{\text{Market Cap}}\right) \times \text{Count}_{\text{insiders}}" /> <BlockMath math="I_{\\text{score}} = \\ln\\left(\\sum_{k=1}^N \\text{Volume}_{\\text{shares}, k}\\right) \\times \\left(\\frac{\\sum_{k=1}^N \\text{Value}_{\\text{USD}, k}}{\\text{Market Cap}}\\right) \\times \\text{Count}_{\\text{insiders}}" />
</div> </div>
</div> </div>
@@ -92,9 +93,9 @@ export default function InsiderMathModal({ isOpen, onClose }: InsiderMathModalPr
<p className="text-xs leading-relaxed text-slate-400"> <p className="text-xs leading-relaxed text-slate-400">
The engine cross-references corporate clusters with the Overreaction Scanner, isolating stocks with the highest rebound probabilities: The engine cross-references corporate clusters with the Overreaction Scanner, isolating stocks with the highest rebound probabilities:
</p> </p>
<div className="bg-slate-950/40 p-4 rounded-xl border border-slate-800/60 my-2"> <div className="bg-slate-955/40 p-4 rounded-xl border border-slate-800/60 my-2">
<p className="text-xs leading-relaxed font-mono"> <p className="text-xs leading-relaxed font-mono">
If <InlineMath math="\text{Alert} \in \text{Scanner}_{\text{Oversold}}" /> and <InlineMath math="\text{Cluster} \in \text{Insider}_{\text{Active}}" />: {"If "}<InlineMath math="\\text{Alert} \\in \\text{Scanner}_{\\text{Oversold}}" />{" and "}<InlineMath math="\\text{Cluster} \\in \\text{Insider}_{\\text{Active}}" />{":"}
<br/> <br/>
Prioritize tickers showing asymmetric insider buying during panic drops, suggesting fundamental divergence from market sentiment. Prioritize tickers showing asymmetric insider buying during panic drops, suggesting fundamental divergence from market sentiment.
</p> </p>

View File

@@ -49,11 +49,11 @@ export default function MacroIndicatorsDemo() {
const data = await response.json(); const data = await response.json();
setPayload(data); setPayload(data);
} else { } else {
setError('Fehler beim Abruf der makroökonomischen Indikatoren.'); setError('Error fetching macroeconomic indicators.');
} }
} catch (err) { } catch (err) {
console.error('Fetch macro indicators error:', err); console.error('Fetch macro indicators error:', err);
setError('Netzwerkfehler beim Laden der Makroökonomischen Daten.'); setError('Network error loading macroeconomic data.');
} finally { } finally {
setLoading(false); setLoading(false);
} }
@@ -95,7 +95,7 @@ export default function MacroIndicatorsDemo() {
return { return {
name: 'Federal Reserve Net Liquidity Proxy', name: 'Federal Reserve Net Liquidity Proxy',
unit: 'T$', unit: 'T$',
category: 'Zentralbanken & Liquidität', category: 'Central Banks & Liquidity',
current, current,
previous, previous,
trend, trend,
@@ -107,7 +107,7 @@ export default function MacroIndicatorsDemo() {
return ( return (
<div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-8 text-slate-100 shadow-xl min-h-[450px] flex flex-col items-center justify-center space-y-4"> <div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-8 text-slate-100 shadow-xl min-h-[450px] flex flex-col items-center justify-center space-y-4">
<div className="w-10 h-10 rounded-full border-2 border-indigo-500 border-t-transparent animate-spin" /> <div className="w-10 h-10 rounded-full border-2 border-indigo-500 border-t-transparent animate-spin" />
<div className="text-slate-400 text-sm font-mono animate-pulse">Lade makroökonomisches Datenarchiv...</div> <div className="text-slate-400 text-sm font-mono animate-pulse">Loading macroeconomic data archive...</div>
</div> </div>
); );
} }
@@ -116,7 +116,7 @@ export default function MacroIndicatorsDemo() {
return ( return (
<div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-6 text-slate-100 shadow-xl min-h-[400px] flex items-center justify-center"> <div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-6 text-slate-100 shadow-xl min-h-[400px] flex items-center justify-center">
<div className="text-rose-400 font-semibold flex items-center gap-2"> <div className="text-rose-400 font-semibold flex items-center gap-2">
<AlertCircle className="w-5 h-5" /> {error || 'Fehler beim Laden.'} <AlertCircle className="w-5 h-5" /> {error || 'Error loading data.'}
</div> </div>
</div> </div>
); );
@@ -218,7 +218,7 @@ export default function MacroIndicatorsDemo() {
<div key={key} className="bg-slate-950/40 border border-slate-850 rounded-xl p-3 flex justify-between items-center hover:bg-slate-950/60 transition-colors"> <div key={key} className="bg-slate-950/40 border border-slate-850 rounded-xl p-3 flex justify-between items-center hover:bg-slate-950/60 transition-colors">
<div className="space-y-0.5 max-w-[130px]"> <div className="space-y-0.5 max-w-[130px]">
<div className="text-xs font-semibold text-slate-200 truncate" title={ind.name}>{ind.name}</div> <div className="text-xs font-semibold text-slate-200 truncate" title={ind.name}>{ind.name}</div>
<div className="text-[9px] text-slate-500 font-mono">Vorherig: {ind.previous === null || ind.previous === undefined ? '' : ind.previous}{ind.unit}</div> <div className="text-[9px] text-slate-500 font-mono">Previous: {ind.previous === null || ind.previous === undefined ? '' : ind.previous}{ind.unit}</div>
</div> </div>
{/* Micro Recharts Sparkline */} {/* Micro Recharts Sparkline */}
@@ -258,7 +258,7 @@ export default function MacroIndicatorsDemo() {
<AlertCircle className="w-5 h-5 text-rose-400 shrink-0" /> <AlertCircle className="w-5 h-5 text-rose-400 shrink-0" />
<div className="flex-1"> <div className="flex-1">
<span className="font-bold font-mono uppercase tracking-wider block mb-0.5">[ API Limit - Historical Archive Active]</span> <span className="font-bold font-mono uppercase tracking-wider block mb-0.5">[ API Limit - Historical Archive Active]</span>
Der Echtzeit-Datenabruf (Juni 2026) ist aufgrund von Ratenbeschränkungen (FMP HTTP 429) gedrosselt. Das System operiert im sicheren, gepufferten historischen Archiv-Modus. Real-time data retrieval (June 2026) is throttled due to rate limits (FMP HTTP 429). The system is operating in a secure, buffered historical archive mode.
</div> </div>
</div> </div>
)} )}
@@ -271,10 +271,10 @@ export default function MacroIndicatorsDemo() {
<div className="space-y-1"> <div className="space-y-1">
<span className="text-indigo-400 text-xs font-semibold uppercase tracking-wider">Macroeconomics Silo</span> <span className="text-indigo-400 text-xs font-semibold uppercase tracking-wider">Macroeconomics Silo</span>
<h2 className="text-2xl font-extrabold text-white flex items-center gap-2"> <h2 className="text-2xl font-extrabold text-white flex items-center gap-2">
<Landmark className="text-indigo-400 w-6 h-6" /> Makroökonomische Indikatoren & Kredit-Silo <Landmark className="text-indigo-400 w-6 h-6" /> Macroeconomic Indicators & Credit Silo
</h2> </h2>
<p className="text-xs text-slate-400"> <p className="text-xs text-slate-400">
Analysiert Zyklen, Liquiditätsflüsse und Zinskurven über die letzten 24 Monate. Analyzes cycles, liquidity flows, and yield curves over the past 24 months.
</p> </p>
</div> </div>
@@ -284,11 +284,11 @@ export default function MacroIndicatorsDemo() {
className="flex items-center gap-1.5 px-4 py-2.5 rounded-xl bg-slate-955/80 hover:bg-slate-900 border border-slate-800 hover:border-slate-700 transition-all font-semibold text-xs tracking-wider text-indigo-400 w-full md:w-auto justify-center h-11 cursor-pointer" className="flex items-center gap-1.5 px-4 py-2.5 rounded-xl bg-slate-955/80 hover:bg-slate-900 border border-slate-800 hover:border-slate-700 transition-all font-semibold text-xs tracking-wider text-indigo-400 w-full md:w-auto justify-center h-11 cursor-pointer"
> >
<BookOpen className="w-4 h-4" /> <BookOpen className="w-4 h-4" />
<span>📖 Modulerklärung</span> <span>📖 Quantitative Handbook</span>
</button> </button>
<div className="bg-slate-955/80 border border-slate-800 rounded-xl px-4 py-2 text-right shrink-0 h-11 flex flex-col justify-center"> <div className="bg-slate-955/80 border border-slate-800 rounded-xl px-4 py-2 text-right shrink-0 h-11 flex flex-col justify-center">
<div className="text-[9px] text-slate-555 uppercase font-mono">Letztes Update</div> <div className="text-[9px] text-slate-555 uppercase font-mono">Last Update</div>
<div className="font-mono text-xs text-slate-300"> <div className="font-mono text-xs text-slate-300">
{new Date(payload.timestamp).toLocaleTimeString()} {new Date(payload.timestamp).toLocaleTimeString()}
</div> </div>
@@ -309,8 +309,8 @@ export default function MacroIndicatorsDemo() {
<div className="absolute top-0 right-0 w-24 h-24 bg-rose-500/5 rounded-full blur-2xl -z-10" /> <div className="absolute top-0 right-0 w-24 h-24 bg-rose-500/5 rounded-full blur-2xl -z-10" />
<div className="flex justify-between items-start"> <div className="flex justify-between items-start">
<div className="space-y-1"> <div className="space-y-1">
<span className="text-slate-400 text-[10px] font-mono uppercase tracking-wider">Kategorie 1</span> <span className="text-slate-400 text-[10px] font-mono uppercase tracking-wider">Category 1</span>
<h4 className="text-sm font-bold text-slate-200">Inflation & Konsum-Stress</h4> <h4 className="text-sm font-bold text-slate-200">Inflation & Consumer Stress</h4>
</div> </div>
{/* Glowing Neon-Ampel Light */} {/* Glowing Neon-Ampel Light */}
<div className={`w-3 h-3 rounded-full ${ <div className={`w-3 h-3 rounded-full ${
@@ -321,11 +321,11 @@ export default function MacroIndicatorsDemo() {
</div> </div>
<div className="mt-4 space-y-3"> <div className="mt-4 space-y-3">
<div className="text-xs text-slate-400"> <div className="text-xs text-slate-400">
Risiko-Status:{' '} Risk Status:{' '}
<span className={`font-bold ${ <span className={`font-bold ${
card1Status === 'RED' ? 'text-rose-400' : card1Status === 'AMBER' ? 'text-amber-400' : 'text-emerald-400' card1Status === 'RED' ? 'text-rose-400' : card1Status === 'AMBER' ? 'text-amber-400' : 'text-emerald-400'
}`}> }`}>
{card1Status === 'RED' ? '🚨 Kritischer Konsumdruck' : card1Status === 'AMBER' ? '⚠️ Erhöhtes Risiko' : '✅ Stabil'} {card1Status === 'RED' ? '🚨 Critical Consumer Pressure' : card1Status === 'AMBER' ? '⚠️ Elevated Risk' : '✅ Stable'}
</span> </span>
</div> </div>
<div className="grid grid-cols-3 gap-2 pt-2 border-t border-slate-800/60 text-center font-mono"> <div className="grid grid-cols-3 gap-2 pt-2 border-t border-slate-800/60 text-center font-mono">
@@ -336,13 +336,13 @@ export default function MacroIndicatorsDemo() {
</div> </div>
</div> </div>
<div> <div>
<div className="text-[10px] text-slate-500">Sparquote</div> <div className="text-[10px] text-slate-500">Savings Rate</div>
<div className={`text-xs font-bold ${savingsRate && savingsRate.current < 3.0 ? 'text-rose-400' : 'text-slate-200'}`}> <div className={`text-xs font-bold ${savingsRate && savingsRate.current < 3.0 ? 'text-rose-400' : 'text-slate-200'}`}>
{savingsRate ? savingsRate.current.toFixed(1) : '0.0'}% {savingsRate ? savingsRate.current.toFixed(1) : '0.0'}%
</div> </div>
</div> </div>
<div> <div>
<div className="text-[10px] text-slate-500">Ausfälle</div> <div className="text-[10px] text-slate-500">Delinquencies</div>
<div className={`text-xs font-bold ${ccDelinquency && ccDelinquency.current > 4.5 ? 'text-rose-400' : 'text-slate-200'}`}> <div className={`text-xs font-bold ${ccDelinquency && ccDelinquency.current > 4.5 ? 'text-rose-400' : 'text-slate-200'}`}>
{ccDelinquency ? ccDelinquency.current.toFixed(1) : '0.0'}% {ccDelinquency ? ccDelinquency.current.toFixed(1) : '0.0'}%
</div> </div>
@@ -360,8 +360,8 @@ export default function MacroIndicatorsDemo() {
<div className="absolute top-0 right-0 w-24 h-24 bg-indigo-500/5 rounded-full blur-2xl -z-10" /> <div className="absolute top-0 right-0 w-24 h-24 bg-indigo-500/5 rounded-full blur-2xl -z-10" />
<div className="flex justify-between items-start"> <div className="flex justify-between items-start">
<div className="space-y-1"> <div className="space-y-1">
<span className="text-slate-400 text-[10px] font-mono uppercase tracking-wider">Kategorie 2</span> <span className="text-slate-400 text-[10px] font-mono uppercase tracking-wider">Category 2</span>
<h4 className="text-sm font-bold text-slate-200">Bewertung & Liquidität</h4> <h4 className="text-sm font-bold text-slate-200">Valuation & Liquidity</h4>
</div> </div>
{/* Glowing Neon-Ampel Light */} {/* Glowing Neon-Ampel Light */}
<div className={`w-3 h-3 rounded-full ${ <div className={`w-3 h-3 rounded-full ${
@@ -372,11 +372,11 @@ export default function MacroIndicatorsDemo() {
</div> </div>
<div className="mt-4 space-y-3"> <div className="mt-4 space-y-3">
<div className="text-xs text-slate-400"> <div className="text-xs text-slate-400">
Risiko-Status:{' '} Risk Status:{' '}
<span className={`font-bold ${ <span className={`font-bold ${
card2Status === 'RED' ? 'text-rose-400' : card2Status === 'AMBER' ? 'text-amber-400' : 'text-emerald-400' card2Status === 'RED' ? 'text-rose-400' : card2Status === 'AMBER' ? 'text-amber-400' : 'text-emerald-400'
}`}> }`}>
{card2Status === 'RED' ? '🚨 Extreme Überbewertung' : card2Status === 'AMBER' ? '⚠️ Liquiditäts-Engpass' : '✅ Ausreichend'} {card2Status === 'RED' ? '🚨 Extreme Overvaluation' : card2Status === 'AMBER' ? '⚠️ Liquidity Squeeze' : '✅ Sufficient'}
</span> </span>
</div> </div>
<div className="grid grid-cols-2 gap-2 pt-2 border-t border-slate-800/60 text-center font-mono"> <div className="grid grid-cols-2 gap-2 pt-2 border-t border-slate-800/60 text-center font-mono">
@@ -405,8 +405,8 @@ export default function MacroIndicatorsDemo() {
<div className="absolute top-0 right-0 w-24 h-24 bg-emerald-500/5 rounded-full blur-2xl -z-10" /> <div className="absolute top-0 right-0 w-24 h-24 bg-emerald-500/5 rounded-full blur-2xl -z-10" />
<div className="flex justify-between items-start"> <div className="flex justify-between items-start">
<div className="space-y-1"> <div className="space-y-1">
<span className="text-slate-400 text-[10px] font-mono uppercase tracking-wider">Kategorie 3</span> <span className="text-slate-400 text-[10px] font-mono uppercase tracking-wider">Category 3</span>
<h4 className="text-sm font-bold text-slate-200">Kredit- & Rezessionsrisiko</h4> <h4 className="text-sm font-bold text-slate-200">Credit & Recession Risk</h4>
</div> </div>
{/* Glowing Neon-Ampel Light */} {/* Glowing Neon-Ampel Light */}
<div className={`w-3 h-3 rounded-full ${ <div className={`w-3 h-3 rounded-full ${
@@ -417,11 +417,11 @@ export default function MacroIndicatorsDemo() {
</div> </div>
<div className="mt-4 space-y-3"> <div className="mt-4 space-y-3">
<div className="text-xs text-slate-400"> <div className="text-xs text-slate-400">
Risiko-Status:{' '} Risk Status:{' '}
<span className={`font-bold ${ <span className={`font-bold ${
card3Status === 'RED' ? 'text-rose-400' : card3Status === 'AMBER' ? 'text-amber-400' : 'text-emerald-400' card3Status === 'RED' ? 'text-rose-400' : card3Status === 'AMBER' ? 'text-amber-400' : 'text-emerald-400'
}`}> }`}>
{card3Status === 'RED' ? '🚨 Rezessions-Inversion' : card3Status === 'AMBER' ? '⚠️ Zinskurven-Warnung' : '✅ Stabil'} {card3Status === 'RED' ? '🚨 Recession Inversion' : card3Status === 'AMBER' ? '⚠️ Yield Curve Warning' : '✅ Stable'}
</span> </span>
</div> </div>
<div className="grid grid-cols-2 gap-2 pt-2 border-t border-slate-800/60 text-center font-mono"> <div className="grid grid-cols-2 gap-2 pt-2 border-t border-slate-800/60 text-center font-mono">
@@ -451,11 +451,11 @@ export default function MacroIndicatorsDemo() {
> >
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Activity className="w-5 h-5 text-indigo-400" /> <Activity className="w-5 h-5 text-indigo-400" />
<span>🏛 Detailliertes makroökonomisches Indikatoren-Hauptbuch (21 Indikatoren)</span> <span>🏛 Detailed Macroeconomic Indicators Ledger (21 Indicators)</span>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="text-xs text-slate-500 font-mono"> <span className="text-xs text-slate-500 font-mono">
{isAccordionOpen ? 'Einklappen' : 'Ausklappen'} {isAccordionOpen ? 'Collapse' : 'Expand'}
</span> </span>
<div className="text-slate-400"> <div className="text-slate-400">
{isAccordionOpen ? <ChevronUp className="w-4 h-4" /> : <ChevronDown className="w-4 h-4" />} {isAccordionOpen ? <ChevronUp className="w-4 h-4" /> : <ChevronDown className="w-4 h-4" />}
@@ -472,9 +472,9 @@ export default function MacroIndicatorsDemo() {
<div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-5 text-slate-100 shadow-xl space-y-4"> <div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-5 text-slate-100 shadow-xl space-y-4">
<div className="border-b border-slate-800 pb-3 flex items-center justify-between"> <div className="border-b border-slate-800 pb-3 flex items-center justify-between">
<h3 className="font-bold text-sm text-white flex items-center gap-2"> <h3 className="font-bold text-sm text-white flex items-center gap-2">
<Activity className="w-4 h-4 text-emerald-400" /> Inflation & Wachstum <Activity className="w-4 h-4 text-emerald-400" /> Inflation & Growth
</h3> </h3>
<span className="text-[10px] bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 px-2 py-0.5 rounded font-mono font-bold">Real-Data</span> <span className="text-[10px] bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 px-2 py-0.5 rounded font-mono font-bold">Real Data</span>
</div> </div>
<div className="space-y-4"> <div className="space-y-4">
@@ -490,7 +490,7 @@ export default function MacroIndicatorsDemo() {
<div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-5 text-slate-100 shadow-xl space-y-4"> <div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-5 text-slate-100 shadow-xl space-y-4">
<div className="border-b border-slate-800 pb-3 flex items-center justify-between"> <div className="border-b border-slate-800 pb-3 flex items-center justify-between">
<h3 className="font-bold text-sm text-white flex items-center gap-2"> <h3 className="font-bold text-sm text-white flex items-center gap-2">
<Coins className="w-4 h-4 text-indigo-400" /> Zentralbanken & Liquidität <Coins className="w-4 h-4 text-indigo-400" /> Central Banks & Liquidity
</h3> </h3>
<span className="text-[10px] bg-indigo-500/10 text-indigo-400 border border-indigo-500/20 px-2 py-0.5 rounded font-mono font-bold">M2 / RRP / TGA</span> <span className="text-[10px] bg-indigo-500/10 text-indigo-400 border border-indigo-500/20 px-2 py-0.5 rounded font-mono font-bold">M2 / RRP / TGA</span>
</div> </div>
@@ -511,7 +511,7 @@ export default function MacroIndicatorsDemo() {
<div className="text-xs font-bold text-indigo-300 truncate" title={netLiquidityIndicator.name}> <div className="text-xs font-bold text-indigo-300 truncate" title={netLiquidityIndicator.name}>
Net Fed Liquidity Net Fed Liquidity
</div> </div>
<div className="text-[9px] text-indigo-400/70 font-mono">Vorherig: {netLiquidityIndicator.previous}{netLiquidityIndicator.unit}</div> <div className="text-[9px] text-indigo-400/70 font-mono">Previous: {netLiquidityIndicator.previous}{netLiquidityIndicator.unit}</div>
</div> </div>
{/* Micro Recharts Sparkline */} {/* Micro Recharts Sparkline */}
@@ -547,9 +547,9 @@ export default function MacroIndicatorsDemo() {
<div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-5 text-slate-100 shadow-xl space-y-4"> <div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-5 text-slate-100 shadow-xl space-y-4">
<div className="border-b border-slate-800 pb-3 flex items-center justify-between"> <div className="border-b border-slate-800 pb-3 flex items-center justify-between">
<h3 className="font-bold text-sm text-white flex items-center gap-2"> <h3 className="font-bold text-sm text-white flex items-center gap-2">
<ShieldAlert className="w-4 h-4 text-rose-400" /> Kredit- & Anleihemarkt <ShieldAlert className="w-4 h-4 text-rose-400" /> Credit & Bond Market
</h3> </h3>
<span className="text-[10px] bg-rose-500/10 text-rose-400 border border-rose-500/20 px-2 py-0.5 rounded font-mono font-bold">Zinskurven & Spreads</span> <span className="text-[10px] bg-rose-500/10 text-rose-400 border border-rose-500/20 px-2 py-0.5 rounded font-mono font-bold">Yield Curves & Spreads</span>
</div> </div>
<div className="space-y-4"> <div className="space-y-4">
@@ -557,10 +557,10 @@ export default function MacroIndicatorsDemo() {
{renderRow('yieldSpread', yieldSpread)} {renderRow('yieldSpread', yieldSpread)}
{renderRow('hySpread', hySpread)} {renderRow('hySpread', hySpread)}
{/* Sub-section named "Immobilien- & Hypotheken-Kredite" */} {/* Sub-section named "Real Estate & Mortgage Credit" */}
<div className="border-t border-slate-800/80 pt-4 mt-4"> <div className="border-t border-slate-800/80 pt-4 mt-4">
<h4 className="text-xs font-bold text-indigo-400 uppercase tracking-wider font-mono mb-3 flex items-center gap-1.5"> <h4 className="text-xs font-bold text-indigo-400 uppercase tracking-wider font-mono mb-3 flex items-center gap-1.5">
<Landmark className="w-3.5 h-3.5" /> Immobilien- & Hypotheken-Kredite <Landmark className="w-3.5 h-3.5" /> Real Estate & Mortgage Credit
</h4> </h4>
</div> </div>
@@ -578,10 +578,10 @@ export default function MacroIndicatorsDemo() {
{/* SECTION 3: Dynamic Macro analysis and explanation */} {/* SECTION 3: Dynamic Macro analysis and explanation */}
<div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-6 text-slate-100 shadow-xl space-y-4"> <div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-6 text-slate-100 shadow-xl space-y-4">
<h3 className="font-bold text-sm text-slate-200">Systemische Macro- & Kreditmarkt-Analyse</h3> <h3 className="font-bold text-sm text-slate-200">Systemic Macro & Credit Market Analysis</h3>
<p className="text-xs text-slate-400 leading-relaxed"> <p className="text-xs text-slate-400 leading-relaxed">
Zinskurveninversionen (z. B. wenn der <span className="text-indigo-400 font-semibold font-mono">2S10S-Yield-Spread</span> negativ ist) gelten historisch als zuverlässige Vorläufer ökonomischer Kontraktionen. Derzeit beträgt der Spread <span className="text-emerald-400 font-bold font-mono">{yieldSpread !== undefined ? (yieldSpread.current >= 0 ? '+' : '') + yieldSpread.current.toFixed(2) : '0.00'}%</span>. Gleichzeitig signalisiert der Buffett-Indikator mit <span className="text-rose-400 font-bold font-mono">{buffett !== undefined ? buffett.current.toFixed(1) : '0.0'}%</span> eine erhebliche Überbewertung des US-Aktienmarktes relativ zur Wirtschaftsleistung. Im Konsumsektor deutet die Kombination aus einer niedrigen Sparquote (<span className="text-amber-400 font-mono">{savingsRate !== undefined ? savingsRate.current.toFixed(1) : '0.0'}%</span>) und steigenden Kreditkartenausfällen (<span className="text-rose-400 font-mono">{ccDelinquency !== undefined ? ccDelinquency.current.toFixed(1) : '0.0'}%</span>) auf echten Stress hin, während der High-Yield Credit Spread (<span className="text-slate-300 font-bold font-mono">{hySpread !== undefined ? hySpread.current.toFixed(1) : '0.0'}%</span>) noch Stabilität anzeigt. Yield curve inversions (e.g. when the <span className="text-indigo-400 font-semibold font-mono">2S10S Yield Spread</span> is negative) are historically reliable leading indicators of economic contractions. Currently, the spread is <span className="text-emerald-400 font-bold font-mono">{yieldSpread !== undefined ? (yieldSpread.current >= 0 ? '+' : '') + yieldSpread.current.toFixed(2) : '0.00'}%</span>. At the same time, the Buffett Indicator indicates an overvaluation of the US stock market relative to economic output. In the consumer sector, the combination of a low savings rate (<span className="text-amber-400 font-mono">{savingsRate !== undefined ? savingsRate.current.toFixed(1) : '0.0'}%</span>) and rising credit card delinquencies (<span className="text-rose-400 font-mono">{ccDelinquency !== undefined ? ccDelinquency.current.toFixed(1) : '0.0'}%</span>) suggests genuine distress, while the High-Yield credit spread (<span className="text-slate-300 font-bold font-mono">{hySpread !== undefined ? hySpread.current.toFixed(1) : '0.0'}%</span>) still indicates stability.
Monetäre Liquidität (<span className="font-bold text-indigo-300 font-mono">Net Fed Liquidity Proxy: {netLiquidityIndicator ? netLiquidityIndicator.current.toFixed(2) : '0.00'} T$</span>) wirkt als zentraler Impulsgeber: Ein Anstieg des TGA-Volumens oder der RRP-Nutzung zieht freie Liquidität aus dem Bankensystem ab (Bremswirkung für Aktien/Krypto), während ein Abbau dieser Posten zusätzliche Liquidität freisetzt (Rückenwind r Risk Assets). Monetary liquidity (<span className="font-bold text-indigo-300 font-mono">Net Fed Liquidity Proxy: {netLiquidityIndicator ? netLiquidityIndicator.current.toFixed(2) : '0.00'} T$</span>) acts as a central impulse: an increase in TGA volume or RRP usage drains liquidity from the banking system (headwind for equities/crypto), while a decrease in these items releases additional liquidity (tailwind for risk assets).
</p> </p>
</div> </div>

View File

@@ -1,115 +0,0 @@
import React from 'react';
import { BookOpen } from 'lucide-react';
import 'katex/dist/katex.min.css';
import { BlockMath, InlineMath } from 'react-katex';
interface PortfolioMathModalProps {
isOpen: boolean;
onClose: () => void;
}
export default function PortfolioMathModal({ isOpen, onClose }: PortfolioMathModalProps) {
React.useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
onClose();
}
};
if (isOpen) {
window.addEventListener('keydown', handleKeyDown);
}
return () => {
window.removeEventListener('keydown', handleKeyDown);
};
}, [isOpen, onClose]);
if (!isOpen) return null;
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-slate-950/85 backdrop-blur-md p-4 sm:p-6 md:p-8">
<div className="bg-slate-900 border border-slate-800/80 rounded-3xl w-full max-w-4xl h-[80vh] flex flex-col overflow-hidden shadow-2xl relative text-slate-300">
{/* Modal Header */}
<div className="flex justify-between items-center px-6 py-4 bg-slate-950/40 border-b border-slate-800/60">
<div>
<h2 className="text-base font-bold bg-gradient-to-r from-teal-400 to-emerald-400 bg-clip-text text-transparent flex items-center gap-2">
<BookOpen className="w-5 h-5 text-teal-400" /> Portfolio Sandbox - Math & Logic Specification
</h2>
<p className="text-[10px] text-slate-500 font-mono">Institutional Specification Manual</p>
</div>
<button
onClick={onClose}
className="text-slate-400 hover:text-slate-200 bg-slate-950/50 border border-slate-800 hover:border-slate-700 px-3 py-1.5 rounded-lg text-xs font-semibold font-mono transition-all cursor-pointer"
>
Schließen (ESC)
</button>
</div>
{/* Modal Body */}
<div className="flex-1 overflow-y-auto p-6 sm:p-8 space-y-6 text-slate-300 scrollbar-thin">
<div className="space-y-6">
<div className="border-b border-slate-800/80 pb-3">
<h3 className="text-base font-bold text-slate-200">5. Portfolio Sandbox & Rebalancing Engine</h3>
<p className="text-xs text-slate-400 mt-1">Estimates aggregate portfolio drawdowns and controls covariance drift boundaries.</p>
</div>
<div className="space-y-3">
<h4 className="text-xs font-bold text-teal-400 uppercase tracking-wider font-mono">A. Synthetic Portfolio Model & Asset Weightings</h4>
<p className="text-xs leading-relaxed text-slate-400">
Constructs a continuous synthetic asset representing your active weight allocations and its daily return track:
</p>
<div className="bg-slate-950/40 p-4 rounded-xl border border-slate-800/60 my-2 space-y-4">
<div>
<p className="text-xs text-slate-400 mb-1">Active Percentage Weighting (<InlineMath math="w_i" />) Calculation:</p>
<BlockMath math="w_i = \\frac{\\text{Shares}_i \\times P_{\\text{current}, i}}{\\sum_{j} \\text{Shares}_j \\times P_{\\text{current}, j}}" />
</div>
<div className="border-t border-slate-850 pt-3">
<p className="text-xs text-slate-400 mb-1">Synthetic Portfolio Log Return (<InlineMath math="R_{pt}" />):</p>
<BlockMath math="R_{pt} = \\sum_{i} w_i \\times \\ln\\left(\\frac{P_{t, i}}{P_{t-1, i}}\\right)" />
</div>
</div>
</div>
<div className="space-y-3">
<h4 className="text-xs font-bold text-teal-400 uppercase tracking-wider font-mono">B. Linear Mixed Effects Panel Regression (LMM)</h4>
<p className="text-xs leading-relaxed text-slate-400">
Solves the system-wide macro response model across all historical event instances <InlineMath math="j" /> using a Swamy-Arora GLS estimator:
</p>
<div className="bg-slate-950/40 p-4 rounded-xl border border-slate-800/60 my-2 space-y-4">
<div>
<p className="text-xs text-slate-400 mb-1">Panel Model Specification with VIX Controls:</p>
<BlockMath math="R_{ptj} = \\beta_0 + \\beta_{\\text{drift}} \\text{Pre}_t + \\beta_{\\text{impact}} \\text{Post}_t + \\beta_{\\text{VIX}} VIX_{tj} + u_j + e_{ptj}" />
<p className="text-[10px] text-slate-500 mt-2 font-mono leading-relaxed">
where:
<br />
- <InlineMath math="t \\in [-30, +30]" /> is the relative day offset from event date <InlineMath math="T_j" />.
<br />
- <InlineMath math="\\text{Pre}_t = \\mathbb{I}(t < 0)" /> and <InlineMath math="\\text{Post}_t = \\mathbb{I}(t > 0)" /> are relative phase indicators.
<br />
- <InlineMath math="VIX_{tj}" /> is the background market-wide volatility covariate.
<br />
- <InlineMath math="u_j \\sim N(0, \\sigma_u^2)" /> is the random group intercept (event instance shock).
<br />
- <InlineMath math="e_{ptj} \\sim N(0, \\sigma_e^2)" /> is the residual error.
</p>
</div>
<div className="border-t border-slate-850 pt-3">
<p className="text-xs text-slate-400 mb-1">Optimal Kelly Criterion Position Sizing:</p>
<BlockMath math="f^* = \\frac{p \\times b - (1 - p)}{b}" />
</div>
</div>
</div>
<div className="space-y-3">
<h4 className="text-xs font-bold text-teal-400 uppercase tracking-wider font-mono">C. Reinvestment & Optimization Generation</h4>
<p className="text-xs leading-relaxed text-slate-400">
Integrates signals across three engines: Scanner (underpriced value), Econometrics (macro event post-event betas), and Insiders (corporate buying).
Ranks candidates and suggests target reallocations.
</p>
</div>
</div>
</div>
</div>
</div>
);
}

View File

@@ -6,7 +6,7 @@ import { calculateEWMA, calculateKellyFraction, calculateAssetCovariance } from
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Legend, ReferenceLine, AreaChart, Area } from 'recharts'; import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Legend, ReferenceLine, AreaChart, Area } from 'recharts';
import 'katex/dist/katex.min.css'; import 'katex/dist/katex.min.css';
import { BlockMath, InlineMath } from 'react-katex'; import { BlockMath, InlineMath } from 'react-katex';
import PortfolioMathModal from './PortfolioMathModal'; import SandboxMathModal from './SandboxMathModal';
import { import {
TrendingUp, Wallet, ArrowDownRight, ArrowUpRight, Percent, Plus, FolderSync, TrendingUp, Wallet, ArrowDownRight, ArrowUpRight, Percent, Plus, FolderSync,
HelpCircle, Settings, Calendar, DollarSign, Tag, Check, AlertCircle, ChevronDown, ChevronUp, Sparkles, HelpCircle, Settings, Calendar, DollarSign, Tag, Check, AlertCircle, ChevronDown, ChevronUp, Sparkles,
@@ -53,7 +53,7 @@ export default function SandboxDemo() {
const [simulateFees, setSimulateFees] = useState(true); const [simulateFees, setSimulateFees] = useState(true);
const [isBackfill, setIsBackfill] = useState(false); const [isBackfill, setIsBackfill] = useState(false);
const [backfillDate, setBackfillDate] = useState('2026-05-20'); const [backfillDate, setBackfillDate] = useState('2026-05-20');
const [hypothesisTag, setHypothesisTag] = useState('Fokus auf KI-Infrastruktur'); const [hypothesisTag, setHypothesisTag] = useState('Focus on AI Infrastructure');
const [orderError, setOrderError] = useState<string | null>(null); const [orderError, setOrderError] = useState<string | null>(null);
const [orderSuccess, setOrderSuccess] = useState(false); const [orderSuccess, setOrderSuccess] = useState(false);
@@ -89,11 +89,11 @@ export default function SandboxDemo() {
const data = await response.json(); const data = await response.json();
setStressData(data); setStressData(data);
} else { } else {
setStressError("Fehler beim Laden der Stresstest-Daten."); setStressError("Error loading stress test data.");
} }
} catch (err) { } catch (err) {
console.error("Stress test fetch error:", err); console.error("Stress test fetch error:", err);
setStressError("Netzwerkfehler beim Laden des Stresstests."); setStressError("Network error loading stress test.");
} finally { } finally {
setStressLoading(false); setStressLoading(false);
} }
@@ -174,7 +174,7 @@ export default function SandboxDemo() {
const shares = Number(newAssetShares); const shares = Number(newAssetShares);
const price = Number(newAssetPrice); const price = Number(newAssetPrice);
if (isNaN(shares) || shares <= 0 || isNaN(price) || price <= 0) { if (isNaN(shares) || shares <= 0 || isNaN(price) || price <= 0) {
alert("Bitte geben Sie eine gültige Stückzahl und einen Einstandskurs an."); alert("Please enter a valid number of shares and entry price.");
return; return;
} }
updatePortfolioAsset(ticker, shares, price); updatePortfolioAsset(ticker, shares, price);
@@ -307,7 +307,7 @@ export default function SandboxDemo() {
if (!mounted) { if (!mounted) {
return ( return (
<div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-6 text-slate-100 shadow-xl min-h-[400px] flex items-center justify-center"> <div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-6 text-slate-100 shadow-xl min-h-[400px] flex items-center justify-center">
<div className="text-slate-400 text-sm font-mono animate-pulse">Lade Sandbox-Modul...</div> <div className="text-slate-400 text-sm font-mono animate-pulse">Loading Sandbox Module...</div>
</div> </div>
); );
} }
@@ -331,7 +331,7 @@ export default function SandboxDemo() {
setOrderSuccess(false); setOrderSuccess(false);
if (tradeShares <= 0 || tradePrice <= 0) { if (tradeShares <= 0 || tradePrice <= 0) {
setOrderError('Bitte geben Sie eine gültige Stückzahl und einen Kurs an.'); setOrderError('Please enter a valid number of shares and price.');
return; return;
} }
@@ -354,8 +354,8 @@ export default function SandboxDemo() {
} else { } else {
setOrderError( setOrderError(
tradeType === 'BUY' tradeType === 'BUY'
? 'Unzureichendes Barguthaben (inklusive allfälliger Transaktionsgebühren).' ? 'Insufficient cash balance (including transaction fees).'
: 'Unzureichende Anteile im Depot für den Verkauf.' : 'Insufficient shares in portfolio for sale.'
); );
} }
}; };
@@ -367,7 +367,7 @@ export default function SandboxDemo() {
<div className="bg-rose-950/40 border border-rose-800/80 text-rose-400 text-xs rounded-xl p-4 flex items-center gap-3 shadow-[0_0_15px_rgba(244,63,94,0.15)] animate-pulse"> <div className="bg-rose-950/40 border border-rose-800/80 text-rose-400 text-xs rounded-xl p-4 flex items-center gap-3 shadow-[0_0_15px_rgba(244,63,94,0.15)] animate-pulse">
<AlertCircle className="w-5 h-5 text-rose-400 shrink-0" /> <AlertCircle className="w-5 h-5 text-rose-400 shrink-0" />
<div className="flex-1"> <div className="flex-1">
<span className="font-bold">Kritische Klumpenrisiken (Kovarianz RED):</span> {activePortfolio.riskProfile.message} <span className="font-bold">Critical Concentration Risks (Covariance RED):</span> {activePortfolio.riskProfile.message}
</div> </div>
</div> </div>
)} )}
@@ -395,7 +395,7 @@ export default function SandboxDemo() {
<button <button
onClick={() => setShowNewPortfolioModal(true)} onClick={() => setShowNewPortfolioModal(true)}
className="p-2 rounded-xl bg-slate-800 hover:bg-slate-700 text-emerald-400 hover:text-emerald-300 transition-colors border border-slate-700" className="p-2 rounded-xl bg-slate-800 hover:bg-slate-700 text-emerald-400 hover:text-emerald-300 transition-colors border border-slate-700"
title="Neues Sandbox-Portfolio erstellen" title="Create new Sandbox Portfolio"
> >
<Plus className="w-5 h-5" /> <Plus className="w-5 h-5" />
</button> </button>
@@ -408,12 +408,12 @@ export default function SandboxDemo() {
className="flex items-center gap-1.5 px-4 py-3 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-emerald-400 justify-center h-[58px] shrink-0" className="flex items-center gap-1.5 px-4 py-3 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-emerald-400 justify-center h-[58px] shrink-0"
> >
<BookOpen className="w-3.5 h-3.5" /> <BookOpen className="w-3.5 h-3.5" />
<span>📖 Modulerklärung</span> <span>📖 Quantitative Handbook</span>
</button> </button>
{/* Net Worth Card */} {/* Net Worth Card */}
<div className="flex-1 md:flex-initial bg-slate-950/80 border border-slate-800 rounded-xl p-3 px-5 min-w-[140px]"> <div className="flex-1 md:flex-initial bg-slate-950/80 border border-slate-800 rounded-xl p-3 px-5 min-w-[140px]">
<div className="text-[10px] text-slate-400 uppercase font-semibold">Gesamtwert</div> <div className="text-[10px] text-slate-400 uppercase font-semibold">Total Value</div>
<div className="font-mono text-xl font-bold text-slate-100 mt-1"> <div className="font-mono text-xl font-bold text-slate-100 mt-1">
${netWorth.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} ${netWorth.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
</div> </div>
@@ -421,7 +421,7 @@ export default function SandboxDemo() {
{/* Performance Card */} {/* Performance Card */}
<div className="flex-1 md:flex-initial bg-slate-950/80 border border-slate-800 rounded-xl p-3 px-5 min-w-[140px]"> <div className="flex-1 md:flex-initial bg-slate-950/80 border border-slate-800 rounded-xl p-3 px-5 min-w-[140px]">
<div className="text-[10px] text-slate-400 uppercase font-semibold">GuV (Gesamt)</div> <div className="text-[10px] text-slate-400 uppercase font-semibold">PnL (Total)</div>
<div className={`font-mono text-xl font-bold mt-1 flex items-center gap-1 ${isPositiveOverall ? 'text-emerald-400' : 'text-rose-400'}`}> <div className={`font-mono text-xl font-bold mt-1 flex items-center gap-1 ${isPositiveOverall ? 'text-emerald-400' : 'text-rose-400'}`}>
{isPositiveOverall ? <ArrowUpRight className="w-5 h-5" /> : <ArrowDownRight className="w-5 h-5" />} {isPositiveOverall ? <ArrowUpRight className="w-5 h-5" /> : <ArrowDownRight className="w-5 h-5" />}
<span>{isPositiveOverall ? '+' : ''}{totalGainLossPct.toFixed(2)}%</span> <span>{isPositiveOverall ? '+' : ''}{totalGainLossPct.toFixed(2)}%</span>
@@ -431,8 +431,8 @@ export default function SandboxDemo() {
{/* Live EWMA Vol Card */} {/* Live EWMA Vol Card */}
<div className="flex-1 md:flex-initial bg-slate-950/80 border border-slate-800 rounded-xl p-3 px-5 min-w-[140px] relative group"> <div className="flex-1 md:flex-initial bg-slate-950/80 border border-slate-800 rounded-xl p-3 px-5 min-w-[140px] relative group">
<div className="text-[10px] text-slate-400 uppercase font-semibold flex items-center gap-1"> <div className="text-[10px] text-slate-400 uppercase font-semibold flex items-center gap-1">
<span>EWMA Volatilität</span> <span>EWMA Volatility</span>
<span className="cursor-help flex items-center" title="Annualisierte Schwankungsbreite basierend auf historischen Renditen."> <span className="cursor-help flex items-center" title="Annualized volatility based on historical returns.">
<HelpCircle className="w-3.5 h-3.5 text-slate-500 group-hover:text-emerald-400 transition-colors" /> <HelpCircle className="w-3.5 h-3.5 text-slate-500 group-hover:text-emerald-400 transition-colors" />
</span> </span>
</div> </div>
@@ -444,8 +444,8 @@ export default function SandboxDemo() {
{/* Covariance Risk Traffic Light Card */} {/* Covariance Risk Traffic Light Card */}
<div className="flex-1 md:flex-initial bg-slate-950/80 border border-slate-800 rounded-xl p-3 px-5 min-w-[150px] relative group"> <div className="flex-1 md:flex-initial bg-slate-950/80 border border-slate-800 rounded-xl p-3 px-5 min-w-[150px] relative group">
<div className="text-[10px] text-slate-400 uppercase font-semibold flex items-center gap-1"> <div className="text-[10px] text-slate-400 uppercase font-semibold flex items-center gap-1">
<span>Kovarianz-Ampel</span> <span>Covariance Traffic Light</span>
<span className="cursor-help flex items-center" title="Systemische Portfolio-Klumpenrisiken basierend auf historischen Asset-Kovarianzen."> <span className="cursor-help flex items-center" title="Systemic portfolio concentration risks based on historical asset covariances.">
<HelpCircle className="w-3.5 h-3.5 text-slate-500 group-hover:text-rose-400 transition-colors" /> <HelpCircle className="w-3.5 h-3.5 text-slate-500 group-hover:text-rose-400 transition-colors" />
</span> </span>
</div> </div>
@@ -471,21 +471,21 @@ export default function SandboxDemo() {
{showNewPortfolioModal && ( {showNewPortfolioModal && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4"> <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4">
<div className="bg-slate-900 border border-slate-800 rounded-2xl p-6 max-w-sm w-full space-y-4 shadow-2xl"> <div className="bg-slate-900 border border-slate-800 rounded-2xl p-6 max-w-sm w-full space-y-4 shadow-2xl">
<h3 className="text-lg font-bold text-white">Neues Sandbox-Portfolio</h3> <h3 className="text-lg font-bold text-white">New Sandbox Portfolio</h3>
<form onSubmit={handleCreatePortfolio} className="space-y-4"> <form onSubmit={handleCreatePortfolio} className="space-y-4">
<div> <div>
<label className="text-xs text-slate-400 block mb-1">Portfolio Name</label> <label className="text-xs text-slate-400 block mb-1">Portfolio Name</label>
<input <input
type="text" type="text"
required required
placeholder="z.B. Biotech Risk High Yield" placeholder="e.g. Biotech Risk High Yield"
className="w-full bg-slate-950 border border-slate-800 rounded-lg p-2.5 text-slate-100 focus:outline-none focus:border-emerald-500" className="w-full bg-slate-950 border border-slate-800 rounded-lg p-2.5 text-slate-100 focus:outline-none focus:border-emerald-500"
value={newPortfolioName} value={newPortfolioName}
onChange={(e) => setNewPortfolioName(e.target.value)} onChange={(e) => setNewPortfolioName(e.target.value)}
/> />
</div> </div>
<div> <div>
<label className="text-xs text-slate-400 block mb-1">Startkapital ($)</label> <label className="text-xs text-slate-400 block mb-1">Starting Capital ($)</label>
<input <input
type="number" type="number"
required required
@@ -500,13 +500,13 @@ export default function SandboxDemo() {
onClick={() => setShowNewPortfolioModal(false)} onClick={() => setShowNewPortfolioModal(false)}
className="flex-1 bg-slate-850 hover:bg-slate-800 text-slate-300 font-semibold py-2 rounded-lg transition-colors border border-slate-700" className="flex-1 bg-slate-850 hover:bg-slate-800 text-slate-300 font-semibold py-2 rounded-lg transition-colors border border-slate-700"
> >
Abbrechen Cancel
</button> </button>
<button <button
type="submit" type="submit"
className="flex-1 bg-gradient-to-r from-emerald-500 to-teal-500 hover:from-emerald-600 hover:to-teal-600 text-slate-950 font-bold py-2 rounded-lg transition-all shadow-lg shadow-emerald-500/20" className="flex-1 bg-gradient-to-r from-emerald-500 to-teal-500 hover:from-emerald-600 hover:to-teal-600 text-slate-950 font-bold py-2 rounded-lg transition-all shadow-lg shadow-emerald-500/20"
> >
Erstellen Create
</button> </button>
</div> </div>
</form> </form>
@@ -521,53 +521,53 @@ export default function SandboxDemo() {
className="flex items-center gap-1.5 text-xs text-slate-400 hover:text-emerald-400 transition-colors focus:outline-none" className="flex items-center gap-1.5 text-xs text-slate-400 hover:text-emerald-400 transition-colors focus:outline-none"
> >
<span>{showMathAccordion ? <ChevronUp className="w-4 h-4" /> : <ChevronDown className="w-4 h-4" />}</span> <span>{showMathAccordion ? <ChevronUp className="w-4 h-4" /> : <ChevronDown className="w-4 h-4" />}</span>
<span className="font-semibold uppercase tracking-wider">Mathematische Spezifikation & EWMA-Volatilitätsmodell</span> <span className="font-semibold uppercase tracking-wider">Mathematical Specification & EWMA Volatility Model</span>
</button> </button>
{showMathAccordion && ( {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 className="mt-4 p-4 rounded-xl border border-slate-850 bg-slate-950/40 text-xs text-slate-300 space-y-4">
<div> <div>
<h4 className="font-semibold text-emerald-400 mb-1.5">1. EWMA Volatilitätsmodell</h4> <h4 className="font-semibold text-emerald-400 mb-1.5">1. EWMA Volatility Model</h4>
<p className="mb-2"> <p className="mb-2">
Die Volatilit&auml;t wird mittels des <strong>Exponentially Weighted Moving Average (EWMA)</strong>-Modells ermittelt. J&uuml;ngere Renditen erhalten hierbei ein h&ouml;heres Gewicht als weiter in der Vergangenheit liegende Renditen, gesteuert durch den Zerfallsparameter <InlineMath math="\lambda" /> (Lambda). Volatility is calculated using the <strong>Exponentially Weighted Moving Average (EWMA)</strong> model. Recent returns receive a higher weighting than returns further in the past, controlled by the decay parameter <InlineMath math="\lambda" /> (Lambda).
</p> </p>
<div className="py-2 overflow-x-auto"> <div className="py-2 overflow-x-auto">
<BlockMath math="\sigma_t^2 = \lambda \sigma_{t-1}^2 + (1 - \lambda) r_{t-1}^2" /> <BlockMath math="\sigma_t^2 = \lambda \sigma_{t-1}^2 + (1 - \lambda) r_{t-1}^2" />
</div> </div>
<p className="mb-2"> <p className="mb-2">
Die t&auml;gliche Volatilit&auml;t <InlineMath math="\sigma_t" /> wird auf ein ganzes Jahr hochgerechnet (Annualisierung) unter der Annahme von 252 Handelstagen: The daily volatility <InlineMath math="\sigma_t" /> is extrapolated to an entire year (annualization) assuming 252 trading days:
</p> </p>
<div className="py-2 overflow-x-auto"> <div className="py-2 overflow-x-auto">
<BlockMath math="\sigma_{\text{ann}} = \sqrt{\sigma_t^2 \times 252}" /> <BlockMath math="\sigma_{\text{ann}} = \sqrt{\sigma_t^2 \times 252}" />
</div> </div>
<p className="text-slate-400"> <p className="text-slate-400">
RiskMetrics empfiehlt f&uuml;r t&auml;gliche Finanzdaten einen Lambda-Wert von <InlineMath math="\lambda = 0.94" />. RiskMetrics recommends a Lambda value of <InlineMath math="\lambda = 0.94" /> for daily financial data.
</p> </p>
</div> </div>
<div className="border-t border-slate-800 pt-3"> <div className="border-t border-slate-800 pt-3">
<h4 className="font-semibold text-emerald-400 mb-1.5">2. Kelly-Kriterium zur Positionsgrößenbestimmung</h4> <h4 className="font-semibold text-emerald-400 mb-1.5">2. Kelly Criterion for Position Sizing</h4>
<p className="mb-2"> <p className="mb-2">
Die Kelly-Formel bestimmt den optimalen Anteil des Kapitals (<InlineMath math="f^*" />), der in ein Geschäft investiert werden soll, um das exponentielle Wachstum des Kapitals zu maximieren: The Kelly formula determines the optimal fraction of capital (<InlineMath math="f^*" />) to invest in a trade to maximize the exponential growth of wealth:
</p> </p>
<div className="py-2 overflow-x-auto"> <div className="py-2 overflow-x-auto">
<BlockMath math="f^* = \frac{p \cdot b - q}{b} = \frac{p \cdot b - (1 - p)}{b}" /> <BlockMath math="f^* = \frac{p \cdot b - q}{b} = \frac{p \cdot b - (1 - p)}{b}" />
</div> </div>
<p className="mb-2"> <p className="mb-2">
Um Risiken durch ungenaue Schätzungen zu verringern, wenden wir das konservative <strong>Half-Kelly</strong>-Sizing an und begrenzen das Ergebnis auf <InlineMath math="0.5 \times f^*" /> (zusätzlich begrenzt auf <InlineMath math="\ge 0" />). To mitigate risks from inaccurate estimations, we apply the conservative <strong>Half-Kelly</strong> sizing and limit the result to <InlineMath math="0.5 \times f^*" /> (additionally constrained to <InlineMath math="\ge 0" />).
</p> </p>
</div> </div>
<div className="border-t border-slate-800 pt-3"> <div className="border-t border-slate-800 pt-3">
<h4 className="font-semibold text-rose-400 mb-1.5">3. Covariance & Cluster Risk (Kovarianz-Ampel)</h4> <h4 className="font-semibold text-rose-400 mb-1.5">3. Covariance & Cluster Risk (Covariance Traffic Light)</h4>
<p className="mb-2"> <p className="mb-2">
Die Kovarianz zwischen Assets wird durch Multiplikation ihrer paarweisen Korrelation mit ihren jeweiligen Standardabweichungen (Volatilitäten) bestimmt: The covariance between assets is determined by multiplying their pairwise correlation by their respective standard deviations (volatilities):
</p> </p>
<div className="py-2 overflow-x-auto"> <div className="py-2 overflow-x-auto">
<BlockMath math="\text{Cov}(A, B) = \text{Corr}(A, B) \times \sigma_A \times \sigma_B" /> <BlockMath math="\text{Cov}(A, B) = \text{Corr}(A, B) \times \sigma_A \times \sigma_B" />
</div> </div>
<p className="text-slate-400"> <p className="text-slate-400">
Ein <strong>Klumpenrisiko (Risk RED)</strong> wird ausgelöst, wenn ein Asset eine Korrelation <InlineMath math="\text{Corr}(A, B) > 0.70" /> zu bestehenden Positionen aufweist und diese Positionen jeweils mehr als 15% des Portfolios ausmachen. A <strong>concentration risk (Risk RED)</strong> is triggered when an asset exhibits a correlation <InlineMath math="\text{Corr}(A, B) > 0.70" /> to existing positions and these positions each exceed 15% of the portfolio.
</p> </p>
</div> </div>
</div> </div>
@@ -575,14 +575,14 @@ export default function SandboxDemo() {
</div> </div>
</div> </div>
{/* SECTION: Mein Portfolio Ingestion Cockpit */} {/* SECTION: My Portfolio Ingestion Cockpit */}
<div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-6 text-slate-100 shadow-xl space-y-4"> <div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-6 text-slate-100 shadow-xl space-y-4">
<div className="flex justify-between items-center border-b border-slate-800 pb-3"> <div className="flex justify-between items-center border-b border-slate-800 pb-3">
<h3 className="text-lg font-bold text-white flex items-center gap-2"> <h3 className="text-lg font-bold text-white flex items-center gap-2">
<Wallet className="text-emerald-400 w-5 h-5" /> Mein Portfolio Cockpit <Wallet className="text-emerald-400 w-5 h-5" /> My Portfolio Cockpit
</h3> </h3>
<span className="text-xs text-slate-400 font-mono"> <span className="text-xs text-slate-400 font-mono">
Gesamt-Inventarwert: <span className="text-emerald-400 font-bold font-mono">${portfolioCalculated.totalValue.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</span> Total Inventory Value: <span className="text-emerald-400 font-bold font-mono">${portfolioCalculated.totalValue.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</span>
</span> </span>
</div> </div>
@@ -591,20 +591,20 @@ export default function SandboxDemo() {
<thead> <thead>
<tr className="border-b border-slate-800 text-slate-400 font-semibold bg-slate-900/40"> <tr className="border-b border-slate-800 text-slate-400 font-semibold bg-slate-900/40">
<th className="p-3">Asset / Ticker</th> <th className="p-3">Asset / Ticker</th>
<th className="p-3 text-center">Stücke (Shares)</th> <th className="p-3 text-center">Shares</th>
<th className="p-3 text-center">Einstandspreis</th> <th className="p-3 text-center">Entry Price</th>
<th className="p-3 text-center">Aktueller Kurs</th> <th className="p-3 text-center">Current Price</th>
<th className="p-3 text-right">Positionswert</th> <th className="p-3 text-right">Position Value</th>
<th className="p-3 text-right">Performance (PnL)</th> <th className="p-3 text-right">Performance (PnL)</th>
<th className="p-3">Gewichtung (w_i)</th> <th className="p-3">Weighting (w_i)</th>
<th className="p-3 text-center">Aktionen</th> <th className="p-3 text-center">Actions</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{portfolioCalculated.items.length === 0 ? ( {portfolioCalculated.items.length === 0 ? (
<tr> <tr>
<td colSpan={8} className="p-8 text-center text-slate-500 italic"> <td colSpan={8} className="p-8 text-center text-slate-500 italic">
Bislang keine Assets im Ingestion-Cockpit. Fügen Sie unten ein Asset hinzu. No assets in the Ingestion Cockpit yet. Add an asset below.
</td> </td>
</tr> </tr>
) : ( ) : (
@@ -687,7 +687,7 @@ export default function SandboxDemo() {
<button <button
onClick={() => removePortfolioAsset(item.ticker)} onClick={() => removePortfolioAsset(item.ticker)}
className="p-1.5 rounded-lg bg-slate-950 hover:bg-rose-950/40 text-slate-500 hover:text-rose-400 transition-colors border border-slate-850 hover:border-rose-900/30 cursor-pointer" className="p-1.5 rounded-lg bg-slate-950 hover:bg-rose-950/40 text-slate-500 hover:text-rose-400 transition-colors border border-slate-850 hover:border-rose-900/30 cursor-pointer"
title="Asset löschen" title="Delete asset"
> >
<Trash2 className="w-4 h-4" /> <Trash2 className="w-4 h-4" />
</button> </button>
@@ -703,7 +703,7 @@ export default function SandboxDemo() {
<input <input
type="text" type="text"
required required
placeholder="Ticker (z.B. AAPL)" placeholder="Ticker (e.g. AAPL)"
className="w-full bg-slate-950 border border-slate-800 rounded-lg p-2 text-slate-100 font-mono text-xs uppercase focus:border-emerald-500 focus:outline-none" className="w-full bg-slate-950 border border-slate-800 rounded-lg p-2 text-slate-100 font-mono text-xs uppercase focus:border-emerald-500 focus:outline-none"
value={newAssetTicker} value={newAssetTicker}
onChange={(e) => setNewAssetTicker(e.target.value)} onChange={(e) => setNewAssetTicker(e.target.value)}
@@ -713,7 +713,7 @@ export default function SandboxDemo() {
<input <input
type="number" type="number"
required required
placeholder="Stücke" placeholder="Shares"
className="w-24 bg-slate-950 border border-slate-800 rounded-lg p-2 text-slate-100 font-mono text-xs text-center focus:border-emerald-500 focus:outline-none" className="w-24 bg-slate-950 border border-slate-800 rounded-lg p-2 text-slate-100 font-mono text-xs text-center focus:border-emerald-500 focus:outline-none"
value={newAssetShares === '' ? '' : newAssetShares} value={newAssetShares === '' ? '' : newAssetShares}
onChange={(e) => setNewAssetShares(e.target.value === '' ? '' : Number(e.target.value))} onChange={(e) => setNewAssetShares(e.target.value === '' ? '' : Number(e.target.value))}
@@ -723,7 +723,7 @@ export default function SandboxDemo() {
<input <input
type="number" type="number"
required required
placeholder="Einstand ($)" placeholder="Entry ($)"
className="w-28 bg-slate-950 border border-slate-800 rounded-lg p-2 text-slate-100 font-mono text-xs text-center focus:border-emerald-500 focus:outline-none" className="w-28 bg-slate-950 border border-slate-800 rounded-lg p-2 text-slate-100 font-mono text-xs text-center focus:border-emerald-500 focus:outline-none"
value={newAssetPrice === '' ? '' : newAssetPrice} value={newAssetPrice === '' ? '' : newAssetPrice}
onChange={(e) => setNewAssetPrice(e.target.value === '' ? '' : Number(e.target.value))} onChange={(e) => setNewAssetPrice(e.target.value === '' ? '' : Number(e.target.value))}
@@ -736,9 +736,9 @@ export default function SandboxDemo() {
<td className="p-3 text-center"> <td className="p-3 text-center">
<button <button
onClick={handleAddNewAsset} onClick={handleAddNewAsset}
className="bg-emerald-500 hover:bg-emerald-600 text-slate-950 font-bold py-1.5 px-3 rounded-lg text-xs shadow-md shadow-emerald-500/10 flex items-center justify-center gap-1 mx-auto transition-all active:scale-[0.96] cursor-pointer animate-pulse hover:animate-none" className="bg-emerald-500 hover:bg-emerald-600 text-slate-950 font-bold py-1.5 px-3 rounded-lg text-xs shadow-md shadow-emerald-500/10 flex items-center justify-center gap-1 mx-auto transition-all active:scale-[0.96] cursor-pointer"
> >
<Plus className="w-3.5 h-3.5" /> Hinzufügen <Plus className="w-3.5 h-3.5" /> Add
</button> </button>
</td> </td>
</tr> </tr>
@@ -747,15 +747,15 @@ export default function SandboxDemo() {
</div> </div>
</div> </div>
{/* SECTION: Systemischer Makro-Stresstest (Portfolio-LMM) */} {/* SECTION: Systemic Macro Stress Test (Portfolio LMM) */}
<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"> <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">
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 border-b border-slate-800 pb-3"> <div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 border-b border-slate-800 pb-3">
<div className="space-y-1"> <div className="space-y-1">
<h3 className="text-lg font-bold text-white flex items-center gap-2"> <h3 className="text-lg font-bold text-white flex items-center gap-2">
<TrendingUp className="text-purple-400 w-5 h-5" /> Systemischer Makro-Stresstest (Portfolio-LMM) <TrendingUp className="text-purple-400 w-5 h-5" /> Systemic Macro Stress Test (Portfolio LMM)
</h3> </h3>
<p className="text-xs text-slate-400"> <p className="text-xs text-slate-400">
Analysiert die historische Sensitivität des Portfolios gegenüber Kern-Makro-Ereignissen über die letzten 36 Monate. Analyzes the historical sensitivity of the portfolio to core macro events over the last 36 months.
</p> </p>
</div> </div>
{/* Event type tabs */} {/* Event type tabs */}
@@ -779,18 +779,18 @@ export default function SandboxDemo() {
{stressLoading ? ( {stressLoading ? (
<div className="h-80 flex flex-col items-center justify-center space-y-3"> <div className="h-80 flex flex-col items-center justify-center space-y-3">
<div className="w-8 h-8 rounded-full border-2 border-purple-500 border-t-transparent animate-spin" /> <div className="w-8 h-8 rounded-full border-2 border-purple-500 border-t-transparent animate-spin" />
<span className="text-xs text-slate-400 font-mono animate-pulse">Kalkuliere Swamy-Arora GLS-Schätzer...</span> <span className="text-xs text-slate-400 font-mono animate-pulse">Calculating Swamy-Arora GLS estimators...</span>
</div> </div>
) : stressError || !stressData ? ( ) : stressError || !stressData ? (
<div className="h-80 flex items-center justify-center text-slate-500 italic"> <div className="h-80 flex items-center justify-center text-slate-500 italic">
{stressError || 'Keine Daten geladen.'} {stressError || 'No data loaded.'}
</div> </div>
) : ( ) : (
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
{/* LMM Summary Statistics */} {/* LMM Summary Statistics */}
<div className="bg-slate-950/40 rounded-xl p-4 border border-slate-850 flex flex-col justify-between space-y-4"> <div className="bg-slate-950/40 rounded-xl p-4 border border-slate-850 flex flex-col justify-between space-y-4">
<div> <div>
<span className="text-[10px] uppercase tracking-wider text-purple-400 font-bold block mb-2">Regressions-Koeffizienten (GLS)</span> <span className="text-[10px] uppercase tracking-wider text-purple-400 font-bold block mb-2">Regression Coefficients (GLS)</span>
{/* Fixed Effects list */} {/* Fixed Effects list */}
<div className="space-y-3"> <div className="space-y-3">
@@ -803,13 +803,13 @@ export default function SandboxDemo() {
}`}> }`}>
<div> <div>
<div className={`text-xs font-semibold ${isImpact ? 'text-purple-300 font-bold' : 'text-slate-350'}`}> <div className={`text-xs font-semibold ${isImpact ? 'text-purple-300 font-bold' : 'text-slate-350'}`}>
{fe.name === 'Intercept' ? 'Basisschnittstelle (Intercept)' : {fe.name === 'Intercept' ? 'Baseline Intercept' :
fe.name === 'Pre-Event Drift' ? 'Pre-Event Trend (Drift)' : fe.name === 'Pre-Event Drift' ? 'Pre-Event Trend (Drift)' :
fe.name === 'Post-Event Impact' ? 'Systemisches Portfolio Beta' : fe.name === 'Post-Event Impact' ? 'Systemic Portfolio Beta' :
'VIX-Volatilitäts-Sensitivität'} 'VIX Volatility Sensitivity'}
</div> </div>
<div className="text-[9px] text-slate-500"> <div className="text-[9px] text-slate-500">
SE: {fe.se.toFixed(4)} | p-Wert: {fe.pVal.toFixed(4)} SE: {fe.se.toFixed(4)} | p-value: {fe.pVal.toFixed(4)}
</div> </div>
</div> </div>
<div className="text-right"> <div className="text-right">
@@ -830,7 +830,7 @@ export default function SandboxDemo() {
{/* Model Fit metrics */} {/* Model Fit metrics */}
<div className="border-t border-slate-850 pt-3 space-y-2"> <div className="border-t border-slate-850 pt-3 space-y-2">
<div className="flex justify-between text-xs"> <div className="flex justify-between text-xs">
<span className="text-slate-400">R-Quadrat (Bestimmtheitsmaß):</span> <span className="text-slate-400">R-Squared:</span>
<span className="font-mono font-bold text-slate-200">{(stressData.regressionResults?.rSquared * 100).toFixed(1)}%</span> <span className="font-mono font-bold text-slate-200">{(stressData.regressionResults?.rSquared * 100).toFixed(1)}%</span>
</div> </div>
<div className="flex justify-between text-[11px] text-slate-500 font-mono"> <div className="flex justify-between text-[11px] text-slate-500 font-mono">
@@ -844,8 +844,8 @@ export default function SandboxDemo() {
{/* Recharts Area/Line Chart (2/3 width) */} {/* Recharts Area/Line Chart (2/3 width) */}
<div className="lg:col-span-2 bg-slate-950/30 rounded-xl p-4 border border-slate-850 space-y-3"> <div className="lg:col-span-2 bg-slate-950/30 rounded-xl p-4 border border-slate-850 space-y-3">
<div className="flex justify-between items-center text-xs"> <div className="flex justify-between items-center text-xs">
<span className="text-slate-400 font-mono">Durchschnittlicher kumulierter Ertrag im Zeitfenster [-30, +30] Tage</span> <span className="text-slate-400 font-mono">Average cumulative return in the [-30, +30] days window</span>
<span className="text-[9px] text-slate-500 font-mono">Akkumulierte Log-Renditen</span> <span className="text-[9px] text-slate-500 font-mono">Accumulated log returns</span>
</div> </div>
<div className="h-64 w-full"> <div className="h-64 w-full">
@@ -875,7 +875,7 @@ export default function SandboxDemo() {
/> />
<Tooltip <Tooltip
contentStyle={{ backgroundColor: '#090d16', borderColor: '#1e293b', borderRadius: '8px', fontSize: '11px' }} contentStyle={{ backgroundColor: '#090d16', borderColor: '#1e293b', borderRadius: '8px', fontSize: '11px' }}
labelFormatter={(label) => `Relativer Tag: T${label >= 0 ? '+' : ''}${label}`} labelFormatter={(label) => `Relative Day: T${label >= 0 ? '+' : ''}${label}`}
/> />
<Legend verticalAlign="top" height={36} iconType="circle" /> <Legend verticalAlign="top" height={36} iconType="circle" />
@@ -911,7 +911,7 @@ export default function SandboxDemo() {
stroke="#ef4444" stroke="#ef4444"
strokeWidth={1.5} strokeWidth={1.5}
strokeDasharray="3 3" strokeDasharray="3 3"
label={{ value: 'Stichtag (T0)', fill: '#ef4444', fontSize: 9, position: 'top' }} label={{ value: 'Event Date (T0)', fill: '#ef4444', fontSize: 9, position: 'top' }}
/> />
</AreaChart> </AreaChart>
</ResponsiveContainer> </ResponsiveContainer>
@@ -925,7 +925,7 @@ export default function SandboxDemo() {
<div className="bg-purple-950/20 border border-purple-900/40 rounded-xl p-4 flex gap-3 items-start text-xs text-purple-300"> <div className="bg-purple-950/20 border border-purple-900/40 rounded-xl p-4 flex gap-3 items-start text-xs text-purple-300">
<Sparkles className="w-5 h-5 text-purple-400 shrink-0 mt-0.5" /> <Sparkles className="w-5 h-5 text-purple-400 shrink-0 mt-0.5" />
<div> <div>
<span className="font-bold uppercase tracking-wider block mb-1">Quantitative Analyse-Auswertung</span> <span className="font-bold uppercase tracking-wider block mb-1">Quantitative Analysis Evaluation</span>
<p className="leading-relaxed"> <p className="leading-relaxed">
{(() => { {(() => {
const impactBeta = stressData.regressionResults?.fixedEffects.find((f: any) => f.name === 'Post-Event Impact')?.estimate || 0; const impactBeta = stressData.regressionResults?.fixedEffects.find((f: any) => f.name === 'Post-Event Impact')?.estimate || 0;
@@ -934,17 +934,17 @@ export default function SandboxDemo() {
const pVal = stressData.regressionResults?.fixedEffects.find((f: any) => f.name === 'Post-Event Impact')?.pVal || 0; const pVal = stressData.regressionResults?.fixedEffects.find((f: any) => f.name === 'Post-Event Impact')?.pVal || 0;
const isSignificant = pVal < 0.05; const isSignificant = pVal < 0.05;
let eventNameText = activeStressTab === 'FOMC Rates' ? 'FOMC-Zinsentscheiden' : let eventNameText = activeStressTab === 'FOMC Rates' ? 'FOMC rate decisions' :
activeStressTab === 'CPI Inflation' ? 'CPI-Inflationsdaten' : 'Arbeitsmarktdaten'; activeStressTab === 'CPI Inflation' ? 'CPI inflation releases' : 'labor market updates';
let significanceText = isSignificant let significanceText = isSignificant
? `Dieser Effekt ist mit einem p-Wert von ${pVal.toFixed(4)} statistisch signifikant.` ? `This effect is statistically significant with a p-value of ${pVal.toFixed(4)}.`
: `Dieser Effekt ist mit einem p-Wert von ${pVal.toFixed(4)} statistisch nicht hochgradig signifikant (Rauscheinfluss möglich).`; : `This effect is not highly statistically significant (potential noise) with a p-value of ${pVal.toFixed(4)}.`;
if (isNegative) { if (isNegative) {
return `Historische Reaktivität: Bei ${eventNameText} zeigt dein Depot ein negatives Beta von -${absBeta}. ${significanceText} Eine Absicherung über defensive Sektoren (z.B. Erhöhung der Bargeldquote oder defensive Consumer-Titel) senkt das Volatilitätsrisiko in dieser Post-Event-Phase um ca. ${Math.round(Math.abs(impactBeta) * 35)}%.`; return `Historical reactivity: During ${eventNameText}, your portfolio exhibits a negative Beta of -${absBeta}. ${significanceText} Hedging via defensive sectors (e.g., increasing cash ratio or defensive consumer stocks) reduces volatility risk in this post-event phase by approx. ${Math.round(Math.abs(impactBeta) * 35)}%.`;
} else { } else {
return `Historische Reaktivität: Bei ${eventNameText} zeigt dein Depot ein positives Beta von +${absBeta}. ${significanceText} Dein Portfolio profitiert tendenziell von der anschließenden Marktdynamik. Sie können erwägen, die Hebelwirkung durch Zukäufe in Momentum-Aktien zu erhöhen.`; return `Historical reactivity: During ${eventNameText}, your portfolio exhibits a positive Beta of +${absBeta}. ${significanceText} Your portfolio tends to benefit from the subsequent market momentum. You might consider increasing leverage via momentum additions.`;
} }
})()} })()}
</p> </p>
@@ -960,7 +960,7 @@ export default function SandboxDemo() {
<div className="xl:col-span-2 bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-6 text-slate-100 shadow-xl space-y-6"> <div className="xl:col-span-2 bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-6 text-slate-100 shadow-xl space-y-6">
<div className="flex justify-between items-center border-b border-slate-800 pb-3"> <div className="flex justify-between items-center border-b border-slate-800 pb-3">
<h3 className="text-lg font-bold text-white flex items-center gap-2"> <h3 className="text-lg font-bold text-white flex items-center gap-2">
<TrendingUp className="text-emerald-400 w-5 h-5" /> Portfolio Wertentwicklung & Benchmark <TrendingUp className="text-emerald-400 w-5 h-5" /> Portfolio Performance & Benchmark
</h3> </h3>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<label className="flex items-center gap-2 text-xs text-slate-400 cursor-pointer"> <label className="flex items-center gap-2 text-xs text-slate-400 cursor-pointer">
@@ -970,7 +970,7 @@ export default function SandboxDemo() {
onChange={(e) => setShowMsciBenchmark(e.target.checked)} onChange={(e) => setShowMsciBenchmark(e.target.checked)}
className="rounded border-slate-800 text-emerald-500 focus:ring-0 accent-emerald-500 w-4 h-4" className="rounded border-slate-800 text-emerald-500 focus:ring-0 accent-emerald-500 w-4 h-4"
/> />
<span>MSCI World (Benchmark) anzeigen</span> <span>Show MSCI World (Benchmark)</span>
</label> </label>
</div> </div>
</div> </div>
@@ -985,7 +985,7 @@ export default function SandboxDemo() {
<Legend verticalAlign="top" height={36} /> <Legend verticalAlign="top" height={36} />
<Line type="monotone" dataKey="Portfolio" name={activePortfolio.name} stroke="#10b981" strokeWidth={3} dot={false} activeDot={{ r: 6 }} /> <Line type="monotone" dataKey="Portfolio" name={activePortfolio.name} stroke="#10b981" strokeWidth={3} dot={false} activeDot={{ r: 6 }} />
{showMsciBenchmark && ( {showMsciBenchmark && (
<Line type="monotone" dataKey="MSCI World (Benchmark)" name="MSCI World Index (Normiert)" stroke="#3b82f6" strokeWidth={2} strokeDasharray="4 4" dot={false} /> <Line type="monotone" dataKey="MSCI World (Benchmark)" name="MSCI World Index (Normalized)" stroke="#3b82f6" strokeWidth={2} strokeDasharray="4 4" dot={false} />
)} )}
</LineChart> </LineChart>
</ResponsiveContainer> </ResponsiveContainer>
@@ -994,8 +994,8 @@ export default function SandboxDemo() {
{/* EWMA parameter tuner slider */} {/* EWMA parameter tuner slider */}
<div className="p-4 rounded-xl border border-slate-850 bg-slate-950/20 flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4"> <div className="p-4 rounded-xl border border-slate-850 bg-slate-950/20 flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4">
<div className="space-y-1"> <div className="space-y-1">
<h4 className="text-sm font-semibold text-slate-200">Parameteranpassung EWMA Lambda (&lambda;)</h4> <h4 className="text-sm font-semibold text-slate-200">Parameter Tuning EWMA Lambda (&lambda;)</h4>
<p className="text-xs text-slate-400">Zerfallsfaktor steuert die Schock-Sensitivität des Volatilitätsmodells.</p> <p className="text-xs text-slate-400">Decay factor controls the shock sensitivity of the volatility model.</p>
</div> </div>
<div className="flex items-center gap-4 w-full sm:w-auto"> <div className="flex items-center gap-4 w-full sm:w-auto">
<input <input
@@ -1017,7 +1017,7 @@ export default function SandboxDemo() {
<div className="space-y-6"> <div className="space-y-6">
<div className="border-b border-slate-800 pb-3"> <div className="border-b border-slate-800 pb-3">
<h3 className="text-lg font-bold text-white flex items-center gap-2"> <h3 className="text-lg font-bold text-white flex items-center gap-2">
<Settings className="text-emerald-400 w-5 h-5" /> Order-Maske (Simuliert) <Settings className="text-emerald-400 w-5 h-5" /> Order Mask (Simulated)
</h3> </h3>
</div> </div>
@@ -1045,7 +1045,7 @@ export default function SandboxDemo() {
/> />
</div> </div>
<div> <div>
<label className="text-xs text-slate-400 block mb-1">Stücke</label> <label className="text-xs text-slate-400 block mb-1">Shares</label>
<input <input
type="number" type="number"
required required
@@ -1055,7 +1055,7 @@ export default function SandboxDemo() {
/> />
</div> </div>
<div> <div>
<label className="text-xs text-slate-400 block mb-1">Kurs ($)</label> <label className="text-xs text-slate-400 block mb-1">Price ($)</label>
<input <input
type="number" type="number"
required required
@@ -1073,14 +1073,14 @@ export default function SandboxDemo() {
onClick={() => setTradeType('BUY')} onClick={() => setTradeType('BUY')}
className={`flex-1 py-1.5 text-xs font-bold rounded-lg transition-all ${tradeType === 'BUY' ? 'bg-emerald-500 text-slate-950 shadow-md shadow-emerald-500/10' : 'text-slate-400 hover:text-slate-200'}`} className={`flex-1 py-1.5 text-xs font-bold rounded-lg transition-all ${tradeType === 'BUY' ? 'bg-emerald-500 text-slate-950 shadow-md shadow-emerald-500/10' : 'text-slate-400 hover:text-slate-200'}`}
> >
Kauf (Long) Buy (Long)
</button> </button>
<button <button
type="button" type="button"
onClick={() => setTradeType('SELL')} onClick={() => setTradeType('SELL')}
className={`flex-1 py-1.5 text-xs font-bold rounded-lg transition-all ${tradeType === 'SELL' ? 'bg-rose-500 text-white shadow-md shadow-rose-500/10' : 'text-slate-400 hover:text-slate-200'}`} className={`flex-1 py-1.5 text-xs font-bold rounded-lg transition-all ${tradeType === 'SELL' ? 'bg-rose-500 text-white shadow-md shadow-rose-500/10' : 'text-slate-400 hover:text-slate-200'}`}
> >
Verkauf (Short) Sell (Short)
</button> </button>
</div> </div>
@@ -1102,15 +1102,15 @@ export default function SandboxDemo() {
onChange={(e) => setKellySource(e.target.value as any)} onChange={(e) => setKellySource(e.target.value as any)}
className="w-full bg-slate-900 border border-slate-800 rounded px-1.5 py-1 text-[10px] text-slate-200 focus:outline-none" className="w-full bg-slate-900 border border-slate-800 rounded px-1.5 py-1 text-[10px] text-slate-200 focus:outline-none"
> >
<option value="custom">Manueller Regler</option> <option value="custom">Manual Slider</option>
<option value="scanner">El. 2 Scanner-Score</option> <option value="scanner">Level 2 Scanner Score</option>
<option value="crypto">El. 4 Bayes Posterior</option> <option value="crypto">Level 4 Bayes Posterior</option>
<option value="econometric">El. 5 ROC Breakout</option> <option value="econometric">Level 5 ROC Breakout</option>
</select> </select>
</div> </div>
<div> <div>
<label className="text-[9px] text-slate-500 block mb-0.5 font-semibold uppercase">Odds-Verhältnis (b)</label> <label className="text-[9px] text-slate-500 block mb-0.5 font-semibold uppercase">Odds Ratio (b)</label>
<input <input
type="number" type="number"
step="0.1" step="0.1"
@@ -1125,7 +1125,7 @@ export default function SandboxDemo() {
{kellySource === 'custom' && ( {kellySource === 'custom' && (
<div className="space-y-1"> <div className="space-y-1">
<div className="flex justify-between text-[9px] text-slate-500"> <div className="flex justify-between text-[9px] text-slate-500">
<span>Erfolgswahrscheinlichkeit:</span> <span>Probability of Success:</span>
<span className="font-mono text-emerald-400 font-bold">{(kellyProbability * 100).toFixed(0)}%</span> <span className="font-mono text-emerald-400 font-bold">{(kellyProbability * 100).toFixed(0)}%</span>
</div> </div>
<input <input
@@ -1142,7 +1142,7 @@ export default function SandboxDemo() {
{kellySource !== 'custom' && ( {kellySource !== 'custom' && (
<div className="text-[9px] text-slate-400 flex justify-between bg-slate-900/40 p-1 px-1.5 rounded border border-slate-900"> <div className="text-[9px] text-slate-400 flex justify-between bg-slate-900/40 p-1 px-1.5 rounded border border-slate-900">
<span>System-Wahrscheinlichkeit:</span> <span>System Probability:</span>
<span className="font-mono text-emerald-400 font-bold">{(kellyProbability * 100).toFixed(1)}%</span> <span className="font-mono text-emerald-400 font-bold">{(kellyProbability * 100).toFixed(1)}%</span>
</div> </div>
)} )}
@@ -1151,18 +1151,18 @@ export default function SandboxDemo() {
<div className="p-2 bg-rose-500/10 text-rose-400 border border-rose-500/20 text-[9px] rounded flex items-start gap-1"> <div className="p-2 bg-rose-500/10 text-rose-400 border border-rose-500/20 text-[9px] rounded flex items-start gap-1">
<AlertCircle className="w-3.5 h-3.5 shrink-0 text-rose-400" /> <AlertCircle className="w-3.5 h-3.5 shrink-0 text-rose-400" />
<div> <div>
<strong>Klumpenrisiko!</strong> Korrelation &gt; 0.70 zu bestehenden Positionen. Kelly-Empfehlung wurde um 50% halbiert. <strong>Concentration Risk!</strong> Correlation &gt; 0.70 to existing positions. Kelly recommendation halved by 50%.
</div> </div>
</div> </div>
)} )}
<div className="bg-slate-900/80 p-2 rounded-lg border border-slate-850 flex justify-between items-center text-xs"> <div className="bg-slate-900/80 p-2 rounded-lg border border-slate-850 flex justify-between items-center text-xs">
<div> <div>
<span className="block text-[9px] text-slate-500 uppercase font-semibold">Kelly-Anteil:</span> <span className="block text-[9px] text-slate-500 uppercase font-semibold">Kelly Fraction:</span>
<span className="font-mono font-bold text-slate-200">{(kellyFraction * 100).toFixed(1)}% des Cashs</span> <span className="font-mono font-bold text-slate-200">{(kellyFraction * 100).toFixed(1)}% of Cash</span>
</div> </div>
<div className="text-right"> <div className="text-right">
<span className="block text-[9px] text-slate-500 uppercase font-semibold">Kaufvolumen:</span> <span className="block text-[9px] text-slate-500 uppercase font-semibold">Buy Volume:</span>
<span className="font-mono font-bold text-emerald-400">${Math.round(recommendedKellyCash).toLocaleString()}</span> <span className="font-mono font-bold text-emerald-400">${Math.round(recommendedKellyCash).toLocaleString()}</span>
</div> </div>
</div> </div>
@@ -1173,11 +1173,11 @@ export default function SandboxDemo() {
<div> <div>
<label className="text-xs text-slate-400 block mb-1 flex items-center gap-1"> <label className="text-xs text-slate-400 block mb-1 flex items-center gap-1">
<Tag className="w-3 h-3 text-emerald-400" /> <Tag className="w-3 h-3 text-emerald-400" />
<span>Hypothese / What-if Notiz</span> <span>Hypothesis / What-if Note</span>
</label> </label>
<input <input
type="text" type="text"
placeholder="z.B. Ferrari E-Auto Skepsis" placeholder="e.g., Ferrari EV Skepticism"
className="w-full bg-slate-950 border border-slate-800 rounded-lg p-2 text-slate-100 text-xs focus:outline-none focus:border-emerald-500" className="w-full bg-slate-950 border border-slate-800 rounded-lg p-2 text-slate-100 text-xs focus:outline-none focus:border-emerald-500"
value={hypothesisTag} value={hypothesisTag}
onChange={(e) => setHypothesisTag(e.target.value)} onChange={(e) => setHypothesisTag(e.target.value)}
@@ -1187,7 +1187,7 @@ export default function SandboxDemo() {
{/* Fees Toggle */} {/* Fees Toggle */}
<div className="flex items-center justify-between border-t border-slate-850 pt-3 text-xs"> <div className="flex items-center justify-between border-t border-slate-850 pt-3 text-xs">
<span className="text-slate-400 flex items-center gap-1"> <span className="text-slate-400 flex items-center gap-1">
<DollarSign className="w-3.5 h-3.5 text-slate-500" /> Ordergebühren simulieren <DollarSign className="w-3.5 h-3.5 text-slate-500" /> Simulate transaction fees
</span> </span>
<input <input
type="checkbox" type="checkbox"
@@ -1201,7 +1201,7 @@ export default function SandboxDemo() {
<div className="space-y-2 border-t border-slate-850 pt-3 text-xs"> <div className="space-y-2 border-t border-slate-850 pt-3 text-xs">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<span className="text-slate-400 flex items-center gap-1"> <span className="text-slate-400 flex items-center gap-1">
<Calendar className="w-3.5 h-3.5 text-slate-500" /> Historischer Backfill <Calendar className="w-3.5 h-3.5 text-slate-500" /> Historical Backfill
</span> </span>
<input <input
type="checkbox" type="checkbox"
@@ -1231,7 +1231,7 @@ export default function SandboxDemo() {
{orderSuccess && ( {orderSuccess && (
<div className="p-3 rounded-lg bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 text-xs flex items-center gap-2"> <div className="p-3 rounded-lg bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 text-xs flex items-center gap-2">
<Check className="w-4 h-4 shrink-0" /> <Check className="w-4 h-4 shrink-0" />
<span>Transaktion erfolgreich gebucht!</span> <span>Transaction successfully recorded!</span>
</div> </div>
)} )}
@@ -1239,7 +1239,7 @@ export default function SandboxDemo() {
type="submit" type="submit"
className={`w-full font-bold py-2.5 px-4 rounded-lg transition-all active:scale-[0.98] mt-2 shadow-lg ${tradeType === 'BUY' ? 'bg-gradient-to-r from-emerald-500 to-teal-500 hover:from-emerald-600 hover:to-teal-600 text-slate-950 shadow-emerald-500/10' : 'bg-gradient-to-r from-rose-500 to-pink-500 hover:from-rose-600 hover:to-pink-600 text-white shadow-rose-500/10'}`} className={`w-full font-bold py-2.5 px-4 rounded-lg transition-all active:scale-[0.98] mt-2 shadow-lg ${tradeType === 'BUY' ? 'bg-gradient-to-r from-emerald-500 to-teal-500 hover:from-emerald-600 hover:to-teal-600 text-slate-950 shadow-emerald-500/10' : 'bg-gradient-to-r from-rose-500 to-pink-500 hover:from-rose-600 hover:to-pink-600 text-white shadow-rose-500/10'}`}
> >
Order an den Markt senden Submit Order to Market
</button> </button>
</form> </form>
</div> </div>
@@ -1254,10 +1254,10 @@ export default function SandboxDemo() {
<div className="xl:col-span-2 bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-6 text-slate-100 shadow-xl space-y-4"> <div className="xl:col-span-2 bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-6 text-slate-100 shadow-xl space-y-4">
<div className="flex justify-between items-center border-b border-slate-800 pb-3"> <div className="flex justify-between items-center border-b border-slate-800 pb-3">
<h3 className="text-lg font-bold text-white flex items-center gap-2"> <h3 className="text-lg font-bold text-white flex items-center gap-2">
<TrendingUp className="text-emerald-400 w-5 h-5" /> Depotbestände ({activePortfolio.holdings.length}) <TrendingUp className="text-emerald-400 w-5 h-5" /> Portfolio Holdings ({activePortfolio.holdings.length})
</h3> </h3>
<div className="text-xs text-slate-400 flex items-center gap-4"> <div className="text-xs text-slate-400 flex items-center gap-4">
<span>Barguthaben: <span className="font-mono text-emerald-400 font-bold">${activePortfolio.cash.toLocaleString()}</span></span> <span>Cash Balance: <span className="font-mono text-emerald-400 font-bold">${activePortfolio.cash.toLocaleString()}</span></span>
</div> </div>
</div> </div>
@@ -1266,18 +1266,18 @@ export default function SandboxDemo() {
<thead> <thead>
<tr className="border-b border-slate-800 text-slate-400 font-semibold bg-slate-900/40"> <tr className="border-b border-slate-800 text-slate-400 font-semibold bg-slate-900/40">
<th className="p-3">Asset</th> <th className="p-3">Asset</th>
<th className="p-3">Stücke</th> <th className="p-3">Shares</th>
<th className="p-3">Einstand</th> <th className="p-3">Avg Price</th>
<th className="p-3">Kurs</th> <th className="p-3">Price</th>
<th className="p-3">Hypothese</th> <th className="p-3">Hypothesis</th>
<th className="p-3 text-right">GuV</th> <th className="p-3 text-right">PnL</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{activePortfolio.holdings.length === 0 ? ( {activePortfolio.holdings.length === 0 ? (
<tr> <tr>
<td colSpan={6} className="p-8 text-center text-slate-500"> <td colSpan={6} className="p-8 text-center text-slate-500">
Keine Bestände in diesem Sandbox-Portfolio. Nutzen Sie die Order-Maske, um Werte hinzuzufügen. No holdings in this Sandbox portfolio. Use the order mask to add assets.
</td> </td>
</tr> </tr>
) : ( ) : (
@@ -1313,13 +1313,13 @@ export default function SandboxDemo() {
<div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-6 text-slate-100 shadow-xl space-y-4"> <div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-6 text-slate-100 shadow-xl space-y-4">
<div className="border-b border-slate-800 pb-3"> <div className="border-b border-slate-800 pb-3">
<h3 className="text-lg font-bold text-white flex items-center gap-2"> <h3 className="text-lg font-bold text-white flex items-center gap-2">
<Calendar className="text-emerald-400 w-5 h-5" /> Letzte Orderbuch-Einträge <Calendar className="text-emerald-400 w-5 h-5" /> Recent Order Book Entries
</h3> </h3>
</div> </div>
<div className="max-h-60 overflow-y-auto space-y-2 pr-1"> <div className="max-h-60 overflow-y-auto space-y-2 pr-1">
{activePortfolio.transactions.length === 0 ? ( {activePortfolio.transactions.length === 0 ? (
<p className="text-xs text-slate-500 text-center py-8">Bislang keine Transaktionen in diesem Portfolio.</p> <p className="text-xs text-slate-500 text-center py-8">No transactions in this portfolio yet.</p>
) : ( ) : (
activePortfolio.transactions.map((tx) => { activePortfolio.transactions.map((tx) => {
const isBuy = tx.type === 'BUY'; const isBuy = tx.type === 'BUY';
@@ -1328,7 +1328,7 @@ export default function SandboxDemo() {
<div className="flex justify-between items-start"> <div className="flex justify-between items-start">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className={`px-1.5 py-0.5 rounded text-[9px] font-bold ${isBuy ? 'bg-emerald-500/10 text-emerald-400 border border-emerald-500/20' : 'bg-rose-500/10 text-rose-400 border border-rose-500/20'}`}> <span className={`px-1.5 py-0.5 rounded text-[9px] font-bold ${isBuy ? 'bg-emerald-500/10 text-emerald-400 border border-emerald-500/20' : 'bg-rose-500/10 text-rose-400 border border-rose-500/20'}`}>
{isBuy ? 'KAUF' : 'VERKAUF'} {isBuy ? 'BUY' : 'SELL'}
</span> </span>
<span className="font-mono font-bold text-slate-200">{tx.symbol}</span> <span className="font-mono font-bold text-slate-200">{tx.symbol}</span>
</div> </div>
@@ -1336,8 +1336,8 @@ export default function SandboxDemo() {
</div> </div>
<div className="flex justify-between text-xs font-mono text-slate-400"> <div className="flex justify-between text-xs font-mono text-slate-400">
<span>{tx.shares} Stk @ ${tx.price.toFixed(2)}</span> <span>{tx.shares} shares @ ${tx.price.toFixed(2)}</span>
<span className="text-[10px] text-slate-500">Gebühr: ${tx.feeApplied.toFixed(2)}</span> <span className="text-[10px] text-slate-500">Fee: ${tx.feeApplied.toFixed(2)}</span>
</div> </div>
{tx.hypothesisTag && ( {tx.hypothesisTag && (
@@ -1355,7 +1355,7 @@ export default function SandboxDemo() {
</div> </div>
<PortfolioMathModal isOpen={isMathModalOpen} onClose={() => setIsMathModalOpen(false)} /> <SandboxMathModal isOpen={isMathModalOpen} onClose={() => setIsMathModalOpen(false)} />
</div> </div>
); );
} }

View File

@@ -0,0 +1,135 @@
import React from 'react';
import { BookOpen, X, TrendingUp, BarChart2, ShieldAlert } from 'lucide-react';
import 'katex/dist/katex.min.css';
import { BlockMath, InlineMath } from 'react-katex';
interface SandboxMathModalProps {
isOpen: boolean;
onClose: () => void;
}
export default function SandboxMathModal({ isOpen, onClose }: SandboxMathModalProps) {
React.useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
onClose();
}
};
if (isOpen) {
window.addEventListener('keydown', handleKeyDown);
}
return () => {
window.removeEventListener('keydown', handleKeyDown);
};
}, [isOpen, onClose]);
if (!isOpen) return null;
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-slate-955/90 backdrop-blur-md p-4 sm:p-6 md:p-8">
<div className="bg-slate-900 border border-slate-800/80 rounded-3xl w-full max-w-4xl h-[80vh] flex flex-col overflow-hidden shadow-2xl relative text-slate-350">
{/* Modal Header */}
<div className="flex justify-between items-center px-6 py-4 bg-slate-950/50 border-b border-slate-800/80">
<div>
<h2 className="text-base font-bold bg-gradient-to-r from-teal-400 to-emerald-400 bg-clip-text text-transparent flex items-center gap-2">
<BookOpen className="w-5 h-5 text-teal-400" /> Portfolio Sandbox - Math & Sizing Handbook
</h2>
<p className="text-[10px] text-slate-500 font-mono">Institutional Portfolio Construction & Allocation Spec</p>
</div>
<button
onClick={onClose}
className="text-slate-400 hover:text-slate-200 bg-slate-955/50 border border-slate-800 hover:border-slate-700 p-2 rounded-xl transition-all cursor-pointer flex items-center justify-center"
aria-label="Close modal"
>
<X className="w-4 h-4" />
</button>
</div>
{/* Modal Body */}
<div className="flex-1 overflow-y-auto p-6 sm:p-8 space-y-8 text-slate-300 scrollbar-thin">
{/* Section A: Synthetic Portfolio Model & Asset Weightings */}
<div className="space-y-3">
<h4 className="text-xs font-bold text-teal-400 uppercase tracking-wider font-mono flex items-center gap-1.5">
<TrendingUp className="w-3.5 h-3.5" /> A. Synthetic Portfolio Model & Asset Weightings
</h4>
<p className="text-xs leading-relaxed text-slate-400">
The sandbox constructs a continuous synthetic asset representing your active weight allocations and its daily return track:
</p>
<div className="bg-slate-950/40 p-4 rounded-xl border border-slate-800/60 my-2 space-y-4">
<div>
<p className="text-xs text-slate-400 mb-1">Active Percentage Weighting (<InlineMath math="w_i" />) Calculation:</p>
<BlockMath math="w_i = \\frac{\\text{Shares}_i \\times P_{\\text{current}, i}}{\\sum_{j} \\text{Shares}_j \\times P_{\\text{current}, j}}" />
</div>
<div className="border-t border-slate-850 pt-3">
<p className="text-xs text-slate-400 mb-1">Synthetic Portfolio Log Return (<InlineMath math="R_{pt}" />):</p>
<BlockMath math="R_{pt} = \\sum_{i} w_i \\times \\ln\\left(\\frac{P_{t, i}}{P_{t-1, i}}\\right)" />
</div>
</div>
</div>
{/* Section B: Linear Mixed Effects Panel Regression (LMM) */}
<div className="space-y-3">
<h4 className="text-xs font-bold text-teal-400 uppercase tracking-wider font-mono flex items-center gap-1.5">
<BarChart2 className="w-3.5 h-3.5" /> B. Linear Mixed Effects Panel Regression (LMM)
</h4>
<p className="text-xs leading-relaxed text-slate-400">
Solves the system-wide macro response model across all historical event instances <InlineMath math="j" /> using a Swamy-Arora GLS estimator:
</p>
<div className="bg-slate-950/40 p-4 rounded-xl border border-slate-800/60 my-2">
<div>
<p className="text-xs text-slate-400 mb-1">Panel Model Specification with VIX Controls:</p>
<BlockMath math="R_{ptj} = \\beta_0 + \\beta_{\\text{drift}} \\text{Pre}_t + \\beta_{\\text{impact}} \\text{Post}_t + \\beta_{\\text{VIX}} VIX_{tj} + u_j + e_{ptj}" />
<p className="text-[10px] text-slate-500 mt-2 font-mono leading-relaxed">
where:
<br />
- <InlineMath math="t \\in [-30, +30]" /> is the relative day offset from event date <InlineMath math="T_j" />.
<br />
- <InlineMath math="\\text{Pre}_t = \\mathbb{I}(t < 0)" /> and <InlineMath math="\\text{Post}_t = \\mathbb{I}(t > 0)" /> are relative phase indicators.
<br />
- <InlineMath math="VIX_{tj}" /> is the background market-wide volatility covariate.
<br />
- <InlineMath math="u_j \\sim N(0, \\sigma_u^2)" /> is the random group intercept (event instance shock).
<br />
- <InlineMath math="e_{ptj} \\sim N(0, \\sigma_e^2)" /> is the residual error.
</p>
</div>
</div>
</div>
{/* Section C: Kelly Criterion & Fractional Betting Sizing */}
<div className="space-y-3">
<h4 className="text-xs font-bold text-teal-400 uppercase tracking-wider font-mono flex items-center gap-1.5">
<ShieldAlert className="w-3.5 h-3.5" /> C. Kelly Criterion & Fractional Betting Sizing
</h4>
<p className="text-xs leading-relaxed text-slate-400">
The Kelly Criterion optimizes allocation sizing to maximize the expected value of the logarithm of wealth, balancing capital preservation with growth:
</p>
<div className="bg-slate-950/40 p-4 rounded-xl border border-slate-800/60 my-2 space-y-4">
<div>
<p className="text-xs text-slate-400 mb-1">Theoretical Kelly Fraction (<InlineMath math="f^*" />) Equation:</p>
<BlockMath math="f^* = \\frac{p \\cdot b - (1 - p)}{b}" />
<p className="text-[10px] text-slate-500 mt-2 font-mono leading-relaxed">
where:
<br />
- <InlineMath math="p" /> is the probability of a positive outcome (rebound or trade success).
<br />
- <InlineMath math="b" /> is the payout odds ratio (average win size divided by average loss size).
</p>
</div>
<div className="border-t border-slate-850 pt-3">
<p className="text-xs text-slate-400 mb-1">Fractional Kelly (Half-Kelly) Safety Buffer:</p>
<BlockMath math="f_{\\text{applied}} = \\max\\left(0, 0.5 \\times f^*\\right)" />
<p className="text-xs text-slate-400 leading-relaxed mt-2">
To mitigate estimation variance and protect against catastrophic drawdown due to model error or fat-tailed market returns, the cockpit clips the suggested sizing to a **Half-Kelly** multiplier ($0.5$).
</p>
</div>
</div>
</div>
</div>
</div>
</div>
);
}

View File

@@ -573,7 +573,7 @@ export default function ScannerDemo() {
)} )}
</h2> </h2>
<p className="text-slate-400 text-xs max-w-2xl"> <p className="text-slate-400 text-xs max-w-2xl">
Isoliert Kursstürze &gt; 5% bei relativem Gesamtmarkt-Stopp (S&P 500 driftet seitwärts oder steigt). Misst die Asymmetrie mittels GJR-GARCH, um Panik von strukturellen Risiken zu separieren. Isolates price crashes &gt; 5% under relative market stability (S&P 500 drifting sideways or rising). Measures asymmetry using GJR-GARCH to separate panic from structural risks.
</p> </p>
</div> </div>
@@ -583,7 +583,7 @@ export default function ScannerDemo() {
className="flex items-center gap-1.5 px-4 py-3 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-amber-400 justify-center" className="flex items-center gap-1.5 px-4 py-3 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-amber-400 justify-center"
> >
<BookOpen className="w-3.5 h-3.5" /> <BookOpen className="w-3.5 h-3.5" />
<span>📖 Modulerklärung</span> <span>📖 Quantitative Handbook</span>
</button> </button>
<button <button
@@ -592,7 +592,7 @@ export default function ScannerDemo() {
className="bg-gradient-to-r from-amber-500 to-orange-500 hover:from-amber-600 hover:to-orange-600 disabled:from-amber-850 disabled:to-orange-900 disabled:text-slate-400 text-slate-950 font-bold py-3 px-6 rounded-xl transition-all shadow-lg shadow-amber-500/10 flex items-center justify-center gap-2 active:scale-[0.98]" className="bg-gradient-to-r from-amber-500 to-orange-500 hover:from-amber-600 hover:to-orange-600 disabled:from-amber-850 disabled:to-orange-900 disabled:text-slate-400 text-slate-950 font-bold py-3 px-6 rounded-xl transition-all shadow-lg shadow-amber-500/10 flex items-center justify-center gap-2 active:scale-[0.98]"
> >
<RefreshCw className={`w-5 h-5 ${scanning ? 'animate-spin' : ''}`} /> <RefreshCw className={`w-5 h-5 ${scanning ? 'animate-spin' : ''}`} />
<span>{scanning ? 'Scanne Markt...' : 'Markt scannen'}</span> <span>{scanning ? 'Scanning Market...' : 'Scan Market'}</span>
</button> </button>
{scanning && ( {scanning && (
<span className="text-[10px] text-amber-400 font-mono text-center md:text-right animate-pulse">{scanProgress}</span> <span className="text-[10px] text-amber-400 font-mono text-center md:text-right animate-pulse">{scanProgress}</span>
@@ -604,11 +604,11 @@ export default function ScannerDemo() {
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 border-t border-slate-850 pt-5 mt-5"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4 border-t border-slate-850 pt-5 mt-5">
{/* Mode Toggles */} {/* Mode Toggles */}
<div className="space-y-2"> <div className="space-y-2">
<span className="text-[10px] text-slate-400 uppercase tracking-wider font-semibold block">Screener-Modus</span> <span className="text-[10px] text-slate-400 uppercase tracking-wider font-semibold block">Screener Mode</span>
<div className="flex flex-wrap gap-1.5 bg-slate-950/60 p-1 rounded-xl border border-slate-800/80 w-fit"> <div className="flex flex-wrap gap-1.5 bg-slate-950/60 p-1 rounded-xl border border-slate-800/80 w-fit">
{[ {[
{ id: 'day_crash', label: 'Day-Crashs' }, { id: 'day_crash', label: 'Day Crashes' },
{ id: 'ma_drop', label: 'MA-Drop (SMA50)' }, { id: 'ma_drop', label: 'MA Drop (SMA50)' },
{ id: '52w_dist', label: '52W-Distance' }, { id: '52w_dist', label: '52W-Distance' },
{ id: 'rsi_oversold', label: 'RSI-Oversold' } { id: 'rsi_oversold', label: 'RSI-Oversold' }
].map((m) => ( ].map((m) => (
@@ -629,7 +629,7 @@ export default function ScannerDemo() {
{/* Region Toggles */} {/* Region Toggles */}
<div className="space-y-2 md:text-right"> <div className="space-y-2 md:text-right">
<span className="text-[10px] text-slate-400 uppercase tracking-wider font-semibold block md:pr-1">Markt-Region</span> <span className="text-[10px] text-slate-400 uppercase tracking-wider font-semibold block md:pr-1">Market Region</span>
<div className="flex flex-wrap gap-1.5 bg-slate-950/60 p-1 rounded-xl border border-slate-800/80 w-fit md:ml-auto"> <div className="flex flex-wrap gap-1.5 bg-slate-950/60 p-1 rounded-xl border border-slate-800/80 w-fit md:ml-auto">
{[ {[
{ id: 'us', label: 'US Markets' }, { id: 'us', label: 'US Markets' },

View File

@@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { BookOpen } from 'lucide-react'; import { BookOpen, X } from 'lucide-react';
import 'katex/dist/katex.min.css'; import 'katex/dist/katex.min.css';
import { BlockMath, InlineMath } from 'react-katex'; import { BlockMath, InlineMath } from 'react-katex';
@@ -26,8 +26,8 @@ export default function ScannerMathModal({ isOpen, onClose }: ScannerMathModalPr
if (!isOpen) return null; if (!isOpen) return null;
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-slate-950/85 backdrop-blur-md p-4 sm:p-6 md:p-8"> <div className="fixed inset-0 z-50 flex items-center justify-center bg-slate-955/90 backdrop-blur-md p-4 sm:p-6 md:p-8">
<div className="bg-slate-900 border border-slate-800/80 rounded-3xl w-full max-w-4xl h-[80vh] flex flex-col overflow-hidden shadow-2xl relative text-slate-300"> <div className="bg-slate-900 border border-slate-800/80 rounded-3xl w-full max-w-4xl h-[80vh] flex flex-col overflow-hidden shadow-2xl relative text-slate-350">
{/* Modal Header */} {/* Modal Header */}
<div className="flex justify-between items-center px-6 py-4 bg-slate-950/40 border-b border-slate-800/60"> <div className="flex justify-between items-center px-6 py-4 bg-slate-950/40 border-b border-slate-800/60">
@@ -39,9 +39,10 @@ export default function ScannerMathModal({ isOpen, onClose }: ScannerMathModalPr
</div> </div>
<button <button
onClick={onClose} onClick={onClose}
className="text-slate-400 hover:text-slate-200 bg-slate-950/50 border border-slate-800 hover:border-slate-700 px-3 py-1.5 rounded-lg text-xs font-semibold font-mono transition-all cursor-pointer" className="text-slate-400 hover:text-slate-200 bg-slate-950/50 border border-slate-800 hover:border-slate-700 p-2 rounded-xl transition-all cursor-pointer flex items-center justify-center"
aria-label="Close modal"
> >
Schließen (ESC) <X className="w-4 h-4" />
</button> </button>
</div> </div>
@@ -59,15 +60,15 @@ export default function ScannerMathModal({ isOpen, onClose }: ScannerMathModalPr
Scans the entire corporate equity universe daily, segmenting equities into three distinct market capitalization classes to identify localized overreactions: Scans the entire corporate equity universe daily, segmenting equities into three distinct market capitalization classes to identify localized overreactions:
</p> </p>
<div className="grid grid-cols-3 gap-3 text-[11px] text-slate-400 font-mono text-center"> <div className="grid grid-cols-3 gap-3 text-[11px] text-slate-400 font-mono text-center">
<div className="bg-slate-950/40 p-3 rounded-lg border border-slate-800/50"> <div className="bg-slate-955/40 p-3 rounded-lg border border-slate-800/50">
<span className="block font-bold text-slate-300">Mega Caps</span> <span className="block font-bold text-slate-300">Mega Caps</span>
<span>&gt; $100B</span> <span>&gt; $100B</span>
</div> </div>
<div className="bg-slate-950/40 p-3 rounded-lg border border-slate-800/50"> <div className="bg-slate-955/40 p-3 rounded-lg border border-slate-800/50">
<span className="block font-bold text-slate-300">Mid Caps</span> <span className="block font-bold text-slate-300">Mid Caps</span>
<span>$10B - $100B</span> <span>$10B - $100B</span>
</div> </div>
<div className="bg-slate-950/40 p-3 rounded-lg border border-slate-800/50"> <div className="bg-slate-955/40 p-3 rounded-lg border border-slate-800/50">
<span className="block font-bold text-slate-300">Small Caps</span> <span className="block font-bold text-slate-300">Small Caps</span>
<span>&lt; $10B</span> <span>&lt; $10B</span>
</div> </div>
@@ -79,20 +80,20 @@ export default function ScannerMathModal({ isOpen, onClose }: ScannerMathModalPr
<p className="text-xs leading-relaxed text-slate-400"> <p className="text-xs leading-relaxed text-slate-400">
Calculates price distance ratios relative to support levels: Calculates price distance ratios relative to support levels:
</p> </p>
<div className="bg-slate-950/40 p-4 rounded-xl border border-slate-800/60 my-2 space-y-4"> <div className="bg-slate-955/40 p-4 rounded-xl border border-slate-800/60 my-2 space-y-4">
<div> <div>
<p className="text-xs text-slate-400 mb-1">1. 52-Week High Deviation:</p> <p className="text-xs text-slate-400 mb-1">1. 52-Week High Deviation:</p>
<BlockMath math="\Delta_{52w} = \frac{P_{\text{current}} - P_{52w\_high}}{P_{52w\_high}}" /> <BlockMath math="\\Delta_{52w} = \\frac{P_{\\text{current}} - P_{52w\\_high}}{P_{52w\\_high}}" />
</div> </div>
<div> <div>
<p className="text-xs text-slate-400 mb-1">2. 50-Day Moving Average Drop:</p> <p className="text-xs text-slate-400 mb-1">2. 50-Day Moving Average Drop:</p>
<BlockMath math="\Delta_{MA} = \frac{P_{\text{current}} - \text{MA}_{50}}{\text{MA}_{50}}" /> <BlockMath math="\\Delta_{MA} = \\frac{P_{\\text{current}} - \\text{MA}_{50}}{\\text{MA}_{50}}" />
</div> </div>
<div> <div>
<p className="text-xs text-slate-400 mb-1">3. Relative Strength Index (RSI-14) with smoothing:</p> <p className="text-xs text-slate-400 mb-1">3. Relative Strength Index (RSI-14) with smoothing:</p>
<BlockMath math="\text{RSI} = 100 - \frac{100}{1 + \text{RS}}" /> <BlockMath math="\\text{RSI} = 100 - \\frac{100}{1 + \\text{RS}}" />
<BlockMath math="\text{RS} = \frac{\text{Smoothed Gain}_t}{\text{Smoothed Loss}_t}" /> <BlockMath math="\\text{RS} = \\frac{\\text{Smoothed Gain}_t}{\\text{Smoothed Loss}_t}" />
<p className="text-[11px] text-slate-505 mt-2 font-mono"> <p className="text-[11px] text-slate-500 mt-2 font-mono">
where smoothed elements use Welles Wilder alpha = 1/14. Deep oversold signals trigger at RSI &lt; 30. where smoothed elements use Welles Wilder alpha = 1/14. Deep oversold signals trigger at RSI &lt; 30.
</p> </p>
</div> </div>
@@ -104,19 +105,19 @@ export default function ScannerMathModal({ isOpen, onClose }: ScannerMathModalPr
<p className="text-xs leading-relaxed text-slate-400"> <p className="text-xs leading-relaxed text-slate-400">
To avoid value traps, technical drop factors are coupled with valuation metrics fetched in real-time from FMP: To avoid value traps, technical drop factors are coupled with valuation metrics fetched in real-time from FMP:
</p> </p>
<div className="bg-slate-950/40 p-4 rounded-xl border border-slate-800/60 my-2 space-y-4"> <div className="bg-slate-955/40 p-4 rounded-xl border border-slate-800/60 my-2 space-y-4">
<ul className="list-disc pl-5 text-xs text-slate-400 space-y-2 font-mono"> <ul className="list-disc pl-5 text-xs text-slate-400 space-y-2 font-mono">
<li><strong>Trailing P/E (KGV)</strong>: Measures the price relative to trailing 12-month earnings.</li> <li><strong>Trailing P/E</strong>: Measures the price relative to trailing 12-month earnings.</li>
<li><strong>Price-to-Book (KBV)</strong>: Measures the asset backing relative to equity capital.</li> <li><strong>Price-to-Book</strong>: Measures the asset backing relative to equity capital.</li>
<li><strong>Dividend Yield (%)</strong>: Tangible dividend payouts to measure cash backflow support.</li> <li><strong>Dividend Yield (%)</strong>: Tangible dividend payouts to measure cash backflow support.</li>
<li><strong>PEG Ratio</strong>: Relates PE multiple to annual earnings growth: <li><strong>PEG Ratio</strong>: Relates PE multiple to annual earnings growth:
<BlockMath math="\text{PEG} = \frac{\text{PE Ratio}}{\text{Earnings Growth Rate} \times 100}" /> <BlockMath math="\\text{PEG} = \\frac{\\text{PE Ratio}}{\\text{Earnings Growth Rate} \\times 100}" />
</li> </li>
</ul> </ul>
<div className="border-t border-slate-850 pt-3"> <div className="border-t border-slate-850 pt-3">
<p className="text-xs text-slate-400 mb-1">Implicit Forward P/E calculation from PEG relationship:</p> <p className="text-xs text-slate-400 mb-1">Implicit Forward P/E calculation from PEG relationship:</p>
<BlockMath math="\text{Forward PE} = \frac{\text{Trailing PE}}{1 + g_{\text{implicit}}}" /> <BlockMath math="\\text{Forward PE} = \\frac{\\text{Trailing PE}}{1 + g_{\\text{implicit}}}" />
<BlockMath math="g_{\text{implicit}} = \frac{\text{Trailing PE}}{\text{PEG} \times 100}" /> <BlockMath math="g_{\\text{implicit}} = \\frac{\\text{Trailing PE}}{\\text{PEG} \\times 100}" />
<p className="text-[11px] text-slate-500 mt-2 font-mono"> <p className="text-[11px] text-slate-500 mt-2 font-mono">
If PEG is unavailable, a default growth rate of 10% is assumed as a conservative fallback baseline. If PEG is unavailable, a default growth rate of 10% is assumed as a conservative fallback baseline.
</p> </p>

View File

@@ -213,12 +213,12 @@ export default function AiSpecialSilo() {
{isShieldActive ? ( {isShieldActive ? (
<span className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-[10px] font-bold bg-amber-500/10 text-amber-400 border border-amber-500/20 shadow-[0_0_10px_rgba(245,158,11,0.15)] ml-2 animate-pulse"> <span className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-[10px] font-bold bg-amber-500/10 text-amber-400 border border-amber-500/20 shadow-[0_0_10px_rgba(245,158,11,0.15)] ml-2 animate-pulse">
<span className="w-1.5 h-1.5 rounded-full bg-amber-500" /> <span className="w-1.5 h-1.5 rounded-full bg-amber-500" />
DEV-ARCHIV AKTIV (0 CALLS) DEV ARCHIVE ACTIVE (0 CALLS)
</span> </span>
) : ( ) : (
<span className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-[10px] font-bold bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 shadow-[0_0_10px_rgba(16,185,129,0.15)] ml-2"> <span className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-[10px] font-bold bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 shadow-[0_0_10px_rgba(16,185,129,0.15)] ml-2">
<span className="w-1.5 h-1.5 rounded-full bg-emerald-500 animate-ping" /> <span className="w-1.5 h-1.5 rounded-full bg-emerald-500 animate-ping" />
LIVE-API ENDPUNKT (FMP CORPO) LIVE API ENDPOINT (FMP CORPO)
</span> </span>
)} )}
</h2> </h2>
@@ -233,7 +233,7 @@ export default function AiSpecialSilo() {
className="flex items-center gap-1.5 px-4 py-2.5 rounded-xl bg-slate-955/80 hover:bg-slate-900 border border-slate-800 hover:border-slate-700 transition-all font-semibold text-xs tracking-wider text-teal-400 w-full md:w-auto justify-center h-11 cursor-pointer" className="flex items-center gap-1.5 px-4 py-2.5 rounded-xl bg-slate-955/80 hover:bg-slate-900 border border-slate-800 hover:border-slate-700 transition-all font-semibold text-xs tracking-wider text-teal-400 w-full md:w-auto justify-center h-11 cursor-pointer"
> >
<BookOpen className="w-4 h-4" /> <BookOpen className="w-4 h-4" />
<span>📖 Modulerklärung</span> <span>📖 Quantitative Handbook</span>
</button> </button>
<div className="bg-slate-955/80 border border-slate-800 rounded-xl px-4 py-2 text-right shrink-0 h-11 flex flex-col justify-center"> <div className="bg-slate-955/80 border border-slate-800 rounded-xl px-4 py-2 text-right shrink-0 h-11 flex flex-col justify-center">

View File

@@ -198,21 +198,21 @@ export default function TechMathModal({ isOpen, onClose }: TechMathModalProps) {
<p className="text-xs text-slate-300 mb-2 font-semibold"> <p className="text-xs text-slate-300 mb-2 font-semibold">
{"Formula for Accruals (\\(\\text{Accruals}\\)):"} {"Formula for Accruals (\\(\\text{Accruals}\\)):"}
</p> </p>
<BlockMath math="\text{Accruals}_{t} = \text{Net Income}_{t} - (\text{CFO}_{t} + \text{CFI}_{t})" /> <BlockMath math="\\text{Accruals}_{t} = \\text{Net Income}_{t} - (\\text{CFO}_{t} + \\text{CFI}_{t})" />
<p className="text-xs text-slate-300 my-2 font-semibold"> <p className="text-xs text-slate-300 my-2 font-semibold">
{"Formula for Sloan Ratio (\\(\\text{Sloan Ratio}\\)):"} {"Formula for Sloan Ratio (\\(\\text{Sloan Ratio}\\)):"}
</p> </p>
<BlockMath math="\text{Sloan Ratio}_{t} = \frac{\text{Accruals}_{t}}{\text{Total Assets}_{t}} \times 100" /> <BlockMath math="\\text{Sloan Ratio}_{t} = \\frac{\\text{Accruals}_{t}}{\\text{Total Assets}_{t}} \\times 100" />
<p className="text-[10px] text-slate-555 mt-3 font-mono leading-relaxed"> <p className="text-[10px] text-slate-555 mt-3 font-mono leading-relaxed">
{"Where:"} {"Where:"}
<br /> <br />
{"- "}<InlineMath math="\text{Net Income}_{t}" />{" is the company's net income for the fiscal period."} {"- "}<InlineMath math="\\text{Net Income}_{t}" />{" is the company's net income for the fiscal period."}
<br /> <br />
{"- "}<InlineMath math="\text{CFO}_{t}" />{" is Cash Flow from Operations (operating cash flow)."} {"- "}<InlineMath math="\\text{CFO}_{t}" />{" is Cash Flow from Operations (operating cash flow)."}
<br /> <br />
{"- "}<InlineMath math="\text{CFI}_{t}" />{" is Cash Flow from Investing activities."} {"- "}<InlineMath math="\\text{CFI}_{t}" />{" is Cash Flow from Investing activities."}
<br /> <br />
{"- "}<InlineMath math="\text{Total Assets}_{t}" />{" is the total assets reported on the balance sheet at the end of the period."} {"- "}<InlineMath math="\\text{Total Assets}_{t}" />{" is the total assets reported on the balance sheet at the end of the period."}
</p> </p>
</div> </div>
<p className="text-xs leading-relaxed text-slate-400"> <p className="text-xs leading-relaxed text-slate-400">

View File

@@ -90,9 +90,9 @@ export default function WhaleMathModal({ isOpen, onClose }: WhaleMathModalProps)
<div className="bg-slate-955/40 p-5 rounded-2xl border border-slate-850 my-2 space-y-4"> <div className="bg-slate-955/40 p-5 rounded-2xl border border-slate-850 my-2 space-y-4">
<div> <div>
<p className="text-xs text-slate-300 mb-2 font-semibold">Velocity of Conviction (VoC) Delta:</p> <p className="text-xs text-slate-300 mb-2 font-semibold">Velocity of Conviction (VoC) Delta:</p>
<BlockMath math="\text{VoC}_{i} = w_{i, t} - w_{i, t-1}" /> <BlockMath math="\\text{VoC}_{i} = w_{i, t} - w_{i, t-1}" />
<p className="text-xs text-slate-300 my-2 font-semibold">Asset Portfolio Weight Calculation:</p> <p className="text-xs text-slate-300 my-2 font-semibold">Asset Portfolio Weight Calculation:</p>
<BlockMath math="w_{i, t} = \frac{V_{i, t}}{\sum_{j} V_{j, t}} \times 100" /> <BlockMath math="w_{i, t} = \\frac{V_{i, t}}{\\sum_{j} V_{j, t}} \\times 100" />
<p className="text-[10px] text-slate-500 mt-3 font-mono leading-relaxed"> <p className="text-[10px] text-slate-500 mt-3 font-mono leading-relaxed">
Where: Where:
<br /> <br />
@@ -102,7 +102,7 @@ export default function WhaleMathModal({ isOpen, onClose }: WhaleMathModalProps)
<br /> <br />
- <InlineMath math="V_{i, t}" /> is the market value of the position in asset \(i\) as reported in the 13F filing for quarter \(t\). - <InlineMath math="V_{i, t}" /> is the market value of the position in asset \(i\) as reported in the 13F filing for quarter \(t\).
<br /> <br />
- <InlineMath math="\sum_{j} V_{j, t}" /> represents the total market value of all reported equity holdings in the filing for quarter \(t\) (AUM proxy). - <InlineMath math="\\sum_{j} V_{j, t}" /> represents the total market value of all reported equity holdings in the filing for quarter \(t\) (AUM proxy).
</p> </p>
</div> </div>
<p className="text-xs leading-relaxed text-slate-400"> <p className="text-xs leading-relaxed text-slate-400">

View File

@@ -106,12 +106,12 @@ export default function WhaleScreener() {
{isShieldActive ? ( {isShieldActive ? (
<span className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-[10px] font-bold bg-amber-500/10 text-amber-400 border border-amber-500/20 shadow-[0_0_10px_rgba(245,158,11,0.15)] ml-2 animate-pulse"> <span className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-[10px] font-bold bg-amber-500/10 text-amber-400 border border-amber-500/20 shadow-[0_0_10px_rgba(245,158,11,0.15)] ml-2 animate-pulse">
<span className="w-1.5 h-1.5 rounded-full bg-amber-500" /> <span className="w-1.5 h-1.5 rounded-full bg-amber-500" />
DEV-ARCHIV AKTIV (0 CALLS) DEV ARCHIVE ACTIVE (0 CALLS)
</span> </span>
) : ( ) : (
<span className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-[10px] font-bold bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 shadow-[0_0_10px_rgba(16,185,129,0.15)] ml-2"> <span className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-[10px] font-bold bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 shadow-[0_0_10px_rgba(16,185,129,0.15)] ml-2">
<span className="w-1.5 h-1.5 rounded-full bg-emerald-500 animate-ping" /> <span className="w-1.5 h-1.5 rounded-full bg-emerald-500 animate-ping" />
LIVE-API ENDPUNKT (FMP CORPO) LIVE API ENDPOINT (FMP CORPO)
</span> </span>
)} )}
</h2> </h2>
@@ -123,7 +123,7 @@ export default function WhaleScreener() {
<div className="flex items-center gap-3 w-full md:w-auto justify-end"> <div className="flex items-center gap-3 w-full md:w-auto justify-end">
<button <button
onClick={() => setRefreshKey(prev => prev + 1)} onClick={() => setRefreshKey(prev => prev + 1)}
className="flex items-center justify-center p-2.5 rounded-xl bg-slate-950/80 hover:bg-slate-900 border border-slate-800 hover:border-slate-700 transition-all text-slate-400 hover:text-slate-200 h-11 w-11 cursor-pointer" className="flex items-center justify-center p-2.5 rounded-xl bg-slate-955/80 hover:bg-slate-900 border border-slate-800 hover:border-slate-700 transition-all text-slate-400 hover:text-slate-200 h-11 w-11 cursor-pointer"
title="Refresh holdings" title="Refresh holdings"
> >
<RefreshCw className="w-4 h-4" /> <RefreshCw className="w-4 h-4" />
@@ -133,7 +133,7 @@ export default function WhaleScreener() {
className="flex items-center gap-1.5 px-4 py-2.5 rounded-xl bg-slate-955/80 hover:bg-slate-900 border border-slate-800 hover:border-slate-700 transition-all font-semibold text-xs tracking-wider text-blue-400 w-full md:w-auto justify-center h-11 cursor-pointer" className="flex items-center gap-1.5 px-4 py-2.5 rounded-xl bg-slate-955/80 hover:bg-slate-900 border border-slate-800 hover:border-slate-700 transition-all font-semibold text-xs tracking-wider text-blue-400 w-full md:w-auto justify-center h-11 cursor-pointer"
> >
<BookOpen className="w-4 h-4" /> <BookOpen className="w-4 h-4" />
<span>📖 Modulerklärung</span> <span>📖 Quantitative Handbook</span>
</button> </button>
</div> </div>
</div> </div>