メンテナンスは面倒だけど、自由度は高い
テキストファイルの読み込み方の応用編です。
エントリーを回避したい経済指標を列記したテキストファイルを事前に用意しておき、その情報をもとに経済指標発表前後のエントリーを回避するプログラムをご紹介します。
関数だけだと分かりづらいと思いましたので、今回はEA丸ごとです。
//+------------------------------------------------------------------+ //| Sample.mq4 | //| Copyright (c) 2018, りゅーき | //| https://autofx100.com/ | //+------------------------------------------------------------------+ #property copyright "Copyright (c) 2018, りゅーき" #property link "https://autofx100.com/" #property version "1.0" #property strict //+------------------------------------------------------------------+ //| ライブラリ | //+------------------------------------------------------------------+ #include <stderror.mqh> #include <stdlib.mqh> #include <WinUser32.mqh> #include <Original/Application.mqh> #include <Original/Basic.mqh> #include <Original/DateAndTime.mqh> #include <Original/LotSizing.mqh> #include <Original/OrderHandle.mqh> #include <Original/OrderReliable.mqh> //+------------------------------------------------------------------+ //| 定数 | //+------------------------------------------------------------------+ //#define //+------------------------------------------------------------------+ //| EAパラメータ設定情報 | //+------------------------------------------------------------------+ enum ENUM_SUMMER_TIME_TYPE{ SummerTimeType0 = 0, // 夏時間無し SummerTimeType1 = 1, // ロンドン基準 SummerTimeType2 = 2, // ニューヨーク基準 }; extern ENUM_SUMMER_TIME_TYPE SummerTimeType = SummerTimeType2; // 夏時間タイプ extern int SummerGMT_Offset = 3; // 夏時間のグリニッジ標準時との時差 extern int WinterGMT_Offset = 2; // 冬時間のグリニッジ標準時との時差 extern bool UseEconomicEvent = false; // 経済指標エントリーフィルターの使用 extern int BeforeEventMinute = 30; // ┣経済指標発表の何分前からエントリーを回避するか extern int AfterEventMinute = 30; // ┗経済指標発表の何分後からエントリーを再開するか //+------------------------------------------------------------------+ //| グローバル変数 | //+------------------------------------------------------------------+ // 共通 double gPipsPoint = 0.0; int gSlippage = 0; color gArrowColor[6] = {Blue, Red, Blue, Red, Blue, Red}; //BUY: Blue, SELL: Red // ローカルGMTオフセット int gLocalGMT_Offset = 0; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // ローカルPCのOSのタイムゾーンが日本ならば、常に9 gLocalGMT_Offset = -1 * (TimeGMTOffset() / 60 / 60); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // ----------------------------------------------------------------- // 仕掛けフィルター // ----------------------------------------------------------------- // サーバとローカルの時差計算 int timeDiff = calcTimeDifference(false, SummerTimeType, SummerGMT_Offset, WinterGMT_Offset, gLocalGMT_Offset); // 指標発表前後は仕掛けない ---------------------------------------- if(UseEconomicEvent){ bool eventFlg = isEconomicEventPeriod(BeforeEventMinute, AfterEventMinute, timeDiff); if(eventFlg){ // 指標発表前後なので後続の処理はスキップ return; } } } //+------------------------------------------------------------------+ //|【関数】経済指標期間判定 | //| | //|【引数】 IN OUT 引数名 説明 | //| --------------------------------------------------------- | //| ○ aBeforeEventMinute 指標発表n分前 | //| ○ aAfterEventMinute 指標発表n分後 | //| ○ aTimeDiff GMTオフセット | //| | //|【戻値】true: 指標発表時間帯である | //| false: 指標発表時間帯ではない | //| | //|【備考】なし | //+------------------------------------------------------------------+ bool isEconomicEventPeriod(int aBeforeEventMinute, int aAfterEventMinute, int aTimeDiff) { const string FileName = "エントリー回避する経済指標日.txt"; // /MQL4/Filesまたは/MQL4/tester/Files datetime eventDateAry[]; // 指標日時(必須) string eventSymbolAry[]; // 影響する通貨ペア(必須) string eventNameAry[]; // 指標名(任意) string tmpAry[]; string tmpAry2[]; int cnt = 0; int fileHandle = FileOpen(FileName, FILE_READ | FILE_TXT); if(fileHandle != INVALID_HANDLE){ while(FileIsEnding(fileHandle) == false){ string tmp = FileReadString(fileHandle); // 先頭が「//」で始まる場合はコメントと判断してスキップ if(StringSubstr(tmp, 0, 2) == "//"){ continue; } ArrayResize(eventDateAry, cnt + 1); ArrayResize(eventSymbolAry, cnt + 1); ArrayResize(eventNameAry, cnt + 1); int aryNum = StringSplit(tmp, '=', tmpAry); if(aryNum == 2){ eventDateAry[cnt] = StringToTime(tmpAry[0]); eventSymbolAry[cnt] = StringTrimRight(StringTrimLeft(tmpAry[1])); eventNameAry[cnt] = ""; }else if(aryNum == 3){ eventDateAry[cnt] = StringToTime(tmpAry[0]); eventSymbolAry[cnt] = StringTrimRight(StringTrimLeft(tmpAry[1])); eventNameAry[cnt] = StringTrimRight(StringTrimLeft(tmpAry[2])); }else{ // エラー Print(FileName, "の中身が正しく記述されていません。"); return(false); } cnt++; } FileClose(fileHandle); } // バックテストの時は、TimeLocal()はバックテスト日時(サーバタイム)を返すので、その考慮が必要 datetime localTime; if(IsTesting() || IsOptimization()){ localTime = TimeCurrent() + aTimeDiff * 60 * 60; }else{ localTime = TimeLocal(); } // 現在が指標日時前後であり、通貨ペアが対象のものであれば、エントリー回避するためにtrueを返す for(int i = 0; i < ArraySize(eventDateAry); i++){ if(localTime >= eventDateAry[i] - aBeforeEventMinute * 60 && localTime <= eventDateAry[i] + aAfterEventMinute * 60){ int aryNum = StringSplit(eventSymbolAry[i], ',', tmpAry2); for(int j = 0; j < ArraySize(tmpAry2); j++){ string symbol = StringTrimRight(StringTrimLeft(tmpAry2[j])); if(symbol == "ALL" || StringFind(Symbol(), symbol) >= 0){ return(true); } } } } return(false); }
この他に用意する必要があるものは「エントリー回避する経済指標日.txt」というテキストファイルです。
// =================================================================== // ■概要 // エントリーを回避したい経済指標を記載します。 // // ■記載ルール // yyyy.mm.dd hh:MM = 通貨シンボル = 指標名 // // 項目 全半 必須 説明 // ------------------------------------------------------------------ // yyyy.mm.dd hh:MM 半角 ○ 経済指標の発表日時(日本時間) // 通貨シンボル 半角 ○ 影響を受ける通貨(大文字で3文字) // 指標名 任意 経済指標名(半角イコール「=」使用禁止) // // [OK例] 2018.04.23 18:00 = USD = サンプル指標 // // ■通貨シンボルの補足 // 1指標が複数通貨に影響を与える場合は、カンマ区切りで記載します。 // // [OK例] 2018.04.23 18:00 = USD,EUR,JPY = サンプル指標 // // 米雇用統計等、全ての通貨に影響を与える場合は、ALLと記載します。 // // [OK例] 2018.04.23 18:00 = ALL = サンプル指標 // // ■指標名の補足 // 指標名を省略する場合は、指標名の直前に付ける半角イコール「=」も記載し // ないでください。 // // [OK例] 2018.04.23 18:00 = ALL // // ■その他の補足 // 冒頭に半角スラッシュを2つ繋げる「//」と、その行はコメントとみな // して読み飛ばします。 // // このファイルは、以下の2箇所に設置してください。 // MQL4/tester/Files → バックテスト用 // MQL4/Files → リアルタイム用(フォワードテスト、本番) // // ■書き方の一例 // 2018.04.30 21:00 = EUR,JPY = 経済指標1 // 2018.05.01 01:00 = USD,GBP,CAD = 経済指標2 // 2018.05.01 19:45 = ALL = 経済指標3 // 2018.05.02 20:45 = EUR,JPY // 2018.05.04 19:30 = EUR // 2018.05.04 20:30 = ALL // =================================================================== 2018.09.25 21:00 = EUR,JPY = 何かの経済指標 2018.09.26 21:00 = USD = どこかの経済指標
このテキストファイルはリアルタイムで使用する場合は/MQL4/Filesに、バックテストで使用する場合は/MQL4/tester/Filesに設置してください。
テキストファイルの記載方法は上記のコメントをお読みください。
自分でテキストファイルを用意する必要があるので、運用方法としては毎週末に翌週分を記載しておく感じになるでしょうか。
サーバ時間とローカル時間の時差を補正することで、テキストファイル内の指標発表時刻を日本時間で記載することが可能になっています。
サーバ時間のGMTオフセットが+3なら、ローカル時間は通常+9(日本を想定)ですから、timeDiffは6となります。
ポイントはisEconomicEventPeriod関数です。引数として指標発表時間n分前(BeforeEventMinute)と指標発表時間n分後(AfterEventMinute)と時差(timeDiff)の3つを渡すことで、現在時刻が指標発表前後かを判定し、結果をtrueかfalseで返してくれます。