Il mio EA fa una doppia entrata - pagina 7

 

se uso il sonno, perderò le zecche?

Quali saranno le conseguenze? può condividere con me?

Documentation on MQL5: Common Functions / Sleep
Documentation on MQL5: Common Functions / Sleep
  • www.mql5.com
Common Functions / Sleep - Documentation on MQL5
 
doshur:

se uso il sonno, perderò le zecche?

Quali saranno le conseguenze? può condividere con me?

Dipende dalla tua strategia. Dato che questo problema dei "doppi trade" può verificarsi solo quando il tuo codice di trading viene eseguito su ogni tick, probabilmente hai una strategia che dipende dai tick. Quindi sta a te valutare quali possono essere le conseguenze se perdi i tick che arrivano durante il tuo ritardo (sleep).

 
angevoyageur:

Dipende dalla tua strategia. Siccome questo problema dei "doppi trade" può verificarsi solo quando il tuo codice di trading viene eseguito su ogni tick, probabilmente hai una strategia che dipende dai tick. Quindi sta a te valutare quali possono essere le conseguenze se perdi i tick che arrivano durante il tuo ritardo (sleep).

Quindi se dormo per 800

significa che perdo ticks per i prossimi 800ms? Dopo che sono entrato nel mio trade, il mio EA non fa nulla, sta solo seduto lì fino al TP o SL o aspetta il tempo per uscire.

Quindi la mia strategia è ok se uso il sonno?

chiamando refreshrates() si recuperano i tick?

Documentation on MQL5: Common Functions / Sleep
Documentation on MQL5: Common Functions / Sleep
  • www.mql5.com
Common Functions / Sleep - Documentation on MQL5
 
doshur:

Quindi se dormo per 800

significa che perdo ticks per i prossimi 800ms? Dopo che sono entrato nel mio trade, il mio EA non fa nulla, solo si siede lì fino al TP o SL o aspetta il tempo per uscire.

Quindi la mia strategia è ok se uso il sonno?

chiamando refreshrates() si recuperano i tick?

doshur, itick che perdi, li perdi, non c'è una macchina del ritorno.

Per quanto riguarda la documentazione suhttps://www.mql5.com/en/docs/common/sleep la funzionesospende l'esecuzione dell'Expert Advisor o dello script corrente entro un intervallo specificato.

Quindi, anche gli eventi OnTimer saranno sospesi, probabilmente perché l'EA usa un solo thread.

Quindi, usare uno Sleep fisso non è una soluzione definitiva, è solo "numerologia", cioè un workaround se il ritardo è inferiore al tuo valore.

E questo è il motivo per cui propongo un ciclo di test PositionSelect dopo l'apertura del commercio, per controllare due volte l'esecuzione PositionOpen e ritorno come un workaround migliore di Sleep(), e che anche comprovare la causa del problema (secondoangevoyageur test).

Documentation on MQL5: Common Functions / Sleep
Documentation on MQL5: Common Functions / Sleep
  • www.mql5.com
Common Functions / Sleep - Documentation on MQL5
 

Questo è quello che sto usando ora. Dove dovrei codificare il workaround fornito da figurelli in un modo più elegante

//
         {
            Price = SymbolInfoDouble(Symbol(), SYMBOL_ASK);

            if(m_Trade.PositionOpen(Symbol(), ORDER_TYPE_BUY, LotSize, Price, 0, 0))
            {
               Sleep(800);

               if(m_Trade.ResultRetcode() == 10009)
               {
                  Print("Position opened in ", Symbol());

                  return;
               }
               else
               {
                  Print("Error opening position in ", Symbol(), " - ", m_Trade.ResultComment(), "\n", "Return Code Desc - ", m_Trade.ResultRetcodeDescription());
               }
            }
            else
            {
               Print("Error with PositionOpen in ", Symbol(), " - ", m_Trade.ResultComment(), "\n", "Return Code Desc - ", m_Trade.ResultRetcodeDescription());
            }
         }
 
doshur:

Questo è quello che sto usando ora. Dove dovrei codificare il workaround fornito da figurelli in un modo più elegante

Ciao doshur, anche io stavo avendo problemi con le doppie entrate in uno dei miei EA. In realtà, questi problemi si verificavano solo quando facevo trading di attività altamente liquide. Anche dopo aver impostato l'invio degli ordini in modalità asincrona, l'EA stava "apparentemente" aspettando troppo a lungo la risposta del server per aggiornare PositionsTotal()... nel frattempo, altri tick in arrivo facevano scattare le condizioni per inviare un secondo ordine... nel forum portoghese ho postato un workaround, che vorrei condividere qui.

L'idea è semplice:

