HELP WITH ERROR 4107

Post Reply
fx800
Trader
Posts: 1334
Joined: Sun Dec 04, 2011 4:11 am

HELP WITH ERROR 4107

Post by fx800 »

Firstly, my congratulations to Steve and Shelley for a very formidable ea, the Bob and Shelley again.

I tried to modify the ea to enter by a pending order rather than buyopen/sellopen in order to avoid a premature entry like the one shown below.

I am getting error 4107. Tried goggling for help without any success.

Would appreciate any help from the brilliant coders in Steve's forum.

Thanks in advance.

peter
You do not have the required permissions to view the files attached to this post.
Last edited by Anonymous on Mon Aug 05, 2013 11:35 pm, edited 2 times in total.
phil_trade

Re: HELP WITH ERROR 4107

Post by phil_trade »

OrderSend Error 4107 (Backtesting)

January 24, 2011 (Last updated on September 22, 2011)


OrderSend Error 4107 is a so-called MQL4 run-time error that is similar to OrderSend Error 129 but, unlike the latter, appears only during backtesting of the Empty4 expert advisors, not during their live or demo run. The error is called ERR_INVALID_PRICE_PARAM (Invalid price) in the Empty4 documentation; it has no counterpart in MT5. There are two main reasons for this 4107 error to appear:
•Negative values in price, stoploss or takeprofit parameters of the OrderSend() function. Just make sure you pass the valid price parameters to this function, they surely shouldn’t be negative.
•Unnormalized doubles in price, stoploss or takeprofit parameters of the OrderSend() function. If your Forex broker uses 4 digits after the dot in quotes and you are trying to use 5 digits in your orders, then you’ll be getting error 4107 during backtesting. The best solution here is to always normalize all the price doubles using the standard Empty4 function before passing them to OrderSend():

OpenPrice = NormalizeDouble(OpenPrice, Digits);
StopLossPrice = NormalizeDouble(StopLossPrice, Digits);
TakeProfitPrice = NormalizeDouble(TakeProfitPrice, Digits);
OrderSend(Symbol(), OP_BUY, 1, OpenPrice, StopLossPrice, TakeProfitPrice, ...);
fx800
Trader
Posts: 1334
Joined: Sun Dec 04, 2011 4:11 am

Re: HELP WITH ERROR 4107

Post by fx800 »

phil_trade wrote:OrderSend Error 4107 (Backtesting)

January 24, 2011 (Last updated on September 22, 2011)


OrderSend Error 4107 is a so-called MQL4 run-time error that is similar to OrderSend Error 129 but, unlike the latter, appears only during backtesting of the Empty4 expert advisors, not during their live or demo run. The error is called ERR_INVALID_PRICE_PARAM (Invalid price) in the Empty4 documentation; it has no counterpart in MT5. There are two main reasons for this 4107 error to appear:
•Negative values in price, stoploss or takeprofit parameters of the OrderSend() function. Just make sure you pass the valid price parameters to this function, they surely shouldn’t be negative.
•Unnormalized doubles in price, stoploss or takeprofit parameters of the OrderSend() function. If your Forex broker uses 4 digits after the dot in quotes and you are trying to use 5 digits in your orders, then you’ll be getting error 4107 during backtesting. The best solution here is to always normalize all the price doubles using the standard Empty4 function before passing them to OrderSend():

OpenPrice = NormalizeDouble(OpenPrice, Digits);
StopLossPrice = NormalizeDouble(StopLossPrice, Digits);
TakeProfitPrice = NormalizeDouble(TakeProfitPrice, Digits);
OrderSend(Symbol(), OP_BUY, 1, OpenPrice, StopLossPrice, TakeProfitPrice, ...);
Many thanks, Phil Trade. I have applied NormalizeDouble to takeprofit and stoploss and wait to see if it fixes the problem.

peter
phil_trade

Re: HELP WITH ERROR 4107

Post by phil_trade »

Unfortunately, the error 4107 persists during demo despite applying NormalizeDouble to price, takeprofit and stoploss.
add a Print to see all prices ( Price/SL/TP and Bid) in journal so you can understand.
phil_trade

