Loop e chiusura o cancellazione di ordini - pagina 5

 
Eleni Anna Branou:

Per favore usa il pulsante </> per inserire il tuo codice.


Le mie scuse... Eccolo in formato corretto.

OrdersTotal() non corretto...

Sono stato sorpreso da una sequenza di codice in loop che usa OrdersTotal() che non dà risultati corretti (osservato con due diversi broker).

Sto usando MT4 versione 1090 su un desktop Linux Ubuntu-MATE 16.04, con WINE 3.0

Ecco cosa ho usato...

Ecco come stanno le cose:

for(int cc = 0; cc < OrdersTotal(); cc++)
{
      if (!OrderSelect(cc, SELECT_BY_POS, MODE_TRADES) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderType() > 1) continue;    //--ignore pending trades

      OpenTradecnt++;    //--counts up for every live position of that symbol that exists
      Print("count of the open trades of this symbol is: ", OpenTradecnt);

Ho notato con due diversi broker che il valore di OrdersTotal() non sempre concorda con quello che viene mostrato nella scheda 'Trade' del broker MT4. Inizialmente, ho pensato che fosse il broker a causare il non corretto funzionamento di OrdersTotal(). Quando l'ho notato sul secondo broker, ho iniziato a chiedermi se MT4 avesse un 'problema' interno, o se il mio codice fosse sbagliato O se questo fosse un problema con MT4 che si sincronizza correttamente con il server....?

Dopo aver letto questo thread del forum, mi chiedo se avrei risultati migliori modificando il ciclo for:

for(int cc = OrdersTotal() - 1; cc >= 0; cc--)
{
      if (!OrderSelect(cc, SELECT_BY_POS, MODE_TRADES) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderType() > 1) continue;    //--ignore pending trades

      OpenTradecnt++;    //--counts up for every live position of that symbol that exists
      Print("count of the open trades of this symbol is: ", OpenTradecnt);
O, c'è un flag o una linea di codice che assicura che OrdersTotal() sia correttamente sincronizzato durante un evento OnTick()?

Qualsiasi chiarimento su questo sarebbe molto utile e sarebbe molto apprezzato!

 
Simon Gniadkowski:

Questo è uno degli errori più comuni che vedo, probabilmente dovuto in parte a spazzatura come Expert Advisor Builder. Così ho pensato che fosse il momento di un thread dedicato all'argomento in modo che possa essere collegato per riferimenti futuri.

Il problema

Facciamo un semplice esempio; vogliamo una funzione per chiudere tutti gli ordini aperti per il nostro EA, ci sono molti esempi ma creiamone uno da zero.

Abbiamo bisogno di un ciclo perché vogliamo chiudere tutti i nostri ordini per uno specifico EA, all'interno di questo ciclo avremo del codice per selezionare l'ordine, il codice per controllare che sia il simbolo e il numero magico corretti e infine il codice per chiudere l'ordine:

Questo codice è cattivo . . . NON USATELO. . . Spiegherò perché nella prossima sezione . . .

La spiegazione

Lavoriamo attraverso il codice di cui sopra . . . linea per linea, ordine per ordine . . .

Supponiamo di avere i seguenti ordini che vogliamo chiudere, tutti hanno lo stesso numero magico e simbolo del nostro EA, quindi vogliamo che il nostro codice li chiuda tutti:

Posizione Numero d'ordine
0111
1222
2 333
3444
4555

1a esecuzione del ciclo:

il valore iniziale di PositionIndex è 0 quindi viene selezionato l'ordine alla posizione 0, il biglietto numero 111, questo ordine viene cancellato con successo e gli ordini rimanenti cambiano posizione come segue:

Posizione Numero del biglietto
0222
1 333
2444
3555

2a esecuzione del ciclo:

ora il valore di PositionIndex è 1 quindi viene selezionato l'ordine in posizione 1, il ticket numero 333, questo ordine viene cancellato con successo e i restanti ordini cambiano posizione come segue:

Posizione Numero del biglietto
0222
1 444
2555

3a esecuzione del ciclo:

ora il valore di PositionIndex è 2 quindi viene selezionato l'ordine in posizione 2, il biglietto numero 555, questo ordine viene cancellato con successo e gli ordini rimanenti cambiano posizione come segue:

Posizione Numero del biglietto
0222
1 444

4a esecuzione del ciclo:

ora il valore di PositionIndex è 3 OrderSelect() cerca di selezionare l'ordine alla posizione 3 e fallisce, il continue porta l'esecuzione del codice al valore successivo nel ciclo .


5° e ultima esecuzione del ciclo:

ora il valore diPositionIndex è 4 OrderSelect() cerca di selezionare l'ordine alla posizione 4 e fallisce, il continue porta l'esecuzione del codice al prossimo valore nel ciclo . . . il ciclo è finito.


Ora siamo rimasti con 2 ordini, i biglietti 222 e 444 che avrebbero dovuto essere chiusi ma non lo sono stati . . . poi, come risolvere questo problema.

La soluzione

Il codice seguente è l'approccio corretto quando si chiudono gli ordini aperti o si cancellano gli ordini in sospeso. . .

La differenza chiave è che il ciclo decrementa da ( TotalNumberOfOrders - 1 ) a 0

Ancora una volta lavoriamo attraverso il codice di cui sopra ... linea per linea, ordine per ordine ...

Abbiamo gli stessi ordini di prima:

Posizione Numero del biglietto
0111
1222
2333
3444
4555

1a esecuzione del ciclo:

il valore iniziale di PositionIndex è TotalNumberOfOrders - 1 che è uguale a 5 - 1 = 4, quindi viene selezionato l'ordine in posizione 4, numero di ticket 555, questo ordine viene cancellato con successo e gli ordini rimanenti cambiano posizione come segue:

Posizione Numero del biglietto
0111
1222
2333
3444

2a esecuzione del ciclo:

ora il valore di PositionIndex è 3 quindi viene selezionato l'ordine in posizione 3, il biglietto numero 444, questo ordine viene cancellato con successo e gli ordini rimanenti cambiano posizione come segue:

Posizione Numero del biglietto
0111
1222
2333

3a esecuzione del ciclo:

ora il valore di PositionIndex è 2 quindi viene selezionato l'ordine in posizione 2, il biglietto numero 333, questo ordine viene cancellato con successo e i restanti ordini cambiano posizione come segue:

Posizione Numero del biglietto
0111
1222

4a esecuzione del ciclo:

ora il valore di PositionIndex è 1 quindi viene selezionato l'ordine in posizione 1, il biglietto numero 222, questo ordine viene cancellato con successo e i restanti ordini cambiano posizione come segue:

Posizione Numero del biglietto
0111

5° e ultimo giro del ciclo:

ora il valore di PositionIndex è 0 quindi viene selezionato l'ordine in posizione 0, biglietto numero 111, questo ordine viene cancellato con successo, il valore 0 è l'ultimo valore valido per il ciclo . . . il ciclo è finito .

Abbiamo cancellato con successo tutti i nostri ordini corrispondenti . . .

Link a questo thread: Loop e chiusura o cancellazione di ordini

grazie mille! è una spiegazione molto chiara
 
Ciao codificatori,
Holetto questo thread sulla selezione degli ordini. In effetti, ho un codice in cui credo di aver fatto le cose per bene ma la selezione non mi funziona perché non riesco a leggere l'OpenPrice dell'ordine selezionato. Tutto il resto funziona bene, solo quella parte del codice fornito. Non sono sicuro del perché.
L'intero codice ha 4 sezioni in cui devo chiamare l'OrderOpenPrice subito dopo l'invio dell'ordine... OrderSend funziona bene, OrderSelect non mi dà i risultati di cui ho bisogno. Fate riferimento a 1 sezione del codice se potete aiutarmi.
Grazie.
 if(Protection_Step_One==1)
        {
        while(Protective_Order<0)
          {
          RefreshRates();
          Protective_Order=OrderSend(Symbol(),OP_SELL,Protective_Lots,NormalizeDouble(MarketInfo(Symbol(),MODE_BID),MarketInfo(Symbol(),MODE_DIGITS)),3,0,0,"Intermediary",MN_Sell_Intermediary_Protection,0,Cyan);
          }
  //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Addition for Clamp       
          for (int i=OrdersTotal()-1; i>=0; i--)
            {if(OrderSelect(i,SELECT_BY_POS, MODE_TRADES)==true)
               {if (OrderMagicNumber()==MN_Sell_Intermediary_Protection)
                  { RefreshRates();
                  Intermediary_OpenPrice_Sell= OrderOpenPrice();
                  }
                }
             }   
               //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>..
        if(Protective_Order!=-1)
          { 
          Protection_Step_One=0;
          RealTime_Drawing=2;
          Protective_Mode_Activated=1;
          Protective_Order=-2;
          Defcon=2;

 

Grazie caroSimon Gniadkowski,

Il tuo post mi ha davvero salvato il tempo.

 
Gelson Kasonia:
void OnStart()
{
     int Protective_Order=OrderSend(_Symbol,ORDER_TYPE_BUY,0.01,Ask,3,0,0,"Intermediary");
     if(Protective_Order<0)
          return;
     if(!OrderSelect(Protective_Order,SELECT_BY_TICKET, MODE_TRADES))
          return;
     Print(Protective_Order, " OrderOpenPrice: ", OrderOpenPrice());
}
 

Questo è il codice che suggerisco per chiudere gli ordini a mercato

int MagicNo=1234;
int Slippage=10;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseOrdersBackward()
  {
   for(int i=OrdersTotal()-1; i>=0 && !IsStopped(); i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         Print("Order Select failed, order index: ",i," Error: ",GetLastError());
         continue;
        }

      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNo && OrderType()<=OP_SELL)
        {
         if(!OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage))

            Print("Order Close failed, order ticket: ",OrderTicket()," Error: ",GetLastError());
        }
     }
  }

E suggerisco che questo è il modo corretto se si usa un ciclo forward for (per rispettare le regole FIFO dei broker statunitensi)

int MagicNo=1234;
int Slippage=10;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseOrdersForward()
  {
   for(int i=0; i<OrdersTotal() && !IsStopped(); i++)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         Print("Order Select failed, order index: ",i," Error: ",GetLastError());
         continue;
        }

      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNo && OrderType()<=OP_SELL)
        {
         if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage))
           {
            i--;
           }
         else
           {
            Print("Order Close failed, order ticket: ",OrderTicket()," Error: ",GetLastError());
           }
        }
     }
  }

Nel ciclo forward for,

  1. La funzione OrderTotal() viene utilizzata all'interno del ciclo for per aggiornare il numero rimanente di ordini aperti a ogni iterazione del ciclo, per evitare che l'indice esca dall'array.
  2. L'indice i viene decrementato ad ogni ordine chiuso, per evitare di saltare alcuni ordini.
 
amrali: L'indice i viene decrementato ad ogni ordine chiuso, per evitare di saltare alcuni ordini.
In presenza di più ordini (un EA più grafici, più EA, trading manuale,) mentre si aspetta che l'operazione corrente (chiusura, cancellazione, modifica) sia completata, un qualsiasi numero di altre operazioni su altri ordini potrebbe essere avvenuto contemporaneamente e cambiare l'indicizzazione della posizione:
  1. Per i non FIFO (broker americani)(o l'EA apre solo un ordine per simbolo), puoi semplicemente fare il conto alla rovescia in un ciclo di posizione, e non perderai ordini. Prendi l'abitudine di fare sempre il conto alla rovescia.
    Loop e chiusura o cancellazione di ordini - Forum di programmazione MQL4
    Per il FIFO (broker USA),e si elaborano (potenzialmente) più ordini per simbolo, è necessario trovare l'ordine più vecchio, chiuderlo e, se l'operazione ha successo, rielaborare tutte le posizioni rimanenti.
    Chiudere gli ordini con regole FIFO - Strategy Tester - Forum di programmazione MQL4 - Pagina 2 #16

  2. e controllare OrderSelect nel caso in cui le posizioni precedenti siano state cancellate.
    Cosa sono i valori di ritorno delle funzioni ? Come posso usarli ? - Forum di programmazione MQL4
    Errori comuni nei programmi MQL4 e come evitarli - Articoli MQL4
  3. e se (potenzialmente) processate ordini multipli, dovete chiamareRefreshRates() dopo le chiamate al server se volete usare, sul prossimo ordine / chiamata al server, le variabili predefinite(Bid/Ask) o (essere indipendenti dalla direzione e usare) OrderClosePrice().
 

Saprete quanto questo mi ha aiutato. Non solo con il codice su cui stavo lavorando, ma con la mia comprensione. Ora funziona perfettamente e ho la comprensione per implementarlo in modi diversi.

Apprezzo davvero molto queste informazioni.