【MQL4の勉強】トレーリングストップ注文のEAを作成!プログラム書き方やサンプルコードあり!

ザフナーラボブログ

MetaTrader4(MT4)においては、標準でトレーリングストップ注文を出す機能が備わっています(詳細は「こちら」を参照してください。)。

しかし、MT4に標準で装備されているトレーリングストップ注文は、「こちら」で解説しているように、約定価格からトレーリングストップを設定した値幅(トレーリングストップ幅)分の利益が出てから初めて機能します。

したがって、注文が約定し、ポジションを保有した時点からトレーリングストップを機能させるためには、別途プログラミングする必要があります。

そこで、MT4のEAにおいて、ポジションを保有した時点からトレーリングストップを機能させるためのプログラミング方法について解説します。

以下のリンクからプログラムのサンプルコードがダウンロード出来ますので、サンプルコードを見ながら記事を読み進めてください。

Trailing-Stop-Code

1.変数の宣言

変数の詳細については「こちら」を参照してください。

EAにトレーリングストップ機能を設定するためには、以下のような変数を宣言します。

サンプルコード


//変数の宣言
extern int Magic = 1111;

extern int Trailing_Stop = 50;

double Pips = 0;

各変数の意味は、以下のとおりです。

  • Magic
    マジックナンバー(EAを識別する整数値)を格納します。
    この変数は、EAをチャートに適用した際に、任意の値に設定することができるようにするため、「extern」(詳細は「こちら」を参照してください。)を付けて宣言します。
  • Trailing_Stop
    トレーリングストップ幅(単位はpips)を格納します。
    この変数は、EAをチャートに適用した際に、任意の値に設定することができるようにするため、「extern」(詳細は「こちら」を参照してください。)を付けて宣言します。
  • Pips
    AdjustPoint()関数の戻り値を格納します。

2.関数の定義

関数の詳細については「こちら」を参照してください。

具体例においては、関数を以下のように定義しています。

サンプルコード

//関数の定義
double AdjustPoint(string Currency)
{
 int Symbol_Digits = (int)MarketInfo(Currency,MODE_DIGITS);
 
 if(Symbol_Digits == 2 || Symbol_Digits == 3)
   {
    double Calculated_Point = 0.01;
   }
 else if(Symbol_Digits == 4 || Symbol_Digits == 5)
          {
            Calculated_Point = 0.0001;
          }
        
 return(Calculated_Point);
}

EAにおけるトレーリングストップは、OrderModify()関数(詳細は「こちら」を参照してください。)を使用して、保有ポジションの損切り価格の修正・変更を適宜行うことによって実行されます。

具体的には、OrderModify()関数の第3引数に、以下の計算式で求められた値を記述します(買いポジションに対する場合。)。

Bid - トレーリングストップ幅 × Point

Point(詳細は「こちら」を参照してください。)には、提示レートの最小変動単位が格納されています。

したがって、例えば、50pipsのトレーリングストップ幅を設定したい場合には、上述の計算式のトレーリングストップ幅の箇所を以下のように設定する必要があります。

  • 提示レートが小数点以下2桁又は4桁の業者の場合
    50
  • 提示レートが小数点以下3桁又は5桁の業者の場合
    500(=50pips × 10)

しかし、提示レートの小数点以下の桁数に応じて、以上ような処理を逐一行うことは、煩雑であるし、思わぬミスをも誘発しかねません。

そこで、AdjustPoint()関数を定義することで、上述の計算式のPointの箇所を、提示レートが3桁又は5桁で表示される業者においては、それぞれ「0.01」と「0.0001」にするという処理を行うようにしています。

これによって、提示レートが3桁又は5桁で表示される業者においても、提示レートが2桁又は4桁で表示される業者と同様に、トレーリングストップ幅の設定をpips単位で行うことができるようになります。

AdjustPoint()関数のより詳しい内容については「こちら」を参照してください。

3.init()関数の記述

init()関数の詳細については「こちら」を参照してください。

AdjustPoint()関数は、EAをチャートに適用した際に一度だけ実行されれば足りるので、init()関数内に、以下のようなコードを記述します。

サンプルコード



int init()
{
  Pips = AdjustPoint(Symbol());
  
  return(0);
}

4.トレーリングストップの記述

トレーリングストップの設定は、start()関数内の、保有ポジションの決済処理及びエントリー処理の記述の後に、以下のようなコードを記述することによって行います。

Trailing-Stop-Setting

 

  • for()文の詳細については「こちら」を参照してください。
  • OrdersTotal()関数の詳細については「こちら」を参照してください。
  • OrderSelect()関数の詳細については「こちら」を参照してください。
  • NormalizeDouble()関数の詳細については「こちら」を参照してください。
  • MarketInfo()関数の詳細については「こちら」を参照してください。
  • MarketInfo()関数の直前にある (int) の詳細については「こちら」を参照してください。
  • Symbol()関数の詳細については「こちら」を参照してください。
  • OrderTicket()関数の詳細については「こちら」を参照してください。
  • OrderOpenPrice()関数の詳細については「こちら」を参照してください。

⑴ 買いポジションに対する設定

OrderType()とは

OrderType()とは、MQL4であらかじめ定義されている関数で、選択したポジションの注文種別を取得するものです。

OrderType()関数の詳細については「こちら」を参照してください。

イ 損切り価格の最大値を設定する

トレーリングストップは、現在価格(決済値を基準とします。買いポジションの場合は買い気配値(Bid)です。)と現在の損切り価格との差が、トレーリングストップ幅よりも大きいかどうかをチェックしながら機能させていきます。

したがって、買いポジションに対してトレーリングストップを機能させるためには、損切り価格の最大値を取得する必要があります。

損切り価格の最大値は、以下の計算式により算出されます。

買い気配値-トレーリングストップ幅×pips

具体例においては、これを以下のように記述しています。


Bid - Trailing_Stop * Pips

Bidとは、MQL4であらかじめ定義されている変数で、現在の通貨ペアの買い気配値(Bid値)を格納しているものです。

Bidの詳細については「こちら」を参照してください。

上記の計算式によって得られた値は、後で損切り価格の変更の要否の判断に使用するので、以下のように記述して、変数Max_Stop_Lossに代入しておきます。

サンプルコード


double Max_Stop_Loss = Bid - Trailing_Stop * Pips;
ウ 現在の損切り価格を取得する

トレーリングストップは、現在価格と現在の損切り価格との差が、トレーリングストップ幅よりも大きいかどうかをチェックしながら機能させていくので、トレーリングストップを機能させるためには、現在の損切り価格を取得する必要があります。

現在の損切り価格を取得するためには、OrderStopLoss()関数を使用します。

OrderStopLoss()関数は、MQL4であらかじめ定義されている関数で、選択した注文の損切り価格を取得するものです。

OrderStopLoss()関数の詳細については「こちら」を参照してください。

OrderStopLoss()関数によって得られた値は、後で損切り価格の変更の要否の判断に使用するので、以下のように記述して、変数Current_Stopに代入しておきます。

サンプルコード


double Current_Stop = 
NormalizeDouble(OrderStopLoss(),
                          MarketInfo(Symbol(),MODE_DIGITS));
エ 損切り価格の変更の要否をチェックする

買いポジションに対するトレーリングストップによる損切り価格の変更は、「現在の損切り価格」<「現在の価格-トレーリングストップ幅」という状態になっている場合に行われる必要があります。

そこで、損切り価格の変更条件を以下のように記述します。

サンプルコード


if(OrderMagicNumber() == Magic && 
   OrderSymbol() == Symbol() && 
   Current_Stop < Max_Stop_Loss)

OrderMagicNumber()とは、MQL4であらかじめ定義されている関数で、選択した注文のマジックナンバー(=各EAを識別する整数値)を取得するものです。

OrderMagicNumber()関数の詳細については「こちら」を参照してください。

OrderSymbol()とは、MQL4であらかじめ定義されている関数で、選択した注文の対象通貨ペア名を取得するものです。

OrderSymbol()関数の詳細については「こちら」を参照してください。

オ 損切り価格を変更する

トレーリングストップによる損切り価格の変更条件を満たした場合には、以下のように記述して、損切り価格をMax_Stop_Lossに格納されている価格に変更します。

サンプルコード


bool Modified = OrderModify(OrderTicket(),OrderOpenPrice(),
                   Max_Stop_Loss,0,0);

⑵ 売りポジションに対する設定

ア 損切り価格の最小値を設定する

トレーリングストップは、現在価格(決済値を基準とします。売りポジションの場合は売り気配値(Ask)です。)と現在の損切り価格との差が、トレーリングストップ幅よりも大きいかどうかをチェックしながら機能させていきます。

したがって、売りポジションに対してトレーリングストップを機能させるためには、損切り価格の最小値を取得する必要があります。

損切り価格の最小値は、以下の計算式により算出されます。

売り気配値+トレーリングストップ幅×pips

具体例においては、これを以下のように記述しています。

サンプルコード


Ask + Trailing_Stop * Pips

Askとは、MQL4であらかじめ定義されている変数で、現在の通貨ペアの売り気配値(Ask値)を格納しているものです。

Askの詳細については「こちら」を参照してください。

上記の計算式によって得られた値は、後で損切り価格の変更の要否の判断に使用するので、以下のように記述して、変数Max_Stop_Lossに代入しておきます。

サンプルコード


Max_Stop_Loss = Ask + Trailing_Stop * Pips;
イ 現在の損切り価格を取得する

トレーリングストップは、現在価格と現在の損切り価格との差が、トレーリングストップ幅よりも大きいかどうかをチェックしながら機能させていくので、トレーリングストップを機能させるためには、現在の損切り価格を取得する必要があります。

現在の損切り価格は、以下のように記述することによって、取得します。

サンプルコード


Current_Stop = 
NormalizeDouble(OrderStopLoss(),
                          MarketInfo(Symbol(),MODE_DIGITS));
ウ 損切り価格の変更の要否をチェックする

売りポジションに対するトレーリングストップによる損切り価格の変更は、「現在の損切り価格」>「現在の価格+トレーリングストップ幅」という状態になっている場合に行われる必要があります。

そこで、損切り価格の変更条件を以下のように記述します。

サンプルコード


if(OrderMagicNumber() == Magic && 
   OrderSymbol() == Symbol() && 
  (Current_Stop > Max_Stop_Loss || Current_Stop == 0))

「Current_Stop == 0」という条件を「||」演算子で付加しているのは、損切り価格を設定していない場合には、OrderStopLoss()関数によって取得される値は「0」になり、「現在の損切り価格」>「現在の価格+トレーリングストップ幅」という条件を満たすことがなくなるからです。

エ 損切り価格を変更する

トレーリングストップによる損切り価格の変更条件を満たした場合には、以下のように記述して、損切り価格をMax_Stop_Lossに格納されている価格に変更します。

サンプルコード


Modified = OrderModify(OrderTicket(),OrderOpenPrice(),
                                    Max_Stop_Loss,0,0);