
MQL4MQL5 イベント関数
OnCalculate()
- できること
- インジケーターの値を計算するために呼ばれる
- 対応
- MQL4・MQL5
OnCalculate() とは
カスタムインジケーターで、価格データが更新されるたびに呼ばれる関数です。インジケーターバッファに値を入れて、チャートに線や矢印を表示します。2通りの書き方があり、ふつうは時刻・4本値・出来高を受け取る長いほうを使います。
OnCalculate() の書式と引数
引数の組み合わせが違う 2 通りの書き方があります。
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 OnCalculate(
const int rates_total,
const int prev_calculated,
const int begin,
const double &price[]
)| 引数 | 型 | 省略時 | 説明 |
|---|---|---|---|
rates_total | const int | 必須 | チャートにあるバーの本数(配列の要素数)。 |
prev_calculated | const int | 必須 | 前回の OnCalculate() が返した値。初回は 0 なので、0 なら全部のバーを計算し、そうでなければ新しいバーだけ計算する、という使い方をします。 |
time | const datetime &[] | 必須 | 各バーの開始時刻の配列。 |
open | const double &[] | 必須 | 始値の配列。 |
high | const double &[] | 必須 | 高値の配列。 |
low | const double &[] | 必須 | 安値の配列。 |
close | const double &[] | 必須 | 終値の配列。 |
tick_volume | const long &[] | 必須 | ティック出来高の配列。 |
volume | const long &[] | 必須 | 実出来高の配列(FX では多くの場合 0)。 |
spread | const int &[] | 必須 | スプレッドの配列。 |
begin | const int | 必須 | 短いほうの書き方で、price[] のうち有効なデータが始まる位置。 |
price | const double &[] | 必須 | 短いほうの書き方で、パラメーター画面の「適用価格」で選んだ価格(終値など)の配列。 |
戻り値
計算し終えたバーの本数を返します。ふつうは rates_total をそのまま返します。この値が次回の prev_calculated になります。
OnCalculate() の使い方(コード例)
MQL4
#property strict
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 clrDodgerBlue
input int InpPeriod = 20; // 期間
double Buf[];
int OnInit()
{
SetIndexBuffer(0, Buf);
SetIndexStyle(0, DRAW_LINE);
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[])
{
if(rates_total < InpPeriod) return 0;
ArraySetAsSeries(close, true); // 0 = 最新のバー
ArraySetAsSeries(Buf, true);
int limit = rates_total - prev_calculated; // 計算が必要な本数
if(prev_calculated == 0) limit = rates_total - InpPeriod;
for(int i = limit; i >= 0; i--)
{
if(i > rates_total - InpPeriod) continue;
double sum = 0;
for(int k = 0; k < InpPeriod; k++) sum += close[i + k];
Buf[i] = sum / InpPeriod;
}
return rates_total;
}MQL5
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDodgerBlue
input int InpPeriod = 20; // 期間
double Buf[];
int OnInit()
{
SetIndexBuffer(0, Buf, INDICATOR_DATA);
return INIT_SUCCEEDED;
}
// 終値の単純移動平均を自分で計算する(0 = 最も古いバーのまま使う)
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 < InpPeriod) return 0;
int start = (prev_calculated == 0) ? InpPeriod - 1 : prev_calculated - 1;
for(int i = start; i < rates_total; i++)
{
double sum = 0;
for(int k = 0; k < InpPeriod; k++) sum += close[i - k];
Buf[i] = sum / InpPeriod;
}
return rates_total;
}MetaEditor でコンパイルできることを確認済みです。
OnCalculate() の注意点
- 毎回すべてのバーを計算し直すと重くなります。prev_calculated を使って、新しいバー(と最新のバー)だけを計算します。
- 配列の並び順に注意します。MQL5 では配列の 0 番が最も古いバーです。0 番を最新のバーとして扱いたいときは、ArraySetAsSeries(close, true) のように時系列の設定をします。MQL4 と MQL5 で同じ書き方にしたい場合も、ArraySetAsSeries() で向きを明示しておくと安全です。
- OnCalculate() が1つもないインジケーターは「event handling function not found」でコンパイルエラーになります。












