2015年12月10日木曜日

[MT4インジケータ」ATR君・・ほしい値はそこじゃない!複数バーを使ったATRを表示する。

 昨日、S/RオシレータとATRの連動をやっていて思ったのですが、確かに5分足を見て取引していますが、あくまでポジションオープンするタイミングのために使っているのであり、平均1時間ぐらいは保有するイメージです。とすると、ATRの値としてほしいのは1時間足です。

 1時間足チャートでATRを表示してその値を見ればよいのですが、取引のために、せっかく5分足を表示しているので、5分足をつかって現在位置を基準に1時間分のATRを描画することで、高速反応を目的にしたマルチバーATRを作成してみました。

■線のなめらかさ比較:マルチバーATR(上)と普通のATR(下) EUR/USD 5M

 まず、通常のATRですが、線がギザギザしていてはっきりと転換をつかめないときが多々あります。期間を長くすると、今度はなだらかになりすぎて反応が遅くなります。

 そこで、マルチバーATRでは、TEMAとEMAによる二つのラインを描画しています。
赤い線がTEMA(α=0.1)、水色の線がEMA(α=0.05)です。

 1時間で動く価格幅 予想値としてはEMA(水色)を、ダイバージェンスなどを見るときはTEMA(赤色)を使用するといったイメージで考えました。

 ATRとマルチバーATR(赤線:TEMA)を比較した場合、マルチバーは12本の値をとっているのにも関わらず、ほぼ5分足のATRと同じ反応を示している事がわかります。かつ、グラフはなめらかに描画されており判定として使用しやすいと思います。


■ダイバージェンス現象確認の容易さ比較:マルチバーATR(上)と普通のATR(下) EUR/USD 5M

 FXの教科書などでは、ATRのダイバージェンス現象を利用した天井圏や底値圏での逆張りが紹介されていますが、実際ATRを見てみるとグラフが不安定すぎて、どうとでも取れてしまうことが多々あります。

 そこで、具体的に赤枠内の値で見てみたいと思います。

 ATRでは、第1波と第2波はグラフ上に現れていますが、第3波は表れていません。

 マルチバーATRのTEMAでは、第3波が描画されています。その上、第1波~第3波にかけてきれいにダイバージェンス現象の発生が見て取れます。

 TEMAと、表示時間足より長い時間からATRを生成することで、高追従性と平滑化効果を両立した効果が表れています。このようにATRの分かりにくさを解消して、取引タイミングを計るインジケータとして作成してみました。

 ATRは、価格レンジをチャート化したもので、この値がトレンドと逆行し始めると、売り買い疲れの症状であるというのは直観的にわかりやすいと思いっています。ただ、ダイバージェンス現象って、EAで判定させようとすると、結構面倒なんです・・・・。バックテストでの検証ははっきりできていません。パッと見、普通のATR使うよりははるかによさそうと思い、公開しちゃいました。

 FX-ON様の無料配布も、近日アップデートいたしますので、コンパイルが面倒な方はしばしお待ちください。

ブログでソース公開中無料インジケータのダウンロードはこちらから
MT4開発日記で公開中の無料インジケータ
MT4開発日記で公開中の無料インジケータ | fx-on.com

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


//------------------------------------------------------------------
// 複数バーATR TEMA平滑化版
#property copyright "Copyright 2015,  Daisuke"
#property link      "http://mt4program.blogspot.jp/"
#property version   "1.00"
#property strict

#property indicator_separate_window

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

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

//TEMA ATR
#property indicator_label1  "EMA ATR"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrAqua
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//EMA ATR
#property indicator_label2  "TEMA ATR"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrIndianRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1

#property indicator_type3   DRAW_NONE
#property indicator_type4   DRAW_NONE
#property indicator_type5   DRAW_NONE

input int Period = 12;//期間

input double TemaAlfa = 0.1;//TEMA 指数係数

input double EmaAlfa = 0.05;//EMA 指数係数

// EMA ATR
double atrEma[];

// TEMA ATR
double atrTema[];

// EMA
double ema1[];

// EMA EMA
double ema2[];

// EMA EMA EMA
double ema3[];

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

   //インジケーターバッファを初期化する。
   SetIndexBuffer(0,atrEma);
   SetIndexBuffer(1,atrTema);
   SetIndexBuffer(2,ema1);
   SetIndexBuffer(3,ema2);
   SetIndexBuffer(4,ema3);
   
 string short_name = "MATR(" + IntegerToString(Period)+")";
 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[])            //スプレット
{
   // 最終計算時間
   static datetime lastCalculate = 0;
   
   //元となる値を計算する。
   for( int i = (rates_total - prev_calculated - 1); i>=0 ; i-- )
   {
      // 期間+ひとつ前の終値が必要
      if( i >= (rates_total - Period - 1) )
      {
         continue;
      }
      
      double beforeClose = close[i + Period];
      double nowHigh = high[ArrayMaximum(high, Period, i)];
      double nowLow = low[ArrayMinimum(low, Period, i)];
      double currentAtr = MathMax(MathMax( nowHigh - beforeClose, beforeClose - nowLow), nowHigh - nowLow);   

      if( i == (rates_total - Period - 2) )
      {
         ema1[i] = currentAtr;
         ema2[i] = currentAtr;
         ema3[i] = currentAtr;
         atrTema[i] = currentAtr;
         atrEma[i] = currentAtr;
      }
      else
      {
         ema1[i] = TemaAlfa * currentAtr + ( 1 - TemaAlfa ) * ema1[i + 1];
         ema2[i] = TemaAlfa * ema1[i] + ( 1 - TemaAlfa ) * ema2[i + 1];
         ema3[i] = TemaAlfa * ema2[i] + ( 1 - TemaAlfa ) * ema3[i + 1];
         atrTema[i] = ema1[i] * 3 - ema2[i] * 3 + ema3[i];
         atrEma[i] = EmaAlfa * currentAtr + ( 1 - EmaAlfa ) * atrEma[i + 1];
      }
   }

   return(rates_total - 1);
}