Nützliche Funktionen von KimIV - Seite 2

 
Wie wäre es damit:
if (err==146)
{
while (IsTradeContextBusy())
{
if (IsTradeAllowed()) break;
else
Sleep(1000*1,1);
}}
Ich denke, das ist eine schnellere Lösung. Bitte teilen Sie uns Ihre Kommentare mit.
Ich danke Ihnen.
 
Red.Line писал (а): Danke für das nützliche Thema, auch wenn es mir um verbrannte Torten geht, aber vielleicht hat sich schon jemand mit dem Problem der Vorratshaltung und der Probenahme aus großen Datensätzen in µl auseinandergesetzt. µl und Datenbanken? Hat jemand in diese Richtung gedacht?
Sicherlich eine einfache Lösung, aber immerhin etwas. https://forum.mql4.com/ru/9377
 
zhuki:
Was würden Sie von dieser Variante halten?
if (err==146)
{
  while (IsTradeContextBusy())
  {
    if (IsTradeAllowed()) break;
    else 
    Sleep(1000*1,1);
  }
}
Dies scheint mir eine schnellere Lösung zu sein, denn ich arbeite auf diese Weise. Kommentar.
Ich danke Ihnen.

Ich werde damit zurechtkommen. Mit Verständnis. Die Pause ist kürzer, es funktioniert schneller... Aber es gibt einige ungerechtfertigte Redundanzen in Ihrer Version.

Die Funktion IsTradeContextBusy gibt das Flag der Belegung des Handels-Threads zurück. Vor dem 195. Baujahr gab es eine solche Funktion nicht. Daher haben wir die Funktion IsTradeAllowed verwendet, die ein Zeichen dafür liefert, dass der EA handeln darf und der Handelsfluss frei ist.

Wir erlauben dem EA den Handel, indem wir im Dialogfeld der EA-Eigenschaften (Taste F7) das Kästchen "EA zum Handel zulassen" aktivieren.

Die Fehlermeldung 146 (Trade Stream is busy) hat nichts damit zu tun, dass der Expert Advisor den Handel zulässt. Schauen wir uns also die Eigenschaften der Funktion IsTradeAllowed an, soweit sie sich nur auf den Handelsfaden beziehen.

Der Handelsfaden ist also frei und die Funktion IsTradeAllowed gibt True zurück. Der Handels-Thread ist beschäftigt, die Funktion IsTradeAllowed gibt False zurück. Werfen wir nun einen Blick auf die Werte, die von der Funktion IsTradeContextBusy zurückgegeben werden. Der Handelsfaden ist frei, die Funktion IsTradeContextBusy gibt False zurück. Der Handels-Thread ist beschäftigt, die Funktion IsTradeContextBusy gibt True zurück. Es ist zu erkennen, dass die Werte der Funktionen IsTradeAllowed und IsTradeContextBusy für dieselben Handelsströme entgegengesetzt sind. Außerdem duplizieren sich diese Funktionen gegenseitig, anstatt sich in Bezug auf die Handelsströme zu ergänzen. Daher kann einer von ihnen ausgeschlossen werden. Welcher ist es? Die IsTradeAllowed Funktion, wie ich bereits oben erwähnt habe, gibt neben dem Trade Flow State Flag auch das Flag zurück, das dem EA den Handel erlaubt, was in dieser Situation, d.h. bei der Behandlung des Fehlers 146 (Trade Flow is busy), für uns nicht notwendig ist. Daher ist es notwendig und ausreichend, nur eine Funktion IsTradeContextBusy zu verwenden. Wenn Sie die oben genannten Abkürzungen ausführen, wird Ihr Code auf meinen reduziert:

if (err==146) while (IsTradeContextBusy()) Sleep(1000*1,1);
Der einzige Unterschied ist die Größe der Pause. Aber das ist eine Frage des Geschmacks, der persönlichen Vorlieben, des Handelsstils usw. Sie könnten eine Pause von 0,1 Sekunden einfügen. Es ist keine große Sache... Ich bevorzuge einfach 11 Sekunden.
 
Aus Gründen der Genauigkeit ziehe ich es jedoch vor, zwischen allen Arten von Handelsoperationen eine Pause von 5 Sekunden bis zur Freigabe des Fadens einzulegen. Ich danke Ihnen.
 

In der Funktion SetOrder wurden zwei Fehler gefunden:

  1. Falsche Verwendung der MarketInfo-Funktion. Sie hätte NACH der Überprüfung des sy-Parameters aufgerufen werden müssen, nicht VOR der Überprüfung.
  2. Korrektur von fehlerhaft arbeitenden Auftragseinstellungsebenen. Darüber hinaus wurden die Preisniveaus von Stopps und Übernahmen nicht korrigiert. Jetzt ist das Problem behoben und funktioniert perfekt. Ich habe diese Sache lange Zeit mit dem Testskript getestet, das ich etwas später zeigen werde.

Achtung! Der Beitrag mit der SetOrder-Funktion für den Online-Handel wurde korrigiert. Die Funktion ist etwas länger. Er passte nicht in den ganzen Pfosten, also musste er in den Anhänger verlegt werden.

 

In diesem Beitrag habe ich beschlossen, die wichtigsten Punkte zu erläutern, wie die Funktion SetOrder funktioniert. Ich selbst arbeite nicht mit Aufträgen, d. h. ich befinde mich hier auf dem Gebiet eines anderen. Vielleicht kann jemand, der weiß, wie die SetOrder-Funktion funktioniert, Verbesserungen vorschlagen oder Fehler finden.

1. In den ersten Zeilen des Codes werden lokale Variablen deklariert und einige von ihnen initialisiert. In lsComm werden zum Beispiel der Name des EA und der Name des von der Funktion GetNameTF zurückgegebenen Zeitrahmens geschrieben. Übrigens werde ich nicht auf Funktionen wie GetNameOP, GetNameTF, Message usw. eingehen, nur wenn jemand Fragen dazu hat.

string   lsComm=WindowExpertName()+" "+GetNameTF(Period());

2. Überprüfung der empfangenen Parameter. Wenn sy leer ist, wird es mit dem Namen des aktuellen Werkzeugs initialisiert. Die Variable für die Farbe des Symbols im Diagramm wird durch die Art der Operation initialisiert. Wenn die Verfallszeit des Auftrags, die nicht Null ist, kleiner als die aktuelle Zeit ist, wird sie auf Null zurückgesetzt.

if (sy=="" || sy=="0") sy=Symbol();
msl=MarketInfo(sy, MODE_STOPLEVEL);
if (op==OP_BUYLIMIT || op==OP_BUYSTOP) clOpen=clOpenBuy; else clOpen=clOpenSell;
if (ex>0 && ex<TimeCurrent()) ex=0;

3. der Körper des Zyklus der Handelsversuche, deren Anzahl durch den Wert der globalen Variablen NumberOfTry begrenzt wird. Es folgen die Operationen, die innerhalb der Hauptschleife der Funktion SetOrder ausgeführt werden.

for (it=1; it<=NumberOfTry; it++)

4. Wenn die Funktion SetOrder im Tester nicht ausgeführt wird, haben wir die Möglichkeit, ihre Ausführung zu beenden. Hier wird auf den Freigabezyklus des Handelsstroms gewartet. Die Variablen der Marktumgebung werden aktualisiert und die aktuelle Zeit wird erfasst.

if (!IsTesting() && (!IsExpertEnabled() || IsStopped())) {
  Print("SetOrder(): Остановка работы функции");
  break;
}
while (!IsTradeAllowed()) Sleep(5000);
RefreshRates();
ot=TimeCurrent();

5. Senden einer Anfrage an einen Handelsserver. Wenn das Ticket positiv ist, wird die Funktion SetOrder beendet.

