EA opens position, but fails to reverse it

 

I've wrote an Expert Advisor to execute a simple two moving average crossover strategy, as follows:

- When the fast moving average crosses the the slow MA up: go long;

- When the slow moving average crosses the fast MA down: go short;

- When price reaches take profit price: close position.


Notes about EA development and demo account testing:

- My broker doesn't accept hedge accounts, so only netting mode is available. As my strategy requires that multiple EAs with different moving average periods run at the same time, I've had to manage positions internally so one EA doesn't mess with the other's positions;

- As a consequence of the issue noted above, take profit can't be managed the usual way (modifying a position), so when the take profit price is reached, the EA sends a closing order.

- This EA has been extensively backtested and run on demo account, which demonstrated that it works perfectly.


Notes about EA real account testing:

- I've tested it twice on my real account, and it opens the position just as expected, but when the moving average crosses back, it doesn't reverse the position;

- I've run two identical EAs (just as I did in my demo account) with different parameters and both showed the above noted behavior;

- It seems it doesn't even try to send the order (see log below);

- I didn't have the chance to check if the take profit routine worked well though, as the prices didn't moved towards trigger price;

- The EA is running at a virtual machine hosted at Amazon, so no power or connection problems take place;

- Margin deposit requirements are properly met;

- My broker says there's nothing wrong with my account.


Instrument specs:

- Symbol: WDOG17 (future contract of 10,000.00 USD quoted in BRL);

- Digits: 3;

- Tick size: 0.5;

- Tick value: 5.00 BRL;

- Execution type: Exchange;

- GTD mode: Today.


EA code:


//------------------------------------------------------------------------------------------------------------
//Application details-----------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------

//Moving-Averages-Crossover version 1.00
//The algorithm buys de asset whenever the fast moving average crosses the slow moving average up and sell whe
//n the opposite happens. Position exit can take place either by a moving average crossover to the opposite di
//rection or by take profit, if set. The user must provide the moving averages calculation periods, methods an
//d applied price, as well as position size and take profit levels. Version built on 2016-11-19.

//Moving-Averages-Crossover version 1.01
//The algorithm was optimized to run simultaneously with other EAs, even in netting mode. It's orders are inde
//pendently placed and executed, disregarding manual orders and other's EAs orders. Version built on 2016-12-2
//2.

#property copyright "Rafael Pereira Gonçalves"
#property version   "1.01"



//------------------------------------------------------------------------------------------------------------
//Include-----------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------

#include <Trade/Trade.mqh>;



//------------------------------------------------------------------------------------------------------------
//Input-------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------

input ulong              expertAdvisorID =           1; //Expert Advisor ID
input int                fastMAPeriod    =          10; //Fast Moving Average Period (Integer)
input int                slowMAPeriod    =          12; //Slow Moving Average Period (Integer)
input ENUM_MA_METHOD     fastMAMethod    =    MODE_SMA; //Fast Moving Average Calculation Method
input ENUM_MA_METHOD     slowMAMethod    =    MODE_SMA; //Slow Moving Average Calculation Method
input ENUM_APPLIED_PRICE fastMAPrice     = PRICE_CLOSE; //Fast Moving Average Applied Price
input ENUM_APPLIED_PRICE slowMAPrice     = PRICE_CLOSE; //Slow Moving Average Applied Price
input double             lotSize         =           1; //Net Position Size (Integer)
input double             takeProfit      =       0.001; //Take Profit (Decimal; "0" to Disable)
input string             startTrading    =  "09:00:00"; //Start Trading Time (HH:MM:SS)
input string             stopTrading     =  "17:50:00"; //Stop Trading Time (HH:MM:SS)
input int                maxSlippage     =           0; //Maximum Slippage (Integer)



//------------------------------------------------------------------------------------------------------------
//Global variables--------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------

double          fastMABuffer[];
double          slowMABuffer[];
int             fastMAHandle;
int             slowMAHandle;
datetime        lastBarTime;
int             position = 0; //-1 is short, 0 is neutral and 1 is long
double          takeProfitPrice;
bool            takeProfitState = 0; //0 is inactive, 1 is active
bool            timeSpanGo;
MqlRates        currentBarInfo[];
MqlTradeRequest tradeRequest;

        
        
//------------------------------------------------------------------------------------------------------------
//Classes-----------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------

CTrade Trade;



//------------------------------------------------------------------------------------------------------------
//OnInit event handler----------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------

