MQL5 ArraySetAsSeriesとは?配列を時系列にする使い方とCopyBufferとの関係を解説

目次

1. ArraySetAsSeriesとは何か(MQL5の配列方向を変更する関数)

ArraySetAsSeries は、MQL5で配列を「時系列データとして扱うかどうか」を設定するための関数です。
簡単に言うと、配列のインデックス(添字)の意味を、チャートの時間順に合わせるための設定です。

MQL5では、価格データやインジケータの値は 時間順のデータ(時系列データ)として扱われます。
しかし、通常のプログラミング言語における配列は、先頭から順番に古いデータ→新しいデータという構造になっています。

この違いを調整するために使用するのが ArraySetAsSeries です。

特に次のような処理では、ほぼ必ず使用されます。

  • インジケータの値を取得する処理
  • CopyBuffer関数でデータを取得する処理
  • EA(自動売買プログラム)のシグナル判定
  • バックテスト用データの取得

この関数を理解していないと、インジケータの値を誤って参照するバグが発生しやすくなります。

1.1 ArraySetAsSeriesの基本概念

MQL5のチャートデータは、最新のバーが最初に来る構造になっています。

例えば、次のような価格データを考えます。

バー 意味
0 最新のローソク足
1 1本前
2 2本前

つまり、MQL5では次のようなルールでデータを扱います。

index 0 = 最新バー
index 1 = 1本前
index 2 = 2本前

これは 時系列(Series)配列と呼ばれる構造です。

一方、通常の配列は次のような順序になります。

index 0 = 最も古いデータ
index n = 最新データ

この違いが、MQL5初心者が最も混乱しやすいポイントです。

ArraySetAsSeries を使うと、配列を以下のように扱えるようになります。

ArraySetAsSeries(array, true);

すると、その配列は Series配列(時系列配列)として扱われ、次のようになります。

array[0] = 最新データ
array[1] = 1つ前のデータ
array[2] = 2つ前のデータ

これにより、チャートデータと同じ感覚で配列を扱えるようになります。

1.2 なぜ配列方向を変更する必要があるのか

MQL5で配列方向を変更する理由は、チャートデータの構造に合わせるためです。

例えば、RSIの値を取得する処理を考えてみます。

double rsi[];

CopyBuffer(rsi_handle,0,0,10,rsi);

この状態では、配列の順序が 通常配列のままです。
つまり、次のような状態になります。

rsi[0] = 古いデータ
rsi[9] = 最新データ

しかし、多くのEAでは次のように使います。

最新RSI = rsi[0]
1本前RSI = rsi[1]

このとき ArraySetAsSeries を設定していないと、
最新データではなく古いデータを参照してしまう可能性があります。

その結果、次のような問題が発生します。

  • 売買シグナルが逆になる
  • バックテスト結果がおかしくなる
  • EAが期待通りに動作しない

このため、実務のEA開発では CopyBufferを使う配列にはほぼ必ずArraySetAsSeriesを設定します。

MQL5 ArraySetAsSeries vs default array indexing in CopyBuffer data retrieval, showing how incorrect index direction causes trading signal errors. Diagram compares normal array (oldest data at index 0) and series array (latest data at index 0), with code examples and RSI indicator chart explaining correct buffer indexing for accurate EA trade execution.

1.3 使用される主な場面

ArraySetAsSeriesは、主に次のような場面で使われます。

① インジケータデータ取得

RSIや移動平均などの値を取得する場合です。

double rsi[];

ArraySetAsSeries(rsi,true);
CopyBuffer(handle,0,0,10,rsi);

② EAのシグナル判定

例えば次のようなロジックです。

RSIが30以下 → 買い
RSIが70以上 → 売り

このとき、通常は次のデータを使います。

rsi[0] = 現在
rsi[1] = 1本前

③ マルチタイムフレームEA

複数の時間足のデータを扱うEAでは、
配列方向の統一が非常に重要になります。

つまずきやすいポイント(初心者がよく失敗する部分)

以下は、MQL5開発でよく起きるミスです。

① ArraySetAsSeriesを設定していない

結果

  • インジケータ値が逆順になる

② CopyBufferのあとに設定している

推奨順序

ArraySetAsSeries
↓
CopyBuffer

③ インデックスの意味を誤解している

初心者がよく勘違いする点

array[0] = 最新
array[1] = 1本前

④ バックテストとリアルで結果が変わる

配列方向のミスは、
バックテストの誤判定の原因になることがあります。

2. ArraySetAsSeriesの構文と使い方(基本仕様)

ArraySetAsSeries は、配列を時系列配列(Series配列)として扱うかどうかを設定する関数です。
主に 価格データ・インジケータデータ・CopyBufferで取得した配列を、チャートと同じ時間順で扱うために使用します。

この関数は 配列の中身を変更するのではなく、配列のインデックス解釈(参照方向)を変更するだけという点が重要です。

つまり、データ自体は変わらず、どの要素を index 0 として扱うかが変わります。

2.1 ArraySetAsSeriesの構文

ArraySetAsSeriesの基本構文は次のとおりです。

bool ArraySetAsSeries(
   void& array[],
   bool flag
);

引数の意味は以下の通りです。

引数 説明
array 対象となる配列
flag Series配列にするかどうか

flag の値によって挙動が変わります。

flag 意味
true 時系列配列として扱う
false 通常配列として扱う

多くのEAでは true を指定して使用します。

2.2 基本的な使用例

最も基本的な使用例は、インジケータデータ取得です。

double rsi[];

ArraySetAsSeries(rsi,true);

CopyBuffer(rsi_handle,0,0,10,rsi);

このコードでは次の処理が行われています。

  1. RSI用の配列を用意
  2. 配列をSeries配列に設定
  3. CopyBufferでRSIデータ取得

結果として配列は次の構造になります。

rsi[0] = 最新RSI
rsi[1] = 1本前RSI
rsi[2] = 2本前RSI

EAではこの形が最も使いやすいため、ほぼ標準的な書き方になっています。

2.3 通常配列との違い

ArraySetAsSeriesを使わない場合、配列は通常配列になります。

double rsi[];

CopyBuffer(rsi_handle,0,0,10,rsi);

この場合の配列構造は次の通りです。

rsi[0] = 最も古いデータ
rsi[9] = 最新データ

つまり 最新値は配列の最後に格納されます。

そのため次のようなコードが必要になります。

double latest_rsi = rsi[9];

しかしEAでは通常、

最新値 = index 0

として扱うことが多いため、ArraySetAsSeriesを使う方が分かりやすくなります。

2.4 戻り値

ArraySetAsSeriesは bool型の値を返します。

戻り値 意味
true 設定成功
false 設定失敗

通常のEAでは戻り値をチェックしないケースもありますが、
堅牢なプログラムを書く場合は確認する方が安全です。

if(!ArraySetAsSeries(rsi,true))
{
   Print("ArraySetAsSeries failed");
}

設定失敗はまれですが、不正な配列を指定した場合などに発生する可能性があります。

つまずきやすいポイント(よくある失敗)

ArraySetAsSeriesは単純な関数ですが、初心者が間違えやすいポイントがあります。

① 配列宣言前に使ってしまう

これはコンパイルエラーになります。

ArraySetAsSeries(rsi,true);
double rsi[];

必ず 配列宣言の後に書きます。

② CopyBufferの後に設定する

次の順序は推奨されません。

CopyBuffer(handle,0,0,10,rsi);
ArraySetAsSeries(rsi,true);

理由

  • データ解釈が混乱する
  • バグの原因になる

推奨順序

ArraySetAsSeries
↓
CopyBuffer

③ Series配列のインデックスを誤解する

初心者が最も混乱する部分です。

Series配列では

array[0] = 最新
array[1] = 1本前
array[2] = 2本前

になります。

④ 配列サイズを意識していない

CopyBufferで取得する数より配列サイズが小さいと、
Array out of range エラーが発生する可能性があります。