Re: HELP WITH ERROR 4107

Post by phil_trade »

fx8000 wrote:Firstly, my congratulations to Steve and Shelley for a very formidable ea, the Bob and Shelley again.

I tried to modify the ea to enter by a pending order rather than buyopen/sellopen in order to avoid a premature entry like the one shown below.

I am getting error 4107. Tried goggling for help without any success.

Would appreciate any help from the brilliant coders in Steve's forum.

Thanks in advance.

peter

?? which lines of code did you modified to get Pending order ?
fx800
Trader
Posts: 1334
Joined: Sun Dec 04, 2011 4:11 am

Re: HELP WITH ERROR 4107

Post by fx800 »

phil_trade wrote:
fx8000 wrote:Firstly, my congratulations to Steve and Shelley for a very formidable ea, the Bob and Shelley again.

I tried to modify the ea to enter by a pending order rather than buyopen/sellopen in order to avoid a premature entry like the one shown below.

I am getting error 4107. Tried goggling for help without any success.

Would appreciate any help from the brilliant coders in Steve's forum.

Thanks in advance.

peter

?? which lines of code did you modified to get Pending order ?
I have added the functions Has Buy Filled and Has Sell Filled, and the Pending order code

Code: Select all

 void HasBuyFilled()
{
   //This function examines the Ask to see if a pending Buy price has been reached, and sends the trade if so.
   //Uses the Bid for buys also, as this is the price we see on the chart and the hi-lo is the Bid hi-lo.

   //Set pending price
   PendingPrice = 0;
   if (ObjectFind(pendingbuypriceline) > -1) PendingPrice = ObjectGet(pendingbuypriceline, OBJPROP_PRICE1);

   RefreshRates();
   if (Bid >= PendingPrice && PendingPrice > 0)
   {
      //Close existing trades
      // Note to self: Cannot delete pending price line before old trade is closed!
      if( SellOpen && CanCloseTrades )
      {
         CloseAllTrades();
         if (ForceTradeClosure)
         {
            OldBars = 0;
            return;
         }//if (ForceTradeClosure)
         else SellOpen = false;
      }//if (SellOpen)

      if ( !BuyOpen ) 
      {
         double take, stop, price;
         int type;
         double SendLot = Lot;
         bool CancelTrade = false;

         price = Ask;
         type = OP_BUY;

         take = CalculateTakeProfit(OP_BUY, price);
         stop = CalculateStopLoss(OP_BUY, price);
         
         if (!TradeLong)
         {
            CancelTrade = true;
         }
         
         //Check filters
         if( !IsTradingAllowed() ) CancelTrade = true;

         if (CancelTrade)
         {
            ObjectDelete(pendingbuypriceline);
            PendingBuy = false;
            return;
         }//if (CancelTrade)
         
         datetime ExpiryTime = TimeCurrent() + (PendingBarsTF * BarsToKeepPendings);//Dietcoke modification

         bool result = SendSingleTrade(Symbol(), type, MainTradeComment, SendLot, price, stop, take, ExpiryTime);
         if (result)
         {
            ObjectDelete(pendingbuypriceline);
            PendingBuy = false;
         }//if (result)
         else
         {
            OldBars = 0;   // Retry next tick
         }
      }
   }//if (Ask >= PendingPrice)
}//End void HasBuyFilled()

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void HasSellFilled()
{
   //This function examines the Bid to see if a pending Sell price has been reached, and sends the trade if so

   //Set pending price
   PendingPrice = 0;
   if (ObjectFind(pendingsellpriceline) > -1) PendingPrice = ObjectGet(pendingsellpriceline, OBJPROP_PRICE1);

   RefreshRates();
   if (Bid <= PendingPrice && PendingPrice > 0)
   {
      //Close existing trades
      if( BuyOpen && CanCloseTrades )
      {
         CloseAllTrades();
         if (ForceTradeClosure)
         {
            OldBars = 0;
            return;
         }//if (ForceTradeClosure)
         else BuyOpen = false;
      }//if (BuyOpen)

      if( !SellOpen )
      {
         double take, stop, price;
         int type;
         double SendLot = Lot;
         bool CancelTrade = false;

         price = NormalizeDouble(Bid, Digits);
         type = OP_SELL;

         take = CalculateTakeProfit(OP_SELL, price);
         stop = CalculateStopLoss(OP_SELL, price);
        
         if (!TradeShort) 
         {
            CancelTrade = true;
         } 
         
         //Check filters
         if (!IsTradingAllowed() ) CancelTrade = true;

         if (CancelTrade)
         {
            ObjectDelete(pendingsellpriceline);
            PendingSell = false;
            return;
         }//if (CancelTrade)

			datetime ExpiryTime = TimeCurrent() + (PendingBarsTF * BarsToKeepPendings);//Dietcoke modification

         bool result = SendSingleTrade(Symbol(), type, MainTradeComment, SendLot, price, stop, take, ExpiryTime);
         if (result)
         {
            ObjectDelete(pendingsellpriceline);
            PendingSell = false;
         }//if (result)
         else
         {
            OldBars = 0;   // Retry next tick
         }
      }
   }//if (Bid >= PendingPrice)
}//End void HasSellFilled()

