English Русский 中文 Español Deutsch Português
人気のトレーディングシステムを基にした Expert Advisors と売買ロボット最適化の錬金術(パート2)

人気のトレーディングシステムを基にした Expert Advisors と売買ロボット最適化の錬金術(パート2)

MetaTrader 4トレーディングシステム | 16 3月 2016, 08:58
766 0
Nikolay Kositsin
Nikolay Kositsin

はじめに

トレーディングシステムの最適化はさまざまな文献で幅広く論じられており、インターネットで簡単に見つけられるものをここで詳しく書くのは筋違いであると思われます。ここでは、自動システムの最適化一般の結果を利用するポイントを理解する理論のそこにある基本的なシンプルな考え、および特に最適化の実用性のみ詳しく述べていきます。


比較的シンプルなトレーディングシステムに基づき構築されたをストラテジーテスタにアップロードするのは簡単であることをみなさんはご存じだと思います。最適化を行ったあと、最適化の履歴データに一致するほとんどすべての履歴データに驚くべき検証結果を得ることができるのです。ただ、ここでは当然の疑問が起こります。「結果がすばらしくても、履歴に応じてシステムを調整したとしたら、自動システムの動作の予測と結果はどんな関係があるのか?」


現時点では、この疑問はかなり性急です。この理由の一つは、最初の正常な最適化後、初心者の EA プログラマーは本番の取引で最適化結果を利用するという軽率な考えについて誤った考え方を抱き、その結果は台無しになる可能性があります。初心者の EA プログラマーは自分自身の資金、または既製のを利用する人の資金を失ってしまいます。そんなわけで、私はこのトピックで本稿を始めます。


狂信的でないバックテストまたは検証最適化結果

通常、最初の EA 最適化経験後、人は、取引で最小限のドローダウン、最大限の利益を出す最適化結果使う戦略を構築しようと思います。そのようなパラメータセットのシステムは最適化期間だけでなく、近い将来にも利益を出すと願って。模式的にそれは以下のようなものです。

これは、トレーディング戦略のテスターを最初に知った後、多くの初心者の EA プログラマが使うロジックです。ただし、残念ながら、将来をちょっとのぞくことはできず、このロジックを使ったトレーディングシステムの効率を決めることはできないのです。本番の市場という点では処理結果の通常レコードに対してリアルタイムモードによりデモアカウントで戦略を検証することは、ひじょうに退屈な仕事です。


何年間も結果を待つに十分忍耐があれば、問題はなにもありません。ただし、その後、システムは完全に使い物にならず、時間とインターネット通信の無駄にとてもがっかりすることになるのです。また、そのような方法では多くのトレーディング戦略を検証することはできません。せいぜい1件か、最大でも2件です。最後です。そのようなトレーディング戦略に費やされる多大な労力は、その動作結果を決定的に推定する能力を作成者から奪ってしまいます。


そのような状況では、心理的に真実に向き合い、結果の戦略は時間と労力の無駄でしかなかったと認めることはきわめてむつかしいものです。当然、そのような労力と時間の無駄は、利益を出す Expert Advisor の作成にはつながりにくいものです。


この状況では、唯一の解決策は履歴データを基に将来をモデル化することです。ひじょうに簡単です。必要なことは、時間境界を前のスキームから時間軸に沿って左に移動することだけです。その場合、最適化後に、最適化データよりも現在に近い最近のデー9たで最適化結果を推定する時間が得られます。

上記を含めた多くの場合、そのような方法により、どんな特定の Expert Advisor に対してもパラメータを最適化した最適化結果を利用するその類の戦略の実際の効率を推定することができます。そのような最適化戦略の分析方法の模式的意味は以下の形で表現できます。


この図はひじょうに明確であると思います。たとえば、分析期間として2007年を取り上げます。1番目の最適化には、最適化期間は 2007.01.01~2007.03.31、検証期間は 2007.04.01~2007.05.31 です。検証し結果を記録したあと、最適化期間と検証期間を1か月先に送ります。最適化期間は 2007.02.01~2007.04.30、検証期間は 2007.05.01~2007.06.30 となります。等々。結果、各最適化結果記録のテーブルを取得します。たとえば以下のようなものです。


第1検証パラメータ/実行 01 02 03 04 05 06 07 08 09 10 11 12
純利益
総利益
総損失
収益性
絶対ドローダウン
相対ドローダウン
トータル取引


もちろん、最適化実行ごとに表のセルを埋める必要があります。そのような表を分析し、そこにある情報を処理することは大した問題にはならないので、この分析の結論は簡単に出すことができます。有効な履歴データ上のEA 動作のこの種の分析は、EA 最適化結果を正しく推定し、この処理に関する妄想を避けることに役立つと思います。デモアカウントでの検証と比較すると、時間の節約はすばらしいものです!


この調査も時間と労力が要求されるものの、バックテストのテクニックは初心者のEA プログラマにきわめて理解しやすいものです。ご自身の EA バックテスト中、よくない結果を得たとしおても、不安になることはありません。ひじょうに収益性があるように見える損失を生む戦略を本番で使用するよりは、仮想損失の方が断然よいのです。


バックテストに関してお伝えしたいことは以上です。最小ドローダウンの最大利益を選択することが唯一可能なシステム最適化戦略ではないことに留意します。それはバックテスト手順を紹介するためだけに提供されているのです。一般的にバックテスト中ほとんどの時間は最適化に費やされます。一方で。最適化戦略の検証にはほとんど時間がかかりません。よって、同時に複数の線りゃぅを検証し、これから得る結論のためにより大きな統計的材料を取得することは合理的です。ゆえにに、検証結果テーブルはより大きなものとなります。


オシレータトレーディング戦略

オシレータを基に、数多くの異なるトレーディング戦略を構築することが可能です。本稿では、買い過ぎ、売り過ぎ領域でエントランスとエグジットを行うことを基にした最も一般的なシステムについて説明します。



オシレータの大半は、一定の最小値から最大値へ値を変えます。オシレータはそれぞれ独自の値を持ちます。極値からある距離で、UpLevel と DownLevel が設定されます。


そのようなシステムでは、オシレータが非トレンド領域から出て、買い過ぎ領域に入ると、買いシグナルが発生します。

売りシグナルはオシレータが非トレンド領域から出て、売り過ぎ領域に入ると、発生します。

こういったメインのシグナル以外にも、このシステムはオシレータが売り過ぎおよび買い過ぎ領域を出て非トレンド領域に入るとき出現する別のシグナルがあります。いわゆる修正シグナルです。


買いシグナルはオシレータが売り過ぎ領域を出て非トレンド領域に入るとき発生します(下落トレンドの修正)。

売りシグナルはオシレータが買い過ぎ領域を出て非トレンド領域に入るとき発生します(上昇トレンドの修正)。


オシレータトレーディングシステム向け Expert Advisor のコード


よって、市場エンターのアルゴリズムが4つあります。ロングポジション用アルゴリズムのバリアントをよく注意して見ると、それらは完全に同じであり、唯一ブレイクアウトレベルで異なると断定することができます。それはプログラムコードを書く観点からはまったく無関係です。ショートポジションについても状況は同様です。以下はオシレータトレーディングシステム実装の私のバージョンです。

//+==================================================================+
//|                                                        Exp_3.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_Up1 = true;//filter of trade calculations direction
extern int    Timeframe_Up1 = 240;
extern double Money_Management_Up1 = 0.1;
extern double IndLevel_Up1 = 0.8; // breakout level of the indicator
extern int    JLength_Up1 = 8;  // depth of JJMA smoothing of entering price
extern int    XLength_Up1 = 8;  // depth of JurX smoothing of obtained indicator 
extern int    Phase_Up1 = 100; // parameter changing in the range -100 ... +100, 
                              //influences the quality of transient processes of smoothing
