Bibliotheken: MT4Orders - Seite 85

 
Wirklich erstaunlich für die nahtlose Umwandlung von mt4-Code. Gut gemacht auf all die harte Arbeit und danke für das Teilen ich wirklich zu schätzen wissen
 

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Bibliotheken: MT4Orders

fxsaber, 2023.07.07 13:12

Leistung.

Leistungstabelle (Ausführungszeit in Millisekunden) für b3815 und b2958.

MT5 Aufbau LetzteSchlussZeitMQL4 LetzteSchlussZeitMQL5 LetzteSchlussZeitMQL4_2 LastCloseTimeMQL4+VIRTUAL::Snapshot LetzteSchlusszeitMQL4+VirtualTester
b3815 2875 113 708 732 45
b2958 2718 107 675 715 50

MT4Orders vom 20.07.2022 wurde überall verwendet.

Mit der gleichen Methodik, eine Vergleichstabelle von zwei MT5-Builds: b4040 und b4057.

MT5 Bauart LetzteSchlussZeitMQL4 LetzteSchlussZeitMQL5 LetzteSchlussZeitMQL4_2 LastCloseTimeMQL4+VIRTUAL::Snapshot LetzteSchlusszeitMQL4+VirtualTester
b4040 3663 117 881 928 27
b4057 246 122 171 213 27

Auf b4057+ ist die Leistung von MT4Orders bei der Arbeit mit der Historie nicht schlechter als die des nativen MQL5.


Daher ist die früher gegebene Empfehlung nicht mehr relevant (für MT5 b4057+).

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien.

Bibliotheken: MT4Orders

fxsaber, 2023.07.07 13:12

  • Es ist notwendig, OrderSelect-Aufrufe für historische Orders zu reduzieren. Dies kann auf die in den drei rechten Spalten der Tabelle gezeigten Arten erreicht werden.
 

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Bibliotheken: MT4Orders

fxsaber, 2017.06.14 11:30 AM.

// Liste ändern:
// 14.06.2017:
// Hinzufügen: Die Implementierung der SL/TP-Erkennung von geschlossenen Positionen (geschlossen über OrderClose) ist aktiviert.
// Hinzufügen: MagicNumber ist jetzt vom Typ long - 8 Bytes (vorher int - 4 Bytes).
// Hinzufügen: Wenn in OrderSend, OrderClose oder OrderModify der Farbeingabeparameter (der jüngste) gleich INT_MAX gesetzt ist, wird er generiert.
// die entsprechende MT5-Handelsanfrage (MT4ORDERS::LastTradeRequest), die jedoch NICHT gesendet wird. Stattdessen wird sie von MT5 geprüft,
// Das Ergebnis wird in MT4ORDERS::LastTradeCheckResult verfügbar sein.
// Wenn OrderModify und OrderClose erfolgreich sind, geben sie true zurück, andernfalls false.
// OrderSend gibt bei Erfolg 0 zurück, andernfalls -1.
//
// Wenn der entsprechende Farbeingangsparameter früher als INT_MIN gesetzt wird, то ТОЛЬКО в случае успешной MT5-проверки сформированного
// Handelsanfrage (wie im Fall von INT_MAX) wird gesendet.
// Hinzufügen: Asynchrone Analoga der MQL4-Handelsfunktionen hinzugefügt: OrderSendAsync, OrderModifyAsync, OrderCloseAsync, OrderDeleteAsync.
// Rückgabe der entsprechenden Result.request_id bei Erfolg, sonst 0.

Wenn Sie verstehen müssen, machte das Terminal eine Ablehnung auf den Handel Ordnung oder der Server.

// Wenn abgelehnt, siehe Grund.  
if (!OrderDelete(OrderTicket(), INT_MIN)) // https://www.mql5.com/ru/forum/93352/page12#comment_5290455
  Print(ToString(MT4ORDERS::LastTradeRequest) + // https://www.mql5.com/en/forum/203931#comment_5287237
        ToString(MT4ORDERS::LastTradeResult) +
        ToString(MT4ORDERS::LastTradeCheckResult));
 

Real. Ich benutze MT4Orders, virtuelle Umgebung über Virtual, ich synchronisiere Virtual mit Real. Zu diesem Zweck gehe ich bei jedem Tick die in Real geöffneten Orders mehrmals durch. Zu diesem Zweck erstelle ich beim ersten Durchlauf eine Liste der Aufträge, die mich interessieren, und bei den weiteren Durchläufen arbeite ich mit dieser Liste.

Früher hatte ich einen solchen Code:

long OrderTickets[];
for(int i=OrdersTotal()-1;i>=0;--i)
{
  if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
    continue;
  AddToArray(OrderTickets,OrderTicket());
}
...
for(int i=ArraySize(OrderTickets)-1;i>=0;--i)
{
  if(!OrderSelect(OrderTickets[i],SELECT_BY_TICKET,MODE_TRADES))
    continue;
  do_something();
}

