- ArrayGetAsSeries関数の働き・役割
- ArrayGetAsSeries関数の引数について
- ArrayGetAsSeries関数の戻り値について
- ArrayGetAsSeries関数を使う際の注意点
- ArrayGetAsSeries関数を使ったサンプルコードについて
- サンプルコード解説1:グローバル領域部分
- サンプルコード解説2:CandleSizeOnBuffer関数(オリジナル関数)その1
- サンプルコード解説3:CandleSizeOnBuffer関数(オリジナル関数)その2
- サンプルコード解説4:CandleSizeOnBuffer関数(オリジナル関数)その3
- サンプルコード解説5:OnInit関数部分
- サンプルコード解説6:OnCalculate関数部分
ArrayGetAsSeries関数の働き・役割
ArrayGetAsSeries関数は、指定された配列が時系列として索引付けされているかどうかを確認するために使用されます。時系列の配列は通常の配列とは異なり、インデックスが後ろから前(最新のデータから過去のデータ)へ向かって並べられています。この関数を使用することで、配列が時系列に従ったアクセス方法を持つかどうかを判別することができます。配列が時系列として設定されている場合、戻り値として「true」が返され、そうでない場合は「false」が返されます。
ArrayGetAsSeries関数の引数について
bool ArrayGetAsSeries(
const void& array[] // チェックされる配列
);
ArrayGetAsSeries関数の引数構成は以下の通りです。
引数1: array
- 種類: void型の配列(任意のデータ型の配列)
- 説明: チェックされる配列を指定します。この配列が時系列で索引付けされているかどうかを確認します。配列の内容は、double型、int型、dateTime型など任意の型でかまいませんが、配列自体が正しく初期化されている必要があります。
ArrayGetAsSeries関数は、この引数を使って、配列が通常の順序(先頭から末尾)でアクセスされるか、時系列順(末尾から先頭)でアクセスされるかを確認します。
ArrayGetAsSeries関数の戻り値について
ArrayGetAsSeries関数の戻り値はbool型です。
- 指定された配列が時系列の順序で索引付けされている場合、戻り値としてtrueが返されます。この場合、配列へのアクセスは時系列に従い、最新のデータが先頭(インデックス0)に配置され、過去のデータに向かってインデックスが進みます。
- 一方、配列が通常の順序で索引付けされている場合、戻り値はfalseです。この場合、配列のインデックスは標準的な方法で、最初のデータがインデックス0に位置し、後のデータに向かってインデックスが進みます。
ArrayGetAsSeries関数を使う際の注意点
ArrayGetAsSeries関数を使用する際には、いくつかの点に気をつける必要があります。
まず、ArrayGetAsSeries関数は配列が時系列として索引付けされているかどうかを確認するための関数であり、配列自体の索引付けの設定を変更することはできません。もし、配列の索引付け方向を変更したい場合は、ArraySetAsSeries関数を使用する必要があります。
また、価格データなどの標準的なデータ配列は、通常時系列とは異なるインデックスを持つことが多いです。例えば、OnCalculate関数内で渡される価格データの配列は、時系列に従った索引付けがされていないため、必要に応じてArraySetAsSeries関数で時系列の形式に変更する必要があります。
さらに、配列が時系列の索引付けを持っているかをチェックするだけでなく、ArrayIsSeries関数を使用して、配列の索引付けを設定することなく、配列の現在の状態を取得することもできます。
ArrayGetAsSeries関数を使ったサンプルコードについて
//--- 指標の設定
#property indicator_separate_window // インジケータをメインチャートウィンドウではなく、別のウィンドウに表示する設定
#property indicator_buffers 1 // インジケータで使用するバッファ数は1
#property indicator_plots 1 // プロット数(描画する要素の数)は1
//---- プロットの設定
#property indicator_type1 DRAW_HISTOGRAM // プロットタイプをヒストグラムに設定
#property indicator_style1 STYLE_SOLID // プロットのスタイルを実線に設定
#property indicator_width1 3 // プロットの線幅を3ピクセルに設定
//--- 入力パラメータ
input bool InpAsSeries=true; // 配列の索引付けを時系列方向にするかどうかのフラグ(デフォルトは時系列)
input bool InpPrices=true; // 計算に使う価格を設定するフラグ(trueなら始値/終値、falseなら高値/安値を使用)
//--- 指標バッファ
double ExtBuffer[]; // インジケータの値を保持するバッファ
//+------------------------------------------------------------------+
//| 指標値の計算を行う関数 |
//+------------------------------------------------------------------+
void CandleSizeOnBuffer(const int rates_total, // 利用可能なバーの総数
const int prev_calculated, // 前回計算したバー数
const double &first[], // 比較する最初の価格配列
const double &second[], // 比較する2つ目の価格配列
double &buffer[]) // 結果を格納するバッファ
{
//--- 計算を開始するバーのインデックスを決定する
int start=prev_calculated; // 前回計算したバーのインデックスから計算を再開
//--- 前のティックで計算されている場合、最後のバーから計算を開始するためインデックスを調整
if(prev_calculated>0)
start--;
//--- 各配列が時系列で索引付けされているかを確認する
bool as_series_first = ArrayGetAsSeries(first); // first配列が時系列順かを確認
bool as_series_second = ArrayGetAsSeries(second); // second配列が時系列順かを確認
bool as_series_buffer = ArrayGetAsSeries(buffer); // buffer配列が時系列順かを確認
//--- 必要に応じて配列の索引付けを通常の順序に設定する(時系列順だと反転させる)
if(as_series_first)
ArraySetAsSeries(first,false); // first配列を通常順に設定
if(as_series_second)
ArraySetAsSeries(second,false); // second配列を通常順に設定
if(as_series_buffer)
ArraySetAsSeries(buffer,false); // buffer配列を通常順に設定
//--- 指標値の計算を行い、バッファに結果を格納する
for(int i=start; i<rates_total; i++)
buffer[i]=MathAbs(first[i] - second[i]); // firstとsecondの差の絶対値を計算し、バッファに保存
}
//+------------------------------------------------------------------+
//| カスタム指標の初期化を行う関数 |
//+------------------------------------------------------------------+
int OnInit()
{
//--- 指標バッファの設定
SetIndexBuffer(0,ExtBuffer); // 指標のバッファ(ExtBuffer)をインデックス0にマッピング
//--- バッファの索引付けを時系列順に設定するかどうかを決定
ArraySetAsSeries(ExtBuffer,InpAsSeries); // InpAsSeriesに基づいてバッファの索引付けを設定
//--- 計算に使用する価格データを判定し、プロットのラベルと色を設定
if(InpPrices)
{
//--- 始値と終値を使用する場合の設定
PlotIndexSetString(0,PLOT_LABEL,"BodySize"); // プロットのラベルを"BodySize"に設定
PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrOrange); // プロットの色をオレンジに設定
}
else
{
//--- 高値と安値を使用する場合の設定
PlotIndexSetString(0,PLOT_LABEL,"ShadowSize"); // プロットのラベルを"ShadowSize"に設定
PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrDodgerBlue); // プロットの色を青に設定
}
//--- 初期化成功のステータスを返す
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| カスタム指標の計算を行う関数 |
//+------------------------------------------------------------------+
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);
}
サンプルコード解説1:グローバル領域部分
このセクションでは、カスタムインジケータのグローバル領域部分に含まれている設定やバッファ宣言について解説します。ここで行われている設定により、インジケータの描画方法や表示されるウィンドウ、計算に使用する価格データが定義されます。
1. indicator_separate_window
このプロパティは、インジケータをメインチャートウィンドウではなく、別のウィンドウに表示する設定を行います。通常、オシレーター系のインジケータ(例:RSI、MACD)はこのようにサブウィンドウで表示されます。
2. indicator_buffers 1
ここでは、インジケータが使用するバッファの数を指定しています。バッファはインジケータの計算結果を保存するメモリ領域で、インジケータが複数のラインやプロットを持つ場合は、複数のバッファが必要になります。この例では、1つのバッファが使われています。
3. indicator_plots 1
プロット数を1と指定しています。これは、インジケータが1つの描画要素を持つことを意味します。例えば、ヒストグラムやライン、バーなどのプロットが1つだけ表示されます。
4. indicator_type1 DRAW_HISTOGRAM
このプロパティは、インジケータのプロット形式を定義します。DRAW_HISTOGRAMは、ヒストグラム形式でデータを描画することを指定しています。ヒストグラムは、データの値の高さを棒グラフのように表示する形式です。
5. indicator_style1 STYLE_SOLID
プロットのスタイルを指定しています。STYLE_SOLIDは、実線でプロットを描画することを意味します。他のスタイルとしては、破線や点線なども指定できます。
6. indicator_width1 3
プロットの線幅を3ピクセルに設定しています。このプロパティにより、プロットがどの程度の太さで描画されるかを指定できます。線の太さを変えることで、より視覚的に強調することができます。
7. input bool InpAsSeries=true
これはユーザーがインジケータの使用時に変更できる入力パラメータで、配列の索引付けを時系列順にするかどうかを制御します。trueに設定されていると、配列が時系列(最新のデータが最初にくる)で扱われます。
8. input bool InpPrices=true
もう1つの入力パラメータで、計算に使用する価格データの種類を指定します。trueであれば、始値と終値を使用して計算が行われ、falseであれば高値と安値が使用されます。
9. double ExtBuffer[]
これは、インジケータの計算結果を保持するためのバッファです。計算されたインジケータの値がこのバッファに格納され、チャートに描画されます。バッファはインジケータの動作において重要な役割を果たし、計算結果を一時的に保存します。
以上の設定によって、インジケータの描画形式や入力パラメータ、バッファの初期設定が行われています。このグローバル領域で定義された内容が、後の関数で使用され、インジケータの動作に影響を与えます。
サンプルコード解説2:CandleSizeOnBuffer関数(オリジナル関数)その1
//+------------------------------------------------------------------+
//| 指標値の計算を行う関数 |
//+------------------------------------------------------------------+
void CandleSizeOnBuffer(const int rates_total, // 利用可能なバーの総数
const int prev_calculated, // 前回計算したバー数
const double &first[], // 比較する最初の価格配列
const double &second[], // 比較する2つ目の価格配列
double &buffer[]) // 結果を格納するバッファ
このセクションでは、CandleSizeOnBuffer関数について解説します。この関数は、カスタムインジケータの計算処理を担当しており、指定された価格データを基に、バー(ローソク足)の大きさを計算し、結果を指定されたバッファに格納します。以下は、関数内で行われている主要な処理についての詳細な説明です。
1. rates_total(利用可能なバーの総数)
この引数は、チャート上のすべてのバー(ローソク足)の数を表します。この値を使用して、どの範囲のデータを処理するかを決定します。rates_totalが多ければ多いほど、より長い期間のデータが処理されることになります。
2. prev_calculated(前回計算したバー数)
この引数は、前回の計算で処理したバーの数を示します。これにより、すでに計算が終わっているデータを再計算する必要がなく、計算の効率化が図られます。例えば、新しいティックデータが到着した場合、前回までに計算されていたバーを再度計算するのではなく、新しいバーだけを計算することが可能です。
3. first[](比較する最初の価格配列)
この配列には、計算のために使用する最初の価格データが格納されています。InpPricesフラグによって、openやhighなどの異なる価格データが渡される可能性があります。ローソク足の始値や高値を指定することで、どの価格情報を基に計算を行うかが決定されます。
4. second[](比較する2つ目の価格配列)
この配列には、first[]と比較する2つ目の価格データが格納されています。例えば、closeやlowなどの終値や安値が渡され、ローソク足の大きさを計算する際の基準として使われます。
5. buffer[](結果を格納するバッファ)
計算された結果を格納するためのバッファです。最終的にこのバッファに保存されたデータが、チャート上でインジケータとして描画されます。buffer[]は、CandleSizeOnBuffer関数で計算されたローソク足のサイズ(例えば、始値と終値の差や高値と安値の差など)が格納される場所です。
このCandleSizeOnBuffer関数は、ローソク足のサイズ(バーのサイズ)を計算するために重要な役割を果たします。価格データの違いに基づいて動的に処理を行い、その結果をバッファに格納することで、視覚的にインジケータとして表示されることになります。
サンプルコード解説3:CandleSizeOnBuffer関数(オリジナル関数)その2
{
//--- 計算を開始するバーのインデックスを決定する
int start=prev_calculated; // 前回計算したバーのインデックスから計算を再開
//--- 前のティックで計算されている場合、最後のバーから計算を開始するためインデックスを調整
if(prev_calculated>0)
start--;
//--- 各配列が時系列で索引付けされているかを確認する
bool as_series_first = ArrayGetAsSeries(first); // first配列が時系列順かを確認
bool as_series_second = ArrayGetAsSeries(second); // second配列が時系列順かを確認
bool as_series_buffer = ArrayGetAsSeries(buffer); // buffer配列が時系列順かを確認
このセクションでは、CandleSizeOnBuffer関数のコードの一部について解説します。この部分のコードでは、前回の計算結果を基にどこから計算を再開するか、そして、配列の索引付けが時系列順であるかどうかを確認し、必要に応じて配列の索引付けの方向を変更する処理が行われています。
1. 計算を開始するバーのインデックスを決定する
まず、start変数にprev_calculatedの値が代入されます。prev_calculatedは前回計算されたバーの数を示しており、これにより、すでに計算が行われたバーを再度計算することを防ぎます。これにより、計算の効率化が図られます。
ただし、前回の計算が少なくとも1回以上行われている場合は、start変数が1つ前のバーに設定されます。これは、最後のバーでの計算結果が最新のティックに基づくものであり、更新が必要になる場合があるためです。
2. 配列の索引付けの方向を確認する
次に、ArrayGetAsSeries関数を使って配列が時系列順に索引付けされているかどうかを確認します。MQL5では、時系列順に設定された配列は最新のデータがインデックス0にあり、過去のデータがインデックスが増加する方向に配置されています。
- as_series_firstは、first配列(始値や高値など)が時系列順であるかどうかをArrayGetAsSeries関数を用いて確認します。
- as_series_secondは、second配列(終値や安値など)が時系列順であるかどうかをArrayGetAsSeries関数を用いて確認します。
- as_series_bufferは、結果を格納するbuffer配列が時系列順であるかどうかをArrayGetAsSeries関数を用いて確認します。
このように、ArrayGetAsSeries関数を用いることで、各配列の索引付けが正しいかどうかを動的にチェックし、必要に応じて後の処理で順序を調整することができます。
3. 配列の索引付けを変更する必要がある場合
この時系列順の確認が行われた後、もし配列が時系列で索引付けされている場合、後続のコードで配列を通常の順序に戻すことができます。これにより、インデックスが0から始まって順次増加していく通常の配列として扱われるようになります。
この処理は、配列のインデックス付けが重要な場合、特に価格データやインジケータの計算において、正確なデータアクセスが求められる際に重要です。
この部分のコードは、インジケータの計算において非常に重要なステップを処理しています。前回の計算結果を基に再計算を効率的に行い、さらに配列が時系列で正しく索引付けされているかを確認することで、データの整合性を保ちながら計算を行うことができます。
サンプルコード解説4:CandleSizeOnBuffer関数(オリジナル関数)その3
//--- 必要に応じて配列の索引付けを通常の順序に設定する(時系列順だと反転させる)
if(as_series_first)
ArraySetAsSeries(first,false); // first配列を通常順に設定
if(as_series_second)
ArraySetAsSeries(second,false); // second配列を通常順に設定
if(as_series_buffer)
ArraySetAsSeries(buffer,false); // buffer配列を通常順に設定
//--- 指標値の計算を行い、バッファに結果を格納する
for(int i=start; i<rates_total; i++)
buffer[i]=MathAbs(first[i] - second[i]); // firstとsecondの差の絶対値を計算し、バッファに保存
}
このセクションでは、CandleSizeOnBuffer関数の最後の部分について解説します。ここでは、配列が時系列で索引付けされている場合に通常の順序に戻す処理を行い、その後、実際のインジケータ値の計算を行って結果をバッファに格納します。
1. 必要に応じた索引付けの変更
ArraySetAsSeries関数を使用して、配列が時系列順であれば通常の順序に変更します。MQL5では、時系列順の配列は最新のデータがインデックス0に配置されていますが、多くの計算では通常の順序(インデックスが小さいほど過去のデータ)での処理が望ましいです。
- as_series_firstが
true
の場合、first配列を通常順に設定します。 - as_series_secondが
true
の場合、second配列を通常順に設定します。 - as_series_bufferが
true
の場合、buffer配列も通常順に設定します。
この処理により、インジケータの計算が通常の順序で正しく行えるようにします。
2. 指標値の計算と結果の格納
各配列の索引付けが適切に設定された後、forループを用いて実際のインジケータ値の計算を行います。first配列とsecond配列の値の差の絶対値を計算し、その結果をbufferに格納します。
- MathAbs関数を使用して、firstとsecondの差の絶対値を計算します。これは、2つの価格データの間の変動幅を表しており、たとえば、ローソク足の始値と終値の差や高値と安値の差を示します。
- 計算結果はbufferに格納され、後にインジケータとしてチャートに描画されます。
この部分の処理では、配列の順序を正しく整えた後、価格データの差を計算してインジケータ値として出力しています。このように、データが正しい順序で処理されることが、正確なインジケータ計算において非常に重要です。
サンプルコード解説5:OnInit関数部分
このセクションでは、カスタムインジケータのOnInit関数について解説します。この関数は、インジケータの初期化時に呼び出され、バッファの設定や、使用する価格データに基づくプロットのラベルや色の設定を行います。初期化が成功すると、インジケータが正常に動作するための環境が整います。
1. 指標バッファの設定
SetIndexBuffer関数は、インジケータのデータを格納するためのバッファを指定します。ここでは、ExtBufferというバッファをインジケータのインデックス0にマッピングしています。これにより、計算された値がこのバッファに格納され、チャート上に描画されます。
2. バッファの索引付けを時系列順に設定
ArraySetAsSeries関数を使用して、ExtBufferの索引付けの方向を設定しています。InpAsSeriesという入力パラメータに基づいて、バッファが時系列順(最新のデータがインデックス0に配置される)に設定されるか、通常順(過去のデータがインデックス0に配置される)に設定されるかが決定されます。
- InpAsSeries = true: バッファが時系列順に設定されます。
- InpAsSeries = false: 通常の順序で設定されます。
3. 使用する価格データに基づくプロット設定
InpPricesフラグに基づいて、どの価格データを使ってインジケータの値を計算するかが決定されます。また、その際にプロットのラベルと色も設定します。
PlotIndexSetInteger関数を使ってプロットの色を青(clrDodgerBlue)に設定しています。されます。
InpPrices = trueの場合: 始値と終値を使用して、ローソク足の実体部分(ボディサイズ)を計算します。
PlotIndexSetString関数を使ってプロットのラベルを「BodySize」に設定しています。1つ目の引数はプロットのインデックス(ここでは0)、2つ目の引数は識別子(PLOT_LABEL)、3つ目の引数はラベル名です。
PlotIndexSetInteger関数を使ってプロットの色をオレンジに設定します。1つ目の引数はプロットのインデックス、2つ目の引数はプロットの色を指定する識別子(PLOT_LINE_COLOR)、3つ目の引数は設定する色(clrOrange)です。
InpPrices = falseの場合: 高値と安値を使用して、ローソク足のひげ部分(シャドウサイズ)を計算します。
PlotIndexSetString関数を使ってプロットのラベルを「ShadowSize」に設定しています。ラベルの設定方法は上記と同様です。
4. 初期化のステータスを返す
関数の最後では、初期化が成功したことを示すINIT_SUCCEEDEDを返しています。これにより、インジケータが正常に初期化されたことを示し、次の計算処理へと進むことができます。
このOnInit関数では、バッファの設定やプロットの外観を決定し、インジケータの初期化を正しく行うための一連の処理を担当しています。この初期設定が正常に行われることで、インジケータが適切に動作することが保証されます。
サンプルコード解説6: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関数について解説します。この関数は、インジケータの計算処理を行う際に呼び出され、与えられた価格データを基に、指定されたバッファに計算結果を格納する役割を持っています。
1. 引数の説明
- rates_total: チャート上の利用可能なバー(ローソク足)の総数を表します。この値を基に、どれだけのデータを処理するかを決定します。
- prev_calculated: 前回の計算で処理されたバーの数を示します。この値に基づいて、すでに計算されたバーを再計算せず、新たなデータのみを処理することで計算の効率化が図られます。
- time[], open[], high[], low[], close[]: これらの配列には、それぞれ時間データ、始値、高値、安値、終値のデータが格納されています。これらのデータは、インジケータの計算の基礎となります。
- tick_volume[], volume[], spread[]: ティックボリューム(取引回数)、実際の取引量、スプレッド(買値と売値の差)などの追加情報が格納されている配列です。
2. CandleSizeOnBuffer関数の呼び出し
この部分では、InpPrices
という入力パラメータに基づいて、どの価格データを使用して計算するかが決定されます。次に、CandleSizeOnBuffer関数を呼び出して、指定された価格データを基にインジケータの計算を行い、結果をバッファ(ExtBuffer)に格納します。
- InpPrices = trueの場合: 始値と終値の差を使って、ローソク足の実体部分(ボディサイズ)を計算します。
open[]
とclose[]
配列が渡され、これらの値を基に計算されます。 - InpPrices = falseの場合: 高値と安値の差を使って、ローソク足のひげ部分(シャドウサイズ)を計算します。
high[]
とlow[]
配列が渡され、これらの値を基に計算されます。
3. 計算結果の返却
計算が完了すると、rates_total(利用可能なバーの総数)を返します。この戻り値を使って、次回の計算時にどのバーから計算を再開するかが決定されます。これにより、効率的な再計算が行われます。
このOnCalculate関数は、チャート上の価格データに基づいてインジケータを計算し、その結果をバッファに格納する重要な役割を果たしています。指定された価格データを使って、ローソク足の実体やひげのサイズを動的に計算し、チャート上に描画することで、トレーダーに視覚的な分析情報を提供します。