EAを再起動しても状態を引き継ぐ方法|MQL5のグローバル変数
EAが、チャートを閉じた時やMT5・VPSの再起動の時に、それまで数えていた値(今日の取引回数など)を忘れるのは、EAの変数がメモリの中だけにあるためです。再起動しても続きから動かすには、値をMT5の外(ディスク)に残して、OnInitで読み戻す作りにします。手軽なのはMT5のグローバル変数(端末に保存される名前付きの数値)で、MQL5リファレンスによると、最後に使ってから4週間保存されます。ポジションのように取引サーバーにあるものは、残すより読み直す方が確実です。
この記事では、EAが状態を失う場面、残し方の選び方、グローバル変数を使う例(0エラー・0警告でコンパイル確認)、気をつける点をまとめます。
(確認:MQL5リファレンス「グローバル変数」「GlobalVariableSet」「TimeCurrent」。確認日:2026年10月10日。サンプルは MetaEditor でコンパイル確認。口座での実行は、この記事では行っていません)
EAが状態を失う場面
MQL5リファレンス「プログラム実行」によると、EAは次の場合にアンロードされます。アンロードされると、次に読み込まれた時は、EAの変数は初期値から始まります。
- チャートからEAを外した、同じチャートに別のEAを入れた、チャートを閉じた(閉じたチャートを元に戻す方法)
- 端末(MT5)を終了した。MT5の再起動・自動アップデート・VPSやPCの再起動もこれに当たる(MT5の自動アップデートでEAが止まる、Windows Updateの再起動でMT5のEAが止まる)
- 定型チャートを読み込んだ、プロファイルを切り替えた(MT5のプロファイルの使い方)
ExpertRemove()を呼んだ(MQL5のExpertRemove)
一方、チャートの銘柄や時間足を変えた時は、EAはアンロードされません。OnDeinitとOnInitが呼ばれますが、グローバル変数と静的変数の値はリセットされない、とリファレンスに書かれています。OnInitで変数を毎回0に戻す書き方にしていると、ここで値を消してしまうことがあります。終了の理由ごとの見分け方はMQL5のOnDeinitの終了理由にまとめています。
何を、どこに残すか
| 状態の種類 | おすすめの方法 | 理由 |
|---|---|---|
| 保有中のポジション・未決注文 | OnInitで口座から読み直す(PositionsTotal など) | 取引サーバーにあり、MT5を再起動しても消えない |
| 今日の取引回数・決済した回数 | 口座の履歴から数え直す(HistorySelect など)か、グローバル変数 | 履歴もサーバーから取れる。数え方が複雑ならグローバル変数が手軽 |
| EAだけが知っている値(最後に判断した時刻、段階など) | グローバル変数、またはファイル | 口座からは読み直せない |
| 文字列や、たくさんの値 | ファイル(FileWrite など) | グローバル変数は数値(double)だけ |
ファイルへの書き方はMQL5でCSVを出力する方法、読み方はMQL5でCSVを読み込む方法にあります。ポジションの決済の書き方はMQL5でポジションを決済する方法です。
グローバル変数の性質(MQL5リファレンス)
- クライアント端末に保存される、名前付きの数値。MQL5のプログラムの中で宣言するグローバル変数とは別物
- 最後にアクセスしてから4週間保存され、その後は自動で削除される(読み込みもアクセスに含まれる)
- 名前は63文字まで
- 端末で動いているすべてのMQL5プログラムから同時にアクセスできる
GlobalVariablesFlush()で、すぐにディスクへ保存できる。GlobalVariableTemp()で作った変数は、端末の今のセッションの間だけ存在する
例:今日の取引回数を、再起動しても引き継ぐ
1日の取引回数に上限があるEAで、回数をグローバル変数に残す例です。日付が変わったら0に戻します。日付の判断は、VPSの時計に左右されないよう、サーバー時刻(TimeCurrent)を使っています(理由はVPSの時計とEAの時刻)。
// EAの状態(今日の取引回数)を、端末のグローバル変数に残して、再起動後に読み戻す例
input int InpMaxTradesPerDay = 3; // 1日の取引回数の上限
string g_keyCount; // グローバル変数の名前(回数)
string g_keyDay; // グローバル変数の名前(数えている日)
int g_count = 0; // 今日の取引回数
// 名前に口座番号と銘柄を入れて、他の口座や銘柄のEAとぶつからないようにする
string MakeKey(const string what)
{
return StringFormat("EA_%I64d_%s_%s", AccountInfoInteger(ACCOUNT_LOGIN), _Symbol, what);
}
// サーバー時刻の「日付」(0時0分0秒)を返す
datetime TodayServer()
{
MqlDateTime t;
TimeToStruct(TimeCurrent(), t);
t.hour = 0; t.min = 0; t.sec = 0;
return StructToTime(t);
}
int OnInit()
{
g_keyCount = MakeKey("count");
g_keyDay = MakeKey("day");
// 保存してある日付が今日なら、回数を読み戻す。違う日なら0から数える
double savedDay = 0.0, savedCount = 0.0;
if(GlobalVariableGet(g_keyDay, savedDay) && (datetime)savedDay == TodayServer()
&& GlobalVariableGet(g_keyCount, savedCount))
g_count = (int)savedCount;
else
g_count = 0;
PrintFormat("再開時の今日の取引回数: %d", g_count);
return INIT_SUCCEEDED;
}
// 取引したら呼ぶ(この例では、注文の処理は省略している)
void CountTrade()
{
g_count++;
GlobalVariableSet(g_keyDay, (double)TodayServer());
GlobalVariableSet(g_keyCount, g_count);
GlobalVariablesFlush(); // すぐにディスクへ書き出す
}
void OnTick()
{
// 日付が変わったら、回数を0に戻す
double savedDay = 0.0;
if(!GlobalVariableGet(g_keyDay, savedDay) || (datetime)savedDay != TodayServer())
{
g_count = 0;
GlobalVariableSet(g_keyDay, (double)TodayServer());
GlobalVariableSet(g_keyCount, 0);
}
if(g_count >= InpMaxTradesPerDay)
return; // 今日の上限に達したので、新しい取引はしない
// ここで売買の条件を判断し、注文が成功したら CountTrade() を呼ぶ
}
注文の処理そのものは省いています。注文が成功した時にCountTrade()を呼ぶ形で組み込みます。
気をつけること
- 名前がぶつからないようにする:グローバル変数は、同じ端末のすべてのプログラムから見えます。同じEAを複数のチャートで動かすなら、銘柄やマジックナンバーを名前に入れて分けます
- 4週間で消える:長く止めていたEAを再開すると、値が消えていることがあります。値がない時の扱い(0から始める、など)を決めておきます
- 別のPC・VPSへ移すと、引き継がれない:グローバル変数は、その端末に保存されています。移した直後は、値がない前提で動くようにします(移し方はMT5の設定とEAを別のPC・VPSへ移す手順)
- 口座から読み直せるものは読み直す:保存した値と、実際の口座の状態が食い違った時は、口座の方が正しい
- テストでは、ストラテジーテスターでの動き(グローバル変数の扱い)も確かめてから使います。この記事では、テスターでの挙動は確認していません
まとめ
- EAの変数はメモリの中だけにある。チャートを閉じる・再起動で、初期値に戻る
- ポジションや履歴は、OnInitで口座から読み直す。EAだけが知っている値は、グローバル変数かファイルに残す
- グローバル変数は、最後のアクセスから4週間で消える・全プログラムから見える。名前と、値がない時の扱いを決めておく
EAが動き続けているかの確認はMT5でEAが動いているかを確認する方法、再起動後にMT5を自動で立ち上げる方法はMT5を自動で起動する方法にあります。
本記事はプログラミングの説明であり、特定の売買を推奨するものではありません。


