FileLoad関数の働き・役割
FileLoad関数は、指定されたバイナリファイルからデータを読み取り、数値型または単純な構造体型の配列に直接格納するために使用されます。この関数を使用することで、既存のファイルから効率的にデータを読み込むことができます。ファイルに格納されたデータが、予め知られている型である場合、FileLoad関数を使うことで、そのデータを適切な配列に格納し、容易にアクセスできる状態にします。
例えば、あるチャートの価格データをバイナリ形式で保存しているファイルがあるとき、そのファイルをFileLoad関数を使って簡単に読み込むことができます。この関数は、ファイル内のデータサイズと配列の要素サイズに基づいて、読み込むデータ量を自動的に調整します。データが数値型や単純な構造体型である限り、FileLoad関数を使用してそのデータを適切な配列に格納し、後の処理に活用することが可能です。
FileLoad関数の引数について
long FileLoad(
const string file_name, // ファイル名
void& buffer[], // 数値型または単純な構造体型の配列
int common_flag=0 // ファイルフラグ、デフォルトでは <data_folder>\MQL5\Files\ で検索される
);
FileLoad関数は、ファイルから数値型または単純な構造体型のデータを読み込み、それを配列に格納するための3つの引数を取ります。
第1引数: file_name
- 種類: 文字列型
- 説明: 読み込むファイルの名前を指定します。このファイルには、数値型または構造体型のデータが含まれている必要があります。file_nameには相対パスまたは絶対パスを指定できますが、特にcommon_flagがデフォルト(0)の場合、ファイルはデフォルトで\MQL5\Files\内にあるものとして扱われます。
第2引数: buffer[]
- 種類: 参照型
- 説明: 読み込まれたデータが格納される配列です。この配列には数値型や単純な構造体型が含まれる必要があります。たとえば、MqlRatesのような構造体や、int型、double型のような数値型の配列が利用されます。この配列は事前に準備されており、FileLoad関数が呼び出されると、ファイルからデータが読み込まれて格納されます。
第3引数: common_flag
- 種類: 整数型
- 説明: ファイルの操作モードを指定するフラグです。このフラグが指定されない場合、デフォルト値の0が使用されます。この場合、ファイルは通常\MQL5\Files\フォルダ内で検索されます。指定するフラグによっては、ファイルの検索場所が変わったり、読み取り方法が変更されたりします。たとえば、FILE_COMMONフラグを指定すると、他のプログラムと共有できるファイルが格納されているフォルダからファイルが検索されます。
FileLoad関数の戻り値について
FileLoad関数の戻り値は、正常に読み取った要素数を表す整数値です。読み込まれたデータの要素数が戻り値として返されます。
具体的には、以下のように動作します。
- ファイルから読み込んだデータが配列に格納された場合、その配列に格納された要素の数を返します。たとえば、ファイル内に10個のdouble型データがあり、それらが配列に読み込まれた場合、戻り値として10が返されます。
- ファイルサイズが配列の要素サイズに満たない場合、読み込めるだけのデータが格納され、その数が返されます。たとえば、ファイルサイズが10バイトで、配列がdouble型(1要素が8バイト)の場合、戻り値は1となります。
- エラーが発生した場合、戻り値は-1となります。この場合、読み込み処理が失敗しているため、GetLastError関数を使用して詳細なエラーコードを確認する必要があります。
戻り値が正の値であれば、ファイルの読み込みが成功したことを示し、データが配列に格納されていますが、-1が返された場合は、ファイルパスの間違いやファイルの存在有無などのエラーが考えられます。
FileLoad関数を使ったサンプルコード
#property script_show_inputs
//--- 入力パラメータの定義
input int bars_to_save=10; // 保存するバー数(ローソク足の数)を指定
//+------------------------------------------------------------------+
//| スクリプトプログラムを開始する関数(スクリプトのエントリーポイント) |
//+------------------------------------------------------------------+
void OnStart()
{
//--- 保存するファイル名をシンボル名に基づいて設定
string filename=_Symbol+"_rates.bin";
//--- 相場データを格納するための配列を定義(MqlRates型の配列)
MqlRates rates[];
//--- シンボル(_Symbol)と期間(_Period)の指定で、指定したバー数(bars_to_save)のデータをコピー
int copied=CopyRates(_Symbol,_Period,0,bars_to_save,rates);
//--- データが正しくコピーされたかを確認
if(copied!=-1)
{
//--- コピーされたバー数をログに出力
PrintFormat(" CopyRates(%s) copied %d bars",_Symbol,copied);
//--- コピーした相場データをファイルに保存(保存が成功したか確認)
if(!FileSave(filename,rates,FILE_COMMON))
//--- 保存が失敗した場合、エラーコードを取得してログに出力
PrintFormat("FileSave() failed, error=%d",GetLastError());
}
else
//--- データコピーに失敗した場合、エラーコードをログに出力
PrintFormat("Failed CopyRates(%s), error=",_Symbol,GetLastError());
//--- rates配列のメモリを解放(データの再利用のためにクリア)
ArrayFree(rates);
//--- 保存したファイルから相場データを再び読み込み
long count=FileLoad(filename,rates,FILE_COMMON);
//--- 読み込みが成功したか確認(countが-1でないことをチェック)
if(count!=-1)
{
//--- 読み込んだデータのヘッダーをログに出力
Print("Time\tOpen\tHigh\tLow\tClose\tTick Voulme\tSpread\tReal Volume");
//--- 読み込んだ全てのデータをループでログに出力
for(int i=0;i<count;i++)
{
//--- 各バーの時刻、始値、高値、安値、終値、ティックボリューム、スプレッド、実ボリュームをフォーマットして出力
PrintFormat("%s\t%G\t%G\t%G\t%G\t%I64u\t%d\t%I64u",
TimeToString(rates[i].time,TIME_DATE|TIME_SECONDS), // 日時をフォーマットして出力
rates[i].open, // 始値
rates[i].high, // 高値
rates[i].low, // 安値
rates[i].close, // 終値
rates[i].tick_volume, // ティックボリューム
rates[i].spread, // スプレッド
rates[i].real_volume); // 実際のボリューム
}
}
}
サンプルコード解説1: グローバル領域部分
#property script_show_inputs
//--- 入力パラメータの定義
input int bars_to_save=10; // 保存するバー数(ローソク足の数)を指定
このセクションでは、スクリプトのグローバル領域にあるコード部分について解説します。この部分は、スクリプト全体で使用する設定やパラメータの宣言が行われており、スクリプトが実行される際に、最初に参照される重要なセクションです。
#property script_show_inputs
この行は、スクリプトの設定オプションの一つで、入力パラメータを表示するためのプロパティを指定しています。これにより、スクリプトが実行される前に、トレーダーがGUI(グラフィカルユーザーインターフェース)で入力パラメータを指定できるようになります。具体的には、スクリプトのパラメータを直接入力したり変更したりする際に、MetaTraderのユーザーインターフェース上でわかりやすく入力画面が表示されます。
input int bars_to_save=10
inputキーワードは、スクリプトの実行時にユーザーが変更可能な変数を定義するために使用されます。この例では、bars_to_saveという整数型の変数が宣言されています。この変数は、ユーザーが保存したいバー(ローソク足)の数を指定するためのものです。
この設定により、ユーザーはスクリプトの実行時に保存するバー数を簡単に調整できます。たとえば、デフォルトの値である10のままにするか、任意の数に変更することが可能です。
サンプルコード解説2: OnStart関数部分その1
//+------------------------------------------------------------------+
//| スクリプトプログラムを開始する関数(スクリプトのエントリーポイント) |
//+------------------------------------------------------------------+
void OnStart()
{
//--- 保存するファイル名をシンボル名に基づいて設定
string filename=_Symbol+"_rates.bin";
//--- 相場データを格納するための配列を定義(MqlRates型の配列)
MqlRates rates[];
//--- シンボル(_Symbol)と期間(_Period)の指定で、指定したバー数(bars_to_save)のデータをコピー
int copied=CopyRates(_Symbol,_Period,0,bars_to_save,rates);
このセクションでは、スクリプトが実行される際に最初に呼び出されるOnStart関数について解説します。OnStart関数は、スクリプトが実行されるたびに一度だけ実行されるエントリーポイントであり、ここに記述されたコードが実際の処理を行います。
関数の始まり: void OnStart()
この行は、OnStart関数が定義されている部分です。voidは、この関数が戻り値を持たないことを示しており、スクリプトが開始されたときにこの関数が自動的に実行されます。MetaTraderのスクリプトは通常この関数内で動作のロジックを定義します。
保存するファイル名の設定
ここでは、シンボル名(取引対象の銘柄)に基づいてファイル名を設定しています。シンボル名は、現在アクティブなチャートのシンボル名を表しており、このシンボル名に「_rates.bin」という接尾辞を付けることで、データを保存するためのファイル名を動的に生成しています。
相場データを格納するための配列を定義
ここでは、相場データを格納するためのMqlRates構造体型の配列を宣言しています。MqlRates構造体は、時間、始値、高値、安値、終値などの価格データを含む構造体です。この配列に、後ほどチャートのローソク足データが格納されます。
データのコピー
ここでは、CopyRates関数を使用して、指定されたシンボルと期間の相場データをコピーしています。この関数は、指定したバー数だけの価格データを取得し、それを配列に格納します。引数として、シンボル名、期間、開始位置(0は最新のバー)、そしてコピーするバー数を指定します。
コピーに成功したバーの数は、変数に格納されます。
サンプルコード解説3: OnStart関数部分その2
//--- データが正しくコピーされたかを確認
if(copied!=-1)
{
//--- コピーされたバー数をログに出力
PrintFormat(" CopyRates(%s) copied %d bars",_Symbol,copied);
//--- コピーした相場データをファイルに保存(保存が成功したか確認)
if(!FileSave(filename,rates,FILE_COMMON))
//--- 保存が失敗した場合、エラーコードを取得してログに出力
PrintFormat("FileSave() failed, error=%d",GetLastError());
}
このセクションでは、OnStart関数の中で、相場データが正しくコピーされたかどうかの確認や、そのデータをファイルに保存する処理について解説します。
データが正しくコピーされたかの確認
相場データのコピーが成功したかどうかを確認するために、if文を使って、copied変数の値をチェックしています。copiedが-1でない場合、データのコピーが成功していることを意味します。
コピーに失敗した場合には、copiedが-1を返すため、この条件文によって成功・失敗を判定しています。
コピーされたバー数をログに出力
次に、データが正しくコピーされた場合、PrintFormat関数を使用して、コピーされたバー数をエキスパートログに出力します。ここでは、シンボル名(_Symbol)とコピーされたバー数がログに記録されます。これは、ユーザーがコピーが成功したことを確認できるようにするためです。
相場データをファイルに保存
コピーされたデータをファイルに保存するために、FileSave関数が使用されています。この関数は、filenameで指定されたファイルに、先ほど取得した相場データを保存します。保存先は、filenameで指定されたファイル名です。
保存が成功すると、次の処理に進みますが、もし保存に失敗した場合、if文でその失敗が検出され、エラー処理が行われます。
エラー処理
もしFileSave関数が失敗した場合、PrintFormat関数を使って、エラーコードがエキスパートログに出力されます。エラーコードはGetLastError関数を使用して取得され、これによりユーザーは何が原因で保存に失敗したかを確認できます。
このように、データのコピーが成功したかどうかの確認と、ファイルへの保存処理、そしてエラー時の処理を適切に行うことで、スクリプトの信頼性が確保されています。
サンプルコード解説4: OnStart関数部分その3
else
//--- データコピーに失敗した場合、エラーコードをログに出力
PrintFormat("Failed CopyRates(%s), error=",_Symbol,GetLastError());
//--- rates配列のメモリを解放(データの再利用のためにクリア)
ArrayFree(rates);
//--- 保存したファイルから相場データを再び読み込み
long count=FileLoad(filename,rates,FILE_COMMON);
このセクションでは、OnStart関数の中で、データコピーが失敗した際のエラーハンドリングや、配列のメモリ解放、ファイルからデータを再読み込みする処理について解説します。
データコピーに失敗した場合のエラーハンドリング
if文で相場データのコピーに失敗した場合、elseブロックが実行されます。このブロックでは、PrintFormat関数を使用して、エラーメッセージとエラーコードをエキスパートログに出力しています。GetLastError関数によって、直前のエラーコードが取得され、問題が発生した理由を確認できるようになっています。
このエラーハンドリングにより、データが正しくコピーできなかった場合でも、その理由をログに記録してトラブルシューティングを容易にしています。
rates配列のメモリ解放
次に、ArrayFree関数を使用して、rates配列のメモリを解放しています。これは、配列を再利用するために重要なステップです。配列に格納されたデータが不要になった場合や、新しいデータを読み込む前に、配列のメモリを解放しておくことで、メモリの効率的な使用が可能になります。
保存したファイルから相場データを再読み込み
次に、FileLoad関数を使用して、先ほど保存したファイルから相場データを再び読み込みます。filenameで指定されたファイルから、rates配列にデータが読み込まれます。FILE_COMMONフラグを指定しているため、共通のファイルフォルダからデータが検索され、適切に配列に格納されます。
このステップでは、ファイルに保存されたデータが再度読み込まれ、rates配列に格納されることにより、データの再利用や後続の処理が可能となります。
サンプルコード解説5: OnStart関数部分その4
//--- 読み込みが成功したか確認(countが-1でないことをチェック)
if(count!=-1)
{
//--- 読み込んだデータのヘッダーをログに出力
Print("Time\tOpen\tHigh\tLow\tClose\tTick Voulme\tSpread\tReal Volume");
//--- 読み込んだ全てのデータをループでログに出力
for(int i=0;i<count;i++)
{
//--- 各バーの時刻、始値、高値、安値、終値、ティックボリューム、スプレッド、実ボリュームをフォーマットして出力
PrintFormat("%s\t%G\t%G\t%G\t%G\t%I64u\t%d\t%I64u",
TimeToString(rates[i].time,TIME_DATE|TIME_SECONDS), // 日時をフォーマットして出力
rates[i].open, // 始値
rates[i].high, // 高値
rates[i].low, // 安値
rates[i].close, // 終値
rates[i].tick_volume, // ティックボリューム
rates[i].spread, // スプレッド
rates[i].real_volume); // 実際のボリューム
}
}
}
このセクションでは、ファイルから読み込んだ相場データを確認し、そのデータをログに出力する処理について解説します。また、PrintFormat関数で使用されているフォーマット指定子についても、初心者向けに詳しく説明します。
読み込み結果の確認
まず、FileLoad関数によって読み込まれたデータが正しく取得されたかどうかを確認しています。count変数が-1でない場合、データの読み込みが成功していることを意味します。成功した場合のみ、次の処理に進み、読み込んだデータをログに出力します。
データのヘッダーを出力
データが正常に読み込まれたら、最初にログにヘッダー行を出力します。このヘッダーには、タイムスタンプ(Time)、始値(Open)、高値(High)、安値(Low)、終値(Close)、ティックボリューム、スプレッド、実ボリュームが表示されます。
データをループで出力
次に、読み込んだデータ全てをループで処理し、各バーの情報をログに出力します。PrintFormat関数を使用して、各バーのデータが指定のフォーマットで出力されます。
フォーマット指定子の解説
PrintFormat関数内で使用されているフォーマット指定子は、表示するデータの型やフォーマットを指定するためのものです。以下に、それぞれの指定子について説明します。
- %s:文字列型を表示します。この場合、TimeToString関数によって変換された日時を文字列として出力しています。日時は、TIME_DATE | TIME_SECONDSフラグにより、日付と秒単位の時刻が表示されます。
- %G: 浮動小数点数を出力します。始値(open)、高値(high)、安値(low)、終値(close)の値はすべて浮動小数点数で表されるため、この指定子を使っています。%Gは、一般的に最適な形式で浮動小数点数を表示します(少数点以下の桁数が多い場合には指数表記にもなります)。
- %I64u: 64ビットの符号なし整数を出力します。この指定子は、ティックボリューム(tick_volume)や実ボリューム(real_volume)など、大きな整数値を表示する際に使用されています。I64は64ビット整数を示し、uは符号なし(unsigned)を表します。
- %d: 整数型を出力します。ここでは、スプレッド(spread)を表示するために使われています。スプレッドは通常小さな整数値として表現されるため、この指定子が適しています。
この部分では、ファイルから読み込んだ相場データを、指定のフォーマットでエキスパートログに出力しています。それぞれのフォーマット指定子は、データの型に応じて適切に使用されており、出力される内容をわかりやすく表示しています。