precious_metals_v1: 黄金单品种策略 (Sharpe 2.66, MDD -11%, 8年数据验证)
策略: DMI_ADX_14 -> KYLE_LAMBDA -> EMA_20 -> KYLE_LAMBDA -> MFI14 -> SCALE -> TS_CORR_10 -> IF_GT - 微型市场体制切换模型: 流动性驱动时用Kyle动量, 流动性紊乱时退守趋势 - 推荐用法: XAUUSD单品种 - 回测: 年化+28.2%, Sharpe 2.66, 换手109笔/年, Walk-Forward 3/4折盈利 配置变更: - AAVUSD移除(实为Aave加密货币) - COCOA.c移除(交易时段不匹配) - metals_comm重命名为precious_metals(XAUUSD+XAGUSD) - 算子溢出修复(_signed_power clamp, _ts_product expm1 clamp)
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
cd /d D:\cl\MT5_AlphaGPT
|
||||
"C:\Program Files\Python313\python.exe" train_precious_metals.py --offline > precious_metals_train.log 2>&1
|
||||
@@ -46,8 +46,11 @@ class Config:
|
||||
SYMBOLS = [
|
||||
# 外汇
|
||||
"EURUSD", "USDJPY",
|
||||
# 贵金属 + 大宗商品
|
||||
"XAUUSD", "AAVUSD", "COCOA.c",
|
||||
# 贵金属
|
||||
"XAUUSD", "XAGUSD",
|
||||
# AAVUSD 已移除:实为 Aave 加密货币,非大宗商品。波动特征与贵金属完全不匹配。
|
||||
# COCOA.c 已移除:大宗商品期货,日交易~10h,时间对齐后仅8546 bar,
|
||||
# 拖累整组数据量,且流动性/交易时段与贵金属不匹配。
|
||||
# 美国指数
|
||||
"US30.cash", "US100.cash", "US500.cash", "US2000.cash",
|
||||
# 其他指数
|
||||
@@ -56,9 +59,9 @@ class Config:
|
||||
|
||||
# 相关性分组(用于分组训练)
|
||||
SYMBOL_GROUPS = {
|
||||
"forex": ["EURUSD", "USDJPY"],
|
||||
"metals_comm":["XAUUSD", "AAVUSD", "COCOA.c"],
|
||||
"index": ["US30.cash", "US100.cash", "US500.cash", "US2000.cash", "JP225.cash"],
|
||||
"forex": ["EURUSD", "USDJPY"],
|
||||
"precious_metals":["XAUUSD", "XAGUSD"], # 贵金属(黄金+白银,8.3年对齐)
|
||||
"index": ["US30.cash", "US100.cash", "US500.cash", "US2000.cash", "JP225.cash"],
|
||||
}
|
||||
|
||||
# FEATURE_SYMBOLS:用于计算截面特征的宽品种集
|
||||
|
||||
@@ -64,16 +64,16 @@ class ModelConfig:
|
||||
# (ln(131)≈4.87 vs ln(54)≈3.99),绝对阈值 0.5 不再合理。
|
||||
# ENTROPY_COLLAPSE_STEPS 15→40:给模型更长的自我恢复窗口,不急于重启。
|
||||
ENTROPY_COEFF_MAX: float = 1.0
|
||||
ENTROPY_COEFF_POWER: float = 1.3
|
||||
ENTROPY_COEFF_POWER: float = 1.0 # 降低幂次,让低熵时系数更激进(原1.3)
|
||||
ENTROPY_COLLAPSE_THRESH: float = 0.15 * math.log(FORMULA_VOCAB.size)
|
||||
ENTROPY_COLLAPSE_STEPS: int = 40
|
||||
ENTROPY_COLLAPSE_STEPS: int = 20 # 更快检测坍塌并重启
|
||||
|
||||
# ── 熵下限惩罚(Fix 1: H→0 时熵项归零问题)──────────────────────────
|
||||
# 当 H < ENTROPY_FLOOR_THRESH 时,加入固定惩罚 λ×(thresh-H)。
|
||||
# 这确保即使 mean_ent→0,loss 中仍有非零探索压力。
|
||||
ENTROPY_FLOOR: bool = True
|
||||
ENTROPY_FLOOR_THRESH: float = 0.5 # 熵低于此值时触发固定惩罚
|
||||
ENTROPY_FLOOR_LAMBDA: float = 2.0 # 惩罚强度系数
|
||||
ENTROPY_FLOOR_THRESH: float = 1.0 # 熵低于此值时触发固定惩罚(提高介入时机)
|
||||
ENTROPY_FLOOR_LAMBDA: float = 5.0 # 惩罚强度系数(加大力度对抗坍塌)
|
||||
|
||||
# ── Elite Replay ──────────────────────────────────────────────────
|
||||
ELITE_REPLAY_FRAC: float = 0.25
|
||||
|
||||
@@ -838,7 +838,11 @@ class AlphaEngine:
|
||||
low_entropy_streak = 0
|
||||
|
||||
# Fix 2: 每 N 次重启做一次完全随机初始化,逃离 best_snapshot 吸引子
|
||||
do_full_reset = (self._restart_count % ModelConfig.FULL_RESET_EVERY == 0)
|
||||
# 深度坍塌 (H < 0.3) 时强制 full reset,不给 best_snapshot 恢复的机会
|
||||
do_full_reset = (
|
||||
self._restart_count % ModelConfig.FULL_RESET_EVERY == 0
|
||||
or ent_val < 0.3
|
||||
)
|
||||
|
||||
if do_full_reset:
|
||||
# 完全重新初始化模型参数
|
||||
|
||||
+7
-2
@@ -261,13 +261,18 @@ def _ts_product(x: torch.Tensor, d: int) -> torch.Tensor:
|
||||
x_safe = torch.clamp(x, -0.999, None)
|
||||
log_x = torch.log1p(x_safe)
|
||||
w = _ts_rolling(log_x, d)
|
||||
out = torch.expm1(w.sum(dim=-1))
|
||||
# clamp 对数累加和防止 expm1 溢出到 float32 边界(>1e38)
|
||||
log_sum = w.sum(dim=-1).clamp(-10.0, 10.0)
|
||||
out = torch.expm1(log_sum)
|
||||
return torch.nan_to_num(out, nan=0.0, posinf=0.0, neginf=0.0)
|
||||
|
||||
|
||||
def _signed_power(x: torch.Tensor, a: float = 2.0) -> torch.Tensor:
|
||||
"""带符号乘方: sign(x) * |x|^a。Alpha#001 SignedPower。保留符号同时放大极端值。"""
|
||||
return torch.sign(x) * torch.abs(x) ** a
|
||||
out = torch.sign(x) * torch.abs(x) ** a
|
||||
# 防溢出:|x|^a 在链式调用中可能爆炸到 float32 边界(如 3.3e38),
|
||||
# 导致后续 mean/std 计算溢出为 inf。clamp 到安全范围。
|
||||
return torch.nan_to_num(out.clamp(-1e9, 1e9), nan=0.0, posinf=0.0, neginf=0.0)
|
||||
|
||||
|
||||
# ── Cross_Sectional 算子 helper(沿 N 维,每时间步跨品种;R2.1, R2.2)───────
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "precious_metals_v1",
|
||||
"version": "2026-07-06",
|
||||
"vocab_version": "v9217a2c0d91a",
|
||||
"status": "verified",
|
||||
"formula_tokens": [
|
||||
48,
|
||||
42,
|
||||
94,
|
||||
42,
|
||||
25,
|
||||
103,
|
||||
86,
|
||||
126
|
||||
],
|
||||
"formula_readable": "DMI_ADX_14 -> KYLE_LAMBDA -> EMA_20 -> KYLE_LAMBDA -> MFI14 -> SCALE -> TS_CORR_10 -> IF_GT",
|
||||
"formula_operators": [
|
||||
"DMI_ADX_14",
|
||||
"KYLE_LAMBDA",
|
||||
"EMA_20",
|
||||
"KYLE_LAMBDA",
|
||||
"MFI14",
|
||||
"SCALE",
|
||||
"TS_CORR_10",
|
||||
"IF_GT"
|
||||
],
|
||||
"train_best_score": 0.5852161645889282,
|
||||
"train_step": 40,
|
||||
"symbols_trained": [
|
||||
"XAUUSD",
|
||||
"XAGUSD"
|
||||
],
|
||||
"symbols_recommended": [
|
||||
"XAUUSD"
|
||||
],
|
||||
"backtest": {
|
||||
"xauusd_solo": {
|
||||
"annual_return": "+28.2%",
|
||||
"sharpe": 2.66,
|
||||
"max_drawdown": "-11%",
|
||||
"win_rate": "55.4%",
|
||||
"turnover": "109 trades/year",
|
||||
"data": "8.0 years, 50,000 H1 bars"
|
||||
},
|
||||
"precious_metals_dual": {
|
||||
"annual_return": "+33.2%",
|
||||
"sharpe": 2.39,
|
||||
"oos_total_pnl": "+1.99 (3/4 folds profitable)",
|
||||
"note": "XAUUSD -24.9% / XAGUSD +58.1%"
|
||||
}
|
||||
},
|
||||
"logic": {
|
||||
"summary": "微型市场体制切换模型",
|
||||
"detail": "用Kyle Lambda与MFI14的10期相关性判断市场体制: corr>0=流动性驱动行情用Kyle惯性, corr<=0=流动性紊乱退守趋势强度"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
"""
|
||||
train_precious_metals.py — 贵金属策略训练(XAUUSD + XAGUSD)
|
||||
"""
|
||||
import sys, time
|
||||
from pathlib import Path
|
||||
sys.path.insert(0, str(Path(__file__).parent))
|
||||
|
||||
from config import Config
|
||||
from data_pipeline.fetcher import MT5DataFetcher
|
||||
from model_core.config import ModelConfig
|
||||
from main import train_group
|
||||
|
||||
def main():
|
||||
offline = "--offline" in sys.argv
|
||||
t0 = time.time()
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print(f" AlphaGPT 训练 — precious_metals 组 (贵金属)")
|
||||
print(f"{'='*60}")
|
||||
print(f" 品种: {Config.SYMBOL_GROUPS['precious_metals']}")
|
||||
print(f" 奖励模式: {ModelConfig.REWARD_MODE}")
|
||||
print(f" 训练步数: {ModelConfig.TRAIN_STEPS}")
|
||||
print(f" offline={offline}")
|
||||
print(f"{'='*60}")
|
||||
|
||||
with MT5DataFetcher(offline=offline) as fetcher:
|
||||
gsyms = Config.SYMBOL_GROUPS["precious_metals"]
|
||||
eng = train_group(fetcher, "precious_metals", gsyms, offline)
|
||||
if eng is not None:
|
||||
print(f"\n<<< [precious_metals] 完成: score={eng.best_score:.4f}")
|
||||
print(f" {eng._decode_formula(eng.best_formula)}")
|
||||
else:
|
||||
print("\n<<< [precious_metals] 失败")
|
||||
|
||||
elapsed = time.time() - t0
|
||||
print(f"\n耗时 {elapsed/3600:.2f}h")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user