エラー129を斬る!!~PART2

前々回の記事の続きです。

 

エラー129を回避するためには、

 

①オリジナル関数の中でAskBidを呼び出し、

②その直前でRefreshrates()関数を実行する必要がある、

 

ということを紹介しました。

 

しかし、(逆)指値発注や損切り・利食いの有無など、いろんな発注パターンを考えると、汎用的なオリジナル関数を作成するのは、実は、そんなに単純なことではないと気づきました。

 

いろいろ悩んだ挙句、とりあえず、以下のプログラムで大丈夫かなと思います。

bool MyOrderSend(int type, double lots, double price, int slip, double sl, double tp, string comment, int magic,color arrow)
{
   price = NormalizeDouble(price, Digits);
   sl = NormalizeDouble(sl, Digits);
   tp = NormalizeDouble(tp, Digits);
  
   int starttime = GetTickCount();
   while(true)
   {
      if(GetTickCount() - starttime > 10000)
       {
         Alert("OrderSend timeout. Check the experts log.");
         return(false);
       }
      if(IsTradeAllowed() == true)
       {       
         if(type==OP_BUY)
            {
               RefreshRates();
               price = NormalizeDouble(Ask,Digits);
               if(sl!=0) sl = NormalizeDouble(price-SL*PIP,Digits);
               if(tp!=0) tp = NormalizeDouble(price+TP*PIP,Digits);
            }
         if(type==OP_SELL)
            {
               RefreshRates();
               price = NormalizeDouble(Bid,Digits);
               if(sl!=0) sl = NormalizeDouble(price+SL*PIP,Digits);
               if(tp!=0) tp = NormalizeDouble(price-TP*PIP,Digits);
            }           
              
         if(OrderSend(Symbol(), type, lots, price, slip, sl, tp, comment, magic, 0, arrow) != -1) return(true);
         int err = GetLastError();
         Print("[OrderSendError] : ", err, " ", ErrorDescription(err));
         if(err == ERR_INVALID_PRICE) break;
         if(err == ERR_INVALID_STOPS) break;
       }
      Sleep(100);
   }
   return(false);
}  

上のプログラム中の、大文字の「SL」「TP」は外部パラメーターから渡される変数で、損切り幅と利食い幅が代入されているものとします。

 

基本的なロジックとしては、

 

①(逆)指値注文のときは、RefreshRates()関数は実行しない。

②成行き注文のときだけ、RefreshRates()関数を実行して、その直後に、AskやBidを取得する。

③②の場合で、損切り値や利食い値を設定しているときは、②の直後で、それらの値を再計算して設定し直す。

 

ということになります。

なので、成行き注文の場合、スタート関数内でこのMyOrderSend()関数を実行する際には、

 

①損切りや利食いを設定しない場合には、MyOrderSend()関数の損切り値や利食い値のパラメーターには「0」を入力をし、

②損切りや利食いを設定している場合には、MyOrderSend()関数の損切り値や利食い値のパラメーターには「0」以外のどんな数字を入力してもよい、

 

という仕様になります。