int OnInit()
{

   //Set expert advisor magic number
   Trade.SetExpertMagicNumber(expertAdvisorID);
  
   //Set trade request constant values  
   tradeRequest.action =       TRADE_ACTION_DEAL;
   tradeRequest.deviation =    maxSlippage;
   tradeRequest.sl =           0;
   tradeRequest.symbol =       _Symbol;
   tradeRequest.tp =           0;
   tradeRequest.type_filling = ORDER_FILLING_FOK;
  
   //Get initial bar opening time
   ArraySetAsSeries(currentBarInfo, true);
   CopyRates(_Symbol, PERIOD_CURRENT, 0, 3, currentBarInfo);
   lastBarTime = currentBarInfo[0].time;
  
   //Initialize indicators
   fastMAHandle = iMA(_Symbol, _Period, fastMAPeriod, 0, fastMAMethod, fastMAPrice);
   slowMAHandle = iMA(_Symbol, _Period, slowMAPeriod, 0, slowMAMethod, slowMAPrice);

   ArraySetAsSeries(fastMABuffer, true);
   ArraySetAsSeries(slowMABuffer, true);
  
   return(0);
  
}



//------------------------------------------------------------------------------------------------------------
//OnDeinit event handler--------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------

void OnDeinit(const int reason)
{

   //Deinitialize indicators, clear indicator buffer and send notification
   IndicatorRelease(fastMAHandle);
   IndicatorRelease(slowMAHandle);
   ArrayFree(fastMABuffer);
   ArrayFree(slowMABuffer);
   SendNotification("Expert Advisor has been deinitialized");

}



//------------------------------------------------------------------------------------------------------------
//OnTick event handler----------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------

void OnTick() {
  
   //Detect new bar
   CopyRates(_Symbol, PERIOD_CURRENT, 0, 3, currentBarInfo);
  
   if(currentBarInfo[0].time != lastBarTime) {
  
      lastBarTime = currentBarInfo[0].time;
      
      timeSpanGo = 0;
            
      //Check if timespan is go for trading
      if(TimeToString(currentBarInfo[0].time, TIME_SECONDS) >= startTrading &&
         TimeToString(currentBarInfo[0].time, TIME_SECONDS) <= stopTrading) {
        
         timeSpanGo = 1;
        
         //Get latest indicator values
         CopyBuffer(fastMAHandle, 0, 0, 3, fastMABuffer);
         CopyBuffer(slowMAHandle, 0, 0, 3, slowMABuffer);
        
         //Test whether to go long or not
         if(position != 1 && fastMABuffer[1] > slowMABuffer[1] && fastMABuffer[2] <= slowMABuffer[2]) {
            
            double volume = 1;
            MqlTradeResult tradeResult;
            
            tradeRequest.comment = StringFormat("Open Long (%d)", expertAdvisorID);
            
            //Modify volume to close short position, if any
            if(position == -1) {
               volume = 2;
               tradeRequest.comment = StringFormat("Close Short/Open Long (%d)", expertAdvisorID);
            }
            
            //Open long position
            tradeRequest.price =  SymbolInfoDouble(_Symbol, SYMBOL_ASK);
            tradeRequest.type =   ORDER_TYPE_BUY;
            tradeRequest.volume = lotSize * volume;
            if(!OrderSend(tradeRequest, tradeResult)) {
  
               PrintFormat("Failed to place '%s' order. Error code: %d", tradeRequest.comment, GetLastError());
               SendNotification("Expert Advisor has just failed to place an order, please check your positions manually");
  
            } else {
            
               do Sleep(10); while(tradeResult.deal == 0);
               takeProfitPrice = floor((tradeResult.price * (1 + takeProfit)) * 2) / 2;
               position = 1;
               takeProfitState = 1;
            
            }
            
         }
        
         //Test whether to go short or not
         else if(position != -1 && fastMABuffer[1] < slowMABuffer[1] && fastMABuffer[2] >= slowMABuffer[2]) {
            
            double volume = 1;
            MqlTradeResult tradeResult;
            
            tradeRequest.comment = StringFormat("Open Short (%d)", expertAdvisorID);
            
            //Modify volume to close long position, if any
            if(position == 1) {
               volume = 2;
               tradeRequest.comment = StringFormat("Close Long/Open Short (%d)", expertAdvisorID);
            }
            
            //Open short position
            tradeRequest.price =  SymbolInfoDouble(_Symbol, SYMBOL_BID);
            tradeRequest.type =   ORDER_TYPE_SELL;
            tradeRequest.volume = lotSize * volume;
            if(!OrderSend(tradeRequest, tradeResult)) {
              
               PrintFormat("Failed to place '%s' order. Error code: %d", tradeRequest.comment, GetLastError());
               SendNotification("Expert Advisor has just failed to place an order, please check your positions manually");
              
            } else {
                          
               do Sleep(10); while(tradeResult.deal == 0);
               takeProfitPrice = ceil((tradeResult.price * (1 - takeProfit)) * 2) / 2;
               position = -1;
               takeProfitState = 1;
              
            }  
            
         }
        
      }
      
   }
      
   //Check for take profit
   if(takeProfitState == 1 && timeSpanGo == 1) {
      
      if(position == 1 && SymbolInfoDouble(_Symbol, SYMBOL_BID) >= takeProfitPrice) {
            
            MqlTradeResult tradeResult;
            
            tradeRequest.price =  takeProfitPrice;
            tradeRequest.type =   ORDER_TYPE_SELL;
            tradeRequest.volume = lotSize;
            tradeRequest.comment = StringFormat("Close Long by Take Profit (%d)", expertAdvisorID);
            if(!OrderSend(tradeRequest, tradeResult)) {
            
               PrintFormat("Failed to place '%s' order. Error code: %d", tradeRequest.comment, GetLastError());
               SendNotification("Expert Advisor has just failed to place an order, please check your positions manually");
              
            } else {
              
               position = 0;
               takeProfitState = 0;
              
            }  
            
      }
      
      if(position == -1 && SymbolInfoDouble(_Symbol, SYMBOL_ASK) <= takeProfitPrice) {
            
            MqlTradeResult tradeResult;
            
            tradeRequest.price =  takeProfitPrice;
            tradeRequest.type =   ORDER_TYPE_BUY;
            tradeRequest.volume = lotSize;
            tradeRequest.comment = StringFormat("Close Short by Take Profit (%d)", expertAdvisorID);
            if(!OrderSend(tradeRequest, tradeResult)) {
              
               PrintFormat("Failed to place '%s' order. Error code: %d", tradeRequest.comment, GetLastError());
               SendNotification("Expert Advisor has just failed to place an order, please check your positions manually");
              
            } else {
              
               position = 0;
               takeProfitState = 0;
            
            }
            
      }
      
   }
  
}


The log:

Below there's a piece of the log where I tested two EAs with different moving average periods. Note that around 15:30:00 and 14:00:00 both positions should be closed due to the moving averages crossing back, but nothing happens.


[log begin]

PF    0    09:37:42.035    Terminal    MetaTrader 5 Terminal x64 build 1495 started ('x broker')
CL    0    09:37:42.036    Terminal    Windows Server 2012 R2 Standard (x64 based PC), IE 11.00, RDP, UAC, Intel Xeon  E5-2676 v3 @ 2.40GHz, RAM: 393 / 1023 Mb, HDD: 10444 / 30367 Mb, GMT-03:00
EE    0    09:37:42.036    Terminal    C:\'default path...'
RD    0    09:38:09.684    Network    'xxxxxx': authorized on x server through MetaTrader 5 Access Server 2 (ping: 3.75 ms)
PF    0    09:38:09.684    Network    'xxxxxx': previous successful authorization performed from 'xxx.xx.xx.xxx' on 2017.01.04 09:29:34
FG    0    09:38:09.696    Network    'xxxxxx': terminal synchronized with 'x broker'
QM    0    09:38:09.696    Network    'xxxxxx': trading has been enabled - netting mode
NE    0    09:38:18.721    Experts    automated trading is enabled
DQ    0    09:38:30.332    Experts    expert Moving-Averages-Crossover (WDOG17,M5) loaded successfully
CJ    0    09:39:54.769    Experts    expert Moving-Averages-Crossover (WDOG17,M5) loaded successfully
IF    0    12:52:38.706    Network    'xxxxxx': scanning network for access points
KN    0    12:52:38.926    Network    'xxxxxx': scanning network finished
HK    0    13:09:52.225    Trades    'xxxxxx': exchange buy 1.00 WDOG17 at market
KL    0    13:09:52.248    Trades    'xxxxxx': exchange buy 1.00 WDOG17 at market placed for execution in 23.323 ms (Order received. Sending to OMS.)
EP    0    13:09:52.334    Trades    'xxxxxx': deal #24936683 buy 1.00 WDOG17 at 3250.500 done (based on order #20123664)
OR    0    13:09:53.735    Notifications    notification 'added order #20123664 buy 1.00 WDOG17 at market, Open Long' sent to 'xxxxxx
HL    0    13:09:53.941    Notifications    notification 'deal #24936683 buy 1.00 WDOG17 at 3250.500 done, based on order #20123664 buy 1.00 WDOG17 at market' sent to 'xxxxxx'
CG    0    14:35:01.673    Trades    'xxxxxx': exchange buy 1.00 WDOG17 at market
RP    0    14:35:01.689    Trades    'xxxxxx': exchange buy 1.00 WDOG17 at market placed for execution in 16.329 ms (Order received. Sending to OMS.)
EM    0    14:35:01.718    Trades    'xxxxxx': deal #24950576 buy 1.00 WDOG17 at 3249.000 done (based on order #20127352)
HO    0    14:35:02.598    Notifications    notification 'added order #20127352 buy 1.00 WDOG17 at market, Open Long' sent to 'xxxxxx'
JL    0    14:35:02.808    Notifications    notification 'deal #24950576 buy 1.00 WDOG17 at 3249.000 done' sent to 'xxxxxx'
RF    0    16:45:44.023    Experts    expert Moving-Averages-Crossover (WDOG17,M5) removed

OH    0    16:45:56.023    Experts    expert Moving-Averages-Crossover (WDOG17,M5) removed

[log end]


I tried to provide all possible information, but let me know if you need more details to help me.

So, what am I missing here?

Reason: