Как изменить StopLoss активной сделки?

У меня возникли проблемы с изменением стоп-лосса текущей сделки с помощью MQL5. Выбор порядка работает для меня. Но если я попытаюсь получить доступ к переменным (например, OrderTicket() и OrderOpenPrice()), он всегда возвращает 0,00000:

2017.06.01 00:06:32.114 2016.04.08 00:00:00   failed modify  buy 0.00  sl: 0.00000, tp: 0.00000 -> sl: 1.41594, tp: 0.00000 [Invalid request]

Вот мой стоп-лосс, модифицирующий пустоту:

void modifyStops() {

   int total = OrdersTotal();          // total number of placed pending orders
   Print( total + " Orders on the line!!!" );

   //--- Over all placed pending orders
   for ( int i = 0; i <  total; i++ )
   {     bool isOrderSelected = OrderSelect( i, SELECT_BY_POS, MODE_TRADES );
         if (  isOrderSelected )
         {  // TODO: Check the Trades to contain the correct Order Number

               Print( "Symbol & Magicnumber matching" );
               double newStopLoss;

            // Update the stop loss
               if (  OrderType() == OP_BUY )
               {
                     newStopLoss = addTolerance( SL );
               } 
               else if (  OrderType() == OP_SELL )
               {
                          newStopLoss = minusTolerance( SL );
               }       
               newStopLoss = NormalizeDouble( newStopLoss, Digits );
               Print( "NEW STOP LOSS::::=====> ", Symbol(), " at ", newStopLoss );

               if ( !OrderModify( OrderTicket(), OrderOpenPrice(), newStopLoss, OrderTakeProfit(), 0, Green ) )
               {
                     Print( "OrderModify returned the error of ", GetLastError() );
               }  
     }
}

Класс CTrade у меня не работает должным образом. Я попытался реализовать код, который вы опубликовали, однако: похоже, он все еще не работает.

К сожалению, я реализовал это в своем советнике, и OrderGetTicket(i) возвращает ноль, когда сделка активна. Итак, моя пустота выглядит так:

void modifyStops() {
for(int i=0; i<PositionsTotal();i++) 
    {
    ulong ticket;
    if((ticket=PositionGetTicket(i))>0) 
        { 
         //--- return order properties 
         double open_price    =PositionGetDouble(POSITION_PRICE_OPEN); 
         datetime time_open     =(datetime)PositionGetInteger(POSITION_TIME); 
         string symbol        =PositionGetString(POSITION_SYMBOL); 
         int order_magic   =PositionGetInteger(POSITION_MAGIC); 
         double volume        =PositionGetDouble(POSITION_VOLUME); 
         double stoploss      =PositionGetDouble(POSITION_SL); 
         double takeprofit    =PositionGetDouble(POSITION_TP); 
         ENUM_ORDER_TYPE type          =EnumToString(ENUM_ORDER_TYPE(PositionGetInteger(POSITION_TYPE))); 
         //--- prepare and show information about the order 
         printf("#ticket %d %s %G %s at %G, with sl: %G tp: %G was set up at %s", 
                ticket,                 // order ticket 
                type,                   // type 
                volume,                 // placed volume 
                symbol,                 // symbol 
                open_price,             // specified open price
                stoploss,               //
                takeprofit,             // 
                TimeToString(time_open) // time of order placing 
                ); 
        } 
    }
}

И функция printf ничего не возвращает:

2017.06.02 01:42:26.910 2016.04.07 00:00:00   #ticket 1 (non-string passed) 0  at 0, with sl: 0 tp: 0 was set up at 1970.01.01 00:00

Не могу поверить, что так сложно просто модифицировать SL в MQL5. Это ужасно. Однако мне нужно пройти через это, чтобы проверить свою стратегию на нескольких парах...

У вас есть другая идея? Я настроил сделки с помощью следующего кода:

void createPendingOrder(ENUM_ORDER_TYPE orderType, double lots, double stopLoss) {
   MqlTradeRequest request={0};
   MqlTradeResult  result={0};

//--- parameters to place a pending order
   request.action   =TRADE_ACTION_PENDING;                             // type of trade operation
   request.symbol   =Symbol();                                         // symbol
   request.volume   =lots;                                             // volume of 0.1 lot
   //request.deviation=2;                                              // allowed deviation from the price
   request.magic    =224466      ;                                     // MagicNumber of the order
   //int offset = 3;                                                   // offset from the current price to place the order, in points
   double price;                                                       // order triggering price
   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);                // value of point
   int digits=SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);                // number of decimal places (precision)
   //--- checking the type of operation
   if(orderType==ORDER_TYPE_BUY_STOP)
     {
      request.type         =ORDER_TYPE_BUY_STOP;                            // order type
      price                =entryPrice;   
      request.price        =NormalizeDouble(price,digits);                      // normalized opening price 
      request.sl           =stopLoss;
     }
   else if(orderType==ORDER_TYPE_SELL_STOP)
     {
      request.type         =ORDER_TYPE_SELL_STOP;                           // order type
      price                =entryPrice;           
      request.price        =NormalizeDouble(price,digits);                  // normalized opening price 
      request.sl           =stopLoss;
     }
   else Alert("This example is only for placing pending orders");   // if not pending order is selected
