【MQL5】 MT5のEA作成 その2 リピート型EA試作

【MQL5】 MT5のEA作成 その2 リピート型EA試作

まえがき

 MT5EA作成の勉強シリーズで、大分知識がついてきたので、実践的なEA開発を試してみたいと思います。勉強の過程で作ったパラボリックSARを参照したEAをその1として、その2からのスタートです。
 今回はリピート型EAを作ろうと思います。リピート型EAとは、指定した価格に到達するたびに少しづつ注文を繰り返す方式のEAです。
 FXブロードネットさんやみんなのFXさんなど、様々なベンダーがサービスの一環として提供している形態でもあります。スタイルとしては、買い/売りのどちらか一方を行うものと、両方を使い分けるものがありますが、とりあえず今回は買い注文のみを行うEAを作ってみたいと思います。

※本記事はEAの基本的な処理(初期化や、注文処理等)の説明は省略し、ポジション保有と決済の条件づけに目とを絞って作成します。その辺りのことを知りたい方は以下の MT5EA作成の勉強シリーズをご覧ください。

【MQL5】 MT5のEA作成の勉強 その1 EAの1番簡単な作り方 + 処理順の確認

設定変数

 設定変数は以下のものを使用します。

  • OrderSize
    一回のポジション保有あたりのLot数を設定します。
  • TakeProfit
    決済までの利益[pips]を設定します。
  • MaxSize
    最大ポジション数を設定します。

ちなみに、損切ラインは以下の式で自動的に計算します。

  • LossCutLine = ((MaxSize/OrderSize)+1)*TakeProfit

現在の損益を取得

 リピート型EAを実現するためには最新の保有ポジションの損益と最古の補修ポジションの損益を常に監視する必要があります。保有ポジションの損益を確認するには、PositionInfoクラスのProfitを参照します。ただし、複数ポジションを持っている場合は事前にどのポジションの損益を確認するのかを、SelectByIndex関数を使って指定する必要があります。引数を現在の保有ポジション数-1にすると、最新のポジションを取得することができます。
 最新ポジションの損益を取得する関数と、保有のポジションの合計利益を取得する関数は以下のようになります。LastPositionProfitが最新のポジションの損益で、FirstPositionProfitが現在の保有ポジションの総損益です。

//--- 最新のポジションの損益
if(m_position.SelectByIndex(PositionsTotal()-1))
    LastPositionProfit = m_position.Profit();

//--- 最古のポジションの利益
if(m_position.SelectByIndex(0))
    FirstPositionProfit = m_position.Profit();

最新のポジションの利益が設定値を上回った/下回ったときに発注

 最新のポジションについてが TakeProfitに設定したpips分だけ利益が出た場合、または損失が出た場合に新しくポジションを保有します。利益が出た場合、持っていたポジションは決済されるので、ポジション数は変動せず、損失が出た場合、持っていたポジションはそのままになるので、保有ポジション数は増加します。
 判定は簡単で、上記のソースで取得したLastPositionProfitの絶対値、設定値を比較するだけです。

//--- 最新のポジションの損益の絶対値が設定値以上なら
   if (TakeProfit <= MathAbs(LastPositionProfit))
   {
      //新規ポジション保有処理へ
      return(1);
   }

こうすると、以下のように、一定間隔でポジション保有と決済を繰り返すようになります。

リピート型EA動作(ポジション保有・決済)
リピート型EA動作(ポジション保有・決済)

全てのポジションの損失が設定値を超えたときに全てのポジションを決済

 ポジションの決済は、最初に保有したポジションの含み損がLossCutLineに設定した値に達したときに行います。この時、全てのポジションを一斉に決済し、保有ポジション数を0にします。 ポジションを一括決済というコマンドはないので(私が知らないだけかもですが)ループ文で一つ一つ決済します。

if(-1 * (FirstPositionProfit) >= LossCutLine)
{
    for(int i=PositionsTotal()-1;i>=0;i--)
     {
        if(m_position.SelectByIndex(i))
           if(LongClosed())
              res = true;
     }
}

ロスカットラインに到達すると以下のように保有ポジションが一括決済されます。

リピート型EA動作 (ロスカット)

リピート型EA動作 (ロスカット)

おまけ(隘路事項)

 うっかり隘路したポイントがあるので、メモしておきます。
一通り、ソースを書いてテストを行うと、何故か一度も取引が行われませんでした。
エラーを確認してみると、「We have no money」、つまり、口座資金が不足しているというエラーが出ていました。
しかし、テストの口座資金設定は10000USDとなっており、テストに使った銘柄のUSD/EURであれば、少なくとも1Lot以上は確実に帰るはずであり、まして0.1Lotを発注できないなど有り得ません。
では、なぜそうなったのか、それは以下のソースをコメントアウトしてしまったからでした。

   if(!m_symbol.RefreshRates())
      return(false);

上記のソースに含まれる「RefreshRates」とは、相場情報を更新する関数なのですが、これを行わないと相場の価格が正確に取得できないため、上記のエラーに繋がるようです。

実行結果

 実行してみると以下のようになりました。
やはり、何にも考えずに一方向にポジションを持つだけでは碌な結果にならないようです。
何らかの条件で途転するなり新規ポジション保有を控えるなりといった条件が必要でしょう。

リピート型EA(買いのみ)実行結果
リピート型EA(買いのみ)実行結果
OrderSize=0.1 , MaxSize=1.0 , TakeProfit=50)

まとめ

 リピート型EAを試作しました。まだまだ改善の余地があるので、今後も検討してゆきたいと思います。