ticket=OrderSend(sy, op, ll, pp, Slippage, sl, tp, lsComm, mn, ex, clOpen);
if (ticket>0) {
  if (UseSound) PlaySound(NameFileSound); break;
 

6. Wenn das Ticket negativ ist, wird die Bearbeitung von Ausführungsfehlern durchgeführt.
7. Bei den Fehlern 128 (Wartezeit für die Geschäftsausführung ist abgelaufen), 142 (Auftrag steht in der Warteschlange) und 143 (Auftrag wird vom Händler zur Ausführung angenommen) wird eine Pause von 66 Sekunden eingelegt. Nach der Pause prüfen wir mit der Funktion ExistOrders (die wir später beschreiben werden), ob die Bestellung in der Zeit zwischen der Anfrage des Servers und dem aktuellen Moment bereits eingestellt wurde. Wenn die Reihenfolge festgelegt wurde, beenden Sie die Funktion.

err=GetLastError();
if (err==128 || err==142 || err==143) {
  Sleep(1000*66);
  if (ExistOrders(sy, op, mn, ot)) {
    if (UseSound) PlaySound(NameFileSound); break;
  }
  Print("Error(",err,") set order: ",ErrorDescription(err),", try ",it);
  continue;
}

8. Die Positionsgröße sowie der Geld- und Briefkurs werden in den lokalen Variablen gespeichert.

mp=MarketInfo(sy, MODE_POINT);
pa=MarketInfo(sy, MODE_ASK);
pb=MarketInfo(sy, MODE_BID);

9. Im Falle des Fehlers 130 (Falsche Stops) werden die Preisniveaus der Order, des Stops und des Take-Outs nach Möglichkeit korrigiert.

// Неправильные стопы
if (err==130) {
  switch (op) {
    case OP_BUYLIMIT:
      if (pp>pa-msl*mp) pp=pa-msl*mp;
      if (sl>pp-(msl+1)*mp) sl=pp-(msl+1)*mp;
      if (tp>0 && tp<pp+(msl+1)*mp) tp=pp+(msl+1)*mp;
      break;
    case OP_BUYSTOP:
      if (pp<pa+(msl+1)*mp) pp=pa+(msl+1)*mp;
      if (sl>pp-(msl+1)*mp) sl=pp-(msl+1)*mp;
      if (tp>0 && tp<pp+(msl+1)*mp) tp=pp+(msl+1)*mp;
      break;
    case OP_SELLLIMIT:
      if (pp<pb+msl*mp) pp=pb+msl*mp;
      if (sl>0 && sl<pp+(msl+1)*mp) sl=pp+(msl+1)*mp;
      if (tp>pp-(msl+1)*mp) tp=pp-(msl+1)*mp;
      break;
    case OP_SELLSTOP:
      if (pp>pb-msl*mp) pp=pb-msl*mp;
      if (sl>0 && sl<pp+(msl+1)*mp) sl=pp+(msl+1)*mp;
      if (tp>pp-(msl+1)*mp) tp=pp-(msl+1)*mp;
      break;
  }
  Print("SetOrder(): Скорректированы ценовые уровни");
}

10. Die Informationen, die zur Lösung des Problems oder zur späteren Fehlersuche beitragen können, werden im Bericht angezeigt.

Print("Error(",err,") set order: ",ErrorDescription(err),", try ",it);
Print("Ask=",pa,"  Bid=",pb,"  sy=",sy,"  ll=",ll,"  op=",GetNameOP(op),
      "  pp=",pp,"  sl=",sl,"  tp=",tp,"  mn=",mn);
if (pa==0 && pb==0) Message("SetOrder(): Проверьте в обзоре рынка наличие символа "+sy);

Am Ende bearbeiten wir weitere Fehler. Einige von ihnen zeigen eine lange Pause (5 Minuten), andere blockieren den Expert Advisor, wieder andere erlauben weitere Handelsversuche, usw.

Das war's! Ende der Beschreibung!

 

Die Funktion ExistOrders().

Gibt ein Kennzeichen für das Vorhandensein eines Auftrags zurück. Beantwortet die Frage, ob der Auftrag eingestellt ist oder nicht. Mit dieser Funktion können Sie jede beliebige Bestellung, aber auch spezifischere Bestellungen anfordern. Der Anfragefilter wird über die Funktionsparameter konfiguriert:

  • sy - Schränkt den Namen des Instruments ein. Der Standardparameter ist "" - keine Einschränkung, d. h. ein beliebiges Instrument. Wenn Sie NULL übergeben, wird die Auftragsauswahl durch das aktuelle Symbol begrenzt.
  • op - schränkt die Auftragsart ein. Standardmäßig keine Einschränkung, d. h. jede Auftragsart wird geprüft. Gültige Werte des Parameters sind -1, OP_BUYLIMIT, OP_BUYSTOP, OP_SELLLIMIT und OP_SELLSTOP.
  • mn - setzt eine Grenze für die Identifikationsnummer ("magische" Nummer) des Auftrags. Standardmäßig keine Einschränkung, d. h. der Auftrag mit einer beliebigen magischen Zahl wird geprüft.
  • ot - setzt eine Grenze für die Zeit der Auftragserteilung. Es wird geprüft, ob der Auftrag später als der Wert dieses Parameters festgelegt wurde. Standardmäßig gibt es kein Limit, d.h. ein Auftrag mit beliebiger Einstellzeit wird geprüft.
//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 12.03.2008                                                     |
//|  Описание : Возвращает флаг существования ордеров.                         |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    sy - наименование инструмента   (""   - любой символ,                   |
//|                                     NULL - текущий символ)                 |
//|    op - операция                   (-1   - любой ордер)                    |
//|    mn - MagicNumber                (-1   - любой магик)                    |
//|    ot - время открытия             ( 0   - любое время установки)          |
//+----------------------------------------------------------------------------+
bool ExistOrders(string sy="", int op=-1, int mn=-1, datetime ot=0) {
  int i, k=OrdersTotal(), ty;
 
  if (sy=="0") sy=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      ty=OrderType();
      if (ty>1 && ty<6) {
        if ((OrderSymbol()==sy || sy=="") && (op<0 || ty==op)) {
          if (mn<0 || OrderMagicNumber()==mn) {
            if (ot<=OrderOpenTime()) return(True);
          }
        }
      }
    }
  }
  return(False);
}
 

Beispiele für die Verwendung der Funktion ExistOrders().

1. Verfügbarkeit einer Bestellung prüfen

ExistOrders();

2. Prüfen Sie die Verfügbarkeit eines beliebigen Auftrags für ein beliebiges Instrument auf dem aktuellen Chart

ExistOrders(NULL);

3. Prüfen Sie das Vorhandensein eines BuyLimit-Auftrags für ein beliebiges Instrument

ExistOrders("", OP_BUYLIMIT);

4. Prüfen Sie, ob eine SellStop-Order mit der magischen Nummer 123456 auf EURUSD vorliegt.

ExistOrders("EURUSD", OP_SELLSTOP, 123456);

5. Prüfen Sie die Verfügbarkeit von Aufträgen mit einer Rüstzeit von 2 Stunden oder weniger

ExistOrders("", -1, -1, TimeCurrent()-2*60*60);
Im Trailer befindet sich ein Skript zum Testen der Funktion ExistOrders. Die ersten 4 Beispiele im Skript sind auskommentiert.

Dateien:
 

Warnung! Im Beitrag vom 12.03.2008 07:24 habe ich den Anhang SetOrder.mq4 ersetzt