Wenn Sie ein Makro aufrufen, dürfen Sie keinen Parameter angeben (auslassen). Manchmal möchten Sie einem Makro ausdrücklich erlauben, mit einem nicht angegebenen Parameter zu arbeiten.
Für solche Fälle gibt es hier einige Hilfsmakros.
1. Manchmal möchten Sie innerhalb Ihres Makros feststellen, ob ein Parameter gesetzt wurde oder nicht. IS_PARAMETER_SET(p) definiert einen Ausdruck, der true zurückgibt, wenn p gesetzt ist (auch wenn die String-Variable ==NULL ist).
Achtung: der Ausdruck wird nach der Vorverarbeitung zur Kompilierzeit ausgewertet!!!, d.h. er kann nicht verwendet werden, um etwas wie #ifdef IS_PARAMETER_SET(p) #else zu implementieren (dies gilt auch für andere Makros unten)
2. Wenn Sie einen Parameterwert explizit in eine Zeichenkette umwandeln müssen, um einen Kompilierfehler mit einem nicht spezifizierten Parameter zu vermeiden, können Sie __EVAL_STR(p) verwenden. Wenn p nicht oder explizit mit NULL-Literal definiert ist, wird "" zurückgegeben. Gilt nicht für Arrays, Strukturen und Klassen.
Die explizite Umwandlung eines Parameters in eine Zahl ist __EVAL_NON_STR(p). Wenn p nicht gesetzt ist, wird 0 zurückgegeben. Funktioniert nicht, wenn p ein String ist!
Code und Anwendungsbeispiele:
//Expression returns true if macro's parameter is specified.#define IS_PARAMETER_SET(p) ("" != #p || __hlp_macro_func(p))
bool __hlp_macro_func(conststring p = NULL) {return"" == p;}
template<typename T> bool __hlp_macro_func(T p) {returntrue;}
template<typename T> bool __hlp_macro_func(T& p) {returntrue;}
template<typename T> bool __hlp_macro_func(T& p[]) {returntrue;}
//Expression returns parameter p; if parameter is not specified returns NULL; if p is string returns p//Error for arrays and objects#define __EVAL(p) (""==#p?NULL:p+NULL)
//Explicit conversion to string. If parameter is not specified or is constant NULL returns ""//Error for arrays and objects#define __EVAL_STR(p) (""==#p || "NULL"==#p? "" :(string)(p+NULL))
//Explicit conversion to number. If parameter is not specified returns 0. Works incorrect if p is string!//Error for arrays and objects#define __EVAL_NON_STR(p) ("" == #p? 0 : p+0)
struct S1
{ int a; };
class C1
{ int a; };
voidOnStart()
{
//---Print(IS_PARAMETER_SET()); //falsePrint(IS_PARAMETER_SET("")); //truePrint(IS_PARAMETER_SET("test")); //truePrint(IS_PARAMETER_SET(NULL)); //truePrint(IS_PARAMETER_SET(0)); //truePrint(IS_PARAMETER_SET(1)); //truestring str;
Print(IS_PARAMETER_SET(str)); //trueint arr[1];
Print(IS_PARAMETER_SET(arr)); //true
S1 _struct;
Print(IS_PARAMETER_SET(_struct)); //true
C1 _class;
Print(IS_PARAMETER_SET(_class)); //true#define MACRO1_(a,b) (IS_PARAMETER_SET(b)?a:-a)
Print(MACRO1_(1, 0)); //1Print(MACRO1_(1,)); //-1#define MACRO2_(a,b,c) Print(a," = ",b + c)
#define MACRO3_(a,b,c) Print(__EVAL_STR(a)," = ",__EVAL_NON_STR(b) + __EVAL_NON_STR(c))
//MACRO2_(, 2,); // ',' - syntax error, parameter missed
MACRO3_(, 2,); // = 2
MACRO3_("a", 2, 3); // a = 5
}
Der folgende Code auf demRannForex-Server Demokonto kann diese Situation sofort reproduzieren, indem dieser Advisor ausgeführt wird.
Ergebnis.
Übrigens, das Skript zeigt (nicht immer zum ersten Mal) einen Fehler in der synchronen OrderSend-Ausführung.
Nachdem OrderSend für einige zehn/hundert Millisekunden ausgeführt wurde, ist der Auftragspreis der alte und nicht derjenige, der durch OrderSend erfolgreich erteilt wurde.
Um auf das Thema der identischen Tickets zurückzukommen, können wir einige Schlussfolgerungen ziehen.
Wenn eine Teil-Limit-Order hängt, wird auf der Registerkarte "Aufträge und Abschlüsse" der generierte Abschluss nicht angezeigt.
Bei einem Hedge kann ein einziger Auftrag mehrere IN-Geschäfte mit unterschiedlichen Preisen hervorbringen. Das Ergebnis ist ein Bruchteil des Eröffnungskurses der Position (im Verhältnis zu den Pips).
Sie können die erzeugte Position schließen, ohne den Partial Put zu entfernen. Wenn aber danach die Pending Order ausgelöst wird, wird ein Handel mit dem Ticket eröffnet, das dem Ticket der Position entspricht, die zuvor geschlossen wurde. Das heißt, es kann eine Situation eintreten, in der Sie eine Position mit einem bestimmten Ticket schließen. Und dann taucht eine Position mit demselben Ticker wieder auf.
Die Teilausführung kann je nach Software des Brokers unterschiedlich umgesetzt werden. Die obige Darstellung ist eine Standardimplementierung von MT5.
Wenn es jemandem gelungen ist, das Problem auf einem anderen Handelsserver zu reproduzieren, teilen Sie uns bitte den Namen mit.
1. Bitte klären Sie Punkt 3: "Sie können die von Ihnen gebildete Position schließen, ohne die Teilausführung zu entfernen. Wenn der Auftrag jedoch danach ausgelöst wird, wird ein Handel mit einem Ticket eröffnet, das dem Ticket der zuvor geschlossenen Position entspricht. Das heißt, es kann eine Situation eintreten, in der Sie eine Position mit einem bestimmten Ticket schließen. Und dann erscheint wieder eine Position mit demselben Ticket." War in diesem Fall POSITION_IDENTIFIER gleich POSITION_TICKET oder nicht?
2. Vorhin im Thread "POSITION_TICKET != POSITION_IDENTIFIER" haben Sie eine andere MT5-Logik demonstriert.
Wenn wir davon ausgehen, dass dies ein normales Verhalten von MT5 ist und keine Besonderheit des Broker-Hacks, dann
ORDER_STATE_PARTIAL ist in historischen Aufträgen nicht vorhanden.
Aufträge, die ausgeführt werden, haben immer den Status ORDER_STATE_FILLED.
Wenn ein Auftrag teilweise ausgeführt wird, wird ein entsprechender neuer Marktauftrag vom Handelsserver angelegt (ORDER_REASON_CLIENT - auch wenn der ursprüngliche Auftrag automatisch erteilt wurde (EXPERT)).
Der alte Live-Auftrag (das Ticket wird nicht geändert) bleibt mit einem reduzierten Volumen (ORDER_VOLUME_CURRENT) anhängig.
Der alte Live-Auftrag hat in diesem Fall den Status ORDER_STATE_PARTIAL. Eigentlich ist dieses Kennzeichen das Ergebnis des Vergleichs von ORDER_VOLUME_CURRENT und ORDER_VOLUME_INITIAL.
Alle offenen Positionen erhalten eine ID == OrderTicket. Dabei ist OrderTicket das vom Handelsserver generierte Ticket.
Ein Geschäft hat immer genau einen historischen Auftrag, und sein Status ist ORDER_STATE_FILLED.
Jeder ausgeführte historische Auftrag hat genau einen Abschluss.
Das ORDER_VOLUME_INITIAL eines ausgeführten Auftrags ist gleich dem Volumen, für das er ausgeführt wurde. D.h. selbst der ursprüngliche Auftrag, der storniert wurde, hat ein ORDER_VOLUME_INITITAL, das dem Volumen des von ihm ausgelösten Handels entspricht.
Der Zeitpunkt des ursprünglichen Auftrags (der teilweise ausgeführt wurde) ändert sich nicht und ist nicht gleich dem Zeitpunkt seines Abschlusses.
Die Historientabelle ist nach Auftragszeit (ORDER_TIME_SETUP), nicht aber nach Geschäftszeit sortiert. Wenn wir also HistorySelect from DEAL_TIME ausführen, können wir die entsprechende Bestellung nicht in die History-Tabelle übernehmen.
HistorySelectByPosition liefert immer die erforderliche Menge an Geschäften/Aufträgen.
Sie können die Slippage für jeden Handel berechnen.
Gibt es Ihrer Erfahrung nach ein allgemeines Muster, in welchen Fällen/Arbeitsweisen der MT5 verwendet wird?
3. Hat es jemals Situationen gegeben, in denen "POSITION_TICKET != POSITION_IDENTIFIER" war?
mktr8591: Beim Aufruf eines Makros ist es möglich, einen Parameter auszulassen, und manchmal möchte man einem Makro ausdrücklich erlauben, mit einem nicht spezifizierten Parameter zu arbeiten.
Es stellt sich heraus, dass ein nicht spezifizierter Parameter in einem Makro vom Compiler als leerer String behandelt wird?
1. Bitte klären Sie Punkt 3: "Sie können eine gebildete Position schließen, ohne die Partial Put Option zu entfernen. Wenn der Auftrag jedoch danach ausgelöst wird, wird ein Handel mit einem Ticket eröffnet, das dem Ticket der zuvor geschlossenen Position entspricht. Das heißt, es kann eine Situation eintreten, in der Sie eine Position mit einem bestimmten Ticket schließen. Und dann erscheint wieder eine Position mit demselben Ticket." War in diesem Fall POSITION_IDENTIFIER gleich POSITION_TICKET oder nicht?
2. Vorhin im Zweig "POSITION_TICKET != POSITION_IDENTIFIER" haben Sie eine andere Logik des MT5 demonstriert.
Wenn Sie kein Benutzerkonto haben, registrieren Sie sich
Erlauben Sie die Verwendung von Cookies, um sich auf der Website MQL5.com anzumelden.
Bitte aktivieren Sie die notwendige Einstellung in Ihrem Browser, da Sie sich sonst nicht einloggen können.
Sie sind angemeldet. Die Zwei-Faktor-Authentifizierung wurde deaktiviert. Richten Sie sie erneut ein und scannen Sie einen neuen QR-Code oder fahren Sie mit deaktivierter Zwei-Faktor-Authentifizierung fort.
Für solche Fälle gibt es hier einige Hilfsmakros.
1. Manchmal möchten Sie innerhalb Ihres Makros feststellen, ob ein Parameter gesetzt wurde oder nicht. IS_PARAMETER_SET(p) definiert einen Ausdruck, der true zurückgibt, wenn p gesetzt ist (auch wenn die String-Variable ==NULL ist).
Achtung: der Ausdruck wird nach der Vorverarbeitung zur Kompilierzeit ausgewertet!!!, d.h. er kann nicht verwendet werden, um etwas wie #ifdef IS_PARAMETER_SET(p) #else zu implementieren (dies gilt auch für andere Makros unten)
2. Wenn Sie einen Parameterwert explizit in eine Zeichenkette umwandeln müssen, um einen Kompilierfehler mit einem nicht spezifizierten Parameter zu vermeiden, können Sie __EVAL_STR(p) verwenden. Wenn p nicht oder explizit mit NULL-Literal definiert ist, wird "" zurückgegeben. Gilt nicht für Arrays, Strukturen und Klassen.
Die explizite Umwandlung eines Parameters in eine Zahl ist __EVAL_NON_STR(p). Wenn p nicht gesetzt ist, wird 0 zurückgegeben. Funktioniert nicht, wenn p ein String ist!
Code und Anwendungsbeispiele:
Der folgende Code auf demRannForex-Server Demokonto kann diese Situation sofort reproduzieren, indem dieser Advisor ausgeführt wird.
Ergebnis.
Übrigens, das Skript zeigt (nicht immer zum ersten Mal) einen Fehler in der synchronen OrderSend-Ausführung.
Nachdem OrderSend für einige zehn/hundert Millisekunden ausgeführt wurde, ist der Auftragspreis der alte und nicht derjenige, der durch OrderSend erfolgreich erteilt wurde.
Um auf das Thema der identischen Tickets zurückzukommen, können wir einige Schlussfolgerungen ziehen.
Wenn es jemandem gelungen ist, das Problem auf einem anderen Handelsserver zu reproduzieren, teilen Sie uns bitte den Namen mit.
Suchbegriff: Oshibka 010.
Nochmals zurück zur Frage der Teilvollstreckung.
1. Bitte klären Sie Punkt 3: "Sie können die von Ihnen gebildete Position schließen, ohne die Teilausführung zu entfernen. Wenn der Auftrag jedoch danach ausgelöst wird, wird ein Handel mit einem Ticket eröffnet, das dem Ticket der zuvor geschlossenen Position entspricht. Das heißt, es kann eine Situation eintreten, in der Sie eine Position mit einem bestimmten Ticket schließen. Und dann erscheint wieder eine Position mit demselben Ticket."
War in diesem Fall POSITION_IDENTIFIER gleich POSITION_TICKET oder nicht?
2. Vorhin im Thread "POSITION_TICKET != POSITION_IDENTIFIER" haben Sie eine andere MT5-Logik demonstriert.
https://www.mql5.com/ru/forum/227423/page2#comment_6543129Schlussfolgerungen
Wenn wir davon ausgehen, dass dies ein normales Verhalten von MT5 ist und keine Besonderheit des Broker-Hacks, dann
Gibt es Ihrer Erfahrung nach ein allgemeines Muster, in welchen Fällen/Arbeitsweisen der MT5 verwendet wird?
3. Hat es jemals Situationen gegeben, in denen "POSITION_TICKET != POSITION_IDENTIFIER" war?
Beim Aufruf eines Makros ist es möglich, einen Parameter auszulassen, und manchmal möchte man einem Makro ausdrücklich erlauben, mit einem nicht spezifizierten Parameter zu arbeiten.
Es stellt sich also heraus, dass ein nicht spezifizierter Parameter in einem Makro vom Compiler als leerer String behandelt wird?
In gewisser Weise ja, obwohl "wie ein leerer Raum" vielleicht ein besseres Wort ist. Schwierig, sich klar auszudrücken :-(.
Aber #p wird definitiv zu string ==""
In gewisser Weise ja, obwohl "wie ein leerer Raum" vielleicht ein besseres Wort ist. Schwierig, sich klar auszudrücken :-(.
Aber #p wird definitiv zu string ==""
Danke, eine interessante Nuance.
@fxsaber
Schauen Sie sich bitte diese Ausgabe an: https://www.mql5.com/ru/forum/170952/page201#comment_21964923
Noch einmal zurück zur Frage der Teilleistung.
1. Bitte klären Sie Punkt 3: "Sie können eine gebildete Position schließen, ohne die Partial Put Option zu entfernen. Wenn der Auftrag jedoch danach ausgelöst wird, wird ein Handel mit einem Ticket eröffnet, das dem Ticket der zuvor geschlossenen Position entspricht. Das heißt, es kann eine Situation eintreten, in der Sie eine Position mit einem bestimmten Ticket schließen. Und dann erscheint wieder eine Position mit demselben Ticket."
War in diesem Fall POSITION_IDENTIFIER gleich POSITION_TICKET oder nicht?
2. Vorhin im Zweig "POSITION_TICKET != POSITION_IDENTIFIER" haben Sie eine andere Logik des MT5 demonstriert.
https://www.mql5.com/ru/forum/227423/page2#comment_6543129Gibt es Ihrer Erfahrung nach ein allgemeines Muster, in welchen Fällen/Betriebsarten das MT5-Schema Anwendung findet?
3. Hat es jemals Situationen gegeben, in denen "POSITION_TICKET != POSITION_IDENTIFIER" war?
Beide Links behandeln verschiedene Implementierungen der partiellen Ausführung. Dies wird von der Software des Brokers bestimmt, nicht von MT5.
Es wurde noch nie eine Diskrepanz zwischen Ticket und ID festgestellt.
Forum zum Thema Handel, automatisierte Handelssysteme und Strategietests
Bibliotheken: Nutzung
fxsaber, 2021.05.01 14:17
GetMicrosecondCount kann einen kleineren Wert ausgeben als beim vorherigen Aufruf (ohne ULONG-Überlauf). Beispiele für solche Situationen.Jede Linie wird von verschiedenen EAs auf drei MT4-Terminals erzielt.
Und auf dem MT5 kommt so etwas vor, auf dem MT4 dagegen viel seltener.
Seien Sie vorsichtig.