量化工具:Python实现库存-基差相关性分析与可视化
好,咱们进入实战环节。
前面几章我们聊了不少理论,库存怎么影响基差,基差怎么反映供需。但说实话,光靠眼睛看K线图,很难捕捉到那种微妙的联动关系。我个人的习惯是——让数据说话。
这一章,我们就用Python把库存和基差的关系量化出来。你想想看,当你能用一行代码算出相关系数,用一张图看清两个变量的走势,那种掌控感是完全不一样的。
准备工作:你需要哪些数据?
做这个分析,核心数据就两样:
- 库存数据:比如某个品种的社会库存、港口库存或交易所仓单。频率最好是周度或日度。
- 基差数据:现货价格减去期货主力合约价格。注意,基差有正负,别搞反了。
我在项目中遇到过一个问题:库存数据经常有缺失,尤其是节假日前后。嗯,这里要注意,缺失值处理不好,相关系数会失真。
第一步:数据导入与清洗
假设我们已经有了一个CSV文件,里面包含日期、库存、基差三列。代码很简单:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 读取数据
df = pd.read_csv('inventory_basis.csv', parse_dates=['date'])
df.set_index('date', inplace=True)
# 看一眼数据长什么样
print(df.head())
# 处理缺失值——我习惯用前向填充
df.fillna(method='ffill', inplace=True)
# 删除仍然存在的空值
df.dropna(inplace=True)
为什么要用前向填充?因为库存数据通常不会突变,上周的库存对本周有很强的参考意义。我曾经试过用插值法,结果把一些异常波动给平滑掉了,反而掩盖了真实的市场信号。
第二步:计算滚动相关系数
静态的相关系数只能告诉你「整体上」库存和基差有没有关系。但做交易的人都知道,这种关系是动态的。有时候正相关,有时候负相关,有时候根本不相关。
所以我更看重滚动相关系数。说白了,就是用一个固定窗口,比如20个交易日,不断计算这段时间内的相关系数,然后画成一条曲线。
# 计算滚动相关系数,窗口设为20天
window = 20
df['rolling_corr'] = df['inventory'].rolling(window=window).corr(df['basis'])
# 看看结果
print(df[['inventory', 'basis', 'rolling_corr']].tail(10))
第三步:可视化——让关系一目了然
光看数字不够直观。我一般会画三张图:
- 库存与基差的走势对比图(双Y轴)
- 滚动相关系数的时序图
- 散点图 + 回归线
下面这段代码,我用了很多年,改过好几版,现在拿出来分享给你:
fig, axes = plt.subplots(3, 1, figsize=(12, 10))
# 图1:库存 vs 基差(双Y轴)
ax1 = axes[0]
color1 = 'tab:blue'
color2 = 'tab:red'
ax1.set_ylabel('库存', color=color1)
ax1.plot(df.index, df['inventory'], color=color1, label='库存')
ax1.tick_params(axis='y', labelcolor=color1)
ax2 = ax1.twinx()
ax2.set_ylabel('基差', color=color2)
ax2.plot(df.index, df['basis'], color=color2, label='基差', alpha=0.7)
ax2.tick_params(axis='y', labelcolor=color2)
ax1.set_title('库存与基差走势对比')
# 图2:滚动相关系数
axes[1].plot(df.index, df['rolling_corr'], color='green', linewidth=2)
axes[1].axhline(y=0, color='gray', linestyle='--')
axes[1].axhline(y=0.5, color='orange', linestyle='--', alpha=0.5)
axes[1].axhline(y=-0.5, color='orange', linestyle='--', alpha=0.5)
axes[1].set_title(f'滚动相关系数(窗口={window}天)')
axes[1].set_ylabel('相关系数')
axes[1].set_ylim([-1, 1])
# 图3:散点图 + 回归线
sns.regplot(x='inventory', y='basis', data=df, ax=axes[2],
scatter_kws={'alpha':0.5}, line_kws={'color':'red'})
axes[2].set_title('库存 vs 基差 散点图')
plt.tight_layout()
plt.show()
这三张图放在一起,你能看到什么?
- 第一张图告诉你:两个变量是不是同涨同跌?还是反向运动?
- 第二张图告诉你:这种关系什么时候强,什么时候弱。
- 第三张图告诉你:整体趋势是正相关还是负相关,有没有明显的异常点。
第四步:输出分析报告
做量化分析,不能只给自己看。我习惯把关键指标整理成表格,方便团队讨论:
# 计算整体相关系数
overall_corr = df['inventory'].corr(df['basis'])
# 统计滚动相关系数的分布
corr_stats = df['rolling_corr'].describe()
# 找出相关系数最强的时段
strong_positive = df[df['rolling_corr'] > 0.7]
strong_negative = df[df['rolling_corr'] < -0.7]
print(f"整体相关系数: {overall_corr:.3f}")
print("\n滚动相关系数统计描述:")
print(corr_stats)
print(f"\n强正相关时段(r > 0.7): {len(strong_positive)} 个交易日")
print(f"强负相关时段(r < -0.7): {len(strong_negative)} 个交易日")
输出结果可以整理成这样的表格:
| 指标 | 数值 |
|---|---|
| 整体相关系数 | -0.42 |
| 滚动相关系数均值 | -0.38 |
| 滚动相关系数标准差 | 0.31 |
| 强正相关天数占比 | 8.2% |
| 强负相关天数占比 | 22.5% |
看到这个表格,你可能会问:整体相关系数只有-0.42,是不是说明库存和基差关系不大?
别急。你看滚动相关系数的标准差是0.31,说明这个关系波动很大。有时候强负相关(-0.7以下),有时候甚至变成正相关。这才是关键——关系不稳定,恰恰意味着有交易机会。当相关系数偏离均值太远时,往往预示着回归。
知识体系:库存-基差分析的核心逻辑
说了这么多,我画张图帮你理一理思路:
这张图把整个分析流程串起来了。从数据输入到最终决策,每一步都有它的意义。我个人觉得,最容易被忽视的是「数据处理」这一步。很多新手拿到数据就直接算相关系数,结果被缺失值和异常点带偏了方向。
实战中的几点体会
- 不要迷信相关系数:0.8的相关系数看起来很漂亮,但如果样本量只有10个,那可能就是运气。我一般要求至少30个样本点才敢说「有关系」。
- 注意滞后效应:库存变化往往领先于基差变化。你可以试试把库存数据向前平移几天,再算相关系数,有时候效果更好。
- 分阶段分析:把数据按牛熊市分段,分别算相关系数。你会发现,牛市里库存和基差的关系,跟熊市里完全不一样。
好了,这一章的内容就到这里。代码你拿去跑一跑,换成你自己的数据,看看能发现什么规律。记住,工具是死的,市场是活的。再好的量化模型,也要结合你对基本面的理解来用。
公众号:蓝海资料掘金营,微信deep3321