【超入門】MQL5 EA講座 第120回「トレードタイマークラスを実装する-その2-」【EAの作り方】

MQL5でEA作ろう講座

前回トレードタイマークラスに実装するメンバ関数の第1弾として、「トレード時間かどうかをチェックする」メンバ関数IsActive関数を実装する様子を解説しました。

まずは、そもそもトレードタイマークラスとは何か?という事を解説し、IsActive関数を実装するまでの時系列的な手順について説明しました。詳しくは前回記事の

トレードタイマーとは?」セクション及び

「トレード時間かどうかをチェックする」メンバ関数実装へのロードマップ」セクションをご確認ください。

そして、ロードマップに示した手順に従い、「OriginalTimer.mqh」ファイルへトレードタイマークラス(=CTradeSessionクラス)を宣言~IsActive関数引数設定~処理実装記述までを解説していきました。

詳しくは前回記事の下記セクションをご確認ください↓

「OriginalTimer.mqh」ファイルに「トレードタイマークラス」を宣言する

アクセスレベル=publicのメンバを追加する

メンバ関数「IsActive」に必要な仮引数を設定する

メンバ関数「IsActive」に処理実装記述をおこなう

スポンサーリンク
スポンサーリンク
  1. はじめに:毎日同じ時間帯に取引できるようにする関数について
    1. アジアセッション(東京市場):
    2. ヨーロピアンセッション(ロンドン市場):
    3. 北米セッション(ニューヨーク市場):
    4. オセアニアセッション(シドニー市場):
  2. 「毎日同じ時間帯に取引できるようにする関数」実装へのロードマップ
  3. 「CTradeSession」クラス内に新しいメンバを加える
    1. メンバ「SessionStartTime」について
    2. メンバ「SessionEndTime」について
    3. DailySessionTimer関数について
  4. メンバ関数「DailySessionTimer」に必要な仮引数を設定する
    1. 第1仮引数「parStartHour」にはトレード開始時間の「時」情報が格納される想定
    2. 第2仮引数「parStartMinute」にはトレード開始時間の「分」情報が格納される想定
    3. 第3仮引数「parEndHour」にはトレード終了時間の「時」情報が格納される想定 
    4. 第4仮引数「parEndMinute」にはトレード終了時間の「分」情報が格納される想定
    5. 第5仮引数「parLocalTime」には『ローカル時間を使用するかどうか』が格納される想定
  5. メンバ関数「DailySessionTimer」に処理実装記述をおこなう
    1. 処理実装記述1:ローカル時間を使うかどうかを判断する
    2. 処理実装記述2:取引開始時間と終了時間を設定する
    3. 処理実装記述3:トレード終了時間が開始時間より前に設定されている場合の記述を行う
    4. 処理実装記述4:IsActive関数を使って、トレード時間の判定を行う
  6. 完成したDailySessionTimer関数を使ってみる
    1. OriginalTimer.mqhファイルをインクルードする
    2. CTradeSessionクラスのインスタンスを宣言
    3. 取引時間を設定するためのinput変数を宣言
    4. OnTick関数内の記述をおこなう
  7. まとめ

はじめに:毎日同じ時間帯に取引できるようにする関数について

今回は、「毎日同じ時間帯に取引できるようにする関数」CTradeSessionクラスメンバ関数に追加していく流れを解説していきたいと思います。

FX取引では、世界中の主要な金融市場が開いている時間帯によって、市場の動きにいくつかの特徴があります。一般的に言われている各市場の特徴で言うと、

アジアセッション(東京市場):

アジアセッション(東京市場)は、取引量は比較的少なく、特に日本の経済ニュースに影響を受けやすい傾向があります。
通常は比較的小さい価格変動ですが、トレンドのスタートが見られることもあります。
JPY(日本円)関連の通貨ペアが活発に動くことが多いです。

ヨーロピアンセッション(ロンドン市場):

ヨーロピアンセッション(ロンドン市場)

活発な取引が行われ、取引量が増加する傾向があります。
多くの重要な経済ニュースがこの時間に発表される事もあり、市場のボラティリティが高まります。
GBP(英ポンド)やEUR(ユーロ)関連の通貨ペアが特に活発化する事が多いです。

