
一般的トレーディングシステムを基にしたExpert Advisors と売買ロボット最適化の錬金術(パート3)
はじめに
前稿のある読者の方から、全最適化の結果を同時に受け取る機能を得るため、バックテストをわずかばかり自動化する提案をいただきました。また、検証期間をマニュアルで変えるのはあまり便利ではなく、この手順も自動化する必要があります。その考えはすばらしいものです。そのようになれば、MQL4 手法はその実装にたいしてすべての可能性を提供するのです。そこで、この課題を解くことから本稿をスタートします。
バックテスト自動化
このタスクの解決に必要な事柄は以下です。
1. 下の必要な Expert Advisor に見出しとして次のような内容を書きます。
//+==================================================================+ //| Custom BackTesting function | //+==================================================================+ #include <IsBackTestingTime.mqh>
この命令を使って、EA コードに関数 IsBackTestingTime() を入れます。そして、忘れてはいけないのが、IsBackTestingTime.mqh ファイルをフォルダ INCLUDE に入れることです。この関数
bool IsBackTestingTime()
{
}
は期間を決定するもので、その中でバックテストの最適化やバックテストが行われるのです。この期間内ではこの関数はつねに『真』と返し、それ以外の期間では『偽』を返します。この関数以外に、外この命令によって外部 EA 変数が EA コードに追加されます。
//---- Declaration of external variables for backtesting extern datetime Start_Time = D'2007.01.01'; // start time of zero optimization extern int Opt_Period = 3; // optimization period in months, if less than zero, parameters are in days extern int Test_Period = 2; // testing period in months extern int Period_Shift = 1; // step of optimization period shift in months extern int Opt_Number = 0; // optimization number
私の前稿,をお読みになった方にはこれら変数の意味が明確であり、また説明する必要はないことを願っています。
2. EA コードの前の関数開始ブロックでは、もっともシンプルな IsBackTestingTime() 呼出しのユニバーサルコードが入れられ、バックテスト最適化数に応じて特定のタイムフレームに対してEA が動作するよう制限します。
//----+ Execution of backtesting conditions if (!IsBackTestingTime()) return(0);
おおまかに以下のようになります。
//+==================================================================+ //| Exp_BackTest.mq4 | //| Copyright © 2008, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+==================================================================+ #property copyright "Copyright © 2008, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //+==================================================================+ //| Custom BackTesting function | //+==================================================================+ #include <IsBackTestingTime.mqh> //---- INPUT PARAMETERS OF THE EA //---- GLOBAL VARIABLES OF THE EA //+==================================================================+ //| USER-DEFINED FUNCTIONS OF THE EA | //+==================================================================+ //+==================================================================+ //| Custom Expert initialization function | //+==================================================================+ int init() { //----+ +------------------------------------------------------------+ //---- CODE FOR THE EA INITIALIZATION //----+ +------------------------------------------------------------+ //---- end of initialization return(0); } //+==================================================================+ //| Custom Expert iteration function | //+==================================================================+ int start() { //----+ Execution of backtesting conditions if (!IsBackTestingTime()) return(0); //----+ +---------------------------------------------------------+ //----+ CODE OF THE EA ALGORITHM //----+ +---------------------------------------------------------+ //----+ return(0); } //+------------------------------------------------------------------+
既製 EA 例での課題解決の詳細にご興味がおありの場合は、EA コードExp_5_1.mq4 を参照ください。それは前稿 からの EA、theExp_5.mq4 でバックテストように変更されたものです。実際、シンプルな Expert Advisor と比較すると、そのような EA の最適化に大きな違いはありません。ただし、私は Opt_Number 以外のバックテスト変数は最適化すべきでないと思います。みなさんは別の考えをお持ちでしょうが。
検証中の最適化後、最適化期間内の結果ではなく、正しい境界を超えたその後の結果を得ることを覚えておくことは重要です。遺伝的アルゴリズムを用いて、1回の実行ですべてのバックテスト最適化を行うのはベストな判断ではありません。インプット変数 Opt_Number の最適化なしで、それぞれのバックテスト最適化を個別に、もっと深く分析する方が面白いものです。
ですが、この場合でさえ、そのような方法は動作の理解を促します。そして、外部変数の値はゼロから次の方法で定義される一定の最大値まで変化することを覚えておくことです。その方法とは、すべてのバックテスト最適化が行われる全期間(月単位)から、月単位のバックテスト最適化期間(Opt_Period)を引き、バックテスト期間(Test_Period)を引くのです。取得した値に1を足します。Period_Shift が1に等しければ、得た結果は、Opt_Number 変数の最大値となります。
2つの移動の交差を基にしたトレーディングシステム
このトレーディングシステムのバリアントはきわめて一般的なものです。その戦略の基礎であるアルゴリズムを分析します。ロングポジションに対しては、入力アルゴリズムは以下のようなものです。
ショートポジションに対しては以下です。
インディケータとして、インディケータ内で平均を決定する異なるパラメータを持つ2つの同一の移動を採用します。MovA 移動の平均を決めるパラメータはつねに MovB 移動の同一パラメータよりも小さいと仮定されます。よって、このトレーディングシステムでは、MovA は高速移動、MovB は低速移動です。以下は、2つの JMA 移動を基にしたトレーディングシステム実装のバリアントです。
//+==================================================================+ //| Exp_6.mq4 | //| Copyright © 2007, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+==================================================================+ #property copyright "Copyright © 2007, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //----+ +-------------------------------------------------------------------------------+ //---- EA INPUT PARAMETERS FOR BUY TRADES extern bool Test_Up = true;//filter of trade calculations direction extern int Timeframe_Up = 240; extern double Money_Management_Up = 0.1; extern int LengthA_Up = 4; // smoothing depth of the quick moving extern int PhaseA_Up = 100; // parameter changing in the range //-100 ... +100, influences the quality of transient process of quick moving extern int IPCA_Up = 0;/* Selecting prices, on which the indicator will be calculated by the quick moving (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ extern int LengthB_Up = 4; // smoothing depth increment of slow moving to quick one extern int PhaseB_Up = 100; // parameter changing in the range //-100 ... +100, influences the quality of transient process of slow moving; extern int IPCB_Up = 0;/* Selecting prices, on which the indicator will be calculated by the slow moving (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ extern int STOPLOSS_Up = 50; // stop loss extern int TAKEPROFIT_Up = 100; // take profit extern bool ClosePos_Up = true; // forced position closing allowed //----+ +-------------------------------------------------------------------------------+ //---- EA INPUT PARAMETERS FOR SELL TRADES extern bool Test_Dn = true;//filter of trade calculations direction extern int Timeframe_Dn = 240; extern double Money_Management_Dn = 0.1; extern int LengthA_Dn = 4; // smoothing depth of the quick moving extern int PhaseA_Dn = 100; // parameter changing in the range // -100 ... +100, influences the quality of transient process of quick moving; extern int IPCA_Dn = 0;/* Selecting prices, on which the indicator will be calculated by the quick moving (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ extern int LengthB_Dn = 4; // smoothing depth increment of slow moving to quick one extern int PhaseB_Dn = 100; // parameter changing in the range // -100 ... +100, influences the quality of transient process of slow moving; extern int IPCB_Dn = 0;/* Selecting prices, on which the indicator will be calculated by the slow moving(0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ extern int STOPLOSS_Dn = 50; // stop loss extern int TAKEPROFIT_Dn = 100; // take profit extern bool ClosePos_Dn = true; // forced position closing allowed //----+ +-------------------------------------------------------------------------------+ //---- Integer variables for the minimum of calculation bars int MinBar_Up, MinBar_Dn; //+==================================================================+ //| Custom Expert functions | //+==================================================================+ #include <Lite_EXPERT1.mqh> //+==================================================================+ //| Custom Expert initialization function | //+==================================================================+ int init() { //---- Checking the correctness of Timeframe_Up variable value if (Timeframe_Up != 1) if (Timeframe_Up != 5) if (Timeframe_Up != 15) if (Timeframe_Up != 30) if (Timeframe_Up != 60) if (Timeframe_Up != 240) if (Timeframe_Up != 1440) Print(StringConcatenate("Parameter Timeframe_Up cannot ", "be equal to ", Timeframe_Up, "!!!")); //---- Checking the correctness of Timeframe_Dn variable value if (Timeframe_Dn != 1) if (Timeframe_Dn != 5) if (Timeframe_Dn != 15) if (Timeframe_Dn != 30) if (Timeframe_Dn != 60) if (Timeframe_Dn != 240) if (Timeframe_Dn != 1440) Print(StringConcatenate("Parameter Timeframe_Dn cannot ", "be equal to ", Timeframe_Dn, "!!!")); //---- Initialization of variables MinBar_Up = 4 + 30; MinBar_Dn = 4 + 30; //---- end of initialization return(0); } //+==================================================================+ //| expert deinitialization function | //+==================================================================+ int deinit() { //----+ //---- End of EA deinitialization return(0); //----+ } //+==================================================================+ //| Custom Expert iteration function | //+==================================================================+ int start() { //----+ Declaring local variables int bar; double MovA[2], MovB[2]; //----+ Declaring static variables static int LastBars_Up, LastBars_Dn; static bool BUY_Sign, BUY_Stop, SELL_Sign, SELL_Stop; //----++ CODE FOR LONG POSITIONS if (Test_Up) { int IBARS_Up = iBars(NULL, Timeframe_Up); if (IBARS_Up >= MinBar_Up) { if (LastBars_Up != IBARS_Up) { //----+ Initialization of variables BUY_Sign = false; BUY_Stop = false; LastBars_Up = IBARS_Up; //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS for(bar = 1; bar < 3; bar++) MovA[bar - 1] = iCustom(NULL, Timeframe_Up, "JJMA", LengthA_Up, PhaseA_Up, 0, IPCA_Up, 0, bar); for(bar = 1; bar < 3; bar++) MovB[bar - 1] = iCustom(NULL, Timeframe_Up, "JJMA", LengthA_Up + LengthB_Up, PhaseB_Up, 0, IPCB_Up, 0, bar); //----+ DEFINING SIGNALS FOR TRADES if ( MovA[1] < MovB[1]) if ( MovA[0] > MovB[0]) BUY_Sign = true; if ( MovA[0] > MovB[0]) BUY_Stop = true; } //----+ EXECUTION OF TRADES if (!OpenBuyOrder1(BUY_Sign, 1, Money_Management_Up, STOPLOSS_Up, TAKEPROFIT_Up)) return(-1); if (ClosePos_Up) if (!CloseOrder1(BUY_Stop, 1)) return(-1); } } //----++ CODE FOR SHORT POSITIONS if (Test_Dn) { int IBARS_Dn = iBars(NULL, Timeframe_Dn); if (IBARS_Dn >= MinBar_Dn) { if (LastBars_Dn != IBARS_Dn) { //----+ Initialization of variables SELL_Sign = false; SELL_Stop = false; LastBars_Dn = IBARS_Dn; //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS for(bar = 1; bar < 3; bar++) MovA[bar - 1] = iCustom(NULL, Timeframe_Dn, "JJMA", LengthA_Dn, PhaseA_Dn, 0, IPCA_Dn, 0, bar); for(bar = 1; bar < 3; bar++) MovB[bar - 1] = iCustom(NULL, Timeframe_Dn, "JJMA", LengthA_Dn + LengthB_Dn, PhaseB_Dn, 0, IPCB_Dn, 0, bar); //----+ DEFINING SIGNALS FOR TRADES if ( MovA[1] > MovB[1]) if ( MovA[0] < MovB[0]) SELL_Sign = true; if ( MovA[0] < MovB[0]) SELL_Stop = true; } //----+ EXECUTION OF TRADES if (!OpenSellOrder1(SELL_Sign, 2, Money_Management_Dn, STOPLOSS_Dn, TAKEPROFIT_Dn)) return(-1); if (ClosePos_Dn) if (!CloseOrder1(SELL_Stop, 2)) return(-1); } } //----+ return(0); } //+------------------------------------------------------------------+
2つのオシレータの交差を基にしたトレーディングシステム
類似のトレーディングシステムは移動だけではなく、オシレータにも使用できますが、この場合、前稿にあるように、シグナルを受け取った直後に市場エンターする代わりに未決注文を出す方がよいものです。明解な例として NACD 図を使用します。
未決の指値買いを出すためのアルゴリズムは以下のようになります。
以下は売りの指値タイプの注文に対するアルゴリズムです。
この EA のコードは前の EA のコードに類似しています。
//+==================================================================+ //| Exp_7.mq4 | //| Copyright © 2007, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+==================================================================+ #property copyright "Copyright © 2007, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //----+ +---------------------------------------------------------------------------+ //---- EA INPUT PARAMETERS FOR BUY TRADES extern bool Test_Up = true; //filter of trade calculations direction extern int Timeframe_Up = 240; extern double Money_Management_Up = 0.1; extern int FST_period_Up = 12; // period of the quick moving extern int SLO_period_Up = 22; // period increment of slow moving to quick one extern int SIGN_period_Up = 8; // period of the signal line extern int Price_Up = 0; // selecting prices, upon which MACD is calculated extern int STOPLOSS_Up = 50; // stop loss extern int TAKEPROFIT_Up = 100; // take profit extern int PriceLevel_Up =40; // difference between the current price and // price of pending order triggering extern bool ClosePos_Up = true; // forced position closing allowed //----+ +---------------------------------------------------------------------------+ //---- EA INPUT PARAMETERS FOR SELL TRADES extern bool Test_Dn = true; //filter of trade calculations direction extern int Timeframe_Dn = 240; extern double Money_Management_Dn = 0.1; extern int FST_period_Dn = 12; // period of the quick moving extern int SLO_period_Dn = 22; // period increment of slow moving to quick one extern int SIGN_period_Dn = 8; // period of the signal line extern int Price_Dn = 0; // selecting prices, upon which MACD is calculated extern int STOPLOSS_Dn = 50; // stop loss extern int TAKEPROFIT_Dn = 100; // take profit extern int PriceLevel_Dn =40; // difference between the current price and // price of pending order triggering extern bool ClosePos_Dn = true; // forced position closing allowed //----+ +---------------------------------------------------------------------------+ //---- Integer variables for the minimum of calculation bars int MinBar_Up, MinBar_Dn; //+==================================================================+ //| Custom Expert functions | //+==================================================================+ #include <Lite_EXPERT1.mqh> //+==================================================================+ //| Custom Expert initialization function | //+==================================================================+ int init() { //---- Checking the correctness of Timeframe_Up variable value if (Timeframe_Up != 1) if (Timeframe_Up != 5) if (Timeframe_Up != 15) if (Timeframe_Up != 30) if (Timeframe_Up != 60) if (Timeframe_Up != 240) if (Timeframe_Up != 1440) Print(StringConcatenate("Parameter Timeframe_Up cannot ", "be equal to ", Timeframe_Up, "!!!")); //---- Checking the correctness of Timeframe_Dn variable value if (Timeframe_Dn != 1) if (Timeframe_Dn != 5) if (Timeframe_Dn != 15) if (Timeframe_Dn != 30) if (Timeframe_Dn != 60) if (Timeframe_Dn != 240) if (Timeframe_Dn != 1440) Print(StringConcatenate("Parameter Timeframe_Dn cannot ", "be equal to ", Timeframe_Dn, "!!!")); //---- Initialization of variables MinBar_Up = 4 + FST_period_Up + SLO_period_Up + SIGN_period_Up; MinBar_Dn = 4 + FST_period_Dn + SLO_period_Dn + SIGN_period_Dn; //---- end of initialization return(0); } //+==================================================================+ //| expert deinitialization function | //+==================================================================+ int deinit() { //----+ //---- End of the EA deinitialization return(0); //----+ } //+==================================================================+ //| Custom Expert iteration function | //+==================================================================+ int start() { //----+ Declaring local variables int bar; double MovA[2], MovB[2]; //----+ Declaring static variables static int LastBars_Up, LastBars_Dn; static datetime StopTime_Up, StopTime_Dn; static bool BUY_Sign, BUY_Stop, SELL_Sign, SELL_Stop; //----++ CODE FOR LONG POSITIONS if (Test_Up) { int IBARS_Up = iBars(NULL, Timeframe_Up); if (IBARS_Up >= MinBar_Up) { if (LastBars_Up != IBARS_Up) { //----+ Initialization of variables BUY_Sign = false; BUY_Stop = false; LastBars_Up = IBARS_Up; StopTime_Up = iTime(NULL, Timeframe_Up, 0) + 60 * Timeframe_Up; //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS for(bar = 1; bar < 3; bar++) MovA[bar - 1] = iMACD(NULL, Timeframe_Up, FST_period_Up, FST_period_Up + SLO_period_Up, SIGN_period_Up, Price_Up, 0, bar); for(bar = 1; bar < 3; bar++) MovB[bar - 1] = iMACD(NULL, Timeframe_Up, FST_period_Up, FST_period_Up + SLO_period_Up, SIGN_period_Up, Price_Up, 1, bar); //----+ DEFINING SIGNALS FOR TRADES if ( MovA[1] < MovB[1]) if ( MovA[0] > MovB[0]) BUY_Sign = true; if ( MovA[0] > MovB[0]) BUY_Stop = true; } //----+ EXECUTION OF TRADES if (!OpenBuyLimitOrder1(BUY_Sign, 1, Money_Management_Up, STOPLOSS_Up, TAKEPROFIT_Up, PriceLevel_Up, StopTime_Up)) return(-1); if (ClosePos_Up) if (!CloseOrder1(BUY_Stop, 1)) return(-1); } } //----++ CODE FOR SHORT POSITIONS if (Test_Dn) { int IBARS_Dn = iBars(NULL, Timeframe_Dn); if (IBARS_Dn >= MinBar_Dn) { if (LastBars_Dn != IBARS_Dn) { //----+ Initialization of variables SELL_Sign = false; SELL_Stop = false; LastBars_Dn = IBARS_Dn; StopTime_Dn = iTime(NULL, Timeframe_Dn, 0) + 60 * Timeframe_Dn; //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS for(bar = 1; bar < 3; bar++) MovA[bar - 1] = iMACD(NULL, Timeframe_Dn, FST_period_Dn, FST_period_Dn + SLO_period_Dn, SIGN_period_Dn, Price_Dn, 0, bar); for(bar = 1; bar < 3; bar++) MovB[bar - 1] = iMACD(NULL, Timeframe_Dn, FST_period_Dn, FST_period_Dn + SLO_period_Dn, SIGN_period_Dn, Price_Dn, 1, bar); //----+ DEFINING SIGNALS FOR TRADES if ( MovA[1] > MovB[1]) if ( MovA[0] < MovB[0]) SELL_Sign = true; if ( MovA[0] < MovB[0]) SELL_Stop = true; } //----+ EXECUTION OF TRADES if (!OpenSellLimitOrder1(SELL_Sign, 2, Money_Management_Dn, STOPLOSS_Dn, TAKEPROFIT_Dn, PriceLevel_Dn, StopTime_Dn)) return(-1); if (ClosePos_Dn) if (!CloseOrder1(SELL_Stop, 2)) return(-1); } } //----+ return(0); } //+------------------------------------------------------------------+
おわりに
もう1つ記事が終わりました。まったく異なるインディケータのバリアントを基にした Expert Advisor にもう一つトレーディングシステムが実装されました。本稿が初心者の EA プログラマーの方にとって、正確に公式化されたアルゴリズムを、出来上がった絶対に動作するご自身の Expert Advisorのコードに変換するスキルをいっそう伸ばすために役立つことを願っています。
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/1521



- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索