Ошибка #1 при модификации ордеров - страница 4

 
hoz:

Борис, предположим, что это так... Предположим. Но, если функция повторно отправляет приказ на модификацию ордера, значитон должен модифицироваться. А у меня он ни модифицируется вообще. Даже если посмотреть на лог в журнале, то мы увидим вот что:

 

Почему ордер отправляется? Если у него не корректные параметры, функция б ругнулась... А тут типа ОК... послан. Потом оказалось, что ошибка есть.. Логика в чём?

 

 

Только включился! Виктор, если "ок", значит какой-то параметр поменялся, а получение ошибки 1 говорит о том, что какой-то из параметров был заявлен на изменение, а оказался неизменным. Потому-то нужно править твою логику, чтобы избежать таких случаев, а на реале все эти неточности обернутся реквотами и кучей ошибок!

Ты знаешь, что я не пользуюсь такой манерой программирования, что всё разбросано по разным местам. Я пишу программу как логический сценарий, все события развиваются последовательно, и всегда всё рядом перед глазами со всеми условиями без необходимости рыскать в поисках чего-то. А внешними функциями пользуюсь для выполнения конечного действия и проверкой на ошибки.

А у тебя непонятно непосвящённому, что у тебя и где проверяется, всё скрыто, иди гадай, провёл ты необходимое условие или нет?! Как-то много слов, как у меня сейчас, а сути твоя программа не доносит. Должно быть ясно и лаконично!

 

Борис, я, конечно, понимаю, что у меня всё не в одном месте. Но вводные параметры прямо перед функцией модификации распринтованы. Я ж скрин кидал. Там текущие и новые ООП, SL и TP. И они все разные. Зачем лезти в дебри, если всё рядом? Если распринтовано, и видно, что параметры разные, значит они, действительно, разные. Или может уже и принту не доверять?

2013.08.26 00:00  Kevin Martens_Moi_Myrei EURUSD,M15: PositionsManipulations::fOrderModify: Тикет № 2; New_OOP = 1.34048; New_SL = 1.34125; New_TP = 1.33362
2013.08.26 00:00  Kevin Martens_Moi_Myrei EURUSD,M15: PositionsManipulations::fOrderModify:  Тикет № 2; OrderOpenPrice() = 1.34048; OrderStopLoss() = 0.0; OrderTakeProfit() = 0.0
2013.08.26 00:00  Kevin Martens_Moi_Myrei EURUSD,M15: PositionsManipulations::fOrderModify: Тикет № 2; New_OOP = 1.34048; New_SL = 1.34125; New_TP = 1.33362
2013.08.26 00:00  Kevin Martens_Moi_Myrei EURUSD,M15: PositionsManipulations::fOrderModify: _LastError = 0
2013.08.26 00:00  Kevin Martens_Moi_Myrei EURUSD,M15: modify #2 sell limit 0.10 EURUSD at 1.34048 sl: 1.34125 tp: 1.33362 ok
2013.08.26 00:00  Kevin Martens_Moi_Myrei EURUSD,M15: OrderModify error 1

А перед этим как я выше показал стоит проверка:

 if ((ND (OrderOpenPrice()) != fd_OpenPrice) || ND ((OrderStopLoss()) != fd_NewSL) || (ND (OrderTakeProfit()) != fd_NewTP))
{
 ... Если какой-то из параметров отличается от нового, значит выполняется это условие...
}

 Куда уж канкретнее? Тут пару клоунов сверху начали небылицы слагать. Видать не смогли или не хотели понять, что я спрашиваю. Так они ржут безпричинно. А вопрос то интересный.

Ведь если в OrderModify() впихнуть, например, параметр другого типа или не то количество или ещё другие варианты, возникают ошибки сразу. А тут она выполняется, пишит типа ОК, а потом оказывается что никакой параметр не изменён.

Возникает вопрос как узнать что там не так? Ведь функцию свою я выкладывал. Там всё понятно должно быть. Вот она:

// 1.2 Функция модифицирует выделенный ордер (установка TP и SL). =========================================================================
bool PositionsManipulations::fOrderModify (int       fi_Ticket,             // OrderTicket()
                                           double    fd_OpenPrice,          // OpenPrice
                                           double    fd_NewSL,              // Новый StopLoss (УРОВЕНЬ !!!)
                                           double    fd_NewTP,              // Новый TakeProfit (УРОВЕНЬ !!!)
                                           datetime  fdt_Expiration = 0,    // Время истечения отложенного ордера
                                           color     fc_Arrow = CLR_NONE)   // Цвет стрелок модификации StopLoss и/или TakeProfit на графике
{
   Print (__FUNCTION__, ": ", "Вошли в функцию ");

//---- Проверяем необходимость модификации
   if (fd_NewSL == OrderStopLoss() && fd_NewTP == OrderTakeProfit())
       return (false);
//----
   string ls_fName = "fOrderModify()";
   int    li_Cnt = 0;
   double ld_Price;
   bool   lb_InvalidSTOP = false,
          lb_FixInvalidPrice = false;    // Флаг первоначальной коррекции отложки

//---- Получаем актуальную информацию по символу и текущему ордеру
   CBase.GetMarkerInfo (OrderSymbol(), fi_Ticket);
   
   Print (__FUNCTION__, ": ", "До проверки на FREEZELEVEL и STOPLEVEL  тикета № ", fi_Ticket);
   Print (__FUNCTION__, ": ", "Тикет № ", OrderTicket(), "; OrderOpenPrice() = ", OrderOpenPrice(),
             "; OrderStopLoss() = ", OrderStopLoss(), "; OrderTakeProfit() = ", OrderTakeProfit());
   Print (__FUNCTION__, ": ", "Тикет № ", fi_Ticket, "; New_OOP = ", fd_OpenPrice, "; New_SL = ", fd_NewSL, "; New_TP = ", fd_NewTP);
//---- Проверяем на условия FREEZELEVEL и STOPLEVEL
   if (!CheckLevelsBLOCK (3, SPos.gs_Symbol, SPos.gi_Type, fd_OpenPrice, fd_NewSL, fd_NewTP, lb_FixInvalidPrice))
   {
      if (StringLen (CErrs.ErrInf) > 0)      // Если переменная для хранения ошибок не пустая..
      {
         CLogs.WriteLog (CErrs.ErrInf);      //.. то, запишем в лог и выйдем из функции
         return (false);
      }
   }
   Print (__FUNCTION__, ": ", "После проверки на FREEZELEVEL и STOPLEVEL  тикета № ", fi_Ticket);
   Print (__FUNCTION__, ": ", "Тикет № ", fi_Ticket, "; New_OOP = ", fd_OpenPrice, "; New_SL = ", fd_NewSL, "; New_TP = ", fd_NewTP);
   
   ResetLastError();
   
//---- Определяем цвет значков модификации ордеров
   if (fc_Arrow == CLR_NONE)
       fc_Arrow = ColorByModify [OrderType() % 2];
   
//---- Выполняем модификацию в тестере
   if (!CBase.GetRealTrade())
   {
      if ((ND (OrderOpenPrice()) != fd_OpenPrice) || ND ((OrderStopLoss()) != fd_NewSL) || (ND (OrderTakeProfit()) != fd_NewTP))
      {
      ResetLastError();
      
      Print (__FUNCTION__, ": ", " Тикет № ", OrderTicket(), "; OrderOpenPrice() = ", OrderOpenPrice(),
             "; OrderStopLoss() = ", OrderStopLoss(), "; OrderTakeProfit() = ", OrderTakeProfit());
      Print (__FUNCTION__, ": ", "Тикет № ", fi_Ticket, "; New_OOP = ", fd_OpenPrice, "; New_SL = ", fd_NewSL, "; New_TP = ", fd_NewTP);
      Print (__FUNCTION__, ": ", "_LastError = ", _LastError);
      
      if (!OrderModify (fi_Ticket, fd_OpenPrice, fd_NewSL, fd_NewTP, fdt_Expiration, fc_Arrow))
      {
         CLogs.WriteLog (StringConcatenate ("fOrderModify(): ", CErrs.ErrorToString (_LastError)));
         Print (__FUNCTION__, ": ", "После модификации тикета № ", fi_Ticket);
         Print (__FUNCTION__, ": ", "Тикет № ", fi_Ticket, "; New_OOP = ", fd_OpenPrice, "; New_SL = ", fd_NewSL, "; New_TP = ", fd_NewTP);
         return (false);
      }
      }
   }
   
 

 Я специально прокомментировал все строки. Можно порчить код просто. Если есть замечания прошу помочь. 

 
hoz:

Борис, я, конечно, понимаю, что у меня всё не в одном месте. Но вводные параметры прямо перед функцией модификации распринтованы. Я ж скрин кидал. Там текущие и новые ООП, SL и TP. И они все разные. Зачем лезти в дебри, если всё рядом? Если распринтовано, и видно, что параметры разные, значит они, действительно, разные. Или может уже и принту не доверять?

А перед этим как я выше показал стоит проверка:


 Всё

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

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

 
borilunad:

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

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


Все операции с ордерами происходят в цикле! Вот отсюда вызывается тот метод fOrderModify(), код которого я привёл выше:

//+---------------------------------------------------------------------------------------------------------------------------------------+
//|                                                   Перенос лимитных ордеров по сигналу                                                 |
//+---------------------------------------------------------------------------------------------------------------------------------------+
void MovingLimitPositions (const double& fd_MurreyLevelsValue[])
{
   double New_OOP = 0.0,
          New_SL = 0.0,
          New_TP = 0.0;
   int    Ticket = -1;
   
   for (int i=0; i<13; i++)
   {
      Print (__FUNCTION__, ": ", "fd_MurreyLevelsValue["+IToS (i)+"] = ", DToS (fd_MurreyLevelsValue[i]));
   }

   for (int i=OrdersTotal()-1; i>=0; i--)
   {
      New_OOP = 0.0;
      New_SL = 0.0;
      New_TP = 0.0;
      
      ResetLastError();
      
      if (!CPosMan.CheckMyOrdersBased(i, 7)) continue;
      if (!OrderSelect (i, SELECT_BY_POS, MODE_TRADES)) continue;

      Ticket = OrderTicket();

      Print (__FUNCTION__, ": ", "Выбран тикет № ", OrderTicket());
      Print (__FUNCTION__, ": ", "Тикет № ", OrderTicket(), "; OrderOpenPrice() = ", OrderOpenPrice(),
             "; OrderStopLoss() = ", OrderStopLoss(), "; OrderTakeProfit() = ", OrderTakeProfit());
          
      if (OrderType() == OP_BUYLIMIT)
      {
         if (ND (OrderOpenPrice()) != ND (fd_MurreyLevelsValue[1]))
            New_OOP = ND (fd_MurreyLevelsValue[1]);
         else New_OOP = ND (OrderOpenPrice());
         if (ND (OrderStopLoss()) != ND (fd_MurreyLevelsValue[0]))
            New_SL = ND (fd_MurreyLevelsValue[0]);
         else New_SL = ND (OrderStopLoss());
         if (ND (OrderTakeProfit()) != ND (fd_MurreyLevelsValue[10]))
            New_TP = ND (fd_MurreyLevelsValue[10]);
         else New_TP = ND (OrderTakeProfit());
         
         Print (__FUNCTION__, ": ", "New_OOP = ", New_OOP, "; New_SL = ", New_SL, "; New_TP = ", New_TP);
         
         if (ND (OrderOpenPrice()) != fd_MurreyLevelsValue[1])
         {
            if (!CPosMan.fOrderModify (OrderTicket(), New_OOP, New_SL, New_TP))
            {
               if (_LastError > 0)
                  CLogs.WriteLog (StringConcatenate (__FUNCTION__, ". В строке ", __LINE__, " ", CErrs.ErrorToString (_LastError)),
                                  CLogs.GetNeedLogs(), CLogs.GetPrintUP(), CLogs.GetCommentUP());
            }
            else
            {Print (__FUNCTION__, ": ", "Модификация тикета №", OrderTicket(), " успешно завершена!");}
         }
      }
      
      if (OrderType() == OP_SELLLIMIT)
      {
         if (ND (OrderOpenPrice()) != ND (fd_MurreyLevelsValue[11]))
            New_OOP = ND (fd_MurreyLevelsValue[11]);
         else New_OOP = ND (OrderOpenPrice());
         if (ND (OrderStopLoss()) != ND (fd_MurreyLevelsValue[12]))
            New_SL = ND (fd_MurreyLevelsValue[12]);
         else New_SL = ND (OrderStopLoss());
         if (ND (OrderTakeProfit()) != ND (fd_MurreyLevelsValue[2]))
            New_TP = ND (fd_MurreyLevelsValue[2]);
         else New_TP = ND (OrderTakeProfit());
         
         Print (__FUNCTION__, ": ", "New_OOP = ", New_OOP, "; New_SL = ", New_SL, "; New_TP = ", New_TP);
         Print (__FUNCTION__, ": ", "Тикет № ", OrderTicket(), "; OrderOpenPrice() = ", OrderOpenPrice(),
             "; OrderStopLoss() = ", OrderStopLoss(), "; OrderTakeProfit() = ", OrderTakeProfit());
             
         if (ND (OrderOpenPrice()) != fd_MurreyLevelsValue[11])
         {
            if (!CPosMan.fOrderModify (Ticket,  New_OOP, New_SL, New_TP))
            {
               if (_LastError != 0)
                  CLogs.WriteLog (StringConcatenate (__FUNCTION__, ". В строке ", __LINE__, " ", CErrs.ErrorToString (_LastError)),
                                  CLogs.GetNeedLogs(), CLogs.GetPrintUP(), CLogs.GetCommentUP());
            }
            else
            {
               Print (__FUNCTION__, ": ", "Модификация тикета №", OrderTicket(), " успешно завершена!");
               Print (__FUNCTION__, ": ", "Тикет № ", OrderTicket(), "; OrderOpenPrice() = ", OrderOpenPrice(),
             "; OrderStopLoss() = ", OrderStopLoss(), "; OrderTakeProfit() = ", OrderTakeProfit());
            }
         }
      }
   }
   Print (__FUNCTION__, ": ", "OUT OF FUNCTION");
}

Там видно всё...  Так же видно, что после каждой итерации цикла происходит сброс ошибки. Таким образом обеспечивается факт, что ошибка на предыдущем ордере, если она была, не перескочит на следующий(имею ввиду её значение разумеется)

Куда может быть проще? Тут и так всё просто.. 

 

Я нашёл сообщение

Там такой же баг терминала. У меня подобного не было ни когда. Т.к. я раньше не пытался изменять у отложенных ордеров сразу 3 параметра (OOП, SL и TP). Вот понадобилось... И наткнулся на баг.

 Я так понимаю, если, например, цена открытия и стоплосс не изменились, и вместо них есс-но поступают те же значения, а тейк изменился. Это тоже приводит к ошибке? Тогда получается, что документация кривая. И этот момент не поддерживается что-ли?

 
hoz:

Я нашёл сообщение

Там такой же баг терминала. У меня подобного не было ни когда. Т.к. я раньше не пытался изменять у отложенных ордеров сразу 3 параметра (OOП, SL и TP). Вот понадобилось... И наткнулся на баг.

 Я так понимаю, если, например, цена открытия и стоплосс не изменились, и вместо них есс-но поступают те же значения, а тейк изменился. Это тоже приводит к ошибке? Тогда получается, что документация кривая. И этот момент не поддерживается что-ли?

 

А ты тоже на каждом тике проверяешь дистанцию?! Я давно взял за правило открывать ордеры на открытии бара ТФ, а модифицировать и закрывать только на открытии бара на М1! Приведённый выше код мне напоминает отчёт за проведённую работу, в котором вроде всё присутствует, но ничего конкретного! Я не вижу цикла, в котором ты по конкретным условиям определяешь все действия! Вижу только цикл, который мне ничего говорит, что нужно модифицировать, тогда просто не модифицируй, и не будет ошибок. 

Обрати внимание на важное замечание Рената, что твои ошибки могут происходить от путаницы, что нужно делать на глобальном уровне и что на локальном, а ошибки всегда последние, более ранние обнуляются без твоего участия с выходом из функции!

 
borilunad:

А ты тоже на каждом тике проверяешь дистанцию?!  

 Нет! У меня разрешение на модификацию происходит только, при соблюдении условия. В данном случает, условием для модификации является изменение рассчитанных уровней. Вот так:

void OnTick()
{
   static double FirstInd = 0.0;                    // Переменная, которая хранит значение 1-ого индекса массива
   double MurreyLevelsValue[13];                    // Массив значений уровней
   GetDataFromIndicator (MurreyLevelsValue);        // Функция, которая получает значения из индикатора уровней
   
   if (gdt_LastBarTime <= Time[0])
   {
      OTotal = CPosInf.FindPositions (AmountPosByType);   // Получаем количество позиций( по типам ).
      
      GetTradeSignal (MurreyLevelsValue);
      
      gdt_LastBarTime = Time[0];
   }

   if (FirstInd != ND (MurreyLevelsValue[1]))      // Если значений текущего состояния переменной FirstInd не равно новому рассчитанном, то.. 

   {
      MovingLimitPositions (MurreyLevelsValue);     // ..модифицируем ордер новым значением
      FirstInd = ND (MurreyLevelsValue[1]);
   }
}

 Просто? Просто....

 

borilunad:


Я давно взял за правило открывать ордеры на открытии бара ТФ, а модифицировать и закрывать только на открытии бара на М1! Приведённый выше код мне напоминает отчёт за проведённую работу, в котором вроде всё присутствует, но ничего конкретного! Я не вижу цикла, в котором ты по конкретным условиям определяешь все действия! Вижу только цикл, который мне ничего говорит, что нужно модифицировать, тогда просто не модифицируй, и не будет ошибок.

  У меня тоже были подобные мысли, чтоб модифицировать только на открытии М1, и, это применимо, если модификация проводится заранее заданным значением. Но ведь бывают ситуации, когда мне не нужно проверять эти данные на М1. Например, у меня стоп тянется по уровню, который расчитан уже. Тогда у меня, как я выше показал, есть проверка в функции OnInit():

if (FirstInd != ND (MurreyLevelsValue[1]))
{
   MovingLimitPositions (MurreyLevelsValue);
   FirstInd = ND (MurreyLevelsValue[1]);
}
Т.е. если изменился уровень, то... модифицирует. Этим мы избавляемся от лишних попыток модификации. Так сказать, модификация по сигналу, а не по таймеру. Понятно тут? 


borilunad:


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

Я там всё распринтовал. Что можно не понять... :(
  

borilunad:

Обрати внимание на важное замечание Рената, что твои ошибки могут происходить от путаницы, что нужно делать на глобальном уровне и что на локальном, а ошибки всегда последние, более ранние обнуляются без твоего участия с выходом из функции!

Эта проблема как я обнаружил стречается, не только у меня. Вот пример...

 И её по ходу не решили, и решать не собираются. Может разработчикам лень? Если уж я не правильно с ошибками работаю, кто-нить, тот же Ренат мог ткнуть в код, а не просто сказать, что у меня не так.

 В конце концов, если перед функцией модификации принтуются новые и текущие значения параметров, которые планируются модифицировать, то понятно становится, что там эти значения есть. Зачем лезть выше куда-то? Есть значения, видно что ошибок нет (я ж принтанул там на наличие ошибок). Значит всё исправно в логике. Значит косяк в функции модификации.

 
hoz:

 Нет! У меня разрешение на модификацию происходит только, при соблюдении условия. В данном случает, условием для модификации является изменение рассчитанных уровней. Вот так:

 Просто? Просто....

 

  У меня тоже были подобные мысли, чтоб модифицировать только на открытии М1, и, это применимо, если модификация проводится заранее заданным значением. Но ведь бывают ситуации, когда мне не нужно проверять эти данные на М1. Например, у меня стоп тянется по уровню, который расчитан уже. Тогда у меня, как я выше показал, есть проверка в функции OnInit():

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


Я там всё распринтовал. Что можно не понять... :(
  

Эта проблема как я обнаружил стречается, не только у меня. Вот пример...

 И её по ходу не решили, и решать не собираются. Может разработчикам лень? Если уж я не правильно с ошибками работаю, кто-нить, тот же Ренат мог ткнуть в код, а не просто сказать, что у меня не так.

 В конце концов, если перед функцией модификации принтуются новые и текущие значения параметров, которые планируются модифицировать, то понятно становится, что там эти значения есть. Зачем лезть выше куда-то? Есть значения, видно что ошибок нет (я ж принтанул там на наличие ошибок). Значит всё исправно в логике. Значит косяк в функции модификации.

Я этот пример уже смотрел. Но нам приходится применяться к любым условиям, пока нет ничего лучшего. Твой код меня не убеждает. Сейчас пообедаю, потом приведу пример цикла, который у меня работает чётко для выставления СЛ, перевода в Б/У и траления всего для одного вызова функции модификации, где обрабатываются ошибки, если вдруг возникнут в работе, в тестере не возникают.

Хочешь функцию Modify()? 

 
hoz:

 

 В конце концов, если перед функцией модификации принтуются новые и текущие значения параметров, которые планируются модифицировать, то понятно становится, что там эти значения есть. Зачем лезть выше куда-то? Есть значения, видно что ошибок нет (я ж принтанул там на наличие ошибок). Значит всё исправно в логике. Значит косяк в функции модификации.

код вроде вполне.. а на реале (не демо) это работает ?
 

Виктор, а зачем ты занялся модификацией СЛ и ТП в отложках?! Вообще, имеет смысл ставить СЛ только после открытия позиции, а ТП после перевода СЛ в Б/У! Так зачем так надоедать серверу понапрасну и тебе эта мука?! 

Надо до минимума сократить и упростить код, чтобы работал быстро и чётко, и потом легче будет его подправлять из-за капризов рынка! Продумай хорошенько все нюансы, связанные с реалиями рынка!

Причина обращения: