Opening Sell Trades

 

I am coding an EA for trading SAR. My bear positions, based on the SAR, never action. All bull positions work fine. Using counters for each function I have confirmed that every function works as required.

values. in the below code simply refers to a pre-made structure.

void OnTick()
  {
   PreambleValues values = GetValues();
// For new minute checker
   datetime currentTime = iTime(cPair, _Period, 0);
   static datetime lastTime;
   static int totalCounter = 1;

// Check the current spread
   double spread = (values.ask - values.bid) * 100000;

// For SAR
   double mySARArray[];
   int SARDefinition = iSAR(_Symbol, _Period, 0.02, 0.2);
   ArraySetAsSeries(mySARArray, true);
   CopyBuffer(SARDefinition, 0, 0, 3, mySARArray);
   double SARValue = NormalizeDouble(mySARArray[0], 5);

   string ifStatement;

// New candle
   if(currentTime != lastTime)
     {
      lastTime = currentTime;
      staticCounter++;
      if(SARValue > values.ask && spread < 15)
        {
         ifStatement = "SELLING";
         CloseAllBuyPositions();
         OpenSellTrade();
        }
      else
         if(SARValue < values.bid && spread < 15)
           {
            ifStatement = "BUYING";
            CloseAllSellPositions();
            OpenBuyTrade();
           }
         else
           {
            ifStatement = "SPREAD TOO MUCH";
            CloseAllSellPositions();
            CloseAllBuyPositions();
           }
     }
  }
//+------------------------------------------------------------------+
//| Open Buy Position                                                     |
//+------------------------------------------------------------------+
void OpenBuyTrade()
  {
// Returned preamble data
   PreambleValues values = GetValues();

   if(PositionsTotal() < 1)
     {
      trade.Buy(values.lotSize, cPair, values.ask, 0, (values.ask + (20 * _Point)), "BUY OPENED");
      openBuyCounter++;
     }
  }
//+------------------------------------------------------------------+
//| Open Sell Position                                                     |
//+------------------------------------------------------------------+
void OpenSellTrade()
  {
// Returned preamble data
   PreambleValues values = GetValues();

   if(PositionsTotal() < 1)
     {
      trade.Sell(values.lotSize, cPair, values.bid, 0, (values.bid + (20 * _Point)), "SELL OPENED");
      openSellCounter++;
     }
  }
//+------------------------------------------------------------------+
//| // Close Open Buy Positions                                      |
//+------------------------------------------------------------------+
void CloseAllBuyPositions()
  {
// Set countdown to 0 open positions
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      // Get ticket number
      ulong ticket = PositionGetTicket(i);

      // Get position direction
      ulong positionDirection = PositionGetInteger(POSITION_TYPE);

      // If a buy position
      if(positionDirection == POSITION_TYPE_BUY)
        {
         // Close all buy positions
         trade.PositionClose(ticket);
         closeBuyCounter++;
        }
     }
  }
//+------------------------------------------------------------------+
//| // Close Open Sell Ppositions                                    |
//+------------------------------------------------------------------+
void CloseAllSellPositions()
  {
// Set countdown to 0 open positions
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      // Get ticket number
      ulong ticket = PositionGetTicket(i);

      // Get position direction
      ulong positionDirection = PositionGetInteger(POSITION_TYPE);

      // If a sell position
      if(positionDirection == POSITION_TYPE_SELL)
        {
         // Close all sell positions
         trade.PositionClose(ticket);
         closeSellCounter++;
        }
     }
  }

Removing all components of CTrade and just using counters each function operates perfectly. Add the CTrade functions and the OpenSell() function never actions although the counter still does. So why do the counters tell me each function is called correctly yet the OpenSell() function is NEVER called?

 
Steve Silcox:

I am coding an EA for trading SAR. My bear positions, based on the SAR, never action. All bull positions work fine. Using counters for each function I have confirmed that every function works as required.

values. in the below code simply refers to a pre-made structure.

