ランダムイメージ

ここでは、著書「新版 魔術師たちの心理学―トレードで生計を立てる秘訣と心構え」を参考にトム・バッソが行なったコイントストレードの実験のうち、下記の2つについてテスト用EAとして再現してみます。

・ランダムエントリー
・3倍のボラティリティ・トレーリングストップ

今回のEAコード

Dr.EADr.EA

今回のテスト用EAの全体コードがこちらじゃ。

extern double  Lots           = 0.1;
extern int     ATR_Period     = 14;
extern double  ATR_Multiple   = 3;

int OnInit()
{
   MathSrand(GetTickCount()); // 乱数のシード設定
   return(INIT_SUCCEEDED);
}

void OnTick()
{
   int ticket;
   double sl, ts;
   
   // 保有ポジションを確認 --------------------------------
   
   int pos_cnt = OrdersTotal();
   
   // ATR トレーリングストップ ----------------------------
   
   if (pos_cnt > 0)
   {
      double atr = iATR(NULL, 0, ATR_Period, 1);
      
      if (OrderSelect(0, SELECT_BY_POS) == false) return;
      sl = NormalizeDouble(OrderStopLoss(), Digits);
      
      if (OrderType() == OP_BUY)
      {
         ts = NormalizeDouble(Bid - atr * ATR_Multiple, Digits);
         
         if (sl == 0 || sl < ts)
            if (OrderModify(OrderTicket(), 0, ts, 0, 0, clrRed) == false)
               Print("OrderModify error.");
      }
      if (OrderType() == OP_SELL)
      {
         ts = NormalizeDouble(Ask + atr * ATR_Multiple, Digits);
         
         if (sl == 0 || sl > ts)
            if (OrderModify(OrderTicket(), 0, ts, 0, 0, clrRed) == false)
               Print("OrderModify error.");
      }
   }
   
   // エントリー-------------------------------------------
   
   if (pos_cnt == 0)
   {
      int sign = MathRand() % 1000; // 0 ~ 999
      
      if (sign == 0) ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 0, 0, 0, NULL, 0, 0, clrBlue);
      if (sign == 1) ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, 0, 0, 0, NULL, 0, 0, clrRed);
   }
}

テスト用EA【RandomEntry_ATRtrail_EA.mq4】をダウンロード

ランダムエントリー

乱数のシードを設定

OnInit()関数内で、乱数のシードを設定します。シード値には、GetTickCount()を使用して、次のようにします。

   MathSrand(GetTickCount()); // 乱数のシード設定

乱数によるシグナル判定とエントリー注文

今回は、このEAでのみポジションを保有するという前提で、ポジション有り無しをOrdersTotal()関数の値のみで判定します。
OnTick()関数内で、次のコードを追加して保有ポジションの有無を判断できるようにしておきます。

   int pos_cnt = OrdersTotal();

次のコードを追加して保有ポジション無しの場合の処理を追加していきます。

   if (pos_cnt == 0)
   {
   }

上記括弧内に、ランダム値(0 ~ 32,767)を返すMathRand()関数を使って、変数signが0~999の値になるように次のコードを追加します。

      int sign = MathRand() % 1000; // 0 ~ 999

その下に次のコードを追加して、変数signの値が0の場合は買い注文、1の場合は売り注文をするようにします。(Lotsはパラメーターとして追加しておきます。)

      if (sign == 0) ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 0, 0, 0, NULL, 0, 0, clrBlue);
      if (sign == 1) ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, 0, 0, 0, NULL, 0, 0, clrRed);

ATR3倍のトレーリングストップ

パラメーターを設置

ATRの期間と、ストップ幅をATRの何倍にするかのパラメータ―を追加します。

extern int     ATR_Period     = 14;
extern double  ATR_Multiple   = 3;

ATRの値によるトレーリングストップ

OnTick()関数内に、次のコードを追加してポジションを保有中の場合の処理を追加していきます。

   if (pos_cnt > 0)
   {
   }

上記コードの括弧内で、ATRの値を取得します。

      double atr = iATR(NULL, 0, ATR_Period, 1);

次に、保有ポジションを選択してSL値を取得します。保有ポジションが1つの場合のインデックスは0となります。(変数slとその後に出てくる変数tsは宣言しておきます。)

      if (OrderSelect(0, SELECT_BY_POS) == false) return;
      sl = NormalizeDouble(OrderStopLoss(), Digits);

買いポジション保有中のトレーリングストップ処理を次のようにします。

      if (OrderType() == OP_BUY)
      {
         ts = NormalizeDouble(Bid - atr * ATR_Multiple, Digits);
         
         if (sl == 0 || sl < ts)
            if (OrderModify(OrderTicket(), 0, ts, 0, 0, clrRed) == false)
               Print("OrderModify error.");
      }

売りポジション保有中のトレーリングストップ処理も同じ要領で追加します。

      if (OrderType() == OP_SELL)
      {
         ts = NormalizeDouble(Ask + atr * ATR_Multiple, Digits);
         
         if (sl == 0 || sl > ts)
            if (OrderModify(OrderTicket(), 0, ts, 0, 0, clrRed) == false)
               Print("OrderModify error.");
      }

感想

早速、バックテストをしてみたのですが、ATRの期間を14くらいにするとよさそうな感じでした。
また、取引機会を増やそうと1時間足で試してみましたが、ATRの3倍だとすぐにノイズにやられてしまうので、4.5倍あたりがよさそうな感じでした。
トレンドフォローのストップの目安になりそうですね!
では、今回はこのへんで。