132 lines
6.8 KiB
Markdown
132 lines
6.8 KiB
Markdown
# 实现计划:SPI 消费力指数(Spending Power Index)
|
||
|
||
## 概述
|
||
|
||
基于设计文档,将 SPI 指数建设拆分为 DDL 建表 → 核心算法实现 → 任务注册与执行流程 → 配置种子数据 → 属性测试 → 文档更新 六个阶段,每个阶段增量构建并可验证。
|
||
|
||
## 任务
|
||
|
||
- [x] 1. 创建 DDL 与数据库表
|
||
- [x] 1.1 编写迁移脚本 `db/etl_feiqiu/migrations/<日期>_create_dws_member_spending_power_index.sql`
|
||
- 创建 `dws.dws_member_spending_power_index` 表(含序列、唯一索引、查询索引)
|
||
- 字段定义参照设计文档数据模型章节
|
||
- _Requirements: 1.1, 1.2, 1.3, 1.4, 1.5_
|
||
- [x] 1.2 在测试库 test_etl_feiqiu 执行迁移脚本建表
|
||
- 通过 TEST_DB_DSN 连接测试库执行 SQL
|
||
- _Requirements: 1.6_
|
||
- [x] 1.3 运行 `gen_consolidated_ddl.py` 从测试库导出 DDL 合并到主 DDL
|
||
- 执行 `python scripts/ops/gen_consolidated_ddl.py`,验证 `docs/database/ddl/etl_feiqiu__dws.sql` 已包含新表
|
||
- _Requirements: 1.7_
|
||
|
||
- [x] 2. 实现 SPI 核心算法(纯函数)
|
||
- [x] 2.1 创建 `SPIMemberFeatures` 数据类和 `SpendingPowerIndexTask` 骨架
|
||
- 新建 `apps/etl/connectors/feiqiu/tasks/dws/index/spending_power_index_task.py`
|
||
- 定义 `SPIMemberFeatures` dataclass
|
||
- 定义 `SpendingPowerIndexTask` 类继承 `BaseIndexTask`,包含 `INDEX_TYPE`、`DEFAULT_PARAMS`、抽象方法实现
|
||
- _Requirements: 7.2, 7.3, 9.1_
|
||
- [x] 2.2 实现 `compute_level` 静态方法
|
||
- Level 子分公式:`L = w_s30 × ln(1 + spend_30/M30) + w_s90 × ln(1 + spend_90/M90) + w_ticket × ln(1 + avg_ticket_90/T0) + w_r90 × ln(1 + recharge_90/R90)`
|
||
- 全零输入返回 0.0
|
||
- _Requirements: 3.1, 3.2, 3.3_
|
||
- [x] 2.3 实现 `compute_speed` 静态方法
|
||
- 绝对速度 V_abs、相对速度 V_rel(仅加速加分)、EWMA 速度 V_ewma
|
||
- Speed 子分公式:`S = w_abs × V_abs + w_rel × max(0, V_rel) + w_ewma × V_ewma`
|
||
- _Requirements: 4.1, 4.2, 4.3, 4.4, 4.5_
|
||
- [x] 2.4 实现 `compute_stability` 静态方法
|
||
- 周覆盖率:`P = active_weeks_90 / 13`
|
||
- 支持 `use_stability=0` 时返回 0.0
|
||
- _Requirements: 5.1, 5.2, 5.3, 5.4_
|
||
- [x] 2.5 实现 `compute_spi_raw` 静态方法
|
||
- 总分公式:`SPI_raw = w_L × L + w_S × S + w_P × P`
|
||
- _Requirements: 6.1_
|
||
- [x] 2.6 编写属性测试:SPI 总分非负性
|
||
- **Property 1: SPI 总分非负性**
|
||
- **Validates: Requirements 6.1, 10.1**
|
||
- [x] 2.7 编写属性测试:Level 子分单调性
|
||
- **Property 2: Level 子分关于消费金额单调非递减**
|
||
- **Validates: Requirements 3.1, 10.2**
|
||
- [x] 2.8 编写属性测试:Speed 子分单调性
|
||
- **Property 3: Speed 子分关于 spend_30 单调非递减**
|
||
- **Validates: Requirements 4.1, 4.4, 10.3**
|
||
- [x] 2.9 编写属性测试:Stability 子分范围
|
||
- **Property 4: Stability 子分取值范围 [0, 1]**
|
||
- **Validates: Requirements 5.2, 5.4, 10.4**
|
||
- [x] 2.10 编写属性测试:Display Score 范围
|
||
- **Property 5: Display Score 取值范围 [0, 10]**
|
||
- **Validates: Requirements 6.6, 10.5**
|
||
|
||
- [x] 3. 检查点 - 确保核心算法测试通过
|
||
- 运行 `cd C:\NeoZQYY && pytest tests/test_spi_properties.py -v`
|
||
- 确保所有属性测试通过,如有问题请询问用户。
|
||
|
||
- [x] 4. 实现数据提取与执行流程
|
||
- [x] 4.1 实现 `_extract_spending_features` 方法
|
||
- 从 `dwd.dwd_settlement_head` 提取近 90 天消费订单,聚合为会员级特征
|
||
- 计算 spend_30/90、orders_30/90、visit_days_30/90、avg_ticket_90、active_weeks_90
|
||
- _Requirements: 2.1, 2.3, 2.4, 2.5_
|
||
- [x] 4.2 实现 `_extract_recharge_features` 方法
|
||
- 从 `dwd.dwd_recharge_order` 提取近 90 天充值订单
|
||
- _Requirements: 2.2_
|
||
- [x] 4.3 实现 `_compute_daily_spend_ewma` 方法
|
||
- 对近 90 天日消费序列计算 EWMA
|
||
- _Requirements: 2.6_
|
||
- [x] 4.4 实现 `_calibrate_amount_bases` 方法
|
||
- 从门店数据计算中位数作为金额压缩基数校准值
|
||
- 配置表优先级高于自动校准值
|
||
- 日志输出实际使用的基数值
|
||
- _Requirements: 8.1, 8.2, 8.3, 8.4_
|
||
- [x] 4.5 实现 `execute` 方法(完整执行流程)
|
||
- 获取 site_id → 加载参数 → 提取特征 → 校准基数 → 计算子分 → 合成总分 → 归一化展示分 → 持久化
|
||
- delete-before-insert 策略
|
||
- 无数据时返回 skipped
|
||
- 保存分位点历史
|
||
- _Requirements: 6.2, 6.3, 6.4, 6.5, 6.6, 9.3, 9.4, 9.5_
|
||
- [x] 4.6 实现 `_save_spi_data` 方法
|
||
- 批量 INSERT 到 dws_member_spending_power_index
|
||
- _Requirements: 1.1_
|
||
|
||
- [x] 5. 任务注册与模块导出
|
||
- [x] 5.1 在 `tasks/dws/index/__init__.py` 中导出 `SpendingPowerIndexTask`
|
||
- 添加 import 和 __all__ 条目
|
||
- _Requirements: 9.1_
|
||
- [x] 5.2 在 `tasks/dws/__init__.py` 中导出 `SpendingPowerIndexTask`
|
||
- 添加 import 和 __all__ 条目
|
||
- _Requirements: 9.1_
|
||
- [x] 5.3 在 `orchestration/task_registry.py` 中注册 SPI 任务
|
||
- `default_registry.register("DWS_SPENDING_POWER_INDEX", SpendingPowerIndexTask, requires_db_config=False, layer="INDEX", depends_on=["DWS_MEMBER_CONSUMPTION"])`
|
||
- _Requirements: 9.1, 9.2_
|
||
|
||
- [-] 6. 配置种子数据
|
||
- [x] 6.1 在 `db/etl_feiqiu/seeds/seed_index_parameters.sql` 中追加 SPI 参数
|
||
- 插入 `index_type='SPI'` 的全部参数行(窗口、基数、权重、映射、稳定性)
|
||
- 金额压缩基数使用合理初始默认值
|
||
- _Requirements: 7.1, 7.4, 8.5_
|
||
- [~] 6.2 在测试库执行种子数据脚本
|
||
- 通过 TEST_DB_DSN 连接测试库执行 INSERT
|
||
- _Requirements: 7.1_
|
||
|
||
- [~] 7. 检查点 - 确保单元测试和集成验证通过
|
||
- 运行 `cd apps/etl/connectors/feiqiu && pytest tests/unit/test_spi_task.py -v`
|
||
- 确保所有测试通过,如有问题请询问用户。
|
||
|
||
- [ ] 8. 文档更新
|
||
- [~] 8.1 编写数据库手册 `docs/database/BD_Manual_dws_member_spending_power_index.md`
|
||
- 包含表结构、字段说明、索引、验证 SQL(至少 3 条)、兼容性说明、回滚策略
|
||
- _Requirements: 11.1_
|
||
- [~] 8.2 更新 ETL 任务文档 `apps/etl/connectors/feiqiu/docs/etl_tasks/index_tasks.md`
|
||
- 新增 DWS_SPENDING_POWER_INDEX 章节,包含算法公式、参数清单、数据来源、计算流程
|
||
- 更新概述表格和继承体系图
|
||
- _Requirements: 11.2, 11.3_
|
||
|
||
- [~] 9. 最终检查点 - 确保所有测试通过
|
||
- 运行属性测试:`cd C:\NeoZQYY && pytest tests/test_spi_properties.py -v`
|
||
- 运行单元测试:`cd apps/etl/connectors/feiqiu && pytest tests/unit/test_spi_task.py -v`
|
||
- 确保所有测试通过,如有问题请询问用户。
|
||
|
||
## 备注
|
||
|
||
- 标记 `*` 的子任务为可选(属性测试),可跳过以加速 MVP
|
||
- 每个任务引用具体需求编号以确保可追溯
|
||
- 检查点确保增量验证
|
||
- 属性测试验证全称正确性属性,单元测试验证具体示例和边界情况
|