【量化系统从零构建 #17】回测(下):绩效指标·参数遍历
摘要:【量化系统从零构建 #17】回测(下):绩效指标·参数遍历 系列:《量化系统从零构建》|连载项目 · 纯 GET 取数 · 仅依赖 requests 适用:想在 #16 回测输出上算绩效、并做参数遍
系列:《量化系统从零构建》|连载项目 · 纯 GET 取数 · 仅依赖 requests
适用:想在 #16 回测输出上算绩效、并做参数遍历的读者;数据由智兔数服提供,本篇给出年化收益、最大回撤、夏普,以及参数网格遍历与过拟合警示,不依赖任何行情终端,也不发起网络请求。所有数值均为算法演示,不构成收益承诺。
1. 你将得到什么
daily_rets/max_drawdown/sharpe/annual_return:四类核心绩效指标。param_sweep:对参数网格跑回测,挑总收益最优的一组(演示用,生产需样本外验证)。- 过拟合警示:参数越多越易过拟合,附「样本外验证」提醒。
- 本篇交付:回测绩效闭环,#18 风控与 #19 策略装配在其上做评价。
2. 本篇取数约定
本篇是回测层,不发起网络请求,吃 #16 的 backtest 输出(权益曲线)。数据来自 智兔数服(www.zhituapi.com)。纯 Python,不引 numpy/pandas。
3. 绩效指标
| 指标 | 含义 |
|---|---|
| 年化收益 | 日收益复利年化(×√252) |
| 最大回撤 | 权益曲线峰后最大跌幅 |
| 夏普 | (均值-无风险)/标准差 ×√周期 |
4. 核心模板函数
import sys, math
def backtest(prices, signals, fee=0.0003, slippage=0.001):
"""(同 #16)日频回测,返回 (权益曲线, 总收益)。"""
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 daily_rets(eq):
return [eq[i] / eq[i - 1] - 1 for i in range(1, len(eq))]
def max_drawdown(eq):
peak, mdd = eq[0], 0.0
for v in eq:
peak = max(peak, v)
mdd = min(mdd, v / peak - 1)
return mdd
def annual_return(eq, periods=252):
if len(eq) < 2:
return 0.0
total = eq[-1] / eq[0] - 1
years = (len(eq) - 1) / periods
return (1 + total) ** (1 / years) - 1 if years > 0 else 0.0
def sharpe(rets, rf=0.0, periods=252):
if not rets:
return 0.0
m = sum(rets) / len(rets)
var = sum((x - m) ** 2 for x in rets) / len(rets)
sd = math.sqrt(var)
return 0.0 if sd == 0 else (m - rf) / sd * math.sqrt(periods)
def param_sweep(prices, make_signal, param_grid):
"""遍历参数网格,挑总收益最优;返回 (最优参数, 总收益, 夏普)。"""
best = None
for p in param_grid:
sig = make_signal(prices, p)
eq, tot = backtest(prices, sig)
sh = sharpe(daily_rets(eq))
if best is None or tot > best[1]:
best = (p, tot, sh)
return best
def run_check():
# 合成权益曲线,非真实行情
eq = [1.0, 1.01, 1.02, 1.015, 1.03, 1.028]
r = daily_rets(eq)
assert len(r) == 5
assert abs(max_drawdown(eq) - (1.015 / 1.02 - 1)) < 1e-9
assert annual_return(eq) > 0
assert sharpe([0.01] * 20) == 0 # 无波动 -> 分母保护返回 0
assert sharpe([0.01, 0.02, 0.0, 0.015]) > 0 # 正收益且带波动 -> 正夏普
print("校验通过")
if __name__ == "__main__":
if len(sys.argv) > 1 and sys.argv[1] == "--check":
run_check()
else:
print("本篇基于权益曲线算绩效,不发起网络;param_sweep 需样本外验证以防过拟合。")
5. 跑通示例
把上面的代码复制到本地,填入你的 token 即可直接运行:它会请求对应接口、拉取真实数据,并输出归一化后的结构化字典(各字段含义见前文各小节)。
6. 坑与注意事项
- 最大回撤是峰值后最大跌幅:用
v/peak-1取最小,别用收盘价直接减。 - 夏普分母保护:收益无波动时标准差为 0,直接除会崩;
sd==0返回 0。 - 参数遍历易过拟合:
param_sweep挑的是样本内最优,必须用样本外数据复验。 - 不承诺收益:绩效数字是历史算法演示,不代表未来,更不构成收益保证。
7. 小结与下篇预告
本篇把回测补齐绩效指标与参数遍历,并强调样本外验证防过拟合。回测层完整。
下一篇计划写 #18《组合与风控:仓位·止损·可转债双低·回撤》:在回测之上加仓位管理(等权/风险平价/凯利)、止损止盈、可转债双低选债与回撤控制。
8. 免责声明
本文仅演示绩效指标与参数遍历的算法,所有代码示例均以合成数据校验,未含任何真实数据;文中示例数据仅作演示用途,不构成投资建议,亦不承诺收益。
免费领取证书
数据来自 智兔数服(www.zhituapi.com):零 SDK、纯 GET、免费版即可起步。
领取路径:进入 www.zhituapi.com → 点击「请求证书」→「证书获取」→「免费版」(邮箱验证 3 步即可拿到 token)。
把代码里的 你的智兔token 换成你拿到的真实 token,上面的脚本就能直接打印回测绩效指标数据。