2016年1月20日水曜日

[MT4インジケータ]漸進計算 上位時間 平均足インジケータを改良する。

相変わらず平均足を研究しています。
[MT4インジケータ]平均足を漸進計算で上位足を表示する。チャート版

で作成したインジケータですが、上位の時間足を表示する際、過去の高値安値の影響が常に最大の影響を及ぼしてしまうことが、問題であるという風に書きました。平均足の特徴である現在価格による素早い反応という特徴が消えてしまっています。

そこで、影響を時間とともに減衰させるようにしてみました。

図 1/6公開の平均足(上)、1/20改良版平均足(下) (M15にH4ベースの漸進計算平均足を表示)



まず見た目的にとても平均足っぽくなりました(笑)
高値安値の影響が減衰していくため、反応が早くなります。漸進計算している意味が出てくるようになりました。

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

ソースコードはこちらから。変更点を赤字にしています。

//------------------------------------------------------------------
// 漸進計算 上位時間平均足
#property copyright "Copyright 2016,  Daisuke"
#property link      "http://mt4program.blogspot.jp/"
#property version   "1.10"
#property strict
#property indicator_chart_window

// 可変特殊タイムフレーム
enum ENUM_VTH_TIMEFRAMES
{
   //5分
   VTH_PERIOD_M5 = 5,
   //15分
   VTH_PERIOD_M15 = 15,
   //1時間
   VTH_PERIOD_H1 = 60,
   //2時間
   VTH_PERIOD_H2 = 120,
   //4時間
   VTH_PERIOD_H4 = 240,
   //8時間
   VTH_PERIOD_H8 = 480,
   //16時間
   VTH_PERIOD_H16 = 960,
   //32時間
   VTH_PERIOD_H32 = 1920,
   //64時間
   VTH_PERIOD_H64 = 3840,
};

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

#property indicator_label1  "HIGE OPEN"
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

#property indicator_label2  "HIGE CLOSE"
#property indicator_type2   DRAW_HISTOGRAM
#property indicator_color2  clrSkyBlue
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1

#property indicator_label3  "HEIKIN OPEN"
#property indicator_type3   DRAW_HISTOGRAM
#property indicator_color3  clrRed
#property indicator_style3  STYLE_SOLID
#property indicator_width3  3

#property indicator_label4  "HEIKIN CLOSE"
#property indicator_type4   DRAW_HISTOGRAM
#property indicator_color4  clrSkyBlue
#property indicator_style4  STYLE_SOLID
#property indicator_width4  3


input ENUM_VTH_TIMEFRAMES Target = VTH_PERIOD_H4;   // 計算平均足
input bool IsHighLowSmooth = true; // 高値安値に平滑化を入れる


// 上げひげ
double lowHighBuffer[];

// 下げひげ
double highLowBuffer[];

// 平均足オープン
double openBuffer[];

// 平均足クローズ
double closeBuffer[];

// 計算足の本数
int barCount = 0;

//------------------------------------------------------------------
//初期化
int OnInit()
{
   //インジケーターバッファを初期化する。
   SetIndexBuffer(0,lowHighBuffer);
   SetIndexBuffer(1,highLowBuffer);
   SetIndexBuffer(2,openBuffer);
   SetIndexBuffer(3,closeBuffer);
   
   barCount = Target / Period();
   
   if( barCount == 0 )
   {
      return INIT_FAILED;
   }
   
   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-- )
   {
      double areaHigh = 0;
      double areaLow = 0;

      // 平滑化を行う、離れたバーほど影響を少なくしていく。      
      if( IsHighLowSmooth )
      {
         int highest = iHighest(Symbol(), Period(), MODE_HIGH, barCount, i);
         int lowest = iLowest(Symbol(), Period(), MODE_HIGH, barCount, i);
         areaHigh = iHigh(Symbol(), Period(), highest);
         areaLow = iLow(Symbol(), Period(), lowest);
         
         areaHigh = (high[i] * ( highest - i ) + areaHigh) / ( highest - i + 1);
         areaLow = (low[i] * ( lowest - i ) + areaLow) / ( lowest - i + 1); 
      }
      else
      {
         areaHigh = iHigh(Symbol(), Period(), iHighest(Symbol(), Period(), MODE_HIGH, barCount, i));
         areaLow = iLow(Symbol(), Period(), iLowest(Symbol(), Period(), MODE_HIGH, barCount, i));
      } 

      
      // 初期値はろうそく足そのもの
      if( i >= rates_total - 1 - barCount)
      {
         openBuffer[i] = open[rates_total - 1];
         closeBuffer[i] = close[i];
         highLowBuffer[i] = areaHigh;
         lowHighBuffer[i] = areaLow;
         continue;
      }
      
      double haOpen = (openBuffer[i + barCount] + closeBuffer[i + 1])/2;
      double haClose = (open[i + barCount - 1] + areaHigh + areaLow + close[i] )/4;

      // Open/Close値を飛ばして計算している事が原因で極端な値をはさむとガタガタしてしまう。
      // 簡単な平滑化を掛けておく。
      if( barCount > 1 )
      {
          haOpen = ( openBuffer[i + 1] + haOpen * 2 ) / 3;
          haClose = ( closeBuffer[i + 1] + haClose * 2 ) / 3;
      }

      double haHigh = MathMax(areaHigh, MathMax(haOpen, haClose));
      double haLow = MathMin(areaLow, MathMin(haOpen, haClose));
      
      if(haOpen < haClose)
      {
         lowHighBuffer[i] = haLow;
         highLowBuffer[i] = haHigh;
      }
      else
      {
         lowHighBuffer[i] = haHigh;
         highLowBuffer[i] = haLow;
      }
      
      openBuffer[i] = haOpen; 
      closeBuffer[i] = haClose;
   }
   //元となる値を計算する。
   return(rates_total - 1);
}