文章 "开发多币种 EA 交易(第 1 部分):多种交易策略的协作" - 页 2

 
fxsaber #:

100%不会有任何伤害。它只是一个不必要的实体。OOP 在架构上遵循从一般到特殊的原则。您将一般类(基类)设置为 "私有"。尽管那里调用的只是 CStrategy::Tick()。

这就是我在这里采用的方法。假设我们可以创建一个线性层次结构 基类 -> 继承者 1 -> 继承者 2 -> 继承者 3。继承者类逐渐使父类复杂化,但继承树没有任何分支,也就是说,所有类都只有一个连续的继承者。那么,如果我们只打算创建几个类的实际对象,它们将成为 Inheritor3 的继承者,而且父类的所有代码都足够紧凑,我们就可以立即创建一个基类,其中包括前三个继承者的内容。

在本文中,基类大体上只包含 CStrategy::Tick()。但我们计划进一步为所有策略添加更多通用代码。

 
fxsaber #:

似乎是编译器出错了,在这样调用时,它没有对这个方法签名发誓。

据我所知,这是因为 MQL5 中的指针与 C++ 中的指针不同。这就是为什么这种变体是合适的。

 
fxsaber CObject 继承。

你不用它。


我注意到从 CObject 继承是很常见的做法。

我不太明白,到底是什么没有被使用,尽管它可能被使用?

CObject 继承只是为了以后使用 Save() 和 Load() 时方便。

 
Yuriy Bykov #:

我不太明白,到底是什么东西没有被使用,尽管它可能被使用?

我将给出完整的代码。

class CObject
  {
private:
   CObject          *m_prev;               // 列表的前一项
   CObject          *m_next;               // 列表的下一个项目

public:
                     CObject(void): m_prev(NULL),m_next(NULL)            {                 }
                    ~CObject(void)                                       {                 }
   //--- 访问受保护数据的方法
   CObject          *Prev(void)                                    const { return(m_prev); }
   void              Prev(CObject *node)                                 { m_prev=node;    }
   CObject          *Next(void)                                    const { return(m_next); }
   void              Next(CObject *node)                                 { m_next=node;    }
   //--- 处理文件的方法
   virtual bool      Save(const int file_handle)                         { return(true);   }
   virtual bool      Load(const int file_handle)                         { return(true);   }
   //--- 识别对象的方法
   virtual int       Type(void)                                    const { return(0);      }
   //--- 比较对象的方法
   virtual int       Compare(const CObject *node,const int mode=0) const { return(0);      }
  };

简而言之,该类用于形成和处理列表,包括可能的排序。

从 CObject 继承只是为了以后使用 Save() 和 Load() 时使用

麻雀的大炮。为什么不在 CStrategy 中添加这两个虚拟方法呢?

 
fxsaber #:

从大炮打麻雀。为什么不在 CStrategy 中添加这两个虚拟方法呢?

是的,我同意。我将在 CStrategy 和其他基类中添加保存方法,而不是从 CObject 继承。

 
Yuriy Bykov #:

您将经典(输入 + 无 OOP)SimpleVolumes.mq5 通过 OOP 转换为 SimpleVolumesStartegy.mqh。

为什么不通过 #include SimpleVolumesStartegy.mqh 来制作 SimpleVolumes.mq5 呢?

 
fxsaber #:

你可以清楚地看到,由于 OOP 的存在,输入非常繁琐。把它去掉会很好。

伪装。

int OnInit() {
   expert.AddStrategy(new CSimpleVolumeStrategy(
                         magic_ + 1, "EURGBP", PERIOD_H1,
                         NormalizeDouble(0.34 * depoPart_, 2),
                         130, 0.9, 1.4, 231, 3750, 50, 600, 3)
                     );
   expert.AddStrategy(new CSimpleVolumeStrategy(
                         magic_ + 2, "EURGBP", PERIOD_H1,
                         NormalizeDouble(0.10 * depoPart_, 2),
                         159, 1.7, 0.8, 248, 3600, 495, 39000, 3)
                     );

   int res = expert.Init();   // 初始化所有专家顾问策略

   return(res);
}

既然他们开始展示 TC 组合的工作,那么适当地处理组合加载(输入)将会很好。

 
fxsaber #:

您需要将经典(输入 + 无 OOP)SimpleVolumes.mq5 转换为 SimpleVolumesStartegy.mqh。

为什么不通过 #include SimpleVolumesStartegy.mqh 来制作 SimpleVolumes.mq5 呢?

因为我想演示从一个普通 EA(输入 + 无 OOP) 到另一个 EA(SimpleVolumesExpert.mq5)的转换过程,在编写该 EA 时,我们并不打算在并行模式下以不同设置使用它(这就是 SimpleVolumes.mq5 角色)。为此,我们需要在 SimpleVolumesStartegy.mqh 中进行 OOP 转换。

 
fxsaber #:

由于他们开始展示 TC 组合的工作,因此最好能胜任组合的加载(输入)工作。

我们一定会在接下来的部分中处理这个问题。要处理的事情还有很多,因此不可能一次全部介绍完。

我非常感谢你们提出的所有意见,因为现在正是提出意见的好时机--对于文章来说,我几乎是从头开始重做过去几年编写的代码,这些代码没有经过清理和优化,没有太多必要。因此,代码完成了它的工作,但有些地方已经不再需要,但还没有清理,还有一些地方,正如你现在看到的,你可以简化代码,或者在总体上采用不同的架构方法。

理想情况下,我希望能使用你们出色的库,实现优化和选择良好策略参数组合的完全自动化。

 
Yuriy Bykov #:

因为我想演示从普通 EA(输入 + 无 OOP) 到 EA(输入 + 无 OOP)的 过程。

明白了。