stats: /stats overview, economy, energy and Gouda pages; CBS series map; nav, homepage, /start and sitemap links
Deploy production / deploy (push) Successful in 1m10s
Deploy production / deploy (push) Successful in 1m10s
- CBS_SERIES: CPI, household tariffs (2007-now), energy balance, renewables, heat pumps, solar, cars, population (monthly, since 1942, components), house prices, housing stock, municipal levies for Gouda and its neighbours - shared StatChart/Kpi/chart helpers with per-chart source attribution - drop Eurostat nrg_pc_20x_h (404; CBS covers that history)
This commit is contained in:
1 parent
6dcbcfee25
commit
76bfb3dcec
24 files changed
+3386
-9
No files matched your search
@@ -0,0 +1,406 @@
|
||||
<script lang="ts">
|
||||
import StatChart from '#lib/stats/StatChart.svelte';
|
||||
import Kpi from '#lib/stats/Kpi.svelte';
|
||||
import { barRankOption, latest, lineOption, spread, yoy } from '#lib/stats/chart.js';
|
||||
import { num, period } from '#lib/stats/format.js';
|
||||
import { COUNTRY } from '#lib/stats/regions.js';
|
||||
|
||||
let { data } = $props();
|
||||
const s = $derived(data.series);
|
||||
const a = $derived(data.attributions);
|
||||
const pts = (id: string) => s[id]?.points ?? [];
|
||||
|
||||
const RATES = [
|
||||
['US', 'Fed', '#3b82f6'],
|
||||
['XM', 'ECB', '#eab308'],
|
||||
['KR', 'Bank of Korea', '#e11d48'],
|
||||
['GB', 'Bank of England', '#a855f7'],
|
||||
['JP', 'Bank of Japan', '#10b981'],
|
||||
['CN', 'PBoC', '#f97316']
|
||||
] as const;
|
||||
const usCpi = $derived(yoy(pts('fred:CPIAUCSL')).filter(([d]) => d >= '1997-01-01'));
|
||||
const hicp = (g: string) => pts(`eurostat:prc_hicp_minr:RCH_A.TOTAL.${g}`);
|
||||
const y = (g: string) => pts(`eurostat:irt_lt_mcby_m:MCBY.${g}`);
|
||||
const frde = $derived(spread(y('FR'), y('DE')));
|
||||
const itde = $derived(spread(y('IT'), y('DE')));
|
||||
const nlde = $derived(spread(y('NL'), y('DE')));
|
||||
const us10 = $derived(pts('fred:DGS10'));
|
||||
const curve = $derived(spread(us10, pts('fred:DGS2')));
|
||||
const EU_LIST = ['NL', 'DE', 'FR', 'BE', 'IT', 'ES', 'PL', 'SE', 'DK', 'AT', 'EU27_2020', 'EA20'];
|
||||
const lastOf = (id: string) => latest(s[id]?.points);
|
||||
const lastYear = (prefix: string) =>
|
||||
EU_LIST.map((g) => ({ g, p: lastOf(`${prefix}.${g}`) }))
|
||||
.filter((r) => r.p)
|
||||
.map((r) => ({
|
||||
label: COUNTRY[r.g] ?? r.g,
|
||||
value: r.p![1],
|
||||
highlight: r.g === 'NL',
|
||||
year: r.p![0].slice(0, 4)
|
||||
}));
|
||||
const debt = $derived(lastYear('eurostat:gov_10dd_edpt1:PC_GDP.S13.GD'));
|
||||
const deficit = $derived(lastYear('eurostat:gov_10dd_edpt1:PC_GDP.S13.B9'));
|
||||
const migrationPerK = $derived(
|
||||
EU_LIST.filter((g) => !g.startsWith('E'))
|
||||
.map((g) => {
|
||||
const m = lastOf(`eurostat:migr_imm1ctz:TOTAL.COMPLET.TOTAL.NR.T.${g}`);
|
||||
const pop = pts(`eurostat:demo_pjan:NR.TOTAL.T.${g}`).find(([d]) => m && d === m[0]);
|
||||
return m && pop
|
||||
? { label: COUNTRY[g] ?? g, value: (m[1] / pop[1]) * 1000, highlight: g === 'NL' }
|
||||
: null;
|
||||
})
|
||||
.filter((r) => r != null)
|
||||
);
|
||||
const k = (id: string) => lastOf(id);
|
||||
const fed = $derived(k('bis:M:US'));
|
||||
const ecb = $derived(k('bis:M:XM'));
|
||||
const bok = $derived(k('bis:M:KR'));
|
||||
const nlInfl = $derived(k('eurostat:prc_hicp_minr:RCH_A.TOTAL.NL'));
|
||||
const eaInfl = $derived(k('eurostat:prc_hicp_minr:RCH_A.TOTAL.EA20'));
|
||||
const usInfl = $derived(latest(usCpi));
|
||||
const spreadNow = $derived(latest(frde));
|
||||
const us10Now = $derived(latest(us10));
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>economy · stats · Stan Runge</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Interest rates, inflation, bond spreads, stock indices, GDP, public debt and migration: the Netherlands, Europe, the US and Korea."
|
||||
/>
|
||||
</svelte:head>
|
||||
|
||||
<section class="stats-intro">
|
||||
<span class="stats-eyebrow">stats / economy</span>
|
||||
<h1>Economy</h1>
|
||||
<p>
|
||||
Central bank rates, inflation, 10-year bond yields and spreads, stock markets, growth, public
|
||||
finances and migration. The Netherlands next to Europe, the US and South Korea, refreshed daily
|
||||
from open sources.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<div class="kpis">
|
||||
<Kpi
|
||||
label="Fed policy rate"
|
||||
value={num(fed?.[1], 2)}
|
||||
unit="%"
|
||||
sub={period(fed?.[0])}
|
||||
color="#3b82f6"
|
||||
/>
|
||||
<Kpi
|
||||
label="ECB policy rate"
|
||||
value={num(ecb?.[1], 2)}
|
||||
unit="%"
|
||||
sub={period(ecb?.[0])}
|
||||
color="#eab308"
|
||||
/>
|
||||
<Kpi
|
||||
label="Bank of Korea"
|
||||
value={num(bok?.[1], 2)}
|
||||
unit="%"
|
||||
sub={period(bok?.[0])}
|
||||
color="#e11d48"
|
||||
/>
|
||||
<Kpi
|
||||
label="NL inflation (HICP)"
|
||||
value={num(nlInfl?.[1])}
|
||||
unit="%"
|
||||
sub={period(nlInfl?.[0])}
|
||||
color="#f97316"
|
||||
/>
|
||||
<Kpi
|
||||
label="Euro area inflation"
|
||||
value={num(eaInfl?.[1])}
|
||||
unit="%"
|
||||
sub={period(eaInfl?.[0])}
|
||||
color="#10b981"
|
||||
/>
|
||||
<Kpi
|
||||
label="US inflation (CPI)"
|
||||
value={num(usInfl?.[1])}
|
||||
unit="%"
|
||||
sub={period(usInfl?.[0])}
|
||||
color="#06b6d4"
|
||||
/>
|
||||
<Kpi
|
||||
label="France–Germany 10y spread"
|
||||
value={num(spreadNow ? spreadNow[1] * 100 : null, 0)}
|
||||
unit="bp"
|
||||
sub={period(spreadNow?.[0])}
|
||||
color="#a855f7"
|
||||
/>
|
||||
<Kpi
|
||||
label="US 10-year yield"
|
||||
value={num(us10Now?.[1], 2)}
|
||||
unit="%"
|
||||
sub={period(us10Now?.[0])}
|
||||
color="#64748b"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h2 class="stats-section-title">Rates and inflation</h2>
|
||||
<div class="stats-grid">
|
||||
<StatChart
|
||||
title="Central bank policy rates"
|
||||
subtitle="% · monthly"
|
||||
sources={['bis']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
RATES.map(([c, name, color]) => ({ name, color, kind: 'step', points: pts(`bis:M:${c}`) })),
|
||||
{ unit: '%', zoom: true }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Inflation"
|
||||
subtitle="% year on year · HICP (Europe), CPI-U (US)"
|
||||
sources={['eurostat', 'fred']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'Netherlands', points: hicp('NL'), color: '#f97316' },
|
||||
{ name: 'Euro area', points: hicp('EA20'), color: '#10b981' },
|
||||
{ name: 'Germany', points: hicp('DE'), color: '#64748b' },
|
||||
{ name: 'United States', points: usCpi, color: '#3b82f6' }
|
||||
],
|
||||
{ unit: '%', zoom: true }
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h2 class="stats-section-title">Bond markets</h2>
|
||||
<div class="stats-grid">
|
||||
<StatChart
|
||||
title="10-year government bond yields"
|
||||
subtitle="% · monthly (EMU convergence criterion yields; US Treasury, Korea via OECD)"
|
||||
sources={['eurostat', 'fred']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'Netherlands', points: y('NL'), color: '#f97316' },
|
||||
{ name: 'Germany', points: y('DE'), color: '#64748b' },
|
||||
{ name: 'France', points: y('FR'), color: '#3b82f6' },
|
||||
{ name: 'Italy', points: y('IT'), color: '#10b981' },
|
||||
{ name: 'Spain', points: y('ES'), color: '#eab308' },
|
||||
{ name: 'United States', points: us10, color: '#a855f7' },
|
||||
{ name: 'South Korea', points: pts('fred:IRLTLT01KRM156N'), color: '#e11d48' }
|
||||
],
|
||||
{ unit: '%', zoom: true }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Spreads over Germany"
|
||||
subtitle="percentage points · 10-year yield minus the German Bund"
|
||||
sources={['eurostat']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'France − Germany', points: frde, color: '#3b82f6', kind: 'area' },
|
||||
{ name: 'Italy − Germany', points: itde, color: '#10b981' },
|
||||
{ name: 'Netherlands − Germany', points: nlde, color: '#f97316' }
|
||||
],
|
||||
{ unit: 'pp', zoom: true }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="US yield curve: 10-year minus 2-year"
|
||||
subtitle="percentage points · monthly average · below zero = inverted"
|
||||
sources={['fred']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(t, [{ name: '10y − 2y', points: curve, color: '#a855f7', kind: 'area' }], {
|
||||
unit: 'pp',
|
||||
zoom: true,
|
||||
legend: false
|
||||
})}
|
||||
/>
|
||||
<StatChart
|
||||
title="Share prices"
|
||||
subtitle="index 2015 = 100 · OECD main economic indicators"
|
||||
sources={['fred']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'Netherlands', points: pts('fred:SPASTT01NLM661N'), color: '#f97316' },
|
||||
{ name: 'United States', points: pts('fred:SPASTT01USM661N'), color: '#3b82f6' },
|
||||
{ name: 'South Korea', points: pts('fred:SPASTT01KRM661N'), color: '#e11d48' },
|
||||
{ name: 'China', points: pts('fred:SPASTT01CNM661N'), color: '#eab308' }
|
||||
],
|
||||
{ zoom: true }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="S&P 500 and NASDAQ Composite"
|
||||
subtitle="index points · weekly average"
|
||||
sources={['fred']}
|
||||
attributions={a}
|
||||
wide
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'S&P 500', points: pts('fred:SP500'), color: '#3b82f6' },
|
||||
{ name: 'NASDAQ Composite', points: pts('fred:NASDAQCOM'), color: '#10b981', right: true }
|
||||
],
|
||||
{ zoom: true, unit: 'S&P', rightUnit: 'NASDAQ' }
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h2 class="stats-section-title">Growth and jobs</h2>
|
||||
<div class="stats-grid">
|
||||
<StatChart
|
||||
title="Real GDP growth"
|
||||
subtitle="% change on the previous year"
|
||||
sources={['eurostat']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{
|
||||
name: 'Netherlands',
|
||||
points: pts('eurostat:nama_10_gdp:CLV_PCH_PRE.B1GQ.NL'),
|
||||
color: '#f97316',
|
||||
kind: 'bar'
|
||||
},
|
||||
{
|
||||
name: 'EU 27',
|
||||
points: pts('eurostat:nama_10_gdp:CLV_PCH_PRE.B1GQ.EU27_2020'),
|
||||
color: '#3b82f6'
|
||||
},
|
||||
{
|
||||
name: 'Germany',
|
||||
points: pts('eurostat:nama_10_gdp:CLV_PCH_PRE.B1GQ.DE'),
|
||||
color: '#64748b'
|
||||
}
|
||||
],
|
||||
{ unit: '%' }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="US real GDP and unemployment"
|
||||
subtitle="billions of chained 2017 USD (SAAR) · unemployment %"
|
||||
sources={['fred']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'Real GDP', points: pts('fred:GDPC1'), color: '#3b82f6', kind: 'area' },
|
||||
{ name: 'Unemployment rate', points: pts('fred:UNRATE'), color: '#e11d48', right: true }
|
||||
],
|
||||
{ unit: 'USD bn', rightUnit: '%', zoom: true }
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h2 class="stats-section-title">Public finances and migration</h2>
|
||||
<div class="stats-grid">
|
||||
<StatChart
|
||||
title="Government debt"
|
||||
subtitle={`% of GDP · ${debt[0]?.year ?? ''}`}
|
||||
sources={['eurostat']}
|
||||
attributions={a}
|
||||
height="360px"
|
||||
option={(t) => barRankOption(t, debt, { unit: '% of GDP', color: '#a855f7' })}
|
||||
/>
|
||||
<StatChart
|
||||
title="Government balance"
|
||||
subtitle={`surplus (+) or deficit (−), % of GDP · ${deficit[0]?.year ?? ''}`}
|
||||
sources={['eurostat']}
|
||||
attributions={a}
|
||||
height="360px"
|
||||
option={(t) => barRankOption(t, deficit, { unit: '% of GDP', color: '#10b981' })}
|
||||
/>
|
||||
<StatChart
|
||||
title="Dutch government: spending vs revenue"
|
||||
subtitle="% of GDP · general government"
|
||||
sources={['eurostat']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{
|
||||
name: 'Spending',
|
||||
points: pts('eurostat:gov_10a_main:PC_GDP.S13.TE.NL'),
|
||||
color: '#e11d48'
|
||||
},
|
||||
{
|
||||
name: 'Revenue',
|
||||
points: pts('eurostat:gov_10a_main:PC_GDP.S13.TR.NL'),
|
||||
color: '#10b981'
|
||||
},
|
||||
{
|
||||
name: 'EU 27 spending',
|
||||
points: pts('eurostat:gov_10a_main:PC_GDP.S13.TE.EU27_2020'),
|
||||
color: '#e11d48',
|
||||
dashed: true
|
||||
},
|
||||
{
|
||||
name: 'EU 27 revenue',
|
||||
points: pts('eurostat:gov_10a_main:PC_GDP.S13.TR.EU27_2020'),
|
||||
color: '#10b981',
|
||||
dashed: true
|
||||
}
|
||||
],
|
||||
{ unit: '% of GDP', min: 'dataMin' }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Immigration"
|
||||
subtitle="people arriving per year"
|
||||
sources={['eurostat']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{
|
||||
name: 'Netherlands',
|
||||
points: pts('eurostat:migr_imm1ctz:TOTAL.COMPLET.TOTAL.NR.T.NL'),
|
||||
color: '#f97316',
|
||||
kind: 'area'
|
||||
},
|
||||
{
|
||||
name: 'Belgium',
|
||||
points: pts('eurostat:migr_imm1ctz:TOTAL.COMPLET.TOTAL.NR.T.BE'),
|
||||
color: '#eab308'
|
||||
},
|
||||
{
|
||||
name: 'Sweden',
|
||||
points: pts('eurostat:migr_imm1ctz:TOTAL.COMPLET.TOTAL.NR.T.SE'),
|
||||
color: '#3b82f6'
|
||||
},
|
||||
{
|
||||
name: 'Austria',
|
||||
points: pts('eurostat:migr_imm1ctz:TOTAL.COMPLET.TOTAL.NR.T.AT'),
|
||||
color: '#e11d48'
|
||||
}
|
||||
],
|
||||
{ decimals: 0 }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Immigration per 1,000 inhabitants"
|
||||
subtitle="latest year"
|
||||
sources={['eurostat']}
|
||||
attributions={a}
|
||||
height="340px"
|
||||
option={(t) => barRankOption(t, migrationPerK, { unit: 'per 1,000', color: '#06b6d4' })}
|
||||
/>
|
||||
</div>
|
||||
<p class="stats-note">
|
||||
Policy rates: BIS central bank policy rates (month end). Yields for the euro countries are
|
||||
Eurostat's EMU convergence-criterion series.
|
||||
</p>
|
||||
Reference in new issue
Block a user