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を設定します。

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])

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

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

その結果

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

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

This website stores cookies on your computer. These cookies are used to provide a more personalized experience and to track your whereabouts around our website in compliance with the European General Data Protection Regulation. If you decide to to opt-out of any future tracking, a cookie will be setup in your browser to remember this choice for one year.

Accept or Deny