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

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

MQL5のArrayCopyは、ある配列のデータを別の配列へ高速にコピーするための組み込み関数です。
FXのシステムトレード(EA開発)において、この関数は「計算負荷の軽減」と「コードの簡略化」という2つの大きな役割を担います。

実務レベルでの活用シーンとしては、主に以下のようなケースが挙げられます。
* インジケーター値の抽出: CopyBufferなどで取得した大量のデータから、特定の期間分だけを別配列に抽出して計算に回す。
* 独自データ構造の管理: 過去の特定期間の価格データ(OHLC)を独自に定義した構造体配列にバッファリングする。
* 多次元配列の整理: 複雑な多次元データを、処理しやすい1次元配列にフラット化して渡す。

初心者が特につまずきやすいのは、「配列のサイズ管理」です。MQL5では動的配列(サイズが決まっていない配列)を使うことが多いですが、ArrayCopyを実行する前に、受け取り側の配列が十分なサイズを確保しているか、あるいは自動で拡張される設定になっているかを理解していないと、ランタイムエラーや予期せぬ挙動を招きます。

2. 構文と戻り値

ArrayCopy関数の基本的な構文は以下の通りです。

uint ArrayCopy(
   void&        dst_array[],         // コピー先配列
   const void&  src_array[],         // コピー元配列
   int          dst_start=0,         // コピー先での開始インデックス
   int          src_start=0,         // コピー元での開始インデックス
   int          count=WHOLE_ARRAY    // コピーする要素数(デフォルトはすべて)
);

パラメーターの解説

  1. dst_array[]: データの貼り付け先となる配列です。
  2. src_array[]: データのコピー元となる配列です。
  3. dst_start: 貼り付け先の何番目の要素から書き込み始めるかを指定します。
  4. src_start: コピー元の何番目の要素から読み取り始めるかを指定します。
  5. count: いくつの要素をコピーするかを指定します。WHOLE_ARRAYを指定すると、src_startから最後までのすべての要素がコピーされます。

戻り値

実際にコピーされた要素の数(uint型)を返します。

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

以下のコードは、過去の確定足(終値)を取得し、その中から特定の直近数本分だけを別の配列に抽出してデバッグ表示する簡単なEAの例です。

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

// EAの初期化やティック毎の処理
void OnTick()
{
    // 1. コピー元の配列(全データ用)
    double closePrices[];

    // 直近10本の終値を取得
    ArraySetAsSeries(closePrices, true); // 時系列(最新が0番目)として扱う
    if(CopyClose(_Symbol, _Period, 0, 10, closePrices) < 0)
    {
        Print("価格データの取得に失敗しました。");
        return;
    }

    // 2. コピー先の配列(特定の3本分だけを保存したい)
    double extractedPrices[];

    // 動的配列の場合、事前にサイズを確保する必要がある(重要)
    ArrayResize(extractedPrices, 3);

    // 3. ArrayCopyを使用して、3番目から5番目(インデックス2〜4)のデータをコピー
    // dst_start=0, src_start=2, count=3
    uint copiedCount = ArrayCopy(extractedPrices, closePrices, 0, 2, 3);

    if(copiedCount > 0)
    {
        PrintFormat("%d 個の要素をコピーしました。", copiedCount);
        for(int i=0; i<(int)copiedCount; i++)
        {
            PrintFormat("extractedPrices[%d] = %f", i, extractedPrices[i]);
        }
    }
}

この例では、closePricesという大きなデータから、必要な部分(インデックス2から3要素分)だけをextractedPricesに高速に転送しています。ループ文(for文)で1つずつ代入するよりも、ArrayCopyを使うほうが実行速度が速く、コードもスマートになります。

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

  1. 動的配列のサイズ不足:
    コピー先の配列が動的配列(double arr[];など)の場合、ArrayCopyは自動的にサイズを拡張してくれません。必ず事前にArrayResizeで必要な要素数を確保しておくか、十分な要素数を持つ固定長配列を準備してください。
  2. 型の一致:
    コピー元とコピー先の配列の型(doubleとintなど)が異なると、コンパイルエラーになるか、暗黙の型変換が意図しない結果を招くことがあります。基本的には同じ型の配列間で利用します。
  3. 時系列設定(AsSeries)の混在:
    ArraySetAsSeriesを使って配列のインデックス順を逆にしている場合、src_startdst_startが指す場所が直感と逆になることがあります。コピーを実行する前に、どちらの配列が「時系列設定」になっているかを確認してください。
  4. メモリのオーバーラップ:
    同じ配列内でデータをずらしてコピーする場合(自分自身のインデックス0から1へコピーするなど)、ArrayCopyは正しく処理を行いますが、複雑なオフセット指定をするとロジックミスが発生しやすいため注意が必要です。

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

アルゴリズムトレードにおいて、プログラムの実行効率を高めるArrayCopyの活用は重要ですが、それ以上に収益へ直結するのが「物理的な通信環境」です。自宅のPCや一般的な光回線でEAを稼働させる場合、MT5サーバーとの間で数十から数百ミリ秒(ms)のネットワーク遅延(レイテンシ)が必ず発生します。

この遅延は、どれだけ最適化されたコードを書いても克服できません。指標発表時や相場の急変時、自宅PCからの注文がサーバーに届く頃には、すでに価格が数ピップス滑っている(スリッページが発生している)という致命的な損失を招きます。プロのクオンツエンジニアが極限まで約定スピードを追求する場合、ブローカーのデータセンターに物理的に近い場所にある「専用のVPS(仮想専用サーバー)」を利用することはもはや常識です。ネットワーク遅延を1ms単位で削ぎ落とすことが、スリッページを抑え、バックテスト通りの期待値を実運用で引き出すための唯一の技術的回答となります。

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

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

コメント

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