【MQL5】FileReadStruct関数について

MQL5リファレンス
スポンサーリンク
スポンサーリンク
  1. FileReadStruct関数の働き・役割
  2. FileReadStruct関数の引数について
    1. 第1引数: file_handle
    2. 第2引数: struct_object
    3. 第3引数: size
  3. FileReadStruct関数を使ったサンプルコード
  4. サンプルコード解説1:プロパティ命令
    1. #property indicator_separate_window
    2. #property indicator_buffers 4
    3. #property indicator_plots 1
    4. #property indicator_label1 “Candles”
    5. #property indicator_type1 DRAW_CANDLES
    6. #property indicator_color1 clrOrange
    7. #property indicator_style1 STYLE_SOLID
    8. #property indicator_width1 1
  5. サンプルコード解説2:input変数部分
    1. input string InpFileName="EURUSD.txt"
    2. input string InpDirectoryName="Data"
  6. サンプルコード解説3:オリジナルの構造体部分
    1. struct candlesticks
    2. double open
    3. double close
    4. double high
    5. double low
    6. datetime date
  7. サンプルコード解説4:その他のグローバル領域部分
    1. double open_buff[]
    2. double close_buff[]
    3. double high_buff[]
    4. double low_buff[]
    5. candlesticks cand_buff[]
    6. int size=0
    7. int ind=0
  8. サンプルコード解説5:OnInit関数部分その1
    1. int default_size=100
    2. ArrayResize(cand_buff,default_size)
    3. ResetLastError
    4. int file_handle=FileOpen(InpDirectoryName+”//”+InpFileName,FILE_READ|FILE_BIN|FILE_COMMON)
  9. サンプルコード解説6:OnInit関数部分その2
    1. if(file_handle!=INVALID_HANDLE)
    2. PrintFormat(“%s file is available for reading”, InpFileName)
    3. PrintFormat(“File path: %s\Files\”, TerminalInfoString(TERMINAL_COMMONDATA_PATH))
    4. while(!FileIsEnding(file_handle))
    5. FileReadStruct(file_handle, cand_buff[size])
    6. size++
    7. if(size==default_size)
    8. default_size+=100
    9. ArrayResize(cand_buff, default_size)
  10. サンプルコード解説7:OnInit関数部分その3
    1. FileClose(file_handle)
    2. PrintFormat(“Data is read, %s file is closed”, InpFileName)
    3. else
    4. PrintFormat(“Failed to open %s file, Error code = %d”, InpFileName, GetLastError())
    5. return(INIT_FAILED)
  11. サンプルコード解説8:OnInit関数部分その4
    1. SetIndexBuffer(0, open_buff, INDICATOR_DATA)
    2. SetIndexBuffer(1, high_buff, INDICATOR_DATA)
    3. SetIndexBuffer(2, low_buff, INDICATOR_DATA)
    4. SetIndexBuffer(3, close_buff, INDICATOR_DATA)
    5. PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0)
    6. return(INIT_SUCCEEDED)
  12. サンプルコード解説9:OnCalculate関数部分
    1. ArraySetAsSeries(time, false)
    2. for(int i=prev_calculated; i<rates_total; i++)
    3. open_buff[i] = 0, close_buff[i] = 0, high_buff[i] = 0, low_buff[i] = 0
    4. if(ind < size)
    5. for(int j=ind; j<size; j++)
    6. if(time[i] == cand_buff[j].date)
    7. open_buff[i] = cand_buff[j].open, close_buff[i] = cand_buff[j].close, high_buff[i] = cand_buff[j].high, low_buff[i] = cand_buff[j].low
    8. ind = j + 1
    9. return(rates_total)

FileReadStruct関数の働き・役割

FileReadStruct関数は、バイナリファイルから構造体形式のデータを読み取るために使用されます。この関数は、ファイルポインタの現在位置から指定された構造体にデータを読み込みます。具体的には、事前にファイルに保存されたバイナリデータを、メモリ上の構造体に直接マッピングすることができます。これにより、ファイルに保存されたデータを効率よく取り扱うことが可能となります。

たとえば、金融データの保存や分析において、複数のローソク足データをバイナリファイルに保存し、後にFileReadStruct関数を用いてそのデータを読み込むことで、チャート上に再現したり、統計的な分析を行うことができます。

FileReadStruct関数の引数について

uint  FileReadStruct(
  int        file_handle,        // ファイルハンドル
  const void&  struct_object,      // コンテンツが読み込まれる構造体
  int          size=-1            // バイト単位の構造体サイズ
  );

FileReadStruct関数は、以下の3つの引数を取ります。

第1引数: file_handle

file_handleは、読み取るバイナリファイルのハンドル(識別子)です。このハンドルは、事前にFileOpen関数などでファイルを開いた際に取得します。ファイルが開けなかった場合、この値はINVALID_HANDLEとなります。正常にファイルが開けていれば、FileReadStruct関数はそのファイルからデータを読み込みます。

第2引数: struct_object

struct_objectは、読み込んだデータを格納する構造体です。この構造体には、仮想関数文字列、または動的配列を含むことはできません。指定された構造体メモリ領域に、ファイルの内容が直接読み込まれます。この引数は、読み取り後のデータが格納されるため、書き込み可能な構造体が必要です。

第3引数: size

sizeは、読み取るデータのサイズをバイト単位で指定する引数です。デフォルト値は -1 であり、この場合は構造体のサイズ全体が使用されます。もし、構造体のサイズよりも大きい値を指定した場合、実際の構造体のサイズに基づいてデータが読み込まれます。

FileReadStruct関数を使ったサンプルコード

//---- インジケータの設定
#property indicator_separate_window  // インジケータを別ウィンドウに表示
#property indicator_buffers 4        // 4つのバッファを使用
#property indicator_plots   1        // 1つのプロットを設定
//---- Label1 をプロットする
#property indicator_label1 "Candles"  // プロット名は「Candles」
#property indicator_type1   DRAW_CANDLES  // ローソク足タイプの描画を指定
#property indicator_color1 clrOrange  // ローソク足の色をオレンジに設定
#property indicator_style1 STYLE_SOLID  // 線のスタイルは実線
#property indicator_width1  1         // 線の太さを1に設定
#property indicator_separate_window   // インジケータを別ウィンドウに表示(重複記述の可能性あり)
//--- データ受信のパラメータ
input string InpFileName="EURUSD.txt"; // 読み込むファイル名を指定
input string InpDirectoryName="Data";  // データが格納されるディレクトリ名を指定
//+------------------------------------------------------------------+
//| ローソク足データを格納する構造体                                          |
//+------------------------------------------------------------------+
struct candlesticks
 {
  double            open;  // 始値を格納するフィールド
  double            close; // 終値を格納するフィールド
  double            high;  // 高値を格納するフィールド
  double            low;   // 安値を格納するフィールド
  datetime          date;  // 日付を格納するフィールド
 };
//--- 指標バッファ
double       open_buff[];  // 始値を格納するバッファ
double       close_buff[]; // 終値を格納するバッファ
double       high_buff[];  // 高値を格納するバッファ
double       low_buff[];   // 安値を格納するバッファ
//--- グローバル変数
candlesticks cand_buff[];  // ローソク足データを格納する配列
int          size=0;       // 読み込んだデータのサイズ(初期値は0)
int          ind=0;        // 現在のインデックスを保持する変数

//+------------------------------------------------------------------+
//| カスタム指標を初期化する関数                                             |
//+------------------------------------------------------------------+
int OnInit()
 {
  int default_size=100;  // 配列の初期サイズを100に設定
  ArrayResize(cand_buff,default_size);  // cand_buff配列を初期サイズにリサイズ
//--- ファイルを開く
  ResetLastError();  // エラーメッセージをリセット
  int file_handle=FileOpen(InpDirectoryName+"//"+InpFileName,FILE_READ|FILE_BIN|FILE_COMMON);
  // ファイルを開き、読み込みモード、バイナリモード、共有フォルダ使用のオプションを指定
  if(file_handle!=INVALID_HANDLE)  // ファイルが正常に開かれた場合
    {
    PrintFormat("%s file is available for reading",InpFileName);  // ファイルが読み込み可能であることを表示
    PrintFormat("File path: %s\\Files\\",TerminalInfoString(TERMINAL_COMMONDATA_PATH));  // ファイルのパスを表示
    //--- ファイルからデータを読む
    while(!FileIsEnding(file_handle))  // ファイルの終端に達していない間ループ
       {
        //--- データを配列に書く
        FileReadStruct(file_handle,cand_buff[size]);  // ファイルからデータを構造体に読み込み
        size++;  // 読み込んだデータ数をインクリメント
        //--- 配列がオーバーフローしているかチェックする
        if(size==default_size)  // 配列のサイズが上限に達した場合
          {
          //--- 配列サイズを増やす
           default_size+=100;  // 配列サイズを100増加させる
          ArrayResize(cand_buff,default_size);  // 配列を再度リサイズ
          }
       }
    //--- ファイルを閉じる
    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);  // 初期化に失敗したことを通知
    }
//--- 指標バッファマッピング
  SetIndexBuffer(0,open_buff,INDICATOR_DATA);  // 始値バッファを設定
  SetIndexBuffer(1,high_buff,INDICATOR_DATA);  // 高値バッファを設定
  SetIndexBuffer(2,low_buff,INDICATOR_DATA);   // 安値バッファを設定
  SetIndexBuffer(3,close_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);  // 配列の時系列順を設定
//--- まだ処理されてないローソク足のループ
  for(int i=prev_calculated;i<rates_total;i++)  // 前回計算されたインデックス以降を処理
    {
    //--- デフォルトでは 0
     open_buff[i]=0;   // 始値バッファを初期化
     close_buff[i]=0;  // 終値バッファを初期化
     high_buff[i]=0;   // 高値バッファを初期化
     low_buff[i]=0;    // 安値バッファを初期化
    //--- まだデータがあるかをチェック
    if(ind<size)  // 未処理のデータがあるか確認
       {
        for(int j=ind;j<size;j++)  // 読み込まれたデータを確認
          {
          //--- 日付が同じならファイルの値を使用する
          if(time[i]==cand_buff[j].date)  // 時間が一致する場合
             {
              open_buff[i]=cand_buff[j].open;    // 始値をバッファに代入
              close_buff[i]=cand_buff[j].close;  // 終値をバッファに代入
              high_buff[i]=cand_buff[j].high;    // 高値をバッファに代入
              low_buff[i]=cand_buff[j].low;      // 安値をバッファに代入
              //--- カウンタを増加する
              ind=j+1;  // 処理済みのインデックスを更新
              break;  // 内部ループを抜ける
             }
          }
       }
    }
//--- 次の呼び出しのために prev_calculated の値を返す
  return(rates_total);  // 処理済みのローソク足数を返す
 }

サンプルコード解説1:プロパティ命令

//---- インジケータの設定
#property indicator_separate_window  // インジケータを別ウィンドウに表示
#property indicator_buffers 4        // 4つのバッファを使用
#property indicator_plots   1        // 1つのプロットを設定
//---- Label1 をプロットする
#property indicator_label1 "Candles"  // プロット名は「Candles」
#property indicator_type1   DRAW_CANDLES  // ローソク足タイプの描画を指定
#property indicator_color1 clrOrange  // ローソク足の色をオレンジに設定
#property indicator_style1 STYLE_SOLID  // 線のスタイルは実線
#property indicator_width1  1         // 線の太さを1に設定
#property indicator_separate_window   // インジケータを別ウィンドウに表示(重複記述の可能性あり)

MQL5では、#property命令を使用して、カスタムインジケータの外観や動作に関する設定を行います。以下のコードでは、インジケータの描画方法やバッファ、プロットの設定が記述されています。

#property indicator_separate_window

