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

 
Кто-нибудь может помочь, пожалуйста, .....
 

Отчасти проблема в том, как вы написали этот код с большими длинными условиями if, полными &&, ||, и вызовом функции за вызовом функции, что затрудняет отладку, и вам повезет, если вы найдете кого-нибудь, у кого хватит времени распутать этот беспорядок. Вам следует посмотреть примеры кодирования в документации, чтобы увидеть, как код должен быть оформлен в гораздо более короткие строки и прокомментирован.

 

" Makes it difficult to debug "?? :( Никогда не слышал о таком, это правда ....

Компилятору также трудно отлаживать мой код :( ?

Если причина в этом, значит, мне придется пересмотреть все мои идеи по кодированию этой части? Тогда получится совсем другая вещь ...... :( :( :( :(

 

Да, его трудно отлаживать, например, посмотрите на этот код для трейлинг-стопа. Легко увидеть, что делает каждая строка, поэтому легко заметить ошибки.

   int total=OrdersTotal();
   
   for(int cnt=0; cnt<total; cnt++)
   {if(!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))  
    {if(OrderType()==OP_BUY)
     {if(TrailingStop>0)
      {if(Bid-OrderOpenPrice()>Point*TrailingStop)
       {if(OrderStopLoss()<Bid-Point*TrailingStop)
        {if(!OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green))
         {Print("OrderModify error ",GetLastError());
          return;
   }}}}}}}
 
Я попробовал удалить условие && и поместить их в оператор if, как после ..... Но это все равно не срабатывало постоянно, иногда стоп-лосс перемещался только один раз, иногда он работал отлично как для ордеров на покупку, так и на продажу.
 
SDC: Да, это трудно отлаживать, например, посмотрите на этот код для трейлинг-стопа. Легко увидеть, что делает каждая линия, поэтому легко заметить ошибки.
   int total=OrdersTotal();
   
   for(int cnt=0; cnt<total; cnt++)
   {if(!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))  
    {if(OrderType()==OP_BUY)
     {if(TrailingStop>0)
      {if(Bid-OrderOpenPrice()>Point*TrailingStop)
       {if(OrderStopLoss()<Bid-Point*TrailingStop)
        {if(!OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green))
         {Print("OrderModify error ",GetLastError());
          return;
   }}}}}}}
  1. Вы ДОЛЖНЫ вести обратный отс чет при закрытии/удалении при наличии нескольких ордеров. Подумайте о советнике на других графиках. Выработайте привычку.
       for(int cnt=OrdersTotal() - 1; cnt >= 0; --cnt)
       {if(!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))  
        {if(OrderType()==OP_BUY)
         {if(TrailingStop>0)
          {if(Bid-OrderOpenPrice()>Point*TrailingStop)
           {if(OrderStopLoss()<Bid-Point*TrailingStop)
            {if(!OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green))
             {Print("OrderModify error ",GetLastError());
              return;
       }}}}}}}
    Также предпочитайте ++x вместо x++ (особенно при работе с классами).
  2. Язык представляет собой оператор for(), оператор if(), поэтому не имеет смысла ставить скобки вокруг одного оператора.
    Вы бы не стали писать
    а
    { i = 1 + 2; }
    { if(i == 3) { Print(i); } }
    i = 1 + 2;
    if(i == 3) Print(i);
    Упрощаем
       for(int cnt=OrdersTotal() - 1; cnt >= 0; --cnt)
       if(!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))  
       if(OrderType()==OP_BUY)
       if(TrailingStop>0)
       if(Bid-OrderOpenPrice()>Point*TrailingStop)
       if(OrderStopLoss()<Bid-Point*TrailingStop)
       if(!OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green))
       {  Print("OrderModify error ",GetLastError());
          return;
       }
  3. Теперь, когда "&&" (и "||") являются операторами замыкания, не составляйте цепочки " если".
       for(int cnt=OrdersTotal() - 1; cnt >= 0; --cnt)
       if(!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))  
       && OrderType()==OP_BUY)
       && TrailingStop>0)
       && Bid-OrderOpenPrice()>Point*TrailingStop)
       && OrderStopLoss()<Bid-Point*TrailingStop)
       && !OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green))
       {  Print("OrderModify error ",GetLastError());
          return;
       }
  4. Вы хотите изменить порядок, когда выбор порядка не уда лся?
       for(int cnt=OrdersTotal() - 1; cnt >= 0; --cnt)
       if(O rderSelect(cnt,SELECT_BY_POS,MODE_TRADES))  
       && OrderType()==OP_BUY)
       && TrailingStop>0)
       && Bid-OrderOpenPrice()>Point*TrailingStop)
       && OrderStopLoss()<Bid-Point*TrailingStop)
       && !OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green))
       {  Print("OrderModify error ",GetLastError());
          return;
       }
  5. Удалите из цикла все тесты, которые не изменяют порядок.
    if TrailingStop>0){
       for(int cnt=OrdersTotal() - 1; cnt >= 0; --cnt)
       if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))  
       && OrderType()==OP_BUY)
       && Bid-OrderOpenPrice()>Point*TrailingStop)
       && OrderStopLoss()<Bid-Point*TrailingStop)
       && !OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green))
       {  Print("OrderModify error ",GetLastError());
          return;
       }
    }
  6. Не продолжайте вычислять одно и то же.
       if(Bid-OrderOpenPrice()>Point*TrailingStop)
       if(OrderStopLoss()<Bid-Point*TrailingStop)
       if(!OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,O...
    Разберитесь, что вы хотите сделать и нужно ли это делать.
    if TrailingStop>0){
       for(int cnt=OrdersTotal() - 1; cnt >= 0; --cnt)
       if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))  
       && OrderType()==OP_BUY){
          double SL = Bid - Point*TrailingStop;
          if(SL > OrderOpenPrice()    // Start trailing above open price
          && SL > OrderStopLoss()     // And it moves up ONLY
          && !OrderModify(OrderTicket(),OrderOpenPrice(),SL,OrderTakeProfit(),0,Green))
          {  Print("OrderModify error ",GetLastError());
             return;
          }
       }
    }
  7. Как насчет других случаев? Как насчет других графиков и советников?
    if TrailingStop>0){
       for(int cnt=OrdersTotal() - 1; cnt >= 0; --cnt)
       if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES)
       && OrderMagicNumber() == MyExternal
       && OrderSymbol()      == Symbol()  
       ){  
          if(OrderType()==OP_BUY)
          {
             double SL = Bid - Point*TrailingStop;
             if(SL > OrderOpenPrice()    // Start trailing above open price
             && SL > OrderStopLoss()     // And it moves up ONLY
             && !OrderModify(OrderTicket(),OrderOpenPrice(),SL,OrderTakeProfit(),0,Green))
             {  Print("OrderModify error ",GetLastError());
                return;
             }
          }  // OP_BUY
          else // OP_SELL (or pending)
          { ...                       
          }                           
       }  // OrderSelect
    }  // Trailing

 
WHRoeder:
  1. Вы ДОЛЖНЫ вести обратный отсчет при закрытии/удалении при наличии нескольких ордеров. Подумайте о советнике на других графиках. Также предпочитайте ++x вместо x++ (особенно при работе с классами).
  2. Язык - это оператор for(), оператор if(), так что не имеет смысла заключать в скобки один оператор.
    Вы бы не стали писать
    но
    Поэтому упрощайте
  3. Теперь, когда "&&" (и "||") являются операторами замыкания, не составляйте цепочки ifs.
  4. Вы хотите изменить порядок, если выборка порядка завершилась неудачей?
  5. Удалите из цикла все тесты, которые не изменяют порядок.
  6. Не продолжайте вычислять одно и то же. Разберитесь, что вы хотите сделать и нужно ли это делать.
  7. А как насчет других случаев? Как насчет других графиков и советников?

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

Это раздел ордеров на покупку в коде трейлинг-стопа из примера советника MetaQuotes MACD, поставляемого с MT4.

1) Неправда, вы можете считать вверх или вниз, цикл более эффективен, OrdersTotal() вызывается один раз и присваивается локальной переменной.

 
SDC: Я разместил этот код просто как пример.
Я разместил только увеличение темы.
 

Спасибо SDC . Спасибо за советы также WHRoeder . Это полезно .

Я попробовал поменять OrderClosePrice() на MarketInfo в предыдущем коде и отредактировал (убрал условие && и поместил их в оператор if как после, тот что во втором цикле for), но результат все равно иногда работает иногда не работает.

В цикле for для подсчета общего количества ордеров в пуле я использую цикл обратного отсчета, но с x--. Я не понимаю, почему вы предлагаете --x.

Я нагуглил "операторы короткого замыкания", но не очень понимаю, что это значит в mql4, не могли бы вы немного объяснить ^_^ ? Почему плохо замыкать цепочки 'if'?

Кстати, код выше, который предложил SDC, это не тот код, который я использую >.< .

 

Неплохо выстраивать цепочки "если". Разработчики языка MQL4 написали код, который я разместил выше. Это код, который я вырезал из их примера советника macd в качестве примера.

WHR имел в виду недавнее изменение в способе оценки условий && ||, которое теперь делает их такими же эффективными, как и цепочки if. Ранее они были менее эффективны. Вы можете использовать любой из этих методов. Цепочки if полезны, когда в коде есть расхождения, и вы можете использовать 'else'.

Длинные строки условий if( && || ) могут создать путаницу в круглых скобках, что затрудняет поиск ошибок, поэтому я не люблю так делать. Кроме того, существует общепринятый стандарт кодирования, согласно которому оно не должно превышать 80 символов. Однако многие кодеры не стремятся придерживаться этого стандарта, и разработчики MQL4 продолжают создавать перечислимые идентификаторы с большими длинными именами, которые используются в вызовах функций с такими же большими длинными именами, что не очень помогает в форматировании кода.