Fragen zu OrderSend() - Seite 5

 

Offensichtlich habe ich das vorherige Problem nicht sehr deutlich erklärt. Lassen Sie es mich noch einmal versuchen.

Im letzten Jahr wurde die Beschreibung der AufzählungswertelisteENUM_ORDER_TYPE_FILLING mindestens dreimal geändert. Die vorherige Beschreibung sah wie folgt aus:

ENUM_ORDER_TYPE_FILLING

Kennung

Beschreibung

AUFTRAG_FUELLUNG_FOK

Ein Geschäft kann nur in der angegebenen Menge und zu einem Preis ausgeführt werden, der gleich oder besser als der im Auftrag angegebene ist. Wenn auf dem Markt nicht genügend Angebot für das Auftragssymbol vorhanden ist, wird der Auftrag nicht ausgeführt. Diese Füllungsart wird im Ausführungsmodus SYMBOL_TRADE_EXECUTION_INSTANT oderSYMBOL_TRADE_EXECUTION_REQUESTverwendet .

AUFTRAG_AUFFUELLEN_IOC

Eine Vereinbarung zur Ausführung eines Geschäfts mit dem maximalen am Markt verfügbaren Volumen innerhalb des im Auftrag angegebenen Volumens und zu einem Preis, der gleich oder besser als der im Auftrag angegebene ist. In diesem Fall werden keine weiteren Bestellungen für den fehlenden Band aufgegeben. Diese Befüllungsart kann nur in den Ausführungsmodi SYMBOL_TRADE_EXECUTION_MARKET undSYMBOL_TRADE_EXECUTION_EXCHANGE verfügbar sein , abhängig von den Einstellungen auf dem Handelsserver.

AUFTRAG_AUFFUELLEN_ZURUECK

Vereinbarung, ein Geschäft mit dem maximalen auf dem Markt verfügbaren Volumen innerhalb des im Auftrag angegebenen Volumens und zu einem Preis auszuführen, der gleich oder besser als der im Auftrag angegebene ist. In diesem Fall wird eine zusätzliche Bestellung für die fehlende Menge zu dem in dieser Bestellung angegebenen Preis aufgegeben. Diese Ausfüllart wird nur für schwebende Aufträge (TRADE_ACTION_PENDING)verwendet.

Wie man unschwer erkennen kann, besteht eine Eins-zu-Eins-Korrespondenz zwischen ORDER_FILLING_RETURN und schwebenden Aufträgen, nämlich: ORDER_FILLING_RETURN konnte nur auf schwebende Aufträge angewendet werden und das Feld type_filling aller schwebenden Aufträge konnte nur mit dem Wert von ORDER_FILLING_RETURN gefüllt werden.

Bei Market Orders(action==TRADE_ACTION_DEAL) sollte das Feld type_filling in Abhängigkeit von den serverseitig eingestellten Ausführungsmodi ausgefüllt sein.

Wir hatten also ein bestimmtes Paradigma: wenn es einen schwebenden Auftrag gab,ORDER_FILLING_RETURN; wenn es einen Marktauftrag gab, ORDER_FILLING_FOK oder ORDER_FILLING_IOC (je nach Modus).

Jetzt wird alles ein bisschen auf den Kopf gestellt, nämlich:

ENUM_ORDER_TYPE_FILLING

Kennung

Beschreibung

AUFTRAG_FUELLUNG_FOK

Diese Auftragsabwicklungspolitik bedeutet, dass der Auftrag nur bis zu dem angegebenen Volumen abgewickelt werden kann. Wenn das Volumen des Finanzinstruments auf dem Markt derzeit nicht ausreicht, wird der Auftrag nicht ausgeführt. Das benötigte Volumen kann aus mehreren auf dem Markt befindlichen Angeboten zusammengestellt werden.

AUFTRAG_AUFFUELLEN_IOC

Zeigt an, dass man bereit ist, ein Geschäft bis zum maximal verfügbaren Volumen auf dem Markt innerhalb des im Auftrag angegebenen Volumens auszuführen. Wenn eine vollständige Ausführung nicht möglich ist, wird der Auftrag bis zum verfügbaren Volumen ausgeführt, und das nicht ausgeführte Volumen wird storniert.

AUFTRAG_AUFFUELLEN_ZURUECK

Dieser Modus wird nur für ORDER_TYPE_BUY_LIMIT und ORDER_TYPE_SELL_LIMIT Aufträge verwendet. Im Falle einer Teilausführung wird der Limitauftrag mit dem verbleibenden Volumen nicht gelöscht, sondern bleibt bestehen.

