Domande di OrderSend() - pagina 5

 

A quanto pare, non ho spiegato molto bene il problema precedente. Lasciatemi provare di nuovo.

Durante l'ultimo anno, la descrizione della lista di valori di enumerazioneENUM_ORDER_TYPE_FILLING è stata cambiata almeno tre volte. La descrizione precedente era la seguente

ENUM_ORDER_TYPE_FILLING

Identificatore

Descrizione

ORDINE_RIEMPIMENTO_FOK

Un'operazione può essere eseguita solo nel volume specificato e a un prezzo uguale o migliore di quello specificato nell'ordine. Se non c'è abbastanza offerta sul mercato al momento per il simbolo dell'ordine, l'ordine non sarà evaso. Questo tipo di riempimento è usato nella modalità di esecuzione SYMBOL_TRADE_EXECUTION_INSTANT oSYMBOL_TRADE_EXECUTION_REQUEST.

ORDINE_RIEMPIMENTO_IOC

Un accordo per eseguire una negoziazione al massimo volume disponibile sul mercato entro il volume specificato nell'ordine e ad un prezzo uguale o migliore di quello specificato nell'ordine. In questo caso non verranno effettuati ordini aggiuntivi per il volume mancante. Questo tipo di riempimento può essere disponibile solo nelle modalità di esecuzione SYMBOL_TRADE_EXECUTION_MARKET eSYMBOL_TRADE_EXECUTION_EXCHANGE a seconda delle impostazioni del server di trading.

ORDINE_RIEMPIMENTO_RITORNO

Accordo per effettuare una negoziazione al massimo volume disponibile sul mercato entro il volume specificato nell'ordine e ad un prezzo uguale o migliore di quello specificato nell'ordine. In questo caso verrà effettuato un ordine aggiuntivo per il volume mancante al prezzo specificato in questo ordine. Questo tipo di riempimento è usato solo per gli ordini in sospeso (TRADE_ACTION_PENDING).

Come possiamo facilmente vedere, c'è una corrispondenza uno-a-uno tra ORDER_FILLING_RETURN e gli ordini pendenti, cioè: ORDER_FILLING_RETURN poteva essere applicato solo agli ordini pendenti e il campo type_filling di tutti gli ordini pendenti poteva essere riempito solo con il valore di ORDER_FILLING_RETURN.

Per gli ordini a mercato(action==TRADE_ACTION_DEAL) il campo type_filling dovrebbe essere stato compilato a seconda delle modalità di esecuzione impostate sul lato server.

Così avevamo un certo paradigma: se c'era un ordine pendente,ORDER_FILLING_RETURN; se c'era un ordine a mercato, ORDER_FILLING_FOK o ORDER_FILLING_IOC (a seconda del modo).

Ora tutto è un po' ribaltato, cioè:

ENUM_ORDER_TYPE_FILLING

Identificatore

Descrizione

ORDINE_RIEMPIMENTO_FOK

Questa politica di riempimento degli ordini significa che l'ordine può essere riempito solo fino al volume specificato. Se non c'è abbastanza volume dello strumento finanziario sul mercato al momento, l'ordine non sarà eseguito. Il volume richiesto può essere compilato da diverse offerte attualmente disponibili sul mercato.

ORDINE_RIEMPIMENTO_IOC

Indica l'accordo di eseguire un trade al massimo volume disponibile sul mercato entro il volume specificato nell'ordine. Se l'esecuzione completa non è possibile, l'ordine sarà riempito al volume disponibile, e il volume non riempito sarà cancellato.

ORDINE_RIEMPIMENTO_RITORNO

Questa modalità è usata solo per gli ordini ORDER_TYPE_BUY_LIMIT e ORDER_TYPE_SELL_LIMIT. In caso di esecuzione parziale l'ordine limite con il volume rimanente non viene cancellato ma rimane in vigore.

Per gli ordini ORDER_TYPE_BUY_STOP_LIMIT e ORDER_TYPE_SELL_STOP_LIMIT viene creato all'attivazione il corrispondente ordine limite ORDER_TYPE_BUY_LIMIT/ORDER_TYPE_SELL_LIMIT con il tipo di esecuzione ORDER_FILLING_RETURN.

La restrizione di usare ORDER_FILLING_FOK e ORDER_FILLING_IOC solo con ordini a mercato è sparita. Inoltre non c'è alcuna restrizione nell'uso di ORDER_FILLING_FOK e ORDER_FILLING_IOC con ordini a mercato a seconda della modalità di esecuzione impostata sul server. C'è una restrizione sull'uso di ORDER_FILLING_RETURN solo con ordini limite e stop_limit .

Quindi la mia domanda è: è accettabile usare ORDER_FILLING_FOK e ORDER_FILLING_IOC per tutti gli ordini (sia a mercato che pendenti) inclusi gli ordini limit e stop_limit? Qualcuno ha capito i cambiamenti?

 

La Libreria Standard ha questo metodo (schematico):

