模糊逻辑介绍·进阶篇
🧠

模糊逻辑介绍·进阶篇

(2/3)· 搞懂两类模糊推理差异并亲手搭出可运行系统,才算真正跨过软计算门槛

偏理论 第 2/3 篇
很多交易者把模糊集合当成黑箱直接套用,却分不清马丹尼型和关野型推理在解模糊时的根本分歧。用错推理架构,专家系统的输出会偏离行情状态识别的本意。外汇与贵金属杠杆高,模型误判只会放大回撤风险。

马丹尼推理怎么把模糊规则变成输出

马丹尼型模糊推理依赖一个模糊知识库:输入与输出变量都由模糊集合定义,规则写成 j=0,1,2…m 的权重结构。每条规则用输入向量 j-th 与输出向量值配对,权重控制该条规则的贡献比例。 计算时先算输入向量对某个模糊特征 t 的隶属度,这里用 s-范数或 t-范数实现 OR/AND 逻辑。实际工程里最常见的实现是:OR 取最大值,AND 取最小值——MT5 里手写这类逻辑时直接 min()/max() 就能跑。 得到 m 个新隶属函数后,它们拼成一个新模糊集合,其论域落在输出变量的特征集合上。接下来要“截”隶属函数到某一级别再做合并,即建模含义与聚合:含义可用取最小或乘积,聚合可用取最大或算术和。 做完这两步得到结果模糊集合,再去模糊化就能拿到系统确切输出。开 MT5 用自定义函数验证 min/max 两种聚合差异,是确认推理倾向的有效办法;外汇与贵金属市场波动剧烈,模糊输出仅作概率参考,实盘高风险。

「关野型把规则变成线性开关」

关野型模糊推理和马丹尼型最大的差别在结论端:马丹尼用模糊特征描述输出,关野直接用输入的线性函数。规则本身像是确定的开关,在多条线性“输入—输出”规律之间切换,而子域边界是模糊的,所以不同线性规律能以不同隶属度同时起作用。 知识库里要列清楚:输入向量、输出变量、第 j 条规则对应的输入向量(j=0,1,…,m)、线性函数里的自由项系数、各特征 i 的系数(i=0,1,…,n),以及第 j 条规则的权重。隶属函数记为 v 落到模糊特征 t 的程度。 输入向量对模糊特征的隶属度按规则库计算,其中 s-范数/t-范数承担 OR/AND 逻辑。关野型常用概率或作 s-范数、乘积作 t-范数。算出 m 个新隶属函数后拼成一个新模糊集,它基于精确数字、属第一顺序普通模糊集合,不像马丹尼输出那样是二级模糊量。 最终输出值是在 n 维因子空间对给定点做线性叠加后去模糊化,取平均权重或加权和。MT5 里若自建关野推理模块,先把乘积 t-范数写成循环累乘,再核对加权和不归一时的偏移,外汇与贵金属波动大,这类模型仅作概率参考,实盘前务必用历史 tick 验证。

◍ 用 FuzzyNet 程序库绕开手写模糊模型

手工搭一个哪怕最简的模糊推理模型,在 MT5 里也得处理隶属度、规则基和去模糊化,实操负担不轻。MQL5 生态里 FuzzyNet 程序库(MQL5 版)直接封装了这些过程,测试脚本里就能看到两种模糊模型的创建与调用方式。 对交易者来说,关键点不是弄懂底层数学,而是把行情状态(比如波动率高低、趋势强度)映射成模糊变量,再让库替你跑推理。外汇与贵金属杠杆高、滑点随机,模糊输出只能作为概率倾向,不能直接当下单指令。 打开 MT5 的 MQL5/Experts/Examples/FuzzyNet 下的测试脚本,编译运行一次,比读十页文档更快建立直觉。

搭一个马丹尼型小费推理系统

