世界中の人たちがなめらかにかつ追従よいMAを考えているわけですが、その中でも1990年代に開発されたTEMAは有名です。
・移動平均遅延を利用するシリーズ
http://mt4program.blogspot.jp/2015/10/blog-post_71.html
で書いたように、移動平均に移動平均を重ねることで遅延分を利用することを書きましたが、TEMAは遅延分を逆に足しこむことで、遅延をなく追従することを目指したEMAです。考え方としてはZEMAに似ています。あちらがモメンタムとして単純な価格の差分から求めているのに対して、TEMAはEMAとEMAEMAの差分を使用しています。
EMAEMAのEMAをとると、EMAEMAに含まれる遅延分も含めて遅延します。それをキャンセルするためにEMAとEMAEMAの差分の3倍を予測値として加えているという形です。
TEMAは、これにより平滑化効果と高追従性の両立を図っています。
さて、TEMAは有名ですので、MT4のインジケータにもたくさんあるかと思います。じゃぁあえてなんで?というと・・昨日の記事からの流れで・・・・。
FX-ONブログランキングにご協力よろしくお願いいたします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 4
//プロット数を指定する。
#property indicator_plots 1
#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
//入力パラメータ 指数係数
extern double Alfa = 0.1;
//入力パラメータ 適用価格
extern ENUM_APPLIED_PRICE MaPrice = PRICE_CLOSE;
// TEMA
double tema[];
// EMA
double ema1[];
// EMA EMA
double ema2[];
// EMA EMA EMA
double ema3[];
//------------------------------------------------------------------
//初期化
int OnInit()
{
//インジケーターバッファを初期化する。
SetIndexBuffer(0,tema);
SetIndexBuffer(1,ema1);
SetIndexBuffer(2,ema2);
SetIndexBuffer(3,ema3);
if( Alfa <= 0 || Alfa >= 1 ) return INIT_PARAMETERS_INCORRECT;
string short_name = "TEMA(" + 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-- )
{
double price = GetPrice(open[i], close[i], high[i], low[i], MaPrice);
if( i == (rates_total - 1) )
{
ema1[i] = price;
ema2[i] = price;
ema3[i] = price;
tema[i] = price;
continue;
}
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];
}
//元となる値を計算する。
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;
}