【MQL5】MT5CopyRatesFromPos関数の使い方と自動売買実装コード

1. MT5CopyRatesFromPos関数の概要と実務での活用法

MQL5(MetaQuotes Language 5)において、過去の価格データ(始値、高値、安値、終値、時間、スプレッド等)を取得する際に最も多用される関数の一つが、特定の「位置(インデックス)」を指定してデータをコピーする手法です。PythonのMetaTrader5ライブラリではcopy_rates_from_posという名称ですが、MQL5の組み込み関数ではCopyRates関数のオーバーロード(引数のパターン違い)として実装されています。

実務レベルの開発では、主に以下のようなシーンで活用されます。
* テクニカル指標の自作: 直近の数本(例えば直近100本)のローソク足データを取得し、独自の計算ロジック(カスタム移動平均やボラティリティ算出)に適用する。
* パターン認識: 「1本前の足が陽線で、2本前の足が陰線である」といったプライスアクションを確認する。
* バックテストの高速化: 必要な期間のデータだけを配列にメモリ展開することで、無駄なリソース消費を抑えた効率的な演算を行う。

初心者が特につまずきやすいのは、「データの同期」です。プログラムを実行した瞬間にヒストリカルデータがターミナルに読み込まれていない場合、関数がエラーを返したり、不完全なデータを返したりすることがあります。実戦的なEA開発では、単に関数を呼ぶだけでなく、正しくコピーできたかをチェックするエラーハンドリングが必須となります。

2. 構文と戻り値

MQL5における「位置指定によるレート取得」の基本構文は以下の通りです。

int  CopyRates( 
   string           symbol_name,       // 通貨ペア名(NULL指定で現在のチャート)
   ENUM_TIMEFRAMES  timeframe,         // 時間軸(PERIOD_M15など)
   int              start_pos,         // コピーを開始する位置(0が最新の足)
   int              count,             // コピーする個数
   MqlRates         rates_array[]      // 格納先のMqlRates型配列
   );

パラメーター解説

  1. symbol_name: 取得したい通貨ペアを指定します。_SymbolまたはNULLを指定すると、EAが動いているチャートの通貨ペアが選択されます。
  2. timeframe: PERIOD_H1(1時間足)やPERIOD_D1(日足)など、取得したい時間枠を指定します。
  3. start_pos: データの取得開始位置です。0を指定すると、現在動いている最新の足(未確定足)から取得を開始します。1を指定すると、一つ前の確定足から取得します。
  4. count: 取得するバーの本数です。
  5. rates_array[]: MqlRatesという構造体の配列を渡します。この配列に、時刻・始値・高値・安値・終値・ティックボリューム・スプレッド・リアルボリュームが格納されます。

戻り値

  • 成功した場合:コピーされた要素(バー)の個数を返します。
  • 失敗した場合:-1 を返します。詳細なエラー内容はGetLastError()関数で確認します。

3. 具体的な使い方・実践サンプルコード

以下のコードは、最新の確定足3本分を取得し、それぞれの終値をログに出力するシンプルなEAの例です。

//+------------------------------------------------------------------+
//|                                              SampleCopyRates.mq5 |
//+------------------------------------------------------------------+
#property strict

void OnTick()
{
   // レート情報を格納するための構造体配列を宣言
   MqlRates rates[];

   // 配列を時系列順(最新の足がインデックス0)に並び替える設定
   // これを行わないと、配列の[0]が最も古いデータになってしまいます
   ArraySetAsSeries(rates, true);

   // 直近の確定足(インデックス1)から3本分のデータを取得
   // 第3引数を「1」にすることで、現在動いている足(0)を除外した確定データを取得できます
   int copied = CopyRates(_Symbol, _Period, 1, 3, rates);

   // エラーチェック
   if(copied < 3)
   {
      Print("データの取得に失敗しました。エラーコード:", GetLastError());
      return;
   }

   // 取得したデータの表示
   for(int i = 0; i < copied; i++)
   {
      PrintFormat("確定足 [%d] 終値: %.5f, 時刻: %s", 
                  i + 1,                   // 1本前、2本前、3本前
                  rates[i].close,          // 終値
                  TimeToString(rates[i].time) // 足の時刻
                 );
   }
}

4. 使用上の注意点とよくあるエラー

開発時に注意すべきポイントがいくつかあります。

  1. ArraySetAsSeriesの有無:
    デフォルトのMqlRates配列は、インデックスが大きくなるほど新しいデータになる「通常の配列」です。しかし、FXトレーダーの感覚では「0が最新の足」である方が扱いやすいため、ArraySetAsSeries(rates, true)を実行して、インデックス0が最新になるように設定するのが一般的です。

  2. データ未ロード(エラー4401):
    ERR_HISTORY_NOT_FOUND(4401)が出る場合、ヒストリーデータがまだサーバーからダウンロードされていない可能性があります。ループで数回リトライするか、SeriesInfoInteger関数でデータの同期状況を確認する処理を入れると堅牢になります。

  3. メモリ負荷:
    countに大きな値(例:1,000,000)を入れ、それをOnTick(毎ティック)ごとに実行すると、PCやVPSのCPU・メモリを激しく消耗します。必要な本数だけをコピーするか、新しい足が生成された時(OnBarイベント)のみ実行するように工夫しましょう。

5. 【重要】自動売買における約定スピードと環境の罠

アルゴリズムトレードにおいて、ロジックの正しさ以上に収益を左右するのが「実行環境の物理的距離」です。自宅のPCや一般的な汎用クラウドサーバーでEAを稼働させる場合、インターネット網を経由する際のネットワーク遅延(レイテンシ)が数十ミリ秒〜数百ミリ秒発生します。この遅延の間に市場価格は刻一刻と変化し、EAが判断した価格と実際に約定する価格の乖離(スリッページ)を引き起こします。特にボラティリティが高い局面では、このわずかな遅延が致命的な損失に直結し、バックテストでは勝てていたロジックがリアル口座では全く通用しないという事態を招きます。

プロのクオンツエンジニアが極限まで約定スピードを追求するのは、コンマ数秒の優位性が年間収益に巨大な差を生むことを知っているからです。取引サーバーの至近距離に位置するFX専用のVPS(仮想専用サーバー)を利用することは、もはやオプションではなく、自動売買における「必須インフラ」と言えます。安定した電源、24時間の稼働保証、そして何よりブローカーへの圧倒的な低遅延環境を整えることで初めて、あなたの書いたアルゴリズムはその真価を発揮することができるのです。

💡 この記事の内容を実運用で活かすには?

この記事の内容を実運用で活かすには、正しい環境が必要です。
特にVPSを使わないと、このロジックは再現できません。

コメント

タイトルとURLをコピーしました