1. MQL5のArrayResizeとは何か
MQL5の ArrayResize は、配列(Array)のサイズを変更するための関数です。
配列とは「同じ型のデータをまとめて保存するデータ構造」であり、EA(自動売買プログラム)やインジケータでは頻繁に使用されます。
MQL5では、配列には次の2種類があります。
- 静的配列(サイズ固定)
- 動的配列(サイズ変更可能)
このうち ArrayResizeが使えるのは動的配列のみです。
動的配列はプログラム実行中にサイズを増減できるため、次のような処理で利用されます。
- 価格データの保存
- インジケータ計算結果の格納
- トレード履歴や統計データの蓄積
- EAの内部ログ管理
例えば、データを追加しながら処理する場合、配列サイズを途中で増やす必要があります。そのときに ArrayResizeで配列の長さを変更します。
1.1 ArrayResizeの基本役割
ArrayResizeの役割は非常にシンプルで、配列の要素数を変更することです。
例えば次のような動的配列があるとします。
double price[];
この状態では、まだ配列のサイズは 0(要素なし) です。
ここでArrayResizeを使うと、配列のサイズを変更できます。
double price[];
ArrayResize(price,10);
この処理を実行すると、配列の状態は次のようになります。
price[0]
price[1]
price[2]
...
price[9]
つまり 10個の要素を持つ配列が作成されます。
初心者がよく誤解するポイントとして、次の点があります。
よくある誤解
- ArrayResizeは「値を追加する関数」ではない
- あくまで「配列のサイズを変更する関数」
つまり次の処理は エラーになります。
double price[];
price[0]=Close[0];
理由は単純で、配列サイズが0のままだからです。
この場合は必ず先にArrayResizeを行います。
double price[];
ArrayResize(price,1);
price[0]=Close[0];
この順番を間違えると、MQL5では非常に多いエラーである
array out of range
が発生します。
1.2 ArrayResizeが必要になる場面
ArrayResizeは、EA開発やインジケータ開発ではかなり頻繁に使われます。
特に次のようなケースで必要になります。
① データを蓄積する処理
例:価格履歴を保存
double history[];
ArrayResize(history,ArraySize(history)+1);
history[ArraySize(history)-1]=Close[0];
このコードでは
- 配列サイズを1つ増やす
- 新しい要素に価格を保存
という流れになります。
② インジケータデータの保存
インジケータの計算結果を配列に保存する場合にも利用されます。
例
- RSI履歴
- ATR履歴
- 移動平均値
③ EAの統計データ管理
EAでは以下のデータを記録する場合があります。
- トレード結果
- 利益履歴
- ドローダウン
- ロットサイズ
こうしたデータを配列に保存する際にもArrayResizeが必要です。
つまずきやすいポイント
初心者がよく失敗するポイントを整理します。
① 配列サイズを変更せずにアクセスする
array out of range
の原因の大半がこれです。
② 静的配列にArrayResizeを使う
次のコードはエラーになります。
double price[10];
ArrayResize(price,20);
理由
静的配列は サイズ固定 のため。
③ ループ内で大量にArrayResizeする
次のようなコードは パフォーマンスが悪化する可能性があります。
for(int i=0;i<10000;i++)
{
ArrayResize(arr,i+1);
}
この問題は reserve_size(メモリ予約) を使うことで改善できます。
ArrayResizeは単純な関数ですが、EAの安定性と速度に影響する重要な関数です。
特に大規模EAでは、メモリ管理を意識した使い方が重要になります。
2. ArrayResizeの構文と引数
ArrayResizeを正しく使うためには、関数の構文(シンタックス)と各引数の意味を理解することが重要です。
特に初心者は 第2引数(新しいサイズ) と 第3引数(reserve_size) の役割を混同しやすいため注意が必要です。
ArrayResizeの基本構文は次の通りです。
int ArrayResize(
void& array[],
int new_size,
int reserve_size=0
);
この関数は 配列サイズの変更を行い、変更後の配列サイズを返す関数です。
2.1 第1引数:array(対象配列)
第1引数には サイズ変更を行う配列を指定します。
例:
double data[];
ArrayResize(data,10);
このコードでは data配列のサイズを10に変更します。
ポイント
- 動的配列のみ指定可能
- 配列名だけを書く
- 添字(index)は付けない
誤った例
ArrayResize(data[0],10);
これは 配列要素を渡しているためエラーになります。
2.2 第2引数:new_size(新しい配列サイズ)
第2引数は 変更後の配列サイズです。
例えば次のコードでは、配列サイズが5になります。
double data[];
ArrayResize(data,5);
この場合、配列は次のようになります。
data[0]
data[1]
data[2]
data[3]
data[4]
つまり 要素数=5 です。
ここで重要な点があります。
配列インデックスは0から始まる
つまり
サイズ5 → 最大indexは4
初心者はここで次のミスをよくします。
ArrayResize(data,5);
data[5]=100;
これは array out of range エラーになります。
正しい書き方
data[4]=100;
2.3 第3引数:reserve_size(メモリ予約)
第3引数 reserve_size は少し上級者向けの機能です。
これは 配列のメモリをあらかじめ確保する機能です。
例
ArrayResize(data,10,100);
この意味は次の通りです。
| 項目 | 意味 |
|---|---|
| 現在サイズ | 10 |
| 確保メモリ | 100 |
つまり
100要素分のメモリを確保しつつ、現在サイズは10
という状態になります。
なぜこれが必要かというと、ArrayResizeは内部でメモリ再確保が発生するためです。
配列を頻繁に拡張すると、次の処理が繰り返されます。
- 新しいメモリ確保
- 既存データコピー
- 古いメモリ解放
この処理は CPU負荷が高いため、EAのパフォーマンスに影響します。
そのため、次のようなケースではreserve_sizeを使うと効率が良くなります。
例:データを大量に追加する場合
double history[];
ArrayResize(history,0,10000);
これにより 1万要素分のメモリを事前確保できます。
2.4 戻り値(Return Value)
ArrayResizeは 変更後の配列サイズを返します。
例
int size;
size=ArrayResize(data,20);
この場合
size = 20
になります。
ただし エラーの場合は -1 が返ります。
例
if(ArrayResize(data,20)==-1)
{
Print("ArrayResize error");
}
実務では 戻り値チェックを入れると安全性が上がります。
よくある失敗
ArrayResizeの典型的なミスをまとめます。
① 静的配列で使う
double data[10];
ArrayResize(data,20);
静的配列はサイズ固定のため コンパイルエラーになります。
② indexをサイズと勘違い
サイズ10
→ indexは0〜9
③ ループ内で毎回ArrayResize
次のコードはパフォーマンスが悪くなります。
for(int i=0;i<10000;i++)
{
ArrayResize(data,i+1);
}
改善方法
reserve_sizeを使う
ArrayResizeの構文は単純ですが、メモリ管理とパフォーマンスに影響する重要な関数です。
正しく理解することで、EAの処理速度や安定性を大きく改善できます。
3. ArrayResizeの基本的な使い方(サンプルコード)
ArrayResizeは構文自体はシンプルですが、実際のEAやインジケータでは使い方のパターンがいくつか存在します。
ここでは、初心者が最初に理解しておくべき 基本パターン をサンプルコードとともに解説します。
実務では主に次の3つの使い方が多くなります。
- 配列を初期化する
- 配列を拡張する
- 配列を縮小する
これらを順番に見ていきます。
3.1 配列を初期化する
動的配列は、宣言しただけではサイズが0の状態です。
double data[];
この状態では、まだ要素は存在しません。
data size = 0
そのため、配列を使用する前に ArrayResizeでサイズを確保する必要があります。
例:
double data[];
ArrayResize(data,10);
この処理により、配列は次の状態になります。
data[0]
data[1]
data[2]
data[3]
data[4]
data[5]
data[6]
data[7]
data[8]
data[9]
ここで初めて値を書き込めます。
data[0] = 1.0;
data[1] = 2.0;
よくある失敗
次のコードは初心者がよく書く間違いです。
double data[];
data[0] = 10;
この場合
array out of range
エラーになります。
理由
配列サイズが0だから
必ず ArrayResize → 配列アクセス の順番で書きます。
3.2 配列サイズを拡張する
EAでは、処理の途中で配列を拡張するケースがよくあります。
例えば、価格履歴を配列に保存する処理です。
例:
double history[];
int size = ArraySize(history);
ArrayResize(history, size + 1);
history[size] = Close[0];
処理の流れ
- 現在の配列サイズを取得
- 配列サイズを1つ増やす
- 新しい要素にデータを保存
図で表すと次のようになります。
Before
history[0]
history[1]
history[2]
After resize
history[0]
history[1]
history[2]
history[3]
新しい要素は
index = size
になります。
注意点
配列サイズを増やした場合、新しい要素の値は 初期化されない場合があります。
環境や型によって動作が異なることもあるため、必要なら明示的に代入する方が安全です。
例
history[size] = Close[0];
3.3 配列サイズを縮小する
ArrayResizeは 配列サイズを小さくすることも可能です。
例
ArrayResize(data,5);
もし元のサイズが10だった場合
Before
data[0]
data[1]
data[2]
data[3]
data[4]
data[5]
data[6]
data[7]
data[8]
data[9]
After
data[0]
data[1]
data[2]
data[3]
data[4]
index 5以降のデータは削除されます。
これは完全に失われるため注意が必要です。
3.4 ArraySizeと組み合わせる
実務では ArraySize関数とセットで使うことが非常に多いです。
ArraySizeは 現在の配列サイズを取得する関数です。
例
double data[];
ArrayResize(data,10);
int size = ArraySize(data);
Print(size);
出力
10
配列を動的に扱う場合は、ほぼ必ず
ArrayResize
ArraySize
をセットで使用します。
よくある失敗
初心者がよくやるミスを整理します。
① resize後のindexを間違える
size = 5
→ 新しい要素は index 5
② resize前にArraySizeを取得しない
次のコードはバグの原因になります。
ArrayResize(data, ArraySize(data)+1);
data[ArraySize(data)] = value;
理由
resize後にArraySizeが変わる
安全な書き方
int size = ArraySize(data);
ArrayResize(data,size+1);
data[size]=value;
③ 大量データでresizeを繰り返す
これは EAの速度低下の原因になります。
改善方法
reserve_sizeを使う
ArrayResizeは、EAの内部データ構造を扱う際に非常に重要な関数です。
特にトレード履歴、価格履歴、統計データなどを扱う場合は必ず理解しておく必要があります。
4. reserve_sizeの意味とパフォーマンス最適化
ArrayResizeには 第3引数 reserve_size というオプションがあります。
これは 配列のメモリを事前に確保する機能であり、特に 大量データを扱うEAやインジケータでは重要なパフォーマンス最適化手法になります。
初心者はこの引数を使わなくても動作しますが、処理速度やメモリ効率を考えると理解しておく価値があります。
4.1 reserve_sizeとは何か
ArrayResizeの構文をもう一度確認します。
int ArrayResize(
void& array[],
int new_size,
int reserve_size=0
);
ここで
reserve_size = 追加で確保するメモリ容量
を意味します。
例えば次のコードを見てみます。
double data[];
ArrayResize(data,10,100);
この処理は次の意味になります。
| 項目 | 値 |
|---|---|
| 現在の配列サイズ | 10 |
| 内部メモリ確保 | 100 |
つまり
100個分のメモリを確保しておく
ただし現在使える要素は10
という状態になります。
4.2 なぜreserve_sizeが必要なのか
ArrayResizeは内部的に メモリ再確保(reallocation) を行います。
配列サイズを変更するたびに、次の処理が発生します。
1 新しいメモリ確保
2 既存データコピー
3 古いメモリ解放
この処理は CPU負荷が比較的大きい処理です。
もし次のようなコードを書くとします。
double data[];
for(int i=0;i<10000;i++)
{
ArrayResize(data,i+1);
}
この場合、10000回メモリ再確保が発生する可能性があります。
EAでは以下の影響が出ることがあります。
- 処理速度低下
- CPU使用率上昇
- ストラテジーテスターの速度低下
そのため あらかじめメモリを確保する方法が推奨されます。
4.3 reserve_sizeを使った最適化
同じ処理を reserve_sizeを使って最適化すると次のようになります。
double data[];
ArrayResize(data,0,10000);
for(int i=0;i<10000;i++)
{
int size = ArraySize(data);
ArrayResize(data,size+1);
data[size]=i;
}
この場合
メモリ確保 = 1回
になる可能性が高くなります。
つまり
ArrayResizeのコストが大幅に減る
というメリットがあります。
4.4 実務でよくある使い方
実務では次のようなケースでreserve_sizeを使います。
ケース1:トレード履歴の保存
EAがトレード履歴を保存する場合
double profitHistory[];
ArrayResize(profitHistory,0,1000);
これにより
最大1000トレード分
の履歴を効率的に管理できます。
ケース2:インジケータ計算
インジケータの計算では、バー数に応じて配列を使用します。
例
double buffer[];
ArrayResize(buffer,0,2000);
これにより
2000バー分の計算用メモリ確保
ができます。
4.5 reserve_sizeを使うべきか?
初心者がよく疑問に思うのが
常にreserve_sizeを使うべき?
という点です。
結論は次の通りです。
| ケース | 必要性 |
|---|---|
| 小規模EA | 不要でも問題なし |
| バックテスト大量データ | 有効 |
| 統計データ管理 | 推奨 |
| 高頻度処理EA | 推奨 |
つまり
パフォーマンス重視なら使う
という位置付けです。
よくある失敗
reserve_sizeに関する典型的なミスをまとめます。
① reserve_sizeをサイズと勘違い
ArrayResize(data,10,100);
これは
サイズ = 10
です。
100ではありません。
② reserve_sizeを毎回変更する
次のコードは意味がありません。
ArrayResize(data,i+1,10000);
reserve_sizeは
最初の1回で十分
です。
③ メモリを過剰確保する
例えば
ArrayResize(data,0,100000000);
これは環境によっては メモリ不足になる可能性があります。
reserve_sizeは EAの高速化に役立つ重要なオプションですが、基本的には 大量データを扱う場合に意識すれば十分です。
5. ArrayResize関連エラー(array out of range)の原因と対処法
MQL5で配列を扱う際、最も多く発生するエラーの一つが
array out of range
です。
これは 配列の範囲外の要素にアクセスしたときに発生するエラーです。
ArrayResizeを正しく理解していない場合、このエラーが頻繁に発生します。
ここでは 典型的な原因と具体的な対処方法を解説します。
5.1 配列サイズを確保せずにアクセスする
最も多い原因が 配列サイズを確保していない状態でアクセスするケースです。
誤ったコード
double data[];
data[0] = Close[0];
このコードでは配列サイズが 0のままです。
data size = 0
そのため
data[0]
にアクセスすると array out of range エラーになります。
正しい書き方
必ず ArrayResizeでサイズを確保します。
double data[];
ArrayResize(data,1);
data[0] = Close[0];
処理の順序
1 配列サイズ確保
2 配列へアクセス
5.2 indexの範囲を間違える
配列のindexは 0から始まるため、初心者はここでミスをします。
例
ArrayResize(data,5);
この場合
data[0]
data[1]
data[2]
data[3]
data[4]
までが有効です。
しかし次のコードはエラーになります。
data[5] = 100;
理由
最大index = size - 1
だからです。
対処方法
安全な書き方は ArraySizeを使う方法です。
int size = ArraySize(data);
data[size-1] = 100;
これにより 範囲外アクセスを防止できます。
5.3 resize後のindexミス
配列拡張処理でよく起きるミスがあります。
誤ったコード
ArrayResize(data, ArraySize(data)+1);
data[ArraySize(data)] = value;
このコードは 範囲外アクセスになる可能性があります。
理由
ArrayResize後
ArraySizeが変わる
ためです。
正しい書き方
先にサイズを保存します。
int size = ArraySize(data);
ArrayResize(data,size+1);
data[size] = value;
この書き方は EA開発で非常によく使われる安全パターンです。
5.4 ループ処理でのエラー
ループ処理でも array out of range が起きやすいです。
誤った例
for(int i=0;i<=ArraySize(data);i++)
{
Print(data[i]);
}
この場合
最後のループで
data[size]
にアクセスしてしまいます。
正しい書き方
for(int i=0;i<ArraySize(data);i++)
{
Print(data[i]);
}
重要ポイント
<= ではなく <
を使うことです。
5.5 ArrayResizeとSeries配列の混同
インジケータや価格データでは Series配列が使われます。
Series配列は
index 0 = 最新バー
という特殊な構造です。
例
Close[0] 最新価格
Close[1] 1本前
しかし ArrayResizeはSeries配列には使用できません。
例えば次の配列
Close[]
Time[]
High[]
Low[]
は ターミナル管理配列なので、resize不可です。
誤った例
ArrayResize(Close,100);
これは コンパイルエラーになります。
よくある失敗まとめ
ArrayResize関連の典型ミスを整理します。
| 失敗 | 原因 |
|---|---|
| array out of range | 配列サイズ未確保 |
| indexエラー | sizeとindex混同 |
| resize後のミス | ArraySizeの再計算 |
| ループバグ | <= 使用 |
| Series配列resize | 不可能 |
安全な配列操作パターン
実務では次の書き方が安全です。
int size = ArraySize(data);
ArrayResize(data,size+1);
data[size] = value;
この方法は
EA
インジケータ
スクリプト
すべてのMQL5プログラムで使われる 基本パターンです。
ArrayResizeのエラーの多くは 配列サイズ管理のミスです。
ArraySizeと組み合わせて使うことで、ほとんどの問題を防ぐことができます。
6. EA開発でよく使うArrayResizeの実践パターン
ArrayResizeは単純な関数ですが、EA(自動売買プログラム)の内部処理では非常に重要な役割を持ちます。
特に次のような場面で頻繁に使用されます。
- トレード履歴の保存
- 価格履歴の管理
- インジケータ計算用データの保存
- 統計データの管理
ここでは 実務でよく使われる代表的なパターンを紹介します。
6.1 トレード結果履歴の保存
EAでは、トレード結果を配列に保存するケースがよくあります。
例えば 利益履歴を保存する配列を作る場合です。
例
double profitHistory[];
トレードが発生するたびに履歴を追加するコードは次のようになります。
void AddProfit(double profit)
{
int size = ArraySize(profitHistory);
ArrayResize(profitHistory,size+1);
profitHistory[size] = profit;
}
処理の流れ
- 現在の配列サイズ取得
- 配列を1つ拡張
- 新しい要素にデータ格納
この方法を使うことで
profitHistory[0]
profitHistory[1]
profitHistory[2]
...
という形で履歴を蓄積できます。
6.2 価格履歴の保存
EAでは、価格履歴を独自に管理することもあります。
例えば 一定期間の終値を保存する場合です。
例
double priceHistory[];
Tickごとに履歴を追加するコード
void AddPrice()
{
int size = ArraySize(priceHistory);
ArrayResize(priceHistory,size+1);
priceHistory[size] = Close[0];
}
これにより
過去価格データの履歴
を保存できます。
注意点
Tickごとに追加すると 配列が無制限に増える可能性があります。
そのため、実務では 履歴サイズを制限する処理を入れることが多いです。
例
#define MAX_HISTORY 1000
void AddPrice()
{
int size = ArraySize(priceHistory);
if(size >= MAX_HISTORY)
return;
ArrayResize(priceHistory,size+1);
priceHistory[size] = Close[0];
}
これにより メモリ使用量の増加を防ぐことができます。
6.3 統計データ管理
EAでは、次のような統計データを管理することがあります。
- 利益履歴
- ドローダウン
- ロットサイズ
- トレード回数
これらを配列で管理することで、EA内部で分析処理を行うことが可能になります。
例:ロット履歴
double lotHistory[];
void AddLot(double lot)
{
int size = ArraySize(lotHistory);
ArrayResize(lotHistory,size+1);
lotHistory[size] = lot;
}
このような履歴は次の分析に利用できます。
- 平均ロット計算
- 最大ロット
- ロット変動
6.4 配列バッファとして使う
インジケータやEAでは 計算用バッファ配列として使うこともあります。
例
double maBuffer[];
初期化
ArrayResize(maBuffer,1000);
この配列に 移動平均などの計算結果を保存します。
例
maBuffer[i] = iMA(NULL,0,20,0,MODE_SMA,PRICE_CLOSE,i);
このように
計算結果
↓
配列に保存
↓
後で分析
という使い方ができます。
6.5 reserve_sizeを併用した履歴管理
履歴データを扱うEAでは、reserve_sizeを併用することで高速化できます。
例
double profitHistory[];
ArrayResize(profitHistory,0,1000);
履歴追加
void AddProfit(double profit)
{
int size = ArraySize(profitHistory);
ArrayResize(profitHistory,size+1);
profitHistory[size] = profit;
}
この方法は
履歴EA
統計EA
分析EA
でよく使われる構造です。
よくある失敗
実務でよくあるミスを整理します。
① 無制限履歴
ArrayResizeを無制限に使う
→ メモリ増加
② resize頻度が高すぎる
Tickごとにresize
→ CPU負荷増加
③ ArraySizeを毎回呼びすぎる
処理速度を重視するEAでは
sizeを変数で管理
することもあります。
実務での基本パターン
EA開発では次の書き方が最もよく使われます。
int size = ArraySize(data);
ArrayResize(data,size+1);
data[size] = value;
このコードは
MQL5配列操作の基本テンプレート
と言ってよいレベルで広く使われています。
ArrayResizeは、EA内部データ構造を管理するための基本関数です。
トレード履歴、価格履歴、統計データなど、多くの処理で使用されます。
7. MQL5 ArrayResizeのFAQ(よくある質問)
ここでは、MQL5のArrayResizeに関して初心者がよく疑問に思うポイントをFAQ形式で整理します。
実際のEA開発やインジケータ作成でも頻繁に出てくる疑問なので、基本事項として理解しておくと役立ちます。
7.1 ArrayResizeはどんな配列でも使えますか?
いいえ。
ArrayResizeが使えるのは動的配列のみです。
動的配列の例
double data[];
この配列は実行中にサイズ変更できます。
一方、次のような 静的配列(サイズ固定)には使用できません。
double data[10];
静的配列にArrayResizeを使うと コンパイルエラーになります。
7.2 ArrayResizeを実行すると配列の値は消えますか?
通常は 既存の要素は保持されます。
例
double data[];
ArrayResize(data,3);
data[0]=1;
data[1]=2;
data[2]=3;
ArrayResize(data,5);
この場合
data[0] = 1
data[1] = 2
data[2] = 3
は保持されます。
ただし
data[3]
data[4]
は 未定義の値になる場合があります。
安全のため、必要なら 明示的に初期化することが推奨されます。
7.3 ArrayResizeを0にするとどうなりますか?
次のコード
ArrayResize(data,0);
は 配列を空にする処理になります。
つまり
配列サイズ = 0
になります。
これは 配列をリセットする用途で使われることがあります。
7.4 reserve_sizeは必ず使う必要がありますか?
必須ではありません。
次のケースでは 使わなくても問題ありません。
- 小規模EA
- データ量が少ない処理
- 一度だけresizeする場合
しかし次のケースでは reserve_sizeを使うと効率が良くなります。
- 大量データ処理
- 履歴データ管理
- 頻繁なresize処理
7.5 ArrayResizeとArraySizeの違いは何ですか?
役割は完全に異なります。
| 関数 | 役割 |
|---|---|
| ArrayResize | 配列サイズ変更 |
| ArraySize | 現在の配列サイズ取得 |
例
double data[];
ArrayResize(data,10);
int size = ArraySize(data);
この場合
size = 10
になります。
実務では
ArraySize
↓
ArrayResize
の組み合わせで使用することが多いです。
7.6 array out of rangeエラーの原因は何ですか?
主な原因は次の3つです。
① 配列サイズ未確保
double data[];
data[0] = 10;
② indexの範囲ミス
size = 5
最大index = 4
③ resize処理の順序ミス
ArrayResize(data,ArraySize(data)+1);
data[ArraySize(data)] = value;
安全な書き方
int size = ArraySize(data);
ArrayResize(data,size+1);
data[size] = value;
7.7 ArrayResizeはEAの速度に影響しますか?
場合によっては影響します。
ArrayResizeは内部で
メモリ再確保
データコピー
メモリ解放
を行うため、大量に呼び出すと処理速度が低下する可能性があります。
対策
- reserve_sizeを使う
- resize回数を減らす
- 配列サイズを事前確保する
ArrayResizeは、MQL5で配列を扱う際の基本関数です。
配列サイズ管理を正しく理解することで、EAやインジケータの安定性とパフォーマンスを大きく改善できます。
