English Deutsch
preview
プライスアクション分析ツールキットの開発(第28回):Opening Range Breakout Tool

プライスアクション分析ツールキットの開発(第28回):Opening Range Breakout Tool

MetaTrader 5 |
36 0
Christian Benjamin
Christian Benjamin

内容



はじめに

2010年5月6日、米国株式市場は悪名高い「フラッシュクラッシュ」に見舞われました。これは息を呑むような急落で、E-Mini S&P 500先物における巨大なアルゴリズム主導の売り注文が高頻度取引による一斉清算を誘発し、ダウ平均株価はわずか数分で約1,000ドルも暴落した後、同じくらい急速に反発しました。この劇的な出来事は重大な脆弱性を露わにしました。つまり、いかに力強く見えても未確認の価格ブレイクに反応してしまうと、流動性が枯渇し市場が急反転したときにトレーダーが置き去りにされてしまうという点です。

ブレイクアウトとは、価格が明確に定義された境界(たとえばセッションの始まりの高値や安値)を決定的に超えることであり、需要または供給が相手方を圧倒したことを示します。真のブレイクアウトを見極めることは不可欠です。なぜなら、真のブレイクアウトは持続的なトレンドの始まりを示すことが多い一方、偽のブレイクアウトに飛び乗ってしまうと、結果的に騙し(Whipsaw)による損失を被るからです。

オープニングレンジブレイクアウト(ORB: Opening Range Breakout)戦略は、この課題に対応します。まず、セッションの始まりの区間(任意の時間幅で設定可能)の高値と安値を捉え、それをチャート上に長方形として表示します。この範囲は視覚的な目印であると同時に、正確なトリガーレベルとして機能します。価格が長方形を超え、その境界をリテストしてから再度ブレイクする場合にのみエントリーを確認することで、ノイズを排除し、実際の市場の確信によって動かされた値動きを抽出します。

本記事では、以下の特徴を備えたプロフェッショナルなMQL5エキスパートアドバイザー(EA)実装のORBをご紹介します。

  • メインループを煩雑にしない、カプセル化された値幅キャプチャ(セッションの始まりの高値・安値を追跡して表示)
  • 再利用可能なATRモジュールを用いた、ボラティリティ調整済みのストップおよびターゲット設定
  • 一時的なスパイクと実際のブレイクアウトを区別するリテスト確認ロジック
  • ダッシュボードラベルやグラフィカルオブジェクトによるチャート上での動的な可視化
  • 各ステップを整理し、セッション終了時にクリーンにリセットする明確なOnTick()内のステートマシン


オープニングレンジ

オープニングレンジとは、取引セッションの最初の数分間、通常は最初の15分または30分で形成される高値と安値の価格レベルを指します。この時間帯は、市場が前日の夜間ニュース、経済指標、機関投資家の動きに即座に反応する局面であり、通常は出来高とボラティリティが高くなります。トレーダーはこの範囲の上下限を基準点として利用し、上抜けまたは下抜けが発生すると、その方向へのモメンタムの可能性を示すシグナルになります。これらのレベルは、エントリー、ストップロス、ターゲットを明確に設定する取引計画を立てるのに役立つため、オープニングレンジは早期トレンド識別や体系的な日中戦略に実用的なツールとなります。

オープニングレンジを理解し、効果的に取引することで得られる日中市場での利点は、以下の通りです。

利点 詳細
早期トレンド検出
最初の15〜30分の範囲をブレイクするとモメンタムの可能性を示し、トレーダーは日中の値動きに沿いやすくなります。
明確な取引ルール
高値/安値の境界を正確に定義することで、客観的なエントリーポイントとストップレベルが得られ、裁量を減らせます。
リスク管理の組み込み
ストップは反対側の境界のすぐ内側に置けるため、リスクリワードが事前に明確になります。
時間効率と一貫性
取引を午前の時間帯に限定することで画面に張り付く時間を減らし、システム化しやすくなります。
市場横断的な適用性
株式、FX、先物、異なる時間軸に適用可能で、トレーダーの柔軟性を高めます。
ボラティリティの優位性
セッション初期の流動性とタイトなスプレッドを活用できます。
戦略の柔軟性  ブレイクアウト、リバーサル、スキャルピング戦略を1つの枠組みでサポートします。

本記事では、オープニングレンジを計算するために、主に2つの方法を使用します。

方法1:2本足レンジ

このアプローチは2本のローソク足のみに基づきます。まず、前回セッションの最後のローソク足を取り、その高値と安値を「昨日のクローズ時点の極値」として定義します。次に、当日セッションの最初のローソク足を取り、その高値と安値で「取引開始直後の値動き」を捉えます。オープニングレンジは、これら2本のローソク足の最高値と最安値の差で表されます。このコンパクトな計算により、早期のモメンタムを即座に把握し、その日のブレイクアウト水準を特定する助けとなります。

まず、取引セッションが始まる正確な日時を計算します(例:サーバー現地時間で09:30)。これはハードコードすることも、SymbolInfoSessionTradeを用いて計算することもできます。

// Example: use SymbolInfoSessionTrade to get today's session start
MqlDateTime nowStruct;
TimeToStruct(TimeCurrent(), nowStruct);
datetime from, to;
SymbolInfoSessionTrade(_Symbol,
                       (ENUM_DAY_OF_WEEK)nowStruct.day_of_week,
                       SessionIndex,
                       from, to);
// 'from' now holds seconds since midnight; convert to full datetime:
datetime todayStart = (TimeCurrent() - TimeCurrent()%86400) + from;

todayStart(当日開始時刻)以降で最初に現れるM1足のインデックスを取得し、その次の足(index+1)を「昨日の最終バー」として扱います。

// Find bar numbers
int firstBarToday = iBarShift(_Symbol, PERIOD_M1, todayStart, false);
int lastBarYesterday = firstBarToday + 1;
組み込みの系列関数を使用して、各バーインデックスの高値/安値を取得します。
double highYesterday = iHigh(_Symbol, PERIOD_M1, lastBarYesterday);
double lowYesterday  = iLow (_Symbol, PERIOD_M1, lastBarYesterday);

double highToday     = iHigh(_Symbol, PERIOD_M1, firstBarToday);
double lowToday      = iLow (_Symbol, PERIOD_M1, firstBarToday);
2つの高値のうち大きい方を取り、2つの安値のうち小さい方を取ってオープニングレンジを形成し、そのサイズを計算します。
double openingHigh = MathMax(highYesterday, highToday);
double openingLow  = MathMin (lowYesterday,  lowToday);
double openingSize = openingHigh - openingLow;

PrintFormat("Opening Range → High: %.5f   Low: %.5f   Size: %.5f",
            openingHigh, openingLow, openingSize);

方法2

特定のローソク足を使うのではなく、このアプローチでは、市場が開いた直後の数分間に記録された最高値と最安値によってオープニングレンジを定義します。これらの初期の極値を追跡することで、その日の初期センチメントとモメンタムをリアルタイムで捉えることができます。その後、このオープニングの高値と安値はブレイクアウトの基準水準となり、価格がそれらを超えたときに、そのセッション残りの時間におけるトレンドの可能性を示します。

まず、現在の取引セッションが始まる正確なタイムスタンプ(例:09:30)を計算します。SymbolInfoSessionTradeを使って「from」の秒数を取得し、それを完全なdatetimeに変換します。

// Calculate the session’s opening datetime
MqlDateTime nowStruct;
TimeToStruct(TimeCurrent(), nowStruct);

datetime fromSec, toSec;
SymbolInfoSessionTrade(_Symbol,
                       (ENUM_DAY_OF_WEEK)nowStruct.day_of_week,
                       SessionIndex,
                       fromSec, toSec);

// Build a full datetime from today’s midnight plus the session offset
datetime sessionStart = (TimeCurrent() - TimeCurrent() % 86400) + fromSec;

次に、sessionStart以降の最初のRangeMinutesの間における各1分足をループ処理し、それまでに記録された最高値と最安値を追跡します。

double orHigh = -DBL_MAX;
double orLow  =  DBL_MAX;

// Find the bar index at or just after sessionStart
int startIdx = iBarShift(_Symbol, TF, sessionStart, false);

// Loop through the first RangeMinutes bars (M1 timeframe)
for(int i = startIdx; i >= startIdx - (RangeMinutes - 1); i--)
{
  if(i < 0) break;  // safety check

  double h = iHigh(_Symbol, TF, i);
  double l = iLow (_Symbol, TF, i);

  orHigh = MathMax(orHigh, h);
  orLow  = MathMin(orLow, l);
}

最後に、orHighとorLowが得られます。ここから範囲の幅を計算し、現在の価格(Bid)をこれらのレベルと比較してシグナルを生成します。

double openingSize = orHigh - orLow;
PrintFormat("Opening Range (Method 2): High=%.5f Low=%.5f Size=%.5f",
            orHigh, orLow, openingSize);

// Breakout detection
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
if(bid > orHigh)
  Alert("Breakout Long at price " + DoubleToString(bid, _Digits));
else if(bid < orLow)
  Alert("Breakout Short at price " + DoubleToString(bid, _Digits));


戦略の概要

このEAはオープニングレンジブレイクアウト戦略を自動化します。まず、セッション開始直後の一定時間内における高値と安値の境界を特定します。各セッションの開始時に始値を記録し、その後のRangeMinutes(例:15分)にわたって高値の最大値と安値の最小値を継続的に更新していきます。この時間窓が終了すると、チャート上に水平ラインと矩形を描画し、初期のボラティリティが存在した価格の動きの範囲を視覚的に示します。ATRフィルター(設定可能なATR期間と乗数を使用)により、ボラティリティが一定のレベルに達した場合にのみ取引シグナルが発生します。

範囲が定義されると、EAは二段階のブレイクアウトを監視します。最初に、価格が範囲の外側でクローズする必要があります。次に、価格が範囲の境界まで戻り、再度そのレベルを超えてクローズする必要があります(これが「リテスト」です)。このリテストの確認がおこなわれると、EAはエントリーバーに上向きまたは下向きの矢印を描画し、ATRに基づいてストップロスとテイクプロフィットのレベルを計算し、シグナルを知らせるアラート(画面表示、メール、プッシュ通知)を発します。チャート上のダッシュボードはEAの現在の状態、ATR値、範囲の幅を常時更新し、すべては次のセッション、または深夜にきれいにリセットされます。

このEAはオープニングレンジブレイクアウト戦略を自動化します。まず、セッション開始直後の一定時間内における高値と安値の境界を特定します。各セッションの開始時に始値を記録し、その後のRangeMinutes(例:15分)にわたって高値の最大値と安値の最小値を継続的に更新していきます。この時間窓が終了すると、チャート上に水平ラインと矩形を描画し、初期のボラティリティが存在した価格の動きの範囲を視覚的に示します。ATRフィルター(設定可能なATR期間と乗数を使用)により、ボラティリティが一定のレベルに達した場合にのみ取引シグナルが発生します。

範囲が定義された後、EAは2段階のブレイクアウトを監視します。まず、価格が範囲外で終値をつける必要があります。次に、境界まで戻り、その後再び境界を超えて終値をつける必要があります(「リテスト」)。このリテストの確認がおこなわれると、EAはエントリーバーに上向きまたは下向きの矢印を描画し、ATRに基づいてストップロスとテイクプロフィットのレベルを計算し、シグナルを知らせるアラート(画面表示、メール、プッシュ通知)を発します。チャート上のダッシュボードは、EAの現在の状態、ATR値、範囲の幅を継続的に更新し、すべてが次のセッションまたは深夜にきれいにリセットされます。



EAコンポーネントの詳細

1. ファイルヘッダとプロパティ

冒頭では、#propertyを使って著作権情報、リンク、バージョンを設定します。単なる定型文ではなく、#property strictによりコンパイラに最新のMQL5ルール(暗黙の型変換の禁止や関数プロトタイプの必須化など)を適用させ、コンパイル時に潜在的なバグを検出しやすくします。さらに、「#property link」を設定することで、MetaEditor上でEAを確認するユーザーがMQL5コミュニティのプロフィールに直接アクセスでき、バージョン管理や著作者の明示に役立ちます。「#property description」を利用すれば、独自の注釈をEAのプロパティダイアログに表示でき、追加のUIコードなしで設定内容を整理し、記録することが可能です。

