2011/08/05

MT4用EA開発時代 - AccountNumberとdeinitとstart



さて前回は、設計書を書いて良かった点今後の予定について書きました。今回は、以前のブログ記事で対応を決めた、デモ口座期限切れ時の作業効率化対応している時に解ったMT4の挙動について書いてみたいと思います。

おさらいからすると、開発したMT4用EA共通部品「ahfw」は大域変数(Global Variable)をたくさん使ってて、デモ口座が期限切れになると、一旦大域変数を削除しなきゃいけないけど、それが面倒。
なので、対応策としてアカウント変更理由のdeinit()で、使ってた大域変数を削除する事にした。




こんなん楽チン!




なぁ~んて、甘くは無かった。。。




元々は、deinit()関数内で、UninitializeReason()がREASON_ACCOUNTだったら、AccountNumber()をキーにした大域変数を削除する予定だった。

つまり、このタイミングで返却されるAccountNumber()は、アカウント変更前のユーザIDが返却されると思ってた。ところがなんと、返却されたのはアカウント変更後のユーザID。



企画倒れ。。




いやいや、init()関数内で、最初にEAを読み込んだ時に、AccountNumber()の結果を変数に格納しておいて、それを使って大域変数を削除すればいい話。


そして、プログラムを修正して実行してみると、なんか変なエラーが。。。


仕方なく、単純なEAを作って色々MT4の挙動を確認することにした。

【アカウント切替時のMT4の挙動確認】
---------------------------------
1.テストに使ったEA
  なんてことはない、単に各関数でAccountNumber()を出力するだけのEA。
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
    Print("init() : AccountNumber("+AccountNumber()+")");   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
    Print("deinit() : AccountNumber("+AccountNumber()+")");
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//----
    Print("start() : AccountNumber("+AccountNumber()+")");   
//----
   return(0);
  }

2.検証方法
  2つのデモアカウントを切り替えた時に、AccountNumber()が切替前か切替後のどちらを返却し、
  どういう順序で処理がされるかを幾つかのパターンで検証。

  以下が検証結果。

  A.EAを停止して、アカウント切替確認後、EAを再開
02:58:36 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(147890)
02:58:37 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(147890)
02:58:41 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(147890)
03:06:33 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(147890)
03:06:33 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(147890)
03:06:35 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(147890)
03:06:36 XAccountChange EURUSDfxf.,M5: deinit() : AccountNumber(156540)
03:06:36 XAccountChange EURUSDfxf.,M5: deinitialized
03:06:36 XAccountChange EURUSDfxf.,M5: uninit reason 6
03:06:36 XAccountChange EURUSDfxf.,M5: init() : AccountNumber(156540)
03:06:36 XAccountChange EURUSDfxf.,M5: initialized
03:07:49 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(156540)
03:07:49 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(156540)
03:07:52 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(156540)
03:08:01 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(156540)

    いたって普通の結果。

  B.EAを停止せずに、アカウント切替直後、EAを再開
    ちょっと乱暴な使い方にチャレンジしてみた。
02:56:35 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(156540)
02:56:39 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(156540)
02:56:44 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(156540)
02:56:46 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(156540)
02:58:21 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(156540)
02:58:21 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(156540)
02:58:22 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(156540)
02:58:26 Experts are disabled because the account has been changed
02:58:28 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(147890)
02:58:28 XAccountChange EURUSDfxf.,M5: deinit() : AccountNumber(147890)
02:58:28 XAccountChange EURUSDfxf.,M5: deinitialized
02:58:28 XAccountChange EURUSDfxf.,M5: uninit reason 6
02:58:28 XAccountChange EURUSDfxf.,M5: init() : AccountNumber(147890)
02:58:28 XAccountChange EURUSDfxf.,M5: initialized
02:58:36 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(147890)
02:58:37 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(147890)
02:58:41 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(147890)
    んが???deinit()が始まる前に、start()が認識しているAccountNumber()が
   変更になってる。。

      ちょっとやり過ぎたかな?? 

  C.EAを停止して、アカウント切替直後、EAを再開

    乱暴すぎたっぽいので、今回EAを一旦停止してから、アカウント切替後にすぐEAを開始。
03:16:29 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(156540)
03:16:29 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(156540)
03:16:37 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(156540)
03:16:38 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(156540)
03:17:01 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(147890)
03:17:01 XAccountChange EURUSDfxf.,M5: deinit() : AccountNumber(147890)
03:17:01 XAccountChange EURUSDfxf.,M5: deinitialized
03:17:01 XAccountChange EURUSDfxf.,M5: uninit reason 6
03:17:01 XAccountChange EURUSDfxf.,M5: init() : AccountNumber(147890)
03:17:01 XAccountChange EURUSDfxf.,M5: initialized
03:17:01 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(147890)
03:17:10 XAccountChange EURUSDfxf.,M5: start() : AccountNumber(147890)

    EA一旦停止してもあかんのか。。。

-------------------------------------------





え~っと、コレってMT4の

仕様バグじゃないんでしょうか??



アカウント切り替えた時に、deinit()もinit()も動いてないのに、start()を動かしちゃだめだし、start()内で切替後のAccountNumber()返却したらダメでしょ?
だって、init()完了しないとstart()開始されない様になってるのに、アンバランスやん。。。





さては、デモ環境がゆえんの

使い方だから手を抜いたな?





さて、対処方法を考えてみた。
#なんか、デモ環境の為だけのロジックって気が進まないけど。。


【対処方法】
----------------------------------
これは迷う余地もなく、start()開始直後に、AccountNumber()を取得して、init()時に取得したAccountNumber()と異なっていたら、何もせずにリターンする様に修正する。
厳密に言うと、既にstart()内の処理に入ってる場合に誤動作する可能性あるけど、わざわざデモ環境のためだけにそんな事してられないので、以上。
もし対処するとしたら、トレードサーバからエラーが返却された時、AccountNumber()がinit()時に取得したAccountNumber()と違っていれば、成功とするぐらい。
----------------------------------





ちなみにデモ口座切替対応として、内部管理しているチケット番号がゼロ(保有オーダなし)の状態なのに、OrderSelect()ループで、オーダを発見した場合は、該当オーダを決済する様にも修正。
結果的に、以前の「OrderSelect問題パート2が再発。絶対MT4のバグ!」への対応にもなったし。よしよし。








え?こんなの常識?





そして、小ネタでお茶を濁しながら、「FXシステムトレード初心者奮闘記」の「MT4用EA開発時代」は、設計書レビュー結果に進むのでした。
#PC障害時の、MT4用EAを動かすPC切替と、その後の処理が上手く動いた!!切り戻しもOK!!

0 件のコメント:

コメントを投稿