指数期货和现货指数,本质上是同一个东西的两种报价:现货是「今天买一篮子股票要多少钱」,期货是「约定未来某天交割这篮子要多少钱」。两者之间的差价叫基差(basis)。在没有摩擦的世界里,基差被一条铁律钉死:
其中 是无风险融资利率, 是指数成份股的股息率, 是合约剩余期限。这条持有成本(cost of carry) 公式说的是:持有现货到交割日,你要付融资利息 、收股息 ,所以期货理应比现货贵出这部分——贵太多或便宜太多,就出现了期现套利的无风险窗口。
本文讲清四件事,并用可复现代码演示:
- 持有成本模型如何把期、现两个价格绑在一起;
- 基差越出成本带时,正向 / 反向套利怎么锁利润;
- 为什么期货到期必然收敛到现货,这正是套利稳赚的根;
- 「用期货复制现货」时,跟踪误差从哪里来、有多大。
一、基差与无套利带#
把期货相对理论价的偏离写成百分比:
在有效市场里, 只在 0 附近小幅游走——因为一旦它显著为正(期货「太贵」),机构立刻卖期货、买现货把价差压回;一旦显著为负(期货「太便宜」),就买期货、卖现货。于是 被这两条力量夹在一个窄带里,这个带就是无套利带,它的宽度由套利成本决定。

二、正向套利(cash-and-carry):期货太贵时#
为什么基差「必然」收敛?关键在于股指期货是现金交割:到期日交易所直接按现货指数结算,期货价被强制拉到现货价。这比 ETF 折溢价更硬——ETF 的收敛靠 AP 自愿套利,遇到停牌成分股 AP 可以停手;期货的收敛靠交易所交割规则,到期那一刻没有「可以不收敛」的选项。这也是为什么期现套利比 ETF 折溢价套利更接近教科书意义上的无风险。
当 ( 为单边套利成本)时,期货相对现货贵出了成本,做正向套利:
- 买入一篮子现货指数成份股(或买入跟踪该指数的 ETF);
- 卖出等值股指期货合约;
- 持有到合约到期(或基差收敛),期货按交割价结算、现货按市价了结;
- 锁定利润 ≈ 开仓时的基差 − 双边成本。
因为交割日期货价格必须等于现货(否则存在无风险循环套利),所以这笔交易的利润在开仓那一刻就基本锁定了,不依赖后市涨跌。这就是它被称为「无风险」的原因。
三、反向套利:期货太便宜时#
当 时,期货相对现货便宜,做反向套利:
- 卖出一篮子现货(需融券);
- 买入等值股指期货合约;
- 到期收敛时平仓,锁定利润 ≈ 基差绝对值 − 双边成本。
反向套利对散户极不友好:它要求融券卖出现货,而 A 股融券成本和可得性都远差于机构,所以现实中反向套利几乎被券商自营和量化基金垄断。
实务中反向套利还隐含一层融券利息:你卖出现货要持续付融券费,通常高于正向套利的融资利率,所以它所能承受的成本带更窄、触发更难落地。这解释了为什么折价窗口(本例约 633 次)看着不少,真正能跑通的却远少于正向窗口——一半的「便宜期货」对没有券源的账户只是看得到吃不到。
四、用 Python 回测收敛套利#
下面这段代码与生成图表的是同一套逻辑:模拟现货 GBM、按持有成本算理论期货价、叠加一个均值回复的基差,再在 越出成本带时开仓、回带时平仓,按日盯市计盈亏。
import numpy as np
def simulate(T=1500, seed=11):
rng = np.random.default_rng(seed)
dt = 1/252
mu, sig = 0.05, 0.16
S = np.empty(T); S[0] = 3000.0
for t in range(1, T):
S[t] = S[t-1] * np.exp((mu-0.5*sig**2)*dt + sig*np.sqrt(dt)*rng.normal())
r, q = 0.025, 0.018
Tm = 3/12 # 合约剩余期限(简化常数)
fair = S * np.exp((r - q) * Tm) # 持有成本理论价
theta, sigma_b = 0.08, 0.004
basis = np.zeros(T)
for t in range(1, T):
basis[t] = basis[t-1] + theta*(0.0 - basis[t-1]) + sigma_b*rng.normal()
F = fair * np.exp(basis)
return S, F, fair, (r - q) * Tm
S, F, fair, carry = simulate(T=1500, seed=11)
T = len(S)
COST = 0.0012 # 机构单边成本约 0.12%
dev = (F - fair) / fair * 100.0
# 收敛套利:dev>+COST 卖期货买现货,dev<-COST 买期货卖现货,回带平仓
pos = np.zeros(T); ret = np.zeros(T)
for i in range(1, T):
d_prev, d_cur = dev[i-1], dev[i]
if d_cur > COST*100: target = -1 # 正向套利
elif d_cur < -COST*100: target = 1 # 反向套利
else: target = 0 # 回带平仓
cost = 0.0
if target != pos[i-1]:
cost = COST*100 if (pos[i-1]==0 or target==0) else 2*COST*100
ret[i] = pos[i-1] * (d_cur - d_prev) - cost
pos[i] = target
pnl = np.cumsum(ret)
print("累计净收益=%.2f%%, 最大回撤=%.2f%%" %
(pnl[-1], np.min(pnl - np.maximum.accumulate(pnl))))python在这组参数下,样本内累计净收益约 +55%,最大回撤仅约 −2.8%。曲线几乎是一条稳定向上的线——因为它赚的不是市场方向,而是「基差终将收敛」这个被交割机制担保的事实。

