記事「多通貨エキスパートアドバイザーの開発(第1回):複数取引戦略の連携」についてのディスカッション - ページ 2

 
fxsaber #:

100%損はしない。ただ、不必要な存在なのだ。OOPはアーキテクチャ上、一般から特殊へという原則に従う。あなたは一般クラス(基本クラス)を「プライベート」にした。そこで呼ばれるのはCStrategy::Tick()だけだが。

これは私がここで取ったアプローチだ。ベース・クラス -> 継承者1 -> 継承者2 -> 継承者3という直線的な階層を作れるとしよう。継承クラスは親クラスを徐々に複雑にしていくが、継承ツリーの分岐はどこにもない。もし、Inheritor3の後継クラスとなるいくつかのクラスからなるオブジェクトを作成するのであれば、親クラスのコードをすべてコンパクトにまとめ、最初の3つの後継クラスの内容を含む基底クラスを一度に作成します。

この記事では、ベース・クラスは大まかに言って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()を使うためだけである。

スズメの大砲から。なぜこの2つの仮想メソッドをCStrategyに追加しないのか?

 
fxsaber #:

スズメの大砲から。なぜこの2つの仮想メソッドをCStrategyに追加しないのか?

そうだね。CObjectを継承する代わりに、CStrategyとその他の基本クラスに保存メソッドを追加することにしよう。

 
Yuriy Bykov #:

あなたは古典的な(入力+OOPなし)SimpleVolumes.mq5をSimpleVolumesStartegy.mqhにOOP変換しています。

なぜSimpleVolumes.mq5を#include SimpleVolumesStartegy.mqhで作らなかったのですか?

 
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();   // すべてのExpert Advisorストラテジーの初期化

   return(res);
}

TCのポートフォリオの仕事を見せるようになったのだから、ポートフォリオの読み込み(インプット)をきちんと処理するのがいいだろう。

 
fxsaber #:

古典的な(入力+OOPなし)SimpleVolumes.mq5からSimpleVolumesStartegy.mqhへのOOP変換を行います。

なぜ、#include SimpleVolumesStartegy.mqhでSimpleVolumes.mq5を作らなかったのですか?

というのも、通常のEA(入力+OOPなし)は、異なる設定で並列モードで使用することを目的とせずに書かれています(これがSimpleVolumes.mq5の役割です)が、この並列使用が可能な別のEA(これがSimpleVolumesExpert.mq5の役割です)に移行するプロセスを示したかったからです。この目的のために、SimpleVolumesStartegy.mqhでOOP変換が必要でした。

 
fxsaber #:

TCのポートフォリオの仕事を見せるようになったのだから、ポートフォリオの読み込み(インプット)にうまく対応するのがいいだろう。

次のパートで必ず扱います。まだ多くのことが残っているので、一度にすべてを紹介することはできなかった。

というのも、今がそのタイミングだからです。記事のために、私はここ数年間、以前書いたコードをほとんどゼロからやり直しています。そのため、コードはその役目を果たしているのだが、もはや必要ないにもかかわらずクリーンアップされていない箇所がいくつかある。また、今ならわかると思うが、コードをシンプルにしたり、一般的に異なるアーキテクチャのアプローチを適用できる箇所もある。

理想的には、貴社の優れたライブラリを使用して、最適化と戦略パラメーターの適切なポートフォリオの選択を完全に自動化するレベルにまで到達したいです。

 
Yuriy Bykov #:

通常のEA(入力+OOPなし)から移行するプロセスを示したかったからだ。

わかった。