この命令は、インジケータがチャートのメインウィンドウではなく、別のウィンドウに表示されることを指定します。インジケータの種類によっては、メインウィンドウに表示するものと、別ウィンドウに表示するものがあり、ここでは別ウィンドウでの描画が指定されています。

#property indicator_buffers 4

インジケータが使用するバッファの数を指定します。バッファは、インジケータのデータを格納するための配列です。このコードでは、4つのバッファを使用し、それぞれに始値、終値、高値、安値のデータを格納します。

#property indicator_plots 1

インジケータが描画するプロットの数を指定しています。ここでは、1つのプロットが描画されることを意味します。プロットとは、インジケータとして描画されるデータの集合で、グラフやローソク足などの表示を行う際に使用されます。

#property indicator_label1 “Candles”

インジケータプロットのラベル(名前)を「Candles」に設定しています。このラベルは、インジケータウィンドウに表示されるプロットの説明となります。

#property indicator_type1 DRAW_CANDLES

プロットの描画タイプを指定します。DRAW_CANDLESは、ローソク足を描画する形式です。この指定によって、チャート上にローソク足が表示されます。

#property indicator_color1 clrOrange

ローソク足の色をオレンジに設定しています。clrOrangeは、MQL5で定義されている色の定数です。これにより、ローソク足の外観がオレンジ色になります。

#property indicator_style1 STYLE_SOLID

ローソク足のスタイルを実線(STYLE_SOLID)に設定しています。インジケータの線を描画する際に、点線や破線などのスタイルを指定することもできますが、ここでは実線で描画する設定となっています。

#property indicator_width1 1

ローソク足の線の太さを1ピクセル(デジタル画像を構成する最小の単位)に設定しています。数字を大きくすることで、線を太くすることが可能です。

サンプルコード解説2:input変数部分

input string InpFileName="EURUSD.txt"; // 読み込むファイル名を指定
input string InpDirectoryName="Data";  // データが格納されるディレクトリ名を指定

MQL5では、input変数を使用することで、外部から設定可能な変数を定義することができます。これにより、エキスパートアドバイザーEA)やインジケータを実行する際に、パラメータをユーザーが変更できるようになります。以下のコードでは、ファイル名やディレクトリ名をユーザーが指定できるように設定されています。

input string InpFileName="EURUSD.txt"

この行は、読み込むファイル名を指定するための入力変数を定義しています。inputキーワードを使うことで、ユーザーが「EURUSD.txt」という初期値を変更して別のファイルを指定できるようにしています。この例では、ローソク足データが保存されているファイル名を指定するためのものです。文字列型の変数InpFileNameには、デフォルトで「EURUSD.txt」というファイル名が設定されています。

input string InpDirectoryName="Data"

こちらは、データが格納されるディレクトリ名を指定するための入力変数です。InpDirectoryNameという変数に「Data」という初期値が設定されており、ユーザーは必要に応じてこのディレクトリ名を変更することが可能です。ファイルの保存場所や管理するデータの種類によって、このディレクトリ名を変更することが有効です。

サンプルコード解説3:オリジナルの構造体部分

//+------------------------------------------------------------------+
//| ローソク足データを格納する構造体                                          |
//+------------------------------------------------------------------+
struct candlesticks
 {
  double            open;  // 始値を格納するフィールド
  double            close; // 終値を格納するフィールド
  double            high;  // 高値を格納するフィールド
  double            low;   // 安値を格納するフィールド
  datetime          date;  // 日付を格納するフィールド
 };

MQL5では、structを使用して構造体を定義し、複数の異なるデータ型を1つにまとめて扱うことができます。以下のコードでは、ローソク足データを格納するためのオリジナル構造体candlesticksが定義されています。この構造体は、始値、終値、高値、安値、日付を1つのデータセットとして扱うために使われます。

struct candlesticks

この行で、candlesticksという名前の構造体が定義されています。この構造体は、ローソク足データを1つのデータ単位として保持するためのもので、複数のフィールドを含んでいます。

double open

このフィールドは、ローソク足の「始値」を格納するためのものです。double型を使用しており、価格データを高精度で保存できます。

double close

このフィールドは、「終値」を格納します。取引の最後の価格を保存するため、チャート上で終値として表示されます。

double high

「高値」を格納するフィールドです。そのローソク足期間中に記録された最も高い価格を保持します。

double low

「安値」を格納するフィールドです。ローソク足期間中の最も低い価格を保持します。

datetime date

このフィールドは、「日付」を格納します。dateTime型を使用しており、具体的な日時を保存できます。ローソク足データを時間と結びつけて管理するために、このフィールドが使用されます。

この構造体を用いることで、ローソク足データを1つの単位としてまとめて処理することが可能になり、ファイルの入出力やチャートへの描画が簡単になります。

サンプルコード解説4:その他のグローバル領域部分

double       open_buff[];  // 始値を格納するバッファ
double       close_buff[]; // 終値を格納するバッファ
double       high_buff[];  // 高値を格納するバッファ
double       low_buff[];   // 安値を格納するバッファ
//--- グローバル変数
candlesticks cand_buff[];  // ローソク足データを格納する配列
int          size=0;       // 読み込んだデータのサイズ(初期値は0)
int          ind=0;        // 現在のインデックスを保持する変数

このセクションでは、グローバル変数として定義されているバッファ配列インデックス変数について解説します。これらの変数は、インジケータのデータ処理や管理に使用されます。

double open_buff[]

この配列は、ローソク足の「始値」を格納するバッファです。インジケータがチャート上に表示する際、各ローソク足の始値データをここに格納し、描画に利用します。

double close_buff[]

この配列は、「終値」を格納するバッファです。各ローソク足の取引終了時の価格がここに保存され、チャート上で終値として描画されます。

double high_buff[]

「高値」を格納するバッファです。各ローソク足の期間内で最も高い価格がこの配列に格納され、チャート上に表示されます。

double low_buff[]

「安値」を格納するバッファです。ローソク足期間中の最も低い価格がこの配列に保存され、インジケータとして表示されます。

candlesticks cand_buff[]

この配列は、構造体candlesticksを使用してローソク足データ全体を格納します。open_buffやclose_buffのように個別の価格要素を分けて保存するのではなく、1つの構造体で始値、終値、高値、安値、日付といったローソク足の全データを1つのエントリとして扱います。

int size=0

この変数は、現在読み込んでいるデータのサイズ(ローソク足の数)を保持します。初期値は0で、ファイルから新しいデータを読み込むごとに、このサイズがインクリメントされます。

int ind=0

この変数は、現在のインデックスを保持するために使用されます。ローソク足データを処理する際、どのデータがすでに処理済みであるかを追跡するために、この変数が利用されます。

サンプルコード解説5:OnInit関数部分その1

