Diskussion zum Artikel "Bibliothek für ein leichtes und schnelles Entwickeln vom Programmen für den MetaTrader (Teil XXI): Handelsklassen - Plattformübergreifendes Basis-Handelsobjekt"
Ich habe mehr als die Hälfte davon sehr sorgfältig gelesen. Danach begann mein Bewusstsein abzuschalten. Der Umfang des Artikels ist extrem groß.
Anatoly Kozharsky hatte immer ein allgemeines Schema der Bibliothek am Ende seiner Artikel, durch das man eine klare Vorstellung von ihrer Struktur bekommen konnte. Ein solches Schema habe ich in Ihren Artikeln nicht gesehen, und deshalb fühle ich mich wie eine "Ameise", die auf dem Körper eines "Elefanten" herumkrabbelt. Ich bin dabei, mir ein genaues Bild von der Bibliothek zu machen, aber wenn ich Ihre Artikel lese, ist es schwierig, sich ein Bild zu machen. Es gibt eine Menge "vorgekauter" Informationen in Form von Details, Code-Erklärungen, Verweisen auf andere Artikel, aber es gibt keine integrale, prägnante Beschreibung und Schema der Bibliothek.
Natürlich ist das Niveau der Implementierung sehr hoch. Alles ist sehr professionell, und das sieht man auch. Aber ich würde die Notwendigkeit von so vielen "Wrappern" in Frage stellen. Zum Beispiel: Die Methode " CTradeObj::SetOrder" hat die folgenden Wrapper:
//--- Legt ausstehende Aufträge fest (1) BuyStop, (2) BuyLimit, (3) BuyStopLimit bool PlaceBuyStop(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=ULONG_MAX, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC); bool PlaceBuyLimit(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=ULONG_MAX, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC); bool PlaceBuyStopLimit(const double volume, const string symbol, const double price_stop, const double price_limit, const double sl=0, const double tp=0, const ulong magic=ULONG_MAX, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC); //--- Legt ausstehende Aufträge fest (1) SellStop, (2) SellLimit, (3) SellStopLimit bool PlaceSellStop(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=ULONG_MAX, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC); bool PlaceSellLimit(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=ULONG_MAX, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC); bool PlaceSellStopLimit(const double volume, const string symbol, const double price_stop, const double price_limit, const double sl=0, const double tp=0, const ulong magic=ULONG_MAX, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC); //---
Sie sind alle nicht viel anders, nehmen aber viel Platz in Anspruch. Mit solch "tiefem Wrapping" werden Material und Codes wie auf "Hefe" wachsen und die Verwendung von Funktionalität wird im Verhältnis zum Wachstum der Anzahl von Entitäten, die sich exponentiell vervielfachen wird, komplizierter werden.
Nein, ich bin nicht dagegen. Ich denke, darum geht es beim Polymorphismus- wenn eine Methode viele Wrapper hervorbringt, von denen jeder seine eigene Besonderheit hat. Das Problem ist, dass die Lösungsstruktur bei diesem Ansatz zu schnell wächst und nicht mehr praktisch nutzbar ist. Wir müssen das Wachstum des Materials begrenzen, sonst wird es immer schwieriger, es zu verstehen und zu benutzen.
Ich habe mehr als die Hälfte davon sehr sorgfältig gelesen. Danach begann mein Bewusstsein abzuschalten. Der Umfang des Artikels ist extrem groß.
Anatoly Kozharsky hatte immer ein allgemeines Schema der Bibliothek am Ende seiner Artikel, durch das man eine klare Vorstellung von ihrer Struktur bekommen konnte. Ein solches Schema habe ich in Ihren Artikeln nicht gesehen, und deshalb fühle ich mich wie eine "Ameise", die auf dem Körper eines "Elefanten" herumkrabbelt. Ich bin dabei, mir ein genaues Bild von der Bibliothek zu machen, aber wenn ich Ihre Artikel lese, ist es schwierig, sich ein Bild zu machen. Es gibt eine Menge "wiedergekäuter" Informationen in Form von Details, Code-Erklärungen, Verweisen auf andere Artikel, aber es gibt keine vollständige, prägnante Beschreibung und kein Schema der Bibliothek.
Natürlich ist das Niveau der Implementierung sehr hoch. Alles ist sehr professionell, und das sieht man auch. Aber ich würde die Notwendigkeit von so vielen "Wrappern" in Frage stellen. Zum Beispiel: Die Methode " CTradeObj::SetOrder" hat die folgenden Wrapper:
Sie unterscheiden sich alle nicht wesentlich voneinander, nehmen aber eine Menge Platz in Anspruch. Mit solch "tiefem Wrapping" werden Material und Codes wie auf "Hefe" wachsen und die Nutzung der Funktionalität wird im Verhältnis zum Wachstum der Anzahl der Entitäten, die sich exponentiell vervielfachen wird, komplizierter werden.
Nein, ich bin nicht dagegen. Ich denke, darum geht es beim Polymorphismus- wenn eine Methode viele Wrapper hervorbringt, von denen jeder seine eigene Besonderheit hat. Das Problem ist, dass die Lösungsstruktur bei diesem Ansatz zu schnell wächst und nicht mehr praktisch nutzbar ist. Wir müssen das Wachstum des Materials begrenzen, sonst wird es immer schwieriger, es zu verstehen und zu benutzen.
Vielen Dank für Ihre Einschätzung, Peter. Sie sollten nur das verwenden, was von CEngine zur Verfügung gestellt wird, was wiederum vom Programm zur Verfügung gestellt wird.
Der ganze Rest ist die Implementierung von Methoden, denen alle notwendigen Parameter übergeben werden. Diese Methoden sind für den praktischen Einsatz in Ihren eigenen Programmen nicht notwendig - sie sind für die Bibliothek selbst notwendig. Für den Endbenutzer gibt es daher immer weniger Methoden, was sich auch in den Testberatern zeigt.
Natürlich wird alles beschrieben. Und die Struktur, und alle Methoden, die dem Benutzer zur Verfügung stehen. Und es werden Benutzerfunktionen erstellt, die die OOP-Implementierung verbergen und keinen expliziten Zugriff auf Bibliotheksobjekte erfordern.
Aber alles liegt noch vor uns - wir müssen die Hauptfunktionalität zusammenstellen, die sowohl strukturell als auch tabellarisch beschrieben werden kann, so dass die Beschreibung vollständig ist und keine Änderungen erfordert.
Und man könnte den Benutzer die notwendigen Strukturen ausfüllen lassen, aber es ist einfacher und freundlicher, die Parameter direkt an die Methode zu übergeben, als die Struktur vorher auszufüllen und sie dann an die Methode zu übergeben. Dies geschieht nur aus Gründen der Benutzerfreundlichkeit für den Endbenutzer und nicht aus Gründen der Bequemlichkeit beim Parsen der Bibliothekskomponenten.
Vielen Dank für Ihre Einschätzung, Peter. Es ist notwendig, nur das zu verwenden, was von CEngine zur Verfügung gestellt wird, was wiederum vom Programm zur Verfügung gestellt wird.
Der ganze Rest ist die Implementierung von Methoden, denen alle notwendigen Parameter übergeben werden. Diese Methoden sind für den praktischen Einsatz in Ihren eigenen Programmen nicht notwendig - sie sind für die Bibliothek selbst notwendig. Für den Endbenutzer gibt es daher immer weniger Methoden, was sich auch in den Testberatern zeigt.
Natürlich wird alles beschrieben. Und die Struktur, und alle Methoden, die dem Benutzer zur Verfügung stehen. Und es werden Benutzerfunktionen erstellt, die die OOP-Implementierung verbergen und keinen expliziten Zugriff auf Bibliotheksobjekte erfordern.
Aber alles liegt noch vor uns - wir müssen die Hauptfunktionalität zusammenstellen, die sowohl strukturell als auch tabellarisch beschrieben werden kann, so dass die Beschreibung vollständig ist und keine Änderungen erfordert.
Um nicht unsubstantiiert zu sein, würde ich folgende Maßnahme vorschlagen, um das "Wrapping" einzuschränken:
Schreiben Sie die Methode " CTradeObj::SetOrder" so um, dass sie einen zusätzlichen Parameter erhält - die Art der zu setzenden Order. Außerdem wird die Methode selbst bestimmen, wie sie vorgehen soll. Sie wird die erforderliche Struktur initialisieren, die erforderlichen Werte setzen und die erforderlichen Methoden aufrufen. Auf diese Weise werden Sie alle Wrapper auf einen zusätzlichen Parameter komprimieren, der an die Methode " CTradeObj::SetOrder" gesendet wird. Sie erhält PlaceBuyStop, PlaceSellStopLimit oder PlaceBuyLimit als Parameter und führt dann die notwendige Arbeit aus.
Natürlich ist diese Option komplizierter zu implementieren, aber Sie gewährleisten eine "Komprimierung" der Bibliotheksfunktionalität und eine einfache Nutzung.
Viel Glück!
Um nicht unsubstantiiert zu sein, würde ich folgende Maßnahme vorschlagen, um das "Wrapping" einzuschränken:
Die Methode " CTradeObj::SetOrder" sollte so umgeschrieben werden, dass sie einen zusätzlichen Parameter erhält - die Art der zu setzenden Order. Außerdem wird die Methode selbst bestimmen, wie sie vorgehen soll. Sie wird die erforderliche Struktur initialisieren, die erforderlichen Werte setzen und die erforderlichen Methoden aufrufen. Auf diese Weise werden Sie alle Wrapper auf einen zusätzlichen Parameter komprimieren, der an die Methode " CTradeObj::SetOrder" gesendet wird. Sie erhält PlaceBuyStop, PlaceSellStopLimit oder PlaceBuyLimit als Parameter und führt dann die notwendige Arbeit aus.
Natürlich ist diese Option komplizierter zu implementieren, aber Sie gewährleisten eine "Komprimierung" der Bibliotheksfunktionalität und eine einfache Nutzung.
Viel Glück!
Diese Methode wird nicht vom Benutzer der Bibliothek benötigt. Sie wird von der Bibliothek selbst benötigt.
Peter. Versuchen Sie, eine Position zu öffnen, indem Sie nur ihren Typ einstellen. Direkt im Terminal. Und dann sehen Sie, was sonst noch von Ihnen verlangt wird. Das Terminal wird nicht für Sie entscheiden, auf welchem Symbol sie eröffnet werden soll, mit welchem Lot sie eröffnet werden soll, welche Stop-Order-Niveaus gesetzt werden sollen, usw.
...
Und schauen Sie sich bitte OrderSend() für jede Art von gesendeten Aufträgen an - welche Parameter es benötigt. Alle diese Parameter werden an Methoden übergeben. Natürlich wäre es möglich, die Parameter über beschriebene Strukturen wie bei Indikatoren zu übergeben, aber das wäre unnötig.
Meiner Meinung nach wäre die freundlichste Option nur ein Wrapper für OrderSend(). Dieser Wrapper würde Parameter vom Benutzer entgegennehmen und entscheiden, wie der Aufruf zu formatieren ist. Ich würde es auf diese Weise machen. Aber Sie wissen es besser.
Ich habe es so gemacht - die Methoden akzeptieren Parameter vom Benutzer.
Ich habe es auf diese Weise gemacht - Methoden akzeptieren Parameter vom Benutzer.
Ja, ich habe es verstanden. Dies ist eine solche "mehrschichtige" Implementierung der Auftragsabwicklung. Das Problem liegt in der "Dicke" der Wrapper. Ich bin durcheinander gekommen, welche Methoden sich auf Mechanismen und welche auf die Benutzeroberfläche der Bibliothek beziehen. Das tut mir leid. Wenn es weniger Wrapper gäbe, wäre es leichter zu verstehen, aber das ist Ihre Entscheidung.
Sehen Sie, Peter, ich versuche, nicht nur eine Arbeitsmethode zu geben, sondern viele Möglichkeiten.
In diesem Artikel wird der Low-Level-Zugang zu den Handelsfunktionen organisiert. Alles, was das Handelsobjekt tut, ist, die empfangenen Parameter korrekt in die Funktion zum Senden eines Auftrags an den Server einzuordnen. Um einen Handelsauftrag zu senden, müssen Sie auf eine Sammlung von Symbolen zugreifen, ein Objekt des gewünschten Symbols erhalten und von diesem Objekt ein Handelsobjekt erhalten. Dann arbeiten Sie mit dem Handelsobjekt. Hier habe ich es für den Benutzer einfacher gemacht, den Handelsauftrag auszufüllen - es reicht, die notwendigen Parameter zu übergeben. Aber diese Parameter müssen unabhängig voneinander auf Korrektheit geprüft werden, da das Handelsobjekt davon ausgeht, dass alle ihm übergebenen Parameter bereits korrekt sind.
Das ist nicht bequem. Aber es gibt einen solchen Zugang. Wer ihn braucht, prüft alles selbst und sendet einen Handelsauftrag. Es gibt keine Server-Antwortverarbeitung. Das ist das erste, was gemacht wurde.
Der nächste Artikel wird eine Handelsklasse beschreiben, die den gleichen Satz von Handelsmethoden mit den gleichen Parametern haben wird, aber jetzt wird alles auf Korrektheit geprüft und an das Programm zurückgegeben, wenn die Parameter nicht korrekt sind (oder einer von ihnen, oder es gibt keine Möglichkeit zu handeln). Dies ist die zweite Stufe - hier gibt es bereits zwei Möglichkeiten - die erste, die bereits existiert, und die zweite, bei der die Bibliothek selbst die Korrektheit der Parameter prüft, und wenn sie alle korrekt sind, dann wird der Auftrag gesendet, und wenn mindestens einer von ihnen nicht korrekt ist oder es keine Möglichkeit zum Handel gibt, dann kehrt sie einfach zum Steuerprogramm zurück. Hier wird dann ein übergeordneter Zugriff mit Korrektheitsprüfungen organisiert.
Aber das ist noch nicht alles. Wir müssen auch auf Fehler reagieren. Und im nächsten Artikel werden wir noch weiter gehen - wir werden die in den Parametern der Handelsaufträge empfangenen Fehler bearbeiten (noch bevor sie an den Server gesendet werden). Schließlich können Sie im Falle eines Fehlers die Eröffnung einer Position verweigern, die Parameter korrigieren und die Anfrage erneut senden. Dies ist bereits die dritte Ebene der Arbeit mit Handelsobjekten.
Und dann wird es eine noch höhere Ebene geben - alles wird automatisch in Übereinstimmung mit den erforderlichen Einstellungen funktionieren. Und es wird zu aufgeschobenen Aufträgen kommen - wenn der Expert Advisor auf den richtigen Moment wartet, um den gewünschten Auftrag erneut zu senden, oder einfach weiß, in welcher Situation er einen Auftrag senden muss. Alle diese aufgeschobenen Aufträge befinden sich in seinem Sparschwein und warten auf den richtigen Zeitpunkt, um den Auftrag zu senden.
Peter, es ist also noch zu früh, um etwas zu beurteilen.
Sie haben vorgeschlagen, einen einzigen Zugang zu den Handelsfunktionen zu schaffen, aber ich möchte eine Vielzahl von Methoden anbieten - für jeden, je nach seinen Bedürfnissen. Obwohl es natürlich unmöglich ist, es allen recht zu machen.
Artyom Trishkin:
...
Ihre Erklärung hat mir gefallen, und dadurch ist ein innerer Widerspruch entstanden.
1. Auf der einen Seite, so dass die Nutzer Zugang zu allen Ebenen der Bibliothek Motor durch den Aufbau einer abgestuften "Wrapper"-Struktur, wo anstelle von komprimierten Algorithmen sind erweitert Beziehungen, und die algorithmische "Rahmen" ist für die einfache Wahrnehmung skaliert, bietet ein komfortables Verständnis der Struktur der Lösungen. Das ist schön, ästhetisch, elegant. Natürlich ist es eine Frage des Designs und der Benutzerfreundlichkeit. Genauer gesagt, um die Freundlichkeit für Forscher, denn für die Nutzer sind Ergebnisse und Effizienz wichtiger. Betrachten wir nun die Lösung aus einer anderen Perspektive.
2- Effizienz bedeutet Prägnanz, eine minimale Anzahl von Entitäten und Wrappern, mit dem kürzest möglichen Zugang zu den Daten. Alles sollte nah beieinander liegen, um nicht zu "strecken" und um nicht eine "Last" von Parametern von Wrapper zu Wrapper zu übertragen. Effizienz und ein eingesetzter, abgestufter, eleganter Stil mit "wandernden" zwischen Wrappern "Schwadronen" von Parametern sind sich fremd und fast unvereinbar.
//-----------------------------------
In Anbetracht dieses Widerspruchs würde ich einen Kompromiss vorschlagen. Begrenzen Sie teilweise das Wachstum der Zahl der Wrapper, indem Sie die Prägnanz der Lösungen erhöhen. Im Prinzip reicht ein Wrapper für die Funktion OrderSend() aus. In einem extremen Fall - mehrere. Aber in diesem Fall wird die Lösung für "Forscher" schwer zu verstehen sein, und der Zugang zu "Ebenen" wird komplizierter werden. Versuchen Sie daher, komprimierte, effiziente Blöcke und die bei Programmierern so beliebten "Lianen" des OOP-Dschungels zu kombinieren. Und Sie werden die goldene Mitte finden.
...
Und dann wird es einen noch höheren Ansatz geben - alles wird im automatischen Modus gemäß den erforderlichen Einstellungen funktionieren. Und es wird zu aufgeschobenen Aufträgen kommen - wenn der Expert Advisor auf den richtigen Moment wartet, um den benötigten Auftrag erneut zu senden, oder einfach weiß, in welcher Situation er einen Auftrag senden muss. Alle diese aufgeschobenen Aufträge befinden sich in seinem Sparschwein und warten auf den richtigen Moment, um den Auftrag zu senden.
Deshalb, Peter, ist es verfrüht, etwas zu beurteilen.
Sie haben vorgeschlagen, einen einzigen Zugang zu den Handelsfunktionen zu schaffen, aber ich möchte eine Vielzahl von Methoden anbieten - für jeden, je nach seinen Bedürfnissen. Obwohl es natürlich unmöglich ist, es allen recht zu machen.
Es ist sehr gut, die Bibliothek in Stufen zu unterteilen und den Benutzern die Möglichkeit zu geben, sie zu bearbeiten. Aber vergessen Sie nicht, dass Quantität die Qualität töten kann. Je mehr Methoden ein Benutzer erhält, desto wahrscheinlicher ist es, dass er verwirrt wird. Das sollte man im Hinterkopf behalten.
Ansonsten stimme ich zu. Ein mehrschichtiger Ansatz für Handelsfunktionen ist eine gute Sache.
- 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 XXI): Handelsklassen - Plattformübergreifendes Basis-Handelsobjekt :
In diesem Artikel werden wir mit der Entwicklung des neuen Bibliotheksbereichs beginnen - die Handelsklassen. Außerdem werden wir die Entwicklung eines einheitlichen Basisobjekts für den Handel auf den Plattformen MetaTrader 5 und MetaTrader 4 in Betracht ziehen. Wenn ein Auftrag an den Server gesendet wird, bedeutet ein solches Handelsobjekt, dass verifizierte und korrekte Parameter der Handelsanfrage an den Server übergeben werden.
Es ist schön, jederzeit einen einfachen Zugriff auf verschiedene Daten zu haben. Diese Daten sind jedoch nutzlos, wenn wir sie nicht beim Handeln verwenden können. Das bedeutet, dass wir neben der bereits vorhandenen Handelsfunktionen auch eine weitere benötigen.
Dieser Abschnitt wird relativ groß sein, und wir werden alles Schritt für Schritt tun.
- Wir sollten in der Lage sein, alle Handelsanfragen von jeder Plattform aus zu senden, sei es MetaTrader 5 oder MetaTrader 4, ohne auch nur an die Unterschiede zwischen ihnen zu denken. Alles sollte vereinheitlicht werden.
- Erstens müssen wir Handelsanforderungen überprüfen, um den Server nicht mit absichtlich fehlerhaften Anforderungen zu belasten.
- Wir müssen die Antworten des Handelsservers berücksichtigen und korrekt behandeln. Was macht ein EA, wenn er eine Anfrage an den Server sendet? Er bestreitet einen den Dialog aus "Frage und Antwort" mit dem Server. Unsere Aufgabe ist es, diesen "Kommunikationskanal" richtig zu gestalten, d.h. die Methoden zur Behandlung der Antworten von Handelsservern zu schaffen.
- Wir müssen mehrere Optionen für die Behandlung der Serverantworten schaffen, da wir manchmal eine Position "vorzugsweise um jeden Preis" eröffnen müssen. Dazu müssen wir eine wiederholte Versendung einer Anfrage an den Server veranlassen, falls eine Order nicht erteilt werden kann — wir können entweder die Parameter der Handelsanfrage anpassen oder erneut senden, oder alle Parameter belassen wie sie sind, und auf den richtigen Moment warten, wenn die Anfrage mit diesen Parametern weitergeleitet wird, um sie sofort zu senden. Außerdem müssen wir das Preisniveau berücksichtigen, um eine Bestellung nicht zu einem bewusst schlechteren Preis erneut zu versenden.
- Außerdem müssen wir die Arbeit mit den Handelsklassen so gestalten, dass Probleme bei der Platzierung eines bibliotheksbasierten Programms auf MQL5 Market vermieden werden. Das Programm sollte alle Prüfungen reibungslos bestehen.
Dies ist mein aktueller Plan bezüglich der Handelsklassen.Manchmal müssen wir eine Handelsanfrage senden und die Arbeit unabhängig von einem Anfrageergebnis fortsetzen.
Autor: Artyom Trishkin