MQL4のMarketInfo()や
iOpen/iClose/iHigh/iLowで取得できるのは、
あくまで「今の最良気配(Bid/Ask)」や「確定した1本のローソク足」
の情報です。
MQL5には、これらとは別に、
現在の売買注文が価格帯ごとにどれだけ積み上がっているかを示す
「板情報(気配値、Depth of Market)」を取得するAPIが用意されています。
MQL4にはこの機能自体が存在しないため、MQL5独自の差分として扱われます。
ただし、この記事で最初に伝えたい落とし穴は使い方以前の話で、
「そもそも自分が使っている銘柄が板情報に対応しているとは限らない」
という点です。
順を追って解説します。
板情報(Depth of Market)とは何か
板情報とは、現在の最良気配(Bid/Ask)だけでなく、
その前後の価格帯にどれだけの買い注文・売り注文が
溜まっているかを一覧にしたものです。
株式や一部の先物CFDでは板情報が需給を読む材料として広く使われますが、
FXの現物・CFDは相対取引(OTC)の色が強く、
ブローカーによっては板情報そのものを提供していません。
最大の落とし穴: 銘柄が対応しているとは限らない
板情報を使う一連の関数は、
対応していない銘柄に対して呼び出してもコンパイルエラーにはならず、
「常に空の板情報が返る」
「登録自体が失敗する」という形で静かに失敗します。
そのため、必ず`MarketBookAdd()`の戻り値を確認し、
`false`が返る場合はそもそもその銘柄が板情報に対応していないと判断してください。
if(!MarketBookAdd(_Symbol))
{
Print(_Symbol, " は板情報に対応していません(MarketBookAdd()がfalseを返しました)");
return(INIT_FAILED);
}
`MarketBookAdd()`が`true`を返しても油断はできません。
ブローカーが登録自体は受け付けても、実際の板データをほとんど送ってこない銘柄も存在します。
その場合は、次の節で説明する`OnBookEvent()`がいつまでたっても呼ばれない、
という形で気づくことになります。
関数の一覧と役割
板情報を扱う一連の関数は、次の4つです。
bool MarketBookAdd(const string symbol); bool MarketBookGet(const string symbol, MqlBookInfo &book[]); bool MarketBookRelease(const string symbol); void OnBookEvent(const string &symbol);
`MarketBookAdd()`は、
指定した銘柄の板情報の購読(サブスクリプション)を開始します。
購読を開始しないと、`MarketBookGet()`は使えません。
`MarketBookGet()`は、
現時点の板情報を`MqlBookInfo`構造体の配列に取得します。
`MarketBookRelease()`は、購読を終了します。
CopyBuffer()とIndicatorRelease()の関係と同じく、
使い終わったら必ず解放するのが作法です(IndicatorCreate/IndicatorReleaseの記事で解説した後片付けの考え方と同じです)。
`OnBookEvent()`は、購読中の銘柄の板情報が更新されるたびに、
MQL5側から自動的に呼び出されるイベントハンドラです。
板情報は値動きよりも頻繁に更新されることがあるため、
`OnTick()`で毎回`MarketBookGet()`を呼ぶより、
`OnBookEvent()`内で処理する設計が推奨されます。
MqlBookInfo構造体の中身
struct MqlBookInfo
{
ENUM_BOOK_TYPE type; //注文の種別
double price; //価格
long volume; //出来高(整数)
double volume_real; //出来高(小数対応版)
};
`type`は次のいずれかです。
BOOK_TYPE_SELL //売り気配(指値) BOOK_TYPE_BUY //買い気配(指値) BOOK_TYPE_SELL_MARKET //成行の売り注文 BOOK_TYPE_BUY_MARKET //成行の買い注文
`MarketBookGet()`で取得できる配列には、
現在の板に積まれている売り・買いの注文が価格帯ごとに並んでおり、
これをループしながら`type`ごとに`volume`を合計すれば、
「今、買い注文と売り注文のどちらが厚いか」という需給の偏りを数値化できます。
実際に動くコード全体
板情報を購読し、
更新のたびに買い注文・売り注文それぞれの出来高合計をチャート左上に表示する、
実際にMetaEditorでコンパイルできるインジケーターです。
//+------------------------------------------------------------------+
//| MarketBookDepthDemo.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"
#property indicator_chart_window
#property indicator_plots 0
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
if(!MarketBookAdd(_Symbol))
{
Print(_Symbol, " は板情報に対応していません(MarketBookAdd()がfalseを返しました)");
return(INIT_FAILED);
}
Print(_Symbol, " の板情報の購読を開始しました。OnBookEventの発火を待っています…");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
MarketBookRelease(_Symbol);
Comment("");
}
//+------------------------------------------------------------------+
//| 板情報が更新されるたびに呼ばれるイベントハンドラ |
//+------------------------------------------------------------------+
void OnBookEvent(const string &symbol)
{
if(symbol != _Symbol)
return;//他の銘柄の更新イベントは無視する
MqlBookInfo book[];
if(!MarketBookGet(symbol, book))
{
Comment(symbol, " の板情報を取得できませんでした。");
return;
}
double buyVolume = 0;
double sellVolume = 0;
for(int i = 0; i < ArraySize(book); i++)
{
if(book[i].type == BOOK_TYPE_BUY || book[i].type == BOOK_TYPE_BUY_MARKET)
buyVolume += book[i].volume_real;
else if(book[i].type == BOOK_TYPE_SELL || book[i].type == BOOK_TYPE_SELL_MARKET)
sellVolume += book[i].volume_real;
}
Comment(
symbol, " の板情報(件数=", ArraySize(book), ")\n",
"買い注文の出来高合計: ", DoubleToString(buyVolume, 2), "\n",
"売り注文の出来高合計: ", DoubleToString(sellVolume, 2)
);
}
//+------------------------------------------------------------------+
MetaEditorで実際に動かす手順
- MetaTrader 5の「ツール」→「MetaQuotes Language Editor」でMetaEditorを開く
- 「ファイル」→「新規作成」→「インジケーター」を選び、名前を「MarketBookDepthDemo」にして作成する(中身は空のテンプレートで構いません)
- テンプレートの中身を全て削除し、上のコードを丸ごと貼り付ける
- F7キー(またはコンパイルボタン)でコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
- チャートへドラッグ&ドロップし、「エキスパート」タブに「板情報の購読を開始しました」のログが出るか確認する。板情報に対応していない銘柄の場合、初期化に失敗した旨のログが出てインジケーターは自動的に外れる
- 対応銘柄の場合、しばらく待ってチャート左上に買い注文・売り注文の出来高合計が表示されれば成功です
コピペしてコンパイルが通らない・値が表示されないときに確認すること
- 初期化直後に外れてしまう: `MarketBookAdd()`が`false`を返している。その銘柄がそもそも板情報に対応していない可能性が高い。デモ口座で提供されている株式CFDや先物CFD銘柄などで試す
- `MarketBookAdd()`は`true`を返すのに、いつまでもComment()が表示されない: `OnBookEvent()`が一度も発火していない。ブローカー側が登録は受け付けても実際の板データをほとんど送っていない可能性がある。時間帯(取引所の取引時間内)を変えて再確認する
- `OnBookEvent()`のsymbol引数が期待と違う: 複数の銘柄を同時に購読している場合、`OnBookEvent()`は購読中のどの銘柄が更新されても呼ばれる。必ず`symbol`引数を確認してから処理する(このコードのように`if(symbol != _Symbol) return;`を入れる)
- インジケーターを外した後もログが出続ける: `OnDeinit()`で`MarketBookRelease()`を呼び忘れていないか確認する。購読を解放しないと、他のチャート・EAでの板情報取得に影響する場合がある
まとめ
MQL5の板情報APIを使えば、MQL4にはなかった需給の厚みという情報を取得できます。
ただし最大の注意点は使い方そのものより前の段階にあり、
`MarketBookAdd()`の戻り値を必ず確認し、
自分が使う銘柄がそもそも対応しているかを最初に見極める必要があります。
対応銘柄で試す際も、`OnBookEvent()`で更新のたびに処理し、
使い終わったら`MarketBookRelease()`で必ず購読を解放してください。
コメント