'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('Error fetching macroeconomic indicators.'); } } catch (err) { console.error('Fetch macro indicators error:', err); setError('Network error loading macroeconomic data.'); } 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: 'Central Banks & Liquidity', current, previous, trend, data: netLiquidityData } as MacroIndicator; }, [payload]); if (loading) { return (
Loading macroeconomic data archive...
); } if (error || !payload) { return (
{error || 'Error loading data.'}
); } 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}
Previous: {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] 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.
)} {/* SECTION 1: Header & Control Bar */}
Macroeconomics Silo

Macroeconomic Indicators & Credit Silo

Analyzes cycles, liquidity flows, and yield curves over the past 24 months.

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

Inflation & Consumer Stress

{/* Glowing Neon-Ampel Light */}
Risk Status:{' '} {card1Status === 'RED' ? '🚨 Critical Consumer Pressure' : card1Status === 'AMBER' ? '⚠️ Elevated Risk' : '✅ Stable'}
CPI
= 3.0 ? 'text-rose-400' : 'text-slate-200'}`}> {cpiYoY ? cpiYoY.current.toFixed(1) : '0.0'}%
Savings Rate
{savingsRate ? savingsRate.current.toFixed(1) : '0.0'}%
Delinquencies
4.5 ? 'text-rose-400' : 'text-slate-200'}`}> {ccDelinquency ? ccDelinquency.current.toFixed(1) : '0.0'}%
{/* CARD 2: Bewertung & Liquidität */}
Category 2

Valuation & Liquidity

{/* Glowing Neon-Ampel Light */}
Risk Status:{' '} {card2Status === 'RED' ? '🚨 Extreme Overvaluation' : card2Status === 'AMBER' ? '⚠️ Liquidity Squeeze' : '✅ Sufficient'}
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 */}
Category 3

Credit & Recession Risk

{/* Glowing Neon-Ampel Light */}
Risk Status:{' '} {card3Status === 'RED' ? '🚨 Recession Inversion' : card3Status === 'AMBER' ? '⚠️ Yield Curve Warning' : '✅ Stable'}
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 & Growth

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

Central Banks & Liquidity

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
Previous: {netLiquidityIndicator.previous}{netLiquidityIndicator.unit}
{/* Micro Recharts Sparkline */}
{netLiquidityIndicator.current}{netLiquidityIndicator.unit}
{renderTrendIcon(netLiquidityIndicator.trend, 'netLiquidity')} {netLiquidityIndicator.trend.toLowerCase()}
)}
{/* PANEL 3: Kredit- & Anleihemarkt */}

Credit & Bond Market

Yield Curves & Spreads
{renderRow('us10y', us10y)} {renderRow('yieldSpread', yieldSpread)} {renderRow('hySpread', hySpread)} {/* Sub-section named "Real Estate & Mortgage Credit" */}

Real Estate & Mortgage Credit

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

Systemic Macro & Credit Market Analysis

Yield curve inversions (e.g. when the 2S10S Yield Spread is negative) are historically reliable leading indicators of economic contractions. Currently, the spread is {yieldSpread !== undefined ? (yieldSpread.current >= 0 ? '+' : '') + yieldSpread.current.toFixed(2) : '0.00'}%. 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 ({savingsRate !== undefined ? savingsRate.current.toFixed(1) : '0.0'}%) and rising credit card delinquencies ({ccDelinquency !== undefined ? ccDelinquency.current.toFixed(1) : '0.0'}%) suggests genuine distress, while the High-Yield credit spread ({hySpread !== undefined ? hySpread.current.toFixed(1) : '0.0'}%) still indicates stability. Monetary liquidity (Net Fed Liquidity Proxy: {netLiquidityIndicator ? netLiquidityIndicator.current.toFixed(2) : '0.00'} T$) 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).

setIsMathModalOpen(false)} />
); }