インジケータ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の期間になります。
------------------------------------------------------------
今回はプログラムのコードのみです。
説明は次回に予定しています。
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/=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
//---
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/=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の期間になります。
------------------------------------------------------------