MQL5 iMAの使い方完全解説|移動平均を取得する正しい方法と実装例

目次

1. iMAとは何か

1.1 iMAの役割と基本概念

iMA(Moving Average) は、MQL5で移動平均線(MA:価格の平均値を一定期間で平滑化した指標)を取得するための標準関数です。

移動平均は、相場の方向性(トレンド)を判断する最も基本的なテクニカル指標の一つであり、以下の用途で広く使われます。

  • トレンド判定(上昇/下降)
  • ゴールデンクロス・デッドクロス検出
  • 押し目・戻りの判断補助
  • フィルター条件(トレンド方向のみエントリー)

MQL5では、移動平均を計算する処理そのものを自作する必要はありません。
iMA関数を使えば、内部で計算された移動平均インディケータを取得できます。

ただし重要な点として、MQL5のiMAは「値を直接返す関数」ではありません。

MQL4では iMA() を呼ぶと即座に値を取得できましたが、MQL5では“インディケータハンドル方式” に変更されています。

1.2 MQL5におけるiMAの仕組み(ハンドル方式)

MQL5では、iMAを呼び出すと以下の流れになります。

  1. iMAで「インディケータハンドル(識別番号)」を作成する
  2. CopyBufferで実際の移動平均値を取得する

つまり、iMAは「移動平均の値」ではなく、移動平均インディケータの参照ID(ハンドル) を返します。

この構造を理解していないと、次のような誤解が発生します。

❌ よくある誤解

  • iMAを呼べば値が返ると思っている
  • OnTick内で毎回iMAを作成してしまう
  • CopyBufferを使わずに比較処理を書いてしまう

これらはすべて典型的な初学者エラーです。

1.3 移動平均の種類(ENUM_MA_METHOD)

iMAでは複数の移動平均タイプを指定できます。

種類 内容
MODE_SMA 単純移動平均(Simple Moving Average)
MODE_EMA 指数平滑移動平均(Exponential Moving Average)
MODE_SMMA 平滑移動平均
MODE_LWMA 加重移動平均

一般的なトレンドフォローではEMAが多く使われますが、戦略によって適切な選択は異なります。

1.4 iMAを使うべき場面

iMAは次のようなケースで使用します。

  • EAでトレンド方向を判定したい
  • 価格が移動平均より上か下かを条件にしたい
  • マルチタイムフレーム(例:H1のMAをM5で参照)を行いたい

特にEA開発では、トレンドフィルターとしての使用頻度が非常に高い関数です。

1.5 つまずきやすいポイント

⚠ MQL4との違いを理解していない

MQL5では値を直接取得できません。
必ず「ハンドル → CopyBuffer」という流れになります。

⚠ インディケータの生成位置を誤る

  • OnTickで毎回iMAを生成すると負荷が増大
  • 正しくはOnInitで生成する

⚠ データ不足

バー数が不足していると、CopyBufferが正しく動作しないことがあります。
特にテスター開始直後は注意が必要です。

iMAを正しく使うには、まず「構文」と「引数の意味」を正確に理解する必要があります。

2. iMAの基本構文

2.1 iMAの関数定義

MQL5におけるiMAの基本構文は以下の通りです。

int iMA(
   string              symbol,         // 通貨ペア
   ENUM_TIMEFRAMES     period,         // 時間足
   int                 ma_period,      // 移動平均期間
   int                 ma_shift,       // 表示シフト
   ENUM_MA_METHOD      ma_method,      // MAの種類
   ENUM_APPLIED_PRICE  applied_price   // 適用価格
);

この関数は、移動平均インディケータのハンドル(識別番号)を返します。

戻り値が INVALID_HANDLE の場合、インディケータ生成に失敗しています。

2.2 各引数の詳細解説

① symbol(通貨ペア)

  • _Symbol を使うのが一般的
  • 例:"EURUSD" などの明示指定も可能
_Symbol

⚠ マルチ通貨EAでは明示指定が必要になる場合があります。

② period(時間足)

時間足を指定します。

例:

  • PERIOD_M1
  • PERIOD_M5
  • PERIOD_H1
  • PERIOD_D1
  • PERIOD_CURRENT(現在のチャート時間足)
PERIOD_CURRENT

⚠ マルチタイムフレーム分析では、ここを誤るとロジックが破綻します。

③ ma_period(移動平均期間)

移動平均の計算期間です。

例:

  • 20(短期)
  • 50(中期)
  • 200(長期)
20

⚠ バー数が不足していると計算できません。
テスター開始直後は特に注意。

④ ma_shift(表示シフト)

移動平均を右方向にずらす値です。

通常は 0 を使用します。

0

⚠ これは「計算のシフト」ではなく「表示位置のシフト」です。
ロジック判定用では基本0固定で問題ありません。

⑤ ma_method(移動平均の種類)

列挙型(ENUM_MA_METHOD)を指定します。

MODE_EMA

主な種類:

  • MODE_SMA(単純移動平均)
  • MODE_EMA(指数)
  • MODE_SMMA(平滑)
  • MODE_LWMA(加重)

戦略ごとに使い分けが必要です。

⑥ applied_price(適用価格)

どの価格を元に計算するかを指定します。

主な指定値:

  • PRICE_CLOSE(終値)
  • PRICE_OPEN(始値)
  • PRICE_HIGH(高値)
  • PRICE_LOW(安値)
  • PRICE_MEDIAN(中央値)
  • PRICE_TYPICAL(典型価格)

通常は PRICE_CLOSE を使用します。

PRICE_CLOSE

2.3 最小構成のiMA例

int maHandle;

int OnInit()
{
   maHandle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_EMA, PRICE_CLOSE);

   if(maHandle == INVALID_HANDLE)
   {
      Print("iMA handle creation failed");
      return(INIT_FAILED);
   }

   return(INIT_SUCCEEDED);
}

ここで重要なのは:

  • OnInitで生成すること
  • INVALID_HANDLEチェックを必ず入れること

2.4 よくある失敗

❌ OnTick内でiMAを呼ぶ

毎Tick生成するとメモリ消費・パフォーマンス低下の原因になります。

❌ ハンドルの解放忘れ

EA終了時に IndicatorRelease() を呼ばないとメモリが残る可能性があります。

❌ ENUMの型を誤る

intで無理やり指定するとコンパイルは通っても可読性が悪化します。

iMAの構文を理解しただけでは、まだ移動平均値は取得できません。

3. iMAの正しい使い方(ハンドル取得と管理)

3.1 ハンドル生成の正しいタイミング

MQL5では、iMAは値を取得する関数ではなく、インディケータハンドルを生成する関数です。
そのため、生成タイミングを誤るとパフォーマンスや安定性に問題が発生します。

正しい基本構造は以下です。

int maHandle;

int OnInit()
{
   maHandle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_EMA, PRICE_CLOSE);

   if(maHandle == INVALID_HANDLE)
   {
      Print("iMA handle creation failed");
      return(INIT_FAILED);
   }

   return(INIT_SUCCEEDED);
}

なぜOnInitで生成するのか?

  • インディケータは一度生成すれば使い回せる
  • 毎Tick生成は無駄な処理になる
  • テスター速度に大きく影響する

❌ よくある間違い

void OnTick()
{
   int handle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_EMA, PRICE_CLOSE);
}

これは毎Tick新しいインディケータを生成している状態です。
バックテストが遅くなる原因になります。

3.2 ハンドルの有効性チェック

ハンドル生成直後には必ず INVALID_HANDLE チェックを入れます。

if(maHandle == INVALID_HANDLE)
{
   Print("Error creating iMA handle");
   return(INIT_FAILED);
}

失敗する主な原因:

  • 不正な時間足指定
  • シンボルが利用不可
  • ヒストリーデータ不足(環境依存)

3.3 インディケータの解放(重要)

MQL5では、生成したインディケータは明示的に解放するのが安全設計です。

void OnDeinit(const int reason)
{
   if(maHandle != INVALID_HANDLE)
      IndicatorRelease(maHandle);
}

解放しないとどうなる?

  • メモリ使用量が増加する可能性
  • 長時間稼働EAで不安定化の原因になる場合あり

特にVPS運用では、メモリ管理は軽視できません。

3.4 マルチタイムフレーム使用時の注意

例:M5チャート上でH1の移動平均を取得する場合

maHandle = iMA(_Symbol, PERIOD_H1, 50, 0, MODE_EMA, PRICE_CLOSE);

注意点:

  • 上位足のデータがロードされている必要がある
  • 初回実行時はデータ不足でCopyBufferが失敗することがある

対策:

if(Bars(_Symbol, PERIOD_H1) < 100)
{
   Print("Not enough bars for H1");
   return;
}

3.5 実運用視点での設計ポイント

✔ ハンドルはグローバル変数で管理する

→ スコープ外になると再生成が必要になる

✔ 複数MAを使う場合は明確に命名

int maFastHandle;
int maSlowHandle;

✔ 再初期化時の挙動を考慮する

パラメータ変更時はOnDeinit → OnInitが再実行されます。
ハンドル管理が適切でないと異常動作の原因になります。

4. CopyBufferで移動平均値を取得する方法

4.1 CopyBufferとは何か

CopyBuffer() は、インディケータハンドルから実際の計算値を取得するための関数です。

iMAは「ハンドル」を返すだけであり、移動平均の値そのものはCopyBufferで取得します。

基本構文は以下です。

int CopyBuffer(
   int      indicator_handle,   // インディケータハンドル
   int      buffer_num,         // バッファ番号
   int      start_pos,          // 取得開始位置
   int      count,              // 取得本数
   double   buffer[]            // 取得先配列
);

戻り値は「コピーできた要素数」です。
0以下の場合は失敗と判断します。

4.2 基本的な取得例(最新値を取得)

double maBuffer[];

ArraySetAsSeries(maBuffer, true);

if(CopyBuffer(maHandle, 0, 0, 3, maBuffer) <= 0)
{
   Print("CopyBuffer failed");
   return;
}

各引数の意味

  • maHandle:iMAで取得したハンドル
  • 0:バッファ番号(iMAは基本0)
  • 0:現在バーから取得
  • 3:3本分取得
  • maBuffer:取得結果格納用配列

4.3 start_posとインデックスの関係(重要)

start_pos = 0 は「現在の未確定バー」を指します。

インデックスの意味:

  • maBuffer[0] → 現在バー(未確定)
  • maBuffer[1] → 1本前(確定済み)
  • maBuffer[2] → 2本前

実運用での注意

未確定バー(index 0)は価格変動により変化します。

EAロジックでは通常:

double currentMA = maBuffer[1]; // 確定足を使う

未確定バーを使うと、バックテストとリアルが一致しない原因になります。

4.4 ArraySetAsSeriesの意味

ArraySetAsSeries(maBuffer, true);

これを指定すると、

  • インデックス0が最新データ
  • インデックスが大きいほど過去データ

という扱いになります。

指定しない場合は逆順になるため、ロジックが混乱します。

❌ よくある失敗

  • ArraySetAsSeriesを忘れる
  • インデックス方向を誤解する
  • 取得本数より大きいインデックスを参照する(array out of range)

4.5 取得前に確認すべきこと

① バー数が足りているか

if(Bars(_Symbol, PERIOD_CURRENT) < 50)
{
   Print("Not enough bars");
   return;
}

期間20のMAなら最低20本以上必要です。

② CopyBufferの戻り値チェック

int copied = CopyBuffer(maHandle, 0, 0, 3, maBuffer);

if(copied <= 0)
{
   Print("CopyBuffer failed. Error: ", GetLastError());
   return;
}

エラー原因は環境依存の場合があります。

4.6 パフォーマンス設計上の注意

  • 毎Tick大量本数を取得しない
  • 必要最小限の本数だけ取得する
  • ループ内でCopyBufferを多重呼び出ししない

例:

// 不適切
for(int i=0; i<100; i++)
{
   CopyBuffer(maHandle, 0, i, 1, maBuffer);
}

これは非常に非効率です。

4.7 最小構成まとめ例

double maBuffer[];

ArraySetAsSeries(maBuffer, true);

int copied = CopyBuffer(maHandle, 0, 0, 2, maBuffer);

if(copied > 0)
{
   double prevMA = maBuffer[1]; // 確定足
}

この構造が、MQL5での移動平均取得の基本形です。

5. よくあるエラーと対策(iMA / CopyBufferで詰まる点)

5.1 エラーを切り分ける基本方針

iMAまわりの不具合は、原因が「ロジックの誤り」ではなく、次のどれかであるケースが多いです。

  • ハンドル生成に失敗している(iMA側)
  • CopyBufferが失敗している(取得側)
  • 配列の扱いが間違っている(典型)
  • ヒストリーデータ不足(環境依存)
  • 未確定足を使って判定が揺れている(実運用で差が出る)

まずは、必ずチェックログを入れて「どこで失敗したか」を確定させます。

int copied = CopyBuffer(maHandle, 0, 0, 3, maBuffer);
if(copied <= 0)
{
   int err = GetLastError();
   Print("CopyBuffer failed. err=", err);
}

5.2 array out of range(配列範囲外参照)

症状

  • 実行時エラーで停止する
  • ログに array out of range が出る
  • 条件判定行で落ちることが多い

主な原因

  • CopyBuffer で取得した本数より大きいインデックスを参照している
  • 配列サイズが確保されていない(動的配列の初期化不足)
  • ArraySetAsSeries() の有無でインデックス方向を誤解している

典型例(失敗)

double maBuffer[];
ArraySetAsSeries(maBuffer, true);

CopyBuffer(maHandle, 0, 0, 2, maBuffer);
// 2本しか取得していないのに maBuffer[2] を参照している
double x = maBuffer[2];

対策

  • 参照する最大インデックス+1 本を必ず取得する
  • CopyBufferの戻り値をチェックしてから参照する
double maBuffer[];
ArraySetAsSeries(maBuffer, true);

int need = 3;
int copied = CopyBuffer(maHandle, 0, 0, need, maBuffer);
if(copied < need)
{
   Print("Not enough data copied: ", copied);
   return;
}

double prevMA = maBuffer[1];
double prev2MA = maBuffer[2];

5.3 INVALID_HANDLE(ハンドル生成失敗)

症状

  • iMA handle creation failed などのログ
  • CopyBufferが常に失敗する
  • EAが初期化失敗(INIT_FAILED)になる

主な原因(環境により異なる)

  • symbol が利用不可(気配値がない、または指定ミス)
  • period の指定ミス(例:カスタム足など特殊環境)
  • 初期起動時にヒストリーが揃っていない
  • テスター環境でデータが不足している

対策

  • ハンドル生成直後にINVALID_HANDLEを必ず判定
  • Bars() で最低バー数を確認する(特に上位足)
int OnInit()
{
   if(Bars(_Symbol, PERIOD_CURRENT) < 100)
   {
      Print("Not enough bars yet");
      return(INIT_FAILED);
   }

   maHandle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_EMA, PRICE_CLOSE);
   if(maHandle == INVALID_HANDLE)
   {
      Print("iMA handle creation failed. err=", GetLastError());
      return(INIT_FAILED);
   }
   return(INIT_SUCCEEDED);
}

5.4 CopyBuffer failed(値が取れない/0以下が返る)

症状

  • CopyBufferの戻り値が 0 または -1 など
  • バッファが常に空、または値が更新されない

主な原因

  • まだ計算できるだけのデータがない(最頻出)
  • start_pos / count の指定が過剰
  • ハンドルが無効(INVALID_HANDLEのまま)
  • 未確定足を前提にしてロジックが壊れている

対策

  • 取得本数を最小限にする(2〜3本で十分なことが多い)
  • バー数不足なら待機する設計にする
  • 必ず確定足([1])を使う
double maBuffer[];
ArraySetAsSeries(maBuffer, true);

if(Bars(_Symbol, PERIOD_CURRENT) < 30) return;

int copied = CopyBuffer(maHandle, 0, 0, 2, maBuffer);
if(copied < 2)
{
   Print("CopyBuffer not ready. copied=", copied, " err=", GetLastError());
   return;
}

double maConfirmed = maBuffer[1];

5.5 値が0になる/あり得ない値になる

症状

  • MAが0付近のまま
  • 価格とかけ離れた値になる
  • テスター開始直後だけ変

主な原因

  • そもそもデータが揃っていない(開始直後)
  • series配列の方向を誤解(ArraySetAsSeries忘れ)
  • 「現在バー(未確定)」を参照して揺れる

対策

  • 初回は一定バーが溜まるまで計算しない
  • maBuffer[1] を使う(確定足)

5.6 実運用で差が出る“危険ポイント”

⚠ 未確定足(index 0)を使う

バックテストとリアルで結果が一致しない原因になります。
EAの判定は基本「確定足」を前提にします。

⚠ 毎TickでCopyBuffer大量取得

VPS運用や複数通貨EAでは、重くなる原因になります。
必要最小限の本数を取得する設計が安全です。

6. 実運用での注意点(パフォーマンス設計と安全設計)

6.1 毎Tickでの無駄な処理を避ける

iMA/CopyBufferを使ったEAで最も多い設計ミスは、毎Tickで不要な計算を繰り返すことです。

❌ よくある非効率な例

void OnTick()
{
   double maBuffer[];
   ArraySetAsSeries(maBuffer, true);

   CopyBuffer(maHandle, 0, 0, 100, maBuffer);
}

問題点:

  • 毎Tick100本取得している
  • 必要以上にメモリ確保が発生
  • 複数通貨EAでは負荷が急増

✔ 改善方針

  • 必要最小限(通常2〜3本)だけ取得
  • 「新しいバーが確定したときのみ」更新

6.2 新バー判定を入れる(実戦設計)

移動平均を使ったロジックの多くは「確定足ベース」です。
そのため、新しいバーができたタイミングだけ処理すれば十分なケースが多いです。

datetime lastBarTime = 0;

void OnTick()
{
   datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);

   if(currentBarTime == lastBarTime)
      return;

   lastBarTime = currentBarTime;

   // ここにMA取得処理を書く
}

これにより:

  • Tickごとの無駄なCopyBufferを防げる
  • テスター速度が向上する
  • ロジックが安定する

6.3 マルチシンボルEAでの注意

複数通貨でiMAを使う場合、以下に注意が必要です。

✔ 各シンボルごとにハンドルを管理する

int maHandle_EURUSD;
int maHandle_USDJPY;

✔ 各通貨のバー更新タイミングは異なる

iTime() 判定もシンボルごとに必要になります。

⚠ よくある失敗

  • 1つの配列を使い回す
  • シンボルが異なるのに _Symbol 固定で処理する

6.4 IndicatorReleaseを忘れない

EAが停止・再初期化されるたびにハンドルは再生成されます。
解放処理を入れないと、長時間稼働で不安定化する可能性があります。

void OnDeinit(const int reason)
{
   if(maHandle != INVALID_HANDLE)
      IndicatorRelease(maHandle);
}

特にVPS常時運用では重要です。

6.5 未確定足を使わない(バックテスト差異の原因)

❌ 危険な例

double currentMA = maBuffer[0];

maBuffer[0] は現在形成中の足です。
リアルでは値が変動しますが、バックテストでは条件次第で確定値扱いになることがあります。

✔ 推奨

double confirmedMA = maBuffer[1];

確定足のみでロジックを組むと、再現性が高くなります。

6.6 フォワード検証を前提にした設計思想

実運用では次を意識します。

  • MA期間変更時の再初期化挙動
  • データ不足時の待機設計
  • CopyBuffer失敗時に即エントリーしない
  • エラー発生時のログ出力

例:

if(copied < 2)
{
   Print("MA data not ready. Skip trading.");
   return;
}

「値が取れなければ取引しない」設計が安全です。

6.7 設計まとめ(実戦基準)

安全なiMA設計の基本原則:

  • ハンドルはOnInitで生成
  • 新バー確定時のみ更新
  • CopyBufferは最小本数
  • 確定足のみ使用
  • 必ずエラーチェック
  • OnDeinitで解放

これらを守るだけで、EAの安定性は大きく向上します。

7. EAへの組み込み例(ゴールデンクロス判定と落とし穴)

7.1 ゴールデンクロス判定の基本

移動平均をEAに組み込む代表例が、短期MAと長期MAのクロス判定です。

  • 短期MAが長期MAを下から上へ抜ける → ゴールデンクロス(買いシグナル)
  • 短期MAが長期MAを上から下へ抜ける → デッドクロス(売りシグナル)

重要なのは「今の位置」ではなく、直前(確定足)との比較でクロスを検出することです。

7.2 2本のMAハンドルを作成する(OnInit)

int maFastHandle;
int maSlowHandle;

int OnInit()
{
   maFastHandle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_EMA, PRICE_CLOSE);
   if(maFastHandle == INVALID_HANDLE)
   {
      Print("Fast MA handle failed. err=", GetLastError());
      return(INIT_FAILED);
   }

   maSlowHandle = iMA(_Symbol, PERIOD_CURRENT, 50, 0, MODE_EMA, PRICE_CLOSE);
   if(maSlowHandle == INVALID_HANDLE)
   {
      Print("Slow MA handle failed. err=", GetLastError());
      return(INIT_FAILED);
   }

   return(INIT_SUCCEEDED);
}

7.3 CopyBufferで確定足2本を取得する(新バーでのみ)

クロス判定には最低でも「確定足2本分」が必要です。
(1本前と2本前を比較するため)

bool GetMAValues(int handle, double &v1, double &v2)
{
   double buf[];
   ArraySetAsSeries(buf, true);

   int copied = CopyBuffer(handle, 0, 1, 2, buf); // 1=確定足から2本
   if(copied < 2)
      return false;

   v1 = buf[0]; // 1本前(確定足)
   v2 = buf[1]; // 2本前(確定足)
   return true;
}

ここでのポイント:

  • start_pos = 1(未確定足を避ける)
  • count = 2(クロス判定に必要な最低本数)

7.4 クロス判定ロジック(確定足ベース)

void OnTick()
{
   static datetime lastBarTime = 0;
   datetime t = iTime(_Symbol, PERIOD_CURRENT, 0);
   if(t == lastBarTime) return;
   lastBarTime = t;

   double fast1, fast2, slow1, slow2;

   if(!GetMAValues(maFastHandle, fast1, fast2))
   {
      Print("Fast MA not ready");
      return;
   }
   if(!GetMAValues(maSlowHandle, slow1, slow2))
   {
      Print("Slow MA not ready");
      return;
   }

   bool goldenCross = (fast2 <= slow2) && (fast1 > slow1);
   bool deadCross   = (fast2 >= slow2) && (fast1 < slow1);

   if(goldenCross)
      Print("Golden Cross detected (confirmed bar)");
   if(deadCross)
      Print("Dead Cross detected (confirmed bar)");
}

この判定は「クロスした瞬間」を確定足で捉えます。
バックテストとリアルの差が出にくい、実運用向けの書き方です。

7.5 よくある落とし穴(ここで詰まる)

❌ 位置判定だけでクロスと誤認する

例:短期が上なら買い、下なら売り、のような単純判定。

問題点:

  • 「すでに上にいる状態」を毎回シグナル扱いしてしまう
  • 連続エントリーの原因になる

クロスは前の状態→現在の状態の変化で判断します。

❌ 未確定足(0番)でクロス判定する

未確定足で判定すると、次のような問題が起きます。

  • Tickごとにクロス判定が揺れる
  • 「クロスした→戻った→またクロス」のような誤検出
  • バックテストとリアルで結果が変わりやすい

対策は start_pos=1 を徹底することです。

❌ CopyBufferの取得開始位置を誤る

例:CopyBuffer(handle, 0, 0, 2, buf) とすると、

  • buf[0] は未確定足
  • buf[1] は確定足

になり、比較が混乱しやすいです。

クロス判定は「確定足だけ」で完結させるのが安全です。

7.6 実戦向けの追加安全策

クロス判定は単体だとノイズが多い戦略になりやすいです。
実運用ではフィルターを組み合わせるのが一般的です。

例:

  • スプレッドが広いときは取引しない
  • 一定時間は再エントリー禁止
  • 上位足のMA方向と一致したときのみ有効

8. 関連トピック(今後拡張予定)

本記事では、MQL5におけるiMAの基本構文から、CopyBufferによる値取得、EAへの組み込み方法までを解説しました。

ただし、iMAを実戦レベルで使いこなすためには、以下の周辺トピックの理解が不可欠です。

8.1 CopyBufferの完全理解

iMAはハンドルを返すだけであり、実際の値取得はCopyBufferに依存します。

今後解説予定の内容:

  • バッファ番号の仕組み
  • start_posとcountの正確な意味
  • ArraySetAsSeriesの内部挙動
  • パフォーマンスを落とさない取得設計
  • 複数バッファを持つインジケータの扱い方

iMAだけ理解しても、CopyBufferを誤るとほぼ確実にバグの温床になります。

8.2 array out of range完全対策

MQL5初心者が最も頻繁に遭遇する実行時エラーです。

今後解説予定:

  • 発生メカニズムの詳細
  • CopyBufferと配列サイズの関係
  • series配列方向ミスの検出方法
  • 再発防止テンプレートコード
  • 実戦EAでの防御設計

エラー対策を体系化することで、EAの安定性は大きく向上します。

8.3 iCustomとの違い

iMAは標準インジケータですが、カスタムインジケータを扱う場合は iCustom を使用します。

予定解説内容:

  • iCustomの基本構文
  • パラメータの渡し方
  • バッファ番号の特定方法
  • マルチバッファインジケータの管理
  • ハンドル管理の共通設計

iMAを理解した段階で、iCustomへ進むのが自然な流れです。

8.4 移動平均を用いたEA設計思想

単純なクロス戦略はノイズが多く、実運用ではそのままでは通用しません。

今後扱うテーマ:

  • フィルター設計(上位足方向一致)
  • エントリー頻度制御
  • ロット自動計算との連携
  • 最大ドローダウン制御との統合
  • フォワード検証前提の構造設計

本サイトでは、単なるコード紹介ではなく、安全設計と再現性を重視したEA構造を扱います。

8.5 本記事の位置付け

本記事は、MQL5におけるインディケータ取得の「最初の基礎」です。

ここを正しく理解していない場合:

  • バックテストとリアルが一致しない
  • CopyBufferエラーで停止する
  • 配列エラーで実行時停止する
  • パフォーマンスが著しく低下する

といった問題が発生します。

iMAは単純に見えて、MQL5のハンドル構造・バッファ構造・系列配列の理解を要求する関数です。

この理解を土台として、次はCopyBufferの詳細設計へ進みます。

9. よくある質問(FAQ)

9.1 MQL5でiMAの値が0になるのはなぜですか?

主な原因は次のいずれかです。

  • ヒストリーデータが不足している(バー数不足)
  • CopyBufferが正常に値を取得できていない
  • 取得開始位置(start_pos)や取得本数(count)が不適切
  • テスター開始直後でまだ十分なデータが形成されていない

対策:

  • Bars() で必要本数以上あるか確認する
  • CopyBufferの戻り値を必ずチェックする
  • 確定足(index 1以降)を使用する

値が0だからといってロジックをそのまま進めると、誤エントリーの原因になります。

9.2 MQL4のiMAとの違いは何ですか?

最大の違いは「ハンドル方式」です。

  • MQL4:iMA() が直接値を返す
  • MQL5:iMA() はハンドルを返し、値取得はCopyBufferで行う

そのため、MQL4のコードをそのまま移植すると動きません。

特に初心者が混乱しやすいのは、「iMAが値を返さない」点です。
MQL5では必ず「ハンドル生成 → CopyBuffer取得」の流れになります。

9.3 CopyBufferで何本取得すればよいですか?

用途により異なります。

  • 単純な値参照:2本(確定足とその前)
  • クロス判定:最低2本(前状態との比較が必要)
  • 傾き判定:3本以上

重要なのは、参照する最大インデックス以上の本数を必ず取得することです。

不足すると array out of range エラーになります。

9.4 iMAを毎Tickで呼ぶと問題になりますか?

推奨されません。

理由:

  • 毎Tickインディケータを生成すると無駄な負荷が発生する
  • バックテスト速度が低下する
  • 複数通貨EAではパフォーマンス問題が顕在化する

安全な設計:

  • OnInitでハンドル生成
  • 新バー確定時のみCopyBuffer実行

9.5 未確定足(index 0)を使ってもよいですか?

技術的には可能ですが、実運用では推奨されません。

理由:

  • 未確定足は価格変動により値が変化する
  • バックテストとリアルの結果が一致しにくくなる
  • クロス判定が揺れやすい

再現性を重視する場合は、確定足(index 1以降)を使用します。

This website stores cookies on your computer. These cookies are used to provide a more personalized experience and to track your whereabouts around our website in compliance with the European General Data Protection Regulation. If you decide to to opt-out of any future tracking, a cookie will be setup in your browser to remember this choice for one year.

Accept or Deny