如果问一个量化新手”什么驱动大宗商品价格”,他大概率会说供给、需求、库存、美元。这些都对,但漏掉了一个最朴素、最常被忽视、也最难被主观操纵的变量:天气。
一场霜冻能让巴西咖啡一夜之间减产 20%;一个比常年更冷的冬天能让天然气库存以肉眼可见的速度被抽干;一次强厄尔尼诺能让南美大豆产区从丰收变歉收。天气是大宗商品世界里少有的、外生于金融市场、且可被客观观测的基本面信号—这正是它作为另类数据的价值。
一、哪些商品被天气”捏着命门”#
不是所有商品都对天气敏感,敏感程度取决于生产/消费对气候的依赖度:
- 农产品(最直接):玉米、小麦、大豆的的单产高度依赖生长季温度、降水与霜冻;咖啡、糖、可可等”软商品”对极端天气的弹性更大,历史上多次因天气出现逼空行情。
- 能源(需求侧驱动):天然气(Henry Hub)的供暖/制冷需求几乎由气温决定;电力负荷与气温强相关;取暖油同理。
- 部分金属(供给侧):铝、锌的冶炼耗电巨大,极端高温/干旱导致的电力短缺或水电不足,会直接压制冶炼开工率。
一句话:凡是产量受单产约束、或需求受温度约束的商品,天气都是核心因子。 对股指、债券而言天气几乎无关,别硬套。
举几个被反复验证的实例:2012 年美国中西部大旱把玉米期货推到历史高点,单产预期下调直接传导到饲料与肉类成本;2021 年欧洲能源危机里,低风速叠加核电检修导致风电与核电出力不足,电价与 TTF 天然气同步暴涨;巴西的 frost(霜冻)事件则数次引发咖啡、糖的逼空行情。这些都不是“新闻扰动”,而是天气→单产/出力→供需→库存→价格的硬传导。值得注意的是,越靠近实物交割、库存越薄的商品,天气的定价权重越高——这也是为什么同样的干旱,对远月合约的影响往往小于近月。
二、关键气象指标#
把”天气”变成可喂进模型的数值,需要落到具体指标上:
- 度日(HDD/CDD):以基准温度 (常用 18°C/65°F)为界, HDD 直接对应供暖需求(天然气、取暖油),CDD 对应制冷需求(电力、天然气)。
- 降水与干旱:标准化降水指数(SPI)、美国干旱监测(USDM)等级,刻画农业墒情。
- ENSO(厄尔尼诺/拉尼娜):用 Niño 3.4 海温距平衡量,是年际尺度上最强的天气信号,能提前数月提示南美降雨异常、澳洲旱涝、东南亚季风强弱。
- 积温与霜冻天数:农作物生长期的有效积温、春季霜冻,直接决定单产。
这些指标的获取门槛比多数人想象得低:气温与 HDD/CDD 可从 NOAA、ECMWF、ERA5 再分析数据免费拿到;ENSO 的 Niño 3.4 指数由 CPC/IRI 每周发布;干旱有美国干旱监测(USDM)与全球 SPI 产品。真正的难点不在“有没有数据”,而在“把全球网格数据降尺度、对齐到具体交割产区与合约月份”——这一步的工程质量,往往决定天气因子是真 alpha 还是噪声。

三、传导机制:天气如何变成价格#
链路很直白,但有几个被低估的缓冲:
容易被忽略的两点:第一,库存是减震器。天气冲击若发生在库存高企时,价格反应会被吸收;只有当库存偏低、逼近交割,天气才会被“计价”。第二,预报会提前反应。现代市场对天气的定价发生在预报阶段而非事实落地阶段,所以“实际气温”往往落后,“预报异常”才是信号。
库存的减震效应可以粗略量化:当某商品库销比低于 5 年 10% 分位时,同样强度的天气冲击带来的价格弹性,往往是高库存时期的 2–3 倍。所以一个稳健的天气因子应当写成“天气异常 × 低库存指示变量”的交互项,而不是单纯的天气水平。这也解释了为什么纯天气模型在库存充裕的年份几乎无效、却在库存紧张的年景大放异彩——它不是年年有用的因子,而是在特定 regime 下集中发力的“条件因子”。

