FileReadLong関数の働き・役割
FileReadLong関数は、バイナリファイルのファイルポインタが指している現在位置から、long型(8バイト)の値を読み込むために使用されます。バイナリデータ(0と1の並び)を扱う際に、ファイルから8バイトの整数データを読み取る場合に便利です。
例えば、取引データや価格データをバイナリ形式で保存している場合、この関数を使って保存された数値を読み取ることができます。ファイルポインタは、ファイルのどの部分を読み込むかを決定するための位置を示しますが、FileReadLong関数を使うとその位置から次の8バイトをlong型の整数として取得することができます。
バイナリファイルは、テキストファイルと異なり、データがそのままの形式で保存されるため、このような関数を使ってデータを効率的に読み取ることが可能です。
FileReadLong関数の引数について
long FileReadLong(
int file_handle // ファイルハンドル
);
FileReadLong関数は、以下の引数を取ります。
file_handle
FileReadLong関数の唯一の引数で、ファイルハンドル(識別子)を指定します。この識別子は、事前にFileOpen関数でファイルを開いた際に取得された値です。
FileOpen関数を使ってファイルを開くと、その戻り値としてファイルハンドルが返されます。このファイルハンドルを使用して、FileReadLong関数がどのファイルからデータを読み込むかを指定します。ファイルハンドルが無効(INVALID_HANDLE)である場合、FileReadLong関数は正常に動作しません。
FileReadLong関数の戻り値について
FileReadLong関数は、指定されたファイルの現在のポインタ位置から8バイトのデータをlong型(64ビットの整数)として読み込みます。戻り値は、そのファイルから読み取ったlong型の値です。
例えば、ファイルがバイナリ形式で取引データやボリュームデータを保存している場合、FileReadLong関数を使うことで、該当データを数値として読み取ることができます。
なお、ファイルの終端に達している場合や、エラーが発生した場合には、エラーコードが返されることがあります。そのため、ファイルからデータを読み取る際は、ファイルが正常に開かれているか、読み取れるデータが残っているかを事前に確認することが重要です。
FileReadLong関数を使ったサンプルコード
#property indicator_buffers 1 // インジケータバッファの数を1に設定
#property indicator_plots 1 // プロットの数を1に設定
//---- Label1 をプロットする
#property indicator_label1 "Volume" // プロットのラベルを「Volume」に設定
#property indicator_type1 DRAW_LINE // プロットの種類をライン描画に設定
#property indicator_color1 clrYellow // ラインの色を黄色に設定
#property indicator_style1 STYLE_SOLID // ラインのスタイルをソリッド(実線)に設定
#property indicator_width1 2 // ラインの幅を2ピクセルに設定
#property indicator_separate_window // インジケータを別ウィンドウに表示する設定
//--- データ読み込みのパラメータ
input string InpFileName = "Volume.bin"; // 読み込むファイル名
input string InpDirectoryName = "Data"; // ディレクトリ名
//--- グローバル変数
int ind = 0; // インデックス(データ位置)を管理する変数
int size = 0; // 読み込むデータのサイズ
long volume_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 open for writing", InpFileName); // ファイルが開かれたことをログに出力
PrintFormat("File path: %s\\Files\\", TerminalInfoString(TERMINAL_DATA_PATH)); // ファイルパスを出力
//--- 初めに、ファイルのデータ量を読み込む
size = (int)FileReadLong(file_handle); // ファイルからデータサイズを読み込む
//--- 配列へメモリを割り当てる
ArrayResize(volume_buff, size); // 読み込むボリュームデータ用に配列サイズを変更
ArrayResize(time_buff, size); // 読み込む日時データ用に配列サイズを変更
//--- ファイルからデータを読む
for (int i = 0; i < size; i++) // データサイズ分のループ処理
{
time_buff[i] = (datetime)FileReadLong(file_handle); // ファイルから日時データを読み込む
volume_buff[i] = FileReadLong(file_handle); // ファイルからボリュームデータを読み込む
}
//--- ファイルを閉じる
FileClose(file_handle); // ファイルを閉じる
PrintFormat("Data is read, %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); // 指標バッファにデータを結合
//---- チャートで表示される指標値を設定する
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); // time配列を通常の順序に設定
//--- まだ処理されていないバーのループ
for (int i = prev_calculated; i < rates_total; i++) // 未処理バーのループ
{
buff[i] = 0; // デフォルトでバッファを0に設定
//--- まだデータがあるかをチェック
if (ind < size) // 読み込んだデータがまだ残っているか確認
{
for (int j = ind; j < size; j++) // 読み込んだデータサイズ分のループ
{
if (time[i] == time_buff[j]) // 現在の時間とファイル内の時間が一致する場合
{
buff[i] = (double)volume_buff[j]; // 一致した場合ボリュームデータをバッファに格納
ind = j + 1; // 次のデータ位置を記録
break; // ループを抜ける
}
}
}
}
return (rates_total); // 全バーのデータ処理が完了したらrates_totalを返す
}
サンプルコード解説1:プロパティ命令
#property indicator_buffers 1 // インジケータバッファの数を1に設定
#property indicator_plots 1 // プロットの数を1に設定
//---- Label1 をプロットする
#property indicator_label1 "Volume" // プロットのラベルを「Volume」に設定
#property indicator_type1 DRAW_LINE // プロットの種類をライン描画に設定
#property indicator_color1 clrYellow // ラインの色を黄色に設定
#property indicator_style1 STYLE_SOLID // ラインのスタイルをソリッド(実線)に設定
#property indicator_width1 2 // ラインの幅を2ピクセルに設定
#property indicator_separate_window // インジケータを別ウィンドウに表示する設定
このセクションでは、指定されたMQL5コード内のプロパティ命令に関して説明します。プロパティ命令は、カスタム指標の外観や動作に関する設定を行うもので、チャート上に表示されるインジケータのプロパティを定義する際に使われます。
indicator_buffers 1
この命令は、インジケータが使用するバッファ(データを一時的に格納する領域)の数を1つに設定しています。MQL5では、インジケータの計算結果を保存するためにバッファを使います。ここでは、1つのプロット(グラフ)に対して1つのバッファを割り当てています。
indicator_plots 1
この命令は、プロット(描画される指標)の数を1つに設定しています。インジケータが描画するデータ系列の数を指定しており、ここでは1つのラインを描画する設定です。
indicator_label1 “Volume”
この命令は、チャートに表示されるインジケータのラベルを「Volume」に設定しています。インジケータがチャート上で表示される際に、このラベルが凡例として表示されます。
indicator_type1 DRAW_LINE
この命令は、プロットの描画タイプを設定しています。DRAW_LINEは、チャート上にラインとしてデータを描画する設定です。このプロパティにより、インジケータが折れ線グラフのように描画されます。
indicator_color1 clrYellow
この命令は、インジケータのラインの色を黄色(clrYellow)に設定しています。チャート上で表示されるラインの色が指定されており、視覚的な区別を容易にしています。
indicator_style1 STYLE_SOLID
この命令は、インジケータラインのスタイルを設定しています。STYLE_SOLIDは、ラインを実線で描画する設定です。その他にも点線や破線のスタイルを指定することができますが、この場合は実線が選択されています。
indicator_width1 2
この命令は、描画されるラインの太さを2ピクセルに設定しています。ピクセルはデジタル画像を構成する最小の単位であり、このプロパティによりラインの見やすさを調整できます。
indicator_separate_window
この命令は、インジケータをメインチャートとは別のウィンドウに表示する設定です。通常の価格チャートとは別の領域にインジケータを描画したい場合、このプロパティを使用します。この設定により、ボリュームやオシレーターなどが別ウィンドウに表示されます。
サンプルコード解説2:グローバル領域部分
//--- データ読み込みのパラメータ
input string InpFileName = "Volume.bin"; // 読み込むファイル名
input string InpDirectoryName = "Data"; // ディレクトリ名
//--- グローバル変数
int ind = 0; // インデックス(データ位置)を管理する変数
int size = 0; // 読み込むデータのサイズ
long volume_buff[]; // ボリュームデータを格納する配列
datetime time_buff[]; // 日時データを格納する配列
//--- 指標バッファ
double buff[]; // チャートに表示するデータを格納するバッファ
このセクションでは、サンプルコードにおけるグローバル領域部分について解説します。このグローバル領域では、データの読み込みに使用するパラメータやインジケータの計算結果を格納する変数が定義されています。グローバル変数として定義されたデータは、プログラムの他の部分からもアクセス可能で、データを効率的に扱うために重要な役割を果たします。
データ読み込みのパラメータ
input string InpFileName = “Volume.bin”;
この命令は、読み込むファイル名を指定するためのパラメータです。ここでは「Volume.bin」というバイナリファイルを読み込み対象として設定しています。このパラメータはinput変数として宣言されており、ユーザーが実行時に変更可能です。
input string InpDirectoryName = “Data”;
この命令は、データを保存しているディレクトリの名前を指定しています。”Data”ディレクトリ内にあるファイルを対象にしています。このパラメータもinput変数として宣言されているため、実行時に変更が可能です。
グローバル変数
int ind = 0;
この変数は、ファイルから読み込むデータの位置を管理するためのインデックス(通し番号)です。ループ処理で使用され、データを順番に読み込む際に、現在どの位置まで処理したかを追跡します。
int size = 0;
この変数は、ファイルから読み込むデータのサイズを格納します。最初にファイルからデータサイズを取得し、それに基づいて配列のメモリを確保します。このサイズに基づいてデータが読み込まれるため、正確なサイズを把握することが重要です。
long volume_buff[];
この配列は、ファイルから読み込んだボリュームデータを格納するためのものです。ボリュームは通常、取引の数量や出来高を表し、インジケータの計算に利用されます。long型で宣言されており、大きな数値を扱うことができます。
datetime time_buff[];
この配列は、ファイルから読み込んだ日時データを格納します。dateTime型は、日時を表すためのデータ型で、各ボリュームデータに対応するタイムスタンプを保持します。この配列により、時間と対応するボリュームデータを管理します。
指標バッファ
double buff[];
この配列は、チャート上に表示されるインジケータデータを格納するためのバッファです。double型で宣言され、インジケータの計算結果がこの配列に格納され、チャート上に描画されます。このバッファを使って、チャート上にプロットするデータを動的に管理します。
このグローバル領域の変数とパラメータ設定により、データの読み込みとチャート描画に必要な情報が効率的に管理されます。ファイルからデータを読み込み、バッファに保存することで、チャート上での表示やインジケータ計算を行う準備が整います。
サンプルコード解説3:OnInit関数部分その1
//+------------------------------------------------------------------+
//| カスタム指標を初期化する関数 |
//+------------------------------------------------------------------+
int OnInit()
{
//--- ファイルを開く
ResetLastError(); // エラーフラグをリセット
int file_handle = FileOpen(InpDirectoryName + "//" + InpFileName, FILE_READ | FILE_BIN);
// バイナリファイルを読み込みモードで開く
このセクションでは、サンプルコードにおけるOnInit関数の初期化部分について解説します。OnInit関数は、カスタム指標が初めて呼び出されたときに実行される関数で、ファイルの読み込みや初期化処理を行います。この関数の役割は、インジケータが正しく動作するために必要な設定やデータの準備をすることです。
ResetLastError
ResetLastError関数は、直前に発生したエラーコードをリセットするために使用されます。FileOpen関数などの関数がエラーを返した場合、GetLastError関数でエラー内容を取得できますが、この命令でエラー状態をリセットし、新たなエラーを確認できる状態にしておきます。これにより、過去のエラーが残らないようにすることができます。
int file_handle = FileOpen(InpDirectoryName + “//” + InpFileName, FILE_READ | FILE_BIN)
この部分では、指定されたディレクトリとファイル名でバイナリファイルを開く操作を行います。FileOpen関数は、ファイルを開くための関数であり、成功するとファイルハンドル(ファイルを操作するための識別子)を返します。この識別子を使って後続のファイル操作を行います。
- InpDirectoryNameとInpFileNameを組み合わせることで、ファイルパスを生成します。InpDirectoryNameはディレクトリ名、InpFileNameはファイル名を示します。
- FILE_READは、ファイルを読み込みモードで開くことを示します。このモードでは、ファイルからのデータ読み取りは可能ですが、書き込みはできません。
- FILE_BINは、バイナリファイルとしてファイルを開くことを指定しています。この設定により、テキストではなくバイナリデータとして処理します。
ファイルが正しく開かれた場合、このファイルハンドルを使用してデータの読み込みを進めます。
サンプルコード解説4:OnInit関数部分その2
if (file_handle != INVALID_HANDLE) // ファイルが正常に開かれた場合
{
PrintFormat("%s file is open for writing", InpFileName); // ファイルが開かれたことをログに出力
PrintFormat("File path: %s\\Files\\", TerminalInfoString(TERMINAL_DATA_PATH)); // ファイルパスを出力
//--- 初めに、ファイルのデータ量を読み込む
size = (int)FileReadLong(file_handle); // ファイルからデータサイズを読み込む
//--- 配列へメモリを割り当てる
ArrayResize(volume_buff, size); // 読み込むボリュームデータ用に配列サイズを変更
ArrayResize(time_buff, size); // 読み込む日時データ用に配列サイズを変更
//--- ファイルからデータを読む
for (int i = 0; i < size; i++) // データサイズ分のループ処理
{
time_buff[i] = (datetime)FileReadLong(file_handle); // ファイルから日時データを読み込む
volume_buff[i] = FileReadLong(file_handle); // ファイルからボリュームデータを読み込む
}
このセクションでは、OnInit関数の続きで、ファイルが正常に開かれた後の処理について解説します。ここでは、ファイルからデータを読み込み、それを配列に格納する準備が行われています。
ファイルハンドルの確認
ファイルが正常に開かれているかどうかは、file_handleが無効なハンドル(INVALID_HANDLE)でないかを確認しています。この条件によって、ファイルが正しく開かれた場合にのみ処理が進むようになっています。
ファイル名とパスのログ出力
ファイルが開かれた際、PrintFormat関数を使用してファイルが正常に開かれたことをログに出力しています。このログは、ターミナルのエキスパートログに表示され、ファイルの操作が成功したかどうかを確認するのに役立ちます。また、TerminalInfoString関数を使用してターミナルのデータディレクトリのパスを取得し、そのパスをログに出力しています。これにより、どの場所にファイルが保存されているかを把握できます。
ファイルからデータサイズを取得
次に、FileReadLong関数を使用して、ファイルから8バイトのlong型データを読み込み、その結果をsize変数に格納しています。このデータはファイルに保存されているデータ量を示しており、このサイズに基づいて、後続の配列のサイズが決定されます。
配列のサイズ調整
ArrayResize関数を使って、volume_buff配列とtime_buff配列のサイズを先ほど取得したsizeに合わせて変更しています。これにより、ファイルから読み込むデータを格納するためのメモリ領域が確保され、データの格納が適切に行えるようになります。
データの読み込みと格納
その後、forループを使用してファイルからデータを順番に読み込んでいます。FileReadLong関数を使用して、ファイルから日時データをtime_buff配列に、ボリュームデータをvolume_buff配列にそれぞれ格納しています。読み込まれたデータは、それぞれの配列に正しく保存され、後で利用できるようになります。
サンプルコード解説5:OnInit関数部分その3
//--- ファイルを閉じる
FileClose(file_handle); // ファイルを閉じる
PrintFormat("Data is read, %s file is closed", InpFileName); // 読み込み完了をログに出力
}
else
{
PrintFormat("Failed to open %s file, Error code = %d", InpFileName, GetLastError()); // ファイルを開けなかった場合のエラー出力
return (INIT_FAILED); // 初期化失敗を返す
}
ここでは、ファイルの読み込み処理が完了した後の動作や、ファイルが開けなかった場合のエラーハンドリングについて説明します。
ファイルの閉鎖
データの読み込みが完了した後、FileClose関数を使用して開いていたファイルを閉じています。ファイル操作が終了した際には、必ずファイルを閉じることが重要です。これにより、ファイルが他のプロセスや操作で適切に利用できるようになります。ファイルを閉じることは、システムリソースの無駄遣いを防ぐためにも推奨される操作です。
読み込み完了のログ出力
ファイルの閉鎖後、PrintFormat関数を使用して、ファイルのデータが正常に読み込まれ、ファイルが閉じられたことをエキスパートログに出力しています。このログは、ファイルの読み込みが正常に終了したかどうかを確認するのに役立ちます。
エラーハンドリング
もしファイルが開けなかった場合、else文でエラーハンドリングが行われます。この場合、PrintFormat関数を使用してエラーメッセージをログに出力しています。エラーメッセージには、開こうとしたファイル名と、GetLastError関数によって取得されたエラーコードが含まれています。
GetLastError関数は、直前に発生したエラーのコードを取得するための関数です。このエラーコードを確認することで、なぜファイルが開けなかったかの原因を特定することができます。
初期化失敗の返却
ファイルを開けなかった場合には、INIT_FAILEDが返されます。これにより、OnInit関数が失敗し、カスタムインジケータの初期化が正常に完了しなかったことが明示されます。このようにして、初期化エラー時の適切な対応が可能になります。
サンプルコード解説6:OnInit関数部分その4
//--- 配列をインデックス0で指標バッファと結合する
SetIndexBuffer(0, buff, INDICATOR_DATA); // 指標バッファにデータを結合
//---- チャートで表示される指標値を設定する
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0); // プロットの空の値を設定
return (INIT_SUCCEEDED); // 初期化成功を返す
}
このセクションでは、OnInit関数の最後の部分について解説します。ここでは、配列とインジケータバッファの結合や、チャート上に表示されるプロットの設定、初期化成功の返却について説明します。
配列と指標バッファの結合
SetIndexBuffer関数は、指定された配列を指標バッファ(インジケータデータを格納するための領域)に結合するために使用されます。ここでは、buffという配列をインジケータバッファの0番目に結合しています。これにより、buff配列に格納されたデータがインジケータの描画データとして使用され、チャート上に表示される準備が整います。インジケータは、このバッファを通じてデータを管理し、プロットに反映させます。
プロットの空の値を設定
PlotIndexSetDouble関数は、インジケータのプロット設定を調整するために使用されます。ここでは、プロットの空の値(表示されないデータ)を設定しています。空の値が設定されることで、データが存在しない場合や無効なデータが発生した場合に、その箇所は描画されないようになります。具体的には、プロットの0番目に対して空の値として0を指定しています。
初期化成功の返却
最後に、INIT_SUCCEEDEDを返すことで、OnInit関数が正常に終了し、初期化が成功したことを示しています。これにより、カスタムインジケータが正常に動作を開始することができます。初期化が成功すると、MQL5プラットフォームはその後のデータ処理やインジケータの描画を行うことができます。
サンプルコード解説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); // time配列を通常の順序に設定
//--- まだ処理されていないバーのループ
for (int i = prev_calculated; i < rates_total; i++) // 未処理バーのループ
{
buff[i] = 0; // デフォルトでバッファを0に設定
//--- まだデータがあるかをチェック
if (ind < size) // 読み込んだデータがまだ残っているか確認
{
for (int j = ind; j < size; j++) // 読み込んだデータサイズ分のループ
{
if (time[i] == time_buff[j]) // 現在の時間とファイル内の時間が一致する場合
{
buff[i] = (double)volume_buff[j]; // 一致した場合ボリュームデータをバッファに格納
ind = j + 1; // 次のデータ位置を記録
break; // ループを抜ける
}
}
}
}
return (rates_total); // 全バーのデータ処理が完了したらrates_totalを返す
}
このセクションでは、OnCalculate関数について解説します。この関数は、カスタム指標のメインの計算ロジックが記述されている場所で、各バー(チャートの時間軸の単位)ごとにインジケータの値を計算します。この関数は、チャートの更新やバーの追加時に繰り返し呼び出され、インジケータの表示が更新されます。
OnCalculate関数の引数
- rates_total: チャート上の全バーの数です。チャートの表示されている範囲や期間に応じて変わります。
- prev_calculated: 前回計算されたバーの数です。この値を使用して、前回の計算結果と比較し、新しいデータのみを処理することが可能です。
- time: 各バーの時間を保持する配列です。
- open, high, low, close: それぞれ、バーのオープン価格、高値、安値、終値の配列です。これらの価格データを使用して、インジケータの計算が行われます。
- tick_volume, volume: ティックボリュームと実際のボリュームの配列です。ボリュームデータは、取引量を表し、インジケータの計算に利用されることがあります。
- spread: 各バーのスプレッド(買値と売値の差)を表す配列です。
time配列の設定
ArraySetAsSeries関数を使用して、time配列を通常の順序に設定しています。この関数は、配列の順序を変更するために使用されます。通常、配列は新しいデータが後ろに追加される形式で保持されますが、この設定を行うことで、処理が直感的に行えるようになります。
バーの処理ループ
次に、forループを使って未処理のバーのデータを処理しています。prev_calculatedからrates_totalまでの範囲でループを回し、前回の計算以降の新しいバーのみを処理するようにしています。これにより、無駄な再計算を防ぎ、効率的にインジケータの値を更新できます。
デフォルト値の設定
各バーに対して、buff配列に初期値として0を設定しています。buff配列は、インジケータの値を格納するバッファで、各バーごとに計算された結果がこの配列に保存されます。デフォルトでは、まだ計算が行われていない場合に備えて、値を0に設定しています。
データの確認と読み込み
if文を使って、ind変数がまだ読み込んだデータのサイズ内にあるかどうかを確認しています。ind変数はファイルから読み込んだデータの位置を管理しており、size変数は読み込んだデータの総量を示しています。この条件を使って、まだ処理されていないデータがあるかを確認します。
内部ループでデータを一致させる
内部のforループでは、ファイルから読み込んだ日時データとチャートのtime配列内のデータが一致するかを確認しています。もし一致すれば、その時点のボリュームデータをbuff配列に格納します。buff配列は、チャート上に表示されるインジケータの値を保持しているため、この処理によってインジケータの値が正しく設定されます。
処理位置の更新
データが一致した場合には、ind変数を更新して次のデータ位置を記録します。これにより、次回のループ処理では既に処理したデータを再度処理することが防がれ、効率的な計算が行えます。
関数の戻り値
最後に、rates_totalを返すことで、全バーのデータ処理が完了したことをMQL5プラットフォームに伝えています。この戻り値を使って、次回以降の呼び出し時に、どの範囲のバーが新しく追加されたかを管理できます。
OnCalculate関数では、各バーのデータを効率的に処理し、インジケータの値をチャート上に正しく反映させるためのロジックが記述されています。時間やボリュームデータを比較し、一致した場合に対応する値をバッファに格納する仕組みを採用しています。