1. MQL5のCopyRatesとは何か
1.1 CopyRatesの基本概念
CopyRates は、MQL5で価格データ(OHLC)を取得するための関数です。
OHLCとは次の4つの価格情報を指します。
| 項目 | 意味 |
|---|---|
| Open | 始値 |
| High | 高値 |
| Low | 安値 |
| Close | 終値 |
これらはローソク足の価格情報であり、テクニカル分析や自動売買ロジックの基本データになります。
MQL5では、価格データは通常 MqlRates構造体(価格情報をまとめたデータ構造)として扱われます。
CopyRatesは、指定した通貨ペア・時間足・バー数に基づいて、この MqlRates配列 に価格データをコピーします。
基本的なイメージは次の通りです。
チャートデータ
↓
CopyRates
↓
MqlRates配列
↓
EAやインジケーターが利用
つまりCopyRatesは、チャート上の価格履歴をプログラムで取得するための関数です。
例えばEA(自動売買プログラム)では、次のような用途で使われます。
- 過去N本のローソク足を取得する
- 直近高値・安値を判定する
- トレンド方向を判断する
- インジケーター計算の元データを取得する
MQL5ではインジケーター値を取得する関数(CopyBufferなど)もありますが、価格そのものを取得する基本関数がCopyRatesです。
そのため、EA開発ではほぼ必ず登場する関数の一つです。
1.2 CopyRatesが使われる場面
CopyRatesは、主に次のような場面で使用されます。
① トレードロジックの作成
EAでは、過去の価格データを元に売買判断を行います。
例えば
- 直近高値ブレイク
- 前回ローソク足の終値
- ボラティリティ計測
といったロジックはすべて価格履歴の取得が必要になります。
例:
MqlRates rates[];
CopyRates(_Symbol, PERIOD_H1, 0, 100, rates);
このコードは
- 現在の通貨ペア
- 1時間足
- 最新から100本
のローソク足データを取得します。
② インジケーター計算
多くのテクニカル指標は、OHLCデータを元に計算されます。
例えば
- 移動平均
- ATR
- ボリンジャーバンド
- RSI
などです。
カスタムインジケーターを作る場合、CopyRatesで取得した価格データを元に計算処理を行うケースもあります。
③ マルチタイムフレーム分析
MQL5では、現在のチャートとは別の時間足データも取得できます。
例:
- M15チャートでH1データを取得
- H1チャートでD1データを取得
これにより
- 上位足トレンド確認
- 下位足エントリー
といった戦略が実装できます。
1.3 初心者がつまずきやすいポイント
CopyRatesは便利な関数ですが、初心者がつまずきやすい点もあります。
特に多いのが次の3つです。
配列の扱い
CopyRatesは 配列にデータをコピーする関数です。
そのため
MqlRates rates[];
のように、MqlRates配列を準備する必要があります。
配列の型を間違えるとコンパイルエラーになります。
データの順序
MQL5では、配列の順序が次のようになります。
| インデックス | 意味 |
|---|---|
| rates[0] | 最新バー |
| rates[1] | 1本前 |
| rates[2] | 2本前 |
ただしこれは ArraySetAsSeries() の設定によって変わるため、実装時には注意が必要です。
ヒストリ不足
CopyRatesが失敗する原因として多いのが
- ヒストリカルデータ未ロード
- Market Watch未登録
です。
例えば
- 初めて開いた通貨ペア
- 新しい時間足
ではデータが不足する場合があります。
この場合
- チャートを開く
- データをロードする
必要があります。
環境によって挙動が異なる場合があるため、取得数をチェックするコードを書くことが重要です。
2. CopyRatesの基本構文とパラメータ
2.1 CopyRatesの関数構文
MQL5で価格データを取得するための CopyRates関数 の基本構文は次の通りです。
int CopyRates(
string symbol,
ENUM_TIMEFRAMES timeframe,
int start_pos,
int count,
MqlRates rates_array[]
);
この関数は、指定した通貨ペアと時間足のローソク足データを取得し、MqlRates配列にコピーします。
戻り値は コピーされたバー数(ローソク足数) です。
取得に失敗した場合は -1 が返されます。
基本的な使用例は次のようになります。
MqlRates rates[];
int copied = CopyRates(_Symbol, PERIOD_H1, 0, 100, rates);
if(copied <= 0)
{
Print("CopyRates failed");
}
このコードでは
- 現在の通貨ペア
- 1時間足
- 最新から100本
のローソク足データを取得しています。
ここで重要なのは、戻り値を必ず確認することです。
CopyRatesはデータ不足などの理由で失敗することがあります。
初心者がよくやってしまう失敗として、戻り値チェックをせずに配列を使うケースがあります。
その場合、EAが誤動作する原因になります。
2.2 各パラメータの意味
CopyRatesを正しく使うためには、各パラメータの意味を理解することが重要です。
| パラメータ | 意味 |
|---|---|
| symbol | 通貨ペア |
| timeframe | 時間足 |
| start_pos | 取得開始位置 |
| count | 取得本数 |
| rates_array | コピー先の配列 |
それぞれ詳しく説明します。
symbol(通貨ペア)
取得する通貨ペアを指定します。
例:
"EURUSD"
通常は現在のチャートを取得するために、次の定数を使います。
_Symbol
例:
CopyRates(_Symbol, PERIOD_H1, 0, 100, rates);
これにより、現在のチャートの通貨ペアが使用されます。
timeframe(時間足)
取得する時間足を指定します。
主な値:
| 時間足 | 定数 |
|---|---|
| 1分足 | PERIOD_M1 |
| 5分足 | PERIOD_M5 |
| 15分足 | PERIOD_M15 |
| 1時間足 | PERIOD_H1 |
| 4時間足 | PERIOD_H4 |
| 日足 | PERIOD_D1 |
例:
PERIOD_H1
これは 1時間足データを取得する意味になります。
現在のチャート時間足を取得する場合は
PERIOD_CURRENT
を使用します。
start_pos(取得開始位置)
取得を開始するバー位置を指定します。
| 値 | 意味 |
|---|---|
| 0 | 最新バー |
| 1 | 1本前 |
| 2 | 2本前 |
例:
CopyRates(_Symbol, PERIOD_H1, 0, 50, rates);
この場合
最新バーから50本取得します。
count(取得本数)
取得するローソク足の数を指定します。
例:
100
これは 100本のローソク足を取得する意味です。
ただし、ヒストリ不足の場合は 指定した本数より少なくなることがあります。
rates_array(コピー先配列)
価格データを格納する配列です。
型は必ず
MqlRates
である必要があります。
例:
MqlRates rates[];
この配列に次のデータが格納されます。
- 時刻
- 始値
- 高値
- 安値
- 終値
- ティック数
MQL5では、価格データはすべてこの構造体で管理されます。
2.3 CopyRatesの基本サンプルコード
実際に使う場合のシンプルな例を示します。
void OnStart()
{
MqlRates rates[];
int copied = CopyRates(_Symbol, PERIOD_H1, 0, 10, rates);
if(copied > 0)
{
Print("最新終値: ", rates[0].close);
}
else
{
Print("CopyRates error");
}
}
このコードの処理は次の通りです。
- MqlRates配列を作成
- H1データを10本取得
- 最新終値を表示
EA開発では、このデータを使ってトレードロジックを作ります。
2.4 よくある失敗
CopyRatesの使用で初心者がよく失敗するポイントをまとめます。
配列を宣言していない
次のようなコードはエラーになります。
CopyRates(_Symbol, PERIOD_H1, 0, 10, rates);
rates配列が存在しないためです。
必ず事前に
MqlRates rates[];
を宣言する必要があります。
データ取得数を確認していない
次のようなコードは危険です。
CopyRates(_Symbol, PERIOD_H1, 0, 10, rates);
Print(rates[0].close);
CopyRatesが失敗した場合、rates配列が空の可能性があります。
必ず次のようにチェックします。
if(copied > 0)
ヒストリ不足
取得本数を多く設定すると、データ不足になる場合があります。
例:
CopyRates(_Symbol, PERIOD_H1, 0, 10000, rates);
この場合
- ヒストリ未ロード
- 初期データ不足
で失敗する可能性があります。
環境によって取得可能な履歴数は異なるため、実際に取得できた数を確認する設計が重要です。
3. MqlRates構造体の中身(OHLCデータの構造)
3.1 MqlRatesとは何か
MqlRates は、MQL5でローソク足データをまとめて扱うための構造体です。
構造体とは、複数のデータを1つのセットとして扱うためのデータ型です。
CopyRates関数は、取得した価格データを MqlRates配列 に格納します。
基本的な宣言は次の通りです。
MqlRates rates[];
この配列の1要素には、1本のローソク足データが入ります。
例えば
rates[0] → 最新のローソク足
rates[1] → 1本前
rates[2] → 2本前
という形でアクセスできます。
EAやインジケーターでは、この構造体から
- 始値
- 高値
- 安値
- 終値
- 時刻
などを取得してトレードロジックを作ります。
3.2 MqlRates構造体のメンバー一覧
MqlRates構造体には次のデータが含まれています。
| メンバー | 意味 |
|---|---|
| time | ローソク足の開始時刻 |
| open | 始値 |
| high | 高値 |
| low | 安値 |
| close | 終値 |
| tick_volume | ティック数 |
| spread | スプレッド |
| real_volume | 実際の出来高(ブローカーによる) |
MQL5の定義は次のようになっています。
struct MqlRates
{
datetime time;
double open;
double high;
double low;
double close;
long tick_volume;
int spread;
long real_volume;
};
多くのEAでは、特に次の4つを使います。
- open
- high
- low
- close
これが OHLCデータ です。
3.3 OHLCデータの取得例
CopyRatesで取得したデータは次のように使います。
MqlRates rates[];
int copied = CopyRates(_Symbol, PERIOD_H1, 0, 10, rates);
if(copied > 0)
{
Print("Open: ", rates[0].open);
Print("High: ", rates[0].high);
Print("Low: ", rates[0].low);
Print("Close: ", rates[0].close);
}
このコードでは
- H1データ10本取得
- 最新バーのOHLCを表示
しています。
よく使われるデータ例を示します。
| コード | 意味 |
|---|---|
| rates[0].close | 最新終値 |
| rates[1].close | 1本前終値 |
| rates[0].high | 最新高値 |
| rates[0].low | 最新安値 |
例えば 直近高値ブレイク戦略 なら次のようなコードになります。
double lastHigh = rates[1].high;
if(Bid > lastHigh)
{
Print("ブレイクアウト");
}
3.4 時刻データの扱い
MqlRatesには time メンバーがあります。
rates[0].time
これは ローソク足の開始時刻 を表します。
型は datetime です。
表示する場合は次のようにします。
Print(TimeToString(rates[0].time));
EAでは次のような用途で使われます。
- 新しいバーの検出
- トレード時間制御
- 時系列分析
3.5 初心者がつまずきやすいポイント
MqlRates構造体の扱いでは、初心者がよく混乱するポイントがあります。
配列インデックスの意味
MQL5では
0 = 最新バー
1 = 1本前
2 = 2本前
です。
初心者は
0 = 一番古い
と勘違いすることが多いです。
未取得データへのアクセス
次のようなコードは危険です。
Print(rates[0].close);
CopyRatesが失敗した場合、rates配列にデータが存在しない可能性があります。
必ず次のチェックを行います。
if(copied > 0)
real_volumeは使えない場合が多い
real_volumeは 実際の出来高 ですが、
- FXブローカー
- CFD
では 0になるケースが多いです。
そのためFXでは通常
tick_volume
を使用します。
3.6 CopyRatesとMqlRatesの関係まとめ
CopyRatesの処理は次の流れになります。
価格履歴
↓
CopyRates
↓
MqlRates配列
↓
EAロジック
つまり
CopyRatesはデータ取得、MqlRatesはデータ保存の役割です。
この2つを理解すると、MQL5での価格処理が非常に分かりやすくなります。
4. CopyRatesの実践サンプルコード(EAでの使い方)
4.1 最も基本的なCopyRatesの使用例
実際のEA開発では、CopyRatesを使って直近のローソク足データを取得し、売買判断に利用するケースが多くあります。
まずは最も基本的なサンプルコードを示します。
void OnTick()
{
MqlRates rates[];
int copied = CopyRates(_Symbol, PERIOD_H1, 0, 5, rates);
if(copied <= 0)
{
Print("CopyRates error");
return;
}
double lastClose = rates[1].close;
double currentClose = rates[0].close;
Print("現在終値: ", currentClose);
Print("1本前終値: ", lastClose);
}
このコードでは次の処理を行っています。
- MqlRates配列を作成
- 1時間足データを5本取得
- 最新終値と1本前終値を取得
- ログに表示
EAでは、このように取得した価格データを使ってトレード条件を作ります。
4.2 直近高値ブレイク戦略の例
CopyRatesを使う典型例として、高値ブレイク戦略があります。
これは
- 前回高値を超えたら買う
という非常にシンプルなロジックです。
void OnTick()
{
MqlRates rates[];
int copied = CopyRates(_Symbol, PERIOD_M15, 0, 3, rates);
if(copied <= 0)
return;
double previousHigh = rates[1].high;
if(Bid > previousHigh)
{
Print("高値ブレイク発生");
}
}
この例では
| データ | 意味 |
|---|---|
| rates[0] | 現在バー |
| rates[1] | 1本前 |
| rates[2] | 2本前 |
を利用しています。
EAではこのように過去バーの価格を参照する処理が非常に多いです。
4.3 新しいローソク足の検出
EAでは新しいバーが確定したタイミングで処理を行うことがよくあります。
CopyRatesとMqlRatesを使えば、簡単に新バー検出ができます。
datetime lastBarTime = 0;
void OnTick()
{
MqlRates rates[];
if(CopyRates(_Symbol, PERIOD_H1, 0, 2, rates) <= 0)
return;
if(rates[0].time != lastBarTime)
{
lastBarTime = rates[0].time;
Print("新しいバーが開始しました");
}
}
このコードでは
- 最新バーの時刻
- 前回記録した時刻
を比較しています。
もし違えば
新しいローソク足が開始した
という意味になります。
この処理はEAで非常によく使われるテクニックです。
4.4 複数時間足のデータ取得(マルチタイムフレーム)
CopyRatesの強みは、現在のチャートとは別の時間足データも取得できる点です。
例:
M15チャートでH1トレンドを確認する場合
void OnTick()
{
MqlRates h1Rates[];
if(CopyRates(_Symbol, PERIOD_H1, 0, 10, h1Rates) <= 0)
return;
double h1Close = h1Rates[0].close;
double h1PrevClose = h1Rates[1].close;
if(h1Close > h1PrevClose)
{
Print("H1は上昇トレンド");
}
}
このように
- 上位足トレンド判定
- 下位足エントリー
という戦略を作ることができます。
マルチタイムフレーム分析は、EA開発では非常に一般的です。
4.5 初心者がよくやる実装ミス
CopyRatesの実装では、初心者がよく失敗するポイントがあります。
必要本数を取得していない
例えば次のコードです。
CopyRates(_Symbol, PERIOD_H1, 0, 1, rates);
この場合
rates[1]
は存在しません。
そのため
CopyRates(..., 2, rates)
のように必要なバー数を確保する必要があります。
毎Tick大量データ取得
次のようなコードは非効率です。
CopyRates(_Symbol, PERIOD_H1, 0, 1000, rates);
これを OnTickで毎回実行するとパフォーマンスが低下します。
通常は
- 必要最小限のバー数
- 新バー時のみ取得
にするのが良い設計です。
CopyRatesの戻り値を確認しない
CopyRatesは失敗することがあります。
例えば
- ヒストリ不足
- サーバ未同期
- 初回ロード
などです。
必ず次のチェックを入れます。
if(copied <= 0)
4.6 実務でよく使われるCopyRatesパターン
EA開発では、次のようなパターンがよく使われます。
| 用途 | 取得本数 |
|---|---|
| 新バー検出 | 2 |
| 前回ローソク足 | 2 |
| ブレイクアウト | 10 |
| テクニカル計算 | 100〜500 |
必要以上にデータを取得すると、EAの処理が重くなるため注意が必要です。
5. CopyRatesでよく発生するエラーと対処方法
5.1 CopyRatesが失敗する主な原因
CopyRatesはシンプルな関数ですが、実際のEA開発ではデータ取得に失敗するケースが少なくありません。
特に初心者が遭遇しやすい原因は次の通りです。
| 原因 | 内容 |
|---|---|
| ヒストリカルデータ不足 | 必要なローソク足データが端末に存在しない |
| Market Watch未登録 | 通貨ペアが監視リストに登録されていない |
| 取得本数が多すぎる | 指定したバー数を取得できない |
| サーバ未同期 | MT5起動直後でデータ同期が完了していない |
| 配列アクセスミス | 取得本数より多いインデックスにアクセス |
これらの問題はプログラムの書き方だけでなく、端末環境にも影響されることがあります。
5.2 ヒストリカルデータ不足
最も多い問題が ヒストリカルデータ不足 です。
例えば次のコードを考えます。
MqlRates rates[];
int copied = CopyRates(_Symbol, PERIOD_H1, 0, 1000, rates);
この場合、MT5端末に 1000本分のH1データが存在しない と、指定数を取得できません。
結果として
copied < 1000
になります。
対処方法は次の通りです。
対処方法
- チャートを開いてデータをロードする
- 取得数を減らす
- 戻り値で実際の取得数を確認する
安全なコード例
int copied = CopyRates(_Symbol, PERIOD_H1, 0, 100, rates);
if(copied <= 0)
{
Print("CopyRates failed");
return;
}
EAでは常に取得成功を確認する設計が重要です。
5.3 Market Watchに通貨ペアがない
別の通貨ペアのデータを取得する場合、Market Watchに登録されていないと失敗することがあります。
例:
CopyRates("GBPUSD", PERIOD_H1, 0, 10, rates);
もしGBPUSDがMarket Watchに存在しない場合、データ取得に失敗することがあります。
対処方法として、次の関数を使います。
SymbolSelect("GBPUSD", true);
これにより
- Market Watchに登録
- データ同期開始
が行われます。
例:
SymbolSelect("GBPUSD", true);
CopyRates("GBPUSD", PERIOD_H1, 0, 10, rates);
5.4 MT5起動直後のデータ未同期
MT5を起動した直後は
- サーバ接続
- ヒストリ同期
が完了していない場合があります。
この状態でCopyRatesを呼ぶと
-1
が返ることがあります。
この場合は
- 数秒待つ
- 再試行する
などの処理を入れると安定します。
例:
if(copied <= 0)
{
Print("data not ready");
return;
}
5.5 配列サイズエラー(Array Out Of Range)
CopyRates関連で非常に多いエラーが
array out of range
です。
原因は
取得本数より大きいインデックスを参照していることです。
例:
CopyRates(_Symbol, PERIOD_H1, 0, 2, rates);
double price = rates[5].close;
この場合
rates[0]
rates[1]
しか存在しません。
対処方法
if(copied >= 2)
{
double price = rates[1].close;
}
EAでは配列アクセス前に取得数を確認するのが基本です。
5.6 データ順序の誤解
初心者が混乱しやすいポイントとして、バーの順序があります。
CopyRatesで取得した配列は通常
| インデックス | 意味 |
|---|---|
| 0 | 最新バー |
| 1 | 1本前 |
| 2 | 2本前 |
です。
しかし
ArraySetAsSeries(rates, true);
を使用すると
時系列配列として扱われるため、挙動が変わることがあります。
EA開発では、配列の順序を常に意識する必要があります。
5.7 CopyRatesエラー対策の基本テンプレート
実務では、次のようなコードパターンがよく使われます。
MqlRates rates[];
int copied = CopyRates(_Symbol, PERIOD_H1, 0, 10, rates);
if(copied <= 0)
{
Print("CopyRates failed");
return;
}
if(copied < 2)
{
Print("not enough bars");
return;
}
double closePrice = rates[1].close;
このように
- 取得成功確認
- 必要本数確認
の2段階チェックを行うと、安全なEAになります。
6. CopyRatesとCopyBufferの違い
6.1 CopyRatesとCopyBufferの役割
MQL5でデータ取得を行う際、初心者が混同しやすい関数に CopyBuffer があります。
どちらも「データをコピーする関数」ですが、取得するデータの種類が異なります。
| 関数 | 取得できるデータ |
|---|---|
| CopyRates | 価格データ(OHLC) |
| CopyBuffer | インジケーター値 |
つまり
CopyRates → ローソク足データ
CopyBuffer → インジケーター計算結果
という役割の違いがあります。
EA開発では、この2つを組み合わせて使うケースが非常に多くあります。
6.2 CopyRatesで取得するデータ
CopyRatesは、チャートのローソク足そのものを取得します。
取得できる主なデータは次の通りです。
| データ | 意味 |
|---|---|
| open | 始値 |
| high | 高値 |
| low | 安値 |
| close | 終値 |
| time | バー時刻 |
| tick_volume | ティック数 |
例:
MqlRates rates[];
CopyRates(_Symbol, PERIOD_H1, 0, 10, rates);
double lastClose = rates[0].close;
このように、価格情報はすべて MqlRates構造体にまとめて格納されます。
CopyRatesは
- ローソク足分析
- ブレイクアウト判定
- ボラティリティ計測
などの用途で使用されます。
6.3 CopyBufferで取得するデータ
CopyBufferは、インジケーターの計算結果を取得する関数です。
例えば
- 移動平均
- RSI
- MACD
- ATR
などです。
基本的な使い方は次の通りです。
int handle = iMA(_Symbol, PERIOD_H1, 20, 0, MODE_SMA, PRICE_CLOSE);
double buffer[];
CopyBuffer(handle, 0, 0, 10, buffer);
このコードでは
- 20期間移動平均を作成
- 移動平均値を取得
しています。
CopyBufferは インジケーターハンドル を使ってデータを取得する仕組みです。
6.4 典型的なEAのデータ取得構成
実際のEAでは、次のように CopyRates + CopyBuffer を組み合わせます。
価格データ → CopyRates
インジケーター → CopyBuffer
例:
MqlRates rates[];
double ma[];
CopyRates(_Symbol, PERIOD_H1, 0, 10, rates);
CopyBuffer(maHandle, 0, 0, 10, ma);
このように
- 価格
- 指標
を同時に取得してトレードロジックを構築します。
6.5 CopyRatesとCopyBufferの比較
初心者向けに整理すると次のようになります。
| 項目 | CopyRates | CopyBuffer |
|---|---|---|
| 用途 | 価格取得 | 指標取得 |
| データ形式 | MqlRates構造体 | double配列 |
| 必要条件 | なし | インジケーターハンドル |
| 主用途 | EAロジック | テクニカル分析 |
簡単に言うと
CopyRates → ローソク足
CopyBuffer → 指標値
と覚えると分かりやすいです。
6.6 初心者がよく混同するポイント
CopyRatesとCopyBufferは似ているため、次のようなミスがよく発生します。
CopyBufferで価格を取得しようとする
CopyBufferは価格データを取得できません。
価格は必ず
CopyRates
を使います。
CopyRatesでインジケーター値を取得しようとする
CopyRatesは 指標値を取得できません。
例えば
- RSI
- MACD
はCopyBufferで取得します。
配列型の違い
CopyRates
MqlRates rates[];
CopyBuffer
double buffer[];
型が異なるため、間違えるとコンパイルエラーになります。
6.7 EA開発の基本データフロー
多くのEAは次のような構造になります。
価格取得 → CopyRates
インジケーター → CopyBuffer
トレード判断 → EAロジック
注文実行 → OrderSend
このデータフローを理解すると、MQL5のEA構造が非常に分かりやすくなります。
7. CopyRatesの実務ベストプラクティス(高速化・安定化)
7.1 CopyRatesは必要最小限のデータだけ取得する
EA開発で重要なのは 処理速度と安定性 です。
CopyRatesは便利な関数ですが、大量データを頻繁に取得するとEAのパフォーマンスが低下します。
初心者がよく書いてしまう例:
MqlRates rates[];
CopyRates(_Symbol, PERIOD_H1, 0, 1000, rates);
このコードを OnTick()で毎回実行すると非常に非効率です。
特に
- 高頻度Tick
- 複数通貨ペアEA
- VPS運用
ではパフォーマンスに影響が出る可能性があります。
そのため実務では、必要最小限のバー数だけ取得する設計にします。
例:
MqlRates rates[];
CopyRates(_Symbol, PERIOD_H1, 0, 3, rates);
このように ロジックに必要なバー数だけ取得するのが基本です。
7.2 新しいバーが発生したときだけデータ取得する
EAの多くは 新しいローソク足が確定したときだけ処理する設計にします。
理由
- Tickごとの計算を減らせる
- CPU負荷を下げられる
- ロジックが安定する
典型的な実装は次の通りです。
datetime lastBarTime = 0;
void OnTick()
{
MqlRates rates[];
if(CopyRates(_Symbol, PERIOD_H1, 0, 2, rates) <= 0)
return;
if(rates[0].time != lastBarTime)
{
lastBarTime = rates[0].time;
Print("新しいバー");
}
}
この設計にすると
Tick毎処理 → 新バー処理
に変わるため、EAが非常に安定します。
7.3 ArraySetAsSeriesを適切に使う
MQL5では、配列の順序を変更する関数があります。
ArraySetAsSeries(array, true);
これを設定すると
| インデックス | 意味 |
|---|---|
| 0 | 最新バー |
| 1 | 1本前 |
| 2 | 2本前 |
という 時系列配列(Series配列)になります。
多くのEAでは、この設定を使用します。
例:
MqlRates rates[];
ArraySetAsSeries(rates, true);
CopyRates(_Symbol, PERIOD_H1, 0, 10, rates);
ただしCopyRatesは、環境によって既にSeries順で格納される場合もあります。
そのため、実装時には
- 実際の配列順序
- ロジックとの整合性
を確認することが重要です。
7.4 CopyRatesは毎Tick呼ぶ必要はない
初心者がやりがちな設計として
OnTick()
{
CopyRates(...);
}
があります。
しかし多くのEAでは
- 新バー
- 注文判定
のタイミングだけ取得すれば十分です。
推奨設計:
Tick受信
↓
新バー判定
↓
CopyRates
↓
ロジック計算
この設計にすると
- CPU負荷減少
- VPS安定
- EA処理高速化
というメリットがあります。
7.5 CopyRatesの安全テンプレート
実務では、次のようなテンプレートコードがよく使われます。
MqlRates rates[];
int copied = CopyRates(_Symbol, PERIOD_H1, 0, 10, rates);
if(copied <= 0)
{
Print("CopyRates error");
return;
}
if(copied < 2)
{
Print("not enough bars");
return;
}
double lastClose = rates[1].close;
このコードでは
- CopyRates成功確認
- 必要バー数確認
- 安全にデータ利用
という3段階チェックを行っています。
EA開発ではこのような 防御的プログラミング が非常に重要です。
7.6 CopyRatesを理解するとEA開発が楽になる
MQL5のEAでは、価格データ取得の多くが
- CopyRates
- CopyBuffer
で構成されています。
その中でもCopyRatesは
EAの基礎データ取得関数
と言える存在です。
これを正しく理解すると
- ブレイクアウトEA
- トレンドEA
- ボラティリティEA
など、ほとんどの戦略を実装できるようになります。
8. FAQ(よくある質問)
8.1 MQL5のCopyRatesとは何ですか?
CopyRates は、MQL5でローソク足データ(OHLC)を取得するための関数です。
EAやインジケーターでは、過去の価格データを利用してトレード判断を行います。そのため、指定した通貨ペア・時間足・バー数の価格履歴を取得する目的でCopyRatesが使用されます。
取得されたデータは MqlRates構造体配列 に格納されます。
8.2 CopyRatesで取得できるデータは何ですか?
CopyRatesで取得できる主なデータは次の通りです。
| データ | 内容 |
|---|---|
| time | ローソク足開始時刻 |
| open | 始値 |
| high | 高値 |
| low | 安値 |
| close | 終値 |
| tick_volume | ティック数 |
| spread | スプレッド |
| real_volume | 実出来高(ブローカー依存) |
多くのEAでは、特に open / high / low / close の4つ(OHLC)が使用されます。
8.3 CopyRatesとCopyBufferの違いは何ですか?
役割が異なります。
| 関数 | 用途 |
|---|---|
| CopyRates | 価格データ取得 |
| CopyBuffer | インジケーター値取得 |
CopyRatesはローソク足データを取得し、CopyBufferは移動平均やRSIなどのインジケーター計算結果を取得します。
EAでは、この2つを組み合わせて使用することが一般的です。
8.4 CopyRatesが失敗する原因は何ですか?
主な原因は次の通りです。
- ヒストリカルデータ不足
- 通貨ペアがMarket Watchに登録されていない
- MT5起動直後でデータ同期が完了していない
- 取得本数が多すぎる
- 配列アクセスミス
特に初心者は、CopyRatesの戻り値を確認しないまま配列にアクセスしてしまうケースが多いです。
8.5 CopyRatesの戻り値は何を意味しますか?
CopyRatesの戻り値は
コピーされたバー数(ローソク足数)
です。
例:
10 → 10本取得成功
0 → データなし
-1 → エラー
そのためEAでは、必ず次のようにチェックします。
if(copied <= 0)
8.6 rates[0]は最新バーですか?
通常は 最新バー を指します。
| インデックス | 意味 |
|---|---|
| rates[0] | 最新バー |
| rates[1] | 1本前 |
| rates[2] | 2本前 |
ただし、配列設定(ArraySetAsSeries)によって挙動が変わる場合があります。
8.7 CopyRatesは毎Tick実行する必要がありますか?
必ずしも必要ではありません。
多くのEAでは
- 新しいローソク足が確定したタイミング
- トレード判定時
のみ実行します。
毎Tick大量データを取得すると、EAの処理負荷が増える可能性があります。
8.8 CopyRatesはどのくらいのバー数を取得すべきですか?
用途によって異なります。
| 用途 | 取得本数 |
|---|---|
| 新バー検出 | 2 |
| 前回ローソク足参照 | 2〜3 |
| ブレイクアウト判定 | 10〜20 |
| テクニカル計算 | 100〜500 |
必要以上に取得すると処理が重くなるため、最小限の本数にするのが基本です。