【MQL5】FileWriteDouble関数について

MQL5リファレンス
スポンサーリンク
スポンサーリンク
  1. FileWriteDouble関数の働き・役割
  2. FileWriteDouble関数の引数について
  3. FileWriteDouble関数の戻り値について
  4. FileWriteDouble関数を使ったサンプルコード
  5. サンプルコード解説1:グローバル領域部分
    1. #property script_show_inputs
    2. input string InpSymbolName = "EURJPY";
    3. input ENUM_TIMEFRAMES InpSymbolPeriod = PERIOD_M15;
    4. input int InpMAPeriod = 10;
    5. input int InpMAShift = 0;
    6. input ENUM_MA_METHOD InpMAMethod = MODE_SMA;
    7. input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE;
    8. input datetime InpDateStart = D'2013.01.01 00:00';
    9. input string InpFileName = "MA.csv";
    10. input string InpDirectoryName = "Data";
  6. サンプルコード解説2:OnStart関数その1
    1. date_finish = TimeCurrent();
    2. ma_buff[]
    3. time_buff[]
    4. size
    5. ResetLastError()
    6. ma_handle = iMA(InpSymbolName, InpSymbolPeriod, InpMAPeriod, InpMAShift, InpMAMethod, InpAppliedPrice)
  7. サンプルコード解説3:OnStart関数その2
    1. ma_handle == INVALID_HANDLE
    2. PrintFormat関数(“Error when receiving indicator handle. Error code = %d”, GetLastError関数());
      1. GetLastError関数
    3. return;
    4. while(BarsCalculated関数(ma_handle) == -1)
      1. BarsCalculated関数
    5. Sleep(20);
    6. PrintFormat(“Indicator values starting from %s will be written to the file”, TimeToString(InpDateStart));
      1. TimeToString関数
  8. サンプルコード解説4:OnStart関数その3
    1. ResetLastError関数();
    2. if(CopyBuffer(ma_handle, 0, InpDateStart, date_finish, ma_buff) == -1)
      1. CopyBuffer関数
    3. PrintFormat(“Failed to copy the indicator values. Error code = %d”, GetLastError());
    4. if(CopyTime(InpSymbolName, InpSymbolPeriod, InpDateStart, date_finish, time_buff) == -1)
      1. CopyTime関数
    5. PrintFormat(“Failed to copy time values. Error code = %d”, GetLastError());
  9. サンプルコード解説5:OnStart関数その4
    1. size = ArraySize(ma_buff);
    2. IndicatorRelease(ma_handle);
    3. ResetLastError();
    4. file_handle = FileOpen(InpDirectoryName + “//” + InpFileName, FILE_READ | FILE_WRITE | FILE_BIN);
      1. FileOpen関数
  10. サンプルコード解説6:OnStart関数その5
    1. if(file_handle != INVALID_HANDLE)
    2. PrintFormat(“%s file is available for writing”, InpFileName);
    3. PrintFormat(“File path: %s\Files\”, TerminalInfoString(TERMINAL_DATA_PATH));
    4. FileWriteDouble(file_handle, (double)size);
    5. for(int i = 0; i < size; i++)
    6. FileWriteDouble(file_handle, (double)time_buff[i]);
    7. FileWriteDouble(file_handle, ma_buff[i]);
    8. FileClose(file_handle);
      1. FileClose関数
    9. PrintFormat(“Data is written, %s file is closed”, InpFileName);
  11. サンプルコード解説7:OnStartその6
    1. else
    2. PrintFormat(“Failed to open %s file, Error code = %d”, InpFileName, GetLastError());

FileWriteDouble関数の働き・役割

FileWriteDouble関数は、指定されたファイルハンドルを使用して、ファイルにdouble型の値をバイナリ形式で書き込むために使用されます。この関数は、ファイルポインタの現在の位置からデータを書き込み、ファイルポインタは書き込まれたバイト数分だけ移動します。バイナリ形式での書き込みが行われるため、書かれるデータは8バイトdouble型のサイズ)となります。

