2016年1月6日水曜日

[MT4インジケータ]平均足を漸進計算で上位足を表示する。チャート版




ここ最近、MQLの入門記事ばかりでしたので、たまにはインジケータを。

漸進マルチタイムフレーム平均のチャート表示版です。

1時間足をベースに取引すると仮定します。その際4時間足の平均足を参考にすると、高値安値の発生が時間によって影響時間が異なるという問題が発生します。

例えば、4時間足で、高値が、0時~1時の間に発生したとします。その場合、その高値はその後3時間平均足に大きく影響します。ところが、3時~4時の間に発生すると、その1時間後には次の足へ移動してしまうため、影響時間は短くなります。

このように、上位時間足を参考にした場合、ある時間でまとめられてしまうため、影響時間が大きく異なる問題が発生してしまいます。過去のデータを参考にする場合には、まとめることがノイズ成分を除去することにつながるため利点が大きいのですが、現在値として参考にしようとするとバーの形成時間によって判断が一定しないという問題が発生します。

そこで、漸進マルチタイムフレームの考え方となります。これは、計算対象の足から必ず指定時間前までの値をとることによって、高値安値発生の影響時間を一定に保つ効果があります。

問題点としては、必ず最大時間の影響を与えるため判断が遅くなるということです。
例として、1時間足に16時間足で計算した平均足を表示します。一度高値が発生すると以後16本影響を及ぼす状況がわかるかと思います。平均足のチャートとしても見た目的に微妙ですよね。

少し触った感じでは、表示時間足の2倍~4倍までの平均足計算が実用的な範囲に思われます。

(追記)
時間の経過において高値安値の影響を減衰させる改良版を作成しています。
http://mt4program.blogspot.jp/2016/01/mt4_20.html

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

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



//------------------------------------------------------------------
// 斬新更新 上位時間平均足
#property copyright "Copyright 2016,  Daisuke"
#property link      "http://mt4program.blogspot.jp/"
#property version   "1.00"
#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;   // 計算平均足

// 上げひげ
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 = iHigh(Symbol(), Period(), iHighest(Symbol(), Period(), MODE_HIGH, barCount, i));
      double 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);
}