北米セッション(ニューヨーク市場):

取引量はこの北米セッション(ニューヨーク市場)で最も多くなり、特にヨーロピアンセッション(ロンドン市場)と重なる時間帯が最も活動的になります。
USD(アメリカドル)関連のニュースや経済データの発表によって、市場の動きが大きくなることが多いです。
ニューヨーク午後の市場のクローズに向けて取引量が徐々に減少し、価格変動も落ち着く傾向がみられます。

オセアニアセッション(シドニー市場):

オセアニアセッション(シドニー市場)アジアセッション(東京市場)の前に開始し、比較的静かな取引から始まります。
AUD(オーストラリアドル)やNZD(ニュージーランドドル)の通貨ペアがより活発になる傾向があります。

以上の事が各市場の特徴としてよく言われます。

各市場が開いている時間帯によって流動性が変わり、それに伴って価格の動きも異なります。

流動性が高い時間帯は価格のスプレッドが狭くなりやすいですが、ニュースイベントや経済データの発表によって大きな価格変動が起こることもあります。

また、時間帯によってトレーダーの戦略も変わり、例えばアジアセッションではレンジトレード、ヨーロピアンセッション(ロンドン市場)がオープン後にブレイクアウトを狙ったトレンドフォロー型のトレード、など様々なアプローチが取られます。

こうした各市場の特徴を捉えたトレード戦略戦略をエキスパートアドバイザーに実装するにあたって、今回実装予定の「毎日同じ時間帯に取引できるようにする関数」が必要になってくる、という訳です。

今回実装する「毎日同じ時間帯に取引できるようにする関数」は、第118回で作成した「GenerateTimestamp関数」(特定の日時を生成する為の独立関数)と、同じく第118回で作成した、「1分」「1時間」「1日」「1週間」に相当する経過秒数で表した定数、そして前回に作成したIsActive関数(=トレードが許可されている時間帯かどうかをチェックするメンバ関数)を組み合わせて作ります。

従って、不安な方は以下の記事リンク群を見直して頂く事をおススメいたします。

「OriginalTimer.mqh」ファイルの中に関数の宣言をする(GenerateTimestamp関数=についての説明)

アクセスレベル=publicのメンバを追加する(=IsActive関数についての説明)

「1分」「1時間」「1日」「1週間」に相当する経過秒数をdefine命令により定数として設定する

「毎日同じ時間帯に取引できるようにする関数」実装へのロードマップ

「毎日同じ時間帯に取引できるようにする関数」は以下の手順を踏んで実装していきます。

「CTradeSession」クラス内に新しいメンバを加える

メンバ関数「DailySessionTimer」に必要な仮引数を設定する

メンバ関数「DailySessionTimer」に処理実装記述をおこなう

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

「CTradeSession」クラス内に新しいメンバを加える

まずは前回作った「CTradeSessionクラスに新しいメンバを追加します。

前回までのクラス内容は以下のようになっているのですが・・・↓

class CTradeSession
{
public:
    // 取引セッションがアクティブかどうかをチェックする関数
    bool IsActive(datetime openTime, datetime closeTime, bool useLocalTime = false);
};

これを以下のように変更します↓

class CTradeSession
  {
private:
   //トレード開始時間と終了時間を格納する
   datetime          SessionStartTime, SessionEndTime;


public:
   // 取引セッションがアクティブかどうかをチェックする関数
   bool              IsActive(datetime openTime, datetime closeTime, bool useLocalTime = false);
   //毎日のトレードタイマーを作成する関数
   bool              DailySessionTimer(int parStartHour, int parStartMinute, int parEndHour, int parEndMinute, bool parLocalTime = false);
  };

アクセスレベルprivateの領域にdateTime型変数SessionStartTime」「SessionEndTime」、

そしてアクセスレベルpublicの領域に今回メインで解説する「DailySessionTimer」というメンバ関数を追加しました。このDailySessionTimer関数「毎日同じ時間帯に取引できるようにする関数」となります。

private,protected,publicなどクラスアクセスレベルについては↓

