Errore #1 quando si modificano gli ordini - pagina 4

 
hoz:

Boris, supponiamo che sia così... Assumendo. Ma, se la funzione invia nuovamente un ordine per modificare l'ordine, il significantton dovrebbe essere modificato. E con me non si modifica affatto. Anche se guardiamo il registro nel registro, quello che vediamo è questo:

Perché l'ordine viene inviato? Se non avesse avuto i parametri giusti, la funzione sarebbe stata buttata fuori... È come OK... ...è stato inviato. Poi si è scoperto che c'era un errore... Qual è la logica che c'è dietro?

Appena acceso! Victor, se "ok", significa che qualche parametro è cambiato, ma l'errore 1 significa che qualche parametro è stato dichiarato per cambiare, ma è risultato invariato. Ecco perché dobbiamo correggere la vostra logica per evitare questi casi, e tutte queste imprecisioni si tradurranno in requote e un sacco di errori sul mercato reale!

Sapete che non uso questo tipo di stile di programmazione, che tutto è sparso dappertutto. Scrivo il programma come uno script logico, tutti gli eventi si sviluppano in modo sequenziale, e tutto è sempre a portata di mano con tutte le condizioni senza dover setacciare in giro alla ricerca di qualcosa. E uso funzioni esterne per eseguire l'azione finale e controllare gli errori.

Ma nel tuo caso, non è chiaro ai non iniziati cosa hai e dove è spuntato, tutto è nascosto, e devi indovinare se hai spuntato il prerequisito o no! Sono un sacco di parole, come le mie adesso, ma il tuo programma non riesce a cogliere il punto. Dovrebbe essere chiaro e conciso!

 

Boris, mi rendo conto naturalmente di non avere tutto in un unico posto. Ma i parametri di input subito prima della funzione di modifica sono agganciati. Ho appena lanciato uno screenshot. Ci sono PLO attuali e nuovi, SL e TP. E sono tutti diversi. Perché entrare nei dettagli quando tutto è vicino? Se non è stampato, e puoi vedere che i parametri sono diversi, significa che sono davvero diversi. O forse non dovreste fidarvi nemmeno della stampa?

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

E prima di questo, come ho mostrato sopra, c'è un test:

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

Come puoi essere più specifico? Ci sono un paio di pagliacci in cima che hanno iniziato a inventare storie. Apparentemente non potevano o non volevano capire quello che chiedevo. Quindi stanno ridendo senza motivo. Ma la domanda è interessante.

Se inseriamo per esempio un parametro di un altro tipo o una quantità sbagliata in OrderModify(), si verificano subito degli errori. Ed ecco che viene eseguito, dice come OK, ma poi si scopre che nessun parametro è stato cambiato.

La domanda è come facciamo a sapere cosa c'è di sbagliato lì? Ho esposto la mia funzione. Tutto dovrebbe essere chiaro lì. Ecco qui:

// 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);
      }
      }
   }
   

Ho volutamente commentato tutte le linee. Potresti solo rovinare il codice. Se avete dei commenti, per favore aiutatemi.

 
hoz:

Boris, mi rendo conto naturalmente di non avere tutto in un unico posto. Ma i parametri di input subito prima della funzione di modifica sono agganciati. Ho appena lanciato uno screenshot. Ci sono PLO attuali e nuovi, SL e TP. E sono tutti diversi. Perché entrare nei dettagli quando tutto è vicino? Se non è stampato, e puoi vedere che i parametri sono diversi, significa che sono davvero diversi. O forse non dovreste fidarvi nemmeno della stampa?

E prima di questo, come ho mostrato sopra, c'è un test:


Tutto

Scusa, non sono in grado di dare un senso a questo perché non vedo nessuna condizione nel ciclo che assicuri che i parametri dell'ordine non si confondano tra loro!

La presenza di un errore vi dice che state facendo un errore logico da qualche parte. Ma dice anche che il programma funziona, ma a noi interessa la qualità del programma!

 
borilunad:

Scusa, non sono in grado di capirlo perché non vedo nessuna condizione nel ciclo che assicuri che i parametri dell'ordine non si confondano tra loro!

La presenza di un errore vi dice che state facendo un errore logico da qualche parte. Ma dice anche che il programma funziona, ma a noi interessa la qualità del programma!


