Need help to limitation 1 order per Signal.

Bui The Vinh  

Hi all.

Please help to add limitation for per bar/signal. Currently it opened alot of order per signal (buy/sell condition).

Thanks alot

#include <stdlib.mqh>
#include <stderror.mqh>

extern double SL_Points = 10;
extern double TP_Points = 50;
extern double Trail_Points = 10;
extern double Trail_Step = 5;
extern double BreakEven_Points = 5;
int LotDigits; //initialized in OnInit
int MagicNumber = 1234;
double TradeSize = 0.1;
double MaxSpread = 40;
int MaxSlippage = 3; //adjusted in OnInit
int MaxOpenTrades = 100;
int MaxLongTrades = 100;
int MaxShortTrades = 100;
int MaxPendingOrders = 1000;
bool Hedging = false;
int OrderRetry = 5; //# of retries if sending order returns error
int OrderWait = 5; //# of seconds to wait if sending order returns error
double myPoint; //initialized in OnInit

void myAlert(string type, string message)
  {
   if(type == "print")
      Print(message);
   else if(type == "error")
     {
     }
   else if(type == "order")
     {
     }
   else if(type == "modify")
     {
     }
  }

int TradesCount(int type) //returns # of open trades for order type, current symbol and magic number
  {
   int result = 0;
   int total = OrdersTotal();
   for(int i = 0; i < total; i++)
     {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) continue;
      if(OrderMagicNumber() != MagicNumber || OrderSymbol() != Symbol() || OrderType() != type) continue;
      result++;
     }
   return(result);
  }

int myOrderSend(int type, double price, double volume, string ordername) //send order, return ticket ("price" is irrelevant for market orders)
  {
   if(!IsTradeAllowed()) return(-1);
   int ticket = -1;
   int retries = 0;
   int err = 0;
   int long_trades = TradesCount(OP_BUY);
   int short_trades = TradesCount(OP_SELL);
   int long_pending = TradesCount(OP_BUYLIMIT) + TradesCount(OP_BUYSTOP);
   int short_pending = TradesCount(OP_SELLLIMIT) + TradesCount(OP_SELLSTOP);
   string ordername_ = ordername;
   if(ordername != "")
      ordername_ = "("+ordername+")";
   //test Hedging
   if(!Hedging && ((type % 2 == 0 && short_trades + short_pending > 0) || (type % 2 == 1 && long_trades + long_pending > 0)))
     {
      myAlert("print", "Order"+ordername_+" not sent, hedging not allowed");
      return(-1);
     }
   //test maximum trades
   if((type % 2 == 0 && long_trades >= MaxLongTrades)
   || (type % 2 == 1 && short_trades >= MaxShortTrades)
   || (long_trades + short_trades >= MaxOpenTrades)
   || (type > 1 && long_pending + short_pending >= MaxPendingOrders))
     {
      myAlert("print", "Order"+ordername_+" not sent, maximum reached");
      return(-1);
     }
   //prepare to send order
   while(IsTradeContextBusy()) Sleep(100);
   RefreshRates();
   if(type == OP_BUY)
      price = Ask;
   else if(type == OP_SELL)
      price = Bid;
   else if(price < 0) //invalid price for pending order
     {
      myAlert("order", "Order"+ordername_+" not sent, invalid price for pending order");
      return(-1);
     }
   int clr = (type % 2 == 1) ? clrRed : clrBlue;
   if(MaxSpread > 0 && Ask - Bid > MaxSpread * myPoint)
     {
      myAlert("order", "Order"+ordername_+" not sent, maximum spread "+DoubleToStr(MaxSpread * myPoint, Digits())+" exceeded");
      return(-1);
     }
   while(ticket < 0 && retries < OrderRetry+1)
     {
      ticket = OrderSend(Symbol(), type, NormalizeDouble(volume, LotDigits), NormalizeDouble(price, Digits()), MaxSlippage, 0, 0, ordername, MagicNumber, 0, clr);
      if(ticket < 0)
        {
         err = GetLastError();
         myAlert("print", "OrderSend"+ordername_+" error #"+IntegerToString(err)+" "+ErrorDescription(err));
         Sleep(OrderWait*1000);
        }
      retries++;
     }
   if(ticket < 0)
     {
      myAlert("error", "OrderSend"+ordername_+" failed "+IntegerToString(OrderRetry+1)+" times; error #"+IntegerToString(err)+" "+ErrorDescription(err));
      return(-1);
     }
   string typestr[6] = {"Buy", "Sell", "Buy Limit", "Sell Limit", "Buy Stop", "Sell Stop"};
   myAlert("order", "Order sent"+ordername_+": "+typestr[type]+" "+Symbol()+" Magic #"+IntegerToString(MagicNumber));
   return(ticket);
  }

