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で実際に動かす手順
- MetaTrader 5の「ツール」→「MetaQuotes Language Editor」でMetaEditorを開く
- 「ファイル」→「新規作成」→「スクリプト」を選び、名前を「GlobalVariableMql5Demo」にして作成する(中身は空のテンプレートで構いません)
- テンプレートの中身を全て削除し、上のコードを丸ごと貼り付ける
- F7キー(またはコンパイルボタン)でコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
- チャートへドラッグ&ドロップし、「エキスパート」タブに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()`による排他制御で、
上書き事故を防ぐ設計にしてください。
コメント