プログラム実行
スクリプト、サービス、エキスパートアドバイザーはそれぞれ独自のスレッドで実行されます。1 つの銘柄に基づいて計算される全ての指標は、別々のチャートに接続されている場合でも同じスレッドで動作します。従って、1 つの銘柄の指標全てが1 つのスレッドのリソースを共有します。
ティック処理や履歴同期のような他の全てのシンボルに関連するアクションは、一貫して指標と同じスレッドで実行されます。これは、指標で無限のアクションが実行されている場合は、そのシンボルに関連した他のイベントは一切行われないことを意味します。
エキスパートアドバイザーを実行する際には、それが実際の取引環境を持ち、必要な銘柄と期間の履歴にアクセスでき、端末とサーバのデータ同期が出来ることをご確認ください。これら全ての手順の終了に、端末は、エキスパートアドバイザーが使用可能なデータで開始されるまでのわずか 5 秒の開始遅延を提供します。そのため、サーバへの接続がない場合、エキスパートアドバイザーの開始の遅れが発生する可能性があります。
以下の表には、MQL5 プログラムの概要が含まれています。
プログラム |
実行 |
注意事項 |
---|---|---|
サービス |
別のスレッド。サービス用のスレッド数はサービス数に等しいです。 |
反復したサービスの実行は、他のプログラムの実行を妨げることは出来ません。 |
スクリプト |
別々のスレッド。スクリプトのスレッド数は、スクリプトの数に等しいです。 |
反復したスクリプトの実行は、他のプログラムの実行を妨げることは出来ません。 |
エキスパートアドバイザー |
別々のスレッド。エキスパートアドバイザーのスレッド数は、エキスパートアドバイザーの数に等しいです。 |
反復したエキスパートアドバイザーの実行は、他のプログラムの実行を妨げることが出来ません。 |
指標 |
シンボルの全ての指標に 1 つのスレッド。スレッド数は指標とシンボルの数に等しいです。 |
1 つの指標での無限ループはこのシンボルの他の全ての指標を停止します。 |
指標は、プログラムがチャートに装着された直後、グローバル変数が初期化されるとともにクライアント端末のメモリにアップロードされます。クラス型のグローバル変数がコンストラクタを持つ場合、コンストラクタはグローバル変数の初期化中に呼ばれます。
その後プログラムはクライアント端末からのイベントを待機します。MQL5 プログラムには少なくとも 1 つのイベントハンドラがあるべきです。さもないと読み込まれたプログラムが実行されません。イベントハンドラは事前定義された名称、パラメータ、及び戻し型を持っています。
Type |
関数名 |
パラメータ |
アプリケーション |
コメント |
---|---|---|---|---|
int |
なし |
エキスパートアドバイザーと指標 |
Init イベントハンドラ。void 戻り値が使用出来ます。 |
|
void |
const int reason |
エキスパートアドバイザーと指標 |
Deinit イベントハンドラ。 |
|
void |
なし |
スクリプトとサービス |
Start イベントハンドラ。 |
|
int |
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 &TickVolume[], const long &Volume[], const int &Spread[] |
指標 |
全価格のイベントハンドラを計算します。 |
|
int |
const int rates_total, const int prev_calculated, const int begin, const double &price[] |
指標 |
単一データ配列のイベントハンドラを計算します。 指標は 2 つのイベントハンドラを同時に持つことは出来ません。 この場合、唯一のイベントハンドラがデータ配列上で動作します。 |
|
void |
なし |
エキスパートアドバイザー |
NewTick イベントハンドラ。新しいティックの受け取りイベントが処理されている場合、他の同型のイベントは受ケ入れられません。 |
|
void |
なし |
エキスパートアドバイザーと指標 |
Timer イベントハンドラ。 |
|
void |
なし |
エキスパートアドバイザー |
Trade イベントハンドラ。 |
|
double |
なし |
エキスパートアドバイザー |
Tester イベントハンドラ。 |
|
void |
const int id, const long &lparam, const double &dparam, const string &sparam |
エキスパートアドバイザーと指標 |
ChartEvent イベントハンドラ。 |
|
void |
const string &symbol_name |
エキスパートアドバイザーと指標 |
BookEvent イベントハンドラ。 |
クライアント端末は、対応するオープンチャートに新しいイベントを送信します。イベントはチャート(チャートイベント)または MQL5 プログラム(カスタムイベント)によっても生成出来ます。チャート上のグラフィカルオブジェクトの作成または削除のイベントの生成は CHART_EVENT_OBJECT_CREATE 及び CHART_EVENT_OBJECT_DELETE チャートプロパティによって有効または無効に出来ます。それぞれの MQL5 プログラムとチャートは、全ての新しい受信イベントが追加される独自のイベントキューを持っています。
プログラムは、それが動作しているチャートからのイベントのみを受け取ります。全てのイベントは、受信された順に次々に処理されます。キューにすでに NewTick イベントがある場合、またはこのイベントが現在処理中の場合、新しい NewTick イベントは MQL5 プログラムのキューには追加されません。似たように ChartEvent がすでにキューに存在する場合、またはこのイベントが現在処理中の場合、同じ型のイベントはキューには追加されません。timer イベントも同じように扱われ、Timer イベントがキューに存在するか処理中の場合、新しい timer イベントはキューに追加されません。
イベントキューは限られてはいますが充分な大きさを持っています。よく書かれたプログラムでのキューのオーバーフローは起こりにくいです。オーバーフローの場合、新しいイベントはキューに追加されずに廃棄されます。
無限ループを使用してのイベント処理は推奨されません。例外は単一のStartイベントを処理するスクリプトとサービスです。
ライブラリはイベントを処理しません。
指標及びエキスパートアドバイザーで使用出来ない関数
指標、スクリプトとエキスパートアドバイザーは MQL5 で書かれた実行可能なプログラムです。これらは、タスクの種類ごとに設計されています。従って、プログラムの種類によって関数の使用に制限が見られます。下記の関数は指標では使用出来ません。
- OrderCalcMargin()
- OrderCalcProfit()
- OrderCheck()
- OrderSend()
- SendFTP()
- Sleep()
- ExpertRemove()
- MessageBox()
指標用に設計された関数の全ては、エキスパートアドバイザーやスクリプトでは使用出来ません。
- SetIndexBuffer()
- IndicatorSetDouble()
- IndicatorSetInteger()
- IndicatorSetString()
- PlotIndexSetDouble()
- PlotIndexSetInteger()
- PlotIndexSetString()
- PlotIndexGetInteger
ライブラリは独立したプログラムではなく、それを呼び出した MQL5 プログラム(スクリプト、指標またはエキスパートアドバイザー)のコンテキストで実行されます。従って、上記の制限は呼ばれたライブラリにも適用されます。
サービスで使用できない関数
チャートにバインドされていないため、サービスはイベントを受け入れません。以下の関数はサービス内で禁止されています。
指標のロードとアンロード
指標は、次の場合に読み込まれます。
- 指標のチャートへの接続
- 端末の開始(指標が端末のシャットダウン前にチャートに接続された場合)
- テンプレートの読み込み(チャートに接続されている指標がテンプレートで指定されている場合)
- プロファイルの変更(指標がプロファイルチャートに接続されている場合)
- 指標が接続されたチャートのシンボル及び/または時間軸の変更
- 指標の再コンパイルの成功(指標がチャートに接続されている場合)
- 端末が接続された口座への接続
- 指標の入力パラメータの変更
指標は、次のような場合にアンロードされます。
- 指標のチャートからの取り外し
- 端末のシャットダウン(指標がチャートに接続されている場合)
- テンプレートの読み込み(チャートに接続されている指標がテンプレートで指定されている場合)
- 指標が接続されたチャートの閉鎖
- プロファイルの変更(指標がプロファイルチャートに接続されている場合)
- 端末が接続された口座への接続
- 指標が接続されたチャートのシンボル及び/または時間軸の変更
- 指標の入力パラメータの変更
エキスパートアドバイザーのロードとアンロード
エキスパートアドバイザーは、次の場合に読み込まれます。
- エキスパートアドバイザーのチャートへの接続
- 端末の開始(エキスパートアドバイザーが端末のシャットダウン前にチャートに接続された場合)
- テンプレートの読み込み(チャートに接続されているエキスパートアドバイザーがテンプレートで指定されている場合)
- プロファイルの変更(エキスパートアドバイザーがプロファイルチャートに接続されている場合)
- 口座への接続(口座番号が同一の場合も含む、エキスパートアドバイザーがサーバ上の端末の許可前にチャートに接続された場合)
エキスパートアドバイザーは、次の場合にアンロードされます。
- エキスパートアドバイザーのチャートからの取り外し
- 新しいエキスパートアドバイザーのチャートへの接続(他のエキスパートアドバイザーが既に接続されている場合、このエキスパートアドバイザーはアンロードされます)
- 端末のシャットダウン(エキスパートアドバイザーがチャートに接続されている場合)
- テンプレートの読み込み(チャートに接続されているエキスパートアドバイザーがテンプレートで指定されている場合)
- 指標が接続されたチャートの閉鎖
- プロファイルの変更(エキスパートアドバイザーがプロファイルチャートに接続されている場合)
- 端末が接続された口座への接続(エキスパートアドバイザーがサーバ上の端末の許可前にチャートに接続された場合)
- ExpertRemove() 関数の呼び出し
エキスパートアドバイザーが接続されているチャートのシンボルや時間軸が変更した場合、エキスパートアドバイザーはロードやアンロードされません。この場合、クライアント端末が古い銘柄/時間軸で OnDeinit() ハンドラを呼び、新しい銘柄/時間軸が存在する場合はその値で OnInit() を呼びます。グローバル変数及び静的変数の値はリセットされません。初期化の前にエキスパートアドバイザーのために受信された全てのイベントは完了します(OnInit() 関数は抜かされます)。
スクリプトのロードとアンロード
スクリプトは、チャートへの取り付けの直後に読み込みられ、操作を完了した直後にアンロードされます。OnInit() 及び OnDeinit() はスクリプトでは呼ばれません。
クライアント端末はプログラムアンロード(チャートからの削除)時にグローバル変数の初期化解除を行い、イベントキューを削除します。この場合、初期化解除とは、全ての string 型変数のリセット、動的配列オブジェクトの 割り当て解除、及び存在する場合はデストラクタの呼び出しです。
サービスのロードとアンロード
ターミナルのシャットダウン時にサービスが起動された場合は、ターミナルの起動直後にサービスがロードされます。サービスは、作業が完了した直後にアンロードされます。
サービスには単一のOnStart()ハンドラがあります。このハンドラでは、ネットワーク機能を使用してカスタム銘柄を作成および更新するなど、無限のデータ受信および処理ループを実装できます。
エキスパートアドバイザー、指標、スクリプトとは異なり、サービスは特定のチャートに縛られていないため、それらを起動するための別のメカニズムが提供されています。[サービスの追加]コマンドを使用して、新しいサービスインスタンスをナビゲータに作成します。適切なインスタンスメニューを使用して、サービスインスタンスを起動、停止、削除できます。すべてのインスタンスを管理するには、サービスメニューを使用します。
エキスパートアドバイザー操作をより良く理解するために、以下のエキスパートアドバイザーのコードをコンパイルし、ロード/アンロード、テンプレートの変更、シンボルの変更、時間軸の変更などのアクションを実行することをお勧めします。
例:
//+------------------------------------------------------------------+
|
参照