【MQL4テクニック】トレーリングストップの基本形《決定版》

MQL4テクニック

トレーリングストップとはEAの中でも非常に人気な機能です。しかしトレーリングストップには様々な実装方法があり、インターネットで調べてみても疎らな情報が多く困っている方も多いのではないでしょうか。

そんな方にトレーリングストップの一番基本的な形をご紹介いたします。

トレーリングストップとは?

トレーリングストップとは価格が有利な方向に進んだ際、随時ストップロスを補正していき現在の利益を無駄にしないという機能になります。基本的にはストップロスのみで決済を行うため、テイクプロフィットは用いません。

例えばドル円を100円で注文しSL = 90円 TP = 110円で設定した時に、最初は109円まで上昇したものの110円に到達して90円まで下落してしまったら最初の9円分の利益は非常に勿体ないですよね?

では109円に到達する時点でストップロスが105円まで引き上げられていたらどうでしょう。
その後どんなに下落したとしても必ず5円分の利益は保証できます。

そんな夢のような機能がトレーリングストップになります。

動作の流れプログラムの観点からを整理してみると、

①注文時点ではSLが初期値にある
②〇Pipsの利益でSLを注文価格の位置に設定する
③以降〇Pipsの利益が出るたびに、SLを〇Pipsずつ現在の価格に寄せていく

このような感じになります。では実装に移りましょう!

サンプルコード

void OnTick(){

   int trailLength = 5;
   
   for (int i = OrdersTotal() - 1; i >= 0; i--){
      OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
      
      if (OrderType() == OP_BUY){
         if (OrderStopLoss() < OrderOpenPrice() || OrderStopLoss() == 0){
            double profit = OrderClosePrice() - OrderOpenPrice();
            if (profit / Pips() > trailLength){
               OrderModify(OrderTicket(), OrderClosePrice(), OrderOpenPrice(), OrderTakeProfit(), OrderExpiration());
            }
         }else{  
            double profit = OrderClosePrice() - OrderStopLoss();
            if (profit / Pips() > trailLength * 2){
               double newStopLoss = OrderStopLoss() + trailLength * Pips();
               OrderModify(OrderTicket(), OrderClosePrice(), newStopLoss, OrderTakeProfit(), OrderExpiration());
            }
         }
      }
      
      if (OrderType() == OP_SELL){
         if (OrderStopLoss() > OrderOpenPrice() || OrderStopLoss() == 0){
            double profit = OrderOpenPrice() - OrderClosePrice();
            if (profit / Pips() > trailLength){
               OrderModify(OrderTicket(), OrderClosePrice(), OrderOpenPrice(), OrderTakeProfit(), OrderExpiration());
            }
         }else{
            double profit = OrderStopLoss() - OrderClosePrice();
            if (profit / Pips() > trailLength * 2){
               double newStopLoss = OrderStopLoss() - trailLength * Pips();
               OrderModify(OrderTicket(), OrderClosePrice(), newStopLoss, OrderTakeProfit(), OrderExpiration());
            }
         }
      }
   }
}

double Pips(){

   int digits = (int)MarketInfo(Symbol(), MODE_DIGITS);

   if(digits == 3 || digits == 5){
     return NormalizeDouble(Point * 10, digits - 1);
   }
   if(digits == 4 || digits == 2){
     return Point;
   }
   return 0.1;
}

コード量は多くなってしまいますが、内容は非常にシンプルですので安心してください。
それでは細かく解説していきます。

for (int i = OrdersTotal() - 1; i >= 0; i--){
   OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
}

現在保有しているポジションを順番に取得していく部分です。Tick更新毎に全てのポジションを監視し、トレーリングを発動するか?を逐一監視します。

if (OrderType() == OP_BUY){
   //買い注文のトレーリング処理
}    
if (OrderType() == OP_SELL){
   //売り注文のトレーリング処理
}

買い注文売り注文では制御方法が異なりますので、OrderType関数を用いて条件分岐をしておきます。

//買い注文
if (OrderStopLoss() < OrderOpenPrice() || OrderStopLoss() == 0){
   //初回のトレーリング
}

//売り注文
if (OrderStopLoss() > OrderOpenPrice() || OrderStopLoss() == 0){
   //初回のトレーリング
}

次の条件分岐では、

買い注文では ストップロス < 注文価格
売り注文では ストップロス > 注文価格 
もしくは ストップロスが設定されていない。

という条件を用いてこのポジションはトレーリングがまだ開始されていないかどうかを判別します。

//買い注文
double profit = OrderClosePrice() - OrderOpenPrice();
if (profit / Pips() > trailLength){
   OrderModify(OrderTicket(), OrderClosePrice(), OrderOpenPrice(), OrderTakeProfit(), OrderExpiration());
}

//売り注文
double profit = OrderOpenPrice() - OrderClosePrice();
if (profit / Pips() > trailLength){
   OrderModify(OrderTicket(), OrderClosePrice(), OrderOpenPrice(), OrderTakeProfit(), OrderExpiration());
}

トレーリングがまだ開始されていない場合は、

買い注文であれば 現在の価格 – 注文価格
売り注文であれば 注文価格 – 現在価格

で利幅を計算します。今回は自作のPips関数を用いて幅をPips単位に変換しています。

この利幅が設定したトレーリング幅を超えていたら、そのポジションのストップロスを注文価格に設定しトレーリングを開始します。

//買い注文
}else{  
   double profit = OrderClosePrice() - OrderStopLoss();
   if (profit / Pips() > trailLength * 2){
      double newStopLoss = OrderStopLoss() + trailLength * Pips();
      OrderModify(OrderTicket(), OrderClosePrice(), newStopLoss, OrderTakeProfit(), OrderExpiration());
   }
}

//売り注文
}else{
   double profit = OrderStopLoss() - OrderClosePrice();
   if (profit / Pips() > trailLength * 2){
      double newStopLoss = OrderStopLoss() - trailLength * Pips();
      OrderModify(OrderTicket(), OrderClosePrice(), newStopLoss, OrderTakeProfit(), OrderExpiration());
   }
}

以降トレーリングが開始されたポジションは、

売り注文であれば 注文価格 – 現在価格
買い注文であれば 現在価格 – 注文価格

で前回トレーリングを設置した場所からの幅を計算します。

この計算した幅がトレーリング幅の2倍になった場合、ポジションのストップロスを現在の価格に寄せる処理を行います。

まとめ

今回はトレーリングストップ機能の一番基本的な形を紹介いたしました。

トレーリングストップには様々な実装方法がありますが、まずは本記事の内容だけ抑えれば問題ありません。

非常に需要が多い機能の一つですので、これを機に是非マスターしましょう!

POINT

こちらの記事で悩みが解決されない場合は、
MQL4 User Community に参加してお気軽にご質問ください。

MQL4初心者の方や開発に行き詰った方の悩みを、 様々なソフトウェアやツールを開発してきた経験豊富なエンジニアたちが解決いたします。