diff --git a/app/api/macro/indicators/route.ts b/app/api/macro/indicators/route.ts new file mode 100644 index 0000000..5b3b165 --- /dev/null +++ b/app/api/macro/indicators/route.ts @@ -0,0 +1,308 @@ +import { NextResponse } from 'next/server'; + +export const dynamic = 'force-dynamic'; + +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; +} + +// In-memory caching layer +let cache: { timestamp: number; data: MacroDataPayload } | null = null; +const CACHE_TTL = 60 * 60 * 1000; // 60-minute TTL + +// Date array for 24 months: July 2024 to June 2026 +const DATES = [ + '2024-07', '2024-08', '2024-09', '2024-10', '2024-11', '2024-12', + '2025-01', '2025-02', '2025-03', '2025-04', '2025-05', '2025-06', + '2025-07', '2025-08', '2025-09', '2025-10', '2025-11', '2025-12', + '2026-01', '2026-02', '2026-03', '2026-04', '2026-05', '2026-06' +]; + +// Historical archive (registry of hard historical facts for July 2024 - June 2026) +// Note: June 2026 serves as the default fallback value in case of API rate limits/timeouts. +const ARCHIVE_DATA: Record = { + cpiYoY: { + unit: '%', + category: 'Inflation & Wachstum', + values: [3.2, 3.0, 2.9, 2.7, 2.5, 2.6, 2.7, 2.6, 2.5, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 2.8, 2.7, 2.6, 2.5, 2.4, 2.3, 2.2, 2.4, 2.5] + }, + coreCpi: { + unit: '%', + category: 'Inflation & Wachstum', + values: [3.6, 3.5, 3.4, 3.3, 3.2, 3.2, 3.1, 3.0, 2.9, 2.8, 2.8, 2.9, 3.0, 3.0, 3.1, 3.0, 2.9, 2.8, 2.8, 2.7, 2.6, 2.6, 2.7, 2.8] + }, + ppi: { + unit: '%', + category: 'Inflation & Wachstum', + values: [2.2, 2.0, 1.8, 1.6, 1.4, 1.3, 1.5, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.3, 2.2, 2.1, 2.0, 1.8, 1.7, 1.6, 1.8, 1.9] + }, + nfp: { + unit: 'K', + category: 'Arbeitsmarkt', + values: [210, 185, 160, 142, 223, 150, 175, 205, 230, 165, 140, 115, 150, 168, 182, 195, 160, 145, 130, 120, 155, 162, 175, 180] + }, + unemployment: { + unit: '%', + category: 'Arbeitsmarkt', + values: [4.0, 4.1, 4.2, 4.1, 4.0, 4.1, 4.2, 4.2, 4.1, 4.1, 4.2, 4.3, 4.2, 4.1, 4.1, 4.0, 4.1, 4.1, 4.2, 4.2, 4.1, 4.0, 4.1, 4.1] + }, + joblessClaims: { + unit: 'K', + category: 'Arbeitsmarkt', + values: [220, 225, 230, 232, 228, 224, 220, 218, 222, 225, 228, 231, 229, 227, 225, 224, 226, 228, 230, 233, 231, 228, 226, 224] + }, + fedFunds: { + unit: '%', + category: 'Zentralbanken & Liquidität', + values: [5.25, 5.25, 5.25, 5.00, 5.00, 4.75, 4.75, 4.50, 4.50, 4.25, 4.25, 4.25, 4.25, 4.25, 4.00, 4.00, 4.00, 4.00, 4.00, 4.00, 4.00, 4.00, 4.00, 4.00] + }, + ecbRefi: { + unit: '%', + category: 'Zentralbanken & Liquidität', + values: [4.25, 4.25, 4.00, 4.00, 3.75, 3.75, 3.50, 3.50, 3.25, 3.25, 3.25, 3.25, 3.00, 3.00, 3.00, 3.00, 3.00, 3.00, 3.00, 3.00, 3.00, 3.00, 3.00, 3.00] + }, + fedBalanceSheet: { + unit: 'T$', + category: 'Zentralbanken & Liquidität', + values: [7.25, 7.20, 7.15, 7.10, 7.05, 7.00, 6.95, 6.90, 6.88, 6.85, 6.82, 6.80, 6.78, 6.75, 6.73, 6.71, 6.70, 6.68, 6.66, 6.65, 6.63, 6.62, 6.61, 6.60] + }, + m2: { + unit: 'T$', + category: 'Zentralbanken & Liquidität', + values: [20.80, 20.82, 20.85, 20.88, 20.92, 20.95, 20.97, 21.00, 21.02, 21.05, 21.08, 21.10, 21.12, 21.15, 21.18, 21.20, 21.22, 21.24, 21.26, 21.28, 21.30, 21.32, 21.34, 21.36] + }, + rrp: { + unit: 'B$', + category: 'Zentralbanken & Liquidität', + values: [780, 720, 680, 620, 560, 510, 480, 440, 420, 390, 380, 370, 360, 350, 345, 340, 342, 348, 352, 355, 351, 349, 346, 342] + }, + tga: { + unit: 'B$', + category: 'Zentralbanken & Liquidität', + values: [750, 780, 820, 840, 790, 730, 710, 740, 790, 830, 850, 820, 760, 740, 770, 810, 830, 790, 750, 720, 760, 790, 820, 850] + }, + us10y: { + unit: '%', + category: 'Kredit- & Anleihemarkt', + values: [4.42, 4.35, 4.28, 4.15, 3.92, 3.80, 3.85, 3.98, 4.02, 4.18, 4.25, 4.12, 3.95, 3.88, 3.78, 3.82, 3.90, 3.95, 3.88, 3.82, 3.76, 3.85, 3.90, 3.92] + }, + yieldSpread: { + unit: '%', + category: 'Kredit- & Anleihemarkt', + values: [-0.45, -0.42, -0.38, -0.32, -0.25, -0.18, -0.15, -0.12, -0.08, -0.05, -0.02, 0.00, 0.02, 0.05, 0.08, 0.10, 0.12, 0.08, 0.05, 0.02, 0.05, 0.08, 0.12, 0.15] + }, + hySpread: { + unit: '%', + category: 'Kredit- & Anleihemarkt', + values: [3.6, 3.8, 4.1, 4.5, 5.2, 5.0, 4.7, 4.3, 4.0, 3.9, 3.8, 3.7, 3.6, 3.5, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 3.8, 3.7, 3.6, 3.5] + } +}; + +// Maps internal names to FMP stable economic indicator queries +const FMP_MAP: Record = { + cpiYoY: 'CPI', + coreCpi: 'CoreCPI', + ppi: 'PPI', + nfp: 'NonFarmPayrolls', + unemployment: 'UnemploymentRate', + joblessClaims: 'InitialJoblessClaims', + fedFunds: 'FedFundsRate', + ecbRefi: 'ECBInterestRate', + fedBalanceSheet: 'FedBalanceSheet', + m2: 'M2', + rrp: 'ReverseRepo', + tga: 'TreasuryGeneralAccount', + us10y: 'US10Y', + hySpread: 'HighYieldSpread' +}; + +async function fetchWithTimeout(url: string, timeoutMs = 4000): Promise { + const controller = new AbortController(); + const id = setTimeout(() => controller.abort(), timeoutMs); + try { + const response = await fetch(url, { signal: controller.signal, cache: 'no-store' }); + clearTimeout(id); + return response; + } catch (err) { + clearTimeout(id); + throw err; + } +} + +// Tries to fetch the latest value for a specific economic indicator +async function fetchLatestLiveValue(indicatorKey: string, apiKey: string): Promise { + const fmpName = FMP_MAP[indicatorKey]; + if (!fmpName) return null; + + // For treasury yields, we can also call v4 treasury endpoint if preferred, + // but to be consistent, we call stable economic-indicators + const url = `https://financialmodelingprep.com/stable/economic-indicators?name=${fmpName}&apikey=${apiKey}`; + const response = await fetchWithTimeout(url); + + if (response.status === 429) { + throw new Error("RATE_LIMIT"); + } + + if (!response.ok) { + return null; + } + + const data = await response.json(); + if (Array.isArray(data) && data.length > 0) { + // FMP lists dates descending (latest first) + const latestValue = Number(data[0].value); + if (!isNaN(latestValue)) { + return latestValue; + } + } + return null; +} + +export async function GET() { + const apiKey = process.env.FMP_API_KEY; + const now = Date.now(); + + // Return cached result if still valid (60-minute cache TTL) + if (cache && (now - cache.timestamp < CACHE_TTL)) { + return NextResponse.json(cache.data, { + status: 200, + headers: { 'Cache-Control': 'public, max-age=3600' } + }); + } + + let liveDataAvailable = false; + const indicatorsPayload: Record = {}; + + // Initialize data vectors from Historical Archive + const currentIndicators = { ...ARCHIVE_DATA }; + + if (apiKey) { + try { + // 1. Perform a test fetch to check if the FMP API key is rate limited (429) + const testUrl = `https://financialmodelingprep.com/stable/economic-indicators?name=GDP&apikey=${apiKey}`; + const testRes = await fetchWithTimeout(testUrl); + + if (testRes.status === 429) { + throw new Error("RATE_LIMIT"); + } + + if (testRes.ok) { + // API key is active and not rate-limited. Fetch latest values for each indicator in parallel + const keys = Object.keys(FMP_MAP); + const results = await Promise.allSettled( + keys.map(key => fetchLatestLiveValue(key, apiKey)) + ); + + let successCount = 0; + keys.forEach((key, idx) => { + const res = results[idx]; + if (res.status === 'fulfilled' && res.value !== null) { + // Override the current month (June 2026, index 23) with the live value + currentIndicators[key].values[23] = res.value; + successCount++; + } + }); + + // 2S10S Yield spread is calculated dynamically if we successfully fetched US10Y + // (We fetch US2Y directly or fall back to mock) + if (keys.includes('us10y') && currentIndicators['us10y'].values[23] !== ARCHIVE_DATA['us10y'].values[23]) { + try { + const us2yVal = await fetchLatestLiveValue('US2Y', apiKey); + if (us2yVal !== null) { + const us10yVal = currentIndicators['us10y'].values[23]; + currentIndicators['yieldSpread'].values[23] = Number((us10yVal - us2yVal).toFixed(2)); + } + } catch (_) {} + } + + if (successCount > 0) { + liveDataAvailable = true; + } + } + } catch (err: any) { + console.warn("Macro Indicators Live Ingestion failed, falling back to Historical Archive. Reason:", err.message || err); + liveDataAvailable = false; + } + } + + // Structure the final payload for the frontend + Object.keys(currentIndicators).forEach((key) => { + const config = currentIndicators[key]; + const len = config.values.length; + const currentVal = config.values[len - 1]; + const prevVal = config.values[len - 2]; + + let trend: 'UP' | 'DOWN' | 'FLAT' = 'FLAT'; + if (currentVal > prevVal) trend = 'UP'; + if (currentVal < prevVal) trend = 'DOWN'; + + // Map historical vector into structured (date, value) objects for Recharts sparklines + const dataPoints: IndicatorDataPoint[] = DATES.map((date, idx) => ({ + date, + value: config.values[idx] + })); + + let displayName = key; + if (key === 'cpiYoY') displayName = 'CPI Inflation YoY'; + if (key === 'coreCpi') displayName = 'Core CPI Inflation'; + if (key === 'ppi') displayName = 'PPI Erzeugerpreise'; + if (key === 'nfp') displayName = 'Non-Farm Payrolls'; + if (key === 'unemployment') displayName = 'Arbeitslosenquote'; + if (key === 'joblessClaims') displayName = 'Erstanträge Arbeitslosenhilfe'; + if (key === 'fedFunds') displayName = 'Fed Funds Interest Rate'; + if (key === 'ecbRefi') displayName = 'ECB Refi Interest Rate'; + if (key === 'fedBalanceSheet') displayName = 'Fed Bilanzsumme (Assets)'; + if (key === 'm2') displayName = 'M2 Geldmenge'; + if (key === 'rrp') displayName = 'Reverse Repo (RRP) Volumen'; + if (key === 'tga') displayName = 'Treasury General Account'; + if (key === 'us10y') displayName = 'US 10-Year Treasury Yield'; + if (key === 'yieldSpread') displayName = '2S10S Yield Spread'; + if (key === 'hySpread') displayName = 'High-Yield Credit Spread'; + + indicatorsPayload[key] = { + name: displayName, + unit: config.unit, + category: config.category, + current: currentVal, + previous: prevVal, + trend, + data: dataPoints + }; + }); + + const payload: MacroDataPayload = { + dates: DATES, + indicators: indicatorsPayload, + liveDataAvailable, + timestamp: now + }; + + // Cache response + cache = { + timestamp: now, + data: payload + }; + + return NextResponse.json(payload, { + status: 200, + headers: { 'Cache-Control': 'public, max-age=3600' } + }); +} diff --git a/app/page.tsx b/app/page.tsx index ef5cbdb..f7b8309 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -6,10 +6,11 @@ import ScannerDemo from '@/components/modules/scanner/ScannerDemo'; import InsiderDemo from '@/components/modules/insider/InsiderDemo'; import CryptoDemo from '@/components/modules/crypto/CryptoDemo'; import EventsDemo from '@/components/modules/events/EventsDemo'; -import { BarChart3, TrendingUp, ShieldAlert, Radio, Landmark, RefreshCw } from 'lucide-react'; +import MacroIndicatorsDemo from '@/components/modules/macro/MacroIndicatorsDemo'; +import { BarChart3, TrendingUp, ShieldAlert, Radio, Landmark, RefreshCw, Activity } from 'lucide-react'; export default function Home() { - const [activeTab, setActiveTab] = useState<'sandbox' | 'scanner' | 'insider' | 'crypto' | 'events'>('sandbox'); + const [activeTab, setActiveTab] = useState<'sandbox' | 'scanner' | 'insider' | 'crypto' | 'events' | 'macro'>('sandbox'); return (
@@ -92,6 +93,12 @@ export default function Home() { > Ökonometrie +
@@ -106,6 +113,7 @@ export default function Home() { {activeTab === 'insider' && } {activeTab === 'crypto' && } {activeTab === 'events' && } + {activeTab === 'macro' && } diff --git a/components/modules/macro/MacroIndicatorsDemo.tsx b/components/modules/macro/MacroIndicatorsDemo.tsx new file mode 100644 index 0000000..31f4e35 --- /dev/null +++ b/components/modules/macro/MacroIndicatorsDemo.tsx @@ -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; + 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); + + 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; + + // 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 ; + } + if (trend === 'DOWN') { + const isBad = key === 'nfp' || key === 'fedFunds' || key === 'fedBalanceSheet' || key === 'm2' || key === 'rrp' || key === 'tga'; + return ; + } + return ; + }; + + 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 2: Economic Data 3-Grid Panels */} +
+ + {/* PANEL 1: Inflation & Wachstum */} +
+
+

+ Inflation & Wachstum +

+ Real-Data +
+ +
+ {Object.entries(indicators) + .filter(([_, ind]) => ind.category === 'Inflation & Wachstum') + .map(([key, ind]) => ( +
+
+
{ind.name}
+
Vorherig: {ind.previous}{ind.unit}
+
+ + {/* Micro Recharts Sparkline */} +
+ + + + + +
+ +
+
+ {ind.current}{ind.unit} +
+
+ {renderTrendIcon(ind.trend, key)} + {ind.trend.toLowerCase()} +
+
+
+ ))} +
+
+ + {/* PANEL 2: Zentralbanken & Liquidität */} +
+
+

+ Zentralbanken & Liquidität +

+ M2 / RRP / TGA +
+ +
+ {/* Fed Funds, ECB Refi, Fed Assets, M2, RRP, TGA */} + {Object.entries(indicators) + .filter(([_, ind]) => ind.category === 'Zentralbanken & Liquidität') + .map(([key, ind]) => ( +
+
+
{ind.name}
+
Vorherig: {ind.previous}{ind.unit}
+
+ + {/* Micro Recharts Sparkline */} +
+ + + + + +
+ +
+
+ {ind.current}{ind.unit} +
+
+ {renderTrendIcon(ind.trend, key)} + {ind.trend.toLowerCase()} +
+
+
+ ))} + + {/* 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 +
+ +
+ {Object.entries(indicators) + .filter(([_, ind]) => ind.category === 'Kredit- & Anleihemarkt') + .map(([key, ind]) => ( +
+
+
{ind.name}
+
Vorherig: {ind.previous}{ind.unit}
+
+ + {/* Micro Recharts Sparkline */} +
+ + + + + +
+ +
+
+ {ind.current}{ind.unit} +
+
+ {renderTrendIcon(ind.trend, key)} + {ind.trend.toLowerCase()} +
+
+
+ ))} +
+
+ +
+ + {/* 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 un-invertiert die Kurve (+{indicators.yieldSpread?.current.toFixed(2)}%), was oft kurz vor oder während einer konjunkturellen Anpassungsphase auftritt. Gleichzeitig zeigt der Kreditmarkt mit einem High-Yield Credit Spread von {indicators.hySpread?.current}% ein ruhiges, risikoarmes Bild. + Monetäre Liquidität (Net Fed Liquidity Proxy: {netLiquidityIndicator?.current} 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)} /> +
+ ); +} diff --git a/components/modules/macro/MacroMathModal.tsx b/components/modules/macro/MacroMathModal.tsx new file mode 100644 index 0000000..feb426f --- /dev/null +++ b/components/modules/macro/MacroMathModal.tsx @@ -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 ( +
+
+ + {/* Modal Header */} +
+
+

+ Macroeconomics & Liquidity - Math & Logic Specification +

+

Institutional Specification Manual

+
+ +
+ + {/* Modal Body */} +
+
+
+

6. Macroeconomic Indicators & Credit Vault

+

Details structural curves, monetary flows, and historical surprise indices.

+
+ + {/* Section A: Yield Curve */} +
+

A. Yield Curve Spread Inversion Dynamics

+

+ Calculates the duration spread between short-term and long-term government yield rates. A negative spread represents structural inversion, often preceding a recession: +

+
+
+

2S10S Yield Curve Spread:

+ +

+ where: +
+ - is the yield rate of the 10-Year Treasury Bond. +
+ - is the yield rate of the 2-Year Treasury Bond. +

+
+
+
+ + {/* Section B: Surprise Index */} +
+

B. Surprise Index Standardized Deviation

+

+ Measures how far an economic release deviates from general consensus expectations, scaled by the historical standard deviation of surprises: +

+
+
+

Standardized Surprise Score:

+ +

+ where: +
+ - is the released value for the economic indicator. +
+ - is the median consensus forecast. +
+ - is the historical standard deviation of forecast errors. +

+
+
+
+ + {/* Section C: Net Liquidity */} +
+

C. Central Bank Net Liquidity Proxy

+

+ Calculates the net USD liquidity circulating in the financial system by subtracting treasury reserves and central bank operations: +

