2011/06/09

MT4用EA開発時代 - 警告メールの嵐対応3(ERR_INVALID_TRADE_PARAMETERS再び)


さて前回は、ECN系FX業者への対応方式を検討した所まで書きました。今回は、以前の記事処置したはずが再発してしまった、「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は成功している。
-------------------------

上記バグの対応時に立てた仮説がOrderSelect()の結果が最新化されるのが、ティックデータ受信後のRefreshRates()後というMT4の動作。

じゃあ、仮説が間違えていたのか?という話ですが、








考慮漏れです。





だからと言って、仮設が正しいという事が証明された訳じゃけど。。
#ティックデータ受信後にRefreshRates()すると、OrderSelect()結果が最新化されるという仮説

考慮モレを簡単に言うと、RefreshRates()でTRUEが返ってきたからと言って、その時受信したティックデータが、SL/TPで決済された後のティックデータである保障は無いということ。
つまり、OrderModify()実行中に受信したティックデータに、SL/TPで決済された旨の情報がはいっているはずがない。以降は詳細。

まずは、前回の対処。

【前回の修正後のロジック】
-----------------------
 ポジション保有中と思っていた場合、以下の様に修正
 ・「ERR_INVALID_TRADE_PARAMETERS」が発生した場合、RefreshRates()がTRUEを返却
  するか、IsStopped()がTRUEになるまで、スリープ&リトライする。
  →RefreshRates()はデータ更新が不要(つまり最新化されていない)であれば、FALSEを返すので。
 ・RefreshRates()がTRUEを返却した場合、ポジション保有中かどうかをOrderSelectのループで確認。
 ・上記でポジション保有していれば、クリティカルエラー扱いに。逆に保有ポジションなしで
  あれば、成功扱いで、ログ出力のみ。
-----------------------

後の説明の為に、前回記事で発生していた事を絵にしてみると。

【ERR_INVALID_TRADE_PARAMETERS発生条件-1】
--------------------------
下図の「エラー検出」箇所が「ERR_INVALID_TRADE_PARAMETERS」検出したところ。
そして、ティックデータ受信していない状態で、RefreshRates()しても、反映する
データが無いので、OrderSelect()しても、オーダ保有中と判断されてしまった。
--------------------------

そして、以前の記事で対処したのが以下。

【ERR_INVALID_TRADE_PARAMETERS発生条件-2】
--------------------------
MT4クライアント側で、RefreshRates()がTRUEを返却するまでループする事で、
ティックデータ受信を確認してから、オーダ保有有無を確認していた。
ここまでが、以前のブログ記事での対処。
--------------------------






一見問題なさそうだけど、

また同じ現象が発生。


そこで改めて、HTTPSのセッションが2本張ってある事実と、それらが「オーダ操作用」と「ティックデータ」受信用という仮説を元に、いろんなタイミングを考えて見ると、以下のタイミングのズレがある事に気付いた。

【ERR_INVALID_TRADE_PARAMETERS発生条件-3】
--------------------------
これに対処する為に、一旦OrderModify()処理中に受信したティックデータをRefreshRates()で反映させてから、さらに次のティックデータ受信するまでRefreshRates()をループする様に修正。すると以下の様なデータの流れになる。
--------------------------


ここで問題なのが、上記図での2回目のティックデータ送信が、本当に「トレードサーバ」でSL/TP決済を認識した後のデータかどうかが解らない点。


つまり、以下の様なケース。


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



こんなケースが

ほんまに起こりうるんかい!


という話もあるんですが。。。。


ここを少しでも緩和する為に、TimeCurrent()を使う事にした。

この関数は、サーバ側時間を秒単位で取得する事ができ、ヘルプを見ると、ティックデータ受信毎に「MT4クライアント側」に反映される。

なので前述の追加修正に加え、「MT4クライアント側」start()関数内のOrderModify()で、ERR_INVALID_TRADE_PARAMETERS」を検出したタイミングで一旦TimeCurrent()を取得しておき、このTimeCurrent()が変わるまで、RefreshRates()をループさせる様にさらに修正。

すると少なくとも、OrderModify()処理中に「MT4クライアント」に溜まっていたデータを吐き出したあと、少しは時間が経った後の2回目のティックデータ受信という事はわかる。
#同じ時分秒で発生したティックデータではないというレベルだけど。。

もう一つ、ヘルプにも書いてないし、なんの検証もしてないけど少しだけ期待している事が。
それは、OrderModify()のレスポンスをMT4クライアント側が受信した時に、TimeCurrent()が更新されること。これが「もし」本当であれば、今回のロジックで穴は無くなるはず。

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






どっちにしても、

根本解決策

思いつかず。





OrderSelectの情報を最新化するAPIが欲しい。。






そして、なかなかバグが取れきれずに、「FXシステムトレード初心者奮闘記」の「MT4用EA開発時代」は、新たなバグが出ない限り、OrderSelect問題」仮説の検証に進むかもしれないのでした。
#実は他にも、ブログ記事にする程のものじゃない、純粋なロジックミスのバグ改修があったりしてた。。。


0 件のコメント:

コメントを投稿