//--- send the request
   if(!OrderSend(request,result))
      PrintFormat("OrderSend error %d",GetLastError());                 // if unable to send the request, output the error code
//--- information about the operation
   PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
}

Можно ли, например, сохранить объект результата в массиве, а затем получить доступ к текущей сделке через этот объект?


person Aurus    schedule 31.05.2017    source источник
comment
функции minusTolerance(SL) и addTolerance() - зацикливаются ли они на сделках? проверять номер тикета при старте и перед отправкой запроса на изменение   -  person Daniel Kniaz    schedule 01.06.2017
comment
Спасибо за Ваш ответ. MinusTolerance и addTolerance добавляют всего несколько пипсов к фиксированной стоп-цене. В этих двойных методах нет цикла. Как вы можете видеть в первом разделе кода поста - выбор порядка работает без ошибки, но переменные не содержат никакого значения. Например, OrderTicket(), OrderOpenPrice() или OrderStopLoss() содержат ноль.   -  person Aurus    schedule 01.06.2017
comment
да, я понимаю проблему, поэтому я посоветовал проверять билет в начале и перед отправкой. кстати, это mql5 или mql4? Print(символ и магическое совпадение +OrderTicket()); чтобы убедиться, что он выбирает правильный билет   -  person Daniel Kniaz    schedule 01.06.2017
comment
Сначала у меня была еще одна строка фильтра, в которой я проверял, совпадают ли пара и магическое число, но забавная часть заключалась в следующем: всякий раз, когда сделки шли в прямом эфире - значит, они были выполнены, а не отложенный ордер - OrderMagicNumber() был нулевым, и то же самое для символа заказа(). Пока ордер находился в ожидании и не был выполнен, эти методы возвращают правильные значения...   -  person Aurus    schedule 01.06.2017
comment
Кстати, это MQL5. Хорошо, я проверю OrderTicket. Что он должен вернуть?   -  person Aurus    schedule 01.06.2017
comment
либо что-то не так с вашим брокером (который меняет магию билетов), но я так не думаю, поскольку насколько я знаю, магия хранится в клиенте mt4, либо вы делаете что-то неправильно. поэтому, пожалуйста, предоставьте фрагмент кода, который может быть скомпилирован, выполнен и все еще имеет проблему, и мы постараемся дать совет. теперь - этот фрагмент кода выглядит нормально (за исключением того, что зацикливание с 0 - это плохая практика, начните с OrdersTotal()-1 до ›=0   -  person Daniel Kniaz    schedule 01.06.2017
comment
Насколько я помню, в MQL5 нет OrderSelect(i,SELECT_BY_POS), требуется только 1 параметр (id тикета, ulong)   -  person Daniel Kniaz    schedule 01.06.2017
comment
Вы правы с этим. В документации сказано, что единственным параметром для OrderSelect является TicketID. Я проверю это сегодня вечером и опубликую дополнительный код, если мне не удастся его запустить. Я также где-то читал, что мне, возможно, придется сделать крест, чтобы разрешить советнику торговать в реальном времени (хотя это только в тестере стратегий). Теперь я предполагаю, что проблема в том, что я вызываю OrderSelect с недопустимыми параметрами, и мне нужно будет вызывать его только с i. Собираюсь проверить это тоже и опубликовать обновление. Спасибо за вашу помощь.   -  person Aurus    schedule 01.06.2017
comment
в тестере не важно разрешаете вы торговать или нет, на демо счете - да нужно заставить еа улыбаться   -  person Daniel Kniaz    schedule 01.06.2017


Ответы (1)


Ваша проблема в том, что вы пытаетесь запустить код MQL4 в MQL5.

В MQL5 нет OrderModify(), OrderOpenPrice(), OrderTicket()!!!

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

вам нужно будет использовать OrderGetDouble(), OrderGetInteger() и OrderGetString() для запроса цены открытия, стоп-лосса и т. д., например.

if((ticket=OrderGetTicket(i))>0) 
    { 
     //--- return order properties 
     open_price    =OrderGetDouble(ORDER_PRICE_OPEN); 
     time_setup    =(datetime)OrderGetInteger(ORDER_TIME_SETUP); 
     symbol        =OrderGetString(ORDER_SYMBOL); 
     order_magic   =OrderGetInteger(ORDER_MAGIC); 
     positionID    =OrderGetInteger(ORDER_POSITION_ID); 
     initial_volume=OrderGetDouble(ORDER_VOLUME_INITIAL); 
     type          =EnumToString(ENUM_ORDER_TYPE(OrderGetInteger(ORDER_TYPE))); 
     //--- prepare and show information about the order 
     printf("#ticket %d %s %G %s at %G was set up at %s", 
            ticket,                 // order ticket 
            type,                   // type 
            initial_volume,         // placed volume 
            symbol,                 // symbol 
            open_price,             // specified open price 
            TimeToString(time_setup)// time of order placing 
            ); 
    } 

Ордера модифицируются с помощью функции OrderSend() https://www.mql5.com/ru/docs/trading/ordersend

Обновлять

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

  • Ордера = Отложенные сделки (Buy Stop, Buy Limit, Sell Stop, Sell Limit)
  • Позиции = открытые сделки (покупка, продажа)
  • HistoryOrders = закрытые/удаленные сделки
  • Сделки = транзакции, составляющие ордер/позицию

Чтобы просмотреть и просмотреть отложенные ордера:

for(int i=0; i<OrdersTotal();i++) 
    {
    if((ticket=OrderGetTicket(i))>0) 
        { 
         //--- return order properties 
         open_price    =OrderGetDouble(ORDER_PRICE_OPEN); 
         time_setup    =(datetime)OrderGetInteger(ORDER_TIME_SETUP); 
         symbol        =OrderGetString(ORDER_SYMBOL); 
         order_magic   =OrderGetInteger(ORDER_MAGIC); 
         positionID    =OrderGetInteger(ORDER_POSITION_ID); 
         initial_volume=OrderGetDouble(ORDER_VOLUME_INITIAL); 
         type          =EnumToString(ENUM_ORDER_TYPE(OrderGetInteger(ORDER_TYPE))); 
         //--- prepare and show information about the order 
         printf("#ticket %d %s %G %s at %G was set up at %s", 
                ticket,                 // order ticket 
                type,                   // type 
                initial_volume,         // placed volume 
                symbol,                 // symbol 
                open_price,             // specified open price 
                TimeToString(time_setup)// time of order placing 
                ); 
        } 
    }

Чтобы просмотреть и просмотреть открытые сделки:

for(int i=0; i<PositionsTotal();i++) 
    {
    if((ticket= PositionGetTicket(i))>0) 
        { 
         //--- return order properties 
         open_price    =PositionGetDouble(POSITION_PRICE_OPEN); 
         time_open     =(datetime)PositionGetInteger(POSITION_TIME); 
         symbol        =PositionGetString(POSITION_SYMBOL); 
         order_magic   =PositionGetInteger(POSITION_MAGIC); 
         volume        =PositionGetDouble(POSITION_VOLUME); 
         stoploss      =PositionGetDouble(POSITION_SL); 
         takeprofit    =PositionGetDouble(POSITION_TP); 
         type          =EnumToString(ENUM_ORDER_TYPE(PositionGetInteger(POSITION_TYPE))); 
         //--- prepare and show information about the order 
         printf("#ticket %d %s %G %s at %G, with sl: %G tp: %G was set up at %s", 
                ticket,                 // order ticket 
                type,                   // type 
                volume,                 // placed volume 
                symbol,                 // symbol 
                open_price,             // specified open price
                stoploss,               //
                takeprofit,             // 
                TimeToString(time_open) // time of order placing 
                ); 
        } 
    }

Надеюсь, кто-то еще сможет дать лучшее объяснение ордерам, позициям, сделкам, истории ордеров, поскольку они все еще вызывают у меня головную боль.

Для простоты я обычно просто создаю экземпляр класса CTrade.

Обновление2

Минимальный пример trailSL для позиций на покупку с использованием стандартных торговых функций и класса Ctrade

В этом

Ctrade *m_trade;
CSymbolInfo *m_symbol;
Void OnInit()
{
    m_trade  = new Ctrade();
    m_trade.SetExpertMagicNumber(100);
    m_symbol = new CSymbolInfo();
    m_symbol.Name(Symbol());
}
void OnTick()
{
   m_symbol.RefreshRates();
}

Трейл SL сделки на покупку со стандартными функциями

void modifysl()
  {
   ulong ticket;
   MqlTradeRequest request = {0};
   MqlTradeResult  result  = {0};
   double newsl;

   for(int i=0; i<PositionsTotal();i++)
     {
      ticket=PositionGetTicket(i);
      if(ticket>0)
        {
         request.action   = TRADE_ACTION_SLTP; // type of trade operation
         request.position = ticket;   // ticket of the position
         request.symbol   = PositionGetString(POSITION_SYMBOL);     // symbol 
         request.sl       = PositionGetDouble(POSITION_SL);                // Stop Loss of the position
         request.tp       = PositionGetDouble(POSITION_TP);                // Take Profit of the position
         request.magic    = 100;                                    // MagicNumber of the position

   
         newsl = NormalizeDouble(m_symbol.Bid()-100*m_symbol.Point(),
                                 m_symbol.Digits());
         if(newsl>request.sl)
           {
            request.sl = newsl;
            if(!OrderSend(request,result))
              {
               PrintFormat("OrderSend error %d",GetLastError());  // if unable to send the request, output the error code
              }
            //--- information about the operation   
            PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
           }
        }
     }
  }

Стоп-лосс трейловой позиции на покупку с использованием CTrade

void modifyslCtrade()
  {
   ulong ticket;
   MqlTradeRequest request= {0};
   MqlTradeResult response ={0};
   double newsl;

   for(int i=0; i<PositionsTotal();i++)
     {
      ticket=PositionGetTicket(i);
      if(ticket>0)
        {
         newsl = NormalizeDouble(m_symbol.Bid()-100*m_symbol.Point(),
                                 m_symbol.Digits());
         if(newsl>PositionGetDouble(POSITION_SL))
           { 
            m_trade.PositionModify(ticket,
                                   newsl,
                                   PositionGetDouble(POSITION_TP));
           }
        }
     }
  }
person rgunning    schedule 01.06.2017