【超入門】MQL5 EA講座 第94回「トレーリングストップにおけるミニマムプロフィットについて」

MQL5でEA作ろう講座

—-

前回は、はトレーリングストップとは何か?という概要部分と、トレーリングストップの基本となるコード記述について解説しました。

前回の最後にも記述した通り、93回で解説したトレーリングストップのコード記述は、基本的かつ最小限のものです。

今回は前回のコード記述に対して、ミニマムプロフィットという概念を落とし込んでいきたいと思います。

今回の記事を読んで理解する事によって、前回までのシンプルなトレーリングストップに細やかな挙動を付け足すことができるようになります。

スポンサーリンク
スポンサーリンク

ミニマムプロフィットとは?

ミニマムプロフィットという言葉がFX、あるいはMQL5の世界で一般的かどうかはわかりませんが、

minimum=最小限の profit=利益 →すなわち「最小限の利益」という意味です。

要は、トレーリングストップを発動させるタイミングを、約定価格から、相場が当初の想定通りに動き、一定の利益が出る段階まで遅らせる回路を埋め込もうという事です。

前回の講座記事のトレーリングストップ記述だと、現在のストップロス価格と、算出したトレーリングストップ価格との比較のみでトレーリングストップを発動するタイミングを決めていた為、トレーリングストップの発動が概して早すぎるという問題があります。

ミニマムプロフィットの概念をトレーリングストップに追加する事で、トレーリングストップの発動タイミングをより柔軟に調整できるようになります。

トレーリングストップにミニマムプロフィットを導入する為のロードマップ

これからトレーリングストップミニマムプロフィットの概念を追加する記述を順を追って見ていきます。

ミニマムプロフィットを算出する為の値をinput変数でパラメータ化する

//パラメータ
input int TrailingStop = 500;//トレイリンストップを設定する
input int MinimumProfit= 200;//ミニマムプロフィットを設定する

まずはミニマムプロフィットを算出する為の値をinput変数でパラメータ化していきます。

前回は、input変数「TrailingStop」でトレーリングストップの値をパラメータ化しました。

その下に、ミニマムプロフィットを設定する為のinput変数「MinimumProfit」を追加します。初期値は仮に200としておきます。

input変数については以下の記事をご参照ください

ポジション選択とトレーリングストップ値の設定有無を確認する

ここは第93回と変更はありません。

OnTick関数内の記述文、一番最初の

if(PositionSelectByTicket(pTicket) == true && TrailingStop > 0)

は、「ポジションの選択ができて、トレーリングストップの値が指定されている」という意味です。

このif文がtrueであれば、トレーリングストップの設定を執行する{}内の記述に移ります。

<参照>

PositionSelectByTicket関数

トレーリングストップ算出に必要な値を取得する その1

ここも前回と記述は変わりません。

	{
		request.action = TRADE_ACTION_SLTP;
		request.position = ポジション番号;
    long posType = PositionGetInteger(POSITION_TYPE);//ポジションタイプ
		double currentStop = PositionGetDouble(POSITION_SL);//ストップロス価格
		double currentLimit = PositionGetDouble(POSITION_TP);//テイクプロフィット価格

MqlTradeRequest構造体の各メンバ変数に値を設定していきます

ストップロスに修正を加えるので.actionには「TRADE_ACTION_SLTP」が入ります。

※この時、まだ指値価格に到達しておらず、ポジション保有に至っていない待機注文の変更をしたい時に使うTRADE_ACTION_MODIFYを用いないよう注意しましょう。

メンバ変数.position には ポジション番号代入されます(ポジション番号を格納した変数が記述されるのが一般的でしょう)

ポジション種類が買いか、売りかを取得するにはPositionGetInteger関数引数定数POSITION_TYPEを記述します。取得出来た値を変数「posType」に格納します。

現在のストップロス価格を取得するにはPositionGetDouble関数引数定数値「POSITION_SL」を記述します。取得出来た値を変数「currentStop」に格納します。

現在のテイクプロフィット価格を取得するにはPositionGetDouble関数引数定数値「POSITION_TP」を記述します。取得出来た値を変数「currentLimit」に格納します。

MqlTradeRequest構造体については↓

第60回「OrderSend関数とMqlTradeRequest構造体」 をご覧ください。

メンバ変数の役割についても詳細に説明してあります。

トレーリングストップ算出に必要な値を取得する その2

ここの部分で

double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);//ポジションの約定価格
		string symbol = PositionGetString(POSITION_SYMBOL);//取引銘柄
    double point = SymbolInfoDouble(symbol,SYMBOL_POINT);//ポイント
    double trailStop = TrailingStop* point;//トレーリングストップポイント
   double minProfit = MinimumProfit* point;//ミニマムプロフィットポイント(この変数を93回の記述に追加している)
  double trailStopPrice;//トレーリングストップ価格
 double currentProfit;//ミニマムプロフィット価格(この変数を93回の記述に追加している)

前回、宣言したローカル変数「trailStop」の下に、最終的なミニマムプロフィットポイントを格納するローカル変数「minProfit」を追加で記述します。

また、最終的なトレーリングストップ価格を格納する、double型変数「trailStopPrice」の下に、現在のポジションにおける損益情報を獲得するdouble型変数「currentProfit」を追加します。

トレーリングストップの注文を出す(買いの場合)

続いて、ポジションタイプが買いだった場合の記述に移ります。

 if(posType == POSITION_TYPE_BUY)
			{   //トレーリングストップ価格を算出
         trailStopPrice = SymbolInfoDouble(symbol,SYMBOL_BID) - trailStop;
         //ミニマムプロフィット価格を算出(追加箇所)
         currentProfit= SymbolInfoDouble(symbol,SYMBOL_BID) - openPrice;
         
         //ミニマムプロフィット条件を追加
         if(trailStopPrice > currentStop&¤tProfit>=minProfit)
          {
           request.sl = trailStopPrice;//
           OrderSend(request,result);
          }//if(trailStopPrice > currentStop)
      }//if(posType == POSITION_TYPE_BUY)

買いの場合のトレーリングストップ価格はBid-変数「trailStop」の値で求まります。

Bidの価格はSymbolInfoDouble関数の第2引数定数値「SYMBOL_BID」を記述することで取得出来ます。

SymbolInfoDouble(symbol,SYMBOL_BID) – trailStopの計算結果を最終的なトレーリングストップ価格を格納する、double型変数「trailStopPrice」に格納します。ここまでは93回と同じです。

この後、変数「trailStopPrice」の記述箇所の下に、変数「currentProfit」に値を代入する記述を追加します。

現在値から約定価格を引いた価格、すなわち

SymbolInfoDouble(symbol,SYMBOL_BID) – openPriceの計算結果を変数「currentProfit」に代入します。

93回の時点での発注条件は↓

if(trailStopPrice > currentStop)

というものでした。今回の記事の「ミニマムプロフィットとは?」セクションでも説明したように、この条件式だけだと、

現在設定されているストップロス価格と、算出したトレーリングストップ価格との比較

のみでトレーリングストップが発動するので、トレーリングストップの発動タイミングが早すぎます。

そこで以下のような条件式に書き換えます。↓

//ミニマムプロフィットの条件を追加
if(trailStopPrice > currentStop && currentProfit>=minProfit)

変数「currentProfit」には現在値から約定値をマイナスした値が格納されていますから、これが変数「minProfit」より大きい場合は、想定した相場の方向にプラスになっているという事です。

この条件式は

「指定したトレーリングストップ値が、現在のストップロス価格より大きく、かつ現在のポジション利益が指定利益(ミニマムプロフィット)より大きい」

と読み解く事ができます。

この条件式によりトレーリングストップのタイミングを柔軟に調整できるようになりました。

論理積条件については下記の記事をご参照ください↓

request.sl変数「trailStopPrice」の値を代入し、OrderSend関数引数MqlTradeRequest構造体MqlTradeResult構造体インスタンスrequest,resultをそれぞれ設定する所は93回と同じです。

続いてはポジションタイプが「売り」の場合です。

トレーリングストップの注文を出す(売りの場合)

ポジションタイプが売りだった場合の記述は以下のようになります。

else if(posType == POSITION_TYPE_SELL)
			{
				trailStopPrice = SymbolInfoDouble(symbol,SYMBOL_ASK) + trailStop;
				//ミニマムプロフィット価格を算出(追加箇所)
				currentProfit= openPrice -SymbolInfoDouble(symbol,SYMBOL_ASK);
				////ミニマムプロフィットの条件を追加
				if(trailStopPrice < currentStop && currentProfit>=minProfit)
				{	
					request.sl = trailStopPrice;
               OrderSend(request,result);
				}//if(trailStopPrice < currentStop && currentProfit>=minProfit)
				
			
			}//else if(posType == POSITION_TYPE_SELL)
		}//if(PositionSelectByTicket(pTicket) == true && TrailingStop > 0)
		
}//OnTick

売りの場合のトレーリングストップ価格はAsk+変数「trailStop」の値で求まります。ちょうど買いの場合と逆になります。

Askの価格はSymbolInfoDouble関数の第2引数定数値「SYMBOL_ASK」を記述することで取得出来ます。

SymbolInfoDouble(symbol,SYMBOL_ASK) + trailStopの計算結果を最終的なトレーリングストップ価格を格納する、double型変数「trailStopPrice」に格納します。

ここまでは前回93回と同じです。

すでに トレーリングストップの注文を出す(買いの場合)セクションで説明した記述ではありますが、ポジションタイプが売りの場合も変数「trailStopPrice」の記述箇所の下に、変数「currentProfit」の記述を追加します。

「買い」の場合だと、現在値から約定価格を引いた価格を変数「currentProfit」に代入していましたが、「売り」の場合、価格が下がるほど利益が伸びていくわけですから、計算式も

約定価格-現在値

と計算位置が逆になります。すなわち、

openPrice –SymbolInfoDouble(symbol,SYMBOL_ASK)の計算結果を価格を変数「currentProfit」に代入します。

93回の時点での発注条件は↓

if(trailStopPrice < currentStop)

というものでした。この条件文を以下のように変えます。

//ミニマムプロフィットの条件を追加
if(trailStopPrice < currentStop && currentProfit>=minProfit)

記述を追加する理由・理屈については、ミニマムプロフィットとは?セクションやトレーリングストップの注文を出す(買いの場合)セクションで説明した通りです。

request.sl変数「trailStopPrice」の値を代入し、OrderSend関数引数MqlTradeRequest構造体MqlTradeResult構造体インスタンスrequest,resultをそれぞれ設定する所も変更点はありません。

まとめ

今回は前回解説した、シンプルな形のトレーリングストップ記述にミニマムプロフィットとという概念を落とし込みました。

もう一度ミニマムプロフィットについて簡単に説明すると、ミニマムプロフィットとは、

トレーリングストップを発動させるタイミングを、約定価格から、相場が当初の想定通りに動き、一定の利益が出る段階まで遅らせる回路

になります。

今回の解説したコードの記述全体は以下のようになります↓

ポジション番号に関する適切な記述をしていないので、コンパイルエラーになります。

あくまで全体的な流れの参考程度にご覧ください。

//パラメータ
input int TrailingStop = 500;//トレイリンストップを設定する
input int MinimumProfit = 200;//ミニマムプロフィットを設定する
-----------------------------------------------------------

void OnTick()
{
if(PositionSelectByTicket(pTicket) == true && TrailingStop > 0)
	{
		request.action = TRADE_ACTION_SLTP;
		request.position = ポジション番号;
    long posType = PositionGetInteger(POSITION_TYPE);//ポジションタイプ
		double currentStop = PositionGetDouble(POSITION_SL);//ストップロス価格
		double currentLimit = PositionGetDouble(POSITION_TP);//テイクプロフィット価格

    double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);//ポジションの約定価格
	string symbol = PositionGetString(POSITION_SYMBOL);//取引銘柄
    double point = SymbolInfoDouble(symbol,SYMBOL_POINT);//ポイント
    double trailStop = TrailingStop* point;//トレーリングストップポイント
    double minProfit = MinimumProfit* point;//ミニマムプロフィットポイント(この変数を93回の記述に追加している)
   
   double trailStopPrice;//トレーリングストップ価格
   double currentProfit;//ミニマムプロフィット価格(この変数を93回の記述に追加している)
   if(posType == POSITION_TYPE_BUY)
			{   //トレーリングストップ価格を算出
         trailStopPrice = SymbolInfoDouble(symbol,SYMBOL_BID) - trailStop;
         //ミニマムプロフィット価格を算出(追加箇所)
         currentProfit= SymbolInfoDouble(symbol,SYMBOL_BID) - openPrice;
         
         //ミニマムプロフィットの条件を追加
         if(trailStopPrice > currentStop && currentProfit>=minProfit)
          {
           request.sl = trailStopPrice;//
           OrderSend(request,result);
          }//if(trailStopPrice > currentStop)
       }//if(posType == POSITION_TYPE_BUY)
  
   else if(posType == POSITION_TYPE_SELL)
			{
				trailStopPrice = SymbolInfoDouble(symbol,SYMBOL_ASK) + trailStop;
				//ミニマムプロフィット価格を算出(追加箇所)
				currentProfit= openPrice -SymbolInfoDouble(symbol,SYMBOL_ASK);
				//ミニマムプロフィットの条件を追加
				if(trailStopPrice < currentStop && currentProfit>=minProfit)
				{	
					request.sl = trailStopPrice;
               OrderSend(request,result);
				}//if(trailStopPrice < currentStop && currentProfit>=minProfit)
				
			
			}//else if(posType == POSITION_TYPE_SELL)
		}//if(PositionSelectByTicket(pTicket) == true && TrailingStop > 0)
		
}//OnTick

今回は以上とさせていただきます。

次回も、引き続き、トレーリングストップについて解説します。

今回解説したコードに追加する形で、「ステップ幅」という概念をトレーリングストップに落とし込んでいきます。

最後までお読みいただきありがとうございました!

※↓の記事でもトレーリングストップを実装している様子を解説しているので、よろしければ参考にしていただければと思います。

MQL5 EA講座 第93回「トレーリングストップについて」

MQL5 EA講座 第95回「トレーリングストップにおけるステップ幅について」

ください。

コメント

タイトルとURLをコピーしました