int myOrderModify(int ticket, double SL, double TP) //modify SL and TP (absolute price), zero targets do not modify
  {
   if(!IsTradeAllowed()) return(-1);
   bool success = false;
   int retries = 0;
   int err = 0;
   SL = NormalizeDouble(SL, Digits());
   TP = NormalizeDouble(TP, Digits());
   if(SL < 0) SL = 0;
   if(TP < 0) TP = 0;
   //prepare to select order
   while(IsTradeContextBusy()) Sleep(100);
   if(!OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES))
     {
      err = GetLastError();
      myAlert("error", "OrderSelect failed; error #"+IntegerToString(err)+" "+ErrorDescription(err));
      return(-1);
     }
   //prepare to modify order
   while(IsTradeContextBusy()) Sleep(100);
   RefreshRates();
   if(CompareDoubles(SL, 0)) SL = OrderStopLoss(); //not to modify
   if(CompareDoubles(TP, 0)) TP = OrderTakeProfit(); //not to modify
   if(CompareDoubles(SL, OrderStopLoss()) && CompareDoubles(TP, OrderTakeProfit())) return(0); //nothing to do
   while(!success && retries < OrderRetry+1)
     {
      success = OrderModify(ticket, NormalizeDouble(OrderOpenPrice(), Digits()), NormalizeDouble(SL, Digits()), NormalizeDouble(TP, Digits()), OrderExpiration(), CLR_NONE);
      if(!success)
        {
         err = GetLastError();
         myAlert("print", "OrderModify error #"+IntegerToString(err)+" "+ErrorDescription(err));
         Sleep(OrderWait*1000);
        }
      retries++;
     }
   if(!success)
     {
      myAlert("error", "OrderModify failed "+IntegerToString(OrderRetry+1)+" times; error #"+IntegerToString(err)+" "+ErrorDescription(err));
      return(-1);
     }
   string alertstr = "Order modified: ticket="+IntegerToString(ticket);
   if(!CompareDoubles(SL, 0)) alertstr = alertstr+" SL="+DoubleToString(SL);
   if(!CompareDoubles(TP, 0)) alertstr = alertstr+" TP="+DoubleToString(TP);
   myAlert("modify", alertstr);
   return(0);
  }

int myOrderModifyRel(int ticket, double SL, double TP) //modify SL and TP (relative to open price), zero targets do not modify
  {
   if(!IsTradeAllowed()) return(-1);
   bool success = false;
   int retries = 0;
   int err = 0;
   SL = NormalizeDouble(SL, Digits());
   TP = NormalizeDouble(TP, Digits());
   if(SL < 0) SL = 0;
   if(TP < 0) TP = 0;
   //prepare to select order
   while(IsTradeContextBusy()) Sleep(100);
   if(!OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES))
     {
      err = GetLastError();
      myAlert("error", "OrderSelect failed; error #"+IntegerToString(err)+" "+ErrorDescription(err));
      return(-1);
     }
   //prepare to modify order
   while(IsTradeContextBusy()) Sleep(100);
   RefreshRates();
   //convert relative to absolute
   if(OrderType() % 2 == 0) //buy
     {
      if(NormalizeDouble(SL, Digits()) != 0)
         SL = OrderOpenPrice() - SL;
      if(NormalizeDouble(TP, Digits()) != 0)
         TP = OrderOpenPrice() + TP;
     }
   else //sell
     {
      if(NormalizeDouble(SL, Digits()) != 0)
         SL = OrderOpenPrice() + SL;
      if(NormalizeDouble(TP, Digits()) != 0)
         TP = OrderOpenPrice() - TP;
     }
   if(CompareDoubles(SL, 0)) SL = OrderStopLoss(); //not to modify
   if(CompareDoubles(TP, 0)) TP = OrderTakeProfit(); //not to modify
   if(CompareDoubles(SL, OrderStopLoss()) && CompareDoubles(TP, OrderTakeProfit())) return(0); //nothing to do
   while(!success && retries < OrderRetry+1)
     {
      success = OrderModify(ticket, NormalizeDouble(OrderOpenPrice(), Digits()), NormalizeDouble(SL, Digits()), NormalizeDouble(TP, Digits()), OrderExpiration(), CLR_NONE);
      if(!success)
        {
         err = GetLastError();
         myAlert("print", "OrderModify error #"+IntegerToString(err)+" "+ErrorDescription(err));
         Sleep(OrderWait*1000);
        }
      retries++;
     }
   if(!success)
     {
      myAlert("error", "OrderModify failed "+IntegerToString(OrderRetry+1)+" times; error #"+IntegerToString(err)+" "+ErrorDescription(err));
      return(-1);
     }
   string alertstr = "Order modified: ticket="+IntegerToString(ticket);
   if(!CompareDoubles(SL, 0)) alertstr = alertstr+" SL="+DoubleToString(SL);
   if(!CompareDoubles(TP, 0)) alertstr = alertstr+" TP="+DoubleToString(TP);
   myAlert("modify", alertstr);
   return(0);
  }

void myOrderClose(int type, int volumepercent, string ordername) //close open orders for current symbol, magic number and "type" (OP_BUY or OP_SELL)
  {
   if(!IsTradeAllowed()) return;
   if (type > 1)
     {
      myAlert("error", "Invalid type in myOrderClose");
      return;
     }
   bool success = false;
   int err = 0;
   string ordername_ = ordername;
   if(ordername != "")
      ordername_ = "("+ordername+")";
   int total = OrdersTotal();
   for(int i = total-1; i >= 0; i--)
     {
      while(IsTradeContextBusy()) Sleep(100);
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(OrderMagicNumber() != MagicNumber || OrderSymbol() != Symbol() || OrderType() != type) continue;
      while(IsTradeContextBusy()) Sleep(100);
      RefreshRates();
      double price = (type == OP_SELL) ? Ask : Bid;
      double volume = NormalizeDouble(OrderLots()*volumepercent * 1.0 / 100, LotDigits);
      if (NormalizeDouble(volume, LotDigits) == 0) continue;
      success = OrderClose(OrderTicket(), volume, NormalizeDouble(price, Digits()), MaxSlippage, clrWhite);
      if(!success)
        {
         err = GetLastError();
         myAlert("error", "OrderClose"+ordername_+" failed; error #"+IntegerToString(err)+" "+ErrorDescription(err));
        }
     }
   string typestr[6] = {"Buy", "Sell", "Buy Limit", "Sell Limit", "Buy Stop", "Sell Stop"};
   if(success) myAlert("order", "Orders closed"+ordername_+": "+typestr[type]+" "+Symbol()+" Magic #"+IntegerToString(MagicNumber));
  }

