- ArrayIsSeries関数の働き・役割
- ArrayIsSeries関数の引数について
- ArrayIsSeries関数の戻り値について
- ArrayIsSeries関数を使ったサンプルコードについて
- サンプルコード解説1:グローバル領域部分
- 1. #property indicator_chart_window
- 2. #property indicator_buffers 1
- 3. #property indicator_plots 1
- 4. #property indicator_label1 "Label1"
- 5. #property indicator_type1 DRAW_LINE
- 6. #property indicator_color1 clrRed
- 7. #property indicator_style1 STYLE_SOLID
- 8. #property indicator_width1 1
- 9. double Label1Buffer[];
- サンプルコード解説2:OnInit関数部分
- サンプルコード解説3:OnCalculate関数部分
ArrayIsSeries関数の働き・役割
ArrayIsSeries関数は、配列が時系列のデータとして扱われているかどうかを確認するために使用されます。MQL5では、配列の要素がインデックス(通し番号)によってアクセスされる順序が重要で、時系列データの場合、配列の最新のデータがインデックスの小さい方に、古いデータがインデックスの大きい方に配置されることが一般的です。
ArrayIsSeries関数は、その配列がこの順序に従っているかどうかをチェックするために使用されます。時系列である場合はtrueを返し、時系列でない場合はfalseを返します。
特に、カスタムインジケータの開発において、価格データや時間データが時系列であるかどうかを確認するために、この関数は便利です。時系列に従わないデータに対して誤った処理を防ぐために、正確なデータの順序を確認する手段として利用されます。
ArrayIsSeries関数の引数について
ArrayIsSeries関数の引数は、以下のように定義されています。
bool ArrayIsSeries(
const void& array[] // チェックされた配列
);
- array[]
チェック対象の配列です。MQL5の配列は時系列データとして扱うことができ、ここで渡される配列がその要素の順序に従って、時系列かどうかが判断されます。この配列には、価格データ(open、high、low、closeなど)や時間データ(timeなど)を指定することが一般的です。
この引数は配列であり、関数の内部でその配列が時系列として扱われるかどうかがチェックされます。配列が逆順で配置されている場合(最新のデータが最初のインデックスにあり、古いデータが後のインデックスにある場合)、関数はtrueを返します。
ArrayIsSeries関数の戻り値について
ArrayIsSeries関数は、指定された配列が時系列であるかどうかを確認し、その結果をbool型で返します。
- true
配列が時系列データとして扱われている場合に返されます。すなわち、配列の最新のデータが最初のインデックス(0番目)にあり、古いデータが後のインデックスに順次配置されている状態です。 - false
配列が時系列データとして扱われていない場合に返されます。この場合、配列は通常の順序(古いデータが先頭、最新のデータが後ろ)で配置されている可能性があります。
この戻り値を利用して、配列のデータ順序に応じた処理を行うことができます。例えば、価格データが期待通りの順序でない場合には、データの変換や再取得を行うことで、後続の処理を正しく実行することができます。
ArrayIsSeries関数を使ったサンプルコードについて
#property indicator_chart_window // インジケータをメインチャートウィンドウに表示する設定
#property indicator_buffers 1 // インジケータで使用するバッファ数は1
#property indicator_plots 1 // プロット数(描画するラインなど)は1
//---- Label1 をプロットする設定
#property indicator_label1 "Label1" // プロットにラベル "Label1" を設定
#property indicator_type1 DRAW_LINE // ラインとして描画する
#property indicator_color1 clrRed // ラインの色は赤
#property indicator_style1 STYLE_SOLID // ラインのスタイルは実線
#property indicator_width1 1 // ラインの幅は1ピクセル
//--- インジケータバッファ
double Label1Buffer[]; // インジケータの値を格納するバッファ
//+------------------------------------------------------------------+
//| カスタムインジケータを初期化する関数 |
//+------------------------------------------------------------------+
void OnInit()
{
//--- 指標バッファをマッピングする
// SetIndexBuffer関数は、インジケータの描画に使うバッファを指定します
// 第1引数: インジケータバッファのインデックス(0から始まる)
// 第2引数: マッピングされるバッファ(ここではLabel1Buffer)
// 第3引数: データの種類(INDICATOR_DATAは描画用データを表す)
SetIndexBuffer(0, Label1Buffer, INDICATOR_DATA);
}
//+------------------------------------------------------------------+
//| カスタムインジケータの計算処理を行う関数 |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total, // 全ての利用可能なバーの数
const int prev_calculated, // 前回計算されたバーの数
const datetime &time[], // 時間(datetime型の配列)
const double &open[], // 始値(open価格の配列)
const double &high[], // 高値(high価格の配列)
const double &low[], // 安値(low価格の配列)
const double &close[], // 終値(close価格の配列)
const long &tick_volume[], // ティックボリューム(取引回数の配列)
const long &volume[], // 実際のボリューム(取引量の配列)
const int &spread[]) // スプレッド(売買差額の配列)
{
//--- open配列が時系列順かどうかを確認する
// ArrayIsSeries関数を使用して、配列が時系列順であるかを判定します
// 配列が時系列順の場合はtrueを返し、そうでない場合はfalseを返します
if (ArrayIsSeries(open))
// 配列が時系列順であれば、以下のメッセージをエキスパートログに出力
Print("open[] is timeseries");
else
// 配列が時系列順でない場合は、以下のメッセージをエキスパートログに出力
Print("open[] is not timeseries!!!");
//--- 次回の呼び出しのために全バー数を返す
// rates_totalはバーの総数を返します。これは、次回のOnCalculate呼び出しで
// 前回の計算状況を維持するために使用されます
return (rates_total);
}
サンプルコード解説1:グローバル領域部分
#property indicator_chart_window // インジケータをメインチャートウィンドウに表示する設定
#property indicator_buffers 1 // インジケータで使用するバッファ数は1
#property indicator_plots 1 // プロット数(描画するラインなど)は1
//---- Label1 をプロットする設定
#property indicator_label1 "Label1" // プロットにラベル "Label1" を設定
#property indicator_type1 DRAW_LINE // ラインとして描画する
#property indicator_color1 clrRed // ラインの色は赤
#property indicator_style1 STYLE_SOLID // ラインのスタイルは実線
#property indicator_width1 1 // ラインの幅は1ピクセル
//--- インジケータバッファ
double Label1Buffer[]; // インジケータの値を格納するバッファ
このセクションでは、カスタムインジケータのグローバル領域部分のコードについて解説します。グローバル領域では、インジケータの基本的な設定やバッファの宣言が行われ、これによりインジケータの外観や機能が定義されます。
1. #property indicator_chart_window
このプロパティは、インジケータをメインチャートウィンドウに表示する設定です。これを指定することで、インジケータはローソク足や価格チャートが表示されているメインのウィンドウ内に描画されるようになります。もし、インジケータを別のサブウィンドウ(例:MACDやRSIなどのように別の領域に表示する)に表示したい場合は、indicator_separate_windowを使用します。
2. #property indicator_buffers 1
この行では、インジケータで使用するバッファ数を指定しています。バッファとは、インジケータが計算結果を保持するためのメモリ領域のことで、ここでは1つのバッファ(Label1Buffer[]
)を使用することを示しています。インジケータによっては、複数のラインや色を描画するために複数のバッファが必要になることもありますが、この例では1つだけです。
3. #property indicator_plots 1
プロット数、つまり描画するインジケータのラインの数を指定します。この例では1本のラインのみを描画する設定になっています。プロット数が増えると、複数のラインや異なるデータを同じウィンドウに表示することが可能になります。
4. #property indicator_label1 "Label1"
このプロパティは、描画されるラインに付与されるラベルを指定しています。Label1
という名前がインジケータの名前として表示され、他の複数のプロットがある場合に識別しやすくなります。
5. #property indicator_type1 DRAW_LINE
インジケータの描画形式を指定します。DRAW_LINEはラインとしてインジケータを描画することを意味します。他にも、棒グラフやヒストグラム、矢印など、さまざまな描画タイプを選択することができますが、今回はシンプルなライン描画です。
6. #property indicator_color1 clrRed
このプロパティは、ラインの色を指定しています。ここでは、clrRedが指定されており、赤色でラインが描画されます。色は定義済みのカラー定数(例:clrBlue, clrGreenなど)を使用して簡単に設定できます。
7. #property indicator_style1 STYLE_SOLID
この部分では、ラインのスタイル(見た目)を指定します。STYLE_SOLIDは実線を意味し、破線や点線にしたい場合は、STYLE_DASHやSTYLE_DOTなどを指定することが可能です。
8. #property indicator_width1 1
この部分では、ラインの太さを指定しています。この例では、1ピクセル(ピクセル:デジタル画像を構成する最小単位)の幅で描画されるように設定されています。太さを変えることで、ラインをより目立たせることができます。
9. double Label1Buffer[];
この部分は、インジケータの計算結果を保存するためのバッファ(データを一時的に保存する領域)の宣言です。バッファは、インジケータが計算した値をチャート上に描画するために使用されます。このLabel1Buffer
には、後ほどSetIndexBuffer関数によって計算結果がマッピングされ、インジケータの値が格納されます。
以上が、グローバル領域のコードの詳細な解説です。この部分では、インジケータの基本的な設定やバッファの準備が行われ、描画の方式や表示されるインジケータの見た目を定義しています。
サンプルコード解説2:OnInit関数部分
//+------------------------------------------------------------------+
//| カスタムインジケータを初期化する関数 |
//+------------------------------------------------------------------+
void OnInit()
{
//--- 指標バッファをマッピングする
// SetIndexBuffer関数は、インジケータの描画に使うバッファを指定します
// 第1引数: インジケータバッファのインデックス(0から始まる)
// 第2引数: マッピングされるバッファ(ここではLabel1Buffer)
// 第3引数: データの種類(INDICATOR_DATAは描画用データを表す)
SetIndexBuffer(0, Label1Buffer, INDICATOR_DATA);
}
OnInit関数は、カスタムインジケータが初期化される際に最初に実行される関数です。この関数では、インジケータが計算するデータやバッファの初期設定を行います。以下は、OnInit関数内で行われている操作についての詳細な解説です。
1. OnInit()
OnInit関数は、インジケータが初期化されるタイミングで自動的に呼び出される関数です。MQL5における全てのカスタムインジケータには、この関数が含まれ、初期設定を行います。関数は戻り値を持たず、初期化処理が正常に完了することを目的としています。
2. SetIndexBuffer(0, Label1Buffer, INDICATOR_DATA)
SetIndexBuffer関数は、インジケータの描画や計算結果を保存するバッファを設定するために使用されます。この関数によって、インジケータのデータバッファが、描画や計算に適した形でマッピングされます。
引数の詳細:
- 第1引数: ここでは 0 が指定されていますが、これはインジケータのバッファ番号(インデックス)を意味します。複数のバッファが存在する場合、番号を0から始めて指定します。
- 第2引数: Label1Bufferが指定されています。このバッファは、インジケータが計算する値を保持するためのもので、ここでマッピングされています。つまり、計算結果がこのバッファに保存され、それがチャート上に描画されるようになります。
- 第3引数: INDICATOR_DATAが指定されています。これは、バッファが描画用のデータを保持することを示す定数です。MQL5では、バッファの用途に応じて、INDICATOR_DATAやINDICATOR_CALCULATIONSなどを指定することが可能です。ここでは、インジケータの描画に使用されるデータとしてバッファが設定されていることを意味します。
このOnInit関数では、インジケータのバッファであるLabel1Bufferを設定し、それを描画データとして使用するようにマッピングしています。これにより、インジケータの計算結果が正しくバッファに保存され、チャート上に反映されるようになります。この初期設定は、インジケータの動作において非常に重要な役割を果たします。
サンプルコード解説3:OnCalculate関数部分
//+------------------------------------------------------------------+
//| カスタム指標の計算を行う関数 |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total, // 利用可能なバーの総数
const int prev_calculated, // 前回計算したバー数
const datetime &time[], // 時間データの配列
const double &open[], // 始値の配列
const double &high[], // 高値の配列
const double &low[], // 安値の配列
const double &close[], // 終値の配列
const long &tick_volume[], // ティックボリュームの配列
const long &volume[], // 実際のボリュームの配列
const int &spread[]) // スプレッドの配列
{
//--- InpPricesに基づいて計算対象の価格データを選択し、CandleSizeOnBuffer関数を呼び出す
if(InpPrices)
CandleSizeOnBuffer(rates_total,prev_calculated,open,close,ExtBuffer); // 始値と終値を使用して計算
else
CandleSizeOnBuffer(rates_total,prev_calculated,high,low,ExtBuffer); // 高値と安値を使用して計算
//--- 次回の呼び出しのために、現在の計算バー数を返す
return(rates_total);
}
OnCalculate関数は、インジケータの計算処理を実行する際に呼び出される関数です。この関数は、チャート上で利用可能なすべてのデータ(価格データ、時間データ、取引量など)を使って、インジケータの値を計算し、描画するために使用されます。ここでは、OnCalculate関数の動作を詳しく解説します。
1. OnCalculate関数の引数
OnCalculate関数では、いくつかの引数が渡されます。それぞれの役割は以下の通りです。
- rates_total: チャート上にあるすべての利用可能なバーの数を表します。この値を使って、どの範囲のデータを計算するかを決定します。
- prev_calculated: 前回計算されたバーの数です。これにより、どこから再計算を始めるかがわかり、効率的に計算を進めることができます。
- time[]: datetime型の配列で、それぞれのバーの時間情報が格納されています。
- open[]: 各バーの始値(open価格)の配列です。これを使ってインジケータの計算を行います。
- high[]: 各バーの高値の配列です。
- low[]: 各バーの安値の配列です。
- close[]: 各バーの終値(close価格)の配列です。
- tick_volume[]: 各バーのティックボリューム(取引回数)の配列です。
- volume[]: 各バーの実際の取引量(ボリューム)の配列です。
- spread[]: 各バーのスプレッド(売買差額)の配列です。
2. 配列が時系列順かどうかの確認
関数内で最初に行っている処理は、open配列が時系列順であるかどうかの確認です。
- ArrayIsSeries関数を使用して、openが時系列順(最新のデータがインデックス0にある形式)であるかどうかをチェックしています。時系列であれば true が返され、それ以外の場合は false が返されます。
- 結果に基づいて、Print関数を使用して、エキスパートログに「時系列順かどうか」を表示します。時系列順の場合は「open[] is timeseries」、そうでない場合は「open[] is not timeseries!!!」と表示されます。
3. 計算結果の返却
OnCalculate関数の最後では、rates_totalの値を返しています。この値は、チャート上の全バー数を示しており、次回の呼び出し時に前回どこまで計算が進んでいたかを基に、効率よく計算を再開するために使用されます。
OnCalculate関数では、価格データや時間データを受け取り、インジケータの計算処理を行います。このサンプルでは、open配列が時系列であるかどうかを確認し、その結果をログに出力しています。配列の順序が重要な場合、このようなチェックは正しいデータ処理に欠かせません。