MQL4のGlobalVariableSet/Getの記事では、

「値が0なのか、それとも変数自体が存在しないのか区別できない」

という罠と、「消し忘れたグローバル変数が別のEAに影響する」

という罠を紹介しました。

MQL5のグローバル変数は基本的な考え方はMQL4と同じですが、

この2つの罠のうち1つ目を直接解決する関数と、

複数のEAが同じグローバル変数を同時に書き換える「競合」を防ぐための、

専用関数が追加されています。

この記事では、その差分に絞って解説します。

罠1の解決: GlobalVariableGetのbool版オーバーロード

MQL4の`GlobalVariableGet(name)`は、

値そのものを`double`で返す一方、変数が存在しない場合も`0`を返すため、

「値が本当に0なのか、そもそも変数がないのか」を戻り値だけでは区別できませんでした。

MQL5には、この問題を解決する2つ目の書式が用意されています。

bool GlobalVariableGet(const string name, double &value);

戻り値の`bool`で成功・失敗が分かり、

取得できた値は参照渡しの`value`に格納されます。

double result;
if(GlobalVariableGet("LastEntryPrice", result))
   Print("取得成功: ", result);
else
   Print("グローバル変数が存在しません。エラーコード=", GetLastError());

従来の`GlobalVariableCheck()`と組み合わせる方法、

(MQL4の記事で紹介した方法)ももちろん使えますが、

このbool版は1回の呼び出しで存在確認と値取得を同時に行えるため、

コードがシンプルになります。

MQL5独自の機能: GlobalVariableSetOnConditionで競合を防ぐ

複数のEAが同じグローバル変数を「使用中フラグ」のように使う場合、

MQL4の`GlobalVariableSet()`には、

「読んで確認してから書く」という2ステップの間に、

別のEAが割り込んで値を書き換えてしまう競合のリスクがあります。

MQL5には、この読み取りと書き込みを1回の呼び出しで不可分に行う、

`GlobalVariableSetOnCondition()`が用意されています。

bool GlobalVariableSetOnCondition(const string name, double value, double check_value);

「現在の値が`check_value`と一致する場合にだけ、

`value`に書き換える」という条件付き更新です。

一致しなければ何もせず`false`を返すため、

「フラグが空いているときだけロックを取得する」という排他制御を、

安全に実装できます。

//フラグの初期値は0(未使用)とする
if(GlobalVariableSetOnCondition("EA_TradeLock", 1, 0))
  {
   Print("ロックを取得しました。取引処理を開始します。");
   //--- 取引処理 ---
   GlobalVariableSet("EA_TradeLock", 0);//処理完了後は必ず解放する
  }
else
  {
   Print("他のEAがロックを保持中のため、今回は処理をスキップします。");
  }

MQL4の`GlobalVariableSet()`だけでこれを再現しようとすると、

確認と設定の間に必ず隙間ができてしまいますが、

`GlobalVariableSetOnCondition()`は、

その隙間自体をなくす設計になっています。

MQL5独自の機能: GlobalVariableTempで終了時に自動削除する

通常のグローバル変数はターミナルを閉じてもディスクに保存され、

次回起動時にも残り続けます。

これがMQL4の記事で紹介した「消し忘れ」の罠につながっていました。

MQL5の`GlobalVariableTemp()`は、

ディスクに保存されない一時的な変数を作成します。

bool GlobalVariableTemp(const string name);

ターミナルを終了すると自動的に消えるため、

「このEAが起動している間だけ有効なフラグ」のような用途では、

消し忘れの心配なく使えます。

if(!GlobalVariableCheck("EA_SessionFlag"))
  {
   GlobalVariableTemp("EA_SessionFlag");//このターミナルが起動している間だけ有効
   GlobalVariableSet("EA_SessionFlag", 1);
  }

実際に動くコード全体

bool版GlobalVariableGetでの安全な値取得、

GlobalVariableSetOnConditionでの排他ロック、

GlobalVariableTempでの一時変数を、それぞれ試せる、

実際にMetaEditorでコンパイルできるスクリプトです。

//+------------------------------------------------------------------+
//|                                    GlobalVariableMql5Demo.mq5     |
//|                     Copyright 2026, FX-EA System Project Creator |
//|                        https://creator.fx-ea-system-project.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, FX-EA System Project Creator"
#property link      "https://creator.fx-ea-system-project.com/"
#property version   "1.00"
#property script_show_inputs

//+------------------------------------------------------------------+
//| bool版GlobalVariableGetで、値0と未設定を確実に区別する              |
//+------------------------------------------------------------------+
void DemoSafeGet()
  {
   double result;
   if(GlobalVariableGet("LastEntryPrice", result))
      PrintFormat("LastEntryPrice=%.5f (取得成功)", result);
   else
      Print("LastEntryPriceは未設定です。エラーコード=", GetLastError());
  }

//+------------------------------------------------------------------+
//| GlobalVariableSetOnConditionで排他ロックを取得・解放する            |
//+------------------------------------------------------------------+
void DemoLock()
  {
   if(!GlobalVariableCheck("EA_TradeLock"))
      GlobalVariableSet("EA_TradeLock", 0);//未作成なら未使用状態で初期化

   if(GlobalVariableSetOnCondition("EA_TradeLock", 1, 0))
     {
      Print("ロックを取得しました。取引処理(想定)を実行します。");
      GlobalVariableSet("EA_TradeLock", 0);//処理完了後は必ず解放する
     }
   else
     {
      Print("他のEAがロックを保持中のため、今回はスキップします。");
     }
  }

//+------------------------------------------------------------------+
//| GlobalVariableTempで、ターミナル終了時に自動削除される変数を作る    |
//+------------------------------------------------------------------+
void DemoTemp()
  {
   if(!GlobalVariableCheck("EA_SessionFlag"))
     {
      GlobalVariableTemp("EA_SessionFlag");
      GlobalVariableSet("EA_SessionFlag", 1);
      Print("EA_SessionFlagを一時変数として作成しました(保存されません)。");
     }
   else
     {
      Print("EA_SessionFlagは既に存在します。");
     }
  }

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   DemoSafeGet();
   DemoLock();
   DemoTemp();
  }
//+------------------------------------------------------------------+

MetaEditorで実際に動かす手順

  1. MetaTrader 5の「ツール」→「MetaQuotes Language Editor」でMetaEditorを開く
  2. 「ファイル」→「新規作成」→「スクリプト」を選び、名前を「GlobalVariableMql5Demo」にして作成する(中身は空のテンプレートで構いません)
  3. テンプレートの中身を全て削除し、上のコードを丸ごと貼り付ける
  4. F7キー(またはコンパイルボタン)でコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
  5. チャートへドラッグ&ドロップし、「エキスパート」タブに3つのデモ関数それぞれの実行結果が表示されることを確認する。2回目に実行すると、DemoSafeGetとDemoTempの結果が変わる(値が既に存在する状態になる)ことも合わせて確認する

コピペしてコンパイルが通らない・想定と違う結果になるときに確認すること

  • `GlobalVariableGet`でエラーが出る: 引数を1つ(`GlobalVariableGet(name)`)にするか2つ(`GlobalVariableGet(name, value)`)にするかで戻り値の型が異なる。参照渡しの`value`は`double`型の変数でなければならない
  • `GlobalVariableSetOnCondition`が常に`false`を返す: `check_value`に渡した値が、実際の現在値と一致しているか確認する。初回実行前に変数自体が存在しない場合は先に`GlobalVariableSet()`で初期化しておく必要がある
  • `GlobalVariableTemp`で作った変数が、次回ターミナル起動時にも残っている: 一時変数は「ターミナルを完全終了した場合」に消える仕様であり、EAやスクリプトの再実行、チャートの再読み込み程度では消えない
  • 複数のEAで排他ロックを試したのに競合が起きる: ロック変数名(`”EA_TradeLock”`等)を、排他制御したい全てのEAで完全に一致させているか確認する

まとめ

MQL4のグローバル変数には、「値0と未設定の区別が付かない」

「消し忘れが残り続ける」という2つの罠がありました。

MQL5では、bool版の`GlobalVariableGet()`で1つ目の罠を、

`GlobalVariableTemp()`で2つ目の罠を、

それぞれ直接解決できます。

さらに複数のEAが同じ変数を取り合う場面では、

`GlobalVariableSetOnCondition()`による排他制御で、

上書き事故を防ぐ設計にしてください。

関連記事