EAのトレード戦略の立て方

記事内に商品プロモーションを含む場合があります
スポンサーリンク

はじめに

EAのトレード戦略(トレード手法)をどうやって立てて、どうEAを作っていくのか迷ったりしませんか?

そんな、EAを新規開発する際どこから手をつけたらいいか全く分からないといった方へ、足掛かりとなる記事を書きました。


※今回の記事はプログラムがある程度組めることが前提です。プログラムを1から学びたい場合はこちら

スタートはシンプルに

私自身全くトレード戦略が思いつかないタイプの人間なので(ちょっと考えただけでEAのトレード戦略がポンポン思いつく人が羨ましい・・・)、どうにかしてトレード戦略を立てる事ができないかと試行錯誤しました。

まず、EAのさわりの部分ですが、難しく考え過ぎずシンプルに考えることが重要だと私は思います。

どれぐらいシンプルかと言うと、

①適当にトレードする
②損切り幅、利確幅は同じにする(1ポジション及び固定ロットで考える)
③スプレッドを考慮する

これだけ考えます。これで勝率は50%で利益はプラマイゼロ(正確にはスプレッド分負ける)というトレード戦略が出来上がります。50%理論は以下の記事に詳細を記載していますので良かったら参考にしてみてください。

まずは、勝率50%前後でスプレッド分だけ負けていくような(ベースとなる)EAを作ります。時間足はいくらでもいいですが、私は大体15分足を多用しています。

時間でロングやショートをするサンプルEA

ベースEAのサンプルです。時間(0分/30分ならロング、15分/45分ならショート)でロングかショートを選んでいるので、なぜロングなのか、ショートなのかというテクニカルな根拠は一切存在しません。あと損切り、利確はどちらも20pipsです。

//+------------------------------------------------------------------+
//|                                                  STOC_Sample.mq4 |
//|                                    Copyright 2020, mef Software. |
//|                                             https://fx-prog.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, mef Software."
#property link      "https://fx-prog.com/"
#property version   "1.00"
      
input int STOP_LOSS = 200;
input int TP = 200;
      
datetime prevtime;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//---
          
//---
   return(INIT_SUCCEEDED);
  }
       
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
int start()
{
int orderPtn=0; //0:何もしない 1:買い 2:売り
int total=0;
       
double ea_order_stop_price=0,ea_order_good_price=0; //ストップロスレート,利確レート,エントリーレート
bool OrderKekka;
      
//---
   //新しい足ができた時だけやる
   if(Time[0] != prevtime){
      prevtime = Time[0];
   }else{
      return(0);
   }
       
//***売買判断箇所***//
      
   //0分、30分の場合はロング
   if(Time[0] % 1800 == 0){
      orderPtn=1;
   }else{
      orderPtn=2;
   }
   
//***売買判断箇所***//
       
//***決済判断箇所***//
   total=OrdersTotal();
   if(total ==0 && orderPtn > 0)   
   {
      if(orderPtn == 1)
      {
         ea_order_stop_price = Ask - STOP_LOSS * Point;
         ea_order_good_price = Ask + TP * Point;          
      }
      else if(orderPtn == 2)
      {
         ea_order_stop_price = Bid + STOP_LOSS * Point;  
         ea_order_good_price = Bid - TP * Point;  
      }   
      
      //新規注文
      OrderKekka = funcOrder_Send(orderPtn - 1,ea_order_stop_price,ea_order_good_price,0,0);
      
   }
         
   return(0);
}
      