Code: Select all

   
   
   //Long 
   if (SendLong)   {
      stype = " BuyStop ";
      type = OP_BUYSTOP;
      
      if (ObjectFind(pendingbuypriceline) == -1 && !BuyOpen)
      {
         target = NormalizeDouble(High[1] + (Buffer / factor), Digits);
         Print( "Drawing line ", pendingbuypriceline, " at price ", DoubleToStr(target,Digits) );
         ObjectCreate(pendingbuypriceline, OBJ_TREND, 0, Time[0], target, TimeCurrent() + (Period() * 60), target); 
         ObjectSet(pendingbuypriceline, OBJPROP_COLOR, Green); 
         ObjectSet(pendingbuypriceline, OBJPROP_WIDTH, 1); 
         ObjectSet(pendingbuypriceline, OBJPROP_STYLE, STYLE_DASH); 
         ObjectSet(pendingbuypriceline, OBJPROP_RAY, true);
      }//if (ObjectFind(pendingbuypriceline) == -1)
      
         
      if (!SendAlertNotTrade)
      {
         
         stop = CalculateStopLoss(OP_BUY, price);
         
         
         take = CalculateTakeProfit(OP_BUY, price);
         
         
         //Lot size calculated by risk
         if (RiskPercent > 0) SendLots = CalculateLotSize(price, NormalizeDouble(stop + (HiddenPips / factor), Digits) );

         type = OP_BUY;
         
      }//if (!SendAlertNotTrade)
      
      SendTrade = true;
      
   }//if (SendLong)
   
   //Short
   if (SendShort)
   {
      stype = " SellStop ";
      type = OP_SELLSTOP;
      
      if (ObjectFind(pendingsellpriceline) == -1 && !SellOpen)
      {
         target = NormalizeDouble(Low[1] - (Buffer / factor), Digits);
         Print( "Drawing line ", pendingsellpriceline, " at price ", DoubleToStr(target,Digits) );
         ObjectCreate(pendingsellpriceline, OBJ_TREND, 0, Time[0], target, TimeCurrent() + (Period() * 60), target); 
         ObjectSet(pendingsellpriceline, OBJPROP_COLOR, Red);
         ObjectSet(pendingsellpriceline, OBJPROP_WIDTH, 1); 
         ObjectSet(pendingsellpriceline, OBJPROP_STYLE, STYLE_DASH); 
         ObjectSet(pendingsellpriceline, OBJPROP_RAY, true);
      }//if (ObjectFind(pendingsellpriceline) == -1))
      

      if (!SendAlertNotTrade)
      {
         
         stop = CalculateStopLoss(OP_SELL, price);
         
         take = CalculateTakeProfit(OP_SELL, price);
         
         
         //Lot size calculated by risk
         if (RiskPercent > 0) SendLots = CalculateLotSize(price, NormalizeDouble(stop - (HiddenPips / factor), Digits) );

         type = OP_SELL;
      }//if (!SendAlertNotTrade)
         
      SendTrade = true;      
   
      
   }//if (SendShort)
   

   if (SendTrade)
   {
      if (!SendAlertNotTrade) 
      { 
         result = SendSingleTrade(Symbol(), type, MainTradeComment, SendLots, price, stop, take);
         if (result) 
         {
            if (EmailTradeNotification) SendMail("Trade sent ", Symbol() + stype + "trade at " + TimeToStr(TimeCurrent(), TIME_DATE|TIME_MINUTES));
            if (AlertPush) AlertNow(WindowExpertName() + " " + Symbol() + " " + stype + " " + DoubleToStr(price, Digits) );
            OrderSelect(TicketNo, SELECT_BY_TICKET, MODE_TRADES);
            CheckTpSlAreCorrect(type);
         }//if (result)          
      }//if (!SendAlertNotTrade) 
      
      if (SendAlertNotTrade && !AlertSent)
      {
         Alert(WindowExpertName(), " ", Symbol(), " ", stype, "trade has triggered. ",  TimeToStr(TimeLocal(), TIME_DATE|TIME_MINUTES|TIME_SECONDS) );
         SendMail("Trade alert. ", Symbol() + " " + stype + " trade has triggered. " +  TimeToStr(TimeLocal(), TIME_DATE|TIME_MINUTES|TIME_SECONDS ));
         if (AlertPush) AlertNow(WindowExpertName() + " " + Symbol() + " " + stype + " " + DoubleToStr(price, Digits) );         
         AlertSent=true;
       }//if (SendAlertNotTrade && !AlertSent)
   }//if (SendTrade)
   
   //Actions when trade send succeeds
   if (SendTrade && result)
   {      
      if (!SendAlertNotTrade && !CloseEnough(HiddenPips, 0) ) ReplaceMissingSlTpLines();
   }//if (result)
   
   //Actions when trade send fails
   if (SendTrade && !result)
   {
      OldBarsTime = 0;
   }//if (!result)
   
   
   if (ObjectFind(pendingbuypriceline) > -1) HasBuyFilled();
   if (ObjectFind(pendingsellpriceline) > -1) HasSellFilled();  