//+------------------------------------------------------------------+
//| カスタム指標を初期化する関数                                             |
//+------------------------------------------------------------------+
int OnInit()
 {
  int default_size=100;  // 配列の初期サイズを100に設定
  ArrayResize(cand_buff,default_size);  // cand_buff配列を初期サイズにリサイズ
//--- ファイルを開く
  ResetLastError();  // エラーメッセージをリセット
  int file_handle=FileOpen(InpDirectoryName+"//"+InpFileName,FILE_READ|FILE_BIN|FILE_COMMON);
  // ファイルを開き、読み込みモード、バイナリモード、共有フォルダ使用のオプションを指定

OnInit関数は、カスタムインジケータの初期化時に呼び出される関数です。この関数内では、変数配列の初期設定、ファイルのオープン、エラーハンドリングなどが行われています。以下のコードでは、ローソク足データを読み込むための準備をしています。

int default_size=100

この行では、cand_buff配列の初期サイズを100に設定しています。ローソク足データを格納する構造体配列が、初期状態で100エントリ分のメモリを確保されます。この値は、ファイルからデータを読み込む際に必要に応じて拡張されます。

ArrayResize(cand_buff,default_size)

この関数は、指定したサイズ(ここでは100)に配列cand_buffをリサイズします。ローソク足データを格納するための構造体配列のサイズを、default_sizeで設定された値に拡張しています。後にファイルからデータが読み込まれると、この配列に格納されます。

ResetLastError

ResetLastError関数は、直前のエラーステータスをリセットするために使用されます。これにより、ファイルを開く際に発生したエラーが残っていないことを確認し、後の処理で正確なエラーコードを取得できるようになります。

int file_handle=FileOpen(InpDirectoryName+”//”+InpFileName,FILE_READ|FILE_BIN|FILE_COMMON)

この行では、FileOpen関数を使用して、指定されたディレクトリとファイル名でバイナリファイルを読み込みモードで開いています。InpDirectoryNameとInpFileName変数によって、ユーザーが指定したファイルが読み込まれます。FILE_READは読み込み専用、FILE_BINはバイナリ形式、FILE_COMMONは共有フォルダからのファイル操作を表します。

この一連の処理によって、ローソク足データを格納する配列の準備が整い、データを読み込むためのファイルが開かれることになります。

サンプルコード解説6:OnInit関数部分その2

  if(file_handle!=INVALID_HANDLE)  // ファイルが正常に開かれた場合
    {
    PrintFormat("%s file is available for reading",InpFileName);  // ファイルが読み込み可能であることを表示
    PrintFormat("File path: %s\\Files\\",TerminalInfoString(TERMINAL_COMMONDATA_PATH));  // ファイルのパスを表示
    //--- ファイルからデータを読む
    while(!FileIsEnding(file_handle))  // ファイルの終端に達していない間ループ
       {
        //--- データを配列に書く
        FileReadStruct(file_handle,cand_buff[size]);  // ファイルからデータを構造体に読み込み
        size++;  // 読み込んだデータ数をインクリメント
        //--- 配列がオーバーフローしているかチェックする
        if(size==default_size)  // 配列のサイズが上限に達した場合
          {
          //--- 配列サイズを増やす
           default_size+=100;  // 配列サイズを100増加させる
          ArrayResize(cand_buff,default_size);  // 配列を再度リサイズ
          }
       }

このセクションでは、ファイルを正常に開いた場合の処理や、ファイルからローソク足データを読み込み、配列に保存する部分について解説します。

if(file_handle!=INVALID_HANDLE)

ファイルが正常に開かれたかどうかをチェックしています。file_handleがINVALID_HANDLEでない場合、ファイルが正しく開かれており、データの読み込みが可能な状態です。ファイルが開けなかった場合には、エラー処理が行われます。

PrintFormat(“%s file is available for reading”, InpFileName)

この行では、読み込むファイルが正しく開かれたことをメッセージとして表示しています。ここで、ファイル名(InpFileName)がユーザーに通知されます。

PrintFormat(“File path: %s\Files\”, TerminalInfoString(TERMINAL_COMMONDATA_PATH))

ファイルが格納されているディレクトリのパスを表示しています。TerminalInfoString関数を使って、ターミナルの共通データフォルダのパスを取得し、ユーザーに知らせます。

while(!FileIsEnding(file_handle))

このループは、ファイルの終端に到達するまで繰り返されます。FileIsEnding関数を使って、ファイルの終わりに達しているかどうかをチェックしています。ファイルの終わりに達していない限り、ループ内でデータが読み込まれ続けます。

FileReadStruct(file_handle, cand_buff[size])

ファイルからデータを読み込み、cand_buff配列の現在のインデックス(size)に格納しています。FileReadStruct関数を使用して、ファイル内のバイナリデータを事前に定義した構造体に読み込みます。ローソク足データの始値、終値、高値、安値、日付がこの関数によって配列に格納されます。

size++

データが1つ読み込まれるたびに、size変数がインクリメントされます。これにより、次のデータを配列のどこに格納するかを指定しています。

if(size==default_size)

この条件は、配列cand_buffが現在のサイズ制限に達したかどうかをチェックしています。配列の容量が不足した場合、データを追加できるように、配列のサイズを増やす必要があります。

default_size+=100

配列のサイズを100ずつ増やします。これにより、メモリを動的に確保し、さらに多くのデータを読み込むことが可能になります。

ArrayResize(cand_buff, default_size)

配列cand_buffのサイズを拡張します。ArrayResize関数を使って、default_sizeで設定した新しいサイズに配列をリサイズし、追加データが格納できるようにします。

この処理により、ファイルから効率よくローソク足データが読み込まれ、メモリが動的に管理されます。

サンプルコード解説7: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(file_handle)

ファイルの読み込みが完了した後、FileClose関数を使ってファイルを閉じます。ファイルを正しく閉じることは、メモリの無駄遣いやファイルのロック状態を防ぐために重要です。これにより、ファイルハンドルが解放され、他の処理が同じファイルにアクセスできるようになります。

PrintFormat(“Data is read, %s file is closed”, InpFileName)

ファイルの読み込みが正常に終了し、ファイルが閉じられたことをユーザーに通知するメッセージです。InpFileNameとして指定されたファイル名が表示され、どのファイルが対象だったかが確認できます。このメッセージは、データが正しく読み込まれたことを示します。

else

このelse文では、ファイルが正常に開けなかった場合のエラーハンドリングを行っています。ファイルが開けなかった原因に対処し、ユーザーにエラーが発生したことを知らせます。

PrintFormat(“Failed to open %s file, Error code = %d”, InpFileName, GetLastError())

ファイルのオープンに失敗した場合、エラーメッセージを表示します。このメッセージには、ファイル名(InpFileName)と、GetLastError関数で取得したエラーコードが含まれます。エラーコードは、失敗の原因を特定するために役立ちます。

return(INIT_FAILED)

初期化が失敗したことを通知するため、INIT_FAILEDを返します。この戻り値は、インジケータの初期化が正常に完了しなかったことを示し、以降の処理を行わないように制御します。

この部分では、ファイル操作の成功・失敗に応じて適切なメッセージを表示し、エラーハンドリングを行うことで、スムーズなデータ処理が行えるように設計されています。

サンプルコード解説8:OnInit関数部分その4

//--- 指標バッファマッピング
  SetIndexBuffer(0,open_buff,INDICATOR_DATA);  // 始値バッファを設定
  SetIndexBuffer(1,high_buff,INDICATOR_DATA);  // 高値バッファを設定
  SetIndexBuffer(2,low_buff,INDICATOR_DATA);   // 安値バッファを設定
  SetIndexBuffer(3,close_buff,INDICATOR_DATA); // 終値バッファを設定
//--- 空の値
  PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);  // 空のデータポイントを設定
//---
  return(INIT_SUCCEEDED);  // 初期化が成功したことを通知
 }

このセクションでは、指標(インジケータ)のバッファを設定し、初期化が成功したことを通知する部分について解説します。

SetIndexBuffer(0, open_buff, INDICATOR_DATA)

この行では、始値(open_buff)をインジケータの0番目のバッファにマッピングしています。SetIndexBuffer関数は、指定されたバッファインジケータに関連付けるために使用され、INDICATOR_DATAフラグはそのバッファインジケータのデータ用であることを示します。

SetIndexBuffer(1, high_buff, INDICATOR_DATA)

この行では、高値(high_buff)をインジケータの1番目のバッファにマッピングしています。インジケータの描画時に、高値データがこのバッファから使用されます。

SetIndexBuffer(2, low_buff, INDICATOR_DATA)

安値(low_buff)をインジケータの2番目のバッファに設定しています。この設定により、インジケータが安値データを利用してチャートに描画します。

SetIndexBuffer(3, close_buff, INDICATOR_DATA)

終値(close_buff)を3番目のバッファに設定しています。終値データは、チャートでの重要な価格データの1つであり、インジケータによって描画されます。

PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0)