extern int    IPC_Up1 = 0;/* Selecting prices on which the indicator will be calculated
(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_Up1 = 50;  // stoploss
extern int    TAKEPROFIT_Up1 = 100; // takeprofit
extern int    TRAILINGSTOP_Up1 = 0; // trailing stop
extern bool   ClosePos_Up1 = true; // forced position closing allowed
//----+ +--------------------------------------------------------------------------+
///---- EA INPUT PARAMETERS FOR BUY TRADES 
extern bool   Test_Up2 = true;//filter of trade calculations direction
extern int    Timeframe_Up2 = 240;
extern double Money_Management_Up2 = 0.1;
extern double IndLevel_Up2 = -0.8; // breakout level of the indicator
extern int    JLength_Up2 = 8;  // depth of JJMA smoothing of entering price
extern int    XLength_Up2 = 8;  // depth of JurX smoothing of obtained indicator
extern int    Phase_Up2 = 100; // parameter changing in the range -100 ... +100, 
                              //influences the quality of transient processes of smoothing
extern int    IPC_Up2 = 0;/* Selecting prices on which the indicator will be calculated 
(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_Up2 = 50;  // stoploss
extern int    TAKEPROFIT_Up2 = 100; // takeprofit
extern int    TRAILINGSTOP_Up2 = 0; // trailing stop
extern bool   ClosePos_Up2 = true; // forced position closing allowed
//----+ +--------------------------------------------------------------------------+
//---- EA INPUT PARAMETERS FOR SELL TRADES 
extern bool   Test_Dn1 = true;//filter of trade calculations direction
extern int    Timeframe_Dn1 = 240;
extern double Money_Management_Dn1 = 0.1;
extern double IndLevel_Dn1 = 0.8; // breakout level of the indicator
extern int    JLength_Dn1 = 8;  // depth of JJMA smoothing of entering price
extern int    XLength_Dn1 = 8;  // depth of JurX smoothing of obtained indicator 
extern int    Phase_Dn1 = 100; // parameter changing in the range -100 ... +100, 
                              //influences the quality of transient processes of smoothing
extern int    IPC_Dn1 = 0;/* Selecting prices on which the indicator will be calculated 
(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_Dn1 = 50;  // stoploss
extern int    TAKEPROFIT_Dn1 = 100; // takeprofit
extern int    TRAILINGSTOP_Dn1 = 0; // trailing stop
extern bool   ClosePos_Dn1 = true; // forced position closing allowed
//----+ +--------------------------------------------------------------------------+
//---- EA INPUT PARAMETERS FOR SELL TRADES
extern bool   Test_Dn2 = true;//filter of trade calculations direction
extern int    Timeframe_Dn2 = 240;
extern double Money_Management_Dn2 = 0.1;
extern double IndLevel_Dn2 = -0.8; // breakout level of the indicator
extern int    JLength_Dn2 = 8;  // depth of JJMA smoothing of entering price
extern int    XLength_Dn2 = 8;  // depth of JurX smoothing of obtained indicator 
extern int    Phase_Dn2 = 100; // parameter changing in the range -100 ... +100, 
                              //influences the quality of transient processes of smoothing
extern int    IPC_Dn2 = 0;/* Selecting prices on which the indicator will be calculated 
(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_Dn2 = 50;  // stoploss
extern int    TAKEPROFIT_Dn2 = 100; // takeprofit
extern int    TRAILINGSTOP_Dn2 = 0; // trailing stop
extern bool   ClosePos_Dn2 = true; // forced position closing allowed
//----+ +--------------------------------------------------------------------------+
//---- Integer variables for the minimum of calculation bars
int MinBar_Up1, MinBar_Dn1;
int MinBar_Up2, MinBar_Dn2;
//+==================================================================+
//| TimeframeCheck() functions                                       |
//+==================================================================+
void TimeframeCheck(string Name, int Timeframe)
  {
//----+
   //---- Checking the correctness of Timeframe variable value
   if (Timeframe != 1)
    if (Timeframe != 5)
     if (Timeframe != 15)
      if (Timeframe != 30)
       if (Timeframe != 60)
        if (Timeframe != 240)
         if (Timeframe != 1440)
           Print(StringConcatenate("Parameter ",Name,
                     " cannot ", "be equal to ", Timeframe, "!!!"));    
//----+ 
  }
//+==================================================================+
//| Custom Expert functions                                          |
//+==================================================================+
#include <Lite_EXPERT1.mqh>
//+==================================================================+
//| Custom Expert initialization function                            |
//+==================================================================+
int init()
  {
//---- Checking the correctness of Timeframe_Up1 variable value
   TimeframeCheck("Timeframe_Up1", Timeframe_Up1);                             
//---- Checking the correctness of Timeframe_Up2 variable value
   TimeframeCheck("Timeframe_Up2", Timeframe_Up2);                              
//---- Checking the correctness of Timeframe_Dn1 variable value 
   TimeframeCheck("Timeframe_Dn1", Timeframe_Dn1);  
//---- Checking the correctness of Timeframe_Dn2 variable value 
   TimeframeCheck("Timeframe_Dn2", Timeframe_Dn2);  
//---- Initialization of variables
   MinBar_Up1 = 3 + 3 * XLength_Up1 + 30;
   MinBar_Up2 = 3 + 3 * XLength_Up2 + 30;
   MinBar_Dn1 = 3 + 3 * XLength_Dn1 + 30;
   MinBar_Dn2 = 3 + 3 * XLength_Dn2 + 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
   double Osc1, Osc2;
   //----+ Declaring static variables
   //----+ +---------------------------------------------------------------+
   static int LastBars_Up1, LastBars_Dn1;
   static bool BUY_Sign1, BUY_Stop1, SELL_Sign1, SELL_Stop1;
   //----+ +---------------------------------------------------------------+
   static int LastBars_Up2, LastBars_Dn2;
   static bool BUY_Sign2, BUY_Stop2, SELL_Sign2, SELL_Stop2;
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR LONG POSITIONS 1
   if (Test_Up1) 
    {
      int IBARS_Up1 = iBars(NULL, Timeframe_Up1);
      
      if (IBARS_Up1 >= MinBar_Up1)
       {
         if (LastBars_Up1 != IBARS_Up1)
          {
           //----+ Initialization of variables 
           BUY_Sign1 = false;
           BUY_Stop1 = false;
           LastBars_Up1 = IBARS_Up1; 
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS        
           Osc1 = iCustom(NULL, Timeframe_Up1, 
                 "JCCIX", JLength_Up1, XLength_Up1,
                                Phase_Up1, IPC_Up1, 0, 1);
                                
           Osc2 = iCustom(NULL, Timeframe_Up1, 
                 "JCCIX", JLength_Up1, XLength_Up1,
                                Phase_Up1, IPC_Up1, 0, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (Osc2 < IndLevel_Up1)
             if (Osc1 > IndLevel_Up1)
                          BUY_Sign1 = true;
                          
           if (Osc1 < IndLevel_Up1)
                          BUY_Stop1 = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (!OpenBuyOrder1(BUY_Sign1, 1, Money_Management_Up1, 
                                          STOPLOSS_Up1, TAKEPROFIT_Up1))
                                                                 return(-1);
          if (ClosePos_Up1)
                if (!CloseOrder1(BUY_Stop1, 1))
                                        return(-1);
                                        
          if (!Make_TreilingStop(1, TRAILINGSTOP_Up1))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR LONG POSITIONS 2
   if (Test_Up2) 
    {
      int IBARS_Up2 = iBars(NULL, Timeframe_Up2);
      
      if (IBARS_Up2 >= MinBar_Up2)
       {
         if (LastBars_Up2 != IBARS_Up2)
          {
           //----+ Initialization of variables 
           BUY_Sign2 = false;
           BUY_Stop2 = false;
           LastBars_Up2 = IBARS_Up2; 
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS        
           Osc1 = iCustom(NULL, Timeframe_Up2, 
                 "JCCIX", JLength_Up2, XLength_Up2,
                                Phase_Up2, IPC_Up2, 0, 1);
                                
           Osc2 = iCustom(NULL, Timeframe_Up2, 
                 "JCCIX", JLength_Up2, XLength_Up2,
                                Phase_Up2, IPC_Up2, 0, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (Osc2 < IndLevel_Up2)
             if (Osc1 > IndLevel_Up2)
                          BUY_Sign2 = true;
                          
           if (Osc1 < IndLevel_Up2)
                          BUY_Stop2 = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (!OpenBuyOrder1(BUY_Sign2, 2, Money_Management_Up2, 
                                          STOPLOSS_Up2, TAKEPROFIT_Up2))
                                                                 return(-1);
          if (ClosePos_Up2)
                if (!CloseOrder1(BUY_Stop2, 2))
                                        return(-1);
                                        
          if (!Make_TreilingStop(2, TRAILINGSTOP_Up2))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+ 
   //----++ CODE FOR SHORT POSITIONS 1
   if (Test_Dn1) 
    {
      int IBARS_Dn1 = iBars(NULL, Timeframe_Dn1);
      
      if (IBARS_Dn1 >= MinBar_Dn1)
       {
         if (LastBars_Dn1 != IBARS_Dn1)
          {
           //----+ Initialization of variables 
           SELL_Sign1 = false;
           SELL_Stop1 = false;
           LastBars_Dn1 = IBARS_Dn1; 
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS        
           Osc1 = iCustom(NULL, Timeframe_Dn1, 
                 "JCCIX", JLength_Dn1, XLength_Dn1,
                                Phase_Dn1, IPC_Dn1, 0, 1);
                                
           Osc2 = iCustom(NULL, Timeframe_Dn1, 
                 "JCCIX", JLength_Dn1, XLength_Dn1,
                                Phase_Dn1, IPC_Dn1, 0, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (Osc2 > IndLevel_Dn1)
             if (Osc1 < IndLevel_Dn1)
                          SELL_Sign1 = true;
                          
           if (Osc1 > IndLevel_Dn1)
                          SELL_Stop1 = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (!OpenSellOrder1(SELL_Sign1, 3, Money_Management_Dn1, 
                                          STOPLOSS_Dn1, TAKEPROFIT_Dn1))
                                                                 return(-1);
          if (ClosePos_Dn1)
                if (!CloseOrder1(SELL_Stop1, 3))
                                        return(-1);
                                        
          if (!Make_TreilingStop(3, TRAILINGSTOP_Dn1))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR SHORT POSITIONS 2
   if (Test_Dn2) 
    {
      int IBARS_Dn2 = iBars(NULL, Timeframe_Dn2);
      
      if (IBARS_Dn2 >= MinBar_Dn2)
       {
         if (LastBars_Dn2 != IBARS_Dn2)
          {
           //----+ Initialization of variables 
           SELL_Sign2 = false;
           SELL_Stop2 = false;
           LastBars_Dn2 = IBARS_Dn2; 
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS        
           Osc1 = iCustom(NULL, Timeframe_Dn2, 
                 "JCCIX", JLength_Dn2, XLength_Dn2,
                                Phase_Dn2, IPC_Dn2, 0, 1);
                                
           Osc2 = iCustom(NULL, Timeframe_Dn2, 
                 "JCCIX", JLength_Dn2, XLength_Dn2,
                                Phase_Dn2, IPC_Dn2, 0, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (Osc2 > IndLevel_Dn2)
             if (Osc1 < IndLevel_Dn2)
                          SELL_Sign2 = true;
                          
           if (Osc1 > IndLevel_Dn2)
                          SELL_Stop2 = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (!OpenSellOrder1(SELL_Sign2, 4, Money_Management_Dn2, 
                                          STOPLOSS_Dn2, TAKEPROFIT_Dn2))
                                                                 return(-1);
          if (ClosePos_Dn2)
                if (!CloseOrder1(SELL_Stop2, 4))
                                        return(-1);
                                        
           if (!Make_TreilingStop(4, TRAILINGSTOP_Dn2))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+ 
//----+ 
    
    return(0);
  }
//+------------------------------------------------------------------+

このコードは先行記事で提供したコードに比べると2倍長いものです。ところで、オーダー管理関数の呼出しの代わりに完全プログラムであれば、この EA コードがどれほど長いものであるか想像してください。このには新しい入力パラメータが入っていることに注意が必要です。それは、IndLevel_Up1、IndLevel_Up2、IndLevel_Dn1、IndLevel_Dn2 です。IndLevel_Up1 と IndLevel_Up2 はロングポジションの2つのアルゴリズムに対し Uplevel と DownLevel を定義します。一方、IndLevel_Dn1 および IndLevel_Dn2 はショートポジションのアルゴリズムに対し DownLevel と Uplevel を定義します。


この Expert Advisor の最適化中、これらレベルの値は -1.0 to +1.0 で変化することを考慮する必要があります。この EA の JCCIX オシレータを別の任意のオシレータと置き換えたければ、これらレベルの最大値と最小値は異なることに配慮が必要です。ソースインディケータ JCCIX は CCI インディケータの類似体で、そこでは一般的な移動平均によるアルゴリズムの平滑化は JMA と超線形平滑化に置き換わります。この EA ではトレーリングストップが使用されています。その値はTRAILINGSTOP_Up1、TRAILINGSTOP_Up2、 TRAILINGSTOP_Dn1、TRAILINGSTOP_Dn2 のような EA の入力パラメータで決められます。それ以外の語に関しては、この EA は完全に前稿で述べた EA に類似しています。

即時の市場参入を未決注文への変更

上記 EA の類似体では多くの場合、即時の市場エンターを未決注文に変更することで、市場参入をより正確にし、ストップロスへの到達可能性を低く、より大きな利益を得ることが可能となります。ファイル Lite_EXPERT1.mqh の関数セットでそのような置換が簡単になります。


必要なことは、関数 OpenBuyOrder1() および OpenSellOrder1() を OpenBuyLimitOrder1() と OpenSellLimitOrder1() にそれぞれ置き換えることだけです。そのような関数置換の間に、それらの新しい入力変数-LEVEL および Expiration、が初期化されます。たとえば、有効な LEVEL 変数が EA の入力パラメータによって定義されるトレーディング戦略を構築することができます。未決注文の取り消し日は現行バーの次の変更時刻として設定します。


ここで同じコードは繰り返して記しません。上記 EA の変更後コードは本稿に添付があります(Exp_4.mq4)。未決注文の使用例として、 OSMA オシレータを使ったオシレータシステムを記述します。

//For the EA operation the Metatrader\EXPERTS\indicators folder 
//must contain the 5c_OsMA.mq4 indicator
//+==================================================================+
//|                                                        Exp_5.mq4 |
//|                             Copyright © 2008,   Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+==================================================================+
#property copyright "Copyright © 2008, 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 double IndLevel_Up = 0; // breakout level of the indicator
extern int    FastEMA_Up = 12;  // period of quick EMA
extern int    SlowEMA_Up = 26;  // period of slow EMA
extern int    SignalSMA_Up = 9;  // period of signal SMA
extern int    STOPLOSS_Up = 50;  // stoploss
extern int    TAKEPROFIT_Up = 100; // takeprofit
extern int    TRAILINGSTOP_Up = 0; // trailing stop
extern int    PriceLevel_Up =40; // difference between the current price and
                                         // the 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 double IndLevel_Dn = 0; // breakout level of the indicator
extern int    FastEMA_Dn = 12;  // period of quick EMA
extern int    SlowEMA_Dn = 26;  // period of slow EMA
extern int    SignalSMA_Dn = 9;  // period of signal SMA
extern int    STOPLOSS_Dn = 50;  // stoploss
extern int    TAKEPROFIT_Dn = 100; // takeprofit
extern int    TRAILINGSTOP_Dn = 0; // trailing stop
extern int    PriceLevel_Dn = 40; // difference between the current price and 
                                         // the 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;
//+==================================================================+
//| TimeframeCheck() functions                                       |
//+==================================================================+
void TimeframeCheck(string Name, int Timeframe)
  {
//----+
   //---- Checking the correctness of Timeframe variable value
   if (Timeframe != 1)
    if (Timeframe != 5)
     if (Timeframe != 15)
      if (Timeframe != 30)
       if (Timeframe != 60)
        if (Timeframe != 240)
         if (Timeframe != 1440)
           Print(StringConcatenate("Parameter ",Name,
                     " cannot ", "be equal to ", Timeframe, "!!!"));    
//----+ 
  }
//+==================================================================+
//| Custom Expert functions                                          |
//+==================================================================+
#include <Lite_EXPERT1.mqh>
//+==================================================================+
//| Custom Expert initialization function                            |
//+==================================================================+
int init()
  {
//---- Checking the correctness of Timeframe_Up variable value
   TimeframeCheck("Timeframe_Up", Timeframe_Up);                                                          
//---- Checking the correctness of Timeframe_Dn variable value 
   TimeframeCheck("Timeframe_Dn", Timeframe_Dn);  
//---- Initialization of variables
   MinBar_Up  = 3 + MathMax(FastEMA_Up, SlowEMA_Up) + SignalSMA_Up;
   MinBar_Dn  = 3 + MathMax(FastEMA_Dn, SlowEMA_Dn) + SignalSMA_Dn;                               
//---- 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
   double Osc1, Osc2;
   //----+ Declaring static variables
   //----+ +---------------------------------------------------------------+
   static datetime StopTime_Up, StopTime_Dn; 
   static int LastBars_Up, LastBars_Dn;
   static bool BUY_Sign1, BUY_Stop1, SELL_Sign1, SELL_Stop1;
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR LONG POSITIONS 1
   if (Test_Up) 
    {
      int IBARS_Up = iBars(NULL, Timeframe_Up);
      
      if (IBARS_Up >= MinBar_Up)
       {
         if (LastBars_Up != IBARS_Up)
          {
           //----+ Initialization of variables 
           BUY_Sign1 = false;
           BUY_Stop1 = false;
           LastBars_Up = IBARS_Up;
           StopTime_Up = iTime(NULL, Timeframe_Up, 0)
                                            + 60 * Timeframe_Up;
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS        
           Osc1 = iCustom(NULL, Timeframe_Up, 
                         "5c_OsMA", FastEMA_Up, SlowEMA_Up,
                                               SignalSMA_Up, 5, 1);
                                
           Osc2 = iCustom(NULL, Timeframe_Up, 
                         "5c_OsMA", FastEMA_Up, SlowEMA_Up,
                                               SignalSMA_Up, 5, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (Osc2 < IndLevel_Up)
             if (Osc1 > IndLevel_Up)
                          BUY_Sign1 = true;
                          
           if (Osc1 < IndLevel_Up)
                          BUY_Stop1 = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (!OpenBuyLimitOrder1(BUY_Sign1, 1, 
              Money_Management_Up, STOPLOSS_Up, TAKEPROFIT_Up,
                                            PriceLevel_Up, StopTime_Up))
                                                                 return(-1);
          if (ClosePos_Up)
                if (!CloseOrder1(BUY_Stop1, 1))
                                        return(-1);
                                        
          if (!Make_TreilingStop(1, TRAILINGSTOP_Up))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR SHORT POSITIONS 1
   if (Test_Dn) 
    {
      int IBARS_Dn = iBars(NULL, Timeframe_Dn);
      
      if (IBARS_Dn >= MinBar_Dn)
       {
         if (LastBars_Dn != IBARS_Dn)
          {
           //----+ Initialization of variables 
           SELL_Sign1 = false;
           SELL_Stop1 = false;
           LastBars_Dn = IBARS_Dn;
           StopTime_Dn = iTime(NULL, Timeframe_Dn, 0) 
                                            + 60 * Timeframe_Dn; 
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS        
           Osc1 = iCustom(NULL, Timeframe_Dn, 
                         "5c_OsMA", FastEMA_Dn, SlowEMA_Dn,
                                               SignalSMA_Dn, 5, 1);
                                
           Osc2 = iCustom(NULL, Timeframe_Dn, 
                         "5c_OsMA", FastEMA_Dn, SlowEMA_Dn,
                                               SignalSMA_Dn, 5, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (Osc2 > IndLevel_Dn)
             if (Osc1 < IndLevel_Dn)
                          SELL_Sign1 = true;
                          
           if (Osc1 > IndLevel_Dn)
                          SELL_Stop1 = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (!OpenSellLimitOrder1(SELL_Sign1, 2, 
              Money_Management_Dn, STOPLOSS_Dn, TAKEPROFIT_Dn,
                                            PriceLevel_Dn, StopTime_Dn))
                                                                 return(-1);
          if (ClosePos_Dn)
                if (!CloseOrder1(SELL_Stop1, 2))
                                        return(-1);
                                        
          if (!Make_TreilingStop(2, TRAILINGSTOP_Dn))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+
//----+ 
    
    return(0);
  }
//+------------------------------------------------------------------+

2つのブレイクアウトレベル UpLevel および DownLevel の代わりに、レベルは1つ使われています。EA にあるポジション管理アルゴリズムが2つだけなのは、そのためです。通常、OsMA と連携するトレーディングシステムでは、このレベルはゼロとして選択されますが、私はそれを変更できるように、EA の外部変数として残すことにしました。すなわち、OSMA インディケータが、インディケータが変化する最大値と最小値を持たず、その結果ブレイクアウトレベルの値に制限がないことを考慮する必要があるのです。ですが、申し上げたように、通常それはゼロです。未決注文鳥軽視時刻を定義するには、静的変数StopTime_Up と StopTime_Dn が使用され、バー変更時に 初めてそれらは次回のバー変更の時刻で初期化されます。

おわりに

結論として、オシレータトレーディングシステムは、現在の市場トレンドに対して多くの誤ったシグナルを出すことを付け加えたいと思います。そのような EA は市場がフラットな期間での処理、またはトレンドのみでのポジションオープンに使用するのがより適しています。


バックテストについては、おそらく初心者の EA プログラマーにとって最適化結果を正しく推定するには一番の方法だろうということを再度申し上げます。履歴を調整する際、すばらしい結果を出す EA には何も問題はありません。ただし、市場が最適化された EA パラメータからかけ離れる状況を避けるために、既製のEA をどのように使用するかはもっと理解が困難です。

MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/1517

添付されたファイル |
EXPERTS.zip (7.48 KB)
INCLUDE.zip (24.26 KB)
indicators.zip (5.59 KB)
TESTER.zip (5.28 KB)
自動化トレーディングシステムの作成 自動化トレーディングシステムの作成
これはおそらく魅力的にうつるでしょう - 数分間で利益を生む自動トレーディングシステム(ATC)を作成するプログラムの所有者になれるのです。望ましいインプットを入れ、Enterを押すのみです。すると、テストされたATCを取得し、期待される結果を得ることができます。ユニークなATCの開発に数千時間もかけているところ、これらの内容は浅はかに聞こえます。一方で、これはとても印象的でもあります。しかし、この問題は解決することができるのです。
外為市場は予測可能なのか?自分独自のトレーディング戦略を作成する方法は? 外為市場は予測可能なのか?自分独自のトレーディング戦略を作成する方法は?
Forex を始める人は皆こういった疑問に答えようとします。しかし、だれもがその答えを見つけるとは限りません。何年も賢明に働き、研究したとしても、です。本項のその他多くの疑問と共に、私は個人的にこの質問に答えてきました。そういう答えの結果として、効率的なトレーディング戦略の作成する方法が決まったのです。
RSS フィードによるトレードシグナルの送信 RSS フィードによるトレードシグナルの送信
みなさんのコミュニティのメンバーと今すぐコミュニケーションをする有名な方法である RSS FEEDS として、トレードシグナルを送信する方法は私のアイデアです。
Expert Advisor Code で簡単にエラーを検出しリカバリする方法 Expert Advisor Code で簡単にエラーを検出しリカバリする方法
Expert Advisor の作成では、コードエラーの検出およびリカバリの質問はひじょうに重要なものです。独特なのは、ちょうど良いタイミングで検出されないエラーが、すでに第一の検証段階にあるトレーディングシステムの貴重な考えを台無しにしてしまうことです。賢明な EA 作成者がだれしもそういった問題を一番最初から考慮に入れるのはそのためです。本稿では、このむつかしい問題に役立つ方法をいくつか詳しく説明します。