//+------------------------------------------------------------------+
//|【関数】新規注文関数                                                 |
//|                                                                  |
//|【引数】 ea_order_entry_Type:売買(0:買 1:売)                         |
//|【引数】 ea_order_stop_price:損切値  ea_order_good_price:利確値      |
//|【引数】 orderComment:オーダーコメント    ea_order_MagicNo:マジックNo       |
//|                                                                  |
//|【戻値】True:成功                                                   |
//|                                                                  |
//| 
bool funcOrder_Send(int ea_order_entry_Type, double ea_order_stop_price, double ea_order_good_price,int orderComment,int ea_order_MagicNo)
{
      
   int order_resend_num;        // エントリー試行回数
   int ea_ticket_res;           // チケットNo
   int errorcode;               // エラーコード
   double ea_order_entry_price; // エントリーレート
   color order_Color;
   bool kekka;
         
   for( order_resend_num = 0; order_resend_num < 10; order_resend_num++ ) {    // エントリー試行回数上限:10回
      
      if(MarketInfo(NULL,MODE_SPREAD) < 20){
      
         if(ea_order_entry_Type == OP_BUY){   
            ea_order_entry_price = Ask;               // 現在の買値でエントリー
            order_Color = clrBlue;
         }else if(ea_order_entry_Type == OP_SELL){        
            ea_order_entry_price = Bid;               // 現在の売値でエントリー
            order_Color = clrRed;            
         }
      
         // FXCMでは新規エントリー時にストップ/リミットを設定出来ない。
         ea_ticket_res = OrderSend(   // 新規エントリー注文
            NULL,                 // 通貨ペア
            ea_order_entry_Type,      // オーダータイプ[OP_BUY / OP_SELL]
            0.01,                     // ロット[0.01単位](FXTFは1=10Lot)
            ea_order_entry_price,     // オーダープライスレート
            20,                       // スリップ上限    (int)[分解能 0.1pips]
            ea_order_stop_price,      // ストップレート
            ea_order_good_price,      // リミットレート
            orderComment,             // オーダーコメント
            ea_order_MagicNo,         // マジックナンバー(識別用)
            0,                        // オーダーリミット時間
            order_Color               // オーダーアイコンカラー
            );
      }
                  
      if ( ea_ticket_res == -1) {            // オーダーエラー
         errorcode = GetLastError();      // エラーコード取得
      
         if( errorcode != ERR_NO_ERROR) { // エラー発生
            printf("エラー");
         }
      
         Sleep(2000);                                           // 1000msec待ち
         RefreshRates();                                        // レート更新
      
         printf("再エントリー要求回数:%d, 更新エントリーレート:%g",order_resend_num+1 ,ea_order_entry_price);
      
      } else {    // 注文約定
         Print("新規注文約定。 チケットNo=",ea_ticket_res," レート:",ea_order_entry_price);
         Sleep(300);                                           // 300msec待ち(オーダー要求頻度が多過ぎるとエラーになる為)
                  
         break;
      }
   }
   return kekka;   
}
   
スポンサーリンク

上記EAの結果はこんな感じです。※アルパリのヒストリカルデータで確認しています

この適当にトレードするEAはもちろんプロフィットファクターもほぼプラマイゼロ、勝率も約50%です。

次に、このベースEAにテクニカル分析を1つ取り入れ勝率を50%より上にしていきます。

テクニカル分析を追加する

今回は例として、オシレータ系のテクニカルでストキャスティクスを追加してみます。

まずは、ストキャスティクスの王道で買われ過ぎたら売る、売られ過ぎたら買うという形にしてみます。

ストキャスティクスを取り入れたEA

先ほどの時間ではなく、ストキャスティクスの値を見て80より大きかったらショート、20より小さかったらロングエントリーするように変更しました。先ほどのベースソースから『売買判断箇所』で囲まれた部分だけ修正したものです。

あと、ストキャスティクスの値は最適化で調整できるように「input int E_KAI = 20」という形で記載しています。

//+------------------------------------------------------------------+
//|                                                  STOC_Sample.mq4 |
//|                                    Copyright 2020, mef Software. |
//|                                             https://fx-prog.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, mef Software."
#property link      "https://fx-prog.com/"
#property version   "1.00"
      
input int E_KAI = 20;
input int E_URI = 80;
      
input int STOP_LOSS = 200;
input int TP = 200;
      
      
double maisuu=0.01;
datetime prevtime;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//---
          
