神经网络: 智能交易系统自我优化·综合运用
🧠

神经网络: 智能交易系统自我优化·综合运用

(3/3)·从算法到ALGLIB落地,两个数学任务验证MLP能否撑起EA的自动重优化闭环

案例拆解 第 3/3 篇
把EA参数一次性优化完就丢着跑,是很多人的习惯。可市场状态漂移后,旧输入值迟早失灵,手动重优化又总慢半拍。让网络按周期自己回炉历史数据,才是把维护成本压下来的路子。

◍ 从文件复原多层感知机并取网络响应

这段逻辑负责把已训练好的神经网络参数从二进制文件读回,并封装成可复用的推理接口。读取时按层遍历:末层(k==numCapas-1)单独处理输出缩放,用 FileReadDouble 取 media 与 sigma 后交给 MLPSetOutputScaling;其余层则逐神经元设 funcTipo、umbral,并把跨层权重写回 MLPSetWeight。 文件指针关闭前若任何一步失败,exito 标记会置否,调用方据此判断网络加载是否成功。实盘里若 exito 返回 false,说明模型文件版本或结构不匹配,直接拿残参跑预测会出野值。 respuestaRed 是推理入口:MLPProcess 算完先把结果塞进 arSalidas。当 desnorm=true 时,按 maxAbsSalida / minAbsSalida 与 arMaxMinRelSals 记录的区间做反归一化,否则输出仍是压缩空间的数值。外汇与贵金属行情高波动,用未反归一化的输出直接下单可能严重偏离真实价格区间,须确认 desnorm 开关。 最终函数只返回 arSalidas[0] 作为网络响应。若你的网络是多输出头(如同时预测方向和波动率),这里要改下标或返回数组,否则只剩首通道有效。

MQL5 / C++
   }
   else if(k==numCapas-class="num">1)
   {
      media= FileReadDouble(puntFichRed);
      sigma= FileReadDouble(puntFichRed);
      CAlglib::MLPSetOutputScaling(objRed, i, media, sigma);
   }
   funcTipo= (class="type">int)FileReadDouble(puntFichRed);
   umbral= FileReadDouble(puntFichRed);
   CAlglib::MLPSetNeuronInfo(objRed, k, i, funcTipo, umbral);
   for(j= class="num">0; k<(numCapas-class="num">1) && j<arNeurCapa[k+class="num">1]; j++)
   {
      peso= FileReadDouble(puntFichRed);
      CAlglib::MLPSetWeight(objRed, k, i, k+class="num">1, j, peso);
   }
         }
      }
   }
   FileClose(puntFichRed);
   class="kw">return(exito);
}
class=class="str">"cmt">//--------------------------------------- 请求网络响应 ---------------------------------
class="type">class="kw">double respuestaRed(CMultilayerPerceptronShell &ObjRed, class="type">class="kw">double &arEntradas[], class="type">class="kw">double &arSalidas[], class="type">bool desnorm= false)
{
   class="type">class="kw">double resp= class="num">0, nNeuron= class="num">0;
   CAlglib::MLPProcess(ObjRed, arEntradas, arSalidas);
   if(desnorm)           class=class="str">"cmt">//如果输出数据规范化应改变
   {
      nNeuron= ArraySize(arSalidas);
      for(class="type">int k= class="num">0; k<nNeuron; k++)
         arSalidas[k]= desNormValor(arSalidas[k], maxAbsSalida, minAbsSalida, arMaxMinRelSals[class="num">1], arMaxMinRelSals[class="num">0]);
   }
   resp= arSalidas[class="num">0];
   class="kw">return(resp);
}

双图表分工让优化不误事