MQL5 的 FuzzyNet 库里有个现成例子 Tips_Sample_Mamdani.mq5,用马丹尼推理算小费:两个输入(服务、食物,标尺均 0–10),一个输出(小费,范围 5%–30% 账单),知识库就三条规则。服务用三角隶属函数分 poor/good/excellent,食物用梯形分 rancid/delicious,输出 tips 用三角分 cheap/average/generous。 规则字符串必须严格用关键词写:if、then、is、and、or、not 加括号,以及语义量词 slightly/somewhat/very/extremely。量词直接改隶属度曲线——very 把结果平方(数值增大),extremely 立方(极大增大),slightly 取立方根(极大压低),写错一个词 ParseRule 就拒解析。 下面这段代码就是空系统填充全过程。先在 MT5 的 MetaEditor 里 include Math\FuzzyNet\MamdaniFuzzySystem.mqh,new 一个 MamdaniFuzzySystem,再逐个加输入变量、输出变量和三条规则即可跑通。 [CODE] #include <Math\FuzzyNet\MamdaniFuzzySystem.mqh> // 引入马丹尼系统头文件,提供建类和操作方法 MamdaniFuzzySystem *fsTips=new MamdaniFuzzySystem(); // 新建空马丹尼系统实例 FuzzyVariable *fvService=new FuzzyVariable("service",0.0,10.0); // 输入变量 service,域 0~10 fvService.Terms().Add(new FuzzyTerm("poor", new TriangularMembershipFunction(-5.0, 0.0, 5.0))); // poor:三角隶属,峰值在0,左右展到-5和5 fvService.Terms().Add(new FuzzyTerm("good", new TriangularMembershipFunction(0.0, 5.0, 10.0))); // good:三角,峰值5 fvService.Terms().Add(new FuzzyTerm("excellent", new TriangularMembershipFunction(5.0, 10.0, 15.0))); // excellent:三角,峰值10 fsTips.Input().Add(fvService); // 把 service 加为系统输入 FuzzyVariable *fvFood=new FuzzyVariable("food",0.0,10.0); // 输入变量 food,域 0~10 fvFood.Terms().Add(new FuzzyTerm("rancid", new TrapezoidMembershipFunction(0.0, 0.0, 1.0, 3.0))); // rancid:梯形,0~1平顶到3降 fvFood.Terms().Add(new FuzzyTerm("delicious", new TrapezoidMembershipFunction(7.0, 9.0, 10.0, 10.0))); // delicious:梯形,7升到9平顶 fsTips.Input().Add(fvFood); // 把 food 加为输入 FuzzyVariable *fvTips=new FuzzyVariable("tips",0.0,30.0); // 输出变量 tips,域 0~30 fvTips.Terms().Add(new FuzzyTerm("cheap", new TriangularMembershipFunction(0.0, 5.0, 10.0))); // cheap:三角峰值5 fvTips.Terms().Add(new FuzzyTerm("average", new TriangularMembershipFunction(10.0, 15.0, 20.0))); // average:峰值15 fvTips.Terms().Add(new FuzzyTerm("generous", new TriangularMembershipFunction(20.0, 25.0, 30.0))); // generous:峰值25 fsTips.Output().Add(fvTips); // 把 tips 加为输出 MamdaniFuzzyRule *rule1 = fsTips.ParseRule("if (service is poor) or (food is rancid) then (tips is cheap)"); // 规则1 MamdaniFuzzyRule *rule2 = fsTips.ParseRule("if (service is good) then (tips is average)"); // 规则2 MamdaniFuzzyRule *rule3 = fsTips.ParseRule("if (service is excellent) or (food is delicious) then (tips is generous)"); // 规则3 fsTips.Rules().Add(rule1); // 加规则进知识库 fsTips.Rules().Add(rule2); fsTips.Rules().Add(rule3); [/CODE] 验证办法很简单:编译后调用 fsTips.Calculate() 喂一组 service=8、food=9,输出会倾向 generous 区间(20–30 附近)。外汇和贵金属市场波动剧烈、杠杆风险高,这类模糊系统只是把主观评判变成数值映射,实盘使用前务必在策略测试器里做历史回放。

MQL5 / C++
class="macro">#include <Math\FuzzyNet\MamdaniFuzzySystem.mqh>
MamdaniFuzzySystem *fsTips=new MamdaniFuzzySystem();
FuzzyVariable *fvService=new FuzzyVariable("service",class="num">0.0,class="num">10.0);
fvService.Terms().Add(new FuzzyTerm("poor", new TriangularMembershipFunction(-class="num">5.0, class="num">0.0, class="num">5.0)));
fvService.Terms().Add(new FuzzyTerm("good", new TriangularMembershipFunction(class="num">0.0, class="num">5.0, class="num">10.0)));
fvService.Terms().Add(new FuzzyTerm("excellent", new TriangularMembershipFunction(class="num">5.0, class="num">10.0, class="num">15.0)));
fsTips.Input().Add(fvService);
FuzzyVariable *fvFood=new FuzzyVariable("food",class="num">0.0,class="num">10.0);
fvFood.Terms().Add(new FuzzyTerm("rancid", new TrapezoidMembershipFunction(class="num">0.0, class="num">0.0, class="num">1.0, class="num">3.0)));
fvFood.Terms().Add(new FuzzyTerm("delicious", new TrapezoidMembershipFunction(class="num">7.0, class="num">9.0, class="num">10.0, class="num">10.0)));
fsTips.Input().Add(fvFood);
FuzzyVariable *fvTips=new FuzzyVariable("tips",class="num">0.0,class="num">30.0);
fvTips.Terms().Add(new FuzzyTerm("cheap", new TriangularMembershipFunction(class="num">0.0, class="num">5.0, class="num">10.0)));
fvTips.Terms().Add(new FuzzyTerm("average", new TriangularMembershipFunction(class="num">10.0, class="num">15.0, class="num">20.0)));
fvTips.Terms().Add(new FuzzyTerm("generous", new TriangularMembershipFunction(class="num">20.0, class="num">25.0, class="num">30.0)));
fsTips.Output().Add(fvTips);
MamdaniFuzzyRule *rule1 = fsTips.ParseRule("if (service is poor) or(food is rancid) then(tips is cheap)");
MamdaniFuzzyRule *rule2 = fsTips.ParseRule("if (service is good) then(tips is average)");
MamdaniFuzzyRule *rule3 = fsTips.ParseRule("if (service is excellent) or(food is delicious) then(tips is generous)");
fsTips.Rules().Add(rule1);
fsTips.Rules().Add(rule2);
fsTips.Rules().Add(rule3);

「用关野模型写平滑巡航控制」

PID 做车速巡航能到位,但加减速过程容易出现跳变和顿挫;模糊控制器在同样任务里倾向给出更平顺的油门请求,乘坐体感更自然。外汇与贵金属自动化同理,硬碰硬的反向手数调整在滑点环境下可能放大冲击成本,平滑输出更有概率优势,但杠杆品种高风险依旧不可忽略。 关野(Sugeno)型把输出从模糊集合改成输入变量的线性组合。本例两个输入:速度误差 SpeedError 域宽 -20~20 km/h,分 slower/zero/faster 三个三角隶属;误差变化率 SpeedErrorDot 域宽 -5~5,同样三特征。输出 Accelerate 无最大最小值,由 zero、faster、slower、func 四条线性函数构成,系数数组长度须为输入数+1(本例 3),末位为自由项。 规则库共九条,例如「误差偏慢且变化率偏慢 → 加速较快」「误差为零且变化率为零 → 加速取 func 线性函数」。下面这段 MQL5 是系统骨架,可直接在 MT5 的 FuzzyNet 库下跑通前四条规则注册: # include <Math\FuzzyNet\SugenoFuzzySystem.mqh> // 引入关野系统头文件 SugenoFuzzySystem *fsCruiseControl=new SugenoFuzzySystem(); // 新建空关野系统 FuzzyVariable *fvSpeedError=new FuzzyVariable("SpeedError",-20.0,20.0); // 速度误差变量,范围±20 fvSpeedError.Terms().Add(new FuzzyTerm("slower",new TriangularMembershipFunction(-35.0,-20.0,-5.0))); // 慢:三角隶属(-35,-20,-5) fvSpeedError.Terms().Add(new FuzzyTerm("zero", new TriangularMembershipFunction(-15.0, -0.0, 15.0))); // 零:三角隶属(-15,0,15) fvSpeedError.Terms().Add(new FuzzyTerm("faster", new TriangularMembershipFunction(5.0, 20.0, 35.0))); // 快:三角隶属(5,20,35) FuzzyVariable *fvSpeedErrorDot=new FuzzyVariable("SpeedErrorDot",-5.0,5.0); // 误差变化率,范围±5 fvSpeedErrorDot.Terms().Add(new FuzzyTerm("slower", new TriangularMembershipFunction(-9.0, -5.0, -1.0))); // 变化慢:(-9,-5,-1) fvSpeedErrorDot.Terms().Add(new FuzzyTerm("zero", new TriangularMembershipFunction(-4.0, -0.0, 4.0))); // 变化零:(-4,0,4) fvSpeedErrorDot.Terms().Add(new FuzzyTerm("faster", new TriangularMembershipFunction(1.0, 5.0, 9.0))); // 变化快:(1,5,9) SugenoVariable *svAccelerate=new SugenoVariable("Accelerate"); // 关野输出变量,无值域边界 double coeff1[3]={0.0,0.0,0.0}; // zero函数系数:全零 svAccelerate.Functions().Add(fsCruiseControl.CreateSugenoFunction("zero",coeff1)); double coeff2[3]={0.0,0.0,1.0}; // faster函数:自由项1 svAccelerate.Functions().Add(fsCruiseControl.CreateSugenoFunction("faster",coeff2)); double coeff3[3]={0.0,0.0,-1.0}; // slower函数:自由项-1 svAccelerate.Functions().Add(fsCruiseControl.CreateSugenoFunction("slower",coeff3)); double coeff4[3]={-0.04,-0.1,0.0}; // func函数:误差系数-0.04,变化率-0.1 svAccelerate.Functions().Add(fsCruiseControl.CreateSugenoFunction("func",coeff4)); fsCruiseControl.Output().Add(svAccelerate); // 输出接入系统 SugenoFuzzyRule *rule1 = fsCruiseControl.ParseRule("if (SpeedError is slower) and (SpeedErrorDot is slower) then (Accelerate is faster)"); // 规则1 SugenoFuzzyRule *rule2 = fsCruiseControl.ParseRule("if (SpeedError is slower) and (SpeedErrorDot is zero) then (Accelerate is faster)"); // 规则2 SugenoFuzzyRule *rule3 = fsCruiseControl.ParseRule("if (SpeedError is slower) and (SpeedErrorDot is faster) then (Accelerate is zero)"); // 规则3 SugenoFuzzyRule *rule4 = fsCruiseControl.ParseRule("if (SpeedError is zero) and (SpeedErrorDot is slower) then (Accelerate is faster)"); // 规则4 把 coeff4 里的 -0.04 和 -0.1 调小一档,系统对误差的加速反应会倾向更温和,适合拿来回测 EURUSD 的 M5 波动率过滤;实盘前务必在策略测试器用点差模型跑一遍,外汇高风险下参数过软可能错过进场窗口。

