MQL4で動いていたインジケーターやEAを「とりあえずMQL5にも移植してみよう」

とコードをそのままコピーしてMetaEditorでコンパイルすると、

`’Bid’ – undeclared identifier`というエラーが大量に出て手が止まった、

という経験はないでしょうか。

原因は単純で、MQL5には`Bid`・`Ask`という予約変数そのものが存在しません。

現在のBid・Ask価格は、`SymbolInfoTick()`という関数を使って取得する仕様に変わっています。

この記事では、MQL4の`Bid`・`Ask`変数がMQL5でなぜ使えなくなったのか、

代わりに使う`SymbolInfoTick()`関数と構造体`MqlTick`の中身、

そして似た用途の`SymbolInfoDouble()`との使い分けを、

実際に動くコードで解説します。

MQL4のBid・Askは「現在チャートの通貨ペア専用」の予約変数

MQL4では、`Bid`と`Ask`はあらかじめ用意された予約変数で、

コード中に書くだけで現在のチャートの通貨ペアの最新価格を参照できました。

double currentBid = Bid;  //MQL4: 現在チャートの通貨ペアのBid価格
double currentAsk = Ask;  //MQL4: 現在チャートの通貨ペアのAsk価格

ただしMQL4でも、現在チャート以外の通貨ペアの価格を知りたい場合は`Bid`・`Ask`は使えず、

`MarketInfo(symbol, MODE_BID)`・`MarketInfo(symbol, MODE_ASK)`という別の関数が必要でした。

「現在チャートは変数、他の通貨ペアは関数」という2系統の使い分けがすでにMQL4の時点で存在していたことになります。

MQL5にはBid・Ask予約変数が存在しない

MQL5では、この2系統がSymbolInfoTick()・SymbolInfoDouble()という関数への呼び出しに統一されました。

`Bid`・`Ask`という識別子自体が言語仕様から削除されているため、

MQL4のコードをそのまま貼り付けると次のようなコンパイルエラーになります。

//MQL5でこのまま書くとエラー
double currentBid = Bid;  //'Bid' - undeclared identifier
double currentAsk = Ask;  //'Ask' - undeclared identifier

現在チャートの通貨ペアであっても、他の通貨ペアであっても、MQL5では常に関数を呼んで値を取得する必要があります。

SymbolInfoTick関数: Bid・Askを同時刻のスナップショットとして取得する

bool SymbolInfoTick(
   string      symbol,   //通貨ペア名
   MqlTick&    tick      //値を受け取る構造体(参照渡し)
   );

戻り値は取得の成否(bool)で、実際のデータは第2引数に渡した`MqlTick`構造体に書き込まれます。

構造体のメンバーは次の通りです。

struct MqlTick
  {
   datetime time;          //直近の価格更新時刻(秒単位)
   double   bid;           //現在のBid価格
   double   ask;           //現在のAsk価格
   double   last;          //直近約定した価格(現物・株式銘柄向け、FXでは0のことが多い)
   ulong    volume;        //直近価格での出来高
   long     time_msc;      //直近の価格更新時刻(ミリ秒単位)
   uint     flags;         //ティックフラグ(どの値が更新されたか)
   double   volume_real;   //出来高(倍精度)
  };

`SymbolInfoTick()`最大の利点は、Bid・Ask・時刻をすべて1回の呼び出しでまとめて取得できることです。

次に説明する`SymbolInfoDouble()`を2回に分けて呼ぶと、

1回目と2回目の呼び出しの間にわずかな時間差が生まれ、価格が動くタイミングによってはBidとAskの組み合わせが「同時刻の実際の値」

ではなくなる可能性があります。

スプレッドを正確に計算したい場面など、BidとAskの整合性が重要な処理では`SymbolInfoTick()`でまとめて取得するほうが安全です。

SymbolInfoDouble関数: 1項目だけ個別に取得する

BidかAskの片方だけで十分な場合や、スプレッド・最小価格変動幅など他のシンボル情報と一緒に取得したい場合は、

`SymbolInfoDouble()`のほうが簡潔に書けます。

double bid = SymbolInfoDouble(symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
MQL4のBid/Ask(予約変数、現在チャートのみ) → MQL5では廃止
MQL4のMarketInfo(symbol, MODE_BID/MODE_ASK)(他通貨ペア用) → MQL5ではSymbolInfoDouble(symbol, SYMBOL_BID/SYMBOL_ASK)
BidとAskをまとめて同時刻で取得したい → MQL5ではSymbolInfoTick(symbol, tick)

実際に動くコード全体

現在チャートの通貨ペアについて、`SymbolInfoTick()`でBid・Ask・更新時刻をまとめて取得し、

スプレッドをポイント単位で計算して表示する、実際にMetaEditorでコンパイルできるスクリプトです。

//+------------------------------------------------------------------+
//|                                          SymbolInfoTickDemo.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 script_show_inputs

input string TargetSymbol = "";//空欄なら現在チャートの通貨ペア

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   string symbol = (TargetSymbol == "") ? _Symbol : TargetSymbol;

   MqlTick tick;
   if(!SymbolInfoTick(symbol, tick))
     {
      Print(symbol, " のティック取得に失敗しました。エラーコード=", GetLastError());
      return;
     }

   double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
   double spreadPoints = (tick.ask - tick.bid) / point;

   PrintFormat("%s Bid=%.5f Ask=%.5f スプレッド=%.1fポイント 更新時刻=%s",
               symbol, tick.bid, tick.ask, spreadPoints,
               TimeToString(tick.time, TIME_DATE | TIME_SECONDS));

   //SymbolInfoDoubleで個別取得した場合との比較(通常はほぼ同じ値になる)
   double bidOnly = SymbolInfoDouble(symbol, SYMBOL_BID);
   double askOnly = SymbolInfoDouble(symbol, SYMBOL_ASK);
   PrintFormat("(参考)SymbolInfoDoubleで個別取得: Bid=%.5f Ask=%.5f",
               bidOnly, askOnly);
  }
//+------------------------------------------------------------------+
Copy

MetaEditorで実際に動かす手順

  1. MetaTrader 5の「ツール」→「MetaQuotes Language Editor」でMetaEditorを開く
  2. 「ファイル」→「新規作成」→「スクリプト」を選び、名前を「SymbolInfoTickDemo」にして作成する(中身は空のテンプレートで構いません)
  3. テンプレートの中身を全て削除し、上のコードを丸ごと貼り付ける
  4. F7キー(またはコンパイルボタン)でコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
  5. チャートへドラッグ&ドロップし、「エキスパート」タブにBid・Ask・スプレッド・更新時刻が表示されることを確認する

コピペしてコンパイルが通らない・値が取得できないときに確認すること

  • MQL4のコードをそのまま貼り付けて`Bid`・`Ask`をコンパイルエラーの箇所に残したままにしていないか(`SymbolInfoTick()`または`SymbolInfoDouble()`への書き換えが必要)
  • `SymbolInfoTick()`が`false`を返す場合、指定した通貨ペア名が「気配値表示」に表示されていない(市場ウォッチに追加されていない)可能性がある。`SymbolSelect(symbol, true)`で表示状態にしてから呼び出す
  • 拡張子が「.mq5」になっているか(このコードはMQL5専用で、MQL4環境ではコンパイルできません)
  • `tick.bid`のように構造体のメンバーへ小文字でアクセスしているか(MqlTickのメンバー名は小文字始まり)

まとめ

MQL4の`Bid`・`Ask`予約変数はMQL5には存在せず、

そのまま移植するとコンパイルエラーになります。

現在値を取得するには、BidとAskをまとめて同時刻のスナップショットとして取得できる`SymbolInfoTick()`(構造体`MqlTick`で受け取る)か、

1項目だけで十分なら`SymbolInfoDouble()`を使います。

他通貨ペアの価格を扱っていたMQL4のMarketInfo()も、

MQL5ではこの2つの関数に置き換わっている、と覚えておくと移植時の書き換え漏れを防げます。

関連記事