MQL5 EA講座 第50回「クラスについて3 -アクセス指定子-」

をご覧ください。

メンバ「SessionStartTime」について

メンバSessionStartTime」はトレード開始時間を格納するための変数です。

アクセスレベルprivateなのでアクセスできるのはCTradeSessionクラスメンバのみです。

トレード開始時間をどうやって取得するのか、またこの変数をどこで使うのか、という点については後程解説します。

メンバ「SessionEndTime」について

メンバSessionEndTime」はトレード終了時間を格納するための変数です。

こちらもアクセスレベルprivateなのでアクセスできるのはCTradeSessionクラスメンバのみです。

トレード終了時間をどうやって取得するのか、またこの変数をどこで使うのか、という点についても後程解説します。

DailySessionTimer関数について

DailySessionTimer関数「毎日同じ時間帯に取引できるようにする関数」となります。

アクセスレベルpublicなので、クラスの外からでもアクセス可能です。メインプログラムで記述される想定のメンバ関数となります。

引数と処理実装記述についての解説はこの後行います。

メンバ関数「DailySessionTimer」に必要な仮引数を設定する

続いてDailySessionTimer関数引数を設定していきます。

DailySessionTimer関数には5つの引数を設定します

//毎日のトレードタイマーを作成する関数
   bool DailySessionTimer(int parStartHour,
               int parStartMinute, 
               int parEndHour,
                       int parEndMinute, 
                          bool parLocalTime = false);

第1仮引数「parStartHour」にはトレード開始時間の「時」情報が格納される想定

第1引数「parStartHour」にはトレードを開始時間の「時」情報が格納される想定です。

例えば「7時24分」という時刻情報があったとして、「7時」に当たる部分ですね。

メインプログラムでinput変数として設定する事になります。

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

【広告】

第2仮引数「parStartMinute」にはトレード開始時間の「分」情報が格納される想定

第2引数「parStartMinute」にはトレードを開始時間の「分」情報が格納される想定が格納される想定です。先程の「7時24分」という時刻情報を引き続き例に使うのであれば、「24分」に当たる部分です。

「parStartHour」と同様にメインプログラムでinput変数として設定する事を想定しています。

第3仮引数「parEndHour」にはトレード終了時間の「時」情報が格納される想定 

第3引数「parEndHour」にはトレード終了時間の「時」情報が格納される想定です。

第1引数と第2引数でトレード開始時間を設定し、この第3引数と第4引数でトレード終了時刻を設定する事になります。

メインプログラムでinput変数として設定する想定なのも同様です。

第4仮引数「parEndMinute」にはトレード終了時間の「分」情報が格納される想定

第4引数「parEndMinute」にはトレード終了時間の「分」情報が格納される想定です。

他の引数と同様にメインプログラムでinput変数として設定する事になります。

第5仮引数「parLocalTime」には『ローカル時間を使用するかどうか』が格納される想定

第5引数「parLocalTime」には『ローカル時間を使用するかどうか』が格納される想定です。

データ型bool型に設定し、メインプログラムでtrueと設定した際にはローカル時間を基準としてトレード時間の設定を行い、falseの場合はサーバー時間を基準としてトレード時間の設定を行うようにしまう。

この第5引数には初期値をfalseに設定しておきます。従って、なにも記述しない場合はサーバー時間を基準としてトレード時間の設定を行う、という事になります。

初期値については↓の記事をご参照ください

メンバ関数「DailySessionTimer」に処理実装記述をおこなう

引数の設定が終わったので、今度は に処理実装記述をほどこしていきましょう

DailySessionTimer関数の全体記述は以下のようになっています。

