基础入门
本讲在同一份最小价格样本上同时跑 5 日和 10 日窗口两种均线设置,并用收益、回撤和交易次数这三把最基础的尺子做结果比较。目标是让入门者第一次真正体验“参数变化会怎样影响信号和回测结果”。
第 8 讲是这套 vectorbt 入门短课的收束课,目标是:在同一份最小价格样本上,同时跑 5 日均线和 10 日均线两种窗口设置,并用同一组观察指标比较它们的差异。你不需要在这一讲找到“最优参数”,而是要第一次体验“参数变化会怎样影响信号和回测结果”。
学完这一讲后,你可以直接完成下面几件事:
这一步看起来只是“多跑一个窗口”,但它其实是从单一案例走向参数比较的入口。
前 7 讲已经把最小数据、均线、信号、回测和结果阅读都搭起来了。最自然的收束动作,不是立刻跳到复杂参数网格,而是先做一组最容易解释的参数对比。5 日和 10 日窗口刚好满足几个条件:
所以第 8 讲的重点不是“找到赢家”,而是第一次真正学会比较。
compare_df = single_df.copy()
compare_df['close'] = pd.to_numeric(compare_df['close'], errors='coerce')
当前最重要的原则是:只换窗口,不换样本。这样你看到的差异,才能主要归因于参数变化,而不是因为输入数据换了。
这一讲的重点不是多写几行代码,而是在完全相同的样本上,把两套窗口结果放到同一把尺子下比较。
compare_df['ma_5'] = compare_df['close'].rolling(window=5).mean()
compare_df['ma_10'] = compare_df['close'].rolling(window=10).mean()
print(compare_df[['date', 'close', 'ma_5', 'ma_10']].head(15))
这一步的关键不是代码复杂,而是让你直接看到:10 日均线通常比 5 日均线更慢、更平滑,前面空值也会更多。
compare_df['buy_5'] = compare_df['close'] > compare_df['ma_5']
compare_df['sell_5'] = compare_df['close'] < compare_df['ma_5']
compare_df['buy_10'] = compare_df['close'] > compare_df['ma_10']
compare_df['sell_10'] = compare_df['close'] < compare_df['ma_10']
这一步的意义在于,你现在已经不是只做“一个规则是否成立”,而是在同一张表里同时维护两套规则结果。
import vectorbt as vbt
work = compare_df.set_index('date')
portfolio_5 = vbt.Portfolio.from_signals(
close=work['close'],
entries=work['buy_5'],
exits=work['sell_5']
)
portfolio_10 = vbt.Portfolio.from_signals(
close=work['close'],
entries=work['buy_10'],
exits=work['sell_10']
)
此时第 8 讲的核心条件已经具备了:同一份样本、两套窗口、两轮结果。
comparison = {
'ma_5': {
'total_return': portfolio_5.total_return(),
'max_drawdown': portfolio_5.max_drawdown(),
'trade_count': len(portfolio_5.trades.records_readable),
},
'ma_10': {
'total_return': portfolio_10.total_return(),
'max_drawdown': portfolio_10.max_drawdown(),
'trade_count': len(portfolio_10.trades.records_readable),
},
}
print(comparison)
这一步是第 8 讲真正的收束:你已经不再只是会跑一轮回测,而是能把两轮结果按同一把尺子并列摆出来。
只要两套均线、两套回测对象和一份比较摘要都能稳定得到,这次参数比较就算真正成立。
assert 'ma_5' in compare_df.columns
assert 'ma_10' in compare_df.columns
assert portfolio_5 is not None
assert portfolio_10 is not None
print(comparison)
例如:
只要你能说出至少一条具体差异,这次比较就已经有了分析意义。
不是。结果接近本身也是结果。它说明在当前这份小样本和这组最小规则下,窗口变化带来的影响可能有限。第 8 讲的目标不是强行制造巨大差异,而是训练你如何把参数变化和结果差异放在一起看。
这是正常现象,因为它需要更长的历史窗口。这个现象本身就说明参数变化会影响信号开始起作用的时点。
这通常也很正常。更短的窗口往往更敏感,容易更快跟价格靠近或分离,从而带来更多信号触发。
第 8 讲不要求你给出绝对答案。你只需要先把收益、回撤、交易次数三项对比清楚,形成最基础的比较习惯。
def summarize_portfolio(portfolio):
return {
'total_return': portfolio.total_return(),
'max_drawdown': portfolio.max_drawdown(),
'trade_count': len(portfolio.trades.records_readable),
}
comparison = {
'ma_5': summarize_portfolio(portfolio_5),
'ma_10': summarize_portfolio(portfolio_10),
}
print(comparison)
这个函数把第 7 讲和第 8 讲自然接起来了。你后面再扩成 20 日、30 日窗口,也能继续沿用同一套比较方式。
虽然这套短课到第 8 讲就收束了,但它留下来的方法并没有停在这里。你现在已经具备了最基础的参数研究路径:
这其实就是后面更复杂参数扫描和策略研究的最小原型。也正因为如此,第 8 讲是非常合适的收束课:它没有把难度拉得太高,却让你真正看见了后面还能怎么走。
如果回头看这 8 讲,你会发现它们已经构成了一条完整路径:
这意味着你已经不只是“能跑一个 demo”,而是已经走完了一条从输入、规则到比较的最小回测研究链。
如果你现在已经能在同一份样本上跑出 ma_5 和 ma_10 两轮回测,并用收益、回撤和交易次数去比较它们,那第 8 讲就已经完成了整套 vectorbt 入门短课的收束任务。
本讲是《vectorbt回测入门短课》的第 8/8 讲,当前主题是《比较5日和10日窗口》。
上一讲:第 7 讲《查看收益回撤和交易次数》。
这是本系列的收束课,目标是让你从“会跑一轮最小回测”进一步走到“会做一组最基础的参数比较”。
风险揭示与免责声明
本页面内容仅用于量化研究与技术交流,旨在展示研究方法与流程,不构成对任何金融产品、证券或衍生品的要约、招揽、推荐或保证。
本文所涉历史数据、回测结果与示例参数不代表未来表现,也不应作为投资决策依据。
市场存在波动、流动性与执行偏差等不确定性,任何策略均可能出现收益波动或阶段性失效。
读者应结合自身风险承受能力进行独立判断,并在必要时咨询持牌专业机构意见。