Die Praxis hat gezeigt, dass dies kein guter Weg ist. Ein teilweise gefüllter Begrenzer generiert 2 Aufträge mit demselben Ticket, und beim zweiten Durchlauf wird es ein Missgeschick sein.

Jetzt bin ich auf diesen Code umgestiegen

int Orders[];
for(int i=OrdersTotal()-1;i>=0;--i)
{
  if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
    continue;
  AddToArray(Orders,i);
}
...
for(int i=0;i!=ArraySize(Orders);++i)
{
  if(!OrderSelect(Orders[i],SELECT_BY_POS,MODE_TRADES))
    continue;
  do_something();
}

Zusätzlich wird vor der Arbeit ein Snapshot gemacht. Funktioniert das korrekt oder kann da noch was kommen?

 
traveller00 jedem Tick die in Real geöffneten Orders mehrmals durch. Zu diesem Zweck erstelle ich beim ersten Durchlauf eine Liste von Aufträgen, die mich interessieren, und bei den weiteren Durchläufen arbeite ich mit dieser Liste.

Der Code sah bisher folgendermaßen aus:

Die Praxis hat gezeigt, dass dies keine gute Methode ist. Ein teilweise gefüllter Begrenzer erzeugt 2 Aufträge mit demselben Ticket, und beim zweiten Durchlauf wird er zum Pechvogel.

Es wird kein Unglück geben, wenn Sie es auf diese Weise machen.

AddToArray(OrderTickets, (OrderType() <= OP_SELL) ? OrderTicket() : - OrderTicket());

Dies ist eine Funktion von MT4Orders. SELECT_BY_TICKET ist jedoch kein schneller Mechanismus in MT4/5 und Virtualisierung. Einer der Gründe dafür ist, dass er, wenn er unter den Live-Tickets nicht fündig wird, auf die Historie zurückgreift (das MODE_TRADES-Flag ist nur eine Prioritätsangabe, wo er zuerst suchen muss).


Jetzt habe ich zu diesem Code gewechselt

Zusätzlich wird vor der Arbeit ein Snapshot gemacht. Wird dies korrekt funktionieren oder kann etwas anderes auftreten?

Wir sprechen hier bereits über das Add-on von Virtual.mqh. Natürlich beschleunigen Snapshots die Arbeit sehr, wenn viele Charaktere/Magier gehandelt werden.

Snapshot reduziert die Arbeit mit der Umgebung außerhalb des Expert Advisors (Trading API) auf ein Minimum. D.h. die langsamsten Funktionen werden einmal für das anfängliche Lesen aufgerufen, und dann geht die gesamte Arbeit mit der Handelsumgebung innerhalb des EA, ohne dass der Programmierer es merkt, weil es derselbe MT4-Stil ist.


Es macht Sinn, eine dieser Snapshot-Varianten zu verwenden.

#define  VIRTUAL_SNAPSHOT_REFRESHTIME 1000 // Snapshot-Lebensdauer für die Aktualisierung. In MT5 erfordert verbunden MT4Orders.mqh
#define  VIRTUAL_SNAPSHOT_WITHOUT_HISTORY // Verwerfen des historischen Schnappschusses für bessere Leistung
#include <fxsaber\Virtual\Virtual.mqh>

VIRTUAL::Snapshot(); // 1: один (_Symbol) символ, все мэджики.
VIRTUAL::Snapshot(VIRTUAL_SNAPSHOT_REFRESHTIME, MyMagic); // 2: один (_Symbol), один мэджик.
VIRTUAL::Snapshot(VIRTUAL_SNAPSHOT_REFRESHTIME, -1, false, ""); // 3: все символы и мэджики.


  1. Ich benutze sie. Ich kann mehrere Sub-OTCs (jeder mit seiner eigenen Majic) in einem monovaluen EA haben. Und selbst wenn es mehrere Expert Advisors auf einem Symbol gibt, halte ich diese Option für sinnvoll. D.h. einmal Snapshot, und dann arbeiten alle Sub-OTCs mit dem Ergebnis.
  2. Wenn ein Monocurrency Expert Advisor nur mit einer Majic arbeitet, ist das die schnellste Option.
  3. Multicurrency Expert Advisor, bei dem Sie eine Majic oder alle Majics einstellen können.


Sie können VIRTUAL::Snapshot() tausendmal hintereinander aufrufen, aber es wird nicht öfter mit der externen Handels-API interagieren, als in VIRTUAL_SNAPSHOT_REFRESHTIME eingestellt (im Beispiel ist es eine Millisekunde - das reicht mir). Es muss also nichts auswendig gelernt werden, der Code sieht ungefähr so aus.

VIRTUAL::Snapshot();

for (uint i = OrdersTotal(); (bool)i--;)
{
  VIRTUAL::Snapshot();
  
  do_something();
}


Hier ist mein Synchronisationscode (aufgerufen für jede subTS) mit virtuellen Umgebungen.

  // Synchronisiert VirtualPointerTo-environment auf der Grundlage der aktuellen (ausgewählten) und VirtualPointerOut (zu schließenden Positionen).
  static bool SyncChannel( const string &Symb, const MAGIC_TYPE Magic, const double Lots,
                           const VIRTUAL_POINTER &VirtualPointerTo, const VIRTUAL_POINTER &VirtualPointerOut, const int FlagChange = false )
  {      
    // Wird für den IsNull-Mechanismus benötigt.
    if (!VirtualPointerTo.GetHandle() || !VIRTUAL::GetHandle())
      _B2(VIRTUAL::Snapshot());    
    
    const bool IsNull = !OrdersTotal() && !_VP(VirtualPointerTo, OrdersTotal());
    bool Res = IsNull || !FlagChange || _B(SYNCCHANNEL::IsNotChange(true), 500);
  
    if (!IsNull)
    {
      Res &= SYNCCHANNEL::IsCloseBy(/*Symb*/.) && MACRO_ISCHANGE(SYNCCHANNEL::SyncCloseBy(Symb, Magic, VirtualPointerTo/*, (inMinLotCorrection <= 0)*/));
      
      Res &= MACRO_ISCHANGE(SYNCCHANNEL::SyncExistOrders(Symb, Magic, VirtualPointerTo, VirtualPointerOut));

      if (Lots && (inMinLotCorrection > Lots))
        ::Alert("inMinLotCorrection(" + (string)inMinLotCorrection + ") > Lots(" + (string)Lots + ")");
      
      Res &= MACRO_ISCHANGE(SYNCCHANNEL::SetNewLimit(Symb, Magic, Lots, OP_BUYLIMIT, VirtualPointerTo, inMinLotCorrection));
      Res &= MACRO_ISCHANGE(SYNCCHANNEL::SetNewLimit(Symb, Magic, Lots, OP_SELLLIMIT, VirtualPointerTo, inMinLotCorrection));
    }    

    return(Res);    
  }

Anhand des hervorgehobenen Teils können Sie die Erstellung des Snapshots sehen. Er sollte nach Bremsfunktionen aufgerufen werden. Zum Beispiel, OrderSend. Wenn Sie es ein zusätzliches Mal aufrufen, ist es keine große Sache, wie im obigen Code gezeigt.

Der Quellcode ist jedoch aus einem anderen Grund angegeben. Ich habe alle potenziell langsamen Funktionen in ein Makro gesteckt, das die Synchronisierung komplett stoppt, wenn während der Synchronisierung ein neuer Tick (SymbolInfoTick oder CopyTicks) eintrifft, denn neue Ticks müssen zuerst durch alle Virtuals geworfen werden und werden erst dann mit dem Real synchronisiert. Alles ist genau so, wie es bei Handelskopierern und externen Krypto-Börsen funktionieren sollte.

 
Caught OrderBug22 Was kann das Problem sein? RP 0 19:00:01.733 Pip Funnels 1.0 (AUDJPY,H2) Line = 1537 NF 0 19:00:01.733 Pip Funnels 1.0 (AUDJPY,H2) Before MT4ORDERS::HistoryDealSelect(Result): DP 0 19:00:01.733 Pip Funnels 1.0 (AUDJPY,H2) MT4ORDERS::OrderSendBug = 22 CL 0 19:00:01.733 Pip Funnels 1.0 (AUDJPY,H2) Result.deal = 0
 
Sviatoslav Tyshchyk :HistoryDealSelect(Result): DP 0 19:00:01.733 Pip Funnels 1.0 (AUDJPY,H2) MT4ORDERS::OrderSendBug = 22 CL 0 19:00:01.733 Pip Funnels 1.0 (AUDJPY,H2) Result.deal = 0

Kein Problem.

 
Diese Technik ermöglicht es, schwebende Aufträge aus der Handelshistorie zu entfernen.
int HistoryOrdersTotalTmp( void ) { return(-1); }

#define HistoryOrdersTotal HistoryOrdersTotalTmp
  #include <MT4Orders.mqh> // https://www.mql5.com/de/code/16006
#undef HistoryOrdersTotal
 
Line = 1773
Before ::HistoryOrderSelect(Result.order):
MT4ORDERS::OrderSendBug = 96
Result.deal = 0
Line = 1796
Before MT4ORDERS::HistoryDealSelect(Result):
MT4ORDERS::OrderSendBug = 96
Result.deal = 0
Alert: OrderSend(1505369998) - BUG!
Alert: Please send the logs to the coauthor - https://www.mql5.com/en/users/fxsaber
Alert: C:\Program Files\MetaTrader 5 5\MQL5\Logs\20240402.log

irgendein Fehler

 
leonerd #:

irgendein Fehler

Das ist normal.