//---
   return(INIT_SUCCEEDED);
  }
       
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
int start()
{
int orderPtn=0; //0:何もしない 1:買い 2:売り
int total=0;
       
double ea_order_stop_price=0,ea_order_good_price=0; //ストップロスレート,利確レート,エントリーレート
bool OrderKekka;
      
//---
   //新しい足ができた時だけやる
   if(Time[0] != prevtime){
      prevtime = Time[0];
   }else{
      return(0);
   }
       
//***売買判断箇所***//
      
   
   //ストキャスティクスの値取得
   double STOC_atai1 = iStochastic(NULL,0,5,3,3,MODE_EMA,0,0,1);
   double STOC_atai2 = iStochastic(NULL,0,5,3,3,MODE_EMA,0,0,2);   
          
   //ストキャの値が、E_KAIより下ならロング(ストキャが下に向かっている事)  
   if(STOC_atai1 < E_KAI && STOC_atai2 > STOC_atai1)
   {
      orderPtn=1;
   }
   //ストキャの値が、E_URIより上ならショート(ストキャが上に向かっている事)     
   else if(STOC_atai1 > E_URI && STOC_atai2 < STOC_atai1)
   {
      orderPtn=2;
   }
   else
   {
      orderPtn=0;
   }
   
//***売買判断箇所***//
       
//***決済判断箇所***//
   total=OrdersTotal();
   if(total ==0 && orderPtn > 0)   
   {
      if(orderPtn == 1)
      {
         ea_order_stop_price = Ask - STOP_LOSS * Point;
         ea_order_good_price = Ask + TP * Point;          
      }
      else if(orderPtn == 2)
      {
         ea_order_stop_price = Bid + STOP_LOSS * Point;  
         ea_order_good_price = Bid - TP * Point;  
      }   
      
      //新規注文
      OrderKekka = funcOrder_Send(orderPtn - 1,ea_order_stop_price,ea_order_good_price,0,0);
      
   }
         
   return(0);
}
      
//+------------------------------------------------------------------+
//|【関数】新規注文関数                                                 |
//|                                                                  |
//|【引数】 ea_order_entry_Type:売買(0:買 1:売)                         |
//|【引数】 ea_order_stop_price:損切値  ea_order_good_price:利確値      |
//|【引数】 orderComment:オーダーコメント    ea_order_MagicNo:マジックNo       |
//|                                                                  |
//|【戻値】True:成功                                                   |
//|                                                                  |
//| 
bool funcOrder_Send(int ea_order_entry_Type, double ea_order_stop_price, double ea_order_good_price,int orderComment,int ea_order_MagicNo)
{
      
   int order_resend_num;        // エントリー試行回数
   int ea_ticket_res;           // チケットNo
   int errorcode;               // エラーコード
   double ea_order_entry_price; // エントリーレート
   color order_Color;
   bool kekka;
         
   for( order_resend_num = 0; order_resend_num < 10; order_resend_num++ ) {    // エントリー試行回数上限:10回
      
      if(MarketInfo(NULL,MODE_SPREAD) < 20){
      
         if(ea_order_entry_Type == OP_BUY){   
            ea_order_entry_price = Ask;               // 現在の買値でエントリー
            order_Color = clrBlue;
         }else if(ea_order_entry_Type == OP_SELL){        
            ea_order_entry_price = Bid;               // 現在の売値でエントリー
            order_Color = clrRed;            
         }
      
         // FXCMでは新規エントリー時にストップ/リミットを設定出来ない。
         ea_ticket_res = OrderSend(   // 新規エントリー注文
            NULL,                 // 通貨ペア
            ea_order_entry_Type,      // オーダータイプ[OP_BUY / OP_SELL]
            0.01,                     // ロット[0.01単位](FXTFは1=10Lot)
            ea_order_entry_price,     // オーダープライスレート
            20,                       // スリップ上限    (int)[分解能 0.1pips]
            ea_order_stop_price,      // ストップレート
            ea_order_good_price,      // リミットレート
            orderComment,             // オーダーコメント
            ea_order_MagicNo,         // マジックナンバー(識別用)
            0,                        // オーダーリミット時間
            order_Color               // オーダーアイコンカラー
            );
      }
                  
      if ( ea_ticket_res == -1) {            // オーダーエラー
         errorcode = GetLastError();      // エラーコード取得
      
         if( errorcode != ERR_NO_ERROR) { // エラー発生
            printf("エラー");
         }
      
         Sleep(2000);                                           // 1000msec待ち
         RefreshRates();                                        // レート更新
      
         printf("再エントリー要求回数:%d, 更新エントリーレート:%g",order_resend_num+1 ,ea_order_entry_price);
      
      } else {    // 注文約定
         Print("新規注文約定。 チケットNo=",ea_ticket_res," レート:",ea_order_entry_price);
         Sleep(300);                                           // 300msec待ち(オーダー要求頻度が多過ぎるとエラーになる為)
                  
         break;
      }
   }
   return kekka;   
}
   