bool CTrade::PositionClose(const string symbol,ulong deviation)
  {
   do
     {
      //--- checking
      if(PositionSelect(symbol))
        {
         if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
           {
            //--- prepare request for close BUY position
            m_request.type =ORDER_TYPE_SELL;
            m_request.price=SymbolInfoDouble(symbol,SYMBOL_BID);
           }
         else
           {
            //--- prepare request for close SELL position
            m_request.type =ORDER_TYPE_BUY;
            m_request.price=SymbolInfoDouble(symbol,SYMBOL_ASK);
           }
        }
      else
        {
         //--- position not found
         m_result.retcode=retcode;
         return(false);
        }
      m_request.action      =TRADE_ACTION_DEAL;
      m_request.volume      =PositionGetDouble(POSITION_VOLUME);
      //--- check volume
      double max_volume=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
      if(m_request.volume>max_volume)
        {
         m_request.volume=max_volume;
         partial_close=true;
        }
      else
         partial_close=false;
      //--- order send
      if(!OrderSend(m_request,m_result))
        {
         if(--retry_count!=0) continue;
         if(retcode==TRADE_RETCODE_DONE_PARTIAL)
            m_result.retcode=retcode;
         return(false);
        }
      retcode=TRADE_RETCODE_DONE_PARTIAL;
      if(partial_close) Sleep(1000);
     }
   while(partial_close);
   return(true);
  }

Qui, nel caso in cui il volume della posizione sia superiore alvolume massimo per effettuare una negoziazione, vengono fattisuccessivi tentativi di chiudere parzialmente la posizione.

Dopo una chiamata riuscita della funzione OrderSend(), viene impostato un ritardo di pochi secondi e poi viene chiamata la funzionePositionSelect() nel corpo del ciclo do-while. Cioè si suppone che nel caso in cui il server accetti con successo un ordine a mercato, un secondo è sufficiente per aggiornare i dati sulla posizione aperta nel terminale base e ottenere i dati di posizione aggiornati (nel nostro esempio - il volume della posizione) alla prossima iterazione. Ma due anni fa, il ritardo nello stesso metodo prima di chiamare la funzione PositionSelect() era di tre secondi. La domanda è quindi:

Un secondo è sufficiente in tutti i casi per assicurare che dopo una chiamata riuscita a OrderSend(), il database del terminale è garantito per ricevere i dati di posizione aggiornati (e quindi permettere che il volume di posizione rimanente sia elaborato correttamente sul lato del terminale)? Qual è il tempo massimo in cui si deve garantire che il database del terminale riceva i dati di posizione aggiornati in questo caso?

 

Il campionato ha una tale regola:

Lecondizioni di trading saranno il più possibile vicine alla realtà:

  • Tempo di elaborazione delle richieste commerciali da 2 a 7 secondi
Su reale con un broker (dopo il ritiro) l'elaborazione è diventata circa 3 secondi (apertura-chiusura-modifica).Immediatamente passato a NDD.Soddisfatto finora.
 
Karlson:

Il campionato ha una tale regola:

Lecondizioni di trading saranno il più possibile vicine alla realtà:

  • tempo di elaborazione da 2 a 7 secondi

OK, grazie per il suggerimento! Risulta che un secondo non è sufficiente per il database del terminale per ricevere i dati di posizione aggiornati dopo una chiamata riuscita della funzione OrderSend()?

Da questa conclusione, ne consegue che il metodo della Libreria Standard che ho citato non garantisce affatto che la posizione venga invertita invece di essere chiusa. Cioè, se il metodo PositionClose() ritarda la prossima iterazione di un secondo, e le richieste di trade possono richiedere 2-7 volte più tempo per essere elaborate, non possiamo escludere che durante le nuove iterazioni, la funzionePositionSelect() riceverà le informazioni precedenti sullo stato della posizione dal terminale base e bombarderà il server con ordini identici, il cui volume totale in questo caso sarà più grande dell'importo iniziale della posizione in chiusura.

Perché allora c'è un ritardo di un secondo nel metodo PositionClose(), se permette di girare la posizione invece di chiuderla? E non è coerente con le"condizioni commerciali, il più vicino possibile a quelle reali"?

In generale, ho bisogno di maggiori informazioni su quanto tempo il database del terminale, dopo una chiamata di successo della funzione OrderSend(), è garantito per ricevere i dati di posizione aggiornati, e qual è la ragione del ritardo di un secondo nel metodo standard PositionClose().

 
Cominciamo con il fatto che
if(PositionSelect(symbol))

non garantisce nulla. Non può essere usato.

In secondo luogo, non vengono fornite garanzie per l'aggiornamento dei dati del terminale. Dovete impostare voi stessi un TradeContextBusy artificiale e aspettare che tutti i vostri ordini vengano elaborati.
Non potete farlo immediatamente e a testa alta in MQL5. Non ci sono garanzie di tempo.

 

sergeev:

начнем с того, что

