ゴトー日を自動判定する逆張りEAの作り方|IsTradeDate関数とマジックナンバー設計を解説

ゴトー日仲値で逆張りする系のEA(サンプルソース有り)
EA・MT4ノウハウ集
記事内に商品プロモーションを含む場合があります
スポンサーリンク

「ゴトー日仲値EAを作ってみたい」「日付指定EAを自動化したい」── そんな方に向けて、この記事ではゴトー日を自動判定する逆張りEAの無料サンプルコードを解説します。

本EAは、ゴトー日(5・10・15・20・25日)を自動で判定し、 土日を考慮したうえで仲値前後に逆張りエントリーを行います。

また、マジックナンバーを考慮した設計のため、 複数EAを同一口座で運用したい方の学習用サンプルとしても最適です。

📘 この記事で解説する内容
  • ゴトー日(5・10・15・20・25日)とは何か
  • ゴトー日を自動で判定するEAロジック
  • 仲値前後で逆張りするエントリー設計
  • マジックナンバーを使ったポジション管理
  • コピペで動くMQL4サンプルコード

📅 ゴトー日(仲値)とは?

FXでは、毎月「5日・10日・15日・20日・25日・30日(ゴトー日)」に、 仲値(9:55)に向けた特徴的な値動きが発生しやすいと言われています。 これは企業の実需(決済・送金)によるドル需要が集中しやすいためです。

その特性を利用した「ゴトー日EA」や「仲値EA」は以前から数多く存在しますが、 近年は単純な順張りロジックでは機能しづらくなってきているのも事実です。

そこで本記事では、ゴトー日そのものを狙うEAではなく、 「ゴトー日かどうかをEAが自動で判定し、その条件をトレード判断に使う」 という設計思想を学ぶためのサンプルEAとして紹介しています。

EAの概要とポイント

  • ゴトー日を自動で判定(年・月の修正不要)
  • 仲値前後に時間指定でエントリー
  • 逆張りロジックを採用
  • マジックナンバー対応(複数EA同時運用可)
  • 最大ポジション数は1

ゴトー日を自動で判定する仕組み

ゴトー日EAでよくある問題が、毎年・毎月の日付を手動で修正しなければならない点です。 このEAでは、ゴトー日を自動判定し、土日の場合は前営業日に補正するロジックを採用しています。

IsTradeDate() 関数の考え方

IsTradeDate() 関数では、

  • 5・10・15・20・25日を基本判定
  • 土日の場合は前営業日に補正

という2点を自動で処理しています。
日付をハードコードしないため、長期運用に向いています。

エントリーロジック解説

ショートエントリー

  • ゴトー日早朝にエントリー
    ゴトー日のAM6:45にショートエントリーします。
    ※サマータイム時はAM5:45

ロングエントリー

  • ショート側が一定pips以上利益を出している場合のみ
    ゴトー日のAM9:55にロングエントリーします。ただし、ショートエントリー側で30pipsを超える利益が出ている場合に限ります。
    ※また、ショートエントリー側がすでにTPに到達している場合で、AM9:55の段階でTPから10pips以上戻している場合はエントリーしません。

⚠️ 注意点

本EAは、ゴトー日・時間帯・マジックナンバーといった 日付・時刻条件をEAに組み込む方法を理解することを目的とした学習用サンプルです。 実運用での安定収益を保証するものではありませんので、その点はご了承ください。

※ 本サンプルEAは、日本時間が -7時間 となっている MT4(FXTF)環境で動作確認を行っています。
ブローカーによってサーバー時間が異なるため、時間条件を使うEAでは必ず調整が必要です。

【その他】

  • 近年はゴトー日仲値の再現性が低下している
  • 祝日は考慮していない
  • マジックナンバーに関する処理が入っているので少し複雑

▶ マジックナンバーがよく分かっていない方はこちら

ダウンロード

EAファイルのダウンロードはこちら👇

📥 ゴトー日逆張りEA をダウンロード

\ 国内最大級のEAプラットフォーム /
GogoJungle(ゴゴジャン)でEAの評価・レビューをチェック!