//+------------------------------------------------------------------+
//|                                                   ORB Breakout EA|
//|                                   Copyright 2025, MetaQuotes Ltd.|
//|                           https://www.mql5.com/ja/users/lynnchris|
//+------------------------------------------------------------------+
#property copyright   "Copyright 2025, MetaQuotes Ltd."
#property link        "https://www.mql5.com/ja/users/lynnchris"
#property version     "1.0"
#property description "Opening‑Range Breakout with ATR confirmation"
#property strict

2. 入力パラメータ

ユーザーが調整可能な設定は、コメントで明確に分類しています。たとえば、セッションインデックスとオープニングレンジの期間、ATRフィルターの設定、矢印のコードや色、アラートのオン/オフなどです。MQL5では、input変数を宣言すると、自動的にEAのプロパティダイアログに表示され、型が適切に設定され、ENUM(例:ENUM_TIMEFRAMES)はドロップダウンとして選択できるため、独自のGUIを作る必要はありません。たとえば、「input int ArrowUpCode」を選択すると、ユーザーは任意のWingdings文字コードを設定できます。一方、特定の候補に制限したい場合は、「enum ArrowSymbol { UP=233, DOWN=234 }」のように独自の列挙型を定義することで、コンパイル時に選択肢を限定することも可能です。また、readonlyを指定すれば、実行中に編集できない設定としてロックすることもできます。

//--- session & range
input int            SessionIndex    = 0;            // 0 = first session
input int            RangeMinutes    = 15;           // minutes to capture range
//--- ATR filter
input ENUM_TIMEFRAMES TF              = PERIOD_M1;   // ATR timeframe
input int            ATRPeriod       = 14;           // ATR look‑back
input double         ATRMultiplier   = 1.5;          // ATR * multiplier
//--- arrows & alerts
input int            ArrowUpCode     = 233;          // wingdings ↑
input int            ArrowDnCode     = 234;          // wingdings ↓
input color          ArrowUpColor    = clrLime;      // long arrow
input color          ArrowDnColor    = clrRed;       // short arrow
input bool           SendEmailAlert  = false;        // email on signal
input bool           PushNotify      = false;        // push on signal
input string         EmailSubject    = "ORB Signal"; // mail subject

3. RangeCaptureクラス

オープニングレンジのロジックを専用クラスCRangeCaptureにカプセル化することで、OnTick()のメイン処理をすっきり保ちつつ、MQL5におけるオブジェクト指向構造を強調できます。このクラスでは、開始時刻と変化する高値/安値を保持し、Init()、Update()、IsDefined()といったメソッドで操作します。MQL5のクラスは自動初期化されないため、明示的にInit()を呼び出す必要がある点に注意してください。また、高値安値をdouble型で保持することで、FX価格に必須の64ビット浮動小数点精度を活かすことができます。必要に応じて、このクラスを拡張して各ティックの高値や安値を内部バッファに記録することも可能で、クラスを進化させつつ元のインターフェースを維持する方法を示すことができます。

class CRangeCapture
  {
private:
   datetime startTime;
   double   hi, lo;
public:
   void Init(datetime t, double price)
     { startTime = t; hi = lo = price; }
   void Update(double price, datetime now)
     { if(now < startTime + RangeMinutes*60)
         { hi = MathMax(hi, price); lo = MathMin(lo, price); } }
   bool IsDefined(datetime now) const
     { return(now >= startTime + RangeMinutes*60); }
   double High() const { return hi; }
   double Low()  const { return lo; }
  };
static CRangeCapture g_range;

4. ATRModuleクラス

