Problema dell'inserimento di ordini multipli per un conto live con un broker specifico - pagina 2

 
Malacarne:

CiaoBlindMist, ha senso controllare il tuo database locale per verificare se il tuo account è sincronizzato con il server del broker.

Per favore dai un'occhiata al post suggerito per affrontare questo problema.

Ho appena esaminato il post suggerito e non menziona come evitare che gli ordini vengano eseguiti più volte...

Anche con la funzione Sleep(), quanto tempo bisogna aspettare per essere certi che il trade è fallito?

Nel mio EA avevo una richiesta di invio dell'ordine che scadeva dopo 10 secondi prima di riprovare... ma a volte l'ordine viene eseguito 15-20 secondi dopo la richiesta iniziale; quindi, con conseguente doppio trade indesiderato.

 
BlindMist:

Ho appena letto il post suggerito e non menziona come evitare che gli ordini vengano eseguiti più volte...

Anche con la funzione Sleep(), quanto tempo bisogna aspettare per avere la certezza che il trade è fallito?

Nel mio EA avevo una richiesta di invio dell'ordine che scadeva dopo 10 secondi prima di riprovare... ma a volte l'ordine viene eseguito 15-20 secondi dopo la richiesta iniziale; quindi, con conseguente doppio trade indesiderato.

CiaoBlindMist, la mia idea su questo argomento, che penso ancora sia l'unico modo per controllarlo (invece di un solo test di PositionSelect o un solo Sleep), è creare qualcosa come un errore fatale dopo aver atteso a lungo, o saltare non appena si ha la posizione del simbolo (codice sotto).

L'unica cosa buona di questo problema è che probabilmente PositionSelect, presto o tardi, otterrà la posizione aggiornata dal server, quindi quello che dobbiamo fare è aspettare un tempo massimo (il nostro timeout) per indicare un errore fatale e fare piccoli campioni per controllare se è OK (100 ms nel mio esempio).

bool fatalError=false; // atention: declare this as global

....

if (fatalError==false) {
  if (m_Trade.PositionOpen(Symbol(), ORDER_TYPE_BUY, LotSize, Price, 0, 0)) {
    Print("Position opened in ", Symbol());
    int maxTimeout=0;
    while (!PositionSelect(Symbol())) {
       Sleep(100);
       maxTimeout++;
       if (maxTimeout>100) {
          Print("### PositionSelect fatal error!");
          fatalError=true;
          break;
       }
    }
    Print("--> PositionSelect delay=",maxTimeout*100);
    break;
  }
}

Un altro modo per fare questo più modulare è creare una funzione per controllare il timeout, per esempio:

bool PositionSelectTimeout(string symbol,int timeout) 
  { // timeout in seconds
   int maxTimeout=0;
   while(!PositionSelect(symbol)) 
     {
      Sleep(100);
      maxTimeout++;
      if(maxTimeout>(timeout*10)) return(false); // fatal error (timeout)
     }
   return(true); // position selected
  }

L'idea principale qui è che la mia PositionSelectTimeout() sostituisca l'originale PositionSelect(), come workaround ovviamente, dato che solo MQ può affrontare una soluzione davvero buona e definitiva.

Per esempio:

if (PositionSelectTimeout(Symbol(),60)) { // 60 seconds timeout
 ...
}

// instead of ...

if (PositionSelect(Symbol())) {
 ...
}

Quindi, secondo me,FinanceEngineer deve fare lo stesso per risolvere il problema, e inserire questo test all'interno del suo ciclo, per controllare due volte se la posizione va bene per fare una pausa.

 
figurelli:

CiaoBlindMist, la mia idea su questo argomento, che penso ancora sia l'unico modo per controllarlo (invece di un solo test di PositionSelect o un solo Sleep), è creare qualcosa come un errore fatale dopo aver atteso a lungo, o saltare appena si ha la posizione del simbolo (codice sotto).

L'unica cosa buona di questo problema è che probabilmente PositionSelect, presto o tardi, otterrà la posizione aggiornata dal server, quindi quello che dobbiamo fare è aspettare un tempo massimo (il nostro timeout) per indicare un errore fatale e fare piccoli campioni per controllare se è OK (100 ms nel mio esempio).

Un altro modo per fare questo più modulare è creare una funzione per controllare il timeout, per esempio:

L'idea principale qui è che la mia PositionSelectTimeout() sostituisca l'originale PositionSelect(), come workaround ovviamente, dato che solo MQ può affrontare una soluzione davvero buona e definitiva.

Per esempio:

Quindi, secondo me,FinanceEngineer deve fare lo stesso per risolvere il problema, e inserire questo test all'interno del suo ciclo, per controllare due volte se la posizione è OK per fare una pausa.

Grazie figurelli, risposta molto dettagliata. Farò un tentativo e vedrò se migliora il mio sistema.
 
BlindMist:
Grazie figurelli, risposta molto dettagliata. Farò un tentativo e vedrò se migliora il mio sistema.
Grazie, non c'è di che.
 
BlindMist:

Ho appena letto il post suggerito e non menziona come evitare che gli ordini vengano eseguiti più volte...

Anche con la funzione Sleep(), quanto tempo bisogna aspettare per avere la certezza che il trade è fallito?

Nel mio EA avevo una richiesta di invio dell'ordine che scadeva dopo 10 secondi prima di riprovare... ma a volte l'ordine viene eseguito 15-20 secondi dopo la richiesta iniziale; quindi, con conseguente doppio trade indesiderato.

15 secondi per l'esecuzione di un ordine. Questo è davvero brutto. Il problema qui è che non possiamo ottenere nulla dal sever del Broker (per esempio, anche un semplice pezzo di codice di controllo dello stato, ecc)
 
