2016年1月18日月曜日

[MQL超入門] その013 OnCalculate解説

前回までで、流れに沿ってインジケータを作成できました。

今後自作のインジケータを作成するためには、もう少し内容を理解する必要があります。
まず、インジケータの本体である、OnCalculateについて解説したいと思います。

ウィザードを使ってインジケータを作成すると、次のコードが作成されます。
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
//---

//--- return value of prev_calculated for next call
   return(rates_total);
  }

[OnInit]は、インジケータの初期化時にMT4から呼び出されます。
インジケータをチャートに挿入したときや、表示時間足を変更した場合に呼び出されます。
[OnCalculate]は、チャート上でTick値が更新されるたびにMT4から呼び出されます。

インジケータを本格的に作成しようとすると、このOnCalculateを詳しく知る必要があります。そこで、今日はOnCalculateを解説したいと思います。
少しわかりやすくするため、日本語のコメントを入れたいと思います。[OnCalculate]が呼び出される際、MT4から10個のデータが渡されます。この10個のデータを使っていろんなインジケータを計算するのが基本です。
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[])            //スプレット

それぞれを解説したいと思います。

・rates_total
これは、インジケータが持っている配列要素数です。チャートに新しいバーが出るたびに、一つ増えます。最初はチャートのバー本数と一致します。
例えば、バー本数を1000本に指定している場合、最初は1000という数字が入ってきますが、バーが一つ更新されると1001になります。

・prev_calculated
[rates_total]にたいして、すでに計算済みの要素数を指定します。
ただし、これは実際には、前回[OnCalculate]を呼び出した際の[return]値が入ってきます。まだ一度も呼び出していない場合は0です。
たとえば、ウィザード初期状態でのプログラムでは[return(rates_total)]と指定されています。この場合、バーの追加がなければrates_totalと同じ値、バーの追加があれば、[rates_total]は一つ増えています。逆に考えるとバーの追加があった場合、[prev_calculated]は[rates_total]に対して一つ少ない値になります。
そのため、[rates_total]と[prev_calculated]の差を見ると、計算していないバーの本数を求めることができる事になります。

私は、[prev_calculated]の最新のバーは常に更新をしてもらうために、
return (rates_total - 1);
という書き方をします。こうすると、Tickの更新があるたびに最新のバーは計算しなさいよという指定になります。

・time open high low close
この5つは実際のチャート上のバーの値が配列として入ってきます。
それぞれ、時間、始値、高値、安値、終値です。
配列として入ってきますが下記の特徴があります。

・要素0が最新の値となる。
・要素数はrates_totalのため、rates_total以上の要素は参照しないようにする事

余談ですがプログラマ的感覚だと、要素があとに行くほど新しい値のイメージがあります。
MT4では逆なので少し戸惑う部分がありますが、0が最新と考えた方がしっくりくる場合も多いです。

ここで改めて、前回作成したTick更新回数インジケータの[OnCalculate]内の[for]部分を見てましょう。
for( int i = rates_total - prev_calculated - 1; i >= 0; i-- )
[i]が[rates_total - prev_calculated - 1]から始まって、0になるまで繰り返しています。

これは古いデータから値を作成していくため、このような書き方をしています。移動平均などは過去データをもとに記述する場合があります。テクニカル値は過去データが計算されていないと現在値が求まらない場合が多いため、このようなループ文にしています。

・tick_volume
Tick更新回数インジケータでも使用しましたTickの更新回数のデータです。

・volume
約定枚数のデータですが、FXでは使用されていません。株とかのデータを受け取った場合には入ってくるようです。

・spread
スプレッドですが、MT4では使用されていません。

OnCalculateにてMT4からどのようなデータがわたってくるかを確認しました。ぜひこれらのデータを使用して自作インジケータを作ってみてくださいね。

次の回へ


ブログランキングにご協力よろしくお願いします。m(._.)m
にほんブログ村 為替ブログへ