MQL5 プログラム

プログラム実行

スクリプト、サービス、エキスパートアドバイザーはそれぞれ独自のスレッドで実行されます。1 つの銘柄に基づいて計算される全ての指標は、別々のチャートに接続されている場合でも同じスレッドで動作します。従って、1 つの銘柄の指標全てが1 つのスレッドのリソースを共有します。

ティック処理や履歴同期のような他の全てのシンボルに関連するアクションは、一貫して指標と同じスレッドで実行されます。これは、指標で無限のアクションが実行されている場合は、そのシンボルに関連した他のイベントは一切行われないことを意味します。

エキスパートアドバイザーを実行する際には、それが実際の取引環境を持ち、必要な銘柄と期間の履歴にアクセスでき、端末とサーバのデータ同期が出来ることをご確認ください。これら全ての手順の終了に、端末は、エキスパートアドバイザーが使用可能なデータで開始されるまでのわずか 5 秒の開始遅延を提供します。そのため、サーバへの接続がない場合、エキスパートアドバイザーの開始の遅れが発生する可能性があります。

以下の表には、MQL5 プログラムの概要が含まれています。

プログラム

実行

注意事項

サービス

別のスレッド。サービス用のスレッド数はサービス数に等しいです。

反復したサービスの実行は、他のプログラムの実行を妨げることは出来ません。

スクリプト

別々のスレッド。スクリプトのスレッド数は、スクリプトの数に等しいです。

反復したスクリプトの実行は、他のプログラムの実行を妨げることは出来ません。

エキスパートアドバイザー

別々のスレッド。エキスパートアドバイザーのスレッド数は、エキスパートアドバイザーの数に等しいです。

反復したエキスパートアドバイザーの実行は、他のプログラムの実行を妨げることが出来ません。

指標

シンボルの全ての指標に 1 つのスレッド。スレッド数は指標とシンボルの数に等しいです。

1 つの指標での無限ループはこのシンボルの他の全ての指標を停止します。

指標は、プログラムがチャートに装着された直後、グローバル変数が初期化されるとともにクライアント端末のメモリにアップロードされます。クラス型のグローバル変数がコンストラクタを持つ場合、コンストラクタはグローバル変数の初期化中に呼ばれます。

その後プログラムはクライアント端末からのイベントを待機します。MQL5 プログラムには少なくとも 1 つのイベントハンドラがあるべきです。さもないと読み込まれたプログラムが実行されません。イベントハンドラは事前定義された名称、パラメータ、及び戻し型を持っています。

Type

関数名

パラメータ

アプリケーション

コメント

int

OnInit

なし

エキスパートアドバイザーと指標

Init イベントハンドラ。void 戻り値が使用出来ます。

void

OnDeinit

const int reason

エキスパートアドバイザーと指標

Deinit イベントハンドラ。

void

OnStart

なし

スクリプトとサービス

Start イベントハンドラ。

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 &TickVolume[],

const long &Volume[],

const int &Spread[]

指標

全価格のイベントハンドラを計算します。

int

OnCalculate

const int rates_total,

const int prev_calculated,

const int begin,

const double &price[]

指標

単一データ配列のイベントハンドラを計算します。

指標は 2 つのイベントハンドラを同時に持つことは出来ません。

この場合、唯一のイベントハンドラがデータ配列上で動作します。

void

OnTick

なし

エキスパートアドバイザー

NewTick イベントハンドラ。新しいティックの受け取りイベントが処理されている場合、他の同型のイベントは受ケ入れられません。

void

OnTimer

なし

エキスパートアドバイザーと指標

Timer イベントハンドラ。

void

OnTrade

なし

エキスパートアドバイザー

Trade イベントハンドラ。

double

OnTester

なし

エキスパートアドバイザー

Tester イベントハンドラ。

void

OnChartEvent

const int id,

const long &lparam,

const double &dparam,

const string &sparam

エキスパートアドバイザーと指標

ChartEvent イベントハンドラ。

void

OnBookEvent

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();

EventSetMillisecondTimer();

EventSetTimer();

EventKillTimer();

SetIndexBuffer();

IndicatorSetDouble();

IndicatorSetInteger();

IndicatorSetString();

PlotIndexSetDouble();

PlotIndexSetInteger();

PlotIndexSetString();

PlotIndexGetInteger();

 

指標のロードとアンロード

指標は、次の場合に読み込まれます。

  • 指標のチャートへの接続
  • 端末の開始(指標が端末のシャットダウン前にチャートに接続された場合)
  • テンプレートの読み込み(チャートに接続されている指標がテンプレートで指定されている場合)
  • プロファイルの変更(指標がプロファイルチャートに接続されている場合)
  • 指標が接続されたチャートのシンボル及び/または時間軸の変更
  • 指標の再コンパイルの成功(指標がチャートに接続されている場合)
  • 端末が接続された口座への接続
  • 指標の入力パラメータの変更

 

指標は、次のような場合にアンロードされます。

  • 指標のチャートからの取り外し
  • 端末のシャットダウン(指標がチャートに接続されている場合)
  • テンプレートの読み込み(チャートに接続されている指標がテンプレートで指定されている場合)
  • 指標が接続されたチャートの閉鎖
  • プロファイルの変更(指標がプロファイルチャートに接続されている場合)
  • 端末が接続された口座への接続
  • 指標が接続されたチャートのシンボル及び/または時間軸の変更
  • 指標の入力パラメータの変更

 

エキスパートアドバイザーのロードとアンロード

エキスパートアドバイザーは、次の場合に読み込まれます。

  • エキスパートアドバイザーのチャートへの接続
  • 端末の開始(エキスパートアドバイザーが端末のシャットダウン前にチャートに接続された場合)
  • テンプレートの読み込み(チャートに接続されているエキスパートアドバイザーがテンプレートで指定されている場合)
  • プロファイルの変更(エキスパートアドバイザーがプロファイルチャートに接続されている場合)
  • 口座への接続(口座番号が同一の場合も含む、エキスパートアドバイザーがサーバ上の端末の許可前にチャートに接続された場合)
     

エキスパートアドバイザーは、次の場合にアンロードされます。

  • エキスパートアドバイザーのチャートからの取り外し
  • 新しいエキスパートアドバイザーのチャートへの接続(他のエキスパートアドバイザーが既に接続されている場合、このエキスパートアドバイザーはアンロードされます)
  • 端末のシャットダウン(エキスパートアドバイザーがチャートに接続されている場合)
  • テンプレートの読み込み(チャートに接続されているエキスパートアドバイザーがテンプレートで指定されている場合)
  • 指標が接続されたチャートの閉鎖
  • プロファイルの変更(エキスパートアドバイザーがプロファイルチャートに接続されている場合)
  • 端末が接続された口座への接続(エキスパートアドバイザーがサーバ上の端末の許可前にチャートに接続された場合)
  • ExpertRemove() 関数の呼び出し

エキスパートアドバイザーが接続されているチャートのシンボルや時間軸が変更した場合、エキスパートアドバイザーはロードやアンロードされません。この場合、クライアント端末が古い銘柄/時間軸で OnDeinit() ハンドラを呼び、新しい銘柄/時間軸が存在する場合はその値で OnInit() を呼びます。グローバル変数及び静的変数の値はリセットされません。初期化の前にエキスパートアドバイザーのために受信された全てのイベントは完了します(OnInit() 関数は抜かされます)。

 

スクリプトのロードとアンロード

スクリプトは、チャートへの取り付けの直後に読み込みられ、操作を完了した直後にアンロードされます。OnInit() 及び OnDeinit() はスクリプトでは呼ばれません。

クライアント端末はプログラムアンロード(チャートからの削除)時にグローバル変数の初期化解除を行い、イベントキューを削除します。この場合、初期化解除とは、全ての string 型変数のリセット、動的配列オブジェクトの 割り当て解除、及び存在する場合はデストラクタの呼び出しです。

 

サービスのロードとアンロード

ターミナルのシャットダウン時にサービスが起動された場合は、ターミナルの起動直後にサービスがロードされます。サービスは、作業が完了した直後にアンロードされます。

サービスには単一のOnStart()ハンドラがあります。このハンドラでは、ネットワーク機能を使用してカスタム銘柄を作成および更新するなど、無限のデータ受信および処理ループを実装できます。

エキスパートアドバイザー、指標、スクリプトとは異なり、サービスは特定のチャートに縛られていないため、それらを起動するための別のメカニズムが提供されています。[サービスの追加]コマンドを使用して、新しいサービスインスタンスをナビゲータに作成します。適切なインスタンスメニューを使用して、サービスインスタンスを起動、停止、削除できます。すべてのインスタンスを管理するには、サービスメニューを使用します。

 

エキスパートアドバイザー操作をより良く理解するために、以下のエキスパートアドバイザーのコードをコンパイルし、ロード/アンロード、テンプレートの変更、シンボルの変更、時間軸の変更などのアクションを実行することをお勧めします。

例:

//+——————————————————————+
//|                                                   TestExpert.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                             https://www.MQL5.com |
//+——————————————————————+
#property copyright “2009, MetaQuotes Software Corp.”
#property link     “https://www.mql5.com”
#property version   “1.00”

class CTestClass
{
public:
CTestClass() { Print(“CTestClass constructor”); }
~CTestClass() { Print(“CTestClass destructor”); }
};
CTestClass global;
//+——————————————————————+
//| エキスパート初期化に使用される関数                                        |
//+——————————————————————+
int OnInit()
{
//—
Print(“Initialization”);
//—
return(INIT_SUCCEEDED);
}
//+——————————————————————+
//| エキスパート初期化解除に使用される関数                                    |
//+——————————————————————+
void OnDeinit(const int reason)
{
//—
Print(“Deinitialization with reason”,reason);
}
//+——————————————————————+
//| エキスパートティック関数                                                 |
//+——————————————————————+
void OnTick()
{
//—

}
//+——————————————————————+

参照

クライアント端末イベント、イベントハンドラ

取引許可

取引の自動化

MQL5 言語は自動売買システムの開発に意図された取引関数 を提供します。人間の介入なしの自動売買のために開発されたプログラムは「エキスパートアドバイザー(EA)」または「取引ロボット」と呼ばれます。MetaEditor でエキスパートアドバイザーを作成するには MQL5 Wizard を起動し、次の 2 つの選択肢の 1 つを選択します。

  • Expert Advisor (template) – 既製のイベント処理の関数を持ち、プログラミングによって必要な関数を全て補足出来る、テンプレートを作成することが出来ます。
  • Expert Advisor (generate) – 単に売買シグナルモジュール、資金管理モジュールとトレイリングストップモジュールなどの必要なモジュールを選択して本格的な取引ロボット開発 が出来ます。

MQL5_Wizard

取引関数はエキスパートアドバイザーと指標のみで動作出来ます。指標では取引が出来ません。

自動売買実行のための権限の確認

人間の介入なしで作業する信頼性のあるエキスパートアドバイザーを開発するためには、いくつかの重要なチェックが必要がです。まず、取引が許可されているかどうかをプログラム的にチェックする必要があります。これは、自動化システムを開発する際に不可欠である基本的なチェックです。

端末で自動売買が許可されているかどうかのチェック

端末の設定が全てのプログラムの自動売買を許可または禁止する機能を提供します。

TERMINAL_TRADE_ALLOWED

自動売買オプションは端末の標準パネルで切り替えることが出来ます。

  • AutoTrading_enabled– 自動売買が有効。起動したアプリケーションでの取引関数の使用が許可されています。
  • AutoTrading_disabled – 自動売買が無効。実行されたアプリケーションは取引関数を実行することが出来ません。

チェックの例

if (!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
  Alert(“Check if automated trading is allowed in the terminal settings!”);

実行中のエキスパートアドバイザーまたはスクリプトで売買が許可されているかのチェック

特定のプログラムの自動売買を起動時に許可または禁止することが出来ます。これを行うには、プログラムのプロパティでの特殊なチェックボックスを使用します。

MQL_TRADE_ALLOWED

チェックの例

  if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
Alert(“Check if automated trading is allowed in the terminal settings!”);
else
{
if(!MQLInfoInteger(MQL_TRADE_ALLOWED))
Alert(“Automated trading is forbidden in the program settings for “,__FILE__);
}

実行中のエキスパートアドバイザーまたはスクリプトで現在の口座での売買が許可されているかのチェック

自動売買はサーバ側で無効に出来ます。チェックの例

  if(!AccountInfoInteger(ACCOUNT_TRADE_EXPERT))
Alert(“Automated trading is forbidden for the account “,AccountInfoInteger(ACCOUNT_LOGIN),
     ” at the trade server side”);

自動売買が取引口座で無効にされている場合、エキスパートアドバイザーやスクリプトの取引操作は実行されません。

売買が現在の口座で許可されているかのチェック

特定の取引口座での取引操作が無効になっていて、手動/自動にかかわらず売買を行うことが出来ない場合があります。投資家のパスワードが取引口座への接続に使用されているかどうかをチェックする例:

  if(!AccountInfoInteger(ACCOUNT_TRADE_ALLOWED))
Comment(“Trading is forbidden for the account “,AccountInfoInteger(ACCOUNT_LOGIN),
“.n Perhaps an investor password has been used to connect to the trading account.”,
“n Check the terminal journal for the following entry:”,
“n'”,AccountInfoInteger(ACCOUNT_LOGIN),“‘: trading has been disabled – investor mode.”);

AccountInfoInteger(ACCOUNT_TRADE_ALLOWED) は次の場合に false を返すことがあります。

  • 取引サーバへの接続がない(この状態は TerminalInfoInteger(TERMINAL_CONNECTED) でチェック出来ます。)
  • 取引口座が読み込み専用モードに切り替えられている(アーカイブに送信された)
  • 口座での売買がサーバ側で無効にされた
  • 取引口座への接続が投資家モードで実行されている

 

参照

クライアント端末プロパティ、口座プロパティ、MQL5 プログラム実行のプロパティ

クライアント端末イベント

Init #

Init イベントは、クライアント端末プログラム(エキスパートアドバイザーまたはカスタム指標)が読み込まれてグローバル変数の初期化プロセスが開始した直後に送信され、存在する場合 OnInit() イベントハンドラで処理されます。このイベントはまた、金融商品及び/またはチャート時間軸の変更後、MetaEditor でのプログラムの 再コンパイル後、エキスパートアドバイザーの設定ウィンドウまたはカスタム指標での入力パラメータの変更後にも生成されます。エキスパートアドバイザーは口座変更後も初期化されます。Init イベントはスクリプトでは生成されません。

Deinit #

グローバル変数が初期化解除されプログラム(エキスパートアドバイザーまたはカスタム指標)がアンロードされる前に、クライアント端末はプログラムに Deinit イベントを送信します。Deinit はまた、クライアント端末の閉鎖時、チャートの閉鎖時、セキュリティ及び/または時間軸の変更直前、プログラムの再コンパイル成功時、入力パラメータの変更時、及び口座変更時に生成されます。

初期化解除の理由は OnDeinit() 関数に渡されたパラメータによって取得出来ます。OnDeinit() 関数の実行は 2.5 秒に制限されています。この間に完了しない場合、この関数は強制的に終了されます。Deinit イベントはスクリプトでは生成されません。

Start #

Startは、スクリプトまたはサービスを読み込んだ後に起動するための特別なイベントです。これはOnStart関数によって処理されます。StartイベントはEAおよびカスタム指標には渡されません。

NewTick #

NewTick イベントは新しい相場が存在する時に生成され、接続されたエキスパートアドバイザーの OnTick() で処理されます。新しい相場を受信した際に前の相場のための OnTick 関数が処理中の場合、対応するイベントはキューに追加されないので、新しい相場はエキスパートアドバイザーによって無視されます。

プログラムの実行中に受信された新しい相場は全て OnTick() が終了するまで無視されます。その後、この関数は新しい相場が受信された後にのみ実行されます。NewTick イベントは自動取引が許可されているか否か(「自動売買」ボタン)に関係なく生成されます。自動売買の禁止は、エキスパートアドバイザーが動作し続ける一方でエキスパートアドバイザーからの取引リクエストの送信が許可されないことだけを意味します。

ボタンを押しての自動取引の禁止は実行中の OnTick() 関数を停止しません。

Calculate #

Calculate イベントは Init イベントの送信直後と価格データの変更時に指標のみに発生します。このイベントは OnCalculate 関数で処理されます。

Timer #

Timer イベントは EventSetTimer 関数でタイマーを起動したエキスパートアドバイザーのクライアント端末によって定期的に生成されます。通常この関数は OnInit で呼び出されます。Timer イベント処理は OnTimer 関数で行われます。エキスパートアドバイザーの操作終了後、タイマーは通常 OnDeinit 関数で呼ばれる EventKillTimer 関数を使用して破壊されるべきです。

Trade #

Trade イベントは取引操作が取引サーバで完了した時に生成されます。Trade イベントは下記の取引操作時に OnTrade() 関数で処理されます。

  • 未決注文の変更または削除
  • 不充分な資金または期限切れによる未決注文の取り消し
  • 未決注文のアクティベーション
  • 注文、ポジション(またはその一部)の追加または決済
  • ポジションの変更(決済逆指及び/または決済指の値の変更)

TradeTransaction #

取引口座にいくつかの明確なアクションを実行すると、状態が変更されます。アクションの例は下記です。

  • クライアント端末内の任意の MQL5 アプリケーションから OrderSend と OrderSendAsync 関数を使用して取引リクエストを送信し、取引が実行される。
  • 端末のグラフィカルインターフェースを使用して取引リクエストを送信し、取引が実行される。
  • サーバ上で未決注文と逆指値注文が執行される。
  • 取引サーバ側で操作を行う。

これらのアクションの結果として以下の取引トランザクションが実行されます。

  • 取引リクエストの処理
  • 未執行注文の変更
  • 注文履歴の変更
  • 約定履歴の変更
  • ポジションの変更

例えば、買いの成行注文を送信すると、注文が処理され、買い注文が口座に記録されます。その後注文が実行されオープン注文の表から削除されて注文履歴に追加されます。 約定が履歴に追加され新しいポジションが作成されます。これらのアクションは全て取引トランザクションです。このようなトランザクションの端末への到着が TradeTransaction イベントです。このイベントは OnTradeTransaction 関数で処理されます。

Tester #

Tester イベントはエキスパートアドバイザーの履歴データテストの終了後に生成されます。このイベントは OnTester() 関数で処理されます。

TesterInit #

TesterInit イベントは、ストラテジーテスターでの最適化の開始の際に初めの最適化パスの前に生成されます。TesterInit イベントは OnTesterInit() 関数で処理されます。

TesterPass #

TesterPass イベントは新しい データフレームが受信された際に生成されます。TesterPass イベントは OnTesterPass() 関数で処理されます。

TesterDeinit #

TesterDeinit イベントはストラテジーテスターでのエキスパートアドバイザーの最適化の終了時に生成されます。TesterDeinit イベントは OnTesterDeinit() 関数で処理されます。

ChartEvent #

ChartEvent はユーザがチャートを操作する時にクライアント端末によってイベント作成されます。

  • チャートウィンドウがフォーカスされている時のキーストローク
  • グラフィックオブジェクト 作成
  • グラフィックオブジェクト 削除
  • チャートのオブジェクトのマウスプレス
  • マウスでのグラフィックオブジェクトの移動
  • LabelEdit でのテキスト編集の終了

また、EventChartCustom 関数を使用して、任意の MQL5 プログラムによってエキスパートアドバイザーに送信することが出来るChartEvent カスタムイベントがあります。このイベントは OnChartEvent 関数で処理されます。

BookEvent #

BookEvent は板情報の変更後にクライアント端末で生成され OnBookEvent 関数で処理されます。指定されたシンボルの BookEvent の生成を始めるには MarketBookAdd 関数を使用してシンボルをイベントにサブスクライブする必要があります。

BookEvent から指定されたシンボルのサブスクライブを停止するには MarketBookRelease 関数を呼ぶ必要があります。BookEvent イベントは、ブロードキャストイベントです。つまり、イベントに 1 つのエキスパートアドバイザーをサブスクライブすれば、OnBookEvent イベントハンドラを持つ他の全てのエキスパートアドバイザーがそれを受信出来ます。これがパラメータとしてハンドラに渡された銘柄名を分析する必要がある理由です。

参照

イベントハンドラ、プログラムの実行

 

リソース

MQL5 プログラムでのグラフィック及び音声リソースの使用

MQL5 プログラムは音声及びグラフィックファイルの操作を可能にします。

  • PlaySound()は音声ファイルを再生します。
  • ObjectCreate() は OBJ_BITMAP 及び OBJ_BITMAP_LABEL グラフィックオブジェクトを使用してのユーザインターフェースの作成を可能にします。

 

PlaySound()

PlaySound() 関数呼び出しの例

//+——————————————————————+
//| 標準的な OrderSend() を呼んで音を再生する                               |
//+——————————————————————+
void OrderSendWithAudio(MqlTradeRequest  &request, MqlTradeResult &result)
{
//— サーバにリクエストを送信する
OrderSend(request,result);
//— リクエストが受け入れられたら Ok.wav を再生する
if(result.retcode==TRADE_RETCODE_PLACED) PlaySound(“Ok.wav”);
//— 失敗したら timeout.wav ファイルの警笛を鳴らす
else PlaySound(“timeout.wav”);
}

この例は標準端末パッケージに含まれている「Ok.wav」と 「timeout.wav」の音の再生の仕方を示します。これらのファイルは terminal_directorySounds フォルダに位置します。ここで terminal_directory は、MetaTrader 5 クライアント端末が起動されるフォルダです。terminal_directory の位置は、MQL5 プログラムから次のように 見つけることが出来ます。

//— 端末データの格納フォルダ
string terminal_path=TerminalInfoString(TERMINAL_PATH);

terminal_directorySounds フォルダだけでなくterminal_data_directoryMQL5 のサブフォルダの音声ファイルも利用可能です。端末データディレクトリは端末メニュの「ファイル」 -> 「データフォルダを開く」またはプログラムのメソッドを使用して見つけることが出来ます。

//— 端末データの格納フォルダ
string terminal_data_path=TerminalInfoString(TERMINAL_DATA_PATH);

例えば、Demo.wav 音声ファイルが terminal_data_directoryMQL5Files に位置する場合、PlaySound() の呼び出しは次のように書かれるべきです。

//— terminal_directory_dataMQL5FilesDemo.wav を再生する
PlaySound(“FilesDemo.wav”);

コメントではファイルパスが「 」バックスラッシュで書かれているのに比べ、関数では「 」が使用されているのにご注意ください。

単一のバックスラッシュはコンパイラがプログラムソースコードの定数文字列及び文字定数扱う際の制御シンボルであるため、パスの指定時は常にセパレータとして二重のバックスラッシュを使用します。

再生を停止するには PlaySound() 関数を NULL パラメータで呼び出します。

//— PlaySound() の NULL パラメータトの呼び出しは再生を停止する
PlaySound(NULL);

 

ObjectCreate()

ObjectCreate() 関数でグラフィックレベル(OBJ_BITMAP_LABEL)を作成するエキスパートアドバイザーの例

string label_name=“currency_label”;       // OBJ_BITMAP_LABEL オブジェクトの名称
string euro      =“Imageseuro.bmp”;   // terminal_data_directoryMQL5Imageseuro.bmp ファイルへのパス
string dollar    =“Imagesdollar.bmp”; // terminal_data_directoryMQL5Imagesdollar.bmp ファイルへのパス
//+——————————————————————+
//| エキスパート初期化に使用される関数                                 &nnbsp;      |
//+——————————————————————+
int OnInit()
{
//— まだ作成されていなければ OBJ_BITMAP_LABEL ボタンを作成する
if(ObjectFind(0,label_name)<0)
{
//— OBJ_BITMAP_LABEL オブジェクト作成を試みる
bool created=ObjectCreate(0,label_name,OBJ_BITMAP_LABEL,0,0,0);
if(created)
{
//— ボタンをチャートの左上にリンクする
ObjectSetInteger(0,label_name,OBJPROP_CORNER,CORNER_RIGHT_UPPER);
//— オブジェクトプロパティを設定する
ObjectSetInteger(0,label_name,OBJPROP_XDISTANCE,100);
ObjectSetInteger(0,label_name,OBJPROP_YDISTANCE,50);
//— 直近エラーの値を 0 にリセットする
ResetLastError();
//— ボタンの「押された」状態を示す画像をダウンロードする
bool set=ObjectSetString(0,label_name,OBJPROP_BMPFILE,0,euro);
//— 結果をテストする
if(!set)
{
PrintFormat(“Failed to download image from file %s. Error code %d”,euro,GetLastError());
}
ResetLastError();
//— ボタンの「押されていない」状態を示す画像をダウンロードする
set=ObjectSetString(0,label_name,OBJPROP_BMPFILE,1,dollar);

if(!set)
{
PrintFormat(“Failed to download image from file %s. Error code %d”,dollar,GetLastError());
}
//— ティックがなくてもボタンが即時表示されるようにチャートにリフレッシュ指令を送る
ChartRedraw(0);
}
else
{
//— オブジェクト作成に失敗したので通知する
PrintFormat(“Failed to create object OBJ_BITMAP_LABEL. Error code %d”,GetLastError());
}
}
//—
return(INIT_SUCCEEDED);
}
//+——————————————————————+
//| エキスパート初期化解除に使用される関数                                    |
//+——————————————————————+
void OnDeinit(const int reason)
{
//— チャートからオブジェクトを削除する
ObjectDelete(0,label_name);
}

OnInit() 関数で currency_label という名称のグラフィックオブジェクトが作成/設定されます。グラフィックファイルへのパスは euro 及び dollar グローバル変数 で設定され、二重のバックスラッシュが区切り文字として使用されます。

string euro      =“Imageseuro.bmp”;   // terminal_dara_directoryMQL5Imageseuro.bmp ファイルへのパス
string dollar    =“Imagesdollar.bmp”; // terminal_dara_directoryMQL5Imagesdollar.bmp ファイルへのパス

ファイルは terminal_data_directoryMQL5Images フォルダに位置します。

OBJ_BITMAP_LABEL オブジェクトは、実際にはボタンの状態(押されたまたは押されていない状態)に応じてeuro.bmp またはdollar.bmp を表示するボタンです。

OBJ_BITMAP_LABEL オブジェクトプロパティ

グラフィカルインターフェースとのボタンのサイズは自動的に画像の大きさに調整されます。画像は OBJ_BITMAP_LABEL オブジェクト上のマウスの左ボタンのクリックによって変更されます(プロパティで「選択を無効化」が設定されている必要があります)。OBJ_BITMAP オブジェクトは同じように作成されます。このオブジェクトは背景を必要な画像と作成するのに使用されます。

OBJ_BITMAP 及び OBJ_BITMAP_LABEL オブジェクトの外観を担当するOBJPROP_BMPFILE プロパティの値は動的に変更出来ます。これによって MQL5 プログラムのための様々なインタラクティブなユーザインタフェースの作成が出来ます。

 

MQL5 プログラムのコンパイル時の実行可能ファイルへのリソースの埋め込み #

MQL5 プログラムはダウンロード可能な多くの映像と音声ファイルの形式のリソースを必要とする場合があります。MQL5 実行ファイルの移動時にこれらのファイルを転送する必要性をなくすには、コンパイラの #resource ディレクティブが使用されるべきです。

#resource path_to_resource_file

#resource コマンドはコンパイラに指定されたパス path_to_resource_file でのリソースが実行可能な EX5 ファイルを埋め込むように指令します。このように、別の端末上でプログラムを実行する場合、必要な画像や音声ファイルの全ては EX5 ファイルに直接配置することが出来るので、別途に転送される必要はありません。リソースはEX5 ファイルに埋め込むことができ、任意の EX5 プログラムは別の EX5 プログラムからのリソースを使用することが出来ます。

BMP 及び WAV 形式のファイルは EX5 ファイルに埋め込まれる前に自動的に圧縮されます。これは、グラフィックと音声を使用する場合にリソースを使用すると、MQL5 プログラムの通常の書き込みの方法に比べて必要なファイルの合計サイズを小さくすることが可能であることを意味します。

リソースファイルサイズは 16 MB を超えてはいけません。

 

コンパイラによる指定されたリソースの検索

リソースは #resource “< リソースファイルへのパス >” 指令を使用して挿入されます。

#resource “< リソースファイルへのパス >”

< リソースファイルへのパス > の定数文字列は 63 文字を超えてはいけません。

コンパイラはリソースを指定されたパスで次の順に探します。

  • (「」として書かれた)バックスラッシュ「」がパスの始めにある場合、リソース検索は terminal_data_directoryMQL5 ディレクトリに相対して行われます。
  • バックスラッシュがない場合、リソースが書かれたソースファイルと相対して検索が行われます。

リソースパスは「 .. 」及び 「 : 」を含むことが出来ません。

リソース埋め込みの例

//— 正しいリソースの指定法
#resource “Imageseuro.bmp” // euro.bmp は terminal_data_directoryMQL5Images に位置する
#resource “picture.bmp”       // picture.bmp はソースファイルと同じディレクトリに位置する
#resource “Resourcemap.bmp” // リソースは source_file_directoryResourcemap.bmp
 
//— 不正なリソースの指定
#resource “:picture_2.bmp”     // 「 : 」を含む
#resource “..picture_3.bmp” // 「 .. 」を含む
#resource “FilesImagesFolder_FirstMy_panelLabelstoo_long_path.bmp” // 63 記号以上

 

リソースの使用

リソース名

#resource ディレクティブでの宣言後、リソースはプログラムの任意の部分で使用出来ます。リソースの名称は、リソースへのパスを設定する行の先頭のバックスラッシュを付けないパスです。自分自身のリソースを使用するにはリソース名の前に「 :: 」特殊記号が加えられるべきです。

例:

//— リソース指定とコメント内での名称の例
#resource “Imageseuro.bmp”         // リソース名 – Imageseuro.bmp
#resource “picture.bmp”                 // リソース名 – picture.bmp
#resource “Resourcemap.bmp”           // リソース名 – Resourcemap.bmp
#resource “FilesPicturesgood.bmp” // リソース名 – FilesPicturesgood.bmp
#resource “FilesDemo.wav”;         // リソース名 – FilesDemo.wav”
#resource “Soundsthrill.wav”;       // リソース名 – Soundsthrill.wav”

//— リソースの使用
ObjectSetString(0,bitmap_name,OBJPROP_BMPFILE,0,“::Imageseuro.bmp”);

ObjectSetString(0,my_bitmap,OBJPROP_BMPFILE,0,“::picture.bmp”);

set=ObjectSetString(0,bitmap_label,OBJPROP_BMPFILE,1,“::FilesPicturesgood.bmp”);

PlaySound(“::FilesDemo.wav”);

PlaySound(“::Soundsthrill.wav”);

リソースファイルの画像を OBJ_BITMAP and OBJ_BITMAP_LABEL オブジェクトに設定する場合、OBJPROP_BMPFILE プロパティ値は手動で変更出来ません。例えば OBJ_BITMAP_LABEL の作成には euro.bmp 及び dollar.bmp を使用します。

#resource “Imageseuro.bmp”;   // euro.bmp は terminal_data_directoryMQL5Images に位置する
#resource “Imagesdollar.bmp”; // dollar.bmp は terminal_data_directoryMQL5Images に位置する

このオブジェクトのプロパティを表示する際、プロパティの「ビットマップファイル(オン)」と「ビットマップファイル(オフ)」が淡色表示されていて、手動変更が不可能だことがわかります。

using_resource

 

他の MQL5 プログラムのリソース使用

リソース使用には、MQL5 プログラムで別の EX5 ファイルのリソースを使用出来るというもう 1 つの利点があります。従って、1 つの EX5 ファイルのリソースは多くの MQL5 プログラムで使用することが出来ます。

別のファイルからのリソース名を使用するためには <path_EX5_file_name>::<resource_name> としての指定が必要です。例として Draw_Triangles_Script.mq5 スクリプトが triangle.bmp 画像ファイルのリソースを含むとします。

#resource “Filestriangle.bmp”

スクリプト自体で使用されるためにはその名称は “Filestriangle.bmp” となり、それを使用するためには「 :: 」がリソース名に追加される必要があります。

//— スクリプトでのリソースの使用
ObjectSetString(0,my_bitmap_name,OBJPROP_BMPFILE,0,“::Filestriangle.bmp”);

別のプログラム(例えばエキスパートアドバイザー)から同じリソースを使用する場合、リソース名に terminal_data_directoryMQL5 に相対した EX5 ファイルのパスとEX5 ファイルの名称 – Draw_Triangles_Script.ex5を加える必要があります。スクリプトが terminal_data_directoryMQL5Scripts 標準フォルダに位置する場合、呼び出しは次のように書かれるべきです。

//— EA でのスクリプトのリソースの使用
ObjectSetString(0,my_bitmap_name,OBJPROP_BMPFILE,0,“ScriptsDraw_Triangles_Script.ex5::Filestriangle.bmp”);

別の EX5 からのリソース呼び出しの際に実行可能ファイルへのパスが指定されていない場合は、実行可能ファイルは、リソースを呼び出すプログラムが含まれている同じフォルダで検索されます。つまり、エキスパートアドバイザーがDraw_Triangles_Script.ex5 のリソースをパスの指定なしにこのように呼び出す場合

//— EA でパスの指定なしでスクリプトリソースを呼ぶ
ObjectSetString(0,my_bitmap_name,OBJPROP_BMPFILE,0,“Draw_Triangles_Script.ex5::Filestriangle.bmp”);

エキスパートアドバイザーが terminal_data_directoryMQL5Experts に位置する場合、ファイルは terminal_data_directoryMQL5で検索されます。

リソースとして含まれたカスタム指標の操作

MQL5 アプリケーションの動作には 1 つまたは複数のカスタム指標が必要であるかもしれません。それらの全ては、実行可能な MQL5 プログラムのコードに含めることが出来ます。指標をリソースとして含むことで、アプリケーションの配布が簡素化します。

下記はterminal_data_folderMQL5Indicators ディレクトリ位置する SampleIndicator.ex5 カスタム指標を含んで使用する例です。

//+——————————————————————+
//|                                                     SampleEA.mq5 |
//|                        Copyright 2013, MetaQuotes Software Corp. |
//|                                             https://www.MQL5.com |
//+——————————————————————+
#resource “IndicatorsSampleIndicator.ex5”
int handle_ind;
//+——————————————————————+
//| エキスパート初期化に使用される関数                                        |
//+——————————————————————+
int OnInit()
{
//—
handle_ind=iCustom(_Symbol,_Period,“::IndicatorsSampleIndicator.ex5”);
if(handle_ind==INVALID_HANDLE)
{
Print(“Expert: iCustom call: Error code=”,GetLastError());
return(INIT_FAILED);
}
//— …
return(INIT_SUCCEEDED);
}

OnInit() 関数のカスタム指標が 1 つ以上の自己コピーをする場合、特別な考慮が必要です。リソースの指定は <path_EX5_file_name>::<resource_name> としてなされることにご注意下さい。

例えば SampleIndicator.ex5 指標が SampleEA.ex5 エキスパートアドバイザーに指標として含まれていて、カスタム指標の初期化関数で iCustom() が呼ばれる場合の位置表現は “ExpertsSampleEA.ex5::IndicatorsSampleIndicator.ex5” のようになります。このパスが明示的に設定されている場合、SampleIndicator.ex5 カスタム指標は厳格にSampleEA.ex5 エキスパートアドバイザーに接続されて、独立して動作する能力を失います。

自己のパスは GetRelativeProgramPath() 関数で受け取ることが出来ます。使用の例は下記の通りです。

//+——————————————————————+
//|                                              SampleIndicator.mq5 |
//|                        Copyright 2013, MetaQuotes Software Corp. |
//|                                             https://www.MQL5.com |
//+——————————————————————+
#property indicator_separate_window
#property indicator_plots 0
int handle;
//+——————————————————————+
//| カスタム指標を初期化する関数                                            |
//+——————————————————————+
int OnInit()
{
//— 自己のリンクを提供する不正な方法
//— 文字列パス =”ExpertsSampleEA.ex5::IndicatorsSampleIndicator.ex5″;  
//— 自己のリンクを受け取る正しい方法
string path=GetRelativeProgramPath();
//— 指標バッファマッピング
handle=iCustom(_Symbol,_Period,path,0,0);
if(handle==INVALID_HANDLE)
{
Print(“Indicator: iCustom call: Error code=”,GetLastError());
return(INIT_FAILED);
}
else Print(“Indicator handle=”,handle);
//—
return(INIT_SUCCEEDED);
}
///….
//+——————————————————————+
//| GetRelativeProgramPath                                           |
//+——————————————————————+
string GetRelativeProgramPath()
{
int pos2;
//— アプリケーションへの絶対パスを取得する
string path=MQLInfoString(MQL_PROGRAM_PATH);
//— “MQL5” サブストリングのポジションを見つける
int    pos =StringFind(path,“MQL5”);
//— サブストリングが見つからないので、エラー
if(pos<0)
return(NULL);
//— “MQL5” ディレクトリをとばす
pos+=5;
//— 余分な「 」’記号をとばす
while(StringGetCharacter(path,pos+1)==”)
pos++;
//— これがリソースならMQL5 ディレクトリに相対したパスを返す
if(StringFind(path,“::”,pos)>=0)
return(StringSubstr(path,pos));
//— MQL5Indicators のような最初の MQL5 サブディレクトリの区切りを見つける
//— 見つからない場合 MQL5 ディレクトリに相対したパスを返す
if((pos2=StringFind(path,“”,pos+1))<0)
return(StringSubstr(path,pos));
//— サブディレクトリ(例えば MQL5Indicators )に相対したパスを返す
return(StringSubstr(path,pos2+1));
}
//+——————————————————————+
//| カスタム指標の反復関数                                                |
//+——————————————————————+
int OnCalculate(const int rates_total,
const int prev_calculated,
const int begin,
const double& price[])
{
//— 次の呼び出しのために prev_calculated の値を返す
return(rates_total);
}

リソース変数 #

リソースは、リソース変数を使用して宣言でき、それらが適切な型の変数と同様に扱われます。宣言の形式:

#resource path_to_the_resource_file as resource_variable_type resource_variable_name

宣言の例:

#resource “data.bin” as int ExtData[]             // data.binファイルからのデータを含む数値配列を宣言
#resource “data.bin” as MqlRates ExtData[]       // data.binファイルからのデータを含む単純構造体配列を宣言
//— 文字列
#resource “data.txt” as string ExtCode           // data.txtファイルデータを含む文字列を宣言(ANSI、UTF-8、UTF-16 エンコードがサポートされる)
//— グラフィックリソース
#resource “image.bmp” as bitmap ExtBitmap[]       // BMPファイルからのビットマップを含む1次元配列を宣言、array size = height * width
#resource “image.bmp” as bitmap ExtBitmap2[][]   // BMPファイルからビットマップを含む2次元配列を宣言、array size [height][width]

このような宣言の場合、リソースデータは 変数を介してのみのアドレス指定が可能で、” :: <rsource name>のような自動アドレス指定は動作しません。

#resource “Imageseuro.bmp” as bitmap euro[][]
#resource “Imagesdollar.bmp”
//+——————————————————————+
//| リソースを使ったOBJ_BITMAP_LABELオブジェクト作成関数                         |
//+——————————————————————+
void Image(string name,string rc,int x,int y)
{
ObjectCreate(0,name,OBJ_BITMAP_LABEL,0,0,0);
ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x);
ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y);
ObjectSetString(0,name,OBJPROP_BMPFILE,rc);
}
//+——————————————————————+
//| スクリプトプログラムを開始する関数                                          |
//+——————————————————————+
void OnStart()
{
//— ユーロリソース変数に格納されている画像サイズ[幅、高さ]を出力する
Print(ArrayRange(euro,1),“, “,ArrayRange(euro,0));
//— ユーロで画像を変更する – 中央に赤い水平ストライプを描画する
for(int x=0;x<ArrayRange(euro,1);x++)
euro[ArrayRange(euro,1)/2][x]=0xFFFF0000;
//— リソース変数を使用してグラフィカルリソースを作成する
ResourceCreate(“euro_icon”,euro,ArrayRange(euro,0),ArrayRange(euro,1),0,0,ArrayRange(euro,1),COLOR_FORMAT_ARGB_NORMALIZE);
//—euro_iconリソースからの画像が設定されるユーログラフィカルラベルオブジェクトを作成する
Image(“Euro”,“::euro_icon”,10,40);
//— リソースを適用するあと一つのメソッド、それへの描画は不可能
Image(“USD”,“::Imagesdollar.bmp”,15+ArrayRange(euro,1),40);
//— euro.bmpリソースをアドレス指定する直接的な方法は、すでにユーロリソース変数<によって宣言されているため利用できない
Image(“E2”,“::Imageseuro.bmp”,20+ArrayRange(euro,1)*2,40); // 実行時エラーが発生する
}

スクリプト実行結果 – 3つのOBJ_BITMAP_LABELのうち2のみが作成されます。最初のオブジェクトの画像には、真ん中に赤いストライプがあります。

res_variables

リソースを適用することの重要な利点は、リソースファイルがコンパイル前に実行可能EX5ファイルに組み込まれる前に自動的に圧縮されることです。したがって、リソース変数を使用すると、実行可能なEX5ファイルにすべての必要なデータを直接入れることができ、MQL5プログラムを書く従来の方法と比較したファイルの数と合計サイズを減らすことができます。

リソース変数の使用はマーケットに製品を公開する場合に特に便利です。

機能

  • 特別なbitmapリソース変数タイプは、リソースが画像であることをコンパイラに通知します。そのような変数はuint型を受け取ります。
  • bitmap 型配列リソース変数は2次元を持つことができます。この場合、配列の大きさは [image_height ][ image_width ].で定義されます。1次元配列が指定されている場合、要素の数はimage_height * image_widthに等しくなります。
  • 24ビット画像のダウンロードではアルファチャネルコンポーネントは、すべての画像画素に対して255に設定されます。
  • アルファチャネルなしでの32ビット画像のダウンロードでは、アルファチャネルコンポーネントもすべての画像画素に対して255に設定されます。
  • アルファチャンネルを使用した32ビット画像のダウンロードでは、画素はまったく処理されません。
  • リソースファイルサイズは128MBを超えてはいけません。
  • 文字列ファイルに対してはBOM(ヘッダ)の存在による自動エンコード検出が実行されます。BOMが存在しない場合、エンコーディングはファイルの内容によって定義されます。ANSI、UTF-8およびUTF-16エンコーディングのファイルがサポートされています。すべての文字列は、ファイルからデータを読み込むときにUnicodeに変換されます。

OpenCLプログラム

ある種のプログラムの開発は、リソース文字列変数の使用によって大幅に容易になります。たとえばOpenCLプログラムのコードを別のCLファイルに書き込んだ後、文字列としてMQL5プログラムリソースに組み込むことが可能です。

#resource “seascape.cl” as string cl_program

int context;
if((cl_program=CLProgramCreate(context,cl_program)!=INVALID_HANDLE)
{
//— OpenCLプログラムでさらなる行動を実行する
}

リソース変数が使用されない場合、この例はcl_program コード全体の単一の大きな文字列としての記述が必要でした。

参照

ResourceCreate()、ResourceSave()、PlaySound()、ObjectSetInteger()、ChartApplyTemplate()、ファイル関数

インポートした関数の呼び出し

MQL5 プログラムの実行時に関数をインポートするには、クライアント端末は事前結合を使用します。これは、プログラムがインポートされた関数を呼び出す場合は、対応するモジュール(EX5またはDLL)がプログラムロード中に読み込まれていることを意味します。MQL5 及び DLL ライブラリは呼び出しモジュールと同じスレッドで実行されます。

Drive:DirectoryFileName.Ext の様なモジュールの絶対パスの指定は推奨されていません。MQL5 ライブラリは terminal_dirMQL5Libraries フォルダから読み込まれます。ライブラリが見つからない場合、クライアント端末は terminal_direxperts フォルダからの読み込みを試みます。

システムライブラリ(DLL)はオペレーティングシステムルールによって読み込みされます。ライブラリがすでに読み込みされている場合(例えば、別のエキスパートアドバイザーや更に別のクライアント端末が並列に実行されている)それは既に読み込まれたライブラリへのリクエストを使用します。それ以外の場合は、以下の順序で検索が実行されます。

  1. モジュールをインポートする dll が開始されたディレクトリ(モジュールとは、エキスパートアドバイザー、スクリプト、指標または EX5 ライブラリ)
  2. terminal_data_directoryMQL5Libraries ディレクトリ(TERMINAL_DATA_PATHMQL5Libraries )
  3. MetaTrader 5 クライアント端末が開始されたディレクトリ
  4. システムディレクトリ
  5. ウィンドウディレクトリ
  6. 現在のディレクトリ
  7. PATH システム変数にリストされたディレクトリ

DLL ライブラリが他の DLL を使用する場合、使用される DLL が存在しない場合、初めの DLL は読み込むことが出来ません。

エキスパートアドバイザー(スクリプト、指標)が読み込まれる前に、全ての EX5 のライブラリモジュールの共通リストが形成されます。これは、読み込まれたエキスパートアドバイザー(スクリプト、指標)とライブラリー両方から使用されます。従って、EX5 ライブラリモジュールの複数使用のために1 回のみの読み込みが必要とされています。ライブラリはエキスパートアドバイザー(スクリプト、指標)の事前定義された変数を使用します。

インポートされたライブラリ EX5 は次の順序で検索されます。

  1. パスが EX5 をインポートしたエキスパートアドバイザー(スクリプト、指標)のディレクトリからの相対に設定されているディレクトリ
  2. terminal_directoryMQL5Libraries ディレクトリ
  3. 全てのクライアント端末の共有ディレクトリ(CommonMQL5Libraries)内の MQL5Libraries ディレクトリ

DLL を MQL5 プログラムにインポートした関数は Windows API 呼び出しルールを守らなければなりません。そのような合意を確保するには、C または C ++ で記述されたプログラムのソーステキストで Microsoft(r) コンパイラに固有のキーワード __stdcall を使用します。この合意は以下のことを特徴としています。

  • 呼び出し側( MQ5 プログラム)は、スタックに正しくパラメータを組み合わせるために、(DLLからインポートされた)呼びだされる関数のプロトタイプを「見る」必要があります。
  • 呼び出し側( MQ5 プログラム)は、インポートされた関数が渡されたパラメータをこの順に読み込むように、右から左の逆の順序でスタックにパラメータを置きます 。
  • パラメータは、明示的に参照で渡されたもの(文字列)を除いて、値によって渡されます。
  • インポートされた関数は、渡されたパラメータを読み込むことにより、独立的にスタックをクリーンします。

インポートされた関数のプロトタイプを記述する場合、デフォルトのパラメータを使用することが出来ます。

対応するライブラリが読み込み出来ない場合、または DLL 使用が禁止されているかインポートされた関数が見つからない場合は、エキスパートアドバイザーは操作ログ(ログファイル)に「Expert Advisor stopped(エキスパートアドバイザー停止)」とのメッセージを書き入れて停止します。この場合、エキスパートアドバイザーは再初期化されるまで実行されません。エキスパートアドバイザーは、再コンパイルの結果として、またはそのプロパティの表が開かれ「OK」が押された後、再初期化することが出来ます。

パラメータの引き渡し

基本データ型のパラメータは全て明示的に参照で渡されるもの以外は値で受け渡されます。string の受け渡し時には、複製された文字列のバッファのアドレスが渡されます。文字列は参照で受け渡された場合、この文字列のバッファのアドレスが複製されずに DLL からインポートされた関数に渡されます。

動的配列、文字列、クラス、またその他の複雑な構造体を含む構造体や、列挙オブジェクトの静的または動的配列はパラメータとしてインポートされた関数に渡すことが出来ません。

配列を DLL に渡す場合 AS_SERIES フラグにかかわらず常にバッファの初めのアドレスが渡されます。DLL 内の関数は AS_SERIES フラグについては何も知らないので、渡された配列は不定のサイズ持つ静的配列となります。配列のサイズを指定するには追加のパラメータが使用されるべきです。

ランタイムエラー

MQL5 実行中にエラーが発生した場合、クライアント端末の実行サブシステムはエラーコードを保存することが出来ます。それぞれの実行可能な MQL5 プログラムは事前定義された _LastError 変数を持っています。

_LastError 変数は OnInit 関数の開始前にリセットされます。計算中や内部関数呼び出しの過程で不正な状況が発生した場合 _LastError 変数は対応するエラーコードを受け付けます。この変数に保存された変数は GetLastError() 関数で取得出来ます。

プログラムの即時終了につながる重大なエラーはいくつかあります。

  • ゼロ除算
  • 配列の境界外のアクセス
  • 不正なオブジェクトポインタの使用

 

取引ストラテジーのテスト

自動売買のアイディアは、取引ロボットが四六時中ノンストップで働くことが出来るという事実によって魅力的です。ロボットは、心理的な問題から完全に解放されており、疲れたり、疑問を持ったり怖がったりしません。取引ルールを定式化してアルゴリズムで実装すれば、ロボットはたゆまず努力する準備ができています。しかし、初めに次の 2 つの重要な条件が満たされていることを確認する必要があります。

  • エキスパートアドバイザーは取引システムの規則に従って取引操作を行う
  • EA に実装された取引ストラテジーが履歴的に利益を示している

これらの質問に答えるためには MetaTrader 5 のクライアント端末に含まれるストラテジーテスターが使用されます。

このセクションでは、ストラテジーテスターでのプログラムのテストと最適化の機能について説明します。

  • ストラテジーテスターーでの機能の制限
  • ティック生成モード
  • スプレッドのシミュレーション
  • テストでの実際ティックの使用
  • クライアント端末のグローバル変数
  • テスト中の指標の計算
  • テスト中の履歴の読み込み
  • 多通貨テスト
  • ストラテジーテスターーでの時間のシミュレーション
  • テストでのグラフィックオブジェクト
  • ストラテジーテスターーでの OnTimer() 関数
  • ストラテジーテスターーでの Sleep() 関数
  • 数値計算や最適化問題のためのストラテジーテスターーの使用
  • 「始値のみ」モードでのバーの同期
  • テスタの IndicatorRelease() 関数
  • テスタでのイベントハンドル
  • テストエージェント
  • 端末とエージェントの間でのデータ交換
  • 全てのクライアント端末の共有フォルダの使用
  • DLL の使用

ストラテジーテスターーでの機能の制限 #

クライアント端末のストラテジーテスターの一部の関数には操作上の制限があります。

Comment()、Print() 及び PrintFormat() 関数 #

パフォーマンス向上のため、Comment()、Print() 及び PrintFormat() 関数は取引ロボットパラメータの最適化の際には実行されません。例外は OnInit() ハンドラでのこれらの関数の使用です。これによって、エラーが発生した時に簡単に原因を見つけることが出来ます

Alert()、MessageBox()、PlaySound()、SendFTP、SendMail()、SendNotification()、及び WebRequest() 関数 #

「外部世界」との相互作用のために設計されたAlert()、MessageBox()、PlaySound()、SendFTP()、SendMail()、SendNotification() 及び WebRequest() 関数はストラテジーテスターでは実行されません。

ティック生成モード #

エキスパートアドバイザーは MQL5 で書かれた、外部のイベント対応するたびに実行されるプログラムです。エキスパートアドバイザーは事前定義されたイベントの 1 つに対応する関数(イベントハンドラ)を持っています。

NewTick イベント(価格変更)はエキスパートアドバイザーの主要なイベントなので、エキスパートアドバイザーのテストは連続してティックを作成することが必要です。MetaTrader 5 クライアント端末のストラテジーテスターには 3 つのティック生成のモードがあります。

  • 全ティック
  • 1 分足 OHLC(1 分足を持ったOHLC 価格)
  • 始値のみ

基本的で最も詳細なものは「全ティック」モードで、他の 2 つのモードは基本的なものを単純化したもので、「全ティック」モードに比較して説明されます。それらの違いを理解するために全ての 3 つのモードを考えてみましょう。

「全ティック」

金融商品の履歴相場データは、パックされた 1 分足の形で MetaTrader 5 クライアント端末に取引サーバから転送されます。リクエストの発生及び必要な時間フレームの構成に関する詳細な情報は MQL5 リフェレンスのデータアクセスの整理チャプターで取得出来ます。

価格履歴の最小要素は1 分足で、価格の 4 値の情報を得ることが出来ます。

  • 始値 – 1 分足が開かれた時の価格
  • 高値 – 1 分足の間に達成された最大値
  • 安値 – 1 分足の間に達成された最小値
  • 終値 – 1 分足の終値

新しい1 分足は、新しい分が始まる(秒数が 0 に等しくなる)瞬間ではなく、価格が少なくても 1 ポイントによって変動しティックが発生した時に開かれます。この図は、2011年1月10日午前零時零分のオープン時間を持つ新たな取引週の最初の1 分足を示します。為替レートは、着信ニュースに反応して週末にでも変動するため、チャート上の金曜日と月曜日との間の価格差は一般的です。

金曜日と月曜日との価格差

1 分足が 2011 年 1 月 10 日午前 0 時 0 分に開かれたことは分かっていますが、秒については何も分かりません。0 時 0 分 12秒 または 0 時 0 分 36秒(新しい日の始まりから 12 または 36 秒後)またはその分内のどの秒に開いたかもしれません。しかし新しい1 分足が開いた時に EURUSD の始値が 1.28940 であったことは分かります。

また、1 分足の終値に対応する2 番目のティックが受信された秒も分かりません。分かっているのは1 分足の最後の終値だけです。この分では、その価格は 1.28958 でした。高値と安値の出現時刻も不明ですが、値がそれぞれ 1.28958 と 1.28940 のレベルにあったことは分かります。

取引ストラテジーのテストには、エキスパートアドバイザーの作業をシミュレートする連続したティックが必要です。全ての1 分足での、価格が間違いなく位置した4制御点の場所は分かっています。足にティックが 4 つある場合、テスト実行には充分な情報ですが、ティックボリュームは通常 4 以上です。

従って、始値、高値、安値及び終値の間に発生したティックの追加制御点を生成する必要があります。「全ティック」の原則は、The Algorithm of Ticks’ Generation within the Strategy Tester of the MetaTrader 5 Terminalに記述されており、下に図が引用されています。

ティック生成アルゴリズム

「全ティック」モードのテストでは、エキスパートアドバイザーの OnTick() が全ての制御点で呼ばれます。各制御点は、生成されたシーケンスからのティックです。エキスパートアドバイザーは、オンラインで作業する場合と同じように、シミュレートされたティックの時間と価格を受信します。

重要事項:「全ティック」テストモードは一番正確ですが、同時に一番時間がかかります。大部分の取引ストラテジーの初期テストとしては、通常、他の 2 つのテストモードのいずれかを使用することで充分です。

「1 分足 OHLC」

3 つのモードのうちで「全ティック」モードは一番正確ですが、同時に一番低速です。ティックボリュームは非常に多くなりえるのですが、OnTick() ハンドラは全てのティックで起こります。足全体での価格変動のティックシーケンスが重要ではないストラテジーでは、より速く、より粗い「1 分足 OHLC」シミュレーションモードがあります。

「1 分足 OHLC」モードでは、ティックシーケンスは1 分足の OHLC 価格でのみ構成され、生成された制御点の数が大幅に削減されます。従って、テスト時間も減少します。OnTick () 関数は 1 分足 OHLC の価格によって構築されている全ての制御点で起動されます。

始値、高値、安値及び終値以外での追加の中間ティックを生成しないことで、始値が決定された瞬間から、価格展開を決定します。これにより、テストバランスの素晴らしい上向きのグラフを示す「テストグレイル」を作成することが出来ます。

そのようなグレイルの例はコードベースの Grr-al でみられます。

Grr-al エキスパートアドバイザーは、OHLC 価格の特別な機能を使用します。

図は、このエキスパートアドバイザーテストの非常に魅力的なグラフを示しています。それはどのように取得されたのでしょうか?1 分足の 4 価格は知られており、また、最初は始値で最後が終値であることも知られています。それらの間に高値と安値があり、発生順序は不明ですが、高値が始値以上であること(かつ安値が始値以下であること)も知られています。

始値を受信した瞬間を決定した後、現時点で持っている価格が高値か安値かを決定するために、次のティックを分析するので充分です。価格が始値を下回っている場合は、このティックでは安値と買いがあり、次のティックは、買いを閉めて売りに開く高値に対応します。終値である次のティックが最後で、ここでは売りを閉じます。

価格の後、始値よりも価格の大きいティックを受信した場合、取引の順番が逆になっています。 この「カンニング」モードで1 分足を処理し、次のものを待ちます。

このようなエキスパートアドバイザーを履歴上でテストする場合全てがスムーズに行きますが、オンラインで起動すると、バランスラインが安定したままですが、下向きだという、真実が明らかになります。このトリックを公開するには、単に「全ティック」モードでエキスパートアドバイザーを実行するだけです。

注意事項: 粗雑なテストモード(「1分 OHLC」と「始値のみ」)でのエキスパートアドバイザーのテスト結果があまりにも良すぎる場合は「全ティック」モードでテストしてみてください。

「始値のみ」

このモードでは、ティックはテストのために選択された時間軸の OHLC 価格に基づいて生成されます。エキスパートアドバイザーの OnTick() 関数は始値でのバーの初めでのみ実行されます。この機能により、ストップレベルや未決済は(特に高い時間軸のテストで)指定とは異なる価格でトリガされることがあります。代わりに、すぐにエキスパートアドバイザーの評価テストを実行する機会があります。

W1 及び MN1 期間は「始値のみ」ティック生成モードの例外です。これらの時間軸では、ティックは週または月の OHLC 価格ではなく、毎日の OHLC 価格に生成されます。

「始値のみ」モードでEURUSD H1 でエキスパートアドバイザーをテストするとします。この場合、ティック(制御点)の合計数はテスト間隔内の1時間のバーの数 4 倍以下です。しかしOnTick() ハンドラは 1 時間足の開始でのみ呼ばれます。. 正しいテストのために必要なチェックは(エキスパートアドバイザーから「隠れ」ている)ティックの残りの部分で発生します。

  • 証拠金要件の計算
  • 決済逆指及び決済指レベルのトリガ
  • 未決注文のトリガ
  • 期限切れの未決注文の削除

ポジションや未決注文がない場合、隠れたティックのチェックは無用で、速度の増加はかなリ大きいです。 この「始値のみ」モードは、未決注文、決済逆指及び決済指注文を使わずにバーの開始時のみで取引を処理するストラテジーのテストに適しています。そのようなストラテジーのクラスでは、テストの必要な精度が維持されます。

どのモードでのテストも可能なエキスパートアドバイザーの一例として、標準パッケージからMoving Average(移動平均)エキスパートアドバイザーを使用してみましょう。このエキスパートアドバイザーの論理は、意思決定の全てがバーのオープン時でなされるような方法で構築されており、取引は未決を使用せずにすぐに実行されます。

エキスパートアドバイザーのテストを 2010.09.01 から 2010.12.31 までの EURUSD H1 で実行し、グラフを比べてみます。図は、3 つのモードの全てのテストレポートからのバランスグラフを示します。

標準パッケージの Moving Average.mq5 エキスパートアドバイザーのテストグラフはテストモードに依存しません。

標準パッケージの Moving Average.mq5 エキスパートアドバイザーのグラフは異なるテストモードで全く同じです。

「始値のみ」モードには制限があります。

  • ランダム遅延実行モードは使用出来ません。
  • テストされているエキスパートアドバイザーでは、テストと最適化に使用されるより低い時間軸のデータはアクセス出来ません。例えば、H1 期間をテスト/最適化する場合、H2、H3、H4のデータにアクセスすることが出来ますが、M30、M20、M10などにはアクセス出来ません。また、アクセスされた長い時間軸は、テストの時間軸の倍数でなければなりません。例えば、M20でテストを実行する場合、M30のデータにアクセスすることは出来ません。が、H1にアクセスすることは可能です。これらの制限は、テスト/最適化中に生成されたバーのうち、下側または非多重時間軸のデータの取得が不可能なことに関係しています。
  • 他の時間軸のデータへのアクセスの制限は、データエキスパートアドバイザーが使用している他のシンボルにも適用されます。この場合、各シンボルの制限は、テスト/最適化中に初めにアクセスされた時間軸によって異なります。EURUSD H1 Eのテスト中に、エキスパートアドバイザーが GBPUSD M20 のデータにアクセスすると仮定します。この場合、エキスパートアドバイザーは EURUSD H1、H2、だけでなく、GBPUSD M20、H1、H2などのデータを使用することが出来るようになります。

注意事項:「始値のみ」モードのテスト時間は最短ですが、このモードは取引ストラテジーの全てには適していません。取引システムの特性に基づいて、所望のテストモードを選択するべきです。

このセクションを締めくくりとして 2011.01.11 21:00:00 から 2011.01.11 21:30:00 の間隔の 2 つの M15 バーでの EURUSD での異なるティック生成モードを視覚的に比較して検討してみましょう。

ティックは WriteTicksFromTester.mq5 エキスパートアドバイザーを使用して異なるファイルに保存され、ファイル名の終わりは filenameEveryTick、filenameOHLC 及び filenameOpenPrice 入力パラメータに指定されています。

WriteTicksFromTester エキスパートアドバイザーのティックの始まりと終わりの日(start 及び end 変数)の指定が可能です。

「全ティック」、「1分 OHLC」と「始値のみ」の 3 つのモードで、3ティック配列で3つのファイルを取得するために、エキスパートアドバイザーは、単一の実行で、対応するモードで 3 回起動されました。そして、この 3 つのファイルからのデータは TicksFromTester.mq5 指標を使用してチャート上に表示されました。 指標コードはこの記事に添付されています。

3 つの異なるテストモードでの MetaTrader 5 端末のストラテジーテスターでのティックシーケンス

デフォルトでは MQL5 言語のファイル操作は「ファイルサンドボックス」内で行われ、テストではエキスパートアドバイザーはこれらの「ファイルサンドボックス」にしかアクセス出来ません。テスト中で指標とエキスパートアドバイザーが 1 つのフォルダのファイルと作業出来るために FILE_COMMON フラグ が使用されました。エキスパートアドバイザーからのコード例

//— ファイルを開く
file=FileOpen(filename,FILE_WRITE|FILE_CSV|FILE_COMMON,“;”);
//— ファイルハンドルをチェックする
if(file==INVALID_HANDLE)
{
PrintFormat(“Error in opening of file %s for writing. Error code=%d”,filename,GetLastError());
return;
}
else
{
PrintFormat(“The file will be created in %s folder”,TerminalInfoString(TERMINAL_COMMONDATA_PATH));
}

指標のデータを読むために FILE_COMMON フラグも使用されました。これによって、必要なファイルの別のフォルダへの手動転送を回避できました。

//— ファイルを開く
int file=FileOpen(fname,FILE_READ|FILE_CSV|FILE_COMMON,“;”);
//— ファイルハンドルをチェックする
if(file==INVALID_HANDLE)
{
PrintFormat(“Error in open of file %s for reading. Error code=%d”,fname,GetLastError());
return;
}
else
{
PrintFormat(“File will be opened from %s”,TerminalInfoString(TERMINAL_COMMONDATA_PATH));
}

スプレッドのシミュレーション #

売値と買値との価格差はスプレッドと呼ばれています。テストでは、スプレッドはモデルされる代わりに履歴データからとられます。履歴データでスプレッドがゼロ以下の場合、最後の既知の(生成の瞬間での)スプレッドがテストエージェントによって使用されます。

ストラテジーテスターでは、スプレッドは常に浮動と考えられています。つまり SymbolInfoInteger(symbol, SYMBOL_SPREAD_FLOAT) は常に true を返します。

更に、履歴データはティック値と取引高を含みます。データ格納と取得のためには特別な MqlRates 構造体が使用されます。

struct MqlRates
{
datetime time;         // 期間開始時刻
double   open;         // 始値
double   high;         // 期間の高値
double   low;         // 期間の安値
double   close;       // 終値
long     tick_volume; // ティックボリューム
int      spread;       // スプレッド
long     real_volume; // 取引高
};

テストでの実際ティックの使用 #

実際ティックのテストと最適化は、実世界の条件をより近く再現します。分足データに基づいてティックを生成する代わりに、ブローカによって蓄積された実際のティックを使用することが可能です。これらは、取引所および流動資産プロバイダーからのティックです。

最も正確なテスト精度を保証するために、分足は実際ティックモードでも使用され、ティックデータをチェックし修正するために適用されます。これにより、テスターとクライアント端末のチャートの相違を避けることもできます。

テスターは、ティックデータと分足パラメータを比較します。ティックはバーの高/低レベルを超えてはならず、最初と最後のティックはバーの始値/終値と一致する必要があります。ボリュームも同様に比較されます。不一致が検出された場合、この分足に対応するすべてのティックは破棄され、生成ティックが代わりに使用されます( 「全ティック」モード同様)。

シンボル履歴にティックデータを持たない分足が存在する場合、テスターは「全ティック」モードでティックを生成します。これにより、ブローカのティックデータが不十分な場合に、テスターに正しいチャートがプロットされます。

シンボル履歴に分足が存在しないが、その分の適切なティックデータが存在する場合、テスターはそのデータを使用します。たとえば、取引シンボルのペアは最終価格を使用して形成されたとします。最終価格が設定されていないBid /Ask価格のティックのみがサーバーから到着した場合、バーは生成されません。これらのティックデータは分データと矛盾しないので、テスターに使用されます。

ソースからクライアント端末にデータを送信する際の接続損失または他の不具合といった様々な理由により、ティックデータは分足と一致しないことがあります。テストにおいては分足データの信頼性はより高いと考えられます。

実際ティックでテストするときは、次の点にご注意ください。

  • テストを開始すると、シンボルの分足データがティックデータと同期されます。
  • ティックは、ストラテジーテスターのシンボル・キャッシュに格納されます。キャッシュサイズは128,000ティックを超えません。新しいティックが到着すると、最も古いデータがキャッシュから削除されます。しかし、CopyTicks機能によってキャッシュ外でティックを受け取ることが可能です(実際ティックでテストする場合のみ)。その場合、データは、対応するクライアント端末データベースと完全に類似しているテスターティックデータベースから要求されます。このベースでは分足は補正されていません。したがって、そこにあるティックは、キャッシュに格納されているティックと異なる場合があります。

クライアント端末のグローバル変数 #

テストではクライアント端末のグローバル変数もエミュレートされますが、これらは、端末で F3 ボタンでみられる、現在の端末のグローバル変数とは関係ありません。これは、テスト中の端末のグローバル変数の全ての操作は、クライアント端末の外で(テストエージェントで)行われることを意味します。

テスト中の指標の計算 #

リアルタイムモードでは、指標値は、全てのティックで計算されます。ストラテジーテスター指標計算のために費用対効果の高いモデルを採用し、エキスパートアドバイザーの実行直前のみに指標が再計算されます。これは、指標の再計算が OnTick()、OnTrade() 及び OnTimer() 関数の呼び出しの前に行われることを意味します。

特定のイベントハンドラで指標の呼び出しがあるかどうかは問題ではありません。iCustom() または IndicatorCreate() 関数によってハンドルが作成された指標の全てが、イベントハンドラを呼び出す前に再計算されます。

結果的に「全ティック」モードでのテストでは、指標の計算は OnTick() 関数呼び出しの前になされます。

エキスパートアドバイザーでEventSetTimer() を使用してタイマーがかかっている場合、指標は OnTimer() ハンドラが呼ばれる前に毎回再計算されます。このため、非最適な方法で記述された指標を使用すると、テスト時間が大幅に増加することがあります。

テスト中の履歴の読み込み #

テストされるシンボルの履歴は、テストプロセスの開始前に端末によって取引サーバから読み込みまた同期されます。端末は、後のリクエストを避けるために、初めに使用可能な全てのシンボル履歴を順番に読み込みます。その後は、新しいデータのみが読み込まれます。

テストエージェントは、テスト開始の直後に、テストされるシンボルの履歴を端末から受け取ります。他の金融製品のデータがテストの過程で使用されている(例えば、多通貨エキスパートアドバイザー)場合、テストエージェントは、データの最初の呼び出し時にクライアント端末から必要な履歴を要求します。履歴データが端末で利用可能な場合、それらはすぐにテストエージェントに渡されます。データが利用可能でない場合は、端末はサーバからリクエスト及びダウンロードしてからテストエージェントに渡します。

取引操作のクロスレートを計算するには、追加的な製品のデータも必要です。例えば、米ドル預金通貨での EURCHF ストラテジーをテストする際、ストラテジーにはそれらを直接使用する呼び出しが含まれないにもかかわらず、テストエージェントは、最初の取引操作を処理する前に、クライアント端末から EURUSD とUSDCHF の履歴データをリクエストします。

多通貨ストラテジーをテストする前に、クライアント端末に全ての必要な履歴データをダウンロードすることをお勧めします。これによって、必要なデータのダウンロードに関連したテスト/最適化の遅れが防げます。例えば、適切なチャートを開いて履歴先頭にスクロールすることによって、履歴をダウンロードすることが出来ます。端末への履歴の強制読み込みの例は MQL5 リフェレンスのデータアクセスの整理セクションでみられます。

代わりに、テストエージェントは端末からパックされた形式で履歴を受け取ります。必要なデータはテスタの前回の実行以降利用可能であるため、次のテスト中にはテスタは端末から履歴を読み込みません。

  • 端末は、エージェントが初めにテストされるシンボルの履歴をリクエストする際に、取引サーバから一度だけ履歴を読み込みます。トラフィックを減らすために、履歴はパック形式で読み込まれます。
  • ティックはネットワーク経由で送信されず、テストエージェント上で生成されます。

多通貨テスト #

ストラテジーテスターは、複数シンボルの売買、ストラテジーのテストを実行することが出来ます。 以前のプラットフォームではテストは単一のシンボルに対して実施されていたので、このようなエキスパートアドバイザーは従来「多通貨エキスパートアドバイザー」と呼ばれます。MetaTrader 5 端末のストラテジーテスターでは、利用可能な全てのシンボルの取引をモデル化することが出来ます。

テスタはシンボルデータの最初の呼び出し時に自動的に使用される記号の履歴を(取引サーバからではなく)クライアント端末 から読み込みます。

テストエージェントはテスト開始時に指標の計算に必要で欠けている小幅な履歴データをダウンロードします。 D1 以下の時間軸では、ダウンロードされた履歴の最小容量は1年です。

よって、2010.11.01-2010.12.01 の間隔を(各足が 15 分に等しい)M15 期間でテストした場合、端末は2010年 1 年間の履歴をリクエストします。週足では、約 2 年(1年は 52 週)である 100 足の履歴を要求します。月足でのテストのために、エージェントは 8 年の履歴(12 カ月 × 8 年 = 96 ヶ月)を要求します。

足が足りない場合、必要な足数を確保するためにテスト前にテストの開始日が過去から現在まで自動的にシフトされます。

テスト中には「気配値表示」もエミュレートされ 銘柄情報が取得出来ます。

デフォルトでは、テスト開始時にストラテジーテスターの「気配値表示」にはテストが実行されている 1 つのみの銘柄が存在します 。必要なシンボルの全ては自動的に(端末ではなく)ストラテジーテスターの「気配値表示」に参照されます。

多通貨エキスパートアドバイザーのテストを開始する前に、端末の「気配値表示」のテストに必要なシンボルを選択して必要なデータを読み込む必要があります。「外来」シンボルの最初の呼び出し時には、その履歴が自動的にテストエージェントとクライアント端末間で同期されます。「外来」シンボルとはテストが実行されているシンボル以外のシンボルです。

「他の」シンボルへの参照は次の場合に起こります。

  • 銘柄/時間軸でのテクニカル指標関数及び IndicatorCreate() の使用時
  • 「気配値表示」の他のシンボルデータのリクエスト
    1. SeriesInfoInteger
    2. Bars
    3. SymbolSelect
    4. SymbolIsSynchronized
    5. SymbolInfoDouble
    6. SymbolInfoInteger
    7. SymbolInfoString
    8. SymbolInfoTick
    9. SymbolInfoSessionQuote
    10. SymbolInfoSessionTrade
    11. MarketBookAdd
    12. MarketBookGet
  • 以下の関数を使用した銘柄/時間軸のための時系列のリクエスト
    1. CopyBuffer
    2. CopyRates
    3. CopyTime
    4. CopyOpen
    5. CopyHigh
    6. CopyLow
    7. CopyClose
    8. CopyTickVolume
    9. CopyRealVolume
    10. CopySpread

「その他」の銘柄の最初の呼び出しの時点で、テストプロセスが停止され、銘柄/時間軸の履歴が端末からテストエージェントにダウンロードされます。同時に、このシンボルのティックシーケンスが生成されます。

シンボルごとに個々のティックシーケンスが、選択されたティック生成モードに応じて生成されます。OnInit() ハンドラの SymbolSelect() の呼び出しによって、目的のシンボルの履歴を明示的にリクエストすることも出来ます。履歴ダウンロードはエキスパートアドバイザーテストの直前に行われます。

この様に MetaTrader 5 クライアント端末での多通貨テストの実行は余分な労力を必要としません。ただ、クライアント端末で適切な銘柄のチャートを開くだけです。適切なデータが含まれていれば全ての必要なシンボルの履歴は自動的に取引サーバからアップロードされます。

ストラテジーテスターーでの時間のシミュレーション #

テスト中、TimeLocal() ローカル時刻は常に TimeTradeServer() サーバ時刻と同じです。そして、サーバ時刻は常に TimeGMT() GMT に等しいです。こうすれば、これらの全ての関数は、テスト中に同じ時刻を表示します。

GMT、ローカル、及びストラテジーテスターでのサーバ時刻との差の欠如は、サーバへの接続がない場合には、意図的に行われます。テスト結果は接続のあるなしに関係なく同じでなければなりません。サーバ時刻に関する情報はローカル格納されておらず、サーバから取得されます。

テストでのグラフィックオブジェクト #

テスト/最適化中には、グラフィックオブジェクトはプロットされません。よって、テスト/最適化の際に作成されたオブジェクトのプロパティを参照すると、エキスパートアドバイザーはゼロ値を受け取ることになります。

この制限は、ビジュアルモードでのテストには適用されません。

ストラテジーテスターーでの OnTimer() 関数 #

MQL5 はタイマーイベントを処理するための機会を提供します。OnTimer() ハンドラはテストモードにかかわらず呼び出されます。これは、テストが H4 期間で「始値のみ」モードを実行し、エキスパートアドバイザーが毎秒コールに設定されたタイマを有する場合、それぞれの H4 足の開始時に OnTick() ハンドラが1 回呼ばれ、その後 OnTimer() ハンドラが 14,400 回( 3,600 秒 * 4 時間)呼ばれることを意味します。エキスパートアドバイザーのテスト時間が増加される量は、その論理に依存します。

テスト時間のタイマーに所定された頻繁度依への存性を確認するために、取引操作なしの簡単なエキスパートアドバイザーを作成しました。

//— 入力パラメータ
input int      timer=1;             // 秒単位でのタイマー値
input bool     timer_switch_on=true; // タイマーがオン
//+——————————————————————+
//| エキスパート初期化に使用される関数                                        |
//+——————————————————————+
int OnInit()
{
//— timer_switch_on==true  の場合タイマーを実行
if(timer_switch_on)
{
EventSetTimer(timer);
}
//—
return(INIT_SUCCEEDED);
}
//+——————————————————————+
//| エキスパート初期化解除に使用される関数                                    |
//+——————————————————————+
void OnDeinit(const int reason)
{
//— タイマーを停止する
EventKillTimer();
}
//+——————————————————————+
//| Timer 関数                                                        |
//+——————————————————————+
void OnTimer()
{
//—
// ハンドラ本体が空なので何もしない
}
//+——————————————————————+

タイマパラメータ(タイマーイベントの時間軸)の異なる値でテスト時間の測定が取られました。取得されたデータを使用して、テスト時間をタイマー時間軸の関数としてプロットします。

タイマー時間軸の関数としてのテスト時間

timer パラメータが小さいほど、EventSetTimer(Timer) 関数の初期化中の OnTimer() ハンドラの呼び出しの間隔が小さく、テスト時間 T が大きいことが明確です。

ストラテジーテスターーでの Sleep() 関数 #

Sleep() 関数は、グラフを操作する場合、エキスパートアドバイザーまたはスクリプトがしばらくの間 MQL5 プログラムの実行を中断することを可能にします。これは、リクエスト時にデータが準備されてなく準備が出来るまで待つ必要がある場合に便利です。Sleep() 関数の繊細な使用例は データーアクセスの整理セクションでみられます。

テストプロセスは Sleep() の呼び出しで滞ることはありません。Sleep() が呼び出されると生成されたティックは指定された遅延以内に「プレイ」され、未決注文やストップのトリガになるかもしれません。Sleep() の呼び出し後に、ストラテジーテスターでのシミュレート時刻は Sleep 関数のパラメータで指定された時間分進みます。

Sleep() 関数の実行結果として、ストラテジーテスターで現在時刻がテスト期間を超えてしまった場合は、「Infinite Sleep loop detected while testing(テスト中に無限スリープループが検出されました)」とのエラーを受け取ることになります。このエラーが受け取られた場合、テスト結果は拒否されず、全ての計算は全体(取引数、沈下など)にわたって行われ、テスト結果は端末に渡されます。

OnDeinit() の呼び出しは、テスト期間の範囲を超えることが保証されるため、Sleep() 関数は OnDeinit() では動作しません。

MetaTrader 5 端末で Sleep() 関数を使用する方式

数値計算や最適化問題のためのストラテジーテスターーの使用 #

MetaTrader 5 端末のテスタは、取引ストラテジーテストにだけでなく数学的な計算のためにも使用することが出来ます。使用するには「数値計算」モードの選択が必要です。

math_calculations

この場合、OnInit()、OnTester()、OnDeinit() の 3 つの関数のみが呼ばれます。「数値計算」モードでは、ストラテジーテスターは、いかなるティックも生成せず履歴もダウンロードしません。

終了日より後日の開始日を指定された場合も、ストラテジーテスター「数値計算」モードで動作されます。

数学問題の解決にテスタを使用する場合は、履歴のアップロードとティックの生成は起こりません。

多変数関数の極値を探すことは MetaTrader 5 ストラテジーテスターで解決する典型的な数学の問題です。

解決するには

  • 関数値の計算は OnTester() 関数に位置するべきです。
  • 関数のパラメータはエキスパートアドバイザーの入力変数として定義されるべきです。

エキスパートアドバイザーをコンパイルして「ストラテジーテスター」ウィンドウを開きます。「パラメータ」タブで必要な入力パラメータを選択し、各関数変数のスタート、ストップ、及びステップ値を指定してパラメータセットの値を定義します。

「設定」タブの「オプティマイズ」(最適化の種類)で、「完全アルゴリズム(低速)」または「遺伝的アルゴリズム(高速)」を選びます。関数の極値の簡単な検索のためには、高速な最適化を選択した方が良いですが、変数のセット全体の値を計算する場合は、時間をかけた最適化を使用するのが最適です。

「数値計算」モードを選び「スタート」ボタンを使用して最適化の実行をします。ストラテジーテスターは最適化中に OnTester 関数の極大値を検索することにご注目ください。極小値を見つけるには OnTester 関数で計算された関数値の逆数を返します。

return(1/function_value);

ゼロ除算による重大なエラーの取得を回避するために function_value がゼロでないことを確認する必要があります。

この記事の読者によって示唆された、より便利で最適化の結果を歪めない別方法があります。

return(-function_value);

このオプションは function_value がゼロに等しいかどうかの確認を必要とせず、3次元表現における最適化の結果の面は同じ図形を有します。違いは、これがオリジナルのミラーリングということです。

例として sink() 関数を提供します。

sink_formula

極値を見つけるためのエキスパートアドバイザーのコードは OnTester() に配置されます。

//+——————————————————————+
//|                                                         Sink.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.MQL5.com |
//+——————————————————————+
#property copyright “Copyright 2011, MetaQuotes Software Corp.”
#property link     “https://www.MQL5.com”
#property version   “1.00”
//— 入力パラメータ
input double   x=-3.0; // スタート= -3、ステップ = 0.05、ストップ = 3
input double   y=-3.0; // スタート = -3、ステップ = 0.05、ストップ = 3
//+——————————————————————+
//| テスタ関数                                                  |
//+——————————————————————+
double OnTester()
{
//—
double sink=MathSin(x*x+y*y);
//—
return(sink);
}
//+——————————————————————+

最適化をして、最適化の結果 を 2D グラフで見ましょう。

2D グラフでみる sink (x*x+y*y) 関数の完全な最適化の結果

より良い値が与えられた(x、y)パラメータの組はより飽和した色を持ちます。sink() 式の形の観点から期待されたように、その値は( 0, 0 )を中心とする同心円を形成しています。関数は、単一の最大値・最小値を持っていないことは 3D グラフで見ることが出来ます。

3D Graph of Sink 関数の 3D グラフ

「始値のみ」モードでのバーの同期 #

MetaTrader 5 クライエント端末のテスタは、いわゆる「多通貨」エキスパートアドバイザーをチェックすることが出来ます。多通貨エキスパートアドバイザーとは 2 つ以上のシンボルで売買をするエキスパートアドバイザーです。

複数のシンボルを売買するストラテジーのテストは、テスタにいくつかの追加的な技術要件を課しています。

  • シンボルのティック生成
  • シンボル指標値の計算
  • シンボルの証拠金要件の計算
  • 全ての取引シンボルの生成されたティックシーケンスの同期

ストラテジーテスターは、ティックを生成し選択された取引モードに応じて各金融製品のためにティックシーケンスを再生します。同時に、他のシンボルにどのようにバーが開いたかに関係なく、それぞれのシンボルに新しいバーが開かれます。これは、多通貨エキスパートアドバイザーのテスト時に、ある製品では新しい足が既に開かれていても他の製品では開かれていないという状態が発生する可能性がある(実際によくあります)ことを意味します。よって、テストでも現実のように事が起こります。

テスタでのこの本格的な履歴シミュレーションは「全ティック」及び「1分足 OHLC」テストモードが使用されている限り問題を発生することはありません。これらのモードでは、1 つのローソク足に充分なティックが生成され、異なるシンボルのバーの同期まで待つことが出来ます。しかし、金融製品の取引でのバーの同期が必須である場合、多通貨ストラテジーは「始値のみ」モードではどのようにテストされるのでしょうか。このモードでは、エキスパートアドバイザーはバーのオープン時に対応する 1 つのティックのみで呼ばれています。

例を使用して説明します。 EURUSD のエキスパートアドバイザーがテストされていて、1 時間足が EURUSD で開いたとします。この事実は簡単に認識出来ます。「始値のみ」モードでは NewTick イベントはテスト期間のバーのオープン時に対応します。しかし、エキスパートアドバイザーで使用されている USDJPY 上で開いたローソク足について保証するものではありません。

通常の状況では OnTick() 関数の操作を完了して次のティックでの新しい USDJPY バーの出現を確認するので充分です。しかし「始値のみ」モードでのテストでは他のティックが存在しないので、このモードは多通貨エキスパートアドバイザーのテストには向いていないように見えるかもしれません。しかし、これはそうではありません。MetaTrader 5 のテスタは現実そっくりに動作することを忘れてはいけません。Sleep() を使用して新しいバーが別のシンボルに開かれるまで待てばいいのです。

「始値のみ」モードでのバー同期化を示すエキスパートアドバイザーの Synchronize_Bars_Use_Sleep.mq5 のコード

//+——————————————————————+
//|                                   Synchronize_Bars_Use_Sleep.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.MQL5.com |
//+——————————————————————+
#property copyright “Copyright 2011, MetaQuotes Software Corp.”
#property link     “https://www.MQL5.com”
#property version   “1.00”
//— 入力パラメータ
input string   other_symbol=“USDJPY”;
//+——————————————————————+
//| エキスパート初期化に使用される関数                                   |
//+——————————————————————+
int OnInit()
{
//— シンボルをチェックする
if(_Symbol==other_symbol)
{
PrintFormat(“You have to specify the other symbol in input parameters or select other symbol in Strategy Tester!”);
//— 強制的なテスト終了
return(INIT_PARAMETERS_INCORRECT);
}
//—
return(INIT_SUCCEEDED);
}
//+——————————————————————+
//| エキスパートティック関数                                             |
//+——————————————————————+
void OnTick()
{
//— 最後のバーの時刻の格納に使用される静的変数
static datetime last_bar_time=0;
//— 同期化フラグ
static bool synchonized=false;
//— 静的変数が初期化されていない場合
if(last_bar_time==0)
{
//— 始めての呼び出し。バーを保存して終了する。
last_bar_time=(datetime)SeriesInfoInteger(_Symbol,Period(),SERIES_LASTBAR_DATE);
PrintFormat(“The last_bar_time variable is initialized with value %s”,TimeToString(last_bar_time));
}
//— チャートシンボルの最後のバーの開始時刻を取得する
datetime curr_time=(datetime)SeriesInfoInteger(Symbol(),Period(),SERIES_LASTBAR_DATE);
//— 時刻が異なる場合
if(curr_time!=last_bar_time)
{
//— バーの開始時刻を静的変数に保存する
last_bar_time=curr_time;
//— 同期されていない
synchonized=false;
//— メッセージを出力する
PrintFormat(“A new bar has appeared on symbol %s at %s”,_Symbol,TimeToString(TimeCurrent()));
}
//— 他のシンボルのバーの開始時刻
datetime other_time;
//—他のシンボルの開始時刻が curr_time になるまで反復する
while(!(curr_time==(other_time=(datetime)SeriesInfoInteger(other_symbol,Period(),SERIES_LASTBAR_DATE)) && !synchonized))
{
PrintFormat(“Waiting 5 seconds..”);
//— 5 秒待ってSeriesInfoInteger(other_symbol,Period(),SERIES_LASTBAR_DATE) を呼び出す
Sleep(5000);
}
//— バーは同期されている
synchonized=true;
PrintFormat(“Open bar time of the chart symbol %s: is %s”,_Symbol,TimeToString(last_bar_time));
PrintFormat(“Open bar time of the symbol %s: is %s”,other_symbol,TimeToString(other_time));
//— TimeCurrent() は役立たないので TimeTradeServer() を使用する
Print(“The bars are synchronized at “,TimeToString(TimeTradeServer(),TIME_SECONDS));
}
//+——————————————————————+

同期の事実が確立された時、現在の時刻を表示するエキスパートアドバイザーの最後の行にご注目ください。

  Print(“The bars synchronized at “,TimeToString(TimeTradeServer(),TIME_SECONDS));

現在時刻の表示には TimeCurrent() の代わりに TimeTradeServer() 関数を使用しました。TimeCurrent() 関数は Sleep() の使用後に変更されない最後のティックの時刻を返します。「始値のみ」モードでエキスパートアドバイザーを実行すると、バーの同期に関するメッセージが表示されます。

Synchronize_Bars_Use_Sleep_EA

最後ティック到着時刻ではなく現在のサーバ時刻を取得する必要がある場合TimeCurrent() の代わりにTimeTradeServer() 関数を使用します。

バーを同期させるためには、タイマーを使用した別方法があります。そのよなエキスパートアドバイザーの例はこの記事に添付されている Synchronize_Bars_Use_OnTimer.mq5 です。

テスタの IndicatorRelease() 関数 #

単一のテストの完了後、機器のチャートが自動的に開かれ、完成した約定とエキスパートアドバイザーで使用される指標を表示します。これは、視覚的にエントリーポイントと終了ポイントをチェックして指標の値と比較するのに役立ちます。

注意事項: テスト終了時に自動に開くチャートに表示された指標は、テスト終了時に新たに計算されます。これらの指標がテストされたエキスパートアドバイザーで使用されていた場合にもです。

しかし、場合によって、プログラマが指標が取引アルゴリズムに関与された場合の情報を非表示にすることがあります。例えば、エキスパートアドバイザーのコードが、ソースコードなしの実行可能ファイルとしてレンタルまたは販売されている場合です。この場合 IndicatorRelease() 関数が適しています。

端末は、クライアント端末のディレクトリ/プロファイル/テンプレートでテンプレートの名称を tester.tpl と設定した場合、それが開かれたチャートに適用されます。それがない場合、デフォルトのテンプレートが適用されます。(default.tpl).

IndicatorRelease() 関数はもともと、不要になった場合指標の演算部を解放するのに意図されています。各ティックが指標計算を呼ぶので、メモリとCPU リソースの両方を保存することが出来ます。 その 2 つ目の目的は、単一のテストの実行後、テストチャートでの指標の表示を禁止することです。

テスト後に指標の表示を禁止するには IndicatorRelease() 関数を OnDeinit()ハンドラの指標ハンドルと呼びます。OnDeinit() 関数は、常にテスト完了後及びチャート表示前に呼び出されます。

//+——————————————————————+
//| エキスパート初期化解除に使用される関数                                 |
//+——————————————————————+
void OnDeinit(const int reason)
{
//—
bool hidden=IndicatorRelease(handle_ind);
if(hidden) Print(“IndicatorRelease() successfully completed”);
else Print(“IndicatorRelease() returned false. Error code “,GetLastError());
}

テスト後に指標の表示を禁止するには OnDeinit() ハンドラで IndicatorRelease() を呼びます。

テスタでのイベントハンドル #

MetaTrader 5 テスタで履歴データのテストをするにはエキスパートアドバイザーでの OnTick() ハンドラの存在は必須ではありません。エキスパートアドバイザーが下記の関数ハンドラの 1 つを持つことで充分です。

  • OnTick() – 新しいティック到着のイベントハンドラ
  • OnTrade() – 取引イベントハンドラ
  • OnTimer() – タイマからの信号到達のイベントハンドラ
  • OnChartEvent() – クライアントイベントハンドラ

エキスパートアドバイザーのテストでは、カスタムイベントは OnChartEvent() 関数で処理出来ますが、指標では、この関数はテスタで呼ぶことが出来ません。指標に OnChartEvent() イベントハンドラがあって指標がテストされたエキスパートアドバイザーに使用されていたとしても、指標自体はカスタムイベントを受け取りません。

テスト時に、指標は EventChartCustom() 関数を使用してカスタムイベントを作成することができ、エキスパートアドバイザーは個のイベントをOnChartEvent() で処理出来ます。

これらのイベントに加えて、ストラテジーテスターではテストと最適化のプロセスに関連する特別なイベントが生成されます。

  • Tester – このイベントはエキスパートアドバイザーの履歴データのテストの完了時に生成されます。Tester イベントは OnTester() 関数で処理されます。この関数は、エキスパートアドバイザーのテスト時にのみ使用でき、主に入力パラメータの遺伝的最適化のためのカスタム最大基準として使用される値の計算のために意図されています。
  • TesterInit – このイベントは、ストラテジーテスターでの最適化の一番初めのパスの開始時に発生します。TesterInit イベントは OnTesterInit() 関数で処理されます。最適化の開始時に、このハンドラを持つエキスパートアドバイザーは、テスタに指定されたシンボルと時間軸を持つ別の端末チャートに自動的に読み込まれ、TesterInit イベントを受け取ります。この関数は、更なる最適化結果の処理のために、最適化の開始前にエキスパートアドバイザーを開始するために使用されます。
  • TesterPass – このイベントは新しいデータ枠が受信された時に生成されます。TesterPass イベントは OnTesterPass() 関数で処理されます。このハンドラを持つエキスパートアドバイザーは、テストのために指定された銘柄/時間軸で別の端末のチャートに自動的に読み込まれ、最適化の間にフレームが受信された時にTesterPass イベントを受け取ります。この関数は、完了を待たずの「その場で」の最適化の結果の動的処理に使用されます。フレームは OnTester() ハンドラの単一パスの後で呼ばれる FrameAdd() 関数で追加されます。
  • TesterDeinit – このイベントは、ストラテジーテスターにおけるエキスパートアドバイザーの最適化の終了後に生成されます。TesterDeinit イベントは OnTesterDeinit() 関数で処理されます。このハンドラを持つエキスパートアドバイザーは、最適化の開始時に自動的にチャートに読み込まれ、終了後にTesterDeinit を受け取ります。この関数は最適化の結果の全ての最終処理に使用されます。

テストエージェント #

MetaTrader 5 クライエント端末でのテストはテストエージェントを使用して行われます。ローカルエージェントは自動的に作成されて有効にされます。ローカルオブジェクトのデフォルト数は、コンピュータ内のコアの数に対応しています。

それぞれのテストエージェントはクライエント端末と関係なく独自のグローバル変数のコピーを持ちます。端末自体は、ローカル及び遠隔エージェントにタスクを分散するディスパッチャです。エキスパートアドバイザーのテストの作業を実行した後、エージェントは指定されたパラメータで端末に結果を返します。単一のテストには、単一のエージェントが使用されます。

端末から受信された履歴はエージェントによって製品の名称を使用した別々のフォルダに保存されるので、EURUSD の履歴はEURUSD という名称のフォルダに保存されます。また、金融製品の履歴は、そのソースによって分類されています。履歴は以下のように保存されます。

tester_catalogAgent-IPaddress-Portbasesname_sourcehistorysymbol_name

例えば MetaQuotes-Demo サーバからの EURUSD の履歴は tester_catalogAgent-127.0.0.1-3000basesMetaQuotes-DemoEURUSD fフォルダに保存されます。

ローカルエージェントは、テストの完了後に次の呼び出しのために立ち上げに時間を無駄にしないように、次のタスクを待って5分間スタンバイモードに入ります。待機期間が終わって初めてローカルエージェントはシャットダウンし CPU メモリからアンロードされます。

ユーザがテストを早期終了(「キャンセル」ボタン)した場合やクライアント端末が閉じられた場合、全てのローカルエージェントはすぐに作業を停止しメモリからアンロードされます。

端末とエージェントの間でのデータ交換 #

テスト実行時に、クライアント端末はエージェントに送信するパラメータブロックをいくつか用意します。

  • テストの入力パラメータ(シミュレーションモード、テスト、金融製品、最適化基準等の間隔など)
  • 「気配値表示」で選択されたシンボルのリスト
  • シンボルテストの仕様(契約サイズ、決済逆指値及び決済指値を設定するための市場からの許容補償金)
  • テストされるエキスパートアドバイザーと入力パラメータの値
  • 追加的なファイルの情報(ライブラリ、指標、データファイル – # property tester_ …)

tester_indicator

string

「indicator_name.ex5」形式でのカスタム指標の名称テストが必要な指標は対応するパラメータが定数文字列で設定されている場合 iCustom() 関数の呼び出しで自動的に定義されます。それ以外は全て( IndicatorCreate() 関数の使用または指標銘を設定するパラメータでの非定数文字列の使用)このプロパティは必須です。

tester_file

string

テスタのファイル名。二重引用符内で拡張子の表示も含みます(文字列定数)。指定されたファイルはテスタに渡されます。テストされるべき入力ファイルがある場合、指定が必ず必要です。

tester_library

string

二重引用符内で拡張子を含むライブラリ名。ライブラリは拡張子として dll または ex5 を持つことが出来ます。テストを必要とするライブラリは自動的に定義されます。しかし、ライブラリがカスタム指標で使用された場合、このプロパティは必須です。

パラメータの各ブロックで、MD5 ハッシュ形式のデジタル指紋が作成されてエージェントに送信されます。MD5 ハッシュは、基づいて計算された情報の量よりもはるかに小さく、セットごとに一意です。

エージェントは、ブロックのハッシュを受信し、既に持っているものと比較します。与えられたパラメータブロックの指紋がエージェントに存在しない、または受信したハッシュが、既存のものと異なる場合、エージェントは、このパラメータのブロックを要求します。これによって、端末とエージェント間のトラフィックが減少します。

テスト後にエージェントは「テスト結果」と「最適化の結果」タブに表示される、受信利益、約定数、シャープ係数、OnTester() 関数の結果などの実行結果をプラットフォームに返します。

最適化中に、端末はエージェントにテスト作業を小型パッケージで渡し、それぞれのパッケージにはいくつかのタスクが含まれています(ここで、それぞれのタスクとは、入力パラメータのセットを持つ単一のテストを意味します。)。これは、端末とエージェント間の交換時間を短縮します。

エージェントは、セキュリティ上の理由のため、端末から取得した EX5 ファイル(エキスパートアドバイザー、指標、ライブラリなど)をハードディスクに記録することはありません。実行中のエージェントを持つコンピュータが送信したデータを使用することが出来ないようにです。DLL を含んだ他の全てのファイルはサンドボックスに記録されます。遠隔エージェントではDLL を使用してのエキスパートアドバイザーのテストは出来ません。

テスト結果は、必要な時に迅速にアクセス出来るように、端末によって結果の特別なキャッシュ(結果キャッシュ)に追加されます。再実行を回避するために、端末はパラメータのセットごとに以前の実行からの既に入手可能な結果を結果キャッシュ内で検索します。この様なパラメータセットで結果が見つからない場合、エージェントにテスト実行タスクが与えられます。<

端末とエージェントの間のトラフィックは全て暗号化されます。

ティックはネットワーク経由で送信されず、テストエージェント上で生成されます。

全てのクライアント端末の共有フォルダの使用 #

全てのテストエージェントは、互いから、またクライアント端末から単離されています。各エージェントは、ログが記録されている独自のフォルダを持っています。また、テスト中のエージェントのファイル操作の全てはagent_name/MQL5/Files フォルダで行われます。しかし、ファイルのオープン時に FILE_COMMON フラグを指定された場合、クライアント端末の全てに共有フォルダを介してローカルエージェントとクライアント端末間の相互作用を実現することが出来ます。

//+——————————————————————+
//| エキスパート初期化に使用される関数                                   |
//+——————————————————————+
int OnInit()
{
//— 全てのクライアント端末の共有フォルダの使用
common_folder=TerminalInfoString(TERMINAL_COMMONDATA_PATH);
//— このフォルダの名称を書く
PrintFormat(“Open the file in the shared folder of the client terminals %s”, common_folder);
//— ファイルを共通フォルダで開く( FILE_COMMON フラッグで示される)
handle=FileOpen(filename,FILE_WRITE|FILE_READ|FILE_COMMON);
… 更なるアクション
//—
return(INIT_SUCCEEDED);
}

DLL の使用 #

最適化を速めるために、ローカルだけではなく遠隔エージェントも利用出来ます。この場合、遠隔エージェントにはいくつかの制限があります。まず第一に、遠隔エージェントはログにポジションの開閉に関する Print() 関数実行の結果を表示しません。間違って書かれたエキスパートアドバイザーが、遠隔エージェントに使用されているコンピューターをメッセージで破壊しないように、ログには最小限の情報が表示されます。

2 番目の制限はエキスパートアドバイザーのテストで DLL が使用出来ないことです。セキュリティ上の理由から、遠隔エージェントでの DLL の呼び出しは絶対禁止となっています。ローカルエージェントでは、エキスパートアドバイザーのテストでの DLL の呼び出しは、適切な「インポートDLLを許可」でのみ許可されています。

MQL5 プログラムの「インポートDLLを許可」オプション

注意事項: DLL 呼び出しを必要とするサードパーティーのエキスパートアドバイザー(スクリプト、指標)の使用にあたって、端末の設定でこのオプションを許可する場合にとるリスクには注意するべきです。エキスパートアドバイザーがどのように(テストまたはチャートでの実行)使用されるかには関係なくです。

 

Originally posted 2019-07-29 22:53:32.

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">