2015年10月15日木曜日

[MT4インジケータ&プログラム]TEMAに標準偏差バンドをつけてみた。

■TEMA 偏差バンド


TEMAに偏差バンドをつけてみました。
デフォルトの設定では、TEMAを1本シフトして表示し、シフトしたTEMAに対してばらつきのバンドを表示しています。
偏差は、TEMAが中心値であると定義して計算しました。

ポジションをとるときに、高値安値つかみをなるべく阻止したいなぁと思い作ってみましたが、まだ何も検証していません。高追従のTEMAを中心値と定義して偏差を求め、2σ越えは異常値であるとして、ポジションをとらないという判断につかえないかな?と考えています。

TEMA平均足でポジションをとる際に、単純判断だと突っ込み売りとかしちゃうんですよねーー^^;; それの防止用にと。

TEMA平均足のご購入はこちらから。

平均足のOPEN値にTEMAを適用したカスタム平均足
TEMA平均足



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

今回のプログラムはこちらです。



//------------------------------------------------------------------
// TEMA 標準偏差バンド
#property copyright "Copyright 2015,  Daisuke"
#property link      "http://mt4program.blogspot.jp/"
#property version   "1.00"
#property strict
#property indicator_chart_window

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

#property indicator_label1  "TEMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrIndianRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

#property indicator_label2  "EMA"
#property indicator_type2   DRAW_NONE
#property indicator_color2  clrNONE

#property indicator_label3  "EMAEMA"
#property indicator_type3   DRAW_NONE
#property indicator_color3  clrNONE

#property indicator_label4  "EMAEMAEMA"
#property indicator_type4   DRAW_NONE
#property indicator_color4  clrNONE

#property indicator_label5  "HIGH1UP"
#property indicator_type5   DRAW_LINE
#property indicator_color5  clrSlateBlue
#property indicator_style5  STYLE_SOLID
#property indicator_width5  1

#property indicator_label6  "HIGH2UP"
#property indicator_type6   DRAW_LINE
#property indicator_color6  clrSlateBlue
#property indicator_style6  STYLE_SOLID
#property indicator_width6  1

#property indicator_label7  "LOW1UP"
#property indicator_type7   DRAW_LINE
#property indicator_color7  clrSlateBlue
#property indicator_style7  STYLE_SOLID
#property indicator_width7  1

#property indicator_label8  "LOW2UP"
#property indicator_type8   DRAW_LINE
#property indicator_color8  clrSlateBlue
#property indicator_style8  STYLE_SOLID
#property indicator_width8  1

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

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

#property indicator_label11  "LOW1DOWN"
#property indicator_type11   DRAW_LINE
#property indicator_color11  clrWheat
#property indicator_style11  STYLE_SOLID
#property indicator_width11  1

#property indicator_label12  "LOW2DOWN"
#property indicator_type12   DRAW_LINE
#property indicator_color12  clrWheat
#property indicator_style12  STYLE_SOLID
#property indicator_width12  1

//入力パラメータ 表示シフト
extern int Shift = 1;

//入力パラメータ 指数係数
extern double Alfa = 0.1;

//入力パラメータ 適用価格
extern ENUM_APPLIED_PRICE MaPrice = PRICE_CLOSE;

//入力パラメータ 標準偏差期間
extern int StdPeriod = 13;

//入力パラメータ σ1
extern double Sigma1 = 1;

//入力パラメータ σ2
extern double Sigma2 = 2;

// TEMA
double tema[];

// EMA
double ema1[];

// EMA EMA
double ema2[];

// EMA EMA EMA
double ema3[];

// 拡散時バンド
double high1Up[];
double high2Up[];
double low1Up[];
double low2Up[];

// 収束時バンド
double high1Down[];
double high2Down[];
double low1Down[];
double low2Down[];

//------------------------------------------------------------------
//初期化
int OnInit()
{
   if( Alfa <= 0 || Alfa >= 1 ) return INIT_PARAMETERS_INCORRECT;

   //インジケーターバッファを初期化する。
   SetIndexBuffer(0,tema);
   SetIndexBuffer(1,ema1);
   SetIndexBuffer(2,ema2);
   SetIndexBuffer(3,ema3);
   SetIndexBuffer(4,high1Up);
   SetIndexBuffer(5,high2Up);
   SetIndexBuffer(6,low1Up);
   SetIndexBuffer(7,low2Up);
   SetIndexBuffer(8,high1Down);
   SetIndexBuffer(9,high2Down);
   SetIndexBuffer(10,low1Down);
   SetIndexBuffer(11,low2Down);
   SetIndexDrawBegin(0, StdPeriod);
   SetIndexDrawBegin(1, StdPeriod);
   SetIndexDrawBegin(2, StdPeriod);
   SetIndexDrawBegin(3, StdPeriod);
   SetIndexDrawBegin(4, StdPeriod);
   SetIndexDrawBegin(5, StdPeriod);
   SetIndexDrawBegin(6, StdPeriod);
   SetIndexDrawBegin(7, StdPeriod);
   SetIndexDrawBegin(8, StdPeriod);
   SetIndexDrawBegin(9, StdPeriod);
   SetIndexDrawBegin(10, StdPeriod);
   SetIndexDrawBegin(11, StdPeriod);
 
   string short_name = "TEMA BB(" + DoubleToStr(Alfa) + ")";
   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[])            //スプレット
{
   for( int i = (rates_total - prev_calculated - 1); i >= 0 && !IsStopped(); i-- )
   {
      if( i >= (rates_total - 1 - Shift) )
      {
         double price = GetPrice(open[i], close[i], high[i], low[i], MaPrice);
         ema1[i] = price;
         ema2[i] = price;
         ema3[i] = price;
         tema[i] = price;
         continue;
      }

      double price = GetPrice(open[i + Shift], close[i + Shift], high[i + Shift], low[i + Shift], MaPrice);
      ema1[i] = Alfa * price + ( 1 - Alfa ) * ema1[i + 1];
      ema2[i] = Alfa * ema1[i] + ( 1 - Alfa ) * ema2[i + 1];
      ema3[i] = Alfa * ema2[i] + ( 1 - Alfa ) * ema3[i + 1];
      tema[i] = ema1[i] * 3 - ema2[i] * 3 + ema3[i];
   
      if( i >= (rates_total - 1 - StdPeriod - Shift) ) continue;
   
      // 標準偏差では、平均値からばらつきを求めるが、ここでは、TEAMが中心値であると定義して、
      // TEMAからのばらつきから偏差を求める。
      double mu = 0 ;
      for( int j = 0; j < StdPeriod; j++ )
      {
         // 偏差を計算するときはShift値は考慮しない。
         // ShiftされたTEMAに対して実際のClose値がどの程度ばらついたかをバンドとして表示する。
         mu += MathPow(close[i + j/* + Shift*/] - tema[i + j], 2);
      }

      // 標本標準偏差
      double std1 = MathSqrt(mu / (StdPeriod - 1));
      double std2 = 0;
   
      if( high1Down[i + 1] > 20000000 )
      {
         std2 = high1Up[i + 1] - tema[i + 1];
      }
      else
      {
         std2 = high1Down[i + 1] - tema[i + 1];
      }

      // 標準偏差の大きさによって値を入れるバッファを切り替える。
      if( std1 < std2 )
      {
         high1Down[i] = tema[i] + std1 * Sigma1;
         high2Down[i] = tema[i] + std1 * Sigma2;
       
         low1Down[i] = tema[i] - std1 * Sigma1;
         low2Down[i] = tema[i] - std1 * Sigma2;
       
         high1Down[i + 1] = tema[i + 1] + std2 * Sigma1;
         high2Down[i + 1] = tema[i + 1] + std2 * Sigma2;
       
         low1Down[i + 1] = tema[i + 1] - std2 * Sigma1;
         low2Down[i + 1] = tema[i + 1] - std2 * Sigma2;
      }
      else
      {
         high1Up[i] = tema[i] + std1 * Sigma1;
         high2Up[i] = tema[i] + std1 * Sigma2;
       
         low1Up[i] = tema[i] - std1 * Sigma1;
         low2Up[i] = tema[i] - std1 * Sigma2;
       
         high1Up[i + 1] = tema[i + 1] + std2 * Sigma1;
         high2Up[i + 1] = tema[i + 1] + std2 * Sigma2;
       
         low1Up[i + 1] = tema[i + 1] - std2 * Sigma1;
         low2Up[i + 1] = tema[i + 1] - std2 * Sigma2;
      }
   
   }
   //元となる値を計算する。
   return(rates_total - 1);
}


//------------------------------------------------------------------
// 価格を計算する。
// return 対象価格
double GetPrice(
   double open,   // オープン値
   double close,  // クローズ値
   double high,   // 高値
   double low,    // 安値
   ENUM_APPLIED_PRICE maPrice    //取得価格
   )
{
   double price = 0;

   switch( maPrice )
   {
      case PRICE_CLOSE:
         price = close;
         break;
      case PRICE_OPEN:
         price = open;
         break;
      case PRICE_HIGH:
         price = high;
         break;
      case PRICE_LOW:
         price = low;
         break;
      case PRICE_MEDIAN:
         price = (high + low) / 2;
         break;
      case PRICE_TYPICAL:
         price = (high + low + close) / 3;
         break;
      case PRICE_WEIGHTED:
         price = (high + low + close + close) / 4;
         break;
   }
   return price;
}