Установка StopLoss и TakeProfit для BUY_STOP_LIMIT и SELL_STOP_LIMIT ордеров - страница 2

 
Aleksey Mavrin:

подозреваю что для вашего типа ордера в структуре stoplimit надо ещё явно указать, хоть в справке и не написано)

а может кривые функции расчета ТП и СЛ? вы их не привели.

Ещё бросилось в глаза- break выходит из for? зачем? вы разве не хотите все ордера пройти?

Насчёт break - это точно мой косяк. Я этот кусок копировал из другой программы, там при успешной модификации надо было выйти, а здесь нужно по всем ордерам пройтись.

 
Aleksey Mavrin:

подозреваю что для вашего типа ордера в структуре stoplimit надо ещё явно указать, хоть в справке и не написано)

а может кривые функции расчета ТП и СЛ? вы их не привели.

Ещё бросилось в глаза- break выходит из for? зачем? вы разве не хотите все ордера пройти?

Кажется понял почему запросы инвалидные. Вот момент когда происходит инвалидный запрос:

Попытка модификации совершается до того как ордер оказывается принятым. А когда ордер принят, модификация проходит успешно. Теперь возник вопрос как выяснить был ли ордер accepted на момент запроса на модификацию?

 
Oleg Remizov:

Кажется понял почему запросы инвалидные. Вот момент когда происходит инвалидный запрос:

Попытка модификации совершается до того как ордер оказывается принятым. А когда ордер принят, модификация проходит успешно. Теперь возник вопрос как выяснить был ли ордер accepted на момент запроса на модификацию?

понятно что модифицируете в момент его исполнения, т.е. лимитник еще не выставился, а стоп уже сработал и удаляется, типа.

Не пойму зачем вы непрерывно пытаетесь модифицировать, если это не трейлинг. Одного раза после установки недостаточно чтоли? На том же тике!  Многие проблемы бы сняло.

 
Aleksey Mavrin:

понятно что модифицируете в момент его исполнения, т.е. лимитник еще не выставился, а стоп уже сработал и удаляется, типа.

Не пойму зачем вы непрерывно пытаетесь модифицировать, если это не трейлинг. Одного раза после установки недостаточно чтоли? На том же тике!  Многие проблемы бы сняло.

Наверно статус ордера так можно проверить:

if(OrderGetInteger(ORDER_STATE)==ORDER_STATE_PLACED) 

{

// ордер принят, можно модифицировать...

}

Сейчас попробую, если ошибка исчезнет, значит причина была в этом.

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

 
Инвалидного реквеста теперь нет, зато установку стопа и тейка опять сломал, не выставляется и снова Invalid price. 
 
Oleg Remizov:

Наверно статус ордера так можно проверить:

Сейчас попробую, если ошибка исчезнет, значит причина была в этом.

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

Можно и так.

Но всё равно постоянно шпарить смысла нет, вы же ордера при обнаружении в список-массив добавляете, так сразу и модифицируйте один раз и всё.

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

 
Aleksey Mavrin:

подозреваю что для вашего типа ордера в структуре stoplimit надо ещё явно указать, хоть в справке и не написано)

а может кривые функции расчета ТП и СЛ? вы их не привели.

Ещё бросилось в глаза- break выходит из for? зачем? вы разве не хотите все ордера пройти?

Да, Вы оказались правы. Если тип ордера BUY_STOP_LIMIT / SELL_STOP_LIMIT надо ещё цену stoplimit у структуры запроса заполнять. Теперь снова стоп и тейк выставляет.

      if(_type_orders == Pending || _type_orders == MarketPending)
        {
         // блок работы с отложенными ордерами
         // срабатывает если выбран тип отложенный или рыночный и отложенный
         // отложенные ордера: buy_stop, buy_limit, sell_stop, sell_limit, buy_stop_limit, sell_stop_limit
         // причина установить тейк: у ордера тейк нулевой, а в настройках указан более нуля
         // причина установить стоп: у ордера стоп нулевой, а в настройках указан более нуля
         bool need_modify = false;
         for(int i = 0; i < ats.pending_order_quantity; i++)
           {
            if(OrderSelect(ats.pending_order_tickets[i]))
              {
               // ордер выделился по тикету
               // сначала проверяем статус, а потом всё остальное
               if(OrderGetInteger(ORDER_STATE) == ORDER_STATE_PLACED)
                 {
                  // размещён
                  // записываем свойства ордера
                  ulong ord_ticket = ats.pending_order_tickets[i];
                  ENUM_ORDER_TYPE ord_type = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
                  double ord_op = OrderGetDouble(ORDER_PRICE_OPEN);
                  double ord_stoplimit = OrderGetDouble(ORDER_PRICE_STOPLIMIT);
                  string ord_symbol = OrderGetString(ORDER_SYMBOL);
                  datetime ord_exp = (datetime)OrderGetInteger(ORDER_TIME_EXPIRATION);
                  ENUM_ORDER_TYPE_TIME ord_type_time = (ENUM_ORDER_TYPE_TIME)OrderGetInteger(ORDER_TYPE_TIME);
                  double ord_tp = OrderGetDouble(ORDER_TP);
                  double ord_sl = OrderGetDouble(ORDER_SL);
                  // чистим флаг модификации
                  need_modify = false;
                  // флаг очищен, теперь проверяем нужно ли его изменить
                  if((ord_tp == 0) && (_tp > 0))
                    {
                     // реальный тейк нулевой, а в настройках более нуля
                     ord_tp = TakeProfitPrice(ord_symbol, _tp, ord_type, ord_ticket, ord_op, true, _sf_lvl_free);
                     if(ord_tp > 0)
                        need_modify = true;
                    }
                  if((ord_sl == 0) && (_sl > 0))
                    {
                     // реальный стоп нулевой, а в настройках более нуля
                     ord_sl = StopLossPrice(ord_symbol, _sl, ord_type, ord_ticket, ord_op, true, _sf_lvl_free);
                     if(ord_sl > 0)
                        need_modify = true;
                    }
                  // теперь на основании флага проводим модификацию ордера
                  if(need_modify)
                    {
                     ZeroMemory(req);
                     ZeroMemory(res);
                     req.action = TRADE_ACTION_MODIFY;
                     req.order = ord_ticket;
                     req.price = ord_op;
                     if(ord_type == ORDER_TYPE_BUY_STOP_LIMIT || ord_type == ORDER_TYPE_SELL_STOP_LIMIT)
                        req.stoplimit = ord_stoplimit;
                     req.sl = ord_sl;
                     req.tp = ord_tp;
                     req.type_time = ord_type_time;
                     req.expiration = ord_exp;
                     if(!OrderSend(req, res) || res.retcode != TRADE_RETCODE_DONE)
                        Print("Ticket:", ord_ticket, " Error: ", ResultRetcode(res));
                    }
                 }
              }
           }
        }
 
Aleksey Mavrin:

Можно и так.

Но всё равно постоянно шпарить смысла нет, вы же ордера при обнаружении в список-массив добавляете, так сразу и модифицируйте один раз и всё.

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

Тогда эту функцию целесообразно будет засунуть внутрь обработчика OnTrade(). Он как раз при изменении состава сделок / ордеров активируется. 

 
Oleg Remizov:

Тогда эту функцию целесообразно будет засунуть внутрь обработчика OnTrade(). Он как раз при изменении состава сделок / ордеров активируется. 

Да, именно. Кстати пару лайфхаков)

1. при использовании стандартной библиотеки вы бы не столкнулись с этими проблемами.

2. Даже если хотите написать сами с нуля, то если бы вы заглянули в методы соответствующие СБ, то сразу бы узнали чем ваш код отличается, т.е. в чём может быть затык.

з.ы. В СБ классы CTrade, CExpertTrade, для списка тикетов CArrayLong и т.д.

Как использовать торговые классы Стандартной библиотеки при написании советника
Как использовать торговые классы Стандартной библиотеки при написании советника
  • www.mql5.com
В статье рассказывается о том, как использовать основной функционал торговых классов Стандартной библиотеки при написании советников, в которых применяется открытие, закрытие и модификация позиции, проверка свободной маржи перед размещением торговых ордеров, размещение и удаление отложенных ордеров. Показано, как использовать торговые классы для получения свойств ордеров и сделок.
 

Вот скрипт -он выставляет https://www.mql5.com/ru/code/30709

 

//+------------------------------------------------------------------+
//|                                                         grid.mq5 |
//|                             Copyright 2020, Zakhvatkin Aleksandr |
//|                              https://www.mql5.com/ru/users/z.a.m |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, Zakhvatkin Aleksandr"
#property link      "https://www.mql5.com/ru/users/z.a.m"
#property version   "1.00"
#property script_show_inputs
//--- input parameters
input double   FixedLot=0.01;   // Fixed lot
input ushort   InStopLoss=400;  // Stop Loss
input ushort   TakeProfit=200;  // Take profit
input ushort   Grid_step=100;   // Grid step
input ushort   N_orders=10;     // Number of orders in one direction
input ushort   Distance=50;     // Price offset
input bool     LimitGrid=false; // Set a grid of limit orders
//--- include
#include <Trade\Trade.mqh>
CTrade trade;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   for(int j=1; j<=N_orders; j++)
     {
      if(!LimitGrid)
        {
         double _pricebuy = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK)+Distance*_Point+Grid_step*j*_Point,_Digits);
         double _pricesell = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID)-Distance*_Point-Grid_step*j*_Point,_Digits);
         trade.BuyStop(FixedLot,_pricebuy,NULL,_pricebuy-InStopLoss*_Point,_pricebuy+TakeProfit*_Point,0,0,NULL);
         trade.SellStop(FixedLot,_pricesell,NULL,_pricesell+InStopLoss*_Point,_pricesell-TakeProfit*_Point,0,0,NULL);
        }
      else
        {
         double _pricebuy = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK)-Distance*_Point-Grid_step*j*_Point,_Digits);
         double _pricesell = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID)+Distance*_Point+Grid_step*j*_Point,_Digits);
         trade.SellLimit(FixedLot,_pricesell,NULL,_pricesell+InStopLoss*_Point,_pricesell-TakeProfit*_Point,0,0,NULL);
         trade.BuyLimit(FixedLot,_pricebuy,NULL,_pricebuy-InStopLoss*_Point,_pricebuy+TakeProfit*_Point,0,0,NULL);
        }
     }
  }
//+------------------------------------------------------------------+
Grid
Grid
  • www.mql5.com
Скрипт выставляет сетку отложенных ордеров.
Причина обращения: