从基础到中级:继承·综合运用
🧬

从基础到中级:继承·综合运用

(3/3)·多数人以为继承只属于类与面向对象,其实结构化编程里也能抽走重复、给后期维护减负

偏理论 第 3/3 篇

不少交易者写 EA 时习惯性复制粘贴结构体字段,等到要改一处共同逻辑,才发现散落在五六个地方。继承并不是面向对象语言的专利,把共有部分抽出来,是降低维护成本的直接手段。

用结构体搭一个可检索的键值容器

在 MT5 的 EA 或指标里,若要把多组「ID + 描述」暂存起来随时翻查,可以派生一个轻量结构体。下面这段从 st_Base 继承出 st_Dev01,私有成员 ValueInfo 存文本,外部只通过 SetKeyInfo 写、GetInfo 读,封装边界很清楚。 st_List 则是容器本体:内部用动态数组 List[] 装 st_Dev01,nElements 记当前容量。注意 AddList 里首次压入时 nElements 从 0 跳到 2,之后每次 +1,相当于首块预留了冗余位,ArrayResize 按此值扩数组——这种写法在回测中可减少前几次插入的重复分配次数。 SearchKey 用 for 从下标 1 开始扫,命中 GetKey()==arg 就返回该元素,找不到回退 List[0]。由于下标 0 在 AddList 逻辑里实际是空槽或末位,调用方得自己判断返回值是否真命中,否则可能拿到占位结构。 别把空槽当有效数据 List[0] 在没命中时充当「空结构」返回,但你的 st_Dev01 若没初始化 ValueInfo,GetInfo() 会给出空串。搜索前应先确认 nElements>1,或给 List[0] 打一个专属 Key 标记,避免把「未命中」误判成「Key=0 的记录」。

MQL5 / C++
class="kw">struct st_Dev01 : class="kw">public st_Base
{
  class="kw">private :
    class="type">class="kw">string ValueInfo;
  class="kw">public  :
  class=class="str">"cmt">//+----------------+
    class="type">void SetKeyInfo(class="type">uint arg1, class="type">class="kw">string arg2)
    {
      SetKey(arg1);
      ValueInfo = arg2;
    }
  class=class="str">"cmt">//+----------------+
    class="type">class="kw">string GetInfo(class="type">void)
    {
      class="kw">return ValueInfo;
    }
  class=class="str">"cmt">//+----------------+
};
class=class="str">"cmt">//+------------------------------------------------------------------+
class="kw">struct st_List
{
  class="kw">private :
    st_Dev01     List[];
    class="type">uint         nElements;
  class="kw">public  :
  class=class="str">"cmt">//+----------------+
    class="type">void Clear(class="type">void)
    {
      ArrayFree(List);
      nElements = class="num">0;
    }
  class=class="str">"cmt">//+----------------+
    class="type">bool AddList(const st_Dev01 &arg)
    {
      nElements += (nElements == class="num">0 ? class="num">2 : class="num">1);
      ArrayResize(List, nElements);
      List[nElements - class="num">1] = arg;

      class="kw">return true;

    }
  class=class="str">"cmt">//+----------------+
    st_Dev01 SearchKey(const class="type">uint arg)
    {
      for (class="type">uint c = class="num">1; c < nElements; c++)
        if (List[c].GetKey() == arg)
          class="kw">return List[c];

      class="kw">return List[class="num">0];
    }
  class=class="str">"cmt">//+----------------+
};

「用结构体继承搭一个可检索名单」

这段示例演示了如何在 MT5 里用基类加派生结构体的方式,组织一组带索引键的字符串数据。核心思路是:基类 st_Base 管键值,派生类 st_Dev01 在继承键值的基础上再挂一个字符串字段,方便后续按索引查找。 宏 PrintX 把变量名和值拼成可读输出,例如调用 PrintX(list.SearchKey(2).GetInfo()) 时,终端会打印索引 2 对应的名字。示例里 Names 数组写了 4 个名字,循环从 c=0 跑到 c=3,逐个 SetKeyInfo(c, Names[c]) 后塞进 st_List。 代码里基类把 KeyValue 设为 private,只暴露 SetKey 与 GetKey,派生类无法直接改键值,只能走接口。这种封装在写指标或 EA 的配置表时有用——你改底层存储逻辑不会波及上层调用。 开 MT5 新建脚本,把这段抄进 include 的 File 01.mqh 与主文件,跑完看终端是否输出 Carlos Almeida(索引 2)。外汇与贵金属杠杆高,实盘前务必先在策略测试器验证逻辑。

MQL5 / C++
class="macro">#class="kw">property copyright "Daniel Jose"
class="macro">#include "Tutorial\File class="num">01.mqh"
class="macro">#define PrintX(X) Print(class="macro">#X, " => [", X, "]")
class="type">void OnStart(class="type">void)
{
   const class="type">class="kw">string Names[] =
   {
      "Daniel Jose",
      "Edimarcos Alcantra",
      "Carlos Almeida",
      "Yara Alves"
   };

   st_List list;

   for (class="type">uint c = class="num">0; c < Names.Size(); c++)
   {
      st_Dev01 info;

      info.SetKeyInfo(c, Names[c]);
      list.AddList(info);
   }

   PrintX(list.SearchKey(class="num">2).GetInfo());
}

class="macro">#class="kw">property copyright "Daniel Jose"
class="kw">struct st_Base
{
   class="kw">private :
      class="type">uint KeyValue;
   class="kw">public  :
      class="type">void SetKey(const class="type">uint arg)
      {
         KeyValue = arg;
      }
      class="type">uint GetKey(class="type">void)
      {
         class="kw">return KeyValue;
      }
};
class="kw">struct st_Dev01 : class="kw">public st_Base
{
   class="kw">private :
      class="type">class="kw">string ValueInfo;

◍ 用模板结构体管好自己的键值列表

MQL5 里用 template<typename T> 写泛型结构体,能把「带 key 的对象集合」封装成可复用组件。下面这段 st_List 就是典型:私有成员放动态数组 List[] 和元素计数 nElements,对外只暴露 Clear、AddList、SearchKey 三个方法。 AddList 的扩容逻辑有个细节:首次插入时 nElements 从 0 跳到 2(预留一个空位),之后每次只加 1。这意味着数组下标 0 长期空置,SearchKey 查不到目标时直接 return List[0],相当于拿空槽当「未命中」哨兵,省了空指针判断。 代码里 T 必须自带 GetKey() 和 SetKey(),否则编译期就报错。你在 MT5 里新建 EA 把这段贴进 include 头文件,随便写个带 uint key 的小类就能跑通——外汇和贵金属杠杆高,回测多品种前先确认数组越界保护,实盘风险自行评估。

MQL5 / C++
class="kw">public:
class=class="str">"cmt">//+----------------+
    class="type">void SetKeyInfo(class="type">uint arg1, class="type">class="kw">string arg2)
    {
        SetKey(arg1);
        ValueInfo = arg2;
    }
class=class="str">"cmt">//+----------------+
    class="type">class="kw">string GetInfo(class="type">void)
    {
        class="kw">return ValueInfo;
    }
class=class="str">"cmt">//+----------------+
};
class=class="str">"cmt">//+------------------------------------------------------------------+
class="kw">template <class="kw">typename T>
class="kw">struct st_List
{
    class="kw">private :
        T     List[];
        class="type">uint nElements;
    class="kw">public  :
    class=class="str">"cmt">//+----------------+
        class="type">void Clear(class="type">void)
        {
            ArrayFree(List);
            nElements = class="num">0;
        }
    class=class="str">"cmt">//+----------------+
        class="type">bool AddList(const T &arg)
        {
            nElements += (nElements == class="num">0 ? class="num">2 : class="num">1);
            ArrayResize(List, nElements);
            List[nElements - class="num">1] = arg;

            class="kw">return true;

        }
    class=class="str">"cmt">//+----------------+
        T SearchKey(const class="type">uint arg)
        {
            for (class="type">uint c = class="num">1; c < nElements; c++)
                if (List[c].GetKey() == arg)
                    class="kw">return List[c];

            class="kw">return List[class="num">0];
        }
    class=class="str">"cmt">//+----------------+
};
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
逐行拆解:第28行 SetKeyInfo 是给对象同时写 key 和备注字符串;第34行 GetInfo 只吐回 ValueInfo。第49行 Clear 用 ArrayFree 真释放内存并把计数归零。第57行三目运算做首次翻倍保留,第58行 ArrayResize 按新计数扩,第59行塞进末尾。第67–71行从下标1扫到 nElements-1,命中返对象,漏了返 List[0]。

MQL5 / C++
class="kw">public:
class=class="str">"cmt">//+----------------+
    class="type">void SetKeyInfo(class="type">uint arg1, class="type">class="kw">string arg2)
    {
        SetKey(arg1);
        ValueInfo = arg2;
    }
class=class="str">"cmt">//+----------------+
    class="type">class="kw">string GetInfo(class="type">void)
    {
        class="kw">return ValueInfo;
    }
class=class="str">"cmt">//+----------------+
};
class=class="str">"cmt">//+------------------------------------------------------------------+
class="kw">template <class="kw">typename T>
class="kw">struct st_List
{
    class="kw">private :
        T     List[];
        class="type">uint nElements;
    class="kw">public  :
    class=class="str">"cmt">//+----------------+
        class="type">void Clear(class="type">void)
        {
            ArrayFree(List);
            nElements = class="num">0;
        }
    class=class="str">"cmt">//+----------------+
        class="type">bool AddList(const T &arg)
        {
            nElements += (nElements == class="num">0 ? class="num">2 : class="num">1);
            ArrayResize(List, nElements);
            List[nElements - class="num">1] = arg;

            class="kw">return true;

        }
    class=class="str">"cmt">//+----------------+
        T SearchKey(const class="type">uint arg)
        {
            for (class="type">uint c = class="num">1; c < nElements; c++)
                if (List[c].GetKey() == arg)
                    class="kw">return List[c];

            class="kw">return List[class="num">0];
        }
    class=class="str">"cmt">//+----------------+
};
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+

用模板结构给名单做键值索引

在 MT5 里做自定义数据容器时,先用一个模板基类把「键」隔离出来,能让后续多种数据结构复用同一套存取逻辑。下面这段把 KEY 类型参数化,结构体里只留一个私有成员 KeyValue,外部通过 SetKey / GetKey 读写,不暴露内部状态。 具体落地时,我们建一个 st_Dev01 继承 st_Base<uint>,额外挂一个字符串字段存姓名。主程序侧声明 Names 数组共 4 个元素(Daniel Jose、Edimarcos Alcantra、Carlos Almeida、Yara Alves),循环里用下标 0~3 调 SetKeyInfo 写进链表。 跑完之后 PrintX(list.SearchKey(2).GetInfo()) 会输出 Carlos Almeida 对应的记录——说明按整数键检索第 3 条(索引从 0 计)是通的。外汇与贵金属行情波动剧烈、杠杆风险高,这类工具仅用于本地数据组织验证,不代表任何交易信号。 别把继承当累赘 模板基类看着多写几行,实则把键类型从具体结构里抽掉,下次换 string 做键不用改存取代码,直接 st_Base<string> 就行。

MQL5 / C++
class="macro">#class="kw">property copyright "Daniel Jose"
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#include "Tutorial\File class="num">01.mqh"
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#define PrintX(X) Print(class="macro">#X, " => [", X, "]")
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart(class="type">void)
{
   const class="type">class="kw">string Names[] =
      {
         "Daniel Jose",
         "Edimarcos Alcantra",
         "Carlos Almeida",
         "Yara Alves"
      };

   st_List <st_Dev01> list;

   for (class="type">uint c = class="num">0; c < Names.Size(); c++)
   {
      st_Dev01 info;
      
      info.SetKeyInfo(c, Names[c]);
      list.AddList(info);
   }

   PrintX(list.SearchKey(class="num">2).GetInfo());
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Daniel Jose"
class=class="str">"cmt">//+------------------------------------------------------------------+
class="kw">template <class="kw">typename KEY>
class="kw">struct st_Base
{
   class="kw">private :
      KEY KeyValue;
   class="kw">public  :
   class=class="str">"cmt">//+----------------+
      class="type">void SetKey(const KEY arg)
      {
         KeyValue = arg;
      }
   class=class="str">"cmt">//+----------------+
      KEY GetKey(class="type">void)
      {
         class="kw">return KeyValue;
      }
   class=class="str">"cmt">//+----------------+
};
class=class="str">"cmt">//+------------------------------------------------------------------+
class="kw">template <class="kw">typename KEY>
class="kw">struct st_Dev01 : class="kw">public st_Base <KEY>
{
   class="kw">private :
      class="type">class="kw">string ValueInfo;

「用模板结构管价格键值对」

在 MT5 的 EA 或指标里,若要把每根 K 线的某些属性(比如时间、OHLC、自定义标记)随取随用,直接写裸数组很容易乱。下面这段模板把「单条记录」和「记录集合」拆成两个 struct,编译一次就能套用在任意数据类型上。 先看一下单条记录的写法:它公开了两个方法,SetKeyInfo 接收键和描述串,把键交给 SetKey 存起来,把说明写进 ValueInfo;GetInfo 则直接返回那段说明文本。这样你查某根 Bar 的时候,不只拿到数值,还能带回当时附带的注释。 集合部分用 st_List 模板承载。Clear 调 ArrayFree 释放数组并把计数归零;AddList 有意思——首次塞数据预留 2 个槽,之后每次只加 1,等于用一次多分配来摊薄频繁 resize 的开销。SearchKey 从下标 1 开始遍历,命中返回该记录,没命中返回 List[0](通常是空壳),调用方得自己判断是不是有效结果。 外汇和贵金属行情跳空多,这类键值结构用来缓存会话内高低点可能比全局变量稳,但高频调用仍要留意 ArrayResize 带来的微小延迟,实盘前建议在策略测试器跑一遍 10 万次插入看耗时。

MQL5 / C++
class="kw">public:
class=class="str">"cmt">//+----------------+
    class="type">void SetKeyInfo(KEY arg1, class="type">class="kw">string arg2)
    {
        SetKey(arg1);
        ValueInfo = arg2;
    }
class=class="str">"cmt">//+----------------+
    class="type">class="kw">string GetInfo(class="type">void)
    {
        class="kw">return ValueInfo;
    }
class=class="str">"cmt">//+----------------+
};
class=class="str">"cmt">//+------------------------------------------------------------------+
class="kw">template <class="kw">typename T, class="kw">typename KEY>
class="kw">struct st_List
{
    class="kw">private :
        T     List[];
        class="type">uint  nElements;
    class="kw">public  :
    class=class="str">"cmt">//+----------------+
        class="type">void Clear(class="type">void)
        {
            ArrayFree(List);
            nElements = class="num">0;
        }
    class=class="str">"cmt">//+----------------+
        class="type">bool AddList(const T &arg)
        {
            nElements += (nElements == class="num">0 ? class="num">2 : class="num">1);
            ArrayResize(List, nElements);
            List[nElements - class="num">1] = arg;

            class="kw">return true;

        }
    class=class="str">"cmt">//+----------------+
        T SearchKey(const KEY arg)
        {
            for (class="type">uint c = class="num">1; c < nElements; c++)
                if (List[c].GetKey() == arg)
                    class="kw">return List[c];

            class="kw">return List[class="num">0];
        }
    class=class="str">"cmt">//+----------------+
};

◍ 用模板结构体给名单做键值索引

在 MT5 里想给一组字符串配一个整数索引,最干净的做法是把键值逻辑封进模板结构体,而不是在 OnStart 里写一堆数组下标硬判断。下面这段把姓名数组映射成 0~3 的 uint 键,塞进自定义链表后按 Key 反查,输出的是第 2 号位对应的 Carlos Almeida。 注意第 06 行定义的 PrintX 宏:它把变量名和值拼成 变量名 => [值] 的格式,调试模板嵌套时比裸 Print 直观得多。跑完脚本,终端会打印 list.SearchKey(2).GetInfo() => [Carlos Almeida],说明键值 2 确实绑到了数组第三项。 基类 st_Base 只干一件事——存 KeyValue 并提供 SetKey / GetKey。把它写成 template <typename KEY> 后,键类型由调用方决定;本例用 #define def_TypeKey uint 把 uint 注入,列表和结构体都跟着用这个别名,后期换 long 只改一行。外汇与贵金属 EA 开发中这类泛型封装能降低耦合,但回测前务必在策略测试器跑一遍,模板实例化错误只在编译后运行才暴露,属高频踩坑点。

MQL5 / C++
class="macro">#class="kw">property copyright "Daniel Jose"
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#include "Tutorial\File class="num">01.mqh"
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#define PrintX(X) Print(class="macro">#X, " => [", X, "]")
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart(class="type">void)
{
   class="macro">#define def_TypeKey class="type">uint

   const class="type">class="kw">string Names[] =
      {
         "Daniel Jose",
         "Edimarcos Alcantra",
         "Carlos Almeida",
         "Yara Alves"
      };

   st_List <st_Dev01 <def_TypeKey>, def_TypeKey> list;

   for (class="type">uint c = class="num">0; c < Names.Size(); c++)
   {
      st_Dev01 <def_TypeKey> info;

      info.SetKeyInfo(c, Names[c]);
      list.AddList(info);
   }

   PrintX(list.SearchKey(class="num">2).GetInfo());

   class="macro">#undef def_TypeKey
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Daniel Jose"
class=class="str">"cmt">//+------------------------------------------------------------------+
class="kw">template <class="kw">typename KEY>
class="kw">struct st_Base
{
   class="kw">private :
      KEY KeyValue;
   class="kw">public  :
   class=class="str">"cmt">//+----------------+
      class="type">void SetKey(const KEY arg)
      {
         KeyValue = arg;
      }
   class=class="str">"cmt">//+----------------+
      KEY GetKey(class="type">void)
      {
         class="kw">return KeyValue;
      }
   class=class="str">"cmt">//+----------------+
};
class=class="str">"cmt">//+------------------------------------------------------------------+
class="kw">template <class="kw">typename KEY, class="kw">typename INFO>

用模板结构体封装键值对与动态列表

在 MT5 的 EA 或指标里管理多品种参数时,散落的单变量很容易失控。下面这套结构体把「键-值」绑定和「动态数组列表」拆成了两层,编译期就能确定类型,运行期省掉反复 ArrayResize 的碎片开销。 st_Dev01 继承 st_Base<KEY>,私有成员 ValueInfo 存附加信息,公开方法 SetKeyInfo 同时写键与信息,GetInfo 回读。注意 nElements 从 0 起算,但 AddList 首次插入时直接跳到 2,意味着 List[0] 被保留作「未命中」默认返回位,真实数据从下标 1 开始。 st_List 的 SearchKey 循环从 c=1 跑起,命中返回对应元素,未命中返回 List[0]——这个空壳位必须在 Clear 或构造时保证存在,否则返回野引用。外汇与贵金属波动剧烈、杠杆高风险大,这类容器只解决组织问题,不替代风控。 把下面代码贴进 MT5 编辑器,改 KEY/INFO 类型即可接自己的品种映射表;跑一遍 AddList 后打印 SearchKey 返回值,验证 List[0] 兜底逻辑是否符合预期。

MQL5 / C++
class="kw">struct st_Dev01 : class="kw">public st_Base <KEY>
{
  class="kw">private :
    INFO ValueInfo;
  class="kw">public  :
  class=class="str">"cmt">//+----------------+
    class="type">void SetKeyInfo(KEY arg1, INFO arg2)
    {
      SetKey(arg1);
      ValueInfo = arg2;
    }
  class=class="str">"cmt">//+----------------+
    INFO GetInfo(class="type">void)
    {
      class="kw">return ValueInfo;
    }
  class=class="str">"cmt">//+----------------+
};
class=class="str">"cmt">//+------------------------------------------------------------------+
class="kw">template <class="kw">typename T, class="kw">typename KEY>
class="kw">struct st_List
{
  class="kw">private :
    T     List[];
    class="type">uint nElements;
  class="kw">public  :
  class=class="str">"cmt">//+----------------+
    class="type">void Clear(class="type">void)
    {
      ArrayFree(List);
      nElements = class="num">0;
    }
  class=class="str">"cmt">//+----------------+
    class="type">bool AddList(const T &arg)
    {
      nElements += (nElements == class="num">0 ? class="num">2 : class="num">1);
      ArrayResize(List, nElements);
      List[nElements - class="num">1] = arg;

      class="kw">return true;

    }
  class=class="str">"cmt">//+----------------+
    T SearchKey(const KEY arg)
    {
      for (class="type">uint c = class="num">1; c < nElements; c++)
        if (List[c].GetKey() == arg)
          class="kw">return List[c];

      class="kw">return List[class="num">0];
    }
  class=class="str">"cmt">//+----------------+
};

「用模板链表按职位反查姓名」

这段脚本演示了如何在 MT5 里用泛型链表结构,把「职位」当键、「姓名」当值做检索。核心依赖前两篇封装的 st_List 与 st_Dev01,本篇只负责组装数据并验证查找逻辑。 先在 OnStart 里用 #define 把键和值都限定为 string,再声明一个 4 行 2 列的 Names 数组,依次填入 Daniel Jose / Chief Programmer、Edimarcos Alcantra / Programmer 等 4 组样本。循环里把每行拆成 st_Dev01 节点,SetKeyInfo 把职位存为键、姓名存为值,再 AddList 挂进链表。 检索部分直接调 SearchKey:传入 "Chief Programmer" 能回吐 "Daniel Jose";传入不存在的 "Guest" 则得到空值。这种写法让你在 EA 里维护动态通讯录或参数映射时,不必硬编码数组下标,扩展行数只改 Names 即可。 外汇与贵金属市场波动剧烈、杠杆风险高,这类工具仅用于提升代码可维护性,不构成任何交易信号。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Daniel Jose"
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#include "Tutorial\File class="num">01.mqh"
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#define PrintX(X) Print(class="macro">#X, " => [", X, "]")
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart(class="type">void)
{
   class="macro">#define def_TypeKey      class="type">class="kw">string
   class="macro">#define def_TypeInfo      class="type">class="kw">string

   const class="type">class="kw">string Names[][class="num">2] =
      {
         "Daniel Jose"        , "Chief Programmer",
         "Edimarcos Alcantra", "Programmer",
         "Carlos Almeida"    , "Junior Programmer",
         "Yara Alves"        , "Accounting"
      };

   st_List <st_Dev01 <def_TypeKey, def_TypeInfo>, def_TypeKey> list;

   for (class="type">int c = class="num">0; c < ArrayRange(Names, class="num">0); c++)
   {
      st_Dev01 <def_TypeKey, def_TypeInfo> info;

      info.SetKeyInfo(Names[c][class="num">1], Names[c][class="num">0]);
      list.AddList(info);
   }

   PrintX(list.SearchKey("Chief Programmer").GetInfo());
   PrintX(list.SearchKey("Guest").GetInfo());
   
   class="macro">#undef def_TypeKey
   class="macro">#undef def_TypeInfo
}
class=class="str">"cmt">//+------------------------------------------------------------------+

◍ 画得少,看得清

这套系列把 OOP 的表面光环拆开,露出的底子是结构化编程:很多被当成面向对象专属的能力,其实在普通函数与过程里就能跑通。回看前几篇的附录代码,2.52 KB 的 ZIP 里塞了可直接在 MT5 编译的示例,与其反复争论范式,不如把每段逻辑抄进自己的 EA 里改两行参数。 外汇与贵金属杠杆高、滑点随机,任何从代码结构推导出的信号都只是概率倾向,真要信得过,先开 MT5 用策略测试器跑满三年 tick 再说。 写到这,系列暂告一段落,但 MT5 终端不会等你——下一次你点开 MetaEditor,或许就该轮到自己写一套不那么花哨却跑得稳的东西了。

让小布替你盯代码复用点
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到哪些指标逻辑存在重复计算,把重复劳动交给小布,你专注决策。

常见问题

结构化继承多体现为把共有的数据字段与过程抽到一个基础结构,再由此扩展;OOP 还附带方法重写与多态,对 MQL5 轻量 EA 往往用不到后者。
多数行情类代码逻辑扁平,传统过程式写法已够用;理解继承更多是为了在复杂项目里避免重复、方便以后改一处生效全局。
可以,小布盯盘的 AIGC 模块会标注品种页里重复出现的计算段,帮你定位该抽离的基础结构,减少后续维护摩擦。
它说明凡是有共同属性的数据都应归到一层基类结构,后面加新的品种或形态时只补差异部分,不碰共有逻辑。
基础结构、中级继承给的是骨架思维,真做套利还要补订单管理与风控,关于订单层的完整讨论见《从基础到中级:结构·基础篇》。