2016年8月8日月曜日

[MT4インジケータ]上位時間足を表示するカラフルなボリンジャーバンドの最新足に対する制御を変更する。

[MT4インジケータ&プログラミング]上位時間足を表示するカラフルなボリンジャーバンド

で作成した、マルチタイムフレーム機能付き、色が変わるボリンジャーバンドですが、マルチタイムで表示した際、過去の足に対して、現在形成中の足の値が表示されるのはよくないなということで、確定足だけ表示するようにしていました。

例えば、15分足で、1時間足のボリンジャーバンドを表示した際、
15分足 9:00足に1時間足の9:00の値をそのまま出してしまうと、9:15以降、確定しているはずの9:00の足の値は、まだ確定していない1時間足のボリンジャーバンドを確定値として表示してしまいます。

作った当初は、これはよくないなーと思い、確定した1時間足の8:00の値を表示していました。

コメントでご指摘いただいて、改めて思うと、表示シフトで、使用者が選べた方が良い気がします。

ということで、修正版です。
マルチタイムの際は、未確定となっている足すべての値を変更しに行きます。
(15分足9:00~9:45までの足は、9時台は常に更新される形です。)

■カラフルBBと、通常のBB(赤線) 旧バージョン



■カラフルBBと、通常のBB(赤線) 新バージョン


表示シフトのパラメータがありますので、従来通り確定足を表示することも可能です。

FX-ONからのダウンロードはこちらから。ソースコードは記事の最後に記載しています。
カラフルで、上位時間足のボリンジャーバンドが表示できます。
拡散収束と移動平均上昇下降で色が変わるアラート付きボリンジャーバンド
拡散収束と移動平均上昇下降で色が変わるアラート付きボリンジャーバンド | fx-on.com

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

Twitterもよろしくお願いします。
https://twitter.com/mt4program

ブログランキングにご協力よろしくお願いします。m(._.)m
にほんブログ村 為替ブログ MetaTraderへ
にほんブログ村

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

ソースコードはこちらから

//------------------------------------------------------------------
// 色が変わるボリンジャーバンド 上位時間足版 アラート機能付き
#property copyright "Copyright 2015,  Daisuke"
#property link      "http://mt4program.blogspot.jp/"
#property version   "2.00"
#property strict
#property indicator_chart_window

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

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

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

#property indicator_label2  "HIGH1UP"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrDodgerBlue
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1

#property indicator_label3  "HIGH2UP"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrDodgerBlue
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1

#property indicator_label4  "LOW1UP"
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrDodgerBlue
#property indicator_style4  STYLE_SOLID
#property indicator_width4  1

#property indicator_label5  "LOW2UP"
#property indicator_type5   DRAW_LINE
#property indicator_color5  clrDodgerBlue
#property indicator_style5  STYLE_SOLID
#property indicator_width5  1

#property indicator_label6  "CenterDown"
#property indicator_type6   DRAW_LINE
#property indicator_color6  clrIndianRed
#property indicator_style6  STYLE_SOLID
#property indicator_width6  1

#property indicator_label7  "HIGH1DOWN"
#property indicator_type7   DRAW_LINE
#property indicator_color7  clrWheat
#property indicator_style7  STYLE_SOLID
#property indicator_width7  1

#property indicator_label8  "HIGH2DOWN"
#property indicator_type8   DRAW_LINE
#property indicator_color8  clrWheat
#property indicator_style8  STYLE_SOLID
#property indicator_width8  1

#property indicator_label9  "LOW1DOWN"
#property indicator_type9   DRAW_LINE
#property indicator_color9  clrWheat
#property indicator_style9  STYLE_SOLID
#property indicator_width9  1

#property indicator_label10  "LOW2DOWN"
#property indicator_type10   DRAW_LINE
#property indicator_color10  clrWheat
#property indicator_style10  STYLE_SOLID
#property indicator_width10  1

input ENUM_TIMEFRAMES TargetPeriod = PERIOD_CURRENT;// 対象タイムフレーム
input int MaPeriod = 21;//移動平均期間
input int   MaShift = 0;//表示移動
input ENUM_MA_METHOD MaMethod = MODE_EMA;//移動平均種別
input ENUM_APPLIED_PRICE MaPrice = PRICE_MEDIAN;//適用価格
input int StdPeriod = 21;//標準偏差期間
input ENUM_MA_METHOD StdMethod = MODE_SMA;//標準偏差算出方法
input double Sigma1 = 1;//σ1
input double Sigma2 = 2;//σ2
input bool IsAlertSound = true;//条件に一致した場合、サウンドを鳴らす。
input string SoundFileName = "alert.wav";//再生サウンド名
input bool IsAlertMail = true;//条件に一致した場合、メールを送信する。
input double AlertSigma = 1;//終値が次シグマを超えた場合アラートを鳴らす

double centerUp[];
double high1Up[];
double high2Up[];
double low1Up[];
double low2Up[];

double centerDown[];
double high1Down[];
double high2Down[];
double low1Down[];
double low2Down[];

//------------------------------------------------------------------
//初期化
int OnInit()
{
   //インジケーターバッファを初期化する。
   SetIndexBuffer(0,centerUp);
   SetIndexBuffer(1,high1Up);
   SetIndexBuffer(2,high2Up);
   SetIndexBuffer(3,low1Up);
   SetIndexBuffer(4,low2Up);
   SetIndexBuffer(5,centerDown);
   SetIndexBuffer(6,high1Down);
   SetIndexBuffer(7,high2Down);
   SetIndexBuffer(8,low1Down);
   SetIndexBuffer(9,low2Down);
   SetIndexDrawBegin(0, MaPeriod);
   SetIndexDrawBegin(1, MaPeriod);
   SetIndexDrawBegin(2, MaPeriod);
   SetIndexDrawBegin(3, MaPeriod);
   SetIndexDrawBegin(4, MaPeriod);
   SetIndexDrawBegin(5, MaPeriod);
   SetIndexDrawBegin(6, MaPeriod);
   SetIndexDrawBegin(7, MaPeriod);
   SetIndexDrawBegin(8, MaPeriod);
   SetIndexDrawBegin(9, MaPeriod);
   
   string short_name = "ClBB(" + 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[])            //スプレット
{
   int targetPeriod = TargetPeriod;
   if( targetPeriod == PERIOD_CURRENT) targetPeriod = Period();
   if( Period() > targetPeriod ) return rates_total ;

   for( int i = (rates_total - prev_calculated - 1); i >= 0 && !IsStopped(); i-- )
   {
      if( i >= rates_total - 2 ) continue;
   
      int shift1 = iBarShift(NULL, targetPeriod, time[i], false);
      if( iBars(NULL, targetPeriod) <= shift1 + 1) continue;
      
      double ma1 = iMA(NULL, targetPeriod, MaPeriod, MaShift, MaMethod, MaPrice, shift1);
      double ma2 = iMA(NULL, targetPeriod, MaPeriod, MaShift, MaMethod, MaPrice, shift1 + 1);
      double std1 = iStdDev(NULL, targetPeriod, StdPeriod, MaShift, StdMethod, MaPrice, shift1);
      double std2 = iStdDev(NULL, targetPeriod, StdPeriod, MaShift, StdMethod, MaPrice, shift1 + 1);
      
      int j = 0;
      for( j = i; j < rates_total && iBarShift(NULL, targetPeriod, time[j]) == shift1; j++)
      {
         //いったんEMPTY_VALUでクリア
         centerDown[j] = EMPTY_VALUE;
         centerUp[j] = EMPTY_VALUE;
         high1Down[j] = EMPTY_VALUE;
         high2Down[j] = EMPTY_VALUE;
         low1Down[j] = EMPTY_VALUE;
         low2Down[j] = EMPTY_VALUE;
         high1Up[j] = EMPTY_VALUE;
         high2Up[j] = EMPTY_VALUE;
         low1Up[j] = EMPTY_VALUE;
         low2Up[j] = EMPTY_VALUE;
      
         // 移動平均の方向によって値を設定するバッファーを変更する。
         if( ma1 < ma2 )
         {
            centerDown[j] = ma1;
         }
         else
         {
            centerUp[j] = ma1;
         }

         // 標準偏差の大きさによって値を入れるバッファを切り替える。
         if( std1 < std2 )
         {
            high1Down[j] = ma1 + std1 * Sigma1;
            high2Down[j] = ma1 + std1 * Sigma2;
            
            low1Down[j] = ma1 - std1 * Sigma1;
            low2Down[j] = ma1 - std1 * Sigma2;
         }
         else
         {
            high1Up[j] = ma1 + std1 * Sigma1;
            high2Up[j] = ma1 + std1 * Sigma2;
            
            low1Up[j] = ma1 - std1 * Sigma1;
            low2Up[j] = ma1 - std1 * Sigma2;
         }
      }
      if( j < rates_total )
      {
         //虫食い穴埋め
         if( centerDown[j] == EMPTY_VALUE && centerDown[j - 1] != EMPTY_VALUE )
         {
            centerDown[j] = centerUp[j];
         }
         if( centerUp[j] == EMPTY_VALUE && centerUp[j - 1] != EMPTY_VALUE )
         {
            centerUp[j] = centerDown[j];
         }
          //虫食い穴埋め
         if( high1Down[j] == EMPTY_VALUE && high1Down[j - 1] != EMPTY_VALUE )
         {
            high1Down[j] = high1Up[j];
            high2Down[j] = high2Up[j];
            low1Down[j] = low1Up[j];
            low2Down[j] = low2Up[j];
         }
         if( high1Up[j] == EMPTY_VALUE && high1Up[j - 1] != EMPTY_VALUE )
         {
            high1Up[j] = high1Down[j];
            high2Up[j] = high2Down[j];
            low1Up[j] = low1Down[j];
            low2Up[j] = low2Down[j];
         }
      }
      // 最終アラート発生時刻
      static datetime lastAlertTime = 0;
      // 前回がアラートシグマ未満で、今回がアラートシグマ以上なら音をならしてメールを送信する。
      // 過去データの計算でアラートが発生するのを防止するため、iが1の時のみ。
      if( i == 1 && (IsAlertMail || IsAlertSound ) && lastAlertTime != time[i] )
      {
         double alertStd1 = std1 * AlertSigma;
         double alertStd2 = std2 * AlertSigma;
         
         if( (close[i + 1] < (ma2 + alertStd2) && close[i] >= (ma1 + alertStd1))
         || (close[i + 1] > (ma2 - alertStd2) && close[i] <= (ma1 - alertStd1)))
         {
            if( IsAlertSound )
            {
               PlaySound(SoundFileName);
            }
            
            if( IsAlertMail )
            {
               //タイトル
               string subject = StringFormat("ColorfulMTBB アラート %s[%d] %s", Symbol(), Period(), TimeToStr(time[i]) );
               
               //本文
               string message = "ColorfulMTBBの設定によりアラートメールを送信しました。\r\n";
               StringAdd(message, StringFormat("MA:%f\r\n", ma1));
               StringAdd(message, StringFormat("LowerStd:%f\r\n", ma1 - alertStd1));
               StringAdd(message, StringFormat("UpperStd:%f\r\n", ma1 + alertStd1));
               StringAdd(message, StringFormat("Close:%f\r\n", close[i]));
               SendMail(subject, message);
            }
            lastAlertTime = time[i];
         }
      }
      
   }
   return(rates_total - 1);
}