ここでは、組み込みのATRインジケーターのハンドル(iATR)をCATRModuleクラス内にラップしています。Init()ではハンドルを作成し、INVALID_HANDLEと比較して銘柄や時間足の問題をチェックします。Value()メソッドはCopyBufferを1ティックごとに1回だけ呼び出すため、OnTick()内で毎回iATRを呼ぶよりもはるかに効率的です。ハンドルをキャッシュすることで、メモリリークを防ぎ、オーバーヘッドを軽減できます。Release()でIndicatorRelease()を呼ぶことでハンドルを解放しない場合、ターミナルの[Indicators]タブに不要なインジケーターが残ってしまう可能性があります。このパターンは他のインジケーター(EMAやボリンジャーバンドなど)もそれぞれのモジュールにラップすれば、クリーンに拡張可能です。

class CATRModule
  {
private:
   int handle;
public:
   bool Init()
     {
      handle = iATR(_Symbol, TF, ATRPeriod);
      return(handle != INVALID_HANDLE);
     }
   double Value() const
     {
      double buf[];
      if(handle != INVALID_HANDLE && CopyBuffer(handle, 0, 0, 1, buf) == 1)
         return buf[0] * ATRMultiplier;
      return 0.0;
     }
   void Release()
     {
      if(handle != INVALID_HANDLE)
         IndicatorRelease(handle);
     }
  };
static CATRModule g_atr;

5. リテストロジッククラス

CRetestSignalクラスは、「ブレイク→リテスト→再ブレイク」のパターンを、3つのシンプルなブール変数で実装しています。内部ではbreakLong、breakShort、retestedを保持し、外部にはReset()、OnBreak()、CheckRetest()のメソッドのみを公開しています。これにより、OnTick()から実装の詳細を隠し、読者は「何をするか」に集中でき、「どのように動作するか」には注意を向けなくて済みます。最新のMqlRatesバーを参照渡しで渡している点にも注目してください。これによりコピーのオーバーヘッドを削減しています。複数の時間足に対応する必要がある場合は、CheckRetest()をMqlRates配列や時間足パラメータを受け取るよう拡張することも可能で、MQL5におけるメソッドオーバーロードの柔軟性を示しています。

class CRetestSignal
  {
private:
   bool breakLong, breakShort, retested;
public:
   void Reset()
     { breakLong = breakShort = retested = false; }
   void OnBreak(double close, double h, double l)
     { breakLong = (close > h); breakShort = (close < l); retested = false; }
   bool CheckRetest(const MqlRates &r, bool &isLong)
     {
      if(breakLong)
        {
         if(!retested && r.low <= g_range.High())
           { retested = true; isLong = true; return false; }
         if(retested && r.close > g_range.High())
           { isLong = true; return true; }
        }
      else if(breakShort)
        {
         if(!retested && r.high >= g_range.Low())
           { retested = true; isLong = false; return false; }
         if(retested && r.close < g_range.Low())
           { isLong = false; return true; }
        }
      return false;
     }
  };
static CRetestSignal g_retest;

6. チャート上ダッシュボード

リアルタイムでのフィードバックを提供するため、CDashboardクラスはチャート左上にシンプルなOBJ_LABELを作成します。Init()、Update()、Delete()がラベルのライフサイクルを管理する仕組みがわかりますが、このパターンはOBJ_TEXT、OBJ_RECTANGLE、その他のオブジェクトタイプでも同様に適用可能です。ラベルは毎ティック更新されますが、同じテキストを繰り返し設定してもコストは低いため、パフォーマンスは高く保たれます。さらに最適化する場合は、最後に設定した文字列をキャッシュして、実際に変更があったときだけObjectSetString()を呼び出すことで、ティックが多いEAでもオブジェクト管理の微調整によるパフォーマンス向上を実現できます。

class CDashboard
  {
private:
   string name;
public:
   void Init()
     {
      name = "ORB_Info";
      if(ObjectFind(0, name) < 0)
        {
         ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
         ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
         ObjectSetInteger(0, name, OBJPROP_XDISTANCE, 10);
         ObjectSetInteger(0, name, OBJPROP_YDISTANCE, 30);
        }
     }
   void Update(const string &txt)
     { ObjectSetString(0, name, OBJPROP_TEXT, txt); }
   void Delete()
     { if(ObjectFind(0, name) >= 0) ObjectDelete(0, name); }
  };
static CDashboard g_dash;

7. 取引インターフェースと通知

ここでは実際の注文を送信するわけではありませんが、後で実取引を統合する方法を示すために「static CTrade trade;」を含めています。より重要なのは、シグナルが確認された際に、ユーザーが選択したWingdingsコードと色を使って矢印(OBJ_ARROW)を描画し、その後Alert()、SendNotification()、SendMail()を発動する点です。この三つ組により、MQL5に標準搭載されたイベントとメッセージング機能を利用できることが示され、外部ライブラリは不要です。さらに、PlaySound()やEventChartCustom()を組み合わせてWebhook通知を追加することも可能で、MQL5が提供する多彩なコミュニケーションチャネルの幅広さを読者に伝えることができます。

static CTrade trade;

// ... inside your retest-confirmation block:
string msg = StringFormat("%s Signal @%.5f SL=%.5f TP=%.5f",
                          isLong ? "LONG" : "SHORT",
                          r[0].close, sl, tp);
Alert(msg);
if(PushNotify)    SendNotification(msg);
if(SendEmailAlert) SendMail(EmailSubject, msg);

// draw arrow on chart:
string arrowName = "ORB_Arrow_" + IntegerToString((int)r[0].time);
ObjectCreate(0, arrowName, OBJ_ARROW, 0,
             r[0].time,
             isLong ? r[0].low - 5 * _Point
                    : r[0].high + 5 * _Point);
ObjectSetInteger(0, arrowName, OBJPROP_ARROWCODE, isLong ? ArrowUpCode : ArrowDnCode);
ObjectSetInteger(0, arrowName, OBJPROP_COLOR,     isLong ? ArrowUpColor : ArrowDnColor);

8. OnInit()とOnDeinit()

OnInit()ではATRモジュールとダッシュボードを初期化し、何らかの問題が発生した場合はINIT_FAILEDを返します。このパターンにより、EAが半壊した状態で動作することを防げます。OnDeinit()では、ATRハンドルを適切に解放し、すべてのチャートオブジェクトを削除します。これにより、EAを再読み込みしたり削除した際に、孤立したインジケーターやオブジェクトが残らないようにします。この手順は実務での実装において非常に重要です。すべてのiXXXハンドルには必ずIndicatorRelease()を対応させ、ObjectCreate()はOnDeinit()内でObjectDelete()するか、リセットルーチンで条件付き削除をおこなうべきです。

int OnInit()
  {
   if(!g_atr.Init())
      return INIT_FAILED;
   g_dash.Init();
   return INIT_SUCCEEDED;
  }

void OnDeinit(const int reason)
  {
   g_atr.Release();
   ObjectDelete(0, "ORB_High");
   ObjectDelete(0, "ORB_Low");
   ObjectDelete(0, "ORB_Range");
   g_dash.Delete();
  }

9. OnTick()ステートマシン

EAの中心はOnTick()です。「static bool inited」と「static int state」を使用して値を保持しており、これによりグローバル変数や外部ストレージを使わずに、EA単位でのメモリを維持できます。まず、セッションの開始時刻を計算し、1日1回リセットします。これは日中ロジックでよく使われる典型的なパターンです。その後、「switch(state)」によって4つのステージ(Capture、Break、Retest、Done)を順に処理します。MQL5はコルーチンのようなyieldをサポートしていないため、ステートマシンを用いることが複数ステップの戦略を1ティック単位で処理する慣用手法です。また、各分岐を小さく保てるため、テストやデバッグが容易になります。

void OnTick()
  {
   static bool    inited = false;
   static int     state  = 0;
   static datetime sessionStart;

   if(!inited)
     {
      // compute sessionStart, init g_range & g_retest, Alert
      inited = true; state = 0;
     }

   // fetch latest MqlRates r[0] and bid/ask

   switch(state)
     {
      case 0: // Capture
         g_range.Update(bid, TimeCurrent());
         if(g_range.IsDefined(TimeCurrent()))
            state = 1;
         break;
      case 1: // Break
         if(r[0].close > g_range.High() || r[0].close < g_range.Low())
           { g_retest.OnBreak(r[0].close, g_range.High(), g_range.Low()); state = 2; }
         break;
      case 2: // Retest
         {
          bool isLong;
          if(g_retest.CheckRetest(r[0], isLong))
             state = 3;
         }
         break;
      case 3: // Done
         break;
     }
  }

10. 深夜リセット

最後に、「today = now - now%86400」と「static datetime lastDay」を比較します。日付が変わったら、古いオブジェクトを削除し、フラグをリセットします。煩雑な「if hour==0」のようなハックは不要です。このパターンは、日単位で動作するEA全般に適用可能です。ゼロバーの処理、日足ピボットの計算、日次レポート作成などにも使えます。この慣用手法を読者に推奨することで、深夜をまたぐタイミングやサマータイムの切り替え時に起こりがちな微妙なオフバイワンエラーを避けられます。

// at the end of OnTick():
static datetime lastDay = 0;
datetime        today   = TimeCurrent() - TimeCurrent() % 86400;
if(today != lastDay)
  {
   lastDay = today;
   inited  = false;
   state   = 0;
   ObjectDelete(0, "ORB_High");
   ObjectDelete(0, "ORB_Low");
   ObjectDelete(0, "ORB_Range");
  }



バックテストと結果

バックテストとは、EAに記述した取引戦略を過去の市場データに対して実行し、過去にどのようなパフォーマンスを示したかを確認するプロセスです。バックテストをおこなうことで、以下のことが可能になります。

  1. ルールが妥当な結果を生むことを検証する
  2. 勝率、ドローダウン、プロフィットファクターなどの主要指標を測定する
  3. 入力パラメータ(オープニングレンジの期間、ATRの乗数など)を最適化し、過去に最も効果的だった組み合わせを特定する

MetaTrader5のストラテジーテスターでは、各過去ティックがOnTick()に供給されます。流れは以下の通りです。

  • OnInit()でATRハンドル、チャートオブジェクト、初期状態などを設定する
  • OnTick()で値幅キャプチャ、ブレイク/リテストロジック、矢印描画、アラート、ダッシュボード更新をシミュレートティックごとに実行する
  • OnDeinit()でテスト終了後の後片付けをする

言い換えれば、ライブチャートで使用するコードと同じ経路を、テスターがバックテストに利用します。

上のアニメーションGIFは、EURUSD M15チャート上でバックテスト中のOpening Range Breakout EAの動作を示しています。メインパネルには、オープニングレンジを示す着色された矩形と、その初期区間の高値・安値に沿った2本の水平ラインが描かれています。この視覚的な枠組みにより、EAが注目する価格変動の領域が一目でわかります。

チャート上の緑色の矢印は、確認済みのロングエントリーを示しています。EAの「ブレイク→リテスト→再ブレイク」ロジックにより、価格はまず上限を突破し、その後再び上限に戻り、最後に再度上抜けでクローズして初めて矢印が表示されます。この二段階の確認により、偽のブレイクアウトを除外し、真のモメンタムが存在する場合のみシグナルを発します。

チャート下部の操作ログペインには、セッション開始、オープニングレンジ(初期の価格幅)の定義、ブレイクアウト検出、最終シグナルとその正確なエントリー、ストップロス、テイクプロフィット値など、すべての重要イベントが記録されます。これらのログはEA内部の状態遷移を反映しており、意思決定のタイミングと内容を透明化します。

この例は、ORB戦略がセッション初期のボラティリティを捉え、真のブレイクアウトを確認し、EURUSD M15の時間軸で再現可能かつ有効なシグナルを生成することを示しています。


さらに、このEAをAUD/USDのM5時間足でもテストし、日中の価格変動をより明確に把握しました。上の図を参照してください。

結論

MQL5で開発したOpening Range Breakout EAは、単純な「セッション初期の価格帯」という概念を、規律ある自動取引戦略へと昇華させます。値幅キャプチャ、ボラティリティに基づくストップ、リテスト確認、チャート上フィードバックといった各コンポーネントをモジュール化することで、保守性に優れ、ライブ運用にも耐えうる高速なコードベースを実現しました。

このアプローチは、日中トレードの2つの核心的課題に対応します。ひとつは、一時的なスパイクと真のモメンタムを区別すること、もうひとつは、リアルタイムの市場状況に応じてリスクを適切に調整することです。「ブレイク→リテスト→再ブレイク」の確認シーケンスは偽の動きを排除し、ATRに基づくストップロスやテイクプロフィットは変動するボラティリティに応じて動的に調整されます。こうしてEAは一貫した、高信頼性のシグナルを提供し、荒れた市場でも耐えうるエントリーを実現し、実際の価格変動を的確に捉えます。

ここからは、ご自分の環境でお試しください。MetaEditorでEAをコンパイルし、さまざまな通貨ペアやセッションでバックテストをおこない、オープニングレンジの期間やATR乗数などの入力パラメータを調整してみてください。チャート上で矩形やライン、矢印が動き出す様子を確認し、操作ログを追うことで意思決定の全過程を把握できます。このORBフレームワークを習得すれば、毎日のオープニングの値動きを再現可能で信頼性の高いトレードへと変換できるでしょう。より鋭いエントリーと賢明なリスク管理を手に入れる一歩です。





   
ChartProjector
Analytical Comment
Analytics Master
Analytics Forecaster 
Volatility Navigator
Mean Reversion Signal Reaper
Signal Pulse 
Metrics Board 
External Flow
VWAP
Heikin Ashi   FibVWAP  
RSI DIVERGENCE
Parabolic Stop and Reverse (PSAR) 
Quarters Drawerスクリプト
Intrusion Detector
TrendLoom Tool  Quarters Board 
ZigZag Analyzer  Correlation Pathfinder  Market Structure Flip Detector Tool
Correlation Dashboard   Currency Strength Meter 
PAQ Analysis Tool 
Dual EMA Fractal Breaker
Pin bar, Engulfing and RSI divergence
Liquidity Sweep Opening Range Breakout Tool    

MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/18486

添付されたファイル |
ORB.mq5 (21.49 KB)
データサイエンスとML(第44回):ベクトル自己回帰(VAR)を用いた外国為替OHLC時系列予測 データサイエンスとML(第44回):ベクトル自己回帰(VAR)を用いた外国為替OHLC時系列予測
本記事では、ベクトル自己回帰(VAR: Vector Autoregression)モデルを用いて、複数の通貨ペアのOHLC(始値、高値、安値、終値)時系列データを予測する方法を解説します。VARモデルの実装、学習、MetaTrader5上でのリアルタイム予測までをカバーし、通貨間の相互依存関係を分析して取引戦略の改善に役立てることができます。
データサイエンスとML(第43回):潜在ガウス混合モデル(LGMM)を用いた指標データにおける隠れパターン検出 データサイエンスとML(第43回):潜在ガウス混合モデル(LGMM)を用いた指標データにおける隠れパターン検出
チャートを見ていて、奇妙な感覚を覚えたことはありませんか。表面のすぐ下にパターンが隠されている気がして、もし解読できれば価格がどこに向かうか分かるかもしれない、そんな秘密のコードが存在するかもしれないという感覚です。ここで紹介するのがLGMM、マーケットの隠れたパターンを検出するモデルです。これは機械学習モデルで、隠れた市場のパターンを識別する手助けをします。
エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法 エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法
この記事では、MT4において複数のEAの衝突をさける方法を扱います。ターミナルの操作、MQL4の基本的な使い方がわかる人にとって、役に立つでしょう。
初心者からエキスパートへ:MQL5を使ったアニメーションニュース見出し(II) 初心者からエキスパートへ:MQL5を使ったアニメーションニュース見出し(II)
本日は、外部ニュースAPIを統合し、News Headline EAの見出し取得元として活用する新たなステップに進みます。このフェーズでは、既存の大手ニュースソースから新興の情報源まで幅広く取り上げ、それぞれのAPIに効果的にアクセスする方法を学びます。さらに、取得したデータをパースし、エキスパートアドバイザー(EA)内での表示に最適化された形式へ変換する手法についても解説します。ニュース見出しや経済指標カレンダーをチャート上に直接表示できることには、大きなメリットがあります。コンパクトで邪魔にならないインターフェースを通じて、取引中でも効率的に情報を確認できるようになるのです。