【量化系统从零构建 #16】回测(上):向量化回测引擎·成本模型
摘要:【量化系统从零构建 #16】回测(上):向量化回测引擎·成本模型 系列:《量化系统从零构建》|连载项目 · 纯 GET 取数 · 仅依赖 requests 适用:想把 #14/#15 的信号变成「可
系列:《量化系统从零构建》|连载项目 · 纯 GET 取数 · 仅依赖 requests
适用:想把 #14/#15 的信号变成「可复现收益曲线」的读者;数据由智兔数服提供,本篇写日频向量化回测引擎 + 手续费/滑点成本模型,不依赖任何行情终端,也不发起网络请求。所有数值均为算法演示,不构成收益承诺。
1. 你将得到什么
backtest:输入价格序列与目标信号(1多/0空/-1空),输出权益曲线与总收益率;切换仓位时扣双边成本。- 成本模型:
fee(手续费)+slippage(滑点),切换日按成交额扣减。 - 本篇交付:回测引擎底座,#17 在其上算绩效指标与做参数遍历。
2. 本篇取数约定
本篇是回测层,不发起网络请求,吃 #09 的 close 序列与 #14/#15 的信号序列。数据来自 智兔数服(www.zhituapi.com)。纯 Python 遍历(向量化即逐根 bar 计算,不引 numpy)。
3. 回测与成本
| 项 | 说明 |
|---|---|
| 信号 | 每日目标方向:1 多 / 0 空 / -1 空 |
| 日收益 | pos * (price[i]/price[i-1]-1) |
| 成本 | 切换日扣 fee+slippage,由多/空互换再双边 ×2 |
成本只在「换仓」时发生,持有期不重复扣,避免虚高换手成本。
4. 核心模板函数
import sys
def backtest(prices, signals, fee=0.0003, slippage=0.001):
"""日频回测:prices/signals 等长;signals 为每日目标方向(1/0/-1)。
返回 (权益曲线, 总收益率)。切换仓位时扣双边成本。"""
eq = [1.0]
pos = 0
for i in range(1, len(prices)):
ret = prices[i] / prices[i - 1] - 1
day_ret = pos * ret
if signals[i] != pos:
cost = (fee + slippage) * 2 if pos != 0 else (fee + slippage)
pos = signals[i]
else:
cost = 0
eq.append(eq[-1] * (1 + day_ret) * (1 - cost))
return eq, eq[-1] - 1
def run_check():
# 合成:价格单边涨,全程持有,非真实行情
prices = [10, 10.1, 10.2, 10.3, 10.4, 10.5]
hold = [1] * len(prices)
eq, tot = backtest(prices, hold)
assert eq[0] == 1.0
assert tot > 0 # 上涨市持有应盈利
assert 1.03 < eq[-1] < 1.05 # 约 +3.8%:首日 pos=0 无收益且扣开仓成本,低于裸涨 5%
# 空仓信号 -> 无盈亏
flat = [0] * len(prices)
_, tot2 = backtest(prices, flat)
assert abs(tot2) < 1e-9
# 切换扣成本:首日多->次日空,涨市下应微亏
sw = [1, -1] + [0] * (len(prices) - 2)
_, tot3 = backtest(prices, sw)
assert tot3 < 0
print("校验通过")
if __name__ == "__main__":
if len(sys.argv) > 1 and sys.argv[1] == "--check":
run_check()
else:
print("本篇基于价格序列与信号回测,不发起网络;用 #09 的 close 与 #15 的 market_timing 喂入即可。")
5. 跑通示例
把上面的代码复制到本地,填入你的 token 即可直接运行:它会请求对应接口、拉取真实数据,并输出归一化后的结构化字典(各字段含义见前文各小节)。
6. 坑与注意事项
- 成本只在换仓日扣:持有期重复扣成本会严重低估收益,务必
if signals[i] != pos才扣。 - 信号是「目标方向」不是「收益率」:回测用
pos*日收益,信号只定方向,幅度由价格给。 - 前视需用滞后信号:实盘第 i 日持仓由第 i-1 日信号决定,回测别用当日未发生的信号。
- 不承诺收益:回测曲线是历史算法演示,不代表未来,更不构成收益保证。
7. 小结与下篇预告
本篇交出日频回测引擎 + 成本模型,把信号变成权益曲线。回测底座到位。
下一篇计划写 #17《回测(下):绩效指标·参数遍历》:在 backtest 输出上算年化、最大回撤、夏普,并做参数遍历与过拟合警示。
8. 免责声明
本文仅演示回测引擎与成本模型的算法,所有代码示例均以合成数据校验,未含任何真实数据;文中示例数据仅作演示用途,不构成投资建议,亦不承诺收益。
免费领取证书
数据来自 智兔数服(www.zhituapi.com):零 SDK、纯 GET、免费版即可起步。
领取路径:进入 www.zhituapi.com → 点击「请求证书」→「证书获取」→「免费版」(邮箱验证 3 步即可拿到 token)。
把代码里的 你的智兔token 换成你拿到的真实 token,上面的脚本就能直接打印回测权益曲线与绩效数据。