TesterStop関数の働き・役割
TesterStop関数は、ストラテジーテスターでのEAテスト中にプログラム操作でテストを終了するために使用されます。この関数を呼び出すことで、特定の条件が満たされた場合、テストを早期にシャットダウンし、時間の節約やリスクの低減が可能になります。
通常、特定のドローダウンレベルや連続する損失回数に達したときに呼び出され、テストの正常終了と見なされます。そのため、終了後にOnTester関数が呼び出され、累積取引統計や最適化基準の値がストラテジーテスターに送信されます。
ExpertRemove関数もテストの終了が可能ですが、EAがメモリから取り除かれるため、テストを再度開始するにはパラメータセットの次のパスを実行する必要があります。このため、テストの早期終了のための効率的な手段としてTesterStop関数が推奨されます。
補足:ドローダウンとは?
ドローダウンとは、投資やトレードにおいて、口座残高や資本が一時的に減少することを指します。特に、口座の資金が過去のピーク(最大値)からどれだけ下がったかを測定することで、運用のリスクや資金管理の重要性を把握するための指標になります。
トレードでは、利益を上げるだけでなく、損失をいかに小さく抑えるかも重要です。ドローダウンを監視することで、ポジションがどれだけ損失に耐えられるかを管理でき、資金の大幅な減少を防ぐためのリスクコントロールが行えます。
絶対ドローダウン
絶対ドローダウンは、口座の初期残高からの最大損失額を示します。例えば、初期資金が10,000ドルで、その後に残高が9,000ドルまで下がった場合、絶対ドローダウンは1,000ドルです。この指標は、運用開始時の基準額(初期残高)に対する損失幅を確認するのに役立ちます。
相対ドローダウン
相対ドローダウンは、運用の中で過去最高の残高(ピーク)から、どれだけ資金が減少したかを示します。例えば、最高残高が12,000ドルで、その後に残高が9,000ドルまで下がった場合、相対ドローダウンは3,000ドルです。これは運用過程での資金の減少幅を示す指標であり、利益が積み上がった後のリスクを把握するのに有効です。
ドローダウンは、損失リスクの大きさを示す重要な指標であり、リスク管理や資金管理において特に注視されます。
TesterStop関数の引数について
void TesterStop();
TesterStop関数は引数を取らない関数です。特定の状況でテストを早期に終了するために使用され、テスト実行中に直接呼び出して実行されます。
TesterStop関数の戻り値について
TesterStop関数には戻り値がありません。この関数の実行によってテストは即座に終了され、テスト終了後にはOnTester関数が呼び出されて取引統計や最適化基準がストラテジーテスターに送信されます。
TesterStop関数を使う際の注意点
TesterStop関数を使用する際は、特定の状況でテストが正常に終了すると見なされるため、その結果としてOnTester関数が呼び出され、累積取引統計や最適化基準の値がストラテジーテスターに送信されます。これにより、テスト結果の集計がスムーズに進み、テスト終了後の評価が容易になります。
テストを終了する他の手段としてExpertRemove関数もありますが、これはEAをメモリから取り除かれる為、次のパラメータセットのテストを再実行する必要があります。一方で、TesterStop関数ではエージェントのメモリ上にプログラムが残るため、効率よくテストを進行することが可能です。
TesterStop関数を適切に機能させるためには、あらかじめテストの終了条件を明確に設定することが重要です。たとえば、残高のドローダウンが特定の値を下回る、または連続する損失回数が一定数を超えるなどの条件を設定し、これに基づいてTesterStop関数を呼び出すことで、効率的で正確なテストを行うことができます。
TesterStop関数を使ったサンプルコード
//--- define
#define BALANCE_LOSS_STOP 100.0 // 残高が指定ドローダウン以上に減少した場合にテストを停止する閾値
#define EQUITY_LOSS_STOP 100.0 // 資本が指定ドローダウン以上に減少した場合にテストを停止する閾値
//--- 必要なライブラリをインクルードする
#include <Trade\Trade.mqh> // 取引機能のライブラリ、CTradeクラスを使用
#include <Trade\SymbolInfo.mqh> // シンボル情報のライブラリ、CSymbolInfoクラスを使用
#include <Trade\PositionInfo.mqh> // ポジション情報のライブラリ
#include <Trade\AccountInfo.mqh> // アカウント情報のライブラリ、CAccountInfoクラスを使用
//--- 入力パラメータ
input double InpLots = 0.1; // ロット数の入力パラメータ
input uint InpStopLoss = 50; // ポイント単位のストップロス
input uint InpTakeProfit = 150; // ポイント単位のテイクプロフィット
input ulong InpMagic = 123; // マジックナンバー(注文識別用)
input ulong InpDeviation = 5; // 発注時の価格の偏差(許容範囲)
//--- グローバル変数
CTrade trade; // 取引クラスのインスタンス
CSymbolInfo symb; // 銘柄クラスのインスタンス
CAccountInfo account; // 取引口座クラスのインスタンス
double balance_prev; // 前回の残高を保存するための変数
double equity_prev; // 前回の資本(エクイティ)を保存するための変数
//+------------------------------------------------------------------+
//| エキスパート初期化関数 |
//+------------------------------------------------------------------+
int OnInit()
{
//--- 初期残高と資本を取得
balance_prev = account.Balance(); // 初期残高をbalance_prevに格納
equity_prev = account.Equity(); // 初期資本をequity_prevに格納
//--- 正常な初期化
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| エキスパートティック関数 |
//+------------------------------------------------------------------+
void OnTick()
{
//--- 現在の相場を更新する
if(!symb.RefreshRates()) // 銘柄情報を最新の状態にリフレッシュ
return;
//--- 残高または資本がBALANCE_LOSS_STOPおよびEQUITY_LOSS_STOP以上に減少した場合
//--- テストは失敗したとみなされ、TesterStop関数が呼び出される
//--- 残高の損失を確認し、BALANCE_LOSS_STOPを超える減少が発生した場合に停止
if(balance_prev != account.Balance()) // 前回と残高が異なるか確認
{
if(account.Balance() < balance_prev - BALANCE_LOSS_STOP) // 指定の損失閾値を超えているか確認
{
PrintFormat("初期残高 %.2f %s から %.2f %s 減少し、現在の残高は %.2f %s です。テストを停止します。",
balance_prev, account.Currency(),
balance_prev - account.Balance(), account.Currency(),
account.Balance(), account.Currency());
TesterStop(); // テストを停止
}
balance_prev = account.Balance(); // 現在の残高を更新
}
//--- 資本の損失を確認し、EQUITY_LOSS_STOPを超える減少が発生した場合に停止
if(equity_prev != account.Equity()) // 前回と資本が異なるか確認
{
if(account.Equity() < equity_prev - EQUITY_LOSS_STOP) // 指定の損失閾値を超えているか確認
{
PrintFormat("初期資本 %.2f %s から %.2f %s 減少し、現在の資本は %.2f %s です。テストを停止します。",
equity_prev, account.Currency(),
equity_prev - account.Equity(), account.Currency(),
account.Equity(), account.Currency());
TesterStop(); // テストを停止
}
equity_prev = account.Equity(); // 現在の資本を更新
}
}
このコードは、エキスパートアドバイザーが稼働中の取引口座の残高(確定済み取引の損益を反映した金額)と資本(エクイティ:未決済ポジションの評価損益を含めた実際の口座資金)をリアルタイムで監視し、指定したドローダウン閾値を超える減少が発生した場合、ストラテジーテスターでのテストを早期に停止します。
初期化時に残高と資本の初期値を取得し、価格が更新されるたびに最新の残高・資本と比較します。閾値を超えた減少を検知すると、テストの終了命令を発行するため、資金リスクをコントロールしながら効率的にテストを進行できます。
サンプルコード解説1:define命令とinclude命令部分
//--- define
#define BALANCE_LOSS_STOP 100.0 // 残高が指定ドローダウン以上に減少した場合にテストを停止する閾値
#define EQUITY_LOSS_STOP 100.0 // 資本が指定ドローダウン以上に減少した場合にテストを停止する閾値
//--- 必要なライブラリをインクルードする
#include <Trade\Trade.mqh> // 取引機能のライブラリ、CTradeクラスを使用
#include <Trade\SymbolInfo.mqh> // シンボル情報のライブラリ、CSymbolInfoクラスを使用
#include <Trade\PositionInfo.mqh> // ポジション情報のライブラリ
#include <Trade\AccountInfo.mqh> // アカウント情報のライブラリ、CAccountInfoクラスを使用
このコードの冒頭では、define命令とinclude命令が使われています。
まず、define命令は「BALANCE_LOSS_STOP」と「EQUITY_LOSS_STOP」という2つの定数を設定します。これらの定数は、テストの途中で残高(確定済み取引の損益を反映した金額)や資本(エクイティ:未決済ポジションの評価損益を含めた実際の口座資金)が設定値以上に減少した場合、テストを停止するための基準値です。具体的には、100.0(通貨単位)までの損失が発生するとテストが終了するよう設定されています。
次に、include命令は、MQL5の標準ライブラリをインポートするために使用されます。これにより、CTrade、CSymbolInfo、CPositionInfo、CAccountInfoなどの取引管理に関するクラスが使えるようになります。それぞれのライブラリは、以下のような機能を提供します。
- Trade.mqh: 取引機能を提供するCTradeクラスをインポートし、取引執行やポジション管理が可能になります。
- SymbolInfo.mqh: シンボル情報を取得するためのCSymbolInfoクラスをインポートし、取引に使用する銘柄の情報を取得・管理します。
- PositionInfo.mqh: ポジション情報にアクセスするCPositionInfoクラスをインポートし、保有ポジションの詳細な管理や取得を行います。
- AccountInfo.mqh: アカウント情報の管理を行うCAccountInfoクラスをインポートし、取引口座に関する情報を取得・管理します。
これらのライブラリをインポートすることで、取引に必要な口座・シンボル・ポジション情報のアクセスが容易になり、テストの自動化や管理がシンプルかつ効率的に行えます。
サンプルコード解説2:input変数とグローバル変数部分
//--- 入力パラメータ
input double InpLots = 0.1; // ロット数の入力パラメータ
input uint InpStopLoss = 50; // ポイント単位のストップロス
input uint InpTakeProfit = 150; // ポイント単位のテイクプロフィット
input ulong InpMagic = 123; // マジックナンバー(注文識別用)
input ulong InpDeviation = 5; // 発注時の価格の偏差(許容範囲)
//--- グローバル変数
CTrade trade; // 取引クラスのインスタンス
CSymbolInfo symb; // 銘柄クラスのインスタンス
CAccountInfo account; // 取引口座クラスのインスタンス
double balance_prev; // 前回の残高を保存するための変数
double equity_prev; // 前回の資本(エクイティ)を保存するための変数
このコードでは、input変数とグローバル変数を設定しています。input変数はエキスパートアドバイザー(EA)の操作時にユーザーが調整可能なパラメータを定義し、グローバル変数はEA全体で使用する必要のある変数を定義しています。
まず、input変数は以下の5つです。
- InpLots: ロット数の指定で、取引の単位量を設定します。
- InpStopLoss: ストップロスのポイント数で、損失が指定値に達したときにポジションを自動的に決済します。
- InpTakeProfit: テイクプロフィットのポイント数で、利益が指定値に達したときにポジションを決済します。
- InpMagic: マジックナンバーで、注文を識別するために使われるユニークな番号です。
- InpDeviation: 発注時の価格の偏差(許容範囲)で、指定した価格からの許容スリッページ範囲を設定します。
次に、グローバル変数には以下の5つがあります。
- trade: CTradeクラスのインスタンスで、注文の執行や管理を行うために使用されます。
- symb: CSymbolInfoクラスのインスタンスで、取引対象のシンボル(通貨ペアや銘柄)情報を取得します。
- account: CAccountInfoクラスのインスタンスで、口座残高や資本などの情報を管理します。
- balance_prev: 前回の残高を保存するための変数で、ドローダウンを監視するために初期残高を記録します。
- equity_prev: 前回の資本を保存するための変数で、資本のドローダウン監視に使用されます。
これらの変数を使うことで、EAは取引のルールに従い、残高や資本に基づくリスク管理を行いながらテストや自動売買を実行します。
サンプルコード解説3:OnInit関数部分
//+------------------------------------------------------------------+
//| エキスパート初期化関数 |
//+------------------------------------------------------------------+
int OnInit()
{
//--- 初期残高と資本を取得
balance_prev = account.Balance(); // 初期残高をbalance_prevに格納
equity_prev = account.Equity(); // 初期資本をequity_prevに格納
//--- 正常な初期化
return(INIT_SUCCEEDED);
}
OnInit関数は、エキスパートアドバイザー(EA)が初めて実行されたときに1回だけ呼び出される初期化関数です。この関数内では、テスト開始時点での残高と資本の初期値を取得して変数に格納し、ドローダウンの監視に備えます。
まず、balance_prevに取引口座の初期残高を取得し、これを保存します。balance_prevは今後、ドローダウン監視の基準として使われ、現在の残高と比較する際に参照されます。同様に、equity_prevには初期の資本(エクイティ)を格納します。資本は未決済ポジションの評価損益を含む口座の総資金であり、残高と同様にドローダウンの監視に役立ちます。
最後に、正常な初期化が行われたことを示すINIT_SUCCEEDEDを返します。この戻り値によって、EAの初期化が問題なく完了したことが確認され、以降の動作を開始できるようになります。
OnInit関数内で使用されているBalanceメソッドとEquityメソッドは、口座の基本的な資金情報を取得するために使用されます。どちらもCAccountInfoクラスに属しており、以下のような働きを持ちます。
- Balanceメソッド
取引口座の「残高」を取得するメソッドです。残高はすでに確定した取引の損益が反映された金額であり、未決済ポジションの評価損益は含みません。つまり、現在の取引が行われる前の口座資金が分かるため、取引開始前の状態を基準にリスク管理を行う際に重要です。 - Equityメソッド
取引口座の「資本」を取得するメソッドです。資本は、残高に加えて、未決済ポジションの評価益・評価損を含む口座の総資金を表します。そのため、現在のポジションを含めた口座の実際の資金状況をリアルタイムで把握できます。
OnInit関数では、初期の残高と資本をそれぞれbalance_prevとequity_prevに保存することで、後続の取引におけるドローダウンの監視やリスク管理を効率的に行えるようにしています。
サンプルコード解説4:OnTick関数部分その1
void OnTick()
{
//--- 現在の相場を更新する
if(!symb.RefreshRates()) // 銘柄情報を最新の状態にリフレッシュ
return;
//--- 残高または資本がBALANCE_LOSS_STOPおよびEQUITY_LOSS_STOP以上に減少した場合
//--- テストは失敗したとみなされ、TesterStop関数が呼び出される
OnTick関数は、新しいティック(価格変動の更新)が発生するたびに実行される関数です。主に現在の相場情報を更新し、指定したドローダウンの条件に基づいてテストを早期に停止するかどうかを判断する役割を持っています。
まず、symb.RefreshRatesメソッドを使い、シンボル(銘柄)情報を最新の状態に更新します。これにより、取引に必要な価格やその他の情報が最新の状態で取得され、正確な判断が行えるようになります。もし更新に失敗した場合はreturnで関数を終了します。
サンプルコード解説5:OnTick関数部分その2
//--- 残高の損失を確認し、BALANCE_LOSS_STOPを超える減少が発生した場合に停止
if(balance_prev != account.Balance()) // 前回と残高が異なるか確認
{
if(account.Balance() < balance_prev - BALANCE_LOSS_STOP) // 指定の損失閾値を超えているか確認
{
PrintFormat("初期残高 %.2f %s から %.2f %s 減少し、現在の残高は %.2f %s です。テストを停止します。",
balance_prev, account.Currency(),
balance_prev - account.Balance(), account.Currency(),
account.Balance(), account.Currency());
TesterStop(); // テストを停止
}
balance_prev = account.Balance(); // 現在の残高を更新
}
この部分では、変数balance_prevおよびaccount.Balanceメソッドを使って、残高の変動を監視し、指定した損失の閾値(BALANCE_LOSS_STOP)を超えた場合にテストを停止する処理を行います。
まず、前回の残高を示すbalance_prevと現在の残高を示すaccount.Balanceメソッドが異なるかどうかを確認します。このチェックにより、前回からの残高の変化が検出されると次の処理に進みます。
次に、現在の残高であるaccount.Balanceが「初期残高 – BALANCE_LOSS_STOP」の閾値よりも小さいかを確認します。この条件を満たす場合、指定の損失限度を超えたと見なし、PrintFormat関数を使用して、初期残高であるbalance_prev、損失額、現在の残高などの情報を出力します。これにより、ドローダウンが発生したことをユーザーが確認できるようになります。
PrintFormat関数のフォーマット指定子と対応値の解説
PrintFormat関数の中では、特定の形式で出力するためにフォーマット指定子を用いています。フォーマット指定子には「%.2f」と「%s」が含まれており、対応する値は以下の通りです。
- %.2f
小数点以下2桁までの浮動小数点数を表します。ここでは、残高や損失額などの金額を「1234.56」のような形式で表示します。具体的には、balance_prev(初期残高)、balance_prev – account.Balance(損失額)、およびaccount.Balance(現在の残高)に対応しています。 - %s
文字列を表します。ここでは、口座通貨の単位(USDなど)を表示するために使用され、account.Currencyに対応しています。
このようにフォーマット指定子を使用することで、各値が正確に整った形式で出力され、ユーザーにとって読みやすくわかりやすい出力が実現されます。
テスト停止と残高の更新
ドローダウンが検知された場合、テストを早期終了させるためにTesterStop関数が呼び出されます。また、処理の終わりでbalance_prevを現在の残高であるaccount.Balanceに更新し、次のティックで再度残高の変化を監視できるようにしています。
サンプルコード解説6:OnTick関数部分その3
//--- 資本の損失を確認し、EQUITY_LOSS_STOPを超える減少が発生した場合に停止
if(equity_prev != account.Equity()) // 前回と資本が異なるか確認
{
if(account.Equity() < equity_prev - EQUITY_LOSS_STOP) // 指定の損失閾値を超えているか確認
{
PrintFormat("初期資本 %.2f %s から %.2f %s 減少し、現在の資本は %.2f %s です。テストを停止します。",
equity_prev, account.Currency(),
equity_prev - account.Equity(), account.Currency(),
account.Equity(), account.Currency());
TesterStop(); // テストを停止
}
equity_prev = account.Equity(); // 現在の資本を更新
}
}
この部分では、変数equity_prevとaccount.Equityメソッドを使い、資本(エクイティ)の変動を監視し、指定した損失の閾値であるEQUITY_LOSS_STOPを超えた場合にテストを停止する処理を行います。
最初に、前回の資本であるequity_prevと現在の資本を表すaccount.Equityメソッドが異なるかどうかを確認します。前回と異なれば資本に変化が生じたことを意味するため、次の処理に進みます。
次に、現在の資本(account.Equity)が「初期資本 – EQUITY_LOSS_STOP」の閾値よりも小さいかを確認します。この条件を満たすと、設定した損失閾値を超えたと判断し、PrintFormat関数を使って、初期資本であるequity_prev、損失額、現在の資本を出力します。これにより、ドローダウンが発生したことをユーザーが確認できます。
PrintFormat関数のフォーマット指定子と対応値の解説
PrintFormat関数の中では、フォーマット指定子として「%.2f」と「%s」を使用しています。これらのフォーマット指定子と対応する値は以下の通りです。
- %.2f
小数点以下2桁までの浮動小数点数を表します。ここでは、初期資本、損失額、現在の資本を「1234.56」のような形式で表示します。具体的には、equity_prev(初期資本)、equity_prev – account.Equity(損失額)、およびaccount.Equity(現在の資本)に対応しています。 - %s
文字列を表します。ここでは、口座通貨の単位(USDなど)を表示するために使用され、account.Currencyに対応しています。
これにより、ドローダウンが発生した際に必要な情報が見やすく整った形式で出力され、ユーザーが資本の変化を理解しやすくなっています。
テスト停止と資本の更新
損失の閾値を超えた場合、テストを早期終了するためにTesterStop関数を呼び出します。また、最後にequity_prevを現在の資本であるaccount.Equityに更新し、次のティックで再度資本の変化を監視できるようにしています。