bool CTradeSession::DailySessionTimer(int parStartHour, int parStartMinute, int parEndHour, int parEndMinute, bool parLocalTime=false)
{
    // 現在の時間を取得
    datetime currentTime;
    if(parLocalTime == true)
        currentTime = TimeLocal(); // ローカル時間を使用
    else
        currentTime = TimeCurrent(); // サーバー時間を使用

    // セッションの開始時間を設定
    SessionStartTime = GenerateTimestamp(parStartHour,parStartMinute);

    // セッションの終了時間を設定
    SessionEndTime = GenerateTimestamp(parEndHour,parEndMinute);

    // セッションの終了時間が開始時間より前に設定されている場合、終了時間を次の日に設定
    if(SessionEndTime <= SessionStartTime) 
    {
        SessionStartTime -= DAYS_TO_SECONDS; // 開始時間を一日分マイナス

        // 現在時刻が終了時間を過ぎていた場合、開始時間と終了時間を次の日にずらす
        if(currentTime > SessionEndTime)
        {
            SessionStartTime += DAYS_TO_SECONDS;
            SessionEndTime += DAYS_TO_SECONDS;
        }
    }

    // セッションがアクティブかどうかを判断
    bool timerOn = IsActive(SessionStartTime, SessionEndTime, parLocalTime);

    // タイマーの状態を出力
    Print(timerOn);

    // タイマーがオンかオフかの状態を返す
    return(timerOn);
}

上から順に分解して見ていきましょう

処理実装記述1:ローカル時間を使うかどうかを判断する

まず冒頭の記述ですが↓

// 現在の時間を取得
    datetime currentTime;
    if(parLocalTime == true)
        currentTime = TimeLocal(); // ローカル時間を使用
    else
        currentTime = TimeCurrent(); // サーバー時間を使用

dateTime型ローカル変数「currentTime」をまず宣言します。

そしてif(parLocalTime == true)

についてですが、parLocalTimeは「第5仮引数「parLocalTime」には『ローカル時間を使用するかどうか』が格納される想定」セクションで解説した引数です。

「parLocalTime」はbool型で、ローカル時間を基準に使う場合はtrueが入り、サーバー時間を使う場合はfalseが入ります。

parLocalTime == trueの条件を満たしている場合、ローカル時間を基準に使う事を意味しますので、

ローカル変数「currentTime」にTimeLocal関数戻り値代入します。

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

そして、else 、即ちparLocalTime == falseの条件を満たしている場合、サーバー時間を基準にすることになりますので、TimeCurrent関数戻り値を「currentTime」に代入します

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

【広告】

処理実装記述2:取引開始時間と終了時間を設定する

続いては、引開始時間と終了時間の設定に関する記述です。

  // セッションの開始時間を設定
    SessionStartTime = GenerateTimestamp(parStartHour,parStartMinute);

    // セッションの終了時間を設定
    SessionEndTime = GenerateTimestamp(parEndHour,parEndMinute);

SessionStartTime」「SessionEndTime」は今回「CTradeSessionクラスに新たに追加した、アクセスレベルprivateメンバです。

※↑「メンバ関数「DailySessionTimer」に必要な仮引数を設定する」セクションを参照。

それぞれのメンバGenerateTimestamp関数戻り値代入しています。

SessionStartTime」にはGenerateTimestamp関数の第1引数に「parStartHour」、第2引数に「parStartMinute」が割り当てられています。それぞれ、メインプログラムでトレード開始時間の「時」情報と「分」情報を格納することを想定した引数です。

同じ理屈で、「SessionEndTime」にはGenerateTimestamp関数の第1引数に「parEndHour」、第2引数に「parStartMinute」が割り当てられています。

それぞれ、メインプログラムでトレード終了時間の「時」情報と「分」情報を格納することを想定した引数です。

GenerateTimestamp関数は、講座記事第118回で実装した特定日時を生成する関数です

詳しい処理実装記述を確認したい方は第118回の↓

関数の仮引数と戻り値の設定を行う」及び「関数の処理実装記述を行う」セクションをご覧頂きたいのですが、簡単に言うと、西暦と日付までは現在時刻の情報をそのまま使い、「時」と「分」情報は任意に引数で好きな値に設定できるような挙動になっています。

処理実装記述3:トレード終了時間が開始時間より前に設定されている場合の記述を行う

続いてはトレード終了時間が開始時間より前に設定されている場合の記述についてです↓

