サマータイムを考慮した自動GMT設定関数

アイキャッチ

自動GMT設定のポイントはサーバーとの時差の計算

※2016/8/6 kumaさんのご指摘でcalcTimeDifference()に不具合があることが判明。修正しました。

為替相場では切っても切り離せない問題。その1つが時差です。

EAによる自動売買でも、時間帯によるエントリー制限等でサーバーとの時差を考慮しなければならない時があります。

サーバーとの時差を考慮する際、気をつけなければならないのがサマータイムです。FX業者が採用しているサマータイムには、主に英国式と米国式があります。

そこで、この2種類のサマータイムを考慮した自動GMT設定関数を紹介します。

上記4つの関数を使って自動GMT設定を実現しています。結構複雑な作りになっていますね。

最初のgetLocalTimeGMT_Offset()関数は、ローカルタイム(MT4を実行するPC)のGMTオフセットを取得する関数です。このブログをご覧の方のPCはほぼ日本にい設定されているでしょうから、「9」になります。

getLocalTimeGMT_Offset()関数内では、Windows APIであるGetTimeZoneInformation()関数を用いています。そのため、実際にgetLocalTimeGMT_Offset()関数を使う際は、EAの冒頭に

を記述する必要があります。これによって、kernel32.dllに含まれているGetTimeZoneInformation()関数をMQL4内に取り込んだことになり、MQL4内で自由に使えるようになるわけです。

次のcalcTimeDifference()関数は、サーバーとの時差を求める関数になっています。UseAutoGMT_Flgがfalse(自動GMT設定をオフ)か、バックテストか、最適化のいずれかの場合、以下のサマータイム期間判定関数を呼び出してから時差を計算します。そうでない場合(フォワードテストか実運用)は、MQL4の標準関数を使って時差を計算します。

3つ目のisSummerTime()関数は、サマータイム期間判定関数です。英国式と米国式の2つに対応しています。サマータイム期間ならtrue、そうでないならfalseを返します。この関数は人力検索はてなの回答を参考にして作成しています。

最後のNthDayOfWeekToDay()関数は、isSummerTime()関数の中で日にちを計算するのに利用しています。この関数も10.3 ○月のN回目のW曜日は何日?をもとに作成しています。

先人の知恵を借りよう
プログラミングは何も全て自分で考えて作る必要はありません。インターネット上には先人の知恵が無数に転がっています。良いものはどんどん真似させてもらいましょう!「学ぶ」は「真似る」から来ていると言われますし。

サンプルEA

関数だけではイメージが沸きづらいと思いますので、サンプルEAを載せておきます。

ブログランキングに参加中!

ポチっとクリック頂けると励みになります♪
(クリックしてもランキング一覧が表示されるだけですが、それでOKです)

  にほんブログ村 為替ブログ FX システムトレード派へ

