feat(macro): deploy Macro Indicators Vault (Phase 4) with hybrid override and sparklines
This commit is contained in:
407
components/modules/macro/MacroIndicatorsDemo.tsx
Normal file
407
components/modules/macro/MacroIndicatorsDemo.tsx
Normal file
@@ -0,0 +1,407 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState, useEffect, useMemo } from 'react';
|
||||
import { LineChart, Line, ResponsiveContainer } from 'recharts';
|
||||
import 'katex/dist/katex.min.css';
|
||||
import MacroMathModal from './MacroMathModal';
|
||||
import {
|
||||
TrendingUp, Landmark, AlertCircle, BookOpen, Percent,
|
||||
ArrowDownRight, ArrowUpRight, Minus, Activity, ShieldAlert, Coins
|
||||
} from 'lucide-react';
|
||||
|
||||
interface IndicatorDataPoint {
|
||||
date: string;
|
||||
value: number;
|
||||
}
|
||||
|
||||
interface MacroIndicator {
|
||||
name: string;
|
||||
unit: string;
|
||||
category: string;
|
||||
current: number;
|
||||
previous: number;
|
||||
trend: 'UP' | 'DOWN' | 'FLAT';
|
||||
data: IndicatorDataPoint[];
|
||||
}
|
||||
|
||||
interface MacroDataPayload {
|
||||
dates: string[];
|
||||
indicators: Record<string, MacroIndicator>;
|
||||
liveDataAvailable: boolean;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export default function MacroIndicatorsDemo() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [payload, setPayload] = useState<MacroDataPayload | null>(null);
|
||||
const [isMathModalOpen, setIsMathModalOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchIndicators = async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const response = await fetch('/api/macro/indicators');
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
setPayload(data);
|
||||
} else {
|
||||
setError('Fehler beim Abruf der makroökonomischen Indikatoren.');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Fetch macro indicators error:', err);
|
||||
setError('Netzwerkfehler beim Laden der Makroökonomischen Daten.');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchIndicators();
|
||||
}, []);
|
||||
|
||||
// Compute Fed Net Liquidity Proxy dynamically across the 24 months
|
||||
// Formula: Net Liquidity = Fed Assets (T$) - TGA (B$/1000) - RRP (B$/1000)
|
||||
const netLiquidityIndicator = useMemo(() => {
|
||||
if (!payload?.indicators?.fedBalanceSheet || !payload?.indicators?.tga || !payload?.indicators?.rrp) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fedBalance = payload.indicators.fedBalanceSheet;
|
||||
const tga = payload.indicators.tga;
|
||||
const rrp = payload.indicators.rrp;
|
||||
|
||||
const netLiquidityData: IndicatorDataPoint[] = fedBalance.data.map((point, idx) => {
|
||||
const assets = point.value;
|
||||
const tgaVal = tga.data[idx]?.value || 0;
|
||||
const rrpVal = rrp.data[idx]?.value || 0;
|
||||
// Convert B$ to T$
|
||||
const liq = assets - (tgaVal + rrpVal) / 1000;
|
||||
return {
|
||||
date: point.date,
|
||||
value: parseFloat(liq.toFixed(3))
|
||||
};
|
||||
});
|
||||
|
||||
const len = netLiquidityData.length;
|
||||
const current = netLiquidityData[len - 1].value;
|
||||
const previous = netLiquidityData[len - 2].value;
|
||||
let trend: 'UP' | 'DOWN' | 'FLAT' = 'FLAT';
|
||||
if (current > previous) trend = 'UP';
|
||||
if (current < previous) trend = 'DOWN';
|
||||
|
||||
return {
|
||||
name: 'Federal Reserve Net Liquidity Proxy',
|
||||
unit: 'T$',
|
||||
category: 'Zentralbanken & Liquidität',
|
||||
current,
|
||||
previous,
|
||||
trend,
|
||||
data: netLiquidityData
|
||||
} as MacroIndicator;
|
||||
}, [payload]);
|
||||
|
||||
if (loading) {
|
||||
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="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>
|
||||
);
|
||||
}
|
||||
|
||||
if (error || !payload) {
|
||||
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="text-rose-400 font-semibold flex items-center gap-2">
|
||||
<AlertCircle className="w-5 h-5" /> {error || 'Fehler beim Laden.'}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const indicators = payload.indicators;
|
||||
|
||||
// Helper to color trends/values based on macroeconomic threshold rules
|
||||
const getValHighlightClass = (key: string, val: number, trend: string) => {
|
||||
if (key === 'hySpread') {
|
||||
return val > 5.0 ? 'text-rose-400 font-bold animate-pulse' : 'text-slate-100';
|
||||
}
|
||||
if (key === 'yieldSpread') {
|
||||
return val < 0.0 ? 'text-rose-500 font-bold' : 'text-emerald-400';
|
||||
}
|
||||
if (key === 'cpiYoY' || key === 'coreCpi') {
|
||||
if (val <= 2.5) return 'text-emerald-400 font-semibold';
|
||||
if (val >= 3.0) return 'text-amber-400';
|
||||
}
|
||||
if (key === 'm2' && trend === 'DOWN') {
|
||||
return 'text-rose-400';
|
||||
}
|
||||
if (key === 'rrp' && val < 400) {
|
||||
return 'text-rose-400';
|
||||
}
|
||||
return 'text-slate-100';
|
||||
};
|
||||
|
||||
// Helper for trend icons
|
||||
const renderTrendIcon = (trend: 'UP' | 'DOWN' | 'FLAT', key: string) => {
|
||||
const baseClass = "w-4 h-4 inline-block align-middle";
|
||||
if (trend === 'UP') {
|
||||
const isBad = key === 'cpiYoY' || key === 'coreCpi' || key === 'ppi' || key === 'unemployment' || key === 'joblessClaims' || key === 'hySpread';
|
||||
return <ArrowUpRight className={`${baseClass} ${isBad ? 'text-rose-400' : 'text-emerald-400'}`} />;
|
||||
}
|
||||
if (trend === 'DOWN') {
|
||||
const isBad = key === 'nfp' || key === 'fedFunds' || key === 'fedBalanceSheet' || key === 'm2' || key === 'rrp' || key === 'tga';
|
||||
return <ArrowDownRight className={`${baseClass} ${isBad ? 'text-rose-400' : 'text-emerald-400'}`} />;
|
||||
}
|
||||
return <Minus className={`${baseClass} text-slate-500`} />;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
|
||||
{/* ⚠️ Dynamic Rate-Limit Override Warning Banner */}
|
||||
{!payload.liveDataAvailable && (
|
||||
<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)]">
|
||||
<AlertCircle className="w-5 h-5 text-rose-400 shrink-0" />
|
||||
<div className="flex-1">
|
||||
<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.
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* SECTION 1: Header & Control Bar */}
|
||||
<div className="bg-slate-900/60 backdrop-blur-md border border-slate-800 rounded-2xl p-6 text-slate-100 shadow-xl relative overflow-hidden">
|
||||
<div className="absolute top-0 right-0 w-32 h-32 bg-indigo-500/10 rounded-full blur-3xl -z-10" />
|
||||
|
||||
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-4">
|
||||
<div className="space-y-1">
|
||||
<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">
|
||||
<Landmark className="text-indigo-400 w-6 h-6" /> Makroökonomische Indikatoren & Kredit-Silo
|
||||
</h2>
|
||||
<p className="text-xs text-slate-400">
|
||||
Analysiert Zyklen, Liquiditätsflüsse und Zinskurven über die letzten 24 Monate.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-3 w-full md:w-auto justify-end">
|
||||
<button
|
||||
onClick={() => setIsMathModalOpen(true)}
|
||||
className="flex items-center gap-1.5 px-4 py-2.5 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-indigo-400 w-full md:w-auto justify-center h-11 cursor-pointer"
|
||||
>
|
||||
<BookOpen className="w-4 h-4" />
|
||||
<span>📖 Modulerklärung</span>
|
||||
</button>
|
||||
|
||||
<div className="bg-slate-950/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-500 uppercase font-mono">Letztes Update</div>
|
||||
<div className="font-mono text-xs text-slate-300">
|
||||
{new Date(payload.timestamp).toLocaleTimeString()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* SECTION 2: Economic Data 3-Grid Panels */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
|
||||
{/* PANEL 1: Inflation & Wachstum */}
|
||||
<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">
|
||||
<h3 className="font-bold text-sm text-white flex items-center gap-2">
|
||||
<Activity className="w-4 h-4 text-emerald-400" /> Inflation & Wachstum
|
||||
</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>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
{Object.entries(indicators)
|
||||
.filter(([_, ind]) => ind.category === 'Inflation & Wachstum')
|
||||
.map(([key, ind]) => (
|
||||
<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="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}{ind.unit}</div>
|
||||
</div>
|
||||
|
||||
{/* Micro Recharts Sparkline */}
|
||||
<div className="w-20 h-8">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<LineChart data={ind.data}>
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey="value"
|
||||
stroke={ind.trend === 'UP' ? '#f43f5e' : '#10b981'}
|
||||
strokeWidth={1.5}
|
||||
dot={false}
|
||||
/>
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
|
||||
<div className="text-right">
|
||||
<div className={`font-mono text-sm font-bold ${getValHighlightClass(key, ind.current, ind.trend)}`}>
|
||||
{ind.current}{ind.unit}
|
||||
</div>
|
||||
<div className="text-[9px] flex items-center justify-end gap-0.5">
|
||||
{renderTrendIcon(ind.trend, key)}
|
||||
<span className="text-slate-500 font-mono capitalize">{ind.trend.toLowerCase()}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* PANEL 2: Zentralbanken & Liquidität */}
|
||||
<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">
|
||||
<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
|
||||
</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>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
{/* Fed Funds, ECB Refi, Fed Assets, M2, RRP, TGA */}
|
||||
{Object.entries(indicators)
|
||||
.filter(([_, ind]) => ind.category === 'Zentralbanken & Liquidität')
|
||||
.map(([key, ind]) => (
|
||||
<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="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}{ind.unit}</div>
|
||||
</div>
|
||||
|
||||
{/* Micro Recharts Sparkline */}
|
||||
<div className="w-20 h-8">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<LineChart data={ind.data}>
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey="value"
|
||||
stroke={key === 'rrp' || key === 'fedBalanceSheet' ? '#f43f5e' : '#10b981'}
|
||||
strokeWidth={1.5}
|
||||
dot={false}
|
||||
/>
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
|
||||
<div className="text-right">
|
||||
<div className={`font-mono text-sm font-bold ${getValHighlightClass(key, ind.current, ind.trend)}`}>
|
||||
{ind.current}{ind.unit}
|
||||
</div>
|
||||
<div className="text-[9px] flex items-center justify-end gap-0.5">
|
||||
{renderTrendIcon(ind.trend, key)}
|
||||
<span className="text-slate-500 font-mono capitalize">{ind.trend.toLowerCase()}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{/* Dynamic Calculated Net Liquidity Proxy Row */}
|
||||
{netLiquidityIndicator && (
|
||||
<div className="bg-indigo-950/20 border border-indigo-900/50 rounded-xl p-3 flex justify-between items-center hover:bg-indigo-950/30 transition-colors">
|
||||
<div className="space-y-0.5 max-w-[130px]">
|
||||
<div className="text-xs font-bold text-indigo-300 truncate" title={netLiquidityIndicator.name}>
|
||||
Net Fed Liquidity
|
||||
</div>
|
||||
<div className="text-[9px] text-indigo-400/70 font-mono">Vorherig: {netLiquidityIndicator.previous}{netLiquidityIndicator.unit}</div>
|
||||
</div>
|
||||
|
||||
{/* Micro Recharts Sparkline */}
|
||||
<div className="w-20 h-8">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<LineChart data={netLiquidityIndicator.data}>
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey="value"
|
||||
stroke="#818cf8"
|
||||
strokeWidth={2}
|
||||
dot={false}
|
||||
/>
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
|
||||
<div className="text-right">
|
||||
<div className="font-mono text-sm font-extrabold text-indigo-300">
|
||||
{netLiquidityIndicator.current}{netLiquidityIndicator.unit}
|
||||
</div>
|
||||
<div className="text-[9px] flex items-center justify-end gap-0.5">
|
||||
{renderTrendIcon(netLiquidityIndicator.trend, 'netLiquidity')}
|
||||
<span className="text-indigo-400 font-mono capitalize">{netLiquidityIndicator.trend.toLowerCase()}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* PANEL 3: Kredit- & Anleihemarkt */}
|
||||
<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">
|
||||
<h3 className="font-bold text-sm text-white flex items-center gap-2">
|
||||
<ShieldAlert className="w-4 h-4 text-rose-400" /> Kredit- & Anleihemarkt
|
||||
</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>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
{Object.entries(indicators)
|
||||
.filter(([_, ind]) => ind.category === 'Kredit- & Anleihemarkt')
|
||||
.map(([key, ind]) => (
|
||||
<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="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}{ind.unit}</div>
|
||||
</div>
|
||||
|
||||
{/* Micro Recharts Sparkline */}
|
||||
<div className="w-20 h-8">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<LineChart data={ind.data}>
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey="value"
|
||||
stroke={key === 'yieldSpread' && ind.current < 0 ? '#f43f5e' : '#10b981'}
|
||||
strokeWidth={1.5}
|
||||
dot={false}
|
||||
/>
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
|
||||
<div className="text-right">
|
||||
<div className={`font-mono text-sm font-bold ${getValHighlightClass(key, ind.current, ind.trend)}`}>
|
||||
{ind.current}{ind.unit}
|
||||
</div>
|
||||
<div className="text-[9px] flex items-center justify-end gap-0.5">
|
||||
{renderTrendIcon(ind.trend, key)}
|
||||
<span className="text-slate-500 font-mono capitalize">{ind.trend.toLowerCase()}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* 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">
|
||||
<h3 className="font-bold text-sm text-slate-200">Systemische Macro- & Kreditmarkt-Analyse</h3>
|
||||
<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 un-invertiert die Kurve (<span className="text-emerald-400 font-bold font-mono">+{indicators.yieldSpread?.current.toFixed(2)}%</span>), was oft kurz vor oder während einer konjunkturellen Anpassungsphase auftritt. Gleichzeitig zeigt der Kreditmarkt mit einem High-Yield Credit Spread von <span className="text-slate-300 font-bold font-mono">{indicators.hySpread?.current}%</span> ein ruhiges, risikoarmes Bild.
|
||||
Monetäre Liquidität (<span className="font-bold text-indigo-300 font-mono">Net Fed Liquidity Proxy: {netLiquidityIndicator?.current} 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 für Risk Assets).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<MacroMathModal isOpen={isMathModalOpen} onClose={() => setIsMathModalOpen(false)} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
128
components/modules/macro/MacroMathModal.tsx
Normal file
128
components/modules/macro/MacroMathModal.tsx
Normal file
@@ -0,0 +1,128 @@
|
||||
import React from 'react';
|
||||
import { BookOpen } from 'lucide-react';
|
||||
import 'katex/dist/katex.min.css';
|
||||
import { BlockMath, InlineMath } from 'react-katex';
|
||||
|
||||
interface MacroMathModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export default function MacroMathModal({ isOpen, onClose }: MacroMathModalProps) {
|
||||
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-purple-400 to-indigo-400 bg-clip-text text-transparent flex items-center gap-2">
|
||||
<BookOpen className="w-5 h-5 text-purple-400" /> Macroeconomics & Liquidity - 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">6. Macroeconomic Indicators & Credit Vault</h3>
|
||||
<p className="text-xs text-slate-400 mt-1">Details structural curves, monetary flows, and historical surprise indices.</p>
|
||||
</div>
|
||||
|
||||
{/* Section A: Yield Curve */}
|
||||
<div className="space-y-3">
|
||||
<h4 className="text-xs font-bold text-purple-400 uppercase tracking-wider font-mono">A. Yield Curve Spread Inversion Dynamics</h4>
|
||||
<p className="text-xs leading-relaxed text-slate-400">
|
||||
Calculates the duration spread between short-term and long-term government yield rates. A negative spread represents structural inversion, often preceding a recession:
|
||||
</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">2S10S Yield Curve Spread:</p>
|
||||
<BlockMath math="\\text{Spread}_{2S10S} = Y_{10Y} - Y_{2Y}" />
|
||||
<p className="text-[10px] text-slate-550 mt-2 font-mono leading-relaxed">
|
||||
where:
|
||||
<br />
|
||||
- <InlineMath math="Y_{10Y}" /> is the yield rate of the 10-Year Treasury Bond.
|
||||
<br />
|
||||
- <InlineMath math="Y_{2Y}" /> is the yield rate of the 2-Year Treasury Bond.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Section B: Surprise Index */}
|
||||
<div className="space-y-3">
|
||||
<h4 className="text-xs font-bold text-purple-400 uppercase tracking-wider font-mono">B. Surprise Index Standardized Deviation</h4>
|
||||
<p className="text-xs leading-relaxed text-slate-400">
|
||||
Measures how far an economic release deviates from general consensus expectations, scaled by the historical standard deviation of surprises:
|
||||
</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">Standardized Surprise Score:</p>
|
||||
<BlockMath math="\\text{Surprise}_t = \\frac{\\text{Actual}_t - \\text{Consensus}_t}{\\sigma_{\\text{surprise}}}" />
|
||||
<p className="text-[10px] text-slate-550 mt-2 font-mono leading-relaxed">
|
||||
where:
|
||||
<br />
|
||||
- <InlineMath math="\\text{Actual}_t" /> is the released value for the economic indicator.
|
||||
<br />
|
||||
- <InlineMath math="\\text{Consensus}_t" /> is the median consensus forecast.
|
||||
<br />
|
||||
- <InlineMath math="\\sigma_{\\text{surprise}}" /> is the historical standard deviation of forecast errors.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Section C: Net Liquidity */}
|
||||
<div className="space-y-3">
|
||||
<h4 className="text-xs font-bold text-purple-400 uppercase tracking-wider font-mono">C. Central Bank Net Liquidity Proxy</h4>
|
||||
<p className="text-xs leading-relaxed text-slate-400">
|
||||
Calculates the net USD liquidity circulating in the financial system by subtracting treasury reserves and central bank operations:
|
||||
</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">Federal Reserve Net Liquidity Equation:</p>
|
||||
<BlockMath math="\\text{Net Liquidity}_t = A_{\\text{Fed}, t} - \\text{TGA}_t - \\text{RRP}_t" />
|
||||
<p className="text-[10px] text-slate-550 mt-2 font-mono leading-relaxed">
|
||||
where:
|
||||
<br />
|
||||
- <InlineMath math="A_{\\text{Fed}, t}" /> is the total Federal Reserve assets (balance sheet volume).
|
||||
<br />
|
||||
- <InlineMath math="\\text{TGA}_t" /> is the Treasury General Account balance at the Fed.
|
||||
<br />
|
||||
- <InlineMath math="\\text{RRP}_t" /> is the Reverse Repo facility usage volume.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user