Typische Fehler und wie man damit umgeht, wenn man mit dem Handelsumfeld zu tun hat - Seite 3

 
fxsaber:

Die richtige Option anhand eines einfachen Beispiels

Ich denke, es ist besser zu warten, bis der Auftrag berücksichtigt wird, wenn er noch nicht in der Position ist.
 
Комбинатор:
Ich denke, es ist besser, wenn der Auftrag noch nicht in der Position verbucht ist, sondern einfach abgewartet wird, bis er verbucht ist.

Ich verstehe die Idee nicht.

 
Bedingtes Implementierungsschema für normales OrderSend (kein Timeout)
static MqlTradeResult LastResult = {0};

void OnTradeTransaction( const MqlTradeTransaction&, const MqlTradeRequest&, const MqlTradeResult &Result )
{ 
  LastResult = Result;
}

// Условный алгоритм реализации штатной OrderSend
bool OrderSend( const MqlTradeRequest &Request, MqlTradeResult &Result )
{  
  bool Res = OrderSendAsync(Request, Result);
  
  if (Res)
  {
    while (LastResult.request_id != Result.request_id)
      OnTradeTransaction(); // условно-схематичный вызов
          
    Result = LastResult;    
    Res = (Result.retcode == TRADE_RETCODE_PLACED) ||
          (Result.retcode == TRADE_RETCODE_DONE) ||
          (Result.retcode == TRADE_RETCODE_DONE_PARTIAL);

    LastResult.request_id = 0;
  }
    
  return(Res);
}


Dieses Diagramm zeigt, dass es bei der Platzierung eines Marktauftrags mit OrderSendAsync in MetaQuotes-Demo unmöglich ist, den entsprechenden Auftrag zuverlässig abzufangen, bis er entweder ausgeführt oder abgelehnt wird. D.h. es gibt in MT5 keine einfachen Mechanismen zur Auswertung von Zwischenergebnissen ihrer OrderSendAsync.

 

scheint ein Thema zu sein,

Ich möchte darauf hinweisen, dass dieser Code :

if ( !OrderSend(request,result) ) PrintFormat("OrderSend error %d",GetLastError());
else Print(result.price);

funktioniert in der DEMO einwandfrei (result=request),

aber bei REAL - ist es unmöglich, ein Ergebnis zu erhalten (Ergebnis=0.0). ... Es sei denn, Sie warten ein paar Sekunden.

 
Ivan Ivanov:

Scheint zum Thema zu gehören,

Ich möchte darauf hinweisen, dass ein solcher Code :

Bei DEMO funktioniert es einwandfrei (Ergebnis=Anfrage),

aber bei REAL - ist es unmöglich, ein Ergebnis zu erhalten (Ergebnis=0.0). ... Es sei denn, Sie warten ein paar Sekunden.

Es fehlen Daten - Protokolle, Strukturfeldwerte nach OrderSend, Name des Handelsservers.

 
fxsaber:

Kurz gesagt: Wenn es einen Marktauftrag gibt, ist er auch als "Position" zu betrachten. In Anführungszeichen, weil es sich um eine umbrochene Position handelt. Der hervorgehobene Code wird normalerweise nirgendwo angezeigt. Sie vermeidet jedoch die Wiedereröffnung von Positionen. Das Interessanteste ist hier in rot hervorgehoben. Die Notwendigkeit dieses Chips ist nicht sofort ersichtlich.

for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderGetTicket(i) && (OrderGetInteger(ORDER_TYPE) <= ORDER_TYPE_SELL) &&
        !OrderGetInteger(ORDER_POSITION_ID) && (OrderGetString(ORDER_SYMBOL) == Symb))
      Res++;  // если мы сюда попадаем при проверке состояния, не запускать стратегию вообще, т.к. это промежуточное состояние.
 
Комбинатор:

Möglicherweise gibt es beim nächsten Tick kein Handelssignal. Da ich selbst MT4 verwende, kann ich nicht umhin, solche "Positionen" zu sehen, ohne in Schwierigkeiten zu geraten.

 
fxsaber:

Es fehlen Daten - Protokolle, Strukturfeldwerte nach OrderSend, Name des Handelsservers.

