NTQ 的回测引擎会自动检测你的 CPU 核心数和内存大小,选择合理的并行参数。大多数情况下你不需要改任何东西。
但如果你遇到了回测崩溃、跑得太慢之类的问题,就需要手动调参了。性能参数都在 worker.json 里配置:
文件 | 路径 |
默认配置 | core/default_config/worker.json |
用户覆写 | userspace/system/config/worker.json |
用户文件只需要写要改的字段,和默认配置深度合并。
NTQ默认都是自动探测,分配和监控系统资源。除非您无法正常运行回测,否则不建议手动配置性能参数。
自定义回测中的资源分配
您在实际使用过程中可能有几种常见情景:
第一种:限制内存预算
在 userspace/system/config/worker.json 里写入:
{
"job_pipeline": {
"enumerator": {
"dispatch": {
"memory_budget_mb": 2048,
"memory_floor_mb": 1024
}
}
}
}这个配置的意思是:
memory_budget_mb设为 2048:每个 worker(子进程) 最大占用内存是 2GBmemory_floor_mb设为 1024:NTQ回测过程中必须保证系统至少保留 1GB 内存空闲,不够就不再启动更多子进程。
第二种:减少每个子进程处理股票的数量从而降低内存使用
系统默认是每个子进程处理 20-100 只股票(auto 模式自动探测)。
{
"job_pipeline": {
"enumerator": {
"dispatch": {
"memory_budget_mb": 2048,
"memory_floor_mb": 1024,
"entities_per_job": 10,
"dispatch_probe": false
}
}
}
}如果您这么配置,那就是:
entities_per_job改为固定值 10:每个子进程只处理 10 只股票dispatch_probe设为 false:已经手动指定了,不需要探针再测
第三种:控制CPU核心使用率
NTQ默认逻辑是使用您的(CPU逻辑核心数 - 2)个或者至少1个子进程来运行回测。这么做是给操作系统留出足够的CPU核心从而不至于系统出现明显卡顿或死机。
比如您的 CPU 是 4 核 ,枚举器默认预留 2 个核给系统,只有 2 个核跑回测。
您可以通过配置改成只预留 1 个以提高效率:
{
"job_pipeline": {
"enumerator": {
"reserve_cores": 1,
"dispatch": {
"memory_budget_mb": 2048,
"memory_floor_mb": 1024,
"entities_per_job": 10,
"dispatch_probe": false
}
}
}
}但风险也很明显:系统可能会卡顿,其他NTQ以外的任务可能会变慢。
其他可用配置
上面的案例只改了回测 enumerator(枚举器)的参数。以下是所有可调参数的完整列表,供参考。
通用参数
每个回测类模块(enumerator / tag / price_factor / scanner)都有这两个基础参数:
参数 | 默认值 | 说明 |
reserve_cores | 1(enumerator 为 2) | 为系统预留的 CPU 核数。实际 worker 数 = CPU 核数 - 预留核数 |
max_parallel_jobs_cap | null | 并行 job 上限。null 表示不限制 |
enumerator(枚举器)
枚举器是回测中最耗资源的步骤——扫描全市场几千只股票。大部分性能调优在这里进行。
worker 并发
参数 | 默认值 | 说明 |
max_workers | "auto" | worker 进程数。auto 时按 CPU 核数 - 预留核数计算。也可手动设为正整数 |
内存管理
参数 | 默认值 | 说明 |
memory_budget_mb | "auto" | 每个 worker 的内存预算(MB)。auto 时按可用内存的 85% 计算 |
memory_floor_mb | "auto" | 系统必须保留的空闲内存(MB)。auto 时取总内存的 15% 和可用内存的 50% 中的较大值 |
warmup_batch_size | "auto" | 预热批次大小 |
min_batch_size | "auto" | 批次下限 |
max_batch_size | "auto" | 批次上限 |
内存预算的 auto 计算逻辑:读取系统总内存和可用内存 → floor = max(总内存 × 15%, 可用内存 × 50%, 1024MB) → budget = (可用内存 - floor) × 85% → 限制在 256MB ~ 16GB 之间。psutil 不可用时回退为 floor=2048MB, budget=4096MB。
调度控制
参数 | 默认值 | 说明 |
entities_per_job | "auto" | 每个 job 处理多少只股票。auto 时先跑探针测量内存占用再决定 |
dispatch_probe | true | 是否运行探针。探针用小样本测量每只股票的内存占用 |
entities_per_job_auto_target | 20 | auto 模式的默认目标值 |
entities_per_job_min | 20 | 每个 job 最少处理多少只 |
entities_per_job_max | 100 | 每个 job 最多处理多少只 |
monitor_interval | 5 | 监控采样间隔(秒) |
mb_per_entity_staged | null | 手动指定每只股票的预估内存(MB),绕过探针 |
dispatch_probe_safety_factor | 1.0 | 探针结果的安全系数。设为 1.2 表示多留 20% 余量 |
切片模式(calendar_slice)
切片模式有自己的一组参数,用于控制"读算分离"的流水线:
参数 | 默认值 | 说明 |
reader_workers | "auto" | Reader 进程数。auto 时取 max(0, CPU 核数 - 预留 - 1) |
queue_depth | "auto" | 队列深度(预加载多少片) |
prefetch_enabled | true | 是否启用预取 |
slice_open_days | "auto" | 每片包含多少个交易日 |
tag(标签/扫描)
和 enumerator 结构基本一样,但范围更宽:
参数 | 默认值 | 说明 |
dispatch.entities_per_job | "auto" | 每 job entity 数 |
dispatch.entities_per_job_min | 1 | 下限(比 enumerator 的 20 低) |
dispatch.entities_per_job_max | 500 | 上限(比 enumerator 的 100 高) |
price_factor(价格因子)
最简单的 profile,计算很轻量,默认固定值不探针:
参数 | 默认值 | 说明 |
dispatch.entities_per_job | 1000 | 每 job 1000 只 |
dispatch.dispatch_probe | false | 不需要探针 |
scanner(扫描器)
参数 | 默认值 | 说明 |
dispatch.entities_per_job_auto_target | 50 | auto 目标 50 只 |
dispatch.entities_per_job_min | 20 | 下限 |
dispatch.entities_per_job_max | 200 | 上限 |
建议调参原则
NTQ 的 auto 模式已经做了大量自动检测。8 核 / 16GB 以上的机器通常不需要改。出问题时按这个顺序排查:
- 先看报错——是内存崩溃还是速度慢?
- 改一个参数——不要一次改一堆,否则不知道哪个起作用
- 内存问题→降 memory_budget_mb、降 entities_per_job
- 速度问题→减 reserve_cores、手动设 max_workers