MT5 允许同一终端里每个图表各挂一个 EA 并行跑。把第一张图设成执行模式管策略,第二张图开优化模式只训练神经网络,执行端每隔一段时间去读优化端写出的网络文本文件,行情监视就不会因算力被吃掉而断档。 原单跑优化约耗 4–6 分钟,拆成双图表后总处理拉到 8–15 分钟,具体看亚洲还是欧洲时段活跃度,但策略端从不停止。外汇与贵金属杠杆高,这种并行只解决算力调度,不削减品种本身风险。 用两个枚举把节奏和角色交给用户:mis_PLAZO_OPTIM 决定每天 / 隔天 / 周末重算,mis_TIPO_EAred 切 _OPTIMIZA 或 _EJECUTA。horaOptim 默认 3 点(本地),对应欧盘清晨低波动;想启动即算就开 optimInicio。 OnTimer 由 OnInit 里 EventSetTimer(tmp) 拉起,tmp 至少每小时触发一次。优化端到点查是否重算,执行端查网络文件是否被更新。实测每晚 3 点用前 3 个月 1H 数据重训:输入 35、隐层 45 与 8、输出 2 神经元,耗时 35–45 分钟。

MQL5 / C++
enum mis_PLAZO_OPTIM {_DIARIO, _DIA_ALTERNO, _FIN_SEMANA};
enum mis_TIPO_EAred {_OPTIMIZA, _EJECUTA};
class="kw">input mis_TIPO_EAred tipoEAred                = _OPTIMIZA;          class=class="str">"cmt">//执行任务类型
class="kw">input mis_PLAZO_OPTIM plazoOptim              = _DIARIO;            class=class="str">"cmt">//网络优化的时间间隔
class="kw">input class="type">int horaOptim                           = class="num">3;                 class=class="str">"cmt">//网络优化的本地时间
class="kw">input class="type">bool optimInicio                        = true;              class=class="str">"cmt">//当 EA 启动时优化神经网络
class="type">class="kw">double fechaUltLectura;
class="type">bool reOptimizada= false;
/---------------------------------- 定时器 --------------------------------------
class="type">void OnTimer()
{
   class="type">bool existe= false;
   class="type">class="kw">string fichRed= "";
   if(tipoEAred==_OPTIMIZA)                class=class="str">"cmt">//EA 工作于 "优化器" 模式
   {
      class="type">bool optimizar= false;
      class="type">int codS= class="num">0,
          hora= infoFechaHora(TimeLocal(), _HORA);      class=class="str">"cmt">//接收完整的当前时间
      if(!redOptimizada) optimizar= horaOptim==hora && permReoptimDia();
      fichRed= "copiaSegurRed_"+Symbol()+".red";         class=class="str">"cmt">//定义神经网络文件名
      existe= buscaFich(fichRed, "*.red");              class=class="str">"cmt">//搜索神经网络文件保存的磁盘位置
      if(!existe || optimizar)
         redOptimizada= gestionRed(objRed, simb, intervEntrada!="", intervSalida!="", imprDatosEntrena, barajaDatos);
      if(hora>(horaOptim+class="num">6)) redOptimizada= false;      class=class="str">"cmt">//评估时间 class="num">6 个小时以上, 实际优化的网络应认定过时
      guardaVarGlobal(redOptimizada);                  class=class="str">"cmt">//在磁盘上保存 "reoptimizada" (重新优化) 的值
   }
   else if(tipoEAred==_EJECUTA)            class=class="str">"cmt">//EA 工作于 "致动器" 模式
   {
      class="type">class="kw">datetime fechaUltOpt= class="num">0;
      fichRed= "copiaSegurRed_"+Symbol()+".red";         class=class="str">"cmt">//定义神经网络文件名
      existe= buscaFich(fichRed, "*.red");              class=class="str">"cmt">//搜索神经网络文件保存的磁盘位置
      if(existe)
      {
         fechaUltOpt= fechaModifFich(class="num">0, fichRed);       class=class="str">"cmt">//定义最后优化日期 (网络文件修改)

「神经网络文件的重读与重优化闸门」

EA 在运行时不会盲目重载模型。它先比对优化日期与最后一次读取日期:若 fechaUltOpt 大于 fechaUltLectura,说明磁盘上的 .red 文件来自更新的训练结果,这时才调用 recuperaRedFich 重建网络,并把当前 TimeCurrent() 写回全局变量落盘。 下面这段逻辑直接决定「哪天允许重优化」。plazoOptim 设为 _DIARIO 时,周二到周六(diaSemana 不为 6 和 0)均可;_DIA_ALTERNO 只在奇数星期几(周二、四、六)放行;_FIN_SEMANA 仅周六(diaSemana==5)开启。改这几个宏,就能控制实盘重训练频率。 文件存在性检查交给 buscaFich:用 FileFindFirst 拿句柄,循环 FileFindNext 比对文件名,命中即返回 true。注意 carpeta 默认 FILE_COMMON,意味着跨终端共享目录——若你手动挪了 .red 文件到本地数据夹,这个函数会一直返回 false 并触发 Alert。外汇与贵金属波动剧烈,自动重优化可能放大过拟合风险,上线前建议在策略测试器跑至少 3 个月 tick 数据验证。

MQL5 / C++
   if(fechaUltOpt>fechaUltLectura)                 class=class="str">"cmt">//是否优化日期晚于最后一次读取
   {
      recuperaRedFich(objRed, fichRed);             class=class="str">"cmt">//读取并生成新的神经网络
      fechaUltLectura= (class="type">class="kw">double)TimeCurrent();
      guardaVarGlobal(fechaUltLectura);             class=class="str">"cmt">//在磁盘上保存新的读取日期
      Print("Network restored after optimization... "+simb);   class=class="str">"cmt">//在屏幕上显示消息
   }
  }
   else Alert("tipoEAred==_EJECUTA --> 神经网络文件未发现: "+fichRed+".red");
  }
  class="kw">return;
}
class=class="str">"cmt">//--------------------------------- 启用重新优化 ---------------------------------
class="type">bool permReoptimDia()
{
   class="type">int diaSemana= infoFechaHora(TimeLocal(), _DSEM);
   class="type">bool permiso= (plazoOptim==_DIARIO && diaSemana!=class="num">6 && diaSemana!=class="num">0) ||     class=class="str">"cmt">//优化 [从周二到周六的每天]
                 (plazoOptim==_DIA_ALTERNO && diaSemana%class="num">2==class="num">1) ||              class=class="str">"cmt">//优化 [周二, 周四和周六]
                 (plazoOptim==_FIN_SEMANA && diaSemana==class="num">5);                   class=class="str">"cmt">//优化 [周六]
   class="kw">return(permiso);
}
class=class="str">"cmt">//-------------------------------------- 搜索文件 --------------------------------------------
class="type">bool buscaFich(class="type">class="kw">string fichBusca, class="type">class="kw">string filtro= "*.*", class="type">int carpeta= FILE_COMMON)
{
   class="type">bool existe= false;
   class="type">class="kw">string fichActual= "";
   class="type">long puntBusca= FileFindFirst(filtro, fichActual, carpeta);
   if(puntBusca!=INVALID_HANDLE)
   {
      ResetLastError();
      class="kw">while(!existe)
      {
         FileFindNext(puntBusca, fichActual);
         existe= fichActual==fichBusca;
      }
      FileFindClose(puntBusca);
   }
   else Print("文件未发现!");
   infoError(_LastError, __FUNCTION__);
   class="kw">return(existe);
}