五、用期货复制现货:跟踪误差从哪来#
很多人买股指期货不是为套利,而是把它当现货的替代品——比如用沪深 300 期货合成一个「沪深 300 多头」。但期货≠现货,复制出来会有跟踪误差(tracking error),主要来源有三:
- 基差风险:期内期货和现货的相对漂移没被完全对冲,残差就是误差;
- 展期收益/损失(roll yield):近月合约到期前要滚到远月,两段合约的基差结构(contango / backwardation)会系统性地给你正或负的偏移;
- 股息率 估计误差:持有成本公式里的 是预期值,实际派息节奏和预测不符,会慢慢累积成偏差。
展期收益(roll yield)是最容易被忽略的一项。若远月处于 contango(升水),每次把近月滚到远月,你都在「低价平近月、高价开远月」,白白损失基差,长期用期货替代现货会被滚仓磨损慢慢吸血;**backwardation(贴水)**则相反,滚仓反而送钱。所以跟踪误差不是常数,它随期限结构走——回测里固定用近月、忽略滚仓,会系统性低估真实误差。
我们用日度收益差的标准差来度量它。下图中,裸持近月期货、不做任何展期调整时,复制现货的日度跟踪误差约 ——看着小,年化却超过 6%,足以吞掉大部分超额收益。而用「持有成本理论价 + 滚动展期」主动管理复制组合,可以把这条误差压向 0(本例理论复制与现货的日度差恒为 0,正是持有成本模型成立的应有结论)。
![]()
六、真实陷阱(别把「无风险」当真)#
1. 保证金与融资不是免费的。 正向套利要同时占用现货资金和期货保证金,融资成本 若高于你测算值,利润直接缩水甚至转负;保证金追缴还会在极端波动里逼你砍仓。
2. 展期不是无成本的。 远月通常处于 contango(升水),每次滚仓都白白损失一点基差,长期持有期货替代现货会被「滚仓磨损」慢慢吸血。
3. 股息率 估不准。 用历史均值当 ,遇到集中分红或政策变化,持有成本理论价本身就偏了,套利触发点跟着错。
4. 合约到期跳跃。 近月合约到期前流动性骤降、基差可能因逼仓或平仓集中而剧烈摆动,收敛未必平滑。
5. 现货卖空约束。 反向套利需要融券卖现货,A 股融券券源紧、成本高,散户基本做不了,等于把一半(更肥的折价)窗口让给机构。
6. 幸存者偏差。 回测默认交割日基差必收敛到 0、保证金永远够、券永远借得到——实盘里这些「必然而然」恰恰是风险爆发的地方。
七、小结#
- 期、现被持有成本公式 钉在一起,基差越出成本带即出现期现套利窗口;
- 正向套利(卖期买现)靠交割日基差必收敛锁利润,是样本内几乎零回撤的「无风险」结构(本例 +55%、回撤 −2.8%);
- 但「无风险」有三个隐藏前提:融资/保证金成本可控、能融券做反向、展期磨损可承受——散户往往只满足第一条;
- 用期货当现货替代品要算清跟踪误差:裸持近月不展期残留基差风险约 0.41%/日,必须用持有成本调整 + 主动滚仓把它压下去。
附:本文所有图表与数值均来自上方可运行代码(现货/期货模拟 + 持有成本理论价 + 收敛套利 + 跟踪误差度量),参数与结果一致,可直接复现。