まぁMT4標準関数のiMAOnArrayがアホほど遅いというのもありますが・・。
単純移動平均は N期間のデータの合計をNで割った値です。
単純に実装するとループでN個分合計を求めて、最後にNで割ると行ったコードです。
double total = 0.0;
for( int j = i + 1; j < i + Period1 + 1; j++)
{
total += close[j];
}
sma1[i + 1] = total / Period1;
こんな感じですね。
ところが、すでに前のバーの値を計算済みの場合、こんなループは不要です。
移動平均の算出計算式を書き出すとこんな感じです。
sma[i] = (value[i] + value[i + 1] ..... + value[i + N - 1]) / N
これを分解すると次の形です。
sma[i] = value[i]/ N + value[i + 1]/ N ..... + value[i + N - 1]/ N
次のsma[i + 1]の値は、このようになります。
sma[i + 1] = value[i + 1]/ N + value[i + 2]/ N .....+ value[i + N - 1]/ N + value[i + N]/ N
さて、sma[i]とsma[i+1]の差分は次の通りです。
sma[i] - sma[i + 1] = value[ i ]/N - value[i + N]/N
両辺にsma[i + 1]を足せば、次の式となります。
sma[i] = sma[i + 1] + value[ i ]/N - value[i + N]/N
つまり、sma[i] は sma[i + 1]の値がわかっていれば、足し算と引き算と割り算で求めることが可能です。
で、終値の単純移動平均を出すプログラムはこんな感じなります。
ふと、どの記事か忘れましたが、移動平均ってループしなくても求められるんだ〜という返事を見た覚えがあったため、案外知られてないのかな?と思い記事にしてみました。
ふと、どの記事か忘れましたが、移動平均ってループしなくても求められるんだ〜という返事を見た覚えがあったため、案外知られてないのかな?と思い記事にしてみました。
//------------------------------------------------------------------
// 単純移動平均
#property copyright "Copyright 2017, Daisuke"
#property link "http://mt4program.blogspot.jp/"
#property version "1.00"
#property strict
#property indicator_chart_window
//バッファーを指定する。
#property indicator_buffers 1
//プロット数を指定する。
#property indicator_plots 1
#property indicator_label1 "SMA"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrAqua
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
input int Period1 = 21; // SMA1期間
double sma1[];
//------------------------------------------------------------------
//初期化
int OnInit()
{
//インジケーターバッファを初期化する。
int count = 0 ;
SetIndexBuffer(count++, sma1);
string short_name = "SMA";
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-- )
{
//計算する長さを算出
if( i > rates_total - Period1 - 1)
{
continue;
}
if( MathIsValidNumber(sma1[i + 1]) )
{
//最初の一つ目はふつうにループして計算する。
double total = 0.0;
for( int j = i + 1; j < i + Period1 + 1; j++)
{
total += close[j];
}
sma1[i + 1] = total / Period1;
}
else
{
sma1[i] = sma1[i + 1] - close[i + Period1] / Period1 + close[i] / Period1;
}
}
return(rates_total - 1);
}
「MT4でFXを勝ち抜く研究をするブログ」で公開している無料インジケータは、こちらの一覧から。インジケータ一覧
Twitterもよろしくお願いします。
https://twitter.com/mt4program
Trading View プロフィール
ブログランキングにご協力よろしくお願いします。m(._.)m
にほんブログ村 |
お約束ですが、本ブログは、投資に対する利益を約束する物ではありません。最終的には自己責任によるご判断よろしくお願いいたします。