高勝率のEAを作る(サンプルソース)

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

今回は、MT4のEAサンプルソース(FX用)を公開します。

トレードに使うテクニカル分析はストキャスティクスとRSIで、順張りエントリーです。

はじめに

MT4のEAで、 FX用の高勝率EAがよく販売されていますが、一体どうやって作っているだろうという疑問から、高勝率になるようなEAを作ってみました。

とにかく高勝率のEAは損大利小が王道なので、エントリー時に損切りと利確の幅を損大利小にして指値・逆指値の比率を1:9ぐらいにしています。

これだけでかなりの高勝率にはなりますが、無駄なエントリーが多く利益が全然出ないので、今回はストキャスティクスとRSIでエントリー回数を間引きました。

短期間ではありますが高勝率・高利益のEAが作れましたのでサンプルソースやテスト結果を掲載しています。EAを作成する際やEAを購入する際の何かのヒントになればと思います。

EAの仕様

それでは、今回のソースコードのエントリー/決済/パラメータ設定についての仕様を説明します。

エントリータイミング

ストキャスティクス(パラメータ設定)とRSI(期間:14)を見てエントリーしています。

決済タイミング

OCOの形で、利確を2.5pips、損切りは17pipsです。

その他の仕様

設定値は以下の通りです。

  • E_KAI = 68 ⇒ ストキャスティクスの値がこれより下回ったら買い
  • E_URI = 80 ⇒ ストキャスティクスの値がこれより上回ったら売り
  • STOP_LOSS = 170 ⇒ ストップロスの値(170=17pips)
  • TP = 25 ⇒ プロフィット(利確)の値(25=2.5pips)
  • A_SPREAD = 20 ⇒ エントリー及び決済時に許容するスプレッドの値(20 = 2pips)
  • Lots = 1 ⇒ ロット数です(0.01=1000通貨)

既に建玉がある場合は追加でエントリーはしません。

値段が変わる度に処理を行いエントリー判断します。

また、マーチンゲール及びナンピンもしていません

スポンサーリンク

EAレポート結果

ここからはバックテスト結果になります。

勝てている期間考察

※メタクオーツ社のヒストリカルデータでバックテストをした結果です

2005年1月10日~2006年10月10日までという短期間5分足でのバックテスト結果です。

自分でも最初驚いたのですが、なんと勝率約95%でPF2.72のEAが完成してしまいました。取引総数も37021回と十分な取引数です。利益も平均2.5pipsで損失も17pipsとなっていますね。

ストキャスティクスがそんな凄いのか?と思ったのですが、ストキャスティクスの条件を抜いてもPF1.5近くいったので、どうやらこの2005年~2006年の期間は利確を2.5pips、損切りは17pipsでトレードするだけで結構稼げたようです。

ダウンロード

上記のEAファイルになります。

“高勝率EA” をダウンロード 18_KouSyou.ex4 – 2067 回のダウンロード – 11.91 KB

ソースコード

以下サンプルソースコードになります。
※丸々コピペでコンパイルできます

//+------------------------------------------------------------------+
//|                                                  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 = 68;      //ストキャスティクスの値がこれより下回ったら買い
input int E_URI = 80;      //ストキャスティクスの値がこれより上回ったら売り
 
input int STOP_LOSS = 170; //ストップロスの値(1000=100pips)
input int TP = 25;         //プロフィット(利確)の値(1000=100pips)
input int A_SPREAD = 20;   //エントリー及び決済時に許容するスプレッドの値です(20 = 2pips)
input double Lots = 1;     //ロット数です(0.01=1000通貨)
       
 
       
       
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,4,3,3,MODE_EMA,0,0,1);
    double STOC_atai2 = iStochastic(NULL,0,4,3,3,MODE_EMA,0,0,2);   
             
    //RSIの値取得(デフォルト値)
    double RSI_atai1 =iRSI(NULL,0,14,PRICE_CLOSE,1);
    double RSI_atai2 =iRSI(NULL,0,14,PRICE_CLOSE,2);
       
   if(STOC_atai1 > E_URI && STOC_atai2 < STOC_atai1 && RSI_atai1 < 80)
   {
      orderPtn=2;
   }
   else if(STOC_atai1 < E_KAI && STOC_atai2 > STOC_atai1 && RSI_atai1 > 20)
   {
      orderPtn=1;
   }
   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) < A_SPREAD){
       
         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]
            Lots,                     // ロット[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;   
}
       
