不使用额外的缓冲区,为中间计算进行系列价格的平均化·综合运用
🧮

不使用额外的缓冲区,为中间计算进行系列价格的平均化·综合运用

(3/3)·把平均线算法收进类里,省掉多余缓冲区还能保住执行速度,收尾篇给出落地写法

含代码示例偏理论 第 3/3 篇
很多人写指标时习惯开一块额外缓冲区存中间均价,结果历史一拉长内存和重算开销都往上走。其实只要把取平均的逻辑收进一个类,当前柱的数据自行进出选择集,缓冲区可以整个省掉。这一篇就把前面两篇拆开的方法拼成可直接抄的工程结构。

平均线类带来的性能与便利实利

把平均线类直接写进代码,最实在的好处是省掉了反复调用技术面和自定义指标的开销,开发出的模块跑起来明显更轻。对 MT5 用户来说,这不是理论优化,而是编译后肉眼可见的响应提升。 另一个常被忽略的点是可读性。William Blau《动量、方向和背离》里那套思路,用这类平均线重写后,指标代码被压到极短,且大多只做单根 K 线重算,逻辑一眼能看完。 平均线算法池子很宽,经典型和技术型都能搭。换不同平滑方式,往往能比传统均线更早抓到趋势苗头,假信号也偏少——但外汇和贵金属波动受事件驱动,早触发不等于胜率必然高,上 MT5 回测自己的品种再说。

◍ 不同均线算法的实战取舍

把同一套指标分别套上不同均线算法,肉眼就能看出曲线形态和滞后程度差得很远。这说明不存在一种算法在所有行情里都占优,硬定死规则没意义,但按算法脾气用还是能少走弯路。 钱德和考夫曼的 AMA 类算法本职是抓趋势,不是拿来当噪音过滤器做二次平滑的。给这类算法喂数据,最好直接丢原始价格或指标原值,别先求一遍平均。用考夫曼算法处理 Momentum 指标值的 4c_Momentum_AMA.mq5 就是照这个思路写的。 经典 SMA、EMA 不用多说,适用性本来就广。凡是原本用基础均线的地方,JMA、T3、超线性、抛物线这四种基本都能顶上。比如 JMACD.mq5 里把 MACD 的 EMA 和 SMA 全换成 JMA,曲线对趋势的确认更直接;而 JMomentum.mq5 是拿 JMA 去平滑算完的指标值,不是换算法确认趋势,两者目的不一样。 市场状态一直在变,幻想找个「唯一完美算法」一劳永逸不现实。我自己在变来变去的环境里,常用 JFATL.mq5 和 J2JMA.mq5 做快、中期趋势跟踪,基于它们的判断胜率够用。外汇和贵金属波动大、滑点突兀,换算法不等于降风险,回测也要带点保守。 均线算法能叠着用。对已经平均过的值再跑一遍平均,往往还能再压一点毛刺。本文开头分析的 MAx4.mq5 就是连续四次套均线的例子,你可以直接挂到 MT5 里看四级平滑后信号怎么钝化。

「均线内核的动态缓冲与增量求和」

写均线指标时,第一步不是算平均值,而是把输入序列塞进一个 m_SeriesArray[] 动态数组。多数算法在检测到关键计算信息出现时,调用 CMovSeriesTools 的 SeriesArrayResize() 一次性分配内存,避免每根 K 线反复申请释放。 每个新柱进来,当前价格系列值要写进数组最老位置,并用 m_count 记偏移编号,这步交给 Recount_ArrayZeroPos() 做。想取相对当前柱平移 iii 根的元素,用 Recount_ArrayNumber() 换算下标——最新值放零位、其余顺移覆盖,比每次重排整个数组更省资源。 代码里三类 BarCheck 负责边界:BarCheck1 在 K 线数不够时直接返 EMPTY_VALUE;BarCheck2 在首次满足数据量时初始化一次变量;BarCheck4/BarCheck5 则分别保存和恢复未平仓柱上的多重计算状态,防止实时 tick 重算错位。 SMA 这类算法若每柱都重新加总周期内的 series 值,开销随周期线性放大。更合理的做法是初始化时算一次总和,之后每柱只加新值、减最老值——前一柱和与当前柱和的差,就是一个新值进、一个老值出的关系。下面这段摘出来的核心片段就是这套机制: 别把缓冲当普通数组 m_SeriesArray 是带环形偏移的滚动窗口,kkk = Recount_ArrayNumber(m_count, Length_, iii) 算出的下标可能绕回头部,直接下标访问会读到错位数据,调试时优先打印 kkk 与 m_count。

MQL5 / C++
class=class="str">"cmt">//----+ 改变变量数组的大小
if(bar==begin && !SeriesArrayResize(__FUNCTION__, Length, m_SeriesArray, m_Size_))
   class="kw">return(EMPTY_VALUE);
class=class="str">"cmt">//----+ m_SeriesArray 数组单元的转移和初始化 
Recount_ArrayZeroPos(m_count, Length_, prev_calculated, series, bar, m_SeriesArray);
for(iii=class="num">1; iii<=Length; iii++, rrr--)
   {
     kkk = Recount_ArrayNumber(m_count, Length_, iii);
     m_sum += m_SeriesArray[kkk] * rrr;
     m_lsum += m_SeriesArray[kkk];
     m_weight += iii;
   }
class=class="str">"cmt">//----+ 检查可靠用于计算的起点
if(BarCheck1(begin, bar, set)) class="kw">return(EMPTY_VALUE);
class=class="str">"cmt">//----+ 初始化零值
if(BarCheck2(begin, bar, set, Length))
class=class="str">"cmt">//----+ 保存变量值 
if(BarCheck4(rates_total, bar, set))
class=class="str">"cmt">//----+ 恢复变量值
if(BarCheck5(rates_total, bar, set))

记住这一条就够了

把平滑算法封装成简单类,是降低 MQL5 指标学习曲线的直接办法。随文给的 Include_zh.zip 只含两份文件,却足够编译 Indicators.zip 里全部指标;测试 EA 则单独放在 Experts.zip,体积 5.03 KB,可立即拖进 MT5 回测。 上面这段枚举定义了 10 种平滑方式,从 MODE_SMA_ 到 MODE_AMA,GetStartBars() 则按所选 Method 与 Length、Phase 返回算法所需最少 bar 数——改一个枚举值,就能切换均线内核。 外汇与贵金属波动剧烈、杠杆高风险突出,这类封装只解决代码组织问题,不预示任何收益。打开 MT5 把 Smooth_Method 里的 MODE_JJMA 换成 MODE_T3,编译跑一遍,比读十篇概述都实在。

MQL5 / C++
enum Smooth_Method
  {
   MODE_SMA_,  class=class="str">"cmt">//SMA
   MODE_EMA_,  class=class="str">"cmt">//EMA
   MODE_SMMA_, class=class="str">"cmt">//SMMA
   MODE_LWMA_, class=class="str">"cmt">//LWMA
   MODE_JJMA,  class=class="str">"cmt">//JJMA.
   MODE_JurX,  class=class="str">"cmt">//JurX
   MODE_ParMA, class=class="str">"cmt">//ParMA
   MODE_T3,    class=class="str">"cmt">//T3
   MODE_VIDYA, class=class="str">"cmt">//维迪亚
   MODE_AMA    class=class="str">"cmt">//AMA
   };


class=class="str">"cmt">//+X================================================================X+
class=class="str">"cmt">//| 计算 XMA 算法所需的最小条数
class=class="str">"cmt">//+X================================================================X+
class="type">int GetStartBars(Smooth_Method Method,class="type">int Length,class="type">int Phase)
把重复劳动交给小布
这些无缓冲平均类的写法小布盯盘的 AIGC 已内置模板,打开对应品种页就能直接生成指标骨架,你只改参数和周期。

常见问题

类内部只保留计算当前柱所需的有限数据,若不按历史顺序预跑一遍,选择集就缺了前面柱的流入流出记录,当前均价会偏。
可以,小布盯盘的 AIGC 侧已预置文中 CMoving_Average 风格的封装,描述周期与价格类型即可吐出可编译片段。
把平均算法做成类后,每次实例化都独占内部变量,不同周期或品种并行调用不会共享状态,冲突概率趋于零。
单周期计算取代写入加搜索两个周期,实测多数品种倾向更轻,极端长历史下差距更明显,但具体取决于调用频次。