首页 / 交易学院 / 把指标实现为类:以峰谷指标与 ATR 为例
把指标实现为类:以峰谷指标与 ATR 为例

把指标实现为类:以峰谷指标与 ATR 为例

MQL5 编程 难度 · 高阶 2011 12 分钟阅读
指标类prev_calculatedATR

为什么把指标做成类

断线或历史同步中断时,prev_calculated 会被清零,触发针对整个历史的重算。影响因素越多(大周期、复杂计算、多品种、机器差),重算代价越大。把指标封装成类、缓存中间结果,是缓解此问题的工程化手段。

prev_calculated 与重算陷阱

⚠ 断线会清零
连接中断或重大历史同步时,prev_calculated 被设为 0,导致整段重算。设计指标时必须能“从任意位置续算”,不能假设总是增量更新。

峰谷指标类

峰谷(ZigZag)指标维护一个极值点序列 ZZBar。类持有 m_prev_calculated 与缓冲,只对新柱计算,避免每 tick 全量重算。

class CCustZigZagPPC
{
   int    m_prev_calculated;
   ZZBar  m_bars[];          // 极值点序列
public:
   bool Init(void);
   int  Calculate(const int rates_total, const int prev_calculated);
};

struct ZZBar { double price; int index; int type; };

ATR 类示例

ATR 类封装 iATR 句柄与缓冲,对外暴露 Calc(pos) 增量计算,便于在多个指标间复用。

class CCustATR
{
   double m_buf[];
public:
   bool Init(void) { /* 建句柄 */ return true; }
   bool Calc(int pos)
   {
      m_buf[pos] = iATR(_Symbol, PERIOD_CURRENT, 14, pos);
      return true;
   }
};

在 OnCalculate 中调用

主指标把子指标组合进来,统一用 prev_calculated 控制增量区间,既清晰又可复用。

int OnCalculate(const int rates_total,
                  const int prev_calculated, ...)
{
   if(!atr.Calc(rates_total-1)) return 0;
   if(!zz.Calculate(rates_total, prev_calculated)) return 0;
   return rates_total;
}

小结

✦ 类封装的收益
指标即类让逻辑可复用、可组合、可单元测试,也便于在断线重算时只补算差异部分,显著提升多品种多周期下的性能。

常见问题

断线或历史同步中断时终端会清零,触发整段重算;类缓存可缓解。
类可持有状态、组合多个子指标、避免重复计算,更适合复杂逻辑。
若每个图表实例都重算会慢;类封装+限制计算深度能显著提速。