2015年7月21日火曜日

移動平均遅延を利用する。その3 移動平均x移動平均 作ってみよう!

某長期休載中マンガ風サブタイトル。早く再開しないかなぁ??

さておき移動平均遅延を利用しよう シリーズその3です。
その1、その2はこちらから。
その1:http://mt4program.blogspot.jp/2015/10/blog-post_33.html
その2:http://mt4program.blogspot.jp/2015/10/mama_8.html

macross8.jpg

サンプルプログラムがたくさんあるページを目指していたのですが、ここ最近プログラムをアップしていないため、久し振りにプログラムです。
移動平均のクロスを参考にされている方は、ぜひ自分の指標と比べてみてください。だましの値動きに強くかつ早めにシグナルをだしていることが分かると思われます。

私は、遅延指数を取得する場合には、いつも7LWMAを使用しています。LWMAは遅延数の計算が簡単で、単純移動平均に比べて少ない遅延で済みます。(7SMAの遅延量は3、7LWMAの遅延量は2と同じ7要素を平滑化しても遅延が少なくてすみます。)4LWMAで1遅延でもよいのですが、グラフ上で見るときにはちょっと線が近すぎて見えにくいので、2遅延を使用しているという形です。
余談ですが、先行値として開発したオシレータでは、4LWMAを使用しています。遅延が1で済みます。たとえばトレンド強度オシレータのトレンド強度を4LWMAで平滑化しています。先行指数は暴れるので平滑化を行いたいところですが、あまり強くかけてしまうと先行値の意味がなくなってしまいます。そこで、最低限の1遅れで済む4LWMAを使用しています。3SMAも同じ遅延ですが、LWMAにすると4要素分を使用した平滑化が可能です。

※ただ、相関もそうですが、トレンド強度など、行ったり来たりする指標にはEMAの方が向いているような気もしています。EMAの特性として一定方向に動く際には遅延が解消されていき、方向が転換すると機敏に反応する為です。そのうちのバージョンアップで変更するかもしれません。

プログラム的な着目点は、iMAOnArrayを使用していない事です。
MQLには配列の移動平均を算出するiMAOnArrayという関数が実装されています。本来ならわざわざ自力で計算する必要性はありません。ところがiMaOnArrayの中身がどうなっているかわかりませんが、あほほど遅いです。単純移動平均ですら、毎回、全要素分、移動平均求めているのではなか?と疑うぐらい遅いです。1要素計算するのに毎回msオーダーです。自力計算と比較して100倍ぐらい遅いです。MT4で実装されている主要な移動平均は4つだけで、計算も大して難しくないため、ここは自力で計算することにしています。バグが怖いといえば怖いのですが、余りにも遅すぎるiMAOnArrayなのでした。

■お知らせ
トレンド強度-相関オシレータを少しバージョンアップしました。
相関係数にEMAをかけて平滑化を行うようにしました。EAに組み込んで検証中なのですが、平滑化なしだと少し敏感すぎるようです。

ご好評いただいております予測移動平均ボリンジャーバンドです。
ボリンジャーバンドの欠点を解決する! 高追従型ボリンジャーバンド
予測移動平均ボリンジャーバンド
予測移動平均ボリンジャーバンド | fx-on.com

トレンド強度-相関オシレータ単品と同じ値段で周期解析がついてきます。
トレンド・周期解析を組み合わせて相場を制する!
トレンド強度ー相関、周期解析オシレータセット
トレンド強度ー相関、周期解析オシレータセット | fx-on.com

またさらに、予測移動平均ボリンジャーバンドとのセット販売も開始しました。単品で購入するよりお買い得となっていますので、よろしければ、こちらもご検討ください。
価格の行き過ぎ、トレンド、周期を確認して相場を制するセット
予測移動平均ボリンジャーバンド、トレンド強度相関、周期分析セット
予測移動平均ボリンジャーバンド、トレンド強度相関、周期分析セット | fx-on.com

//------------------------------------------------------------------
// 移動平均&移動平均移動平均
#property copyright "Copyright 2015,  Daisuke"
#property link      "http://mt4program.blogspot.jp/"
#property version   "1.00"
#property strict
#property indicator_chart_window

#include 

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

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

#property indicator_label1  "MA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrYellow
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

#property indicator_label2  "MAMA"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_style2  STYLE_DOT
#property indicator_width2  1

// 入力パラメータ 移動平均期間
input int MaPeriod = 21;

//入力パラメータ 表示移動
input int   MaShift = 0;

//入力パラメータ 移動平均種別
input ENUM_MA_METHOD MaMethod = MODE_SMA;

//入力パラメータ 適用価格
input ENUM_APPLIED_PRICE MaPrice = PRICE_MEDIAN;

//入力パラメータ 移動平均移動平均種別
input int MaMaPeriod = 7;

//入力パラメータ 移動平均移動平均種別
input ENUM_MA_METHOD MaMaMethod = MODE_LWMA;

// バッファー
double ma[];
double mama[];

// 平滑化指数
double alfa;

//------------------------------------------------------------------
//初期化
int OnInit()
{
if( MaMaPeriod <= 1 || MaPeriod <= 1 ) return INIT_PARAMETERS_INCORRECT;

//インジケーターバッファを初期化する。
SetIndexBuffer(0, ma);
SetIndexBuffer(1, mama);

SetIndexDrawBegin(0, MaPeriod);
SetIndexDrawBegin(1, MaPeriod + MaMaPeriod);

string short_name = "MAMA( " + IntegerToString(MaPeriod)+ "," + IntegerToString(MaMaPeriod) +  " )";
IndicatorShortName(short_name);

alfa = 2.0 / ( MaMaPeriod + 1.0);

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-- )
{
ma[i] = iMA(NULL, PERIOD_CURRENT, MaPeriod, MaShift, MaMethod, MaPrice, i);

if( i > rates_total - MaPeriod - MaMaPeriod )
{
mama[i] = ma[i];
continue;
}

// iMaOnArrayは、ものすごく遅い。高速化のため移動平均は自力で計算する。
double sum = 0;
double count = 0 ;
switch( MaMaMethod )
{
case MODE_SMA:
// 単純移動平均
for( int j = i; j < i + MaMaPeriod; j++ )
{
sum += ma[j];
count ++ ;
}
mama[i] = (count == 0 ? 0 : sum / count);
break;
case MODE_LWMA:
// 線形加重移動平均
for( int j = i; j < i + MaMaPeriod; j++ )
{
sum += ma[j] * (MaMaPeriod - j + i);
count += (MaMaPeriod - j + i);
}
mama[i] = (count == 0 ? 0 : sum / count);
break;
case MODE_SMMA:
// スムース移動平均
mama[i] = (mama[ i + 1 ] * ( MaMaPeriod - 1 ) + ma[i]) / MaMaPeriod;
break;
case MODE_EMA:
// 指数平滑化移動平均
mama[i] = ma[i] * alfa + (1 - alfa) * mama[i + 1];
break;
}
}

return(rates_total - 1);
}