Removing all components of CTrade and just using counters each function operates perfectly. Add the CTrade functions and the OpenSell() function never actions although the counter still does. So why do the counters tell me each function is called correctly yet the OpenSell() function is NEVER called?

//+------------------------------------------------------------------+
//| Open Sell Position                                                     |
//+------------------------------------------------------------------+
void OpenSellTrade()
  {
// Returned preamble data
   PreambleValues values = GetValues();

   if(PositionsTotal() < 1)
     {
      trade.Sell(values.lotSize, cPair, values.bid, 0, (values.bid + (20 * _Point)), "SELL OPENED");
      openSellCounter++;
     }
  }

shouldnt the sell tp, be a minus? And I also recommend that you Normalise tps on both buys and sells to avoid any errors caused by excess digits.

 

This code can help to fix the problem and will tell you the error code

#include <Trade\SymbolInfo.mqh> // Code to add before OnInit()
CSymbolInfo m_symbol; // Code to add before OnInit()


if(!m_symbol.Name(Symbol())) // This code for OnInit()
   return(INIT_FAILED);
//+------------------------------------------------------------------+
//| Open Buy Position                                                |
//+------------------------------------------------------------------+
void OpenBuyTrade()
  {
// Returned preamble data
   PreambleValues values = GetValues();

   if(PositionsTotal() < 1)
     {
      ResetLastError();
      bool res = trade.Buy(values.lotSize, cPair, SymbolInfoDouble(cPair,SYMBOL_ASK), 0, m_symbol.NormalizePrice((SymbolInfoDouble(cPair,SYMBOL_ASK) + (20 *  Point()))), "BUY OPENED");
      if(res == false)
         Print("trade for Buy error: ", GetLastError());

      openBuyCounter++;
     }
  }
//+------------------------------------------------------------------+
//| Open Sell Position                                               |
//+------------------------------------------------------------------+
void OpenSellTrade()
  {
// Returned preamble data
   PreambleValues values = GetValues();

   if(PositionsTotal() < 1)
     {
      ResetLastError();
      bool res = trade.Sell(values.lotSize, cPair, SymbolInfoDouble(cPair,SYMBOL_BID), 0, m_symbol.NormalizePrice(((SymbolInfoDouble(cPair,SYMBOL_BID) - (20 * Point()))), "SELL OPENED");
      if(res == false)
         Print("trade for Sell error: ", GetLastError());

      openSellCounter++;
     }
  }
//+------------------------------------------------------------------+

+ A function to check stop/freeze levels should also be added

SymbolInfoInteger(Symbol(), SYMBOL_TRADE_FREEZE_LEVEL)
SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL)

Here sample:

//+------------------------------------------------------------------+
//| Refreshes the symbol quotes data                                 |
//+------------------------------------------------------------------+
bool RefreshRates(void)
  {
//--- refresh rates
   if(!m_symbol.RefreshRates())
     {
      Print("RefreshRates error");
      return(false);
     }
//--- protection against the return value of "zero"
   if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
      return(false);
//---
   return(true);
  }
//+------------------------------------------------------------------+
//| Check Freeze and Stops levels                                    |
//+------------------------------------------------------------------+
bool FreezeStopsLevels(double &level)
  {
//--- check Freeze and Stops levels
/*
   Type of order/position  |  Activation price  |  Check
   ------------------------|--------------------|--------------------------------------------
   Buy Limit order         |  Ask               |  Ask-OpenPrice  >= SYMBOL_TRADE_FREEZE_LEVEL
   Buy Stop order          |  Ask                   |  OpenPrice-Ask  >= SYMBOL_TRADE_FREEZE_LEVEL
   Sell Limit order        |  Bid                   |  OpenPrice-Bid  >= SYMBOL_TRADE_FREEZE_LEVEL
   Sell Stop order            |  Bid                |  Bid-OpenPrice  >= SYMBOL_TRADE_FREEZE_LEVEL
   Buy position            |  Bid                   |  TakeProfit-Bid >= SYMBOL_TRADE_FREEZE_LEVEL 
                           |                    |  Bid-StopLoss   >= SYMBOL_TRADE_FREEZE_LEVEL
   Sell position           |  Ask                   |  Ask-TakeProfit >= SYMBOL_TRADE_FREEZE_LEVEL
                           |                    |  StopLoss-Ask   >= SYMBOL_TRADE_FREEZE_LEVEL
                           
   Buying is done at the Ask price                 |  Selling is done at the Bid price
   ------------------------------------------------|----------------------------------
   TakeProfit        >= Bid                        |  TakeProfit        <= Ask
   StopLoss          <= Bid                          |  StopLoss          >= Ask
   TakeProfit - Bid  >= SYMBOL_TRADE_STOPS_LEVEL   |  Ask - TakeProfit  >= SYMBOL_TRADE_STOPS_LEVEL
   Bid - StopLoss    >= SYMBOL_TRADE_STOPS_LEVEL   |  StopLoss - Ask    >= SYMBOL_TRADE_STOPS_LEVEL
*/
   if(!RefreshRates() || !m_symbol.Refresh())
      return(false);
//--- FreezeLevel -> for pending order and modification
   double freeze_level=m_symbol.FreezeLevel()*m_symbol.Point();
   if(freeze_level==0.0)
      freeze_level=(m_symbol.Ask()-m_symbol.Bid())*3.0;
   freeze_level*=1.1;
//--- StopsLevel -> for TakeProfit and StopLoss
   double stop_level=m_symbol.StopsLevel()*m_symbol.Point();
   if(stop_level==0.0)
      stop_level=(m_symbol.Ask()-m_symbol.Bid())*3.0;
   stop_level*=1.1;

   if(freeze_level<=0.0 || stop_level<=0.0)
      return(false);

   level=(freeze_level>stop_level)?freeze_level:stop_level;
//---
   return(true);
  }

Sometimes it is necessary to add a volume check

Sample function:

//+------------------------------------------------------------------+
//| Check the correctness of the position volume                     |
//+------------------------------------------------------------------+
bool CheckVolumeValue(double volume,string &error_description)
  {
//--- minimal allowed volume for trade operations
   double min_volume=m_symbol.LotsMin();
   if(volume<min_volume)
     {
      if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")
         error_description=StringFormat("Объем меньше минимально допустимого SYMBOL_VOLUME_MIN=%.2f",min_volume);
      else
         error_description=StringFormat("Volume is less than the minimal allowed SYMBOL_VOLUME_MIN=%.2f",min_volume);
      return(false);
     }
//--- maximal allowed volume of trade operations
   double max_volume=m_symbol.LotsMax();
   if(volume>max_volume)
     {
      if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")
         error_description=StringFormat("Объем больше максимально допустимого SYMBOL_VOLUME_MAX=%.2f",max_volume);
      else
         error_description=StringFormat("Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f",max_volume);
      return(false);
     }
//--- get minimal step of volume changing
   double volume_step=m_symbol.LotsStep();
   int ratio=(int)MathRound(volume/volume_step);
   if(MathAbs(ratio*volume_step-volume)>0.0000001)
     {
      if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")
         error_description=StringFormat("Объем не кратен минимальному шагу SYMBOL_VOLUME_STEP=%.2f, ближайший правильный объем %.2f",
                                        volume_step,ratio*volume_step);
      else
         error_description=StringFormat("Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f",
                                        volume_step,ratio*volume_step);
      return(false);
     }
   error_description="Correct volume value";
   return(true);
  }









 
Michael Charles Schefe #:

shouldnt the sell tp, be a minus? And I also recommend that you Normalise tps on both buys and sells to avoid any errors caused by excess digits.

Yes, I hadn't noticed that. Thanks!

 
Igor Zakharev #:

This code can help to fix the problem and will tell you the error code

+ A function to check stop/freeze levels should also be added

Here sample:

Sometimes it is necessary to add a volume check

Sample function:









Thanks Igor, a lot of information to go through there but looks good to me.