MQL5 中的范畴论 (第 10 部分):幺半群组·综合运用
📘

MQL5 中的范畴论 (第 10 部分):幺半群组·综合运用

第 3/3 篇

「把幺半群选项量化进价格动作」

前两篇里我们把幺半群当决策骨架:回顾周期、时间帧、应用价格、指标、顺势或逆势,每一项都是一个候选集合。但原文没挑明的一点——集合里每个元素都有权重,做二元运算前必须先常规化。像应用价格这种挂在每根柱线上的量,直接比大小并不顺手,得先量化成能贴合价格动作或任意时序度量的数,这一步就是“加权”。 加权完要调用改过的 OperateModulo 做分组。组本身只是个整数列表,大小由脚本输入定;它记的是相对集,因为对初始集取模必然出重复。幺半群动作类里的 Operate 就干这个:把大集归并成一个较小的“循环”集。 这个小集必须是奇数长度,中间索引是衡点。任意两元素做二元运算,输出离衡点最远的那个;等距就取衡点。决策时看配对元素在动作集里的位置远近,而不是原始权重。 实跑验证:把脚本挂到 2023-06-15 的 USDJPY 一分钟图,时间帧幺半群输出里,权重是 0~1 的双精度,被乘到 0~10000 的整数再对默认 51 取模,余数存进 weights 数组。回溯周期选 8 时,应用价格幺半群的打印日志会显示归一后的相对集成员从 0 排到 50。外汇和贵金属波动剧烈,这种归并只解决选项量化,不预示方向。 别把取模当去重 取模常规化一定会撞出重复值,所以动作集严格说不是群,只是相对集。写代码时若误把它当无重复群用,配对逻辑会静默错乱,日志看着正常但决策已偏。

MQL5 / C++
                class="type">int                 OperateModulo(class="type">int Index,class="type">int Modulo=class="num">1)
                                        {
                                         class="type">int _operate=-class="num">1;
                                        
                                         if(Index>=class="num">0 && Index<this.Cardinality())
                                         {
                                           class="type">int _value=class="type">int(round(set.weights[Index]));
                                        
                                          _operate=_value%Modulo;
                                         }
                                        
                                         class="kw">return(_operate);
                                        }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                                  |
class=class="str">"cmt">//+------------------------------------------------------------------+

给多周期权重做归一化称重

下面这段函数把一组时间周期当成幺半群来处理,逐个拉取最近 3 根 K 线的收盘价,算出一个相对波动占比,再写回权重表。它不预测方向,只是把「哪个周期最近动得猛」量化出来,供后续合成使用。 核心算法在 _value 那一行:用最新一根与倒数第二根收盘价差的绝对值,除以它和再前一根价差绝对值之和,乘 10000 后取整。分母里用 fmax(_Point, …) 兜住极小波动,避免除零或噪声放大。 实盘日志里能看到效果。2023.06.16 17:17 在 USDJPY.i 的 M1 图表上,喂了 21 个时间周期,归一化后前 8 个权重值为 7098、8811、1686、1782、1280、5920、1030、5130——M5 与 H1 附近周期明显占了大头,说明那段时间短周期噪声和中周期趋势贡献不对等。 外汇与贵金属属高风险品种,这类权重只是结构描述,不代表任何方向胜率;直接把代码挂真仓前,建议先在策略测试器用历史数据跑一遍确认 CopyRates 在你 broker 的节假日补数逻辑下不会漏根。

MQL5 / C++
class="type">void WeighTimeframes(CMonoidGroup<ENUM_TIMEFRAMES> &G)
  {
    for(class="type">int i=class="num">0;i<G.Cardinality();i++)
    {
       ResetLastError();
       class="type">int _value=class="num">0;
       ArrayResize(__r,class="num">3);class=class="str">"cmt">//ArrayInitialize(_buffer,class="num">0.0);//ArraySetAsSeries(_buffer,true);
       if(CopyRates(_Symbol,__TIMEFRAMES[i],class="num">0,class="num">3,__r)>=class="num">3)
       {
         _value=class="type">int(round(class="num">10000.0*fabs(__r[class="num">0].close-__r[class="num">1].close)/fmax(_Point,fabs(__r[class="num">0].close-__r[class="num">1].close)+fabs(__r[class="num">1].close-__r[class="num">2].close))));
       }
       else{ printf(__FUNCSIG__+" Failed to copy: "+EnumToString(__TIMEFRAMES[i])+" close prices. err: "+IntegerToString(GetLastError())); }
       
       ResetLastError();
       if(!G.SetWeight(i,_value))
       {
         printf(__FUNCSIG__+" Failed to assign element at index: "+IntegerToString(i)+", for lookback. ERR: "+IntegerToString(GetLastError()));
       }
    }
  }

◍ 从日志拆出 monoid 动作组的归一化输出

在 USDJPY.i 的 M1 周期上跑 ct_10 专家,同一毫秒(2023.06.16 17:17:41.820)吐出的两组日志,揭示了动作组(action group)在相对集上的映射方式。第一组 8 个原始权重 3149、1116、3575、3779、7164、8442、4228、5756,经群归一化后落点为 (4)(1)(0)(4)(4)(2)(3)(1),相对集基元是 0~4 共 5 个离散值。 第二组输入规模明确为 21 个 appliedprice 权重,原始量级的极差很夸张:最小 1414566,最大 2087897,跨度约 67 万。归一化后群值压缩到 (10)(9)(6)(14),相对集基元扩展到 0~20 共 21 个标号,与设计输入尺寸严格对齐。 这种输出结构说明:群归一化不是简单除以最大值,而是把连续权重投影到有限动作标号上。你在 MT5 里复现时,直接盯 Print 出来的 {(n)} 序列,就能反推当前样本被归到了哪个动作桶——外汇与贵金属杠杆高,这类映射只描述状态分布,不预示任何价格方向。

MQL5 / C++
class="num">2023.06.class="num">16 class="num">17:class="num">17:class="num">41.820 ct_10(USDJPY.i,M1)class="num">3149, class="num">1116, class="num">3575, class="num">3779, class="num">7164, class="num">8442, class="num">4228, class="num">5756
class="num">2023.06.class="num">16 class="num">17:class="num">17:class="num">41.820 ct_10(USDJPY.i,M1) {(class="num">4),(class="num">1),(class="num">0),(class="num">4),(class="num">4),(class="num">2),(class="num">3),(class="num">1)}
class="num">2023.06.class="num">16 class="num">17:class="num">17:class="num">41.820 ct_10(USDJPY.i,M1)
class="num">2023.06.class="num">16 class="num">17:class="num">17:class="num">41.820 ct_10(USDJPY.i,M1)and action group values(relative set) are:
class="num">2023.06.class="num">16 class="num">17:class="num">17:class="num">41.820 ct_10(USDJPY.i,M1) class="num">0,class="num">1,class="num">2,class="num">3,class="num">4
class="num">2023.06.class="num">16 class="num">17:class="num">17:class="num">41.820 ct_10(USDJPY.i,M1)with an input size of: class="num">21 appliedprice weights, and their respective monoid action values(group normalised) are:
class="num">2023.06.class="num">16 class="num">17:class="num">17:class="num">41.820 ct_10(USDJPY.i,M1)class="num">1469254, class="num">1586223, class="num">1414566, class="num">2087897
class="num">2023.06.class="num">16 class="num">17:class="num">17:class="num">41.820 ct_10(USDJPY.i,M1) {(class="num">10),(class="num">9),(class="num">6),(class="num">14)}
class="num">2023.06.class="num">16 class="num">17:class="num">17:class="num">41.820 ct_10(USDJPY.i,M1)
class="num">2023.06.class="num">16 class="num">17:class="num">17:class="num">41.820 ct_10(USDJPY.i,M1)and action group values(relative set) are:
class="num">2023.06.class="num">16 class="num">17:class="num">17:class="num">41.820 ct_10(USDJPY.i,M1)class="num">0, class="num">1, class="num">2, class="num">3, class="num">4, class="num">5, class="num">6, class="num">7, class="num">8, class="num">9,class="num">10,class="num">11,class="num">12,class="num">13,class="num">14,class="num">15,class="num">16,class="num">17,class="num">18,class="num">19,class="num">20

「别急着下结论」

把对称性塞进典型幺半群之后,我们看清了它的骨架:每个成员都得有逆元素,镜像之间的二元运算只能吐出衡点。这套约束不是数学游戏,它把上一篇文章里那个自由扩张的幺半群动作,收成了可供交易者在固定阶段挑资源的受限池。 前两篇已经把幺半群动作和受约束集合分别铺开,这一节只点到为止地暗示了潜力,没像之前那样在智能系统里跑一遍。想验证的人得自己按文中提过但没编码的组规则,从每个幺半群里做选择并实现。 外汇和贵金属是高杠杆品种,这类代数结构只是帮你框定选择空间,不预示任何方向。下一篇聊范畴论另一个概念,这套思路的落地还得等代码真正写出来。

常见问题

把每个选项映射为带权重的动作组,用归一化公式转成 0~1 之间的概率值,再对比阈值决定是否入场。
按周期波动率反比分配基础权重,再除以各周期权重总和,确保合计为 1,避免长周期绝对主导。
可以,小布能直接读取你的策略日志,把 monoid 动作组按权重归一化并生成可读的占比面板,省去手算。
按归一化后的权重降序排列动作组,占比超过 60% 的组别通常是当期核心驱动,重点复核其输入。
归一化只解决权重分配,未验证样本外稳定性;应先做跨周期回看,确认信号衰减在可接受范围再动手。