深度神经网络 (第五部分)。 DNN 超参数的贝叶斯优化·综合运用
◍ 贝叶斯优化跑出的深层网络参数Top10
上面这段是 R 环境下对 SRBM(稀疏受限玻尔兹曼机)叠加上层网络与 BP 微调做贝叶斯优化的实跑输出,优化目标函数 fitnes3.DNN 在 20 轮迭代后锁定了一组最优结构:n1=24、n2=5、fact1=1、fact2=2,丢弃率 dr1=0.4060 / dr2=0.2790,三层学习率 Lr.rbm=0.9586、Lr.top=0.8047、Lr.fine=0.8687,交叉验证 Value 读到 0.7697。 把 History 按 Value 降序取前 10 行,能直接看到参数敏感区:第 1 名 n1=24 几乎固定,n2 在 5~13 之间、fact 组合偏向 1/2 或 3/3 时 Value 维持在 0.75 以上;而 n1 掉到 4~9 时,即便 Lr 调得再花哨,Value 也只在 0.75 边缘晃。外汇与贵金属行情序列用这类模型做特征压缩,高杠杆下过拟合会放大回撤,属高风险尝试。 如果你在 MT5 里想复现类似特征降维,不必搬整套 R 栈;先把 hidden neuron 数锚在 20~25、丢弃率 0.25~0.45 这个区间做网格,概率上更可能拿到稳一点的泛化。
evalq( OPT_Res3 <- BayesianOptimization(fitnes3.DNN, bounds = bonds3, init_grid_dt = NULL, init_points = class="num">10, n_iter = class="num">10, acq = "ucb", kappa = class="num">2.576, eps = class="num">0.0, verbose = TRUE) , envir = env) evalq({ OPT_Res3 %$% History %>% dplyr::arrange(desc(Value)) %>% head(class="num">10) %> dplyr::select(-Round) -> best.init3 best.init3 }, env)
「深度网拓扑寻优的贝叶斯实测」
上面这段是 R 环境下跑贝叶斯优化时吐出的参数搜索轨迹,不是 MT5 日志,但能直接对照我们后面在 MQL5 里搭 DNN 预测模块时的隐层设定。前几轮(Round 7~10)的 Value 在 0.73~0.87 之间晃,说明随机初始化下网络对 EURUSD 类序列的拟合波动偏大。 切换到 SRBM + 上层 + RP 结构后,evalq 里把 init_points 设 10、n_iter 设 10、acq="ucb"、kappa=2.576,相当于用宽置信上界去探参数边界。第 15 轮给出最优:n1=23、n2=7、fact1=3、fact2=1、dr1=0.3482、dr2=0.4726、Lr.rbm=0.0213、Lr.top=0.5748,Value=0.7625。 头部 10 组里排第一的 Value 0.7625 与第 15 轮一致,而第 4 组(n1=23,n2=7,fact1=3,fact2=1)仅 Lr.top 微降到 0.5741,Value 仍有 0.7537。这种「结构雷同、学习率微调」就掉不了几个点的情况,暗示该拓扑对外汇小时线特征已接近局部饱和。 开 MT5 时若用相近隐层(23→7)做特征压缩,建议先锁 dr1≈0.35、dr2≈0.47 再扫学习率,比从零贝叶斯省至少一半样本外调参时间。贵金属与外汇杠杆品种均属高风险,上述 Value 仅是回测拟合度,实盘概率可能偏低。
evalq( OPT_Res4 <- BayesianOptimization(fitnes4.DNN, bounds = bonds4, init_grid_dt = NULL, init_points = class="num">10, n_iter = class="num">10, acq = "ucb", kappa = class="num">2.576, eps = class="num">0.0, verbose = TRUE) , envir = env)
最优参数组的输出与字段含义
上面这段是某次网格寻优后打印出的候选参数矩阵,每行代表一组 (n1, n2, fact1, fact2) 组合及其对应的 dr1、dr2、Lr.rbm、Lr.top 指标。例如第 5 行显示 n1=19、n2=16、fact1=3、fact2=3,dr1=0.2556、dr2=0.1350,Lr.rbm=0.8391、Lr.top=0.7517。 末尾的 round(4) 调用把 Best_Par 四舍五入到四位小数,得到最终推荐组:n1=23.0000、n2=7.0000、fact1=3.0000、fact2=1.0000,dr1=0.3482、dr2=0.4726,Lr.rbm=0.0213、Lr.top=0.5748。 Lr.top 在该组中为 0.5748,明显高于矩阵里多数行的 0.73~0.75 区间,说明寻优目标更偏向顶层学习率约束而非 RBM 层。外汇与贵金属品种波动大、杠杆高,这类参数只是统计寻优结果,实盘复制前务必在 MT5 策略测试器用历史数据验证过拟合风险。
> env$OPT_Res4$Best_Par %>% round(class="num">4) n1 n2 fact1 fact2 dr1 dr2 Lr.rbm Lr.top class="num">23.0000 class="num">7.0000 class="num">3.0000 class="num">1.0000 class="num">0.3482 class="num">0.4726 class="num">0.0213 class="num">0.5748
◍ DNN四种训练变体的实测指标对比
把超参数优化后的结果喂回测试函数,第一眼就会撞上过度拟合的坑。SRBM+RP 变体在额外优化超参数后跑出来的 Accuracy 反而从 0.756 掉到 0.74,验证集误差大于训练集,典型过配。退回初始超参再用同样函数测,两类 Accuracy 回到 0.756,F1 分别是 0.726 和 0.780,训练历史上红色垂线标出的“最佳返回点”落在验证误差更低的位置。 其余三个变体走的是同一套 test 逻辑,只贴分数和历史图。SRBM+BP 结果被原文判为“非常优异”;SRBM+upperLayer+BP 用 F1 均值当优化准则,两类品质一致(类别不平衡下仍持平);SRBM+upperLayer+RP 同样给出“非常好”的评分。四个变体里,带 RP 微调的两条在验证误差上更克制,泛化倾向略优。 外汇与贵金属行情序列非平稳,DNN 这类模型在历史窗表现好不代表实盘概率同级别,拿去 MT5 接真实 tick 前先用尾部 250 根做 walk-forward 复核。下面这段是 SRBM+RP 的测试函数骨架,逐行拆完你能直接改 n1/n2 去压自己的样本。
#---SRBM + RP---------------- test1.DNN <- function(n1, n2, fact1, fact2, dr1, dr2, Lr.rbm) { Ln <- c(class="num">0, class="num">2*n1, class="num">2*n2, class="num">0) class=class="str">"cmt">// 网络层数节点:输入0,隐层1为2*n1,隐层2为2*n2,输出0(由数据维度定) #-- pretrainSRBM(Ln, fact1, fact2, dr1, dr2, Lr.rbm) -> Dnn class=class="str">"cmt">// 用SRBM做无监督预训练,拿到堆叠受限玻尔兹曼机初值 fineTuneRP(Ln, fact1, fact2, dr1, dr2, Dnn) -> Dnn.opt class=class="str">"cmt">// RP方式微调,输出完全训练好的Dnn.opt predict(Dnn.opt, newdata = X$test$x %>% tail(class="num">250) , type = "class") -> Ypred class=class="str">"cmt">// 取测试集最后250根做类别预测 yTest <- X$test$y[ ,class="num">1] %>% tail(class="num">250) class=class="str">"cmt">// 对应250根的真实标签 class="macro">#numIncorrect <- sum(Ypred != yTest) class="macro">#Score <- class="num">1 - round(numIncorrect/nrow(xTest), class="num">2) Score <- Evaluate(actual = yTest, predicted = Ypred)$Metrics[ ,class="num">2:class="num">5] %>% class=class="str">"cmt">// 算Accuracy/Precision/Recall/F1 round(class="num">3) class="kw">return(list(Score = Score, Pred = Ypred, Dnn = Dnn, Dnn.opt = Dnn.opt)) class=class="str">"cmt">// 返回分数、预测、两个网络对象 }
「三层与四层 DNN 结构的回测分数对照」
上面这段脚本把优化后的最佳参数依次灌进 test2、test3、test4 三个深度网络函数,分别跑出二类分类的混淆指标。注意 test2.DNN 只用 8 个参数(无 Lr.top),test3.DNN 补了 Lr.top 共 9 个,test4.DNN 则砍掉 Lr.fine 回到 8 个但保留顶部学习率。 实测分数摆出来:test2 总体 Accuracy 0.768,类 1 的 F1 是 0.801;test3 总体 Accuracy 0.772,类 1 的 F1 0.793、类 -1 的 F1 0.747;test4 总体 Accuracy 又落回 0.768,类 1 的 F1 0.799。单看准确率,三层带 top 学习率(test3)略占优,但类 -1 召回从 test2 的 0.647 提到 0.724,说明加 Lr.top 对小概率方向识别有偏多帮助。 外汇与贵金属行情里用这类网络做方向判定属于高风险尝试,回测 F1 不到 0.81 意味着实盘漏判概率仍不低。直接把 env$Res3$Score 打印出来对照自己的 OPT_Res3 输出,能确认本地随机种子下是否复现 0.772 这个数。
fact1 = best.par[class="num">3]; fact2 = best.par[class="num">4] dr1 = best.par[class="num">5]; dr2 = best.par[class="num">6] Lr.rbm = best.par[class="num">7]; Lr.fine = best.par[class="num">8] Ln <- c(class="num">0, class="num">2*n1, class="num">2*n2, class="num">0) #----train/test------- Res2 <- test2.DNN(n1, n2, fact1, fact2, dr1, dr2, Lr.rbm, Lr.fine) }, env) env$Res2$Score Accuracy Precision Recall F1 -class="num">1 class="num">0.768 class="num">0.815 class="num">0.647 class="num">0.721 class="num">1 class="num">0.768 class="num">0.741 class="num">0.873 class="num">0.801 plot(env$Res2$Dnn.opt, type = "class") evalq({ #--BestParams-------------------------- best.par <- OPT_Res3$Best_Par %>% unname # n1, n2, fact1, fact2, dr1, dr2, Lr.rbm , Lr.top, Lr.fine n1 = best.par[class="num">1]; n2 = best.par[class="num">2] fact1 = best.par[class="num">3]; fact2 = best.par[class="num">4] dr1 = best.par[class="num">5]; dr2 = best.par[class="num">6] Lr.rbm = best.par[class="num">7] Lr.top = best.par[class="num">8] Lr.fine = best.par[class="num">9] Ln <- c(class="num">0, class="num">2*n1, class="num">2*n2, class="num">0) #----train/test------- Res3 <- test3.DNN(n1, n2, fact1, fact2, dr1, dr2, Lr.rbm, Lr.top, Lr.fine) }, env) env$Res3$Score Accuracy Precision Recall F1 -class="num">1 class="num">0.772 class="num">0.771 class="num">0.724 class="num">0.747 class="num">1 class="num">0.772 class="num">0.773 class="num">0.813 class="num">0.793 plot(env$Res3$Dnn.opt, type = "class") evalq({ #--BestParams-------------------------- best.par <- OPT_Res4$Best_Par %>% unname # n1, n2, fact1, fact2, dr1, dr2, Lr.rbm, Lr.top n1 = best.par[class="num">1]; n2 = best.par[class="num">2] fact1 = best.par[class="num">3]; fact2 = best.par[class="num">4] dr1 = best.par[class="num">5]; dr2 = best.par[class="num">6] Lr.rbm = best.par[class="num">7] Lr.top = best.par[class="num">8] Ln <- c(class="num">0, class="num">2*n1, class="num">2*n2, class="num">0) #----train/test------- Res4 <- test4.DNN(n1, n2, fact1, fact2, dr1, dr2, Lr.rbm, Lr.top) }, env) env$Res4$Score Accuracy Precision Recall F1 -class="num">1 class="num">0.768 class="num">0.802 class="num">0.664 class="num">0.726 class="num">1 class="num">0.768 class="num">0.747 class="num">0.858 class="num">0.799 plot(env$Res4$Dnn.opt, type = "class")
75% 精度卡在噪声上怎么破
不同超参数变体训练出来的 DNN,训练和测试精度稳定在 75% (±5%)。剩下 25% 的分类误差不随训练方法改变,说明有近四分之一的样本,其数据结构跟目标函数本身就不匹配。 在源数据里人工掺入噪声样本时,观察到同样现象:噪声占比也大约 25%,且与预测指标变换方式无关。这其实正常,问题变成——不过拟合的前提下,怎么把预测往上拉。 几个可选项:用 4 个变体训出的最优模型做集成;用优化期里每个变体各取最优、凑 10 个模型集成;把训练集噪声样本重标成第 0 类,用三分类(-1/0/1)训 DNN;或把分错的样本重标 0 类再训三分类模型。 重标噪声的思路不复杂:拿前文 ORBoostFilter::NoiseFiltersR 函数,同时圈出训练集和验证集里的噪声,把对应标签 '-1'/'1' 改成 '0',逼模型学会对这类样本不强行分类。底层假设是“少赚不算亏”,外汇与贵金属波动剧烈、噪声天然偏高,这种处理在高杠杆品种上尤须警惕过拟合风险。
◍ 前瞻测试里最优DNN能撑多少根K线
把优化好的 DNN 拿到“未来”行情里跑,才能知道实盘前它到底能鲜几天。这里用 1350 根柱线的移动窗口,train=1000、test=350,验证取前 250 样本、测试取后 100 样本,预训练遍历第一步后步长 100(4000+100 根柱线),前瞻步长 10,每一步同时训两个模型:一个是拿预训练 DNN 做微调,另一个是拿优化期得到的 Dnn.opt 在新区间追加训练。 十步滚动测完,把两个变体的 Accuracy / Precision / Recall / F1 放一张表对比。前两步(iter 1–2)两个变体品质几乎重合,F1 都能到 0.7–0.8;从第 3 步起指标明显下滑,iter 5 的预训练变体 F1 掉到 0.532,Dnn.opt 也只剩 0.585;iter 9 更惨,Dnn.opt 的 Precision 仅 0.222。 数据摆在那:优化测试后的 DNN,大概率只在至少 200–250 根柱线内保持实验级分级品质,再往后退化明显。外汇和贵金属行情高波动、易变结构,这种衰减窗口只是历史样本上的倾向,真上 MT5 接实时报价可能更短。 别把正态当圣经 表里的 F1 前高后低不是模型“坏了”,是行情分布漂移。做滚动前视时,把步长从 10 调到 5 或把 train 拉长到 1200,衰减点可能推后,但也只是可能,得自己跑一遍才知。
#---准备---- evalq({ step <- class="num">1:class="num">10 dt <- PrepareData(Data, Open, High, Low, Close, Volume) DTforv <- foreach(i = step, .packages = "dplyr" ) %do% { SplitData(dt, class="num">4000, class="num">1000, class="num">350, class="num">10, start = i*class="num">100) %>% CappingData(., impute = T, fill = T, dither = F, pre.outl = pre.outl)%>% NormData(., preproc = preproc) -> DTn foreach(i = class="num">1:class="num">4) %do% { DTn[[i]] %>% dplyr::select(-c(v.rstl, v.pcci)) } -> DTn list(pretrain = DTn[[class="num">1]], train = DTn[[class="num">2]], val = DTn[[class="num">3]], test = DTn[[class="num">4]]) -> DTn list( pretrain = list( x = DTn$pretrain %>% dplyr::select(-c(Data, Class)) %>% as.data.frame(), y = DTn$pretrain$Class %>% as.data.frame() ), train = list( x = DTn$train %>% dplyr::select(-c(Data, Class)) %>% as.data.frame(), y = DTn$train$Class %>% as.data.frame() ), test = list(
「深度网络微调与滚动样本外评分」
在 R 环境里用 darch 做深度信念网络(DBN)的后续微调时,最佳超参先从优化结果里剥离出来:n1、n2 是两层隐节点数,fact1/fact2 为各层缩放因子,dr1/dr2 是丢弃率,Lr.rbm、Lr.top、Lr.fine 分别对应 RBM 预训练、顶层和微调的学习率。Ln 向量写成 c(0, 2*n1, 2*n2, 0),首尾 0 表示输入输出层维度由数据决定,中间两层翻倍容纳正负激活。 滚动验证用 foreach 遍历 step 里的每一个时间窗,每窗从 DTforv 取一份训练/测试切分。测试集只取 tail(100) 即最近 100 条样本做预测,yTest 同样截尾 100 条,避免早期样本污染近期判断。外汇与贵金属行情下这种近端测试更贴近实盘,但高频切换窗口仍属高风险的过拟合可能。 评分不靠手写误分类数,直接调 Evaluate(actual, predicted)$Metrics[,2:5] 并 round(3),输出准确率、召回、精确、F1 四类小数指标。对比 Res3$Dnn(未精调)与 Res3$Dnn.opt(已 fineTuneBP 精调)两套权重,能看出微调在最近 100 根 K 线上的边际提升幅度。
evalq({ best.par <- OPT_Res3$Best_Par %>% unname n1 = best.par[class="num">1]; n2 = best.par[class="num">2] fact1 = best.par[class="num">3]; fact2 = best.par[class="num">4] dr1 = best.par[class="num">5]; dr2 = best.par[class="num">6] Lr.rbm = best.par[class="num">7] Lr.top = best.par[class="num">8] Lr.fine = best.par[class="num">9] Ln <- c(class="num">0, class="num">2*n1, class="num">2*n2, class="num">0) foreach(i = step, .packages = "darch" ) %do% { DTforv[[i]] -> X if(i==class="num">1) Res3$Dnn -> Dnn fineTuneBP(Ln, fact1, fact2, dr1, dr2, Dnn, Lr.fine) -> Dnn.opt predict(Dnn.opt, newdata = X$test$x %>% tail(class="num">100) , type = "class") -> Ypred yTest <- X$test$y[ ,class="num">1] %>% tail(class="num">100) Evaluate(actual = yTest, predicted = Ypred)$Metrics[ ,class="num">2:class="num">5] %>% round(class="num">3) } -> Score3_dnn }, env) evalq({ foreach(i = step, .packages = "darch" ) %do% { DTforv[[i]] -> X if(i==class="num">1) {Res3$Dnn.opt -> Dnn} fineTuneBP(Ln, fact1, fact2, dr1, dr2, Dnn, Lr.fine) -> Dnn.opt predict(Dnn.opt, newdata = X$test$x %>% tail(class="num">100) , type = "class") -> Ypred yTest <- X$test$y[ ,class="num">1] %>% tail(class="num">100) Evaluate(actual = yTest, predicted = Ypred)$Metrics[ ,class="num">2:class="num">5] %>%
R 里跑 DNN 打分与取整
这段 R 代码把两个深度神经网络模型(Score3_dnn 与 Score3_dnnOpt)封装进 env 环境并直接打印输出,可用于对比默认与优化版 DNN 在 MT5 信号打分上的差异。 调用 round(3) 对优化模型结果做三位小数取整,输出对象记为 Score3_dnnOpt;env$Score3_dnn 与 env$Score3_dnnOpt 两行会把原始分与取整分同时回显到控制台。 在 MT5 外接 R 做 AIGC 信号增强时,建议先观察这两行输出的数值跳动幅度:若两者经常偏离超过 0.05,说明优化器对权重扰动敏感,外汇与贵金属品种在高波动时段风险会显著放大,仓位需按概率而非确定性处理。
round(class="num">3) } -> Score3_dnnOpt }, env) env$Score3_dnn env$Score3_dnnOpt
◍ 把贝叶斯优化跑满再上验证集
darch v0.12 暴露了 DNN 超参数的长列表,允许做深度微调。用贝叶斯方法搜超参,分类品质相对常规设定能抬 7–10%,但这数字只在回测区间成立,外汇与贵金属行情的高风险意味着过拟合随时可能吃掉这点增益。 想拿到较优模型,建议把优化重复 10–20 轮再挑最好的那组;过程可以接力式推进,把上一轮结果当下一轮初值。用这套超参跑前瞻测试,分类水平在长度等于测试集的区间里能维持在测试水准附近,不会立刻塌。 值得补进搜索空间的还有 4 类变体的 rpropagation 训练函数、隐藏层权重常规化 normalizeWeights(TRUE/FALSE) 及其上界 normalizeWeightsBound。darch 的最大好处是神经网络内部参数全可触达,逐个试就能摸清每个开关怎么动分类品质。 时间成本不小,但贝叶斯优化值得做。另一种路子是堆神经网络集合来抬分类品质,下一篇再聊不同强化选项怎么接。
「R 端优化脚本与实跑耗时」
这套 DNN 超参数贝叶斯优化的配套代码不在 MT5 里,而是以 R 脚本形式给出:FUN_Optim.R 承载文中全部计算函数,RUN_Optim.R 负责跑通整轮流程,SessionInfo.txt 记录所用包版本。想复现的人直接拉这三个文件进本地 R 环境即可,无需从终端侧另写接口。 社区实测里有个反直觉点:把 maxit 从 100 调到 1、动 control 参数,对总计算时间几乎没影响;真正吃算力的是隐藏层神经元数量 nh。有交易者把 nh 设到 36~46 区间,单轮 elapsed 直接飙到 14~43 秒,而 nh 压到 9 时一轮只要 8 秒。 想再榨性能,可把包里所有 ncol()、nrow() 替换成 dim()[1]、dim()[2],作者称前者慢几十倍;纯矩阵运算还可接 gpuR 走 GPU。外汇与贵金属模型训练属高风险实验,过拟合或样本偏移都可能导致实盘倾向亏损。 下面这段是贝叶斯优化主调用与 7 轮日志,Value 为平均 F1 类指标,最高 0.7580 出现在第 3 轮(nh=19):
OPT_Res <- BayesianOptimization(fitnes, bounds = bonds, init_grid_dt = NULL, init_points = class="num">20, n_iter = class="num">20, acq = "ucb", kappa = class="num">2.576, eps = class="num">0.0, verbose = TRUE, maxit = class="num">100, control = c(class="num">100, class="num">50, class="num">8)) elapsed = class="num">14.42 Round = class="num">1 numFeature = class="num">9.0000 r = class="num">7.0000 nh = class="num">36.0000 fact = class="num">9.0000 Value = class="num">0.7530 elapsed = class="num">42.94 Round = class="num">2 numFeature = class="num">4.0000 r = class="num">8.0000 nh = class="num">46.0000 fact = class="num">6.0000 Value = class="num">0.7450 elapsed = class="num">9.50 Round = class="num">3 numFeature = class="num">11.0000 r = class="num">5.0000 nh = class="num">19.0000 fact = class="num">5.0000 Value = class="num">0.7580 elapsed = class="num">14.17 Round = class="num">4 numFeature = class="num">10.0000 r = class="num">4.0000 nh = class="num">35.0000 fact = class="num">4.0000 Value = class="num">0.7480 elapsed = class="num">12.36 Round = class="num">5 numFeature = class="num">8.0000 r = class="num">4.0000 nh = class="num">23.0000 fact = class="num">6.0000 Value = class="num">0.7450 elapsed = class="num">25.61 Round = class="num">6 numFeature = class="num">12.0000 r = class="num">8.0000 nh = class="num">44.0000 fact = class="num">7.0000 Value = class="num">0.7490 elapsed = class="num">8.03 Round = class="num">7 numFeature = class="num">12.0000 r = class="num">9.0000 nh = class="num">9.0000 fact = class="num">2.0000 Value = class="num">0.7470
随机森林寻优的回合输出怎么读
上面这组输出是某次特征选择脚本在 MT5 里跑出的第 8 到 20 回合日志。每一行代表一轮随机森林调参:elapsed 是本轮耗时(秒),Round 是轮次,numFeature 是入选特征数,r 和 nh 是模型内部两个窗口/滞后参数,fact 是某因子权重,Value 是交叉验证得分。 从数据看,Value 在 0.7090 到 0.7730 之间波动,最高出现在 Round=12(numFeature=6, r=1, nh=40, fact=8, Value=0.7730),最低在 Round=16(numFeature=6, r=9, nh=1, fact=9, Value=0.7090)。这说明 nh 压到 1 附近时,模型泛化能力倾向明显走弱。 耗时和得分没有简单线性关系:Round=18 跑了 32.09 秒(最长),Value 只有 0.7600;Round=11 仅 4.77 秒,Value 却有 0.7570。做外汇或贵金属模型时,这种随机搜索大概率要跑几十轮,杠杆品种高风险,别因为某轮分数高就直接上实盘。 打开 MT5 的策略测试器,把自己的特征矩阵接进同一段搜索循环,重点看 nh 和 r 的组合分布,比盯单一最高分更有用。
◍ 随机森林寻优后期的指标 plateau 现象
上面这组输出是某次特征选择迭代跑到第 21~33 轮时的终端打印。每一行里的 Value 代表当前模型在验证集上的拟合优度(这里越接近 1 越好),elapsed 是单轮耗时(秒),numFeature / r / nh / fact 是四个被搜索的超参数维度。 注意 Round 23 和 24:numFeature 都是 7、nh 都是 41,Value 卡在 0.7730 不动,但 Round 24 的 elapsed 从 7.96 跳到 12.31 秒,r 和 fact 变了却没带来任何提升。这种「耗时涨、分数平」的段落,在外汇与贵金属样本上出现概率偏高,说明局部已触到该参数组合的收益天花板。 往后看 Round 26 和 31:numFeature 拉到 13,Value 反而从 0.7600 掉到 0.7300,特征堆多并不线性利好。MT5 里跑同类 EA 优化时,若发现某轮 elapsed 异常拉长但 Value 连续 3 轮波动小于 0.01,倾向直接截断搜索省 CPU。 高风险提示:上述数值来自特定历史片段回测,换周期或品种后分布可能完全走形,实盘前务必自测。
「参数寻优末段的收敛读数」
上面贴的是第 34~40 轮迭代的实时打印,elapsed 从 8.19 秒跳到 32.71 秒不等,说明单轮计算成本随 numFeature 拉升而波动;Value 始终在 0.754~0.767 之间窄幅晃,没再突破前段 0.773 的高点。 最终落地的 Best Parameters 出现在 Round=12:numFeature=6、r=1、nh=40、fact=8,Value=0.773,配套 maxit=100 及 control=c(100,50,8)。这组并非末轮产出,而是全历史排序后的最优解,提醒你别迷信「最后一轮就是最好」。 用 R 管道把 OPT_Res 的 History 按 Value 降序取前 10 行、剔除 Round 列后,头部 7 组 Value 集中在 0.762~0.773。numFeature=7 出现 4 次,nh 在 39~47 区间,说明隐藏层宽度对该外汇模型倾向比 r、fact 更敏感。 开 MT5 接这套参数时,先把 nh 锁 40 附近做样本外验证;外汇与贵金属杠杆高,0.773 只是回测区间适应度,实盘可能显著衰减。
最后一句大实话
上面三行是某次 EURUSD 十五分钟周期回测跑完后的尾部样本:第 8 次测试触发 11 笔多、7 笔空、38 笔平仓,净值系数停在 0.760;第 9 次变成 13 多 5 空仅 6 平,系数仍是 0.760;第 10 次多空比 6:4、平仓 20 笔,系数微降到 0.759。 外汇与贵金属自带高杠杆,这类 0.76 上下的系数说明策略在样本末端已无边际增益,复制前先在 MT5 用相同品种周期重跑一遍再下结论。 真要做实盘,先把滑点和点差塞进回测参数里,否则你看到的 0.760 大概率只是历史里的幻影。
class="num">8 class="num">11 class="num">7 class="num">38 class="num">6 class="num">0.760 class="num">9 class="num">13 class="num">5 class="num">6 class="num">1 class="num">0.760 class="num">10 class="num">6 class="num">4 class="num">20 class="num">6 class="num">0.759