2012/01/23

MT4用EA開発時代 - MT4のバグとOrderSelectの内部動作妄想



さて前回は、トレーディング・プランの見直しをして、ついに本番開始したところまで書きました。今回は、MT4用EAを開発中に見つけたMT4のバグとOrderSelect動作の妄想について書いてみたいと思います。

今までブログ記事にしてなかったけどMT4用共通部品で対処や検討した点が幾つか。せっかくなので認識してるMT4の問題は一旦吐き出しておこうかと。

【今回のテーマ】
------------------------
1.オーダ操作関数から不正なエラーコード返却
2.OrderSelect()について
  ・期待していたMT4内部動作が外れていて障害発生
  ・OrderSelect()内部動作妄想
------------------------

という事で一つづつ。

【オーダ操作関数から不正なエラーコード返却】
-----------------------------
1.OrderModify()で「ERR_INVALID_TICKETが返却が返却される
  ログに出力していたチケット番号は、口座履歴に存在していて、SL決済されている事を確認済み。
  
  本来であれば、トレードサーバで検出されるべき状況なので、
  「ERR_INVALID_TRADE_PARAMETERS」が返却されるのが正しいはず。
  
  推測だけど、OrderSelect()用の内部メモリテーブルが未完成の状態で、指定したチケット番号
  がどちらにもなかったのが原因なのではないかと思う。※後述
  Build406で発生。
  
2.OrderSend()で「ERR_NO_RESULT」が返却される
  「ERR_NO_RESULT」はOrderModify()の時だけに返却されるエラーコード。
  PC過負荷+NW過負荷の状態で発生。
  実は発注成功しているケースがあり、失敗したと思ってリトライすると
  不要オーダ発生になるので注意。
  Build225/Build229/Build406で発生。
  
  ●参考
  
3.OrderSend()/OrderModify()/OrderClose()で「ERR_COMMON_ERROR」
  PC過負荷+NW過負荷状態なのでバグというかは微妙。
  但し、OrderSend()では上記「2.」と同じ様に実は発注成功しているケース
  あった。これについてはMT4ヘルプの記載漏れだと思う。
  雰囲気的に通信エラーで発生するっぽく感じた。
  
4.マーケットが閉じた時に「ERR_TRADE_DISABLED」が返却される。
  「ODL Japan」の場合のみ発生。
  デモ口座用のトレードサーバ側の運用の都合かもしれないけど、本来であれば、
  「ERR_MARKET_CLOSED」が返却されるべき。
-----------------------------

さて「OrderSelect()」問題。
今回新たな障害が発生。OrderSelect()挙動による動作不正を回避するために、あるMT4内部動作を前提としていたけど違ったみたいだから修正したという話。

【発生事象】
-------------------------
以下の記事内の、「ERR_INVALID_TRADE_PARAMETERS発生条件-4」のパターンが発生。
そして、「OrderSelect()の結果が最新化されるのはティックデータ受信後のRefreshRates()後」という想定でロジックを組んでいたけど、見事期待が外れて、クリティカル・エラーが発生。


●発生条件と考察(再掲)
下図の「トレードサーバ」側からの2回目のティックデータ送信をMT4クライアント側で受信するタイミングがずれて、「MT4クライアント側」の1回目のRefreshRates()実施後になってしまった場合。

・実際とは異なった前提としたMT4内部動作仮説
以下のいづれか(もしくは両方)が違うという事。
OrderSelect()の結果が最新化されるのが、ティックデータ受信後のRefreshRates()後
OrderModify()のレスポンスをMT4クライアント側が受信した時に、TimeCurrent()が更新される

・前提とした仮説が違っていた場合の方針
これでダメなら、後はTimeCurrent()が何秒ずれるまで待つ、という設定を追加するか、クリティカルエラーをあきらめて、警告レベルのエラー扱いにするかぐらいしか思いつかない。

という事で、前回のMT4用EA共通部品リリースでは警告レベルのエラーとして扱う事にした。
-------------------------

そういや過去の開発経緯を見ると、OrderSelectに振り回されてきた。

【「OrderSelect」に関するブログ記事】
-------------------------
-------------------------

これらの動きを総合すると、OrderSelect()の動作は以下の雰囲気になるのではないかと。

