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

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

MQL5のOnTimerは、指定した時間間隔(秒単位またはミリ秒単位)で定期的に実行される「タイマーイベント」を処理するための関数です。

通常、EA(エキスパートアドバイザー)は価格が動いた瞬間(ティック受信時)にOnTick関数が動くことで動作します。しかし、相場のボラティリティが低い時間帯や、土日のメンテナンス時など、価格が全く動かない状況ではOnTickは一切実行されません。

実務開発において、OnTimerは以下のようなケースで非常に重宝されます。
* 画面表示の更新: ティックが来なくても、チャート上のパネルや残り時間をリアルタイムに更新したい場合。
* 定時処理: 「日本時間の午前9時に特定の処理を行う」など、価格の動きに関係なく時刻ベースでロジックを動かしたい場合。
* 監視機能: オーダーの有効期限のチェックや、サーバーとの通信状態の定期的確認。

初心者の方は「とりあえずOnTickに全部書けばいい」と思いがちですが、価格変動に依存しないロジックをOnTimerに分離することで、プログラムの信頼性とユーザー体験(UIのレスポンスなど)が劇的に向上します。

2. 構文と戻り値

OnTimer関数の基本構文は非常にシンプルです。

void OnTimer();
  • 型: void(戻り値なし)
  • パラメーター: なし
  • 実行の条件:
    1. OnInit関数内でEventSetTimer(秒)またはEventSetMillisecondTimer(ミリ秒)を呼び出し、タイマーを起動していること。
    2. 設定した時間が経過するごとに、MT5ターミナルから自動的に呼び出されます。

注意点として、OnTimerを使用する際は、EAがチャートから削除される際(OnDeinit内)に、必ずEventKillTimer()を呼び出してタイマーを停止させるのがMQL5の作法です。

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

以下のコードは、1秒ごとに動作し、現在のサーバー時刻をチャート上に表示するとともに、特定の時刻になったらアラートを鳴らす実用的なサンプルです。

//+------------------------------------------------------------------+
//|                                              TimerExampleEA.mq5 |
//+------------------------------------------------------------------+
#property strict

//--- 初期化関数
int OnInit()
{
    // 1秒ごとにOnTimerイベントを発生させる設定
    if(!EventSetTimer(1))
    {
        Print("タイマーの初期化に失敗しました。");
        return(INIT_FAILED);
    }

    return(INIT_SUCCEEDED);
}

//--- 終了処理関数
void OnDeinit(const int reason)
{
    // EA終了時には必ずタイマーを破棄する
    EventKillTimer();
}

//--- タイマーイベント関数(1秒ごとに実行される)
void OnTimer()
{
    // サーバー時刻を取得
    datetime now = TimeCurrent();
    string timeStr = TimeToString(now, TIME_DATE|TIME_SECONDS);

    // チャートの左上に現在の時刻を表示(ティックがなくても更新される)
    Comment("現在のサーバー時刻: " + timeStr + "\n" +
            "この表示は価格変動に関係なく1秒ごとに更新されます。");

    // 実践例:特定の時間(例:サーバー時間 10:00:00)にログを出力
    MqlDateTime dt;
    TimeToStruct(now, dt);

    if(dt.hour == 10 && dt.min == 0 && dt.sec == 0)
    {
        Print("指定時刻になりました。ロジックを実行します。");
        // ここにエントリーや決済のロジックを記述可能
    }
}

//--- ティック受信関数(価格が動いた時だけ実行される)
void OnTick()
{
    // 通常のロジックはここ
}

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

開発において陥りやすいポイントがいくつかあります。

  1. タイマーの重複に注意: EventSetTimerを複数回呼び出すと、最後に設定した時間間隔に上書きされます。複数の異なる間隔でタイマーを動かすことは標準ではできないため、最小公倍数の秒数で設定し、OnTimer内でカウンタ変数を使って処理を振り分ける工夫が必要です。
  2. 処理の重さ: OnTimer内で非常に重い計算やループ処理を行うと、次のOnTickOnTimerの実行が遅れる原因になります。MQL5は基本的にシングルスレッドで動作するため、タイマー内の処理は簡潔に保つのが鉄則です。
  3. バックテストでの挙動: ストラテジーテスターでは、OnTimerの間隔は最小でも「1秒」に制限されます。ミリ秒単位の設定をしていても、バックテスト上では1秒単位になる点に注意してください。
  4. EventKillTimerの忘れ: タイマーを止め忘れても致命的なクラッシュは稀ですが、リソース管理の観点から必ずOnDeinitに記述する癖をつけましょう。

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

どれほど完璧なOnTimerロジックを組み上げたとしても、自動売買の世界にはエンジニアがコードだけでは解決できない「物理的な壁」が存在します。それが、実行環境におけるネットワーク遅延(レイテンシ)です。

自宅のPCや一般的なWi-Fi環境から自動売買を行う場合、FX業者の取引サーバーまでの距離が遠く、パケットの往復に数十ミリ秒から数百ミリ秒の時間を要します。この「わずかな遅れ」の間に市場価格は変動し、プログラムが意図した価格での約定を逃す「スリッページ」を引き起こします。特に指標発表時やスキャルピングロジックにおいて、自宅PCでの運用は致命的な機会損失と無駄なコストを生むリスクが非常に高いのが現実です。

プロのクオンツや勝率の高いシストレ開発者が、例外なく取引サーバーに物理的に近い場所にある専用のVPS(仮想専用サーバー)を利用するのは、この約定スピードを極限まで高めるためです。ミリ秒単位の優位性を確保し、ネットワークトラブルによる機会損失を避けることは、アルゴリズムを改善することと同等、あるいはそれ以上に収益に直結する重要な戦略と言えます。

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

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

コメント

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