void TrailingStopTrail(int type, double TS, double step, bool aboveBE) //set Stop Loss to "TS" if price is going your way with "step"
  {
   int total = OrdersTotal();
   TS = NormalizeDouble(TS, Digits());
   step = NormalizeDouble(step, Digits());
   for(int i = total-1; i >= 0; i--)
     {
      while(IsTradeContextBusy()) Sleep(100);
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(OrderMagicNumber() != MagicNumber || OrderSymbol() != Symbol() || OrderType() != type) continue;
      RefreshRates();
      if(type == OP_BUY && (!aboveBE || Bid > OrderOpenPrice() + TS) && (NormalizeDouble(OrderStopLoss(), Digits()) <= 0 || Bid > OrderStopLoss() + TS + step))
         myOrderModify(OrderTicket(), Bid - TS, 0);
      else if(type == OP_SELL && (!aboveBE || Ask < OrderOpenPrice() - TS) && (NormalizeDouble(OrderStopLoss(), Digits()) <= 0 || Ask < OrderStopLoss() - TS - step))
         myOrderModify(OrderTicket(), Ask + TS, 0);
     }
  }

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {   
   //initialize myPoint
   myPoint = Point();
   if(Digits() == 5 || Digits() == 3)
     {
      myPoint *= 10;
      MaxSlippage *= 10;
     }
   //initialize LotDigits
   double LotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
   if(LotStep >= 1) LotDigits = 0;
   else if(LotStep >= 0.1) LotDigits = 1;
   else if(LotStep >= 0.01) LotDigits = 2;
   else LotDigits = 3;
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   int ticket = -1;
   double price;   
   double SL;
   double TP;
   
   TrailingStopTrail(OP_BUY, Trail_Points * myPoint, Trail_Step * myPoint, false); //Trailing Stop = trail
   TrailingStopTrail(OP_SELL, Trail_Points * myPoint, Trail_Step * myPoint, false); //Trailing Stop = trail
   
   //Close Long Positions
   if(iCustom(NULL, PERIOD_CURRENT, "ArrowTrend", 1, 0) != 0 && iCustom(NULL, PERIOD_CURRENT, "ArrowTrend", 1, 0) != EMPTY_VALUE //INDI is not equal to fixed value
   )
     {   
      if(IsTradeAllowed())
         myOrderClose(OP_BUY, 100, "");
      else //not autotrading => only send alert
         myAlert("order", "");
     }
   
   //Close Short Positions
   if(iCustom(NULL, PERIOD_CURRENT, "ArrowTrend", 0, 0) != 0 && iCustom(NULL, PERIOD_CURRENT, "ArrowTrend", 0,0) != EMPTY_VALUE //INDI is not equal to fixed value
   )
     {   
      if(IsTradeAllowed())
         myOrderClose(OP_SELL, 100, "");
      else //not autotrading => only send alert
         myAlert("order", "");
     }
   
   //Open Buy Order
   if(iCustom(NULL, PERIOD_CURRENT, "ArrowTrend", 0,0) != 0 && iCustom(NULL, PERIOD_CURRENT, "ArrowTrend", 0,0) != EMPTY_VALUE
   

   )
     {
      RefreshRates();
      price = Ask;
      SL = SL_Points * myPoint; //Stop Loss = value in points (relative to price)
      TP = TP_Points * myPoint; //Take Profit = value in points (relative to price)   
      if(IsTradeAllowed())
        {
         ticket = myOrderSend(OP_BUY, price, TradeSize, "");
         if(ticket <= 0) return;
        }
      else //not autotrading => only send alert
         myAlert("order", "");
      myOrderModifyRel(ticket, SL, 0);
      myOrderModifyRel(ticket, 0, TP);
     }
   
   //Open Sell Order
   if(iCustom(NULL, PERIOD_CURRENT, "ArrowTrend", 1,0) != 0 && iCustom(NULL, PERIOD_CURRENT, "ArrowTrend", 1,0) != EMPTY_VALUE //INDI is not equal to fixed value
   )
     {
      RefreshRates();
      price = Bid;
      SL = SL_Points * myPoint; //Stop Loss = value in points (relative to price)
      TP = TP_Points * myPoint; //Take Profit = value in points (relative to price)   
      if(IsTradeAllowed())
        {
         ticket = myOrderSend(OP_SELL, price, TradeSize, "");
         if(ticket <= 0) return;
        }
      else //not autotrading => only send alert
         myAlert("order", "");
      myOrderModifyRel(ticket, SL, 0);
      myOrderModifyRel(ticket, 0, TP);
     }
  }
