MT4 Expert Advisor Cannot Submit Orders: Order error 130

 

I am taking an online course, but I am stuck. The Expert Advisor I am coding cannot submit automated orders on the Demo Account.


I am attaching a file showing the output of the EA. The source code is listed below. It compiles cleanly, and it does execute on the IG chart.

As you can see from the screen print, the EA submits either a Buy or a Sell order when price crosses over either one of the

light green Bollinger Bands.


Hopefully this is a simple fix. I look forward to your comments. Thanks so much.


//+------------------------------------------------------------------+
//|                                              BB Test Strat 2.mq4 |
//|                                                     Len Cheatham |
//|                                             https://www.mql4.com |
//+------------------------------------------------------------------+
#property copyright "Len Cheatham"
#property link      "https://www.mql4.com"
#property version   "1.00"
#property strict
//+------------------------------------------------------------------+

#include <C:/Program Files (x86)/IG MetaTrader 4 Terminal/MQL4/Include/Strings/CustomFunctions01.mqh>

int bbPeriod = 20;
int band1Std = 1;
int band2Std = 4;
input double riskPerTrade = 0.02;

//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   Alert("");
   Alert("Symbol = ", Symbol());  
   Alert("MODE_LOTSIZE = ", MarketInfo(Symbol(),MODE_LOTSIZE));  
   Alert("MODE_MINLOT = ", MarketInfo(Symbol(),MODE_MINLOT));  
   Alert("MODE_LOTSTEP = ", MarketInfo(Symbol(),MODE_LOTSTEP));  
   Alert("MODE_MAXLOT = ", MarketInfo(Symbol(),MODE_MAXLOT));  
   Alert("Point = ", Point());  
   
   double bbLower1 = iBands(NULL,0,bbPeriod,band1Std,0,PRICE_CLOSE,MODE_LOWER,0);
   double bbUpper1 = iBands(NULL,0,bbPeriod,band1Std,0,PRICE_CLOSE,MODE_UPPER,0);
   double bbMid = iBands(NULL,0,bbPeriod,band1Std,0,PRICE_CLOSE,0,0);
   
   double bbLower2 = iBands(NULL,0,bbPeriod,band2Std,0,PRICE_CLOSE,MODE_LOWER,0);
   double bbUpper2 = iBands(NULL,0,bbPeriod,band2Std,0,PRICE_CLOSE,MODE_UPPER,0);
   
   if(Ask < bbLower1) //buying
   {
      Alert("Price is below bbLower1, Sending buy order");
      double stopLossPrice = NormalizeDouble(bbLower2,Digits);
      double takeProfitPrice = NormalizeDouble(bbMid,Digits);
      Alert("Entry Price = " + Ask);
      Alert("Stop Loss Price = " + stopLossPrice);
      Alert("Take Profit Price = " + takeProfitPrice);
      
      double lotSize = OptimalLotSize(riskPerTrade,Ask,stopLossPrice);
            
//      int orderID = OrderSend(NULL,OP_BUYLIMIT,lotSize,Ask,100,stopLossPrice,takeProfitPrice);
      int orderID = OrderSend(NULL,OP_BUYLIMIT,0.01,ND(Ask),1,ND(Ask + 0.001),ND(Ask - 0.001));
      if(orderID < 0) Alert("Order rejected, Order error: " + GetLastError());
   }
   else
      if(Bid > bbUpper1) //Shorting
      {
      Alert("Price is above bbUpper1, Sending short order");
      double stopLossPrice = NormalizeDouble(bbUpper2,Digits);
      double takeProfitPrice = NormalizeDouble(bbMid,Digits);
      Alert("Entry Price = " + Bid);
      Alert("Stop Loss Price = " + stopLossPrice);
      Alert("Take Profit Price = " + takeProfitPrice);
      
      double lotSize = OptimalLotSize(riskPerTrade,Bid,stopLossPrice);
            
//      int orderID = OrderSend(NULL,OP_SELLLIMIT,lotSize,Bid,100,stopLossPrice,takeProfitPrice);
      int orderID = OrderSend(NULL,OP_SELLLIMIT,0.01,ND(Bid),1,ND(Bid - 0.001),ND(Bid + 0.001));
      if(orderID < 0) Alert("Order rejected, Order error: " + GetLastError());
      }
      else
      {
         Alert("No signal was found. Will compute again on next price update.");
      }
  }
