プロフィット引き出しモデル構築のためのTesterWithdrawal() 関数の使用
はじめに
投機的なトレーディングの目的は収益を得ることです。通常、トレードシステムが検証されると、次以外のすべての面が分析されます。生活のために、得た資金の一部を引き出すことです。トレーダーにとって、トレーディングだけが収入源でなかったとしても、トレード期間(月、四半期、年)について計画された収益に関する疑問は遅かれ早かれ持ち上がります。MQL5のTesterWithdrawal()関数はアカウントから資金の引出をエミュレートするための関数の一つです。
1. 何を確認することができるのか?
危険な状況で資金を越える引出しを示唆するトレーディングシステムやトレーディングに関する意見はあります。資本合計のほんの一部がトレードアカウントにあります。これは予測のつかない理由により資金をすべて失うことからの防御策です。
実際、それは資金管理戦略の一例です。資金管理のために投資を受け入れるファンドは、トレーダーに対して特定のクオーた(合計資本の一部)を与えますが、全資本は決してトレーダーに与えられません。または、オープンしているポジションボリュームの制限に追加して、トレーダーが動かすことのできり資本に制限を設けている、とも言えます。最終的に、トレーダーは危険をはらんだ投機には資産のほんの一部のみにアクセス可能なのです。
もうひとつ別の問題は検証中に得た資産の闘争的な再投資です。トレーダーは残高を得、最適化中にイクイティラインを持ち上げるのを目的としています。資金のレベルには一定のルールがあると解っていながらも、100ロットのトレーディングの際0.1ロットの収益性のあるシステムが良いと信じても意味はありません。
また、心理的問題もあります。活動中のトレーダーはトレーディングシステムの動作にアカウントの一定の資金レベルで干渉すると告白します。そうしないと約束しながらも。こういった視点から、超過分の引出はトレーディングにおいて 安定化要因です。
MQL5には、Expert Advisorの検証中に資金の引出をするための関数があります。次のセクションはその関数について述べられます。
2. 関数の使い方は?
TesterWithdrawal()関数はストラテジーテスタにおいてアカウントから資金を引き出すモデルを構築するものです。また、通常モードの Expert Advisorの動作には影響を与えません。
bool TesterWithdrawal(double money);
入力パラメータmoneyは預金通貨で引き出す資金の額を指定します。返される値から処理がうまくいったか確認することができます。検証中に行われる引き出し処理は、図1に示されているように、『ジャーナル』タブまたは『結果』タブの対応する入力で表示されます。
図1 検証中の成功的な資産引き出しに関するエントリー
引き出しサイズがフリーマージンサイズを超え、引き出しが行われない場合、以下のエントリーが『ジャーナル』に表示されます。
図2 検証中の成功的な資産引き出し処理に関するエントリー
この関数を呼ぶとき、現在残高および 資本のサイズは引き出された資金の額だけ減少します。ストラテジーテスタは収益と損失を計算する際、引き出しを考慮しません。ただ、図3のように7『引き出し』割合にて引き出しの合計額を計算します。
図3 報告上の引き出し合計額の割合
トレードアカウントに対する デポジット 資産の逆関数はまだMQL5にはなく、実装される予定もないことに留意が必要です。デポジットが常に増加することを要求するシステムを必要な人がいるでしょうか?
次の項では、トレード戦略実装だけでなく、ここに見られる関数を使用して資金の引き出しモデルを作成するためのツールキットについてもExpert Advisorの例を述べます。
3. 検証の実験台
ごくシンプルなExpert Advisorにおける検証を作成していきます。Expert Advisorの処理にご興味のある方は、下記にてそのトレードシステムの記述を参照いただけます。
価格の最大最低値は5Mデータにて指定の期間で計算を行います。それは PERIOD入力変数を使って設定されます。サポート(CalcLow変数)とレジスタンス(CalcHigh変数)ラインを伴う水平チャンネルから計算されたレベル指値注文はチャンネルの境界にセットされます。ゲームはチャンネルに突き刺してプレーされます。
指値注文は、チャンネル内でINSIDE_LEVEL 入力変数の値を下回らない範囲に価格があるときに出されます。また、指値注文はひとつだけ出され、一つの方向にオープンされます。
レベルの再計算時、チャンネルが狭くなり価格がまたその間にあると、指値注文は市場価格に近づきます。指値注文移動のステップはORDER_STEP入力変数を使って設定されます。
取引からの収益サイズはTAKE_PROFIT入力変数で指定され、最大損失はSTOP_LOSSにより指定されます。
Expert AdvisorはTRAILING_STOP 入力変数により指定されるステップによりストップロスを移動します。
固定ロット、デポジットのパーセンテージとして計算されたロットどちらでもトレードは可能です。ロット値はLOT入力変数を使って設定され、ロット計算メソッドは LOT_TYPE 変数を使って設定されます。ロット修正機能(LOT_CORRECTION = true)があります。固定ロットで取引を行い、サイズがポジションを開くのに許されている範囲を超えた場合、ロットサイズは許される最も近い値に修正されます。
Expert Advisorのアルゴリズムの調整には、ログを書く関数(WRITE_LOG_FILE = true)を使用できます。すべての取引処理に関するエントリーはテキストファイルlog.txtに書き込まれます。.
資金の引き出しを管理するのにExpert Advisorに 入力変数をいくつか追加します。
最初のパラメータは資産引き出しの可能性フラグとして使われます。
input bool WDR_ENABLE = true; // Allow withdrawal
二番目のパラメータは引き出し周期を決定します。
enum wdr_period { days = -2, // Day weeks = -1, // Week months = 1, // Month quarters = 3, // Quarter halfyears = 6, // Half a year years = 12 // Year };
input wdr_period WDR_PERIOD = weeks; // Periodicity of withdrawals三番目のパラメータは引き出し金額を設定します。
input double WDR_VALUE = 1; // Amount of money to be withdrawn
四番目のパラメータは引き出し金額の計算方法を決定します。
enum lot_type { fixed, // Fixed percent // Percentage of deposit };
input lot_type WDR_TYPE = percent; // Method of calculation of the withdrawal amount
アカウントから引き出す一回あたりの金額を計算するには wdr_valueが使われます。wdr_summa変数は引き出す合計金額の計算に使われます。
また、wdr_count変数によってうまく引き出し処理が行われた合計回数も計算します。これら変数の値は検証結果報告作成に必要となります。資金引き出しの全体機能は以下の関数で示されます。
//--- Function of withdrawing assets from the account //+------------------------------------------------------------------+ bool TimeOfWithDrawal() //+------------------------------------------------------------------+ { if(!WDR_ENABLE) return(false); // exit if withdrawal is prohibited if( tick.time > dt_debit + days_delay * DAY) // periodic withdrawals with specified period { dt_debit = dt_debit + days_delay * DAY; days_delay = Calc_Delay();// Updating the value of period-number of days between withdrawal operations if(WDR_TYPE == fixed) wdr_value = WDR_VALUE; else wdr_value = AccountInfoDouble(ACCOUNT_BALANCE) * 0.01 * WDR_VALUE; if(TesterWithdrawal(wdr_value)) { wdr_count++; wdr_summa = wdr_summa + wdr_value; return(true); } } return(false); }
ここから、Expert Advisorを最適化モードで検証する準備に入ります。最適化パラメータはいくつかあります。必要なパラメータを選択するのに使用する入力変数を宣言します。
enum opt_value { opt_total_wdr, // Total sum of withdrawal opt_edd_with_wdr, // Drawdown with consideration of withdrawal opt_edd_without_wdr // Drawdown without consideration of withdrawal };
input opt_value OPT_PARAM = opt_total_wdr; // Optimization by the parameter
また、Expert Advisorにもうひとつすばらしい関数を追加する必要があります。それは、OnTester()関数で、この関数が返す値が最適化基準を決定します。
//--- Displaying information about testing //+------------------------------------------------------------------+ double OnTester(void) //+------------------------------------------------------------------+ { //--- Calculation of parameters for the report CalculateSummary(initial_deposit); CalcEquityDrawdown(initial_deposit, true, false); //--- Creation of the report GenerateReportFile("report.txt"); //--- Returned value is the optimization criterion if (OPT_PARAM == opt_total_wdr) return(wdr_summa); else return(RelEquityDrawdownPercent); }
次の項ではExpert Advisorの検証について詳しく考察していきます。
4. Expert Advisorの検証
検証の統一のため、まずするべきことは、引き出し不能の関数にてExpert Advisorの検証結果を取得することです。そのためには、図5にあるように検証前に『引き出し許可』パラメータをfalseに設定します。
検証結果を繰り返すことにご興味のあるかたのために、Expert Advisorの設定と入力パラメータの値が下記の図4および図5にあります。
図4 Expert Advisor検証のための設定
図5 引き出し不能の関数に対するExpert Advisorのパラメータ
検証の最後の得られる結果は図6、図7に示しています。
Figure 6. Expert Advisorの検証動作の6か月間のバランス変化
図7 Expert Advisor動作結果表
興味を引かれるパラメータは資本の相対的ドローダウンです。今回の場合は、4.75%です。
では、資金の引き出しを可能にしたらこのパラメータはどのように変化するか確認します。引き出しの異なる金額と時期で検証をしなおします。
図8では、最適化と引き出し可能としたExpert Advisorのパラメータを表示しています。図9ではその条件における検証の結果を示しています。
図8 最適化と引き出し可能としたExpert Advisorのパラメータ
図9 equityの相対的drawdown計算結果
検証結果は少し驚くものです。なぜなら、引き出しの周期を1日または1週間と設定した方が引き出し不能よりもドローダウンが低いからです。
また、日次ドローダウンが100%まで増加し、その後8%まで落ち、そこから下がり続けています。結果を正しく解釈するには、資本の相対ドローダウンがストラテジーテス内でどのように計算されるか知る必要があります。これが次項でのトピックです。
5. 資本のドローダウン計算
探究心のある方は、ストラテジーテスタにおける資本計算方法、またこのパラメータを自動で計算する方法について疑問に思われるでしょう。
みなさんのExpert AdvisorでTesterWithdrawal()関数が使われていないなら、ここで分析するパラメータ計算はMetaTrader 4の計算と変わる点はありません。それは、 『エクスパート検証報告の数字が意味するものは?』の稿で述べられています。またそのコースコードと結果検証報告のパラメータは『エクスパート検証結果の評価方法』に示されています。
ストラテジーテスタの相対的最大ドローダウンの計算の記述は下の 図10 にあります。
図10 引き出しに配慮しない資本のドローダウン計算
その動作中、ストラテジーテスタは現在の資本の最大最小値を決定します。新規資本最大値が現れると、それはブルーのチェックマークでマークされ、最大最小ドローダウンが再計算され、最高値が保存されて結果報告に表示されます。
重要なことは検証の最後のパラメータの最終計算です。というのも、最後に登録されていない資本の極値がドローダウンの最高値となる状況が生じる可能性があるからです。ドローダウンの最高値変更についてはそれぞれ青と赤で示されます。グレーは新しい最高値が現れるたびに登録されるドローダウンを表しています。
ストラテジーテスタにおけるドローダウン計算のアルゴリズムはTesterWithDrawal()関数が変更することに注意が必要です。前のバリアントとの違いはドローダウンの再計算が資本の新し最高値が起こったときのみならず、資産の引き出し時にも行われる点です。図11に示しています。
図11 引き出しを考慮したドローダウン計算
上図では資産引き出しの瞬間をグリーンでマークして示しています。資金の引き出しはかなり頻繁で、そのためチャート上、固定するための極値により決定された最大ドローダウン値は許可されていません。結果、引き出しを考慮した結果ドローダウンは考慮なしのものよりも低くなる可能性があります。図9に示した通りです。
引き出し額が収益から得られる資本成長よりも大きければ、これドローダウン率を下げる結果になります。理由はこの状況はチャートに極値を形成させないからです。そして限界下降する直線のように見えます。ここでは相対 ドローダウンがゼロになる傾向にあります。この影響は図9に示されるチャートでの日々の引き出しが1,000ドルを上回ると出始めます。
MQL5で資本の最大および相対ドローダウンの計算を作成します。以下のように全アルゴリズムをひとつのプロシージャCalcEquityDrawdownにまとめて行います。
double RelEquityDrawdownPercent; // relative drawdown of equity in percentage terms double MaxEquityDrawdown; // maximal drawdown of equity
//--- Calculation of the drawdown of equity //+------------------------------------------------------------------+ void CalcEquityDrawdown(double initial_deposit, // initial deposit bool finally) // flag of calculation that registers extremums //+------------------------------------------------------------------+ { double drawdownpercent; double drawdown; double equity; static double maxpeak = 0.0, minpeak = 0.0; //--- exclusion of consideration of profit withdrawals for the calculation of drawdowns if(wdr_ignore) equity = AccountInfoDouble(ACCOUNT_EQUITY) + wdr_summa; else equity = AccountInfoDouble(ACCOUNT_EQUITY); if(maxpeak == 0.0) maxpeak = equity; if(minpeak == 0.0) minpeak = equity; //--- check of conditions of extremum if((maxpeak < equity)||(finally)) { //--- calculation of drawdowns drawdown = maxpeak - minpeak; drawdownpercent = drawdown / maxpeak * 100.0; //--- Saving maximal values of drawdowns if(MaxEquityDrawdown < drawdown) MaxEquityDrawdown = drawdown; if(RelEquityDrawdownPercent < drawdownpercent) RelEquityDrawdownPercent = drawdownpercent; //--- nulling the values of extremums maxpeak = equity; minpeak = equity; } if(minpeak > equity) minpeak = equity; }
計算の精度を保つため、新規ティックが来るたびに以下に与えられたパラメータと共に上述のプロシージャをExpert Advisor本体から呼びます。
CalcEquityDrawdown(initial_deposit, false);
また、ドローダウンの相対値を得るため、計算が終了したことを示す finally = trueパラメータと共にOnTester()関数中でExpert Advisorの最後に呼びます。現在の固定されていないドローダウンが登録されている最大値より大きい場合は、最大値を置き換え、結果報告にその旨表示します。
CalcEquityDrawdown(initial_deposit, true);
Expert Advisorに引き出しのアルゴリズムが実装されていれば、正しいドローダウンの計算のために、引き出しが行われるたびにfinally=trueパラメータを伴って CalcEquityDrawdown関数を呼ぶ必要があります。呼び出しの順番は以下です。
//--- Withdrawing assets and calculating drawdowns of equity if(TimeOfWithDrawal()) CalcEquityDrawdown(initial_deposit, true); else CalcEquityDrawdown(initial_deposit, false);
上述の方法論の正しさを確認するため、計算ずみデータとストラテジーテスタのデータを比較します。そのためには、OnTester() 関数に確認したいパラメータ値を返させる必要があります。RelEquityDrawdownPercent変数に保存されている資本の相対ドローダウンです。
それは、『パラメータによる最適化』入力パラメータの『引き出しに配慮したドローダウン』値を設定することでExpert Advisorのコードに実装されます。残りのパラメータは図8のように変更せずそのまま残しておきます。検証結果は図12に表示しています。
図12 計算結果のストラテジーテスタデータとの比較
取得した結果の比較は相対ドローダウンの計算アルゴリズムが正しいことを証明しています。
ドローダウン計算にその他のバリアントを追加します。そこでは、資本に対する資金引き出しの影響を含めます。そして資本の相対ドローダウンの変化を見守ります。
この目的のためにExpert Advisorに変数を追加します。Expert Advisorのパラメータ計算において引き出しの考慮が必要か否かを判断するのに使います。
bool wdr_ignore; // calculation of rate without the consideration of withdrawals
『パラメータによる最適化』変数が『引き出しを考慮しないドローダウン』に設定されていれば、wdr_ignore の値はtrueとなります。
また、以下に示すように、そのパラメータの処理を追加することで、ドローダウン、CalcEquityDrawdownの計算手順を修正する必要があります。
if (wdr_ignore) equity = AccountInfoDouble(ACCOUNT_EQUITY) + wdr_summa; else equity = AccountInfoDouble(ACCOUNT_EQUITY);
これでdrawdownsの新しい値を得る準備がすべて整いました。計算有効の新規アルゴリズムを用いて検証を行います。検証結果は図13に示しています。
図13 引き出しに配慮しない資本のドローダウン計算
結果から、資産引き出しの事実も、引き出した金額もドローダウンに依存しないことが判ります。よって、TesterWithDrawal()関数に影響されない純粋な要素を手に入れました。ただし、この類の計算を使うには、収益と損失の値を修正する必要があります。というのも、それらの実際の値は変更されており、これら要因はテスターの結果報告上正しくないからです。
では、収益、損失、その割合(収益率)を計算し、得られた値を報告書としてテキストファイルに保存しましょう。以下にリストにあるパラメータの計算手順を記述します。
double SummaryProfit; // Total net profit double GrossProfit; // Gross profit double GrossLoss; // Gross loss double ProfitFactor; // Profitability
//--- Calculation of parameters for the report //+------------------------------------------------------------------+ void CalculateSummary(double initial_deposit) //+------------------------------------------------------------------+ { double drawdownpercent, drawdown; double maxpeak = initial_deposit, minpeak = initial_deposit, balance = initial_deposit; double profit = 0.0; //--- Select entire history HistorySelect(0, TimeCurrent()); int trades_total = HistoryDealsTotal(); //--- Searching the deals in the history for(int i=0; i < trades_total; i++) { long ticket = HistoryDealGetTicket(i); long type = HistoryDealGetInteger(ticket, DEAL_TYPE); //--- Initial deposit is not considered if((i == 0)&&(type == DEAL_TYPE_BALANCE)) continue; //--- Calculation of profit profit = HistoryDealGetDouble(ticket, DEAL_PROFIT) + HistoryDealGetDouble(ticket, DEAL_COMMISSION) + HistoryDealGetDouble(ticket, DEAL_SWAP); balance += profit; if(minpeak > balance) minpeak = balance; //--- if((!wdr_ignore)&&(type != DEAL_TYPE_BUY)&&(type != DEAL_TYPE_SELL)) continue; //--- if(profit < 0) GrossLoss += profit; else GrossProfit += profit; SummaryProfit += profit; } if(GrossLoss < 0.0) GrossLoss *= -1.0; //--- Profitability if(GrossLoss > 0.0) ProfitFactor = GrossProfit / GrossLoss; }
報告をテキストファイルに生成する関数は以下です。
//--- Forming the report //+------------------------------------------------------------------+ void GenerateReportFile(string filename) //+------------------------------------------------------------------+ { string str, msg; ResetLastError(); hReportFile = FileOpen(filename, FILE_READ|FILE_WRITE|FILE_TXT|FILE_ANSI); if(hReportFile != INVALID_HANDLE) { StringInit(str,65,'-'); // separator WriteToReportFile(str); WriteToReportFile("| Period of testing: " + TimeToString(first_tick.time, TIME_DATE) + " - " + TimeToString(tick.time,TIME_DATE) + "\t\t\t|"); WriteToReportFile(str); //---- WriteToReportFile("| Initial deposit \t\t\t"+DoubleToString(initial_deposit, 2)); WriteToReportFile("| Total net profit \t\t\t"+DoubleToString(SummaryProfit, 2)); WriteToReportFile("| Gross profit \t\t\t"+DoubleToString(GrossProfit, 2)); WriteToReportFile("| Gross loss \t\t\t"+DoubleToString(-GrossLoss, 2)); if(GrossLoss > 0.0) WriteToReportFile("| Profitability \t\t\t"+DoubleToString(ProfitFactor,2)); WriteToReportFile("| Relative drawdown of equity \t"+ StringFormat("%1.2f%% (%1.2f)", RelEquityDrawdownPercent, MaxEquityDrawdown)); if(WDR_ENABLE) { StringInit(msg, 10, 0); switch(WDR_PERIOD) { case day: msg = "day"; break; case week: msg = "week"; break; case month: msg = "month"; break; case quarter: msg = "quarter"; break; case year: msg = "year"; break; } WriteToReportFile(str); WriteToReportFile("| Periodicity of withdrawing \t\t" + msg); if(WDR_TYPE == fixed) msg = DoubleToString(WDR_VALUE, 2); else msg = DoubleToString(WDR_VALUE, 1) + " % from deposit " + DoubleToString(initial_deposit, 2); WriteToReportFile("| Amount of money withdrawn \t\t" + msg); WriteToReportFile("| Number of withdrawal operations \t\t" + IntegerToString(wdr_count)); WriteToReportFile("| Withdrawn from account \t\t" + DoubleToString(wdr_summa, 2)); } WriteToReportFile(str); WriteToReportFile(" "); FileClose(hReportFile); } }
この関数の実行結果は、図14に示す情報を盛り込んだテキストファイルです。
Figure 14. GenerateReportFileプロシージャにより生成される報告書ファイル
この関数は新規レポートが既存のファイルコンテンツに追加されるように書かれます。このおかげで、検証結果の値をExpert Advisorの異なる入力パラメータと比較することが可能です。
レポートから解るように、テスターの計算(上の表)と比較すると、引き出しを考慮しない計算(下の表)では合計のネット収益が小さく、引き出された金額によるグロス損失が大きくなっています。資産引き出しを行う場合、収益と損失のほんとうの値をストラテジーテスタ上で得るためには、『引き出し』パラメータの値合計のネット収益から引き、それをグロス損失に足す必要があります。
6. 結果分析
これまで行った試みから得た結果を見て至る結論があります。
- TesterWithDrawal()関数の使用により、ストラテジーテスタでドローダウンを計算するアルゴリズムは変化する。異なる複数のExpert Advisorsを相対ドローダウンにより比較することは、そのうち一つでも資金の引き出しをしていたら正しくない。この関数を使い、指定した受付可能なパーセンテージの資本ドローダウンによってアカウントから定期的に資金をいくら出せるか実際的な計算ができる。
- この関数の使用は、Expert Advisor の安定的動作を確認するため、また資金の管理を左右する理論の調整をするためにに使われるトレーディングの人工的非安定要因として実装される。みなさんのExpert Advisorがバランスまたは資本レベルに応じて判断をするロジックをもっているなら、この関数の使用により検証と調整のさらなる機会を得ることができる。
- 引き出しを考慮しない相対ドローダウンを計算するとき、本稿で述べているアルゴリズムを使用すると、この関数の使用による影響を受けない相対ドローダウンの真の値を取得することができる。
おわりに
本稿はアカウントから資産を引き出すプロセスをモデル化するためのTesterWithdrawal()関数の使用法を述べました。また、ストラテジーテスタにおける資本ドローダウン計算のアルゴリズムに対するその関数の影響についても述べています。
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/131
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索