FileReadDouble関数の働き・役割
FileReadDouble関数は、バイナリファイルから倍精度浮動小数点数(double型のデータ)を読み込むために使用されます。この関数は、FileOpen関数で開かれたファイルハンドルを用いて、ファイルの現在位置から順番にdouble型のデータを1つ読み出し、次に読み込む位置を自動的に更新します。
ファイル操作において、データを効率的に読み出すために用いられる基本的な関数の1つであり、主に数値データを含むバイナリファイルを処理する際に使用されます。例えば、トレード履歴やテクニカルインジケータの結果などを保存していたバイナリファイルから、再びそのデータを読み出して利用する場合に役立ちます。
FileReadDouble関数の引数について
double FileReadDouble(int file_handle);
FileReadDouble関数は、1つの引数を取ります。以下はその引数の詳細です。
file_handle
- 説明: FileOpen関数で開かれたファイルのハンドルを指定します。このハンドルは、ファイルの読み書き操作を行う際に必要です。ファイルが正常に開かれていない場合、このハンドルはINVALID_HANDLEとなります。
この引数は、FileOpen関数から取得したファイルハンドルを使ってファイルを操作するための識別子であり、バイナリファイル内のデータを順次読み込む際に使用されます。
FileReadDouble関数の戻り値について
FileReadDouble関数は、バイナリファイルから読み取った倍精度浮動小数点数(double型のデータ)を戻り値として返します。この値は、ファイル内の現在の読み取り位置から取得され、次に読み込む位置が自動的に更新されます。
もし何らかの理由で読み取りが失敗した場合、戻り値として0が返されることがあります。このような場合には、GetLastError関数を使用してエラーの詳細を確認する必要があります。
FileReadDouble関数を使ったサンプルコード
#property indicator_chart_window // 指標をチャートウィンドウに表示
#property indicator_buffers 1 // 指標バッファの数を1に設定
#property indicator_plots 1 // プロットの数を1に設定
//---- Label1 をプロットする
#property indicator_label1 "MA" // プロット1のラベルを "MA" に設定
#property indicator_type1 DRAW_LINE // プロットの描画タイプをラインに設定
#property indicator_color1 clrGreen // プロットの色を緑色に設定
#property indicator_style1 STYLE_SOLID // プロットのスタイルを実線に設定
#property indicator_width1 2 // プロットの線の幅を2ピクセルに設定
#property indicator_separate_window // 別ウィンドウに表示するように設定
//--- データ読みのパラメータ
input string InpFileName="MA.csv"; // 読み込むファイル名を指定(デフォルトは"MA.csv")
input string InpDirectoryName="Data"; // 読み込むファイルが保存されているディレクトリ名を指定
//--- グローバル変数
int ind=0; // ファイルからの読み込み開始位置を管理する変数
int size=0; // ファイル内のデータサイズを格納する変数
double ma_buff[]; // 読み込んだ移動平均データを保存する配列
datetime time_buff[]; // 読み込んだ時刻データを保存する配列
//--- 指標バッファ
double buff[]; // チャートに表示するための指標データを格納する配列
//+------------------------------------------------------------------+
//| カスタム指標を初期化する関数 |
//+------------------------------------------------------------------+
int OnInit()
{
//--- ファイルを開く
ResetLastError(); // 直前のエラーコードをリセット
int file_handle=FileOpen(InpDirectoryName+"//"+InpFileName,FILE_READ|FILE_BIN); // 指定されたファイルをバイナリ読み取りモードで開く
if(file_handle!=INVALID_HANDLE) // ファイルが正常に開けたかどうか確認
{
// ファイルが正常に読み取れることをメッセージで通知
PrintFormat("%s file is available for reading",InpFileName);
// ファイルパスを表示
PrintFormat("File path: %s\\Files\\",TerminalInfoString(TERMINAL_DATA_PATH));
//--- 初めに、ファイルのデータ量を読み込む
size=(int)FileReadDouble(file_handle); // ファイルの最初のデータからデータの数を取得
//--- 配列へメモリを割り当てる
ArrayResize(ma_buff,size); // 読み込んだ移動平均データ用の配列をサイズに合わせて調整
ArrayResize(time_buff,size); // 読み込んだ時刻データ用の配列をサイズに合わせて調整
//--- ファイルからデータを読む
for(int i=0;i<size;i++)
{
time_buff[i]=(datetime)FileReadDouble(file_handle); // ファイルから時刻データを読み込み、time_buffに格納
ma_buff[i]=FileReadDouble(file_handle); // ファイルから移動平均データを読み込み、ma_buffに格納
}
//--- ファイルを閉じる
FileClose(file_handle); // ファイルの読み取りが完了したので閉じる
PrintFormat("Data is written, %s file is closed",InpFileName); // ファイルが閉じたことを通知
}
else
{
// ファイルが開けなかった場合、エラーメッセージを出力
PrintFormat("Failed to open %s file, Error code = %d",InpFileName,GetLastError());
return(INIT_FAILED); // ファイルが開けなかった場合は初期化に失敗したことを返す
}
//--- 配列をインデックス0で指標バッファと結合する
SetIndexBuffer(0,buff,INDICATOR_DATA); // buff配列をチャート表示用の指標データバッファに設定
//---- チャートでは表示されない指標値を設定する
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,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); // チャートの時刻データを通常の配列順に設定
//--- まだ処理されてないバーのループ
for(int i=prev_calculated;i<rates_total;i++) // 前回処理されたバー以降からデータを処理
{
//--- デフォルトでは 0
buff[i]=0; // デフォルトでは表示する値を0に初期化
//--- データがまだあるかをチェック
if(ind<size) // 読み込んだデータがまだ残っているか確認
{
for(int j=ind;j<size;j++) // 読み込んだデータを順番に確認
{
//--- 日付が同じならファイルの値を使用する
if(time[i]==time_buff[j]) // チャート上の時刻とファイルから読み取った時刻が一致した場合
{
buff[i]=ma_buff[j]; // ファイルの移動平均データを指標バッファに格納
ind=j+1; // 読み取ったデータの位置を1つ進める
break; // ループを抜ける
}
}
}
}
//--- 次の呼び出しのために prev_calculated の値を返す
return(rates_total); // 処理された全データ数を返す
}
サンプルコード解説1:プロパティ命令部分
#property indicator_chart_window // 指標をチャートウィンドウに表示
#property indicator_buffers 1 // 指標バッファの数を1に設定
#property indicator_plots 1 // プロットの数を1に設定
//---- Label1 をプロットする
#property indicator_label1 "MA" // プロット1のラベルを "MA" に設定
#property indicator_type1 DRAW_LINE // プロットの描画タイプをラインに設定
#property indicator_color1 clrGreen // プロットの色を緑色に設定
#property indicator_style1 STYLE_SOLID // プロットのスタイルを実線に設定
#property indicator_width1 2 // プロットの線の幅を2ピクセルに設定
#property indicator_separate_window // 別ウィンドウに表示するように設定
プロパティ命令は、カスタムインジケータの動作や外観を定義するために使用されます。この部分では、インジケータがチャートウィンドウにどのように表示されるかを設定しています。
indicator_chart_window
この命令は、インジケータをメインチャートウィンドウに表示することを示します。例えば、価格チャートと同じウィンドウに移動平均線を表示する場合に使用されます。
indicator_buffers 1
インジケータバッファは、チャートに表示される値を格納するためのメモリ領域です。この設定では、バッファの数を1つに制限しています。つまり、1つのインジケータ(この場合は移動平均線)のみが表示されることになります。
indicator_plots 1
プロットは、インジケータの線やグラフが実際に表示されるものです。この命令では、1つのプロットが表示されることを示しています。
indicator_label1 “MA”
インジケータのラベルを設定する命令です。ここでは、移動平均線を示す「MA」というラベルがプロットに付けられます。このラベルは、チャートの凡例やプロパティウィンドウで表示され、どのプロットがどのインジケータに対応しているかを示します。
indicator_type1 DRAW_LINE
描画タイプを指定する命令です。DRAW_LINEは、インジケータを線で描画する設定で、移動平均線などの連続したデータを視覚的に表現するのに適しています。
indicator_color1 clrGreen
インジケータの表示色を設定する命令です。ここでは、移動平均線の色を緑色に指定しています。これはチャート上でインジケータが視覚的に識別しやすくするための設定です。
indicator_style1 STYLE_SOLID
線のスタイルを設定する命令です。STYLE_SOLIDは、線を実線で描画することを指定しています。他の選択肢としては、点線や破線なども設定可能です。
indicator_width1 2
描画される線の太さを2ピクセルの幅に設定しています。
indicator_separate_window
この命令は、インジケータをメインチャートウィンドウではなく、別ウィンドウに表示する設定です。
このプロパティ設定によって、インジケータの外観や動作が定義され、チャート上でどのように表示されるかが決まります。特に、視覚的なスタイルや描画方法の設定が重要です。
サンプルコード解説2:グローバル領域部分
//--- データ読みのパラメータ
input string InpFileName="MA.csv"; // 読み込むファイル名を指定(デフォルトは"MA.csv")
input string InpDirectoryName="Data"; // 読み込むファイルが保存されているディレクトリ名を指定
//--- グローバル変数
int ind=0; // ファイルからの読み込み開始位置を管理する変数
int size=0; // ファイル内のデータサイズを格納する変数
double ma_buff[]; // 読み込んだ移動平均データを保存する配列
datetime time_buff[]; // 読み込んだ時刻データを保存する配列
//--- 指標バッファ
double buff[]; // チャートに表示するための指標データを格納する配列
このセクションでは、カスタムインジケータのグローバル変数や設定値が定義されています。ここでは、ファイルからデータを読み込むためのパラメータや、読み込んだデータを保存するための変数が定義されています。
InpFileName
この変数は、読み込むファイルの名前を指定するための入力パラメータです。デフォルトでは「MA.csv」というファイル名が指定されていますが、ユーザーが任意のファイル名を設定することも可能です。ここで指定されたファイル名を基に、プログラムがファイルを開いてデータを読み込みます。
InpDirectoryName
こちらも入力パラメータで、ファイルが保存されているディレクトリ名を指定します。デフォルトでは「Data」というディレクトリ名が指定されています。このパラメータと先述のファイル名を組み合わせて、プログラムがデータを読み込むファイルの場所を特定します。
ind
この変数は、ファイルから読み込みを開始する位置を管理するためのグローバル変数です。初期値は0で設定されており、データを順次読み込んでいく際にこの変数の値が更新されます。ファイル内のどこから読み込みを再開するかを管理する重要な役割を担っています。
size
ファイル内に保存されているデータの総量を格納するための変数です。ファイルを開いた際に、この変数にデータのサイズが格納され、プログラムはこのサイズに基づいてメモリを割り当てたり、データを読み込んだりします。
ma_buff
この配列は、ファイルから読み込んだ移動平均(Moving Average)のデータを保存するために使用されます。ファイルから複数の移動平均値を読み込み、それを配列に格納して、後でチャートに表示できるようにします。配列は動的にサイズを変更できるように、ファイルのデータ量に応じてサイズが設定されます。
time_buff
こちらも配列で、ファイルから読み込んだ各データの時刻情報を保存します。移動平均データと対応する時刻データがセットで保存され、チャート上で正しいタイミングに移動平均線を描画するために使用されます。
buff
この配列は、実際にチャートに表示されるインジケータデータを格納するためのバッファです。移動平均データや他の計算結果がこの配列に格納され、最終的にチャート上に描画されます。指標バッファと呼ばれるこの領域は、SetIndexBuffer関数を使用してチャートと関連付けられます。
これらのグローバル変数やパラメータによって、ファイルからデータを読み込み、それをチャートに反映させるための準備が行われます。
サンプルコード解説3:OnInit関数部分その1
//+------------------------------------------------------------------+
//| カスタム指標を初期化する関数 |
//+------------------------------------------------------------------+
int OnInit()
{
//--- ファイルを開く
ResetLastError(); // 直前のエラーコードをリセット
int file_handle=FileOpen(InpDirectoryName+"//"+InpFileName,FILE_READ|FILE_BIN);
// 指定されたファイルをバイナリ読み取りモードで開く
OnInit関数は、カスタムインジケータが初期化される際に自動的に呼び出されます。この関数の役割は、インジケータが動作するための初期設定を行い、必要なファイルを開いたり、バッファや変数の初期化を行うことです。ここでは、OnInit関数の冒頭部分について詳しく解説します。
OnInit関数の開始
この部分では、OnInit関数が定義されます。戻り値の型は整数で、関数の実行が成功したかどうかを示す値を返します。成功した場合には、INIT_SUCCEEDEDが返され、失敗した場合には、INIT_FAILEDが返されます。
ResetLastError
この命令は、前回の操作で発生したエラーコードをリセットするために使用されます。これにより、前回のエラー情報が残らず、次の操作がエラーのない状態で開始されることを保証します。
FileOpen
次に、ファイルを開くための命令が続きます。FileOpen関数は、指定されたファイルを開き、そのファイルに対して読み書きを行うためのハンドル(識別子)を返します。ここでは、InpDirectoryNameで指定されたディレクトリ内のInpFileNameという名前のファイルを、バイナリ読み取りモードで開いています。
ファイルが正常に開かれると、FileOpen関数はファイルハンドルを返します。これにより、プログラムはそのハンドルを使用してファイルにアクセスし、データを読み取ることができます。
サンプルコード解説4:OnInit関数部分その2
if(file_handle!=INVALID_HANDLE) // ファイルが正常に開けたかどうか確認
{
// ファイルが正常に読み取れることをメッセージで通知
PrintFormat("%s file is available for reading",InpFileName);
// ファイルパスを表示
PrintFormat("File path: %s\\Files\\",TerminalInfoString(TERMINAL_DATA_PATH));
//--- 初めに、ファイルのデータ量を読み込む
size=(int)FileReadDouble(file_handle); // ファイルの最初のデータからデータの数を取得
//--- 配列へメモリを割り当てる
ArrayResize(ma_buff,size); // 読み込んだ移動平均データ用の配列をサイズに合わせて調整
ArrayResize(time_buff,size); // 読み込んだ時刻データ用の配列をサイズに合わせて調整
このセクションでは、ファイルが正常に開けた場合の処理について説明します。
file_handle != INVALID_HANDLE
この条件文では、ファイルハンドルが無効でないことを確認しています。FileOpen関数が正常にファイルを開けなかった場合、INVALID_HANDLEという値が返されますが、正常にファイルを開けた場合には有効なハンドルが返されます。この条件が満たされた場合、次のステップでファイルのデータを読み込みます。
PrintFormat
ファイルが正常に開けたことを確認した後、PrintFormat関数を使用して、指定されたファイルが読み込み可能であることをエキスパートログに出力します。この出力には、読み込むファイル名が含まれており、プログラムがどのファイルを処理しているかを確認できます。
ファイルパスの表示
PrintFormat関数を用いて、ファイルのパス情報を表示します。TerminalInfoString関数を使って、ターミナルのデータパスを取得し、そのパスにあるFilesフォルダ内のファイルが対象であることを示します。
ファイルデータの読み込み
次に、FileReadDouble関数を使って、ファイルの最初のデータを読み込みます。ここでは、最初に読み込まれたデータがデータの数を示す値であり、size変数にその数が格納されます。このsize値を基に、後でデータを配列に格納する際のメモリを確保します。
ArrayResize
データの数(size)が確定した後、それに基づいて2つの配列のサイズを調整します。まず、移動平均データを格納するためのma_buff配列、次に時刻データを格納するtime_buff配列のメモリを確保し、それぞれのサイズをsizeに設定します。この処理により、ファイルから読み込んだデータを正確に配列に格納できるようになります。
この部分では、ファイルが正常に開けた後の初期処理が行われており、特にデータの読み込みやメモリの確保に関する重要なステップが含まれています。
サンプルコード解説5:OnInit関数部分その3
//--- ファイルからデータを読む
for(int i=0;i<size;i++)
{
time_buff[i]=(datetime)FileReadDouble(file_handle); // ファイルから時刻データを読み込み、time_buffに格納
ma_buff[i]=FileReadDouble(file_handle); // ファイルから移動平均データを読み込み、ma_buffに格納
}
//--- ファイルを閉じる
FileClose(file_handle); // ファイルの読み取りが完了したので閉じる
PrintFormat("Data is written, %s file is closed",InpFileName); // ファイルが閉じたことを通知
}
このセクションでは、ファイルからデータを読み込み、それを配列に格納する処理、そしてファイルを閉じる部分について解説します。
データ読み込みのループ処理
ここでは、forループを使って、ファイルからデータを順次読み込んでいます。ループは、データのサイズ(size変数)に従って、0からsize-1まで繰り返されます。各ループの中で、時刻データと移動平均データがファイルから読み込まれ、それぞれ対応する配列に格納されます。
time_buff配列への時刻データの読み込み
ループ内で、FileReadDouble関数を使用して、まず時刻データをファイルから読み込みます。この時、読み込まれたデータはdatetime型にキャストされ、time_buff配列に保存されます。この配列には、後でチャート上で使用するためのデータの時刻情報が格納されます。
ma_buff配列への移動平均データの読み込み
次に、同じくFileReadDouble関数を使って、移動平均データをファイルから読み込みます。このデータは、そのままma_buff配列に格納され、チャート上で移動平均線を描画するためのデータとなります。これにより、ファイルから読み込んだ値がプログラム内で利用可能になります。
ファイルを閉じる
データの読み込みがすべて完了した後、FileClose関数を使用してファイルを閉じます。これにより、ファイルへのアクセスが終了し、システムリソースが解放されます。
メッセージの出力
最後に、PrintFormat関数を使って、ファイルが正常に読み取られ、閉じられたことをエキスパートログに出力します。これにより、ユーザーはファイルが無事に閉じられたことを確認でき、トラブルシューティングの際にも役立ちます。
この部分では、ファイルからのデータ読み込みと、配列への格納が行われており、ファイル操作の一連の流れが完了します。
サンプルコード解説6:OnInit関数部分その4
else
{
// ファイルが開けなかった場合、エラーメッセージを出力
PrintFormat("Failed to open %s file, Error code = %d",InpFileName,GetLastError());
return(INIT_FAILED); // ファイルが開けなかった場合は初期化に失敗したことを返す
}
//--- 配列をインデックス0で指標バッファと結合する
SetIndexBuffer(0,buff,INDICATOR_DATA); // buff配列をチャート表示用の指標データバッファに設定
//---- チャートでは表示されない指標値を設定する
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0); // プロットに表示されない値を設定
//--- 初期化が成功したことを返す
return(INIT_SUCCEEDED);
}
このセクションでは、ファイルが開けなかった場合のエラーハンドリング処理と、インジケータの初期化処理の残りの部分について解説します。
ファイルが開けなかった場合の処理
もしFileOpen関数がファイルを正常に開けなかった場合、elseブロック内でエラーメッセージが出力されます。
まず、PrintFormat関数を使って、指定されたファイルが開けなかったことをエキスパートログに出力します。このエラーメッセージには、失敗したファイル名とエラーコードが含まれています。エラーコードはGetLastError関数で取得され、何が問題だったかを判断する手掛かりとなります。
次に、ファイルが開けなかったため、INIT_FAILEDを返してOnInit関数を終了させます。これにより、インジケータの初期化が失敗したことを示します。
SetIndexBuffer
ファイルが正常に開かれてデータが正しく読み込まれた場合、SetIndexBuffer関数を使用して、buff配列をチャートに表示するためのデータバッファに設定します。このbuff配列は、先にファイルから読み込んだ移動平均データなどを格納しているもので、ここで指定されたインデックス(0)が、チャート上に表示されるインジケータデータと結びつけられます。
PlotIndexSetDouble
PlotIndexSetDouble関数を使って、プロットに表示されない値を設定します。ここでは、PLOT_EMPTY_VALUEに0を設定しており、これによりチャート上で「表示しない値」が0であることを定義しています。これは、移動平均値などを表示しない部分に使用される設定です。
初期化成功の戻り値
すべての初期化が正常に完了した場合、OnInit関数はINIT_SUCCEEDEDを返します。これにより、インジケータが正しく初期化されたことが示され、以降の計算や表示が正常に行われます。
この部分では、エラーハンドリングやインジケータのバッファ設定が行われており、インジケータの初期化が最終的に完了します。
サンプルコード解説7: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[]) // チャートのスプレッドデータ
{
ArraySetAsSeries(time,false); // チャートの時刻データを通常の配列順に設定
//--- まだ処理されてないバーのループ
for(int i=prev_calculated;i<rates_total;i++) // 前回処理されたバー以降からデータを処理
{
//--- デフォルトでは 0
buff[i]=0; // デフォルトでは表示する値を0に初期化
//--- データがまだあるかをチェック
if(ind<size) // 読み込んだデータがまだ残っているか確認
{
for(int j=ind;j<size;j++) // 読み込んだデータを順番に確認
{
//--- 日付が同じならファイルの値を使用する
if(time[i]==time_buff[j]) // チャート上の時刻とファイルから読み取った時刻が一致した場合
{
buff[i]=ma_buff[j]; // ファイルの移動平均データを指標バッファに格納
ind=j+1; // 読み取ったデータの位置を1つ進める
break; // ループを抜ける
}
}
}
}
//--- 次の呼び出しのために prev_calculated の値を返す
return(rates_total); // 処理された全データ数を返す
}
OnCalculate関数は、チャートのデータが更新されるたびに呼び出され、インジケータの計算や描画を行うメインの関数です。ここでは、チャート上に表示するデータを生成し、必要な計算を行います。
OnCalculate関数の引数
この関数には、以下の複数の引数が渡されます。
- rates_total:チャートの全バー(データ点)の数を表します。
- prev_calculated:前回計算されたデータ数を表し、すでに処理されたバーの数を示します。
- time[]:チャートの時刻データの配列です。各バーに対応する日時が格納されています。
- open[]:チャートのオープン価格データの配列です。
- high[]:チャートの高値データの配列です。
- low[]:チャートの安値データの配列です。
- close[]:チャートの終値データの配列です。
- tick_volume[]:ティックボリューム(取引の頻度)データの配列です。
- volume[]:出来高データの配列です。
- spread[]:スプレッド(売買価格差)データの配列です。
ArraySetAsSeries
時刻データ(time配列)の順序を通常の配列順に設定します。配列が時間順に並んでいることで、後続の処理が正しく行われます。
forループ(データ処理のループ)
前回処理されたバー(prev_calculated)以降のバーに対して、データを処理します。ループの開始位置は、前回計算したバーの位置(prev_calculated)で、終了位置はチャートの全バー数(rates_total)です。これにより、新しいデータのみを処理することで、効率的な計算が行われます。
デフォルト値の設定
各バーの指標値(buff配列)は、デフォルトで0に初期化されます。これは、何らかのデータが読み込まれなかった場合、表示される値が0になるようにするためです。
データが残っているかの確認
ind変数は、ファイルから読み込んだデータの現在位置を示しています。この変数がsize未満であれば、まだファイルから読み込んだデータが残っていることを示します。
時刻データの一致確認とデータの格納
ファイルから読み込んだデータの時刻と、チャート上の時刻データ(time配列)が一致するかどうかを確認します。一致した場合、対応する移動平均データ(ma_buff配列のデータ)をbuff配列に格納します。これにより、チャート上の特定のバーに対応する移動平均値が表示されます。
データ位置の更新
一度データが読み込まれた場合、ind変数をインクリメントして、次のデータ位置を指すように更新します。これにより、次回以降のループでは新しいデータが読み込まれることが保証されます。
関数の終了と戻り値
最後に、rates_totalを返すことで、処理が終了したことを示します。この値は、次回OnCalculate関数が呼ばれた際にprev_calculatedとして使用されます。
このOnCalculate関数は、チャートのデータに基づいてインジケータを計算し、チャートに表示するための重要な部分です。ファイルからのデータの読み込み、時刻データとの一致確認、そしてそれに基づくインジケータの表示が行われています。