OpenPosition() для MQL5

 

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

//+----------------------------------------------------------------------------+
//|  Версия   : 21.06.2010                                                     |
//|  Описание : Открывает позицию и возвращает её тикет.                       |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    sy  - наименование инструмента   (NULL или "" - текущий символ)         |
//|    op  - операция (BUY или SELL)                                           |
//|    lot - лот                                                               |
//|    sl  - уровень стоп                                                      |
//|    tp  - уровень тейк                                                      |
//|    mn  - MagicNumber                                                       |
//+----------------------------------------------------------------------------+
int OpenPosition(string sy, ENUM_ORDER_TYPE op, double lot, double sl=0, double tp=0, int mn=0) {
   MqlTradeRequest trReq;     // Будет использоваться для отсылки торговых запросов
   MqlTradeResult  trRez;     // Будет использоваться для получения результатов выполнения торговых запросов
   MqlTick tick;              // Будет использоваться для текущих котировок
//---переменные ---------------------------------------------------------------+
int    Slippage      = 5;                // Проскальзывание цены

   ResetLastError();
   if(sy=="" || sy=="0") sy=Symbol();

// параметры по умолчанию для всех новых торговых запросов
   trReq.action = TRADE_ACTION_DEAL;                                  // немедленное исполнение
   trReq.type_time=ORDER_TIME_GTC;                                    // в очереди пока не будет снят
   trReq.type_filling = ORDER_FILLING_AON;                            // тип исполнения ордера - все или ничего
   trReq.deviation=Slippage;                                          // проскальзывание от текущей цены
   trReq.magic = mn;                                                  // Magic Number
   trReq.comment=""; 
   trReq.symbol = sy;                                                 // символ
   trReq.volume = lot;                                                // количество лотов для торговли
//--- Получить текущее значение котировки в структуру типа MqlTick
   if(!SymbolInfoTick(sy,tick))
     {
      Alert("Ошибка получения последних котировок - ошибка:",GetLastError());
      return(0);
     }
   if(op==ORDER_TYPE_BUY) {
      trReq.price = NormalizeDouble(tick.ask,_Digits);                   // последняя цена ask
      trReq.sl = NormalizeDouble(tick.ask - sl*_Point,_Digits);          // Stop Loss
      trReq.tp = NormalizeDouble(tick.ask + tp*_Point,_Digits);          // Take Profit
      trReq.type = ORDER_TYPE_BUY;                                       // ордер на покупку
   }
   if(op==ORDER_TYPE_SELL)  {
      trReq.price = NormalizeDouble(tick.bid,_Digits);                   // последняя цена Bid
      trReq.sl = NormalizeDouble(tick.bid + sl*_Point,_Digits);          // Stop Loss
      trReq.tp = NormalizeDouble(tick.bid - tp*_Point,_Digits);          // Take Profit
      trReq.type= ORDER_TYPE_SELL;                                       // ордер на продажу
   }
//--- сбросим код последней ошибки в ноль
   ResetLastError();
//--- отправим запрос
   OrderSend(trReq,trRez);
   // анализируем код возврата торгового сервера
   int answer=trRez.retcode;
   if(answer==10009 || answer==10008) //все ок, ордер принят или выполнен
      {
      //Alert("Ордер "+op+" успешно размещен);
      }
   else  //--- если результат неудачный - попробуем узнать в чем дело
      {
      Print("Ошибка ордер ",op, " - код ошибки:",GetLastError()," request.price=",trReq.price," result.ask=",trRez.ask," result.bid=",trRez.bid,
            " request.sl =",trReq.sl," request.tp =",trReq.tp," request.volume=",trReq.volume,
            " result.volume=",trRez.volume," result.comment=",trRez.comment);
      switch(answer)
        {
         //--- реквота
         case 10004:
           {
            //Print("TRADE_RETCODE_REQUOTE");
            break;
           }
         //--- ордер не принят сервером
         case 10006:
           {
            //Print("TRADE_RETCODE_REJECT");
            break;
           }
         //--- неправильная цена
         case 10015:
           {
            //Print("TRADE_RETCODE_INVALID_PRICE");
            break;
           }
         //--- неправильный SL и/или TP
         case 10016:
           {
            //Print("TRADE_RETCODE_INVALID_STOPS");
            break;
           }
         //--- некорректный объем
         case 10014:
           {
            //Print("TRADE_RETCODE_INVALID_VOLUME");
            break;
           }
         //--- не хватает денег на торговую операцию  
         case 10019:
           {
            //Print("TRADE_RETCODE_NO_MONEY");
            break;
           }
         //--- какая-то другая причина, сообщим код ответа сервера   
         default:
           {
            Print("Other answer =",answer);
           }
        }// end       switch(answer)
      //--- сообщим о неудачном результате торгового запроса возвратом 0
      return(0);
     } // end else

  return(trRez.order);
}
 