【OrderSelect()動作概略の妄想】
--------------------
1.OrderSelect()でのデータ取得元はクライアント上のメモリデータ
2.該当メモリデータは、「取引一覧」と「履歴一覧」の2つに分かれている。
  排他制御も「取引一覧」と「履歴一覧」は別々に制御。
3.サーバ側での情報変化をクライアント側のメモリデータに反映するタイミングは、
  何かのオーダ操作やティックデータ受信時等の他動作の延長線上で更新されるのではない。
  一定間隔等、他動作と同期をとらずにメモリデータが更新される
4.メモリデータ更新中は排他制御に隙間があり、更新中にOrderSelect()すると
  不定な結果になるケースがある。
5.サーバ側動作の結果、オーダが「取引一覧」から「履歴一覧」に移動する際、
  該当オーダ情報が一旦どちらのテーブルにも無いタイミングが存在する。
6.通信障害があると「履歴一覧」は不完全になるケースがある
--------------------

これを絵にしてみるとこんなイメージ。

【SL/TP決済時の「OrderSelect」イメージ】
--------------------
OrderSelect()用テーブルの状態遷移イメージを書いてみた。

状態1.いくつかの決済済みオーダと保有中オーダがある状態
    左の点線で囲った「取引一覧」は、OrderSelect(MODE_TRADES)で取得されるデータ群。
    右の点線で囲った「履歴一覧」は、OrderSelect(MODE_HISTORY)で取得されるデータ群。
    排他制御は「取引一覧」と「履歴一覧」それぞれ別個に実施されている。
    

状態2.サーバ側でオーダが決済された事を何らかのタイミングで検出
    ここが一番状態として不安定な状態。
    ・「保有中オーダ5」がSL/TP等により決済された旨をサーバ側から受信した後の処理。
     このオーダがどちらのテーブルにも属していない状態。つまりOrderSelect(BY_TICKET)でも
     「保有中オーダ5」が見つからない状態になる。
    この「保有中オーダ5」を「取引一覧」から切り離す処理をしている間に、OrderSelect()
     ループを行った時に色々不整合が発生しそう。
    本来であれば、図中の「①切り離し」を処理中は「取引一覧」をロックしていると思う。
     OrderSelect()で「取引一覧」からデータを読み込む時も「取引一覧」をロックすべき
     なんだけど、実はしていないんじゃないかという妄想。なので不整合が発生しうる。
    ・もしOrderSelect()実行時に排他制御しているのであれば、エラーが発生しうるはず。
     エラー発生時はGetLastError()にエラーコードが設定されるはずだけど、OrderSelect()は
     エラーコードが設定されない仕様。
    「取引一覧」から該当情報を切り離した後、サーバから「保有中オーダ5」の最新情報
      取得する際、通信障害等によりデータ取得失敗した場合、「履歴一覧」に「保有中オーダ5」
      の情報が追加されない。
    

状態3.オーダが決済された事が完全にMT4クライアントに反映された
      この状態になれば安定する。
    --------------------

こういうツクリであれば、今まで発生した事象のほとんどで辻褄があう気がする。
で、もしこれが事実であれば、明らかにMT4の設計ミス。
もしMT4を修正するのであれば、以下の様な大幅な修正が必要になってしまうので、修正される可能性は低い(と思う)。

という事で、無駄とはわかりつつもMT4修正案を考えてみたw 

【仮説が正しかった場合のMT4設計修正案】
--------------------
1.オーダを「取引一覧」から切り離して、データ最新化後「履歴一覧」に繋ぎ直すのであれば、
  排他制御の単位は、「取引一覧」と「履歴一覧」の両方を対象にしないと必ず隙間ができる。
2.OrderSelect()する際は、「取引一覧」と「履歴一覧」の両方をロックしてから実行しないとやはり隙間
  が発生して不整合が起きる。
3.この両方のテーブルを最新化するAPIが必要。そうでないとサーバからエラー応答がされた時に、
  クライアントとサーバ側の不整合に起因したエラーなのか、EAバグ起因なのかが区別できない。
--------------------




さて、どうでしょう????

あくまでも妄想です。。
実際どうなのかを、ご存知の方おられたら教えて欲しいです。。


そして、「FXシステムトレード初心者奮闘記」は、本番開始前に実施したMT4用EA実行環境構築について進むのでした。
#今ライブ口座で動作中のEA君は当初資金から0.87%減少。。

0 件のコメント:

コメントを投稿