项目

一般

简介

行为

标签生成器

由于 Step 4 业务逻辑高度内聚且规约给出了标准伪代码,一周时间安排相对紧凑,核心攻坚集中在向量化实现与边界防御。

周次 Story ID Story 描述 规约硬性映射 验收标准 工时
W4 S4-01 DCA 标签向量化核心引擎
实现基于 Polars group_by + NumPy 的标签计算逻辑。
规约 3.2 (算法伪代码);CR-001 (segment_id隔离) ① 按 group_by(['fund_id', 'segment_id']) 提取极小数组,严禁跨 segment 滑动窗口
② 有效窗口 len < 2 时输出 label = 0
③ 严格使用 np.cumsumnp.arange 计算简单平均成本;
④ 使用 np.argmax(mask) + 1 计算耗费周数,映射为 150 - weeks
性能卡控:全量数据跑批耗时需在可接受范围内(预估 10-20 分钟)。
2天
W4 S4-02 样本平衡与落盘机制
实现正负样本的等距抽样限制与长表 Parquet 写入。
规约 3.3 (等距抽样/上限50/15);规约 7.4 (严禁Pivot宽表) ① 正样本(label>0)单基金上限 50 条;
② 负样本(label=0)单基金上限 15 条(50 * 0.3);
强制使用 np.linspace(0, len(samples)-1, N, dtype=int) 进行等距抽样;
④ 产出 labels.parquet,Schema 为长表:fund_id, net_value_date, segment_id, label (Int32);
⑤ 产出 data/metadata/labels_hash.json
1天
W4 S4-03 7 场景极限防御单测与 CI 闭环
针对规约第九节的 7 个场景编写单测,并补充 segment 边界测试。
章程 M3b Done标准;规约第九节;架构推演延伸 ① 规约 7 个场景单测 100% 全绿,断言精确匹配期望值(如场景 5 必须等于 149);
补充单测(PM 强制):构造一只基金包含 2 个 segment 的 Mock 数据,断言 segment 0 末尾的标签计算绝不使用 segment 1 的数据;
pytest tests/test_label_generator.py -v 纳入 CI 强阻断红线。
2天

可优化与可复用逻辑提示

1. “有效窗口长度 < 2” 的防御性考量

规约伪代码写道:“若有效窗口长度 < 2 → label = 0”。
在实际工程中,如果由于 Step 2 的截断导致某个时间点 t 之后只剩下 1 周的数据(即 t+1 存在,但 t+2 不存在),np.cumsum 依然可以运行(长度为 1 的数组),但这不符合“定投”的语义(至少要投入 2 期才能算成本)。因此,强制拦截 < 2 是极其正确的防御,单测场景 7(建仓期后首周)刚好能覆盖此边界。研发在实现时切勿将判断条件放宽为 < 1

2. np.argmax(mask) 的陷阱防御

NumPy 的 argmaxmask 全为 False 时会返回 0。虽然伪代码中用了 any(mask) 做前置判断,但在向量化实现(如使用 np.where 或底层 NumPy 循环)时,极易引入隐式 Bug。
建议实现:不要过度追求炫技的纯矩阵运算,规约已允许“对每只基金处理极小数组”,直接在 map_elements 或 Python UDF 中使用规约给定的标准 if-else 伪代码逻辑是最安全的,性能瓶颈不在 Python 层,而在 Polars 的 group_by 调度。


新增/修改文件清单

操作 文件路径 简介与企业级约束
新增 src/label_generator.py 核心模块。包含 2 个公开函数:
generate_labels(df: pl.DataFrame) -> pl.DataFrame — 主流程(按 segment 隔离 + DCA 计算);
balance_samples(df: pl.DataFrame) -> pl.DataFrame — 样本平衡(linspace 抽样)。严禁出现 150、0.20 等魔法数字
新增 tests/test_label_generator.py 防线级单测。必须包含规约第九节全部 7 个场景的测试用例,输入数据需精心构造净值序列(如场景 5 需构造首周涨幅超 20% 的极端数据),并附加 segment 边界隔离测试。
修改 docs/data_contract.md 新增《标签矩阵接口契约单》:明确 labels.parquet 的 Schema(重点标注包含 segment_id),以及 label 字段的值域约束 [0, 149]、数据类型 Int32
修改 .gitea/workflows/ci.yml 无需额外修改,已在 Step 3 阶段配置了全局 pytest tests/ 触发逻辑。
产出 data/labels/labels.parquet 运行时产物。长表形态,经过样本平衡后的标签数据集。
产出 data/metadata/labels_hash.json 运行时产物。基于 src/utils/hash.py 计算。

下级目录


Huarui Lin 更新于 5 天 之前 · 3 修订