MQL4の配列で最も危険なのは、文法を間違えることより「`array[0]`が何を指しているか」
を思い込むことです。
普通の配列では0番が先頭ですが、時系列配列では0番が最新データです。
この記事では、よく一緒に使う3関数を次の役割に分けて解説します。
- `ArrayResize()`:動的配列の要素数を決める
- `ArrayCopy()`:配列の値を別の配列へコピーする
- `ArraySetAsSeries()`:添字の向きを時系列形式へ変える
ArrayResize:動的配列の大きさを確保する
int ArrayResize( void& array[], int new_size, int reserve_size=0 );
戻り値は変更後の全要素数、失敗時は`-1`です。
サイズを実行時に変えられるのは`double values[];`のような動的配列です。
`double values[100];`のような静的配列は対象ではありません。
3番目の`reserve_size`は、少しずつ配列を拡張する処理で物理的なメモリ再確保を減らすための予約領域です。
1回だけサイズを決めるなら省略して構いません。
ArrayCopy:何個コピーできたかを戻り値で確認する
int ArrayCopy( void& dst_array[], const void& src_array[], int dst_start=0, int src_start=0, int count=WHOLE_ARRAY );
戻り値はコピーした要素数です。
コピー元とコピー先が同じ配列の場合、結果は未定義です。
型が異なる場合は変換が試みられますが、暗黙変換に頼るより同じ型を使う方が安全です。
ArraySetAsSeries:0番を最新データにする
bool ArraySetAsSeries( const void& array[], bool flag );
`true`にすると、時系列と同じく0番が最新側になります。
数値の動的配列に対して使い、静的配列と多次元配列には設定できません。
値そのものを逆順に並べ替える関数ではなく、添字の解釈を変える関数です。
3関数を一度に確認するスクリプト
//+------------------------------------------------------------------+
//| ArrayFunctionsDemo.mq4 |
//+------------------------------------------------------------------+
#property strict
#property script_show_inputs
input int DataCount = 5;
void OnStart()
{
if(DataCount < 2)
{
Print("DataCountは2以上にしてください");
return;
}
double normal[];
if(ArrayResize(normal,DataCount,100) == -1)
{
Print("ArrayResize失敗");
return;
}
//普通の配列: 0番から古い→新しい順に値を入れる
for(int i=0;i<DataCount;i++)
normal[i]=100.0+i;
double copied[];
int copiedCount=ArrayCopy(copied,normal,0,0,WHOLE_ARRAY);
if(copiedCount != DataCount)
{
Print("ArrayCopy失敗 copied=",copiedCount);
return;
}
Print("通常方向 copied[0]=",copied[0],
" copied[last]=",copied[ArraySize(copied)-1]);
if(!ArraySetAsSeries(copied,true))
{
Print("ArraySetAsSeries失敗");
return;
}
Print("時系列方向 copied[0]=",copied[0],
" copied[last]=",copied[ArraySize(copied)-1]);
}
この例では、通常方向の`copied[0]`は最初に入れた100です。
`ArraySetAsSeries(copied,true)`の後は、
同じ配列の0番から見える値が最新側へ変わります。
MetaEditorでの実行手順
- MT4のMetaEditorで「新規作成」→「スクリプト」を選ぶ
- `ArrayFunctionsDemo`として保存し、コードを貼り付ける
- F7でコンパイルし、エラー・警告が0件であることを確認する
- 任意のチャートへ実行し、「エキスパート」タブの2行を比較する
よくあるエラーと勘違い
- 配列範囲外になる:`ArrayResize()`の戻り値を確認せず代入している
- 最新足のつもりが最古データになる:`ArraySetAsSeries()`の設定状態を確認していない
- コピー結果が欠ける:`src_start`と`count`の合計がコピー元範囲を超えている
- 処理が極端に遅い:ループのたびに予約なしで1要素ずつ`ArrayResize()`している
まとめ
配列処理は「サイズ」
「内容」
「向き」を分けて考えると混乱しません。
`ArrayResize()`で領域を確保し、`ArrayCopy()`の戻り値でコピー件数を確認し、
最新データを0番として扱いたい場合だけ`ArraySetAsSeries()`を使います。
関数を呼んだ事実ではなく、各戻り値と0番要素の意味を確認する習慣が、
気づきにくい売買ロジックのずれを防ぎます。
コメント