Предлагаю, обсудить не только данную функцию, но и все остальное связанное с торговой механикой-открытие, закрытие,модификация,удаление, различные механизмы трейлинг-стопа и т.д. И конечно реализовать все это с применением ООП, т.е. создать класс содержащий в себе различные методы для управления торговыми функциями. Что бы не казаться "пустословом", предлагаю свои наброски такого класса.  Думаю тема будет полезна и интересна всем.
Документация по MQL5: Торговые функции
Документация по MQL5: Торговые функции
  • www.mql5.com
Торговые функции - Документация по MQL5
Файлы:
tm.mqh  19 kb
 
В функцию передается sy, а нормализация по _Digits.
 

Да, надо использовать SymbolInfoInteger(sy,SYMBOL_DIGITS).

Кроме того, надо проверять стоп-лоссс и тэйк профит на 0 и устанавливать

trReq.sl, trRec.tp в 0
если они равны 0, иначе получим Ask для Buy и Bid для Sell с ошибкой:Неверные стопы.
 
Kos:
Предлагаю, обсудить не только данную функцию, но и все остальное связанное с торговой механикой-открытие, закрытие,модификация,удаление, различные механизмы трейлинг-стопа и т.д. И конечно реализовать все это с применением ООП, т.е. создать класс содержащий в себе различные методы для управления торговыми функциями. Что бы не казаться "пустословом", предлагаю свои наброски такого класса.  Думаю тема будет полезна и интересна всем.

А почему вместо false Вы используете NULL? Чем NULL лучше?
 
DC2008:
А почему вместо false Вы используете NULL? Чем NULL лучше?
Разницы никакой. false=NULL=0, это просто привычка:)
 
DC2008:
А почему вместо false Вы используете NULL? Чем NULL лучше?

NULL не привязан к конкретному типу данных, поэтому в определенных случая его использовать гораздо удобней.

Кроме того, применение именно NULL в коде делает этот код гораздо более восприимчивым для человека.

Документация по MQL5: Основы языка / Типы данных
Документация по MQL5: Основы языка / Типы данных
  • www.mql5.com
Основы языка / Типы данных - Документация по MQL5
 
Kos:
 Предлагаю ...

трудно мне пока с ООП, но вродебы CTradingManager::StopsIsInvalid   в коде 2 раза повторется. Скрипт бы где показывалось как это все использовать (как это работает) легче было бы разобраться
 
Prival:
трудно мне пока с ООП, но вродебы CTradingManager::StopsIsInvalid   в коде 2 раза повторется. Скрипт бы где показывалось как это все использовать (как это работает) легче было бы разобраться
bool  StopsIsInvalid(ENUM_POSITION_TYPE OPEN_POSITION,double Price,uchar OrderType=Loss);
bool  StopsIsInvalid(ENUM_ORDER_TYPE OPEN_ORDER,double Price,uchar OrderType=Loss);

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


 
Prival:
трудно мне пока с ООП, но вродебы CTradingManager::StopsIsInvalid   в коде 2 раза повторется. Скрипт бы где показывалось как это все использовать (как это работает) легче было бы разобраться
Это перегрузка функций. Первая функция проверяет StopsLevel при модификации рыночных позиций, вторая при установке ордеров.
Документация по MQL5: Основы языка / Функции / Перегрузка функций
Документация по MQL5: Основы языка / Функции / Перегрузка функций
  • www.mql5.com
Основы языка / Функции / Перегрузка функций - Документация по MQL5
 
Кстати код менеджера  был изменен, изменились некоторые функции...

Файлы:
tm.mqh  23 kb