Für ORDER_TYPE_BUY_STOP_LIMIT und ORDER_TYPE_SELL_STOP_LIMIT Aufträge wird bei der Aktivierung der entsprechende ORDER_TYPE_BUY_LIMIT/ORDER_TYPE_SELL_LIMIT Limitauftrag mit der Ausführungsart ORDER_FILLING_RETURN erstellt.

Die Einschränkung, dass ORDER_FILLING_FOK und ORDER_FILLING_IOC nur bei Marktaufträgen verwendet werden können, wurde aufgehoben. Außerdem gibt es keine Einschränkung bei der Verwendung von ORDER_FILLING_FOK und ORDER_FILLING_IOC mit Marktaufträgen, je nach dem auf dem Server eingestellten Ausführungsmodus. Es gibt eine Einschränkung für die Verwendung von ORDER_FILLING_RETURN nur bei Limit- und Stop_limit-Aufträgen .

Meine Frage lautet also: Ist es akzeptabel, ORDER_FILLING_FOK und ORDER_FILLING_IOC überhaupt für alle Aufträge (sowohl Markt- als auch schwebende Aufträge) einschließlich Limit- und Stop_limit-Aufträgen zu verwenden? Hat jemand die Änderungen herausgefunden?

 

Die Standardbibliothek verfügt über diese Methode (schematisch):

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

Ist das Positionsvolumen größer als dasmaximale Volumen für einen Abschluss, werden mehrere Versuche unternommen, die Position teilweise zu schließen.

Nach einem erfolgreichen Aufruf der Funktion OrderSend() wird eine Verzögerung von einigen Sekunden eingestellt, und dann wird die FunktionPositionSelect() im Körper der do-while-Schleife aufgerufen. D.h. es wird angenommen, dass im Falle einer erfolgreichen Annahme einer Marktorder durch den Server eine Sekunde ausreicht, um die Daten über die offene Position im Basisterminal zu aktualisieren und die aktualisierten Positionsdaten (in diesem Beispiel das Positionsvolumen) bei der nächsten Iteration zu erhalten. Aber vor zwei Jahren betrug die Verzögerung in derselben Methode vor dem Aufruf der Funktion PositionSelect() drei Sekunden. Die Frage ist also:

Reicht eine Sekunde in allen Fällen aus, um sicherzustellen, dass die Terminaldatenbank nach einem erfolgreichen Aufruf von OrderSend() garantiert aktualisierte Positionsdaten erhält (und damit das verbleibende Positionsvolumen auf der Terminalseite korrekt verarbeitet werden kann)? Wie lange sollte die Terminaldatenbank in diesem Fall garantiert aktualisierte Positionsdaten erhalten?

 

Für die Meisterschaft gilt diese Regel:

DieHandelsbedingungen werden so realitätsnah wie möglich sein:

  • Bearbeitungszeit von Handelsanfragen von 2 bis 7 Sekunden
Auf realen mit einem Makler (nach dem Rückzug) Verarbeitung wurde etwa 3 Sekunden (Eröffnung-Schließung-Änderung).sofort zu NDD.zufrieden so weit gewechselt.
 
Karlson:

Die Meisterschaft hat eine solche Regel:

DieHandelsbedingungen werden so realitätsnah wie möglich sein:

  • Bearbeitungszeit von 2 bis 7 Sekunden

OK, danke für den Tipp! Es stellt sich heraus, dass eine Sekunde nicht ausreicht, damit die Terminaldatenbank nach einem erfolgreichen Aufruf der Funktion OrderSend() die aktualisierten Positionsdaten erhält?

Aus dieser Schlussfolgerung folgt, dass die von mir zitierte Methode der Standardbibliothek überhaupt nicht garantiert, dass die Position umgekehrt wird, anstatt geschlossen zu werden. D.h. wenn die Methode PositionClose() die nächste Iteration um eine Sekunde verzögert und die Bearbeitung von Handelsanfragen 2-7 mal länger dauern kann, ist nicht auszuschließen, dass die FunktionPositionSelect() während der neuen Iterationen die vorherigen Informationen über den Zustand der Position vom Basisterminal erhält und den Server mit identischen Aufträgen bombardiert, deren Gesamtvolumen in diesem Fall größer ist als derursprüngliche Betrag der zu schließenden Position.

Warum gibt es dann eine einsekündige Verzögerung in der PositionClose()-Methode, wenn sie es erlaubt, die Position zu drehen, anstatt sie zu schließen? Und es ist nicht mit den"möglichst realitätsnahen Handelsbedingungen" vereinbar?

Generell benötige ich mehr Informationen darüber, wie lange die Terminal-Datenbank nach einem erfolgreichen Aufruf der OrderSend()-Funktion garantiert die aktualisierten Positionsdaten erhält und was der Grund für die einsekündige Verzögerung in der Standard-Methode PositionClose() ist.

 
Beginnen wir mit der Tatsache, dass
if(PositionSelect(symbol))

ist keine Garantie für irgendetwas. Sie kann nicht verwendet werden.

Zweitens gibt es keine Garantien für die Aktualisierung der Terminaldaten. Sie müssen selbst einen künstlichen TradeContextBusy einrichten und darauf warten, dass alle Ihre Aufträge bearbeitet werden.
Sie können nicht sofort und ohne Umschweife in MQL5 einsteigen. Es gibt keine Zeitgarantien.

 

sergeev:

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

if(PositionSelect(symbol))

ist keine Garantie für irgendetwas. Sie kann nicht angewendet werden.

Zweitens gibt es keine Garantie für die Aktualisierung der Terminaldaten - Sie müssen selbst einen künstlichen TradeContextBusy organisieren und warten, bis alle Ihre Aufträge verarbeitet sind.
Sie können MQL5 nicht direkt und unmittelbar verwenden. Es gibt keine Zeitgarantien.

Ja, ich werde weiter darüber nachdenken müssen. Es stellt sich heraus, dass ich die Standardmethode aus der Bibliothek als Beispiel für das Recycling hätte nehmen sollen.

Können Sie mir sagen, ob ein Geschäft in der Historie mit dem

DEAL_ENTRY_OUT

Marktaustritt

bedeutet dies, dass alle Informationen in der Datenbank des Terminals automatisch geändert (auf den aktuellen Stand gebracht) wurden? Oder der Handel erscheint bereits in der Historie und die Informationen über die Position werden trotzdem nicht aktualisiert? Mit anderen Worten, die Frage ist interessant: Ändern sich Informationen über Geschäfte in der Vergangenheit und Informationen über die entsprechenden Positionen gleichzeitig? Oder werden in diesem Fall die Geschäfte und Positionen auch im Terminal asynchron aktualisiert? Ich habe es in Roshs Artikel nicht mitbekommen - soweit ich es verstanden habe, wird dort die Asynchronität zwischen der Aktualisierung der Terminalbasis und der Rückgabe des Ergebnisses der Handelsanfrage beschrieben.

 

Wie Sie bemerkt haben, ist das Datenaustauschmodell im Terminal asynchron.

Beim Handel (Abruf von Eigenschaften von Aufträgen/Geschäften/Positionen) müssen wir also den Erfolg des Datenabrufs analysieren. Im Falle eines Fehlers (falsch/0) wird die Analyse der Handelslogik abgebrochen.

Alle ausgeführten und unbestätigten OrdSend-Aufträge sollten gespeichert werden und auf das Erscheinen des Auftrages warten, wobei das Senden des neuen Auftrages selbst blockiert wird, wenn es noch keine Antwort vom vorherigen Senden gibt.

Und es wäre zum Beispiel besser, PositionSelect durch ein Konstrukt zu ersetzen

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

Im Allgemeinen muss die Handelslogik asynchron sein. Da das Terminal asynchron ist, sind auch der MT-Server und der Server des Liquiditätsanbieters asynchron.

Die Aufgabe, die Synchronisation zu überprüfen, obliegt ausschließlich dem MQL-Programmierer.

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

Ich hatte kein Problem damit, diese Antwort in der letzten Meisterschaft zu verwenden

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

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

Und es wäre zum Beispiel besser, PositionSelect durch das Konstrukt

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

Erläutern Sie bitte, wenn es nicht schwierig ist, was der Vorteil der Verwendung vonPositionsTotal() + PositionGetSymbol() gegenüber der Verwendung von PositionSelect() ist. Alle drei Funktionen greifen auf dieselbe Klemmenbasis zu, und PositionGetSymbol() und PositionSelect() können fehlschlagen. D.h. wenn die Position in der Terminalbasis existiert, können sowohl die Funktion PositionSelect() als auch die vorgeschlagene Konstruktion fehlschlagen. Sie müssen trotzdem den Fehlercode überprüfen.

Was sind die Besonderheiten/Verlässlichkeit Ihres Konstrukts? Ich konnte es immer noch nicht herausfinden.

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

Ich zerbreche mir den Kopf... der Anschlag will sich einfach nicht setzen... und eine Menge Fehler. Das ist das, was von dem Experiment übrig ist, und es funktioniert nicht mehr

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

Wenn Sie dies tun, treten keine Fehler auf, aber der Stop-Loss ist immer noch nicht gesetzt.

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