3. CopyBufferとArraySetAsSeriesの関係(EA開発で最も重要なポイント)

MQL5で ArraySetAsSeries が特に重要になるのは、CopyBuffer関数と組み合わせて使用する場合です。
実際のEA開発では、インジケータの値を取得する処理のほとんどが CopyBuffer+ArraySetAsSeries の形で実装されます。

この関係を理解していないと、最新データではなく古いデータを参照してしまうバグが発生するため注意が必要です。

3.1 CopyBufferとは何か(簡単なおさらい)

CopyBuffer は、インジケータの計算結果を配列へコピーする関数です。

基本構文

int CopyBuffer(
   int indicator_handle,
   int buffer_num,
   int start_pos,
   int count,
   double buffer[]
);

主な引数の意味

引数 意味
indicator_handle インジケータハンドル
buffer_num 取得するバッファ番号
start_pos 取得開始位置
count 取得するデータ数
buffer コピー先配列

この関数を使うと、インジケータ値を配列に取得できます。

例(RSI取得)

double rsi[];

CopyBuffer(rsi_handle,0,0,10,rsi);

ここで問題になるのが 配列の順序です。

3.2 CopyBufferで取得した配列の順序

CopyBufferで取得したデータは、通常配列として格納されます。

つまり、配列の構造は次のようになります。

rsi[0] = 最も古いデータ
rsi[1] = ...
rsi[9] = 最新データ

しかし、多くのEAでは次のように使いたいケースが多いはずです。

rsi[0] = 最新値
rsi[1] = 1本前

このときに使用するのが ArraySetAsSeries です。

3.3 CopyBufferとArraySetAsSeriesの正しい組み合わせ

EA開発での標準的なコードは次の形になります。

double rsi[];

ArraySetAsSeries(rsi,true);

CopyBuffer(rsi_handle,0,0,10,rsi);

この処理を行うと、配列は次の構造になります。

rsi[0] = 最新RSI
rsi[1] = 1本前RSI
rsi[2] = 2本前RSI

つまり チャートのバー番号と同じ感覚で配列を扱えるようになります。

3.4 EAの売買ロジック例

ArraySetAsSeriesを設定している場合、売買ロジックは次のように書けます。

例:RSIによる売買判定

if(rsi[0] < 30)
{
   // 買いシグナル
}

if(rsi[0] > 70)
{
   // 売りシグナル
}

また、クロス判定なども書きやすくなります。

例:RSIの反転

if(rsi[1] < 30 && rsi[0] > 30)
{
   // 買い
}

このように 最新バーと1本前バーを簡単に比較できるため、
EAのロジックが非常に読みやすくなります。

3.5 よくあるバグ(非常に多い)

ArraySetAsSeriesを設定していない場合、次のようなコードは意図通り動きません。

double rsi[];

CopyBuffer(handle,0,0,10,rsi);

if(rsi[0] < 30)
{
   Buy();
}

この場合、rsi[0]最新値ではなく古い値になります。

つまりEAは

  • 古いデータ
  • 過去のシグナル

を使って売買してしまいます。

結果として

  • バックテスト結果がおかしい
  • EAが遅れてエントリーする
  • シグナルがずれる

といった問題が発生します。

3.6 CopyBuffer使用時の推奨テンプレート

実務では、次の書き方が最も安全です。

double buffer[];

ArraySetAsSeries(buffer,true);

if(CopyBuffer(handle,0,0,10,buffer) <= 0)
{
   Print("CopyBuffer error");
   return;
}

double current = buffer[0];
double prev = buffer[1];

このようにすると

  • 配列方向のミス
  • データ取得失敗
  • バッファ不足

などの問題を防ぐことができます。

つまずきやすいポイント(CopyBuffer関連)

① ArraySetAsSeriesを忘れる

EA初心者が最もやりがちなミスです。

② CopyBufferの戻り値を確認していない

CopyBufferは 取得できたデータ数を返します。

失敗すると

0
または
-1

になることがあります。

③ 配列サイズ不足

取得数が配列サイズより大きいと

array out of range

エラーになります。

④ Series配列と通常配列を混在させる

同じロジック内で

  • Series配列
  • 通常配列

が混在すると、バグの原因になります。

4. ArraySetAsSeriesが使えない配列と制限事項

ArraySetAsSeriesは便利な関数ですが、すべての配列に対して使用できるわけではありません。
MQL5では配列の種類によって、Series配列(時系列配列)に変更できるものとできないものがあります。

この制限を理解していないと、コンパイルエラーや実行時エラーの原因になります。

4.1 ArraySetAsSeriesが使える配列

基本的に 動的配列(dynamic array)には使用できます。

動的配列とは、サイズを固定せずに宣言する配列のことです。

double price[];

このような配列には、次のように設定できます。

double price[];

ArraySetAsSeries(price,true);

また、以下のような型でも使用できます。

配列型 使用可否
double[] 使用可能
int[] 使用可能
datetime[] 使用可能
long[] 使用可能
bool[] 使用可能

つまり、通常の1次元動的配列であれば基本的に問題なく使用できます。

4.2 ArraySetAsSeriesが使えない配列

次のような配列では、ArraySetAsSeriesを使用できません。

① 固定サイズ配列

固定サイズで宣言した配列です。

double price[100];

この場合

ArraySetAsSeries(price,true);

エラーになります。

理由は、固定サイズ配列はコンパイル時にメモリ配置が決定されるため、
配列方向を変更する仕組みが適用できないためです。

② 多次元配列

ArraySetAsSeriesは 1次元配列のみ対応しています。

double matrix[10][10];

この配列に対して

ArraySetAsSeries(matrix,true);

を使うことはできません。

③ 構造体配列

構造体を格納した配列でも使用できません。

struct Data
{
   double value;
};

Data arr[];

このような配列に対してSeries設定を行うと、エラーになる場合があります。

※環境やコード構造により挙動が異なる場合があります。

4.3 MQL5の標準時系列配列

MQL5には、最初からSeries配列として扱われるデータがあります。

代表例

配列 意味
Time[] バー時間
Open[] 始値
High[] 高値
Low[] 安値
Close[] 終値
Volume[] 出来高

これらは チャートの価格データ配列です。

これらの配列は、最初から次の構造になっています。

index 0 = 最新バー
index 1 = 1本前
index 2 = 2本前

つまり ArraySetAsSeriesを設定する必要はありません。

4.4 ArraySetAsSeriesを解除する方法

Series配列を 通常配列に戻すことも可能です。

方法は、flagを false にするだけです。

ArraySetAsSeries(buffer,false);

この場合、配列は次のようになります。

buffer[0] = 古いデータ
buffer[n] = 最新データ

ただし、EA開発では falseに戻すケースはほとんどありません。

通常は

ArraySetAsSeries(array,true);

のまま使用します。

つまずきやすいポイント(制限関連)

① 固定サイズ配列で使ってしまう

次のコードはエラーになります。

double buffer[100];
ArraySetAsSeries(buffer,true);

解決方法

double buffer[];

に変更します。

② 多次元配列に適用する

Series設定は 1次元配列専用です。

③ 時系列配列と勘違いする

次の配列は すでにSeries配列です。

Close[]
Open[]
High[]
Low[]

そのため、通常はArraySetAsSeriesは不要です。

④ Series配列を前提にコードを書いてしまう

ArraySetAsSeriesを設定していない配列で

buffer[0] = 最新

としてしまうと、ロジックが破綻する可能性があります。

5. ArraySetAsSeriesを使った実践コード(EA開発例)

ArraySetAsSeriesは、実際のEA(自動売買プログラム)ではインジケータデータの取得処理と組み合わせて使用することがほとんどです。
ここでは、実務でよく使われる代表例として

  • RSIによる売買判定
  • 移動平均クロス判定

の2つを紹介します。

これらは CopyBuffer+ArraySetAsSeriesの典型パターンでもあります。

5.1 RSIを使った売買判定

まずは最もシンプルな例です。

