Discussion of article "LifeHack for traders: Blending ForEach with defines (#define)"

 

New article LifeHack for traders: Blending ForEach with defines (#define) has been published:

The article is an intermediate step for those who still writes in MQL4 and has no desire to switch to MQL5. We continue to search for opportunities to write code in MQL4 style. This time, we will look into the macro substitution of the #define preprocessor.

Creating Expert Advisors almost always entails a lot of work with loops. Loops surround us everywhere: searching orders, trades in history, chart objects, Market Watch symbols, bars in an indicator buffer. To make a programmer's life a bit easier, MetaEditor features snippets meaning that when you enter the first characters, they automatically turn into a small piece of code after pressing Tab. This is how the 'for' loop snippet works:

Author: Vladimir Karputov

 
To the piggy bank

Forum on trading, automated trading systems and testing trading strategies

Libraries: CDouble & CDoubleVector

amrali, 2018.02.12 23:53

#define  forEach(element, array)  for (int __i = 0, __max = ArraySize((array)); __i < __max && ((element) = array[__i]) == (element); __i++)
Everything needs to be stuffed into the internals of for, so that you can call forEach repeatedly. Otherwise it will be a bummer with redefined variables.
 
HistorySelect before TimeCurrent is a typical error. Since the significance of the statements for someone may depend on the author, here is a set of quotes

Forum on trading, automated trading systems and testing trading strategies

FORTS. Questions on execution

Renat Fatkhullin, 2015.02.10 08:16

I haven't run the code yet, but the source code shows the classic error of wrong end date in HistorySelect.

Every first programmer calls this function with wrong date, constantly snacks the end of history and detects "long time trade getting into history".

Forum on trading, automated trading systems and testing trading strategies

FORTS. Questions on execution

Renat Fatkhullin, 2015.02.10 09:15

The mistake is that people do not think about what the current moment is and substitute the wrong date taken from the wrong source.

It is enough to specify a known distant date as the end date, not the obsolete serverTime.

Forum on trading, automated trading systems and testing trading strategies

FORTS. Questions on execution

Renat Fatkhullin, 2015.02.10 13:56

And the start and end date should be set with the realisation of errors and with a mandatory margin. That is, minus N sec and plus N sec as a minimum.

TimeTradeServer() is not a rltime accurate time, but is updated solely on price ticks coming into the market overview.


If you suddenly have no data in the history sample, it means 99% that the error is in the query boundaries.

HistorySelect(0, LONG_MAX);
 

Предопределённые переменные _XXXX переводятся в функции MQL5 при помощи беспараметрической формы #define:

//--- the _Digits variable stores number of digits after a decimal point,
#define _Digits         Digits()
Why?! Moreover, with such a macro you cannot use _Digits as an input parameter of some functions. That is, the code will cease to work.
 
//--- the latest known seller's price (ask price) for the current symbol 
double GetAsk()
  {
   MqlTick tick;
   SymbolInfoTick(Symbol(),tick);
   return(tick.ask);
  }

Terribly expensive! If you really want to do it through the structure, you should have at least done it. And there is no check for some reason.

SymbolInfoDouble is fully compliant with MT4.

 
#define IsTradeContextBusy  true

Huh?

maybe false?
 
For MarketInfo it is better to use the approach via enumerations + overloads

Forum on trading, automated trading systems and testing trading strategies.

Expert Advisors: Quantum 103

fxsaber, 2017.09.26 09:55 pm.

bool RefreshRates( void ) { return(true); }

double MarketInfo( const string Symb, const ENUM_SYMBOL_INFO_DOUBLE Property )  { return(SymbolInfoDouble(Symb, Property)); }
int    MarketInfo( const string Symb, const ENUM_SYMBOL_INFO_INTEGER Property ) { return((int)SymbolInfoInteger(Symb, Property)); }

bool IsTesting(void)            { return(MQLInfoInteger(MQL_TESTER) || MQLInfoInteger(MQL_OPTIMIZATION)); }
bool IsTradeContextBusy( void ) { return(false); }
bool IsTradeAllowed(void)       { return(MQLInfoInteger(MQL_TRADE_ALLOWED)); }
bool IsExpertEnabled(void)      { return(AccountInfoInteger(ACCOUNT_TRADE_EXPERT)); }

int    ObjectFind( const string Name )   { return(ObjectFind(0, Name)); }
int    ObjectsTotal( void )              { return(ObjectsTotal(0)); }
bool   ObjectDelete( const string Name ) { return(ObjectDelete(0, Name)); }
string ObjectName( const int Pos )       { return(ObjectName(0, Pos)); }

double AccountFreeMarginCheck(const string Symb,const int Cmd,const double dVolume)
{
 double Margin;

 return(OrderCalcMargin((ENUM_ORDER_TYPE)Cmd, Symb, dVolume,
        SymbolInfoDouble(Symb, (Cmd == ORDER_TYPE_BUY) ? SYMBOL_ASK : SYMBOL_BID), Margin) ?
        AccountInfoDouble(ACCOUNT_MARGIN_FREE) - Margin : -1);
}

#define False false
#define True  true

#define Digits _Digits
#define Point  _Point

#define MODE_BID       SYMBOL_BID
#define MODE_ASK       SYMBOL_ASK
#define MODE_POINT     SYMBOL_POINT
#define MODE_DIGITS    SYMBOL_DIGITS
#define MODE_STOPLEVEL SYMBOL_TRADE_STOPS_LEVEL
#define MODE_SPREAD    SYMBOL_SPREAD

#define StrToTime    StringToTime
#define StrToInteger StringToInteger
#define TimeToStr    TimeToString
#define DoubleToStr  DoubleToString

#define Bid SymbolInfoDouble(_Symbol, SYMBOL_BID)
#define Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)
 
Only simplified trading functions of MQL4 are missing for full compatibility. But even this issue can be solved if desired.
To do this, you need to understand both architectures very well. Not everything is still obvious.
 

fxsaber:
В копилку

#define  forEach(element, array)  for (int __i = 0, __max = ArraySize((array)); __i < __max && ((element) = array[__i]) == (element); __i++)

Interesting and non-obvious technique )

[Deleted]  

How many twisted things can you do?

Define is a stupid substitution of one text for another. There's no power in them!

Better try to do the same thing on templates.

 
Koldun Zloy:

How many times can you do this?

Define is a stupid substitution of one text for another. There's no power in them!

Less writing is sometimes convenient

Better try to do the same thing on templates.

It's just a question of feasibility, usability and performance.