◍ 拿二进制转十进制给网络做压力测试

想验证一套神经网络系统靠不靠谱,最省事的办法是先拿一个有标准答案的任务喂给它,再把它的输出和已知结果比对。二进制到十进制的映射就是这种任务:规则明确、答案确定,适合用来探网络的底。 脚本用前 800 个自然数的 10 位二进制串(10 个输入神经元、1 个输出神经元、无隐藏层)训练网络,再用 801 到 1000 的 200 个数做评估。比如输入 1100110100(即十进制 820),网络应当输出接近 820 的值,第三列标记 'true' 表示预测与期望一致。 以「10 输入、0 隐藏、1 输出、线性激活」跑完,Terminal\Common\Files 下的 ScriptBinDec-infRN.csv 显示 200 个评估样本全部命中,结果堪称优秀。 换结构就翻车了:若改成「10 输入、隐藏层 20+8 神经元、1 输出」,评估列里大量非 'true',属于不可接受误差。这暴露出神经网络最麻烦的一点——层数、每层神经元数、激活函数怎么配,没有理论公式直接给答案。 别把结构当成随便叠积木 实际只能靠经验趟坑:自己跑几千次组合,或先用快速挖掘类统计软件在进 MQL5 前筛掉明显低效的结构,再上 MT5 实测。外汇与贵金属行情受宏观事件驱动,用 NN 做此类映射验证时同样要意识到过拟合与样本外失效的高风险。

MQL5 / C++
class="macro">#class="kw">property script_show_confirm
class="macro">#define FUNC_CAPA_OCULTA   class="num">1
class="macro">#define FUNC_SALIDA        -class="num">5
            class=class="str">"cmt">//class="num">1= 双曲正切; class="num">2= e^(-x^class="num">2); class="num">3= x>=class="num">0 raizC(class="num">1+x^class="num">2) x<class="num">0 e^x; class="num">4= S 形函数;
            class=class="str">"cmt">//class="num">5= 二项式 x>class="num">0.5?class="num">1: class="num">0; -class="num">5= 线性函数
class="macro">#include <Math\Alglib\alglib.mqh>
enum mis_PROPIEDADES_RED {N_CAPAS, N_NEURONAS, N_ENTRADAS, N_SALIDAS, N_PESOS};
class=class="str">"cmt">//---------------------------------  输入  ---------------------
sinput class="type">int nNeuronEntra= class="num">10;                    class=class="str">"cmt">//输入层神经元数量
                                                  class=class="str">"cmt">//class="num">2^class="num">8= class="num">256 class="num">2^class="num">9= class="num">512; class="num">2^class="num">10= class="num">1024; class="num">2^class="num">12= class="num">4096; class="num">2^class="num">14= class="num">16384 
sinput class="type">int nNeuronCapa1= class="num">0;                     class=class="str">"cmt">//第一个隐藏层的神经元数量 (不能 <class="num">1)
sinput class="type">int nNeuronCapa2= class="num">0;                     class=class="str">"cmt">//第二个隐藏层的神经元数量 (不能 <class="num">1)                                                                       //class="num">2^class="num">8= class="num">256 class="num">2^class="num">9= class="num">512; class="num">2^class="num">10= class="num">1024; class="num">2^class="num">12= class="num">4096; class="num">2^class="num">14= class="num">16384 
sinput class="type">int nNeuronSal= class="num">1;                       class=class="str">"cmt">//输出层的神经元数量
sinput class="type">int    historialEntrena= class="num">800;            class=class="str">"cmt">//训练历史
sinput class="type">int    historialEvalua= class="num">200;             class=class="str">"cmt">//评估历史
sinput class="type">int    ciclosEntrena= class="num">2;                 class=class="str">"cmt">//训练循环
sinput class="type">class="kw">double tasaAprende= class="num">0.001;               class=class="str">"cmt">//网络训练级别
sinput class="type">class="kw">string intervEntrada= "";                class=class="str">"cmt">//输入规范化: 期望的最小值和最大值 max(空= 无需优化)
sinput class="type">class="kw">string intervSalida= "";                 class=class="str">"cmt">//输出优化: 期望最小值和最大值 (空= 无需优化)
sinput class="type">bool   imprEntrena= true;                class=class="str">"cmt">//显示训练/评估数据
            
class=class="str">"cmt">// ------------------------------ 全局变量 -----------------------------    
class="type">int puntFichTexto= class="num">0;
class="type">class="kw">ulong contFlush= class="num">0;
CMultilayerPerceptronShell redNeuronal;
CMatrixDouble arDatosAprende(class="num">0, class="num">0);
CMatrixDouble arDatosEval(class="num">0, class="num">0);
class="type">class="kw">double minAbsSalida= class="num">0, maxAbsSalida= class="num">0;

用脚本把二进制塞进神经网络验精度

这段 MT5 脚本把「二进制转十进制」当成一个极小监督任务,用来跑通你自建的神经网络函数簇。它不交易,只验证 redNeuronal 在已知映射上的拟合能力,外汇与贵金属行情用这类模型前务必自测,杠杆品种误判即放大亏损。 脚本先以 creaRedNeuronal 建网,再用 preparaDatosEntra 与 normalizaDatosRed 把训练集 arDatosAprende 投喂进去;entrenaEvalRed 返回的 errorMedioEntren 就是本次平均训练误差,直接落盘到 csv 方便你横向比参数。 评估段从 inicio 到 fin 遍历整数,dec_A_baseNumerica 把 k 编成 2 进制串喂网,respuestaRed 吐出小数后用 MathRound 取整。correcto 标记网络输出是否等于原十进制数,全部写进『numBinEntra;numDecSalidaRed;correcto』三列——你开 MT5 跑完搜 csv,数 correcto=false 的行就能算出误判率。 别把正态当圣经:normEntrada / normSalida 只是开关,intervEntrada 为空时网络拿原始 0/1 训练,误差曲线可能更抖,但小样本下未必更差。

MQL5 / C++
class="type">class="kw">string nombreEA= "ScriptBinDec";
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart()                 class=class="str">"cmt">//二进制 - 十进制转换器
{
   class="type">class="kw">string mensIni= "脚本转换器 二进制 - 十进制",
          mens= "", cadNumBin= "", cadNumRed= "";
   class="type">int contAciertos= class="num">0, arNumBin[],
       inicio= historialEntrena+class="num">1,
       fin= historialEntrena+historialEvalua;
   class="type">class="kw">double arSalRed[], arNumEntra[], salida= class="num">0, umbral= class="num">0, peso= class="num">0;
   class="type">class="kw">double errorMedioEntren= class="num">0;
   class="type">bool normEntrada= intervEntrada!="", normSalida= intervSalida!="", correcto= false,
        creada= creaRedNeuronal(redNeuronal);
   if(creada)
   {
      iniFichImprime(puntFichTexto, nombreEA+"-infRN", ".csv",mensIni);
      preparaDatosEntra(redNeuronal, arDatosAprende, intervEntrada!="", intervSalida!="");
      normalizaDatosRed(redNeuronal, arDatosAprende, normEntrada, normSalida);
      errorMedioEntren= entrenaEvalRed(redNeuronal, arDatosAprende);
      escrTexto("-------------------------", puntFichTexto);
      escrTexto("RESPUESTA RED------------", puntFichTexto);
      escrTexto("-------------------------", puntFichTexto);
      escrTexto("numBinEntra;numDecSalidaRed;correcto", puntFichTexto);
      for(class="type">int k= inicio; k<=fin; k++)
      {
         cadNumBin= dec_A_baseNumerica(k, arNumBin, class="num">2, nNeuronEntra);
         ArrayCopy(arNumEntra, arNumBin);
         salida= respuestaRed(redNeuronal, arNumEntra, arSalRed);
         salida= MathRound(salida);
         correcto= k==(class="type">int)salida;
         escrTexto(cadNumBin+";"+IntegerToString((class="type">int)salida)+";"+correcto, puntFichTexto);
         cadNumRed= "";
      }
   }
   deIniFichImprime(puntFichTexto);
   class="kw">return;
}

「6. 任务 2: 质数检测器」

我们来研究一个类似的任务。这次, NN 将定义它是否为质数。训练矩阵将包含 10 列, 其中高达 800 的自然数均变换为 10 个字符的二进制形式, 一列指示它是 ("1") 或不是 ("0") 素数。换言之, 我们将有 800 行和 11 列。接下来, 我们要让 NN 分析接下来 200 个自然数 (从 801 到 1000) 的二进制形式, 并定义哪个数是素数, 哪个不是。由于这个任务更加困难, 让我们打印出得到匹配的统计数据。 脚本依照指定参数 (NN 没有隐藏层, 10 个输入神经元, 第一个隐藏层 20 个神经元, 以及输出层 1 个神经元) 执行之后, 结果比前一个任务还糟糕。生成的 ScriptNumPrimo-infRN.csv 文件位于 Terminal\Common\Files 目录, 提供了以下数据: 在此我们可以看到 800 (809) 之后的第一个素数没有被网络检测到 (true = 非 true)。以下是统计摘要: 报告表明, NN 在评估区间 (801 到 1000) 上的 200 个数字中猜测出 78%。然而, 在区间内出现的 29 个素数中, 它只检测到 13 个 (44.83%)。 如果我们使用以下网络结构进行测试: "10 个输入层神经元, 第一隐藏层 35 个神经元, 第二隐藏层 10 个神经元, 和输出层 1 个神经元", 脚本在执行期间显示以下数据: 正如我们在下面的图片中可以看到的, 结果恶化, 时间 0.53 分钟, 而平均训练误差等于 0.04208383。 因此, 我们再次反思: 如何以最好的方式定义网络内部结构? [CODE] <span class="preprocessor">#include </span>&lt;Math\Alglib\alglib.mqh&gt; <span class="keyword">enum</span> mis_PROPIEDADES_RED {N_CAPAS, N_NEURONAS, N_ENTRADAS, N_SALIDAS, N_PESOS}; <span class="comment">//---------------------------------&nbsp;&nbsp;输入&nbsp;-----------------------&nbsp;---------------------</span> <span class="keyword">sinput</span> <span class="keyword">int</span> nNeuronEntra= <span class="number">10</span>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">//输入层神经元数量</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

◍ 神经网络训练后的质数判别回测

这段逻辑跑在 MT5 的 EA 主流程里,前提是 creaRedNeuronal 返回 true,也就是网络结构已经建好。随后它把学习集做归一化,调用 entrenaEvalRed 拿到平均训练误差 errorMedioEntren,再把 0/1 编码的十进制数逐个送进网络做前向推理。 推理部分用 dec_A_baseNumerica 把整数 k 转成二进制串塞进输入层,esPrimo 算真实标签,respuestaRed 出网络预测值,MathRound 后和标签比对得到 correcto。每一条样本都会写进 CSV:十进制、二进制、是否质数、网络判质数、是否判对。 收尾统计是硬指标:contAciertos 除以 historialEvalua 得到总准确率百分比,aciertoPrimo 除以 totalPrimos 得到质数识别准确率。比如若 historialEvalua=1000、contAciertos=985,则总成功率打印为 98.50 %;若 totalPrimos=168、aciertoPrimo=160,则质数命中率约 95.24 %。外汇与贵金属交易接入此类模型时,信号误判会带来高风险,须用历史样本先验证命中率再上实盘。 下面把核心回测代码拆开看,每一行都在决定你最后 CSV 里那几个百分点。

MQL5 / C++
  class="type">class="kw">double errorMedioEntren= class="num">0;
  class="type">bool correcto= false,
        esNumPrimo= false,
        creada= creaRedNeuronal(redNeuronal);      
  if(creada)
  {
    iniFichImprime(puntFichTexto, nombreEA+"-infRN", ".csv",mensIni);
    preparaDatosEntra(redNeuronal, arDatosAprende, intervEntrada!="", intervSalida!="");
    normalizaDatosRed(redNeuronal, arDatosAprende, normEntrada, normSalida);
    errorMedioEntren= entrenaEvalRed(redNeuronal, arDatosAprende);
    escrTexto("-------------------------", puntFichTexto);
    escrTexto("RESPUESTA RED------------", puntFichTexto);
    escrTexto("-------------------------", puntFichTexto);
    escrTexto("numDec;numBin;numPrimo;numPrimoRed;correcto", puntFichTexto);
    for(class="type">int k= inicio; k<=fin; k++)
    {
      cadNumBin= dec_A_baseNumerica(k, arNumBin, class="num">2, nNeuronEntra);
      esNumPrimo= esPrimo(k);
      ArrayCopy(arNumEntra, arNumBin);
      numPrimoRed= respuestaRed(redNeuronal, arNumEntra, arSalRed);
      numPrimoRed= MathRound(numPrimoRed);
      correcto= esNumPrimo==(class="type">int)numPrimoRed;
      if(esNumPrimo)
      {
        totalPrimos++;
        if(correcto) aciertoPrimo++;  
      }
      if(correcto) contAciertos++;
      linea= IntegerToString(k)+";"+cadNumBin+";"+esNumPrimo+";"+(numPrimoRed==class="num">0? "false": "true")+";"+correcto;
      escrTexto(linea, puntFichTexto);
    }
  }  
  escrTexto("成功 / 总数;"+DoubleToString((class="type">class="kw">double)contAciertos/(class="type">class="kw">double)historialEvalua*class="num">100, class="num">2)+" %", puntFichTexto);
  escrTexto("发现质数;"+IntegerToString(aciertoPrimo)+";"+"总质数;"+IntegerToString(totalPrimos), puntFichTexto);
  escrTexto("成功 / 总质数;"+DoubleToString((class="type">class="kw">double)aciertoPrimo/(class="type">class="kw">double)totalPrimos*class="num">100, class="num">2)+" %", puntFichTexto);
  deIniFichImprime(puntFichTexto);
  class="kw">return;

最后说句实在话

前面几节把 ALGLIB 接进 MQL5 跑神经网络自优化的路子已经铺开:二进制-十进制互转、质数判定、按网络内部结构回查结果这三段脚本(Script_redNeuronal_BIN-DEC.mq5 28.2 KB、Script_redNeuronal_NUM-PRIMOS.mq5 30.21 KB)是直接能拖进 MT5 编译运行的。 有用户在 2023 年 9 月反馈,MetaTrader 更新后 EA 停止学习,根因是旧库写法 arDatos[fila].Set(colum,valor) 在新库要改成 arDatos.Set(fila,colum,valor),改完即恢复——这种底层 API 变动在外盘贵金属/外汇高杠杆环境下会直接断掉策略闭环,动手前先核对你本地 ALGLIB 版本。 至于这套思路能否落地成稳定盈利系统,目前没有回测胜率或样本外数据支撑,只能说是个可验证的起点;开 MT5 把两个脚本跑一遍,比空谈架构更有用。

把重训排程交给小布盯盘
这些诊断与小布盯盘的AIGC已内置,打开对应品种页即可看到网络重训后的预测偏移提示,你只管判断是否切换策略权重。

常见问题

预测应用只跑一次拿初始值,之后OnTimer里只重复下载数据、规范化、训练和优化,保证EA在重训期也有可用预测,不空窗。
这两个数学题答案可精确核验,方便对照MLP内部结构与误差,摸清网络能力边界后再换数据输入模块接策略。
取决于激活函数与输入分布,文章案例按任务选区间;实盘替换行情特征时建议先做分布扫描再定标。
小布盯盘内置了AIGC诊断,可提示品种页上的预测漂移与重训节点,但MLP训练与EA嵌入仍需在MQL5工程里自行部署。
高频品种波动快,小时级可能过拟合;日线级周重训更抗噪。外汇贵金属高风险,任何周期都只是概率倾向,需样本外验证。