主に、金融データや指標の計算結果など、精度の高い数値データをファイルに保存する際に用いられます。この関数を使うことで、チャートデータや指標値などの履歴をファイルに保存し、後で参照したり分析したりすることが可能です。

FileWriteDouble関数の引数について

uint  FileWriteDouble(
  int    file_handle,    // ファイルハンドル
  double  value            // 書かれる値
  );

FileWriteDouble関数は、以下の2つの引数を取ります。

  1. file_handle
    この引数は、ファイル操作を行うためのファイルハンドル(ファイル識別子)を指定します。ファイルハンドルは、FileOpen関数数を使用してファイルを開いた際に取得されます。ファイルハンドルが無効な場合(INVALID_HANDLE)、FileWriteDouble関数は動作しません。
  2. value
    この引数は、ファイルに書き込むdouble型の値を指定します。書き込まれた値は、バイナリ形式で8バイトの大きさになります。この形式により、数値データの保存や高精度なデータ処理が可能となります。

FileWriteDouble関数の戻り値について

FileWriteDouble関数戻り値は、正常に書き込まれたバイト数です。この関数が成功すると、書き込まれたバイト数が返されます。double型のデータは8バイトであるため、戻り値は常に8になります。

もしファイルに書き込みが失敗した場合、戻り値は0になります。このような場合は、ファイルハンドルが無効であったり、ファイルの書き込み権限がないなどの問題が考えられます。

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

//--- スクリプトの起動時に入力パラメータのウィンドウを表示する
#property script_show_inputs

//--- 端末からデータを受け取るパラメータ
input string             InpSymbolName="EURJPY";         // 分析対象の通貨ペア
input ENUM_TIMEFRAMES    InpSymbolPeriod=PERIOD_M15;     // 分析に使用する時間軸(15分足)
input int                InpMAPeriod=10;                 // 移動平均線の平滑化期間
input int                InpMAShift=0;                   // 移動平均線のシフト数(0でシフトなし)
input ENUM_MA_METHOD     InpMAMethod=MODE_SMA;           // 移動平均の計算方法(単純移動平均)
input ENUM_APPLIED_PRICE InpAppliedPrice=PRICE_CLOSE;    // 移動平均の計算に使用する価格の種類(終値)
input datetime           InpDateStart=D'2013.01.01 00:00'; // データコピーの開始日

//--- データをファイルに書き込むためのパラメータ
input string             InpFileName="MA.csv";           // 書き込み先のファイル名
input string             InpDirectoryName="Data";        // 保存先のディレクトリ名