//+------------------------------------------------------------------+

 
  1. #include <C:/Program Files (x86)/IG MetaTrader 4 Terminal/MQL4/Include/Strings/CustomFunctions01.mqh>

    Does that even compile? All files are within the sandbox. #include "Strings/CustomFunctions01.mqh" should be sufficient.

  2. int orderID = OrderSend(NULL,OP_BUYLIMIT,0.01,ND(Ask),1,ND(Ask + 0.001),ND(Ask - 0.001));
    

    Be careful with NULL.

    1. On MT4, you can use NULL in place of _Symbol only in those calls that the documentation specially says you can. iHigh does, iCustom does, MarketInfo does not, OrderSend does not.
    2. Don't use NULL (except for pointers where you explicitly check for it.) Use _Symbol and _Period, that is minimalist as possible and more efficient.
    3. Zero is the same as PERIOD_CURRENT which means _Period. Don't hard code numbers.
    4. MT4: No need for a function call with iHigh(NULL,0,s) just use the predefined arrays, i.e. High[].
    5. Cloud Protector Bug? - MQL4 programming forum (2020)
    1. You can't use pending orders at the market.

      You can't move stops (or pending prices) closer to the market than the minimum: MODE_STOPLEVEL * _Point or SymbolInfoInteger(SYMBOL_TRADE_STOPS_LEVEL).
                Requirements and Limitations in Making Trades - Appendixes - MQL4 Tutorial

      On some ECN type brokers, the value might be zero (the broker doesn't know). Use a minimum of two (2) PIPs.

      The checks a trading robot must pass before publication in the Market - MQL5 Articles (2016)

    2. There is no need to create pending orders in code.

      1. The pending has the slight advantage, A) you are closer to the top of the queue (filled quicker), B) there's no round trip network delay (filled quicker.)
      2. Don't worry about it unless you're scalping M1 or trading news.
      3. Humans can't watch the screen 24/7, so they use pending orders; EAs can, so no need for pending orders, have it wait until the market reaches the trigger price and just open an order.
  3. You buy at the Ask and sell at the Bid. Pending Buy Stop orders become market orders when hit and open at the Ask.

    1. Your buy order's TP/SL (or Sell Stop's/Sell Limit's entry) are triggered when the Bid / OrderClosePrice reaches it. Using Ask±n, makes your SL shorter and your TP longer, by the spread. Don't you want the specified amount used in either direction?

    2. Your sell order's TP/SL (or Buy Stop's/Buy Limit's entry) will be triggered when the Ask / OrderClosePrice reaches it. To trigger close to a specific Bid price, add the average spread.
                MODE_SPREAD (Paul) - MQL4 programming forum - Page 3 #25

    3. The charts show Bid prices only. Turn on the Ask line to see how big the spread is (Tools → Options (control+O) → charts → Show ask line.)
      Most brokers with variable spreads widen considerably at end of day (5 PM ET) ± 30 minutes. My GBPJPY shows average spread = 26 points, but average maximum spread = 134 (your broker will be similar).

 

William Roeder, thanks for your very informative post. I have done my best to get this to work, even now submitting just market orders instead of limit orders, but still all I get is the Error 130 or 131.

Regarding your question about whether or not the code even compiles, it does indeed. For your information, I am on a Linux machine, using Wine to get the MT4 platform to function. That is why I need that #include statement, or it won't compile.

I am attaching the current code here, as well as a screen print of the latest output. This has got me beat. Hopefully you or someone else can shed some light and get me into a Demo Account position. Thanks!

//+------------------------------------------------------------------+
//|                                              BB Test Strat 2.mq4 |
//|                                                     Len Cheatham |
//|                                             https://www.mql4.com |
//+------------------------------------------------------------------+
#property copyright "Len Cheatham"
#property link      "https://www.mql4.com"
#property version   "1.00"
#property strict
//+------------------------------------------------------------------+

#include <C:/Program Files (x86)/IG MetaTrader 4 Terminal/MQL4/Include/Strings/CustomFunctions01.mqh>

int bbPeriod = 20;
int band1Std = 1;
int band2Std = 4;
input double riskPerTrade = 0.02;

//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   Alert("");
   Alert("Symbol = ", Symbol());  
   Alert("MODE_LOTSIZE = ", MarketInfo(Symbol(),MODE_LOTSIZE));  
   Alert("MODE_MINLOT = ", MarketInfo(Symbol(),MODE_MINLOT));  
   Alert("MODE_LOTSTEP = ", MarketInfo(Symbol(),MODE_LOTSTEP));  
   Alert("MODE_MAXLOT = ", MarketInfo(Symbol(),MODE_MAXLOT));  
   Alert("Point = ", Point());
      
   double bbLower1 = iBands(_Symbol,0,bbPeriod,band1Std,0,PRICE_CLOSE,MODE_LOWER,0);
   double bbUpper1 = iBands(_Symbol,0,bbPeriod,band1Std,0,PRICE_CLOSE,MODE_UPPER,0);
   double bbMid = iBands(_Symbol,0,bbPeriod,band1Std,0,PRICE_CLOSE,0,0);
   
   double bbLower2 = iBands(_Symbol,0,bbPeriod,band2Std,0,PRICE_CLOSE,MODE_LOWER,0);
   double bbUpper2 = iBands(_Symbol,0,bbPeriod,band2Std,0,PRICE_CLOSE,MODE_UPPER,0);
   
   if(Ask < bbLower1) //buying
   {
      Alert("Price is below bbLower1, Sending buy order");
      double stopLossPrice = NormalizeDouble(bbLower2,Digits);
      double takeProfitPrice = NormalizeDouble(bbMid,Digits);
      Alert("Entry Price = " + Ask);
      Alert("Stop Loss Price = " + stopLossPrice);
      Alert("Take Profit Price = " + takeProfitPrice);
      
//      double lotSize = OptimalLotSize(riskPerTrade,Ask,stopLossPrice);
      double lotSize = 10000;
            
//      int orderID = OrderSend(_Symbol,OP_BUYLIMIT,lotSize,Ask,100,stopLossPrice,takeProfitPrice);
//      int orderID = OrderSend(_Symbol,OP_BUYLIMIT,0.01,Ask,1,1.09855,1.10065);
      int orderID = OrderSend(_Symbol,OP_BUY,1,Ask,10,1.001,1.001);
      if(orderID < 0) Alert("Order rejected, Order error: " + GetLastError());
   }
   else
      if(Bid > bbUpper1) //Shorting
      {
      Alert("Price is above bbUpper1, Sending short order");
      double stopLossPrice = NormalizeDouble(bbUpper2,Digits);
      double takeProfitPrice = NormalizeDouble(bbMid,Digits);
      Alert("Entry Price = " + Bid);
      Alert("Stop Loss Price = " + stopLossPrice);
      Alert("Take Profit Price = " + takeProfitPrice);
      
//      double lotSize = OptimalLotSize(riskPerTrade,Bid,stopLossPrice);
      double lotSize = 10000;
            
//      int orderID = OrderSend(_Symbol,OP_SELLLIMIT,lotSize,Bid,100,stopLossPrice,takeProfitPrice);
      int orderID = OrderSend(_Symbol,OP_SELL,1,Bid,10,1.001,1.001);
      if(orderID < 0) Alert("Order rejected, Order error: " + GetLastError());
      }
      else
      {
         Alert("No signal was found. Will compute again on next price update.");
      }
  }
//+------------------------------------------------------------------+