VeighNa CtaBacktester CTA回测研究模块完全指南:数据下载、历史回测、结果分析与参数优化
【免费下载链接】vnpy基于Python的开源量化交易平台开发框架项目地址: https://gitcode.com/gh_mirrors/vn/vnpy
CtaBacktester 是 VeighNa(vnpy)平台中面向 CTA 策略的图形化回测研究模块,它把"数据下载 → 历史回测 → 结果分析 → 参数优化 → 代码迭代"整条研究链路收敛到一套交互式界面中,无需编写 Jupyter Notebook 脚本即可完成策略的快速验证与参数寻优。阅读本篇指南后,你将掌握该模块的加载启动方式、历史数据的一键下载(数据服务/IB 两种来源)、回测参数的完整配置口径、四张业绩图表与统计指标的正确解读方法、委托/成交/每日盈亏/K线图表的明细核查技巧,以及穷举与遗传两种多进程参数优化算法的原理与实操,并了解其底层与 VeighNa 核心框架(数据库抽象、数据服务抽象、优化引擎、回测撮合)的协作关系。
功能简介
CtaBacktester 是 VeighNa 框架中用于CTA 回测研究的功能模块(对应独立项目 vnpy_ctabacktester,在 README.md 的模块清单中归类为"CTA策略回测模块"),用户可以通过其 UI 界面便捷完成以下四类任务:
- 数据下载:一键获取回测所需的历史行情数据并存入本地数据库;
- 历史回测:基于本地历史数据驱动 CTA 策略,模拟撮合得到完整交易过程;
- 结果分析:通过统计指标、业绩图表与逐笔明细多维度评估策略表现;
- 参数优化:使用穷举或遗传算法自动搜索最优策略参数组合。
模块的运行依赖 VeighNa Trader 主程序框架(MainEngine应用模块注册机制),同时其回测功能对接 CTA 策略引擎(vnpy_ctastrategy)提供的策略模板与回测引擎,优化能力则复用核心框架vnpy.trader.optimize中抽象出的通用优化工具(详见 optimize.py)。
加载启动
CtaBacktester 的加载方式与 VeighNa 其他应用模块一致,提供图形化与脚本化两种途径。
VeighNa Station 加载
启动登录 VeighNa Station 后,点击【交易】按钮,在配置对话框中的【应用模块】栏勾选【CtaBacktester】即可随 VeighNa Trader 一起启动。
脚本加载
如果使用自定义启动脚本,则需要在脚本中完成模块导入与注册,参考仓库中 examples/veighna_trader/run.py 的完整示例:
from vnpy.event import EventEngine from vnpy.trader.engine import MainEngine from vnpy.trader.ui import MainWindow, create_qapp # 写在顶部:导入回测模块 from vnpy_ctabacktester import CtaBacktesterApp # 写在创建main_engine对象后:注册应用模块 def main(): qapp = create_qapp() event_engine = EventEngine() main_engine = MainEngine(event_engine) main_engine.add_app(CtaBacktesterApp) # 注册CtaBacktester应用 main_window = MainWindow(main_engine, event_engine) main_window.showMaximized() qapp.exec()从代码结构看,CtaBacktesterApp遵循 VeighNa 的App抽象(定义于 app.py),通过MainEngine.add_app()注册后,主窗口会自动生成对应的功能菜单与按钮入口。注意启动脚本所在目录决定了运行时目录,模块的策略扫描、配置读写均以该目录为基准。
启动模块
对于用户自行开发的策略,需要放到 VeighNa Trader 运行时目录下的strategies目录中,才能被回测模块识别加载。运行时目录的具体路径,可以在 VeighNa Trader 主界面顶部的标题栏查看。
提示:VeighNa 通过
_get_trader_dir逻辑解析运行时目录(见 utility.py):若当前工作目录下存在.vntrader文件夹则优先使用,否则使用系统用户主目录下的.vntrader文件夹;TEMP_DIR(即.vntrader目录)随后会被加入sys.path,因此放置其中的策略模块可被直接导入。
对于在 Windows 上默认安装的用户来说,放置策略的 strategies 目录路径通常为:
C:\Users\Administrator\strategies其中Administrator为当前登录 Windows 的系统用户名。
启动 VeighNa Trader 后,在菜单栏中点击【功能】->【CTA回测】,或者点击左侧按钮栏的回测图标,即可打开图形化的回测界面。界面左侧为操作面板(数据下载、回测设置、参数优化、日志输出与委托/成交/每日盈亏明细按钮),右侧为回测结果的业绩图表展示区。
下载数据
在开始策略回测之前,首先需要保证数据库内有足够的历史数据。CtaBacktester 模块提供了一键下载历史数据的功能:下载的数据会直接写入 VeighNa 所配置的本地数据库(默认 SQLite),后续回测时直接读取,无需重复下载。
下载参数
下载数据需要填写本地代码、K线周期、开始日期以及结束日期四个字段信息:
- 本地代码
- 格式为"合约代码 + 交易所名称",即 VeighNa 的
vt_symbol规范,核心框架通过extract_vt_symbol()按.分隔解析(见 utility.py); - 例如
IF888.CFFEX、rb2105.SHFE; - 交易所名称取值可参考 constant.py 中的
Exchange枚举,国内包括CFFEX(中金所)、SHFE(上期所)、CZCE(郑商所)、DCE(大商所)、INE(能源中心)、GFEX(广期所)、SSE/SZSE(沪深交易所)等,外盘包括GLOBEX、CME、NYMEX、ICE、SGX、HKFE等。
- 格式为"合约代码 + 交易所名称",即 VeighNa 的
- K线周期
1m(1分钟K线)1h(1小时K线)d(日K线)w(周K线)tick(一个Tick)- 上述枚举与 constant.py 中
Interval枚举的取值一一对应。
- 开始和结束日期
- 格式为
yyyy/mm/dd; - 例如
2018/2/25、2021/2/28。
- 格式为
填写完成后,点击下方【下载数据】按钮启动下载任务,下载成功后会输出日志提示。注意下载完成后的历史数据保存在本地数据库中,后续回测时可以直接使用,无需每次都重复下载。
数据来源:数据服务(期货、股票、期权)
以 RQData 为例,RQData 提供国内期货、股票以及期权的历史数据。在使用前需要保证数据服务已经正确配置(配置方法详见 数据库与数据服务配置 与 数据服务接入 部分)。打开 CtaBacktester 时会自动执行数据服务登录初始化,若成功则会输出"数据服务初始化成功"的日志。
从核心框架看,数据服务通过BaseDatafeed抽象类接入(见 datafeed.py),其query_bar_history()/query_tick_history()接口统一封装了向第三方数据源请求历史行情的逻辑;而数据库侧则通过BaseDatabase抽象类提供save_bar_data()/save_tick_data()等持久化接口(见 database.py)。下载任务的实际链路可以概括为:调用数据服务接口拉取历史行情 → 写入本地数据库 → 回测时从数据库读取。
数据来源:IB(外盘期货、股票、现货等)
Interactive Brokers 盈透证券(IB)提供丰富的外盘市场历史数据下载(包括股票、期货、期权、现货等)。注意下载前需要先启动 IB TWS 交易软件,并在 VeighNa Trader 主界面连接好 IB 接口,并订阅所需合约行情。下载成功后会输出相应的完成日志。
执行回测
准备好数据后即可开始使用历史数据对策略进行回测研究,回测时需要配置好相关的参数:
- 策略品种
- 交易策略:在下拉框中选择要回测的策略名称(仅显示放在 strategies 目录下、被成功扫描加载的 CTA 策略类);
- 本地代码:注意不要漏掉交易所后缀。
- 数据范围
- 开始/结束日期,格式详见上文"下载数据"部分的介绍。
- 交易成本
- 滑点:下单交易点位与实际交易点位的差别,回测撮合时会在委托价基础上加减滑点后确定成交价;
- 百分比手续费:填写数字即可(如 0.5 表示成交金额的 0.5%),不要填写百分数;
- 固定手续费:可以手续费填 0,然后把手续费除以合约乘数后,加在滑点中。
- 合约属性
- 合约乘数:合约的交易单位,用于将点位盈亏换算为资金盈亏;
- 价格跳动:合约价格的最小变动价位(即 pricetick),撮合与价格取整均依赖该值;
- 回测资金:账户初始资金;
- 合约模式:正向(即普通的多空双向合约,非反向/币本位合约)。
配置完成后,点击下方的【开始回测】按钮,会弹出策略参数配置对话框,用于设置策略参数(即策略类中声明的parameters对应的字段与取值)。点击【确定】按钮后开始执行回测任务,同时日志界面会输出回测进度相关信息。
回测完成后,会自动在右侧区域显示策略回测业绩的统计指标以及相关图表。
若数据库没有准备好所需的历史数据就点击【开始回测】,则日志界面会输出"历史数据不足,回测终止"的日志,回测任务不会继续执行。从版本演进看,CTA 回测相关实现还针对"加载的历史数据为空则不执行后续回测"、"回测中资金爆仓(小于等于 0)的检查"等边界情况做了专门处理(见 CHANGELOG.md 相关条目)。
回测引擎的撮合原理
从源码结构看,CTA 回测引擎(属于 vnpy_ctastrategy 项目,不在本仓库内)负责把历史 K 线逐根推送给策略并模拟撮合:
- 成交价并非原始下单价格:回测引擎基于当时的行情数据和下单价格进行撮合后算出成交价(通常是委托价加上/减去滑点,再按价格跳动取整);
- 账户与持仓计算:引擎根据合约乘数、手续费率(百分比/固定)、滑点等参数逐笔核算资金变动;
- 每日盈亏:采用期货市场普遍使用的逐日盯市(Marking-to-Market)规则,以每日收盘价对持仓进行结算。
回测结果的统计计算与绩效指标(如夏普比率、收益回撤比等)由回测引擎统一产出,CtaBacktester 界面负责展示。本仓库 vnpy/alpha/strategy/backtesting.py 中同样存在一套面向 Alpha 多因子策略的BacktestingEngine实现(set_parameters/add_strategy/load_data等方法),可视为同一套"参数设置 → 策略实例化 → 数据加载 → 逐bar驱动 → 结果统计"回测范式在组合策略方向的印证。
结果分析
业绩图表
右侧的业绩图表由以下四张子图构成,均以时间或盈亏数值为轴,帮助从不同维度审视策略表现:
**【账户净值】**图的横轴是时间,纵轴是资金,体现了账户净值在交易时段内随着交易日变化的情况,是判断策略整体盈利能力的直观曲线。
**【净值回撤】**图的横轴是时间,纵轴是回撤,体现了净值从最近高点回撤程度随着交易日变化的情况,用于衡量策略持有过程中的风险暴露。
**【每日盈亏】**图的横轴是时间,纵轴是日盈亏的金额(采用逐日盯市规则以收盘价结算),体现了整个回测周期内策略的每日盈亏变化情况,可用于观察盈亏在时间上的集中度与稳定性。
**【盈亏分布】**图的横轴是每日盈亏的数值,纵轴是该盈亏数值的出现概率,体现了整体每日盈亏的概率分布情况,可辅助判断策略盈利的稳定性与尾部风险。
统计指标
统计指标区域用于显示策略历史回测业绩的相关统计数值。根据数据类型,指标可以分类为:
- 日期信息
- 首个交易日
- 最后交易日
- 总交易日
- 盈利交易日
- 亏损交易日
- 资金盈亏
- 起始资金
- 结束资金
- 总收益率
- 年化收益
- 最大回撤
- 百分比最大回撤
- 总盈亏
- 交易成本
- 总手续费
- 总滑点
- 总成交额
- 总成交笔数
- 日均数据
- 日均盈亏
- 日均手续费
- 日均滑点
- 日均成交额
- 日均成交笔数
- 日均收益率
- 收益标准差(日均)
- 绩效评价
- 夏普比率
- 收益回撤比
其中"总收益率 / 年化收益 / 最大回撤 / 夏普比率 / 收益回撤比"是评判策略的核心指标,也是参数优化时常用的目标函数候选。
详细信息
回测完成后,可点击左侧区域的【委托记录】按钮,查看回测过程中策略逐笔委托的细节信息(委托时间、方向、价格、数量、状态等)。
如果发现表格内容显示不完整,可以单击鼠标右键弹出菜单后,选择【调整列宽】按钮,即可进行自动列宽缩放。
表格也支持一键将表内数据保存为 CSV 文件,在上一步右键弹出的菜单中,点击【保存数据】按钮,即可弹出选择保存文件名的对话框。
回测过程中策略发出委托的成交价不一定是原始下单的价格,而由回测引擎基于当时的行情数据和下单价格进行撮合后算出。每笔委托对应的具体成交细节可以点击【成交记录】按钮后查看,包括逐笔成交的时间、价格、数量以及对应的委托。
点击【每日盈亏】按钮后,可以看到策略每日盈亏细节。这里每日盈亏的统计采用期货市场普遍使用的逐日盯市(Marking-to-Market)规则进行计算:
- 持仓盈亏:今日开盘持仓的部分,以昨收盘价开仓、今收盘价平仓,计算出的盈亏金额;
- 交易盈亏:今日日内成交的部分,以成交价格开仓、今收盘价平仓,计算出的盈亏金额;
- 总盈亏:汇总持仓盈亏和交易盈亏后的金额;
- 净盈亏:总盈亏扣除手续费和滑点后的金额,也是最终计算显示四张图表时用到的每日盈亏金额。
K线图表
点击【K线图表】按钮,即可打开用于显示回测 K 线数据,以及策略具体买卖点位置的图表。注意绘图耗时可能需要一定时间(通常在数十秒到几分钟),请耐心等待。
K线图表中的图例说明可以在窗口底部看到,整体上采用了国内市场标准的配色和风格。开平仓之间的连线采用的是逐笔配对(First-in, First-out,即先进先出)规则进行绘制:每一笔成交会根据其数量自动和其他成交进行匹配,即使策略有复杂的加减仓操作也能正确绘制买卖点对应关系。
参数优化
对于开发好的策略,可以使用 CtaBacktester 内置的优化算法快速进行参数寻优,目前支持穷举和遗传两种优化算法。优化功能的底层实现位于核心框架的 optimize.py:OptimizationSetting负责管理参数空间与优化目标,run_bf_optimization实现穷举优化,run_ga_optimization实现遗传优化,check_optimization_setting在启动前校验参数组合与优化目标是否完备。
设置优化参数
点击【参数优化】按钮,会弹出"优化参数配置"的窗口:
- 点击【目标】下拉框,选择优化过程中要使用的目标函数(即以该数值最大化为目标进行优化),常用的目标包括总收益率、夏普比率、收益回撤比等。对应源码中
OptimizationSetting.set_target()方法记录目标字段(见 optimize.py)。 - 对于要进行优化的策略参数,需要配置:
- 【开始】和【结束】:用于给定参数优化的范围;
- 【步进】:用于给定参数每次变化的数值。
举例:如一个参数的【开始】设为 10,【结束】设为 20,【步进】设为 2,则该参数在优化过程中的寻优空间为:10、12、14、16、18、20。这与源码中add_parameter()按步进生成等差序列的逻辑一致(见 optimize.py),且源码校验"起始点必须小于终止点""步进必须大于 0"。
对于要设置固定数值的策略参数,请将【开始】和【结束】都同样设为该数值即可,此时该参数在寻优空间中仅保留单个取值。
穷举算法优化
设置好需要优化的参数后,点击窗口底部的【多进程优化】按钮,此时 CtaBacktester 会调用 Python 的multiprocessing模块,根据当前电脑 CPU 的核心数量,启动对应数量的进程来并行执行穷举优化任务。
在优化的过程中,穷举算法会遍历参数寻优空间中的每一个组合。遍历的过程即使用该组合作为策略参数运行一次历史回测,并返回优化目标函数的数值。完成遍历后,根据所有目标函数的数值进行排序,从而选出最优的参数组合结果。
穷举算法优化的效率和 CPU 核心数量直接相关:若用户计算机是 2 核,则优化时间为单核的 1/2;若计算机是 10 核,则优化时间会大幅降低到单核的 1/10。
源码印证:run_bf_optimization()先将OptimizationSetting.generate_settings()生成的参数组合列表(笛卡尔积)通过ProcessPoolExecutor(spawn方式启动子进程)并行执行evaluate_func,并用tqdm输出进度条,最后按key_func降序排序返回结果(见 optimize.py)。从 CHANGELOG.md 的演进记录看,该模块还支持"最大进程数量限制"参数,避免多进程优化占用过多系统资源。
遗传算法优化
设置好需要优化的参数后,点击窗口底部的【遗传算法优化】按钮,此时 CtaBacktester 会调用 Python 的multiprocessing模块和deap模块,来执行高效智能化的多进程遗传算法优化任务。
遗传算法的简要工作原理如下:
- 定义优化方向,如总收益率最大化;
- 随机从全局寻优空间中,选择出部分参数组合形成初始族群;
- 对族群内所有个体进行评估,即运行回测获取目标函数结果;
- 基于目标函数结果进行排序,剔除表现不好的个体(参数组合);
- 对剩下的个体进行交叉或者变异,通过评估和筛选后形成新的族群;
- 以上 3-5 步为一次完整的种群迭代,在整个优化过程中需要多次重复;
- 多次迭代后,种群内差异性减少,参数收敛向最优解,最终输出结果。
源码印证:run_ga_optimization()基于deap的creator(FitnessMax/Individual)构建遗传算法个体,采用双点交叉tools.cxTwoPoint、自定义参数变异mutate_individual与 NSGA2 选择tools.selNSGA2,并通过ctx.Pool多进程执行pool.map评估;优化过程中使用manager.dict()作为结果缓存,同一参数组合只回测一次;随后以eaMuPlusLambda算法迭代ngen(默认 30)代,pop_size默认 100、交叉概率默认 0.95(见 optimize.py)。从版本演进看,遗传算法优化还开放了全部超参(族群大小、迭代次数、交叉/变异概率等)供用户控制,且子进程统一使用spawn方式启动以避免数据库连接对象异常(见 CHANGELOG.md)。
与穷举算法相比,遗传算法不需要遍历全部组合,而是通过"评估→筛选→交叉变异→再评估"的迭代逼近最优解,在参数空间较大时效率优势明显,但其结果是近似最优而非全局最优,且受随机种子影响。
优化结果分析
优化完成后,会在日志区域输出提示信息(包含优化耗时、参数优化空间大小等)。此时点击【优化结果】按钮即可查看相关结果:参数优化结果会基于启动优化任务时所选的目标函数(如【总收益率】)的数值,由高到低进行排序,便于快速定位表现最好的参数组合。
最后,点击右下角的【保存】按钮即可将优化结果保存到本地 CSV 文件中,便于后续分析使用。
策略代码
代码编辑
如果需要对策略进行修改,在 CtaBacktester 界面左上角的下拉框中选择策略后,点击左下角的【代码编辑】按钮,即可自动打开 Visual Studio Code 进行代码编辑。若找不到 Visual Studio Code,则会弹出启动代码编辑器失败对话框。从版本演进看,该功能后续还扩展支持了 cursor 和 pycharm 编辑器(见 CHANGELOG.md 相关条目)。
策略重载
当用户通过 CtaBacktester 对策略源代码进行修改后,此时的修改尚停留在硬盘上的代码文件层面,内存中依然是修改前的策略代码。
想让修改内容在内存中立即生效,需要点击左下角的【策略重载】按钮,此时 CtaBacktester 会自动扫描并重新加载所有策略文件中的策略代码,同时会有相关日志输出。
重载刷新完成后,再运行回测或者优化时,使用的就是修改后的策略代码了。这一机制与 CTA 策略引擎"扫描特定目录下的策略文件(glob 方式)、加载时增加模块重载使修改立即生效"的实现相互配合(见 CHANGELOG.md 相关条目)。
与 VeighNa 核心框架的协作关系
从仓库源码看,CtaBacktester 虽然作为独立项目(vnpy_ctabacktester)维护,但其运行深度依赖本仓库(vnpy)提供的核心抽象:
| 能力 | 核心抽象 | 仓库位置 |
|---|---|---|
| 应用模块注册 | App/MainEngine.add_app() | app.py |
| 本地代码与周期解析 | extract_vt_symbol/Exchange/Interval | utility.py、constant.py |
| 数据库读写 | BaseDatabase(load_bar_data/save_bar_data等) | database.py |
| 数据服务下载 | BaseDatafeed(query_bar_history/query_tick_history) | datafeed.py |
| 参数优化引擎 | OptimizationSetting/run_bf_optimization/run_ga_optimization | optimize.py |
| 运行时目录解析 | _get_trader_dir/TEMP_DIR | utility.py |
回测研究的数据链路可概括为:数据服务/IB 行情 → BaseDatabase 持久化 → CtaBacktester 界面发起回测 → CTA 回测引擎加载数据库数据并驱动策略 → 产出统计指标与图表 → 优化引擎(穷举/遗传)自动迭代参数组合。理解这条链路后,无论是排查"历史数据不足"还是规划大规模参数优化任务,都能快速定位到对应的配置与代码环节。
小结
CtaBacktester 将 CTA 策略研究中重复性最高的数据准备、回测执行、结果评估与参数寻优整合为图形化操作,显著降低了策略迭代的摩擦成本。使用时的关键要点包括:
- 策略必须放入运行时目录的
strategies文件夹,且修改代码后需【策略重载】才能在内存中生效; - 本地代码务必携带交易所后缀,日期格式为
yyyy/mm/dd,数据下载一次后持久化于本地数据库; - 回测前核对滑点、手续费(百分比/固定两种口径)、合约乘数、价格跳动与回测资金;
- 委托成交价由撮合引擎基于行情与滑点计算,每日盈亏采用逐日盯市规则,注意区分持仓盈亏、交易盈亏、总盈亏与净盈亏;
- 参数优化时按【开始/结束/步进】定义寻优空间,固定参数将开始与结束设为同一数值;穷举算法适合小空间精确寻优,遗传算法适合大空间快速逼近。
【免费下载链接】vnpy基于Python的开源量化交易平台开发框架项目地址: https://gitcode.com/gh_mirrors/vn/vnpy
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考