- FileReadDatetime関数の働き・役割
- FileReadDatetime関数の引数について
- FileReadDatetime関数の戻り値について
- FileReadDatetime関数を使ったサンプルコード
- サンプルコード解説1:プロパティ命令部分
- indicator_chart_window
- indicator_buffers 2
- indicator_plots 2
- indicator_label1 “UpSignal”
- indicator_type1 DRAW_ARROW
- indicator_color1 clrRed
- indicator_style1 STYLE_SOLID
- indicator_width1 4
- indicator_label2 “DownSignal”
- indicator_type2 DRAW_ARROW
- indicator_color2 clrRed
- indicator_style2 STYLE_SOLID
- indicator_width2 4
- サンプルコード解説2:グローバル領域部分
- サンプルコード解説3:OnInit関数部分その1
- サンプルコード解説4:OnInit関数部分その2
- サンプルコード解説5:OnInit関数部分その3
- サンプルコード解説6:OnCalculate関数部分その1
- サンプルコード解説7:OnCalculate関数部分その2
FileReadDatetime関数の働き・役割
FileReadDatetime関数は、CSV形式のファイルから「YYYY.MM.DD HH:MM」や「YYYY.MM.DD」、または「HH:MM」フォーマットの文字列を読み込み、それをdateTime型の値に変換するための関数です。これにより、ファイルに保存されている日時情報をプログラムで利用できるようになります。
ファイルを操作する際は、まずFileOpen関数でファイルを開き、ファイルハンドルを取得します。このファイルハンドルを引数としてFileReadDatetime関数に渡すことで、ファイルから日付や時間のデータを読み込み、dateTime型の値として扱うことが可能です。
FileReadDatetime関数の引数について
FileReadDatetime関数の引数構成は以下の通りです。
datetime FileReadDatetime(
int file_handle // ファイルハンドル
);
file_handle
- 種類: 整数型 (int)
- 説明: ファイルハンドルは、ファイルを操作するために使用する識別子です。この識別子は、事前にFileOpen関数を使用してファイルを開いた際に取得します。FileOpen関数の戻り値であるファイルハンドルを引数として指定します。
FileReadDatetime関数の戻り値について
FileReadDatetime関数の戻り値は、dateTime型の値です。dateTime型とは、日時を表すために使用されるデータ型で、年、月、日、時、分、秒を含む形式です。
この関数は、指定されたファイルから読み取った日付や時間の情報をdateTime型に変換して返します。たとえば、ファイル内に「2024.09.24 14:30:00」といった文字列が含まれている場合、この文字列はdateTime型の値として返されます。
ファイル内のデータが正しく読み取れない場合や、無効なデータが含まれている場合、エラーが発生し、無効な値が返される可能性があるため、データの整合性を確認することが重要です。
FileReadDatetime関数を使ったサンプルコード
#property indicator_chart_window // チャートウィンドウにインディケータを表示するプロパティ
#property indicator_buffers 2 // 使用するバッファの数を2つに設定
#property indicator_plots 2 // 表示するプロットの数を2つに設定
//---- Label1("UpSignal")をプロットする設定
#property indicator_label1 "UpSignal" // 最初のプロットのラベルを"UpSignal"に設定
#property indicator_type1 DRAW_ARROW // 矢印を使ってプロットを描画
#property indicator_color1 clrRed // プロットの色を赤に設定
#property indicator_style1 STYLE_SOLID // 線のスタイルをソリッド(実線)に設定
#property indicator_width1 4 // 矢印の幅を4に設定
//---- Label2("DownSignal")をプロットする設定
#property indicator_label2 "DownSignal" // 2つ目のプロットのラベルを"DownSignal"に設定
#property indicator_type2 DRAW_ARROW // 矢印を使ってプロットを描画
#property indicator_color2 clrRed // プロットの色を赤に設定
#property indicator_style2 STYLE_SOLID // 線のスタイルをソリッド(実線)に設定
#property indicator_width2 4 // 矢印の幅を4に設定
//--- データ読み込みのパラメータ
input string InpFileName="MACD.csv"; // 読み込むファイル名の入力パラメータ
input string InpDirectoryName="Data"; // ディレクトリ名の入力パラメータ
//--- グローバル変数
int ind=0; // データのインデックス
double upbuff[]; // 上向き矢印を表示するための指標バッファ
double downbuff[]; // 下向き矢印を表示するための指標バッファ
bool sign_buff[]; // シグナル配列(true: 買いシグナル, false: 売りシグナル)
datetime time_buff[]; // シグナルのタイムスタンプを保持する配列
int size=0; // シグナル配列のサイズ
//+------------------------------------------------------------------+
//| カスタム指標の初期化関数 |
//+------------------------------------------------------------------+
int OnInit()
{
//--- ファイルを開く
ResetLastError(); // エラーフラグをリセット
int file_handle=FileOpen(InpDirectoryName+"//"+InpFileName,FILE_READ|FILE_CSV); // ファイルを読み取りモードで開く
if(file_handle!=INVALID_HANDLE)
{
// ファイルが正常に開けた場合
PrintFormat("%s file is open for reading",InpFileName); // 開いたファイルの情報をエキスパートログに出力
//--- シグナル数を読み込む
size=(int)FileReadNumber(file_handle); // ファイルの最初の値をシグナルの数として読み込む
//--- 配列にメモリを割り当てる
ArrayResize(sign_buff,size); // シグナル配列のサイズを調整
ArrayResize(time_buff,size); // タイムスタンプ配列のサイズを調整
//--- ファイルからデータを読み込む
for(int i=0;i<size;i++)
{
//--- シグナルの時間情報を読み込む
time_buff[i]=FileReadDatetime(file_handle); // ファイルから時間データを読み込んで配列に格納
//--- シグナルの値を読み込む
sign_buff[i]=FileReadBool(file_handle); // ファイルからシグナル(true/false)を読み込んで配列に格納
}
//--- ファイルを閉じる
FileClose(file_handle); // ファイルを閉じる
}
else
{
// ファイルが開けなかった場合
PrintFormat("Failed to open %s file, Error code = %d",InpFileName,GetLastError()); // エラー情報をエキスパートログに出力
return(INIT_FAILED); // 初期化失敗を示すコードを返す
}
//--- 配列を指標バッファに結合
SetIndexBuffer(0,upbuff,INDICATOR_DATA); // 上向き矢印のデータを格納するバッファをセット
SetIndexBuffer(1,downbuff,INDICATOR_DATA); // 下向き矢印のデータを格納するバッファをセット
//--- 矢印シンボルを設定
PlotIndexSetInteger(0,PLOT_ARROW,241); // 上向き矢印のシンボルコードを設定(241は矢印のシンボルコード)
PlotIndexSetInteger(1,PLOT_ARROW,242); // 下向き矢印のシンボルコードを設定(242は矢印のシンボルコード)
//--- 空の値として描画されないよう設定
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0); // 上向き矢印のデフォルト値を0(表示されない)に設定
PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0); // 下向き矢印のデフォルト値を0(表示されない)に設定
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[])
{
//--- タイム配列や価格データのインデックスを昇順に並べ替える
ArraySetAsSeries(time,false); // time配列を昇順に設定
ArraySetAsSeries(low,false); // low配列を昇順に設定
ArraySetAsSeries(high,false); // high配列を昇順に設定
//--- 未処理のバーをループ処理
for(int i=prev_calculated;i<rates_total;i++)
{
//--- デフォルト値を設定(描画されない値)
upbuff[i]=0; // 上向き矢印のバッファにデフォルト値0を設定
downbuff[i]=0; // 下向き矢印のバッファにデフォルト値0を設定
//--- シグナルがまだ残っているか確認
if(ind<size)
{
for(int j=ind;j<size;j++)
{
//--- 時間が一致したらファイルの値を使用
if(time[i]==time_buff[j])
{
//--- シグナルに基づいて矢印を描画
if(sign_buff[j]) // シグナルがtrueなら(買いシグナル)
upbuff[i]=high[i]; // 高値位置に上向き矢印を表示
else // シグナルがfalseなら(売りシグナル)
downbuff[i]=low[i]; // 安値位置に下向き矢印を表示
//--- インデックスを増加
ind=j+1; // 次のシグナルへ進める
break;
}
}
}
}
//--- 次回計算のために処理済みのバーの数を返す
return(rates_total);
}
サンプルコード解説1:プロパティ命令部分
#property indicator_chart_window // チャートウィンドウにインディケータを表示するプロパティ
#property indicator_buffers 2 // 使用するバッファの数を2つに設定
#property indicator_plots 2 // 表示するプロットの数を2つに設定
//---- Label1("UpSignal")をプロットする設定
#property indicator_label1 "UpSignal" // 最初のプロットのラベルを"UpSignal"に設定
#property indicator_type1 DRAW_ARROW // 矢印を使ってプロットを描画
#property indicator_color1 clrRed // プロットの色を赤に設定
#property indicator_style1 STYLE_SOLID // 線のスタイルをソリッド(実線)に設定
#property indicator_width1 4 // 矢印の幅を4に設定
//---- Label2("DownSignal")をプロットする設定
#property indicator_label2 "DownSignal" // 2つ目のプロットのラベルを"DownSignal"に設定
#property indicator_type2 DRAW_ARROW // 矢印を使ってプロットを描画
#property indicator_color2 clrRed // プロットの色を赤に設定
#property indicator_style2 STYLE_SOLID // 線のスタイルをソリッド(実線)に設定
#property indicator_width2 4 // 矢印の幅を4に設定
MQL5でカスタムインジケータを作成する際、#property命令を使って様々な設定を行います。これにより、インジケータがどのように描画されるか、どのようなパラメータを持つかを定義できます。ここでは、サンプルコードに含まれるプロパティ命令部分について解説します。
indicator_chart_window
このプロパティは、インジケータがチャートウィンドウに表示されることを示しています。MQL5では、インジケータをチャートウィンドウに直接表示するか、別のウィンドウに表示するかを選ぶことができます。この設定により、インジケータがメインチャートの価格グラフと同じウィンドウ内に描画されるようになります。
indicator_buffers 2
このプロパティは、使用するバッファの数を設定します。バッファは、インジケータの値を格納するためのメモリ領域です。ここでは、2つのバッファが使用されており、それぞれが異なるデータ(上向きのシグナルと下向きのシグナル)を格納します。
indicator_plots 2
このプロパティは、描画されるプロットの数を設定します。プロットは、インジケータの描画要素を指し、ここでは2つのプロットが設定されています。1つ目のプロットは上向きシグナル、2つ目のプロットは下向きシグナルを表示するために使われます。
indicator_label1 “UpSignal”
このプロパティは、最初のプロット(上向きシグナル)に名前を付けています。このラベルはインジケータの凡例などで表示され、ユーザーがインジケータの内容を理解しやすくするために役立ちます。ここでは、”UpSignal”というラベルを指定しており、これは上昇のシグナルを意味します。
indicator_type1 DRAW_ARROW
このプロパティは、最初のプロットの描画形式を指定しています。DRAW_ARROWは、チャート上に矢印を描画することを意味します。ここでは、上向きのシグナルが矢印として表示されます。
indicator_color1 clrRed
このプロパティは、最初のプロットの色を設定しています。clrRedは赤色を表しており、上向きの矢印シグナルが赤色で描画されることを意味します。
indicator_style1 STYLE_SOLID
このプロパティは、描画される矢印のスタイルを設定します。STYLE_SOLIDは実線のスタイルを意味し、矢印が途切れない線で描画されます。
indicator_width1 4
このプロパティは、最初のプロットの線幅を設定しています。値は「4」となっており、これは比較的太い矢印が描画されることを示しています。
indicator_label2 “DownSignal”
2つ目のプロットのラベル設定です。”DownSignal”は、下降シグナルを表すラベルであり、下降トレンドを示すシグナルがこの名前で凡例に表示されます。
indicator_type2 DRAW_ARROW
2つ目のプロットも、最初のプロットと同様に矢印で描画されます。ここでは、下降シグナルが矢印として表示されます。
indicator_color2 clrRed
2つ目のプロットも赤色で描画されます。これにより、下降シグナルが赤い矢印で表示されます。
indicator_style2 STYLE_SOLID
2つ目のプロットも実線のスタイルで描画されます。これは、下降シグナルの矢印が実線で表示されることを意味します。
indicator_width2 4
2つ目のプロットの線幅も「4」と設定されています。これにより、太めの矢印が描画され、視覚的に目立つようになります。
これらのプロパティ命令によって、インジケータがチャートウィンドウにどのように描画されるか、どのようなラベルやスタイルで表示されるかが定義されています。特に、上向きシグナルと下向きシグナルを異なるプロットで表示し、それぞれに矢印を使って描画する設定が行われています。
サンプルコード解説2:グローバル領域部分
//--- データ読み込みのパラメータ
input string InpFileName="MACD.csv"; // 読み込むファイル名の入力パラメータ
input string InpDirectoryName="Data"; // ディレクトリ名の入力パラメータ
//--- グローバル変数
int ind=0; // データのインデックス
double upbuff[]; // 上向き矢印を表示するための指標バッファ
double downbuff[]; // 下向き矢印を表示するための指標バッファ
bool sign_buff[]; // シグナル配列(true: 買いシグナル, false: 売りシグナル)
datetime time_buff[]; // シグナルのタイムスタンプを保持する配列
int size=0; // シグナル配列のサイズ
ここでは、データ読み込みのための入力パラメータやグローバル変数について解説します。この部分では、インジケータが使用するデータファイルやバッファ、シグナルの状態を保持するための変数が定義されています。
データ読み込みのパラメータ
InpFileName=”MACD.csv”
このパラメータは、読み込むファイル名を指定する入力パラメータです。ユーザーはこのパラメータを変更することで、読み込むデータファイルを選択することができます。ここでは、デフォルトで”MACD.csv”というファイルが指定されています。
InpDirectoryName=”Data”
このパラメータは、ファイルが保存されているディレクトリ名を指定します。ユーザーはこの値を変更することで、データファイルが格納されているフォルダを指定することができます。ここでは、”Data”というディレクトリがデフォルトで設定されています。
グローバル変数
ind=0
この変数は、データのインデックスを保持するために使用されます。データファイルを読み込んだ際に、どこまで読み込んだかを記録しておくための変数です。初期値は0に設定されており、インジケータが動作する際に逐次更新されます。
upbuff[]
この配列は、上向き矢印(買いシグナル)を表示するためのバッファです。MQL5では、インジケータの表示データをバッファに格納しておき、描画時に使用します。この配列に上昇シグナルのデータが格納され、チャート上に矢印が表示されます。
downbuff[]
この配列は、下向き矢印(売りシグナル)を表示するためのバッファです。upbuff配列と同様に、インジケータが売りシグナルを描画するためのデータを格納します。下落シグナルがある場合、このバッファを使ってチャートに下向きの矢印を描画します。
sign_buff[]
この配列は、シグナルの状態(買いまたは売り)を保持します。配列には、true
(買いシグナル)またはfalse
(売りシグナル)の値が格納されます。この値に基づいて、チャートに表示する矢印の方向が決定されます。
time_buff[]
この配列は、シグナルが発生した時刻を保持します。シグナルの時系列データを保存し、どの時点で買いや売りのシグナルが発生したかを記録するために使用されます。このデータを元に、指定された時間に対応するシグナルがチャート上に表示されます。
size=0
この変数は、シグナル配列のサイズを保持します。読み込んだデータファイル内のシグナル数を保持し、配列のサイズを動的に調整する際に使用されます。ファイルからデータを読み込んだ後、この変数にシグナルの総数が格納されます。
このセクションでは、インジケータがファイルからデータを読み込み、それを処理するために使用するグローバル変数や入力パラメータについて説明しました。これらの変数は、チャートにシグナルを描画するために必要なデータを保持し、後の処理で重要な役割を果たします。
サンプルコード解説3:OnInit関数部分その1
//+------------------------------------------------------------------+
//| カスタム指標の初期化関数 |
//+------------------------------------------------------------------+
int OnInit()
{
//--- ファイルを開く
ResetLastError(); // エラーフラグをリセット
int file_handle=FileOpen(InpDirectoryName+"//"+InpFileName,FILE_READ|FILE_CSV); // ファイルを読み取りモードで開く
if(file_handle!=INVALID_HANDLE)
{
// ファイルが正常に開けた場合
PrintFormat("%s file is open for reading",InpFileName); // 開いたファイルの情報をエキスパートログに出力
//--- シグナル数を読み込む
size=(int)FileReadNumber(file_handle); // ファイルの最初の値をシグナルの数として読み込む
//--- 配列にメモリを割り当てる
ArrayResize(sign_buff,size); // シグナル配列のサイズを調整
ArrayResize(time_buff,size); // タイムスタンプ配列のサイズを調整
//--- ファイルからデータを読み込む
for(int i=0;i<size;i++)
{
//--- シグナルの時間情報を読み込む
time_buff[i]=FileReadDatetime(file_handle); // ファイルから時間データを読み込んで配列に格納
//--- シグナルの値を読み込む
sign_buff[i]=FileReadBool(file_handle); // ファイルからシグナル(true/false)を読み込んで配列に格納
}
//--- ファイルを閉じる
FileClose(file_handle); // ファイルを閉じる
}
OnInit関数は、MQL5においてカスタムインジケータが初期化される際に最初に実行される関数です。ここでは、ファイルを開いてデータを読み込み、初期化を行う部分について解説します。
ファイルを開く
ResetLastError
この関数は、直前に発生したエラーコードをリセットします。ファイル操作などでエラーが発生した場合、エラーコードが保持されますが、このコードをリセットすることで新しいエラーを検出しやすくします。
file_handle=FileOpen(InpDirectoryName+”//”+InpFileName,FILE_READ|FILE_CSV)
FileOpen関数を使って、指定したファイルを開きます。InpDirectoryNameとInpFileNameを組み合わせたパスにあるファイルを、読み取り専用(FILE_READ)かつCSV形式(FILE_CSV)で開きます。この関数が正常に動作すれば、ファイルハンドルが返されます。ファイルハンドルは、その後のファイル操作(読み込みや閉じる操作)に使用される識別子です。
if(file_handle!=INVALID_HANDLE)
ファイルが正常に開けたかどうかを確認しています。FileOpen関数が失敗するとINVALID_HANDLEが返されるため、ここではそのチェックを行っています。ファイルが正常に開けた場合、次の処理に進みます。
ファイルが正常に開けた場合
PrintFormat(“%s file is open for reading”,InpFileName)
この行では、開いたファイルの名前をエキスパートログに出力します。PrintFormat関数を使うことで、指定したフォーマットに従って文字列を整形し、ファイル名を表示します。これにより、デバッグ時にファイルが正しく開かれたかどうかを確認できます。
シグナル数を読み込む
size=(int)FileReadNumber(file_handle)
ファイルの最初の行から数値を読み込み、その数値をシグナルの数として格納します。読み込まれた数値は、sizeという変数に格納されます。これにより、シグナルのデータがいくつあるかを判別し、後続の処理で使用されます。
配列にメモリを割り当てる
ArrayResize(sign_buff,size)
シグナルデータを格納するための配列sign_buffのサイズを、読み込んだシグナル数に合わせて動的に変更します。この操作により、必要なメモリ領域が確保されます。
ArrayResize(time_buff,size)
sign_buffと同様に、シグナルのタイムスタンプを格納するための配列time_buffのサイズも、シグナル数に合わせて変更します。これにより、各シグナルに対応する時間情報が保存される配列が準備されます。
ファイルからデータを読み込む
for(int i=0;i<size;i++)
このループでは、ファイルからシグナルと時間データを1行ずつ読み込み、それぞれの配列に格納します。
time_buff[i]=FileReadDatetime(file_handle)
FileReadDatetime関数を使用して、ファイルから日時データを読み込みます。これにより、シグナルが発生した時間をtime_buff配列に保存します。
sign_buff[i]=FileReadBool(file_handle)
FileReadBool関数を使用して、シグナルの論理値(true または false)を読み込み、sign_buff配列に保存します。これにより、各シグナルが買い(true)か売り(false)かを示す情報が保存されます。
ファイルを閉じる
FileClose(file_handle)
最後に、使用したファイルを閉じます。これにより、ファイルが他のプロセスや操作で使用可能な状態になり、リソースの無駄遣いを防ぎます。
このOnInit関数の部分では、主にファイルのオープン、シグナルデータの読み込み、配列の初期化といった基本的な初期化処理が行われています。
サンプルコード解説4:OnInit関数部分その2
else
{
// ファイルが開けなかった場合
PrintFormat("Failed to open %s file, Error code = %d",InpFileName,GetLastError()); // エラー情報をエキスパートログに出力
return(INIT_FAILED); // 初期化失敗を示すコードを返す
}
ここでは、OnInit関数のファイルが開けなかった場合の処理について解説します。正常にファイルを開けなかった場合のエラーハンドリングが行われており、トラブル発生時に適切な対応を取るための重要な部分です。
else
if(file_handle != INVALID_HANDLEのチェックに失敗し、ファイルが開けなかった場合に実行される処理です。つまり、ファイルのパスが間違っている、ファイルが存在しない、または何らかの理由でファイルにアクセスできなかった場合、このelseブロックが実行されます。
PrintFormat(“Failed to open %s file, Error code = %d”, InpFileName, GetLastError)
この行では、ファイルが開けなかった場合のエラーメッセージをエキスパートログに出力します。
- PrintFormat関数は、指定したフォーマットでメッセージを整形し、ログに出力します。
- %sは文字列フォーマットを表し、InpFileName(開こうとしたファイル名)がここに挿入されます。
- %dは整数フォーマットを表し、GetLastError関数によって取得されたエラーコードがここに挿入されます。
GetLastError関数は、最後に発生したエラーのコードを返します。このエラーコードを確認することで、開けなかった原因を特定しやすくなります。デバッグやトラブルシューティングにおいて、エキスパートログを確認することで問題の箇所を迅速に特定できます。
return(INIT_FAILED)
ファイルを開けなかった場合、この行で初期化の失敗を示すコードが返されます。INIT_FAILEDは、初期化に失敗したことを示す定数で、これによりMQL5プログラムは正常に動作を停止します。
このセクションでは、ファイルが開けなかった場合のエラーハンドリングを実装する部分について解説しています。特にエラー情報のログ出力と、初期化失敗時の適切な終了処理が重要なポイントです。
サンプルコード解説5:OnInit関数部分その3
//--- 配列を指標バッファに結合
SetIndexBuffer(0,upbuff,INDICATOR_DATA); // 上向き矢印のデータを格納するバッファをセット
SetIndexBuffer(1,downbuff,INDICATOR_DATA); // 下向き矢印のデータを格納するバッファをセット
//--- 矢印シンボルを設定
PlotIndexSetInteger(0,PLOT_ARROW,241); // 上向き矢印のシンボルコードを設定(241は矢印のシンボルコード)
PlotIndexSetInteger(1,PLOT_ARROW,242); // 下向き矢印のシンボルコードを設定(242は矢印のシンボルコード)
//--- 空の値として描画されないよう設定
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0); // 上向き矢印のデフォルト値を0(表示されない)に設定
PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0); // 下向き矢印のデフォルト値を0(表示されない)に設定
return(INIT_SUCCEEDED); // 初期化成功を示すコードを返す
}
OnInit関数の最後の部分では、インジケータがチャート上にどのように描画されるかを設定する処理が行われます。ここでは、指標バッファの設定や矢印シンボルの指定、空の値の設定について解説します。
配列を指標バッファに結合
まず、データを表示するためのバッファをインジケータに結合します。
SetIndexBuffer(0, upbuff, INDICATOR_DATA)
最初に、上向き矢印のデータを保持するためのバッファを設定します。上向きのシグナルは、このバッファに格納された値に基づいて表示されます。このバッファがインジケータの描画データとして使用されます。
SetIndexBuffer(1, downbuff, INDICATOR_DATA)
次に、下向き矢印のデータを保持するためのバッファを設定します。こちらは、下向きのシグナルを描画するためのバッファで、同様にインジケータの描画データとして利用されます。
矢印シンボルを設定
矢印をチャート上に描画するために、そのシンボルを指定します。
PlotIndexSetInteger(0, PLOT_ARROW, 241)
最初のプロットに、上向き矢印を表示するためのシンボルを指定しています。この場合、シンボルコード241を使用して上向きの矢印が描画されます。
PlotIndexSetInteger(1, PLOT_ARROW, 242)
次に、下向き矢印のシンボルを指定します。シンボルコード242を使用して、下向きの矢印が描画されるように設定します。
空の値として描画されないよう設定
インジケータの表示時に、空の値が描画されないようにする設定を行います。
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0)
上向き矢印が描画されるバッファにおいて、値が0の場合は描画しないように設定しています。これにより、不要な描画が防がれます。
PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0)
下向き矢印のバッファにおいても、同様に値が0の場合は描画されないように設定しています。
return(INIT_SUCCEEDED)
最後に、初期化が正常に完了したことを示すために、INIT_SUCCEEDEDを返します。これにより、インジケータが正しく初期化され、描画の準備が整ったことをMQL5プラットフォームに通知します。
この部分では、主にインジケータがどのようにチャート上に描画されるかを制御するための設定が行われています。指標バッファや矢印シンボルの設定により、上向きと下向きのシグナルを矢印で視覚的に表示する準備が整います。
サンプルコード解説6:OnCalculate関数部分その1
//+------------------------------------------------------------------+
//| カスタム指標の計算関数 |
//+------------------------------------------------------------------+
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[])
{
//--- タイム配列や価格データのインデックスを昇順に並べ替える
ArraySetAsSeries(time,false); // time配列を昇順に設定
ArraySetAsSeries(low,false); // low配列を昇順に設定
ArraySetAsSeries(high,false); // high配列を昇順に設定
OnCalculate関数は、カスタムインジケータの計算処理を行う関数であり、指標が新しいデータを受け取るたびに実行されます。ここでは、時間データや価格データの処理がどのように行われるかについて解説します。
引数の説明
この関数は複数の引数を受け取ります。以下がその引数の概要です。
- rates_total: チャートに表示されているバーの総数を表します。これにより、全てのバーに対して処理を行うことができます。
- prev_calculated: 以前に計算されたバーの数を示します。この値を利用して、必要な部分だけを再計算することができます。
- time[]: 各バーの時間情報が格納された配列です。
- open[]: 各バーの始値が格納された配列です。
- high[]: 各バーの高値が格納された配列です。
- low[]: 各バーの安値が格納された配列です。
- close[]: 各バーの終値が格納された配列です。
- tick_volume[]: 各バーのティックボリュームを表します。
- volume[]: 各バーの取引ボリュームを表します。
- spread[]: 各バーのスプレッド情報を持つ配列です。
タイム配列や価格データのインデックスを昇順に並べ替える
ArraySetAsSeries(time, false)
time配列は、各バーの時間情報を格納している配列です。MQL5では、配列を「昇順」または「降順」に設定することができます。ここでは、time配列を「昇順」に設定しています。これは、最新のバーが配列の末尾に配置されるようにするためです。
ArraySetAsSeries(low, false)
low配列には、各バーの安値が格納されています。この配列も「昇順」に設定されており、時間に沿って順次処理を行うための準備をしています。
ArraySetAsSeries(high, false)
high配列には、各バーの高値が格納されています。この配列も同様に「昇順」に設定され、後で処理が行われる際に、新しいバーから順に計算が行われるようになっています。
サンプルコード解説7:OnCalculate関数部分その2
//--- 未処理のバーをループ処理
for(int i=prev_calculated;i<rates_total;i++)
{
//--- デフォルト値を設定(描画されない値)
upbuff[i]=0; // 上向き矢印のバッファにデフォルト値0を設定
downbuff[i]=0; // 下向き矢印のバッファにデフォルト値0を設定
//--- シグナルがまだ残っているか確認
if(ind<size)
{
for(int j=ind;j<size;j++)
{
//--- 時間が一致したらファイルの値を使用
if(time[i]==time_buff[j])
{
//--- シグナルに基づいて矢印を描画
if(sign_buff[j]) // シグナルがtrueなら(買いシグナル)
upbuff[i]=high[i]; // 高値位置に上向き矢印を表示
else // シグナルがfalseなら(売りシグナル)
downbuff[i]=low[i]; // 安値位置に下向き矢印を表示
//--- インデックスを増加
ind=j+1; // 次のシグナルへ進める
break;
}
}
}
}
//--- 次回計算のために処理済みのバーの数を返す
return(rates_total);
}
ここでは、OnCalculate関数の中でバーをループ処理し、シグナルに基づいてチャートに矢印を描画する部分について解説します。OnCalculate関数は、バーごとに繰り返し処理を行い、シグナルが発生したタイミングに応じてチャートに上向きまたは下向きの矢印を表示します。
未処理のバーをループ処理
for(int i=prev_calculated; i<rates_total; i++)
このループでは、未処理のバーを対象にして処理を行います。prev_calculatedは前回までに計算されたバーの数を示し、rates_totalは全バーの数を表します。このため、ループは新しいバー(まだ処理されていないバー)だけを対象にして進行します。
デフォルト値を設定(描画されない値)
upbuff[i]=0
上向き矢印のバッファupbuffには、デフォルト値として0が設定されます。この値が設定されたバーでは、矢印は描画されません。シグナルが発生した場合にのみ、この値が変更され、矢印が描画されるようになります。
downbuff[i]=0
下向き矢印のバッファdownbuffにも同様に、デフォルト値として0が設定されます。このバーにシグナルが発生しなければ、下向き矢印も描画されません。
シグナルがまだ残っているか確認
if(ind<size)
indは現在処理中のシグナルのインデックスを示し、sizeはシグナルの総数です。この条件で、まだ処理していないシグナルが残っているかどうかを確認しています。シグナルが残っていれば、次の処理に進みます。
シグナルと時間が一致した場合
if(time[i]==time_buff[j])
この条件では、現在のバーの時間time[i]が、シグナルの時間time_buff[j]と一致するかを確認しています。もし一致すれば、そのバーに対するシグナルが存在することを示します。
シグナルに基づいて矢印を描画
if(sign_buff[j])
シグナルバッファsign_buff[j]がtrueであれば、買いシグナルを意味します。したがって、この条件が成立した場合、上向き矢印を描画します。
upbuff[i]=high[i]
買いシグナルが発生した場合、上向き矢印を描画するため、upbuff[i]にそのバーの高値high[i]を設定します。これにより、高値位置に上向き矢印が描かれます。
シグナルバッファがfalseの場合は売りシグナルを意味します。この場合、下向き矢印が描かれます。
downbuff[i]=low[i]
売りシグナルが発生した場合、下向き矢印を描画するため、downbuff[i]にそのバーの安値low[i]を設定します。これにより、安値位置に下向き矢印が描かれます。
インデックスを増加
ind=j+1
シグナルが処理された後、シグナルのインデックスindを次に進めます。これにより、次のシグナルが処理される準備が整います。
次回計算のために処理済みのバーの数を返す
return(rates_total)
最後に、この関数が処理したバーの数を返します。これにより、次回以降の計算でどこまで処理されたかがわかるため、不要な再計算を避けることができます。
この部分では、シグナルの時間とバーの時間を照らし合わせて、シグナルに基づいて上向きまたは下向きの矢印を描画する処理が行われています。シグナルが発生した場合のみ、該当するバーに矢印が描画されるため、効率的にチャート表示が行われます。