さて前回は、「OrderSelect問題」という仮説への対処のため、start関数同時実行を回避する方法を検討したところまで書いたけど、そもそも仮説がビックリな内容という反応だったところまででした。
今回は、まだ続くエラーを検出した旨の警告メールへの対応について書きたいと思います。
未だ続く
エラー発生検出の
メール達。
狙ってもやりづらいテストを、実施できたの事になるので良かったけど。
ともかく、今回発生した主な事象。
#凡ミスはこの記事の他にもいっぱいあるけど。。
【発生した事象】
-------------------
1.OrderModify()で、ERR_TRADE_MODIFY_DENIEDでリトライアウト
2.「zero divide(ゼロによる除算)」が発生
3.OrderModify時に、ERR_INVALID_TRADE_PARAMETERSが発生し、
クリティカル・エラー扱いに。
-------------------
じゃあ、個別の詳細な発生事象と対応内容について。
#やっぱり軽い順に。。
#やっぱり軽い順に。。
【1.OrderModify()で、ERR_TRADE_MODIFY_DENIEDでリトライアウト】
-------------------
これは、MarketInfoでMODE_FREEZELEVELが指定されていた場合の話。
OrderModify/OrderClose時、SL/TPがAsk/Bid±MODE_FREEZELEVELの範囲にあった場合に、返却されるエラー。以前の記事でのエラーコード毎の振る舞いを整理したときは、リトライする事にしていたが、今回リトライアウト(500msec×240回)が発生。
でも、その後のブログ記事では、OrderModifyをリトライせずに、次のティックデータを待つ事にしていたはずなのに、修正していなかった。。
要は修正漏れ。。。
-------------------
なんじゃそりゃ、というバグ。次はもう少しまとも。
【2.「zero divide(ゼロによる除算)」が発生】
-------------------
とある日、「zero divide」というログを最後にトレードが停止。。。
トレード停止するのに、ログ出力だけかよ。。。
ここの一番の問題は、EAのプログラムで検出したわけじゃないので、メール通知もできないし、MT4が落ちるわけでもないし、何かダイアログが出るわけじゃないので、トレードが停止されている事に気付きづらい点。
ともかく、該当箇所が無いかどうかチェックしたところ、除算の母数でゼロになりそうなところがない。。
しょうがないので、除算する箇所全てで、母数がゼロかどうかチェックして、ゼロであればクリティカルエラー扱いになる様に修正。なので、根本解決にはならず、単に事象に気付ける様になっただけ。
MT4自体のバグが原因であれば別だけど、少なくともまた発生した時は、問題の切り分けにはなる。
#MT4のバグだったらどうしよう。。。
-------------------
次が、今日のメイン。
【3.「ERR_INVALID_TRADE_PARAMETERS」でクリティカル・エラー】
-------------------
まずは、発生した事象を詳細に。
●発生事象詳細
1.OrderModify時に、ERR_INVALID_TRADE_PARAMETERSが発生
ログを見ると、チケット番号も、指定価格も間違えてない。
ロジックは、ERR_INVALID_TRADE_PARAMETERSが発生した場合、RefreshRates()後、
OrderSelectをループさせて、ポジションが無くなっていれば成功扱いとしていた。
しかし、そこでポジションありと判定されたため、今回のERR_INVALID_TRADE_PARAMETERS
がクリティカル・エラー扱いとなった。
2.その直後のログで、StopLossにひっかかって、決済された旨のログが出力されていた。
3.ERR_INVALID_TRADE_PARAMETERS発生の前のバーでは、OrderModifyは成功している。
さて、上記事象から想定されるのは、SL決済されたポジションに対してOrderModifyをしたから。
決済されたポジションに対するOrderModify/OrderCloseから返却されるエラーコードは、「ERR_INVALID_TRADE_PARAMETERS」としていた事は正解っぽい。
ここは満足!!
しかし腑に落ちないのは、クリティカル・エラーになってしまった点。
なぜかと言うと、「ERR_INVALID_TRADE_PARAMETERS」検出後は、RefreshRates()した後にOrderSelect()をループさせて確認しているにも関わらず、ポジション有りと判定されてしまった。つまり、上記仮説にはあわない。さらに元々疑問だったのが、OrderSelect()で取得できるデータが最新化されるタイミング。
しかし、プログラムをよく見ると、RefreshRates()の成否について確認していなかった。
しかし、プログラムをよく見ると、RefreshRates()の成否について確認していなかった。
なので、仮説として成り立ちそうなのは、いくらRefreshRates()しても、次のティックデータを受信していなければ、OrderSelect()で得られる情報は最新化されないのではないか、という事。
#他にも最新化されるタイミングとして、オーダ関連関数成功時がある様な気もしますが。。。
なので、結局以下の様に修正。
●修正後のロジック
ポジション保有中と思っていた場合、以下の様に修正
・「ERR_INVALID_TRADE_PARAMETERS」が発生した場合、RefreshRates()がTRUEを返却
するか、IsStopped()がTRUEになるまで、スリープ&リトライする。
するか、IsStopped()がTRUEになるまで、スリープ&リトライする。
→RefreshRates()はデータ更新が不要(つまり最新化されていない)であれば、FALSEを返すので。
・RefreshRates()がTRUEを返却した場合、ポジション保有中かどうかをOrderSelectのループで確認。
・上記でポジション保有していれば、クリティカルエラー扱いに。逆に保有ポジションなしで
あれば、成功扱いで、ログ出力のみ。
正直、ループを抜ける条件にリトライアウトを付けてないのが怖いんやけど、ポジションがあった場合は、プログラムミスが原因になるので、クリティカルエラーにする必要があるレベル。なので、リトライアウト時にどうすべきか悩ましい。
リトライアウトさせた場合の問題は、エラーが正常なのか異常なのかが不明なままになってしまうという事。そしてリトライアウトという事象は、サーバで障害が発生していると当然起きうる話。そして仕方なく。。。
-------------------
当初のテスト計画では、設計書を作成するところからだったけど、相次ぐ警告メールでなかなか手につかない。。。 しかも、他にも気になる点と、まだブログ記事にしていない点が。
【対応/検討予定】
-----------------------
1.ERR_TRADE_TIMEOUT発生時の処理
何回か発生したので、ヘルプを見てみると。。。また面倒な話が。。
言われてみれば当たり前の話なんだけど。 ブログ書きながら考えよう。。
言われてみれば当たり前の話なんだけど。 ブログ書きながら考えよう。。
2.ECN系への対応
OrderSendした後にOrderModifyするという話だけなんだけど、異常系を考えると結構悩ましい。
→ 既に実装してデモ口座で動かしてるけど、まだブログ記事にしてないので。
3.「OrderSelect問題」の仮説のウラとり作業
そこまでまだ手が回らないし、再発もしてない。再発すれば一気に白黒はっきりするけど、
再発してないからといって仮説が正しいという訳でもない。。
OrderSelectした後、異なるスリープ時間でOrderSymbol()を出力するEA作って、
複数動作させれば、わかるはずなんだけど。
-----------------------
テストを開始したような、
開始してないような。。
そして、なかなかテスト計画通りのテストが開始されないまま、「FXシステムトレード初心者奮闘記」の「MT4用EA開発時代」は、「ERR_TRADE_TIMEOUT発生時の処理」に進みたいと思うのでした。
#外出中にクリティカルエラーが検出され、PCのアラームが鳴りっぱなしになってしまった。。。お義母さんすみません。。
0 件のコメント:
コメントを投稿