MQL5 / C++
class="macro">#include <Math\FuzzyNet\SugenoFuzzySystem.mqh>
SugenoFuzzySystem *fsCruiseControl=new SugenoFuzzySystem();
FuzzyVariable *fvSpeedError=new FuzzyVariable("SpeedError",-class="num">20.0,class="num">20.0);
fvSpeedError.Terms().Add(new FuzzyTerm("slower",new TriangularMembershipFunction(-class="num">35.0,-class="num">20.0,-class="num">5.0)));
fvSpeedError.Terms().Add(new FuzzyTerm("zero", new TriangularMembershipFunction(-class="num">15.0, -class="num">0.0, class="num">15.0)));
fvSpeedError.Terms().Add(new FuzzyTerm("faster", new TriangularMembershipFunction(class="num">5.0, class="num">20.0, class="num">35.0)));
FuzzyVariable *fvSpeedErrorDot=new FuzzyVariable("SpeedErrorDot",-class="num">5.0,class="num">5.0);
fvSpeedErrorDot.Terms().Add(new FuzzyTerm("slower", new TriangularMembershipFunction(-class="num">9.0, -class="num">5.0, -class="num">1.0)));
fvSpeedErrorDot.Terms().Add(new FuzzyTerm("zero", new TriangularMembershipFunction(-class="num">4.0, -class="num">0.0, class="num">4.0)));
fvSpeedErrorDot.Terms().Add(new FuzzyTerm("faster", new TriangularMembershipFunction(class="num">1.0, class="num">5.0, class="num">9.0)));
SugenoVariable *svAccelerate=new SugenoVariable("Accelerate");
class="type">class="kw">double coeff1[class="num">3]={class="num">0.0,class="num">0.0,class="num">0.0};
svAccelerate.Functions().Add(fsCruiseControl.CreateSugenoFunction("zero",coeff1));
class="type">class="kw">double coeff2[class="num">3]={class="num">0.0,class="num">0.0,class="num">1.0};
svAccelerate.Functions().Add(fsCruiseControl.CreateSugenoFunction("faster",coeff2));
class="type">class="kw">double coeff3[class="num">3]={class="num">0.0,class="num">0.0,-class="num">1.0};
svAccelerate.Functions().Add(fsCruiseControl.CreateSugenoFunction("slower",coeff3));
class="type">class="kw">double coeff4[class="num">3]={-class="num">0.04,-class="num">0.1,class="num">0.0};
svAccelerate.Functions().Add(fsCruiseControl.CreateSugenoFunction("func",coeff4));
fsCruiseControl.Output().Add(svAccelerate);
SugenoFuzzyRule *rule1 = fsCruiseControl.ParseRule("if (SpeedError is slower) and(SpeedErrorDot is slower) then(Accelerate is faster)");
SugenoFuzzyRule *rule2 = fsCruiseControl.ParseRule("if (SpeedError is slower) and(SpeedErrorDot is zero) then(Accelerate is faster)");
SugenoFuzzyRule *rule3 = fsCruiseControl.ParseRule("if (SpeedError is slower) and(SpeedErrorDot is faster) then(Accelerate is zero)");
SugenoFuzzyRule *rule4 = fsCruiseControl.ParseRule("if (SpeedError is zero) and(SpeedErrorDot is slower) then(Accelerate is faster)");
让小布替你跑这套
这些模糊推理结构在小布盯盘的 AIGC 诊断里已内置,打开对应品种页就能看到隶属度分布,你只管调语义变量。

常见问题

马丹尼用 min 取交、max 取并再做重心法解模糊;关野直接用单值模糊化与乘积推理,计算更轻,倾向实时控制。
库提供直接、间接与相对次数等构造方式,可基于专家经验定义,不必从零推导连续单调函数。
目前小布内置的是标准模糊诊断视图,自定义模型需导出隶属度表后对照品种页观测,暂不支持外挂脚本。
应结合论域样本与领域证据,使特征覆盖边界与中间态,避免只设 0 和 1 两种极端导致退化为普通集合。
对流动性好、跳点少的贵金属时段概率更稳,但高波动新闻行情仍可能失真,需降权处理。