インジケータ2

カスタムインジケータ 6


  今回はプログラムのコードのみです。
説明は次回に予定しています。
MT4をもっている方はコンパイルし、チャートで試して見てください。

//+------------------------------------------+
#property copyright "Copyright 2015, T.S."
#property link "http://"
#property version "1.00"
#property strict

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Silver
input int mPeriod=200;

double mBuffer[];

void OnInit(void)
{

IndicatorBuffers(1);
IndicatorDigits(Digits);
//--- drawing style

SetIndexBuffer(0,mBuffer);

SetIndexStyle(0,DRAW_LINE,STYLE_SOLID);

int draw_begin=mPeriod-1;
SetIndexDrawBegin(0,draw_begin);

}

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[])
{
if(rates_total
ArraySetAsSeries(mBuffer,false);
ArraySetAsSeries(close,false);
---------------------------------
if(prev_calculated==0)
ArrayInitialize(mBuffer,0);

int i,limit;

if(prev_calculated==0)
{
limit=mPeriod;

double firstValue=0;
for(i=0; i firstValue+=close[i];
firstValue/=mPeriod;
mBuffer[limit-1]=firstValue;
}
else
limit=prev_calculated-1;
//(a)
if(prev_calculated>=1 && prev_calculated<=mPeriod-1)
Print("Next (prev_caluculated of 0) is to be found ");

//--- main loop
for(i=limit; i mBuffer[i]=mBuffer[i-1]+(close[i]-close[i-mPeriod])/mPeriod;

//---
return(rates_total);
}



カスタムインジケータ 7


アルゴリズムの説明

 以前説明したように配列バッファーのバインドは次の関数で行います。
SetIndexBuffer(0,mBuffer);
これで配列バッファmBufferは時系列配列バッファになり、
インデックス0番にバインドされています。

SetIndexDrawBegin(0,draw_begin);
この関数ではインデックス0番のバッファに開始位置をセットします。
バッファの要素は0番から始まりますので、mPeriodから1を引くことで、
バッファの0、1、...、mPeriod-1、の要素数はmPeriod個となり、
描こうとする移動平均線の期間と同じになります。

draw_beginの定義は
int draw_begin=mPeriod-1;
ですが、
ここでmPeriodは移動平均線の期間。
mPeriod=1は平均値では必要ありませんので計算しません。
2であればバーが2本の平均値、
3であればバーが3本の平均値
...
nであればバーがn本の平均値を計算することになります。

int draw_begin=mPeriod-1;
の計算で、
SetIndexDrawBegin()関数にdraw_beginの値を渡します

配列バッファmBufferは、
SetIndexBuffer()により時系列配列になっており、
このままではこれ以上計算は出来ないので、
配列バッファに戻すため、
int OnCalculate()の中で修正されます。

int OnCalculate()の計算ではまず最初に
if(rates_totalを行います。
ここでの計算は
計算可能なバーの数rates_totalが
mPeriod-1未満では移動平均線の期間に足りませんのでカット、
mPeriodが2未満では移動平均値の計算が出来ませんのでこれもカットします。

(分り易い例として
if( X || Y )の式を考えると、
||は、XあるいはYがtrueならばreturn(0);を実行することになります。
コンデション条件が満足するまで計算が開始されません。)
この後、
ArraySetAsSeries(mBuffer,false);
ArraySetAsSeries(close,false);
の計算が行われます。
この関数でmBufferとcloseは配列バッファに修正されます。
こうすることで、配列番号の0番側に、
チャートバーの古い方をセットすることが出来るようになるわけです。

次は
1)prev_calculatedが0のときですが、
まず、
if(prev_calculated==0)
ArrayInitialize(mBuffer,0);
の計算で
mBufferは0に初期化されます。
その後さらに、

imit=mPeriod;
for(i=0; i firstValue+=close[i];
firstValue/=mPeriod;
mBuffer[limit-1]=firstValue;
の計算では、
SetIndexDrawBegin(0,draw_begin);により、
mBufferの開始位置はmPeriod-1から始まることになります。
この後、
firstValue/=mPeriod;
mBuffer[limit-1]=firstValue;

mBuff[]のmPeriod-1要素の平均値を計算します。
そして、
else
limit=prev_calculated-1;
の計算ですが、
すでに
mBuff[0]からmBuff[mPeriod-1]要素まで、
mPeriod個が入力されたことになり、
prev_calculatedは、
0の後、SetIndexDrawBeginの設定により、
mPeriod+1から始まることになります。

次の
//(a)
if(prev_calculated>=1 && prev_calculated<=mPeriod-1)
Print("Next (”To be found ");
はテストするためのものです。
prev_calculatedが1以上でかつmPeriod-1以下のときは、
エキスパートタブに
To be found
が表示されません。


2)、次のfor(i=limit; i
else limit=prev_calculated-1;の計算により、

i=limitは
limit=prev_calculated-1=(mPeriod+1)-1=mPeriod
から始まります。

mBuffer[i]=mBuffer[i-1]+(close[i]-close[i-mPeriod])/mPeriod;

limit=mPeriodでは
mBuffer[mPeriod]=mBuffer[mPeriod-1]+(close[mPeriod]-close[mPeriod-mPeriod])/mPeriod
となります。
この式の右辺は
(close[0]+close[1]+...+closer[mPeriod-1])/mPeriod+(close[mPeriod]-close[0])/mPeriod
なので、
(close[1]+close[2]+...+closer[mPeriod])/mPeriod
となります。

limit=mPeriod+1は同様なので省略します。

limit=mPeriod+nでは
mBuffer[mPeriod+n]=mBuffer[mPeriod+n-1]+(close[mPeriod+n]-close[mPeriod+n-mPeriod])/mPeriod
ですが、
この式の右辺は、
(close[mPeriod+n-1-(mPeriod-1)]+close[mPeriod+n-1-(mPeriod-2)]+...
+close[Period+n-1])/mPeriod+(close[mPeriod+n]-close[n])/mPeriod
なので、
(close[n]+close[n+1]+...+closer[mPeriod+n])/mPeriod
と同じになります。

最終的にprev_calculatedの値は
rates_totalと同じ値になります。
なので、
limit=prev_calculated-1;の計算により、
for(i=limit; i各テックごとに計算されることになります。



カスタムインジケータ 8

iCustom

 今回からiCustomを使ったインジケータです。
メタエデイターのindicatorsフォルダ内にある
インジケータを使って作ることになります。
10月18日付の「さかたつとむMLメール(NO.102)」、
カスタムインデイケータ 3で紹介したコードを
少し修正したtest25.mql4使用します。
すでにコンパイル済みのファイルtest25.mql4を
iCustomで使うことになります。

作り方はカスタムインデイケータ 3のときと同じですが、
先に修正したtest25.mql4のコードを紹介します。
//+------------------------------------
//------------------------------------+
//| test25.mq4 |
//| Copyright 2015, T.S. |
//| http:// |
//------------------------------------+
#property copyright "Copyright 2015, T.S."
#property link "http://"
#property version "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Silver

input int mPeriod=200;

double mBuffer[];


void OnInit(void)
{
IndicatorBuffers(1);
IndicatorDigits(Digits);
SetIndexStyle(0,DRAW_LINE,STYLE_SOLID);

SetIndexBuffer(0,mBuffer);//,INDICATOR_CALCULATIONS

}

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[])
{
int limit=rates_total-prev_calculated;
//---
if(rates_total<=mPeriod)return(0);
//---
if(prev_calculated>0)
limit++;

for(int i=0; i{

mBuffer[i]=iMA(NULL,0,mPeriod,0,MODE_SMA,PRICE_CLOSE,i);

}
//---
return(rates_total);
}
//+------------------------------------

 次は新しいインジケータで使用するアイテムですが、
始にプロパティからにします。

#property indicator_chart_window
の代わりに
#property indicator_separate_window
を使いますが、これは変更しなくても問題なく動作します。


そして、
#property indicator_color1 Silver
の代わりに
#property indicator_color1 Red
を使います。

さらに、
SetIndexStyle(0,DRAW_LINE,STYLE_SOLID);
の代わりに
SetIndexStyle(0,DRAW_LINE,STYLE_DOT);
を使います。
変更しない場合はtest25.mq4 のプロパティでそれぞれ動作します。

 今回、セットアイテム、インテグレーションアイテムはtest25.mq4 と同じです。
変更するアイテムはソリューションアイテムのみになります。

iCustom()が増え、代わりにiMA()が減ります。

iCustom()の使い方は、以下のようになります。

double iCustom(
string symbol, // symbol
int timeframe, // timeframe
string name, // path/name of the custom indicator compiled program
... // custom indicator input parameters (if necessary)
int mode, // line index
int shift // shift
);
となっており、パラメータは

symbolは通貨ペアの名前、NULL はチャートの通貨ペア。

timeframeは通貨ペア足の期間、0はチャートの通貨ペア足の期間。

nameはMQL4/Indicators/のルートディレクトリのコンパイルされたカスタムインジケータ。
上記の場合では"test25"になります。 test25.mq4 の.mq4 は記載しません。

...にはinputパラメータ。不要なら記載しなくても良し。

modeにはSetIndexBuffer() に記載の指標番号。

shiftはインジケータバッファの要素番号。

戻り値はカスタムインジケータの値になります。




カスタムインジケータ 9

iCustom
(前回の続き)

 始にiCustomを使ったプログラムtest28.mq4 のコードを記述しておきます。

//+------------------------------------
//+------------------------------------+
//| test28.mq4 |
//| Copyright 2015, T.S. |
//| http:// |
//+------------------------------------+
#property copyright "Copyright 2015, T.S."
#property link "http://"
#property version "1.00"
#property strict

//--- indicator settings
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red

input int MA_Period=200; 

double mBuffer[];


void OnInit(void)
{
IndicatorBuffers(1);
IndicatorDigits(Digits);
SetIndexStyle(0,DRAW_LINE,STYLE_DOT);
SetIndexBuffer(0,mBuffer);

}

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[])
{
int limit=rates_total-prev_calculated;
//---
if(rates_total<=MA_Period)
return(0);
//---
if(prev_calculated>0)
limit++;

for(int i=0; i{

//(A)
mBuffer[i]=iCustom(NULL,0,"test25",MA_Period,0,i);

}
//
eturn(rates_total);
}
//+------------------------------------------------------------------+


アルゴリズムの説明

 アルゴリズムは、カスタムインジケータ 3のときと同じになります。

違いは、
//(A)式の
mBuffer[i]=iMA(NULL,0,mPeriod,0,MODE_EMA,PRICE_CLOSE,i);

mBuffer[i]=iCustom(NULL,0,"test25",MA_Period,0,i);
に変わっていることです。

注意しなければならないのは、
MT5で使えるがMT4では、
CopyBuffe()という関数が使えず、さらに
ArrayCopy()と言う関数が同じタイプの配列のみしかコピー出来ないということです。

このプログラムを実行すると、
チャートウインドウの下にセパレートウインドウが開き、
赤い点線で200期間単純移動平均線が描かれます。
MA_Periodは省略可能です。
このときはtest25.mq4の期間になります。


------------------------------------------------------------