The same pending order code has been working fine in other ea's.
fx800
Trader
Posts: 1334
Joined: Sun Dec 04, 2011 4:11 am

Re: HELP WITH ERROR 4107

Post by fx800 »

Two more examples where a pending order a few pips above High[1] would have avoided a premature entry.
You do not have the required permissions to view the files attached to this post.
phil_trade

Re: HELP WITH ERROR 4107

Post by phil_trade »

fx8000 wrote:Two more examples where a pending order a few pips above High[1] would have avoided a premature entry.
the better way to debug is to add Lprint() with Bid/ Pending Price, SL ans TP to see why OrderSend is rejected
fx800
Trader
Posts: 1334
Joined: Sun Dec 04, 2011 4:11 am

Re: HELP WITH ERROR 4107

Post by fx800 »

I am often puzzled why using the following BuyStop/SellStop code doesn't work. Can someone please explain.

Thanks.

Code: Select all

       stype = " BuyStop ";
      type = OP_BUYSTOP;
      
      if (!BuyOpen)
      {
         price = NormalizeDouble(High[1] + (Buffer / factor), Digits);
      } 

Code: Select all

      stype = " SellStop ";
      type = OP_SELLSTOP;
      
      if (!SellOpen)
      {
         price = NormalizeDouble(Low[1] - (Buffer / factor), Digits);
      } 
phil_trade

Re: HELP WITH ERROR 4107

Post by phil_trade »

fx8000 wrote:I am often puzzled why using the following BuyStop/SellStop code doesn't work. Can someone please explain.

Thanks.

Code: Select all

       stype = " BuyStop ";
      type = OP_BUYSTOP;
      
      if (!BuyOpen)
      {
         price = NormalizeDouble(High[1] + (Buffer / factor), Digits);
      } 

Code: Select all

      stype = " SellStop ";
      type = OP_SELLSTOP;
      
      if (!SellOpen)
      {
         price = NormalizeDouble(Low[1] - (Buffer / factor), Digits);
      } 
what do you mean by "doesn't work" ?
Post Reply

Return to “Coders Hangout”