8件のコメント

  • 匿名

    こんにちは、とても勉強になるブログで、色々と試させてもらっています。この関数についてもサンプルで試してみたのですが、コンパイルは通るのですが、実行させると
    “Cannot call ‘kernel32.dll::GetTimeZoneInformation’, DLL is not allowed”
    ~”: unresolved import function call”
    ~”: not initialized”
    とのエラーが出て動作しないようです。4.00 Build950 で Windows7 です。
    考えられることはあるでしょうか?
    自分のEAに組み込んでみようと思っていたので、とりあえず、うちは日本なので、getLocalTimeGMT_Offset()の戻り値を9に指定してこの関数呼ばないようにして対処していますが…(^_^;

    • りゅーき

      「DLL is not allowed」は直訳すると、DLLが許可されていないという意味になります。
      MT4の[ツール]-[オプション]-[エキスパートアドバイザ]タブで[DLLの使用を許可する]にチェックが入っていますか?
      NOであれば、チェックを入れて再度試してみてください。

      • 感謝している人

        なるほど、[DLLの使用を許可する]チェックですか!
        逆に今まで、この[DLLの使用を許可する]は何のためのチェックボックスなのか分かっていませんでした。エラーメッセージ”DLL is not allowed”あたりで冷静に考えてみれば思い当たりそうなのに、指摘されるまで気付きませんでした。お恥ずかしい。
        わざわざお返事いただき、ありがとうございました。
        サンプルソースが付いていて実践的で本当に勉強になるブログで、これからも楽しみにしています!

        • りゅーき

          うまく動いたようで良かったです。
          英語のエラーメッセージを見ると、「ナニコレ!分からない!」ってなってしまうのは皆同じですよね。
          でも、そこをグッとこらえてじっくり読んでみると意外と簡単なことを言っていたりします。
          これからも読者の方にとって有益な記事を書いていきたいと思いますので、応援よろしくお願いします!

  • kuma

    いつも参考にさせていただいています。

    早速でございますが、上記コードを利用しMT4のGMTオフセットをPrintで出力した所おかしな数値を出力します。
    環境としては
    運用PC:日本国内のPC(GMT+9)
    運用ブローカー:TitanFX(サマータイプNY方式,夏時間GMT+3、冬時間GMT+2)
    ブローカーです。

    上記に伴いパラは
    UseAutoGMT_Flg = true;
    SummerTimeType = 2;
    SummerGMT_Offset = 3;
    WinterGMT_Offset = 2;

    のため、timeDiffの値をプリントしたところ本来6と出るべき値が5と出力しています。

    念のため getLocalTimeGMT_Offset()をPrintで確認しましたが、こちらは問題なく9を出力しています。
    結果gLocalGMT_Offset – timeDiffとしても本来3と出るべき所が4となっています状況です。

    また公開いただいていますテスト用EAコードをコンパイルしテストしましたが同様の数値です。
    どうもcalcTimeDifferenceがうまく動作していないように感じますがいかがでしょうか?
    現在既に使用している機能のため、何とか改善方法を知りたく何卒宜しくお願い致します。

    • りゅーき

      ご指摘ありがとうございます。
      kumaさんの読み通り、calcTimeDifferenceが、ある条件下ではうまく動作しないことが分かりました。

      serverGMT_Offset = aLocalGMT_Offset – TimeHour(TimeLocal() – TimeCurrent());
      の部分が問題のコードです。

      ローカルタイムがサーバタイムより少し遅い場合、1時間不足する不具合が発生します。

      TimeLocal() = 2016.08.06 23:25:26
      TimeCurrent() = 2016.08.05 10:25:46
      TimeLocal() – TimeCurrent() = 1970.01.01 12:59:40
      この場合、時差 = 12hと出てしまいますが、本来は13h。

      TimeHour()で時間hだけを取得するため、59分40秒が切り捨てられ、結果として、1時間不足するわけです。
      この類の問題は意外と厄介です。

      解決案を色々考えたのですが、スマートな解決策を見つけられず、泥臭い感じの修正になりました。
      ブログ記事を更新しましたので、ご確認ください。
      これで問題を回避できるかと思いますので、お試し頂ければ幸いです。

      • kuma

        ご確認ありがとうございます。
        そして修正版のご紹介ありがとうございます。

        私の方でも色々と案を模索したのですが、サマータイプのタイプとサマータイム時のGMT、通常時のGMTを入力するのであれば、無理に全ての工程を内部計算に依存せずとも良いのではと考えました。(バックテスト時にはこれらのパラを使うわけですから)

        そこで元々ご紹介いただいていました各関数内の冒頭部にあった
        UseAutoGMT_Flg・ IsTesting() ・ IsOptimization()の判定を削除し
        、どのような場面でもisSummerTime関数で計算するよう改造してみました。
        これですと先日の環境でも問題なく自動判定してくれますので、これでも良いかなとも思えてきています(苦笑)

        • りゅーき

          仰る通り、isSummerTime関数を常時使うようにロジックを修正するか、UseAutoGMT_Flgをfalseにすれば、パラメータで設定したGMTオフセット値で計算します。
          重要なのは目的を達成する(今回の場合、正しく時差を計算する)ことですので、方法は自分の好みに合わせれば良いと思います。正解は1つではないですから。

コメントを残す



four × two =