Fragen zu OOP in MQL5 - Seite 28

 
Dmitry Fedoseev:

Und wenn Sie keine Klassen verwenden, werden Sie es leid, ständig etwas wie SymbolInfoDouble(_Symbol,MODE_BID) zu schreiben. Solche Tänze gibt es jedes Mal - sowohl Klammern als auch Unterstriche, und man weiß nicht, ob man die Feststelltaste drücken (und dann irgendwo anders, ohne hinzuschauen, eine ganze großgeschriebene Zeichenkette eintippen und erneut eingeben) oder die Umschalttaste gedrückt halten soll. Zumindest in diesem Bereich ist OOP nützlich. Wenn zumindest Klassen für all diese Funktionen, dann ja - sie sind riesig. Wenn Sie es für sich selbst schreiben, ist das kein Problem. Was die Arbeit mit Aufträgen betrifft, so gibt es nicht so viele häufig verwendete Funktionen, wir können einfach ein paar Funktionen in eine Bibliothek aufnehmen. Aber im Allgemeinen ist noch kein idealer Ansatz gefunden worden.

Hier ist meine Vorstellung von der Klasse, die öffnen/schließen/den Stop-Loss setzen und später denAuftragsstatus anzeigen kann

class CConstVolume
{
protected:
   static const double  VolumeMAX;
   static const double  VolumeMIN;
   static const double  VolumeSTEP;
   static const double  ZerroPrice;
   static const int     VolumeDIGITS;
   static int           GetDigitsInVolumeStep(); };
//___________________________________________________________________________
static int CConstVolume::GetDigitsInVolumeStep()
{  int result = 0;
   long i = 10000000, k = long(::SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP) / 0.0000001);
   while(result < 7 && k % i > 0)
   {  i /= 10;
      result++; }
   return(result); }
//____________________________________________________________________
static const double CConstVolume::VolumeMAX = ::SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
//____________________________________________________________________
static const double CConstVolume::VolumeMIN = ::SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
//____________________________________________________________________
static const double CConstVolume::VolumeSTEP = ::SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
static const double CConstVolume::ZerroPrice = ::NormalizeDouble(0.0, _Digits);
//____________________________________________________________________
static const int CConstVolume::VolumeDIGITS = CConstVolume::GetDigitsInVolumeStep();
//____________________________________________________________________




//+------------------------------------------------------------------+
//|   class COrder                                                   |
//+------------------------------------------------------------------+
class COrder : private CConstVolume
{
private:
   SOrderInfo        m_info;        //структура для инициализации класса, и хранения информации о ордере, тип, цена отркытия, лот, и состояние ордера
   CError            error;         //класс с описание ошибок на 2-х языках
   int               sl_error_count;//счетчик ошибок установки стоплосса/тейка
   bool              m_needstoploss;//флаг для установки стоплосса, сбросим когда все ОК
   bool              CheckMarginRequirements();
   bool              ServerDisable();
   int               Ordersend();
   int               CheckOrderByMagicnumber(int magic_);   //метод нужен для поиска открытого ордера по магику, использую в конструкторе
   void              SetStoploss();
   void              NULLOrder()             { ZeroMemory(m_info); m_info.cmd = -1; m_info.status = ErrorOrder; m_needstoploss = false;   }
   void              PrintError(string func) { Print(func); error.GetLastError();                                                         }
public:
                     COrder():m_needstoploss(false) { NULLOrder();                                                                        }
                     COrder(SOrderInfo &ordersetting);
   SOrderInfo        GetOrderInfo(); 
   bool              Orderclose();};
//________________________________

und beachten Sie die Verwendung auf ein Symbol - speziell eine statische Klasse zu verwenden

Alles in allem funktioniert alles wie vorgesehen.... aber ich mag es nicht, wie ich oben schrieb, ist es umständlich und überflüssig

 
Dmitry Fedoseev:

Und wenn Sie keine Klassen verwenden, werden Sie es leid sein, ständig etwas wie SymbolInfoDouble(_Symbol,SYMBOL_BID) zu schreiben. Das tanzt jedes Mal ...

Man könnte bequemere und prägnantere Wrapper für diese Funktionen erstellen, während man sie im prozeduralen Stil belässt. Vor allem unter Berücksichtigung der Tatsache, dass sie in den letzten Builds endlich Namespace hinzugefügt haben, ist alles großartig. Vorher musste man sie als statische Methoden implementieren, aber jetzt ist alles viel einfacher:

namespace SymbolInfo
{
  double Bid(string symbol) { return SymbolInfoDouble(symbol, SYMBOL_BID); }
  double Ask(string symbol) { return SymbolInfoDouble(symbol, SYMBOL_ASK); }
};
 
Alexey Navoykov:

Man kann bequemere und prägnantere Wrapper für diese Funktionen erstellen, ohne den prozeduralen Stil zu vernachlässigen. Vor allem, da sie in den letzten Builds endlich Namespace hinzugefügt haben, ist das großartig. Vorher musste man sie als statische Methoden implementieren, aber jetzt ist alles viel einfacher:

Ist es wirklich wichtig, die Grenzen einzuhalten? Wenn es wichtig ist, die Grenzen einzuhalten, können Sie Funktionen schreiben.

 
Igor Makanu:

Nun, nicht viel, ich würde sagen, eine ganze Menge von Aktionen, um eine Bestellung zu setzen, hier ist meine Vision für eine Klasse, die weiß, wie zu öffnen / schließen / Stoploss / und weitere Ausgabe um Status

und beachten Sie die Verwendung auf ein Symbol - speziell eine statische Klasse zu verwenden

Alles in allem funktioniert alles wie vorgesehen.... aber ich mag es nicht, wie ich oben schrieb, ist es umständlich und überflüssig

Ja, das ist eine weitere Frage, die sich immer wieder stellt und auf die es keine eindeutige Antwort gibt. Wenn Sie Ihre eigene Klasse erben müssen - was ist besser, sie zu erben oder eine neue erweiterte Version Ihrer Klasse zu schreiben.

 
Alexey Navoykov:

Es ist möglich, bequemere und prägnantere Wrapper für diese Funktionen zu erstellen und dabei den prozeduralen Stil beizubehalten. Vor allem, da sie in den letzten Builds endlich Namespace hinzugefügt haben, ist das großartig. Vorher musste man sie als statische Methoden implementieren, jetzt sind die Dinge viel einfacher:

Sie haben keine prägnante Notation, wenn es keine Prüfungen gibt, ist es einfacher, es so zu schreiben, wie es ist:

#define  Ask SymbolInfoDouble(_Symbol,SYMBOL_ASK)
#define  Bid SymbolInfoDouble(_Symbol,SYMBOL_BID)

void OnStart()
  {
   Print("Ask = ",Ask);
   Print("Bid = ",Bid);
  }
 
Igor Makanu:

und beachten Sie, dass die Verwendung auf ein einzelnes Zeichen - insbesondere eine statische Klasse verwendet werden

Was hindert Sie daran, den Namen des Symbols an den Konstruktor zu übergeben, um die Klasse flexibel und vielseitig zu gestalten? Sie halten die Möglichkeit des Portfoliohandels grundsätzlich für ausgeschlossen?
 
Igor Makanu:

Ihr Eintrag ist nicht knapp, wenn es keine Häkchen gibt, ist es einfacher zu schreiben, wie es ist:

Es gibt eine Reihe von Funktionen wie SymbolInfoDouble. Es ist mühsam, sich kurze Namen für alle auszudenken. Wenn man sie in Klassen zusammenfasst, muss man sich um die Eindeutigkeit der Namen keine Sorgen machen.

 

Ich habe die folgende Schaltung, bei der ich keine Probleme hatte.

  1. Ich schreibe TC nur für Tester. Keine Protokolle, Fehlerbehandlungsroutinen oder sonstiger Unsinn. Der Code ist sehr prägnant, verständlich und kann überarbeitet werden, wenn er mit OOP erstellt wurde (aber nicht grundlegend). Ich habe das Beispiel bereits in KB veröffentlicht. Der Bonus ist die schnelle Optimierung.
  2. Die Hauptsache ist, dass sie für den Prüfer und in unabhängigen Blöcken verfügbar sind. Die Erzeugung von Handelssignalen - ein Block. Signalhandel - ein weiterer Block.
  3. Die Überweisung auf das echte Konto erfolgt immer in mehreren Zügen. Der TS wird in einer virtuellen Umgebung platziert, ohne dass der Code geändert wird. Wenn mehrere TS in einer Umgebung oder jeder TS in einer eigenen Umgebung platziert werden kann, dann ist das OOP besonders praktisch. Dann nehmen wir einen Kopierer (der Markt ist voll davon, also sind die Leute gut in Kopierlogik), der einfach Geschäfte/Aufträge aus der virtuellen Umgebung in die reale kopiert.
  4. Mit diesem Schema ist das Schreiben von TS schnell und einfach. Die Übergabe an Real (die in der Tat selten ist) erfolgt immer einheitlich, schnell und klar.
 
Igor Makanu:

Sie haben keinen präzisen Eintrag, und wenn es keine Kontrollen gibt, ist es einfacher, ihn so zu schreiben, wie er ist:

So wird das nicht gemacht. Ihr Eintrag sieht aus wie eine Variable, die den Anschein erweckt, dass ihr Wert unverändert ist, obwohl dies in Wirklichkeit nicht der Fall ist.
 
Alexey Navoykov:
Was hindert Sie daran, den Namen des Symbols an den Konstruktor zu übergeben, um die Klasse flexibel und vielseitig zu gestalten? Ziehen Sie die Möglichkeit des Portfoliohandels grundsätzlich nicht in Betracht?

Dies wird dadurch erschwert, dass EAs meist nur aus einem Zeichen bestehen und die Übergabe eines Symbols in den meisten Fällen eine unnötige (und anstrengende))) Aktion wäre. Eine weitere Möglichkeit besteht darin, das Diagrammsymbol standardmäßig automatisch auszuwählen, und bei Bedarf können Sie das Symbol für eine Weile außer Kraft setzen. Aber auch hier stellt sich die Frage, was besser ist - eine Instanz der Klasse zu verwenden und das Symbol nach Bedarf zu überschreiben oder für jedes Symbol eine eigene Instanz zu erstellen.

Grund der Beschwerde: