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

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

MQL5におけるArrayResizeは、動的配列(宣言時にサイズが決まっていない配列)のサイズを、プログラムの実行中に変更するための非常に重要な関数です。

FXの自動売買(EA)開発では、事前に扱うデータの数が確定していないケースが多々あります。例えば、「直近1時間のボラティリティが一定以上の足だけを抽出して保存したい」場合や、「特定の条件を満たしたティックデータのみを記録したい」場合などです。

実務で初心者が最もつまずきやすいのが、「配列の宣言だけして、サイズを確保せずに値を代入しようとする」ことです。MQL5では、動的配列はそのままでは箱が一つもありません。ArrayResizeでメモリを確保しなければ、実行時に「Array out of range(配列の範囲外)」という致命的なエラーが発生し、EAが停止してしまいます。

プロのクオンツエンジニアは、単にサイズを増やすだけでなく、後述する「予備サイズ(reserve_size)」を適切に設定することで、メモリ再割り当てによる計算負荷を抑え、プログラムの高速化を図ります。

2. 構文と戻り値

ArrayResize関数の構文は以下の通りです。

int ArrayResize(
   void&  array[],              // サイズを変更する配列(参照渡し)
   int    new_size,             // 新しいサイズ
   int    reserve_size = 0      // 予備のメモリ確保サイズ(オプション)
);

パラメーター

  1. array[]: 対象となる配列を指定します。必ず「動的配列」である必要があります。
  2. new_size: 新しく設定したい配列の要素数です。
  3. reserve_size: 非常に重要な隠れた設定です。次にサイズを増やすことを見越して、あらかじめ多めにメモリを確保しておく量です。頻繁にArrayResizeを繰り返す場合、この値を設定することでパフォーマンスが劇的に向上します。

戻り値

  • 成功した場合:変更後の配列の要素数を返します。
  • 失敗した場合:-1 を返します。メモリ不足などが原因です。

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

以下は、特定の条件(RSIが70以上)を満たした時の価格を動的配列に記録していく、実戦的なサンプルコードです。

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

// 記録用の動的配列
double highPriceHistory[];

void OnTick()
{
    // 現在のRSI値を取得(計算部分は簡略化)
    double rsi = CalculateRSI(); 

    if(rsi >= 70.0)
    {
        // 現在の配列サイズを取得
        int currentSize = ArraySize(highPriceHistory);

        // 配列を1つ増やす。
        // 第3引数に10を指定することで、10回に1回しか実際のメモリ確保を行わない(高速化)
        int newSize = ArrayResize(highPriceHistory, currentSize + 1, 10);

        if(newSize != -1)
        {
            // 新しく確保された末尾の要素に現在の価格を代入
            highPriceHistory[currentSize] = SymbolInfoDouble(_Symbol, SYMBOL_BID);

            Print("価格を記録しました。現在の記録数: ", newSize);
        }
        else
        {
            Print("エラー: ArrayResizeに失敗しました。エラーコード: ", GetLastError());
        }
    }
}

// ダミーのRSI計算関数
double CalculateRSI() { return 75.0; } 

このコードでは、reserve_sizeに「10」を指定しています。これにより、10回分のデータが入る領域を一気に確保するため、ティック毎のメモリ再構築を防ぎ、動作を軽くしています。

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

  1. 静的配列には使用不可
    double my_array[10]; のように、宣言時にサイズを指定している配列(静的配列)に対してArrayResizeを使うとコンパイルエラーになります。必ず double my_array[]; と宣言してください。

  2. 多次元配列の制約
    MQL5のArrayResizeでサイズ変更ができるのは、最初の次元のみです。2次元配列 array[X][Y] の場合、Xのサイズは変えられますが、Yのサイズを動的に変えることはできません。

  3. パフォーマンスの罠
    reserve_sizeを指定せずに、ループの中で毎回1ずつサイズを増やすと、その都度メモリのコピーが発生します。データの件数が数千、数万となる場合は、EAの動作が極端に重くなり、約定判断の遅れ(レイテンシ)を招く原因となります。

  4. ArraySetAsSeriesとの併用
    ArraySetAsSeries(array, true) を使って時系列(インデックス0が最新)にしている配列にArrayResizeを行うと、新しい要素は末尾(過去方向)に追加されます。混乱しないよう、リサイズ後に再度インデックス順序を確認することが重要です。

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

アルゴリズムの効率化と同様に、あるいはそれ以上に重要なのが「実行環境」です。どれほどArrayResizeの予備サイズを最適化してプログラムを高速化したとしても、ご自宅のPCから一般的なインターネット回線でトレードを行っている限り、物理的な「ネットワーク遅延(レイテンシ)」という壁にぶち当たります。自宅PCからの注文は、プロバイダーを経由して証券会社のサーバーに届くまでに数十〜数百ミリ秒の時間を要し、その間に有利な価格は消え去り、スリッページによる損失を招きます。

自動売買の世界で利益を安定させるには、証券会社のデータセンターに物理的に近い場所に位置する「専用のVPS(仮想専用サーバー)」の利用が不可欠です。24時間365日安定して稼働し、ミリ秒単位のスピード競争を勝ち抜くためのインフラを整えることは、勝つための最低条件と言えます。ネットワーク遅延による致命的な損失を避けるためにも、プロレベルの取引環境を構築することをお勧めします。

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

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

コメント

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