MTFインジEA化02

ここでは、MTF機能付きのカスタムインジケーターのシグナルによって自動売買する自作EAの作り方を解説します。

MTF機能付きのiCustom()関数の使い方を復習したい人は前編をご覧ください。
前回記事【MTF機能付きのカスタムインジケーターをEAにする方法(前編)】へ

下記の機能を盛り込んだEAを作成していきます。

・シグナルが出た瞬間か次の始値かの取引タイミング選択
・インジケーターのシグナルによる決済のON/OFF

シグナルが出た瞬間にエントリーする設定の場合で、シグナルがダマシだった場合は、次のローソク足の始値で決済してノーポジション状態になるようにしていきます。

既存EAをカスタマイズする

今回は、過去の記事【MetaTrader4のEAを改良する方法】で作成したEAをカスタマイズして、目的のEAを作成していきます。

過去の記事【MetaTrader4のEAを改良する方法】へ

Dr.EADr.EA

念のため、カスタマイズ前のコードをお見せするぞい!

//+------------------------------------------------------------------+
//|                                             MA_Doten_EAv1.01.mq4 |
//+------------------------------------------------------------------+
#property copyright "Dr.EA Keiji"
#property link      "https://www.dr-ea.com/meta-blog/"
#property version   "1.01"
#property strict

// パラメーター
extern int     StopLoss    = 500;
extern int     TakeProfit  = 500;
extern double  Lots        = 0.1;
extern int     MagicNumber = 20191030;

extern int     MA_Period   = 20;
extern int     MA_Shift    = 0;
extern ENUM_MA_METHOD MA_Method = MODE_SMA;
extern ENUM_APPLIED_PRICE MA_Applied = PRICE_CLOSE;

extern bool    ExitByMA    = false;

// グローバル変数
int entry_bar; // エントリーした時のバーの数

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   // 使い回ししそうな変数を宣言
   int i, ticket;
   double sl, tp;
   
   
   // 保有ポジションを確認 -------------------------------
   
   int ticket_buy = 0;  // 買いポジションの注文番号
   double lots_buy = 0; // 買いポジションのロット数
   int ticket_sell = 0; // 売りポジションの注文番号
   double lots_sell = 0;// 売りポジションのロット数
   
   for (i=0; i<OrdersTotal(); i++)
   {
      // ポジション選択
      if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) return;
      // 通貨ペアまたはマジックナンバーが違う場合はスキップ
      if (OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber) continue;
      
      // 保有ポジションの注文番号とロット数を変数に代入
      if (OrderType() == OP_BUY)
      {
         ticket_buy = OrderTicket();
         lots_buy = OrderLots();
      }
      if (OrderType() == OP_SELL)
      {
         ticket_sell = OrderTicket();
         lots_sell = OrderLots();
      }
   }
   
   
   // 取引シグナルを判定 ---------------------------------
   
   int entry_sign = 0;  // エントリー用シグナル
   int exit_sign = 0;   // 決済用シグナル
   
   // MAの値を取得
   double ma_1 = iMA(NULL, 0, MA_Period, MA_Shift, MA_Method, MA_Applied, 1);
   double ma_2 = iMA(NULL, 0, MA_Period, MA_Shift, MA_Method, MA_Applied, 2);
   
   // 条件を満たしたらシグナル発生 (1: 買いシグナル, -1: 売りシグナル)
   if (Close[2] <= ma_2 && Close[1] > ma_1)
   {
      if (ma_2 < ma_1) entry_sign = 1;       // MAが上昇ならエントリー許可
      if (ExitByMA == true) exit_sign = 1;   // ExitByMAがtrueなら決済許可
   }
   if (Close[2] >= ma_2 && Close[1] < ma_1)
   {
      if (ma_2 > ma_1) entry_sign = -1;      // MAが下降ならエントリー許可
      if (ExitByMA == true) exit_sign = -1;  // ExitByMAがtrueなら決済許可
   }
   
   
   // 決済 -----------------------------------------------
   
   // 買いポジション決済
   if (ticket_buy > 0 && exit_sign == -1)
   {
      if (OrderClose(ticket_buy, lots_buy, Bid, 0, clrYellow) == true)
         ticket_buy = 0;
      else
         Print("OrderClose error.");
   }
   
   // 売りポジション決済
   if (ticket_sell > 0 && exit_sign == 1)
   {
      if (OrderClose(ticket_sell, lots_sell, Ask, 0, clrYellow) == true)
         ticket_sell = 0;
      else
         Print("OrderClose error.");
   }
   
   
   // エントリー-------------------------------------------
   
   if (ticket_buy == 0 && ticket_sell == 0 && entry_bar != Bars)
   {
      // 買いエントリー
      if (entry_sign == 1)
      {
         sl = 0;
         tp = 0;
         if (StopLoss > 0) sl = Ask - StopLoss * Point;
         if (TakeProfit > 0) tp = Ask + TakeProfit * Point;
            
         ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 0, sl, tp, NULL, MagicNumber, 0, clrBlue);
         if(ticket > 0)
            entry_bar = Bars;
         else
            Print("OrderSend error.");
      }
      
      // 売りエントリー
      if (entry_sign == -1)
      {
         sl = 0;
         tp = 0;
         if (StopLoss > 0) sl = Bid + StopLoss * Point;
         if (TakeProfit > 0) tp = Bid - TakeProfit * Point;
         
         ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, 0, sl, tp, NULL, MagicNumber, 0, clrRed);
         if(ticket > 0)
            entry_bar = Bars;
         else
            Print("OrderSend error.");
      }
   }
  }

カスタマイズ前のEAファイル【MA_Doten_EAv1.01.mq4】をダウンロード

Dr.EADr.EA

そして今回完成したEAのコードはこちら。どーん!

にゃんたにゃんた

あわわ


// パラメーター
extern int     StopLoss       = 500;
extern int     TakeProfit     = 500;
extern double  Lots           = 0.1;
extern int     MagicNumber    = 20191030;

extern string  IndicatorName  = "BBands_Stops_mtf";
extern int     TimeFrame      = 0;
extern int     Length         = 13;
extern double  Deviation      = 1.62;

extern int     SignalShift    = 1;
extern bool    ExitBySignal   = false;

// グローバル変数
int entry_bar; // エントリーした時のバーの数

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   // 使い回ししそうな変数を宣言
   int i, ticket;
   double sl, tp;
   
   
   // 保有ポジションを確認 -------------------------------
   
   int ticket_buy = 0;  // 買いポジションの注文番号
   double lots_buy = 0; // 買いポジションのロット数
   datetime open_time_buy = 0; // 買いポジ取得時間
   int ticket_sell = 0; // 売りポジションの注文番号
   double lots_sell = 0;// 売りポジションのロット数
   datetime open_time_sell = 0; // 売りポジ取得時間
   
   for (i=0; i 0)
   {
      // シグナルによる決済
      if (ExitBySignal == true && entry_sign == -1) exit_ok = true;
      
      // ダマシ後の決済
      if (SignalShift == 0 && iBarShift(NULL, TimeFrame, open_time_buy) == 1)
      {
         up_sign = iCustom(NULL, TimeFrame, IndicatorName, 0, Length, Deviation, 2, 1);
         if (up_sign == -1) exit_ok = true;
      }
      
      if (exit_ok == true)
      {
         if (OrderClose(ticket_buy, lots_buy, Bid, 0, clrYellow) == true)
            ticket_buy = 0;
         else
            Print("OrderClose error.");
      }
   }
   
   // 売りポジション決済
   if (ticket_sell > 0)
   {
      if (ExitBySignal == true && entry_sign == 1) exit_ok = true;
      
      if (SignalShift == 0 && iBarShift(NULL, TimeFrame, open_time_sell) == 1)
      {
         dn_sign = iCustom(NULL, TimeFrame, IndicatorName, 0, Length, Deviation, 3, 1);
         if (dn_sign == -1) exit_ok = true;
      }
      
      if (exit_ok == true)
      {
         if (OrderClose(ticket_sell, lots_sell, Ask, 0, clrYellow) == true)
            ticket_sell = 0;
         else
            Print("OrderClose error.");
      }
   }
   
   
   // エントリー-------------------------------------------
   
   if (ticket_buy == 0 && ticket_sell == 0 && entry_bar != Bars)
   {
      // 買いエントリー
      if (entry_sign == 1)
      {
         sl = 0;
         tp = 0;
         if (StopLoss > 0) sl = Ask - StopLoss * Point;
         if (TakeProfit > 0) tp = Ask + TakeProfit * Point;
            
         ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 0, sl, tp, NULL, MagicNumber, 0, clrBlue);
         if(ticket > 0)
            entry_bar = Bars;
         else
            Print("OrderSend error.");
      }
      
      // 売りエントリー
      if (entry_sign == -1)
      {
         sl = 0;
         tp = 0;
         if (StopLoss > 0) sl = Bid + StopLoss * Point;
         if (TakeProfit > 0) tp = Bid - TakeProfit * Point;
         
         ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, 0, sl, tp, NULL, MagicNumber, 0, clrRed);
         if(ticket > 0)
            entry_bar = Bars;
         else
            Print("OrderSend error.");
      }
   }
  }

今回完成EAファイル【BBands_Stops_EA_Ver1.01.mq4】をダウンロード

パラメーターを差し替える

基となるEAは、MAによるシグナルで取引するEAなので使用するMAを設定するパラメーターがあります。それを今回必要なパラメーターに差し替えます。

MA_Period~ExitByMAのパラメーター部分を次のコードに変更します。

extern string  IndicatorName  = "BBands_Stops_mtf";
extern int     TimeFrame      = 0;
extern int     Length         = 13;
extern double  Deviation      = 1.62;

extern int     SignalShift    = 1;
extern bool    ExitBySignal   = false;

使用するカスタムインジケーター名とそのパラメーターと、下記の機能を搭載するためのパラメーターです。

・シグナルが出た瞬間か次の始値かの取引タイミング選択
・インジケーターのシグナルによる決済のON/OFF

SignalShiftが0の場合は、シグナルが出た瞬間にエントリー注文するようにします。SignalShiftが1の場合は、次の始値でエントリー注文するようにします。

シグナル判定を差し替える

今回のシグナル判定は、次のようにエントリー用シグナルのみを先に判定するようにします。

   int entry_sign = 0;  // エントリー用シグナル
   
   // インジケーターのシグナルの値を取得
   double up_sign = iCustom(NULL, TimeFrame, IndicatorName, 0, Length, Deviation, 2, SignalShift);
   double dn_sign = iCustom(NULL, TimeFrame, IndicatorName, 0, Length, Deviation, 3, SignalShift);
   
   // 条件を満たしたらシグナル発生 (1: 買いシグナル, -1: 売りシグナル)
   if (up_sign != -1) entry_sign = 1;
   if (dn_sign != -1) entry_sign = -1;

決済判定と決済処理

決済用シグナルを次のように真偽型に変更しておきます。

   bool exit_ok = false;   // 決済用シグナル

決済条件を満たした場合に、変数exit_okをtrueにして、決済処理を実行するように変更します。

買いポジションの決済判定と決済処理

datetime変数「open_time_buy」は予め宣言しておいて、保有ポジション確認で、買いポジションをオープンした時間を格納しておきます。
買いポジションの決済判定と決済処理を次のようにします。

   if (ticket_buy > 0)
   {
      // シグナルによる決済
      if (ExitBySignal == true && entry_sign == -1) exit_ok = true;
      
      // ダマシ後の決済
      if (SignalShift == 0 && iBarShift(NULL, TimeFrame, open_time_buy) == 1)
      {
         up_sign = iCustom(NULL, TimeFrame, IndicatorName, 0, Length, Deviation, 2, 1);
         if (up_sign == -1) exit_ok = true;
      }
      
      if (exit_ok == true)
      {
         if (OrderClose(ticket_buy, lots_buy, Bid, 0, clrYellow) == true)
            ticket_buy = 0;
         else
            Print("OrderClose error.");
      }
   }

ダマシ後の決済条件では、TimeFrameで指定した時間足の1つ前のローソク足でエントリーていて、そのローソク足にシグナルがない場合に一旦決済するようにしています。

売りポジションの決済判定と決済処理

売りポジションの決済についても、買いポジション決済と同じ要領でコードにします。

   if (ticket_sell > 0)
   {
      if (ExitBySignal == true && entry_sign == 1) exit_ok = true;
      
      if (SignalShift == 0 && iBarShift(NULL, TimeFrame, open_time_sell) == 1)
      {
         dn_sign = iCustom(NULL, TimeFrame, IndicatorName, 0, Length, Deviation, 3, 1);
         if (dn_sign == -1) exit_ok = true;
      }
      
      if (exit_ok == true)
      {
         if (OrderClose(ticket_sell, lots_sell, Ask, 0, clrYellow) == true)
            ticket_sell = 0;
         else
            Print("OrderClose error.");
      }
   }

まとめ

MTF機能付きのカスタムインジケーターをiCustom()関数でEA化する方法を解説しました。
ダマシの場合の対処は他にいろんな方法がありそうですね。
いろいろと試してみてください。