FXメタトレーダー実践プログラミングへの補足(1)/MyCurrentOrders()の危険

豊嶋先生の著書「FXメタトレーダー実践プログラミング」は、プログラミングの超・初心者には、日本語で読める資料としてかなりお勧めです。シンプルなロジックの組み立てから、実際に売買できるEAを作り上げるまでのステップは楽に進めると思います。
(但し、英語が得意で、プログラミング経験のある人には物足りないでしょう...^^;



この本の中には、便利な関数をまとめたMyLib.mq4 や、EAのサンプルがいくつか収められているのですが、それらを元にEAを作りこんでゆくと、思わぬ落とし穴に嵌る危険性があります。そういう問題は、本文中にも一部記述があるものの、初心者にはなかなか気付きにくいので、具体的に説明してみたいと思います。
(他人の書いたコードを批判するみたいで申し訳ないのですが..、相場で高い授業料を払う人が出るのも可哀想ですので...^^;


まずは、BBCross1.mq4 に使われているMyCurrentOrders()の問題から。

↑BBCross1.mq4 は、買いシグナルが出たら、売りポジションを閉じて、買いポジションを建てるシステムです。
買いシグナルは、「ポジション無し or 売りポジション有り 」の時に一定条件を満たすと発生します。


↓MyCurrentOrders()の実装は以下のようになっています。

MyCurrentOrders(MY_OPENPOS, magic) は、最初に見つかったポジションのロット数を返します。
たったこれだけのコードですが、どんな問題が起こり得るのか想像してみてください。
(5分で解けたら初段...違




問題が起きる時のフローはこんな感じです。

(1) 現在売り1ロットを保有している。
(2) 買いシグナルが発生。
(3) 売り1ロットを閉じる...のになぜか失敗する。(想定外のトラブル発生)
(4) 買い1ロットを建てる。


次のTick更新で

(5) MyCurrentOrders()は、残っている売り1ロットを最初に見つけて、売り1ロット保有と判断。
(6) 売りがあるので、再び、買いシグナルが発生。
(7) 売り1ロットを閉じる...のに再び失敗する。
(8) 買い1ロットを建てる。合計 買い2ロットとなる。

次のTick更新でも(5)〜(8)が起こります。


つまり最初の売り1ロットが、何らかの事情でクローズできなかった場合、それがクローズできない間、延々と証拠金が不足するまで買い続けてしまいます。
少し怖くなりました?^^;


売り1ロットが閉じられないなんて、そんなことあるのか?と思われるかもしれませんが、MODE_FREEZELEVELが設定されているブローカーで指値の入ったポジションをクローズする時に稀に起こります。↓ヘルプにも、closed 出来ないと書いてあります..。

MODE_FREEZELEVEL Order freeze level in points. If the execution price lies within the range defined by the freeze level, the order cannot be modified, cancelled or closed.

厳密には、BBCross1.mq4 自体は、ポジションにSL/TPの指値が入って無いので、FREEZELEVELの問題とは無関係です。でも、このEAを元に改造する人は、おそらく、SL/TPを設定してしまいますよね....。なので、要注意なのです。



さて、この問題への対策ですが...方法はいろいろあります。
応急処置としては、MyCurrentOrders 内の下記一行をコメントアウトすることです。

//if(lots != 0) break;

これだけで、売り1/買い2 になった状態で買いシグナルは止まります。
他には、

MyCurrentOrders(OP_BUY,magic)
MyCurrentOrders(OP_SELL,magic)

のようにポジションの種類を指定して取得する方法もあると思います。
正攻法は、MyOrderClose が成功した時だけ(=ポジションがゼロの時だけ)、新規ポジションを建てることですが、MyOrderClose の実装にも手直ししたい点があるので、続きはまた明日。