//+------------------------------------------------------------------+
//|【関数】直近の高値安値を取得する                                       |
//|                                                                  |
//|【引数】 Type=(1:高値 2:安値)  Kikan=確認する期間                     |
//|                                                                  |
//|【戻値】最高値又は最安値                                              |
//|                                                                  |
double funcHighLowGet(int Type,int Kikan,int Start)
{
   double Kakaku=0;
       
   if(Type==1){
      Kakaku = iHigh(NULL, 0, iHighest(NULL,0,MODE_HIGH,Kikan,Start));
   }
   else if(Type==2){
      Kakaku = iLow(NULL, 0, iLowest(NULL,0,MODE_LOW,Kikan,Start));
   }
   return Kakaku;   
}
スポンサーリンク

このEAが負けだした期間を考察

ちなみに2007年からの結果は悲惨な状況で、こんな感じです。

2006年10月10日以降は全く勝てず右肩下がりのダメEAになってしまいました。これで同じEAなの?と思ってしまうかもしれませんが同じEAです。

取引数37021回でも不確実なのか

2005年1月10日~2006年10月10日までで37021回というそれなりの試行回数でトレードして、めちゃくちゃ利益を出していたにもかかわらず、その後ことごとく負けてしまうというのは個人的にも結構腑に落ちない部分(期待値のある取引を続けるという意味で)があります。

このような尻下がりになってしまった結果として、思い当たる部分は2点です。

まず、勝率が95%あったのが88%にまで落ちている点です。一見そこまで落ちていないように思いますが、結果を見る限りこれがかなりの致命傷となっています。あまりにも勝率を高くしてしまうと、少し歯車が狂っただけで全く稼げなくなるという事があるのではないかと思いました。損大利小の高勝率でEAを稼働した場合、勝っている場合はサクサクエントリー→決済を繰り返し利益を出していきますが、負けだすと損失ポジションをなかなか決済できず効率がガクッと落ちます。このEAはポジションを1つしか保有しない作りですので、その事象が顕著に表れています。もしかしたら、複数ポジションを持つことによりカバーすることができるかもしれません。

次は、EAの処理(トレード方法)がめちゃくちゃ単調な点です。ストキャスティクスもRSIも使っているようでエントリーの根拠としてはとても弱いです。このEAの一番の武器は、利確を2.5pips、損切りは17pipsとしている所です。予想ですが、このトレード方法を破綻させる新たなトレード方法が市場に出てきたという事かもしれません。(ゼロサムゲームという意味で)
※実際この損切り、利確の値を逆にするだけで2006年10月11日~2011年6月6日でも利益を出すことが可能でした

おまけ

今回はメタクオーツ社のヒストリカルデータを使ってテストをしたのですが、FXDD社のヒストリカルデータだと上記のような右肩上がりのグラフにはならないようです。各社提供されているヒストリカルデータにはやはり結構な違いがあるようなので調べてみました。

さいごに

高勝率EAを作りましたが、2006年10月10日以降は残念な結果に終わってしまいました。この結果を見て、短期的にうまくいっていても、ある時突然負けだすという事はあり得そうだなと思いました。gogojungleの直近1年で成績が良くないEAに対するコメントとかでも、このEAは時代遅れだ!みたいなコメントをたまに見かけていたんですが、私個人的には時代遅れなんてあるの?と思っていました。どうやら時代遅れという言葉が正しいようです。

今回の事象を踏まえ、

  • 高勝率だけが全てではない
  • EAの成果を定期的に見直す必要がある
  • EAがある日突然全く機能しなくなることも想定しなければならない

という事を念頭にFXに向き合っていこうと思います。「EAがある日突然全く機能しなくなることも想定」というと大袈裟かもしれないですが、自分のEAがある日を境にめちゃくちゃ負けだして止まらなくなったらそういう事かもしれないという感じです。


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

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


コメント