made a 2 EMA cross EA, need advice

 

Hi there!

I am new to mql 4 and I made a simple 2 EMA cross advisor, which I have tested on demo account, but a little bit scared to get it on a real one

Testing it with small lots on 1h scale would take too much time, and testing it on minutes scales is expensive, because the minimal lot at my broker is about 7 usd.

So, I would be grateful if you take a look at it and may be point to some obvious mistakes I could have made.

This advisor is supposed to trade on Bitcoin/USD market which is extremly volatile (price can go + - 30% a day), so stop loss and take profit are not in pips but in percents of a bid or ask.

The variables and stuff:

#property copyright "me"
#property link      "killnosock.net"
extern int SlowEma = 21;
extern int FastEma = 10;
extern int MaxRisk = 100;// % of Depo to be traded per order
extern int  TakeProfit=100;
extern int  StopLoss=100;
extern int Slippage = 10;

int LastBars = 0;

int init(){return(0);}
int deinit() {return(0);}

This function is to determine the lot size, according to % of depo it is allowed to use per order (int Risk)

double GetLot(int Risk)
{double Free    =AccountFreeMargin();
 double One_Lot =MarketInfo(Symbol(),MODE_MARGINREQUIRED);
 double Min_Lot =MarketInfo(Symbol(),MODE_MINLOT);
 double Max_Lot =MarketInfo(Symbol(),MODE_MAXLOT);
 double Step    =MarketInfo(Symbol(),MODE_LOTSTEP);
 double Lot     =MathFloor(Free*Risk/100/One_Lot/Step)*Step;
 if(Lot<Min_Lot) Lot=Min_Lot;
 if(Lot>Max_Lot) Lot=Max_Lot;
 if(Lot*One_Lot>Free) {
 Alert(" free= ", AccountFreeMargin()," for one lot= ", MarketInfo(Symbol(),MODE_MARGINREQUIRED)," lot= ", Lot);
 return(0.0);}
return(Lot);}

This is the function that opens new order, Cmd is buy or sell

int NewOrder(int Cmd,double Lot)
{double TP=0; //takeprofit
 double SL=0; //stoploss
 double PR=0; //price
 color clr = CLR_NONE;
 while(!IsTradeAllowed()) Sleep(10);
 RefreshRates();
 if(Cmd==OP_BUY)
   {PR=Ask;
    if(TakeProfit>0) TP=Ask + Ask*TakeProfit/100;
    if(StopLoss>0) SL=Ask - Ask*StopLoss/100;
    if(SL<0) SL = 0;
    if(TP<0) TP = 0;
    clr = Green;}
 if(Cmd==OP_SELL)
   {PR=Bid;
    if(TakeProfit>0) TP=Bid - Bid*TakeProfit/100;
    if(StopLoss>0) SL=Bid + Bid*StopLoss/100;
    if(SL<0) SL = 0;
    if(TP<0) TP = 0;
    clr = Red;}
 int tic=OrderSend(Symbol(),Cmd,Lot,PR,Slippage,SL,TP,"",0,0,clr);
 if(tic<0) Print("Open order error: ",GetLastError());
return(tic);}

Here I close 1 order or close all orders:

//CloseOrder
void CloseOrder()
{double PR=0;
 while(!IsTradeAllowed()) Sleep(10);
 RefreshRates();
 if(OrderType()==OP_BUY)  PR=Bid;
 if(OrderType()==OP_SELL) PR=Ask;
 if(!OrderClose(OrderTicket(),OrderLots(),PR,Slippage,CLR_NONE))
   Print("Order close error: ",GetLastError());
return;}
//Close all Orders
void CloseAllOrders()
{
  for(int i=OrdersTotal()-1;i>=0;i--)
   if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
     {
      CloseOrder();
     }
return;}

This function is used to calculate fast and slow EMA difference (fast EMA - slow EMA):

double EmaDiff(int shift)
   {
      double difference;
      difference = iMA(Symbol(),0,FastEma,0,MODE_EMA,PRICE_CLOSE,shift)
                 - iMA(Symbol(),0,SlowEma,0,MODE_EMA,PRICE_CLOSE,shift);
      return(difference);
   }

And here goes the main body:

int start()
  {
double Lot;
    // check if new bar opened
    if (LastBars == Bars) return(0);
    else LastBars = Bars;
      {         
         if ((EmaDiff(1) > 0) && (EmaDiff(2) < 0))
            {
               CloseAllOrders();
               Lot = GetLot(MaxRisk);
               NewOrder(OP_BUY,Lot);
            }
            
         if ((EmaDiff(2) > 0) && (EmaDiff(1) < 0))
            {
               CloseAllOrders();
               Lot = GetLot(MaxRisk);
               NewOrder(OP_SELL,Lot);
            }                    
      }
   return(0);
  }

I am going to add a trailing stop, and consider comparing EmaDiff not to zero but to some small walue not to get chopped uo when slow and fast EMA get very close to each other and intersect every bar.

 
 //CloseOrder
void CloseOrder()
{double PR=0;
 while(!IsTradeAllowed()) Sleep(10);
 RefreshRates();
 if(OrderType()==OP_BUY)  PR=Bid;
 if(OrderType()==OP_SELL) PR=Ask;
 if(!OrderClose(OrderTicket(),OrderLots(),PR,Slippage,CLR_NONE))
   Print("Order close error: ",GetLastError());
return;}



//Close all Orders
void CloseAllOrders()
{
  for(int i=OrdersTotal()-1;i>=0;i--)
   if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
     {
      CloseOrder();
     }
return;}

not checking symbol not checking a magicnumber....

then what will happen using it live with different EA's on it ???

 
deVries:

not checking symbol not checking a magicnumber....

then what will happen using it live with different EA's on it ???


Do you mean running two EA's from 1 account?
 
prupru:

Do you mean running two EA's from 1 account?
Two EAs or one EA and manually placed trades . . . or just manually placed trades.
 
prupru:

Hi there!

I am new to mql 4 and I made a simple 2 EMA cross advisor, which I have tested on demo account, but a little bit scared to get it on a real one

Testing it with small lots on 1h scale would take too much time, and testing it on minutes scales is expensive, because the minimal lot at my broker is about 7 usd.

So, I would be grateful if you take a look at it and may be point to some obvious mistakes I could have made.

It's good to see somone checking trading function return values without being prompted to do so . . . but you need more information if you get an error so that you can diagnose what caused the issue, you cannot go back in time in alive situation to check what the Spread was or what the Freeze level was at the time . . .

if(tic < 0) Print("Open order error: ", GetLastError());

. . . this is good but you need more, what variables will you need to print so that you can determine the cause of any error you get ? when you have determined what you might need add them all into your Print() call making sure you use the correct number of decimals (DoubeToStr(value, digits)) for any double variables such as Ask, Bid, etc

 
RaptorUK:

It's good to see somone checking trading function return values without being prompted to do so . . .

Sorry, but I didn't understand that part. The only thing I got is that I need to add as much variables as I can to Print() call. Point taken, thank you.

deVries, thanks for your advice too, now I understand what you mean.

Is there anything else to be fixed?

 

ofcours there is

    // check if new bar opened
    if (LastBars == Bars) return(0);
    else LastBars = Bars;

suppose you have already maximum bars (there is a limit).....

 
deVries:

ofcours there is

suppose you have already maximum bars (there is a limit).....


ok, so how do I better catch the moment when a new candle opens?
 
prupru:

ok, so how do I better catch the moment when a new candle opens?


check the time of the latest bar Time[0]

search for NewBar and you find some examples

 
deVries:


check the time of the latest bar Time[0]

search for NewBar and you find some examples


thanks, I found this https://www.mql5.com/en/code/10370

 
 if(Cmd==OP_BUY)
   {PR=Ask;
    if(TakeProfit>0) TP=Ask + Ask*TakeProfit/100;
    if(StopLoss>0) SL=Ask - Ask*StopLoss/100;
    if(SL<0) SL = 0;
    if(TP<0) TP = 0;
    clr = Green;}

I don't think this is right

how do you get 100 pips takeprofit and 150 pips Stoploss ???

update see " so stop loss and take profit are not in pips but in percents of a bid or ask. "

still do you get a valid price that way ... if your symbol has 5 digits the outcome will be often 2 digits more

Reason: