MQL5 中的范畴论 (第 16 部分):多层感知器函子·综合运用
(3/3)·从财经日历范畴到 MLP 函子,把抽象映射落进可回测的进出场逻辑
◍ 用范畴映射把财经日历喂进多层感知机
把标普500指数变化看成一条线性序,财经日历数据则通过两个函子(对象与态射都要接上)映射到同一协域。实战里,信号由 csv 里的输入日期决定,权重在每次训练结束得出;本文附带的训练在智能系统初始化时跑一次,读者也可按计时器在新柱线写入 csv 后重训,只是文中没展开。 GetOutput 是决策取数的入口:它先按日期门槛打印训练收益与净值,若浮盈超过初始入金差额就把感知机权重写盘;随后从共用目录 csv 读日历读数填进 _x_inputs,再丢给 CMLPBase 的 MLPProcess 前向计算,输出 _y_inputs[0] 作为信号值。 下面对清单做逐行拆解: // 函数头注释:取输出值,预测下一根价格棒区间的变化 double CSignalCT::GetOutput(datetime Date) — 定义返回 double 的信号函数,入参为时间 if(Date>=D'2023.07.01') — 仅对2023年7月1日后的行情做日志与存盘 printf(...) — 打印函数签名、训练利润、账户利润、净值、入金,便于 MT5 终端查训练轨迹 if(m_training_profit<m_account.Equity()-m_training_deposit) — 当前浮盈大于训练起始差额才触发写盘 printf(..."perceptron write... ") — 提示感知机即将写入 m_training_profit=m_account.Equity()-m_training_deposit — 更新训练利润基准 WritePerceptron(m_training_profit,_MLP) — 把权重和利润写回文件 ... — 省略的范畴更新与输入准备 _value="";_e.Let();_e.Cardinality(1) — 清空取值串,建单元素枚举 _d_economic.Get(3,_e);_e.Get(0,_value) — 取经济数据第3类第0项填进 _value _x_inputs[3]=StringToDouble(_value) — 转 double 后塞入网络第4输入 CMLPBase _base; _base.MLPProcess(_MLP,_x_inputs,_y_inputs) — 实例化基类并前向传播 _output=_y_inputs[0] — 取网络首输出为信号 return(_output) — 回传信号值 持仓规模可挂在信号幅度上:把 _output 常规化后接 ExpertMoney 自定义实例即可,但外汇/贵金属杠杆高,改仓位前先在策略测试器跑穿尾随再上实盘。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Get Output value, forecast for next change in price bar range. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">class="kw">double CSignalCT::GetOutput(class="type">class="kw">datetime Date) { if(Date>=D&class="macro">#x27;class="num">2023.07.class="num">01&class="macro">#x27;) { printf(__FUNCSIG__+" log profit: "+DoubleToString(m_training_profit)+", account profit: "+DoubleToString(m_account.Profit())+", equity: "+DoubleToString(m_account.Equity())+", deposit: "+DoubleToString(m_training_deposit)); if(m_training_profit<m_account.Equity()-m_training_deposit) { printf(__FUNCSIG__+" perceptron write... "); m_training_profit=m_account.Equity()-m_training_deposit; WritePerceptron(m_training_profit,_MLP); } } ... _value="";_e.Let();_e.Cardinality(class="num">1); _d_economic.Get(class="num">3,_e);_e.Get(class="num">0,_value); _x_inputs[class="num">3]=StringToDouble(_value);class=class="str">"cmt">//printf(__FUNCSIG__+" val class="num">4: "+_value); class=class="str">"cmt">//forward feed?... CMLPBase _base; _base.MLPProcess(_MLP,_x_inputs,_y_inputs); _output=_y_inputs[class="num">0]; class=class="str">"cmt">//printf(__FUNCSIG__+" output is: "+DoubleToString(_output)); class="kw">return(_output); }
「用无效参数榨出多层回测」
在隐藏层权重优化里,可选项只有 5 到 12 共 8 个数字,单次优化跑一遍根本不足以判断哪个权重更稳。做法是塞一个对策略逻辑零影响的参数进优化器,单纯为了把总运行次数堆起来,让每个权重数字都能被反复测。 测试以最大盈利为优化准则,放在月度时间帧跑——财经日历类数据的平均更新节奏大致就是月频,和这个周期能对上。标普 500 的实测区间取了 2022-07-01 到 2023-08-01,对象到对象函子和对到态射函子各自出了报告。 翻两份报告的回撤与盈利因子,态射到态射函子这两项更靠前,被挑出来当当前最佳表现。外汇与贵金属品种叠加杠杆,这类神经网络权重回测结论仅代表样本内概率倾向,实盘前须自担高风险。 要不要拿它继续深挖,不只看换标的后的表现,也得换训练频率试:每根新柱线重训、还是按季度重训,结果可能完全两样。
把感知器信号接进策略测试器
感知器测试跑下来,最实在的结论是:信号文件里现成的买卖标记,确实能拿来搭一套可回测的交易系统。但前提是你得先圈定一个合适的域范畴,让数据格式能被 MT5 策略测试器直接读,而且靠谱的验证往往要跨好几年,数据必须往前续够。 多层感知器在这里当函子用,不只是算法上的递进,好处在于神经网络可选的类型和格式太多,扩展空间比传统规则宽。文章里那些指向进一步研究的超链接,本身只是路标——极限、协限和通用属性里讲过的概念,大多能借神经网络重新表述一遍。 想自己验,开 MT5 把信号文件按域格式铺好,丢进策略测试器拉一根 5 年以上走势,外汇和贵金属波动剧烈、杠杆高风险,回测结论只代表历史概率,别当实盘保票。
◍ 文件落位与组装的实操提醒
把 SignalCT_16_.mqh 丢进 MQL5\include\Expert\Signal\ 目录,ct_16.mqh 放 MQL5\include\ 根目录即可,两者差一个层级,放错向导会找不到信号类。 附件里 ct_16.mqh 占 73.54 KB、SignalCT_16_.mqh 18.34 KB、ct_16.mq5 7.45 KB,三个文件需配合 MT5 向导组装成 EA,不是直接挂图表就能跑。 原作者没接尾随止损和固定保证金模块,这两块在 MQL5 标准库里现成,按需自己拼。外汇与贵金属杠杆高、滑点跳空频繁,这套思路只供你改参数验证,不代表任何收益预期。 想跑通就开 MT5 把 ZIP 里五个文件按路径落位,用向导走一遍组装,再切到 USD_SPX500 月线看 _true / _false 两个 CSV(7.49 KB 与 7.44 KB)的差异点。