Обсуждение статьи "LifeHack для трейдера: замешиваем ForEach на дефайнах (#define)"

 

Опубликована статья LifeHack для трейдера: замешиваем ForEach на дефайнах (#define):

Промежуточная ступенька для тех, кто всё ещё пишет на MQL4, но никак не может перейти на MQL5. Мы продолжаем искать возможности для написания кода в стиле MQL4. На этот раз рассмотрим макроподстановку препроцессора — #define.

Создание советников или торговых роботов — это почти всегда много работы с циклами. Циклы окружают нас везде: перебор ордеров, сделок в истории, объектов на графике, символов в Обзоре рынка, баров в индикаторном буфере. И чтобы немного облегчить жизнь программиста, в MetaEditor добавлены сниппеты — это когда вы набираете начальные символы, и по нажатию Tab они автоматически разворачиваются в небольшой кусок кода. Вот как работает сниппет для цикла for:

Автор: Vladimir Karputov

 
В копилку

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++)
Все нужно запихивать во внутренности for, чтобы можно было forEach вызывать повторно. Иначе будет облом с заново определяемыми переменными.
 
HistorySelect до TimeCurrent - типичная ошибка. Поскольку значимость заявлений для кого-то может зависеть от автора, привожу набор цитат

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

ФОРТС. Вопросы по исполнению

Renat Fatkhullin, 2015.02.10 08:16

Код еще не запускал, но исходнику видна классическая ошибка неправильной конечной даты в HistorySelect.

Каждый первый программист вызывает эту функцию с неправильной датой, постоянно закусывает конец истории и обнаруживает "долгое попадание сделки в историю". 

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

ФОРТС. Вопросы по исполнению

Renat Fatkhullin, 2015.02.10 09:15

Вот ошибка как раз в том, что люди не задумываются, что такое текущий момент и подставляют туда неправильную дату, взятую с неправильного источника.

Достаточно указать в качестве конечной заведомо дальнюю дату, а не устаревший serverTime.

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

ФОРТС. Вопросы по исполнению

Renat Fatkhullin, 2015.02.10 13:56

И начальная и конечная дата должна устанавливаться с осознанием погрешностей и с обязательным запасом. То есть минус N сек и плюс N сек как минимум.

TimeTradeServer() - это не рилтайм точное время, а обновляется исключительно по ценовым тикам, приходящим в обзор рынка.


Если у вас в выборке истории вдруг нет данных, значит 99% что ошибка в границах запроса.

HistorySelect(0, LONG_MAX);
 

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

//--- the _Digits variable stores number of digits after a decimal point,
#define _Digits         Digits()
Зачем?! Более того, с таким макросом нельзя использовать _Digits в качестве входного параметра некоторых функций. Т.е. код перестанет быть рабочим.
 
//--- the latest known seller's price (ask price) for the current symbol                  
double GetAsk()
  {
   MqlTick tick;
   SymbolInfoTick(Symbol(),tick);
   return(tick.ask);
  }

Жутко дорого! Если очень хочется через структуру, то надо было ее хотя бы static делать. И проверки по какой-то причине нет.

SymbolInfoDouble полностью соответствует MT4.

 
#define IsTradeContextBusy  true

эээ?

может все-таки false?
 
Для MarketInfo лучше использовать подход через перечисления + перегрузки

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Советники: Quantum 103

fxsaber, 2017.09.26 09:55

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)
 
Для полной совместимости не хватает только упрощенных торговых функций MQL4. Но и этот вопрос при желании решается.
Для этого нужно очень хорошо разбираться в обеих архитектурах. Далеко не все до сих пор очевидно.
 

fxsaber:
В копилку

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

Интересный и неочевидный прием )

 

Сколько можно извращаться?

Дефайн - это тупая замена одного текста другим. Никакой силы в них нет!

Лучше попробуйте тоже самое сделать на шаблонах.

 
Koldun Zloy:

Сколько можно извращаться?

Дефайн - это тупая замена одного текста другим. Никакой силы в них нет!

Меньше писанины - иногда удобно

Лучше попробуйте тоже самое сделать на шаблонах.

Вопрос только в целесообразности, удобстве использования и производительности.