本篇重点:本篇讲「软件设置」里每一项的作用,以及大规模回测前怎么估算数据量、选加载模式。
1 打开和保存
- 点主界面工具栏「设置」,打开「软件设置」对话框。
- 顶部是标签页,V2 有「基本设置」「数据设置」「回测性能」三页。
- 改完后点右下角「保存设置」,弹出「成功」提示,点「确定」后对话框关闭。直接点「关闭」不会保存(界面字号倍率除外,它在关闭时也会保存)。
对话框左下角有「反馈问题」按钮,遇到问题可以从这里反馈。

2 基本设置
2.1 基本参数设置
| 选项 | 默认值 | 说明 |
|---|---|---|
| 无风险收益率 | 0.03 | 年化值,0.03 表示 3%,最多 6 位小数。用于计算回测报告里的夏普比率、索提诺比率和阿尔法。研究中常用十年期国债收益率作参考 |
| 延迟显示日志 | 开启 | 回测期间日志先缓存,结束后一次显示到右侧面板。开启时回测更快;想边跑边看日志时关闭 |
| 最大日志显示行数 | 1000 | 右侧日志面板最多保留的行数,范围 100~100000。超过后删掉最早的行,完整日志在 app.log 文件里 |
| 界面字号倍率 | 0(显示为「自动」) | 0 表示按屏幕分辨率自动调整;1.0 表示 100%。建议范围 0.8~1.6。保存后部分窗口需要重新打开才生效 |
| 停止后直接退出 | 开启 | 开启时,回测中途点「停止运行」直接停止,不显示报告,也不保存回测记录。需要保留中途结果时关闭 |
| 回测前数据检查 | 自动(推荐) | 三个选项:自动(推荐)、每次全量检查、关闭检查。自动模式在股票多、分钟线规模大时跳过检查,详见《1.11 数据维护》 |
2.2 成交量限制
成交量限制用来模拟资金量大时成交不了那么多的情况。默认关闭。
| 选项 | 默认值 | 说明 |
|---|---|---|
| 启用成交量限制 | 关闭 | 勾选后,每笔订单的成交数量不超过当根 K 线成交量的一定比例;挂单之后在后面的 K 线上成交时,也按同样的比例限制 |
| 市场参与率 | 10% | 上面说的「一定比例」,填百分数,范围 0.1~100 |
| 允许部分成交 | 开启 | 订单超过上限时:开启则按上限成交一部分,成交的部分记入交易记录,剩余数量保留原来的委托价和订单类型继续挂单;关闭则这一根 K 线整笔不成交(刚下的单直接被拒绝,已经在挂单中的继续挂着等后面的 K 线) |
开启后的计算规则(源码):
- 可成交上限 = 当根 K 线成交量(手)× 100 × 市场参与率,即先把手换算成股再乘参与率;至少 100 股,再向下取整到 100 的整数倍。
- 部分成交后剩下的数量:限价单按原限价继续挂单;市价单在下一根 K 线按开盘价继续成交(遇到一字涨停不能买、一字跌停不能卖),有效期沿用原来的订单,默认当日有效,日线回测中剩余数量当天收盘就过期。
- 当根 K 线成交量为 0 时(包括最高价、最低价、收盘价相同的情况),照常撮合,不按停牌拒单;开启成交量限制时,零成交量的 K 线不做数量限制。V2 和 V3 规则相同。
- 成交量字段无论「数据字段」里是否勾选都会加载;只有数据源本身缺少成交量这一列时才无法限制,运行日志会提示一次。
资金量小、交易的是流动性好的股票时,开不开差别不大。回测资金较大或者股票池里有成交清淡的股票时,建议开启,避免回测里出现现实中成交不了的大单。
2.3 账户设置
「账户名称」(默认预填 8888888888)和「账户类型」(V2 只有 STOCK)目前对回测结果没有影响,保持默认即可。
2.4 股票列表管理
「更新成分股列表」按钮通过 BaoStock 更新本地股票池和主要指数成分股,免费、不需要账号;随安装包附带的场内基金和转债列表保持不变。同时会刷新上市、退市日期表,回测前数据检查用它排除上市前、退市后的日子。
- 更新需要一些时间,过程中会显示进度,不需要频繁更新。
- 指数成分股有调整、或者很久没更新时再点一次即可。
2.5 版本信息
显示当前版本号和构建日期。反馈问题时请附上。

3 数据设置
3.1 DuckDB 数据路径
所有行情都存在这个目录里,回测只从这里读数据。
- 默认位置:
%LOCALAPPDATA%\KhQuantOS\khData。第一次启动时的引导页也可以选这个目录。 - 建议改到系统盘以外、空间充足的磁盘,全市场数据会占用较多空间。
- 点「浏览…」选文件夹,或直接输入路径。输入的路径不存在时,保存时软件会自动创建。
换了数据路径,软件就去新目录里读数据,原目录里的数据不会自动搬过去。需要沿用原来的数据时,先把原目录里的文件复制到新目录,再改路径。
3.2 Tushare 接口配置
需要 1 分钟线或 ETF 数据时,要用 Tushare 下载,先在这里配置:
- 「Token」框里填入你在 Tushare 注册后得到的 Token。输入内容默认隐藏,点「显示」可以查看。
- 点「测试连接」,弹出「连接成功」说明 Token 可用。
- 「API 地址」一般留空,使用 Tushare 默认地址。
- 需要通过代理访问时,勾选「使用网络代理访问 Tushare」,在「代理地址」里填写,例如
http://127.0.0.1:7890。 - 点「保存设置」。
界面上的提示:Token 在本地编码保存;1 分钟线需要在 Tushare 开通 stk_mins 权限;复权价需要复权因子接口权限:股票用 adj_factor,ETF 等场内基金用 fund_adj(积分和权限要求以 Tushare 官方说明为准)。

4 回测性能
这一页控制回测时怎么把行情读进内存。一般只需要选「数据加载模式」,其余保持默认。
4.1 数据加载模式
| 模式 | 说明 |
|---|---|
| 智能(推荐) | 按数据规模和可用内存自动决定:数据小时一次全部载入,数据大时自动分段,分段大小按可用内存调整。绝大多数情况用它 |
| 全量加载 | 一次把全部行情载入内存,不分段。数据量小、内存充足时最快;数据太大内存不够时,会自动降级为分段重试 |
| 省内存(分段) | 强制分段加载,最省内存。数据大或内存有限时用;仍然不够时自动降到更低的内存档重试。分段大小按可用内存调整,最少 20 个交易日 |
选中某个模式后,下方会显示它的说明。
三种加载模式只影响速度和内存占用,不影响回测结果:分段加载时,时间轴按股票池里所有股票实际有行情的时间合并,和股票池的排列顺序无关,跑出来的结果与全量加载一致。
「内存不足时自动启用分段加载并重跑」开启时,如果回测中途内存不够,软件会降一档内存模式,从头重新跑一遍这次回测。重跑的结果同样存成一条独立的回测记录,记录里保存的是重跑时实际使用的完整配置,在回测历史里点「还原」可以原样恢复。
4.2 详细设置
点「显示详细设置」展开进阶选项。选择数据加载模式时,这些选项会自动填好,一般不用改:
- 内存不足时自动启用分段加载并重跑(建议保持开启)
- khHistory 优先读内存
- khHistory 缺历史数据时弹窗确认(股票池很大时建议关闭,免得反复弹窗)
- 框架原始 DuckDB 加载
- 历史预热天数(默认 300):提前加载回测开始日之前的 K 线,供
khHistory直接从内存取 - khHistory 缓存、khHistory 预取、DuckDB 排序、空数据日志(汇总提示 / 逐根K线详细)
- DuckDB批大小、并行读取
每一项下面都有一行说明。排查读取问题时才需要调整。
4.3 Parquet 缓存(独立可选)
Parquet 缓存适合反复回测同一批全市场分钟线的场景,会额外占用磁盘空间,所以不跟随上面的三档模式自动开启。
- 「Parquet 缓存」有三个选项:关闭(默认,最稳妥)、只读使用(有缓存就用,不自动生成)、缺失时构建后读取(没有缓存时先生成再用)。
- 「Parquet缓存目录」:留空则使用软件默认的临时缓存目录。
- 批大小、线程、压缩:可以填 auto;压缩率越高越省空间,构建越慢。
- 下方四个按钮:「查看缓存」「清理缓存」「检查当前配置」「显式构建」。

只做日线回测,或者股票池只有几十只时,不需要开 Parquet 缓存,保持「智能(推荐)」即可。
V3 的「基本设置」和「回测性能」两页与 V2 基本相同,差别如下(另外 V3 Windows 版「数据设置」页多一项「回测数据源:miniQMT / DuckDB本地数据库」,Mac 版不显示):
- 「数据设置」页:DuckDB 数据路径默认为空,需要自己选择;Tushare 配置之外还有「同花顺(扶摇)接口配置」,填 API Key 后可用同花顺导入日线及复权数据。
- 「更新成分股列表」优先用同花顺(扶摇)接口,可同时更新场内基金(含 ETF/LOF)列表;没有配置同花顺 API Key 时退回 BaoStock。
V3 在 Windows 上多一个「包管理」页(基于 pip 的 Python 包管理器)。策略要用第三方 Python 库时,在这一页输入包名、点安装即可,库会装到软件自己的目录里,供策略直接导入,不用自己另外配置 Python 环境。命令行里也可以用 kh config 管理全局配置。
▶ 本节视频:1.12 进阶 · 大规模回测与性能
5 大规模回测(进阶)
上面第 4 节讲的是「回测性能」页每个选项在哪里、叫什么。这一节讲它们背后的规则:数据量多大要分段、「智能」怎么判断、怎样让结果可复现、能不能同时跑几个回测。V2 和 V3 用同一套回测内核,规则相同;只有 V3 才有的命令行用法放在「仅 V3」提示框里。批量试参数(用脚本循环跑回测)见 2.2《命令行模式与 AI 智能策略研究》第 4.7 节。
5.1 先估算规模
回测要载入的数据行数大约是:
行数 ≈ 股票数 × 交易日数 × 每天 K 线根数
(日线 1,5 分钟 48,1 分钟 241,tick 约 2000)
每行大约占 200 多字节内存(随字段数变化)。几个量级:
- 全 A 约 5000 只 × 日线 × 10 年 ≈ 1200 万行,约 2.5GB,一般电脑都能一次载入。
- 全 A × 1 分钟线 × 1 年 ≈ 2.8 亿行,一次载入要几十 GB,只能分段。
作者用全 A 1 分钟线跑一年的实测(SSD,数字随机器不同会有差异):
| 每段天数 | 用时 | 峰值内存 |
|---|---|---|
| 20(省内存的默认下限) | 约 170 分钟 | 18.3GB |
| 120 | 约 70 分钟 | 31.6GB |
| 240(不分段) | 约 65 分钟 | 36.4GB |
分段越大越快、也越吃内存;20 天左右最省,再调小并不会更省内存。16GB 内存的电脑跑不了全 A 分钟线一整年,只能缩小股票池或缩短区间。
5.2 「智能」做了什么

- 开始回测时估算这次要占多少内存。估算值不超过当前可用内存的 35%,就一次全部载入;超过就分段载入,每段至少 20 个交易日,可用内存充裕时自动放大分段。
- 数据量超过约 1.2 亿行时,会直接进入分段,内存再紧张时进入更保守的分段档。
- 回测中如果内存不够,会自动降一档、从头重新跑一遍。
想知道这次实际用了哪一档:看日志里 Memory profile: requested=… effective=… 那一行,或结果目录 config.csv 里的 memory_profile_effective 列(standard 为一次载入,low、ultra_low 为分段)。
命令行 kh run 触发降档重跑时,终端会提示「回测触发内存保护,已从 X 自动降级到 Y 并重新运行」。
三档模式的区别:「智能」自动判断;「全量加载」先一次载入,并且一次预取整个区间的历史数据,内存溢出时自动降级为分段重跑;「省内存(分段)」总是分段。分段只影响速度和内存,不影响结果(实测日线、分钟线三档结果逐笔一致)。
| 想做什么 | 命令 |
|---|---|
| 这一次强制一次载入 | kh run x.kh --memory-profile standard |
| 这一次强制分段 | kh run x.kh --memory-profile low(更保守用 ultra_low) |
| 判成低内存档也不分段 | kh run x.kh --no-auto-dynamic-load |
| 改全局模式 | kh config set performance_preset balanced(智能)/ performance(全量)/ low_memory(省内存) |
| 查看当前性能设置 | kh config show,看「性能-」开头的几行 |
设置的生效顺序:命令行参数 > .kh 里手写的性能设置 > 「回测性能」页里改过的项 > 默认值。改设置只影响下一次回测。
早期版本的日线策略在分段载入时取不到数据,回测一笔交易都没有、也不生成结果。V3 请升级到最新版;V2 的日线回测请在界面里选「全量加载」(不要用「智能」或「省内存(分段)」,「智能」在内存紧张时也会自动分段)。
5.3 详细设置里值得了解的几项


