さて前回は、デモ口座期限切れで、ログインするユーザIDを切り替えた際、AccountNumberが返却するIDの罠にはまり、対応策を検討したところまで書きました。今回は予定を変更し、EAが無言停止するという事象が発生したため、事象内容と対応策について書いてみたいと思います。
事の発端は、インターネットサービルプロバイダのメンテナンスによる通信障害検出。
通信障害自体は、メンテナンスによるものなのでしょうがない。
15分程で復旧し、その後、4つ全てのデモ環境とも、障害監視システム「ahfw_hc」から回線復旧メールが到着。つい安心して、そのまま放置していた。
しかし!
翌日昼頃、何気なくデモ環境の「操作履歴」タブを見ていたら、
1つのデモ環境が全く動いてない事に気付いた。。
#何の異常検出メール通知も無し。。。。
怖いです。。
プロセス障害やスレッド障害発生時は、障害監視システム「ahfw_hc」で自動的にMT4を再起動する様にしていた。そして今回の事象が発生した時は、通信できている事も画面でも確認したし、チャート表示も最新化されていた。
そして、MT4を再起動すると普通に動き始めた。。。
プロセス障害/スレッド障害検出ロジックと、MT4用EA共通部品「ahfw」のソース、出力されているログをあわせて考えると、原因は以下の2ケースしか考えられない。
#ちなみにスレッド障害は、start()関数に入ってから一定時間以上start()関数から抜けなかった場合にスレッド障害と判断していた。
【障害仮説】
--------------------------
1.start()排他制御用関数の処理が失敗
スレッド障害検出対応として、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.00002:05:14 '1476182': request was accepted by server02:05:14 '1476182': request in process02:05:14 '1476182': order #5171007 sell 1.00 USDJPY at 77.059 was modified -> sl: 77.077 tp: 0.00002:07:46 '1476182': connect failed [回線不通!]02:13:23 Mail: error connecting to smtp.mail.yahoo.co.jp:58702:19:55 '1476182': login02:19:56 Mail: '[[AHFW_HC]][[WARN]][DEMO][ODL Securities][TEST4](AHFW_HC) Connection was closed.' has been sent02: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 件のコメント:
コメントを投稿