Files
Neo-ZQYY/docs/prd/specs/P19-index-backtest-task-simulation.md
Neo 6f8f12314f feat: 累积功能变更 — 聊天集成、租户管理、小程序更新、ETL 增强、迁移脚本
包含多个会话的累积代码变更:
- backend: AI 聊天服务、触发器调度、认证增强、WebSocket、调度器最小间隔
- admin-web: ETL 状态页、任务管理、调度配置、登录优化
- miniprogram: 看板页面、聊天集成、UI 组件、导航更新
- etl: DWS 新任务(finance_area_daily/board_cache)、连接器增强
- tenant-admin: 项目初始化
- db: 19 个迁移脚本(etl_feiqiu 11 + zqyy_app 8)
- packages/shared: 枚举和工具函数更新
- tools: 数据库工具、报表生成、健康检查
- docs: PRD/架构/部署/合约文档更新

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 00:03:48 +08:00

126 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# P19历史指数回测 + 任务引擎模拟
> 版本v1.0 | 日期2026-03-29 | 来源:本轮对话需求讨论
---
## 1. 背景
任务引擎P17 + OS 分级分配)已实现,但缺乏历史验证手段。需要:
- 回测过去一个月的指数变化,验证指数算法的稳定性
- 模拟任务引擎运行一个月,验证分级分配、升级、转移逻辑的合理性
- 最终数据落库(`test_zqyy_app`),可在小程序和管理后台中查看
## 2. 需求拆分
### 2.1 指数历史回测Phase 1
**目标**:给 4 个指数任务加 `as_of_date` 参数,支持"假装今天是 X 日"重算指数。
**涉及任务**
| 任务 | 输入数据源 | 时间依赖点 |
|------|-----------|-----------|
| `DWS_WINBACK_INDEX` (WBI) | `dws_member_visit_detail` + `dws_member_consumption_summary` | 距上次到店天数、到店频率衰减 |
| `DWS_NEWCONV_INDEX` (NCI) | `dws_member_visit_detail` + `dws_member_consumption_summary` | 新客首次到店后的天数 |
| `DWS_RELATION_INDEX` (RS/OS/MS/ML) | `dwd_assistant_service_log` | 服务记录的时间衰减halflife |
| `DWS_SPENDING_POWER_INDEX` (SPI) | `dws_member_consumption_summary` | 消费金额时间窗口 |
**改动要点**
- 每个指数任务的 `_do_extract()` 中,将 `NOW()` / `CURRENT_DATE` 替换为 `as_of_date` 参数
- 衰减计算中的"距今天数"改为"距 as_of_date 天数"
- 输出表新增 `calc_date` 字段(或复用 `calc_time`),标记是哪天的快照
**回测参数**
- 时间范围:过去 30 天2026-02-27 ~ 2026-03-29
- 回测间隔:每 6 小时一个快照(共 120 个快照点)
- 数据落库:每个快照覆盖写入 ETL 测试库的指数表delete-before-insert by calc_date
**CLI 接口设计**
```bash
# 单次回测(指定日期)
python -m cli.main --tasks DWS_WINBACK_INDEX --as-of-date "2026-03-01"
# 批量回测(日期范围 + 间隔)
python scripts/ops/backtest_indexes.py \
--start "2026-02-27" --end "2026-03-29" \
--interval-hours 6 \
--store-id 2790685415443269
```
### 2.2 任务引擎模拟Phase 2
**目标**:基于回测的指数快照,模拟任务引擎运行一个月,数据落入业务测试库。
**模拟参数**
- 时间范围2026-02-27 ~ 2026-03-29
- 模拟粒度每小时一次720 次循环)
- 指数数据:使用 Phase 1 回测的快照(每 6 小时更新一次,中间小时复用最近快照)
- 回店判定:使用 DWD 真实服务记录(`dwd_assistant_service_log.create_time`
**模拟流程(每小时)**
```
1. 设置模拟时钟 sim_time
2. 如果 sim_time 是 6 小时整点 → 切换到对应的指数快照
3. 检查 DWD 服务记录中 create_time 在 [sim_time-1h, sim_time] 的记录
→ 匹配 active 召回任务 → 标记 completedcompleted_at = sim_time
4. 检查过期任务expires_at < sim_time→ 标记 abandoned
5. 执行任务生成逻辑OS 分级分配):
a. MAIN 助教:生成召回/关系构建任务
b. COMANAGE仅生成关系构建检查升级条件升级倍数 ≥ 3
c. 转移检查(升级倍数 ≥ 5
6. 已完成的召回任务 → 生成 follow_up_visit48h 保留期)
7. 记录当小时的任务快照
```
**数据落库**
- 所有任务写入 `biz.coach_tasks``created_at` 用模拟时钟值)
- 历史记录写入 `biz.coach_task_history`
- 转移日志写入 `biz.coach_task_transfer_log`
**期望输出**
1. 每天的任务数量变化(按类型分组)
2. 一个月后各类型任务的最终分布
3. COMANAGE 升级触发次数和时间点
4. POOL 转移触发次数和时间点
5. 回访任务的生成数量和完成率
6. 每个助教的任务负载分布
### 2.3 输出报告
**脚本输出**
- 控制台:每天一行摘要(日期 | 新增 | 完成 | 升级 | 转移 | 总 active
- CSV 文件:`export/backtest/task_simulation_daily.csv`(每天快照)
- JSON 文件:`export/backtest/task_simulation_summary.json`(最终统计)
## 3. 技术约束
- 指数回测和任务模拟都在测试库执行(`test_etl_feiqiu` / `test_zqyy_app`
- 模拟脚本放 `scripts/ops/`,遵循现有脚本规范
- 环境变量从根 `.env` 加载(`load_dotenv`
- 指数回测需要 ETL 库连接(`PG_DSN`),任务模拟需要业务库连接(`APP_DB_DSN`
- 模拟前清空 `coach_tasks` / `coach_task_history` / `coach_task_transfer_log`
## 4. 实施顺序
1. Phase 1a`RelationIndexTask`RS/OS/MS/ML`as_of_date` 支持
2. Phase 1b`WinbackIndexTask`WBI`as_of_date` 支持
3. Phase 1c`NewconvIndexTask`NCI`as_of_date` 支持
4. Phase 1d`SpendingPowerIndexTask`SPI`as_of_date` 支持
5. Phase 1e编写批量回测脚本 `backtest_indexes.py`
6. Phase 2编写任务模拟脚本 `simulate_task_engine.py`
## 5. 依赖
- P17助教客户归属与任务生成引擎已完成
- OS 分级分配改动(本轮已完成)
- DWS_TASK_ENGINE ETL 任务(本轮已完成)
- DWD 层服务记录数据(已有)
## 6. 关键文件参考
- 指数任务:`apps/etl/connectors/feiqiu/tasks/dws/index/`
- 任务生成器:`apps/backend/app/services/task_generator.py`
- 召回检测器:`apps/backend/app/services/recall_detector.py`
- FDW 查询:`apps/backend/app/services/fdw_queries.py`
- 参数配置:`biz.cfg_task_generator_params`16 条参数)