FinanceEngineer:
15 secondi per l'esecuzione di un ordine. Questo è davvero brutto. Il problema qui è che non possiamo ottenere nulla dal server del Broker (per esempio, anche il semplice controllo dello stato del codice, ecc.)

CiaoFinanceEngineer, hai ragione, tuttavia la prima cosa da gestire è selezionare un broker a bassa latenza, poiché i mercati sono ogni volta più veloci, e sarà solito tali problemi.

Inoltre, è sempre bene pensare al caso peggiore, perché si può avere un broker a bassa latenza ma in alcuni momenti della giornata un grande ritardo, per esempio quando si hanno notizie rilevanti.

Comunque, OrderSend() in MT5 non è così facile da gestire come in MT4, perché il valore restituito da MT4 è un Ticket. Questo cambiamento è stato necessario in MT5 perché la comunicazione asincrona dei mercati azionari, introdotta nell'architettura MQL5, è abilitata a comunicare con il protocollo OMS del broker (come FIX, per esempio).

Ma penso che questo sia il grande cambiamento di OMS per la gestione degli ordini oggi, dal momento che è molto difficile ottenere un biglietto in tempo reale, e MT5 è aggiornato a questo nuovo scenario, soprattutto se usiamo i mercati azionari, dove abbiamo più latenza.

In questo senso, la cosa più rilevante da fare dopo un OrderSend() a MT5 è controllare PositionSelect(), e suggerisco vivamente di usare la mia proposta PositionSelectTimeout() workaround, per tutte le ragioni di cui sopra.

L'unico modo che vedo per pensare ai casi peggiori è gestire tutte le condizioni if { } else { } dopo aver inviato un ordine al mercato, in modo da poter gestire qualsiasi situazione.

Mi piacerebbe avere anche catch { }, ma possiamo usare GetLastError() per fare qualcosa di simile.

Questo perché hai anche bisogno del ticket per confermare una posizione e MT5 OrderSend() non restituisce il ticket in modo sincrono come fa MT4.

 
BlindMist:

Ho appena letto il post suggerito e non menziona come evitare che gli ordini vengano eseguiti più volte...

Anche con la funzione Sleep(), quanto tempo bisogna aspettare per avere la certezza che il trade è fallito?

Nel mio EA ho avuto una richiesta di invio dell'ordine che scade dopo 10 secondi prima di riprovare... ma a volte l'ordine viene eseguito 15-20 secondi dopo la richiesta iniziale; quindi, con conseguente doppio trade indesiderato.

Questo è il mio codice che sto usando attualmente. Finora non ho alcun problema. Potete provare questo codice e se funziona per quel broker.

      bool checkOrderSend = OrderSend(request, result);
     
      if(result.retcode==10009 || result.retcode==10008)
      {
          Print("OrderSend was successful. Code: ",result.retcode);

          
          break;
      }
      else
      {
          Print(ResultRetcodeDescription(result.retcode));
      }
     

 
FinanceEngineer:

Questo è il mio codice che sto usando attualmente. Finora non ho alcun problema. Potete provare questo codice e se funziona per quel broker.

      bool checkOrderSend = OrderSend(request, result);
     
      if(result.retcode==10009 || result.retcode==10008)
      {
          Print("OrderSend was successful. Code: ",result.retcode);

          
          break;
      }
      else
      {
          Print(ResultRetcodeDescription(result.retcode));
      }
     

Cosa fai con la variabile checkOrderSend?

Come impedisci che vengano eseguiti più ordini senza controllare il completamento dell'operazione sul server?

 
figurelli:

Cosa fate con la variabile checkOrderSend?

Come si impedisce l'esecuzione di più ordini senza controllare il completamento dell'affare del server?

Ciao figurelli

Il mio punto era di controllare entrambi i codici 10009 e 10008 alla fine della funzione OrderSend. Perché ho trovato molte persone che controllano solo uno dei due codici di ritorno (cioè 10009 o 10008) e ricevono molti ordini multipli perché normalmente inseriscono un ciclo for per evitare la situazione di nessun ordine.

Nel mio caso, il mio ciclo for tenterà 10 volte se non ottengo alcun ordine con quel broker. Quindi probabilmente vale la pena di chiarire che se qualcuno sta ricevendo ordini multipli, allora dovrebbe controllare se stanno fermando il loro ciclo Ordersending controllando sia 10009 che 10008.

Tuttavia, ironicamente, nel conto demo, controllare solo un codice di ritorno va bene. Non vi darà alcun problema di ordine multiplo. Quindi qui ho trovato che il conto live e il conto demo si comportano in modo leggermente diverso.

Cordiali saluti.

 
FinanceEngineer:

Ciao figurelli

Il mio punto era di controllare entrambi i codici 10009 e 10008 alla fine della funzione OrderSend. Perché ho trovato molte persone che controllano solo uno dei due codici di ritorno (cioè 10009 o 10008) e ottengono molti ordini multipli, perché normalmente inseriscono un ciclo for per evitare la situazione di nessun ordine.

Nel mio caso, il mio ciclo for tenterà 10 volte se non ottengo alcun ordine con quel broker. Quindi probabilmente vale la pena di chiarire che se qualcuno sta ricevendo ordini multipli, allora dovrebbe controllare se stanno fermando il loro ciclo Ordersending controllando sia 10009 che 10008.

Tuttavia, ironicamente, nel conto demo, controllare solo un codice di ritorno va bene. Non vi darà alcun problema di ordine multiplo. Quindi qui ho trovato che il conto live e il conto demo si comportano in modo leggermente diverso.

Cordiali saluti.

CiaoFinanceEngineer, forse sarebbe meglio iniziare a controllare il tuo codice originale il problema degli ordini multipli, dato che se facciamo questo probabilmente affronteremo altri punti critici qui e non perdere il focus, cosa ne pensi?