//--- global variables
CTrade trade;
bool position_opened=false;

//--- inside OnTick()
if( conditions to open && position_opened==false )
  {
   //--- set the global variable to true to avoid duplicate orders
   position_opened=true;
   trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,"comment");
  }

L'unico problema con questo codice è il caso in cui l'ordine non viene accettato dal server, quindi è necessario "resettare" la variabile globale... Si potrebbe usare questo:

MqlTradeResult mresult;

//--- 
if(mresult.retcode==10009 || mresult.retcode==10008)
  {Print("Success!");}
else 
  {
   Print("Error = ",GetLastError());
   ResetLastError();
   //--- Sets the global variable to false
   position_opened=false;
   return;
  }

Così, nel caso in cui il primo ordine inviato restituisca un errore, la variabile globale sarà impostata su false in modo che l'EA possa inviare un altro ordine. Tuttavia, devo dire che ho testato questo codice solo in azioni e futures, ma non nel mercato forex... :-(

 
Malacarne:

Ciao doshur, anche io ho avuto problemi con le doppie voci in uno dei miei EA. In realtà, questi problemi si verificavano solo quando facevo trading di attività altamente liquide. Anche dopo aver impostato gli ordini da inviare in modalità asincrona, l'EA stava "apparentemente" aspettando troppo a lungo una risposta del server per aggiornare PositionsTotal()... nel frattempo, altri tick in arrivo facevano scattare le condizioni per inviare un secondo ordine... nel forum portoghese ho pubblicato un workaround, che vorrei condividere qui.

L'idea è semplice:

L'unico problema con questo codice è il caso in cui l'ordine non viene accettato dal server, quindi è necessario "resettare" la variabile globale... Potreste usare questo:

Così, nel caso in cui il primo ordine inviato restituisca un errore, la variabile globale sarà impostata su false in modo che l'EA possa inviare un altro ordine. Tuttavia, devo dire che ho testato questo codice solo in azioni e futures, ma non nel mercato forex... :-(

Questo sembra fattibile. Vediamo sefigurelli eangevoyageur hanno qualche commento su questo workaround...
 
doshur:
Questo sembra fattibile. Vediamo sefigurelli eangevoyageur hanno qualche commento su questo workaround...

Questa soluzione proposta da Malacarne (con alcuni aggiustamenti che proporrò) è ottima, poiché per me non è un workaround (come si riferisce modestamente Malacarne), ma un modo elegante e giusto di affrontare la questione.

A mio parere, il problema originale della doppia entrata non è un bug di MT5, ma un bug di codifica, dal momento che la guida afferma:

"Il completamento con successo del metodo PositionOpen(...) non significa sempre l'esecuzione con successo dell'operazione di trading. È necessario controllare il risultato della richiesta di negoziazione (codice di ritorno del server di negoziazione) utilizzandoResultRetcode() e il valore, restituito daResultDeal()".

Quindi, suggerisco alcune piccole modifiche per essere più resistenti a qualsiasi condizione di mercato:

1) Testate anche il ritorno di PostionOpen(), come il codice originale, per esempio:

if (trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,"comment")) position_opened=true;

2) Un trattamento più completo di ResultRetcode(), poiché si possono avere altre posizioni rilevanti aperte, come 10010 -TRADE_RETCODE_DONE_PARTIAL - Solo una parte della richiesta è stata completata. Inoltre, 10008 - TRADE_RETCODE_PLACED - Order placed non è Success per me, solo 10009 -TRADE_RETCODE_DONE -Request completed, e questi sono messaggi asincroni, quindi la seconda parte del codice Malacarne potrebbe considerare questo e/o ildeal ticket, dopo che il deal è stato eseguito,anche.

Comunque, mi sembra che ora siamo sulla strada giusta e sul taglio finale.

 
Malacarne:

Ciao doshur, anche io ho avuto problemi con le doppie voci in uno dei miei EA. In realtà, questi problemi si verificavano solo quando facevo trading di attività altamente liquide. Anche dopo aver impostato l'invio degli ordini in modalità asincrona, l'EA stava "apparentemente" aspettando troppo a lungo la risposta del server per aggiornare PositionsTotal()... nel frattempo, altri tick in arrivo facevano scattare le condizioni per inviare un secondo ordine... nel forum portoghese ho postato un workaround, che vorrei condividere qui.

L'idea è semplice:

L'unico problema con questo codice è il caso in cui l'ordine non viene accettato dal server, quindi è necessario "resettare" la variabile globale... Potreste usare questo:

Così, nel caso in cui il primo ordine inviato restituisca un errore, la variabile globale sarà impostata su false in modo che l'EA possa inviare un altro ordine. Tuttavia, devo dire che ho testato questo codice solo in azioni e futures, ma non nel mercato forex... :-(

E' un approccio valido, tuttavia devi resettare la tua variabile globale position_opened a false quando la tua posizione viene chiusa. Dove lo stai facendo?

Riguardo alla tua implementazione, alcuni dettagli:

  1. Non c'è bisogno di impostare position_opened a true e poi a false se c'è un errore.
  2. State usando un oggetto della classe CTrade, quindi non c'è bisogno di usare una nuova struttura MqlTradeResult.
  3. Come ha notato Figurelli nel suo post, dovete controllare il valore restituito di PositionOpen.
  4. Il nome della classe è CTrade, non Ctrade. mql5 è sensibile alle maiuscole.
  5. position_opened è un bool, non è necessario confrontarlo con false. Se lo fate, dovete usare '==' e non '='.

Quindi, ecco il codice modificato(compilato ma non testato):

//+------------------------------------------------------------------+
//|                                                      ProjectName |
//|                                      Copyright 2012, CompanyName |
//|                                       http://www.companyname.net |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>

//--- global variables
CTrade trade;
bool position_opened=false;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
   bool conditions_to_open;
   ENUM_ORDER_TYPE order_type;
   double lot;
   double price,sl,tp;

//---...set variables

//--- inside OnTick()
   if(conditions_to_open && !position_opened) //-- Or position_opened==false
     {
      if(trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,"comment")
         && 
         (trade.ResultRetcode()==10009 || trade.ResultRetcode()==10008)) //-- Or others condition according to your needs
        {
         //--- set the global variable to true to avoid duplicate orders
         position_opened=true;
         Print("Success!");
        }
      else
        {
         Print("Error = ",GetLastError(), "trade error = ", trade.ResultRetcode());
         //--- Sets the global variable to false
         // position_opened=false;                                         //-- Not needed as position_opened is already false
         return;
        }

     }
//--- 
  }
//+------------------------------------------------------------------+
 
figurelli:

...

A mio parere, il problema originale della doppia entrata non è un bug di MT5, ma un bug di codifica, dato che la guida afferma che:

"Il completamento con successo del metodo PositionOpen(...) non significa sempre l'esecuzione con successo dell'operazione di trading. È necessario controllare il risultato della richiesta di negoziazione (codice di ritorno del server di negoziazione) utilizzandoResultRetcode() e il valore, restituito daResultDeal()".

Non credo che sia collegato al problema di questo argomento. Il problema che otteniamo è nel caso in cui una richiesta è stata compilata con successo e viene aperta una posizione. Ma questa posizione è aperta sul server commerciale, il problema che abbiamo incontrato è quando c'è un ritardo più importante del solito e il terminale MT5 viene notificato di questa nuova posizione DOPO che un nuovo tick è già stato elaborato.

Non è un bug, in quanto è progettato in questo modo. MA a mio parere è un cattivo disegno per una piattaforma che permette esplicitamente richieste di trading sincrone e asincrone. Stiamo parlando qui di una richiesta che dovrebbe essere sincrona, ma in realtà non è veramente sincrona in quanto quando si ottiene la risposta dal server per la richiesta (trade.ResultRetCode nel codice sopra) dobbiamo ancora aspettare che la piattaforma MT5 sia informata e aggiornata sui risultati del trading. (Ho capito tutto questo con questo thread).

Quindi, suggerisco alcune piccole modifiche per essere più resistenti a qualsiasi condizione di mercato:

1) Testate anche il ritorno di PostionOpen(), come il codice originale, per esempio:

2) Un trattamento più completo di ResultRetcode(), dal momento che si possono avere altre posizioni rilevanti aperte, come 10010 -TRADE_RETCODE_DONE_PARTIAL - Solo una parte della richiesta è stata completata. Inoltre, 10008 - TRADE_RETCODE_PLACED - Order placed non è Success per me, solo 10009 -TRADE_RETCODE_DONE -Request completed, e questi sono messaggiasincroni, quindi la seconda parte del codice Malacarne potrebbe considerare questo e/o ildeal ticket, dopo che il deal è stato eseguito,anche.

Comunque, mi sembra che siamo sulla strada giusta e sul taglio finale ora.

Naturalmente, hai assolutamente ragione sul fatto che bisogna controllare il valore restituito di PositionOpen E il codice restituito del risultato della negoziazione. Tuttavia il ResultRetCode è sincrono, è l'aggiornamento del database MT5 sulla posizione (operazione e ordine) che è asincrono. Il test che ho fatto con la tua proposta lo ha dimostrato, dato che uso ovviamente un codice che controlla il valore restituito della richiesta di trade.