スポンサーリンク

上記EAの結果はこんな感じです。

とりあえず、スプレッド分の損失は補填してくれるようなEAを作る事ができました。

設定値等でつめていく

最適化で検討する

先ほどの結果を見てもわかる通り、現状の設定ではあまり有効なEAではないので、最適化でより良いストキャスティクスの値と損切り、利確幅を確認していきます。
※最適化については以下の記事に詳細を記載していますので、分からない場合は参考にしてみてください

※テスト値はこんな感じ

最適化の設定はこんな感じにしてみました。ストキャスティクスがいくらまで下がったらロングがいいのか、ストキャスティクスがいくらまで上がったらショートがいいのか、また損切り、利確幅はいくらがいいのかを最適化で確認していきます。

勝率が高いパターンで良さそうな値

勝率が70%を超え、かつプロフィットファクタも1.10になる設定がありました。

ストキャスティクスの値が13より下になったらロング、90を超えたらショート、損切りは21pipsで利確は9pipsという設定です。結果はこんな感じです。

プログラムは一切変えておらず、設定を少し変えただけです。

設定を少し変えるだけで結構変わりますね!設定の内容としては、ストキャスティクスの値を厳しめに見つつエントリーし、損切り幅を大きめにとり、利確は小さめといった感じです。

勝率は低いけど利確幅は大きい値

勝率は20%前半ですが、プロフィットファクタは1.04の設定も紹介します。

ストキャスティクスの値が17より下になったらロング、73を超えたらショート、損切りは6pipsで利確は22pipsという設定です。結果はこんな感じです。

プロフィットファクタはそんなに高くないです。

が、注目するポイントとしては現在時間に近い方が利益がよく出ています。

この直近の方が利益がでてる方が良い傾向です。
※勝率が高いパターンの方は現在時間は横ばいグラフだったので、リアルタイムだと微妙かも

こんな感じに最適化で確認していくだけで、トレード戦略として有益な情報が結構出てきます。

スポンサーリンク

時間足を検討する

色んな時間足の目線で確認して行く事も重要です。

ストキャスティクスは5分足だと機能するのかしないのか、他の時間足ならどうなるのか等を見ていくと良いヒントが出てきたりします。

5分足の結果

先ほどの高勝率の設定をそのまま使って、5分足で確認してみました。

当然ですが、15分足で確認した程安定はしていない結果となります。
※ただし、5分足で最適化をして確認していくとさらにいいものが見つかるかもしれません

30分足の結果

30分足で最適化してよさそうなものを選びました。プロフィットファクタが1.26と割と良い感じになっています。

トレード回数を15分足よりも減らしていきたい場合、30分足等で最適化して確認するとトレード回数を減らして行く事も可能です。逆にトレード回数を増やしたい場合は、1分足や5分足で調整していく形になります。

通貨を検討する

ここまでは全てドル円通貨で確認しましたが、もちろんユーロドルやポンド円等で確認していき、よりストキャスティクスが効いている通貨を探すのも手です。

