1. CustomBookAdd関数の概要と実務での活用法
CustomBookAddは、MQL5で作成した「カスタムシンボル」に対して、板情報(DOM: Depth of Market)を外部から追加・更新するための関数です。
通常のFX取引ではブローカーが配信する板情報をそのまま利用しますが、プロの開発現場では「外部のデータソース(仮想通貨取引所のAPIや他のリクイディティプロバイダのデータ)をMT5上に取り込み、独自の銘柄としてバックテストや分析を行いたい」というニーズがあります。
実務レベルでは、主に以下のようなシーンで活用されます。
* 裁定取引(アービトラージ)の検証: 他の取引所の板情報をMT5に反映させ、価格差を可視化する。
* 板情報に基づいたインジケーター開発: カスタムシンボルに板情報を流し込み、独自のボリュームプロファイルを作成する。
* シミュレーション: 過去の板データ(L2データ)を再現し、より高精度なバックテスト環境を構築する。
初心者の方がつまずきやすいポイントは、この関数が「既存のブローカー銘柄(USDJPYなど)」には使えないという点です。必ずCustomSymbolCreateで作成した、自分専用のカスタム銘柄に対して使用する必要があります。
2. 構文と戻り値
CustomBookAddの基本構文は以下の通りです。
int CustomBookAdd(
const string symbol, // カスタムシンボル名
const MqlBookInfo& book[], // 板情報の配列
uint count=WHOLE_ARRAY // 追加する要素数
);
パラメーター解説
- symbol: 板情報を追加したいカスタムシンボルの名前を指定します。
- book[]:
MqlBookInfo構造体の配列です。ここに価格、数量、注文の種類(買い・売り)を格納します。 - count: 配列から読み込む要素数です。デフォルト(WHOLE_ARRAY)では配列全体が対象となります。
戻り値
成功した場合は、処理された要素の数が返ります。失敗した場合は -1 が返ります。エラーの詳細を確認するには GetLastError() を呼び出します。
3. 具体的な使い方・実践サンプルコード
以下は、カスタムシンボルを作成し、そこに擬似的な板情報を追加する実践的なスクリプトの例です。
//+------------------------------------------------------------------+
//| カスタムシンボルに板情報を追加するサンプル |
//+------------------------------------------------------------------+
void OnStart()
{
string customSymbolName = "MY_CUSTOM_SYMBOL";
// 1. カスタムシンボルが存在しない場合は作成(既存のUSDJPYをベースにする)
if(!SymbolInfoInteger(customSymbolName, SYMBOL_EXIST))
{
if(!CustomSymbolCreate(customSymbolName, "CustomData", "USDJPY"))
{
Print("カスタムシンボルの作成に失敗しました: ", GetLastError());
return;
}
}
// 2. カスタムシンボルを「気配値表示」ウィンドウに表示させる
SymbolSelect(customSymbolName, true);
// 3. 板情報(MqlBookInfo)の配列を準備
MqlBookInfo bookGap[];
ArrayResize(bookGap, 4); // 売り2本、買い2本の例
double currentPrice = SymbolInfoDouble("USDJPY", SYMBOL_BID);
double point = SymbolInfoDouble("USDJPY", SYMBOL_POINT);
// --- 売り注文(ASK)の設定 ---
bookGap[0].type = TICK_TYPE_SELL;
bookGap[0].price = currentPrice + 20 * point; // 少し高い価格
bookGap[0].volume = 15;
bookGap[1].type = TICK_TYPE_SELL;
bookGap[1].price = currentPrice + 10 * point;
bookGap[1].volume = 10;
// --- 買い注文(BID)の設定 ---
bookGap[2].type = TICK_TYPE_BUY;
bookGap[2].price = currentPrice - 10 * point;
bookGap[2].volume = 12;
bookGap[3].type = TICK_TYPE_BUY;
bookGap[3].price = currentPrice - 20 * point;
bookGap[3].volume = 20;
// 4. 板情報をカスタムシンボルに流し込む
int result = CustomBookAdd(customSymbolName, bookGap);
if(result > 0)
{
Print(customSymbolName, " に ", result, " 件の板情報を追加しました。");
}
else
{
Print("板情報の追加に失敗。エラーコード: ", GetLastError());
}
}
4. 使用上の注意点とよくあるエラー
-
配列のソート順:
MqlBookInfo配列にデータを入れる際、価格順に並んでいなくても関数自体は動作しますが、MT5の板表示ウィンドウで正しく視認するためには、売りは価格の昇順、買いは価格の降順で整理して渡すのがベストプラクティスです。 -
既存データの全書き換え:
CustomBookAddを呼び出すと、そのシンボルの現在の板情報は、渡した配列の内容で完全に置き換わります。差分だけを追加することはできないため、常に最新の板全体を配列に格納して呼び出す必要があります。 -
Volumeの精度:
MqlBookInfo.volumeはlong型ではなく、実際には内部でdoubleのような扱いを受ける場合もありますが、基本は整数(または最小単位の倍数)で指定します。ブローカーの仕様に合わせたボリューム制限(最小ロットなど)を無視して数値を入れすぎると、表示がバグる原因になります。 -
エラーコード 4001 (Internal Error):
カスタムシンボルが正しく選択(SymbolSelect)されていない場合や、読み取り専用の設定になっている場合に発生しがちです。
5. 【重要】自動売買における約定スピードと環境の罠
アルゴリズムトレードにおいて、CustomBookAddなどを駆使してどれほど高度なロジックを組み上げたとしても、実行環境が「自宅のPC」であれば、その優位性の多くは失われてしまいます。FX市場はミリ秒(1000分の1秒)単位の争いです。自宅のインターネット回線では、プロバイダを経由する際の物理的な距離やネットワークの混雑により、ブローカーのサーバーに注文が届くまでに致命的な遅延(レイテンシ)が発生します。
この数ミリ秒の遅れは、板情報が変化した瞬間のチャンスを逃すだけでなく、スリッページを増大させ、バックテストの結果とはかけ離れた損失を生む原因となります。プロのクオンツエンジニアにとって、トレード専用のVPS(仮想専用サーバー)を利用することは「推奨」ではなく「必須条件」です。ブローカーのデータセンターに近いロケーションのVPS上でEAを稼働させることで、ネットワーク遅延を極限まで排除し、初めてアルゴリズムの真価を発揮できる環境が整います。
💡 この記事の内容を実運用で活かすには?
この記事の内容を実運用で活かすには、正しい環境が必要です。
特にVPSを使わないと、このロジックは再現できません。

コメント