fix: FRED data quality — GDP growth %, CPI/PCE YoY%, ICSA in K

- GDPC1 replaces A191RL1Q225SBEA: compute annualized QoQ growth from
  GDP level ((val/prev)^4 - 1)*100 → displays proper ~2-3% not 31 819
- CPIAUCSL/CPILFESL/PCEPILFE: yoy_pct transform (val/val_12m_ago-1)*100
  → displays 3.x% YoY inflation, not raw index level 334
- ICSA: div1000 transform → displays 226 K claims, not 226 000 K
- delta_absolute flag: pp change for rate/% series, % change for levels
- SurprisePct component: shows 'pp' suffix for %, '%' for K/levels
- Column header renamed from 'Δ%' to 'Δ vs préc.' with tooltip
- Deprecated A191RL1Q225SBEA rows cleaned from DB on next bootstrap
- Warm-up periods: 2yr for yoy_pct, 3yr for qoq_annualized, 1yr others

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OpenSquared
2026-06-26 15:16:44 +02:00
parent 2469b76769
commit d25ca92694
2 changed files with 124 additions and 48 deletions

View File

@@ -118,12 +118,19 @@ function DirBadge({ dir }: { dir: string | null }) {
)
}
function SurprisePct({ v }: { v: number | null }) {
// For rate/spread series (unit % or pp): delta_absolute=true → show absolute pp change
// For level series (K, raw): delta_absolute=false → show relative % change
const DELTA_ABSOLUTE_UNITS = new Set(['%', 'pp'])
function SurprisePct({ v, unit }: { v: number | null; unit: string }) {
if (v === null || v === undefined) return <span className="text-slate-600"></span>
const isPp = DELTA_ABSOLUTE_UNITS.has(unit)
const sign = v > 0 ? '+' : ''
const decimals = isPp ? 2 : 1
const suffix = isPp ? ' pp' : '%'
return (
<span className={clsx('text-xs font-mono', v > 0 ? 'text-emerald-400' : v < 0 ? 'text-red-400' : 'text-slate-400')}>
{sign}{v.toFixed(1)}%
{sign}{v.toFixed(decimals)}{suffix}
</span>
)
}
@@ -510,7 +517,7 @@ export default function CalendarPage() {
</th>
<th className="text-right py-1.5 pr-3">Actuel</th>
<th className="text-right py-1.5 pr-3">Précédent</th>
<th className="text-right py-1.5 pr-3">Δ%</th>
<th className="text-right py-1.5 pr-3" title="Variation vs période précédente (pp pour les séries en %, % pour les niveaux)">Δ vs préc.</th>
<th className="text-right py-1.5 pr-3 cursor-pointer hover:text-white" onClick={() => toggleSort('zscore')}>
Z-Score <SortIcon col="zscore" />
</th>
@@ -542,7 +549,7 @@ export default function CalendarPage() {
{fmt(ev.previous_value)}
</td>
<td className="py-1.5 pr-3 text-right">
<SurprisePct v={ev.surprise_pct} />
<SurprisePct v={ev.surprise_pct} unit={ev.actual_unit} />
</td>
<td className="py-1.5 pr-3 text-right">
<ZBadge z={ev.surprise_zscore} dir={ev.surprise_direction} />