日別アーカイブ: 2015年1月29日

ブレイクアウトシステムと BBW フィルタ

自作ブレイクアウトシステム(yasciiBreakout05)に BBW フィルタを組み込んでみました。

ドル円 4時間足 2014/1/1-2015/1/1

1つの負けが減って、1つ勝ちが増えただけのようです。

ちなみに前作はこちら。

まあ、ブレイクアウトするときは当然 BBW の値は増加しているわけで、やらずもがな(意味がなかった)というオチかなとも思っていましたが、1つだけでも改善したのはもうけものです。

プログラムソース

 

//
// yasciiBreakout06.mq4
//
//    with BBW filter

//マジックナンバーの定義
#define MAGIC  42882        

//パラメーターの設定//
extern double Lots = 1.0;     //取引ロット数
extern int Slip = 10;         //許容スリッページ数
extern string Comments =  "Breakout06"; //コメント

extern int Fast_period = 14 ;
extern int Slow_period = 40 ;
extern int Range_period = 21 ;
extern double margin = 0.0 ;
extern double Range_threshold = 550.0 ;

extern int       BB_Period=20;
double    Deviation=1.0;

extern double ILC = 160.0 ;
// extern double TP = 1100 ;

//変数の設定//
int Ticket_L = 0; //買い注文の結果をキャッチする変数
int Ticket_S = 0; //売り注文の結果をキャッチする変数
int Exit_L = 0;   //買いポジションの決済注文の結果をキャッチする変数
int Exit_S = 0;   //売りポジションの決済注文の結果をキャッチする変数
int OS1 ;
int OS2 ;

double   OOPL;
double   OOPS;

int start()
  {

   double FastHH1 = Close[iHighest(NULL, 0, MODE_CLOSE, Fast_period, 1)];
   double FastLL1 = Close[iLowest(NULL, 0, MODE_CLOSE, Fast_period, 1)];

   OS1 = OrderSelect(Ticket_L, SELECT_BY_TICKET);  

   //買いポジションのエグジット
   if( Bid < FastLL1-margin 
       && ( Ticket_L != 0 && Ticket_L != -1 ))
    {     
      Exit_L = OrderClose(Ticket_L,Lots,Bid,Slip,Red);
      if( Exit_L ==1 ) {Ticket_L = 0;}
    }    

   OS2 = OrderSelect(Ticket_S, SELECT_BY_TICKET); 

   //売りポジションのエグジット
   if( Ask> FastHH1+margin
       && ( Ticket_S != 0 && Ticket_S != -1 ))
    {     
      Exit_S = OrderClose(Ticket_S,Lots,Ask,Slip,Blue);
      if( Exit_S ==1 ) {Ticket_S = 0;} 
    }   

   if (Volume[0]>1 || IsTradeAllowed() == false) return(0) ;

   double FastHH2 = Close[iHighest(NULL, 0, MODE_CLOSE, Fast_period, 2)];
   double FastLL2 = Close[iLowest(NULL, 0, MODE_CLOSE, Fast_period, 2)];
   double SlowHH2 = Close[iHighest(NULL, 0, MODE_CLOSE, Slow_period, 2)];
   double SlowLL2 = Close[iLowest(NULL, 0, MODE_CLOSE, Slow_period, 2)];

   double value_range = High[iHighest(NULL, 0, MODE_HIGH, Range_period, 2)]-Low[iHighest(NULL, 0, MODE_LOW, Range_period, 2)];

   double bbw1 = iBands( NULL, 0, BB_Period, Deviation, 0, PRICE_CLOSE, 1, 1) -  iBands( NULL, 0, BB_Period, Deviation, 0, PRICE_CLOSE, 0, 1);
   double bbw2 = iBands( NULL, 0, BB_Period, Deviation, 0, PRICE_CLOSE, 1, 2) -  iBands( NULL, 0, BB_Period, Deviation, 0, PRICE_CLOSE, 0, 2);

   double lc = ILC;
   if(( Digits ==3 ) ||(Digits ==5)) lc = lc*10.0 ;

   //買いポジションのエグジット
   OS1 = OrderSelect(Ticket_L, SELECT_BY_TICKET);  
   OOPL = OrderOpenPrice();   
   if( ( (Close[2] >=FastLL2-margin && Close[1] < FastLL2-margin) || ( OOPL - lc*Point >= Close[1] ) ) //|| ( OOPL+TP*Point <= Close[1] ))
       && ( Ticket_L != 0 && Ticket_L != -1 ))
    {     
      Exit_L = OrderClose(Ticket_L,Lots,Bid,Slip,Blue);
      if( Exit_L ==1 ) {Ticket_L = 0;}
    }    

   //売りポジションのエグジット
   OS2 = OrderSelect(Ticket_S, SELECT_BY_TICKET); 
   OOPS = OrderOpenPrice();
   if(    ((Close[2] <=FastHH2+margin && Close[1] > FastHH2+margin) ||( OOPS + lc*Point <= Close[1] ))  //|| ( OrderOpenPrice()-TP*Point >= Close[1] ))
       && ( Ticket_S != 0 && Ticket_S != -1 ))
    {     
      Exit_S = OrderClose(Ticket_S,Lots,Ask,Slip,Red);
      if( Exit_S ==1 ) {Ticket_S = 0;} 
    }   

   //買いエントリー
   if(    Close[2] <= SlowHH2+margin && Close[1] > SlowHH2+margin && value_range < Range_threshold*Point && bbw1 > bbw2
       && ( Ticket_L == 0 || Ticket_L == -1 ) 
       && ( Ticket_S == 0 || Ticket_S == -1 ))
    {  
      Ticket_L = OrderSend(Symbol(),OP_BUY,Lots,Ask,Slip,0,0,Comments,MAGIC,0,Blue);
    }

   //売りエントリー
   if(    Close[2] >= SlowLL2-margin && Close[1] < SlowLL2-margin  && value_range < Range_threshold*Point && bbw1 > bbw2
       && ( Ticket_S == 0 || Ticket_S == -1 )
       && ( Ticket_L == 0 || Ticket_L == -1 ))
    {   
      Ticket_S = OrderSend(Symbol(),OP_SELL,Lots,Bid,Slip,0,0,Comments,MAGIC,0,Red);     
    } 

   return(0);
  }

###

VQ システムとフィルタ

本日、Boliinger BandWidth のプログラムを作りましたが、それをもとに BBW フィルタを作り、VQ を使った自作 EA に組み込んでみました。

このシステムにはすでに、

  1. Damiani フィルタ
  2. QQE フィルタ

を組み込んだものを作っています。

それぞれのフィルタの効果を調べてみました。

ドル円 4時間足 2014/1/1 – 2015/1/1

なし

Damiani

QQE

BBW

QQE+BBW

総損益$

22017

22141

10489

8149

3112

PF

1.87

1.88

2.15

2.26

1.87

勝率%

43.41

43.63

41.25

45.9

46.88

最大ドローダウン

39.22

14.32

45.83

16.64

26.75

最大勝ち$

4777.44 4777.44 4777.44

2727.81

1805.5

最大負け$

-906 -906

-591.79

-522.94

-519.2

勝数

89 89 33 28 15

負数

116 115 47 33 17

取引回数

205 204 80 61 32
  1. Damiani は 1回しか削減しませんでしたが、かなり大きな負けをカットしてくれたようで最大ドローダウンが激減しています。まあ、たまたまでしょうが。
  2. QQE は最大負けをカット。最大勝ちの分はカットせず。勝率やドローダウンはかえって少し悪くなったものの、PF(プロフィットファクター)は改善。回数が減るのがイタイですね。
  3. BBW はさらに回数が減ったが、勝率とPFはいい。ただ最大勝ちの分をカットしたのは残念。
  4. QQE+BBW ではその傾向がさらに顕著に。勝率 47.06%は魅力的ですがねぇ。

さらにいいフィルタを考え出すことにします。

システムによってフィルタの相性があるでしょうね。

たとえば BBW はブレイクアウトシステムにはもってこいだと思います。

関連記事

###

Bollinger BandWidth について

ボリンジャーバンド Bollinger Band という、投資家にとってはなくてはならないものがあります。

ご存じでない方、メインチャートに表示されている、平均足を上下から包むような緑のバンドがそれですよ。

これなくては投資の判断ができません (EA に任せきりの私が言っても説得力はないですが)。

Bollinger BandWidth というのはこのバンド幅のことです。

+σバンドとセンターバンドとの幅をとれば、StandardDeviation(この場合はインディケーター) と全く同じです。

*

ところが、この値は%表示ではなく、元となる値(ここでは価格)によって絶対値がそれぞれ異なってきます。

このような値は上昇や下降の判定が難しくなるので、シグナル(たいてい移動平均線)を作って、それとの大小関係をもって判断します。

そのもののカーブを時間軸方向にずらしたものもシグナル線として使えますが。

で、Bollinger BandWidth とシグナルが出るインディケーターを自作してみました。

上のチャートの黄色のVと緑のAは私があとで適当に書き加えました。

で、これがなんの役に立つのかというと、私の知る限り2つあります。

急激な上昇または下降の始まりを知る

「緑のA」をつけた部分では、Bollinger BandWidth がシグナルを上抜けていますが、これはトレンド発生(の可能性)を示します。

ブレイクアウトなどでエントリの判定基準の一つ(つまりフィルタ)に使えますね。

上昇か下降かの判定はできませんので、他の指標(VQ とか ADXDMI とかいろいろあるでしょ)で判断してください。

バンドウォークなどの利益確定に使う

「黄色のV」をつけた部分では、Bollinger BandWidth がシグナルを下抜けていますが、これはトレンド衰退の開始(の可能性)を示します。

バンドウォーク時などトレンドに乗っていると、最後の最後はだんだん ちゃぶついて来ますよね。

そのときにどこかで一度利益確定をしておこうかと思いますが、どこでやるのか非常に迷います。

そういうときの判断に役立つわけです。

シグナルを下抜けたところで早めに利益確定しておくと、すばやく頭を切り替えて次の勝負に取り掛かれますから。

プログラムソース

//+------------------------------------------------------------------+
//|                                            BBWRatio_S.mq4
//|                                                Yascii             
//|               MA_Period が 1 のときは単に曲線を1つずらします 
//+------------------------------------------------------------------+

#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1 Orange
#property indicator_color2 Aqua
#property indicator_width1 2
#property indicator_width2 1

//---- input parameters
extern int       BB_Period=20;
extern int       MA_Period=5;
extern double    Deviation=1.0;

double buf1[];
double buf2[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   IndicatorBuffers(2);
   IndicatorDigits(MarketInfo(Symbol(), MODE_DIGITS));
   SetIndexDrawBegin(0,BB_Period);
   SetIndexLabel(0,"BBandWidthRatio");
   SetIndexBuffer(0, buf1);
   SetIndexDrawBegin(1,BB_Period);
   SetIndexBuffer(1, buf2);
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----

//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {

   int i ;
   if(Bars<=BB_Period) return(0);
   int counted_bars=IndicatorCounted();
   int limit = Bars - counted_bars;
   if(counted_bars>BB_Period) i=Bars-counted_bars-1;

   i=Bars-BB_Period;

   for (i=limit - BB_Period; i>=0; i--)
   {
      buf1[i] = iBands( NULL, 0, BB_Period, Deviation, 0, PRICE_CLOSE, 1, i) -  iBands( NULL, 0, BB_Period, Deviation, 0, PRICE_CLOSE, 0, i);
    }

    if(MA_Period >1){
      for (i=limit - BB_Period; i>=0; i--)
      {
         buf2[i] = iMAOnArray(buf1,0,MA_Period,0,MODE_EMA,i);
      }
   }
   else     // MA_Period が 1 のとき
   {
      for (i=limit - BB_Period; i>=0; i--)
      {
         buf2[i] = buf1[i+1];
      }
   }
    return(0);

  }
//+------------------------------------------------------------------+

###