18.外部入力パラメータを設定する

EAを稼働させる際に、そのEAに使わせるデータを外部入力できるようにしておくことで、EAの挙動に幅を持たせることができます。

外部入力パラメータとして用意されるものとしては、EAのマジックナンバー、ロット数や許容スリッページの値、ストップロスやテイクプロフィットの値幅などが挙げられます。

前回までで作成したsimple.mq4のソースコードに外部入力パラメータ用の記述を追加すると以下のようになります。
(追加記述をハイライトしています。)

#property copyright ""
#property link      ""
#property version   "1.00"
#property strict

input double Lots = 0.1;   //ロット
input int StopLoss = 200;  //ストップロス(ポイント指定)

int OnInit() {
   return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason) {
}
void OnTick() {
   if(OrdersTotal() == 0) {
      //ポジションを持っていない時は、ここに処理が入る
      double sma200 = iMA(Symbol(), Period(), 200, 0, MODE_SMA, PRICE_CLOSE, 0); //現在時点での200SMA
      double sma200_prev = iMA(Symbol(), Period(), 200, 0, MODE_SMA, PRICE_CLOSE, 1);  //1本前のバー時点での200SMA
      double sma20 = iMA(Symbol(), Period(), 20, 0, MODE_SMA, PRICE_CLOSE, 0);   //現在時点での20SMA
      double sma20_prev = iMA(Symbol(), Period(), 20, 0, MODE_SMA, PRICE_CLOSE, 1); //1本前のバー時点での20SMA
      double bb_upper = iBands(Symbol(), Period(), 20, 2.0, 0, PRICE_CLOSE, MODE_UPPER, 0);  //ボリンジャーバンド+2σ
      double bb_lower = iBands(Symbol(), Period(), 20, 2.0, 0, PRICE_CLOSE, MODE_LOWER, 0);  //ボリンジャーバンド-2σ
      if(sma200 > sma200_prev) {
         //200SMAが上昇なら、ここに処理が入る
         if(sma20 > sma200) {
            //20SMAが200SMAより上に位置するなら、ここに処理が入る
            if(Open[1] < sma20_prev && Close[1] >= sma20_prev && Bid > sma20) {
               //バーが20SMAを上抜けたら、ここに処理が入る
               if(bb_lower > sma200) {
                  //200SMAがボリンジャーバンドの外側(下)にある場合のみエントリー
                  OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, Bid-200*Point(), 0, NULL, 12345);   //買い注文・マジックナンバー12345
               }
            }
         }
      } else if(sma200 < sma200_prev) {
         //200SMAが下降なら、ここに処理が入る
         if(sma20 < sma200) {
            //20SMAが200SMAより下に位置するなら、ここに処理が入る
            if(Open[1] > sma20_prev && Close[1] <= sma20_prev && Bid < sma20) {
               //バーが20SMAを下抜けたら、ここに処理が入る
               if(bb_upper < sma200) {
                  //200SMAがボリンジャーバンドの外側(上)にある場合のみエントリー
                  OrderSend(Symbol(), OP_SELL, 0.1, Bid, 3, Bid+200*Point(), 0, NULL, 12345);   //売り注文・マジックナンバー12345
               }
            }
         }
      } else {
         //200SMAが水平移動しているなら、ここに処理が入る
      }
   } else {
      //ポジションを持っている時は、ここに処理が入る
      double sma200 = iMA(Symbol(), Period(), 200, 0, MODE_SMA, PRICE_CLOSE, 0); //現在時点での200SMA
      for(int i=OrdersTotal()-1; i>=0; i--) {
         if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
            if(OrderMagicNumber() == 12345) {
               //このEAによるポジションがあればここに処理が入る
               if(OrderType() == OP_BUY && Bid <= sma200) {
                  //200SMAタッチで決済
                  OrderClose(OrderTicket(), OrderLots(), Bid, 3);
               } else if(OrderType() == OP_SELL && Bid >= sma200) {
                  //200SMAタッチで決済
                  OrderClose(OrderTicket(), OrderLots(), Ask, 3);
               }
            }
         }
      }
   }
}

ロットとストップロスを指定できるように設定しました。
通常の変数定義の先頭に、”input”と書くだけです。後ろに何のデータなのかを表すコメントを書いておきます。

input データ型 定数名 = 初期値; //何のデータかコメント

プログラム内で使用できるようになりますが、変更することはできないので定数と同じ扱いです。

inputは、EAの上の方に記述するのが一般的です。
また、OnInitやOnTickのブロックの外側に宣言されていますので、EAのプログラム全体から使用可能です(グローバルスコープ)。

これをコンパイルして、ストラテジーテスターから「エキスパート設定」を開きます。

記述追加前は無かった「パラメーターの入力」タブが表示され、ロットとストップロスをここから入力できるようになりました。
入力された値は、そのまま上記で宣言された定数に代入されます。

プログラム内の然るべき箇所をこの定数に書き換えます(OrderSendのロットとストップロス部分)。

#property copyright ""
#property link      ""
#property version   "1.00"
#property strict

input double Lots = 0.1;   //ロット
input int StopLoss = 200;  //ストップロス(ポイント指定)

int OnInit() {
   return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason) {
}
void OnTick() {
   if(OrdersTotal() == 0) {
      //ポジションを持っていない時は、ここに処理が入る
      double sma200 = iMA(Symbol(), Period(), 200, 0, MODE_SMA, PRICE_CLOSE, 0); //現在時点での200SMA
      double sma200_prev = iMA(Symbol(), Period(), 200, 0, MODE_SMA, PRICE_CLOSE, 1);  //1本前のバー時点での200SMA
      double sma20 = iMA(Symbol(), Period(), 20, 0, MODE_SMA, PRICE_CLOSE, 0);   //現在時点での20SMA
      double sma20_prev = iMA(Symbol(), Period(), 20, 0, MODE_SMA, PRICE_CLOSE, 1); //1本前のバー時点での20SMA
      double bb_upper = iBands(Symbol(), Period(), 20, 2.0, 0, PRICE_CLOSE, MODE_UPPER, 0);  //ボリンジャーバンド+2σ
      double bb_lower = iBands(Symbol(), Period(), 20, 2.0, 0, PRICE_CLOSE, MODE_LOWER, 0);  //ボリンジャーバンド-2σ
      if(sma200 > sma200_prev) {
         //200SMAが上昇なら、ここに処理が入る
         if(sma20 > sma200) {
            //20SMAが200SMAより上に位置するなら、ここに処理が入る
            if(Open[1] < sma20_prev && Close[1] >= sma20_prev && Bid > sma20) {
               //バーが20SMAを上抜けたら、ここに処理が入る
               if(bb_lower > sma200) {
                  //200SMAがボリンジャーバンドの外側(下)にある場合のみエントリー
                  OrderSend(Symbol(), OP_BUY, Lots, Ask, 3, Bid-StopLoss*Point(), 0, NULL, 12345);   //買い注文・マジックナンバー12345
               }
            }
         }
      } else if(sma200 < sma200_prev) {
         //200SMAが下降なら、ここに処理が入る
         if(sma20 < sma200) {
            //20SMAが200SMAより下に位置するなら、ここに処理が入る
            if(Open[1] > sma20_prev && Close[1] <= sma20_prev && Bid < sma20) {
               //バーが20SMAを下抜けたら、ここに処理が入る
               if(bb_upper < sma200) {
                  //200SMAがボリンジャーバンドの外側(上)にある場合のみエントリー
                  OrderSend(Symbol(), OP_SELL, Lots, Bid, 3, Bid+StopLoss*Point(), 0, NULL, 12345);   //売り注文・マジックナンバー12345
               }
            }
         }
      } else {
         //200SMAが水平移動しているなら、ここに処理が入る
      }
   } else {
      //ポジションを持っている時は、ここに処理が入る
      double sma200 = iMA(Symbol(), Period(), 200, 0, MODE_SMA, PRICE_CLOSE, 0); //現在時点での200SMA
      for(int i=OrdersTotal()-1; i>=0; i--) {
         if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
            if(OrderMagicNumber() == 12345) {
               //このEAによるポジションがあればここに処理が入る
               if(OrderType() == OP_BUY && Bid <= sma200) {
                  //200SMAタッチで決済
                  OrderClose(OrderTicket(), OrderLots(), Bid, 3);
               } else if(OrderType() == OP_SELL && Bid >= sma200) {
                  //200SMAタッチで決済
                  OrderClose(OrderTicket(), OrderLots(), Ask, 3);
               }
            }
         }
      }
   }
}

外部入力ができるようになると、MAの期間やボリンジャーバンドの偏差など具体的な値をソースコードから取り除くことができます。
もっと言えば、SMAを使うかEMAを使うか、どういったときに売るのか買うのか、あらゆるものを全て外部入力に任せることも可能になりますが、普通のEAであれば、核となるロジック部分は変更できないように設定しましょう。

次回は、この外部入力パラメータを使った最適化について解説します。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

コメントする