2017年12月13日水曜日

[MT4インジケータ]ちょっと分けて考えてみよう。半分だけのボリンジャーバンド

最近LSMAを研究していて、わりかしいい感じなのですが、その中で、バンドは分けて考えたほうがいいのではないか?ということに気が付きました。
本家のLSMAの方は、二乗平均誤差をベースにあれこれしていますが、メジャーインジケータであるボリンジャーバンドも、分けて考えると違った物が見えてくるかもしれません。

ということで、早速サラッと作ってみました。標準的なボリンジャーバンドの計算方法を移動平均より上のデータと下のデータを分けて計算して描画しています。
データ量が1/2になっっている前提で、バンド幅のσ値を通常の2倍にしています。


わりあい機能するような・・・しないような??
M1とかの逆張りとかのほうがいいのかもしれません。

ソースコードはブログの最後です。

ボリンジャーバンド特有の価格が動いた時に逆方向にもバンド幅が伸びてしまう症状が無いだけでも優秀かもしれません。

せっかく上と下に分けるんだから、high/low見た方がいいかな?ということで、下はlow、上はhighと分けて計算しています。

「MT4でFXを勝ち抜く研究をするブログ」で公開している無料インジケータは、こちらの一覧から。
インジケータ一覧

Twitterもよろしくお願いします。
https://twitter.com/mt4program
Trading View プロフィール

ブログランキングにご協力よろしくお願いします。m(._.)m
にほんブログ村 為替ブログ FX テクニカルトレード派へ
にほんブログ村

お約束ですが、本ブログは、投資に対する利益を約束する物ではありません。最終的には自己責任によるご判断よろしくお願いいたします。

//------------------------------------------------------------------
// +と-側のボリンジャーバンドを別に計算してみた。
#property copyright "Copyright 2017,  Daisuke"
#property link      "http://mt4program.blogspot.jp/"
#property version   "1.00"
#property strict
#property indicator_chart_window

//バッファーを指定する。
#property indicator_buffers 5

//プロット数を指定する。
#property indicator_plots   5

#property indicator_label1  "Band1"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrAqua
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

#property indicator_label2  "Band2"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrAqua
#property indicator_style2  STYLE_DOT
#property indicator_width2  1

#property indicator_label3  "Band3"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrIndianRed
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1

#property indicator_label4  "Band4"
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrIndianRed
#property indicator_style4  STYLE_SOLID
#property indicator_width4  1

#property indicator_label5  "MA"
#property indicator_type5   DRAW_LINE
#property indicator_color5  clrYellow
#property indicator_style5  STYLE_DOT
#property indicator_width5  2

double m_buffer1[];
double m_buffer2[];
double m_buffer3[];
double m_buffer4[];
double m_buffer5[];

input int MaPeriod = 21;   // 移動平均期間
input ENUM_APPLIED_PRICE PriceMode = PRICE_TYPICAL;   // 対象価格
input double BandWidth1 = 2.0; // バンド幅1
input double BandWidth2 = 4.0; // バンド幅2

//------------------------------------------------------------------
//初期化
int OnInit()
{
   //インジケーターバッファを初期化する。
   SetIndexBuffer(0,m_buffer1);
   SetIndexBuffer(1,m_buffer2);
   SetIndexBuffer(2,m_buffer3);
   SetIndexBuffer(3,m_buffer4);
   SetIndexBuffer(4,m_buffer5);
   
   string short_name = "HBB(" + IntegerToString(MaPeriod) + ")";
   IndicatorShortName(short_name);
   
   return(INIT_SUCCEEDED);
}


//------------------------------------------------------------------
//計算イベント
int OnCalculate(const int rates_total,          //各レート要素数
                const int prev_calculated,      //計算済み要素数
                const datetime &time[],         //要素ごとの時間配列
                const double &open[],           //オープン価格配列
                const double &high[],           //高値配列
                const double &low[],            //安値配列
                const double &close[],          //クローズ価格配列
                const long &tick_volume[],      //ティック数(要素の更新回数)
                const long &volume[],           //実ボリューム(?)
                const int &spread[])            //スプレット
{
   double upDiff[];
   double downDiff[];
   ArrayResize(upDiff, MaPeriod);
   ArrayResize(downDiff, MaPeriod);
   for( int i = rates_total - prev_calculated - 1; i >= 0 && !IsStopped(); i-- )
   {
      if( i > rates_total - MaPeriod ) continue;
      
      m_buffer5[i] = iMA(NULL, PERIOD_CURRENT, MaPeriod, 0, MODE_SMA, PriceMode, i);
      
      ArrayInitialize(upDiff, 0);
      ArrayInitialize(downDiff, 0);
      for( int j = 0; j < MaPeriod; j++ )
      {
         if( high[i + j] > m_buffer5[i + j] ) upDiff[j] = high[i + j] - m_buffer5[i + j];
         if( low[i + j] < m_buffer5[i + j] ) downDiff[j] = m_buffer5[i + j] - low[i + j];
      }
      
      double upStd = StdDev(upDiff, MaPeriod, 0);
      double downStd = StdDev(downDiff, MaPeriod, 0);
      
      m_buffer1[i] = m_buffer5[i] + BandWidth1 * upStd;
      m_buffer2[i] = m_buffer5[i] + BandWidth2 * upStd;
      m_buffer3[i] = m_buffer5[i] - BandWidth1 * downStd;
      m_buffer4[i] = m_buffer5[i] - BandWidth2 * downStd;
   }

   ArrayFree(upDiff);
   ArrayFree(downDiff);

   return rates_total - 1;
}

//------------------------------------------------------------------
//標準偏差を求める。
// return 標準偏差
double StdDev(
   const double &values[],      //元となる配列
   int count,                   //計算対象数
   int shift                    //シフト
)
{
   if( (count + shift) > ArraySize(values) ) return 0;

   double avg = 0 ;
   double mu = 0 ;
   for( int i = shift; i < shift + count; i++ )
   {
      avg += values[i];
   }
   avg = avg / count;

   for( int i = shift; i < shift + count; i++ )
   {
      mu += MathPow(values[i] - avg, 2);
   }

   // 標本標準偏差
   return MathSqrt(mu / (count - 1));
}