前回でFX自動売買のベース部分が完成したのでこれからFX自動化開発(ワイコフ)としてFXのロジックのブラッシュアップをしていきます。 プログラムなどの技術的な部分をAIに補ってもらえて、クリエイティブな部分に自分のリソースを割けるのはとても有意義ですね。

レンジの定義ロジックの実装
ワイコフ理論では、価格が「レンジ(Trading Range)」にあるのか、そこから逸脱しようとしているのかを把握することが全ての始まりです。ここでは、過去の高値・安値を計算し、現在の相場環境を数値化するクラス CSignalWyckoff を作成します。
新規ファイルの作成
作成ファイル: Experts/Wyckoff_EA/SignalWyckoff.mqh

まず、ロジック専用の新しいファイルを作成します。Cursorで新規ファイル SignalWyckoff.mqh を作成し、以下のコードを記述してください。
SignalWyckoff.mqh
//+------------------------------------------------------------------+
//| SignalWyckoff.mqh |
//| Wyckoff Logic Class |
//+------------------------------------------------------------------+
#property strict
class CSignalWyckoff
{
private:
string m_symbol; // 通貨ペア
ENUM_TIMEFRAMES m_period; // 時間足
int m_range_period; // レンジ計算期間(バー数)
double m_range_high; // レンジ最高値
double m_range_low; // レンジ最安値
public:
// コンストラクタ
CSignalWyckoff() : m_symbol(_Symbol), m_period(PERIOD_CURRENT), m_range_period(20) {}
~CSignalWyckoff() {}
// 初期化メソッド
void Init(string symbol, ENUM_TIMEFRAMES period, int range_period)
{
m_symbol = symbol;
m_period = period;
m_range_period = range_period;
}
// データ更新メソッド(OnTick内で呼び出す)
void Update()
{
// 過去 m_range_period 本の最高値・最安値のインデックスを取得(現在の足を含めないためにシフト1から開始)
// iHighest/iLowest [3, 4]
int high_idx = iHighest(m_symbol, m_period, MODE_HIGH, m_range_period, 1);
int low_idx = iLowest(m_symbol, m_period, MODE_LOW, m_range_period, 1);
if(high_idx != -1) m_range_high = iHigh(m_symbol, m_period, high_idx);
if(low_idx != -1) m_range_low = iLow(m_symbol, m_period, low_idx);
}
// ゲッター(値を外部から取得するための関数)
double GetRangeHigh() { return m_range_high; }
double GetRangeLow() { return m_range_low; }
// 現在価格がレンジ内にあるか判定
bool IsInRange(double price)
{
return (price <= m_range_high && price >= m_range_low);
}
// レンジに対する相対位置を取得 (0.0 = 安値, 1.0 = 高値)
double GetRelativePosition(double price)
{
if(m_range_high - m_range_low == 0) return 0.5;
return (price - m_range_low) / (m_range_high - m_range_low);
}
};
//+------------------------------------------------------------------+
このクラスは、指定した期間(RangePeriod)内の最高値と最安値を計算し、現在の価格がレンジのどの位置にあるかを判定します。
Main.mq5の修正
修正コード
//+------------------------------------------------------------------+
//| Main.mq5 |
//| Wyckoff Logic EA |
//+------------------------------------------------------------------+
#property copyright "Wyckoff Trader"
#property version "1.01"
#property strict
#include <Trade\Trade.mqh>
#include "SignalWyckoff.mqh" // 作成したクラスをインクルード
//--- input parameters
input int InpMagicNumber = 123456;
input double InpLots = 0.01;
input int InpRangePeriod = 20; // レンジ期間設定を追加
//--- global variables
CTrade trade;
CSignalWyckoff wyckoff; // ワイコフロジックのインスタンス
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
trade.SetExpertMagicNumber(InpMagicNumber);
// ワイコフクラスの初期化
wyckoff.Init(_Symbol, PERIOD_CURRENT, InpRangePeriod);
Print("Wyckoff EA Initialized.");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// 1. データの更新
wyckoff.Update();
// 2. 現在のレート取得
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double close = iClose(_Symbol, PERIOD_CURRENT, 1); // 確定足の終値
// 3. デバッグ表示(テスターの「操作ログ」で確認するため)
// 毎回表示するとログが溢れるので、新しい足ができた時だけ表示するなどの工夫が通常は必要ですが、
// 今回は動作確認のためCommentでチャート左上に表示します。
string comment = StringFormat(
"Wyckoff EA Status\n"
"-----------------\n"
"Range High: %.5f\n"
"Range Low: %.5f\n"
"Close Price: %.5f\n"
"In Range: %s\n"
"Rel Pos: %.2f%%",
wyckoff.GetRangeHigh(),
wyckoff.GetRangeLow(),
close,
wyckoff.IsInRange(close) ? "Yes" : "No",
wyckoff.GetRelativePosition(close) * 100
);
Comment(comment);
// --- ここからエントリーロジック(次回フェーズで実装) ---
// 現在はランダムトレードを無効化し、数値の確認に集中します
}
//+------------------------------------------------------------------+
ヒューマンエラーが怖いのでコンポーザーで修正を依頼しました。
CursorのAI
以下のように Main.mq5 を修正しました。
変更内容
- SignalWyckoff の組み込み
- #include “SignalWyckoff.mqh” を追加
- グローバルで CSignalWyckoff wyckoff を宣言
- Input
- 既存の InpMagicNumber, InpLots に加え、InpRangePeriod = 20(レンジ期間)を追加
- OnInit
- wyckoff.Init(_Symbol, PERIOD_CURRENT, InpRangePeriod) でワイコフクラスを初期化
- 後のエントリ実装に備え、trade.SetTypeFillingBySymbol を設定
- OnDeinit
- EA 終了時に Comment(“”) でチャート左上の表示を消す処理を追加
- OnTick
- wyckoff.Update() でレンジ High/Low を更新
- 確定足の終値 close で GetRangeHigh(), GetRangeLow(), IsInRange(close), GetRelativePosition(close) を取得
- 上記を Comment() でチャート左上に表示(計算結果の確認用)
- ランダムトレード
- 計算確認に集中するため、以前のランダム Buy/Sell テストは削除済みです。
動作確認の仕方
- ストラテジーテスターで実行するか、チャートにアタッチすると、左上に次のように表示されます。
- Range High / Range Low: 直近 InpRangePeriod 本(現在足を除く)の高値・安値
- Close Price: 直近確定足の終値
- In Range: その終値がレンジ内なら “Yes”、外なら “No”
- Rel Pos: レンジ内での相対位置(0%=安値側、100%=高値側)
バックテストやリアルタイムで、表示される数値とチャートの値が一致しているか確認してください。
コンパイルとテスト
- コンパイルしてエラーがないか確認してください。
- ストラテジーテスターを「ビジュアルモード(可視化)」で実行してください。
- チャートの左上に 「Range High」「Range Low」 などの数値が表示され、価格の動きに合わせて変動していれば、フェーズ1は完了です。
コンパイルしてエラーがないか確認してください。

つくる人OK!
ストラテジーテスターを「ビジュアルモード(可視化)」で実行してください。





実行中!問題なし!
前回と同条件でテストを実行しましたが。最初のテストよりも倍以上、
処理に時間がかかっています(3分ほど)。
チャートの左上に 「Range High」「Range Low」 などの数値が表示され、価格の動きに合わせて変動していれば、フェーズ1は完了です。





ちゃんとのってる!OK
FX開発特化型LMの回答
フェーズ1の完了、お疲れ様でした!レンジ(Trading Range)の数値が正しく取得できている状態で、素晴らしい進捗です。それでは、「フェーズ2: セットアップ(Spring/Upthrustの検知)」 に進みます。



どんどん進めてこう!