【MQL5】iAD関数の使い方と自動売買実装コード

1. iAD関数の概要と実務での活用法

iAD関数は、メタトレーダー5(MQL5)でアキュムレーション/ディストリビューション(Accumulation/Distribution, A/D)指標の値を取得するための組み込み関数です。

A/Dは、価格の推移に「出来高」の概念を組み合わせた指標です。「買い集め(Accumulation)」と「投げ売り(Distribution)」の勢いを可視化し、現在のトレンドが本物かどうかを判定するのに役立ちます。

実務での活用シーン

クオンツトレードの実務において、A/Dは主に「ダイバージェンス(逆行現象)」の検知に利用されます。
* 価格が高値を更新しているのにA/Dが下がっている場合、上昇の勢いが弱まっており、反転の兆しと判断する。
* 価格が安値を更新しているのにA/Dが上がっている場合、底打ちが近いと判断する。

初心者がつまずきやすいポイント

FX(為替)市場には中央取引所がないため、株と違って「正確な総取引高」は存在しません。MQL5のiADで使われるボリュームは、あくまで「ティックボリューム(価格の変化回数)」です。「実際の資金流入量ではない」という前提を理解して設計しないと、計算結果を過信してしまうリスクがあります。


2. 構文と戻り値

iAD関数は、指標の計算設定を行い、そのデータを参照するための「ハンドル」と呼ばれる識別番号を返します。

構文

int iAD(
   string              symbol,          // 通貨ペア(NULLなら現在の通貨)
   ENUM_TIMEFRAMES     period,          // 時間足(0なら現在の時間足)
   ENUM_APPLIED_VOLUME applied_volume   // 使用する出来高の種類
);

パラメーター解説

  1. symbol: 対象となる通貨ペアを指定します(例: "EURUSD")。
  2. period: 計算する時間足を指定します(例: PERIOD_H1)。
  3. applied_volume: 出来高のタイプを選択します。
    • VOLUME_TICK: ティックボリューム(FXでは一般的にこちらを使用)。
    • VOLUME_REAL: 実際の取引高(株や先物など、リアルボリュームが提供されている銘柄用)。

戻り値

  • 成功した場合:指標のハンドル(int型の整数)。
  • 失敗した場合:INVALID_HANDLE

取得したハンドルを使い、CopyBuffer関数で実際の数値(配列)を取り出すという2ステップの処理が必要になります。


3. 具体的な使い方・実践サンプルコード

以下は、iADを使用して現在の値を読み取り、ログに出力するシンプルなEA(エキスパートアドバイザー)の構成例です。

//+------------------------------------------------------------------+
//|                                              Sample_iAD_EA.mq5   |
//+------------------------------------------------------------------+
#property strict

// グローバル変数
int adHandle; // iADのハンドルを格納する変数

//+------------------------------------------------------------------+
//| 初期化関数                                                        |
//+------------------------------------------------------------------+
int OnInit()
{
   // iADのハンドルを作成
   // 現在の通貨ペア、現在の時間足、ティックボリュームを使用
   adHandle = iAD(_Symbol, _Period, VOLUME_TICK);

   // ハンドルの取得失敗チェック
   if(adHandle == INVALID_HANDLE)
   {
      Print("iADハンドルの作成に失敗しました。エラーコード:", GetLastError());
      return(INIT_FAILED);
   }

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| 終了処理関数                                                      |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // 使用したハンドルを解放してメモリを節約
   IndicatorRelease(adHandle);
}

//+------------------------------------------------------------------+
//| ティック毎の処理                                                  |
//+------------------------------------------------------------------+
void OnTick()
{
   double adValues[]; // 値を格納する動的配列

   // 配列を時系列(新しい順)にセット
   ArraySetAsSeries(adValues, true);

   // ハンドルを使って最新のデータを配列にコピー(最新2個分)
   if(CopyBuffer(adHandle, 0, 0, 2, adValues) < 0)
   {
      Print("データのコピーに失敗しました。エラー:", GetLastError());
      return;
   }

   // 最新のA/D値を取得
   double currentAD = adValues[0];
   double prevAD    = adValues[1];

   // ロジック例:A/Dが上昇傾向にあるか確認
   if(currentAD > prevAD)
   {
      Comment("A/D上昇中: ", currentAD);
   }
   else
   {
      Comment("A/D下降中: ", currentAD);
   }
}

4. 使用上の注意点とよくあるエラー

1. ハンドルの解放を忘れない

OnInitで作成したハンドルは、EAが停止する際にOnDeinitIndicatorRelease(adHandle)を呼び出して解放してください。これを忘れると、バックテストや長期間の稼働時にメモリ(PCの負荷)を無駄に消費する原因になります。

2. データが溜まるまで待つ

EAを起動した直後、CopyBufferで十分なデータが取得できないことがあります。特に過去の値を参照するロジックの場合、SeriesInfoInteger等でバーの数を確認するか、データ取得の成否を必ずチェックするガードコードを入れてください。

3. 計算ロジックの違い

A/Dは累積値(累積加算)であるため、チャートを表示させたタイミングやサーバーによって、表示される数値自体が異なる場合があります。絶対的な数値(例:1000を超えたら買い)ではなく、「前日より上がったか」「価格と逆方向に動いていないか」という相対的な動きに注目するのが正しい使い方です。


5. 【重要】自動売買における約定スピードと環境の罠

アルゴリズムトレードにおいて、ロジックの精度と同じか、それ以上に重要なのが「実行環境」です。自宅のPCや一般的な光回線でEAを稼働させることは、プロの現場から見れば極めて大きなリスクを伴います。なぜなら、自宅環境ではインターネットの経路が複雑で、証券会社サーバーとの間に数十〜数百ミリ秒の遅延(レイテンシ)が発生するためです。

このわずかな遅延が、相場急変時の約定価格を滑らせ(スリッページ)、バックテストでは利益が出ていたはずのロジックを赤字へと変貌させます。また、Windowsの予期せぬアップデートや停電によるPC停止は、ポジション管理を不能にし、致命的な損失を招きかねません。安定した利益を追求し、約定スピードを極限まで高めるには、証券会社のデータセンターに近い場所に位置する専用のVPS(仮想専用サーバー)の使用が必須です。プロのエンジニアにとって、VPSはコストではなく、勝つための「インフラ」であることを理解してください。

💡 この記事の内容を実運用で活かすには?

この記事の内容を実運用で活かすには、正しい環境が必要です。
特にVPSを使わないと、このロジックは再現できません。

コメント

タイトルとURLをコピーしました