この行では、0番目のプロットに空の値を設定しています。PLOT_EMPTY_VALUEは、値が存在しないことを意味する特別な値で、データが欠けている部分に適用されます。これにより、空白の領域が正しく処理されるようになります。

return(INIT_SUCCEEDED)

最後に、初期化が成功したことを示すためにINIT_SUCCEEDEDを返します。これにより、インジケータの初期化が正常に完了したことが通知され、その後のデータ処理や描画が可能になります。

この部分では、インジケータが正しくデータを描画できるようにバッファのマッピングを行い、初期化が成功したかどうかを確認する処理が行われています。

サンプルコード解説9: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
     open_buff[i]=0;   // 始値バッファを初期化
     close_buff[i]=0;  // 終値バッファを初期化
     high_buff[i]=0;   // 高値バッファを初期化
     low_buff[i]=0;    // 安値バッファを初期化
    //--- まだデータがあるかをチェック
    if(ind<size)  // 未処理のデータがあるか確認
       {
        for(int j=ind;j<size;j++)  // 読み込まれたデータを確認
          {
          //--- 日付が同じならファイルの値を使用する
          if(time[i]==cand_buff[j].date)  // 時間が一致する場合
             {
              open_buff[i]=cand_buff[j].open;    // 始値をバッファに代入
              close_buff[i]=cand_buff[j].close;  // 終値をバッファに代入
              high_buff[i]=cand_buff[j].high;    // 高値をバッファに代入
              low_buff[i]=cand_buff[j].low;      // 安値をバッファに代入
              //--- カウンタを増加する
              ind=j+1;  // 処理済みのインデックスを更新
              break;  // 内部ループを抜ける
             }
          }
       }
    }
