FX自動売買基礎と応用

朝スキャEAにトレーリングストップを実装するカスタマイズ【コピペで使用可能】


前回の記事では、単純な時間制限をかけた逆張りのロジックに対して、最大保有ポジション数を増やすとどのような影響が出るのかを実験しました。
今回の記事では、「最大保有ポジション数」ではなく「トレーリングストップ」を実装することで、どのような結果になるのかを確認します。

トレーリングストップのメリットとデメリット

まずは、トレーリングストップのメリットとデメリットについてまとめます。

<メリット>

メリットはリスクを抑えながら利益幅を伸ばせる点です。
トレーリングストップが行われた時点で損切り地点が引き上げられるわけなので、単純な損切り・利確による決済よりも、利益を獲得できるチャンスが増えます。

<デメリット>

デメリットは少しの利益が発生した時点で決済をしてしまい、せっかく取れたかもしれない利益を逃してしまう可能性がある点です。
この微益決済を防ぐには、トレーリングストップの幅を綿密に調整する必要があります。
トレーリングストップの幅設定を誤ると「少し反発しただけですぐに決済されてしまう」「そもそもトレーリングストップ自体が行われない」といったことが起こり得ます。

    トレーリングストップの種類

    トレーリングストップと一口にいっても、その実装方法はいくつか存在します。
    例えば「一定の利益幅が出たら損切り地点を切り上げる」「利益が少しでも発生したら損切り地点を切り上げる」「相場の勢いによって損切り幅を変更する」といった方法です。
    トレーリングストップはEAのロジックに合わせて適切なロジックを設定することで、利益を伸ばす強力な武器です。

仕様

まずは前回作成したEAの仕様をまとめます。

・エントリー

時間が日本時間早朝かつRSIが売られすぎラインを下回ったら、買いエントリー
時間が日本時間早朝かつRSIが買われすぎラインを上回ったら、売りエントリー

・決済

利確価格と損切り価格による決済

・その他

著作権を「OANDA」に設定
スリッページ、スプレッドによってエントリーを制限する
ポジションは同時に1つのみ保有するようにする
マジックナンバーとロット数を変更できるようにする

以上です。
今回はトレーリングストップによって損切りを制御するので、決済ロジックの「損切り価格による決済」を「トレーリングストップによる損切り決済」に変更します。

EAを作成する

プログラムは前回の「5.朝スキャのEAを作ってみよう」をもとに作成していくので、前回までの内容は割愛し、今回追加する機能のみ紹介します。

フィールド


input int                   MAGICMA = 23498721;                       // マジックナンバー
input double                Lots =0.01;                                  // 1ロット十万通貨単位
input int                   Slippage = 4;                                 // エントリー見送りスリッページ
input double                MaxSpread = 5;                              // エントリー見送りスプレッド
input double                TakeProfit = 30.0;                           // 利益確定幅(pips)
input int                   RSIPeriod=6;                                // 期間
input   ENUM_APPLIED_PRICE  RSIAppliedPrice = PRICE_CLOSE;      // 適用価格
input int                   UpLine = 85;                                // 上の線
input int                   DownLine = 25;                              // 下の線
input int                   TradeTime = 0;                              // トレードを行う時間
input int                   TrailWidth = 10;                              // トレール幅(pips)

double dSpread;

前回のプログラムの「損切確定幅(pips)」を削除し、新たに「トレール幅(pips)」というパラメータを追加します。

OnTick関数


void OnTick()
{
   dSpread = (Ask - Bid) / (Point * 10);
   if(CalculateCurrentOrders()==0 && dSpread < MaxSpread) CheckForOpen(); 前回まで
   TrailingStop(); //今回

}

OnTick関数です。
今回は分かりやすいTrailingStopという関数を用意し、OnTick関数内から呼び出すだけでトレーリングストップが実行されるようにしました。

CheckForOpen関数


void CheckForOpen()
{
   int res;
   double RSI = iRSI(Symbol(), 0, RSIPeriod, RSIAppliedPrice, 1);
   if(TradeTime == TimeHour(Time[1]))
   {
      if(RSI < DownLine)
      {
         res=OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, Bid - TrailWidth * Point * 10, Ask + TakeProfit * Point * 10,"", MAGICMA, 0, Red);
      }
      if(RSI > UpLine)
      {
         res=OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, Ask + TrailWidth * Point * 10,  Bid - TakeProfit * Point * 10, "", MAGICMA, 0, Blue);
      }
   }
}

OrderSend関数の損切り価格部分で、パラメータTrailWidthを使用するように変更しました。
こうすることで、ポジションを持った時点での損切り幅がTrailWidthの値です。

TrailingStop関数


for (int i = OrdersTotal() - 1; i >= 0; i--){
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;     
      if (OrderType() == OP_BUY){
         if ((Bid - OrderStopLoss()) / (Point * 10) > TrailWidth * 2){         //①
            int om = OrderModify(OrderTicket(),                          //②
OrderOpenPrice(), 
OrderStopLoss() + TrailWidth * (Point * 10), 
OrderTakeProfit(), 
OrderExpiration());
         }
      }
      if (OrderType() == OP_SELL){
         if ((OrderStopLoss() - Ask) / (Point * 10) > TrailWidth * 2){         //①
            int om = OrderModify(OrderTicket(),                          //②
OrderOpenPrice(), 
OrderStopLoss() - TrailWidth * (Point * 10), 
OrderTakeProfit(), 
OrderExpiration());
         }
      }
   }

行っていることは単純で、保有しているポジションに対して「①トレーリングストップの条件を満たしているかどうかチェックする」「②トレーリングストップの条件を満たしていればOrderModify関数を用いて損切りポイントを引き上げる」の2つ処理です。
(上記プログラムのコメントアウト部分) では1つずつ確認していきましょう。

①トレーリングストップの条件を満たしているかどうかチェックする


if ((Bid - OrderStopLoss()) / (Point * 10) > TrailWidth * 2){

買いポジションの例です。
左辺は現在の価格と損切り価格の幅をpipsで求めており、その値がパラメータTrailWidthの2倍の値よりも大きい値かどうかを判定しています。ここではTrailWidth を2倍することがポイントです。
左辺は「現在の価格とエントリー価格の幅」ではなく「現在の価格と損切り価格の幅」なので、2倍する必要があります。

② OrderModify関数を用いて損切りポイントを引き上げる


int om = OrderModify(OrderTicket(),                     
OrderOpenPrice(), 
OrderStopLoss() - TrailWidth * (Point * 10), 
OrderTakeProfit(), 
OrderExpiration());

第三引数は損切り価格を指定する引数です。
トレーリングストップの条件を満たしていた場合、パラメータTrailWidthの値だけ損切りポイントを引き上げます。

バックテスト

今回作成したトレーリングストップのEAと、前回作成した単ポジ型のEAのバックテスト結果を比較してみましょう。
条件は以下の通りです。

  • 通貨ペア:GBPUSD
  • 時間足:5分足
  • 期間:2018年1月1日~2023年1月1日の5年間
  • スプレッド:15固定

・単ポジ型

単ポジ型

・トレーリングストップのEA

トレーリングストップのEA

「取引回数」が511回から714回に上昇しました。
トレーリングストップによって損切り地点が引き上げられ、単純な損切りロジックよりも早く決済されたことが原因です。

また、グラフを見ると分かるように、前者はジグザグな形ですがトレーリングストップの方は滑らかです。
このようなグラフの形になることはトレーリングストップの1つの特徴です。

「勝率」を確認すると、35.29%と大きく下がっていることが分かります。
これはトレーリングストップによって損切りが早まり、逆に利益はしっかりと獲得している証拠です。
勝率に関してはパラメータの最適化を行うことで上昇させることも十分可能です。

注意点

今回のバックテストはスプレッドを固定で行っています。
日本時間早朝の相場が緩やかになる時間帯は、スプレッドが広がりやすいという特徴があります。
実運用を行うにはスプレッド制限をかけるなど、十分にスプレッドに十分注意しましょう。

プログラム全文


#property copyright "Copyright(C) 2023, OANDA"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

input int                   MAGICMA = 23498721;                         // マジックナンバー
input double                Lots =0.01;                                 // 1ロット十万通貨単位
input int                   Slippage = 4;                               // エントリー見送りスリッページ
input double                MaxSpread = 5;                              // エントリー見送りスプレッド
input double                TakeProfit = 30.0;                          // 利益確定幅(pips)
input int                   RSIPeriod=6;                                // 期間
input   ENUM_APPLIED_PRICE  RSIAppliedPrice = PRICE_CLOSE;              // 適用価格
input int                   UpLine = 85;                                // 上の線
input int                   DownLine = 25;                              // 下の線
input int                   TradeTime = 0;                              // トレードを行う時間
input int                   TrailWidth = 10;                            // トレール幅(pips)
  
double dSpread;

int OnInit()
{
   return(INIT_SUCCEEDED);
}
void OnTick()
{
   dSpread = (Ask - Bid) / (Point * 10);
   if(CalculateCurrentOrders()==0 && dSpread < MaxSpread) CheckForOpen(); 
   TrailingStop();

}
void CheckForOpen()
{
   int res;
   double RSI = iRSI(Symbol(), 0, RSIPeriod, RSIAppliedPrice, 1);
   if(TradeTime == TimeHour(Time[1]))
   {
      if(RSI < DownLine)
      {
         res=OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, Bid - TrailWidth * Point * 10, Ask + TakeProfit * Point * 10,"", MAGICMA, 0, Red);
      }
      if(RSI > UpLine)
      {
         res=OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, Ask + TrailWidth * Point * 10,  Bid - TakeProfit * Point * 10, "", MAGICMA, 0, Blue);
      }
   }
}

int CalculateCurrentOrders()
{
   int positions = 0;
   for(int i=0;i= 0; i--){
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;     
      if (OrderType() == OP_BUY){
         if ((Bid - OrderStopLoss()) / (Point * 10) > TrailWidth * 2){
            int om = OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss() + TrailWidth * (Point * 10), OrderTakeProfit(), OrderExpiration());
         }
      }
      if (OrderType() == OP_SELL){
         if ((OrderStopLoss() - Ask) / (Point * 10) > TrailWidth * 2){
            int om = OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss() - TrailWidth * (Point * 10), OrderTakeProfit(), OrderExpiration());
         }
      }
   }
}

EA(自動売買)を学びたい方へオススメコンテンツ

EA運用の注意点

OANDAではEA(自動売買)を稼働するプラットフォームMT4/MT5の基本的な使い方について、画像や動画付きで詳しく解説しています。MT4/MT5のインストールからEAの設定方法までを詳しく解説しているので、初心者の方でもスムーズにEA運用を始めることが可能です。またOANDAの口座をお持ちであれば、独自開発したオリジナルインジケーターを無料で利用することもできます。EA運用をお考えであれば、ぜひ口座開設をご検討ください。


本ホームページに掲載されている事項は、投資判断の参考となる情報の提供を目的としたものであり、投資の勧誘を目的としたものではありません。投資方針、投資タイミング等は、ご自身の責任において判断してください。本サービスの情報に基づいて行った取引のいかなる損失についても、当社は一切の責を負いかねますのでご了承ください。また、当社は、当該情報の正確性および完全性を保証または約束するものでなく、今後、予告なしに内容を変更または廃止する場合があります。なお、当該情報の欠落・誤謬等につきましてもその責を負いかねますのでご了承ください。

この記事をシェアする

ホーム » FX自動売買基礎と応用 » 朝スキャEAにトレーリングストップを実装するカスタマイズ【コピペで使用可能】