前回まででワイコフ理論の基本的なロジックが実装できました。今回は予測不能な動きする経済指標では、トレードを行わない。という安全装置を実装します。
前回の記事

内蔵経済カレンダー機能の連携
FX開発特化型LMの回答
それでは、仕上げとなる「フェーズ4: 経済指標フィルター(リスク管理)」に入りましょう。 ワイコフ理論は「自然な需給のバランス」を前提としています。雇用統計やCPIのような突発的なニュースによる乱高下(ギャンブル的な動き)は、テクニカル分析を無効化するため、
この時間は「何もしない」のが正解です。
MQL5には強力な内蔵経済カレンダー機能がありますので、これを活用します。
NewsFilter.mqh の作成
新しいファイル NewsFilter.mqh を作成し、以下のコードを記述してください。 このクラスは、チャートの通貨ペア(例: USDJPYならUSDとJPY)に関連する「重要度が高い(High)」ニュースを自動で検出し、その前後30分間(設定可)を「トレード禁止時間」と判定します。
NewsFilter.mqhに記述するコード
//+------------------------------------------------------------------+
//| NewsFilter.mqh |
//| Economic Calendar Filter |
//+------------------------------------------------------------------+
#property strict
class CNewsFilter
{
private:
string m_symbol;
string m_currency_base;
string m_currency_profit;
int m_before_min; // ニュース前の停止時間(分)
int m_after_min; // ニュース後の停止時間(分)
bool m_use_filter; // フィルターを使うかどうか
public:
CNewsFilter() : m_before_min(30), m_after_min(30), m_use_filter(true) {}
~CNewsFilter() {}
// 初期化
void Init(string symbol, bool use_filter, int before_min, int after_min)
{
m_symbol = symbol;
m_use_filter = use_filter;
m_before_min = before_min;
m_after_min = after_min;
// 通貨ペアから通貨コードを取得 (例: "USDJPY" -> "USD", "JPY")
m_currency_base = SymbolInfoString(m_symbol, SYMBOL_CURRENCY_BASE);
m_currency_profit = SymbolInfoString(m_symbol, SYMBOL_CURRENCY_PROFIT);
}
// 今がニュースの時間(トレード禁止)かどうか判定
bool IsNewsTime()
{
if(!m_use_filter) return false;
MqlCalendarValue values[];
datetime start_time = TimeTradeServer() - (m_before_min * 60); // 検索開始:現在時刻 - N分
datetime end_time = TimeTradeServer() + (m_after_min * 60); // 検索終了:現在時刻 + N分
// 1. カレンダーから期間内のイベント値を取得
// 実際にはイベントIDが必要なため、範囲を少し広めに取って変更履歴を取得するのが一般的ですが、
// ここでは簡易的に CalendarValueHistory を使用します。
// Base通貨のニュースチェック
if(CheckNewsForCurrency(m_currency_base, start_time, end_time)) return true;
// Profit通貨のニュースチェック
if(CheckNewsForCurrency(m_currency_profit, start_time, end_time)) return true;
return false;
}
private:
// 指定通貨のニュースがあるかチェック
bool CheckNewsForCurrency(string currency, datetime start, datetime end)
{
MqlCalendarValue values[];
// 指定期間・指定通貨のイベントを取得
if(CalendarValueHistory(values, start, end, NULL, currency))
{
for(int i=0; i<ArraySize(values); i++)
{
MqlCalendarEvent event;
// イベントの詳細(重要度)を取得
if(CalendarEventById(values[i].event_id, event))
{
// 重要度が高い(HIGH)場合のみ禁止とする
if(event.importance == CALENDAR_IMPORTANCE_HIGH)
{
// 念のため、イベント発生時刻が禁止期間内か再確認
if(values[i].time >= start && values[i].time <= end)
{
return true; // ニュースあり
}
}
}
}
}
return false;
}
};
//+------------------------------------------------------------------+
つくる人こちらは手動で作成!
Main.mq5 のアップデート
作成したフィルターをEAに組み込みます。 ニュースの時間帯はチャート上に「NEWS FILTER ACTIVE」と表示させ、エントリーをブロックします。
Main.mq5アップデート分
//+------------------------------------------------------------------+
//| Main.mq5 |
//| Wyckoff Logic EA |
//+------------------------------------------------------------------+
#property copyright "Wyckoff Trader"
#property version "1.04" // Phase 4 (Final)
#property strict
#include <Trade\Trade.mqh>
#include "SignalWyckoff.mqh"
#include "NewsFilter.mqh" // 追加
//--- input parameters
input int InpMagicNumber = 123456;
input double InpLots = 0.01;
input int InpRangePeriod = 20;
// --- Phase 3 Parameters ---
input bool InpUseFilter = true;
input double InpPinBarRatio = 2.0;
input double InpVolMult = 1.5;
// --- Phase 4 Parameters (ニュースフィルター) ---
input bool InpUseNewsFilter = true; // ニュースフィルターを使うか
input int InpNewsBefore = 30; // 指標発表前の停止時間(分)
input int InpNewsAfter = 30; // 指標発表後の停止時間(分)
//--- global variables
CTrade trade;
CSignalWyckoff wyckoff;
CNewsFilter newsFilter; // インスタンス追加
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
trade.SetExpertMagicNumber(InpMagicNumber);
// ワイコフ初期化
wyckoff.Init(_Symbol, PERIOD_CURRENT, InpRangePeriod);
// ニュースフィルター初期化
newsFilter.Init(_Symbol, InpUseNewsFilter, InpNewsBefore, InpNewsAfter);
Print("Wyckoff EA Phase 4 (Full) Initialized.");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
static datetime last_bar_time = 0;
// 1. ニュースフィルターのチェック (毎ティック確認しても良いが、重い場合はバー更新時のみにする)
// ここでは安全のため毎ティック確認し、ニュース時間なら即リターン
if(newsFilter.IsNewsTime())
{
Comment("=== NEWS FILTER ACTIVE ===\nTrading Paused due to High Impact News");
return; // トレード処理を行わずに終了
}
// --- ここから下は通常ロジック ---
datetime current_bar_time = iTime(_Symbol, PERIOD_CURRENT, 0);
if(last_bar_time == current_bar_time) return;
last_bar_time = current_bar_time;
// 2. データ更新
wyckoff.Update(1);
// 3. セットアップ判定
bool isSpring = wyckoff.CheckSpring(1);
bool isUpthrust = wyckoff.CheckUpthrust(1);
// 4. トリガー判定
bool isBullTrigger = false;
bool isBearTrigger = false;
if (isSpring)
{
bool pattern = wyckoff.IsPinBar(1, true, InpPinBarRatio) || wyckoff.IsEngulfing(1, true);
bool volume = wyckoff.IsVolumeSurge(1, InpVolMult);
if (!InpUseFilter || (pattern && volume)) isBullTrigger = true;
}
if (isUpthrust)
{
bool pattern = wyckoff.IsPinBar(1, false, InpPinBarRatio) || wyckoff.IsEngulfing(1, false);
bool volume = wyckoff.IsVolumeSurge(1, InpVolMult);
if (!InpUseFilter || (pattern && volume)) isBearTrigger = true;
}
// 5. アクション
if(isBullTrigger)
{
Print("Strong Spring Entry Signal!");
// 矢印等の描画処理(省略または既存コード維持)
// trade.Buy(...);
}
if(isBearTrigger)
{
Print("Strong Upthrust Entry Signal!");
// 矢印等の描画処理
// trade.Sell(...);
}
// デバッグ表示(ニュース時は上書きされるため、通常時のみ表示)
string comment = StringFormat(
"Wyckoff Logic: Active\n"
"Range: %.5f - %.5f\n"
"Last Signal: %s",
wyckoff.GetRangeHigh(), wyckoff.GetRangeLow(),
isBullTrigger ? "BUY" : (isBearTrigger ? "SELL" : "Wait")
);
Comment(comment);
}
//+------------------------------------------------------------------+
アップデートなのでCorsorに依頼します。
CursorのAI
反映しました。変更点は次のとおりです。
組み込み内容
- バージョン
- #property version “1.04”(Phase 4 Final)
- NewsFilter の組み込み
- #include “NewsFilter.mqh”
- グローバル変数に CNewsFilter newsFilter; を追加
- 追加 input パラメータ
- InpUseNewsFilter (true) … ニュースフィルターの有効/無効
- InpNewsBefore (30) … 指標発表前の停止時間(分)
- InpNewsAfter (30) … 指標発表後の停止時間(分)
- OnInit
- newsFilter.Init(_Symbol, InpUseNewsFilter, InpNewsBefore, InpNewsAfter); を追加
- 起動メッセージを “Wyckoff EA Phase 4 (Full) Initialized.” に変更
- OnTick の流れ
- 先頭でニュース判定
newsFilter.IsNewsTime() が true のとき
- Comment(“=== NEWS FILTER ACTIVE ===\nTrading Paused due to High Impact News”); を表示
- その場で return し、以降のエントリー・矢印描画は実行しない
- ニュース時間でないときだけ、これまで通り新足判定 → ワイコフロジック → トリガー → 矢印描画を実行
- 既存処理の維持
- 矢印の ObjectCreate 戻り値チェック(if で囲む形式)
- 青/赤の矢印描画(StrongSpring / StrongUpthrust)
- trade.Buy / trade.Sell はコメントアウトのまま
- OnDeinit で Comment(“”) を実行
ニュース時間帯ではチャートに「NEWS FILTER ACTIVE」と表示され、その間はエントリーと矢印描画が行われません。
最終確認とテスト
エラーがないことを確認してください。





OK!さあ!次!
しかしここで問題が!
バックテストで確認できないこと
使っているXMMT5ではバックテストで過去の経済指標カレンダーを読み込みできないようです。
リアルタイムでのカレンダー読み込みはできるようなので。
テストはデモ口座で実際に経済指標の時間に出来るか確認していきます。
基本開発完了!
FX開発特化型LMの回答
これで、ワイコフ理論に基づいたEAの基本開発は完了です!
- 環境認識: レンジの自動定義 完了
- セットアップ: スプリング/アップスラストの検知 完了
- トリガー: ピンバー/包み足 + 出来高による厳選 完了
- リスク管理: 経済指標フィルター 実装済み:経過観察中
お疲れ様でした。もし実際の運用に向けて「利食い・損切りのロジック(トレーリングストップなど)」を追加したい場合や、コードの微調整が必要であれば、いつでもご相談ください。



やりましたー!!基本ロジックは2日ほどで完成です。
次は実際に注文できるように設定したあと
独自のカスタマイズで勝てるEAをつくるぞー!
次回は実際に注文するときのアクションを追加して。「どれだけ稼げるか」
検証をすすめていきたいです。