//+------------------------------------------------------------------+
//| スクリプトプログラムを開始する関数                               |
//+------------------------------------------------------------------+
void OnStart()
 {
  // 現在のサーバー時刻を取得し、終了時間として設定
  datetime date_finish = TimeCurrent();
  
  // 移動平均線の値を格納するためのバッファを宣言
  double ma_buff[];
  
  // 時間データを格納するためのバッファを宣言
  datetime time_buff[];
  
  // バッファのサイズを格納する変数
  int size;

  //--- 移動平均(MA)指標のハンドルを取得
  ResetLastError();  // エラーコードをリセット
  int ma_handle = iMA(InpSymbolName, InpSymbolPeriod, InpMAPeriod, InpMAShift, InpMAMethod, InpAppliedPrice);

  // 指標ハンドルが無効である場合の処理
  if(ma_handle == INVALID_HANDLE)
    {
    //--- 指標ハンドルの取得に失敗したことをエキスパートログに出力
    PrintFormat("Error when receiving indicator handle. Error code = %d", GetLastError());
    return;  // エラーが発生したため処理を終了
    }

  //--- 全ての指標値が計算されるまで一時停止
  while(BarsCalculated(ma_handle) == -1)
    Sleep(20);  // 指標が計算されるまで20ミリ秒の間隔で待機

  // 指定した日付から計算が開始されることをエキスパートログに出力
  PrintFormat("Indicator values starting from %s will be written to the file", TimeToString(InpDateStart));

  //--- 指標値をバッファに複製する
  ResetLastError();  // エラーコードをリセット
  if(CopyBuffer(ma_handle, 0, InpDateStart, date_finish, ma_buff) == -1)
    {
    //--- 指標値のコピーに失敗した場合のエラーメッセージをエキスパートログに出力
    PrintFormat("Failed to copy the indicator values. Error code = %d", GetLastError());
    return;  // 処理を終了
    }

  //--- 適切な時間データをバッファに複製する
  ResetLastError();  // エラーコードをリセット
  if(CopyTime(InpSymbolName, InpSymbolPeriod, InpDateStart, date_finish, time_buff) == -1)
    {
    //--- 時間データのコピーに失敗した場合のエラーメッセージをエキスパートログに出力
    PrintFormat("Failed to copy time values. Error code = %d", GetLastError());
    return;  // 処理を終了
    }

  //--- バッファサイズを取得する
  size = ArraySize(ma_buff);

  //--- 使用した指標ハンドルのメモリを解放する
  IndicatorRelease(ma_handle);

  //--- 指標データを書き込むためにファイルを開く(存在しない場合は自動的に作成)
  ResetLastError();  // エラーコードをリセット
  int file_handle = FileOpen(InpDirectoryName + "//" + InpFileName, FILE_READ | FILE_WRITE | FILE_BIN);

  if(file_handle != INVALID_HANDLE)
    {
    // ファイルが正常に開けたことをエキスパートログに出力
    PrintFormat("%s file is available for writing", InpFileName);
    PrintFormat("File path: %s\\Files\\", TerminalInfoString(TERMINAL_DATA_PATH));
    
    //--- 初めにデータサンプルのサイズを書き込む
    FileWriteDouble(file_handle, (double)size);
    
    //--- 指標の時間と値をファイルに書き込む
    for(int i = 0; i < size; i++)
       {
        FileWriteDouble(file_handle, (double)time_buff[i]);  // 時間データを書き込む
        FileWriteDouble(file_handle, ma_buff[i]);            // 移動平均値を書き込む
       }

    //--- ファイルを書き込み完了後に閉じる
    FileClose(file_handle);
    PrintFormat("Data is written, %s file is closed", InpFileName);
    }
  else
    {
    // ファイルのオープンに失敗した場合のエラーメッセージをエキスパートログに出力
    PrintFormat("Failed to open %s file, Error code = %d", InpFileName, GetLastError());
    }
 }

サンプルコード解説1:グローバル領域部分

//--- スクリプトの起動時に入力パラメータのウィンドウを表示する
#property script_show_inputs

//--- 端末からデータを受け取るパラメータ
input string             InpSymbolName="EURJPY";         // 分析対象の通貨ペア
input ENUM_TIMEFRAMES    InpSymbolPeriod=PERIOD_M15;     // 分析に使用する時間軸(15分足)
input int                InpMAPeriod=10;                 // 移動平均線の平滑化期間
input int                InpMAShift=0;                   // 移動平均線のシフト数(0でシフトなし)
input ENUM_MA_METHOD     InpMAMethod=MODE_SMA;           // 移動平均の計算方法(単純移動平均)
input ENUM_APPLIED_PRICE InpAppliedPrice=PRICE_CLOSE;    // 移動平均の計算に使用する価格の種類(終値)
input datetime           InpDateStart=D'2013.01.01 00:00'; // データコピーの開始日

//--- データをファイルに書き込むためのパラメータ
input string             InpFileName="MA.csv";           // 書き込み先のファイル名
input string             InpDirectoryName="Data";        // 保存先のディレクトリ名

このセクションでは、グローバル領域で定義されているパラメータについて解説します。スクリプトの実行時に必要なデータや設定項目を、スクリプト全体で使用できるように定義しています。

#property script_show_inputs

この設定は、スクリプトが起動された際に、入力パラメータのウィンドウを表示するためのものです。スクリプトを実行する際に、ユーザーが必要なパラメータを入力できるようにする役割を果たします。