- 历史预热天数(默认 300):从回测开始日往前推多少个自然日一起载入,让
khHistory、khMA能直接从内存取开始日之前的数据。300 个自然日约等于 200 个交易日,够 200 日以内的均线用。不够时会回到数据库再查,结果不变,只是慢一些。 - 并行读取(默认 4):读数据库的线程数。作者实测全 A 一年,1 线程约 3 小时,4 线程约 44 分钟。调太高会加大磁盘压力。
- khHistory 预取:选「整段回测窗口」时一次预取整个区间,对不复权的分钟线回测更快。
- 没有界面的「连接池上限」等项不建议改。
5.4 回测前数据检查什么时候被跳过
「回测前数据检查」选「自动(推荐)」时,满足以下任一条件就跳过回测前的全量扫描,改为在回测过程中汇总提示空数据:
- 股票数(含基准)达到 1000 只;
- 分钟线或 tick,且股票数达到 500 只;
- 估算要扫描的 K 线达到 25 万根。
第三条门槛不高,几只股票的分钟线回测一年就会被跳过。跳过时界面日志会写「检测到大规模回测……已跳过 GUI 前置全量扫描」。
命令行直接 kh run 不做这项检查,只检查每只股票的数据文件是否存在。
5.5 Parquet 缓存
同一个股票池、同一段区间,只改策略参数反复跑全市场分钟线时,每次都要打开几千个数据库文件,本身就很慢。Parquet 缓存会把这一次要读的全部数据打包成几个文件,下次直接读。
- 命中条件很严:数据目录、周期、字段、复权、股票池、区间都要相同,而且每只股票的数据文件不能变过。补过一次数据、换了股票池或区间,就要重建。
- 只在一次全部载入时起作用,分段载入时不使用;还要求勾选详细设置里的「框架原始 DuckDB 加载」,并且触发方式不是自定义定时触发。没命中时自动照常读数据库,不会报错。
- 上面第 4 节说的「软件默认的临时缓存目录」,在 Windows 安装版就是安装目录下的
temp\parquet_cache_pack。 - 日线或几十只股票用不着它。
kh tool parquet-cache check x.kh # 看当前配置能不能命中
kh tool parquet-cache build x.kh # 构建缓存
kh tool parquet-cache list # 列出已有缓存
kh tool parquet-cache clean --yes # 清理(不加 --yes 只预览)
Windows 上没设置「Parquet缓存目录」时,缓存默认建在安装目录里,命令行没有写权限,build 会报「拒绝访问」(PermissionError)退出。用命令行构建前,先在「回测性能」里设好缓存目录,或者 kh config set performance_parquet_cache_pack_root D:\khParquet(目录随意,有写权限即可)。只在一条命令里加 --root 目录 也能构建,但回测时读的是设置里的目录,两者要一致。
构建好后,把「回测性能」里的 Parquet 缓存设为「只读使用」,或 kh config set performance_parquet_cache_pack read_only。这组命令的输出是英文的。
5.6 结果能不能复现
- 软件启动时会自动固定 Python 的哈希随机,保证同样的代码遍历顺序每次相同,不需要自己设置。
- 但软件不会固定
random模块的随机数。自带案例的参数是用random生成的,所以每次结果不同。想要可复现,把参数写成固定值,或在策略开头自己写random.seed(…)。 - 实测固定参数连跑多次,交易记录和汇总结果完全一致。
5.7 同时跑几个回测
- 回测只读数据库,多个回测同时跑没有问题。实测同时跑 3~4 个小回测全部正常,总用时比一个个跑短一半多。
- 每个回测各自载入数据,同时跑 N 个大约要 N 倍内存,大回测不建议并发。
- 不要在补数据(下载、定时补充)时跑回测:数据库正在写入时,回测会直接失败,提示「DuckDB数据源初始化失败」。
- 回测中途某只股票的数据被占用时,会重试后跳过这只,日志里会提示跳过了哪些(V3 命令行的结果摘要会多一行「数据库占用: 跳过 N 项」)。批量跑完请留意。
5.8 看日志找瓶颈
每次回测结束,日志里都有一段「【性能剖析】_run_backtest 阶段级墙钟耗时」,分成初始化、基准数据加载、行情数据加载、时间索引构建、循环前预处理、主循环六个阶段,各占多少时间一目了然。命令行在终端里能看到;图形界面的日志在 V2 是 %LOCALAPPDATA%\KhQuantOS\logs\app.log;V3 在 Windows 上优先写到程序目录旁的 logs 文件夹,写不进去时改用 用户目录\KhQuant\logs,macOS 在 ~/Library/Logs/khQuant/(见 1.9)。慢在「行情数据加载」就考虑并行读取和 Parquet 缓存;慢在「主循环」就要优化策略代码。
常见问题
问:改了设置没有生效?
答:确认点的是「保存设置」,看到「设置已保存」的提示。界面字号改动后,已经打开的部分窗口需要关掉重开;无风险收益率改动后,要重新打开回测报告。
问:Tushare 测试连接失败?
答:先确认 Token 没有多复制空格;再确认网络能访问 Tushare,需要代理时勾选代理并填写地址。1 分钟线下载失败而日线正常,一般是没有开通 stk_mins 权限。
问:回测到一半提示内存不足?
答:把「数据加载模式」改为「省内存(分段)」,并确认「内存不足时自动启用分段加载并重跑」处于勾选状态。分段加载和全量加载的回测结果一致,放心切换。
问:中途停止的回测为什么没有报告?
答:「停止后直接退出」默认开启,手动停止时不显示报告、不保存记录。需要中途结果时关闭这一项。
问:开了成交量限制后,有些买单只成交了一部分?
答:这是成交量限制在起作用:订单超过「当根 K 线成交量(手)× 100 × 市场参与率」时,只成交上限部分,剩下的数量继续挂单,后面的 K 线上还会接着成交(同样受这个比例限制)。不想部分成交时,取消「允许部分成交」:刚下的超限订单会整笔被拒绝,已经在挂单中的则等到某根 K 线的量足够时再整笔成交。
问:16GB 内存能跑全 A 分钟线吗?
答:一整年跑不了。缩小股票池(比如沪深300成分股)或缩短区间。
问:Parquet 缓存为什么没命中?
答:V3 可以用 kh tool parquet-cache check x.kh 检查。补过数据、改过股票池或区间,缓存就失效了,需要重建。
- 包管理页:在软件里安装策略要用的第三方 Python 库
- 同花顺(扶摇)接口配置
- CLI 的 kh config 命令管理全局配置
本篇基于开源 V2 和 V3.4.1.10 编写。