今日も窓辺でプログラム

外資系企業勤めのエンジニアが勉強した内容をまとめておくブログ

MT4でカスタム指標を定義してみる

前回はMT4でスクリプトを実行してみました。今回はチャートに自分で定義した指標を描画するカスタム指標を定義してみようと思います。

カスタム指標とは

前回も紹介した通り、カスタム指標 (Custom Indicator) とは独自に作成したテクニカル指標をチャートに描画するためのプログラムです。

カスタム指標には初期化のためのOnInit()関数と実際に指標を計算するOnCalculate()関数を定義しますが、カギとなるのは OnCalculate() 関数で、次のような場合にカスタム指標を計算するために呼ばれます。 1. カスタム指標がチャートに読み込まれ、初期化処理 (OnInit()) が終了した直後 1. 新しいティックを受信したとき

始値と終値の平均

まずはサンプルプログラムを紹介します。特に意味はありませんが、各期間ごとの始値と終値の平均で定義されるカスタム指標を描画してみます。

#property copyright "Copyright 2019, madopro"
#property link      "https://www.madopro.net"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers   1
#property indicator_color1 clrRed // 指標1の色の指定

// 指標1を保持する配列
double my_indicator[];

int OnInit() {
  // 指標1の配列を指定
  SetIndexBuffer(0, my_indicator);
  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[]) {
  // 計算が必要な範囲
  int len = rates_total - prev_calculated;
  for(int i =0; i < len; i++) {
    my_indicator[i] = (open[i] + close[i]) / 2.0;
  }

  // この戻り値が次に OnCalculate が呼ばれる際の prev_calculated となる
  return rates_total - 1;
}

カスタム指標のデータ構造

カスタム指標は各期間での数値列なので、double型の動的配列として定義します。

double my_indicator[];

上記のように配列の要素数を省略して宣言するとその配列は動的配列となります。動的配列では、既にメモリを確保しているインデックスよりも大きいインデックスにアクセスがあった際に、自動的に新しいメモリが確保される、というような挙動をするようです。また、動的配列のスコープを抜けるとメモリが自動で解放されるようです。

インデックスは0が現在、1が1単位時間前、2が2単位時間前、というように解釈します。たとえば1分足チャートであれば、最新の指標は my_indicator[0], 1分前の指標は my_indicator[1] に格納します。

OnInit関数

次に注目すべきはOnInit関数です。SetIndexBufferでカスタム指標として使用する配列を指定します。一つのプログラムで複数個のカスタム指標 (#property indicator_buffers で定義された値の数だけ)を定義できるので、第1引数で何個目の指標か、第2引数でどの配列を指標として使用するかを指定します。

戻り値は INIT_SUCCEEDED を返しておけばよいです。

OnCalculate関数

初期化処理後、および毎ティック呼ばれるOnCalculate関数ですが、引数は主に2種類あります。 rates_totalprev_calculated はチャートに含まれるバーの本数に関する情報、その他の引数は各バーの具体的な数値を保持しています。

rates_total はチャートに含まれるバーの本数を表しています。たとえばチャートにバーが100本存在していたら、rates_total = 100 です。

prev_calculated は直前に呼ばれた OnCalculate() の戻り値の値となります。通常、指標をどこまで計算済みかを示す値を保存して使用します。たとえば、rates_total = 100 で OnCalculate が呼ばれた場合、1個前の時点までの指標は確定していて再計算する必要がないので、次の呼び出し時に prev_calculated = 99 となるように99を返します。(最新の指標は変更される可能性があるので、次の呼び出し時にも再度計算してあげます。)

後者は簡単で、例えば始値を保持している open という引数は、 open[0] で直近の始値、 open[1] で1つ前の始値にアクセスできます。

以上がサンプルプログラムの概要になります。 #property で線の色などを指定していますので、このファイルをコンパイルしチャートにドラッグすると、始値と終値のちょうど中間の点が赤色の線で結ばれるような指標が描画されます。

定義済みのテクニカル指標を参照する

MQL4には様々なテクニカル指標が定義されていて、簡単にそれを使用することができます。たとえば移動平均をみたければiMAという関数を使用します。各引数の使い方は公式ドキュメントに譲りますが、10単位時間(例えば日足チャートの場合10日)の移動平均は下記のように関数を呼ぶだけで計算できてしまいます。

my_indicator[i] = iMA(_Symbol, PERIOD_CURRENT, 10, 0, MODE_SMA, PRICE_OPEN, i);

参考

新MT4対応 FXメタトレーダープログラミング入門

新MT4対応 FXメタトレーダープログラミング入門