2011/08/08

MT4用EA開発時代 - EAが無言で止まってた。。。



さて前回は、デモ口座期限切れで、ログインするユーザIDを切り替えた際、AccountNumberが返却するIDの罠にはまり、対応策を検討したところまで書きました。今回は予定を変更し、EAが無言停止するという事象が発生したため、事象内容と対応策について書いてみたいと思います。


事の発端は、インターネットサービルプロバイダのメンテナンスによる通信障害検出。
通信障害自体は、メンテナンスによるものなのでしょうがない。

15分程で復旧し、その後、4つ全てのデモ環境とも、障害監視システム「ahfw_hc」から回線復旧メールが到着。つい安心して、そのまま放置していた。



しかし!



翌日昼頃、何気なくデモ環境の「操作履歴」タブを見ていたら、
1つのデモ環境が全く動いてない事に気付いた。。
#何の異常検出メール通知も無し。。。。




怖いです。。



プロセス障害やスレッド障害発生時は、障害監視システム「ahfw_hc」自動的にMT4を再起動する様にしていた。そして今回の事象が発生した時は、通信できている事も画面でも確認したし、チャート表示も最新化されていた。

そして、MT4を再起動すると普通に動き始めた。。。

プロセス障害/スレッド障害検出ロジックと、MT4用EA共通部品「ahfw」のソース、出力されているログをあわせて考えると、原因は以下の2ケースしか考えられない。
#ちなみにスレッド障害は、start()関数に入ってから一定時間以上start()関数から抜けなかった場合にスレッド障害と判断していた。

【障害仮説】
--------------------------
1.start()排他制御用関数の処理が失敗
  スレッド障害検出対応として、start()関数に入った時の時刻を大域変数に格納しているけど、
  このタイミングが、start()排他制御でロックを取った後。
  そして、このロックする関数内で、処理に失敗してもログ出力してない箇所があった。
  すると無限に待ち続ける事になるので、該当事象とマッチする。
2.そもそもstart()関数が呼ばれない
  通信障害復旧後に停止してるので、状況証拠的にはこっちなんじゃないかと思ってる。
--------------------------

結局、うっかりさしたる情報採取もせずに直ぐに再起動しちゃって、正常になってしまったから、これ以上の情報はナシ。

ちなみに、ログを見ると以下の様な感じ。
#ちなみにMT4は、「ODL Japan」のBuild228

【操作履歴ログ】
------------------------------
最後の行で停止したままでした。。。 
02:05:14 '1476182': modify order #5171007 sell 1.00 USDJPY at 77.059 sl: 77.091 tp: 0.000 -> sl: 77.077 tp: 0.000
02:05:14 '1476182': request was accepted by server
02:05:14 '1476182': request in process
02:05:14 '1476182': order #5171007 sell 1.00 USDJPY at 77.059 was modified -> sl: 77.077 tp: 0.000
02:07:46 '1476182': connect failed [回線不通!]
02:13:23 Mail: error connecting to smtp.mail.yahoo.co.jp:587
02:19:55 '1476182': login
02:19:56 Mail: '[[AHFW_HC]][[WARN]][DEMO][ODL Securities][TEST4](AHFW_HC) Connection was closed.' has been sent
02:19:56 Mail: '[[AHFW_HC]][[INFO]][DEMO][ODL Securities][TEST4](AHFW_HC) Connection was opened.' has been sent
---------------------------------





半日近く気付かなかったのが致命的。



さて、対処方法。

【対処方法の検討】
----------------------------------
スレッド障害検出方法として今までは、start()に入ってから抜けなかった場合だけを想定していた。
しかし、そもそもstart()が開始されないパターンは、回線を監視していたのでノーチェックだった。

原因が、前述の仮説原因がどっちだったとしても、MT4が不安定な状況には変わりなく、
検出できなかったのも事実。

じゃぁ、そもそもロックする前にstart()開始時刻を大域変数に格納すればいいじゃないかという
話もあるんだけど、1つのMT4で複数EA(もしくは通貨ペア)を同時実行している場合、
ロック待ち時間を障害検出の処理時間に入れたくなかったから。
やっぱりロックを取れる取れないは結構運・不運があって、間の悪いやつが必ずでてくる。

それと、実際問題ティックデータが来ずに、start()が開始されない事象が発生したら、気付かない
事も事実。

1.方式の大枠
  ・各EAでstart()開始時刻を大域変数に格納する。start()関数抜けてもゼロクリアしない。
   (今までのスレッド障害対策はstart()関数抜けた時にゼロクリアしていた)
  障害監視システム「ahfw_hc」で、各start()開始時間が一定時間以上更新されなければ、
   ティックデータが来てないと判断して、MT4を強制再起動させるとともに、メール通知。

2.課題
  さてここで問題なのが、今想定している運用の場合、不都合がある点。
  つまり、日曜の晩にMT4を起動して、土曜の昼頃にMT4を停止させる。

  普通にしてしまうと、マーケットが閉じたらティックデータが来なくなるから、
  異常が発生したと思って、MT4を強制再起動して、メール送信されてしまう。
  マーケットが開く前日に起動していても同じ。何回も再起動されてしまう。

3.対策案
  これを回避するのを散々考えた上げて苦肉の策で思いついたのがTimeCurrent()を使う事。
  
  これはティックデータ受信しないと更新されないので、マーケットが閉じると、TimeCurrent()が
  返却する値は、マーケットが閉じる直前のサーバ時刻を指す事になる。

  そして今回はstart()が開始されない事象で、チャートが最新化されている事を踏まえると、
  TimeCurrent()はちゃんとティックデータ受信毎に最新化されている事を期待できる。
 
  という事は、障害監視システム「ahfw_hc」ずっとstart()関数内でループしているので、
  常に正しい最新のTimeCurrent()を取得できて、マーケットが閉じると、TimeCurrent()も
  変わらなくなる。
 
  なので、各EAで認識している最新のTimeCurrent()と、障害監視システム「ahfw_hc」
  認識しているTimeCurrent()で時間差が一定以上開けば、start()関数が開始されなくなって
  いると判断できる。
 
  今までのスレッド障害検出タイマが10分で、今回のはレアケースとも考えられるので、
  ざっくり15分の差異が発生したらstart()関数が開始されない障害が発生したと判断
  することにする。
 
  そして、この障害を検出した場合は、MT4の強制終了と再起動を実施。
 -------------------------------------------





うーん。。。

デモ口座でEAを動かし始めて約2ヶ月強。
まだ新たな問題が発生するとは。。。










あっ!!
また予想外のことが。。







そして、また新たな発見をして、「FXシステムトレード初心者奮闘記」の「MT4用EA開発時代」は、新たに発見した事に進むのでした。
#設計書レビュー結果の反映まで終った~ 今回の記事分は反映してないけど。

0 件のコメント:

コメントを投稿