▶ GogoJungleでEAを探す ゴトー日を自動判定する逆張りEAの作り方|IsTradeDate関数とマジックナンバー設計を解説

このEAでマジックナンバーをどう使っているか

このEAは、複数EAを同一口座で運用することを前提に、
マジックナンバーを使って「自分のポジションだけ」を正確に管理しています。

エントリー判定・決済判定・損益取得のすべてで
マジックナンバーによるフィルタリングを行っているため、
他EAのポジションを誤って操作することはありません。

マジックナンバーでポジションを管理する仕組み

本EAでは、OrderSelect() を直接使うのではなく、
マジックナンバーを条件にした専用関数 funcOrder_Select() を用意しています。

これにより、
・現在の保有ポジション数
・最新ポジションの選択
・過去ポジションの参照
をすべて「自分のEAの取引だけ」に限定して取得できます。

エントリー・決済を関数化している理由

OrderSend() や OrderClose() を直接書かず、
専用関数として切り出しているのは、以下の理由からです。

・スプレッドチェックを毎回共通化できる
・再エントリー/再決済処理を一元管理できる
・マジックナンバーを必ず通す設計にできる

EAを複数動かす前提では、
このような関数分離がトラブル防止に直結します。

📜 ゴトー日仲値で逆張りするのサンプルコード解説

以下にMQL4サンプルコードを掲載します。
そのままコピーしてMT4(MetaEditor)に貼り付ければコンパイル可能で、動作確認も済んでいます。

//+------------------------------------------------------------------+
//|                                          21_Gotobi-Gyakubari.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 MagicNo = 123456;   //マジックナンバー
input double Lots = 0.01;        //ロット数です(0.01=1000通貨)
input int A_SPREAD = 100;      //エントリー及び決済時に許容するスプレッドの値です(10 = 1pips)

input int Order_SL = 650;     //ストップロスの値(1000=100pips)
input int Order_TP = 650;     //プロフィット(利確)の値(1000=100pips)


input int Entry_Hour_S = 22;  //早朝エントリーする時間(サマータイム時)
input int Entry_Minute_S = 45;//早朝エントリーする分(サマータイム時)

input int Entry_Hour_W = 23;  //早朝エントリーする時間
input int Entry_Minute_W = 45;//早朝エントリーする分

bool entryflg=false;
//+------------------------------------------------------------------+
//| 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(IsSummerTime()==false){
//ショートエントリー側///////////////////////

   if(IsTradeDate()==true){
      if(Hour() == Entry_Hour_W && Minute() == Entry_Minute_W){
         orderPtn=2;
      }
   }    
   
   total=funcOrder_Select(0,MagicNo);

   //9時55分に決済
   if(OrderType()==OP_SELL && total ==1 && Hour() == 2 && Minute() == 55){
      OrderKekka = funcOrder_Close(A_SPREAD,MagicNo,clrGray);
      total=funcOrder_Select(0,MagicNo);         
   }
//ショートエントリー側///////////////////////

//ロングエントリー側///////////////////////
   if(entryflg==true){
      //9時55分にロング
      if(Hour() == 2 && Minute() == 55){
         entryflg=false;

         if(getProfit(1,MagicNo)> 30 && OrderClosePrice() > Ask - 100*Point  ){
            orderPtn=1;
         }
      }
   }   

   //14時に決済
   if(OrderType()==OP_BUY && total ==1 && Hour() == 7 && Minute() == 00){
      OrderKekka = funcOrder_Close(A_SPREAD,MagicNo,clrGray);
   }
}else if(IsSummerTime()==true){
//ショートエントリー側///////////////////////

   if(IsTradeDate()==true){
      if(Hour() == Entry_Hour_S && Minute() == Entry_Minute_S){
         orderPtn=2;
      }
   }    
   
   total=funcOrder_Select(0,MagicNo);

   //9時55分に決済
   if(OrderType()==OP_SELL && total ==1 && Hour() == 3 && Minute() == 55){
      OrderKekka = funcOrder_Close(A_SPREAD,MagicNo,clrGray);
      total=funcOrder_Select(0,MagicNo);         
   }
//ショートエントリー側///////////////////////

//ロングエントリー側///////////////////////
   if(entryflg==true){
      //9時55分にロング
      if(Hour() == 3 && Minute() == 55){
         entryflg=false;

         if(getProfit(1,MagicNo)> 30 && OrderClosePrice() > Ask - 100*Point  ){
            orderPtn=1;
         }
      }
   }   

   //14時に決済
   if(OrderType()==OP_BUY && total ==1 && Hour() == 8 && Minute() == 00){
      OrderKekka = funcOrder_Close(A_SPREAD,MagicNo,clrGray);
   }
}

   
   //新規注文
   if(total ==0 && orderPtn > 0)   
   {
      if(orderPtn == 1)
      {
         ea_order_stop_price = Ask - Order_SL * Point;
         ea_order_good_price = Ask + Order_TP * Point;

      }
      else if(orderPtn == 2)
      {
         ea_order_stop_price = Bid + Order_SL * Point;  
         ea_order_good_price = Bid - Order_TP * Point;
         entryflg=true;
      }   
          
      //新規注文
      OrderKekka = funcOrder_Send(orderPtn - 1,ea_order_stop_price,ea_order_good_price,0,MagicNo);

          
   }
    
   return(0);
}

//+------------------------------------------------------------------+
//|【関数】オーダーセレクト関数
//| 
//|【引数】 mode 0:最新ポジション選択(ポジション数も取得) 1:1つ前の決済ポジ 2:2つ前の決済ポジ ・・・ 
//|【引数】 マジックナンバー
//|【引数(参照)】 mode 0の場合、最新のチケット番号群を更新する
//|
//|【戻値】ポジション数(過去の場合はあったINDEX)
//| 
int funcOrder_Select(int mode,int ea_order_MagicNo){
int total=0,cnt=0,ticket_buf=0;
bool OrderKekka =false;

   total = 0;

   if(mode==0){

      for(cnt = 0; cnt < OrdersTotal(); cnt++){
         if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES) == true){
            if(OrderMagicNumber() == ea_order_MagicNo){
               ticket_buf = OrderTicket();
               
               total = total+1;

            }
         }
      }

      //最新のポジションを選択する     
      if(ticket_buf !=0){
         OrderKekka = OrderSelect(ticket_buf,SELECT_BY_TICKET,MODE_TRADES); 
      }

   }else{

      for(cnt = OrdersHistoryTotal(); cnt > 0; cnt--){
         if(OrderSelect(cnt-1,SELECT_BY_POS,MODE_HISTORY) == true){
            if(OrderMagicNumber() == ea_order_MagicNo){
               total = total+1;
               
               if(mode <= total){
                  break;
               }
            }
         }
      }
   }



   return(total);
   
}

     
//+------------------------------------------------------------------+
//|【関数】新規注文関数                                                 |
//|                                                                  |
//|【引数】 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;   
}
       
       
       
//+------------------------------------------------------------------+
//|【関数】決済関数
//|
//|【引数】 kessaiSpread:許容する決済時のスプレッド
//|
//|【戻値】True:成功 False:失敗
//|
//|
bool funcOrder_Close(int kessaiSpread, int ea_order_MagicNo, color order_Color)
{
   bool kekka,OrderKekka;
   int total,order_resend_num;
   double ea_order_entry_price; // エントリーレート
   double KessaiBuff;
   
   kekka=false;

   total=funcOrder_Select(0,ea_order_MagicNo);
      
   if(total >0){
      for(order_resend_num = 0; order_resend_num < 100; order_resend_num++ ) {
         if(MarketInfo(NULL,MODE_SPREAD) <= kessaiSpread){

            if(OrderType() == OP_BUY){   
               ea_order_entry_price = Bid;               // 現在の売値で決済
            }else if(OrderType() == OP_SELL){
               ea_order_entry_price = Ask;               // 現在の買値で決済          
            }
            KessaiBuff = OrderProfit();
            OrderKekka = OrderClose(OrderTicket(),OrderLots(),ea_order_entry_price,10,order_Color);
         
            if(OrderKekka==false){
               Print("決済注文失敗 エラーNo:",GetLastError()," リトライ回数:",order_resend_num+1);
                        
               RefreshRates();
               Sleep(1000);
            }else{
               Print("決済注文完了 レート:",ea_order_entry_price," 決済結果:",KessaiBuff,"円"," Magic:",ea_order_MagicNo);
               break;
            }
         }else{
            Print("スプレッド拡大中(銭)=",MarketInfo(NULL,MODE_SPREAD) / 10," リトライ回数=",order_resend_num+1);
                   
            Sleep(5000);                                           // msec待ち
            RefreshRates();                                        // レート更新
         }
      }
   }
   kekka=true;
      
   return kekka;   
}

//+------------------------------------------------------------------+
//|【関数】前回トレードの損益をpips数で取得する
//| 
//|【引数】 0:現在のプロフィット 1:過去の1つ前のプロフィット
//|
//|【戻値】pips数
//| 
double getProfit(int mode,int ea_order_MagicNo){
int ticket = 0,total=0,cnt=0;
double ans = 0.0;
bool OrderKekka =false;

   if(mode==0){
      if(funcOrder_Select(0,ea_order_MagicNo) > 0){
         if(OrderType()==OP_SELL){
            ans = OrderOpenPrice()-Ask;
         }else if(OrderType()==OP_BUY){
            ans = Bid-OrderOpenPrice();
         }
   
         if(Digits==2 || Digits==3){
            ans *= 100;
         }else if(Digits==4 || Digits==5){
            ans *= 10000;
         }
      }
   
   }else{
      if(funcOrder_Select(mode,ea_order_MagicNo) > 0){
      
         if(OrderType()==OP_SELL){
            ans = OrderOpenPrice()-OrderClosePrice();
         }else if(OrderType()==OP_BUY){
            ans = OrderClosePrice()-OrderOpenPrice();
         }
   
         if(Digits==2 || Digits==3){
            ans *= 100;
         }else if(Digits==4 || Digits==5){
            ans *= 10000;
         }
      }

   }

   return(ans);
   
}

//+------------------------------------------------------------------+
//|【関数】サマータイム確認                                                |
//|                                                                  |
//|【引数】 なし                                                        |
//|                                                                  |
//|【戻値】True:サマータイム                                               |
//|【備考】3月第2日曜日~11月第1日曜日までをサマータイムとする                 |
//|                                                                  |
bool IsSummerTime(){
    
   switch(Year()){
      case 2020: if(StringToTime("2020.3.8") <=TimeCurrent()&&TimeCurrent()<=StringToTime("2020.11.1"))return true; break;
      case 2021: if(StringToTime("2021.3.14")<=TimeCurrent()&&TimeCurrent()<=StringToTime("2021.11.7"))return true; break;
      case 2022: if(StringToTime("2022.3.13")<=TimeCurrent()&&TimeCurrent()<=StringToTime("2022.11.6"))return true; break;
      case 2023: if(StringToTime("2023.3.12")<=TimeCurrent()&&TimeCurrent()<=StringToTime("2023.11.5"))return true; break;
      case 2024: if(StringToTime("2024.3.10")<=TimeCurrent()&&TimeCurrent()<=StringToTime("2024.11.3"))return true; break;
      case 2025: if(StringToTime("2025.3.9") <=TimeCurrent()&&TimeCurrent()<=StringToTime("2025.11.2"))return true; break;
      case 2026: if(StringToTime("2026.3.8") <=TimeCurrent()&&TimeCurrent()<=StringToTime("2026.11.1"))return true; break;
      case 2027: if(StringToTime("2027.3.14")<=TimeCurrent()&&TimeCurrent()<=StringToTime("2027.11.7"))return true; break;
      case 2028: if(StringToTime("2028.3.12")<=TimeCurrent()&&TimeCurrent()<=StringToTime("2028.11.5"))return true; break;
      case 2029: if(StringToTime("2029.3.11")<=TimeCurrent()&&TimeCurrent()<=StringToTime("2029.11.4"))return true; break;
      case 2030: if(StringToTime("2030.3.10")<=TimeCurrent()&&TimeCurrent()<=StringToTime("2030.11.3"))return true; break;
      case 2031: if(StringToTime("2031.3.9") <=TimeCurrent()&&TimeCurrent()<=StringToTime("2031.11.2"))return true; break;
      case 2032: if(StringToTime("2032.3.14")<=TimeCurrent()&&TimeCurrent()<=StringToTime("2032.11.7"))return true; break;
      case 2033: if(StringToTime("2033.3.13")<=TimeCurrent()&&TimeCurrent()<=StringToTime("2033.11.6"))return true; break;
      case 2034: if(StringToTime("2034.3.12")<=TimeCurrent()&&TimeCurrent()<=StringToTime("2034.11.5"))return true; break;
      case 2035: if(StringToTime("2035.3.11")<=TimeCurrent()&&TimeCurrent()<=StringToTime("2035.11.4"))return true; break;
      case 2036: if(StringToTime("2036.3.9") <=TimeCurrent()&&TimeCurrent()<=StringToTime("2036.11.2"))return true; break;
      case 2037: if(StringToTime("2037.3.8") <=TimeCurrent()&&TimeCurrent()<=StringToTime("2037.11.1"))return true; break;
      case 2038: if(StringToTime("2038.3.14")<=TimeCurrent()&&TimeCurrent()<=StringToTime("2038.11.7"))return true; break;
      case 2039: if(StringToTime("2039.3.13")<=TimeCurrent()&&TimeCurrent()<=StringToTime("2039.11.6"))return true; break;
      case 2040: if(StringToTime("2040.3.11")<=TimeCurrent()&&TimeCurrent()<=StringToTime("2040.11.4"))return true; break;      
   }
   return false;
}

//+------------------------------------------------------------------+
//|【関数】ゴトー日かどうか判定                                        |
//|                                                                  |
//|【戻値】true  : ゴトー日(補正後)                                 |
//|        false : それ以外                                           |
//+------------------------------------------------------------------+
bool IsTradeDate()
{
   int gotobi[5] = {5, 10, 15, 20, 25};
   int today = Day();
   int month = Month();
   int year  = Year();

   for(int i = 0; i < 5; i++)
   {
      int d = gotobi[i];

      // 月末を超える場合はスキップ
      if(d > DaysInMonth(year, month)) continue;

      // 対象日付の曜日を取得
      datetime t = StringToTime(
         StringFormat("%04d.%02d.%02d", year, month, d)
      );
      int w = TimeDayOfWeek(t); // 0=日, 6=土

      // 土日なら前営業日に補正
      if(w == 6)      d -= 1; // 土曜 → 金曜
      else if(w == 0) d -= 2; // 日曜 → 金曜

      if(today == d)
         return true;
   }
   return false;
}
int DaysInMonth(int year, int month)
{
   if(month == 2)
   {
      if((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
         return 29;
      return 28;
   }

   if(month == 4 || month == 6 || month == 9 || month == 11)
      return 30;

   return 31;
}

スポンサーリンク

IsTradeDate() 関数の解説

このEAでは、ゴトー日(5・10・15・20・25日)かどうかを自動で判定するために IsTradeDate() 関数を使用しています。

よくあるゴトー日EAでは、 「1月は◯日、2月は◯日…」と年・月ごとに日付を固定で記述しているものも多く、 毎年メンテナンスが必要になるケースがあります。

本サンプルEAではそのような手動管理を避け、 現在の日付からゴトー日に該当するかを動的に判定する設計にしています。

この IsTradeDate() 関数は、ゴトー日EAに限らず、

  • 月初・月末のみ取引するEA
  • 特定日(指標日・イベント日)だけ動かすEA
  • 曜日フィルタ付きEA

といった「日付条件・曜日条件EA」全般に応用可能です。

売買判定について

ゴトー日を自動判定する逆張りEAの作り方|IsTradeDate関数とマジックナンバー設計を解説

早朝にショートエントリーし、AM9:55に決済しています。利益が30pipsを超えているため、そこからすぐにロングエントリーしPM2:00に決済している動きとなっています。

利益が30pips未満の場合、ロングエントリーはしません。

決済タイミング

TP(指値)とSL(逆指値)を65pipsで管理していますが、時間で決済管理をしています。

ショートエントリー側

ショートポジションを持っている場合、AM9:55に強制決済します。

ロングエントリー側

ロングポジションを持っている場合、PM2:00に強制決済します。

パラメータとカスタマイズ

今回のパラメータ設定は以下の通りです:

  1. MagicNumber= 123456 ⇒ マジックナンバーです
  2. LotSize= 0.01 ⇒ ロット数です(0.01=1000通貨)
  3. A_Spread= 20 ⇒ エントリー時に許容するスプレッドの値です(20 = 2pips)
  4. Order_TP= 650 ⇒ ストップロスまでのポイントです(1000=100pips)
  5. Order_SL= 650 ⇒ ストップロスまでのポイントです(1000=100pips)
  6. Entry_Hour_S= 22 ⇒ 早朝エントリーする時間(サマータイム時) ※日本時間換算は+7時間
  7. Entry_Minute_S= 45 ⇒ 早朝エントリーする分(サマータイム時)
  8. Entry_Hour_W= 23 ⇒ 早朝エントリーする時間 ※日本時間換算は+7時間
  9. Entry_Minute_W= 45 ⇒ 早朝エントリーする分

また、同時に保持するポジションは最大1つです。

EAレポート結果

USDJPY(H1, 2023/01〜2025/12, 初期証拠金100万円, FXTFヒストリカル)での結果:

通貨ペア・時間足PF勝率最大DD取引回数備考
USDJPY M51.3054%4.56%200回利益はしっかり出ているがトレード回数は少ない
ゴトー日逆張りEAのバックテストレポート

まとめ

本記事では、ゴトー日を自動判定し、時間条件とマジックナンバーを組み合わせて制御するEA設計を、 学習用サンプルとして解説しました。

近年は、いわゆる「ゴトー日仲値の順張り」が機能しづらくなっており、 本EAはその前提を疑い、逆張りという視点でロジックを組み直した一例です。 収益性そのものよりも、日付・時間・ポジション管理をEAでどう扱うかを理解することを目的としています。

特に、IsTradeDate() によるゴトー日の自動判定や、 マジックナンバーを前提とした関数分離設計は、 ゴトー日EAに限らず、日付条件EA・イベントEA全般に応用可能です。

ソースコードがある程度読める方であれば、 本サンプルをベースに順張り版ゴトー日EAや、別の特定日トレードEAへ発展させることも容易です。 ぜひ、ご自身のロジック検証やEA設計の参考として活用してみてください。


✅ 今回のロジックをベースにしたEAサンプルも多数公開中

今回紹介したようなEAの売買ロジック・考え方をベースに、
当サイトではさまざまなFX自動売買EAのサンプルコードを公開しています。

ロジックの違いや設計の考え方を比較しながら、
自分に合ったEA構成を探したい方はぜひチェックしてみてください。


📊 【2025年最新】FX自動売買EAランキングも公開中!

当サイトの「どのEA(インジ)が実際に勝っているのか?」を知りたい方はこちら👇
PF(プロフィットファクター)や勝率で徹底比較した最新ランキングから、あなたに最適なEA(インジ)を見つけましょう。


EA開発初心者向けに、今後も実践的なMQL4関数を紹介していきます。
気になる機能やロジックがあれば、ぜひ他の記事もあわせてご覧ください!

コメント

  1. 新さんのアイコン より:

    いつもお世話になっております。
    ソースコードをコピペしてバックテストを試しましたが、
    パラメータ設定で0.01ロットにしても、1ロットでのエントリーになってしまう状態です。

    私の方の問題なんでしょうか?

タイトルとURLをコピーしました