MQL4: Пишем один советник сразу для MT4 и MT5

Приветствую вас, друзья!
Многие из вас наверняка уже не раз сталкивались с таким неудобством: написали советник на языке mql4, а потом захотелось попробовать поиграться с ним в MetaTrader 5. Переписывать заново весь код - довольно кропотливое и долгое занятие, к тому же приходится сначала разобраться с работой уже имеющегося. Писать два разных советника отдельно для MT4 и для MT5 - тоже накладно по времени. Именно эту задачу мы с вами сегодня и решим в новом видео уроке.
Итак, что же делать? Ответ прост - написать один советник сразу для двух терминалов. Ведь по большей части языки mql4 и mql5 отличаются не так уж и сильно, многие методы и основная структура у скриптов на этих языках схожая. Если бы можно было писать общий код в одном скрипте, а отличающиеся участки просто каким-то образом переписать на обоих языках и заставить компилятор самому выбрать нужные куски кода, это сэкономило бы кучу времени и нервов.
К счастью, MetaEditor поддерживает директивы условной компиляции препроцессора. И сегодня мы на очень простом примере рассмотрим, как это делается.
#ifdef identifier // код, находящийся здесь, компилируется, если identifier уже был определен для препроцессора в команде #define. #endif
В коде для МТ5 будем заменять переменные из MQL4 c помощью директивы #define:
#ifdef __MQL5__ #define OrdersTotal PositionsTotal #endif
В шапке советника поместим входные переменные:
input int Stop = 300; input int Take = 400; input int Slip = 100; input int MN = 123; input double LT = 0.1;
Теперь можно написать методы для покупки и продажи:
bool Buy(double price,double sl,double tp)
{
#ifdef __MQL4__
int ticket = OrderSend(Symbol(), 0, LT, price, Slip, sl, tp, "", MN);
if (ticket<0) {
PrintFormat("OrderSend error %d",GetLastError());
}
#endif
#ifdef __MQL5__
//--- объявление и инициализация запроса и результата
MqlTradeRequest request = {0};
MqlTradeResult result = {0};
//--- параметры запроса
request.action =TRADE_ACTION_DEAL; // тип торговой операции
request.symbol =Symbol(); // символ
request.volume =LT; // объем
request.type =0; // тип ордера
request.price =price; // цена для открытия
request.sl =sl; // цена StopLoss
request.tp =tp; // цена TakeProfit
request.deviation=Slip; // допустимое отклонение от цены
request.magic =MN; // MagicNumber ордера
//--- отправка запроса
if (!OrderSend(request, result)) {
// если отправить запрос не удалось, вывести код ошибки
PrintFormat("OrderSend error %d", GetLastError());
}
//--- информация об операции
PrintFormat("retcode=%u deal=%I64u order=%I64u",
result.retcode, result.deal, result.order);
#endif
//---
return(false);
}
Метод для продажи подобен методу buy(). Над стратегией в данном примере думать особо не будем, получим условие на открытие случайным образом и поместим этот код в OnTick():
int oper=(int)(GetTickCount() % 2); // остаток от деления на два всегда либо 0 либо 1
if (oper == 0) {
double price = Ask;
double SL = NormalizeDouble(Bid - Stop * _Point, _Digits);
double TP = NormalizeDouble(Bid + Take * _Point, _Digits);
Buy(Ask, SL, TP);
}
if (oper == 1) {
double price = Bid;
double SL = NormalizeDouble(Ask + Stop *_Point, _Digits);
double TP = NormalizeDouble(Ask - Take *_Point, _Digits);
Sell(Ask, SL, TP);
}
Заключение

Вот и все. Теперь можно компилировать код в MetaEditor 4 и в терминале MetaTrader 4 он будет работать. Можно скомпилировать советник в MetaEditor 5 и он будет нормально работать в терминале MetaTrader 5. При всем при этом для смены терминала не нужно переписывать ни строчки кода - все будет нормально компилироваться и работать.
С уважением, Дмитрий аkа Silentspec
TradeLikeaPro.ru