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

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

MQL5のGlobalVariableSetOnConditionは、指定したグローバル変数の値が「特定の数値である場合のみ」新しい値を上書きする関数です。プログラミング用語でいうところの「Compare-and-Swap (CAS)」操作にあたります。

実務レベルのEA開発において、この関数は「排他制御(ミューテックス)」を実現するために不可欠です。

例えば、複数の通貨ペアで同じEAを動かしている際、「同時に2つ以上のポジションを持ちたくない」あるいは「共通の資金管理用フラグを書き換えたい」という場面があります。単なるGlobalVariableSetでは、複数のEAがほぼ同時に書き込みを行った際、意図しない値の上書き(レースコンディション)が発生し、システムが暴走する原因となります。

この関数を使うことで、「もしフラグが0(空き)なら、1(使用中)に変える」という処理を、他のEAに割り込まれることなくアトミック(不可分)に実行できるため、安全なマルチタスク処理が可能になります。

2. 構文と戻り値

関数の構文は以下の通りです。

bool GlobalVariableSetOnCondition(
   string name,        // グローバル変数名
   double value,       // 条件一致時にセットする新しい値
   double check_value  // 現在の値と比較する条件値
);

パラメーター

  • name: 操作したいターミナル・グローバル変数の名前です。
  • value: 条件が一致したときに新しく設定したい数値を指定します。
  • check_value: 現在のグローバル変数の値が「この値であること」を条件とします。

戻り値

  • true: 現在の値がcheck_valueと一致し、無事にvalueへ書き換えられた場合。
  • false: 現在の値がcheck_valueと異なっていた場合、またはエラーが発生した場合。

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

以下の例は、複数のEA間で「注文処理の重複」を防ぐためのロック機構(排他制御)を実装したサンプルです。

// 共通のロック用変数名
const string LOCK_NAME = "Order_Sync_Lock";

void OnTick()
{
    // 1. ロック用変数が存在しない場合は作成(初期値は0: 未使用)
    if(!GlobalVariableCheck(LOCK_NAME))
    {
        GlobalVariableTemp(LOCK_NAME); // ターミナル再起動で消える一時変数として作成
        GlobalVariableSet(LOCK_NAME, 0);
    }

    // 2. ロックを取得(現在値が 0 なら 1 に書き換える)
    // これにより、他のEAはこの瞬間からロックを取得できなくなる
    if(GlobalVariableSetOnCondition(LOCK_NAME, 1, 0))
    {
        Print("ロック取得成功:注文処理を開始します。");

        // --- ここに注文処理や重要な計算を記述 ---
        // 例: OrderSend(...) など

        Sleep(100); // 処理時間をシミュレート

        // --- 処理終了 ---

        // 3. ロックを解放(値を 0 に戻す)
        if(!GlobalVariableSet(LOCK_NAME, 0))
        {
            Print("エラー:ロック解放に失敗しました。");
        }
        else
        {
            Print("ロック解放成功。");
        }
    }
    else
    {
        // 他のEAが処理中の場合は、ここに到達する
        Print("待機中:他のEAが注文処理を実行しています...");
    }
}

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

グローバル変数の事前存在が必須

GlobalVariableSetOnConditionは、既に対象の変数が存在していないと動作しません。 変数が存在しない状態で実行すると、単に false を返し、エラーコード ERR_GLOBAL_VARIABLE_NOT_FOUND (4501) が生成されます。必ず GlobalVariableCheck などで存在を確認し、なければ作成する処理を入れてください。

型の精度問題

引数は double 型です。基本的には整数値(0や1)をフラグとして使うのが安全です。非常に細かい小数点を含む数値を check_value に指定すると、浮動小数点誤差によって「一致しているはずなのに false になる」という現象が起きる可能性があります。

デッドロックの回避

ロックを取得した後にEAがエラーで停止したり、GlobalVariableSet(name, 0) を忘れたりすると、その変数は「使用中(1)」のまま残り続けます。すると、他のすべてのEAが永遠に処理待ち(デッドロック)になってしまいます。エラーハンドリングを行い、確実に値を戻す設計を心がけましょう。

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

アルゴリズムトレードにおいて、GlobalVariableSetOnConditionのようなコードレベルの最適化以上に重要なのが、「物理的な実行環境」です。市場の価格は1ミリ秒(1000分の1秒)単位で変動しており、EAがいかに正確なロジックでシグナルを出しても、ブローカーのサーバーに注文が届くまでの「ネットワーク遅延(レイテンシ)」が大きければ、スリッページによって期待した利益は削り取られます。

特に自宅のPC環境での稼働は、ネットワーク経路の不安定さやOSの更新による予期せぬ再起動など、自動売買において致命的なリスクを孕んでいます。プロのクオンツエンジニアが共通して認めるのは、「VPS(仮想専用サーバー)の利用は、もはやコストではなく必要経費である」ということです。取引サーバーに近いロケーションのVPSを選択し、24時間365日、低遅延かつ安定した環境でEAを稼働させることが、安定した収益曲線を描くための絶対条件となります。

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

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

コメント

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