【超入門】MQL5 EA講座 第124回「OnTimer関数について」【EAの作り方】

MQL5でEA作ろう講座
スポンサーリンク
スポンサーリンク

はじめに:OnTimer関数について

ここしばらくは、ずっと時間情報を管理・操作をする為の講座内容が続いていました↓

時間情報の管理・操作については、突き詰めていけばそれこそ無限に掘り下げていける奥深い領域ではありますが、いつまでも続けている訳にはいかないので一旦この辺にしておきましょう。

が!最後の最後に、時間情報の管理・操作に関連するイベントハンドラーであるOnTimer関数という関数について触れてからにしたいと思います。

改めて復習:イベントハンドラーとは?

OnTimer関数について触れる前に、改めてここで一度「そもそもイベントハンドラーとは何か?」という部分をおさらいしておきましょう(この講座もだいぶ長丁場になってきましたからね・・・)

イベントハンドラーとは

event=出来事 handler=処理・扱うもの

すなわち、特定の出来事が起こるたびに実行される関数のことを指します。

今までに取り上げてきた中だと、OnTick関数OnStart関数OnInit関数OnDeinit関数などがイベントハンドラーにあたります。

<参照>

OnTick関数であれば値動きの変化をイベントと捉え、その度に処理が実行されますし、

OnInit関数であればMT5のチャートにプログラムファイルが挿入された事をイベントとして捉え、それをきっかけに処理を実行する・・・といった具合です。

そしてこれまでの講座記事では基本的にOnTick関数OnInit関数しか使っていませんでした。

EAというのは、自動売買プログラムな訳ですから、価格の変動に対するアクションに反応するよう設計されることは自然な事ですし、今後も主要な記述はOnTick関数の{}内に記述していく事に変わりはないでしょう。

その一方で、OnTick関数は言い換えれば「価格の変動がなければ処理を実行しない」とも言えますから、価格の変動を待たずに実行させたい処理がある場合は、別のイベントハンドラーを用いる必要があります。

今回解説するOnTimer関数もその1つです。

OnTimer関数の役割・働き

OnTick関数が、価格変動が受信されたときにのみ実行されるのに対し、

OnTimer関数は、任意に指定する「X秒」ごとに実行することができる関数=イベントハンドラー)となっています。(秒数の指定方法は後程説明します)

取引戦略を「価格変動」に依存せず、定期的な間隔でアクションを実行させたい場合は、そのコードを OnTimer関数の{}内に記述すればよい、という事になります。

OnTimer関数の引数と戻り値について

void  OnTimer(void);

上記のOnTimer関数に関する定義を見てもらえばわかる通り、OnTimer関数引数を取りません。

したがって、特定のパラメーターを入力せずに{}内に指定間隔ごとに実行してほしい処理を記述していけば大丈夫です。

またOnTimer関数戻り値も持たないvoid型です。直接的な出力値を生成せず、{}内に記述された処理のみをおこないます。

OnTimer関数を使ったサンプルコードを作成するためのロードマップ

これからOnTimer関数の使い方を理解するためのサンプルコードを作っていきます。

サンプルコードの全体は以下のようになっています。

// OnInit関数でタイマーを1秒間隔で設定します
int OnInit() {
    Comment("");  // コメントをクリア
    EventSetTimer(1);  // 1秒ごとにタイマーイベントを生成
    
    return(INIT_SUCCEEDED);
}

// OnTimer関数でタイマーイベントが発生するたびに呼ばれます
void OnTimer() {
    datetime serverTime = TimeCurrent();  // サーバーの現在時刻を取得

    // サーバー時刻をコンソールに出力
    Print("サーバーの現在時刻: ", TimeToString(serverTime, TIME_DATE|TIME_MINUTES));
}


// ファイルがチャートから削除される時に実行される関数
void OnDeinit(const int reason) {
    EventKillTimer();  // タイマーを停止します

    // チャートから削除されたことをユーザーに通知
    if (reason == REASON_REMOVE) {
        Comment("このエキスパートアドバイザーはチャートから削除されました。");
        
    
        
    }
}

上記のコードは以下のような手順を踏んで記述していきます。

手順1:OnInit関数内にEventSetTimer関数を記述し、タイマーイベントを設定する。

手順2:OnTimer関数内に実行したい処理を記述する

手順3:OnDeinit関数内にEventKillTimer関数を記述し、タイマーイベント削除設定をする。

順を追って見ていきましょう

手順1:OnInit関数内にEventSetTimer関数を記述し、タイマーイベントを設定する。

// OnInit関数でタイマーを1秒間隔で設定します
int OnInit() {
    Comment("");  // コメントをクリア
    EventSetTimer(1);  // 1秒ごとにタイマーイベントを生成
    
    return(INIT_SUCCEEDED);
}

OnTimer関数はそれ単体で使えるものではありません。「どのくらいの間隔で処理を実行するか」という設定をOnInit関数内でおこないます。

OnInit関数内は、プログラムの初期化段階で実行されるため、設定に関連する記述を行うにはもっとも都合が良いイベントハンドラーになります。

冒頭の、

Comment(“”);

Comment関数に空の文字列引数に記述しています。このような記述を行うと、チャートに以前のコメントが残っていた場合にそのコメントを消去してくれます。

「どのくらいの間隔で処理を実行するか」という設定はEventSetTimer関数という関数を使います。

EventSetTimer関数引数に、定期実行したい間隔を「秒」単位で指定します。今回は1秒ごとに処理を行いたいので引数に「1」と記述しました。

EventSetTimer(1);

EventSetTimer関数についての詳細は↓の記事をご参照ください

なお、今回はタイマー設定としてEventSetTimer関数を使いましたが、EventSetMillisecondTimer関数というミリ秒(=1/1000秒)というもっと短い間隔でタイマー設定できる関数もあります。

EventSetMillisecondTimer関数についての詳細は↓の記事をご参照ください

手順2:OnTimer関数内に実行したい処理を記述する

void OnTimer() {
    datetime serverTime = TimeCurrent();  // サーバーの現在時刻を取得

    // サーバー時刻をコンソールに出力
    Print("サーバーの現在時刻: ", TimeToString(serverTime, TIME_DATE|TIME_MINUTES));
}

続いてOnTimer関数の記述に移ります。

まずdateTime型ローカル変数「serverTime」に現在のサーバー時刻情報を代入します。

現在のサーバー時間情報を取得するにはTimeCurrent関数を使います。

TimeCurrent関数についての詳細は↓の記事をご参照ください

最後にPrint関数を使い、特定のフォーマットにてローカル変数「serverTime」の値をエキスパートログに出力しています。

EventSetTimer関数で1秒ごとにタイマーイベントを生成するようOnInit関数内に記述していますから、1秒間隔でエキスパートログに指定したメッセージが出力されることになります。

Print関数の第2引数に記述されているTimeToString関数dateTime型の情報を文字列型にタイプキャスト型変換)する関数です。

TimeToString関数についての詳細は↓の記事をご参照ください

タイプキャストについての詳細は↓の記事をご参照ください

手順3:OnDeinit関数内にEventKillTimer関数を記述し、タイマーイベント削除設定をする。

// ファイルがチャートから削除される時に実行される関数
void OnDeinit(const int reason) {
    EventKillTimer();  // タイマーを停止します

    // チャートから削除されたことをユーザーに通知
    if (reason == REASON_REMOVE) {
        Comment("このエキスパートアドバイザーはチャートから削除されました。");
        
    
        
    }
}

最後にOnDeinit関数内の記述を行います。OnDeinit関数は講座記事第7回で解説して以来、殆ど出番がありませんでしたが、MQL5 Program FileMT5のチャート上から削除された際に、一度だけ処理を行う関数です。

OnDeinit関数内にはEventKillTimer関数という関数を記述します。EventKillTimer関数引数もとらず、戻り値も返さないvoid型関数なので記述するだけで処理を実行します。