//+------------------------------------------------------------------+
d12081986  

hi, I state that I am not a programmer. I have the same problem. I have ea that work and I wish they only traded once a day. I found this from previous forums but it returns the error: 'for' - expressions are not allowed on a global scope and '}' - unexpected end of program. thanks to those who want to help me


for(i=0;i<totalorders; i++)

{

  if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true)

  { datetime A = OrderOpenTime();

     if( (TimeYear(A)==Year())

     && (TimeMonth(A)==Month())

     && (TimeDay(A)==Day()) )

     {

        onedayorder = 1;

     }

     else

     {onedayorder =2;

     }

}

Jason Grosser  
d12081986:

hi, I state that I am not a programmer. I have the same problem. I have ea that work and I wish they only traded once a day. I found this from previous forums but it returns the error: 'for' - expressions are not allowed on a global scope and '}' - unexpected end of program. thanks to those who want to help me


for(i=0;i<totalorders; i++)

{

  if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true)

  { datetime A = OrderOpenTime();

     if( (TimeYear(A)==Year())

     && (TimeMonth(A)==Month())

     && (TimeDay(A)==Day()) )

     {

        onedayorder = 1;

     }

     else

     {onedayorder =2;

     }

}

The global scope error occurs because your code above is not contained within the onstart() function

d12081986  
Jason Grosser:

The global scope error occurs because your code above is not contained within the onstart() function


thank you Jason Grosser. should this code be inserted at the beginning or end of the ea? thank you

Jason Grosser  

So when you say you only want your code to trade once per day, do you mean once on the start of a new day candle, or do you mean at anytime during the day but once it has traded no more trades until the start of the next day?

Either is quite simple to do. If you mean the first one, code to execute on the start of a new days candle you can use the following function. The charts needs to be a on a day chart.


void start()
  {

    if(IsNewCandle())
    {

    //execute code

    }

}

//+------------------------------------------------------------------+
// v1.0
// New candle function
//+------------------------------------------------------------------+
bool IsNewCandle()
  {
   static int BarsOnChart=0;
   if(Bars == BarsOnChart)
      return(false);
   BarsOnChart = Bars;
   return(true);
  } 
Jason Grosser  
d12081986:

thank you Jason Grosser. should this code be inserted at the beginning or end of the ea? thank you

All of the functions must have and open and closed curly bracket, and all of the functions must be outside of

void start()
{


}


// functions here

d12081986  

Thanks again Jason. I use the following code to have only one trade per day (my ea has tf 15m). However, I would like to create a variant indicating a single trade per candle (therefore with multiple trades per day). ps: is it possible to insert the trailing stop in the backtests? thanks always for your help datetime midnight = TimeCurrent()-(TimeCurrent() % (PERIOD_D1*60)); for(int i =OrdersHistoryTotal( )-1 ;i>=0;i--) { OrderSelect(i, SELECT_BY_POS, MODE_HISTORY); if( OrderMagicNumber( ) ==MagicNumber ) { if ( OrderOpenTime()>= midnight) return(0); } } for(i =OrdersTotal( )-1 ;i>=0;i--) { OrderSelect(i, SELECT_BY_POS, MODE_TRADES); if( OrderMagicNumber( ) ==MagicNumber ) { if ( OrderOpenTime()>= midnight) return(0); } }

d12081986  
datetime midnight = TimeCurrent()-(TimeCurrent() % (PERIOD_D1*60)); for(int i =OrdersHistoryTotal( )-1 ;i>=0;i--) { OrderSelect(i, SELECT_BY_POS, MODE_HISTORY); if( OrderMagicNumber( ) ==MagicNumber ) { if ( OrderOpenTime()>= midnight) return(0); } } for(i =OrdersTotal( )-1 ;i>=0;i--) { OrderSelect(i, SELECT_BY_POS, MODE_TRADES); if( OrderMagicNumber( ) ==MagicNumber ) { if ( OrderOpenTime()>= midnight) return(0); } }
Reason: