Diskussion zum Artikel "Bibliothek für ein leichtes und schnelles Entwickeln vom Programmen für den MetaTrader (Teil XXV): Behandlung der Fehlermeldungen von Server"
Exchange Symbole, Broker Otkritie, Version 5.00 build 2190.
Sorry, es gab eine Fortsetzung der Diskussion in Teil 23, aber ich wurde aufgehalten und habe sie verpasst. Jedenfalls habe ich die Version 25 heruntergeladen und das Problem bleibt bestehen. In der Diskussion des 23. Teils hast du geschrieben, dass es notwendig ist, zusätzliche Zeilen in onInit'e nach bestimmten Zeilen einzufügen, aber diese von dir grün hervorgehobenen Zeilen habe ich weder in onInit'e in der 23. noch in der 25:
//--- Setzen von globalen EA-Variablen
prefix=MQLInfoString(MQL_PROGRAM_NAME)+"_";
for(int i=0;i<TOTAL_BUTT;i++)
{
butt_data[i].name=prefix+EnumToString((ENUM_BUTTONS)i);
butt_data[i].text=EnumToButtText((ENUM_BUTTONS)i);
}
lot=NormaliseLot(Symbol(),fmax(InpLots,MinimumLots(Symbol())*2.0));
magic_number=InpMagic;
stoploss=InpStopLoss;
takeprofit=InpTakeProfit;
distance_pending=InpDistance;
abstand_stoplimit=InpDistanceSL;
Schlupf=InpSlippage;
trailing_stop=InpTrailingStop*Point();
trailing_step=InpTrailingStep*Point();
trailing_start=InpTrailingStart;
stoploss_to_modify=InpStopLossModify;
takeprofit_to_modify=InpTakeProfitModify;
//--- Initialisierung der DoEasy-Bibliothek
OnInitDoEasy();
//--- Überprüfen und Löschen von nicht freigegebenen grafischen Objekten des Expert Advisors
if(IsPresentObects(prefix))
ObjectsDeleteAll(0,prefix);
//--- Erstellen der Schaltflächenleiste
if(!CreateButtons(InpButtShiftX,InpButtShiftY))
return INIT_FAILED;
//--- Setzen des Zustands der hinteren Aktivierungsschaltfläche
ButtonState(butt_data[TOTAL_BUTT-1].name,trailing_on);
//tr.SetCorrectTypeExpiration();
engine.TradingSetCorrectTypeExpiration();
engine.TradingSetCorrectTypeFilling();
//--- Prüfen der Wiedergabe von Standardgeräuschen durch Makrosubstitution und benutzerdefinierten Geräuschen durch Beschreibung
engine.PlaySoundByDescription(SND_OK);
Sleep(600);
engine.PlaySoundByDescription(TextByLanguage("Das Geräusch einer fallenden Münze 2", "Das Geräusch einer fallenden Münze 2"));
//---
return(INIT_SUCCEEDED);
Exchange Symbole, Broker Otkritie, Version 5.00 build 2190.
Sorry, es gab eine Fortsetzung der Diskussion in Teil 23, aber ich wurde aufgehalten und habe sie verpasst. Jedenfalls habe ich die Version 25 heruntergeladen und das Problem bleibt bestehen. In der Diskussion des 23. Teils haben Sie geschrieben, dass es notwendig ist, zusätzliche Zeilen in onInit'e nach bestimmten Zeilen einzufügen, aber diese von Ihnen grün hervorgehobenen Zeilen habe ich in onInit'e überhaupt nicht, weder in der 23. noch in der 25:
Verwenden Sie den Test-EA aus Artikel 25 - "TestDoEasyPart25.mq5" ?
Jetzt habe ich onInit aus Version 23 mit den von mir hinzugefügten Funktionen eingefügt, aber ich habe Version 25 verwendet, die auch nicht die von Ihnen grün hervorgehobenen Zeilen in Version 23 hat, und Version 25 funktioniert nicht so gut wie 23.
Ich verstehe nicht, von welchen grün hervorgehobenen Zeilen Sie sprechen.
Und bitte verwenden Sie keinen Test-EA aus einem anderen Artikel - jeder Artikel enthält seinen eigenen EA zum Testen - Sie sollten ihn verwenden und alle Fehler, die Sie finden, in Bezug auf den richtigen Test-EA melden, nicht aus einem anderen Artikel.
Ok, sorry, in Bezug auf den letzten Artikel:
Orders sind geöffnet, aber alle Pending Orders nicht, das Log sagt 2019.11.21 12:59:20.689 2019.11.18 10:00:02 failed sell stop limit 2.00 Si-12.19 bei 63972 (64022) sl: 64072 tp: 63972 [Ungültiger Verfall] und 2019.11.21 12:59:20.689 2019.11.18 10:00:02 Handelsversuch #3. Fehler : Ungültiges Ablaufdatum der Order in der Anfrage
Okay, Entschuldigung, in Bezug auf den letzten Artikel:
Orders werden geöffnet, aber alle Pending Orders nicht, das Log sagt 2019.11.21 12:59:20.689 2019.11.18 10:00:02 failed sell stop limit 2.00 Si-12.19 bei 63972 (64022) sl: 64072 tp: 63972 [Ungültiger Verfall] und 2019.11.21 12:59:20.689 2019.11.18 10:00:02 Handelsversuch #3. Fehler : Ungültiges Ablaufdatum der Order in der Anfrage
Okay, danke, ich werde es mir ansehen.
Können Sie hier einen Screenshot mit der Angabe des Symbols anhängen, bei dem Sie den Fehler erhalten?
Bildschirm der Si-12.19-Spezifikation in der Datei.
In dieser Version der Bibliothek, wie auch in der nächsten, habe ich es versäumt, die Auftragsausfüllungs- und Verfallstypen zu überprüfen. Dies wird im nächsten (27) Artikel korrigiert werden.
Fürs Erste kann ich vorschlagen, dass Sie beim Senden einer Handelsanfrage den Verfallstyp explizit angeben sollten. Um zum Beispiel eine Sell Limit Pending Order zu platzieren, müssen Sie diese im Test Expert Advisor hinzufügen:
//--- Wenn die Taste BUTT_SELL_LIMIT gedrückt wird: SellLimit setzen else if(button==EnumToString(BUTT_SELL_LIMIT)) { //--- SellLimit-Auftrag einstellen engine.PlaceSellLimit(lot,Symbol(),distance_pending,stoploss,takeprofit,magic,TextByLanguage("Schwebendes Verkaufslimit","Pending order SellLimit"),0,ORDER_TIME_DAY); }
Und tun Sie dasselbe in allen Zeilen, die den Aufruf von Methoden zum Setzen von Pending Orders enthalten.
Artem, vielen Dank für die Arbeit, die Sie geleistet haben, sehr durchdacht.
Um ehrlich zu sein, habe ich den Sinn von zusammengesetzten magischen Zahlen nicht ganz verstanden....
Nehmen wir an, ich möchte die Trades in einem EA in mehrere Gruppen mit unterschiedlichen magischen Zahlen aufteilen.
Beim klassischen Ansatz gehe ich anschließend die Aufträge durch, vergleiche die magischen Zahlen und verteile das Ergebnis auf die Gruppen.
In der Bibliothek, so verstehe ich, ändert sich in dieser Situation nicht viel - nur die Zuordnung dieser Zahlen kann irgendwie systematisiert werden? Oder gibt es noch etwas anderes, das davon betroffen ist?
Und dann gibt es noch eine bestimmte Funktionsebene, die ich in Ihrer Bibliothek kategorisch vermisse: die Aggregation.
Sehr oft müssen wir die Frage beantworten, wie hoch der aggregierte Gewinn bei einer Reihe von Parametern (Magie, Symbol, Auftragsart) ist. Und die Gesamtmenge, zum Beispiel. Und die Gewinnschwelle. Und die Anzahl der Trades.
Diese Gesamtwerte werden überall und immer wieder benötigt; sie bei jeder neuen Methode stichprobenartig zu berechnen, ist ein offensichtlicher Overkill.
Es wäre großartig, eine Reihe von Aggregationen zu haben, die jeweils mit einer Reihe von Stichprobenkriterien (Symbol, Typ, Magie, Gruppennummer) konfiguriert werden und auf die in CEngine zugegriffen werden kann - und die einmal in Refresh aktualisiert werden.
Wenn Sie keine Pläne für diese Art von Verfeinerung haben, könnte ich das fertigstellen und teilen..... aber nur, wenn wir einen signifikant unterschiedlichen Code-Stil haben, würde dieses Stück fremd aussehen.
Artem, vielen Dank für die Arbeit, die Sie geleistet haben, sehr aufmerksam.
Ich habe den Sinn der zusammengesetzten Magie nicht ganz verstanden, um ehrlich zu sein....
Nehmen wir an, ich möchte die Trades in einem Expert Advisor in mehrere Gruppen mit unterschiedlichen magischen Zahlen aufteilen.
Beim klassischen Ansatz gehe ich anschließend die Aufträge durch, vergleiche die magischen Zahlen und verteile das Ergebnis auf die Gruppen.
In der Bibliothek, so verstehe ich, ändert sich in dieser Situation nicht viel - nur die Zuordnung dieser Zahlen kann irgendwie systematisiert werden? Oder gibt es noch etwas anderes, das davon beeinflusst wird?
Und es gibt auch eine bestimmte Funktionsebene, die ich in Ihrer Bibliothek kategorisch vermisse: die Aggregation.
Sehr oft müssen wir die Frage beantworten, wie hoch der aggregierte Gewinn bei einer Reihe von Parametern (Magie, Symbol, Auftragsart) ist. Und die Gesamtmenge, zum Beispiel. Und die Gewinnschwelle. Und die Anzahl der Trades.
Diese aggregierten Werte werden überall und immer wieder benötigt; sie bei jeder neuen Methode stichprobenartig zu berechnen, ist ein offensichtlicher Overkill.
Es wäre großartig, eine Reihe von Aggregationen zu haben, die jeweils mit einer Reihe von Stichprobenkriterien (Symbol, Typ, Magie, Gruppennummer) konfiguriert werden und auf die in der CEngine zugegriffen werden kann - und die einmal in Refresh aktualisiert werden.
Wenn Sie keine Pläne für diese Art von Verfeinerung haben, könnte ich das fertigstellen und teilen..... aber nur, wenn wir einen deutlich unterschiedlichen Codestil haben, würde dieses Stück fremd aussehen.
Zu den Informationen, die im Wert der Magischen Zahl aufgezeichnet werden:
Sie können für jede Gruppe eine andere Magie verwenden, um verschiedene Gruppen zu erstellen. Wenn die Magie des Beraters beispielsweise 123 ist, wird die Magie der ersten Gruppe 124 sein, die Magie der zweiten Gruppe 125, die der dritten Gruppe 126 und so weiter.
Die Bibliothek bietet eine andere Möglichkeit, verschiedene Gruppen zu erstellen - die Nummer jeder Untergruppe wird direkt im Wert der Magischen Zahl gespeichert. Dann ist die magische Zahl des EA auch ein Gruppenbezeichner, aber sie wird in einer unabhängigen Gruppe namens MagicID gespeichert - dem Bezeichner der magischen Zahl des EA. Und es gibt noch zwei weitere Gruppen. Jede von ihnen hat 15 Untergruppen. Und jede dieser Untergruppen kann einen eigenen Bezeichner haben.
Das gibtmehr Flexibilität bei der Arbeit mit Gruppen.
Ein Beispiel: Wir möchten ein Raster von schwebenden Aufträgen hinter den Preis verschieben - wir fügen sie der Gruppe 1 in Untergruppe 1 hinzu. Gruppe 1 bewegt sich hinter dem Preis. Untergruppe 1 bewegt sich entlang des MA. Nun wollen wir einige dieser Aufträge, die sich hinter dem Preis (Gruppe 1) bewegen, um den Parabolic SAR verschieben. Wir geben ihnen die Untergruppe 2. Dann bewegt sich Gruppe 1 nach dem Kurs, aber Untergruppe 1 bewegt sich entlang des MA, und Untergruppe 2 bewegt sich entlang des Parabolic SAR.
Die Orders werden ausgelöst und verwandeln sich in Positionen - Sie können Ihre eigenen Gruppen für die Modifikation des Stop Loss und Ihre eigenen Untergruppen in dieser Gruppe für die Modifikation durch verschiedene Werte festlegen. Modifikationsalgorithmen werden in Untergruppen geschrieben.
Im Allgemeinen - ein Höhenflug der Fantasie. Sie können auch eine einfache Magie verwenden, aber dann müssen Sie die Logik der Verfolgung verschiedener Gruppen selbst erfinden.
Zur zweiten Frage:
Es gibt eine Klasse CSelect. Sie ist im Programm verfügbar und bietet Methoden zur Auswahl und Suche aus allen vorhandenen Sammlungen: Account, Event, Order, Symbol.
Sie können die Objekte jeder Sammlung in einer Liste nach allen Kriterien auswählen. In der erstellten Liste können Sie durch Verfeinerung der Kriterien neu selektieren, Sie können die Maximal- und Minimalwerte für ein Selektionskriterium finden.
Es wird aber noch weitere Benutzerfunktionen geben (viel später), um schnell und bequem auf alle Eigenschaften aller Sammlungen zuzugreifen und in ihnen zu suchen.
Aber erst einmal - nur über CSelect, und wenn Sie es brauchen. Die Klasse ist statisch, daher erfolgt der Zugriff auf ihre Methoden über ":::" Zum Beispiel, CSelect::ByOrderProperty().
Ja, übrigens, es gibt ein Beispiel für die Verwendung im Programm direkt in der Test-EA - zum Beispiel in den nachgeschalteten Funktionen:
//+------------------------------------------------------------------+ //| Durchsuchen Sie die am weitesten entfernten ausstehenden Aufträge. //+------------------------------------------------------------------+ void TrailingOrders(void) { MqlTick tick; if(!SymbolInfoTick(Symbol(),tick)) return; double stop_level=StopLevel(Symbol(),2)*Point(); //--- Abrufen der Liste aller eingestellten Aufträge CArrayObj* list=engine.GetListMarketPendings(); //--- Nur Aufträge mit dem aktuellen Symbol aus der Liste auswählen list=CSelect::ByOrderProperty(list,ORDER_PROP_SYMBOL,Symbol(),EQUAL); //--- Nur Aufträge in Kaufrichtung aus der Liste auswählen CArrayObj* list_buy=CSelect::ByOrderProperty(list,ORDER_PROP_DIRECTION,ORDER_TYPE_BUY,EQUAL); //--- Sortieren Sie die Liste nach dem Abstand vom Preis in Pips (nach Gewinn in Pips) list_buy.Sort(SORT_BY_ORDER_PROFIT_PT); //--- Ermittelt den Index des Auftrags in Kaufrichtung mit dem größten Abstand int index_buy=CSelect::FindOrderMax(list_buy,ORDER_PROP_PROFIT_PT); if(index_buy>WRONG_VALUE) { COrder* buy=list_buy.At(index_buy); if(buy!=NULL) { //--- Wenn der Auftrag unterhalb des Preises (BuyLimit) liegt und hinter den Preis "gehoben" werden muss if(buy.TypeOrder()==ORDER_TYPE_BUY_LIMIT) { //--- Berechnen des neuen Preises und der Stoppniveaus für den Auftrag anhand des neuen Preises double price=NormalizeDouble(tick.ask-trailing_stop,Digits()); double sl=(buy.StopLoss()>0 ? NormalizeDouble(price-(buy.PriceOpen()-buy.StopLoss()),Digits()) : 0); double tp=(buy.TakeProfit()>0 ? NormalizeDouble(price+(buy.TakeProfit()-buy.PriceOpen()),Digits()) : 0); //--- Wenn der berechnete Preis niedriger ist als der StopLevel-Abstand, wird vom Ask-Order-Setzungspreis verschoben (der StopLevel-Abstand wird eingehalten) if(price<tick.ask-stop_level) { //--- Wenn der berechnete Preis höher ist als der vom Auftragssetzungspreis verschobene Schleppnetzschritt - ändern Sie den Auftragssetzungspreis if(price>buy.PriceOpen()+trailing_step) { engine.ModifyOrder((ulong)buy.Ticket(),price,sl,tp,-1); } } } //--- Wenn die Order oberhalb des Preises (BuyStop und BuyStopLimit) gesetzt ist und hinter den Preis "gesenkt" werden soll else { //--- Berechnen des neuen Preises und der Stoppniveaus für den Auftrag anhand des neuen Preises double price=NormalizeDouble(tick.ask+trailing_stop,Digits()); double sl=(buy.StopLoss()>0 ? NormalizeDouble(price-(buy.PriceOpen()-buy.StopLoss()),Digits()) : 0); double tp=(buy.TakeProfit()>0 ? NormalizeDouble(price+(buy.TakeProfit()-buy.PriceOpen()),Digits()) : 0); //--- Wenn der berechnete Preis höher ist als der StopLevel-Abstand, wird vom Ask-Order-Setzungspreis verschoben (der StopLevel-Abstand wird eingehalten) if(price>tick.ask+stop_level) { //--- Wenn der berechnete Preis niedriger ist als der vom Auftragssetzungspreis verschobene Schleppnetzschritt - ändern Sie den Auftragssetzungspreis if(price<buy.PriceOpen()-trailing_step) { engine.ModifyOrder((ulong)buy.Ticket(),price,sl,tp,-1); } } } } } //--- Nur Aufträge in Verkaufsrichtung aus der Liste auswählen CArrayObj* list_sell=CSelect::ByOrderProperty(list,ORDER_PROP_DIRECTION,ORDER_TYPE_SELL,EQUAL); //--- Sortieren Sie die Liste nach dem Abstand vom Preis in Pips (nach Gewinn in Pips) list_sell.Sort(SORT_BY_ORDER_PROFIT_PT); //--- Ermittelt den Index des Auftrags in Richtung Sell mit dem größten Abstand int index_sell=CSelect::FindOrderMax(list_sell,ORDER_PROP_PROFIT_PT); if(index_sell>WRONG_VALUE) { COrder* sell=list_sell.At(index_sell); if(sell!=NULL) { //--- Wenn die Order oberhalb des Preises (SellLimit) gesetzt ist und hinter den Preis "gesenkt" werden soll if(sell.TypeOrder()==ORDER_TYPE_SELL_LIMIT) { //--- Berechnen des neuen Preises und der Stoppniveaus für den Auftrag anhand des neuen Preises double price=NormalizeDouble(tick.bid+trailing_stop,Digits()); double sl=(sell.StopLoss()>0 ? NormalizeDouble(price+(sell.StopLoss()-sell.PriceOpen()),Digits()) : 0); double tp=(sell.TakeProfit()>0 ? NormalizeDouble(price-(sell.PriceOpen()-sell.TakeProfit()),Digits()) : 0); //--- Wenn der berechnete Preis höher ist als der StopLevel-Abstand, wird vom Bid-Order-Setting-Preis verschoben (der StopLevel-Abstand wird beachtet) if(price>tick.bid+stop_level) { //--- Wenn der berechnete Preis niedriger ist als der vom Auftragssetzungspreis verschobene Schleppnetzschritt - ändern Sie den Auftragssetzungspreis if(price<sell.PriceOpen()-trailing_step) { engine.ModifyOrder((ulong)sell.Ticket(),price,sl,tp,-1); } } } //--- Wenn die Order unterhalb des Preises gesetzt ist (SellStop und SellStopLimit) und sie hinter den Preis "gehoben" werden soll else { //--- Berechnen des neuen Preises und der Stoppniveaus für den Auftrag anhand des neuen Preises double price=NormalizeDouble(tick.bid-trailing_stop,Digits()); double sl=(sell.StopLoss()>0 ? NormalizeDouble(price+(sell.StopLoss()-sell.PriceOpen()),Digits()) : 0); double tp=(sell.TakeProfit()>0 ? NormalizeDouble(price-(sell.PriceOpen()-sell.TakeProfit()),Digits()) : 0); //--- Wenn der berechnete Preis niedriger ist als der StopLevel-Abstand, wird vom Bid-Order-Setzungspreis verschoben (der StopLevel-Abstand wird eingehalten) if(price<tick.bid-stop_level) { //--- Wenn der berechnete Preis höher ist als der vom Auftragssetzungspreis verschobene Schleppnetzschritt - ändern Sie den Auftragssetzungspreis if(price>sell.PriceOpen()+trailing_step) { engine.ModifyOrder((ulong)sell.Ticket(),price,sl,tp,-1); } } } } } } //+------------------------------------------------------------------+

- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.
Neuer Artikel Bibliothek für ein leichtes und schnelles Entwickeln vom Programmen für den MetaTrader (Teil XXV): Behandlung der Fehlermeldungen von Server :
Nachdem wir einen Handelsauftrag an den Server gesendet haben, müssen wir die Fehlercodes oder das Fehlen von Fehlern überprüfen. In diesem Artikel werden wir die Behandlung von Fehlern, die vom Handelsserver zurückgegeben werden, besprechen und die Erstellung von ausstehenden Handelsanfragen vorbereiten.
In den letzten Versionen von MetaTrader 5 (ab build 2201) verfügt der Tester über die Möglichkeit, Parameter eines Symbols einzustellen, an dem der Test durchgeführt wird. So ist es möglich, Handelsbeschränkungen für ein Symbol festzulegen und das Verhalten der Bibliothek zu testen, wenn die Symbolbeschränkungen erkannt werden.
Um das Fenster für die Symboleinstellungen aufzurufen, klicken Sie auf die Schaltfläche rechts neben der Auswahl des getesteten Zeitrahmens:
Erlauben Sie die Eröffnung von Kaufpositionen nur für ein Symbol und setzen Sie die Volumenbegrenzung von gleichzeitig geöffneten Positionen und platzierten Pending-Orders in einer Richtung auf 0,5.
So können wir nur Kaufpositionen nutzen und haben das maximale Gesamtvolumen der Kaufpositionen und Aufträge von nicht mehr als 0,5 Lot im Markt. Mit anderen Worten, wenn wir eine Position mit dem Lot 0,1 eröffnen, können wir nur fünf Positionen eröffnen oder eine einzige Pending-Order platzieren und vier Positionen eröffnen:
Für mehr Authentizität könnten wir die automatische Schließung von Positionen deaktivieren, wenn ein bestimmter Gewinn überschritten wird. Wir sehen jedoch, dass wir keine Verkaufsposition eröffnen konnten und die Warnung erhielten, dass nur Kaufpositionen auf ein Symbol erlaubt sind. Weiterhin erhalten wir beim Versuch, eine Anzahl von Positionen zu öffnen, deren Gesamtvolumen 0,5 Lots übersteigt, die Meldung, dass wir eine Position nicht öffnen können, weil das maximale Gesamtvolumen von Positionen und Aufträgen in einer Richtung überschritten wird.
Autor: Artyom Trishkin