行为
Sprint 5 执行步骤与交付契约¶
Step 4.0: 前置准备与配置收敛¶
执行动作:
- 通过
core.config_loader加载更新后的config.yaml,提取s5.data_start_year(2015) 与s5.data_end_year(2026)。 - 扫描
data/processed/s3_*.parquet与data/processed/s4_*.parquet,校验年份文件集合的对称性(必须完全覆盖配置指定的年份区间),缺失则阻断。
交付内容:
- 更新后的
configs/config.yaml及src/core/config_loader.py(新增年份与内存阈值强校验字段)。 - 更新后的
src/core/constants.py(新增STREAM_HARD_MEMORY_CEILING_GB = 15.0硬编码常量)。
Step 4.1: 纯横截面聚合(极小宽表生成)¶
执行动作:
- 采用“按年 Lazy Scan 聚合”路径,循环扫描 S3 年份文件。
- 在 LazyFrame 状态下执行
group_by("net_value_date").agg(),仅计算 38 维特征的mean, std, median, mad。 - 将各年产出的极小 DataFrame(每个截面仅 1 行)零成本
concat为完整的聚合宽表。 - 基于宽表向量化推导 MAD 裁剪上下界,并执行生产就绪判定(
std==0 | mad==0 -> is_production_ready=False)。
交付内容:
- 内存中的聚合极小宽表 DataFrame(Schema:
net_value_date+ 38维统计列 + 上下界列 + 哨兵列)。
Step 4.2: 双形态参数物理时序对齐与落盘¶
执行动作:
-
路径 A(训练宽表):基于 Step 4.1 产出的宽表,在稀疏的
net_value_date索引上执行.shift(1)实现 T-1 对齐。调用core.physical_storage_contract(使用默认排序键)落盘为standardization_params_wide.parquet。 -
路径 B(推理长表):
- 将宽表 Unpivot 为长表形态。
- 扫描 S3 全量数据获取全局最小/最大日期极值,动态生成绝对自然日历表。
- 将长表与自然日历表 Left Join,执行
forward_fill补齐非交易日后,后置过滤掉未来日期(仅保留<= max_date的数据)。 - 调用升级后的
core.physical_storage_contract,显式传入override_sort_keys=["feature_name", "date"],落盘为standardization_params.parquet。
交付内容:
artifacts/standardization_params_wide.parquetartifacts/standardization_params.parquet
Step 4.3: 按年流式标准化 Apply¶
执行动作:
- 循环读取 S3 年份文件并
.collect()为实体表。 - 与
standardization_params_wide.parquet通过net_value_date执行等值 Join。 - 遍历 38 个特征列,构建
pl.when(std==0).then(None).otherwise(clip -> sub -> div)的 IEEE 754 拦截表达式,原地 Apply。 - 调用
core.physical_storage_contract(使用默认排序键),按年落盘标准化后的特征。
交付内容:
-
data/processed/s5_standardized_{year}.parquet(严格 42 列,与 S3 Schema 结构一致,仅数值被标准化)。
Step 4.4: 标签关联与毒样本截断¶
执行动作:
- 循环年份,按自然序读取 S4 标签表与 Step 4.3 产出的标准化表。
- 执行三键死锁 Join:
["fund_id", "net_value_date", "segment_id"]。 - 哨兵覆写:使用
pl.when(is_feature_complete == False).then(pl.lit(0)).otherwise(pl.col("label"))截断毒样本。 - 按年落盘最终的纯净训练集。
交付内容:
-
data/processed/s5_train_joined_{year}.parquet(Schema: 3主键 + 38维标准化特征 + 1标签 + 1哨兵)。
Step 4.5: Spearman 秩相关内存防爆防线¶
执行动作:
- 严格复用
core.stream_engine(此时受 15GB 硬天花板保护),按年流式加载 Step 4.4 产出的训练集。 - 在每个年份的闭包内,按
net_value_date分组,调用scipy.stats.rankdata(method="average")显式锁定平均秩算秩。 - 算秩后立即执行中心化,利用 Pearson 展开项跨年累加
sum_xy, sum_x, sum_xx, count_xy。 - 循环结束后,组装矩阵并执行
(matrix + matrix.T) / 2.0强制对称化截断。 - 基于
config.yaml中的spearman.threshold(0.90) 剔除共线性特征。
交付内容:
-
artifacts/final_feature_list.json(降维后的最终特征子集列表)。
🛑 必须执行的文档/代码修改清单¶
为了支撑上述步骤,您必须在 Step 4.0 之前完成以下文件的修改:
1. configs/config.yaml (修改)¶
新增以下节点:
# [S5 数据流] 动态时间窗口边界
s5:
data_start_year: 2015
data_end_year: 2026
# [Core 引擎] 流式安全池弹性断言 (严禁在 50GB 生产环境设为超过 10.0)
engine:
stream_max_memory_peak_gb: 3.0
2. src/core/config_loader.py (修改)¶
在 PipelineConfig 中新增对应的 Pydantic 字段,以实现启动强校验:
class S5Config(BaseModel):
data_start_year: int
data_end_year: int
class EngineConfig(BaseModel):
stream_max_memory_peak_gb: float
class PipelineConfig(BaseModel):
# ... 原有字段 ...
s5: S5Config = Field(...)
engine: EngineConfig = Field(...)
3. src/core/constants.py (修改)¶
新增硬编码天花板常量:
STREAM_HARD_MEMORY_CEILING_GB = 15.0
4. docs/baseline/2-dry_module_list.md (修改)¶
按照会议纪要决议,精准修改以下 3 个模块的描述:
-
core.standardization_math:将“被依赖方”修改为“S6 推理服务(注:S5 训练阶段因 3000万行宽表 OOM 红线已豁免复用)”。将“复用意义”修改为“S6 推理作为该内核的唯一复用方...”。 -
core.physical_storage_contract:在“强制入参”中增加override_sort_keys: Optional[List[str]] = None。在“内部死锁逻辑”中增加“若传入override_sort_keys,则替换默认的物理排序键,否则强制注入默认键”。 -
core.stream_engine:将“强制断言内存峰值 < 3GB”修改为“强制断言内存峰值 < min(config.engine.stream_max_memory_peak_gb, 常量.STREAM_HARD_MEMORY_CEILING_GB)”。
5. docs/baseline/3-steps.md (修改)¶
精准替换以下 4 处描述:
-
Step 2.0 第 2 点:“单次内存驻留强制锁定在 < 3GB 绝对安全红线内” 替换为 “单次内存驻留受
core.stream_engine保护,严格执行‘配置化阈值与 15GB 硬天花板取小’的弹性断言”。 -
Step 4.1 第 3 点:“按
["feature_name", "date"]绝对物理排序落盘” 替换为 “调用升级后的core.physical_storage_contract(显式传入override_sort_keys=["feature_name", "date"])按双键绝对物理排序落盘”。 -
Step 4.4 第 5 点:“输出
final_feature_list” 替换为 “将最终特征子集物理落盘为final_feature_list.json”。 -
Step 6.3 第 2 点:“复用 S5 内核:调用
core.standardization_math.apply_zscore” 替换为 “调用core.standardization_math.apply_zscore(注:S5 训练阶段因内存红线已豁免复用,S6 推理为该内核的唯一复用方)”。
由 Huarui Lin 更新于 5 个月 之前 · 1 修订