if(PositionSelect(symbol))

non garantisce nulla. Non può essere applicato.

In secondo luogo, non c'è garanzia per l'aggiornamento dei dati del terminale - devi organizzare tu stesso un TradeContextBusy artificiale e aspettare che tutti i tuoi ordini siano processati.
Non si può usare MQL5 direttamente e direttamente. Non ci sono garanzie di tempo.

Sì, dovrò continuare a riflettere. Si scopre che avrei dovuto prendere il metodo standard della libreria come esempio per il riciclaggio.

Potete dirmi se un accordo appare nella storia con il

DEAL_ENTRY_OUT

Uscita dal mercato

significa che tutte le informazioni nel database del terminale sono cambiate automaticamente (aggiornate allo stato attuale)? O il trade può già apparire nella storia e le informazioni sulla posizione non saranno ancora aggiornate? In altre parole, la domanda è interessante: le informazioni sugli accordi nella storia e le informazioni sulle posizioni corrispondenti cambiano simultaneamente? Oppure, in questo caso, gli affari e le posizioni sono anche aggiornati nel terminale in modo asincrono? Non sono riuscito a prenderlo nell'articolo di Rosh - per quanto ho capito, l'asincronia tra l'aggiornamento della base del terminale e il ritorno del risultato della richiesta di scambio è descritto lì.

 

Il modello di scambio di dati nel terminale è asincrono, come avete notato.

quindi quando si fa trading (recuperando le proprietà di ordini/commerci/posizioni) dobbiamo analizzare il successo del recupero dei dati. E nel caso di qualsiasi errore (falso/0), termina l'analisi della logica di trading.

Tutti gli ordini OrdSend eseguiti e non confermati devono essere memorizzati e attendere la comparsa dell'ordine, bloccando l'invio del nuovo ordine stesso se non c'è ancora una risposta dal precedente invio.

E, per esempio, sarebbe meglio sostituire PositionSelect con un costrutto

for(int i=PositionsTotal()-1;i>=0;i--) 
{
  if(PositionGetSymbol(i)==Symbol())
  {
    ....
  }

In generale, la logica di trading deve essere asincrona. Poiché il terminale è asincrono, il server MT e il server del fornitore di liquidità sono asincroni.

Il compito di controllare la sincronizzazione spetta interamente al programmatore MQL.

Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Типы торговых операций
Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Типы торговых операций
  • www.mql5.com
Стандартные константы, перечисления и структуры / Торговые константы / Типы торговых операций - Документация по MQL5
 

Non ho avuto problemi a usare questa risposta nell'ultimo campionato

https://www.mql5.com/ru/forum/4342#comment_88688

Дублирование запросов на открытие позиций.
Дублирование запросов на открытие позиций.
  • www.mql5.com
Дублирование запросов на открытие позиций.
 
sergeev:

E, per esempio, sarebbe meglio sostituire PositionSelect con il costrutto

for(int i=PositionsTotal()-1;i>=0;i--) 
{
  if(PositionGetSymbol(i)==Symbol())
  {
    ....
  }

Per favore spiegate, se non è difficile, qual è il vantaggio di usarePositionsTotal() + PositionGetSymbol() invece di usare PositionSelect()? Tutte e tre le funzioni accedono alla stessa base terminale, e le funzioni PositionGetSymbol() e PositionSelect() possono fallire. Cioè, se la posizione esiste nella base terminale, sia la funzione PositionSelect() che la costruzione proposta possono fallire. Dovete comunque controllare il codice di errore.

Quali sono le peculiarità/affidabilità del vostro costrutto? Ancora non riuscivo a capirlo.

Документация по MQL5: Торговые функции / PositionSelect
Документация по MQL5: Торговые функции / PositionSelect
  • www.mql5.com
Торговые функции / PositionSelect - Документация по MQL5
 

Mi sto scervellando... lo stop non si imposta... e un sacco di errori. questo è ciò che resta dell'esperimento, e non funziona più

void OnTick(){ if(PositionsTotal()<1){OPEN();}}

bool OPEN(){
             MqlTradeRequest request;
             MqlTradeResult result;
             

             request.symbol       = _Symbol;
             request.action       = TRADE_ACTION_DEAL;
             request.type_filling = ORDER_FILLING_FOK;
             request.deviation    = 100;
             request.volume       = NormalizeDouble(2,2);
             request.type         = ORDER_TYPE_BUY;
             request.price        = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
             request.tp           = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK) + 500*_Point,_Digits);
             request.sl           = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK) - 500*_Point,_Digits);

             OrderSend(request,result);     
                        
             if(result.retcode==10009 || result.retcode==10008)  Print("Succsesful open");
             else                                               Print("Error open: ",DoubleToString(GetLastError(),0),"  response code: ",result.retcode);
    
   return(true);}

Se fate questo, non ci sono errori, ma lo stop-loss non è ancora impostato

MqlTradeRequest request={0};MqlTradeResult result={0};
Motivazione: