1. UninitializeReason関数の概要と実務での活用法
MQL5の UninitializeReason() は、EA(エキスパートアドバイザー)やインジケーターが終了(終了処理:OnDeinit)した「理由」を特定するための関数です。
FXの自動売買プログラムを運用していると、チャートの時間軸を変更したり、パラメーターを書き換えたり、あるいはMetaTrader 5(MT5)自体を終了させたりといった様々な「終了イベント」が発生します。実務において、この関数が必要な理由は「終了の理由に応じて、後処理(クリーンアップ)の内容を変えたいから」に他なりません。
例えば、以下のようなケースでつまずきがちです。
– チャートからEAを削除した時だけ、作成した図形オブジェクトを消したい(時間軸変更では消したくない)。
– パラメーター変更時だけ、内部変数をリセットしたい。
– 口座の切り替え時だけ、ログに警告を出したい。
これらを区別せずに一律で終了処理を行ってしまうと、意図しないデータの消失や、描画オブジェクトの残存によるチャートの汚れを招きます。プロのクオンツエンジニアは、この関数を使いこなすことで堅牢なシステムを構築します。
2. 構文と戻り値
UninitializeReason() 関数は引数を取らず、戻り値として「終了理由コード」を整数型(int)で返します。
構文
int UninitializeReason();
主な戻り値(ENUM_UNINITIALIZE_REASON)
代表的なコードは以下の通りです。
| 定数 | 値 | 内容 |
|---|---|---|
| REASON_PROGRAM | 0 | EA自体のコードから ExpertRemove() が呼ばれた |
| REASON_REMOVE | 1 | ユーザーがチャートからEAを削除した |
| REASON_RECOMPILE | 2 | ソースコードが再コンパイルされた |
| REASON_CHARTCHANGE | 3 | チャートの通貨ペアや時間軸が変更された |
| REASON_CHARTCLOSE | 4 | チャート自体が閉じられた |
| REASON_PARAMETERS | 5 | ユーザーがパラメーター設定を変更した |
| REASON_ACCOUNT | 6 | 別の口座にログインした、またはサーバー接続が変わった |
| REASON_TEMPLATE | 7 | チャートテンプレートが適用された |
| REASON_INITFAILED | 8 | OnInitハンドラが失敗を返した |
| REASON_CLOSE | 9 | MT5ターミナル自体が終了した |
3. 具体的な使い方・実践サンプルコード
実務で最も頻繁に利用される「EA削除時のみオブジェクトを全削除する」というパターンを例に解説します。
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// 引数として渡されるreasonもUninitializeReason()と同じ値を持つ
// ここでは分かりやすく UninitializeReason() を呼び出して判定する例を示す
int deinitReason = UninitializeReason();
// 終了理由をログに出力(デバッグに非常に便利)
Print("終了理由コード: ", deinitReason);
switch(deinitReason)
{
case REASON_REMOVE:
case REASON_CHARTCLOSE:
// ユーザーがEAを明示的に消した、またはチャートを閉じた場合
Print("EAが削除されました。チャート上のオブジェクトをクリーンアップします。");
ObjectsDeleteAll(0, "MyEA_"); // プレフィックスが付いたオブジェクトのみ削除
break;
case REASON_PARAMETERS:
Print("パラメーターが変更されました。内部計算をリセットします。");
// パラメーター変更時はオブジェクトを消さず、計算状態だけ整えることが多い
break;
case REASON_CHARTCHANGE:
Print("時間軸または通貨ペアが変更されました。");
break;
case REASON_ACCOUNT:
Print("口座が変更されました。未決済注文の確認が必要です。");
break;
default:
Print("その他の理由で終了しました。コード: ", deinitReason);
break;
}
}
4. 使用上の注意点とよくあるエラー
OnDeinitの引数と関数の使い分け
OnDeinit(const int reason) の引数 reason には、既に UninitializeReason() の実行結果と同じ値が渡されています。そのため、OnDeinit 内ではわざわざ関数を呼ばず、引数 reason をそのまま使うのがスマートです。
処理時間の制約
終了処理(OnDeinit)には時間制限があります(通常は約2.5秒)。この時間内に処理が終わらない場合、システムによって強制終了されます。REASON_CLOSE(MT5終了)の際に重いファイルの書き出しや複雑な通信処理を行おうとすると、データが破損する可能性があるため注意が必要です。
実行順序の罠
特に「パラメーター変更(REASON_PARAMETERS)」の際、OnDeinit が呼ばれた直後に新しい設定で OnInit が呼ばれます。この順序を理解していないと、OnDeinit で消すべきではないグローバル変数をリセットしてしまい、EAの挙動が不安定になるバグを誘発します。
5. 【重要】自動売買における約定スピードと環境の罠
自動売買プログラムを開発する上で、ロジックと同じくらい重要なのが「実行環境」です。どれほど優れたEAを組み、UninitializeReason で完璧な終了処理を実装したとしても、自宅のPC環境から一般的なインターネット回線でトレードを行っている限り、プロのクオンツの世界では「土俵にすら立てていない」のが現実です。
自宅PCでの運用は、プロバイダー経由のネットワーク遅延(レイテンシ)が大きく、証券会社のサーバーに注文が届くまでにコンマ数秒のラグが発生します。このわずかな遅延が、相場急変時のスリッページを招き、期待収益を劇的に押し下げます。約定スピードを極限まで高め、物理的な距離による遅延を最小化するには、証券会社のサーバーと同じデータセンター内、あるいは至近距離に設置されたトレード専用のVPS(仮想専用サーバー)の利用が必須です。コンマミリ秒を争うシストレの世界では、VPSの導入は「推奨」ではなく「プロとしての最低条件」であると断言できます。
💡 この記事の内容を実運用で活かすには?
この記事の内容を実運用で活かすには、正しい環境が必要です。
特にVPSを使わないと、このロジックは再現できません。

コメント