Expert Advisors: Successful EA's Hints & Tricks

 
Ever wonder why your EA does not sell on market? Only very few comment about it? So, this is the place to share experiences on how you changed your EA to make it useful! Or not... :P
 

Hi!

I have a hint: most people try to use, at least once, outside Metatrader Demo account. Not just only FOREX, but also Equities, Derivatives, options and many other instruments. So, before trying to sell an EA, have you tested it against a real FOREX account, at least? Or tried it on equities? What about netting accounts? Does it work? Always make these questions before thinking your EA is the "Holy Grail".

 

Hint on volumes:

I make these lines of code present on all my EA's:

input uint InpVolume = 1; // Volume
double ExtVolume;
int OnInit()
  {
   ExtVolume=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN)+MathMax(InpVolume-1,0)*SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
  }

I hope the above lines will help your EA work on any financial instrument.

 

Another hint: I've seen people using indicators to set order prices :P

Sou, most people use NormalizeDouble(). However, all transaction prices must be integer multiple of it's own Tick Size... So?

There's a function called NormalizePrice(). What it does is simply dividing by Tick Size (minimal price change), flooring/rounding the price, and then multiply by tick size again, normalizing double. Sweet as an apple pie.

#include <Trade\SymbolInfo.mqh>
CSymbolInfo _CSymbolInfo;
_CSymbolInfo.NormalizePrice(your price goes here)

Source code:

//+------------------------------------------------------------------+
//| Normalize price                                                  |
//+------------------------------------------------------------------+
double CSymbolInfo::NormalizePrice(const double price) const
  {
   if(m_tick_size!=0)
      return(NormalizeDouble(MathRound(price/m_tick_size)*m_tick_size,m_digits));
//---
   return(NormalizeDouble(price,m_digits));
  }

If you do not want to include SymbolInfo.mqh, because I mostly need TickSize info everywhere to make EA's compatible with different market and brokers, try the following:

static double _TickSize;
int OnInit()
  {
   _TickSize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
   return(INIT_SUCCEEDED);
  }

And use it everywhere.

 
Arthur Albano:

Hint on volumes:

I make these lines of code present on all my EA's:

I hope the above lines will help your EA work on any financial instrument.

A more robust version of volume:

#define ReLU(a) (a>0?a:0)
sinput uint InpVolume = 1; //Volume
double ExtVolume;
int OnInit()
  {
   ExtVolume = MathMin(SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN)+ReLU(InpVolume-1)*SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP),SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX));
   return(INIT_SUCCEEDED);
  }
 
Arthur Albano:

A more robust version of volume:

Not correct. Try it :-D

2018.11.25 18:56:44.766    291656 (PETR4,M15)    Volume: Input = 10  Output = 1000.00

 
Alain Verleyen:

Not correct. Try it :-D

2018.11.25 18:56:44.766    291656 (PETR4,M15)    Volume: Input = 10  Output = 1000.00




Well, It worked, as volumes are multiples of 100...

 
Alain Verleyen:

Not correct. Try it :-D

2018.11.25 18:56:44.766    291656 (PETR4,M15)    Volume: Input = 10  Output = 1000.00

EURUSD



 
Arthur Albano:

Another hint: I've seen people using indicators to set order prices :P

Sou, most people use NormalizeDouble(). However, all transaction prices must be integer multiple of it's own Tick Size... So?

There's a function called NormalizePrice(). What it does is simply dividing by Tick Size (minimal price change), flooring/rounding the price, and then multiply by tick size again, normalizing double. Sweet as an apple pie.

Source code:

If you do not want to include SymbolInfo.mqh, because I mostly need TickSize info everywhere to make EA's compatible with different market and brokers, try the following:

And use it everywhere.

One can also use macro to normalize prices:

//--- Normalize Price
#define NP(a,b) (b!=0?int(a/b)*b:a)

input double InpPrice = 1.4234764368276428764 // Price

static double   _TickSize;
MqlTradeRequest _MqlTradeRequest;

int OnInit()
  {
   _TickSize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
   return(INIT_SUCCEEDED);
  }
void OnTick()
  {
   _MqlTradeRequest.price = NP(InpPrice,_TickSize);
  }
 
Arthur Albano:




Well, It worked, as volumes are multiples of 100...

You request 10 and you get 1000 and you find it works ?
 
Alain Verleyen:
You request 10 and you get 1000 and you find it works ?
In the past they didn't work with cents, so standard volume was 1000... :P