EventKillTimer関数は呼び出したタイマーイベントを安全に停止させるための関数です。

OnDeinit関数が実行されるとき、すなわちMQL5 Program FileMT5のチャート上から削除される際にタイマーが自動的に停止します。

もっとも、EventKillTimer関数が記述されていない場合、プログラムの操作の終了時に強制的に破壊されるようになっているのですが、プログラムが終了する際には、それまでに使用していたリソースを適切に解放することが一般的なプログラミングの慣習となっています。

よって、OnInit関数で設定したタイマーは、終了する際にOnDeinit関数で停止させる事によって不要なタイマーがシステム資源を消費し続けることを防ぎます。

EventKillTimer関数についての詳細は↓の記事をご参照ください

その下の記述

if (reason == REASON_REMOVE)

についてですが、まずreasonという引数OnDeinit関数で定義されている引数です。

OnDeinit(const int reason) 

constという修飾子をつける事によって、値を定数化させています。

※constについての詳細は↓

MQL5 EA講座 第17回「定数(Constant)について」をご覧ください。

講座記事第7回OnDeinit関数について解説した際には、初心者の方を混乱させてしまうと思い、あえて触れなかったのですが、この「reason」には「プログラムが終了した理由」を事前に定数化した値が格納される仕様になっています。

REASON_REMOVEというのは、その定数の1つでありプログラム終了の理由が「プログラムがチャートから削除された」場合に返ってくる定数となります。

つまり

  if (reason == REASON_REMOVE) {
        Comment("このエキスパートアドバイザーはチャートから削除されました。");
        

↑は「もしプログラム終了の理由が『プログラムがチャートから削除された』場合であればComment関数を使い、チャート上にコメント表示する」

と読み解けます。

REASON_REMOVE以外にもreasonにはプログラム終了終了理由が格納されることがあります。

興味ある方は↓の「初期化解除の理由コード」に関する記事もご参照ください

まとめ

今回はOnTimer関数について解説しました。

OnTimer関数とは、任意に指定する「X秒」ごとに実行することができるイベントハンドラーです。

今後もEAの記述の大半はOnTick関数 に記述していくことに変わりはないでしょう。

その一方でOnTick関数は「価格の変動がなければ処理を実行しない」ので、価格の変動を待たずに実行させたい処理がある場合は定期的な間隔で処理を実行できるOnTimer関数を使うのは有効な選択肢と言えます。

OnTimer関数を使いこなせるようになる事でEA開発だけでなく、カスタムインジケ-タ開発にも応用が利くようになります。

ただし、OnTimer関数は単体で使える訳ではありません。

まず「どのくらいの間隔で処理を実行するか」という設定をOnInit関数内でおこないます。

「どのくらいの間隔で処理を実行するか」という具体的な設定にはEventSetTimer関数という関数を使います。

※詳細は当記事の「手順1:OnInit関数内にEventSetTimer関数を記述し、タイマーイベントを設定する。」セクションをご覧ください。

また、プログラムファイルをMT5のチャート上から削除する際に、タイマーイベントを停止させる処理も必要になります。

この処理は、OnDeinit関数内にはEventKillTimer関数という関数を記述する事によって実現します。

※詳細は当記事の「手順3:OnDeinit関数内にEventKillTimer関数を記述し、タイマーイベント削除設定をする。」セクションをご覧ください。

今回は以上とさせていただきます。

最後までお読みいただきありがとうございました。

<参照>

OnTick関数/OnStart関数/OnInit関数/OnDeinit関数/イベントハンドラー/EventSetTimer関数/EventSetMillisecondTimer関数/TimeCurrent関数/タイマーイベント/EventKillTimer関数/初期化解除の理由コード

MQL5 EA講座 第123回「トレードタイマークラスを実装する-その5-」

MQL5 EA講座 第125回「EA開発用のテンプレートを作る-その1-」

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