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

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

CopySpreadは、指定した通貨ペアと時間軸における「スプレッド(売値と買値の差)」の履歴データを取得するための関数です。MQL5ではスプレッドはint型の配列として格納され、単位は「ポイント」で返されます。

実務での活用シーン:
FXの自動売買(EA)において、スプレッドは単なる取引コストではなく、「フィルタリング」の重要な指標です。
指標発表時や週明けの回避: スプレッドが極端に拡大している局面でのエントリーを阻止する。
スキャルピングの優位性判定: 過去1時間(または直近数本)の平均スプレッドを算出し、現在のスプレッドが「通常時」の範囲内かどうかを判定する。
バックテストの精度向上: リアルタイムのスプレッドだけでなく、過去のスプレッド状況を分析してロジックの堅牢性を確認する。

多くの開発者が、現在のスプレッド(SymbolInfoIntegerで取得可能)だけを見てしまいがちですが、CopySpreadを使って「傾向」を把握することで、急な約定拒否や大きなスリッページによる損失を未然に防ぐことが可能になります。


2. 構文と戻り値

CopySpread関数には、取得方法の違いによって3つのオーバーロード(書き方)がありますが、実務で最も多用される「開始位置と個数を指定する形式」を中心に解説します。

構文

int  CopySpread(
   string           symbol_name,      // 通貨ペア名(NULLで現在のチャート)
   ENUM_TIMEFRAMES  timeframe,        // 時間軸(PERIOD_CURRENTで現在の足)
   int              start_pos,        // 開始位置(0が最新のバー)
   int              count,            // 取得する個数
   int              spread_array[]    // コピー先のint型配列
);

戻り値

  • 成功時: コピーされた要素の数(countで指定した数)を返します。
  • 失敗時: -1 を返します。

※データがまだ準備できていない場合、期待した数より少ない値が返ることがあります。そのため、戻り値のチェックは必須です。


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

以下は、直近10本のローソク足におけるスプレッドの平均値を算出し、現在のスプレッドが平均の1.5倍を超えている場合に「異常」と判定する実戦的なコード例です。

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

// エントリー可否を判定する関数
bool IsSpreadNormal()
{
    int spreadArray[];
    int lookback = 10; // 直近10本を対象

    // 配列を時系列順(最新がインデックス0)に設定
    ArraySetAsSeries(spreadArray, true);

    // スプレッドデータのコピー(現在の通貨ペア・時間軸)
    int copied = CopySpread(_Symbol, _Period, 0, lookback, spreadArray);

    if(copied < lookback)
    {
        Print("スプレッドデータの取得に失敗しました。");
        return false;
    }

    // 平均スプレッドの算出
    double sum = 0;
    for(int i = 0; i < copied; i++)
    {
        sum += spreadArray[i];
    }
    double avgSpread = sum / copied;

    // 現在のスプレッドを取得(最新の足のスプレッド)
    int currentSpread = spreadArray[0];

    // ロジック:現在のスプレッドが過去平均の1.5倍以内なら許可
    if(currentSpread <= avgSpread * 1.5)
    {
        PrintFormat("スプレッド正常: 現在(%d) / 平均(%.1f)", currentSpread, avgSpread);
        return true;
    }
    else
    {
        PrintFormat("スプレッド拡大中につき待機: 現在(%d) / 平均(%.1f)", currentSpread, avgSpread);
        return false;
    }
}

void OnTick()
{
    if(IsSpreadNormal())
    {
        // ここにエントリーロジックを記述
    }
}

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

1. 単位は「ポイント」である

初心者が最も陥りやすい罠は、単位の勘違いです。CopySpreadで取得できる「10」という値は、多くの5桁ブローカーにおいて「1.0 pips」を意味します。_Digits_Pointを用いて、自身の計算ロジックがpips単位なのかポイント単位なのかを明確に区別してください。

2. ArraySetAsSeriesを忘れない

デフォルトの配列は古いデータから順に並んでいます([0]が最も古い)。EA開発で「[0]を最新の足」として扱いたい場合は、必ず ArraySetAsSeries(spreadArray, true) を実行してください。これを忘れると、10本前の古いスプレッドを最新だと誤認して判定してしまいます。

3. ヒストリーデータの未ロード

MT5を起動した直後などは、過去のスプレッドデータがローカルPCにダウンロードされていない場合があります。このとき、CopySpread-1 を返すか、あるいは少ない個数しか返しません。実戦では必ず戻り値を確認し、必要な個数が取得できていない場合は処理をスキップするガードコードを入れてください。


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

どれほど高度なアルゴリズムでスプレッドを監視していても、エントリー信号を出してから注文が証券会社のサーバーに届くまでに時間がかかってしまえば、その間にスプレッドは変化し、有利な価格は逃げてしまいます。特に日本国内の自宅PCから海外の取引サーバー(ロンドンやニューヨーク)へ注文を出す場合、物理的な距離による通信遅延(ネットワークレイテンシ)は避けられず、数百ミリ秒の遅れが発生します。この遅延は、スキャルピングや高頻度取引においては致命的な損失要因となります。

プロのクオンツエンジニアが環境構築において最優先するのは、ロジック以上に「ブローカーの取引サーバーとの物理的な近さ」です。取引サーバーと同じデータセンター内、あるいは至近距離に設置された専用のVPS(仮想専用サーバー)を利用することで、遅延を数ミリ秒単位まで抑えることが可能になります。約定スピードの極限までの追求は、勝率を数%底上げするのと同等、あるいはそれ以上の価値をトレード収益にもたらします。安定した収益を目指すのであれば、インフラへの投資を惜しまず、最適なVPS環境を整えることがエンジニアとしての第一歩です。

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

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

コメント

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