MTFインジケーターのサンプルコードをそのままメタエディタにコピペしたのに、
「’Current’ – undeclared identifier」のようなエラーが出て
コンパイルできなかった——という人向けの記事です。
原因は、パラメーターのデフォルト値にMQL4には存在しない名前が使われていたことです。
この記事では、どこが間違っていたか、正しくはどう書けばよいかを説明しながら、
実際にコンパイルできる完全なMTF移動平均線インジケーターのコードを紹介します。
MTF(マルチタイムフレーム)で移動平均線を表示するインジケーター
MTFとはマルチタイムフレームの略語で、
ある時間軸の移動平均線を違う時間軸のチャートに表示できるインジケーターです。
MTFインジケーターを活用することで、
下位足を表示させていても上位足の状況を判断することができるといった優れものです。
今回は、MTFで移動平均線を表示するインジケーターを作成していきます。
メタエディタ(MetaEditor)を立ち上げる
メタエディタ(MetaEditor)を立ち上げましょう。
今回は名前を「MTF-Ma」で作成します。
プロパティを記述する
プロパティを記述しましょう。バッファはラインを表示させるだけなので1です。
#property indicator_buffers 1//バッファ1
線に設定します。
#property indicator_type1 DRAW_LINE//線
色を水色に設定します。
#property indicator_color1 clrAqua//色
線の種類を実線にします。
#property indicator_style1 STYLE_SOLID//実線
幅を1にします。これでプロパティの記述は完了です。
#property indicator_width1 1//幅
#property indicator_buffers 1//バッファ1 #property indicator_type1 DRAW_LINE//線 #property indicator_color1 clrAqua//色 #property indicator_style1 STYLE_SOLID//実線 #property indicator_width1 1//幅
バッファを定義する
バッファを定義しましょう。これでバッファの定義は完了です。
double ma[];//バッファ
double ma[];//バッファ
OnInit()関数を記述する
OnInit()関数を記述しましょう。インデックス0にmaを格納します。
SetIndexBuffer(0, ma);//インデックス0にmaを格納
ラベルを表示させます。これでOnInit()関数の記述は完了です。
SetIndexLabel(0, StringFormat("MA(%d) [%s]", MaPeriod, EnumToString(TimeFrame)));//ラベル
SetIndexBuffer(0, ma);//インデックスにmaを格納
SetIndexLabel(0, StringFormat("MA(%d) [%s]", MaPeriod, EnumToString(TimeFrame)));//ラベル
パラメーターを記述する
パラメーターを記述しましょう。
TimeFrameは対象の時間軸を指定します。
今回は現在の時間軸を対象にするのでPERIOD_CURRENTにします。
input ENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT;//対象の時間軸
MAの期間を21に指定します。
input int MaPeriod = 21;//期間
シフトは0に指定します。
input int MaShift = 0;//シフト
MAの種類は単純移動平均MODE_SMAに指定します。
input ENUM_MA_METHOD MaMethod = MODE_SMA;//種類
適正価格は終値PRICE_CLOSEに指定します。これでパラメーターの記述は完了です。
input ENUM_APPLIED_PRICE MaAppliedPrice = PRICE_CLOSE;//適正価格
input ENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT;//対象の時間軸 input int MaPeriod = 21;//期間 input int MaShift = 0;//シフト input ENUM_MA_METHOD MaMethod = MODE_SMA;//種類 input ENUM_APPLIED_PRICE MaAppliedPrice = PRICE_CLOSE;//適正価格
「Current」「simple」「ClosePrice」は存在しない
このパラメーターは、書き方を間違えるとコンパイルが通らない代表的な箇所です。
ENUM_TIMEFRAMES・ENUM_MA_METHOD・
ENUM_APPLIED_PRICEは、
それぞれMQL4があらかじめ用意した決まった名前の定数しか使えません。
- 対象の時間軸を「現在の足」にしたい場合は
CurrentではなくPERIOD_CURRENT - 単純移動平均にしたい場合は
simpleではなくMODE_SMA(他に指数平滑=MODE_EMA、平滑化=MODE_SMMA、線形加重=MODE_LWMA) - 終値を使いたい場合は
ClosePriceではなくPRICE_CLOSE(他に始値=PRICE_OPEN、高値=PRICE_HIGH、安値=PRICE_LOW)
「わかりやすい英語」で書きたくなる気持ちは自然ですが、
MQL4では定義されていない単語を使うと、
コンパイル時に
「’○○’ – undeclared identifier」というエラーになります。
エラーが出たら、まずこの3種類の定数名を疑ってみてください。
OnCalculateを記述する
OnCalculateを記述しましょう。
iBarShift()関数は、指定した通貨ペア・時間軸・日時における
バーの位置を取得するために使用します。
int shift_need_recalculate = iBarShift(NULL, Period(), iTime(NULL, TimeFrame, 0));
rates_total・prev_calculatedで再計算範囲を決める
rate_totalとはインジケーターが持っている配列の要素数です。
チャートに新しいバーが出るたびに1つずつ増えていきます。
最初はチャートのバー本数と一致します。
rate_totalがshift_need_recalculateよりも低ければ、
return0で返します。
if (rates_total <= shift_need_recalculate)
{
return 0;
}
prev_calculatedはrate_totalに対して
すでに計算済みの要素数を指定します。
ただし、実際にはOnCalculateを呼び出した際のreturnの値が格納されています。
まだ一度も呼び出されていない場合は0です。
rates_totalからprev_calculatedを引いているので
現在の最新のバーが残ります。
int num_uncalculated = rates_total - prev_calculated;
MathMaxでループの開始位置を決めてiMAの値を代入する
MathMaxで
- shift_need_recalculate
- num_uncalculated – 1
の2つの値の最大値を返します。
その値を初期値iに代入して、for文で0になるまでループさせます。
for (int i = MathMax(shift_need_recalculate, num_uncalculated - 1); i >= 0; i--)
iBarShiftでtime[i]をshiftに代入します。
shiftをiMA関数のシフトの引数にしてma[i]に代入します。
int shift = iBarShift(NULL, TimeFrame, time[i]); ma[i] = iMA(NULL, TimeFrame, MaPeriod, MaShift, MaMethod, MaAppliedPrice, shift);
OnCalculateはこれで完了です。
int shift_need_recalculate = iBarShift(NULL, Period(), iTime(NULL, TimeFrame, 0));
if (rates_total <= shift_need_recalculate)
{
return 0;
}
int num_uncalculated = rates_total - prev_calculated;
for (int i = MathMax(shift_need_recalculate, num_uncalculated - 1); i >= 0; i--)
{
int shift = iBarShift(NULL, TimeFrame, time[i]);
ma[i] = iMA(NULL, TimeFrame, MaPeriod, MaShift, MaMethod, MaAppliedPrice, shift);
}
元記事のこの部分には全角スペースによるインデントが混ざっていましたが、
上のコードでは半角スペースに統一しています。
MQL4は全角スペース・全角文字を使うとエラーになるため、
コピペする際は貼り付け先のエディタで全角文字が紛れ込んでいないか確認してください。
コンパイルする
コンパイルして、移動平均線の上位足を下位足にセットすれば表示されます。

ソースコード全体
MTF-Maのソースコード全体は以下に記載しています。
存在しない定数を正しいものに修正し、
全角スペースも半角に統一した、そのままコンパイルできる完全版です。
//+------------------------------------------------------------------+
//| MTF-Ma.mq4 |
//| Copyright 2020, FX-EA System Project Creator |
//| https://creator.fx-ea-system-project.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, FX-EA System Project Creator"
#property link "https://creator.fx-ea-system-project.com/"
#property version "1.01"
#property strict
/*プロパティ*/
#property indicator_chart_window//メインウィンドウ
#property indicator_buffers 1//バッファ1
#property indicator_type1 DRAW_LINE//線
#property indicator_color1 clrAqua//色
#property indicator_style1 STYLE_SOLID//実線
#property indicator_width1 1//幅
/*バッファ*/
double ma[];//バッファ
/*パラメーター*/
input ENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT;//対象の時間軸
input int MaPeriod = 21;//期間
input int MaShift = 0;//シフト
input ENUM_MA_METHOD MaMethod = MODE_SMA;//種類
input ENUM_APPLIED_PRICE MaAppliedPrice = PRICE_CLOSE;//適正価格
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0, ma);//インデックス0にmaを格納
SetIndexLabel(0, StringFormat("MA(%d) [%s]", MaPeriod, EnumToString(TimeFrame)));//ラベル
//---
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[])
{
//---
int shift_need_recalculate = iBarShift(NULL, Period(), iTime(NULL, TimeFrame, 0));
if(rates_total <= shift_need_recalculate)
{
return 0;
}
int num_uncalculated = rates_total - prev_calculated;
for(int i = MathMax(shift_need_recalculate, num_uncalculated - 1); i >= 0; i--)
{
int shift = iBarShift(NULL, TimeFrame, time[i]);
ma[i] = iMA(NULL, TimeFrame, MaPeriod, MaShift, MaMethod, MaAppliedPrice, shift);
}
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
あわせて読みたい: 【MQL】猿でもできてしまうMTF(マルチタイムフレーム)の作成のテンプレートについてわかりやすく説明してみた
トレードでの使い方: FXのMTF分析(マルチタイムフレーム分析)の環境認識のコツや時間足の組み合わせなどわかりやすく解説してみた
【MQL】MTF(マルチタイムフレーム)で移動平均線を表示するインジケーター【上級編】:まとめ
MTFは独特な考え方が必要で難易度が高くなりますが、
考え方さえわかってしまえば他にもMTFは応用が可能です。
MTFのインジケーターは非常に重要なのでぜひマスターしておきましょう。
コメント