RSIの値を取得し、過売り・過買い判定を行います。

コード例

int rsi_handle;
double rsi[];

int OnInit()
{
   rsi_handle = iRSI(_Symbol,_Period,14,PRICE_CLOSE);
   return(INIT_SUCCEEDED);
}

void OnTick()
{
   ArraySetAsSeries(rsi,true);

   if(CopyBuffer(rsi_handle,0,0,3,rsi) <= 0)
      return;

   double current = rsi[0];
   double previous = rsi[1];

   if(current < 30)
   {
      Print("Buy signal");
   }

   if(current > 70)
   {
      Print("Sell signal");
   }
}

処理の流れ

  1. RSIインジケータハンドルを作成
  2. RSI値を配列へ取得
  3. 最新値と1本前を参照
  4. 売買シグナル判定

Series配列にしているため

rsi[0] = 最新RSI
rsi[1] = 1本前

という形で扱えます。

5.2 移動平均クロス判定

EAで最もよく使われるロジックの1つが 移動平均クロスです。

  • 短期MA
  • 長期MA

を比較して売買判断を行います。

コード例

int fast_handle;
int slow_handle;

double fast_ma[];
double slow_ma[];

int OnInit()
{
   fast_handle = iMA(_Symbol,_Period,10,0,MODE_EMA,PRICE_CLOSE);
   slow_handle = iMA(_Symbol,_Period,50,0,MODE_EMA,PRICE_CLOSE);

   return(INIT_SUCCEEDED);
}

void OnTick()
{
   ArraySetAsSeries(fast_ma,true);
   ArraySetAsSeries(slow_ma,true);

   if(CopyBuffer(fast_handle,0,0,3,fast_ma) <= 0)
      return;

   if(CopyBuffer(slow_handle,0,0,3,slow_ma) <= 0)
      return;

   if(fast_ma[1] < slow_ma[1] && fast_ma[0] > slow_ma[0])
   {
      Print("Golden Cross");
   }

   if(fast_ma[1] > slow_ma[1] && fast_ma[0] < slow_ma[0])
   {
      Print("Dead Cross");
   }
}

Series配列を使うことで

fast_ma[0] = 現在
fast_ma[1] = 1本前

となるため、クロス判定が非常に書きやすくなります。

5.3 実務で使われる安全テンプレート

EA開発では、以下のようなテンプレートがよく使われます。

double buffer[];

ArraySetAsSeries(buffer,true);

int copied = CopyBuffer(handle,0,0,3,buffer);

if(copied <= 0)
{
   Print("CopyBuffer error");
   return;
}

double current = buffer[0];
double previous = buffer[1];

この書き方にすると

  • データ取得失敗
  • 配列順序ミス
  • インデックスバグ

を防ぐことができます。

よくある失敗(実装時)

① OnInitでArraySetAsSeriesを書いてしまう

次の書き方は問題になることがあります。

int OnInit()
{
   ArraySetAsSeries(buffer,true);
}

理由

  • 配列が再生成される可能性
  • CopyBufferで上書きされる可能性

安全なのは

OnTickで設定

です。

② CopyBufferの取得数が少ない

次のコードは危険です。

CopyBuffer(handle,0,0,1,buffer);

その後

buffer[1]

を参照すると

array out of range

になります。

③ 配列サイズを意識していない

安全な取得数

3〜10

程度にするのが一般的です。

④ Series配列を前提にロジックを書く

ArraySetAsSeriesを忘れると

最新 = buffer[0]

という前提が崩れます。

このミスは EA初心者の典型的なバグです。

6. ArraySetAsSeriesに関するよくある質問

ArraySetAsSeries は単純な関数に見えますが、実際のMQL5開発では CopyBuffer・価格配列・EAロジックと深く関係するため、初心者が混乱しやすいポイントが多くあります。
ここでは、実務で特によく出る質問とその考え方を整理します。

6.1 ArraySetAsSeriesを使うと配列の中身は並び替えられるのか

結論から言うと、配列の中身そのものを並び替えるわけではありません。

ArraySetAsSeries が変更するのは、あくまで 配列要素の参照方向です。
つまり、物理的に配列データを並べ替えるのではなく、index 0 を最新として扱うか、古いデータとして扱うかを切り替えています。

そのため、次の点は必ず理解しておく必要があります。

  • データの意味付けが変わる
  • ロジックの書き方が変わる
  • 既存コードの添字の意味が変わる

例えば、同じ配列でも設定次第で意味が変わります。

double buffer[];

ArraySetAsSeries(buffer,true);

この場合は

buffer[0] = 最新
buffer[1] = 1本前

です。

一方で false の場合は

buffer[0] = 古いデータ
buffer[n] = 最新

になります。

ここを誤解すると、コードは動くのに売買判断だけ間違うという厄介な不具合が起きます。

6.2 CopyBufferを使うなら毎回ArraySetAsSeriesを書くべきか

実務上は、対象配列を使う前に明示しておく方が安全です。
特にEAでは、可読性と再現性を重視したほうがよいため、CopyBufferを使う配列には毎回同じルールで書くのが無難です。

推奨形は次の通りです。

double ma_buffer[];

ArraySetAsSeries(ma_buffer,true);

if(CopyBuffer(handle,0,0,3,ma_buffer) <= 0)
   return;

この書き方の利点は次の通りです。

  • 配列方向の見落としを防げる
  • コードレビュー時に意図が明確
  • 他人が見ても誤読しにくい

逆に、どこかで一度だけ設定して省略しようとすると、後からコードを修正したときに Series設定済みかどうか分からなくなることがあります。

6.3 Time[]やClose[]にもArraySetAsSeriesは必要か

通常、不要です。

Time[] Open[] High[] Low[] Close[] などの価格配列は、MQL5で時系列データとして扱う前提があるため、一般に 最新バーが index 0 です。
そのため、通常のEAやインジケータでこれらを参照するだけなら、あらためて ArraySetAsSeries を設定する必要はありません。

ただし注意点があります。

  • 標準の価格配列と
  • 自分で用意した配列

は別物です。

例えば CopyBuffer で取得した配列は、自分で方向を意識して管理しないと混乱しやすくなります。
つまり、標準配列は最初から時系列、独自配列は自分で管理するという整理が重要です。

6.4 ArraySetAsSeriesを使えばバグは防げるのか

完全には防げません。
正しく使えば配列方向のミスはかなり減らせますが、それだけでEA全体の安全性が保証されるわけではありません。

よくある失敗は次の通りです。

  • CopyBuffer の戻り値を確認していない
  • 取得数が足りないのに buffer[1]buffer[2] を参照する
  • Series配列と通常配列を混在させる
  • 現在足と確定足を混同する

特に初心者が見落としやすいのが、現在足(形成中のバー)を使うか、確定足を使うかです。

例えば

buffer[0] = 現在進行中のバー
buffer[1] = 確定済みの1本前

として扱う場面があります。
戦略によっては buffer[0] を使うとシグナルが変動するため、確定足ベースで判定したい場合は buffer[1] を使う設計もあります。

つまり、ArraySetAsSeriesを理解した上で、どのバーを使うかまで設計しないと実運用では足りません。

6.5 初心者はどういうルールで使えばよいか

初心者が最も安全に運用するなら、次のルールに統一するのが実務的です。

  • CopyBuffer 用の配列は動的配列にする
  • 取得前に ArraySetAsSeries(array,true); を書く
  • CopyBuffer の戻り値を必ず確認する
  • 最新値は array[0]、確定足は array[1] と整理する
  • 同じEA内では配列方向のルールを統一する

特に重要なのは、配列方向をEAごとに統一することです。
一部はSeries、一部は通常配列、という状態にすると、後でロジックを追加したときに事故が起きやすくなります。

初心者向けの最小テンプレートは次の形です。

double buffer[];

ArraySetAsSeries(buffer,true);

int copied = CopyBuffer(handle,0,0,3,buffer);
if(copied <= 0)
   return;

double current = buffer[0];
double previous = buffer[1];

この形を繰り返し使えば、ArraySetAsSeriesまわりの初歩的なミスはかなり減らせます。

つまずきやすい点・注意点・よくある失敗

① ArraySetAsSeriesだけ理解して満足してしまう

実際には

  • CopyBuffer
  • 配列サイズ
  • 戻り値確認
  • 現在足と確定足

までセットで理解する必要があります。

② 最新バーと確定バーを混同する

buffer[0] は最新でも、確定済みとは限りません。

③ 配列方向のルールを途中で変える

EAの保守性が大きく下がります。

④ 標準価格配列と自作配列を同じ感覚で扱う

ここを混同すると、ロジックが破綻しやすくなります。

7. ArraySetAsSeriesを安全に使うためのベストプラクティス

ArraySetAsSeriesは単純な関数ですが、EAの売買ロジックの正確性に直結する重要な設定です。
実務では、配列方向のミスが原因で

  • シグナルが逆になる
  • バックテスト結果が異常になる
  • エントリータイミングがずれる

といった問題が発生することがあります。

ここでは、実務のMQL5開発で推奨される 安全な実装ルール(ベストプラクティス)を整理します。

7.1 CopyBufferと必ずセットで使用する

EAでArraySetAsSeriesが必要になる場面のほとんどは、CopyBufferでインジケータ値を取得する場合です。

このときは次の順序を必ず守ります。

ArraySetAsSeries
↓
CopyBuffer
↓
配列参照

コード例

double buffer[];

ArraySetAsSeries(buffer,true);

int copied = CopyBuffer(handle,0,0,3,buffer);

if(copied <= 0)
   return;

double current = buffer[0];
double previous = buffer[1];

この順序を守ることで、配列方向の混乱を防ぐことができます。

7.2 EA内で配列方向のルールを統一する

EAの中で

  • Series配列
  • 通常配列

が混在すると、ロジックの可読性が大きく下がります。

特に複数のインジケータを使うEAでは、次のような混乱が起きやすくなります。

Aインジケータ → index0が最新  
Bインジケータ → index0が古い

この状態では、売買ロジックを追加するたびにミスが起きやすくなります。

そのため、実務では次のルールが推奨されます。

「インジケータ配列はすべてSeries配列にする」

つまり

ArraySetAsSeries(array,true);

を基本ルールにします。

7.3 CopyBufferの戻り値を必ず確認する

CopyBufferは、取得したデータ数を返します。

戻り値 意味
正の数 取得成功
0 取得できない
-1 エラー

戻り値を確認しないと、次のような問題が起きることがあります。

データが存在しない
↓
buffer[0]参照
↓
不正データ

安全な書き方

int copied = CopyBuffer(handle,0,0,3,buffer);

if(copied <= 0)
{
   Print("CopyBuffer failed");
   return;
}

このチェックを入れるだけで、EAの安定性が大きく向上します。

7.4 必要以上のデータを取得しない

CopyBufferでは、取得するデータ数を指定できます。

CopyBuffer(handle,0,0,3,buffer);

EAのロジックでは通常

  • 最新バー
  • 1本前
  • 2本前

程度で十分です。

そのため、実務では

3〜10本

程度の取得が一般的です。

必要以上のデータを取得すると

  • 無駄なメモリ使用
  • パフォーマンス低下

につながる可能性があります。

7.5 最新バーと確定バーを意識する

EAロジックで重要なのが、現在足(未確定バー)と確定バーの違いです。

Series配列では次の構造になります。

buffer[0] = 現在バー(未確定)
buffer[1] = 1本前(確定)
buffer[2] = 2本前

戦略によっては、buffer[0]を使うとシグナルが変動することがあります。

例えば

buffer[0] > buffer[1]

のような条件は、バー確定前に変わる可能性があります。

そのため、次のように設計するケースもあります。

buffer[1] を基準に判定

つまり

double current = buffer[1];
double previous = buffer[2];

とすることで、確定足ベースのロジックになります。

つまずきやすいポイント(実務で多いミス)

① ArraySetAsSeriesを忘れる

EA初心者で最も多いバグです。

結果

古いデータで売買

になります。

② CopyBufferの戻り値を確認していない

データ取得失敗時に

ゴミデータ

を参照する可能性があります。

③ buffer[0]を確定足だと思い込む

buffer[0]形成中のバーです。

④ 配列方向のルールが統一されていない

EAの保守性が大きく低下します。

実務で推奨される最小テンプレート

初心者が最も安全に使えるテンプレートは次の形です。

double buffer[];

ArraySetAsSeries(buffer,true);

int copied = CopyBuffer(handle,0,0,3,buffer);

if(copied <= 0)
   return;

double current = buffer[0];
double previous = buffer[1];

この形をベースにすれば、ArraySetAsSeries関連の初歩的なミスはほぼ防げます。

8. ArraySetAsSeriesのFAQ

Q1. ArraySetAsSeriesとは何をする関数ですか?

ArraySetAsSeries は、MQL5の配列を 時系列データ(Series配列)として扱うための設定を行う関数です。

Series配列では、インデックスの意味が次のようになります。

array[0] = 最新データ
array[1] = 1本前
array[2] = 2本前

これはMetaTraderのチャート構造と同じ並び方です。
そのため、インジケータデータや価格データを扱うEAではよく使用されます。

Q2. ArraySetAsSeriesを使うと配列のデータは並び替えられますか?

いいえ。
配列のデータ自体は並び替えられません。

この関数は

  • データの並び
  • メモリ配置

を変更するのではなく、配列の参照方向(インデックスの解釈)だけを変更します。

そのため、ArraySetAsSeriesを設定すると

array[0]

が最新データとして扱われます。

Q3. CopyBufferを使う場合はArraySetAsSeriesが必要ですか?

多くの場合、使用することが推奨されます。

CopyBufferで取得した配列は、デフォルトでは通常配列になります。

つまり

array[0] = 古いデータ
array[n] = 最新データ

となります。

しかしEAのロジックでは

array[0] = 最新
array[1] = 1本前

として扱う方が自然です。

そのため次のように書くケースが一般的です。

double buffer[];

ArraySetAsSeries(buffer,true);

CopyBuffer(handle,0,0,3,buffer);

Q4. Time[] や Close[] に ArraySetAsSeries は必要ですか?

通常は 不要です。

次の価格配列は、最初から時系列配列として扱われます。

  • Time[]
  • Open[]
  • High[]
  • Low[]
  • Close[]
  • Volume[]

これらは

index 0 = 最新バー

の構造になっています。

Q5. ArraySetAsSeriesはどの配列でも使えますか?

いいえ。
使用できるのは主に1次元の動的配列です。

使用できない例

  • 固定サイズ配列
  • 多次元配列
  • 一部の構造体配列

例(使用不可)

double buffer[100];
ArraySetAsSeries(buffer,true);

この場合はエラーになります。

Q6. ArraySetAsSeriesはどこで呼び出すべきですか?

通常は 配列を使用する直前に呼び出します。

特にCopyBufferと組み合わせる場合は次の順序が安全です。

ArraySetAsSeries
↓
CopyBuffer
↓
配列参照

ArraySetAsSeries(buffer,true);

CopyBuffer(handle,0,0,3,buffer);

Q7. buffer[0]は確定バーですか?

必ずしもそうではありません。

Series配列では

buffer[0] = 現在バー(形成中)
buffer[1] = 1本前(確定バー)

になります。

そのため、戦略によっては

buffer[1]

を使って売買判定することもあります。

Q8. ArraySetAsSeriesを使わないとどうなりますか?

EAのロジックが 古いデータを基準に動作する可能性があります。

例えば次のコード

if(buffer[0] > buffer[1])

古いデータ > さらに古いデータ

という意味になる可能性があります。

その結果

  • 売買タイミングがずれる
  • バックテスト結果が不自然になる

といった問題が発生することがあります。