私の場合、スプレッドが狭いドル円が主戦場なので通貨を変えて確認していませんが、ポンド円など動きの大きい通貨だと、ドル円よりこのテクニカルがすごく効くとかっていうパターンもあると思うので色々な通貨で確認するのも一つの手です。

注意点として、通貨を検討する場合はポンド円等の場合スプレッドは10とかになってくると思うのでその辺は、そのスプレッド幅を補って行くトレード戦略を立てる必要がでてきます。
※今回はドル円で確認したのでスプレッドは全て2で確認しています

さいごに

以上が、『EAのトレード戦略の立て方』となります。

EAを作る上で大切なのは、

  • 利益を上げる事ができるEAなのか
  • 直近で通用しているのか
  • 過去もある程度通用しているのか
  • カーブフィッティング系の処理を入れ込んでいないか

だと思います。

もし、EAが全然作れない場合上記のことを思い出してシンプルな所から考えていくと、良いEAを作る近道になりかもしれません。色々考え過ぎると、謎のEAが出来上がったり、極端にカーブフィッティング寄りなEAが出来上がったりするのでシンプルにシンプルに考えていきましょう。

どんなにシンプルだったとしても、ほんの少しのテクニカル分析の組み合わせ(移動平均線とストキャスティクス)や、時間足、通貨、損切・利確幅の調整、テクニカル自体の設定変更(今回ストキャスティクスは一律5,3,3の初期値で確認しています)、クオンツアナライザーで調整等々考えていくと、数えきれない程のパターンでEAが作れていくと思います。

あと、要所要所でビジュアルモードで実際に動きを確認しましょう。

もっとエントリーすべきポイント、損切りすべきポイント等々EAを修正すべき点が見つかりまくるはずです!
※カーブフィッティングにならないように注意!

※ EAのサンプルソースを一覧表にまとめました

※オンラインレッスンやってます


コメント

  1. イノウエ より:

    1分間でどれだけ上下しているのかを探す、EAがないか探しておりましたら、こちらのサイトに行き着きました。
    プログラミングが得意ではないですが、拝見させていただいて、EAを選ぶのに参考になりました。

    • イノウエ より:

      ✕1分間でどれだけ上下しているのかを探す、EAがないか探して

      ○1分間で相場がどれだけ上下?しているのをカウントする、EAがないか探しております。

      わかりにくかったので訂正します。これでも伝わらないかもしれません。すみません。

      希望としては公開はしてほしくはありません。

      • りょう りょう より:

        『1分間で相場がどれだけ上下?しているのをカウントする』というのは出来高の事ですか?1分足が形成される間に105.410→105.411→105.412→105.411→105.411→105.410→105.409・・・というように値動きが何回起きたかを確認したい場合、MT4のインディケータ(標準搭載)でボリューム→Volumesを1分足チャート上に表示すると1分間に何回値動きがあったかを表示してくれますよ。ただ、それを用いてトレードするEAとなると私はまだ作った事がない&オススメの販売EAもわからないのでお力になれません!

  2. イノウエ より:

    ありがとうございます。
    書いたのが、どのページが忘れてしまって遅れてすみません。
    ちょっと違います。
    始まり→ 上1回→ 上1回→ 下1回→ 同じ1回→下1回 →下1回
    105.410→105.411→105.412→105.411→105.411→105.410→105.409・

    その1分足の結果
    上2回 下3回 同じ1回(カウントなし)
    というのを ローソク足の上下に数値で表せないかということです。
    すっと観ていて、パターンがあるのではないかと。
    それで、検証したら面白いのではないかと

    • りょう りょう より:

      なるほど、上下をカウントして表示するといった感じでしたか!
      1分前のデータがカウントできないので現在(MT4とインジを起動してから)からのカウントしか出来ないですけど、作ろうと思えば作れそうです。プライスアクション系のインジケータになりそうですね。ただ、ブローカーによって数値がかなりブレる気もします!