新兴市场的覆盖并不均衡,所以对比之前需要先做覆盖测试。Narwhal 为印度尼西亚和巴西返回月度通胀、政策利率和 GDP 增长,对于月度路由没有数据的国家,则返回 World Bank 的年度序列。
请求一个新兴市场的通胀数据
curl -s "https://api.narwhalapi.com/v1/economics/IDN/inflation" \
-H "Authorization: Bearer $NARWHAL_API_KEY"{
"country": "IDN",
"period": "2026-09",
"year_over_year": "3.28",
"month_over_month": "0.3",
"released_on": "2026-10-29",
"source": {
"publisher": "Statistics Indonesia (BPS)",
"distributor": "OECD"
}
}year_over_year 和 month_over_month 是百分比,period 是所覆盖的月份,released_on 是发布日期。在统计机构已知时,source 会写明发布方和分发方。政策利率路由对每个国家的结构都一样:GET /v1/economics/{country}/central-bank/policy-rate 为印度尼西亚返回 rate 5.75(instrument 为 bi_rate),为巴西返回 13.75(instrument 为 selic_target)。增长数据来自 GET /v1/economics/{country}/gdp-growth。
测试哪些国家有数据
覆盖范围因国家和序列而异,所以不要假设数据齐全,要逐个组合测试。以下是六个大型新兴市场的 HTTP 结果。
| 国家 | 通胀 | 政策利率 | GDP 增长率 | 失业率 |
|---|---|---|---|---|
| 印度尼西亚 (IDN) | 200 | 200 | 200 | 404 |
| 巴西 (BRA) | 200 | 200 | 200 | 404 |
| 墨西哥 (MEX) | 200 | 404 | 200 | 200 |
| 印度 (IND) | 404 | 404 | 200 | 200 |
| 南非 (ZAF) | 404 | 404 | 200 | 200 |
| 土耳其 (TUR) | 404 | 404 | 404 | 404 |
404 会带有问题代码 series_not_found。它表示该路由没有这个国家的已发布序列,把它当作数据缺口,继续往下处理即可。在设计版面之前,请对你需要的其他国家代码运行同样的循环,因为一次运行就能看出表格里哪些单元格可以由月度路由填充,哪些需要年度回退。
读取同一批国家的增长数据
GET /v1/economics/{country}/gdp-growth 返回 year_over_year、quarter_over_quarter、period 和 released_on。各国的发布日期差别很大,所以请把 released_on 打印在数字旁边。
| 国家 | 期间 | 同比 | 季环比 | 发布日期 |
|---|---|---|---|---|
| 印度尼西亚 | 2026-Q2 | 5.3 | 1.3 | 2026-10-30 |
| 巴西 | 2026-Q2 | 1.9 | 0.5 | 2026-10-30 |
| 墨西哥 | 2026-Q2 | 1.9 | 1.4 | 2026-08-24 |
| 南非 | 2026-Q2 | 0.9 | -0.2 | 2026-09-08 |
南非的响应带有 year_over_year_not_seasonally_adjusted,印度的响应带有 not_seasonally_adjusted。把两个国家放进同一张图表之前,请先看这些标志。
用 World Bank 年度数据填补缺口
即使月度路由没有序列,目录里仍可能有年度序列。GET /v1/economics/catalogue 按 q 和 source 搜索。在 wdi 来源中搜索通胀,会返回带有 {country} 占位的 id_template。把占位替换成小写的三字母代码即可,例如印度为 wdi:fp.cpi.totl.zg/ind。
curl -s "https://api.narwhalapi.com/v1/economics/catalogue?source=wdi&q=inflation&limit=1" \
-H "Authorization: Bearer $NARWHAL_API_KEY"{
"results": [
{
"id_template": "wdi:fp.cpi.totl.zg/{country}",
"source": "wdi",
"title": "Inflation, consumer prices (annual %)",
"frequency": "annual",
"unit_label": "Inflation, consumer prices (annual %)"
}
]
}用 GET /v1/economics/catalogue/series/observations?id=... 读取观测值,年度序列的 start 和 end 填年份。每个响应都会重复给出 attribution 和 licence_url,请把它们放在图表旁边。土耳其是个很好的测试对象,因为月度路由里没有它的数据。
curl -s "https://api.narwhalapi.com/v1/economics/catalogue/series/observations?id=wdi:fp.cpi.totl.zg/tur&start=2024&end=2025" \
-H "Authorization: Bearer $NARWHAL_API_KEY"{
"id": "wdi:fp.cpi.totl.zg/tur",
"title": "Inflation, consumer prices (annual %), Turkiye",
"country": "TUR",
"frequency": "annual",
"unit_label": "Inflation, consumer prices (annual %)",
"attribution": "World Bank, World Development Indicators, CC BY 4.0. Values normalised by Narwhal.",
"observations": [
{
"period": "2024",
"value": "58.5064492168435"
},
{
"period": "2025",
"value": "34.8811700293777"
}
]
}把各国并排对比
- 先请求月度数据 脚本对每个国家请求通胀和政策利率。遇到 404 时返回
None。 - 回退到年度序列 如果缺少月度通胀,就读取 2025 年的 World Bank 年度序列,并把这一行标注为年度。遇到 503 时重试一次。
- 计算差值 当通胀和政策利率都存在时,输出政策利率减去通胀的差值,单位为百分点。
import os import time import requests BASE = "https://api.narwhalapi.com" HEAD = {"Authorization": f"Bearer {os.environ['NARWHAL_API_KEY']}"} def get(path, **params): for _ in range(2): r = requests.get(BASE + path, params=params, headers=HEAD, timeout=15) if r.status_code != 503: break time.sleep(3) if r.status_code == 404: return None r.raise_for_status() return r.json() for c in ("IDN", "BRA", "MEX", "IND", "ZAF", "TUR"): infl = get(f"/v1/economics/{c}/inflation") rate = get(f"/v1/economics/{c}/central-bank/policy-rate") if infl: line = f"{c} inflation {infl['year_over_year']}% ({infl['period']})" else: wb = get("/v1/economics/catalogue/series/observations", id=f"wdi:fp.cpi.totl.zg/{c.lower()}", start="2025", end="2025") v = wb["observations"][0] line = f"{c} inflation {float(v['value']):.2f}% (annual {v['period']}, World Bank)" if rate: line += f" | policy rate {rate['rate']}%" if infl: line += f" | gap {float(rate['rate']) - float(infl['year_over_year']):.2f}" else: line += " | no policy rate" print(line)
运行后输出如下。
| 国家 | 通胀 | 口径 | 政策利率 | 政策利率减通胀 |
|---|---|---|---|---|
| IDN | 3.28% | 月度,2026-09 | 5.75% | 2.47 |
| BRA | 4.58% | 月度,2026-09 | 13.75% | 9.17 |
| MEX | 3.45% | 月度,2026-09 | 无 | 无 |
| IND | 2.40% | 年度,2025 | 无 | 无 |
| ZAF | 3.21% | 年度,2025 | 无 | 无 |
| TUR | 34.88% | 年度,2025 | 无 | 无 |
不要把年度行和月度行放在一起排名。某一个月的同比增速与全年数值覆盖的跨度不同,所以每个数字旁边都要放 Basis 列。
为什么巴西的利差比印度尼西亚大得多?
这个差值是政策利率减去同比通胀,巴西为 13.75 减 4.58,印度尼西亚为 5.75 减 3.28。它只是两个已发布数字的简单相减。若要用 1 加利率除以 1 加通胀的精确算法,请看如何计算实际利率。
换一个路由,就能拿到没有序列的国家的数据吗?
月度路由并不覆盖所有国家。请像土耳其的例子那样,在目录里搜索含义相同的序列,并在与月度数字比较之前先看它的 frequency。
为什么目录调用返回了 503?
尚未读取过的 World Bank 序列,可能会返回 503,代码为 upstream_busy。对测试过的序列,几秒后第二次调用成功了,所以脚本会等待并重试一次。目录搜索本身每次都返回 200,503 出现在读取序列时。
发布于。