「米雇用統計が発表された瞬間、スプレッドが異常に広がって、EAが不利な価格で約定した」
という経験はないでしょうか。
経済指標の発表前後は、レートが数秒で大きく動きます。
通常のロジックのまま自動売買を続けると、意図しないタイミングでエントリーしてしまいます。
MQL5には、このタイミング判定に使える経済指標カレンダー機能が、
標準で組み込まれています。
この記事では、`CalendarValueHistory`関数で、
指標発表の日時と重要度を取得し、
「重要度の高い指標が近いときだけ新規エントリーを止める」判定関数を作る方法を、
実際に動くコードで解説します。
MQL5の経済指標カレンダー機能とは
MQL5には`Calendar`系の関数群があり、
MetaTrader 5が保持している経済指標カレンダーのデータに、
プログラムから直接アクセスできます。
MQL4にはこの機能自体が存在せず、外部のWebRequestや、
手動での指標カレンダー確認に頼るしかありませんでした。
CalendarValueHistoryで期間内の指標を取得する
指定した期間内に発表される(された)指標の一覧を取得するのが、
`CalendarValueHistory`です。
bool CalendarValueHistory( MqlCalendarValue& values[], //取得結果を受け取る配列 datetime datetime_from, //期間の開始 datetime datetime_to=0, //期間の終了(省略可) const string country_code=NULL, //国コード(空欄で全部) const string currency=NULL //通貨コード(空欄で全部) );
戻り値は取得の成否で、
実際のデータは第1引数の`MqlCalendarValue`配列に格納されます。
補足: MqlCalendarValueには、
actual_valueやforecast_value等のメンバーがあります。
これらの数値は、実際の値の1,000,000倍で格納されています。
桁を戻さずに比較すると、期待した結果になりません。
この記事のサンプルでは数値そのものは使わず、
発表の有無や重要度だけを判定に使うため影響しません。
CalendarEventByIdで重要度(importance)を調べる
`MqlCalendarValue`には指標の名前や重要度が直接入っていないため、
`event_id`を使って`CalendarEventById`から詳細情報を引きます。
bool CalendarEventById( ulong event_id, //イベントID MqlCalendarEvent& event //イベントの説明を受け取る変数 );
`MqlCalendarEvent`の`importance`メンバーは、
`ENUM_CALENDAR_EVENT_IMPORTANCE`型です。
次の4段階があります。
| 値 | 意味 |
|---|---|
| CALENDAR_IMPORTANCE_NONE | 重要度未設定 |
| CALENDAR_IMPORTANCE_LOW | 低重要度 |
| CALENDAR_IMPORTANCE_MODERATE | 中程度の重要度 |
| CALENDAR_IMPORTANCE_HIGH | 高重要度(雇用統計・政策金利など) |
「直近N分以内に高重要度指標があるか」を判定する関数を作る
やりたいことは、現在時刻の前後一定時間以内に、
`CALENDAR_IMPORTANCE_HIGH`の指標が含まれるかどうかの判定です。
この1つの判定関数さえ作れば、既存のEAのエントリー処理の先頭に、
1行足すだけで指標対策を組み込めます。
設計思想: エントリー判定と指標判定を分離する
指標判定のロジックをエントリーロジックの中に混ぜ込むと、
後から時間幅を変えたり判定条件を増やしたりするたびに、
EA全体を読み直す必要が出てきます。
判定を独立した関数に切り出しておけば、他のEAにもそのまま流用できます。
bool IsNearHighImpactEvent(int windowMinutes)
{
MqlCalendarValue values[];
datetime from = TimeCurrent() - windowMinutes * 60;
datetime to = TimeCurrent() + windowMinutes * 60;
if(!CalendarValueHistory(values, from, to, NULL, NULL))
{
Print("CalendarValueHistoryに失敗しました。error=", GetLastError());
return(false);
}
for(int i = 0; i < ArraySize(values); i++)
{
MqlCalendarEvent event;
if(!CalendarEventById(values[i].event_id, event))
continue;
if(event.importance == CALENDAR_IMPORTANCE_HIGH)
{
Print("高重要度指標が近い: ", event.name);
return(true);
}
}
return(false);
}
実際に動くコード全体(高重要度指標の前後だけエントリーを止めるEA)
上の判定関数を組み込んだ、実際にMetaEditorでコンパイルできるEAの全体です。
//+------------------------------------------------------------------+
//| CalendarNewsFilterEA.mq5 |
//| Copyright 2026, FX-EA System Project Creator |
//| https://creator.fx-ea-system-project.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, FX-EA System Project Creator"
#property link "https://creator.fx-ea-system-project.com/"
#property version "1.00"
input int NewsWindowMinutes = 30; //指標発表の前後、止める時間(分)
input double LotSize = 0.10;
//+------------------------------------------------------------------+
//| 直近NewsWindowMinutes分以内に高重要度指標があるか判定する |
//+------------------------------------------------------------------+
bool IsNearHighImpactEvent(int windowMinutes)
{
MqlCalendarValue values[];
datetime from = TimeCurrent() - windowMinutes * 60;
datetime to = TimeCurrent() + windowMinutes * 60;
if(!CalendarValueHistory(values, from, to, NULL, NULL))
{
Print("CalendarValueHistoryに失敗しました。error=", GetLastError());
return(false);
}
for(int i = 0; i < ArraySize(values); i++)
{
MqlCalendarEvent event;
if(!CalendarEventById(values[i].event_id, event))
continue;
if(event.importance == CALENDAR_IMPORTANCE_HIGH)
{
Print("高重要度指標が近い: ", event.name);
return(true);
}
}
return(false);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
if(PositionsTotal() > 0)
return; //保有中は何もしない(この記事の主題はエントリー抑制のため)
if(IsNearHighImpactEvent(NewsWindowMinutes))
return; //指標発表の前後はエントリーしない
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = LotSize;
request.type = ORDER_TYPE_BUY;
request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
request.deviation = 10;
if(!OrderSend(request, result))
Print("OrderSendに失敗しました。retcode=", result.retcode);
}
注意: このサンプルは判定ロジックの見せ方に絞った最小構成です。
実運用では、損切りや利益確定、ロット管理などの実装を別途組み込んでください。
MetaEditorで実際に動かす手順
- MetaEditorで「ファイル」→「新規作成」→「エキスパートアドバイザー」で「CalendarNewsFilterEA」を作成する
- ウィザードの中身を削除し、上のコードを丸ごと貼り付ける
- F7キーでコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
- デモ口座のチャートに適用し、「エキスパート」タブに「高重要度指標が近い」のログが指標発表前後だけ出るか確認する
よくあるエラーと注意点
実際にコンパイル・実行してみると、つまずきやすいポイントが2つあります。
CalendarValueHistoryがfalseを返す・空配列になる
端末の経済指標カレンダーのデータが、未取得の状態だと空になることがあります。
一度MetaTrader 5の「ツール」メニューから「オプション」
→「経済指標カレンダー」を開き、データが表示されるか確認してください。
重要度の判定が甘い・厳しいと感じる
`CALENDAR_IMPORTANCE_HIGH`だけでなく、
`CALENDAR_IMPORTANCE_MODERATE`以上も止めたい場合は、
比較演算子を`>=`に変えれば範囲を広げられます。
要点: MQL4にはCalendar系の関数が存在しません。
同じ判定をしたい場合は、
WebRequestで外部の指標カレンダーAPIを呼ぶなど別の実装が必要になります。
MQL5だけで完結できる点が、明確な違いです。
よくある質問
CalendarValueHistoryの実装でよく検索されている疑問を、
3つにまとめて回答します。
通貨ペアごとに関係ある国の指標だけに絞れますか?
`CalendarValueHistory`の第4・第5引数に、
国コード・通貨コードを渡せば絞り込めます。
たとえばUSD関連だけにしたい場合は、`currency`に”USD”を渡してください。
指標カレンダーのデータはどこから来ていますか?
MetaTrader 5端末が定期的に取得・キャッシュしている、
経済指標カレンダーのデータです。
ブローカーやMetaQuotes側のサーバーから配信されています。
プログラム側で独自にデータを用意する必要はありません。
ポジション保有中に指標発表をまたいでも大丈夫ですか?
この記事の判定関数は、新規エントリーを止める用途のみです。
保有中のポジションをどう扱うかは、
別のロジック(強制決済・損切り幅の拡大等)として設計する必要があります。
【MQL5】経済指標発表の前後だけEAを止めたい?CalendarValueHistoryで指標発表時刻を取得する方法:まとめ
MQL5に標準搭載されている経済指標カレンダー機能を使えば、
`CalendarValueHistory`と
`CalendarEventById`の組み合わせだけで、
「重要度の高い指標が近いか」を
判定できます。
判定ロジックを独立した関数として切り出しておけば、既存のEAのエントリー処理の先頭に、
1行足すだけで指標対策を組み込めます。
MQL4にはこの機能自体が存在しない、MQL5ならではの差別化ポイントです。
コメント