input string InpSymbolName = "EURJPY";

このパラメータは、分析対象とする通貨ペアを指定します。初期値として「EURJPY」(ユーロ/円)が設定されていますが、スクリプト実行時に他の通貨ペアを指定することも可能です。

input ENUM_TIMEFRAMES InpSymbolPeriod = PERIOD_M15;

このパラメータは、分析に使用する時間軸を指定します。初期値として15分足(PERIOD_M15)が設定されていますが、ユーザーが他の時間軸(例: PERIOD_H1など)に変更することも可能です。

input int InpMAPeriod = 10;

このパラメータは、移動平均線を計算する際の平滑化期間を指定します。ここでは、10期間の移動平均線を計算するように設定されていますが、任意の期間に変更可能です。

input int InpMAShift = 0;

このパラメータは、移動平均線のシフト数を指定します。シフトとは、移動平均線を右または左にずらすことを指し、0の場合はシフトしません。ユーザーが必要に応じてこの値を変更することもできます。

input ENUM_MA_METHOD InpMAMethod = MODE_SMA;

このパラメータは、移動平均線の計算方法を指定します。初期値単純移動平均SMA: Simple Moving Average)に設定されていますが、他の移動平均線の計算方法(例: EMALWMAなど)を選択することもできます。

input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE;

このパラメータは、移動平均線を計算する際に使用する価格の種類を指定します。初期値は終値(PRICE_CLOSE)ですが、高値(PRICE_HIGH)や安値(PRICE_LOW)など、他の価格を使用することも可能です。

input datetime InpDateStart = D'2013.01.01 00:00';

このパラメータは、データコピーを開始する日時を指定します。ここでは2013年1月1日からのデータを使用するように設定されていますが、ユーザーが任意の日付に変更することが可能です。

input string InpFileName = "MA.csv";

このパラメータは、スクリプトで書き込むファイルの名前を指定します。ここでは「MA.csv」という名前のファイルが設定されていますが、ユーザーが他のファイル名に変更することもできます。

input string InpDirectoryName = "Data";

このパラメータは、ファイルを保存するディレクトリ名を指定します。ここでは「Data」というディレクトリが設定されています。デフォルトでは、ターミナルの「Files」フォルダ内に「Data」フォルダが作成され、その中にファイルが保存されます。ユーザーが他のディレクトリ名を指定することも可能です。

以上がグローバル領域で設定されたパラメータの解説です。これらのパラメータは、スクリプト全体で使用され、ユーザーがスクリプト実行時に必要に応じて変更できるように設計されています。

サンプルコード解説2:OnStart関数その1

//+------------------------------------------------------------------+
//| スクリプトプログラムを開始する関数                               |
//+------------------------------------------------------------------+
void OnStart()
 {
  // 現在のサーバー時刻を取得し、終了時間として設定
  datetime date_finish = TimeCurrent();
  
  // 移動平均線の値を格納するためのバッファを宣言
  double ma_buff[];
  
  // 時間データを格納するためのバッファを宣言
  datetime time_buff[];
  
  // バッファのサイズを格納する変数
  int size;

  //--- 移動平均(MA)指標のハンドルを取得
  ResetLastError();  // エラーコードをリセット
  int ma_handle = iMA(InpSymbolName, InpSymbolPeriod, InpMAPeriod, InpMAShift, InpMAMethod, InpAppliedPrice);

このセクションでは、OnStart関数の最初の部分について解説します。OnStart関数は、スクリプトが実行される際に最初に呼び出される関数です。以下では、その初期処理について詳しく説明します。

date_finish = TimeCurrent();

TimeCurrent関数は、現在のサーバー時刻を取得する関数です。この時刻は、スクリプト内で移動平均線を計算する際の終了時間として使用されます。このdate_finish変数は後で移動平均線のデータを取得する際に使用され、スクリプトの実行時にサーバーから提供される最新の時刻を基準にします。

ma_buff[]

ma_buffは、移動平均線の値を格納するためのバッファ配列)です。iMA関数で取得した移動平均線のデータが、この配列に保存されます。配列動的にサイズが決まるため、ここでは単に宣言のみ行われ、具体的なサイズは後に設定されます。

