From 404a4d8a04233a32d2042d7c674def440f2a62d2 Mon Sep 17 00:00:00 2001 From: yuxuanhui Date: Tue, 8 Sep 2026 08:47:15 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=E6=97=A7=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E5=9B=9E=E6=B5=8B=E6=A8=A1=E5=9D=97=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E6=A2=B3=E7=90=86=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/legacy-backtest-module.md | 281 +++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 docs/legacy-backtest-module.md diff --git a/docs/legacy-backtest-module.md b/docs/legacy-backtest-module.md new file mode 100644 index 0000000..18c412b --- /dev/null +++ b/docs/legacy-backtest-module.md @@ -0,0 +1,281 @@ +# 旧系统回测模块功能梳理 + +整理日期:2026-09-07。目标:为后续将 `worldquant-constract-system` 的回测能力重构到 `wq-alpha-system` 提供功能和实现依据。本阶段仅整理文档,不实施迁移、不启动真实回测。 + +代码基线:旧仓库提交 `08edb0baa380eeb8102e74f8d0cff7b8987df1e3`,检查时工作区干净。以下“默认值”指该代码基线的默认配置,不代表历史所有版本或生产环境的实际设置。未发现旧仓库根目录及 `apps/backend/` 下的 `.env`,没有读取运行中进程配置或查询真实账户限额。文中 8 个任务、10 条表达式的上限是旧代码的校验和注释口径,未向当前 WorldQuant 平台重新核验。 + +## 1. 核心结论 + +旧系统并不是一个所有入口都共用的回测中心,而是三套执行管理方式并存: + +- **预回测列表、模板研究**:生产者从数据库取表达式,通过统一 `BacktestQueueService` 提交;默认共享 **6 个任务槽位,每任务通常 8 条表达式**。 +- **Factory**:每个执行实例使用独立 `BacktestScheduler` 和模拟器;默认 **3 个任务并发,每任务最多 8 条表达式**。 +- **CLI**:从配置文件读取表达式,独立模拟器执行,本地 JSON 文件记录进度。常规命令在默认配置下实际是 **6 个任务并发,每任务 8 条表达式**,因为旧兼容参数 `--limit-multi=6` 会覆盖配置中的 3。 + +所以不能回答成“整个系统最多并发 6 个”或“最多 48 个 Alpha”。6×8=48 只是统一队列满批时所承载的表达式数;Factory、CLI、其他进程以及浏览器里的平台操作没有纳入这个队列的共享预算。平台真正如何执行批内表达式,也不能由本地槽位数推出。[S1–S5] + +旧系统最值得保留的能力是:待回测表达式管理、参数分组与切批、空槽补位、结果回调、业务批次关联、暂停后继续提交,以及基于 progress URL 的结果找回。最需要在重构时重新定义的是:账户级并发、逐表达式状态、任务持久化、结果归属和“回测成功”的口径。 + +## 2. 管理对象与边界 + +| 对象 | 在旧系统中的含义 | 主要保存位置 | +| --- | --- | --- | +| 表达式及回测参数 | 一次 Alpha 模拟的输入;相同表达式配不同参数仍可形成不同实验 | `pre_simulate_expressions`、Factory/模板研究表达式表、CLI 输入 JSON | +| 平台提交任务 | 一次向 simulations 接口提交的单个或多个配置;本地并发控制以此为单位 | `BacktestTask` / 模拟器内部 task;统一队列部分主要在内存 | +| 业务批次 | 给表达式和 Alpha 归组的业务标识,并不等于一个平台任务 | `batch_tracking`、表达式 `batch_id`、Alpha 业务字段 | +| 研究执行 | Factory 一次执行、模板一次采样或深度回测;可包含多个平台任务 | 各业务模块专用表 | +| 平台模拟标识 | 提交返回的 `progress_url`;多模拟还有 parent/child simulation ID | 运行时对象、结果对象、部分错误日志 | +| Alpha 结果 | 平台生成的 `alpha_id`、表达式、指标、检查摘要等 | `alphas`,`alpha_id` 唯一 | + +`SimulationConfig` 包含 expression、decay、region、universe、neutralization、instrument type、delay、truncation、pasteurization、unit/nan handling、language、visualization、maxTrade。旧序列化固定提交 `type=REGULAR`,不能直接据此认定支持 SUPER 回测。[S6] + +同一平台任务按四个字段保持一致:`region / delay / language / instrument_type`。按这些字段分组后再切批;不是把所有参数都相同的配置才合并。模拟器的批量入口负责自动分组,`run_single_task()` 要求上游已经分好组,并再次检查一致性与数量。[S6、S7] + +## 3. 用户以前怎样管理回测 + +### 3.1 预回测列表:从表达式池提交 + +典型流程是:准备待回测表达式并关联业务批次 → 在列表选择表达式、指定批次或执行全部 → 后台生产者读取数据库 → 分组、按 8 条切批 → 等待队列空位 → 提交任务 → 回调更新状态和 Alpha 归属。 + +启动支持 `expression_ids`、`batch_id`、`include_completed`。前两者都不传时,范围是全部匹配记录;默认查询只排除 `completed`,因此 `failed` 和遗留 `running` 也可能重新进入提交,而不只是 `pending`。API 先返回,再异步执行。[S8] + +状态实际写入 `pending → running → completed/failed`,但 Schema、状态筛选和部分统计只认识 `pending/completed/failed`。这使“正在运行”在列表统计中没有完整表达,不能把统计缺口当作记录丢失。[S8] + +页面提供“停止推送”,含义是停止后续批次进入队列。已经提交的任务继续运行;未提交部分保持或恢复为 `pending`。没有针对单个已运行任务的远端取消,也没有预回测列表专用的 pause/resume 工作流;继续执行主要靠再次启动。[S8] + +### 3.2 模板研究:采样、评估、深度回测 + +模板研究采用业务表管理研究任务、采样记录及表达式: + +1. 生成采样预览及表达式,研究任务进入 `pending_sampling`。 +2. 启动采样,后台生产者以每批 8 条向统一队列提交,进入 `sampling`。 +3. 回调逐条保存 Alpha、指标、`done/failed` 和 `passed`;业务层据此统计样本与通过情况,供密度评估使用。 +4. 深度回测先生成全量表达式,执行记录进入 `generated`;这个动作本身不启动回测。 +5. 用户再启动深度回测,进入 `running`,同样按每批 8 条使用共享队列,最终更新研究与深度执行统计。 + +暂停通过内存 stop flag 阻止继续推送,已提交部分继续完成。采样恢复从 `stopped` 的 pending 表达式继续;深度启动接受 `generated/stopped`,继续未提交部分。业务记录持久化不等于运行中的队列任务持久化:没有据此证明进程崩溃后可以自动接续所有平台任务。[S9] + +### 3.3 Factory:独立的自动研究调度 + +创建 Factory execution 时,先生成一阶表达式和 JSON,返回 `pending_review`,不会立即回测。用户启动后,独立调度器读取 pending 表达式,混合轮转一阶/二阶任务,维护运行中的批次集合。完成结果写到 `FactoryExpression.alpha_id/backtest_status/passed`,并衔接减枝、通过统计与增量二阶生成;没有待执行和可生成工作时结束 execution。[S3] + +暂停 API 写数据库 `paused`,调度循环读取该状态后停止补充任务;停止还会发送内存 stop event,并写 `stopped/end_time`。启动或恢复会把遗留 `running` 表达式重置为 `pending` 后重新调度。这是重新提交候选表达式,不能等同于继续轮询先前已被平台接受的任务。[S10] + +### 3.4 CLI:文件驱动回测 + +CLI 读取配置文件,把未处理配置交给独立模拟器。状态保存在 `src/cli/.progress/{source}.progress.json`,包括最后处理位置、失败配置、状态和时间戳;`--resume` 从已记录位置之后继续。`status` 命令用于查看和清理进度文件。[S4、S11] + +第一次 Ctrl+C 设置停止标志;模拟器只在向线程池提交任务时检查它,已经排入线程池的工作不会因该标志自动取消。因为配置会较快地一次性排入线程池,所以“暂停”不保证立即停止后续平台提交。进度主要在模拟器整次返回后更新,并非每个 child 完成后就可靠写检查点。[S7、S11] + +CLI 还提供 `retry-timeout`:从失败配置中识别轮询超时,查询原模拟是否完成、找回 Alpha,并输出 `.retry.json` / `.retry_failed.json`。这是结果补取路径,不等于通用自动重试队列。[S11] + +## 4. 并发到底是多少 + +### 4.1 默认值与生效范围 + +| 层级或入口 | 默认并发任务数 | 默认单任务表达式数 | 配置与边界 | +| --- | ---: | ---: | --- | +| 通用 `SimulationSettings` | 3 | 8 | `max_concurrent_tasks` 校验 1–8;`max_alphas_per_task` 校验 1–10;可从 `.env` 读取 | +| 统一 `BacktestQueueService` | 6 | 输入模型允许 1–10 | 自行初始化 6 个 semaphore、6 个线程和并发为 6 的模拟器;覆盖通用并发默认 3 | +| 预回测列表 | 共享上行 6 | 8 | producer 对 `batch_size` 再取 `min(batch_size, 8)` | +| 模板采样、深度回测 | 共享上行 6 | 8 | 两个服务的 `DEFAULT_BATCH_SIZE=8`,没有各自独立的队列预算 | +| Factory 单个 scheduler | 3 | 最多 8 | API 传 `simulation_settings.max_concurrent_tasks`,批大小取 8 与配置上限的较小值 | +| CLI 常规命令、所有默认值 | 实际 6 | 8 | 默认 `--limit-multi=6` 与通用配置 3 不相等,触发覆盖;实际切批由模拟器配置决定 | +| 裸调用模拟器且不覆盖 | 3 | 8 | 使用通用配置;单个实例内部生效 | + +以上均为代码默认值。[S1–S5] + +CLI 的兼容逻辑尤其容易误解:它先读取 `--max-concurrent-tasks` 或通用配置,再判断 `limit_multi != simulation_settings.max_concurrent_tasks`,若不相等就用 `limit_multi` 覆盖。因而即使显式指定了新参数,也可能被默认旧参数覆盖;`--limit-children=10` 虽仍显示,却不决定模拟器实际切批的默认 8。[S4、S7] + +### 4.2 统一队列如何占槽和补位 + +```mermaid +flowchart TD + A[数据库表达式:预回测 / 模板研究] --> B[生产者按参数分组并切批] + B --> C[wait_for_slot 等待提交容量] + C --> D[submit_task 创建内存异步任务] + D --> E[获取 asyncio semaphore] + E --> F[线程池调用同步模拟器] + F --> G[模拟器 threading semaphore] + G --> H[提交平台任务并轮询结果] + H --> I[获取 Alpha 详情并保存] + I --> J[队列再次执行结果保存] + J --> K[释放信号量并移除运行登记] + K --> L[通知生产者补位] + K --> M[执行业务完成回调] + L --> C +``` + +这里有三层容量控制:生产者按未完成任务数量做背压、队列的异步信号量与线程池控制工作数量、模拟器的线程信号量控制该实例内部执行。提交和轮询都在同一个占槽周期内,遇到 429 后 sleep 也继续占槽。不是 POST 返回后就立即释放槽位。[S2、S7] + +实际代码在释放执行槽位、移除 `_running_tasks` 并通知生产者后才执行业务回调,因此下一批可以在上一批回调完成前开始。旧设计文档中“回调完成后再补位”的描述不完全符合当前实现。[S2] + +生产者 `wait_for_slot()` 使用 condition 等待,完成任务会 `notify_all()`;默认每 60 秒醒来检查关闭状态。它不原子预留名额,`submit_task()` 本身也不保证所有调用者先经过这一等待,因此多生产者唤醒竞争时,已登记任务数量可能超过软限制;实际执行仍被底层信号量约束。没有发现按业务来源分配配额、优先级或持久化公平调度机制。[S2] + +### 4.3 动态修改槽位的实际效果 + +监控界面可以把槽位设置为 1–8,后端 `update_max_slots()` 只修改内存 `_max_slots`: + +- 降到 3:使用 `wait_for_slot()` 的生产者会等未完成任务减少后再补充,已有任务继续运行。 +- 升到 8:允许更多任务被登记,但初始化的 semaphore、线程池和模拟器仍为 6;不能据此宣称实际执行能力变为 8。 +- 进程重启后重新按默认 6 初始化,动态修改没有持久化。 + +“设置值”“已登记未完成数”“真正执行数”应分别理解,旧监控把它们部分合并显示了。[S2] + +### 4.4 为什么不是账户级全局限流 + +统一队列只是 Python 进程内单例。Factory 和 CLI 创建独立模拟器,不共享它的 semaphore;多个后端进程也会各自创建一份队列。例如统一队列 6 个加一个 Factory 的 3 个,代码上没有共同的 8 槽账户预算来协调。是否被平台接受、何时返回 429,由平台当时状态决定。[S2–S4] + +旧代码有并发数量限制和遇限流等待,但没有由这些模块共同使用的账户级请求速率、每日额度预算或自适应降并发控制。不能把“最多 8”理解为自动识别账户剩余名额。 + +## 5. 提交、轮询和失败处理 + +### 5.1 正常路径 + +模拟器对一个配置提交 JSON 对象,对多个配置提交数组;要求返回 HTTP 201 和 `Location`。单模拟直接轮询 progress URL 获取 Alpha;多模拟先轮询父任务得到 children,再在本地逐个轮询 child。这里“逐个”指本地查询顺序,不表示平台按顺序运行表达式。[S7] + +成功结果包含 `alpha_id`、表达式、progress URL、simulation ID、parent ID、child index、完成时间和可选完整指标。取得 Alpha 后另行请求详情,尝试写入本地数据库;详情获取或保存异常不会自动把平台已完成结果改为失败。[S6、S7、S12] + +### 5.2 重试与超时 + +| 场景 | 旧实现处理 | +| --- | --- | +| 提交返回 429 | 固定等待 8 秒重试,不采用该响应的 Retry-After;提交循环最多 100 次 | +| 提交返回 401 | 强制重新认证,成功后等待 2 秒重试 | +| 提交网络异常 | 默认等待轮询间隔 5 秒后重试,受提交次数上限约束 | +| 提交其他非 201 或缺少 Location | 抛出 API 异常;不进入正常轮询 | +| 单模拟 / 父模拟轮询 | 最多 300 次;默认间隔 5 秒,依据 Retry-After 调整;429 默认回退 8 秒 | +| child 轮询 | 每个最多 100 次;404 直接生成失败结果 | +| 轮询 401 | 尝试检查会话并重新登录;不同于提交阶段的强制认证路径 | +| child 的 DAILY_SIMULATION_LIMIT WARNING | 旧实现特殊映射为 COMPLETE,并尝试取 Alpha;其他 WARNING 判失败 | +| 队列完成回调 | 最多等待 120 秒,超时/异常记录错误,不自动重试 | + +300×5 秒只能作为无额外请求耗时、无 Retry-After 变化时的粗略等待量,**不是严格的 25 分钟墙钟超时**;父任务轮询和各 child 轮询也有各自预算。队列没有独立的整个任务总时限。[S7、S2] + +这些机制是 HTTP/轮询层的重试。业务 task 失败后,统一队列不会按 retry_count 自动重新入队;重新提交失败表达式和找回已提交结果是另两类操作,应分开理解。 + +## 6. 结果、状态和批次如何关联 + +### 6.1 结果保存 + +模拟器已经尝试保存完整详情,统一队列随后还会再保存一次。批量保存按 `alpha_id` 去重,用 SQLite `ON CONFLICT DO NOTHING`,遵循先写入者保留的策略;失败时退回查询后插入。因此重复落库通常不会重复插入相同 Alpha,但也不保证把旧记录刷新到最新。[S7、S12] + +队列对缺详情的 COMPLETE 结果会构造基础指标,并把部分缺失值写成 0。`_persist_alphas_sync()` 返回的 `alpha_ids` 来自模拟器结果,而不是数据库逐条成功确认;保存函数返回失败统计也不必然抛出。因此“Alpha ID 已返回”不能证明“完整指标已可靠入库”。[S2、S12] + +### 6.2 成功统计存在多个口径 + +| 位置 | 现有口径 | 影响 | +| --- | --- | --- | +| 队列 `completed_count` | 执行未抛异常即加 1 | 一个批内全部结果 FAILED,也可能计入已完成任务 | +| 队列 `failed_count` | 整体执行抛异常才加 1 | 不是失败表达式总数 | +| `BacktestResult.is_success` | `success_count > 0` 且没有整体 error | 部分成功也算任务成功 | +| 预回测完成回调 | 按 task 的 is_success 更新整批表达式 | 只要一条成功,整批可能全被标记 completed | +| 模板研究回调 | 逐结果更新表达式 done/failed 和 passed | 比预回测整批状态更细,但仍依赖回调成功 | +| CLI `SimulationBatchResult` | 成功数按 Alpha 累加,task_count 按平台任务数 | `success_rate` 的分子分母单位不同,不能直接作正确成功率 | + +“执行完成”“平台成功”“详情完整”“落库成功”“业务筛选通过”在重构时必须分别定义。[S2、S6–S9] + +### 6.3 批次是归组标签,不是执行状态机 + +`batch_tracking` 保存 batch_id、名称、来源、说明与时间,没有任务状态、重试次数或执行检查点。表达式通过字符串 `batch_id` 归属批次;Alpha 通过 `business_type/business_id` 关联,缺少数据库外键保证。[S13] + +批次页提供搜索、分页、详情、改名、删除和统计。统计分两部分:按表达式 batch_id 聚合状态,按 `Alpha.business_type='batch'` 且 business_id 匹配统计 Alpha。删除批次仅删除批次元数据,保留表达式和 Alpha,可能留下悬空业务引用。[S13] + +预回测回调还按数据库查出的表达式顺序与成功 `alpha_ids` 顺序进行位置配对。发生部分失败或结果缺失时,不能保证这种配对正确,尤其当同一个 task 包含多个业务批次时;迁移时应使用明确的表达式 ID 与结果对应关系。[S8] + +## 7. 停止、恢复与错误找回 + +| 动作 | 实际改变什么 | 不能据此保证什么 | +| --- | --- | --- | +| 预回测停止推送 | 停止 producer 后续提交 | 不取消已进入队列或平台的任务 | +| 模板研究暂停/继续 | stop flag 停止生产;继续 pending 表达式 | 不保证重启后自动恢复 running 任务 | +| Factory 暂停/停止 | 数据库状态及内存 event 控制调度 | 不代表平台停止;重置 running 再提交可能重复实验 | +| CLI Ctrl+C / resume | 停止标志及本地位置文件 | 不保证已排队工作被取消或逐结果实时保存进度 | +| 队列关闭 | 停止接收,最多等待 30 秒,超时取消异步任务 | `cancel()` 不保证终止线程内同步网络工作,也不保证回调已完成 | +| 错误恢复页 | 查询既有平台任务、补取并保存 Alpha | 不重新提交回测,不修复原表达式状态或原研究任务状态 | + +队列运行任务、producer 管理状态、槽位设置和 callback error 列表主要存在内存;数据库虽然保存了表达式状态,却没有完整持久化的统一执行日志。生产者 manager 只有一个当前 producer 指针,启动 API 没有拒绝重复运行的明确保护,重复启动可能覆盖控制对象而让旧 producer 继续运行。[S2、S8–S11] + +### 7.1 错误恢复页的范围 + +错误写到按日期划分的 `apps/backend/src/logs/backtest_errors/backtest_errors_YYYY-MM-DD.jsonl`。每条含时间、task_id、错误文本、progress URL、来源、表达式数和配置摘要。[S14] + +恢复资格靠错误文本包含 `429 / rate limit / polling timeout / Too Many Requests`,并能取得 progress URL。用户选择日期、任务和目标批次后,服务查询原父模拟;未完成返回 `still_running`,完成则读取 children、找回 Alpha 详情并更新或插入数据库。它是人工发起的一次结果找回,未完成时要再次发起,不是后台持续恢复器。[S14] + +边界:恢复路径按父任务 children 读取,不能据此认定兼容所有单模拟响应;无 progress URL 的失败无法走此路径。恢复不会更新原 `pre_simulate_expressions` 或研究表达式状态,没有任务级恢复闭环。 + +恢复后的 Alpha 使用 `business_type='error_recovery'`,普通批次页却只统计 `business_type='batch'`,所以恢复成功也可能不出现在目标批次 Alpha 数中。恢复已有 Alpha 会覆盖指标及业务归属;目标 batch_id 直接写入,缺少存在性校验。[S13、S14] + +## 8. 页面、接口与可观测性 + +| 入口 | 功能 | 主要接口或控制位置 | +| --- | --- | --- | +| 预回测列表 | 选中/批次/全部启动、停止推送、状态查看 | `/api/v1/pre-simulate/backtest`、`/backtest/stop`、`/backtest/producer/status` | +| 回测监控 | 槽位、运行任务及表达式配置、progress URL、累计完成/失败、回调错误 | `/api/v1/pre-simulate/backtest/stats`、`/backtest/slots` | +| 错误日志 | 按日期查询原始错误 | `/api/v1/pre-simulate/backtest/error-logs/dates` 及日期查询 | +| 错误恢复 | 日期与任务选择、目标批次、恢复结果 | `/api/v1/backtest-errors/dates`、`/{date}`、`/recover` | +| 批次管理 | 业务归组元数据与统计 | `api/batch_tracking.py` | +| 模板研究 / Factory | 专属执行状态、表达式和通过统计 | 各自 API 与业务表 | +| CLI status | 文件级进度查询、清理 | 本地 `.progress` JSON | + +上表省略相同前缀的路径均相对其本行首项;最终接口拼接可从源文件定位。[S8–S11、S13–S15] + +监控页自动刷新默认关闭,开启后每 2 秒查询队列统计。预回测列表则在进入页面、启动或人工刷新时加载状态。监控仅涵盖统一队列,不是 Factory/CLI 的全局运行视图。[S15] + +`running_tasks` 统计的是已登记、尚未移除的异步 task,其中可能包括等待 semaphore 的任务;不包括已被移除但仍在回调中的任务。启动 API 的 `tasks_submitted` 还按每 10 条表达式估算,实际生产者却按每 8 条并分组,因此返回值不是实际提交任务数。[S2、S8] + +## 9. 与旧设计文档的差异 + +旧仓库 `docs/backtest-queue-service-design.md` 是设计与阶段记录,不能直接作为最新功能说明: + +| 旧文档容易造成的理解 | 当前代码事实 | +| --- | --- | +| 统一队列未来统一 Factory/CLI | 两者仍独立;模板研究已经接入共享队列 | +| 6 槽、每 task 最多 10 条即可概括 | 底层配置默认 3/8,队列覆盖为 6,常用 producer 是每批 8 | +| 修改最大槽位即可改变实际并发 | 当前只修改软提交限制,底层执行资源未同步调整 | +| 回调完成后再补位 | 当前移除任务、通知补位后才运行回调 | +| 回调前完成 alphas 保存即数据安全 | 保存失败可只返回统计;回测成功与持久化成功未形成可靠闭环 | +| 已完成计数等于成功回测数 | 队列正常返回、逐 Alpha 成功和业务通过是不同口径 | + +以本次源码证据为准;旧文档保留作历史背景,未作修改。 + +## 10. 后续重构需要保留的功能与待决策事项 + +以下是从旧功能提炼的后续候选范围,不是已批准的实现方案。当前新项目计划将回测列在后续阶段,本次不改变首期只读平台的边界,也不要求迁移旧数据库。 + +| 功能主题 | 应保留的用户能力 | 后续需要明确的规则 | +| --- | --- | --- | +| 表达式池 | 待执行列表、按选择/批次启动、参数预览 | 重复实验如何识别;是否允许运行中再次提交 | +| 业务批次 | 命名、来源、结果归组、统计 | 批次与执行记录分开;一个 Alpha 能否归属多个实验 | +| 调度 | 同参数分组、切批、空槽补位 | 单账户共同预算;软等待数与真实运行数分开;公平性 | +| 配置 | 并发和单批数量调整 | 统一配置来源、变更何时生效、是否持久化 | +| 状态 | 查看总体及逐表达式进度 | 平台状态、落库状态、业务通过状态分别存储 | +| 暂停与恢复 | 停止继续提交、恢复未完成工作 | 停止生产/本地取消/远端取消分别定义;崩溃后先对账再决定重提 | +| 错误处理 | 展示原因、重试失败、找回平台结果 | 可重试分类、次数与总时限;有无 progress URL 分流 | +| 结果管理 | Alpha 指标、原输入、结果关联 | ID 映射、缺失值保持未知、可靠保存与重复回调幂等 | +| 研究编排 | 采样、密度评估、深度回测、Factory 后处理 | 哪些首批迁移、哪些保持为业务层;不要把减枝塞进通用执行器 | +| 监控 | 队列、任务详情、错误、运行时间 | 统一覆盖所有入口;重启后历史仍可查询 | + +后续设计至少应验证:混合参数分批、单表达式与多表达式响应、多个来源争用名额、运行中升降并发、部分成功、详情/落库失败、429/401/超时、暂停后继续、重复启动、进程重启和找回结果后的原任务状态修复。本轮未执行这些运行验证。 + +## 11. 源码证据索引与验证范围 + +以下均为旧仓库本机绝对路径;代码行号对应前述提交。引用提供关键起点,相关逻辑见对应函数及邻近定义。 + +- **S1 配置**:[SimulationSettings](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/core/config.py:204)。 +- **S2 队列**:[初始化](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/backtest/queue_service.py:46)、[提交与执行](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/backtest/queue_service.py:122)、[保存](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/backtest/queue_service.py:326)、[动态槽位与关闭](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/backtest/queue_service.py:444)、[背压等待](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/backtest/queue_service.py:534)、[任务结果模型](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/backtest/models.py:24)。 +- **S3 Factory 调度**:[调度器](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/factory/backtest_scheduler.py:44)、[创建仅准备](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/api/factory.py:316)、[调用模拟器](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/factory/backtest_scheduler.py:335)。 +- **S4 CLI 配置**:[参数默认](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/cli/commands/simulate.py:451)、[兼容覆盖](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/cli/commands/simulate.py:614)、[独立模拟器](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/cli/core/executor.py:121)。 +- **S5 生产者批量**:[预回测](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/pre_simulate/producer.py:139)、[采样](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/template_research/sampling_service.py:51)、[深度回测](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/template_research/deep_backtest_service.py:51)。 +- **S6 模型**:[分组字段及配置](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/core/simulate/models.py:17)、[结果及统计](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/core/simulate/models.py:188)。 +- **S7 模拟器**:[实例信号量与会话](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/core/simulate/simulator.py:57)、[批量执行](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/core/simulate/simulator.py:200)、[单任务提交](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/core/simulate/simulator.py:339)、[单模拟轮询](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/core/simulate/simulator.py:648)、[父模拟轮询](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/core/simulate/simulator.py:807)、[子模拟轮询](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/core/simulate/simulator.py:1009)、[分组算法](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/core/simulate/params.py:109)。 +- **S8 预回测管理**:[生产者管理](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/pre_simulate/producer.py:31)、[提交流程](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/pre_simulate/producer.py:167)、[回调及取数](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/pre_simulate/producer.py:305)、[启动 API](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/api/pre_simulate_list.py:394)、[控制 API](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/api/pre_simulate_list.py:503)、[Schema 状态](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/schemas/pre_simulate.py:20)。 +- **S9 模板研究**:[采样预览](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/template_research/sampling_service.py:56)、[采样推送](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/template_research/sampling_service.py:357)、[采样恢复](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/template_research/sampling_service.py:533)、[深度生命周期](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/template_research/deep_backtest_service.py:197)、[完成回调](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/template_research/template_research_callback.py:94)、[研究模型](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/models/template_research.py:15)。 +- **S10 Factory 控制**:[暂停、启动与恢复](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/api/factory.py:1123)、[停止](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/api/factory.py:1326)、[结果模型](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/models/factory.py:99)。 +- **S11 CLI 恢复**:[进度文件](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/cli/core/progress.py:14)、[停止控制](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/cli/core/executor.py:43)、[位置更新](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/cli/core/executor.py:142)、[状态命令](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/cli/commands/status.py:16)、[超时结果找回](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/cli/commands/retry_timeout.py:480)。 +- **S12 Alpha 保存**:[详情读取](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/core/simulate/alpha_detail.py:451)、[指标落库字段](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/core/simulate/alpha_detail.py:190)、[批量插入去重](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/core/simulate/alpha_detail.py:1201)。 +- **S13 批次**:[批次模型](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/models/batch_tracking.py:20)、[统计](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/batch_tracking.py:80)、[删除行为](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/batch_tracking.py:253)、[Alpha 业务归属](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/models/alpha.py:43)。 +- **S14 错误找回**:[错误日志](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/backtest/error_logger.py:18)、[恢复筛选](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/backtest/recovery_service.py:24)、[查询原模拟](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/backtest/recovery_service.py:239)、[保存及改归属](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/services/backtest/recovery_service.py:403)、[API](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/api/backtest_error.py:22)。 +- **S15 监控与生命周期**:[监控页](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/frontend/src/pages/backtest-management/backtest-monitor.vue:395)、[刷新频率](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/frontend/src/pages/backtest-management/backtest-monitor.vue:589)、[列表刷新](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/frontend/src/pages/backtest-management/pre-simulate-list.vue:961)、[应用初始化](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/main.py:152)、[应用关闭](/Users/yuxuanhui/bcc-github/quant-project/worldquant-constract-system/apps/backend/src/main.py:182)。 + +验证方式:对照旧代码、默认配置、前端控制入口与历史设计文档;关键并发、槽位更新、回调顺序及结果保存逻辑做了直接源码抽查,并检查本文引用的本地文件与行号有效性。没有启动旧服务、调用平台回测/恢复接口、修改旧库或运行真实账户测试。本文描述的是代码现状及其可推导限制,不将其表述为已验证的线上运行效果。