MQL5でEA開発 66 高安でトレーリングストップを実行する関数

高安でトレーリングストップを実行する関数

高安でトレーリングストップを実行する関数を作ります。

買いポジションなら直近安値に、売りポジションなら直近高値+スプレッドにストップを置きます。

名前はTrailingStopHL関数とします。

戻り値はありません。

引数は

  • 第1引数:足の種類。ENUM_TIMEFRAMES型

  • 第2引数:計算期間。int型

  • 第3引数:シフト。int型

  • 第4引数:スプレッド(価格単位)。double型

  • 第5引数:注文間隔(ミリ秒)。int型

  • 第6引数:マジックナンバー。int型

とします。

関数の作成にあたって、以下の定義済み変数、関数、メソッドを使用しました。

  • _Point

  • Sleep関数

  • SymbolInfoDouble関数

  • SymbolInfoInteger関数

  • PositionsTotal関数

  • PositionGetSymbol関数

  • PositionGetDouble関数

  • PositionGetInteger関数

  • PositionModifyメソッド

  • DC関数

自作関数のDC関数も使用します。

関数のコード

void TrailingStopHL(ENUM_TIMEFRAMES timeframe, int period, int shift, double spread, int order_interval, int magic)
  {
/*
   timeframe:足の種類
   period:計算期間
   shift:シフト
   spread:スプレッド(価格単位)
   order_interval:注文間隔(ミリ秒)
   magic:マジックナンバー
*/
   double new_sl=0.0;  // 新しいストップ
   double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);  // ASK
   double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID);  // BID
   long stops_level=SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL);  // ストップレベル
   int positions_total=PositionsTotal();  // ポジション数
//--- リスト内番号の大きい順、つまりポジションの新しい順に検索し、新しいもののみ処理する
   for(int i=positions_total-1; i>=0; i--)
     {
      string position_symbol=PositionGetSymbol(i);  // ポジションの銘柄
      long position_magic=PositionGetInteger(POSITION_MAGIC);  // ポジションのマジックナンバー
      long position_type=PositionGetInteger(POSITION_TYPE);  // ポジションのタイプ
      long position_ticket=PositionGetInteger(POSITION_TICKET);  // ポジションのチケット番号
      double position_sl=PositionGetDouble(POSITION_SL);  // ポジションのストップ
      double position_tp=PositionGetDouble(POSITION_TP);  // ポジションのリミット
      if(position_symbol==_Symbol && position_magic==magic)
        {
         //--- 買いポジションの場合
         if(position_type==POSITION_TYPE_BUY)
           {
            new_sl=DC(_Symbol,timeframe,period,2,shift)-_Point;
            if(new_sl>=position_sl+_Point && new_sl<=bid-stops_level*_Point)  // 前の条件は1ポイント加えないと同値になることがある
              {
               ExtTrade.PositionModify(position_ticket,new_sl,position_tp);
               Sleep(order_interval);  // 短時間に注文を繰り返すことを避けるため、一定時間スリープする
               return;
              }
           }
         //--- 売りポジションの場合
         if(position_type==POSITION_TYPE_SELL)
           {
            new_sl=DC(_Symbol,timeframe,period,1,shift)+spread+_Point;
            if((new_sl<=position_sl-_Point || position_sl==0.0) && new_sl>=ask+stops_level*_Point)  // 前の条件は1ポイント減じないと同値になることがある
              {
               ExtTrade.PositionModify(position_ticket,new_sl,position_tp);
               Sleep(order_interval);  // 短時間に注文を繰り返すことを避けるため、一定時間スリープする
               return;
              }
           }
        }
     }
  }

この関数では直近高安をサポート、レジスタンスとしてストップを移動していますが、これを雛型にして移動平均線、ボリンジャーバンド、一目均衡表などでトレーリングストップを実行する関数を作ることもできるでしょう。

サンプルコード

#include <Trade\Trade.mqh>

CTrade ExtTrade;

double DC(string symbol, ENUM_TIMEFRAMES timeframe, int period, int mode, int shift)
/*
   symbol:銘柄
   timeframe:足の種類
   period:計算期間
   mode:モード
   shift:シフト
*/
  {
   double res=0.0; // 戻り値
/*
   mode
   0:最高値と最安値の中間値
   1:最高値
   2:最安値
*/
//--- 最高値と最安値の中間値
   if(mode==0)
     {
      int highest=iHighest(symbol,timeframe,MODE_HIGH,period,shift);  // 最高値の位置
      int lowest=iLowest(symbol,timeframe,MODE_LOW,period,shift);  // 最安値の位置
      double upper=iHigh(symbol,timeframe,highest);  // 最高値
      double lower=iLow(symbol,timeframe,lowest);  // 最安値
      res=(upper+lower)/2.0;  // 最高値と最安値の中間値
     }
//--- 最高値
   if(mode==1)
     {
      int highest=iHighest(symbol,timeframe,MODE_HIGH,period,shift);  // 最高値の位置
      res=iHigh(symbol,timeframe,highest);  // 最高値
     }
//--- 最安値
   if(mode==2)
     {
      int lowest=iLowest(symbol,timeframe,MODE_LOW,period,shift);  // 最安値の位置
      res=iLow(symbol,timeframe,lowest);  // 最安値
     }
   return(res);
  }
void TrailingStopHL(ENUM_TIMEFRAMES timeframe, int period, int shift, double spread, int order_interval, int magic)
  {
/*
   timeframe:足の種類
   period:計算期間
   shift:シフト
   spread:スプレッド(価格単位)
   order_interval:注文間隔(ミリ秒)
   magic:マジックナンバー
*/
   double new_sl=0.0;  // 新しいストップ
   double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);  // ASK
   double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID);  // BID
   long stops_level=SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL);  // ストップレベル
   int positions_total=PositionsTotal();  // ポジション数
//--- リスト内番号の大きい順、つまりポジションの新しい順に検索し、新しいもののみ処理する
   for(int i=positions_total-1; i>=0; i--)
     {
      string position_symbol=PositionGetSymbol(i);  // ポジションの銘柄
      long position_magic=PositionGetInteger(POSITION_MAGIC);  // ポジションのマジックナンバー
      long position_type=PositionGetInteger(POSITION_TYPE);  // ポジションのタイプ
      long position_ticket=PositionGetInteger(POSITION_TICKET);  // ポジションのチケット番号
      double position_sl=PositionGetDouble(POSITION_SL);  // ポジションのストップ
      double position_tp=PositionGetDouble(POSITION_TP);  // ポジションのリミット
      if(position_symbol==_Symbol && position_magic==magic)
        {
         //--- 買いポジションの場合
         if(position_type==POSITION_TYPE_BUY)
           {
            new_sl=DC(_Symbol,timeframe,period,2,shift)-_Point;
            if(new_sl>=position_sl+_Point && new_sl<=bid-stops_level*_Point)  // 前の条件は1ポイント加えないと同値になることがある
              {
               ExtTrade.PositionModify(position_ticket,new_sl,position_tp);
               Sleep(order_interval);  // 短時間に注文を繰り返すことを避けるため、一定時間スリープする
               return;
              }
           }
         //--- 売りポジションの場合
         if(position_type==POSITION_TYPE_SELL)
           {
            new_sl=DC(_Symbol,timeframe,period,1,shift)+spread+_Point;
            if((new_sl<=position_sl-_Point || position_sl==0.0) && new_sl>=ask+stops_level*_Point)  // 前の条件は1ポイント減じないと同値になることがある
              {
               ExtTrade.PositionModify(position_ticket,new_sl,position_tp);
               Sleep(order_interval);  // 短時間に注文を繰り返すことを避けるため、一定時間スリープする
               return;
              }
           }
        }
     }
  }
void OnTick()
  {
   TrailingStopHL(PERIOD_D1,10,0,0.006,60000,20248);
  }

自作関数のDC関数も使用しているので、DC関数の定義もコードに書き込みます。

実行

まだポジションがないので、このコードを実行しても何も起きません。

仮に150.000円で売ったポジションがあり、マジックナンバーが20248だったとします。

そして、152.000円にストップが置いてあるとします。

もし、当日を含む直近10日高値が151.993円になったとします。

売りポジションの決済はASKで行われるので、スプレッドを加えます。

想定するスプレッド0.006円を足すと151.999円です。

すると、152.000円より低いのでストップは151.999円に移動します。

いいなと思ったら応援しよう!