MQL4で配列の途中に要素を割り込ませたいとき、標準関数だけでは対応できません。
ArrayResize()で配列全体のサイズを1つ増やし、
割り込ませたい位置より後ろの要素を1つずつ後ろへずらすループを、
自分で書く必要がありました。
特定の要素だけを削除する場合も同様で、後ろの要素を前に詰めるループが必須でした。
MQL5では、この「途中への挿入」「途中の削除」がArrayInsert()・ArrayRemove()という2つの関数だけでできるようになりました。
この記事では、グリッド(ナンピン)注文の価格帯リストを、あとから1本だけ追加したり、
約定済みのレベルを取り除いたりする実装を例に、この2関数と、
配列の中身をログへ出力するArrayPrint()をあわせて解説します。
ArrayInsert関数の書式
bool ArrayInsert( void &array[], //挿入先の配列(動的配列のみ対応) const void &src[], //挿入する値が入った配列 uint dst, //挿入先の位置(0始まり) uint src_start=0, //srcの何番目から使うか uint count=WHOLE_ARRAY //srcから何個コピーするか );
戻り値は成功・失敗を表すbool値です。
array側の指定位置(dst)より後ろの要素は、挿入した分だけ自動的に後ろへずれます。
この「自動でずらしてくれる」部分が、
MQL4で自分でループを書いていた処理をまるごと肩代わりしてくれる部分です。
注意点が1つあります。
ArrayInsert()は動的配列(サイズ未指定の[]で宣言し、ArrayResize()等でサイズを決める配列)にしか使えません。
固定サイズの配列(double arr[10]のように要素数を書いた配列)には使えないため、
宣言時から気をつけてください。
ArrayRemove関数の書式
bool ArrayRemove( void &array[], //対象の配列(動的配列のみ対応) uint start, //削除を始める位置 uint count=WHOLE_ARRAY //削除する個数 );
startからcount個の要素を取り除き、残った要素は前へ詰められ、
配列全体のサイズも自動的に縮みます。
こちらもArrayInsertと同じく、動的配列にしか使えません。
ArrayPrint関数の書式
void ArrayPrint( const void &array[], //出力したい配列 int digits=_Digits, //小数点以下の桁数 string separator=NULL //要素の区切り文字(省略時は半角スペース) );
配列の中身をまとめて「エキスパート」タブのログへ出力するデバッグ用の関数です。
要素を1つずつPrint()でループ出力する手間が省け、
ArrayInsert()・ArrayRemove()の前後で配列の状態を目視確認するのに便利です。
グリッド価格帯リストを動的に管理する設計
ナンピン・マーチンゲール系のグリッドEAでは、
あらかじめ決めた間隔の価格帯に順番に注文を並べる設計がよく使われます。
この記事のサンプルは、その価格帯を昇順に並べた動的配列として管理し、
次の3つの操作をArrayInsert()・ArrayRemove()・ArrayPrint()だけで実現します。
- 新しい価格帯を、昇順を保ったまま好きな位置に割り込ませる(
ArrayInsert()) - 約定・決済済みの価格帯を取り除く(
ArrayRemove()) - 操作のたびに配列全体をログへ出力して状態を確認する(
ArrayPrint())
実際に動くコード全体
グリッド価格帯リストへの挿入・削除・ログ出力を実際に確認できる、
MetaEditorでコンパイルできるスクリプトです。
//+------------------------------------------------------------------+
//| ArrayInsertRemoveDemo.mq5 |
//| Copyright 2026, FX-EA System Project Creator |
//| https://creator.fx-ea-system-project.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, FX-EA System Project Creator"
#property link "https://creator.fx-ea-system-project.com/"
#property version "1.00"
#property script_show_inputs
input double GridStep = 50;//グリッドの初期間隔(point)
double GridLevels[];//昇順に並んだ価格レベルを保持する動的配列
//+------------------------------------------------------------------+
//| 指定した価格を、昇順を保ったまま配列へ挿入する |
//+------------------------------------------------------------------+
bool InsertGridLevel(double price)
{
int total = ArraySize(GridLevels);
int pos = total;//デフォルトは末尾に追加
for(int i=0; i<total; i++)
{
if(price < GridLevels[i])
{
pos = i;
break;
}
}
double src[1];
src[0] = price;
if(!ArrayInsert(GridLevels, src, pos, 0, 1))
{
Print("ArrayInsertに失敗しました。エラーコード=", GetLastError());
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
//| 指定した価格を配列から取り除く(約定・決済済みのレベル) |
//+------------------------------------------------------------------+
bool RemoveGridLevel(double price)
{
int total = ArraySize(GridLevels);
for(int i=0; i<total; i++)
{
if(MathAbs(GridLevels[i]-price) < _Point)//浮動小数点の誤差を許容して比較
{
if(!ArrayRemove(GridLevels, i, 1))
{
Print("ArrayRemoveに失敗しました。エラーコード=", GetLastError());
return(false);
}
return(true);
}
}
Print("指定した価格が配列内に見つかりませんでした: ", price);
return(false);
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
ArrayResize(GridLevels, 0);
double base = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double step = GridStep*_Point;
//まず3つの価格レベルを追加する(順不同で追加しても昇順に整列される)
InsertGridLevel(base + step*2);
InsertGridLevel(base);
InsertGridLevel(base + step);
Print("--- 3レベル追加後 ---");
ArrayPrint(GridLevels);
//あとから1本だけ、間に割り込ませたいレベルを追加する
InsertGridLevel(base + step*1.5);
Print("--- 割り込みレベル追加後 ---");
ArrayPrint(GridLevels);
//一番下のレベルが約定・決済されたと仮定して取り除く
RemoveGridLevel(base);
Print("--- 最下段レベル削除後 ---");
ArrayPrint(GridLevels);
}
//+------------------------------------------------------------------+
MetaEditorで実際に動かす手順
- MetaTrader 5の「ツール」→「MetaQuotes Language Editor」でMetaEditorを開く
- 「ファイル」→「新規作成」→「スクリプト」を選び、名前を「ArrayInsertRemoveDemo」にして作成する(中身は空のテンプレートで構いません)
- テンプレートの中身を全て削除し、上のコードを丸ごと貼り付ける
- F7キー(またはコンパイルボタン)でコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
- MT5の「ナビゲーター」パネルからスクリプトを探し、任意のチャートへドラッグ&ドロップして実行する
- 「エキスパート」タブに、3レベル追加後・割り込み追加後・削除後の3回分の配列の中身が、それぞれ昇順で出力されることを確認する
コピペしてコンパイルが通らない・意図通りに動かないときに確認すること
GridLevelsが固定サイズ配列(double GridLevels[10]のように要素数を書いた宣言)になっていないか。ArrayInsert()・ArrayRemove()は動的配列(double GridLevels[])にしか使えないArrayInsert()の第3引数(dst)が配列のサイズを超えていないか。末尾に追加したい場合は現在のArraySize()をそのまま渡せば末尾追加になるRemoveGridLevel()のような価格の一致判定を==で書いていないか。double型の価格は微小な誤差を含むことがあるため、この記事のように`MathAbs(a-b) < _Point`のような許容誤差つき比較にするArrayPrint()の出力が期待した順番になっていない場合、InsertGridLevel()側の挿入位置探索ロジック(`price < GridLevels[i]`の向き)が昇順・降順のどちらを想定しているか見直す
【MQL5入門】MQL4にはない配列操作|ArrayInsert・ArrayRemove・ArrayPrintでグリッド価格帯を動的に編集する:まとめ
ArrayInsert()・ArrayRemove()は、
MQL4では手動のループでしか実現できなかった「配列の途中への挿入・削除」を標準関数だけで完結させてくれる、
MQL5で追加された機能です。
どちらも動的配列にしか使えないという制約さえ押さえておけば、
グリッド注文の価格帯リストのように、順序を保ちながら要素が増減するデータ構造を、
自分でずらし処理を書くことなく安全に管理できます。
ArrayPrint()と組み合わせて、
操作の前後で配列の状態をログ確認する習慣もあわせて身につけてください。
コメント