あるシンボル(銘柄)の価格情報を取得する方法はいろいろ用意されています。
SymbolInfoTick
… 最新のティック情報を取得するCopyRates
… 各バーの四本値を取得するSymbolInfoDouble/Integer
… 最新の価格情報を個別に取得する(SymbolInfoTick
の方を使えば OK)
似たような関数があって混乱するかもしれませんが、ティック情報(Bid/Ask などの値動き)を取得する手段と、各バーの情報(OHLC 四本値情報)を取得する手段の 2 種類が用意されていると考えると理解しやすいです。
SymbolInfoTick … 最新のティック情報を取得する
SymbolInfoTick 関数(日本語)を使用すると、指定したシンボルの最後の値動き(ティック)における Bid/Ask 値やボリュームの情報を取得することができます。
bool SymbolInfoTick(string symbol, MqlTick& tick);
得られる情報の MqlTick 構造体(日本語) は次のようになっています。
struct MqlTick {
datetime time; // 価格更新時間(datetime 値)
double bid; // Bid 価格(売値)
double ask; // Ask 価格(買値)
double last; // 取引価格(注: ターミナル起動直後は 0.0 になる)
ulong volume; // 取引ボリューム
long time_msc; // 取引時間時間(ミリ秒)
uint flags; // 変化理由(TICK_FLAG_BID など)
double volume_real; // より正確な取引ボリューム(取得できれば)
};
この構造体は、あくまで 1 ティックの情報だけを含むため、ローソク足のような四本値 (OHLC) 情報は含まれていないことに注意してください。
次のスクリプトを実行すると、カレントチャートのシンボルにおける最新価格情報を出力します。
void OnStart() {
MqlTick tick;
if (!SymbolInfoTick(_Symbol, tick)) {
Print("Error SymbolInfoTick: ", GetLastError());
return;
}
Print("time=", tick.time, ", ask=", tick.ask,
", bid=", tick.bid, ", volume=", tick.volume);
}
EA(エキスパートアドバイザー)であれば、OnTick
関数の中で SymbolInfoTick
を呼び出せば、ティックが発生するごとに最新の価格を取得できます。
void OnTick() {
// 同上
}
Ask
、Bid
といった組み込み変数でカレントシンボルの現在価格を参照できました。
MT5 にはこのような組み込み変数は用意されていないので、SymbolInfoTick
関数などを使って価格情報を取得する必要があります。CopyRates … 各バーの四本値 (OHLC) を取得する
CopyRates 関数(日本語)を使うと、各バーの四本値 (OHLC) 情報を取得することができます。
CopyRates
関数にはいくつかのバリエーションがあり、取得するデータの位置を、ポジション(start_pos = 0
は最新のバー)で指定するか、時刻(datetime 値)で指定するかによって使い分けます。
int CopyRates(
string symbol_name, ENUM_TIMEFRAMES timeframe,
int start_pos, int count, MqlRates rates_array[]);
int CopyRates(
string symbol_name, ENUM_TIMEFRAMES timeframe,
datetime start_time, int count, MqlRates rates_array[]);
int CopyRates(
string symbol_name, ENUM_TIMEFRAMES timeframe,
datetime start_time, datetime stop_time, MqlRates rates_array[]);
取得結果は次のような MqlRates 構造体(日本語)の配列です。
struct MqlRates {
datetime time; // 期間開始時間
double open; // 始値
double high; // 期間中の最高値
double low; // 期間中の最安値
double close; // 終値
long tick_volume; // ティックボリューム
int spread; // スプレッド
long real_volume; // 取引高
};
スプレッドの情報も取得できるのが面白いですね。
次のスクリプトでは、最新のバーから 3 本分の四本値 (OHLC) 情報を取得しています。 データ格納先の配列を ArraySetAsSeries 関数(日本語)でシリーズ化(時系列化)すると、配列の先頭要素が最新のバーの情報を表すようになります(デフォルトでは、配列の先頭要素は一番過去のバー情報)。
void OnStart() {
MqlRates rates[];
ArraySetAsSeries(rates, true); // 先頭要素を最新バーとする
int copiedCount = CopyRates(_Symbol, PERIOD_CURRENT, 0, 3, rates);
for (int i = 0; i < copiedCount; i++) {
Print(i, ": time=", rates[i].time,
", O=", rates[i].open, ", H=", rates[i].high,
", L=", rates[i].low, ", C=", rates[i].close,
", tick_volume=", rates[i].tick_volume, ", spread=", rates[i].spread);
}
}
0: time=2021.02.12 19:00:00, O=1.07397, H=1.07435, L=1.0736, C=1.07428, tick_volume=4880, spread=11
1: time=2021.02.12 20:00:00, O=1.0743, H=1.07461, L=1.07408, C=1.07448, tick_volume=3688, spread=11
2: time=2021.02.12 21:00:00, O=1.07447, H=1.07452, L=1.07412, C=1.07445, tick_volume=3043, spread=11
上記のように、CopyRates
関数を使うと各バーの四本値 (OHLC) 情報を MqlRates
の形でまとめて取得できますが、始値 (Open) や終値 (Close) だけが欲しい場合は、代わりに以下のような関数を使って取得することができます。
- CopyTime(日本語)… 各バーの開始時刻 (
datetime[]
) を取得 - CopyOpen(日本語)… 各バーの始値 (
double[]
) を取得 - CopyHigh(日本語)… 各バーの高値 (
double[]
) を取得 - CopyLow(日本語)… 各バーの安値 (
double[]
) を取得 - CopyClose(日本語)… 各バーの終値 (
double[]
) を取得 - CopySpread(日本語)… 各バーのスプレッド(ポイント数)(
int[]
) を取得
void OnStart() {
double closes[];
ArraySetAsSeries(closes, true);
int copiedCount = CopyClose(_Symbol, PERIOD_CURRENT, 0, 3, closes);
for (int i = 0; i < copiedCount; i++) {
Print(i, ": ", closes[i]);
}
// 配列の内容は次のように出力しても OK
// ArrayPrint(closes);
}
SymbolInfoDouble/Integer … 最新の価格情報を個別に取得する
SymbolInfoDouble 関数(日本語)などの数値プロパティ取得用の関数を使うと、あるシンボルの Ask/Bid 値などを個別に取得することができます。
void OnStart() {
datetime time = (datetime) SymbolInfoInteger(_Symbol, SYMBOL_TIME);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
long volume = SymbolInfoInteger(_Symbol, SYMBOL_VOLUME);
Print("time=", time, ", ask=", ask, ", bid=", bid, ", volume=", volume);
}
SymbolInfoTick
関数で最新のティック情報 (MqlTick
) を一度に取得するのと同じかと思うかもしれませんが、まさに同じ値が取得できます(^^;
SymbolInfoTick と SymbolInfoDouble のどちらで Bid/Ask 値を取得すべきか?
結論から言うと、SymbolInfoTick
関数の方を使えばよさそう です。
Bid/Ask 値を取得するのであれば、どちらの関数でも同じ値が取得できるので、違いはコードの可読性と、実行時のパフォーマンスだけです。
可読性はどちらもそんなに変わらないので、パフォーマンスを調べて速い方を使うのがよさそうです。
予想では、取得できる情報量の少ない SymbolInfoDouble
の方が速いと思いましたが、プロファイリングを取ってみると、わずかに SymbolInfoTick
関数の方が速そうです。

関連記事
- MetaTrader/MQL: 描画オブジェクトの基本 (ObjectCreate, ObjectDelete, ObjectSetXxx)
- MetaTrader/MQL: OrderSend で決済注文を出す(ポジションのクローズ)(MT5)
- MetaTrader/MQL: ヘッジアカウントとネットアカウントの違いを理解する
- MetaTrader/MQL: OrderSend で成行注文を出す (MT5)
- MetaTrader/MQL: チャート上でのキーハンドリング (OnChartEvent)
- MetaTrader/MQL: プログラムがデモ口座で実行されている調べる (ACCOUNT_TRADE_MODE)
- MetaTrader/MQL: 注文時のフィル・ポリシー(充填ポリシー)を理解する