Simple EA not working

 

Hello all,

I looked on past posts here and elsewhere, tried, tried and tried but still I am stuck. Can anyone lend a hand? I simply want to write a basic EA that works. This is my code:


#include <Trade\PositionInfo.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\OrderInfo.mqh>
#include <Trade\DealInfo.mqh>
#include <Trade\HistoryOrderInfo.mqh>


input int    Inp_FastMA  =12;
input int    Inp_SlowMA  =24;
input int    Inp_PeriodSignal=9;
input int    Inp_phase  =0;
input int    Inp_sl =50;
input int    Inp_tp =0;

bool glBuyPlaced = false;
bool glSellPlaced = false;



int hfast,hslow;
double bfast[],bslow[];





int OnInit()
  {
   
//---
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  { 
  
   
  
    MqlTradeRequest request;
    MqlTradeResult result;
    
    double close[];
    ArraySetAsSeries(close,true);
    CopyClose(_Symbol,_Period,0,1,close);
    
    bool openPosition = PositionSelect(_Symbol);
    long positionType = PositionGetInteger(POSITION_TYPE);
    
    double currVolume =0;
    
    if (openPosition) currVolume = PositionGetDouble(POSITION_VOLUME);
      
    ArraySetAsSeries(bfast,true);
    ArraySetAsSeries(bslow,true);
    
    double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
    double bid =SymbolInfoDouble(_Symbol,SYMBOL_BID);
    
    hfast = iMA(_Symbol,_Period,Inp_FastMA,0,MODE_SMMA,PRICE_CLOSE);
    Print(hfast);
    CopyBuffer(hfast,0,0,1,bfast);
    
    
    hslow = iMA(_Symbol,_Period,Inp_SlowMA,0,MODE_SMMA,PRICE_CLOSE);
    CopyBuffer(hslow,0,0,1,bslow);
    
    
    int diff = bfast[0]-bslow[0];
 
       
    
    if( (diff=0) && (glBuyPlaced = false) && ((positionType != POSITION_TYPE_BUY) || (openPosition == false)))
    {
       
       request.action = TRADE_ACTION_DEAL;
       request.symbol = _Symbol;
       request.volume = 1+currVolume;
       request.price = ask;
       request.type_filling = ORDER_FILLING_FOK;
       request.sl = 0;
       request.tp = 0;
       request.deviation = 50;
             
       OrderSend(request,result);
       
       if (result.retcode == TRADE_RETCODE_PLACED || result.retcode == TRADE_RETCODE_DONE) 
       {     
              request.action = TRADE_ACTION_SLTP;
              do Sleep(100); while(PositionSelect(_Symbol) == false); double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);

              if(Inp_sl > 0) request.sl = positionOpenPrice - (Inp_sl * _Point);
              if(Inp_tp > 0) request.tp = positionOpenPrice + (Inp_tp * _Point);
              if(request.sl > 0 && request.tp > 0) OrderSend(request,result);
              
              glBuyPlaced = true;
              glSellPlaced = false;
              
        }

      
    }
    
    
    else if((diff==1) && (glSellPlaced == false) && (positionType != POSITION_TYPE_SELL))
    {
    
                request.action = TRADE_ACTION_DEAL;
                request.type = ORDER_TYPE_SELL;
                request.symbol = _Symbol;
                request.volume = 1 + currVolume;
                request.type_filling = ORDER_FILLING_FOK;
                request.price = bid;
                request.sl = 0;
                request.tp = 0;
                request.deviation = 50;
                
                OrderSend(request,result);
     
                if((result.retcode == TRADE_RETCODE_PLACED || result.retcode == TRADE_RETCODE_DONE) && (Inp_sl > 0 || Inp_tp > 0))
                {
                
                    request.action = TRADE_ACTION_SLTP;
                    do Sleep(100); while(PositionSelect(_Symbol) == false);
                    double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
                    if(Inp_sl > 0) request.sl = positionOpenPrice + (Inp_sl * _Point);
                    if(Inp_tp > 0) request.tp = positionOpenPrice - (Inp_tp * _Point);


                    if(request.sl > 0 && request.tp > 0) OrderSend(request,result);
                    
                    glBuyPlaced = false;
                    glSellPlaced = true;
                    
                    
                 }

    
    }
    
    
//---
   
  }
//+------------------------------------------------------------------+
//| Trade function                                                   |
//+------------------------------------------------------------------+
void OnTrade()
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Tester function                                                  |
//+------------------------------------------------------------------+
double OnTester()
  {


   double ret=0.0;
//--- get trade results to the array
   double array[];
   double trades_volume;
   GetTradeResultsToArray(array,trades_volume);
   int trades=ArraySize(array);
//--- if there are less than 10 trades, test yields no positive results
   if(trades<10)
      return (0);
//--- average result per trade
   double average_pl=0;
   for(int i=0;i<ArraySize(array);i++)
      average_pl+=array[i];
   average_pl/=trades;
//--- display the message for the single-test mode
   if(MQLInfoInteger(MQL_TESTER) && !MQLInfoInteger(MQL_OPTIMIZATION))
      PrintFormat("%s: Trades=%d, Average profit=%.2f",__FUNCTION__,trades,average_pl);
//--- calculate linear regression ratios for the profit graph
   double a,b,std_error;
   double chart[];
   if(!CalculateLinearRegression(array,chart,a,b))
      return (0);
//--- calculate the error of the chart deviation from the regression line
   if(!CalculateStdError(chart,a,b,std_error))
      return (0);
//--- calculate the ratio of trend profits to the standard deviation
   ret=(std_error == 0.0) ? a*trades : a*trades/std_error;
//--- return custom criterion optimization value
   return(ret);
}

bool GetTradeResultsToArray(double &pl_results[],double &volume)
  {
//--- request the complete trading history
   if(!HistorySelect(0,TimeCurrent()))
      return (false);
   uint total_deals=HistoryDealsTotal();
   volume=0;
//--- set the initial size of the array with a margin - by the number of deals in history
   ArrayResize(pl_results,total_deals);
//--- counter of deals that fix the trading result - profit or loss
   int counter=0;
   ulong ticket_history_deal=0;
//--- go through all deals
   for(uint i=0;i<total_deals;i++)
     {
      //--- select a deal 
      if((ticket_history_deal=HistoryDealGetTicket(i))>0)
        {
         ENUM_DEAL_ENTRY deal_entry  =(ENUM_DEAL_ENTRY)HistoryDealGetInteger(ticket_history_deal,DEAL_ENTRY);
         long            deal_type   =HistoryDealGetInteger(ticket_history_deal,DEAL_TYPE);
         double          deal_profit =HistoryDealGetDouble(ticket_history_deal,DEAL_PROFIT);
         double          deal_volume =HistoryDealGetDouble(ticket_history_deal,DEAL_VOLUME);
         //--- we are only interested in trading operations        
         if((deal_type!=DEAL_TYPE_BUY) && (deal_type!=DEAL_TYPE_SELL))
            continue;
         //--- only deals that fix profits/losses
         if(deal_entry!=DEAL_ENTRY_IN)
           {
            //--- write the trading result to the array and increase the counter of deals
            pl_results[counter]=deal_profit;
            volume+=deal_volume;
            counter++;
           }
        }
     }
//--- set the final size of the array
   ArrayResize(pl_results,counter);
   return (true);
  } 
  
  
  bool CalculateLinearRegression(double  &change[],double &chartline[],
                               double  &a_coef,double  &b_coef)
  {
//--- check for data sufficiency
   if(ArraySize(change)<3)
      return (false);
//--- create a chart array with an accumulation
   int N=ArraySize(change);
   ArrayResize(chartline,N);
   chartline[0]=change[0];
   for(int i=1;i<N;i++)
      chartline[i]=chartline[i-1]+change[i];
//--- now, calculate regression ratios
   double x=0,y=0,x2=0,xy=0;
   for(int i=0;i<N;i++)
     {
      x=x+i;
      y=y+chartline[i];
      xy=xy+i*chartline[i];
      x2=x2+i*i;
     }
   a_coef=(N*xy-x*y)/(N*x2-x*x);
   b_coef=(y-a_coef*x)/N;
//---
   return (true);
  }
//+------------------------------------------------------------------+
//|  Calculate mean-square deviation error for specified a and b     |
//+------------------------------------------------------------------+
bool  CalculateStdError(double  &data[],double  a_coef,double  b_coef,double &std_err)
  {
//--- sum of error squares
   double error=0;
   int N=ArraySize(data);
   if(N<=2)
      return (false);
   for(int i=0;i<N;i++)
      error+=MathPow(a_coef*i+b_coef-data[i],2);
   std_err=MathSqrt(error/(N-2));
//--- 
   return (true);}


The condition have obsiouly no meaning, was an attempt to simplify it and being sure the problem was not there.

This should be the most basic, naive, model for an EA, can not get why it doesn´t work. Trying to backtesting no trade at all takes place, and with MT5 I don´t know any way to debug it via the strategy tester: with optimization (is there a way to disable ti in MT5?) no "Print", "Comment", "PlaySound" are possible.

Any hint would be appreciated... Thanks!

 
Please read the help. The indicator handle is created ONCE - and this is done in OnInit.
 

Thanks, that´s correct. But still does not work. All passed results are zeros, and it is not possible that the condition had never matched, neither for buy nor for sell. There must be an error in the structure. Here is the code with the proper condition:


    int diff = bfast[0]-bslow[0];
 
       
    
    if( (diff=0) && (bfast[1]<bslow[1]) && (glBuyPlaced = false) && ((positionType != POSITION_TYPE_BUY) || (openPosition == false)))
    {
       
       request.action = TRADE_ACTION_DEAL;
       request.symbol = _Symbol;
       request.volume = 1+currVolume;
       request.price = ask;
       request.type_filling = ORDER_FILLING_FOK;
       request.sl = 0;
       request.tp = 0;
       request.deviation = 50;
             
       OrderSend(request,result);
       
       if (result.retcode == TRADE_RETCODE_PLACED || result.retcode == TRADE_RETCODE_DONE) 
       {     
              request.action = TRADE_ACTION_SLTP;
              do Sleep(100); while(PositionSelect(_Symbol) == false); double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);

              if(Inp_sl > 0) request.sl = positionOpenPrice - (Inp_sl * _Point);
              if(Inp_tp > 0) request.tp = positionOpenPrice + (Inp_tp * _Point);
              if(request.sl > 0 && request.tp > 0) OrderSend(request,result);
              
              glBuyPlaced = true;
              glSellPlaced = false;
              
        }

      
    }
    
    
    else if((diff==0) && (bfast[1]-bslow[1]>0) && (glSellPlaced == false) && (positionType != POSITION_TYPE_SELL))
    {
    
                request.action = TRADE_ACTION_DEAL;
                request.type = ORDER_TYPE_SELL;
                request.symbol = _Symbol;
                request.volume = 1 + currVolume;
                request.type_filling = ORDER_FILLING_FOK;
                request.price = bid;
                request.sl = 0;
                request.tp = 0;
                request.deviation = 50;
                
                OrderSend(request,result);
     
                if((result.retcode == TRADE_RETCODE_PLACED || result.retcode == TRADE_RETCODE_DONE) && (Inp_sl > 0 || Inp_tp > 0))
                {
                
                    request.action = TRADE_ACTION_SLTP;
                    do Sleep(100); while(PositionSelect(_Symbol) == false);
                    double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
                    if(Inp_sl > 0) request.sl = positionOpenPrice + (Inp_sl * _Point);
                    if(Inp_tp > 0) request.tp = positionOpenPrice - (Inp_tp * _Point);


                    if(request.sl > 0 && request.tp > 0) OrderSend(request,result);
                    
                    glBuyPlaced = false;
                    glSellPlaced = true;
                    
                    
                 }

    
    }


Also, I received an "Array out of range" error while trying to test, in the rows in which bfast[1] and bslow[1] were present. I thought the size of the buffer was the problem (0) and added these lines in OnIit()


ArrayResize(bfast,2,0);
ArrayResize(bslow,2,0);


Does it makes sense to you? How can I even debug without "Comment" or "Print"..?

 
Davide Cosentino :

Thanks, that´s correct. But still does not work. All passed results are zeros, and it is not possible that the condition had never matched, neither for buy nor for sell. There must be an error in the structure. Here is the code with the proper condition:



Also, I received an " Array out of range " error while trying to test, in the rows in which bfast[1] and bslow[1] were present. I thought the size of the buffer was the problem (0) and added these lines in OnIit()



Does it makes sense to you? How can I even debug without "Comment" or "Print"..?

Please correct errors and attach the full file (using the button )

 
I already moved the definition of handlers in OnInit(). Attached the file
Files:
Prova.mq5  10 kb
 
Davide Cosentino :
I already moved the definition of handlers in OnInit(). Attached the file

Senseless code - you just took the code and jotted it all together.


You have declared two arrays

 int hfast,hslow;
 double bfast[],bslow[];
 //+------------------------------------------------------------------+
 //| Expert initialization function                                   |
 //+------------------------------------------------------------------+
 int OnInit ()

as I understand it, they should contain the values of the indicators - but you NEVER even try to get data from the indicators. Correct this error and re-attach the full advisor.

 


I moved the lines with the CopyBuffer function in OnTick(), if I got your hint.

If you meant instead I don´t even retrieve data from indicators, then

hfast = iMA(_Symbol,_Period,Inp_FastMA,0,MODE_SMMA,PRICE_CLOSE);
hslow = iMA(_Symbol,_Period,Inp_SlowMA,0,MODE_SMMA,PRICE_CLOSE);

I am not sure what is wrong with that..

Thanks!

Files:
Prova.mq5  10 kb
 
Davide Cosentino :


I moved the lines with the CopyBuffer function in OnTick(), if I got your hint.

If you meant instead I don´t even retrieve data from indicators, then

I am not sure what is wrong with that..

Thanks!

Array indexing starts at '0'.

 

We all agree on this, an bfast[1] should contain the value of the previous tick. Right?

 
Davide Cosentino :

We all agree on this, an bfast[1] should contain the value of the previous tick. Right?

For ordinary people, yes, but not in your case.

You FORGOT about ArraySetAsSeries (xxxx, true). You copy ONLY one item from the indicator and then try to access index [1].

 

OK.. count is the amount to be copied, not some kind of step! Silly msitake. But still:

int OnInit()
  {
    hfast = iMA(_Symbol,_Period,Inp_SlowMA,0,MODE_SMMA,PRICE_CLOSE);
    hslow = iMA(_Symbol,_Period,Inp_SlowMA,0,MODE_SMMA,PRICE_CLOSE);
     
    
   
//---

   
//---
   return(INIT_SUCCEEDED);
  }

// [...]

void OnTick()
  { 
  
 // [...]
    
CopyBuffer(hfast,0,0,3,bfast);
    CopyBuffer(hslow,0,0,3,bslow);
    
    ArraySetAsSeries(bfast,true);
    ArraySetAsSeries(bslow,true);


all variables are defined globally.


Handler is "loaded", arrays normalized with the first value corresponding to the latest tick, arrays filled with CopyBuffer. At this point b[0], b[1] and b[2] have a value. At the second tick b[0] will have the new value and b[1] would still be the previous value, because of ArraySetAsSeries after CopyBuffer function. Still results al

Reason: