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>
This commit is contained in:
125
docs/prd/specs/P19-index-backtest-task-simulation.md
Normal file
125
docs/prd/specs/P19-index-backtest-task-simulation.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# 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 召回任务 → 标记 completed(completed_at = sim_time)
|
||||
4. 检查过期任务(expires_at < sim_time)→ 标记 abandoned
|
||||
5. 执行任务生成逻辑(OS 分级分配):
|
||||
a. MAIN 助教:生成召回/关系构建任务
|
||||
b. COMANAGE:仅生成关系构建;检查升级条件(升级倍数 ≥ 3)
|
||||
c. 转移检查(升级倍数 ≥ 5)
|
||||
6. 已完成的召回任务 → 生成 follow_up_visit(48h 保留期)
|
||||
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 条参数)
|
||||
Reference in New Issue
Block a user