// セッションの終了時間が開始時間より前に設定されている場合、終了時間を調整する
    if(SessionEndTime <= SessionStartTime) 
    {
        SessionStartTime -= DAYS_TO_SECONDS; // 開始時間を一日分マイナス

        // 現在時刻が終了時間を過ぎていた場合、開始時間と終了時間を次の日にずらす
        if(currentTime > SessionEndTime)
        {
            SessionStartTime += DAYS_TO_SECONDS;
            SessionEndTime += DAYS_TO_SECONDS;
        }
    }

「トレード終了時間が開始時間より前に設定されている場合」

if(SessionEndTime <= SessionStartTime) の記述を満たしている時、ということになるのですが、文章だけ見てもピンとこないかもしれません。要は以下のような場合です。

SessionStartTimeに格納されている値→2024.04.01 22:00

SessionEndTimeに格納されている値→2024.04.01 08:00

これは本来、「夜10時から翌朝8時までの間に取引したい」という意図なのですが、現状GenerateTimestamp関数には日時をまたいだ情報の取得をするような記述がなされていません。

従って、日をまたいだ日時設定をしても支障のない記述をここで行います。

具体的には、これも講座記事第第118回の「「1分」「1時間」「1日」「1週間」に相当する経過秒数をdefine命令により定数として設定する」セクションにて追加した定数を使います

「DAYS_TO_SECONDS」という定数は1日を秒に換算した値→「86400」秒という値を格納しています。

SessionStartTime -= DAYS_TO_SECONDS;

という記述によって、1日分の時間が減じられることになり、SessionStartTimeに格納されている値は

SessionStartTimeに格納されている値→2024.03.31 22:00

となりました。

SessionEndTimeに格納されている値→2024.04.01 08:00

は変わらないので、これで「22時~8時まで」という時間指定が行えた事になります。

そして、現在時刻が2024.04.01 08:00を過ぎた場合(=if(currentTime > SessionEndTime))、

{}の中の処理で

SessionStartTime += DAYS_TO_SECONDS;
SessionEndTime += DAYS_TO_SECONDS;

にそれぞれ1日分の時間情報を足すことによって↓

SessionStartTimeに格納されている値→2024.04.01 22:00

SessionEndTimeに格納されている値→2024.04.02 08:00

となります。

これが毎回繰り返されることになります。

※+= 、-=などの複合代入演算子を用いた計算については↓の記事リンクをご参照ください

【広告】

処理実装記述4:IsActive関数を使って、トレード時間の判定を行う

最後にIsActive関数を使って、トレード時間の判定を行います↓

   // セッションがアクティブかどうかを判断
    bool timerOn = IsActive(SessionStartTime, SessionEndTime, parLocalTime);

    // タイマーの状態を出力
    Print(timerOn);

    // タイマーがオンかオフかの状態を返す
    return(timerOn);

IsActive関数前回実装過程を解説した、「トレード時間かどうかをチェックする」メンバ関数です。

IsActive関数の第1引数には開始時間を格納したSessionStartTime、第2引数には終了時間を格納したSessionEndTimeが入ります。

bool型ローカル変数「timerOn」を宣言し、IsActive関数戻り値代入します

最後に、Print関数で「timerOn」の値をログ出力し、returnで「timerOn」を返してDailySessionTimer関数の処理実装記述は完了です。

完成したDailySessionTimer関数を使ってみる

それでは、完成したをメインプログラムで使ってみましょう。

使い方の1例となるサンプルコードは以下の通りです。

//+------------------------------------------------------------------+
//|                                       IsActive_Test.mq5          |
//|                 ティックデータに応じて処理を実行するためのコード  |
//|                                                                  |
//+------------------------------------------------------------------+

// OriginalTimer.mqhファイルをインクルード(事前定義された時間変換定数やクラスが含まれる)
#include <OriginalTimer.mqh>

// CTradeSessionクラスのインスタンスを生成(取引セッションを管理する)
CTradeSession TradeTimer;

// 入力パラメータの設定(外部から変更可能な変数)
input bool ActivateTimer=false;          // タイマーをアクティブにするかどうか
input int TradeStartHour=20;             // 取引開始時
input int TradeStartMinute=0;            // 取引開始分
input int TradeEndtHour=8;               // 取引終了時
input int TradeEndtMinute=0;             // 取引終了分
input bool ActivateLocalTimer=false;     // ローカルタイムをアクティブにするかどうか

// 新しいティックデータが来たときに実行される関数
void OnTick()
  {
   bool TradeOn=true;

   if(ActivateTimer==true)
     {


      // 現在の時刻が取引時間内かどうかをチェック(取引可能時間かを確認)
      TradeOn=
         TradeTimer.DailySessionTimer(TradeStartHour,TradeStartMinute,TradeEndtHour,TradeEndtMinute,ActivateLocalTimer);
     }

// 取引時間内であれば
   if(TradeOn==true)
     {
      // 注文を発注する処理をここに書く(取引時間内なら注文を出す)
     }
  }
//+------------------------------------------------------------------+

OriginalTimer.mqhファイルをインクルードする

まずはメインプログラムで今回作ったクラスを使えるようにするためにinclude命令OriginalTimer.mqhファイルを読み込みます。


// OriginalTimer.mqhファイルをインクルード
#include <OriginalTimer.mqh>

include命令については↓の記事をご参照ください

MQL5 EA講座 第56回「#include命令(#include directive)」

CTradeSessionクラスのインスタンスを宣言

続いてCTradeSessionクラスインスタンスを宣言します。

インスタンス名は「TradeTimer」としました。

// CTradeSessionクラスのインスタンスを生成
CTradeSession TradeTimer;

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

MQL5 EA講座 第54回「インスタンスについて」

取引時間を設定するためのinput変数を宣言

続いてグローバル領域に取引時間を設定するためのinput変数を宣言します


// 入力パラメータの設定(外部から変更可能な変数)
input bool ActivateTimer=false;          // タイマーをアクティブにするかどうか
input int TradeStartHour=20;             // 取引開始時
input int TradeStartMinute=0;            // 取引開始分
input int TradeEndtHour=8;               // 取引終了時
input int TradeEndtMinute=0;             // 取引終了分
input bool ActivateLocalTimer=false;     // ローカルタイムをアクティブにするかどうか

↑一番上の「ActivateTimer」はそもそも、トレードタイマーをしようするかどうかの判定を行うinput変数となります。

「ActivateTimer」がfalseの場合、時間帯によるトレード制限は設けず、全時間帯取引OKという事になります(時間以外の諸条件によって発注するかどうかが決まる)

残りの5つは当記事の「メンバ関数「DailySessionTimer」に必要な仮引数を設定する」セクションで解説したDailySessionTimer関数引数に対応するinput変数となります。

input変数については↓の記事をご参照ください

MQL5 EA講座 第24回「Input変数」

dateTime型については↓の記事群をご参照ください

MQL5 EA講座 第16回「データ型その6 datetime型」

MQL5 EA講座 第116回「DateTime型を使って、日時データを操作する時の基本的な考え方」

【広告】

OnTick関数内の記述をおこなう

グローバル領域での記述が終わったので、今度はOnTick関数内の記述をおこないます

// 新しいティックデータが来たときに実行される関数
void OnTick()
  {
   bool TradeOn=true;// 取引が可能かどうかを管理するフラグ。初期値はtrue

   if(ActivateTimer==true)// もしタイマーをアクティブにする設定なら
     {


      // 現在の時刻が取引時間内かどうかをチェック(取引可能時間かを確認)
      TradeOn=
         TradeTimer.DailySessionTimer(TradeStartHour,TradeStartMinute,TradeEndtHour,TradeEndtMinute,ActivateLocalTimer);
     }

// 取引時間内であれば
   if(TradeOn==true)
     {
      // 注文を発注する処理をここに書く(取引時間内なら注文を出す)
     }
  }
//+------------------------------------------------------------------+

まずbool型ローカル変数「 TradeOn」を宣言します。この変数は取引が可能かどうかを管理するフラグに用います。この時初期値はtrueにしておきます。

初期値をtrueにしておくことによって、仮にActivateTimer==falseの時、即ちトレードタイマーを用いない時でもトレードが行えるようにしておきます。

そして、if(ActivateTimer==true)という記述は「もしトレードタイマーをアクティブにする設定なら」という意味になりますので、{}内の処理記述で、変数「TradeOn」に今回作ったDailySessionTimer関数戻り値代入するようにします。

input変数で事前に設定したトレード開始時間と終了時間内であればtrue,時間外であればfalseが格納されます。

if(TradeOn==true)を満たす時は、トレード時間内という事になりますので{}内に具体的な発注記述を行います

まとめ

今回はトレードタイマークラスに実装するメンバ関数の第2弾として、「毎日同じ時間帯に取引できるようにする関数」=DailySessionTimer関数を実装する様子を解説しました。

まず最初に、FXにおける各オープン市場の特徴を簡単に紹介した上で、毎日同じ時間帯に取引できるようにシステム的に管理できる事の意義を説明しました。詳しくは当記事の

はじめに:毎日同じ時間帯に取引できるようにする関数について」セクションをご確認ください。

そして、ロードマップに示した手順に従い、CTradeSessionクラスDailySessionTimer関数を始めとしたいくつかのメンバを追加し、

引数設定~処理実装記述までを解説していきました。

詳しくは当記事の下記セクションをご確認ください↓

「CTradeSession」クラス内に新しいメンバを加える

メンバ関数「DailySessionTimer」に必要な仮引数を設定する

メンバ関数「DailySessionTimer」に処理実装記述をおこなう

そして、最後に実装を終えたDailySessionTimer関数をメインプログラムでどのように使っていくのか、という記述例の紹介をしました。詳しくは当記事の↓

完成したDailySessionTimer関数を使ってみる」セクションをご覧ください

現時点での「OriginalTimer.mqh」ファイルに記述した内容は以下の通りです↓

//+------------------------------------------------------------------+
//|                                                OriginalTimer.mqh |
//|                                                                  |
//|                                                                  |
//+------------------------------------------------------------------+

#define MINUTES_TO_SECONDS 60 // 1分を秒に変換する定数(60秒)
#define HOURS_TO_SECONDS 3600 // 1時間を秒に変換する定数(3600秒)
#define DAYS_TO_SECONDS 86400 // 1日を秒に変換する定数(86400秒)
#define WEEKS_TO_SECONDS 604800 // 1週間を秒に変換する定数(604800秒)



//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class OriginalCNewBar
  {
private:
   datetime TimeArray[], //現在の時間を格納
            LastTimeVar;//直近にチェックした時間

public:

   void              OriginalCNewBar();//配列「TimeArray」に時系列セットを施すコンストラクタ
   //新しいバーがオープンした瞬間かどうかをチェックする
   bool              CheckNewBar(string parSymbol, ENUM_TIMEFRAMES parTimeframe);
  };
//+------------------------------------------------------------------+

//コンストラクタOriginalCNewBarの処理実装記述
void OriginalCNewBar::OriginalCNewBar(void)
  {
   ArraySetAsSeries(TimeArray,true);//配列「TimeArray」を時系列にセットする
  }

// 新しいバーがオープンしたかどうかをチェックするメンバ関数の実装
bool OriginalCNewBar::CheckNewBar(string parSymbol, ENUM_TIMEFRAMES parTimeframe)
  {
// 初回実行かどうかを判定するフラグ
   bool firstExe = false;
// 新しいバーがオープンしたかどうかを示すフラグ
   bool newBarOpen = false;

// 指定されたシンボルと時間枠の現在と一つ前のバーの時間をTimeArrayにコピー
   CopyTime(parSymbol, parTimeframe, 0, 2, TimeArray);

// LastTimeVarが0の場合、これが初回実行と判断
   if(LastTimeVar == 0)
      firstExe = true;

// TimeArrayの最新の時間がLastTimeVarより大きい場合、新しいバーと判断
   if(TimeArray[0] > LastTimeVar)
     {
      // 初回実行ではない場合、newBarフラグをtrueに設定
      if(firstExe == false)
         newBarOpen = true;
      // 最後にチェックしたバーのオープン時間を更新
      LastTimeVar = TimeArray[0];
     }

// 新しいバーの有無を返す
   return(newBarOpen);
  }


