ledger: GDP (nominal, current US$) top-20 countries 2023 from World Bank API

This commit is contained in:
ledger committed 2026-10-21 15:49:15 +00:00
1 parent 3f389acf3c
commit d2964cd4af
6 files changed
+461

No files matched your search

@@ -0,0 +1,70 @@
#!/usr/bin/env python3
"""Extract GDP (nominal, current US$) for the top 20 countries, 2023.
Source: World Bank API, indicator NY.GDP.MKTP.CD (GDP, current US$), country:all, date=2023.
Filter: keep only records whose country.id is a real ISO 3166-1 alpha-3 code
(iso3_codes.txt from the Wikipedia ISO3 list), dropping World Bank aggregates.
Artifacts (written alongside this script):
- gdp_nominal_usd_2023.csv (rank, country, iso3, gdp_nominal_usd_billions)
- gdp_nominal_usd_2023.md (markdown table of the same top-20)
"""
import csv
import json
import os
HERE = os.path.dirname(os.path.abspath(__file__))
ISO3_PATH = os.path.join(HERE, "iso3_codes.txt")
JSON_PATH = os.path.join(HERE, "gdp_nominal_usd_2023.json")
CSV_PATH = os.path.join(HERE, "gdp_nominal_usd_2023.csv")
MD_PATH = os.path.join(HERE, "gdp_nominal_usd_2023.md")
TOP_N = 20
with open(ISO3_PATH, "r", encoding="utf-8") as f:
iso3_codes = set(line.strip() for line in f if line.strip())
with open(JSON_PATH, "r", encoding="utf-8") as f:
payload = json.load(f)
records = payload[1] # payload[0] is the metadata envelope
rows = []
for r in records:
country = r.get("country", {})
value = r.get("value")
code = r.get("countryiso3code") # ISO 3166-1 alpha-3; aggregates use non-ISO codes
if value is None or code not in iso3_codes:
continue
rows.append(
{
"country": country.get("value", ""),
"iso3": code,
"gdp_raw_usd": float(value),
}
)
rows.sort(key=lambda x: -x["gdp_raw_usd"])
top = rows[:TOP_N]
with open(CSV_PATH, "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["rank", "country", "iso3", "gdp_nominal_usd_billions"])
for i, r in enumerate(top, 1):
writer.writerow([i, r["country"], r["iso3"], round(r["gdp_raw_usd"] / 1e9, 3)])
lines = [
"# Top 20 countries by GDP (nominal, current US$) — 2023",
"",
"Source: World Bank API (`NY.GDP.MKTP.CD`, 2023). Only ISO 3166-1 alpha-3 countries "
"are counted (World Bank aggregates excluded).",
"",
"| Rank | Country | ISO3 | GDP nominal (USD billions) |",
"|---:|---|:--:|---:|",
]
for i, r in enumerate(top, 1):
lines.append(f"| {i} | {r['country']} | {r['iso3']} | {r['gdp_raw_usd'] / 1e9:.3f} |")
with open(MD_PATH, "w", encoding="utf-8") as f:
f.write("\n".join(lines) + "\n")
print(f"PARSED rows={len(rows)} kept_countries={len(top)}")
for r in top:
print(f" {r['country']} ({r['iso3']}) {r['gdp_raw_usd'] / 1e9:.3f}B")
+82
View File
@@ -0,0 +1,82 @@
#!/usr/bin/env python3
"""Real cross-check: re-fetches the World Bank GDP nominal-2023 API and compares the
committed gdp_nominal_usd_2023.csv (next to this script) against a fresh computation.
Exit code: 0 = artifact matches the live source of truth; 1 = mismatch.
"""
import csv
import json
import os
import sys
import urllib.request
HERE = os.path.dirname(os.path.abspath(__file__))
CSV_PATH = os.path.join(HERE, "gdp_nominal_usd_2023.csv")
ISO3_PATH = os.path.join(HERE, "iso3_codes.txt")
API_URL = ("https://api.worldbank.org/v2/country/all/indicator/NY.GDP.MKTP.CD"
"?format=json&date=2023:2023&per_page=1000")
TOLERANCE_USD = 1_000_000 # 1e6 USD == 0.001B (artifact rounds to 3 decimals)
def fetch_json(url):
req = urllib.request.Request(url, headers={"User-Agent": "ledger/extract/1.0"})
with urllib.request.urlopen(req, timeout=40) as r:
return json.loads(r.read().decode("utf-8"))
def main():
with open(ISO3_PATH, encoding="utf-8") as f:
iso3 = {ln.strip() for ln in f if ln.strip()}
payload = fetch_json(API_URL)
records = payload[1] if isinstance(payload, list) and payload else []
api = []
for rec in records:
iso = rec.get("countryiso3code")
val = rec.get("value")
if iso in iso3 and val is not None:
api.append((rec["country"]["value"], iso, float(val)))
api.sort(key=lambda x: -x[2])
top20 = api[:20]
with open(CSV_PATH, encoding="utf-8") as f:
rows = [r for r in csv.reader(f) if r]
if not rows:
print("FAIL: artifact CSV is empty")
sys.exit(1)
data = rows[1:]
if len(data) != 20:
print(f"FAIL: artifact has {len(data)} data rows, expected 20")
sys.exit(1)
ok = True
for i, (cname, ciso, cval) in enumerate(top20):
row = data[i]
try:
artifact_usd = float(row[3]) * 1e9
except (ValueError, IndexError):
artifact_usd = None
good = (row[1] == cname) and (row[2] == ciso) and (artifact_usd is not None
and abs(artifact_usd - cval) < TOLERANCE_USD)
if not good:
ok = False
print(f"MISMATCH rank {i+1}: source={cname} {ciso} {cval:.3f}B; "
f"artifact={row}")
values = [float(r[3]) for r in data]
if values != sorted(values, reverse=True):
ok = False
print("FAIL: artifact rows are not in descending GDP order")
if ok:
print(f"CHECK OK: {len(top20)} countries match the live World Bank API "
f"(US={top20[0][1]}, China={top20[1][1]}).")
sys.exit(0)
print("CHECK FAIL")
sys.exit(1)
if __name__ == "__main__":
main()
@@ -0,0 +1,21 @@
rank,country,iso3,gdp_nominal_usd_billions
1,United States,USA,27811.517
2,China,CHN,18270.357
3,Germany,DEU,4562.208
4,Japan,JPN,4384.854
5,India,IND,3500.906
6,United Kingdom,GBR,3420.797
7,France,FRA,3056.251
8,Italy,ITA,2316.882
9,Canada,CAN,2196.594
10,Brazil,BRA,2191.132
11,Russian Federation,RUS,2046.285
12,"Korea, Rep.",KOR,1844.801
13,Mexico,MEX,1794.41
14,Australia,AUS,1734.451
15,Spain,ESP,1619.482
16,Indonesia,IDN,1371.167
17,Saudi Arabia,SAU,1218.585
18,Turkiye,TUR,1141.243
19,Netherlands,NLD,1135.476
20,Switzerland,CHE,928.435
1 rank country iso3 gdp_nominal_usd_billions
2 1 United States USA 27811.517
3 2 China CHN 18270.357
4 3 Germany DEU 4562.208
5 4 Japan JPN 4384.854
6 5 India IND 3500.906
7 6 United Kingdom GBR 3420.797
8 7 France FRA 3056.251
9 8 Italy ITA 2316.882
10 9 Canada CAN 2196.594
11 10 Brazil BRA 2191.132
12 11 Russian Federation RUS 2046.285
13 12 Korea, Rep. KOR 1844.801
14 13 Mexico MEX 1794.41
15 14 Australia AUS 1734.451
16 15 Spain ESP 1619.482
17 16 Indonesia IDN 1371.167
18 17 Saudi Arabia SAU 1218.585
19 18 Turkiye TUR 1141.243
20 19 Netherlands NLD 1135.476
21 20 Switzerland CHE 928.435
@@ -0,0 +1 @@
[{"page":1,"pages":1,"per_page":1000,"total":266,"sourceid":"2","lastupdated":"2026-10-08"},[{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"ZH","value":"Africa Eastern and Southern"},"countryiso3code":"AFE","date":"2023","value":1179121535535.41,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"ZI","value":"Africa Western and Central"},"countryiso3code":"AFW","date":"2023","value":938480674635.085,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"1A","value":"Arab World"},"countryiso3code":"ARB","date":"2023","value":3617895070373.04,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"S3","value":"Caribbean small states"},"countryiso3code":"CSS","date":"2023","value":79594075306.6477,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"B8","value":"Central Europe and the Baltics"},"countryiso3code":"CEB","date":"2023","value":2273564082260.43,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"V2","value":"Early-demographic dividend"},"countryiso3code":"EAR","date":"2023","value":14791485754640,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"Z4","value":"East Asia & Pacific"},"countryiso3code":"EAS","date":"2023","value":31597454903562.8,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"4E","value":"East Asia & Pacific (excluding high income)"},"countryiso3code":"EAP","date":"2023","value":21645526054900.4,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"T4","value":"East Asia & Pacific (IDA & IBRD countries)"},"countryiso3code":"TEA","date":"2023","value":21618798469116.4,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"XC","value":"Euro area"},"countryiso3code":"EMU","date":"2023","value":15957338405375.8,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"Z7","value":"Europe & Central Asia"},"countryiso3code":"ECS","date":"2023","value":27758730809930.4,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"7E","value":"Europe & Central Asia (excluding high income)"},"countryiso3code":"ECA","date":"2023","value":2141252006536.72,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"T7","value":"Europe & Central Asia (IDA & IBRD countries)"},"countryiso3code":"TEC","date":"2023","value":5535571828711.02,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"EU","value":"European Union"},"countryiso3code":"EUU","date":"2023","value":18659279022583.3,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"F2","value":"Fragility, Conflict, and Violence (FCV) situations"},"countryiso3code":"FCV","date":"2023","value":2043142894382.41,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"XE","value":"Heavily indebted poor countries (HIPC)"},"countryiso3code":"HPC","date":"2023","value":1060851525652.8,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"XD","value":"High income"},"countryiso3code":"","date":"2023","value":69198099195981.1,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"XF","value":"IBRD only"},"countryiso3code":"IBD","date":"2023","value":39083500948084.9,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"ZT","value":"IDA & IBRD total"},"countryiso3code":"IBT","date":"2023","value":42011330091982.8,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"XH","value":"IDA blend"},"countryiso3code":"IDB","date":"2023","value":1277421993702.09,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"XI","value":"IDA only"},"countryiso3code":"IDX","date":"2023","value":1650407150195.89,"unit":"","obs_status":"","decimal":0},{"indicator":{"id":"NY.GDP.MKTP.CD","value":"GDP (current US$)"},"country":{"id":"XG","value":"IDA total"},"countryiso3code":"IDA","date":"2023","value":2927829143897.98,"unit":"","obs_status":Line truncated
@@ -0,0 +1,26 @@
# Top 20 countries by GDP (nominal, current US$) — 2023
Source: World Bank API (`NY.GDP.MKTP.CD`, 2023). Only ISO 3166-1 alpha-3 countries are counted (World Bank aggregates excluded).
| Rank | Country | ISO3 | GDP nominal (USD billions) |
|---:|---|:--:|---:|
| 1 | United States | USA | 27811.517 |
| 2 | China | CHN | 18270.357 |
| 3 | Germany | DEU | 4562.208 |
| 4 | Japan | JPN | 4384.854 |
| 5 | India | IND | 3500.906 |
| 6 | United Kingdom | GBR | 3420.797 |
| 7 | France | FRA | 3056.251 |
| 8 | Italy | ITA | 2316.882 |
| 9 | Canada | CAN | 2196.594 |
| 10 | Brazil | BRA | 2191.132 |
| 11 | Russian Federation | RUS | 2046.285 |
| 12 | Korea, Rep. | KOR | 1844.801 |
| 13 | Mexico | MEX | 1794.410 |
| 14 | Australia | AUS | 1734.451 |
| 15 | Spain | ESP | 1619.482 |
| 16 | Indonesia | IDN | 1371.167 |
| 17 | Saudi Arabia | SAU | 1218.585 |
| 18 | Turkiye | TUR | 1141.243 |
| 19 | Netherlands | NLD | 1135.476 |
| 20 | Switzerland | CHE | 928.435 |
+261
View File
@@ -0,0 +1,261 @@
ABW
AFG
AGO
AIA
ALA
ALB
AND
ARE
ARG
ARM
ASM
ATA
ATF
ATG
AUS
AUT
AZE
BDI
BEL
BEN
BES
BFA
BGD
BGR
BHR
BHS
BIH
BLM
BLR
BLZ
BMU
BOL
BRA
BRB
BRN
BTN
BVT
BWA
CAF
CAN
CCK
CHE
CHL
CHN
CIV
CMR
COD
COG
COK
COL
COM
CPV
CRI
CUB
CUW
CXR
CYM
CYP
CZE
DEU
DJI
DMA
DNK
DOM
DZA
ECU
EGY
ERI
ESH
ESP
EST
ETH
FIN
FJI
FLK
FRA
FRO
FSM
GAB
GBR
GEO
GGY
GHA
GIB
GIN
GLP
GMB
GNB
GNQ
GRC
GRD
GRL
GTM
GUF
GUM
GUY
HKG
HMD
HND
HRV
HTI
HUN
IDN
IMN
IND
IOT
IRL
IRN
IRQ
ISL
ISR
ITA
JAM
JEY
JOR
JPN
KAZ
KEN
KGZ
KHM
KIR
KNA
KOR
KWT
LAO
LBN
LBR
LBY
LCA
LIE
LKA
LSO
LTU
LUX
LVA
MAC
MAF
MAR
MCO
MDA
MDG
MDV
MEX
MHL
MKD
MLI
MLT
MMR
MNE
MNG
MNP
MOZ
MRT
MSR
MTQ
MUS
MWI
MYS
MYT
NAM
NCL
NER
NFK
NGA
NIC
NIU
NLD
NOR
NPL
NRU
NZL
OMN
PAK
PAN
PCN
PER
PHL
PLW
PNG
POL
PRI
PRK
PRT
PRY
PSE
PYF
QAT
REU
ROU
RUS
RWA
SAU
SDN
SEN
SGP
SGS
SHN
SJM
SLB
SLE
SLV
SMR
SOM
SPM
SRB
SSD
STP
SUR
SVK
SVN
SWE
SWZ
SXM
SYC
SYR
TCA
TCD
TGO
THA
TJK
TKL
TKM
TLS
TON
TTO
TUN
TUR
TUV
TWN
TZA
UGA
UKR
UMI
URY
USA
UZB
VAT
VCT
VEN
VGB
VIR
VNM
VUT
WLF
WSM
XXB
XXE
XXG
XXI
XXL
XXM
XXN
XXP
XXR
XXS
XXW
XXY
YEM
ZAF
ZMB
ZWE