'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, ChevronDown, ChevronUp } 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; liveDataAvailable: boolean; timestamp: number; } export default function MacroIndicatorsDemo() { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [payload, setPayload] = useState(null); const [isMathModalOpen, setIsMathModalOpen] = useState(false); const [isAccordionOpen, setIsAccordionOpen] = useState(false); // Collapsible accordion closed by default 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 (
Lade makroökonomisches Datenarchiv...
); } if (error || !payload) { return (
{error || 'Fehler beim Laden.'}
); } const indicators = payload.indicators; // Safe destructuring of all 21 indicators to guarantee no undefined layout shifts const { cpiYoY, coreCpi, ppi, savingsRate, ccDelinquency, nfp, unemployment, joblessClaims, fedFunds, ecbRefi, fedBalanceSheet, m2, rrp, tga, buffett, us10y, yieldSpread, hySpread, housingStarts, mortgageApps, caseShiller } = indicators; // Compute Ampel (traffic light) health states const getCard1Status = () => { const cpiVal = cpiYoY?.current ?? 0; const ccVal = ccDelinquency?.current ?? 0; const saveVal = savingsRate?.current ?? 5; if (cpiVal >= 3.0 || ccVal > 4.5 || saveVal < 3.0) return 'RED'; if (cpiVal >= 2.5 || ccVal > 3.5 || saveVal < 4.0) return 'AMBER'; return 'GREEN'; }; const getCard2Status = () => { const bufVal = buffett?.current ?? 0; const m2Trend = m2?.trend ?? 'FLAT'; if (bufVal > 150.0 || m2Trend === 'DOWN') return 'RED'; if (bufVal > 130.0 || (rrp && rrp.current < 400)) return 'AMBER'; return 'GREEN'; }; const getCard3Status = () => { const yieldVal = yieldSpread?.current ?? 0; const hyVal = hySpread?.current ?? 0; if (yieldVal < 0.0 || hyVal > 5.0) return 'RED'; if (yieldVal < 0.1 || hyVal > 4.0) return 'AMBER'; return 'GREEN'; }; const card1Status = getCard1Status(); const card2Status = getCard2Status(); const card3Status = getCard3Status(); // 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-rose-400'; } if (key === 'm2' && trend === 'DOWN') { return 'text-rose-400 font-bold animate-pulse'; } if (key === 'rrp' && val < 400) { return 'text-rose-400'; } if (key === 'buffett' && val > 150.0) { return 'text-rose-400 font-bold animate-pulse'; } if (key === 'ccDelinquency' && val > 4.5) { return 'text-rose-400 font-bold animate-pulse'; } if (key === 'savingsRate' && val < 3.0) { return 'text-rose-400 font-bold'; } 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"; const inverseIndicators = ['cpiYoY', 'coreCpi', 'ppi', 'unemployment', 'joblessClaims', 'hySpread', 'ccDelinquency', 'buffett']; const isInverse = inverseIndicators.includes(key); if (trend === 'UP') { return ; } if (trend === 'DOWN') { return ; } return ; }; // Render individual row helper const renderRow = (key: string, ind: MacroIndicator) => { if (!ind) return null; const inverseIndicators = ['cpiYoY', 'coreCpi', 'ppi', 'unemployment', 'joblessClaims', 'hySpread', 'ccDelinquency', 'buffett']; const isInverse = inverseIndicators.includes(key); const strokeColor = (ind.trend === 'UP' && isInverse) || (ind.trend === 'DOWN' && !isInverse) ? '#f43f5e' : '#10b981'; return (
{ind.name}
Vorherig: {ind.previous === null || ind.previous === undefined ? '' : ind.previous}{ind.unit}
{/* Micro Recharts Sparkline */}
{ind.current}{ind.unit}
{renderTrendIcon(ind.trend, key)} {ind.trend.toLowerCase()}
); }; return (
{/* ⚠️ Dynamic Rate-Limit Override Warning Banner */} {!payload.liveDataAvailable && (
[⚠️ API Limit - Historical Archive Active] Der Echtzeit-Datenabruf (Juni 2026) ist aufgrund von Ratenbeschränkungen (FMP HTTP 429) gedrosselt. Das System operiert im sicheren, gepufferten historischen Archiv-Modus.
)} {/* SECTION 1: Header & Control Bar */}
Macroeconomics Silo

Makroökonomische Indikatoren & Kredit-Silo

Analysiert Zyklen, Liquiditätsflüsse und Zinskurven über die letzten 24 Monate.

Letztes Update
{new Date(payload.timestamp).toLocaleTimeString()}
{/* 🏛️ SECTION 1.5: 3 Large Glowing Neon-Ampel Cards */}
{/* CARD 1: Inflation & Konsum-Stress */}
Kategorie 1

Inflation & Konsum-Stress

{/* Glowing Neon-Ampel Light */}
Risiko-Status:{' '} {card1Status === 'RED' ? '🚨 Kritischer Konsumdruck' : card1Status === 'AMBER' ? '⚠️ Erhöhtes Risiko' : '✅ Stabil'}
CPI
= 3.0 ? 'text-rose-400' : 'text-slate-200'}`}> {cpiYoY ? cpiYoY.current.toFixed(1) : '0.0'}%
Sparquote
{savingsRate ? savingsRate.current.toFixed(1) : '0.0'}%
Ausfälle
4.5 ? 'text-rose-400' : 'text-slate-200'}`}> {ccDelinquency ? ccDelinquency.current.toFixed(1) : '0.0'}%
{/* CARD 2: Bewertung & Liquidität */}
Kategorie 2

Bewertung & Liquidität

{/* Glowing Neon-Ampel Light */}
Risiko-Status:{' '} {card2Status === 'RED' ? '🚨 Extreme Überbewertung' : card2Status === 'AMBER' ? '⚠️ Liquiditäts-Engpass' : '✅ Ausreichend'}
Buffett Indicator
150.0 ? 'text-rose-400' : 'text-slate-200'}`}> {buffett ? buffett.current.toFixed(1) : '0.0'}%
Net Fed Liquidity
{netLiquidityIndicator ? netLiquidityIndicator.current.toFixed(2) : '0.0'} T$
{/* CARD 3: Kredit- & Rezessionsrisiko */}
Kategorie 3

Kredit- & Rezessionsrisiko

{/* Glowing Neon-Ampel Light */}
Risiko-Status:{' '} {card3Status === 'RED' ? '🚨 Rezessions-Inversion' : card3Status === 'AMBER' ? '⚠️ Zinskurven-Warnung' : '✅ Stabil'}
2S10S Spread
{yieldSpread ? (yieldSpread.current >= 0 ? '+' : '') + yieldSpread.current.toFixed(2) : '0.00'}%
High-Yield Spread
5.0 ? 'text-rose-400' : 'text-slate-200'}`}> {hySpread ? hySpread.current.toFixed(1) : '0.0'}%
{/* SECTION 2: Accordion for Detailed Economic Data 3-Grid Panels */}
{isAccordionOpen && (
{/* PANEL 1: Inflation & Wachstum */}

Inflation & Wachstum

Real-Data
{renderRow('cpiYoY', cpiYoY)} {renderRow('coreCpi', coreCpi)} {renderRow('ppi', ppi)} {renderRow('savingsRate', savingsRate)} {renderRow('ccDelinquency', ccDelinquency)}
{/* PANEL 2: Zentralbanken & Liquidität */}

Zentralbanken & Liquidität

M2 / RRP / TGA
{renderRow('fedFunds', fedFunds)} {renderRow('ecbRefi', ecbRefi)} {renderRow('fedBalanceSheet', fedBalanceSheet)} {renderRow('m2', m2)} {renderRow('rrp', rrp)} {renderRow('tga', tga)} {renderRow('buffett', buffett)} {/* Dynamic Calculated Net Liquidity Proxy Row */} {netLiquidityIndicator && (
Net Fed Liquidity
Vorherig: {netLiquidityIndicator.previous}{netLiquidityIndicator.unit}
{/* Micro Recharts Sparkline */}
{netLiquidityIndicator.current}{netLiquidityIndicator.unit}
{renderTrendIcon(netLiquidityIndicator.trend, 'netLiquidity')} {netLiquidityIndicator.trend.toLowerCase()}
)}
{/* PANEL 3: Kredit- & Anleihemarkt */}

Kredit- & Anleihemarkt

Zinskurven & Spreads
{renderRow('us10y', us10y)} {renderRow('yieldSpread', yieldSpread)} {renderRow('hySpread', hySpread)} {/* Sub-section named "Immobilien- & Hypotheken-Kredite" */}

Immobilien- & Hypotheken-Kredite

{renderRow('housingStarts', housingStarts)} {renderRow('mortgageApps', mortgageApps)} {renderRow('caseShiller', caseShiller)}
)}
{/* SECTION 3: Dynamic Macro analysis and explanation */}

Systemische Macro- & Kreditmarkt-Analyse

Zinskurveninversionen (z. B. wenn der 2S10S-Yield-Spread negativ ist) gelten historisch als zuverlässige Vorläufer ökonomischer Kontraktionen. Derzeit beträgt der Spread {yieldSpread !== undefined ? (yieldSpread.current >= 0 ? '+' : '') + yieldSpread.current.toFixed(2) : '0.00'}%. Gleichzeitig signalisiert der Buffett-Indikator mit {buffett !== undefined ? buffett.current.toFixed(1) : '0.0'}% eine erhebliche Überbewertung des US-Aktienmarktes relativ zur Wirtschaftsleistung. Im Konsumsektor deutet die Kombination aus einer niedrigen Sparquote ({savingsRate !== undefined ? savingsRate.current.toFixed(1) : '0.0'}%) und steigenden Kreditkartenausfällen ({ccDelinquency !== undefined ? ccDelinquency.current.toFixed(1) : '0.0'}%) auf echten Stress hin, während der High-Yield Credit Spread ({hySpread !== undefined ? hySpread.current.toFixed(1) : '0.0'}%) noch Stabilität anzeigt. Monetäre Liquidität (Net Fed Liquidity Proxy: {netLiquidityIndicator ? netLiquidityIndicator.current.toFixed(2) : '0.00'} T$) 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).

setIsMathModalOpen(false)} />
); }