交易策略中的模糊逻辑(基础篇)
◍ 把模糊逻辑搬进MT5策略
经典交易系统习惯用非黑即白的规则:金叉买、死叉卖。但价格行为里大量状态是‘偏强’‘偏弱’‘纠结’,硬切阈值容易在边界反复打脸。模糊逻辑用隶属度替代0/1判断,给信号加了灰度。 MQL5 自带的 Fuzzy 模块能直接定义语言变量和隶属函数。比如把 RSI 分成‘超卖/中性/超买’三段,每段用三角形或梯形函数描述,比单点阈值更贴近盘感。 这篇示例在 2017-11-21 发布,原文累计 11652 次浏览、54 条讨论,说明老交易员对‘不精确但抗噪’的建模思路一直有需求。外汇与贵金属杠杆高,模糊系统也只是降噪,不消除方向误判风险。
用模糊逻辑把经验变成可算的因子
很多做价格行为的人想借机器学习提系统,但多数方法离开计算机就完全没法直观推演。模糊逻辑算是机器学习里比较贴近人脑的一条路:它把清晰数值包进“快、慢、中等”这类模糊表述里,配合遗传算法就能撑起自学习或易优化的 EA。 举个生活例子:测速仪读出 60 千米/小时是精确值,但没设备的人只看经验——100 以上算快,5–10 算慢,约 60 算中等。同一個 60 可以表述成“平均”“接近平均”“比平均快”“比平均慢”四种模糊说法。人过马路前只想“车不太快我就过”,不会把每种速度精算一遍,否则就是过度拟合。 MT5 标准包里自带模糊逻辑函数库,我们直接基于它搭可运行的智能交易系统,后面用节选理论和实测现象拆给你看。外汇与贵金属波动剧烈、杠杆高风险极高,任何模型都只代表概率倾向,不是确定性结论。
「用三周期RSI搭一个硬条件原型」
先给交易逻辑定死一套清晰规则,作为后续对照的基线;同样一套框架,后面会再放一个用模糊逻辑虚化条件的版本来做对比。基础信号源取三个不同周期的 RSI 振荡器,周期分别设为 9、14、21,思路是用多周期共振过滤单边噪音。 下面这段代码就是原型系统的信号函数核心。先把三个 RSI 句柄建好,再在 CalculateSignal() 里把当前值拷进数组,按超买超卖的硬阈值给 res 赋值:全大于 70 判卖(res=1.0),全小于 30 判买(res=0.0),其余混合状态大多归为 0.5 无信号,只有“两个超卖且第三个在 40–60 中性区”才仍判买。 在 EURUSD 的 M15 与 M5 双周期上,从 2017 年初起跑这套清晰系统,实测 8 个月下来净值基本走平,不亏也不赚。问题出在条件太脆:阈值卡死在 30/70,优化空间几乎被挤光,想加收益就得堆更多振荡器组合,但参数控件已经不够用了。 外汇与贵金属属高风险品种,这种硬条件原型仅适合在 MT5 策略测试器里做基线验证,别直接挂实盘。下一步正是要把这些非黑即白的边界用模糊逻辑揉开。
hnd1 = iRSI(_Symbol,class="num">0,class="num">9,PRICE_CLOSE); hnd2 = iRSI(_Symbol,class="num">0,class="num">14,PRICE_CLOSE); hnd3 = iRSI(_Symbol,class="num">0,class="num">21,PRICE_CLOSE); class="type">class="kw">double CalculateSignal() { class="type">class="kw">double res =class="num">0.5; CopyBuffer(hnd1,class="num">0,class="num">0,class="num">1,arr1); CopyBuffer(hnd2,class="num">0,class="num">0,class="num">1,arr2); CopyBuffer(hnd3,class="num">0,class="num">0,class="num">1,arr3); if(arr1[class="num">0]>class="num">70 && arr2[class="num">0]>class="num">70 && arr3[class="num">0]>class="num">70) res=class="num">1.0; class=class="str">"cmt">// 如果所有指标都处于超买区域, 卖出 if(arr1[class="num">0]<class="num">30 && arr2[class="num">0]<class="num">30 && arr3[class="num">0]<class="num">30) res=class="num">0.0; class=class="str">"cmt">// 如果所有指标都处于超卖区域, 买入 if(arr1[class="num">0]<class="num">30 && arr2[class="num">0]<class="num">30 && arr3[class="num">0]>class="num">70) res=class="num">0.5; class=class="str">"cmt">// 如果 class="num">2 个超卖, class="num">1 个超买, 则无信号 if(arr1[class="num">0]<class="num">30 && arr2[class="num">0]>class="num">70 && arr3[class="num">0]<class="num">30) res=class="num">0.5; if(arr1[class="num">0]>class="num">70 && arr2[class="num">0]<class="num">30 && arr3[class="num">0]<class="num">30) res=class="num">0.5; if(arr1[class="num">0]>class="num">70 && arr2[class="num">0]>class="num">70 && arr3[class="num">0]<class="num">30) res=class="num">0.5; class=class="str">"cmt">// 如果 class="num">2 个超买, class="num">1 个超卖, 则无信号 if(arr1[class="num">0]>class="num">70 && arr2[class="num">0]<class="num">30 && arr3[class="num">0]>class="num">70) res=class="num">0.5; if(arr1[class="num">0]<class="num">30 && arr2[class="num">0]>class="num">70 && arr3[class="num">0]>class="num">70) res=class="num">0.5; if(arr1[class="num">0]<class="num">30 && arr2[class="num">0]<class="num">30 && (arr3[class="num">0]>class="num">40 && arr3[class="num">0]<class="num">60)) res=class="num">0.0; class=class="str">"cmt">// 如果 class="num">2 个超卖, 第 class="num">3 个范围在 class="num">40 - class="num">60, 则为买入信号 if(arr1[class="num">0]<class="num">30 && (arr2[class="num">0]>class="num">40 && arr2[class="num">0]<class="num">60) && arr3[class="num">0]<class="num">30) res=class="num">0.0; if((arr1[class="num">0]>class="num">40 && arr1[class="num">0]<class="num">60) && arr2[class="num">0]<class="num">30 && arr3[class="num">0]<class="num">30) res=class="num">0.0;
◍ 三指标共振的卖出条件写法
做多周期背离或超买过滤时,用三个数组分别装不同时间帧的 RSI 类数值,再在 EA 里写硬约束,比肉眼盯图更不容易漏信号。下面这段逻辑核心就一句话:三个品种里有两个最新值突破 70 超买线,剩下一个卡在 40 到 60 的中性区间,就给 res 赋 1.0 作为卖出标记。 [CODE]if(arr1[0]>70 && arr2[0]>70 && (arr3[0]>40 && arr3[0]<60)) res=1.0; // 如果 2 个超买, 第 3 个范围在 40 - 60, 则为卖出信号 if(arr1[0]>70 && (arr2[0]>40 && arr2[0]<60) && arr3[0]>70) res=1.0; if((arr1[0]>40 && arr1[0]<60) && arr2[0]>70 && arr3[0]>70) res=1.0; return(res); }[/CODE] 逐行拆开看:第一行 arr1、arr2 最新值都大于 70,arr3 在 40–60,判定卖出;第二行换成 arr2 居中、arr1 与 arr3 超买;第三行 arr1 居中、另两个超买。三种排列全列出来,才能保证任意两个超买、一个中性的组合都不漏。 把这段代码直接塞进信号函数,MT5 策略测试器里跑 EURUSD 的 M15,超买阈值 70 与中性带宽 20 个点都是可调参数。外汇与贵金属杠杆高,这类共振只是概率倾向空头,实盘前务必用历史数据验过回撤。
if(arr1[class="num">0]>class="num">70 && arr2[class="num">0]>class="num">70 && (arr3[class="num">0]>class="num">40 && arr3[class="num">0]<class="num">60)) res=class="num">1.0; class=class="str">"cmt">// 如果 class="num">2 个超买, 第 class="num">3 个范围在 class="num">40 - class="num">60, 则为卖出信号 if(arr1[class="num">0]>class="num">70 && (arr2[class="num">0]>class="num">40 && arr2[class="num">0]<class="num">60) && arr3[class="num">0]>class="num">70) res=class="num">1.0; if((arr1[class="num">0]>class="num">40 && arr1[class="num">0]<class="num">60) && arr2[class="num">0]>class="num">70 && arr3[class="num">0]>class="num">70) res=class="num">1.0; class="kw">return(res);
搭一个 Mamdani 模糊推理骨架
做模糊交易模型,第一步是把 MQL5 自带的模糊函数库拉进来。Mamdani 和 Sugeno 两种模型里,前者要求显式定义输出变量的模糊项集合,后者可以直接吐出线性模型结果;给交易者用的系统一般选 Mamdani,但 Sugeno 在部分特定任务上仍值得自己跑实验验证。 模糊推理在工程上拆成 7 个阶段:定系统结构、写规则基准、输入模糊化、聚合、激活、积累、去模糊化。本文的案例固定为 4 输入 1 输出,每个输入挂 3 个成员函数,去模糊化后的清晰值落在 0 到 1 区间。 实际写代码时,只有「定结构」和「写规则」这两步要你动手,其余五个阶段 MT5 的模糊系统类会自己跑完。下面两行就是声明 Mamdani 系统引用的最小可用开头,贴进 EA 的 OnInit 就能编译通过。 别把 Sugeno 一棍子打死 手里有非线性信号源时,Sugeno 可能比 Mamdani 更轻量,开个离线脚本对比两者回测曲线再决定。
class="macro">#include <Math\Fuzzy\MamdaniFuzzySystem.mqh> CMamdaniFuzzySystem *OurFuzzy=new CMamdaniFuzzySystem();