移動平均(Moving Average)は、一定期間の価格の平均値を線でつないだ、もっとも基本的なテクニカル指標です。MT4には標準で「Moving Average」が入っていますが、ここではMQL4のiMA()関数を使って、移動平均線を描くカスタムインジケータを一から作ってみます。
自分で書いてみると、インジケータの基本的な作り(バッファの用意と OnCalculate() での計算)がよくわかります。

移動平均とiMA()関数
MQL4で移動平均の値を取得するには、iMA()関数を使います。書式は次のとおりです。
|
1 2 3 4 5 6 7 8 9 |
double iMA( string symbol, // symbol int timeframe, // timeframe int ma_period, // MA averaging period int ma_shift, // MA shift int ma_method, // averaging method int applied_price, // applied price int shift // shift ); |
それぞれの引数の意味は次のとおりです。
| 引数 | 意味 | 例 |
| symbol | 計算する通貨ペア。NULLで現在のチャートの通貨ペア | NULL |
| timeframe | 時間足(ENUM_TIMEFRAMES)。0で現在のチャートの時間足 | 0、PERIOD_H1 |
| ma_period | 平均する期間(バーの本数) | 14 |
| ma_shift | 移動平均線を横方向にずらす本数(ラインのオフセット) | 0 |
| ma_method | 平均化手法(ENUM_MA_METHOD) | MODE_SMA |
| applied_price | 計算に使う価格(ENUM_APPLIED_PRICE) | PRICE_CLOSE |
| shift | 何本前のバーの値を取り出すか。0が最新バー | i |
サンプルコード
MetaEditorで新しいカスタムインジケータを作成し、次のコードを貼り付けてコンパイルすると、チャート上にマゼンタ色の14期間SMA(終値ベース)が表示されます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
//+------------------------------------------------------------------+ // MovingAverage_01.mq4 //+------------------------------------------------------------------+ #property strict // インジケーターをチャートウィンドウに表示させる #property indicator_chart_window // インジケーター描画用のバッファー数 #property indicator_buffers 1 // 1番目のインジケータの描画スタイル #property indicator_type1 DRAW_LINE // 1番目のインジケータの描画色 #property indicator_color1 clrMagenta // 1番目のインジケータのラインの太さ #property indicator_width1 2 // データウィンドウに表示するラベル #property indicator_label1 "MA" // 移動平均の平均期間 input int MovingPeriod = 14; // 移動平均のシフト input int MovingShift = 0; // インジケータのバッファ double Buffer[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit(){ // Buffer配列を表示用として設定 SetIndexBuffer(0, Buffer, INDICATOR_DATA); 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 limit = rates_total - prev_calculated; // 2回目以降は、形成中の最新バーも毎ティック計算し直す if(prev_calculated > 0) limit++; for(int i = limit - 1; i >= 0; i--){ Buffer[i] = iMA( NULL, // 通貨ペア名, NULLは現在の通貨ペア 0, // ENUM_TIMEFRAMES の時間足, 0は現在の時間足 MovingPeriod, // 平均する期間 MovingShift, // 移動平均線のシフト MODE_SMA, // 平均するメソッド, ENUM_MA_METHOD PRICE_CLOSE, // サンプリングする価格, ENUM_APPLIED_PRICE i // 0が最新バーで過去へのシフト ); } return(rates_total); } |
このサンプルは単純移動平均(SMA)ですが、iMA()では4種類の平均化手法を選べます(後述)。
コードのポイント
- バッファの用意:#property indicator_buffers 1 で描画用のバッファを1本確保し、OnInit()のSetIndexBuffer()で配列Buffer[]と結びつけます。MQL4のインジケータバッファは、添字0が最新のバーで、数字が大きいほど過去のバーになります。
- 計算する範囲(limit):初回は prev_calculated が0なので、すべてのバーを計算します。2回目以降は prev_calculated に前回の rates_total が入るため、差は新しいバーができたときだけ1、それ以外は0になります。このままでは形成中の最新バー(i=0)が更新されないので、limit++ で最新バーを毎ティック計算し直しています。
- input パラメータ:MovingPeriod と MovingShift は input で宣言しているので、チャートに挿入するときのパラメータ画面から変更できます。
- MQL5との違い:MQL5でよく見る #property indicator_plots はMQL4にはない設定なので、MQL4では使いません。
平均化手法
iMA()の第5引数 ma_method には、次の4種類を指定できます。
| 定数 | 名称 | 特徴 |
| MODE_SMA | 単純移動平均(SMA) | 期間内の価格をそのまま平均。なめらかだが反応は遅め |
| MODE_EMA | 指数移動平均(EMA) | 直近の価格ほど重みを大きくする。SMAより反応が速い |
| MODE_SMMA | 平滑移動平均(SMMA) | 過去の平均値を引き継ぎながら平滑化。もっともゆるやかな線になりやすい |
| MODE_LWMA | 加重移動平均(LWMA) | 新しい価格ほど直線的に重みを大きくする。反応が速い |
たとえばEMAに変えたいときは、サンプルコードの MODE_SMA を MODE_EMA に書き換えるだけです。

同じ期間でも、平均化手法によって線の形はかなり変わります。反応の速さとダマシの多さはトレードオフなので、それぞれの特徴を知ったうえで使い分けるとよいでしょう。
References:




