time_buff[]

time_buffは、各バーの時間情報を格納するためのバッファです。この配列には、各バーのタイムスタンプが保存されます。CopyTime関数で取得した時間データがこの配列に格納され、移動平均線の値と共に後でファイルに書き込まれます。

size

sizeは、移動平均線や時間データを格納するバッファのサイズを保持するための変数です。このサイズは、後に計算され、バッファに格納されたデータの個数を示します。

ResetLastError()

ResetLastError関数は、最後に発生したエラーコードをリセットするための関数です。これにより、次の操作でエラーが発生した場合に、正確なエラーコードを取得できるようになります。この関数を使うことで、以前のエラー情報が残らず、新しいエラーが正確に検出されます。

ma_handle = iMA(InpSymbolName, InpSymbolPeriod, InpMAPeriod, InpMAShift, InpMAMethod, InpAppliedPrice)

iMA関数は、指定されたパラメータを基に移動平均線(MA)の計算を行うためのハンドルを取得する関数です。この関数は、以下の引数を取ります:

この関数が成功すると、移動平均線のデータを取得するためのハンドルがma_handleに格納されます。このハンドルを使用して、後ほど移動平均線のデータを取得します。


サンプルコード解説3:OnStart関数その2

  // 指標ハンドルが無効である場合の処理
  if(ma_handle == INVALID_HANDLE)
    {
    //--- 指標ハンドルの取得に失敗したことをエキスパートログに出力
    PrintFormat("Error when receiving indicator handle. Error code = %d", GetLastError());
    return;  // エラーが発生したため処理を終了
    }

  //--- 全ての指標値が計算されるまで一時停止
  while(BarsCalculated(ma_handle) == -1)
    Sleep(20);  // 指標が計算されるまで20ミリ秒の間隔で待機

  // 指定した日付から計算が開始されることをエキスパートログに出力
  PrintFormat("Indicator values starting from %s will be written to the file", TimeToString(InpDateStart));

このセクションでは、OnStart関数の次の部分について解説します。特にエラーチェックや指標データの計算待機、およびログへの出力について詳しく説明します。

ma_handle == INVALID_HANDLE

この部分は、移動平均指標のハンドルが無効であるかどうかを確認するための条件文です。iMA関数で取得した指標ハンドルが無効(INVALID_HANDLE)であった場合、何らかのエラーが発生していることを示します。無効なハンドルが返されると、以降の処理を正常に行うことができないため、このチェックが重要です。

PrintFormat関数(“Error when receiving indicator handle. Error code = %d”, GetLastError関数());

この行では、エラーメッセージをエキスパートログに出力します。PrintFormat関数は、指定されたフォーマットに従ってログメッセージを出力する関数です。ここでは、GetLastError関数によって取得された最新のエラーコードを出力しています。

GetLastError関数

GetLastError関数は、最後に発生したエラーコードを返す関数です。これにより、どのようなエラーが発生したかを把握し、デバッグやエラー処理がしやすくなります。エラーコードは整数値で返され、各エラーには特定のコードが割り当てられています。

return;

この部分では、エラーが発生した場合、処理を中断して関数から抜け出します。これにより、無効なデータを扱わないようにし、スクリプトが予期せぬ動作をするのを防ぎます。

while(BarsCalculated関数(ma_handle) == -1)

この行は、移動平均線の計算が完了するまでスクリプトを待機させるためのループです。BarsCalculated関数を使用して、指定した指標ハンドルの全てのバーの計算が完了したかどうかを確認しています。BarsCalculated関数が-1を返す場合、まだ計算が完了していないことを意味します。

BarsCalculated関数

BarsCalculated関数は、指定された指標ハンドルに対して、計算が完了したバーの数を返す関数です。計算が未完了の場合は-1を返します。指標の計算には時間がかかることがあるため、この関数を使って計算完了を確認することが必要です。

Sleep(20);

計算が完了していない間、スクリプトを20ミリ秒一時停止させます。Sleep関数は、指定した時間だけスクリプトの実行を停止させるために使用します。ここでは20ミリ秒の待機時間を設定しており、計算が完了するまで短い間隔でループを繰り返します。※ミリ秒は1/1000秒です。

PrintFormat(“Indicator values starting from %s will be written to the file”, TimeToString(InpDateStart));

この行では、指定された日付から指標値が計算されることをエキスパートログに出力しています。InpDateStartはユーザーが指定したデータコピーの開始日であり、この日時からデータが取得されます。PrintFormat関数を使用して、TimeToString関数によって変換された日付がログに出力されます。

TimeToString関数

TimeToString関数は、dateTime型の時刻データを文字列形式に変換する関数です。この関数を使うことで、取得した時間データを読みやすい形式に変換し、ログに出力したり、ユーザーに表示したりすることが可能になります。ここでは、InpDateStartの日時を文字列に変換してログに表示しています。


サンプルコード解説4:OnStart関数その3

 //--- 指標値をバッファに複製する
  ResetLastError();  // エラーコードをリセット
  if(CopyBuffer(ma_handle, 0, InpDateStart, date_finish, ma_buff) == -1)
    {
    //--- 指標値のコピーに失敗した場合のエラーメッセージをエキスパートログに出力
    PrintFormat("Failed to copy the indicator values. Error code = %d", GetLastError());
    return;  // 処理を終了
    }

  //--- 適切な時間データをバッファに複製する
  ResetLastError();  // エラーコードをリセット
  if(CopyTime(InpSymbolName, InpSymbolPeriod, InpDateStart, date_finish, time_buff) == -1)
    {
    //--- 時間データのコピーに失敗した場合のエラーメッセージをエキスパートログに出力
    PrintFormat("Failed to copy time values. Error code = %d", GetLastError());
    return;  // 処理を終了
    }

このセクションでは、OnStart関数の指標値と時間データをバッファに複製する部分を解説します。この段階では、取得した指標データと時間データをメモリ上に確保し、後の処理に備えています。さらに、エラー処理についても解説します。

ResetLastError関数();

ResetLastError関数は、最後に発生したエラーコードをリセットします。エラーコードが残っていると、次の処理で正しいエラー検出ができなくなる可能性があるため、各操作の前にリセットを行うことで、正確なエラーチェックを保証します。

if(CopyBuffer(ma_handle, 0, InpDateStart, date_finish, ma_buff) == -1)

この部分では、CopyBuffer関数を使用して、移動平均線(MA)指標の値をバッファ(ma_buff)にコピーします。ma_handleは、iMA関数で取得した移動平均指標のハンドルで、他の引数により指定した期間のデータがコピーされます。

  • ma_handleは、取得した移動平均ハンドルを指定します。
  • 0は、コピーするデータのバッファ番号(ここでは移動平均の値)を指定します。
  • InpDateStartは、データのコピーを開始する日時を指定します。
  • date_finishは、コピーするデータの終了日時です。
  • ma_buffは、コピーされた指標値が格納されるバッファです。

戻り値が-1の場合、データのコピーに失敗したことを示します。この条件を満たすと、エラーメッセージをログに出力し、処理を終了します。

CopyBuffer関数

CopyBuffer関数は、指定された指標データをバッファにコピーするための関数です。ここでは、指定された期間の移動平均指標の値をma_buffに格納します。戻り値が-1の場合はコピーに失敗したことを示し、エラー処理を行う必要があります。

PrintFormat(“Failed to copy the indicator values. Error code = %d”, GetLastError());

この行は、指標データのコピーに失敗した場合に、エラーメッセージをエキスパートログに出力する処理です。PrintFormat関数は、エラーメッセージと共に、GetLastError関数で取得したエラーコードを出力します。これにより、エラーの詳細を確認できます。

if(CopyTime(InpSymbolName, InpSymbolPeriod, InpDateStart, date_finish, time_buff) == -1)

この部分では、CopyTime関数を使用して、指定された期間の時間データをバッファ(time_buff)にコピーします。時間データは各バー(ローソク足)のタイムスタンプであり、移動平均のデータと対応しています。

  • InpSymbolNameは、分析対象の通貨ペアを指定します。
  • InpSymbolPeriodは、使用する時間軸(例:15分足)を指定します。
  • InpDateStartは、データのコピーを開始する日時を指定します。
  • date_finishは、コピーするデータの終了日時です。
  • time_buffは、コピーされた時間データが格納されるバッファです。

戻り値が-1の場合、時間データのコピーに失敗したことを示します。この場合もエラーメッセージをログに出力し、処理を終了します。

CopyTime関数

CopyTime関数は、指定されたシンボルと時間軸におけるバーの時間データをバッファにコピーするための関数です。この関数を使って、移動平均の各値に対応するバーの時間情報が取得され、time_buffに格納されます。戻り値が-1の場合、データのコピーに失敗したことを示します。

PrintFormat(“Failed to copy time values. Error code = %d”, GetLastError());

この行は、時間データのコピーに失敗した場合に、エラーメッセージをエキスパートログに出力する処理です。エラーが発生した際にGetLastError関数で取得したエラーコードを出力し、詳細なエラーメッセージをログに記録します。

サンプルコード解説5:OnStart関数その4

  //--- バッファサイズを取得する
  size = ArraySize(ma_buff);

  //--- 使用した指標ハンドルのメモリを解放する
  IndicatorRelease(ma_handle);

  //--- 指標データを書き込むためにファイルを開く(存在しない場合は自動的に作成)
  ResetLastError();  // エラーコードをリセット
  int file_handle = FileOpen(InpDirectoryName + "//" + InpFileName, FILE_READ | FILE_WRITE | FILE_BIN);

このセクションでは、OnStart関数内でバッファサイズの取得、メモリ解放、ファイルのオープンに関する部分を解説します。

size = ArraySize(ma_buff);

ArraySize関数を使用して、移動平均の値が格納されたバッファ(ma_buff)のサイズを取得します。ArraySize関数は、配列要素数を返します。この数値は、後にファイルに書き込むデータ量を処理するために使用されます。

IndicatorRelease(ma_handle);

IndicatorRelease関数は、使用していた指標ハンドルメモリを解放します。これにより、使用が終わった指標のリソースが解放され、不要なメモリ消費を防ぎます。指標を使い終わった後には必ずこの関数を呼び出すことが推奨されます。

ResetLastError();

ResetLastError関数は、前述したようにエラーコードをリセットします。ファイル操作などの重要な処理を行う前にリセットすることで、正確にエラーを検出できるようにします。

file_handle = FileOpen(InpDirectoryName + “//” + InpFileName, FILE_READ | FILE_WRITE | FILE_BIN);

FileOpen関数を使用して、ファイルを開きます。この場合、ファイルが存在しない場合には自動的に新規作成されます。InpDirectoryNameとInpFileNameの組み合わせにより、指定されたディレクトリとファイル名でファイルが開かれます。ファイルのオープンモードとして、読み込み(FILE_READ)、書き込み(FILE_WRITE)、およびバイナリモード(FILE_BIN)が指定されています。

FileOpen関数

FileOpen関数は、指定されたファイルを開くための関数です。ここでは、ファイルが存在しない場合には新規作成され、存在する場合は既存のファイルにデータを追記または更新するために使用されます。

サンプルコード解説6:OnStart関数その5

  if(file_handle != INVALID_HANDLE)
    {
    // ファイルが正常に開けたことをエキスパートログに出力
    PrintFormat("%s file is available for writing", InpFileName);
    PrintFormat("File path: %s\\Files\\", TerminalInfoString(TERMINAL_DATA_PATH));
    
    //--- 初めにデータサンプルのサイズを書き込む
    FileWriteDouble(file_handle, (double)size);
    
    //--- 指標の時間と値をファイルに書き込む
    for(int i = 0; i < size; i++)
       {
        FileWriteDouble(file_handle, (double)time_buff[i]);  // 時間データを書き込む
        FileWriteDouble(file_handle, ma_buff[i]);            // 移動平均値を書き込む
       }

    //--- ファイルを書き込み完了後に閉じる
    FileClose(file_handle);
    PrintFormat("Data is written, %s file is closed", InpFileName);
    }

このセクションでは、ファイルが正常に開けた後のデータ書き込み処理について解説します。指標データと時間データをファイルに書き込み、その後ファイルを閉じる一連の流れを見ていきます。

if(file_handle != INVALID_HANDLE)

この部分では、FileOpen関数で取得したファイルハンドルが有効かどうかを確認しています。INVALID_HANDLEが返されている場合、ファイルのオープンに失敗していることを意味します。ここでは、file_handleが有効である場合にのみ、ファイルへの書き込み処理を続行します。

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

ファイルが正常に開けたことをエキスパートログに出力しています。PrintFormat関数は、フォーマット付きの文字列を出力する関数です。ここでは、ファイル名(InpFileName)が出力され、ファイルが書き込み可能であることが確認できます。

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

TerminalInfoString関数を使用して、ファイルが保存されるディレクトリのパスをログに出力します。TerminalInfoString関数は、ターミナルに関する情報を文字列形式で取得するための関数で、ここではTERMINAL_DATA_PATHを指定することで、ターミナルのデータディレクトリのパスを取得しています。

FileWriteDouble(file_handle, (double)size);

最初に、データサンプルのサイズ(size)をファイルに書き込んでいます。FileWriteDouble関数を使用して、double型のデータをファイルに書き込みます。ここでは、データのサイズを8バイトで保存します。

for(int i = 0; i < size; i++)

このループでは、移動平均の時間データと値をそれぞれファイルに書き込んでいます。size変数は、バッファに格納されたデータの数を示しており、そのサイズに基づいてループを繰り返します。

FileWriteDouble(file_handle, (double)time_buff[i]);

この行では、time_buff配列に格納された時間データをファイルに書き込んでいます。各バーのタイムスタンプが順番に書き込まれ、データが正しい順序で保存されます。

FileWriteDouble(file_handle, ma_buff[i]);

次に、ma_buff配列に格納された移動平均の値をファイルに書き込みます。この操作も、各バーのタイムスタンプと同様に、データが順序よく書き込まれます。

FileClose(file_handle);

データの書き込みが完了したら、FileClose関数を使用してファイルを閉じます。ファイルを開いた後には必ず閉じる操作を行う必要があり、これによりファイルに対するすべての操作が完了し、データの破損などを防ぎます。

FileClose関数

FileClose関数は、指定されたファイルハンドルに関連付けられたファイルを閉じるための関数です。これにより、ファイルへの書き込みや読み込みが終了し、ファイルは他の操作に備えて解放されます。

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

最後に、ファイルが正常に閉じられたことをエキスパートログに出力します。書き込みが完了したことと、ファイルが閉じられたことが確認できます。

サンプルコード解説7:OnStartその6

このセクションでは、ファイルのオープンに失敗した場合のエラーメッセージ出力に関する部分を解説します。ファイル操作においてエラーが発生した場合、そのエラーを適切に処理することは非常に重要です。

else

この部分は、if文で指定した条件(file_handleがINVALID_HANDLEでない場合)を満たさなかった場合に実行される処理です。具体的には、FileOpen関数がファイルのオープンに失敗し、INVALID_HANDLEが返された場合にこの処理が行われます。

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

ファイルが開けなかった場合、この行でエラーメッセージをエキスパートログに出力します。PrintFormat関数は、指定されたフォーマットに基づいて、エラーメッセージをログに出力します。

この場合、ファイル名(InpFileName)と、GetLastError関数で取得したエラーコードがログに表示され、エラーの原因を特定しやすくなります。


この処理によって、ファイルのオープンに失敗した場合でも、適切なエラーメッセージがログに出力され、後のデバッグや問題解決が容易になります。

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