//+------------------------------------------------------------------+
//|                                                      TestBUY.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{//--- объявление и инициализация запроса и результата
  MqlTradeRequest request={0};
  MqlTradeResult result={0};
//--- параметры запроса
  request.action =TRADE_ACTION_DEAL;
  request.symbol=_Symbol; 
  request.volume=0.01;
  request.type=ORDER_TYPE_BUY;
  request.price=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
  request.deviation=5;
  request.magic=1234;
  request.tp=0.0;
  request.comment=DoubleToString(request.price,_Digits);
//--- отправка запроса
  if ( !OrderSend(request,result) )
    PrintFormat("OrderSend error %d",GetLastError()); // если отправить запрос не удалось, вывести
//--- информация об операции
  PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order," NewOrder");
}


2018.02.20 15:20:35.845 Trades order #66745055 buy 0.01 / 0.01 EURUSDeur at market done in 610.625 ms

2018.02.20 15:20:35.935 Trades deal #5461453 buy 0.01 EURUSDeur at 1.23403 done (based on order #66745055)

2018.02.20 15:20:35.845 TestBUY (EURUSDeur,M15) retcode=10009 deal=0 order=66745055

Wenn die Anforderung erfüllt ist (10009), warum deal=0

 
Ivan Ivanov:

Wenn die Anfrage erledigt ist (10009), warum deal=0

Das war fast der Ausgangspunkt der Diskussion. Die Links enthalten alle Einzelheiten.

Es gibt eine Lösung, damit OrderSend perfekt funktioniert, aber das wäre Werbung.

 
fxsaber:

Die richtige Option anhand eines einfachen Beispiels

Kurz gesagt: Wenn es einen Marktauftrag gibt, ist er auch als "Position" zu betrachten. In Anführungszeichen, denn es handelt sich um eine verpackte Position. Der hervorgehobene Code wird normalerweise nirgendwo angezeigt. Sie vermeidet jedoch die Wiedereröffnung von Positionen. Das Interessanteste ist hier in rot hervorgehoben. Die Notwendigkeit dieses Chips ist nicht sofort ersichtlich.

Es geht darum, dass es so genannte "closing market orders" gibt. Die gleiche SL/TP. Natürlich möchten wir solche Marktaufträge nicht als "Positionen" sehen. Und wir möchten nicht, dass diese Aufträge, die wir erteilt haben, auch noch geschlossen werden. Die hervorgehobene Bedingung ist also der geeignete Filter.

for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderGetTicket(i) && (OrderGetInteger(ORDER_TYPE) <= ORDER_TYPE_SELL) &&
        !OrderGetInteger(ORDER_POSITION_ID) && (OrderGetString(ORDER_SYMBOL) == Symb))
      Res++;  

SZY Fügen Sie diesen Code hier ein und prüfen Sie das Ergebnis auf einem Demo-Server.

Ich lade alle Interessierten ein, diese Frage zu diskutieren. Meine Meinung zu diesem Thema ist folgende:


  1. Wir senden eine Bestellung an den Server.
  2. Ein Marktauftrag erscheint und kann eventuell storniert werden, aber haben wir ihn bereits als Position gezählt?
for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderGetTicket(i) && (OrderGetInteger(ORDER_TYPE) <= ORDER_TYPE_SELL) &&
        !OrderGetInteger(ORDER_POSITION_ID) && (OrderGetString(ORDER_SYMBOL) == Symb))
      Res++;  

Diese Schleife fügt eine Position hinzu, wenn ein Auftrag gefunden wird, der keinen Positionsbezeichner hat (die ID ist Null).

Wir haben eine weitere Stelle zurückgegeben.

Was passiert, wenn die Bestellung vom Server storniert wird?

...

Ich denke, dass wir bei der Berechnung von Marktaufträgen WRONG_VALUE zurückgeben sollten, zum Beispiel, wenn wir einen gefunden haben - Positionen können nicht kleiner als Null sein. Dies ist ein Signal, dass ein nicht erfasster Marktauftrag vorliegt. Aber nicht, um die Anzahl der Stellen zu erhöhen.