// 日付時間値を生成する関数
datetime GenerateTimestamp(int newHour = 0, int newMinute = 0)
  {
   MqlDateTime dateTimeDetails; // MqlDateTime構造体を使用して日時データを保存するための変数
   TimeToStruct(TimeCurrent(), dateTimeDetails); // 現在のサーバーの時間を取得し、dateTimeDetails構造体に代入

   dateTimeDetails.hour = newHour; // 時間を新しい値に設定
   dateTimeDetails.min = newMinute; // 分を新しい値に設定

   datetime constructedTime = StructToTime(dateTimeDetails); // MqlDateTime構造体値をdatetime値に変換

   return(constructedTime); // 変換したdatetime値を返す
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CTradeSession
  {
private:
   //トレード開始時間と終了時間を格納する
   datetime          SessionStartTime, SessionEndTime;


public:
   // 取引セッションがアクティブかどうかをチェックする関数
   bool              IsActive(datetime openTime, datetime closeTime, bool useLocalTime = false);
   //毎日のトレードタイマーを作成する関数
   bool DailySessionTimer(int parStartHour, int parStartMinute, int parEndHour, int parEndMinute, bool parLocalTime = false);
  };

// 取引セッションがアクティブかどうかをチェックする関数の実装
bool CTradeSession::IsActive(datetime openTime, datetime closeTime, bool useLocalTime = false)
  {
// 開始時間が終了時間より後であるかどうかを確認
   if(openTime >= closeTime)
     {
      // 開始時間と終了時間が不正である場合、警告メッセージを出力して処理を中止
      Alert("エラー:開始時間または終了時間が不正です");
      return false; // 不正な時間設定のため、falseを返す
     }

// 現在時刻を取得する
   datetime currentTime;
//ローカル時間を使うかどうかのチェック
   if(useLocalTime == true)
      currentTime = TimeLocal();
   else
      currentTime = TimeCurrent();

// 現在時刻が開始時間と終了時間の範囲内かどうかをチェック
   bool timerOn = false; // タイマーがオンかどうかのフラグを初期化
   if(currentTime >= openTime && currentTime < closeTime)
     {
      // 現在時刻が指定された時間範囲内にある場合、タイマーをオンにする
      timerOn = true;
     }

   return timerOn; // タイマーの状態を返す
  }

// Daily timer
bool CTradeSession::DailySessionTimer(int parStartHour, int parStartMinute, int parEndHour, int parEndMinute, bool parLocalTime=false)
{
    // 現在の時間を取得
    datetime currentTime;
    if(parLocalTime == true)
        currentTime = TimeLocal(); // ローカル時間を使用
    else
        currentTime = TimeCurrent(); // サーバー時間を使用

    // セッションの開始時間を設定
    SessionStartTime = GenerateTimestamp(parStartHour,parStartMinute);

    // セッションの終了時間を設定
    SessionEndTime = GenerateTimestamp(parEndHour,parEndMinute);

    // セッションの終了時間が開始時間より前に設定されている場合、終了時間を調整する
    if(SessionEndTime <= SessionStartTime) 
    {
        SessionStartTime -= DAYS_TO_SECONDS; // 開始時間を1日分マイナスする

        // 現在時刻が終了時間を過ぎていた場合、開始時間と終了時間を次の日にずらす
        if(currentTime > SessionEndTime)
        {
            SessionStartTime += DAYS_TO_SECONDS;
            SessionEndTime += DAYS_TO_SECONDS;
        }
    }

    // セッションがアクティブかどうかを判断
    bool timerOn = IsActive(SessionStartTime, SessionEndTime, parLocalTime);

    // タイマーの状態を出力
    Print(timerOn);

    // タイマーがオンかオフかの状態を返す
    return(timerOn);
}

//+------------------------------------------------------------------+

今回は以上とさせて頂きます。

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

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

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

<参照>

TimeCurrent関数/TimeToString関数/UNIXタイム/タイムスタンプ/datetime型/iTime関数/StringToTime関数/ENUM_TIMEFRAMES/TimeToStruct関数/GetTickCount関数/MqlDateTime構造体/タイムゾーン/TimeDaylightSavings関数/TimeGMT関数/TimeGMTOffset関数/TimeLocal関数/夏時間

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