Tutte le operazioni con gli ordini si svolgono in un ciclo! È qui che viene chiamato il metodo fOrderModify(), il cui codice ho citato sopra:

//+---------------------------------------------------------------------------------------------------------------------------------------+
//|                                                   Перенос лимитных ордеров по сигналу                                                 |
//+---------------------------------------------------------------------------------------------------------------------------------------+
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");
}

Si può vedere tutto lì... Potete anche vedere che dopo ogni iterazione del ciclo l'errore viene cancellato. Così, il fatto è garantito che un errore nell'ordine precedente, se c'è stato, non salterà a quello successivo (intendo il suo valore, ovviamente).

Quanto può essere più facile? È così semplice...

 

Ho trovato un messaggio.

È lo stesso bug del terminale. Non ho mai avuto un bug del genere prima d'ora. Non ho mai provato a cambiare i 3 parametri (OOP, SL e TP) degli ordini in sospeso. Ma ho dovuto farlo. E mi sono imbattuto in un bug.

Vedo che se, per esempio, il prezzo aperto e lo Stop Loss non sono cambiati e al loro posto otteniamo gli stessi valori, ma i Take Point sono cambiati. Causa anche l'errore? Poi si scopre che la documentazione è storta. E questo punto non è supportato o cosa?

 
hoz:

Ho trovato un messaggio.

È lo stesso bug del terminale. Non ho mai avuto un bug del genere prima d'ora. Non ho mai provato a cambiare i 3 parametri (OOP, SL e TP) degli ordini in sospeso. Ma ho dovuto farlo. E mi sono imbattuto in un bug.

Vedo che se, per esempio, il prezzo aperto e lo Stop Loss non sono cambiati e al loro posto otteniamo gli stessi valori, ma i Take Point sono cambiati. Causa anche l'errore? Poi si scopre che la documentazione è storta. E questo punto non è supportato o cosa?

Controllate anche la distanza ad ogni spunta? Ho adottato da tempo la regola di aprire gli ordini all'apertura della barra TF e di modificarli e chiuderli solo all'apertura della barra su M1! Il codice di cui sopra mi ricorda un rapporto di progresso, che sembra contenere tutto, ma niente di concreto! Non vedo un ciclo in cui si definiscono tutte le azioni in base a condizioni specifiche! Vedo solo un ciclo che mi dice che non c'è niente da modificare, quindi basta non modificare e non ci saranno errori.

Notate l'importante osservazione di Renat che i vostri errori possono derivare dalla confusione su cosa fare globalmente e cosa fare localmente, e gli errori sono sempre questi ultimi, quelli precedenti vengono resettati senza il vostro coinvolgimento con l'uscita della funzione!

 
borilunad:

Controlli anche la distanza ad ogni spunta?!

No! Permetto le modifiche solo se viene soddisfatta una condizione. In questo caso, la condizione per la modifica è cambiare i livelli calcolati. Proprio così:

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]);
   }
}

Semplice? Semplice....

Borilunad:


Ho stabilito da tempo la regola di aprire gli ordini all'apertura di una barra in TF, e di modificare e chiudere solo all'apertura di una barra in M1! Il codice di cui sopra mi ricorda un progress report, che sembra contenere tutto, ma niente di specifico! Non vedo un ciclo in cui si definiscono tutte le azioni in base a condizioni specifiche! Vedo solo un ciclo che mi dice di non modificare nulla, quindi basta non modificare e non ci saranno errori.

Anch'io ho avuto pensieri simili, per modificare solo all'apertura di M1, e, questo è applicabile se la modifica è fatta da un valore predefinito. Ma ci sono situazioni in cui non ho bisogno di controllare questi dati su M1. Per esempio, ho uno stop tirato a un livello che è già stato calcolato. Poi, come ho mostrato sopra, ho un controllo nella funzione OnInit():

if (FirstInd != ND (MurreyLevelsValue[1]))
{
   MovingLimitPositions (MurreyLevelsValue);
   FirstInd = ND (MurreyLevelsValue[1]);
}
Cioè se il livello è cambiato... modifica. Questo evita inutili tentativi di modifica. Per così dire, modifica per segnale e non per timer. Capito qui?


borilunadi:


Non vedo un ciclo in cui si definiscono tutte le azioni in base a condizioni specifiche! Vedo solo un ciclo che mi dice di non modificare nulla, poi basta non modificare e non ci sono errori.

Ho tutto spogliato là fuori. Cosa c'è da non capire... :(

borilunadi:

Notate l'importante punto di Renat che i vostri errori possono venire dalla confusione su cosa fare globalmente e cosa fare localmente, e gli errori sono sempre questi ultimi, quelli precedenti vengono resettati senza il vostro coinvolgimento con l'uscita della funzione!

Questo problema, come ho scoperto, non si verifica solo con me. Ecco un esempio...

E sembra che non sia stato risolto e non lo sarà. Forse gli sviluppatori sono pigri? Se non sto lavorando correttamente con gli errori, qualcuno, compreso Renat avrebbe potuto frugare nel codice, e non solo dire che ho sbagliato.

Dopo tutto, se i valori nuovi e attuali dei parametri da modificare sono stampati prima della funzione di modifica, è chiaro che questi valori sono lì. Perché andare più in alto da qualche parte? Ci sono dei valori, è chiaro che non ci sono errori (ho stampato lì per gli errori). Significa che tutto va bene nella logica. Quindi la colpa è della funzione di modifica.

 
hoz:

No! Permetto le modifiche solo se viene soddisfatta una condizione. In questo caso, la condizione per la modifica è cambiare i livelli calcolati. Proprio così:

Semplice? Solo....

Anch'io ho avuto pensieri simili, per modificare solo all'apertura di M1, e, questo è applicabile se la modifica viene effettuata da un valore predeterminato. Ma ci sono situazioni in cui non ho bisogno di controllare questi dati su M1. Per esempio, ho uno stop tirato a un livello che è già stato calcolato. Poi, come ho mostrato sopra, c'è un controllo nella funzione OnInit():

Cioè se il livello è cambiato, è... modifica. Questo evita inutili tentativi di modifica. Per così dire, modifica per segnale e non per timer. Capito qui?


Ho staccato tutto lì. Cosa c'è da non capire... :(

Non sono l'unico ad avere questo problema, come ho scoperto. Ecco un esempio...

E sembra che non sia stato risolto e non lo sarà. Forse gli sviluppatori sono pigri? Se non sto lavorando correttamente con gli errori, qualcuno, compreso Renat potrebbe frugare nel codice, e non solo dire che ho sbagliato.

Dopo tutto, se i valori nuovi e attuali dei parametri da modificare sono stampati prima della funzione di modifica, è chiaro che questi valori sono lì. Perché andare più in alto da qualche parte? Ci sono dei valori, è chiaro che non ci sono errori (ho stampato lì per gli errori). Significa che tutto va bene nella logica. Quindi la colpa è della funzione di modifica.

Ho già guardato questo esempio. Ma dobbiamo applicarci a qualsiasi condizione, finché non c'è niente di meglio. Il tuo codice non mi convince. Ora vado a pranzo, poi vi darò un esempio di un ciclo, che funziona bene per l'impostazione di SL, la conversione in B/S e la pesca a strascico per una sola chiamata alla funzione di modifica, dove gli errori sono gestiti, se si presentano improvvisamente nel lavoro, nel tester non si presentano.

Volete la funzione Modify()?

 
hoz:

Dopo tutto, se i valori nuovi e attuali dei parametri da modificare sono stampati prima della funzione di modifica, è chiaro che questi valori ci sono. Perché andare più in alto da qualche parte? Ci sono dei valori, è chiaro che non ci sono errori (ho stampato lì per gli errori). Significa che tutto va bene nella logica. Quindi la colpa è della funzione di modifica.

Il codice sembra a posto... e sul reale (non demo) funziona?
 

Victor, perché hai modificato lo SL e il TP nelle posizioni in sospeso? In generale, ha senso impostare lo SL solo dopo aver aperto una posizione, e il TP dopo il trasferimento dello SL al B/S! Allora perché disturbare così tanto il server per niente e perché devi fare tutto questo casino?

È necessario ridurre al minimo e semplificare il codice, per farlo funzionare in modo veloce e chiaro, e poi sarà più facile modificarlo a causa dei capricci del mercato! Pensate attentamente a tutte le sfumature legate alle realtà del mercato!

Motivazione: