MetaTrader 5をダウンロードする

通貨ペアバスケットをトレードするときに発生するパターンのテスト。 パート I

1 9月 2017, 09:46
Andrei Novichkov
0
352

イントロダクション

トレードにおける通貨ペアバスケットの適用について、以前の記事では、トレードの原理、技術的な分析の手段と、検出することができるパターンを検討しました。 もちろん、特定のパターンパラメータを確認せずにそのようなメソッドに従うことは不可能です。 例えば、売られ過ぎ/買われ過ぎのレベルが上に配置される特定の値を明確にする必要があります。 ここでは、検出されたパターンのパラメータを調べ、トレーダーに対する推奨事項を試してみます。

研究ツール

以前に開発した "複合 WPR" を使用します。 多くの場合、以前の記事シリーズでを適用しており、ほとんどのパターンを検出するのに役立つことが証明されています。

インジケーターチャートを滑らかするために、WPR 期間を14から20に増やします。 これで品質を失うことなく、チャートを "真っすぐ" することができます。

D1、H4、H1 の3つのタイムフレームに関する研究を行います。 ここで説明するメソッドを使用して、他の期間の結果を得ることができます。 

基本的な用語と原則はここにあります。

研究パターン

ここでは、ここで説明したパターン #3 を使って学習を始めましょう。 パターンは非常に簡単です。 別の通貨ペアに相当するということは、長い間よく知られています。 トレード通貨ペアに対して次のメソッドで適用されます

トレーダーは、買われ過ぎのレベルが下向きにクロスされている場合、またはロウソクが閉じられた後に結合WPR によって上向きにクロスしている場合、バスケットのすべての通貨ペアのエントリシグナルを受信します。

どこで売られ過ぎ/買われ過ぎのレベルを見つけることができるでしょうか? 別の通貨ペアの標準 WPR については、この質問に答えることができます:

  • 買われ過ぎレベル:-20%
  • 売られ過ぎレベル:-80 パーセント

ここに研究の出発点があります。 データを使用して、結合 WPR のレベルのポジションを明確にします。 この結果は、パターンをチェックするときだけでなく、他の同様のケースでも参考になります。 適用されるメソッドはまた便利である。

インジケーターラインは、買われ過ぎの上か売られ過ぎの下にする必要があります。 潜在的な相場のエントリの数を定義するために履歴を分析してみましょう。 この段階でインジケーターを使用するつもりはありません。 代わりに、以前に開発された testIndexZig-Zag1 mq5 と testWPReur mq5 インジケーターを適用する予定です。 testWPReur mq5 では、バスケットコンポーネントに従ってデータを置き換えるだけです。 すでにインジケータの高低を知っているので、testIndexZig-Zag1 mq5 インジケーターのソースコードを簡素化します (100% から-100% に):

#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#propertyindicator_separate_window
#propertyindicator_buffers6
#propertyindicator_plots  3
//--- plot High
#property indicator_label1 「ハイ」
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrGreen
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//--- plot Low
#property indicator_label2 "低"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrGreen
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
//--- plot ZigZag
#property indicator_label3  "ZigZag"
#property indicator_type3 DRAW_SECTION
#property indicator_color3 clrRed
#property indicator_style3 STYLE_SOLID
#property indicator_width3 1
//--- plot Direction
#property indicator_label4  "Direction"
#property indicator_type4 DRAW_LINE
#property indicator_style4 STYLE_SOLID
#property indicator_width4 1
//--- plot LastHighBar
#property indicator_label5 「LastHighBar」
#property indicator_type5 DRAW_LINE
#property indicator_style5 STYLE_SOLID
#property indicator_width5 1
//--- plot LastLowBar
#property indicator_label6 「LastLowBar」
#property indicator_type6 DRAW_LINE
#property indicator_style6 STYLE_SOLID
#property indicator_width6 1

#include<ZigZag\CSorceData.mqh>
#include<ZigZag\CZZDirection.mqh>
#include<ZigZag\CZZDraw.mqh>
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum EDirection
  {
   Dir_NBars=0,
   Dir_CCI=1
  };
//---エントリーパラメータ
input EDirection  DirSelect=Dir_NBars;
input int                  CCIPeriod   =  14;
input ENUM_APPLIED_PRICE   CCIPrice    =  PRICE_TYPICAL;
input int                  ZZPeriod=14;

string               name;

CZZDirection*dir;
CZZDraw*zz;

//---インジケーターバッファ
double         HighBuffer[];
double         LowBuffer[];
double         ZigZagBuffer[];
double         DirectionBuffer[];
double         LastHighBarBuffer[];
double         LastLowBarBuffer[];
//+------------------------------------------------------------------+
//カスタムインジケーター初期化関数                                       |
//+------------------------------------------------------------------+
int h;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int()
  {
   switch(DirSelect)
     {
      case Dir_NBars:
         dir=new CNBars(ZZPeriod);
         break;
      case Dir_CCI:
         dir=new CCCIDir(CCIPeriod,CCIPrice);
         break;
     }
   if(!dir.CheckHandle())
     {
      Alert("Indicator 2 download error");
      return(INIT_FAILED);
     }
   zz=new CSimpleDraw();
//---インジケーターバッファマッピング
   SetIndexBuffer(0,HighBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,LowBuffer,INDICATOR_DATA);
   SetIndexBuffer(2,ZigZagBuffer,INDICATOR_DATA);
   SetIndexBuffer(3,DirectionBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(4,LastHighBarBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(5,LastLowBarBuffer,INDICATOR_CALCULATIONS);
   name = _Symbol + TimeFrameToShortString(Period()) + ".txt";
   h=FileOpen(name,FILE_CSV|FILE_WRITE|FILE_ANSI,',');
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {

   if(CheckPointer(dir)==POINTER_DYNAMIC)
     {
      delete(dir);
     }
   if(CheckPointer(zz)==POINTER_DYNAMIC)
     {
      delete(zz);
     }
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int ind=0;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
intOnCalculate(const int rates_total、
                constint prev_calculated,
                const int begin,
                const double &price[]
                )
  {
   int start;

   if(prev_calculated==0)
     {
      start=0;
     }
   else
     {
      start=prev_calculated-1;
     }

   for(int i=start;i<rates_total;i++)
     {
      HighBuffer[i]=price[i];
      LowBuffer[i]=price[i];
     }

   int rv;
   rv=dir.Calculate(rates_total,
                    prev_calculated,
                    HighBuffer,
                    LowBuffer,
                    DirectionBuffer);
   if(rv==0)return(0);
   zz.Calculate(rates_total,
                prev_calculated,
                HighBuffer,
                LowBuffer,
                DirectionBuffer,
                LastHighBarBuffer,
                LastLowBarBuffer,
                ZigZagBuffer);

   if(ind<= 10) ind++;
   if(ind == 10)
     {
      double mx=100,mn=-100;
      double lg;
      lg=mx-mn;
      lg/=100;
      double levels[100];
      int    count[100];
      ArrayInitialize(count,0);
      for(int i=1; i<101; i++) levels[i-1]=NormalizeDouble(lg*i + mn,_Digits);
      for(int i=0;i<rates_total;i++)
        {
         if(ZigZagBuffer[i]==0 || ZigZagBuffer[i]==EMPTY_VALUE) continue;
         else 
           {
            for(int j=0; j<100; j++) 
              {
               if(ZigZagBuffer[i]<levels[j]) 
                 {
                  count[j]++;
                  break;
                 }
              }
           }
        }
      for(int i=0; i<100; i++)
        {
         FileWrite(h,i,levels[i],count[i]);
        }
      FileClose(h);
      Print("Work complete: ",name);
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+


string TimeFrameToShortString(ENUM_TIMEFRAMES period)
{
   switch (period )
   {
      case PERIOD_M1:  return ("M1");
      case PERIOD_M2:  return ("M2");
      case PERIOD_M3:  return ("M3");
      case PERIOD_M4:  return ("M4");
      case PERIOD_M5:  return ("M5");
      case PERIOD_M6:  return ("M6");
      case PERIOD_M10: return ("M10");
      case PERIOD_M12: return ("M12");
      case PERIOD_M15: return ("M15");
      case PERIOD_M20: return ("M20");
      case PERIOD_M30: return ("M30");
      case PERIOD_H1:  return ("H1");
      case PERIOD_H2:  return ("H2");
      case PERIOD_H3:  return ("H3");
      case PERIOD_H4:  return ("H4");
      case PERIOD_H6:  return ("H6");
      case PERIOD_H8:  return ("H8");
      case PERIOD_H12: return ("H12");
      case PERIOD_D1:  return ("D1");
      case PERIOD_W1:  return ("W1");
      case PERIOD_MN1: return ("MN1");
   }
   return ("");
} 

前述したように、このインジケーターの主なコードは、この記事Dmitry Fedoseev氏によってコミュニティに提供されています。 上記のインジケータは、以下に添付のtest.zipアーカイブにあります。 必要なツールを用意しましたので、必要なデータを調べてみましょう。

トレードの可能な数

結合WPR の範囲は-100% から + 100% に変わるます。従って今のところ買われ過ぎのレベルが + 60% にあると仮定し、売られ過ぎのレベルは-60%に対応するとします。 インジケーターが買われ過ぎ/売られ過ぎのレベルを超えた回数を調べてみましょう。 これを行うには、ここで説明するメソッドを使用する必要があります。

  • 結合WPR チャート (testWPReur mq5) に testIndexZig-Zag1 mq5 インジケーターを適用します。 我々の目標は、以下の図のように、+ 70% と + 80% または-70% と-80% のレベルを超える極端な値の数を決定することです。 青色の4角形としてマークされている領域に注意してください。 今のところ、このような極値は計算に含まれていますが、今後はそのような値を整理します。

  • 適用された testIndexZig-Zag1 mq5 インジケーターは、testWPReur の mq5 インジケーターの範囲を 1% の間隔に分割し、各間隔内での極端な値の数を定義します。 結果がファイルに送信されます。 選択したすべてのタイムフレームに対して計算が繰り返されます。 その後、testWPReur のバスケット内容のデータを mq5 に変更し、次の通貨バスケットでタスクを続けます。

より利便にするため、すべてのバスケットと選択した期間の取得データは、テーブルとして配置されています。 EUR バスケットに関する表の断片が下に表示されます。 テーブルの行と列の値の意味を明確にしましょう。

  • Num. —インデックス番号。
  • Indicator ー-% 単位のインジケーターの値。 たとえば、-96 の値を持つラインは、-96% から-98% の間隔を組み合わせた WPR を意味します。
  • EUR —選択した期間ごとに極端な値の数を持つ3つの列。 たとえば、96% から 98% に変化する結合 WPR インジケーターを持つNum. 1 行は、この間隔内にある次の極値値の数が、各時間枠で D1-ゼロ、H4、および H1-1 であることを示しています。
  • History Depth - 計算に使用できる履歴の深さ。
  • Trade count (80%) —各タイムフレームの可能なエントリの総数。 たとえば、H4 の EUR バスケットは83のエントリを提供しており、結合WPR インジケーターが 80% の値を超えたか、指定した回数-80% よりも低かったことを意味します。
  • Trade cound(70%) - 70% の結合WPR の値の同じ変数。
  • Trade total (80%) - すべてのバスケットの潜在的なエントリの合計数および 80% の結合WPR の値のタイムフレーム。
  • Trade total (70%)-70% と同じ。


EUR ----
Num. Indicator Timeframe ----
D1 H4 H1 ----
0 -98 2 3 4 ----
1 -96 0 1 1 ----
2 -94 0 0 1 ----
3 -92 0 3 3 ----
4 -90 1 4 5 ----
5 -88 3 4 10 ----
6 -86 1 2 7 ----
7 -84 2 8 7 ----
8 -82 1 8 21 ----
9 -80 4 6 22 ----
---- ---- ---- ---- ---- ----
95 92 0 2 6 ----
96 94 0 1 4 ----
97 96 0 0 3 ----
98 98 0 3 0 ----
99 100 0 0 0 ----
History Depth 2000.11.09 2005.04.12 2006.01.17 ----





----
Trade count (80%) 25 83 165 ----
Trade count (70%) 45 207 449 ----












Trade total (80%) 3793


Trade total (70%) 7885


テーブルは、添付にあります。 zip アーカイブ。

最後の2つのテーブル行には、検索値が含まれます。 シグナルの一部が選別されることを考慮に入れても、エントリー可能な相場が多くあります。 したがって、今のところ同じ場所で売られ過ぎ/買われ過ぎレベルを残してみましょう。 すべての見つかった (および既存の) 値は、確率的であり、修正することに注意してください。

パターンフォーム

相場に参入するために識別する必要があるパターンの形状を定義しましょう。

  • トレーダーは、結合WPR インジケーターが買われ過ぎレベル + 60% 下方にクロスする場合、通貨ペアのバスケットを売りしています。 ロウソク足クロージャーでは、インジケーターの値は + 50% より低くはありませんでした。インジケーターラインの減少は、+ 70% より低い値から発生します。 このポイントの2番目のオプションは + 80% 以上であり、買われ過ぎレベルでは + 70% です。
  • 通貨ペアのバスケットを買いする場合は、対称です。

上記の画像で強調表示されている3つのパターンはすべて、条件を満たします。 アルゴリズムに変換することができる数値と条件を持つ明確な "美しい" パターンです。

つまり、EAが必要です。

パターンをテストするためのEA

まず、バスケットの買い/売りに対処しましょう。 この記事では、トレード通貨バスケットの詳細を検索し、各バスケットの実用的なテーブルを調べることができます。 この表を使用して、EAを同じ原理を実装してみましょう。

探しているパターンをもう一度見ましょう:

ターゲットパターン
パターンなし



売られ過ぎ/買われ過ぎレベルが 60-70% の範囲でシフトする可能性があると仮定します。 チェックパターンによるトレードの数にをチェックしてみましょう, トレードの期間, ドローダウンと潜在的な収益性. 今のところ EA から安定した利益を必要としません。 目標は、パターンの形状を明らかにする最初のステップを獲得することです。 したがって、EA の収益性には関心がないため、標準のテスターレポートは公開しませんが、必要なデータは標準レポートには含まれていません。 得られた結果を表示することに注力します。

前に選択された期間に EURUSD の EA を配置することにより、米ドル通貨バスケットから分析を開始します:

//+------------------------------------------------------------------+
//                                                  testBasket mq5 |
//|                        Copyright 2017, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
//---エントリーパラメータ

#include<Trade\\Trade.mqh>


#defineLG 7

input int SELLPROFIT =   0;
input int SELL1LIMIT =  70;
input int SELL2FROM  =  60;
input int SELL2TO    =  50;

input int BUYPROFIT  =   0;
input int BUY1LIMIT  = -70;
input int BUY2FROM   = -60;
input int BUY2TO     = -50;

input int WPR=20;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum BSTATE 
  {
   BCLOSE = 0,
   BBUY   = 1,
   BSELL  = 2
  };

string pair[]={"EURUSD","GBPUSD","AUDUSD","NZDUSD","USDCAD","USDCHF","USDJPY"};
bool bDirect[]={false,false,false,false,true,true,true};
datetime TimeParam[3];

double dWpr[3];
ulong  Ticket[LG];
double TradeResult[LG];
double TradeCurrency;
double Drw;
string sLog;

double TradeTotalResult[LG];
double TradeTotalCurrency;
int    iTradeCount;
double mDrw;

int h1[LG];
BSTATE bstate;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double GetValue1(int shift)
  {
   double dBuf[1];
   double res=0.0;
   for(int i=0; i<LG; i++)
     {
      CopyBuffer(h1[i],0,shift,1,dBuf);
      if(bDirect[i]==true)
         res+=dBuf[0];
      else
         res+=-(dBuf[0]+100);
     }//end for (int i = 0; i < iCount; i++)      
   res=res/LG;
   return (NormalizeDouble((res + 50) * 2, _Digits) );
  }

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int lh;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int()
  {
   EventSetTimer(1);

   for(int i=0; i<LG; i++)
     {
      h1[i]=iWPR(pair[i],0,WPR);
     }
   bstate=BCLOSE;

   ArrayInitialize(TradeTotalResult,0);
   ArrayInitialize(dWpr,EMPTY_VALUE);
   TradeTotalCurrency=0;
   iTradeCount=0;
   mDrw=1000000;

   lh=INVALID_HANDLE;
   string lname = _Symbol + "_" + TimeFrameToShortString(Period() );
   string t1, t = lname;
   int i=0;
   for(;;) 
     {
      t+=".html";
      long lg=FileFindFirst(t,t1);
      if(lg==INVALID_HANDLE) 
        {
         lh= FileOpen(t,FILE_WRITE | FILE_TXT | FILE_ANSI);
         Print("CREATE ",t);
         break;
        }
      FileFindClose(lg);
      t=lname+"_"+IntegerToString(i++);
     }

   FileWriteString(lh,"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\r\n");
   FileWriteString(lh,"<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n");
   FileWriteString(lh,"<head>\r\n");
   FileWriteString(lh,"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\r\n");
   FileWriteString(lh,"<title>"+lname+"</title>\r\n");
   FileWriteString(lh,"</head>\r\n<body>\r\n");
   FileWriteString(lh,"<H2>"+_Symbol+" "+TimeFrameToShortString(Period())+"</H2>\r\n");
   FileWriteString(lh,"<H3>Pattern Params:</H3>\r\n");
   FileWriteString(lh,"<table width=\"100%\" cellspacing=\"0\" cellpadding=\"5\">\r\n");
   FileWriteString(lh,"<thead>\r\n<tr>\r\n<th>BUY</th>\r\n<th>SELL</th>\r\n</tr>\r\n</thead>\r\n<tbody>\r\n<tr>\r\n");
   t=StringFormat("Point 1: %d Point 2 from: %d to: %d Close at: %d",BUY1LIMIT,BUY2FROM,BUY2TO,BUYPROFIT);
   FileWriteString(lh,"<td style=\"text-align:center;\">\r\n<ul>\r\n<li>"+t+"</li>\r\n</ul>\r\n</td>\r\n");
   t=StringFormat("Point 1: %d Point 2 from: %d to: %d Close at: %d",SELL1LIMIT,SELL2FROM,SELL2TO,SELLPROFIT);
   FileWriteString(lh,"<td style=\"text-align:center;\">\r\n<ul>\r\n<li>"+t+"</li>\r\n</ul>\r\n</td>\r\n");
   FileWriteString(lh,"</tr>\r\n</tbody>\r\n</table>\r\n");
   FileWriteString(lh,"<H2>"+"Tester Result"+"</H2>\r\n");
   FileWriteString(lh,"<table border=\"1\" width=\"100%\" cellspacing=\"0\" cellpadding=\"5\">\r\n");
   FileWriteString(lh,"<thead>\r\n<th>Num.</th>\r\n<th>Type</th>\r\n<th>WPR(P1/P2)</th>\r\n<th>Time(Begin/End/Length)</th>\r\n<th>Drawdown/<br/>Profit</th>\r\n<th>Pair Profit</th>\r\n</tr>\r\n</thead>\r\n<tbody>\r\n");

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void PushWpr(double wpr) 
  {
   dWpr[2] = dWpr[1]; dWpr[1] = dWpr[0];
   dWpr[0] = wpr;
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void Stat() 
  {

   double d=0;
   for(int i=0; i<LG; i++) 
     {
      PositionSelectByTicket(Ticket[i]);
      d+=PositionGetDouble(POSITION_PROFIT);
     }
   if(d<Drw) Drw=d;
   if(Drw<mDrw) 
     {
      mDrw=Drw;
      TimeParam[2]=TimeCurrent();
     }
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   if(bstate!=BCLOSE) 
     {
      Stat();
     }
   if(IsNewCandle()) 
     {
      double res=GetValue1(0);
      PushWpr(res);
      if(dWpr[1]!=EMPTY_VALUE) 
        {
         if(bstate==BBUY && (dWpr[0]>=BUYPROFIT )) 
           {
            CloseAllPos();
            bstate=BCLOSE;
           }
         if(bstate==BSELL && (dWpr[0]<=SELLPROFIT )) 
           {
            CloseAllPos();
            bstate=BCLOSE;
           }
         if(bstate==BCLOSE && dWpr[0]<=SELL2FROM && dWpr[0]>=SELL2TO && dWpr[1]>=SELL1LIMIT) 
           {
            EnterSell(0.01);
            bstate=BSELL;
            TimeParam[0]=TimeCurrent();
            TradeCurrency=0;
            Drw=1000000;
            iTradeCount++;
            sLog=StringFormat("<tr>\r\n<td>%d</td>\r\n<td>SELL</td>\r\n<td>%.2f/<br/>%.2f</td>\r\n<td>%s/<br/>",iTradeCount,dWpr[1],dWpr[0],TimeToString(TimeCurrent()));
            return;
           }
         if(bstate==BCLOSE && dWpr[0]>=BUY2FROM && dWpr[0]<=BUY2TO && dWpr[1]<=BUY1LIMIT) 
           {
            EnterBuy(0.01);
            bstate=BBUY;
            TimeParam[0]=TimeCurrent();
            TradeCurrency=0;
            Drw=1000000;
            iTradeCount++;
            sLog=StringFormat("<tr>\r\n<td>%d</td>\r\n<td>BUY</td>\r\n<td>%.2f/<br/>%.2f</td>\r\n<td>%s/<br/>",iTradeCount,dWpr[1],dWpr[0],TimeToString(TimeCurrent()));
            return;
           }
        }//if (stc.Pick(1) != EMPTY_VALUE)
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseAllPos() 
  {

   CTrade Trade;
   Trade.LogLevel(LOG_LEVEL_NO);

   TimeParam[1]=TimeCurrent();
   string p="<td>";
   for(int i=0; i<LG; i++) 
     {
      xTradeResult[i]=PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_SWAP);
      p+=StringFormat("%s = %.2f<br/>",pair[i],TradeResult[i]);
      TradeCurrency       += TradeResult[i];
      TradeTotalResult[i] += TradeResult[i];
      Trade.PositionClose(Ticket[i]);
     }
   p+="</td>\r\n";
   TradeTotalCurrency+=TradeCurrency;
   sLog += StringFormat("%s/<br/>%s</td>\r\n<td>%.2f/<br/>%.2f</td>\r\n",TimeToString(TimeParam[1]), TimeIntervalToStr(TimeParam[0], TimeParam[1]), Drw, TradeCurrency );
   sLog += p;
   FileWriteString(lh,sLog);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void EnterBuy(double lot) 
  {

   CTrade Trade;
   Trade.LogLevel(LOG_LEVEL_NO);

   for(int i=0; i<LG; i++) 
     {
      if(bDirect[i]) 
        { //send buy
         Trade.Buy(lot,pair[i]);
         Ticket[i]=Trade.ResultDeal();
        }
      else 
        { //send sell
         Trade.Sell(lot,pair[i]);
         Ticket[i]=Trade.ResultDeal();
        }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void EnterSell(double lot) 
  {

   CTrade Trade;
   Trade.LogLevel(LOG_LEVEL_NO);

   for(int i=0; i<LG; i++) 
     {
      if(bDirect[i]) 
        { //send sell
         Trade.Sell(lot,pair[i]);
         Ticket[i]=Trade.ResultDeal();
        }
      else 
        { //send buy
         Trade.Buy(lot,pair[i]);
         Ticket[i]=Trade.ResultDeal();
        }
     }
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();

   FileWriteString(lh,"</tbody>\r\n</table>\r\n");
   FileWriteString(lh,"<H2>Total Result</H2>\r\n");
   FileWriteString(lh,"<table border=\"1\" width=\"100%\" cellspacing=\"0\" cellpadding=\"5\">\r\n");
   FileWriteString(lh,"<thead>\r\n<tr>\r\n<th>Deal's<br/>Count</th>\r\n<th>Profit</th>\r\n<th>Max.Drawdown</th>\r\n<th>Pair's Profit</th>\r\n</tr>\r\n</thead>\r\n<tbody>\r\n");
   string p = StringFormat("<tr><td>%d</td>\r\n<td>%.2f</td>\r\n<td>%.2f at<br/>%s</td>\r\n<td>",iTradeCount,TradeTotalCurrency,mDrw,TimeToString(TimeParam[2]));
   for(int i=0; i<LG; i++)
     {
      if(h1[i]!=INVALID_HANDLE) IndicatorRelease(h1[i]);
      p+=StringFormat("%s = %.2f<br/>",pair[i],TradeTotalResult[i]);
     }
   p+="</td>\r\n</tr>\r\n";
   FileWriteString(lh,p);
   FileWriteString(lh,"</tbody>\r\n</table>\r\n");
   FileWrite(lh,"</body>\r\n</html>"); //End log
   FileClose(lh);
  }
//+------------------------------------------------------------------+

boolIsNewCandle () 
  {

   static int candle=-1;

   int t1=0;
   switch(_Period)
     {
      case PERIOD_H1:  t1 = Hour();   break;
      case PERIOD_H4:  t1 = Hour4();  break;
      case PERIOD_D1:  t1 = Day();    break;
     }
   if(t1!=candle) {candle=t1; return(true);}
   return (false);
  }
int Hour4(){return((int)Hour()/4);}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int Day()
  {
   MqlDateTime tm;
   TimeCurrent(tm);
   return(tm.day);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int Hour()
  {
   MqlDateTime tm;
   TimeCurrent(tm);
   return(tm.hour);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string TimeIntervalToStr(datetime dt1,datetime dt2) 
  {
   string tm;
   if(dt1 >= dt2)   tm = TimeToString(dt1 - dt2);
   else tm = TimeToString(dt2 - dt1,TIME_DATE|TIME_MINUTES|TIME_SECONDS);
   string ta[],ta1[];
   StringSplit(tm,StringGetCharacter(" ",0),ta);
   StringSplit(ta[0],StringGetCharacter(".",0),ta1);
   ta1[0] = IntegerToString( StringToInteger(ta1[0]) - 1970);
   ta1[1] = IntegerToString( StringToInteger(ta1[1]) - 1);
   ta1[2] = IntegerToString( StringToInteger(ta1[2]) - 1);
   return (ta1[0] + "." + ta1[1] + "." + ta1[2] + " " + ta[1]);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string TimeFrameToShortString(ENUM_TIMEFRAMES period)
  {
   switch(period)
     {
      case PERIOD_H1:  return ("H1");
      case PERIOD_H4:  return ("H4");
      case PERIOD_D1:  return ("D1");
     }
   return ("");
  }
//+------------------------------------------------------------------+

テスト用の最初の EA バージョンは、添付の testBasket mq5 ファイルにあります。 このアルゴリズムには特別なものは含まれていませんが、レポートフォームには多くの注意が払われています。 EA のエントリーの意味を明確にしてみましょう:

  • SELLPROFIT. 結合WPR インジケーターがこの値に達すると、バスケットを売りするために開いたすべてのポジションを閉じます。 デフォルト値は 0% です。
  • SELL1LIMIT. ポイント 1 (上の画像を参照) の組み合わせ WPR の最小値であり、バスケットの売りパターンの識別を開始します。 デフォルト値は 70% です。
  • SELL2FROM。バスケットの売りパターンを識別するために、ポイント2の組み合わせ WPR の最大値。 デフォルトでは、60% は買われ過ぎレベルです。
  • SELL2TO. バスケットの売りパターンの最終的な識別のポイント2の結合WPR の最小値。 デフォルト値は 50% です。
  • BUYPROFIT. 結合WPR インジケーターがこの値に達すると、バスケットを買いするために開いたすべてのポジションを閉じます。 デフォルト値は 0% です。
  • BUY1LIMIT. ポイント1の組み合わせ WPR の最大値で、バスケットの買いパターンを識別します。 デフォルト値は-70% です。
  • BUY2FROM。バスケットの買いパターンを識別するために、ポイント2の組み合わせ WPR の最小値。 デフォルトでは、60% は売られ過ぎのレベルです。
  • BUY2TO. バスケットの買いパターンの最終的な識別のポイント2の結合WPR の最大値。 The default is -50%.
  • WPR. WPR 標準技術インジケーターの期間。 デフォルト値は20です。

次に、1月2016からテスターで EA をテストします。 選択したテスト日は、履歴の品質によって異なります。 2パターンの形態を分析します。 最初のものは、上記で説明されており、デフォルトで設定します。 2つ目は、次のように最初の1つに対して相対的にシフトされます。

  • SELLPROFIT. 結合WPR インジケーターがこの値に達すると、バスケットを売りするために開いたすべてのポジションを閉じます。 0% の値です。
  • SELL1LIMIT. ポイント 1 (上の画像を参照) の組み合わせ WPR の最小値であり、バスケットの売りパターンの識別を開始します。 80% の値です。
  • SELL2FROM。バスケットの売りパターンを識別するために、ポイント2の組み合わせ WPR の最大値。 70%、買われ過ぎレベルの値です。
  • SELL2TO. バスケットの売りパターンの最終的な識別のポイント2の結合WPR の最小値。 50% の値です。
  • BUYPROFIT. 結合WPR インジケーターがこの値に達すると、バスケットを買いするために開いたすべてのポジションを閉じます。 0% の値です。
  • BUY1LIMIT. ポイント1の組み合わせ WPR の最大値で、バスケットの買いパターンを識別します。 -80% の値です。
  • BUY2FROM。バスケットの買いパターンを識別するために、ポイント2の組み合わせ WPR の最小値。 -70%、売られ過ぎのレベルの値です。
  • BUY2TO. バスケットの買いパターンの最終的な識別のポイント2の結合WPR の最大値。 -50% の値です。

結果は html レポートです。

EA レポートフォーム

このEA のレポートは、理解しやすいです。 例として、EUR バスケットレポートを使用したレポートの構造を考えてみましょう。

最初の行には、EA が開始されたチャートとタイムフレームの名前を含むヘッダがあります。

EA はバスケットを買いして売りするために別々に適用されているパターンのパラメータが続きます: ポイント 1-ポイント1場所: SELL1LIMIT (BUY1LIMIT). ポイント2からポイント2へ次のように:...-ロケーション: SELL2FROM (BUY2FROM) と SELL2TO (BUY2TO)。 閉じる-SELLPROFIT (BUYPROFIT) パターンクロージャーポイントの場所:

EURUSD H4

パターンパラメータ:

BUY SELL
  • ポイント 1:-80 ポイント2から:-70 から:-50: 0で決済
  • ポイント 1:80 ポイント 2:70 から:50 0で決済

パターンパラメータには、テスト期間中の各トレードのデータを次のオーダーで含むテスターの結果テーブルが続きます。

  • Num. —インデックス番号
  • タイプ-トレードタイプ: バスケットの売りまたは買い
  • WPR (P1/P2)-相場に参入するために使用されるポイント 1/point 2 形式の結合 WPR のデータ
  • 時間 (開始/決済/長さ)-トレード時間に関するデータ: 相場参入時間/決済時間/トレード期間
  • ドローダウン/利益-トレードタイム/最終利益あたりの最大ドローダウン。 資産通貨のデータ。
  • ペア利益-個々のペアによる利益通貨バスケットはから成っている。 資産通貨のデータ。

最初のトレードは8時間続き、16.34 ドルの損失をもたらしたことを見ることができます。 特に、EURUSD のオーダーは2.55 ドルの損失で決済された:

Num. Type WPR(P1/P2) Time(Begin/End/Length) Drawdown/
Profit
Pair Profit
1 SELL 86.26/
67.15
2016.03.23 20:00/
2016.03.24 04:00/
0.0.0 08:00:00
-21.70/
-16.34
EURUSD = -2.55
GBPUSD = -1.58
AUDUSD = -2.02
NZDUSD = -3.66
USDCAD = -2.15
USDCHF = -2.97
USDJPY = -1.41


次のオーダーでテスト期間のサマリーデータを含む "合計結果" テーブルが最後に来ます:

  • ディールのカウント-テスト期間全体のトレード数。
  • 利益-全体のテスト期間の利益を得た。 資産通貨のデータ。
  • マックスドローダウン-最大ドローダウンと検出された瞬間。 資産通貨と日付のデータ。
  • ペアの利益-各通貨ペアごとの合計利益バスケットの通貨から成ります。 資産通貨のデータ。

次に、レポートから直接テーブルを示します。

Deal's
Count
Profit Max.Drawdown Pair's Profit
22 189.06 -52.37 at
2016.05.02 19:53
EURUSD = 52.43
GBPUSD = 24.50
AUDUSD = 45.88
NZDUSD = 13.94
USDCAD = 15.73
USDCHF = 12.26
USDJPY = 24.32


取得したレポートは DocUSD.zip に添付されています。

D1 上のトレードが意外に少ないことは注目に値します。 しかし、心強いシグナルがあります。

  • EA は、H4 と H1 に肯定的な結果を示している。

データはかなり限られていますが、予備的な結論を出すことができます。

  1. パターンはほとんど毎日の時間枠で見つけられない。 このトレンドは、ほとんどの場合、D1 よりも高いタイムフレームで継続する可能性があります。
  2. 買われ過ぎ/売られ過ぎのレベルは 60% の範囲内である-70% の場合には-60%--70% の場合には売られ過ぎです。 70% および-70% の下で多くのトレードがない。 この場合、ポイント1は 90% 以上である必要があります。これは-90% 以下のパターンを識別するために、まれに発生します。 60% 以上-60% 以下では、ポイント2が 40% または-40% 近くになり、潜在的な平坦領域に近づきます。 この領域は、インジケーターの測定値と複数の偽のエントリシグナルのさらに大きなボラティリティによって特徴付けられる。

EA を完成させ、バスケットの次の通貨-NZD を続行します。 まず、 "ポジティブドローダウン"値を推測して、レポートフォームの変更を行う必要があります。 この概念の背後にあるアイデアは何でしょうか? バスケットは、特定の利益価値または指定されたトレードレベルではなく、インジケーターの測定値に従って閉じられます。 決済の前に、オーダーのバスケット内のオーダーは EA によって監視されるドローダウンにある場合もあります。 同じオーダーは、インジケーターがまだ決済に必要な値に達していないため、固定できない重要な利益を示すことがあります。 これを「ポジティブドローダウン」と呼び、その最大値がレポートに送信されます。 潜在的な利益とは、バスケットの能力をプラス側に移動することを知っている。

この値をテスターの結果テーブルの2番目の列に追加してみましょう。 ドローダウン/利益列は、現在ドローダウン/+ ドローダウン/利益と呼ばれています。 列の各セルからのデータは、次のオーダーで配置されます: ドローダウン/ポジティブドローダウン/利益。 すべてのデータは、資産通貨になります。

加えて、最大のポジティブドローダウンは、合計結果テーブルに表示されます。 さらに2番目の "Max. + ドローダウン" 列を紹介し、ドローダウンが修正されたときのテスト期間全体の最大ポジティブドローダウンを示しましょう。

次の EAのソースコードは、以下に添付されている testBasket1 の mq5 ファイルにあります。

取得した NZD のバスケットレポートは、DocNZD のアーカイブにあります。 結論は次の通りです:

  • 買われ過ぎ/売られ過ぎのレベルの場所の仮定が確認されます。 NZDUSD_H1_1 の html レポートは、多数の偽のエントリを含むレンジに近いレベルでアーカイブに追加されます。 結果は明白です。
  • D1 のこのパターンによる少数のトレードが確認されます。
  • H1 の結果は残念なものです。 時間枠の "ノイズレベル" は、虚偽のシグナルを引き起こすすべてのバスケットの通貨ペアの合計であると仮定することができます。

残りのバスケット通貨 (豪ドル、ユーロ、英ポンド、カナダドル、日本円、スイスフラン) を使用して、研究を締めくくりましょう。 通貨に関するレポートは、添付のドキュメント .zip アーカイブで確認してください。 結果をまとめましょう。

結果

  • 買われ過ぎレベルは、実際には 60-70% の範囲内で、売られ過ぎレベルは-60% と-70% 以内です。 この仮定は、得られたレポートと標準WPR インジケーターの対応するレベルの場所によって確認されます。
  • チェックは3つのタイムフレームとすべての8つのバスケットに実施されています。 買われ過ぎ/売られ過ぎラインの 画期的な2つの形式を分析しています:
    1. パターンのポイント1は 80% を超えています。 売られ過ぎのレベルは 70% です。 ポイント2は 70% および 50% の内にあります。 バスケットは、インジケーターが0%より小さいときに閉じられます。 バスケットを売りするために相場に入るためのパターンの形態はここに示されています。 買いエントリの形式は、マイナスシンボルで対称です。
    2. パターンのポイント1は 70% を超えています。 売られ過ぎのレベルは 60% です。 ポイント2は 60% と 50% の間にあります。 バスケットは、インジケーターが0%より小さいときに閉じられます。 バスケットを売りするために相場に入るためのパターンの形態はここに示されています。 バスケットの買いエントリの形式は、マイナスシンボルと対称です。
  • D1の少数の取り引きがあることをもう一度注意するべきであり、もはやこの記事でを参照しません。 すべてのレポートの [集計結果] テーブルのデータを使用して、他のタイムフレームの集計表を作成してみましょう。 この表は、各通貨バスケットの資産通貨での EA のトレードの結果と、前の段落で説明した両方のパターンフォームを示しています。

     

    H1 timeframe
      AUD EUR USD GBP NZD CAD CHF JPY
    Pattern 1 -590 90 -37 -991 -141 -80 -118 -514
    Pattern 2 -259 -67 328 -714 -352 -446 -118 -272

     

    H4 timeframe
      AUD EUR USD GBP NZD CAD CHF JPY
    Pattern 1 286 -72 189 -400 104 60 -209 120
    Pattern 2 -208 25 40 80 172 10 -69 -176

     

    H1 残念な結果に注目してみましょう。 おそらく、この時間枠の通貨ペアの高い "ノイズ" レベルによるものです。
  • H4 の結果はより有望です。 この時間枠に特に注意を払いましょう。

得られた結果は、パターンの2つのフォームの間で選択することはできませんので、両方で動作する必要があります。 2番目のフォームの可能性はは大きいようですが、これは主観的な意見です。 これついては、後で最終決定をします。

H1のタスクを完了した方がよいでしょうか? 少なくともそれはないでしょう! 覚えているかもしれませんが、レポートに "ポジティブドローダウン" パラメータを導入しています。 従来のドローダウンと比較すると、次のことがわかります。

  • 結合WPR の測定値に従ってバスケットを閉じる最初の考えは (価値がゼロに達するとき) 十分ではない。 損失を制限する問題も解決されていません。 オーダーのバスケットを取扱うので、通貨のストップロスを割り当て、通貨の利益をまた辿ることは論理的です。 利益から損失を防ぐことが、一方で、合理的なメソッドで潜在的損失を制限することができます。 このようなメソッドは、H1 の肯定的な結果につながると H4 の収益性を向上させることができます。 今のところの計画の一部ではありませんが、提案された解決策は、将来的に有用である可能性があります。

結論

パターンテストの最初の段階が完了しました。 得られた結果は考察を必要とします。 今後のタスクでは、シグナルを選別することに着目し、他の既知のパターンからの追加シグナルを解析します。 新たな情報を得ることができるだけでなく、既に得られたデータを徐々に絞り込みます。

この記事で使用されるプログラム:

 # Name
Type
 Description
1 Pair.zip Archive
3つの選択されたタイムフレームによってすべてのバスケットの通貨の可能なトレードの数を計算する結果。
2
testBasket.mq5 EA
テストEA。
3
DocUSD.zip Archive 米ドルバスケットと testBasket mq5 EA の操作に関する Html レポート。
 4 DocNZD.zip Archive testBasket1 に関する Html レポートは、NZD バスケットで mq5 EA の操作を行います。
5
testBasket1.mq5 EA テストEA-次のバージョン。
 6  Doc.zip Archive
他のバスケットとの testBasket1 mq5 EA 操作に関する Html レポート。
7 test.zip
 Archive testIndexZig-Zag1 の mq5 と testWPReur mq5 のインジケーターでアーカイブします。



MetaQuotes Software Corp.によりロシア語から翻訳された
元の記事: https://www.mql5.com/ru/articles/3339

添付されたファイル |
testBasket.mq5 (26.57 KB)
DocUSD.zip (14.3 KB)
DocNZD.zip (27.8 KB)
testBasket1.mq5 (27.74 KB)
Doc.zip (99.72 KB)
test.zip (3.82 KB)
Pair.zip (7.92 KB)
クロスプラットフォームEA: タイムフィルタ クロスプラットフォームEA: タイムフィルタ

この記事では、クロスプラットフォームEAによるさまざまな時間フィルタリングメソッドの実装について説明します。 時間フィルタクラスは、特定の時間が一定の時間構成設定に該当するかどうかをチェックします。

通貨バスケットをトレードするときに利用可能なパターン。 パート III 通貨バスケットをトレードするときに利用可能なパターン。 パート III

通貨ペアバスケットをトレードするときに発生するパターンに特化した最後の記事です。 複合トレンドフォローインジケーターと標準グラフィカル構造のアプリケーションを考察します.

MQL5ソースコードに基づくドキュメントの作成 MQL5ソースコードに基づくドキュメントの作成

本稿では、必要なタグの自動マークアップから始まるMQL5コードのドキュメントの作成について考察し、Doxygenソフトウェアの使い方と正しい設定の仕方、html、HtmlHelp、PDFなどのさまざまな形式で結果を受け取る方法についても説明します。

MQL5を使用した整列法とその可視化 MQL5を使用した整列法とその可視化

Graphic.mqhライブラリは、MQL5のグラフィックスで動作するように設計されています。本稿では、実用的なアプリケーションの例を示し、ソートの概念について説明します。ソートタイプには既に少なくとも1つの別個の記事が書かれておりソートタイプのいくつかは詳細な調査の対象なので、ここではソートの一般的な概念が説明されます。