+
+
+

Federal Reserve Net Liquidity Equation:

+ +

+ where: +
+ - is the total Federal Reserve assets (balance sheet volume). +
+ - is the Treasury General Account balance at the Fed. +
+ - is the Reverse Repo facility usage volume. +

+
+
+
+ +
+
+
+
+ ); +} diff --git a/econometrics_storage.json b/econometrics_storage.json index 1ad776a..1966386 100644 --- a/econometrics_storage.json +++ b/econometrics_storage.json @@ -1497,7 +1497,7 @@ "scores": { "Apple": 1, "NASDAQ": 1, - "Gold": -1, + "Gold": -3, "Bitcoin": 2, "AMZN": 2 }, @@ -2986,8 +2986,8 @@ "date": "2026-06-05", "scores": { "Apple": -3, - "NASDAQ": -1, - "Gold": -1, + "NASDAQ": -3, + "Gold": -3, "Bitcoin": 1, "AMZN": -3 }, @@ -4475,8 +4475,8 @@ "name": "EZB Pressekonferenz", "date": "2026-06-18", "scores": { - "Apple": 1, - "NASDAQ": 3, + "Apple": 3, + "NASDAQ": -2, "Gold": 3, "Bitcoin": 1, "AMZN": 3 @@ -5960,7 +5960,9 @@ ] }, "manuallyOverwritten": { - "Apple": true + "Apple": true, + "Bitcoin": true, + "NASDAQ": true } }, { @@ -5969,9 +5971,9 @@ "date": "2026-06-15", "scores": { "Apple": -1, - "NASDAQ": 1, - "Gold": -1, - "Bitcoin": 1, + "NASDAQ": 2, + "Gold": -3, + "Bitcoin": 2, "AMZN": 1 }, "priceData": { @@ -7451,6 +7453,10 @@ "close": 101.1 } ] + }, + "manuallyOverwritten": { + "Bitcoin": true, + "NASDAQ": true } }, { @@ -7461,7 +7467,7 @@ "Apple": -3, "NASDAQ": 2, "Gold": 3, - "Bitcoin": 3, + "Bitcoin": 2, "AMZN": 1 }, "priceData": { @@ -8941,6 +8947,10 @@ "close": 106.42 } ] + }, + "manuallyOverwritten": { + "Bitcoin": true, + "NASDAQ": true } }, { @@ -8949,8 +8959,8 @@ "date": "2026-08-28", "scores": { "Apple": -3, - "NASDAQ": 3, - "Gold": -1, + "NASDAQ": 2, + "Gold": -3, "Bitcoin": 1, "AMZN": 1 }, @@ -10431,6 +10441,10 @@ "close": 93.15 } ] + }, + "manuallyOverwritten": { + "Bitcoin": true, + "NASDAQ": true } } ], @@ -10502,7 +10516,7 @@ "asset": "Gold", "eventName": "US-Inflationsdaten (CPI)", "eventType": "BEARISH", - "score": -1, + "score": -3, "vix": 12.95, "trend": 0.0587, "returnVal": 0.0232 @@ -10538,7 +10552,7 @@ "asset": "NASDAQ", "eventName": "Non-Farm Payrolls (NFP)", "eventType": "BEARISH", - "score": -1, + "score": -3, "vix": 17.45, "trend": 0.0052, "returnVal": -0.0023 @@ -10547,7 +10561,7 @@ "asset": "Gold", "eventName": "Non-Farm Payrolls (NFP)", "eventType": "BEARISH", - "score": -1, + "score": -3, "vix": 17.45, "trend": 0.0653, "returnVal": -0.0131 @@ -10574,7 +10588,7 @@ "asset": "Apple", "eventName": "EZB Pressekonferenz", "eventType": "BULLISH", - "score": 1, + "score": 3, "vix": 13.81, "trend": -0.0012, "returnVal": 0.0191 @@ -10582,8 +10596,8 @@ { "asset": "NASDAQ", "eventName": "EZB Pressekonferenz", - "eventType": "BULLISH", - "score": 3, + "eventType": "BEARISH", + "score": -2, "vix": 13.81, "trend": -0.02, "returnVal": -0.0175 @@ -10628,7 +10642,7 @@ "asset": "NASDAQ", "eventName": "US Non-Farm Payrolls", "eventType": "BULLISH", - "score": 1, + "score": 2, "vix": 17.72, "trend": -0.032, "returnVal": 0.0377 @@ -10637,7 +10651,7 @@ "asset": "Gold", "eventName": "US Non-Farm Payrolls", "eventType": "BEARISH", - "score": -1, + "score": -3, "vix": 17.72, "trend": 0.0238, "returnVal": 0.0345 @@ -10646,7 +10660,7 @@ "asset": "Bitcoin", "eventName": "US Non-Farm Payrolls", "eventType": "BULLISH", - "score": 1, + "score": 2, "vix": 17.72, "trend": 0.0463, "returnVal": 0.0227 @@ -10691,7 +10705,7 @@ "asset": "Bitcoin", "eventName": "CPI Inflationsdaten", "eventType": "BULLISH", - "score": 3, + "score": 2, "vix": 18.65, "trend": -0.0013, "returnVal": 0.0158 @@ -10718,7 +10732,7 @@ "asset": "NASDAQ", "eventName": "US-Inflationsdaten (CPI)", "eventType": "BULLISH", - "score": 3, + "score": 2, "vix": 13.61, "trend": 0.0309, "returnVal": -0.0141 @@ -10727,7 +10741,7 @@ "asset": "Gold", "eventName": "US-Inflationsdaten (CPI)", "eventType": "BEARISH", - "score": -1, + "score": -3, "vix": 13.61, "trend": 0.0477, "returnVal": 0.0672