按 CPI 调整租金的租约,会比较两个基准月份的指数,再把变化率限制在下限和上限之间应用。Narwhal 提供各国的月度 CPI 指数,其余由一个简短的脚本完成。
获取每个基准月份的指数
CPI 租金条款会比较两个基准月份的指数,通常是相隔一年的同一个日历月。本例使用 9 月和英国。一次请求就返回 2022 年 9 月到 2026 年 9 月每个月的指数,下面的响应只保留了第一个和最后一个。
curl -s -H "Authorization: Bearer $NARWHAL_API_KEY" \
"https://api.narwhalapi.com/v1/economics/GBR/cpi/observations?start=2022-09&end=2026-09&limit=100"{
"country": "GBR",
"as_of": "2026-10-21T00:00:00Z",
"index_base": "2015=100",
"observations": [
{
"period": "2022-09",
"value": "123.8"
},
{
"period": "2026-09",
"value": "144.1"
}
],
"next_cursor": null
}observations 按从旧到新的顺序列出每个 period 及其 value。英国的 index_base 是 2015=100,对百分比变化没有影响。as_of 是该序列所反映的日期。这个请求返回 49 个月度值,全部在一页之内,next_cursor 为 null。
用下限和上限计算调整幅度
一年的调整幅度等于新指数除以旧指数再减一。下限设定租金至少上涨多少,上限设定最多上涨多少。实际适用的比率是把调整幅度限制在两者之间的结果,新租金等于旧租金乘以一加适用比率。
import json
import os
import urllib.request
from decimal import Decimal, ROUND_HALF_UP
def get(path):
req = urllib.request.Request(
"https://api.narwhalapi.com" + path,
headers={"Authorization": "Bearer " + os.environ["NARWHAL_API_KEY"]},
)
with urllib.request.urlopen(req, timeout=30) as r:
return json.load(r)
def escalate(rent, cpi_old, cpi_new, floor, cap):
change = cpi_new / cpi_old - 1
applied = min(max(change, floor), cap)
return (rent * (1 + applied)).quantize(Decimal("0.01"), ROUND_HALF_UP), change, applied
data = get("/v1/economics/GBR/cpi/observations?start=2022-09&end=2026-09&limit=100")
cpi = {o["period"]: Decimal(o["value"]) for o in data["observations"]}
rent, floor, cap = Decimal("2000.00"), Decimal("0.02"), Decimal("0.05")
for year in (2023, 2024, 2025, 2026):
old, new = cpi[f"{year - 1}-09"], cpi[f"{year}-09"]
rent, change, applied = escalate(rent, old, new, floor, cap)
print(f"{year}: CPI {old} -> {new}, change {change:.2%}, applied {applied:.2%}, rent {rent}")
本例的租约起始租金为每月 2,000.00,下限为 2%,上限为 5%。每个周年日都用 9 月与上一年的 9 月比较。脚本每年打印一行,例如 2023: CPI 123.8 -> 132.0, change 6.62%, applied 5.00%, rent 2100.00。它全程使用 Decimal 计算,并且每年只把租金四舍五入到分一次,所以如果租约先对比率取整,或者用别的方式对租金取整,结果会相差几分。
| 年份 | 指数变化 | 适用比率 | 租金 |
|---|---|---|---|
| 2023 | 123.8 到 132.0,6.62% | 5.00%(触及上限) | 2,100.00 |
| 2024 | 132.0 到 134.2,1.67% | 2.00%(触及下限) | 2,142.00 |
| 2025 | 134.2 到 139.3,3.80% | 3.80% | 2,223.40 |
| 2026 | 139.3 到 144.1,3.45% | 3.45% | 2,300.01 |
手工验证第一年。132.0 除以 123.8 等于 1.0662,所以指数上涨了 6.62%。这高于上限,因此适用比率是 5%,2,000.00 乘以 1.05 得 2,100.00。2024 年,134.2 除以 132.0 等于 1.0167,低于 2% 的下限,所以租金上涨 2%,变为 2,142.00。
2023 年触及上限,2024 年被下限抬高,后面两年则跟随指数。租金是复利增长的,因为每一年都从上一年的租金出发。如果租约把每年的比率都用于起始租金、不做复利,就需要把起始租金放在单独的变量里。
API 提供什么,租约规定什么
| 项目 | 来源 |
|---|---|
| 每个月的指数值 | Narwhal 的 CPI 观测值 |
| 租约指定了哪个指数 | 租约 |
| 基准月份 | 租约 |
| 下限和上限 | 租约 |
| 取整与复利 | 租约 |
Narwhal 提供的是各国的总体居民消费价格指数。如果合同指定了其他指数,比如核心指数、地区指数或另一家发布机构的指数,这里的数据可能就不是合同所用的数字。运行脚本前请先读懂条款。
租金调整应该用哪个月的指数?
用租约指定的月份。本例用的是 9 月,因为这里的条款是把 9 月与上一年的 9 月比较,而且英国的最新指数是 2026 年 9 月的。用 start 和 end 请求这两个月,或者用 /v1/economics/{country}/cpi?period=YYYY-MM 读取过去的某一个月。
如果周年日时新的月份还没有公布怎么办?
请求一个尚无公布数值的月份,会返回代码为 series_not_found 的 404 问题响应。不带 period 的 CPI 端点返回最新的月份及其 released_on 日期。如果周年日早于基准月份的公布时间,请先保持租金不变,等该月份出来后再运行脚本,或者按租约规定的替代办法处理。
如果物价下降会怎样?
变化率为负时,结果由上下限的限制来决定。下限为 0% 时,适用比率为 0%,租金保持不变。像上面那样下限为 2% 时,租金仍然上涨 2%。没有下限的租约会让租金按变化率下降,同一个函数把下限设为 -1 就能处理这种情况。
其他国家也能做同样的检查吗?
改一下路径里的国家代码即可。端点返回该国的总体指数,所以条款也必须指定这个指数。start 和 end 接受 YYYY、YYYY-MM 或 YYYY-QN,响应中 period 字符串的格式会告诉你该序列是月度还是季度。百分比变化的更多细节见计算 CPI 同比的指南。
发布于。