MQL5で足データを取得する方法|配列の向きに注意
MQL5で過去のローソク足を取るには CopyRates を使います。受け取る配列は MqlRates 型です。
ここで多くの人が一度つまずきます。受け取った配列の index 0 は、既定では「最新の足」ではなく「いちばん古い足」です。MQL4の感覚のまま書くと、値は取れているのに時系列が逆になります。
(確認環境:MetaTrader 5 / Windows 11)
最小のコード
MqlRates rates[];
ArraySetAsSeries(rates, true); // index 0 を最新にする
int copied = CopyRates(_Symbol, _Period, 0, 100, rates);
if(copied <= 0)
{
Print("取得失敗 err=", GetLastError());
return;
}
Print("最新の終値 ", rates[0].close);
Print("1本前の高値 ", rates[1].high);
CopyRates はコピーできた本数を返し、失敗すると −1 を返します。戻り値を見ずに配列を参照すると、中身が空のまま進みます。
MqlRates に入っているもの
| メンバ | 内容 |
|---|---|
time |
足の開始時刻(サーバー時刻) |
open / high / low / close |
4本値 |
tick_volume |
ティック数 |
spread |
スプレッド(ポイント) |
real_volume |
実ボリューム(FXでは0のことが多い) |
1行目の time はサーバー時刻です。日本時間で判定したい場合は自分でずらします。違いはMT5の時刻がずれる理由にまとめています。
🔴 配列の向きは「並べ替え」ではない
ArraySetAsSeries の説明としてよくあるのが「配列を新しい順に並べ替える」ですが、実際には要素は動いていません。
MQL5公式リファレンスの CopyRates の項にはこう書かれています。
対象配列の as_series が true か false かにかかわらず、最も古い要素が、配列に割り当てられた物理メモリの先頭に置かれる。
つまりデータの並びは常に「古い順」で、ArraySetAsSeries が変えるのはアクセスする時のインデックスの向きだけです。
| 設定 | index 0 | index 1 |
|---|---|---|
| 既定(false) | いちばん古い足 | その次に古い足 |
ArraySetAsSeries(arr, true) |
最新の足 | 1本前 |
MQL4では index 0 が常に最新でした。MQL5では自分で指定しない限りそうなりません。「計算結果がおかしい」「移動平均のクロス判定が逆になる」といった症状は、ここが原因であることが多いです。
設定できない配列がある
公式リファレンスによると、AS_SERIESフラグは多次元配列と静的配列には設定できません。
double a[]; // 動的配列 → 設定できる
double b[100]; // 静的配列 → 🔴 設定できない
宣言時に角括弧の中へサイズを書いた配列は静的配列です。ArraySetAsSeries を呼んでも効きません。必ず動的配列で受け取ってください。
🔴 インジケーターでは −1 が返ることがある
もう1つ、公式リファレンスに明記されている挙動です。
インジケーターから呼んだ場合、履歴の準備ができていなければ即座に −1 を返します。そのうえで、裏で読み込みが開始されます。
EAやスクリプトから呼んだ場合は、タイムアウトまでに用意できた分を返し、次に同じ要求をすればより多く返ります。
起動直後の1回だけ失敗するのはこのためです。対策は単純で、失敗したらその回は何もせず戻ることです。
int copied = CopyRates(_Symbol, _Period, 0, 100, rates);
if(copied < 100)
return(prev_calculated); // 次の呼び出しに任せる
ここでエラーを表示して止めてしまうと、本来なら次の呼び出しで取れるものを取り損ねます。値が取れない場合の切り分け全般はMQL5でiCustom・CopyBufferの値が取れない原因にまとめています。
必要な本数だけ取る
毎回1万本コピーするような書き方は、OnTick や OnCalculate の中では重くなります。
- 判定に使う本数だけ取る — 直近3本で足りるなら3本
- 足が更新された時だけ取り直す — 同じ足の中で何度も取らない
取得した値をそのまま検証したい場合は、画面で数えるよりファイルに書き出す方が確実です。方法はMQL5でCSVを出力する方法に、実際にZigZagの値を書き出す例はMT5のZigZagをCSVに出力する方法にまとめました。
高値・安値だけが必要なら、配列を持たずに済む方法もあります。MQL5で高値・安値を探す方法を参照してください。
まとめ
CopyRatesはコピーできた本数を返す。失敗は −1。戻り値を必ず見る- 🔴 既定では index 0 がいちばん古い足。MQL4とは逆
- 🔴
ArraySetAsSeriesは並べ替えではなくインデックスの向きの変更 - 静的配列・多次元配列にはAS_SERIESを設定できない
- インジケーターでは起動直後に −1 が返る。その回は戻って次に任せる
本記事はMQL5の仕様と実装方法を説明したものであり、特定の売買を推奨するものではありません。仕様はビルドによって変わる可能性があります。投資判断はご自身の責任で行ってください。


