[MT4インジケータ]未来はわかる!そう過去ならね!前方移動平均 その1
通常の移動平均とは逆方向に移動平均をとります。
値が未確定の範囲は赤く、確定している範囲は青い線で描画するようにします。
EMAやSMMAなど、指数移動平均がベースになっている移動平均では最新の値の影響が1%を切るまでは未確定としています。
普通に描画すると、逆に移動平均の遅延分だけ未来情報がやってきます。これは、これでもありだとは思うのですが、進み分を自動的に相殺できるようにAutoShiftというパラメータをつけています。
それぞれの移動平均にて進みが0になる個所まで自動シフトする機能です。こちらも指数移動平均の場合、最新の値の影響が5割になる位置まで移動しています。
移動平均をトレンドをつかむためのテクニカル分析ツールだとすると、前方移動平均は確定した未来のトレンドを表示していることになります。つまり、インジケータに対する答え合わせの対象となるはずです。
これを使って、明日の記事では、いろいろ統計を取ってみたいと思います。
これだけだと寂しいので、あともう一点、おまけです。
図 EURUSD 1H 後方移動平均EMA(41)と、前方移動平均EMA(41)
前方移動平均においては結果論にて移動平均を描画します。後方移動平均EMAと未来から見たEMAを比較すると、デッドクロス・ゴールデンクロスがほぼ完璧に描画可能です。
これは未来情報をもとに描画しているため、過去の値位置と未来の値位置の変化をとらえることができるためです。
当然のことながら最新の位置では未来の情報はわからないため、価格が最新に近いほど信頼性に問題が出てきます。
どの程度の信頼性なのでしょうか?
まずAutoShiftを有効にしている場合、最新の値は5割の影響度になるように位置調整されています。例えば、図の前方移動平均EMA(41)は、AutoShiftがTrue時14本過去方向へのシフトを行っています。
これは図上の前方移動平均値は5割は確定している事になります。
8割の確定は32本です。14本過去シフトしているため差し引き18本です。
ということで、後方移動平均と前方移動平均のEMA(41)同士を比較した場合、18本前にクロスが発生した場合、8割の可能性でトレンド変更があったということになります。
で、なんなの?っいう話ですが、前方移動平均EMA(41)を使うと、18本前でよければ8割の確率でトレンド転換がわかります。
さらにAutoShiftによって最新値は影響度が5割の時点の値を表示しています。
ここから先は考え方なのですが、相場が完全にランダムであると仮定するなら、移動平均の相対位置にかかわらず、その先の値動きは1/2になるのであまり意味はありません。しかしトレンドが存在するとすれば・・・・なんて様々な仮定を立てて検証することができるような気がしませんか?
ブログランキングにご協力よろしくお願いします。m(._.)m
プログラムはこちらから。
//------------------------------------------------------------------
// 前方移動平均
#property copyright "Copyright 2016, Daisuke"
#property link "http://mt4program.blogspot.jp/"
#property version "1.00"
#property strict
#property indicator_chart_window
//バッファーを指定する。
#property indicator_buffers 2
//プロット数を指定する。
#property indicator_plots 2
#property indicator_label1 "MA"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrAqua
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
#property indicator_label2 "MA un fix"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrIndianRed
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
input int MaPeriod = 21; //移動平均種別
input ENUM_MA_METHOD MaMethod = MODE_SMA; //移動平均種別
input ENUM_APPLIED_PRICE MaPrice = PRICE_CLOSE;//適用価格
input int MaShift = 0; //表示シフト
input bool AutoShift = false; // 進み量が0になるように自動シフトする場合true
//バッファー
double ma[];
double maUnFix[];
// 未確定期間
int unFixPeriod = 0;
double alfa = 0.0;
//------------------------------------------------------------------
//初期化
int OnInit()
{
//インジケーターバッファを初期化する。
SetIndexBuffer(0,ma);
SetIndexBuffer(1,maUnFix);
string short_name = "BMA";
IndicatorShortName(short_name);
alfa = 0.0 ;
unFixPeriod = MaPeriod ;
if( MaMethod == MODE_SMMA )
{
//SmoothMAは 1/n EMA
alfa = 1 / (double)MaPeriod;
}
if( MaMethod == MODE_EMA )
{
alfa = 2 / (double)( MaPeriod + 1);
}
if( alfa > 0.0 )
{
unFixPeriod = MathLog(0.01) / MathLog(1 - alfa);
}
if( alfa > 1 || alfa < 0 ) return INIT_PARAMETERS_INCORRECT;
if( unFixPeriod == 0 ) return INIT_PARAMETERS_INCORRECT;
int shift = MaShift;
// 自動シフト量計算
if( AutoShift )
{
if( MaMethod == MODE_SMA )
{
shift = (MaPeriod - 1) / 2;
}
else if( MaMethod == MODE_LWMA)
{
shift = (MaPeriod - 1) / 3;
}
else if( MaMethod == MODE_EMA || MaMethod == MODE_SMMA )
{
shift = (int)((2 / alfa - 1) / 2.88);
}
}
SetIndexShift(0, shift);
SetIndexShift(1, shift);
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 = 0; i < rates_total - prev_calculated && !IsStopped(); i++ )
{
double result = 0 ;
if( MaMethod == MODE_SMA )
{
double sum = 0;
int count = 0 ;
for( int j = 0; j < MaPeriod && (i - j) >= 0; j++ )
{
int index = i - j;
sum += GetPrice(open[index], close[index], high[index], low[index], MaPrice);
count ++ ;
}
if( count > 0 )
{
result = sum / count;
}
}
else if( MaMethod == MODE_LWMA)
{
double sum = 0;
int count = 0 ;
for( int j = 0; j < MaPeriod && (i - j) >= 0; j++ )
{
int index = i - j;
int weight = MaPeriod - j;
sum += GetPrice(open[index], close[index], high[index], low[index], MaPrice) * weight;
count += weight ;
}
if( count > 0 )
{
result = sum / count;
}
}
else if( MaMethod == MODE_EMA || MaMethod == MODE_SMMA )
{
double price = GetPrice(open[i], close[i], high[i], low[i], MaPrice);
// 最新値を起点にEMAを計算する。
if( i == 0 )
{
result = price;
}
else if( i <= unFixPeriod )
{
// iがunFixPriod間は、maUnFixから値を取得する。
result = alfa * price + ( 1 - alfa ) * maUnFix[ i - 1 ];
}
else
{
result = alfa * price + ( 1 - alfa ) * ma[ i - 1 ];
}
}
if( i == unFixPeriod )
{
ma[i] = result;
maUnFix[i] = result;
}
else if( i >= unFixPeriod )
{
ma[i] = result;
maUnFix[i] = EMPTY_VALUE;
}
else
{
ma[i] = EMPTY_VALUE;
maUnFix[i] = result;
}
}
//元となる値を計算する。unFix期間は計算し続ける。
return(rates_total - unFixPeriod - 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;
}