7bit氏作成 MQLライブラリー解析 part7

スポンサーリンク

おはようございます。キリンです。
今日も7bitさんのライブラリーの解析をしていきます。
誰得路線まっしぐら。でも僕は楽しいのですw
何してるの?という方はpart1をどうぞ。

7bit氏作成 MQLライブラリー解析 part1

さて、今日はこれです。
■超直感!MT4(MQL)プログラミング講座■
ついに来ました。発注関数。
こいつの勉強が一番必要だと思ってたんですよね。
MT4で一番しっかりと管理しなければいけないのがこの発注関数です。
何も制御せずに発注を行うと、
MT4で業者側で約定拒否などざらで、さらに他のEAと同タイミングで別のEAが発注していた場合、
どちらかの注文が通らなくなってしまいます。
それを防ぐためにつくるのがこのような発注関数です。
さぁ、見ていきましょう。

int orderSendReliable(   string symbol,    int cmd,    double volume,    double price,    int slippage,    double stoploss,   double takeprofit,   string comment="",   int magic=0,   datetime expiration=0,   color arrow_color=CLR_NONE){   int ticket;   int err;   Print("orderSendReliable("       + symbol + ","       + cmd + ","       + volume + ","       + price + ","       + slippage + ","       + stoploss + ","      + takeprofit + ","      + comment + ","      + magic + ","      + expiration + ","      + arrow_color + ")");
while(true){      if (IsStopped()){         Print("orderSendReliable(): Trading is stopped!");         return(-1);      }      RefreshRates();      if (cmd == OP_BUY){         price = Ask;      }      if (cmd == OP_SELL){         price = Bid;      }      if (!IsTradeContextBusy()){         ticket = OrderSend(            symbol,            cmd,            volume,            NormalizeDouble(price, MarketInfo(symbol, MODE_DIGITS)),             slippage,            NormalizeDouble(stoploss, MarketInfo(symbol, MODE_DIGITS)),            NormalizeDouble(takeprofit, MarketInfo(symbol, MODE_DIGITS)),            comment,            magic,            expiration,            arrow_color         );         if (ticket > 0){            Print("orderSendReliable(): Success! Ticket: " + ticket);            return(ticket); // the normal exit         }
err = GetLastError();         if (isTemporaryError(err)){            Print("orderSendReliable(): Temporary Error: " + err + " "             + ErrorDescription(err) + ". waiting.");         }else{            Print("orderSendReliable(): Permanent Error: " + err             + " " + ErrorDescription(err) + ". giving up.");            return(-1);         }      }else{         Print("orderSendReliable(): Must wait for trade context");      }      Sleep(MathRand()/10);   }}

また結構なボリュームですw
上からの流れを説明していきます。
最初に「発注しますよ」というのをPrintで表しています。
これは特に説明不要です。
IsStoped()関数では、「EAが止まっていないか?」を判別できます。
リファレンスから言えば、
「チャートからプログラムを取り外すと、通貨ペアの変更や、チャート期間の変更、アカウントの変更、チャートが閉
じられる、クライアント ターミナルのシャットダウンと同様に、プログラムの実行が中断されます。もし、処理停止コマンドが与えられた時、この時点で start() 関数が実行されていた場合は、その処理の残り時間は 2.5秒に制限されます。プログラムは、IsStopped() の組み込み関数でシャットダウンして、正しく処理が終了される事を知ることができます。」
だそうです。要は、手動でEAを取り外すときは、start()が起動していれば2.5秒間だけ処理を継続して、処理を続けるってことですね。
あれ?でも、deinit()も2.5秒間だったような・・・
start()の残処理で2.5秒間使ってしまったら処理がdeinit()は起動するのでしょうか。
これについては明日書きます。
さて、次。
RefreshRates()は言わずと知れた、「チャートの表示中の価格にAskとBidを更新する」というもの。
発注リトライが5秒間続いたりすると、RefreshRates()をしなければ5秒前の価格でずっと発注をチャレンジしてしまうんですよね。
そして、注文の種類によって、priceを更新します。
次のIsTradeContexBusy()ですが、IsTradeAllowed()と機能がさほど変わりません・・・。
どちらがいいのでしょう。僕はIsTradeAllowed()派ですね。
違いは、IsTradeContexBusdy()は「他のEAが発注を行っているか」を見ます。
IsTradeAllowe()は、「他のEAが発注を行っていなくて、さらにAllow live tradingにチェックが入っているか」を
見ています。
次に、OrderSend()で実際に発注を行います。
priceやtp,slがNormalizeDoubleされているのは、4桁業者でたまーにバックデータに5桁のものが混入されているバグがあって、それを避けるためです。
正常に発注されると、OrderSend()はチケット番号を返します。
今回はそれをticketに値を置いています。
0より大きければ発注が正常終了したってことですね。
逆に、0以下の場合はエラーが起こっています。
そのエラーをGetLastError()でerrに格納。
面白いのが、isTemporaryError()という関数を用いている点ですね。
コイツの中身はこれ。

bool isTemporaryError(int error){   return(      error == ERR_NO_ERROR ||      error == ERR_COMMON_ERROR ||      error == ERR_SERVER_BUSY ||      error == ERR_NO_CONNECTION ||      error == ERR_MARKET_CLOSED ||      error == ERR_PRICE_CHANGED ||      error == ERR_INVALID_PRICE ||  //happens sometimes      error == ERR_OFF_QUOTES ||      error == ERR_BROKER_BUSY ||      error == ERR_REQUOTE ||      error == ERR_TRADE_TIMEOUT ||      error == ERR_TRADE_CONTEXT_BUSY    );}

それぞれのエラーについてはこちらで確認してください。
上記のエラーだったら発注をリトライさせます。
逆に、上記エラー以外だったら発注をやめてしまいます。
滑った場合を考慮して、INVALID_STOPSをリトライの中に含めてもいいかなぁと思う僕。
最後が謎の、Sleep(MathRand()/10) で待機しています。
MathRand()とは、0 から 32767 の範囲内の擬似乱数の整数を返します。
なんでMathRand()なんでしょう?
長い時で3秒も待つのは結構辛い気がするんですが><
僕個人としては、一定間隔でいいのじゃないかなと思います。
豊嶋先生のMyOrderSend()と比較しても甲乙つけ難い関数でした。
MyOrderSend()の優秀さを表していますね。
ざくっと関数の説明をさせてもらいました。
ご参考になりましたら幸いです・・・。
今日もお読み下さり、ありがとうございます^^

コメント

タイトルとURLをコピーしました