2026-07-02 00:51:15 +08:00
|
|
|
|
"""
|
|
|
|
|
|
model_core/config.py — 模型层配置
|
|
|
|
|
|
|
|
|
|
|
|
仅保留模型训练所需的参数。
|
|
|
|
|
|
品种、数据、风控等全局配置统一由根目录 config.py 的 Config 类管理。
|
|
|
|
|
|
"""
|
2026-07-04 10:34:51 +08:00
|
|
|
|
import math
|
|
|
|
|
|
|
2026-07-02 00:51:15 +08:00
|
|
|
|
import torch
|
|
|
|
|
|
from .vocab import FORMULA_VOCAB
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ModelConfig:
|
2026-07-03 17:23:56 +08:00
|
|
|
|
# ── 训练设备 ─────────────────────────────────────────────────────────
|
|
|
|
|
|
# 注意:本任务 CPU 训练速度反而比 GPU 快(实测约 2.3 倍),故强制用 CPU。
|
|
|
|
|
|
# 原因:
|
|
|
|
|
|
# 1. 张量太小——forex 组仅 (2 品种 × 3508 × 20 特征),单个算子的
|
|
|
|
|
|
# 计算量小于 CUDA kernel 启动开销(数十微秒),GPU 算得快但启动慢。
|
|
|
|
|
|
# 2. 训练循环是 Python 串行调度:每 step 逐条跑 128 条公式 × 8 个
|
|
|
|
|
|
# VM 步 × 4 个 walk-forward 折,GPU 被切成上万个碎片段,吃不满。
|
|
|
|
|
|
# 3. host↔device 拷贝 + kernel 启动延迟主导总耗时,而非张量计算本身。
|
|
|
|
|
|
# 4. 实测 GPU 利用率 ~51%,正是 GPU 一半时间在干等 Python 喂下一个
|
|
|
|
|
|
# kernel 的证据(不是“还能压榨”,而是“调度瓶颈”)。
|
|
|
|
|
|
# 基准测试(forex 组, 50 步, RTX 4060, 2026-07-03):
|
|
|
|
|
|
# cuda: 4.48 s/步 Best=4.875
|
|
|
|
|
|
# cpu : 1.91 s/步 Best=5.103
|
|
|
|
|
|
# 加速比 = 0.43x(GPU 反而慢 2.3 倍)
|
|
|
|
|
|
# 若后续改为批量并行公式评估(一次喂大批张量进 GPU),再切回 cuda。
|
|
|
|
|
|
DEVICE = torch.device("cpu")
|
2026-07-02 00:51:15 +08:00
|
|
|
|
|
2026-07-04 10:34:51 +08:00
|
|
|
|
# ── 训练参数(大搜索空间适配版,2026-07-04 重构)─────────────────────
|
|
|
|
|
|
# 背景:特征库扩展到 65、算子库扩展到 66(vocab=131),8-token 搜索空间
|
|
|
|
|
|
# 从旧版 ~7亿 暴增到 ~8.67×10^16(1.2 亿倍)。旧的采样预算(128×3000)
|
|
|
|
|
|
# 覆盖率趋近于零,导致熵坍塌 Early Stop、公式退化。
|
|
|
|
|
|
# 对策(训练时间不敏感场景):
|
|
|
|
|
|
# 1. 特征剪枝(active_features.json)把 vocab 降到 ~90,空间缩小约 20 倍
|
|
|
|
|
|
# 2. 放大采样预算:BATCH_SIZE 128→256,TRAIN_STEPS 3000→8000
|
|
|
|
|
|
# 3. 更大精英池(60)保留更多历史最优
|
|
|
|
|
|
BATCH_SIZE = 192 # 每步采样公式数(原 128,1.5x 提升覆盖率)
|
2026-07-10 18:04:25 +08:00
|
|
|
|
TRAIN_STEPS = 9000 # 每组训练步数(55次重启需要更多步数)
|
2026-07-05 12:50:50 +08:00
|
|
|
|
MAX_FORMULA_LEN = 8 # 公式长度上限:保持 8(10 会导致 CPU 训练慢 3 倍)
|
2026-07-02 00:51:15 +08:00
|
|
|
|
|
|
|
|
|
|
# ── 特征维度(由 vocab.py 自动派生,无需手动修改)──────────────────
|
|
|
|
|
|
INPUT_DIM: int = FORMULA_VOCAB.feature_count # == 10
|
|
|
|
|
|
|
2026-07-04 16:59:12 +08:00
|
|
|
|
# ── Reward:Sortino 为主,IC 做门控 ──────────────────────────────────
|
2026-07-05 02:26:39 +08:00
|
|
|
|
# IC_NEG_MULT 0.30→0.50:0.30 对反向因子惩罚过重,可能误杀非线性高收益因子。
|
|
|
|
|
|
# 收益优先模式下,只要年化收益是正的,适当负 IC 可以接受。
|
2026-07-03 01:11:00 +08:00
|
|
|
|
REWARD_ALPHA: float = 1.0
|
2026-07-05 02:26:39 +08:00
|
|
|
|
IC_GATE_THRESH: float = 0.01
|
2026-07-03 01:11:00 +08:00
|
|
|
|
IC_GATE_MULT: float = 1.15
|
2026-07-05 03:11:29 +08:00
|
|
|
|
IC_NEG_MULT: float = 0.75 # 收益优先:不过度误杀反向/非线性高收益因子
|
2026-07-02 00:51:15 +08:00
|
|
|
|
|
2026-07-05 10:18:17 +08:00
|
|
|
|
# ── FTMO 专属奖励模式 ─────────────────────────────────────────────
|
|
|
|
|
|
# "standard": 收益+风险平衡(默认,原权重)
|
|
|
|
|
|
# "ftmo": FTMO 考试盘专属——年化收益权重 0.60→0.75,Calmar 0.05→0.10
|
|
|
|
|
|
# (控制 MDD 贴近 10% Max Loss 上限),其余指标权重下调。
|
|
|
|
|
|
# 目标:在 10% Max Loss 约束下最大化年化收益,快速达标。
|
2026-07-08 21:59:07 +08:00
|
|
|
|
# "forex": 外汇均值回归专属(2026-07-08)——
|
|
|
|
|
|
# 降年化收益权重(0.80→0.25)、提IC权重(0.03→0.25)、
|
|
|
|
|
|
# 新增反转奖励(0.20,奖励低/负因子自相关)和多空对称检查(0.15)。
|
|
|
|
|
|
# 原因:外汇H1以震荡为主,趋势算子效果差,需引导模型偏好
|
|
|
|
|
|
# 均值回归信号而非追涨杀跌。
|
2026-07-05 10:18:17 +08:00
|
|
|
|
REWARD_MODE: str = "ftmo"
|
|
|
|
|
|
|
2026-07-04 10:34:51 +08:00
|
|
|
|
# ── 熵保护(大空间加强版)──────────────────────────────────────────
|
|
|
|
|
|
# ENTROPY_COEFF_MAX 0.5→1.0:加倍探索压力,对抗大 vocab 的过早收敛。
|
|
|
|
|
|
# ENTROPY_COLLAPSE_THRESH 改为相对阈值 0.15×ln(vocab):大 vocab 最大熵更高
|
|
|
|
|
|
# (ln(131)≈4.87 vs ln(54)≈3.99),绝对阈值 0.5 不再合理。
|
|
|
|
|
|
# ENTROPY_COLLAPSE_STEPS 15→40:给模型更长的自我恢复窗口,不急于重启。
|
|
|
|
|
|
ENTROPY_COEFF_MAX: float = 1.0
|
2026-07-06 23:05:05 +08:00
|
|
|
|
ENTROPY_COEFF_POWER: float = 1.0 # 降低幂次,让低熵时系数更激进(原1.3)
|
2026-07-04 10:34:51 +08:00
|
|
|
|
ENTROPY_COLLAPSE_THRESH: float = 0.15 * math.log(FORMULA_VOCAB.size)
|
2026-07-06 23:05:05 +08:00
|
|
|
|
ENTROPY_COLLAPSE_STEPS: int = 20 # 更快检测坍塌并重启
|
2026-07-02 00:51:15 +08:00
|
|
|
|
|
2026-07-06 09:40:39 +08:00
|
|
|
|
# ── 熵下限惩罚(Fix 1: H→0 时熵项归零问题)──────────────────────────
|
|
|
|
|
|
# 当 H < ENTROPY_FLOOR_THRESH 时,加入固定惩罚 λ×(thresh-H)。
|
|
|
|
|
|
# 这确保即使 mean_ent→0,loss 中仍有非零探索压力。
|
|
|
|
|
|
ENTROPY_FLOOR: bool = True
|
2026-07-06 23:05:05 +08:00
|
|
|
|
ENTROPY_FLOOR_THRESH: float = 1.0 # 熵低于此值时触发固定惩罚(提高介入时机)
|
|
|
|
|
|
ENTROPY_FLOOR_LAMBDA: float = 5.0 # 惩罚强度系数(加大力度对抗坍塌)
|
2026-07-06 09:40:39 +08:00
|
|
|
|
|
2026-07-03 01:11:00 +08:00
|
|
|
|
# ── Elite Replay ──────────────────────────────────────────────────
|
2026-07-04 10:34:51 +08:00
|
|
|
|
ELITE_REPLAY_FRAC: float = 0.25
|
|
|
|
|
|
ELITE_POOL_SIZE: int = 60 # 30→60:大空间需要更大的精英记忆
|
2026-07-03 01:11:00 +08:00
|
|
|
|
ELITE_REWARD_SCALE: float = 1.2
|
2026-07-02 00:51:15 +08:00
|
|
|
|
|
2026-07-04 10:34:51 +08:00
|
|
|
|
# ── 坍塌重启(大空间加强版)─────────────────────────────────────────
|
2026-07-10 18:04:25 +08:00
|
|
|
|
# MAX_RESTARTS 8→25→55、RESTART_NOISE 0.05→0.1→0.25:时间不敏感,多给机会+更强扰动。
|
2026-07-04 10:34:51 +08:00
|
|
|
|
# 配合 engine.py:超过 MAX_RESTARTS 后不再 Early Stop,改为强扰动继续训练。
|
2026-07-10 18:04:25 +08:00
|
|
|
|
# 2026-07-09: US100 训练 24/25 重启仍有突破,扩到 55 次。
|
|
|
|
|
|
MAX_RESTARTS: int = 55
|
2026-07-05 21:08:39 +08:00
|
|
|
|
RESTART_NOISE: float = 0.25
|
2026-07-02 00:51:15 +08:00
|
|
|
|
|
2026-07-05 12:50:50 +08:00
|
|
|
|
# ── 自适应噪声:Best 停滞时自动增大扰动 ─────────────────────────────
|
|
|
|
|
|
# stagnation_window: 判断停滞的步数窗口
|
|
|
|
|
|
# noise_min / noise_max: 噪声下界和上界
|
|
|
|
|
|
# noise_boost: 停滞时噪声提升倍率
|
|
|
|
|
|
ADAPTIVE_NOISE: bool = True
|
|
|
|
|
|
STAGNATION_WINDOW: int = 500
|
2026-07-05 21:08:39 +08:00
|
|
|
|
NOISE_MIN: float = 0.15
|
|
|
|
|
|
NOISE_MAX: float = 0.60
|
|
|
|
|
|
NOISE_BOOST_FACTOR: float = 2.0 # noise += 0.2 * (stagnation / window)
|
2026-07-05 12:50:50 +08:00
|
|
|
|
|
2026-07-06 09:40:39 +08:00
|
|
|
|
# ── 重启多样性(Fix 2: best_snapshot 吸引子效应)─────────────────────
|
|
|
|
|
|
# 每 FULL_RESET_EVERY 次重启中,做 1 次完全随机初始化而非从 best_snapshot 恢复。
|
|
|
|
|
|
FULL_RESET_EVERY: int = 3 # 每 3 次重启中第 3 次做 full reset
|
|
|
|
|
|
|
|
|
|
|
|
# ── Reward baseline(Fix 3: 全负 batch 相对优选问题)──────────────────
|
|
|
|
|
|
# 用 EMA baseline 替代 batch mean 计算 advantage,避免全负 batch 的问题。
|
|
|
|
|
|
REWARD_EMA_BASELINE: bool = True
|
|
|
|
|
|
REWARD_EMA_DECAY: float = 0.95 # EMA 衰减系数
|
|
|
|
|
|
REWARD_EMA_WARMUP: int = 10 # 前 N 步用 batch mean(EMA 未稳定)
|
|
|
|
|
|
|
2026-07-05 12:50:50 +08:00
|
|
|
|
# ── 重启时部分重置参数:保留底层,扰动顶层 ───────────────────────────
|
|
|
|
|
|
PARTIAL_RESET: bool = True
|
2026-07-05 21:08:39 +08:00
|
|
|
|
PARTIAL_RESET_LAYERS: tuple = ("ln_f", "mtp_head", "head_critic", "blocks", "token_emb")
|
2026-07-05 12:50:50 +08:00
|
|
|
|
|
|
|
|
|
|
# ── Elite Replay 衰减:旧 elite 采样权重随时间衰减 ──────────────────
|
|
|
|
|
|
ELITE_DECAY: bool = True
|
2026-07-05 21:08:39 +08:00
|
|
|
|
ELITE_DECAY_HALF_LIFE: int = 300 # 每 300 步旧 elite 权重减半
|
2026-07-05 12:50:50 +08:00
|
|
|
|
|
|
|
|
|
|
# ── 多起点并行(Island)──────────────────────────────────────────────
|
|
|
|
|
|
# 注意:Island 模式在 CPU 训练下会让总时间变成 N 倍(islands 串行),
|
|
|
|
|
|
# 对于 index 这类大数组(T=32076)会变得极慢。当前默认关闭,保留配置开关。
|
|
|
|
|
|
N_ISLANDS: int = 1
|
|
|
|
|
|
MIGRATION_INTERVAL: int = 500
|
|
|
|
|
|
MIGRATION_TOP_K: int = 5
|
|
|
|
|
|
# island 默认关闭,避免用户误开导致速度爆炸
|
|
|
|
|
|
|
2026-07-02 00:51:15 +08:00
|
|
|
|
# ── 因子去相关参数 ────────────────────────────────────────────────
|
2026-07-05 03:11:29 +08:00
|
|
|
|
FACTOR_TOP_K: int = 25
|
|
|
|
|
|
CORR_THRESHOLD: float = 0.85
|
|
|
|
|
|
CORR_PENALTY: float = 0.8
|
2026-07-02 00:51:15 +08:00
|
|
|
|
|
|
|
|
|
|
# ── Walk-Forward Gap ───────────────────────────────────────────────
|
2026-07-21 09:33:43 +08:00
|
|
|
|
# P2-6 修复说明:gap 必须按 target_horizon 标定,且与 CPCV purge gap 统一。
|
|
|
|
|
|
# 当前 target_horizon=2(data_manager 用 log(open[t+2]/open[t+1]) 作 target_ret),
|
|
|
|
|
|
# gap=20 相当于 10 个「真实预测步」——对 H1 数据足够,但若切换到 D1/15min
|
|
|
|
|
|
# 需要重新评估。CPCV 模式(未实现)的 purge gap 应等于 WF_GAP,避免两套阈值。
|
|
|
|
|
|
# 调整时同时检查:
|
|
|
|
|
|
# 1. engine.py _build_walk_forward_folds 的 val_start = train_end + gap
|
|
|
|
|
|
# 2. fold_size 应 >> gap(建议 fold_size >= 5*gap)以保证 val 有效性
|
2026-07-02 00:51:15 +08:00
|
|
|
|
WF_GAP: int = 20
|
2026-07-05 23:16:08 +08:00
|
|
|
|
|
|
|
|
|
|
# ── 公式结构约束(2026-07-05 新增)──────────────────────────────────
|
|
|
|
|
|
# 背景:index 组因子因 TS_RANK 连续使用退化为 beta 因子(91.8% 做多),
|
|
|
|
|
|
# 前半段市场跌亏钱、后半段市场涨赚钱,不是 alpha 而是 beta。
|
|
|
|
|
|
# 对策:在采样阶段禁止恒正算子链,在评分阶段添加 beta 中性 + 前后一致性奖惩。
|
|
|
|
|
|
ENABLE_FORMULA_STRUCTURE_CONSTRAINT: bool = True # 总开关
|
|
|
|
|
|
BETA_NEUTRAL_PENALTY: bool = True # 多空比例失衡惩罚
|
|
|
|
|
|
HALF_CONSISTENCY_BONUS: bool = True # 前后一致性奖惩
|
|
|
|
|
|
BETA_NEUTRAL_THRESH: float = 0.85 # 超过此比例同方向触发重罚
|
|
|
|
|
|
BETA_NEUTRAL_LIGHT_THRESH: float = 0.70 # 轻度失衡阈值
|
2026-07-23 09:29:01 +08:00
|
|
|
|
|
|
|
|
|
|
# ── 并行评估(CPU 利用率优化)────────────────────────────────────────
|
|
|
|
|
|
# 将 Part C 公式评估(VM 执行 + WF 折叠评估 + IC + 惩罚)并行化到
|
|
|
|
|
|
# ThreadPoolExecutor(PyTorch CPU 算子释放 GIL,多线程真正并行)。
|
|
|
|
|
|
# workers × intra_threads ≈ 物理核数,避免超线程过度订阅。
|
|
|
|
|
|
# EVAL_WORKERS=0: 自动 = 物理核数(cap 在 8)
|
|
|
|
|
|
# EVAL_INTRA_THREADS=0: 自动 = 物理核数(不分割,让每个 worker 的 torch 跑满)
|
|
|
|
|
|
PARALLEL_EVAL: bool = True
|
|
|
|
|
|
EVAL_WORKERS: int = 0 # 0=auto (physical cores, cap 8)
|
|
|
|
|
|
EVAL_INTRA_THREADS: int = 0 # 0=auto (physical cores)
|