ArrayFree関数の働き・役割
ArrayFree関数は、動的配列のメモリバッファを解放し、その配列の次元をゼロに設定するために使用されます。この関数は、動的に生成された配列のメモリ管理を明示的に行う場合に役立ちます。この関数を使用することで、不要になった配列のメモリを即座に開放し、システムリソースを効率的に使用することができます。
通常、MQL5の動的配列は自動的にメモリ管理されますが、特にアプリケーションの複雑な環境下でメモリを手動で管理する必要がある場合に、この関数が使用されます。
ArrayFree関数の引数について
void ArrayFree(
void& array[] // 配列
);
ArrayFree関数は、1つの引数を取ります。引数として渡された動的配列のメモリが解放され、次元がゼロに設定されます。
引数構成
この関数は、異なるデータ型の動的配列に対して使用することが可能です。
ArrayFree関数の戻り値について
ArrayFree関数には戻り値がありません。関数が実行されると、指定された動的配列のメモリが解放され、次元がゼロに設定されます。
ArrayFree関数を使う際の注意点
ArrayFree関数を使用する際には、配列のメモリ管理が自動的に行われていることを理解しておくことが重要です。MQL5では、動的配列のメモリは通常、自動的に管理されるため、この関数を使用する必要はあまり多くありません。特に、配列がインジケータやバッファに関わる場合には、メモリ管理がシステムによって行われます。
手動でメモリを解放する必要があるのは、非常に複雑なプログラムや特定の状況でメモリ使用量を最適化する場合です。また、ArrayFree関数を呼び出すと、その配列は再利用する前に必ず新しいメモリを割り当てる必要があります。
配列を解放した後に再び使用しようとすると、予期しないエラーが発生する可能性があるため、ArrayResize関数などで再度メモリを割り当てる処理が必要となります。
ArrayFree関数を使ったサンプルコード
#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)を表示するために使われています。スプレッドは通常小さな整数値として表現されるため、この指定子が適しています。
この部分では、ファイルから読み込んだ相場データを、指定のフォーマットでエキスパートログに出力しています。それぞれのフォーマット指定子は、データの型に応じて適切に使用されており、出力される内容をわかりやすく表示しています。