//--- 次の呼び出しのために prev_calculated の値を返す
  return(rates_total);  // 処理済みのローソク足数を返す
 }

OnCalculate関数は、カスタムインジケータが再計算されるたびに呼び出されます。ローソク足データのバッファを更新し、チャートに描画するためのデータを処理します。この部分では、配列を初期化し、必要なデータをバッファに格納する処理が行われています。

ArraySetAsSeries(time, false)

この行は、配列の時系列順序を設定しています。falseを指定することで、配列のデータが時間順(過去から未来への順序)で格納されるようにしています。

for(int i=prev_calculated; i<rates_total; i++)

このループは、前回の計算で処理されたローソク足のインデックス(prev_calculated)から最新のローソク足インデックス(rates_total)までを処理するためのものです。新しいデータが到着した場合、それらを順次処理します。

open_buff[i] = 0, close_buff[i] = 0, high_buff[i] = 0, low_buff[i] = 0

それぞれのバッファ(始値、終値、高値、安値)を0で初期化します。これにより、以前のデータが残らないようにクリアされます。

if(ind < size)

この条件では、未処理のデータがあるかを確認しています。sizeはファイルから読み込んだデータの数であり、indはすでに処理されたデータのインデックスを指しています。

for(int j=ind; j<size; j++)

このループは、ファイルから読み込まれたデータを確認するためのものです。未処理のデータから順次処理し、日付が一致するデータを探します。

if(time[i] == cand_buff[j].date)

この条件では、ローソク足の時刻がファイルから読み込んだデータの日付と一致するかどうかを確認しています。時間が一致すれば、そのデータを現在のローソク足データとしてバッファに格納します。

open_buff[i] = cand_buff[j].open, close_buff[i] = cand_buff[j].close, high_buff[i] = cand_buff[j].high, low_buff[i] = cand_buff[j].low

時間が一致した場合、ファイルから読み込んだローソク足データ(始値、終値、高値、安値)を、それぞれ対応するバッファに格納します。このバッファは、インジケータの描画時に使用されます。

ind = j + 1

処理済みのインデックスを更新し、次に処理するデータの位置を示します。これにより、次の計算で未処理のデータを効率よく処理することができます。

return(rates_total)

処理が完了した後、rates_totalを返します。これにより、次回のOnCalculate関数呼び出し時に、どのインデックスから処理を再開すれば良いかがわかります。

この関数では、読み込んだローソク足データをバッファに格納し、チャートに描画するための準備を整えています。バッファを初期化し、必要なデータを正しく処理することで、インジケータの正確な表示を実現します。

タイトルとURLをコピーしました