feat(economic): Economic Stress Composite Index panel (FRED 6-series, 0-100 score) (#2461)

* feat(economic): Economic Stress Composite Index panel (FRED 6-series, 0-100 score)

- Add T10Y3M and STLFSI4 to FRED_SERIES in seed-economy.mjs and ALLOWED_SERIES
- Create proto message GetEconomicStressResponse with EconomicStressComponent
- Register GetEconomicStress RPC in EconomicService (GET /api/economic/v1/get-economic-stress)
- Add seed-economic-stress.mjs: reads 6 pre-seeded FRED keys via Redis pipeline, computes weighted composite score (0-100) with labels Low/Moderate/Elevated/Severe/Critical
- Create server handler get-economic-stress.ts reading from economic:stress-index:v1
- Register economicStress in BOOTSTRAP_CACHE_KEYS (both cache-keys.ts and api/bootstrap.js) as slow tier
- Add gateway.ts cache tier entry (slow) for new RPC route
- Create EconomicStressPanel.ts: composite score header, gradient needle bar, 2x3 component grid with score bars, desktop notification on threshold cross (>=70, >=85)
- Wire economic-stress panel in panels.ts (all 4 variants), panel-layout.ts, and data-loader.ts
- Regenerate OpenAPI docs and TypeScript client/server types

* fix(economic-stress): null for missing FRED data + tech variant panel

- Add 'economic-stress' panel to TECH_PANELS defaults (was missing, only appeared in full/finance/commodity variants)
- Seed: write rawValue: null + missing: true when no valid FRED observation found, preventing zero-valued yield curve/bank spread readings from being conflated with missing data
- Proto: add missing bool field to EconomicStressComponent message; regenerate client/server types + OpenAPI docs
- Server handler: propagate missing flag from Redis; pass rawValue: 0 on wire when missing to satisfy proto double type
- Panel: guard on c.missing (not rawValue === 0) to show grey N/A card with no score bar for unavailable components

* fix(economic-stress): add purple Critical zone to gradient bar

Update gradient stops to match the 5 equal tier boundaries (0-20-40-60-80-100),
adding the #8e44ad purple stop at 80% so scores 80-100 render as Critical purple
instead of plain red.
This commit is contained in:
Elie Habib
2026-03-29 11:19:35 +04:00
committed by GitHub
parent ba54dc12d7
commit aa3e84f0ab
18 changed files with 644 additions and 2 deletions

View File

@@ -676,6 +676,32 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/economic/v1/get-economic-stress:
get:
tags:
- EconomicService
summary: GetEconomicStress
description: GetEconomicStress retrieves the composite Economic Stress Index (0-100) from 6 FRED series.
operationId: GetEconomicStress
responses:
"200":
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/GetEconomicStressResponse'
"400":
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
default:
description: Error response
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
Error:
@@ -1857,3 +1883,39 @@ components:
value:
type: number
format: double
GetEconomicStressRequest:
type: object
GetEconomicStressResponse:
type: object
properties:
compositeScore:
type: number
format: double
label:
type: string
components:
type: array
items:
$ref: '#/components/schemas/EconomicStressComponent'
seededAt:
type: string
unavailable:
type: boolean
EconomicStressComponent:
type: object
properties:
id:
type: string
label:
type: string
rawValue:
type: number
format: double
score:
type: number
format: double
weight:
type: number
format: double
missing:
type: boolean