四、Python 实战#
以下三段代码可独立运行(数据为合成序列,便于复现),对应前面的三张图。
4.1 计算 HDD / CDD#
import numpy as np
def degree_days(temp, t_ref=18.0):
"""输入日平均气温序列,返回 HDD 与 CDD 序列。"""
hdd = np.where(temp < t_ref, t_ref - temp, 0.0)
cdd = np.where(temp > t_ref, temp - t_ref, 0.0)
return hdd, cdd
# 合成一年气温(北半球季节性)
days = np.arange(365)
rng = np.random.default_rng(0)
temp = 15 + 12 * np.sin(2 * np.pi * (days - 80) / 365) + rng.normal(0, 2.2, 365)
hdd, cdd = degree_days(temp)
print(f"全年累计 HDD={hdd.sum():.0f}, CDD={cdd.sum():.0f}")python4.2 ENSO 与商品收益的领先关系#
import numpy as np
T = 240
rng = np.random.default_rng(1)
enso = 1.2 * np.sin(2 * np.pi * np.arange(T) / 48) + rng.normal(0, 0.4, T)
# 厄尔尼诺(ENSO>0)通常压制南美大豆供应预期 → 价格负相关
log_p = (0.012 * np.arange(T)
- 0.16 * enso
+ 0.05 * np.roll(enso, 3)
+ np.cumsum(rng.normal(0, 0.012, T)))
ret = np.diff(log_p, prepend=log_p[0])
corr = np.corrcoef(enso, ret)[0, 1]
print(f"ENSO 与商品收益相关系数 = {corr:.3f} (负值=暖相位压制价格)")python4.3 用天气特征预测商品收益(特征重要性)#
import numpy as np
rng = np.random.default_rng(3)
n = 2000
# 合成天气特征
HDD = rng.gamma(2, 1, n)
CDD = rng.gamma(2, 1, n)
precip = rng.normal(0, 1, n)
enso = rng.normal(0, 1, n)
drought = rng.beta(2, 5, n)
heat = rng.normal(0, 1, n)
wind = rng.normal(0, 1, n)
frost = rng.poisson(1, n)
X = np.column_stack([HDD, CDD, precip, enso, drought, heat, wind, frost])
# 真实关系:HDD/CDD 主导,其余较弱
y = (0.30*HDD + 0.26*CDD + 0.14*precip + 0.12*enso
+ 0.07*drought + rng.normal(0, 0.3, n))
# 标准化后用正规方程拟合线性回归,|标准化系数|即线性重要性
Xs = (X - X.mean(0)) / X.std(0)
beta, *_ = np.linalg.lstsq(Xs, y, rcond=None)
names = ["HDD", "CDD", "降水", "ENSO", "干旱", "积温", "风速", "霜冻"]
imp = np.abs(beta) / np.abs(beta).sum()
for name, v in sorted(zip(names, imp), key=lambda z: -z[1]):
print(f"{name:>4}: {v:.1%}")
# 注:树模型(如随机森林)能捕捉非线性与特征交互,生产环境重要性排序更稳健python
五、真实陷阱(不说的都是坑)#
- 预报不确定性:你拿到的是预报不是事实,而市场已经提前定价了预报。用”实测”回测会系统性高估收益,因为实盘你只能用当时的预报。
- 季节性与基差:天气对远月合约和近月合约的影响完全不同。寒冬推高的是近月天然气,远月受库存重建预期压制。不做期限结构分析,容易做反方向。
- 库存缓冲:如前所述,高库存会把天气冲击吸收掉。必须同时跟踪库存/库销比,天气信号 + 低库存才是强组合。
- 空间错配:产区天气和交割品未必同地。巴西下雨不代表交割仓库所在国减产,需映射到可交割供给而非泛泛产区。
- 数据延迟与口径:官方干旱/库存报告有滞后,直接用于日内信号会引入前视。卫星降水、再分析气象数据(ERA5)能补高频缺口,但要处理空间降尺度的误差。
- 过拟合到历史极端年:用 2012 美国大旱或 2021 欧洲天然气危机单点校准模型,会把偶发事件当常态。务必用至少包含多个天气 regime 的样本外窗口验证,并对天气因子做 regime 分层(高库存/低库存)后再评估,而不是汇报一个被极端年拉高的整体夏普。
六、小结#
天气是大宗商品量化里最被低估、也最干净的另类数据之一:它外生于金融市场、可被客观观测、且传导链路清晰。用好它的关键是—盯预报而非实测、结合库存看缓冲、分清近月与远月的期限结构、落到可交割供给而非泛泛产区。把 HDD/CDD、ENSO、干旱指数这些结构化特征接进你的因子框架,你会多出一个与量价几乎正交、且在极端行情里最管用的信息源。不过要提醒一句:天气因子的夏普高度集中在“低库存 + 极端天气”的少数年景,把它当成“常年稳定增厚”的因子会失望;把它当成危机与逼空行情里的“保险与放大器”,才是对的位置。