English Русский 中文 Español 日本語 Português
Ein Expert Advisor mit GUI: Erstellen des Panels (Teil I)

Ein Expert Advisor mit GUI: Erstellen des Panels (Teil I)

MetaTrader 5Beispiele | 6 August 2018, 17:40
2 143 0
Anatoli Kazharski
Anatoli Kazharski

Inhalt

Einführung

Trotz der aktiven Entwicklung des algorithmischen Handels bevorzugen viele Händler immer noch den manuellen Handel. Die Automatisierung von Routineaufgaben lässt sich jedoch kaum ganz vermeiden.

Der Artikel zeigt die Entwicklung eines Expert Advisor mit Signalen von mehreren Symbolen für den manuellen Handel. Als Beispiel verwenden wir die Signale der Stochastic aus der Standardauslieferung des Terminals. Sie können diesen Code verwenden, um eigene EAs mit grafischer Oberfläche (GUI) zu entwickeln: Jeder andere Indikator kann darin enthalten sein, ebenso wie die Ergebnisse bestimmter Berechnungen, um Entscheidungen zu treffen.

Für diejenigen, die Aufträge anderer Händler ausführen, kann der Artikel als Beispiel für eine technische Aufgabe dienen, die dem Kunden demonstriert werden soll. Dieses Beispiel kann Ihnen Zeit sparen, wenn Sie ein verständliches Pflichtenheft für die Entwicklung eines Programms mit GUI erstellen.

Hier sind die Themen, die in diesem Artikel ausführlich diskutiert werden.

  • Erstellen eines GUI.
  • Abrufen einer Liste von Symbolen mit bestimmten Eigenschaften. 
  • Steuerung des Handelsbetriebs. 
  • Schnelles Umschalten von Symbolen und Zeitrahmen auf Charts ohne die EA-Neuinitialisierung.
  • Verwaltung der Chart-Eigenschaften über die Benutzeroberfläche.
  • Empfang von Indikatorsignalen von mehreren Symbolen mit Farbanzeige.
  • Arbeiten mit offenen Positionen. 
  • EasyAndFast Aktualisierung der Bibliothek.

Der Artikel soll in zwei Teilen veröffentlicht werden. In diesem Artikel betrachten wir die Entwicklung des Panels, während der nächste beschreibt, wie man es mit Funktionen füllt.

GUI Elemente

Wir beginnen die Entwicklung des EAs mit dem Aufbau einer GUI, die es den Benutzern ermöglicht, mit dem Programm zu interagieren und Daten zu visualisieren. Es ist möglich, ein GUI mit den Möglichkeiten der Standardbibliothek zu erstellen, aber in meinem Beispiel ist es auf Basis der EasyAndFast-Bibliothek implementiert. Seine reichhaltigen Funktionen ermöglichen es, sich auf die Funktionalität des Programms selbst zu konzentrieren, ohne durch die Verfeinerung seines grafischen Teils abgelenkt zu werden.

Lassen Sie uns zunächst die allgemeine GUI-Struktur skizzieren. Das folgende Diagramm zeigt das GUI-Fenster, das aus zwei Registerkarten besteht. Die Listen zeigen die Funktionen an, die darauf platziert werden sollen. Dies ist ein vereinfachtes Beispiel. Ein Kunde und ein Entwickler könnten dies im Gespräch näher ausarbeiten.

Abb. 1. Ansicht des General GUI mit Anmerkungen

Abb. 1. Ansicht des General GUI mit Anmerkungen

Das GUI könnte viele Steuerelement haben. Daher listen wir sie in einer hierarchischen Ordnung, zu Anfang:

  • Aussehen der Kontrollelemente
    • Statusleiste für die Anzeige zusätzlicher Übersichtsinformationen
    • Die Gruppe der Karteireiter:
      • Handel:
        • Eingabefeld mit Ankreuzkästchen zum Filtern der Symbolliste
        • Taste "Anfordern", um mit der Erstellung der Liste der Symbole zu beginnen.
        • Taste für VERKAUFEN
        • Taste für KAUFEN
        • Eingabefeld für das Handelsvolumen
        • Taste zum Schließen aller offenen Positionen
        • Eingabefeld zur Einstellung eines Verkaufssignals
        • Eingabefeld zur Einstellung eines Kaufsignals
        • Tabelle der Symbole für den Handel
        • Diagramm zur Visualisierung von Symboldaten. Für mehr Komfort, ermöglichen wir die Verwaltung einiger Chart-Eigenschaften mit der folgenden Gruppe von Elementen:
          • Kombinationsfeld mit einer Auswahlliste zum Umschalten der Zeitrahmen 
          • Kontrollkästchen zum Aktivieren/Deaktivieren der Zeitmaßstabes 
          • Ankreuzkästchen zum Aktivieren/Deaktivieren der Preisstaffel 
          • Eingabefeld für den Maßstab 
          • Taste zum Aktivieren einer Einrückung 
          • Ankreuzfeld zur Anzeige des Indikators 
      • Positionen:
        • Tabelle der Positionen
    • Indikator für die Wiedergabe von Rahmen

Wir Deklarieren in der Hauptprogrammklasse (CProgram) die Methoden und Klasseninstanzen der oben genannten Elemente. Der Code der Methoden zum Erzeugen von Elementen wird in einer separaten Datei bereitgestellt und in die Datei mit einer MQL-Programmklasse eingebunden:

//+------------------------------------------------------------------+
//| Klasse der Entwicklungsanwendung                                 |
//+------------------------------------------------------------------+
class CProgram : public CWndEvents
  {
private:
   //--- Fenster
   CWindow           m_window1;
   //--- Statusleiste
   CStatusBar        m_status_bar;
   //--- Karteireiter
   CTabs             m_tabs1;
   //--- Eingabefelder
   CTextEdit         m_symb_filter;
   CTextEdit         m_lot;
   CTextEdit         m_up_level;
   CTextEdit         m_down_level;
   CTextEdit         m_chart_scale;
   //--- Tasten
   CButton           m_request;
   CButton           m_chart_shift;
   CButton           m_buy;
   CButton           m_sell;
   CButton           m_close_all;
   //--- Kombinationsfeld
   CComboBox         m_timeframes;
   //--- Ankreuzfeld
   CCheckBox         m_date_scale;
   CCheckBox         m_price_scale;
   CCheckBox         m_show_indicator;
   //--- Tabellen
   CTable            m_table_positions;
   CTable            m_table_symb;
   //--- Standardchart
   CStandardChart    m_sub_chart1;
   //--- Fortschrittsanzeige
   CProgressBar      m_progress_bar;
   //---
public:
   //--- Erstellen des GUI
   bool              CreateGUI(void);
   //---
private:
   //--- Formular
   bool              CreateWindow(const string text);
   //--- Statusleiste
   bool              CreateStatusBar(const int x_gap,const int y_gap);
   //--- Karteireiter
   bool              CreateTabs1(const int x_gap,const int y_gap);
   //--- Eingabefelder
   bool              CreateSymbFilter(const int x_gap,const int y_gap,const string text);
   bool              CreateLot(const int x_gap,const int y_gap,const string text);
   bool              CreateUpLevel(const int x_gap,const int y_gap,const string text);
   bool              CreateDownLevel(const int x_gap,const int y_gap,const string text);
   bool              CreateChartScale(const int x_gap,const int y_gap,const string text);
   //--- Tasten
   bool              CreateRequest(const int x_gap,const int y_gap,const string text);
   bool              CreateChartShift(const int x_gap,const int y_gap,const string text);
   bool              CreateBuy(const int x_gap,const int y_gap,const string text);
   bool              CreateSell(const int x_gap,const int y_gap,const string text);
   bool              CreateCloseAll(const int x_gap,const int y_gap,const string text);
   //--- Kombinationsfeld
   bool              CreateComboBoxTF(const int x_gap,const int y_gap,const string text);
   //--- Ankreuzfeld
   bool              CreateDateScale(const int x_gap,const int y_gap,const string text);
   bool              CreatePriceScale(const int x_gap,const int y_gap,const string text);
   bool              CreateShowIndicator(const int x_gap,const int y_gap,const string text);
   //--- Tabellen
   bool              CreatePositionsTable(const int x_gap,const int y_gap);
   bool              CreateSymbolsTable(const int x_gap,const int y_gap);
   //--- Standardchart
   bool              CreateSubChart1(const int x_gap,const int y_gap);
   //--- Fortschrittsanzeige
   bool              CreateProgressBar(const int x_gap,const int y_gap,const string text);
  };
//+------------------------------------------------------------------+
//| Methoden zum Erstellen der Steuerelemente                        |
//+------------------------------------------------------------------+
#include "CreateGUI.mqh"
//+------------------------------------------------------------------+

Als nächstes betrachten wir die Zusammenstellung des GUI, die Methoden zum Erstellen ihrer Elemente und Eigenschaften.

Zusammenstellen des GUI

Wir werden die Elemente von zehn Typen in der GUI der entwickelten Anwendung verwenden.

  • Formular für Steuerungen (CWindow)
  • Statusleiste (CStatusBar)
  • Gruppe von Karteireiter (CTabs)
  • Eingabefeld (CTextEdit)
  • Taste (CButton)
  • Combobox mit Auswahlliste (CComboBox)
  • Ankreuzfeld (CCheckBox)
  • Tabelle (CTable)
  • Standardtabelle (CStandardChart)
  • Fortschrittsbalken (CProgressBar)

Wir werden mehr als ein Element in einigen Kategorien aus dieser Liste benötigen, also werden wir nur ein Element pro Gruppe berücksichtigen. Betrachten wir die Methoden ihrer Erstellung in der gleichen Reihenfolge. 

Aussehen der Kontrollelemente

Unten ist der Code der Methode zur Erstellung eines Formulars, auf dem sich alle anderen Elemente befinden sollen. Zuerst müssen wir das Formular in die Liste der Programm-GUI-Elemente aufnehmen. Dazu rufen wir die Methode CWndContainer::AddWindow() auf, indem Sie ihr das Elementobjekt vom Typ CWindow übergeben. Wir bestimmen dann seine Eigenschaften, bevor wir das Formular erstellen. Wir stellen die folgenden Eigenschaften ein (in der gleichen Reihenfolge wie in der Liste unten):

  • Formulargröße (Breite und Höhe)
  • Schriftgröße der Kopfzeile
  • Bewegungsmodus des Formulars (innerhalb des Charts)
  • Modus der manuellen Größenanpassung des Formulars (durch Ziehen der Ränder)
  • Tasten des Formulars. Die Sichtbarkeit der einzelnen Tasten ist anpassbar. In diesem Fall werden die folgenden verwendet:
    • Schließen des Formulars. Wenn Sie auf die Schaltfläche klicken, erscheint im Hauptformular des Programms das Bestätigungsfenster für das Schließen des Programms.
    • Maximieren/Minimieren des Formulars. 
    • Tooltips Elemente. Diese Taste hat auch zwei Zustände. Wenn aktiviert, werden die angegebenen Tooltips in den Steuerelementen angezeigt.
    • Erweitern des Formulars auf den gesamten Chart. Dies kann durch erneutes Anklicken der Schaltfläche rückgängig gemacht werden.
  • Für jede Taste kann ein Tooltip gesetzt werden.

Nach dem Setzen der Eigenschaften rufen Sie die Formularerstellungsmethode - CWindow::CreateWindow() auf und übergeben diese:

  • Chart-ID,
  • Index der Unterfenster des Charts,
  • Text der Kopfzeile,
  • Anfangskoordinaten des Formulars.
//+------------------------------------------------------------------+
//| Erstellen des Formulars des Steuerelements                       |
//+------------------------------------------------------------------+
bool CProgram::CreateWindow(const string caption_text)
  {
//--- Hinzufügen des Pointers auf das Fenster zum Array der Fenster
   CWndContainer::AddWindow(m_window1);
//--- Eigenschaften
   m_window1.XSize(750);
   m_window1.YSize(450);
   m_window1.FontSize(9);
   m_window1.IsMovable(true);
   m_window1.ResizeMode(true);
   m_window1.CloseButtonIsUsed(true);
   m_window1.CollapseButtonIsUsed(true);
   m_window1.TooltipsButtonIsUsed(true);
   m_window1.FullscreenButtonIsUsed(true);
//--- Festlegen der Tooltips
   m_window1.GetCloseButtonPointer().Tooltip("Close");
   m_window1.GetTooltipButtonPointer().Tooltip("Tooltips");
   m_window1.GetFullscreenButtonPointer().Tooltip("Fullscreen");
   m_window1.GetCollapseButtonPointer().Tooltip("Collapse/Expand");
//--- Erstellen der Formulars
   if(!m_window1.CreateWindow(m_chart_id,m_subwin,caption_text,1,1))
      return(false);
//---
   return(true);
  }

Es wird empfohlen, das Programm zu kompilieren und das Ergebnis jedes Mal zu überprüfen, wen ein neuen Element dem GIU hinzugefügt wurde. 

Abb. 2. Aussehen der Kontrollelemente

Abb. 2. Aussehen der Kontrollelemente

Bildschirmfotos aller Zwischenschritte werden unten angezeigt.

Statusleiste

Der Code der Methode zur Erstellung einer Statusleiste beginnt mit der Angabe des Hauptelements, mit dem die daran gebundenen Elemente berechnet und in ihrer Größe ausgerichtet werden. Das spart Zeit bei der Entwicklung einer Anwendung: Eine ganze Gruppe von verwandten Elementen kann verschoben werden, indem nur die Koordinaten des Hauptelements geändert werden. Um das Element zu binden, wird sein Pointer an die Methode CElement::MainPointer() übergeben. In diesem Beispiel binden wir die Statusleiste an das Formular, daher wird das Formularobjekt der Methode übergeben.

Dann setzen wir die Eigenschaften der Statusleiste. Sie soll drei Abschnitte mit Informationen für Benutzer anzeigen. 

  • Um keine Maße relativ zum Formular anzugeben, stellen wir sicher, dass sich die Breite automatisch ändert, wenn die Breite des Formulars geändert wird.
  • Die Abstand des rechten Randes des Elements beträgt 1 Pixel.
  • Wir binden die Statusleiste an den unteren Rand des Formulars, so dass sie automatisch an den unteren Rand angepasst wird, wenn sich die Formularhöhe ändert.
  • Wenn wir dann Punkte hinzufügen, stellen wir die Breite für jeden von ihnen ein.

Nachdem die Eigenschaften gesetzt sind, legen wir das Element an. Jetzt ist es bereit für die Arbeit, und wir können den Text in seinen Abschnitten während der Laufzeit ändern. In unserem Beispiel, setzen wir den Text "Für Hilfe, drücken Sie F1" im ersten Abschnitt

Wir stellen am Ende der Methode sicher, dass der Pointer des erzeugten Elements in der allgemeinen Liste der GUI-Elemente gespeichert wird. Wir rufen dazu die Methode CWndContainer::AddToElementsArray() auf und übergeben ihr den Formularindex und das Elementobjekt. Da wir nur ein einziges Formular haben, ist sein Index 0.

//+------------------------------------------------------------------+
//| Erstellen einer Statusleiste                                     |
//+------------------------------------------------------------------+
bool CProgram::CreateStatusBar(const int x_gap,const int y_gap)
  {
#define STATUS_LABELS_TOTAL 3
//--- Sichern des Pointers zum Fenster
   m_status_bar.MainPointer(m_window1);
//--- Eigenschaften
   m_status_bar.AutoXResizeMode(true);
   m_status_bar.AutoXResizeRightOffset(1);
   m_status_bar.AnchorBottomWindowSide(true);
//--- Setzen der Anzahl der Zeile und ihrer Eigenschaften
   int width[STATUS_LABELS_TOTAL]={0,200,110};
   for(int i=0; i<STATUS_LABELS_TOTAL; i++)
      m_status_bar.AddItem(width[i]);
//--- Erstellen des Kontrollelements
   if(!m_status_bar.CreateStatusBar(x_gap,y_gap))
      return(false);
//--- Setzen des Textes in der Statusleiste
   m_status_bar.SetValue(0,"For Help, press F1");
//--- Hinzufügen des Objekts zum allg. Array der Objektgruppe
   CWndContainer::AddToElementsArray(0,m_status_bar);
   return(true);
  }

Die verbleibende Elemente der Bibliothek EasyAndFast werden nach demselben Prinzip erstellt. Daher betrachten wir nur die anpassbaren Eigenschaften, die in unserem EA verwendet werden.

Abb. 3. Hinzufügen der Statusleiste

Fig. 3. Hinzufügen der Statusleiste

Gruppen von Karteireitern

Bestimmen wir in der Methode zum Anlegen der Gruppen von Karteireitern die folgenden Element-Eigenschaften:

  • Zentrieren der Texte auf dem Karteireiter.
  • Lokalisieren der Karteireiter im oberen Teil des Arbeitsbereiches.
  • Die Größe wird automatisch an den Bereich des Hauptelements (Formulars) angepasst. In diesem Fall ist es nicht notwendig, die Größe der Gruppen von Karteireitern anzugeben.
  • Wir stellen die Einzüge der rechten und unteren Kante des Hauptelements ein. Wenn das Formular seine Größe ändert, bleiben diese Abstände erhalten.
  • Beim Hinzufügen der folgenden Registerkarten werden auch der Name der Karteireiter und die Breite in die Methode übernommen.

Unten ist der Code der Methode:

//+------------------------------------------------------------------+
//| Erstellen eines Karteireiters in Gruppe 1                        |
//+------------------------------------------------------------------+
bool CProgram::CreateTabs1(const int x_gap,const int y_gap)
  {
#define TABS1_TOTAL 2
//--- Sichern des Pointers auf das Hauptelement
   m_tabs1.MainPointer(m_window1);
//--- Eigenschaften
   m_tabs1.IsCenterText(true);
   m_tabs1.PositionMode(TABS_TOP);
   m_tabs1.AutoXResizeMode(true);
   m_tabs1.AutoYResizeMode(true);
   m_tabs1.AutoXResizeRightOffset(3);
   m_tabs1.AutoYResizeBottomOffset(25);
//--- Hinzufügen von Karteireitern mit den angegebenen Eigenschaften
   string tabs_names[TABS1_TOTAL]={"Trade","Positions"};
   for(int i=0; i<TABS1_TOTAL; i++)
      m_tabs1.AddTab(tabs_names[i],100);
//--- Erstelle des Steuerelements
   if(!m_tabs1.CreateTabs(x_gap,y_gap))
      return(false);
//--- Hinzufügen des Objekts zum allg. Array der Objektgruppe
   CWndContainer::AddToElementsArray(0,m_tabs1);
   return(true);
  }

Abb. 4. Hinzufügen der Gruppe von Karteireiter

Abb. 4. Hinzufügen der Gruppe von Karteireiter

Eingabefeld

Betrachten wir beispielsweise ein Eingabefeld, in dem ein Benutzer Währungen und/oder Währungspaare angeben kann, um die Symbolen in einer Tabelle aufzulisten. Sein Hauptelement ist eine Gruppe von Karteireiter. Hier müssen wir die Karteireiter angeben, auf der das Eingabefeld angezeigt werden soll. Dazu rufen wir die Methode CTabs::AddToElementsArray() auf und übergeben ihr den Registerindex und das angehängte Elementobjekt.

Betrachten wir nun die Eigenschaften für dieses Eingabefeld.

  • Standardmäßig ist im Eingabefeld "USD" eingetragen: Das Programm sammelt Symbole mit USD in der Tabelle. Währungen und/oder Symbole in diesem Eingabefeld sind durch Komma getrennt. Im Folgenden werde ich die Methode zur Bildung einer Liste von Symbolen durch kommagetrennte Zeilen in diesem Eingabefeld zeigen.
  • Das Eingabefeld enthält ein Ankreuzfeld. Nach dem Deaktivieren des Ankreuzfelds wird der Text im Eingabefeld ignoriert. Alle erkannten Währungspaare werden in die Symbolliste aufgenommen.
  • Die Breite des Eingabefelds ist gleich der gesamten Breite des Hauptelements und wird angepasst, wenn sich die Breite des Karteireiters ändert.
  • Die Taste Request befindet sich rechts neben dem Eingabefeld. Während das Programm läuft, können im Eingabefeld weitere Währungen und/oder Symbole angeben werden. Ein Klick auf diese Taste erstellt die Liste. Da die Breite des Eingabefelds sich automatisch ändern soll, während die Taste Request immer rechts davon stehen soll, ist darauf zu achten, dass die rechte Seite des Eingabefeldes einen Abstand vom rechten Rand des Hauptelements hat. 

Das Element vom Typ CTextEdit besteht aus mehreren anderen Elementen. Deshalb, wenn ihre Eigenschaften geändert werden müssen, können die Zeiger abgefragt werden. Wir mussten einige Eigenschaften des Texteingabefeldes ändern (CTextBox). Betrachten wir sie in der gleichen Reihenfolge wie in der folgenden Codeliste.

  • Eingabefeld Einrückung vom linken Rand des Hauptelements (CTextEdit). 
  • Automatische Änderung der Breite relativ zum Hauptelement.
  • Beim Aktivieren des Eingabefeldes (durch Linksklick auf das Eingabefeld) wird der Text für einen schnellen Änderung vollautomatisch hervorgehoben.
  • Befindet sich überhaupt kein Text im Eingabefeld, wird Folgendes angezeigt: "Beispiel EURUSD, GBP, NOK".  

Das Ankreuzfeld des Eingabefeldes ist standardmäßig aktiviert. Wir aktivieren sie dazu direkt nach dem Anlegen des Elements.

//+------------------------------------------------------------------+
//| Erstzellen eines Ankreuzfelds mit Eingabefeld "Symbols filter"   |
//+------------------------------------------------------------------+
bool CProgram::CreateSymbolsFilter(const int x_gap,const int y_gap,const string text)
  {
//--- Sichern des Pointers auf das Hauptelement
   m_symb_filter.MainPointer(m_tabs1);
//--- Reserviert für den letzten Karteireiter
   m_tabs1.AddToElementsArray(0,m_symb_filter);
//--- Eigenschaften
   m_symb_filter.SetValue("USD"); // "EUR,USD" "EURUSD,GBPUSD" "EURUSD,GBPUSD,AUDUSD,NZDUSD,USDCHF"
   m_symb_filter.CheckBoxMode(true);
   m_symb_filter.AutoXResizeMode(true);
   m_symb_filter.AutoXResizeRightOffset(90);
   m_symb_filter.GetTextBoxPointer().XGap(100);
   m_symb_filter.GetTextBoxPointer().AutoXResizeMode(true);
   m_symb_filter.GetTextBoxPointer().AutoSelectionMode(true);
   m_symb_filter.GetTextBoxPointer().DefaultText("Example: EURUSD,GBP,NOK");
//--- Erstellen des Kontrollelements
   if(!m_symb_filter.CreateTextEdit(text,x_gap,y_gap))
      return(false);
//--- Aktivieren des Ankreuzfelds
   m_symb_filter.IsPressed(true);
//--- Hinzufügen eines Objekts zum gemeinsamen Array der Objektgruppen
   CWndContainer::AddToElementsArray(0,m_symb_filter);
   return(true);
  }

Zusätzlich zum Text des Eingabefelds gibt es ein numerisches in dem GUI. Zum Beispiel das Eingabefeld Lot (Volumen für Öffnungspositionen). Andere Eigenschaften dieses Typs sollten für Eingabefelder angegeben werden.

  • Gesamtbreite des Elements.
  • Maximaler einzugebender Wert.
  • Minimaler einzugebender Wert.
  • Schrittweite beim Umschalten mit den Tasten Inkrement und Dekrement.
  • Anzahl der Nachkommastellen.
  • Damit das Eingabefeld numerisch wird, sollten wir dies mit der Methode CTextEdit::SpinEditMode() spezifizieren.
  • Standardwert nach dem Laden des Programms auf dem Chart.
  • Eingabefeldbreite.
  • Automatische Texthervorhebung im Eingabefeld beim Anklicken.
  • Verankerung des Eingabefeldes am rechten Rand des Elements.

Hier ist der Code dieser Methode:

//+------------------------------------------------------------------+
//| Erstellen des Eingabefelds "Lot"                                 |
//+------------------------------------------------------------------+
bool CProgram::CreateLot(const int x_gap,const int y_gap,const string text)
  {
//--- Sichern des Pointers auf das Hauptelement
   m_lot.MainPointer(m_tabs1);
//--- Reserviert für den letzten Karteireiter
   m_tabs1.AddToElementsArray(0,m_lot);
//--- Eigenschaften
   m_lot.XSize(80);
   m_lot.MaxValue(1000);
   m_lot.MinValue(0.01);
   m_lot.StepValue(0.01);
   m_lot.SetDigits(2);
   m_lot.SpinEditMode(true);
   m_lot.SetValue((string)0.1);
   m_lot.GetTextBoxPointer().XSize(50);
   m_lot.GetTextBoxPointer().AutoSelectionMode(true);
   m_lot.GetTextBoxPointer().AnchorRightWindowSide(true);
//--- Erstellen des Kontrollelements
   if(!m_lot.CreateTextEdit(text,x_gap,y_gap))
      return(false);
//--- Hinzufügen eines Objekts zum gemeinsamen Array der Objektgruppen
   CWndContainer::AddToElementsArray(0,m_lot);
   return(true);
  }

Abb. 5. Ergänzen der Eingabefelder

Abb. 5. Ergänzen der Eingabefelder

Das Bild sieht nicht sehr logisch aus, aber wenn man andere Elemente hinzufügt, stellt sich heraus, dass alles an seinem Platz ist.

Tasten

Fügen wir dem GUI des EAs ein paar Tasten hinzu. Wir betrachten die mit den meisten Eigenschaften: die Taste zum Öffnen von VERKAUFSPOSITION.

  • Tastenbreite.
  • Der Text der Taste ist sowohl vertikal als auch horizontal exakt zentriert.
  • Hintergrundfarbe der Schaltfläche.
  • Hintergrundfarbe beim Bewegen des Cursors.
  • Hintergrundfarbe bei Linksklick.
  • Textfarbe der Schaltfläche.
  • Textfarbe beim Bewegen des Cursors.
  • Textfarbe bei Linksklick.
  • Farbe des Tastenrahmens.
  • Rahmenfarbe beim Bewegen des Cursors.
  • Rahmenfarbe bei Linksklick.

Die gleichen Eigenschaften werden für die Schaltfläche KAUFEN mit Ausnahme der angegebenen Hintergrundfarben geändert.

//+------------------------------------------------------------------+
//| Erstellen der Verkaufstaste                                      |
//+------------------------------------------------------------------+
bool CProgram::CreateSell(const int x_gap,const int y_gap,const string text)
  {
//--- Sichern des Pointers auf das Hauptelement
   m_sell.MainPointer(m_tabs1);
//--- Reserviert für den letzten Karteireiter
   m_tabs1.AddToElementsArray(0,m_sell);
//--- Eigenschaften
   m_sell.XSize(80);
   m_sell.IsCenterText(true);
   m_sell.BackColor(C'255,51,51');
   m_sell.BackColorHover(C'255,100,100');
   m_sell.BackColorPressed(C'195,0,0');
   m_sell.LabelColor(clrWhite);
   m_sell.LabelColorHover(clrWhite);
   m_sell.LabelColorPressed(clrWhite);
   m_sell.BorderColor(clrBlack);
   m_sell.BorderColorHover(clrBlack);
   m_sell.BorderColorPressed(clrBlack);
//--- Erstellen des Kontrollelements
   if(!m_sell.CreateButton(text,x_gap,y_gap))
      return(false);
//--- Hinzufügen des Element-Pointers auf die Datenbasis
   CWndContainer::AddToElementsArray(0,m_sell);
   return(true);
  }

Abb. 6. Ergänzen von Tasten

Abb. 6. Ergänzen von Tasten

Kombinationsfeld mit einer Auswahlliste

Um den Zeitrahmen zu ändern, erstellen wir ein Kombinationsfeld mit einer Auswahlliste. Wir definieren die Eigenschaften seiner Konfiguration.

  • Gesamtbreite des Elements. 
  • Anzahl der Listenelemente (in unserem Fall sind es 21, es ist die Anzahl der Zeitfenster des Terminals).
  • Das Element soll an den rechten Teil des Registerkartenbereichs gebunden werden.
  • Breite der Taste des Kombinationsfelds.
  • Die Taste wird an den rechten Teil des Elements gebunden.

Jedem Listenelement werden Werte zugewiesen, und einige Eigenschaften werden danach über den Zeiger für die Liste gesetzt.

  • Hervorheben von Elementen beim Bewegen des Mauszeigers.
  • Hervorgehobenes Element. In unserem Fall ist dies der Punkt mit dem Index 18 (Zeitrahmen D1).

Im Folgenden finden Sie den Code der Methode zur Erstellung des Kombinationsfelds:

//+------------------------------------------------------------------+
//| Erstellen eines Kombinationsfelds für die Zeitrahmen             |
//+------------------------------------------------------------------+
bool CProgram::CreateComboBoxTF(const int x_gap,const int y_gap,const string text)
  {
//--- Gesamtzahl der Elemente der Liste
#define ITEMS_TOTAL2 21
//--- Übergabe des Panel-Objektes
   m_timeframes.MainPointer(m_tabs1);
//--- Anker auf den Karteireiter
   m_tabs1.AddToElementsArray(0,m_timeframes);
//--- Eigenschaften
   m_timeframes.XSize(115);
   m_timeframes.ItemsTotal(ITEMS_TOTAL2);
   m_timeframes.AnchorRightWindowSide(true);
   m_timeframes.GetButtonPointer().XSize(50);
   m_timeframes.GetButtonPointer().AnchorRightWindowSide(true);
//--- Sichern der Werte des Elements in der Liste des Kombinationsfelds
   string items_text[ITEMS_TOTAL2]={"M1","M2","M3","M4","M5","M6","M10","M12","M15","M20","M30","H1","H2","H3","H4","H6","H8","H12","D1","W1","MN"};
   for(int i=0; i<ITEMS_TOTAL2; i++)
      m_timeframes.SetValue(i,items_text[i]);
//--- Abfrage des Pointers auf die Liste
   CListView *lv=m_timeframes.GetListViewPointer();
//--- Setzen der Eigenschaften der Liste
   lv.LightsHover(true);
   lv.SelectItem(18);
//--- Erstelle des Steuerelements
   if(!m_timeframes.CreateComboBox(text,x_gap,y_gap))
      return(false);
//--- Hinzufügen des Element-Pointers auf die Datenbasis
   CWndContainer::AddToElementsArray(0,m_timeframes);
   return(true);
  }

Abb. 7. Ergänzen des Kombinationsfelds

Abb. 7. Ergänzen des Kombinationsfelds

Kontrollkästchen

Ein Ankreuzfeld ist das einfachste Element. Es müssen nur zwei Eigenschaften angegeben werden.

  • Die Breite.
  • Lage des rechten Teils des Hauptelements.

Nach dem Erzeugen des Elements können wir das Ankreuzfeld programmtechnisch aktivieren.

//+------------------------------------------------------------------+
//| Erstellen des Ankreuzfelds "Date scale"                          |
//+------------------------------------------------------------------+
bool CProgram::CreateDateScale(const int x_gap,const int y_gap,const string text)
  {
//--- Sichern des Fensterpointers
   m_date_scale.MainPointer(m_tabs1);
//--- Reserviert für den letzten Karteireiter
   m_tabs1.AddToElementsArray(0,m_date_scale);
//--- Eigenschaften
   m_date_scale.XSize(70);
   m_date_scale.AnchorRightWindowSide(true);
//--- Erstellen des Kontrollelements
   if(!m_date_scale.CreateCheckBox(text,x_gap,y_gap))
      return(false);
//--- Aktivieren des Ankreuzfelds
   m_date_scale.IsPressed(true);
//--- Hinzufügen eines Objekts zum gemeinsamen Array der Objektgruppen
   CWndContainer::AddToElementsArray(0,m_date_scale);
   return(true);
  }

Abb. 8. Ergänzen des Ankreuzfelds

Abb. 8. Ergänzen des Ankreuzfelds

Tabelle

Das GUI soll zwei Tabellen erhalten. Betrachten wir diejenige, die die gebildete Liste von Symbolen und Signalen für Eröffnungspositionen enthält. Sie ist Teil des ersten Karteireiters. Deklarieren und initialisieren wir zunächst die Arrays für die Platzierung der Tabelleneigenschaften. Wir stellen die folgenden Eigenschaften ein.

  • Elementbreite.
  • Abmessungen der Tabelle (Anzahl der Spalten und Zeilen).
  • Spaltenbreite (Werte werden im Array übergeben).
  • Textausrichtung (Werte werden im Array übergeben).
  • Abstand des Textes von den Zellrändern.
  • Anzeige der Kopfzeile.
  • Möglichkeit, Zeilen zu markieren.
  • Möglichkeit der manuellen Größenanpassung von Spalten durch Ziehen im Kopfbereich.
  • Anzeige der Formatierung im Zebra-Stil.
  • Automatische Änderung der vertikalen Größe relativ zum Hauptelement.
  • Einrückung von der Unterkante des Hauptelements.

Die Texte der Überschriften sind nach dem Anlegen der Tabelle anzugeben:

//+------------------------------------------------------------------+
//| Erstellen der Symboltabelle                                      |
//+------------------------------------------------------------------+
bool CProgram::CreateSymbolsTable(const int x_gap,const int y_gap)
  {
#define COLUMNS1_TOTAL 2
#define ROWS1_TOTAL    1
//--- Sichern des Pointers auf das Hauptelement
   m_table_symb.MainPointer(m_tabs1);
//--- Reserviert für den letzten Karteireiter
   m_tabs1.AddToElementsArray(0,m_table_symb);
//--- Array der Spaltenbreite
   int width[COLUMNS1_TOTAL]={95,58};
//--- Array der Textausrichtung der Spalte
   ENUM_ALIGN_MODE align[COLUMNS1_TOTAL]={ALIGN_LEFT,ALIGN_RIGHT};
//--- Array der Textabstände der Spalten von X
   int text_x_offset[COLUMNS1_TOTAL]={5,5};
//--- Eigenschaften
   m_table_symb.XSize(168);
   m_table_symb.TableSize(COLUMNS1_TOTAL,ROWS1_TOTAL);
   m_table_symb.ColumnsWidth(width);
   m_table_symb.TextAlign(align);
   m_table_symb.TextXOffset(text_x_offset);
   m_table_symb.ShowHeaders(true);
   m_table_symb.SelectableRow(true);
   m_table_symb.ColumnResizeMode(true);
   m_table_symb.IsZebraFormatRows(clrWhiteSmoke);
   m_table_symb.AutoYResizeMode(true);
   m_table_symb.AutoYResizeBottomOffset(2);
//--- Erstellen des Kontrollelements
   if(!m_table_symb.CreateTable(x_gap,y_gap))
      return(false);
//--- Setzen der Namen der Kopfzeile
   m_table_symb.SetHeaderText(0,"Symbol");
   m_table_symb.SetHeaderText(1,"Values");
//--- Hinzufügen eines Objekts zum gemeinsamen Array der Objektgruppen
   CWndContainer::AddToElementsArray(0,m_table_symb);
   return(true);
  }

Die zweite Tabelle zeigt einige Eigenschaften der offenen Positionen. Zehn Spalten zeigen die folgenden Daten an.

  • Symbol der Position.
  • Anzahl der Positionen.
  • Gesamtvolumen aller offenen Positionen.
  • Volumen der KAUFPOSITIONEN.
  • Volumen der VERKAUFSPOSITIONEN.
  • Das aktuelle Gesamtergebnis aller offenen Positionen.
  • Das aktuelle Ergebnis aller offenen KAUFPOSITIONEN.
  • Das aktuelle Ergebnis aller offenen VERKAUFSPOSITIONEN.
  • Kontobelastung jedes einzelnen Symbols.
  • Medianpreis

Die folgenden Eigenschaften sollten zusätzlich in der zweiten Tabelle konfiguriert werden.

  • Bildabstände vom rechten und oberen Zellrand.
  • Fähigkeit, Werte zu sortieren.
  • Automatische Änderung der horizontalen Größe relativ zum Hauptelement.
  • Einrückung vom rechten Rand des Hauptelements.

Bilder in den Zellen der ersten Spalte symbolisieren die Taste, mit denen man eine Position oder alle schließen kann, wenn es sich um ein Hedge-Konto auf einem bestimmten Symbol handelt. 

//+------------------------------------------------------------------+
//| Erstellen der Positionentabelle                                  |
//+------------------------------------------------------------------+
bool CProgram::CreatePositionsTable(const int x_gap,const int y_gap)
  {
...
//--- Eigenschaften
   m_table_positions.TableSize(COLUMNS2_TOTAL,ROWS2_TOTAL);
   m_table_positions.ColumnsWidth(width);
   m_table_positions.TextAlign(align);
   m_table_positions.TextXOffset(text_x_offset);
   m_table_positions.ImageXOffset(image_x_offset);
   m_table_positions.ImageYOffset(image_y_offset);
   m_table_positions.ShowHeaders(true);
   m_table_positions.IsSortMode(true);
   m_table_positions.SelectableRow(true);
   m_table_positions.ColumnResizeMode(true);
   m_table_positions.IsZebraFormatRows(clrWhiteSmoke);
   m_table_positions.AutoXResizeMode(true);
   m_table_positions.AutoYResizeMode(true);
   m_table_positions.AutoXResizeRightOffset(2);
   m_table_positions.AutoYResizeBottomOffset(2);
...
   return(true);
  }

Abb. 9. Hinzufügen einer Tabelle zum ersten Karteireiter

Abb. 9. Hinzufügen einer Tabelle zum ersten Karteireiter

Abb. 10. Hinzufügen einer Tabelle zum zweitem Karteireiter

Abb. 10. Hinzufügen einer Tabelle zum zweitem Karteireiter

Details zum Arbeiten mit den Tabellen in der Hauptprogrammdatei (CProgram) sind in einem der folgenden Artikelabschnitte zu erläutert.

Standardchart

Das Element vom Typ CStandardChart dient zur Visualisierung von Daten durch Symbole. Standardmäßig wird EURUSD D1 angezeigt. Es zeichnet sich durch folgende Eigenschaften aus.

  • Horizontales Blättern.
  • Automatische Breitenanpassung.
  • Automatische Höhenanpassung.
  • Einrückung vom rechten Rand des Hauptelements.
  • Einrückung von der Unterkante des Hauptelements.

Bei Bedarf ist es möglich, ein Array von Charts in einer horizontalen Zeile zu erstellen. Wir verwenden dazu die Methode CStandardChart::AddSubChart(), indem wir das Symbol und den Zeitrahmen als Argumente übergeben. In diesem Fall benötigen wir jedoch ein einziges Chart, während Symbole und Zeitrahmen über andere Steuerelemente umgeschaltet werden.

//+------------------------------------------------------------------+
//| Erstellendes Standardcharts 1                                    |
//+------------------------------------------------------------------+
bool CProgram::CreateSubChart1(const int x_gap,const int y_gap)
  {
//--- Sichern des Pointers zum Fenster
   m_sub_chart1.MainPointer(m_tabs1);
//--- Reserviert für den ersten Karteireiter
   m_tabs1.AddToElementsArray(0,m_sub_chart1);
//--- Eigenschaften
   m_sub_chart1.XScrollMode(true);
   m_sub_chart1.AutoXResizeMode(true);
   m_sub_chart1.AutoYResizeMode(true);
   m_sub_chart1.AutoXResizeRightOffset(125);
   m_sub_chart1.AutoYResizeBottomOffset(2);
//--- Hinzufügen von Charts
   m_sub_chart1.AddSubChart("EURUSD",PERIOD_D1);
//--- Erstellen des Kontrollelements
   if(!m_sub_chart1.CreateStandardChart(x_gap,y_gap))
      return(false);
//--- Hinzufügen des Objekts in den allg. Array der Objektgruppen
   CWndContainer::AddToElementsArray(0,m_sub_chart1);
   return(true);
  }

Abb. 11. Hinzufügen eines Charts

Abb. 11. Hinzufügen eines Charts

Fortschrittsanzeige

Der Fortschrittsbalken ermöglicht es dem Benutzer zu verstehen, was das Programm jetzt macht. Also, fügen wir ihn dem GUI hinzu. Nachfolgend die Eigenschaften für unser Beispiel (in der gleichen Reihenfolge wie im Code).

  • Gesamthöhe des Elements.
  • Die Anzeigehöhe (Fortschrittsbalkenlinie).
  • Balkenabstand von X.
  • Balkenabstand von Y.
  • Abstand des Haupttextbezeichnung von X.
  • Abstand des Haupttextbezeichnung von Y.
  • Abstand der prozentualen Textbeschriftung von X.
  • Abstand der prozentualen Textbeschriftung von Y.
  • Anzeige eines Dropdown-Steuerelements (zum automatischen Ausblenden). 
  • Schriftart 
  • Rahmenfarbe des Indikators.
  • Hintergrundfarbe des Indikators.
  • Anzeige der Zeile des Fortschrittsbalkens.
  • Automatische Breitenanpassung.
  • Einrückung vom rechten Rand des Hauptelements.

Die Beispiele von Fortschrittsanzeigen sind unten aufgeführt:

//+------------------------------------------------------------------+
//| Erstellen der Fortschrittsanzeige                                |
//+------------------------------------------------------------------+
bool CProgram::CreateProgressBar(const int x_gap,const int y_gap,const string text)
  {
//--- Sichern des Pointers auf das Hauptelement
   m_progress_bar.MainPointer(m_status_bar);
//--- Eigenschaften
   m_progress_bar.YSize(17);
   m_progress_bar.BarYSize(14);
   m_progress_bar.BarXGap(0);
   m_progress_bar.BarYGap(1);
   m_progress_bar.LabelXGap(5);
   m_progress_bar.LabelYGap(2);
   m_progress_bar.PercentXGap(5);
   m_progress_bar.PercentYGap(2);
   m_progress_bar.IsDropdown(true);
   m_progress_bar.Font("Consolas");
   m_progress_bar.BorderColor(clrSilver);
   m_progress_bar.IndicatorBackColor(clrWhiteSmoke);
   m_progress_bar.IndicatorColor(clrLightGreen);
   m_progress_bar.AutoXResizeMode(true);
   m_progress_bar.AutoXResizeRightOffset(2);
//--- Erstellen des Elements
   if(!m_progress_bar.CreateProgressBar(text,x_gap,y_gap))
      return(false);
//--- Hinzufügen des Element-Pointers auf die Datenbasis
   CWndContainer::AddToElementsArray(0,m_progress_bar);
   return(true);
  }

Wir haben alle Steuerelemente beschrieben, die in unserem GUI des EAs verwendet werden sollen. Im Moment ist dies nur eine grafische Oberfläche. Im Weiteren werden wir alle notwendigen Methoden entwickeln, um die ursprünglichen Idee zu verwirklichen.

Aktualisierte Bibliothek EasyAndFast

In der Bibliothek EasyAndFast wurde die 'public' Methode CTable::SortData() in der CTable Klasse überarbeitet. Als zweites Argument können wir nun die Sortierrichtung der Tabelle (optionaler Parameter) angeben. Bisher hat der Aufruf der Methode CTable::SortData() die Sortierung in die entgegengesetzte Richtung gestartet. Außerdem wurden die Methoden zum Empfang von der aktuellen Sortierrichtung und dem sortierten Spaltenindex hinzugefügt. Wenn die Tabelle von einem Benutzer manuell sortiert wurde (durch Klicken auf einen Spaltenkopf) und die Daten in der Tabelle nicht in der gleichen Reihenfolge aktualisiert wurden, ist es möglich, sie wiederherzustellen, nachdem die aktuelle Sortierrichtung gefunden wurde. 

//+------------------------------------------------------------------+
//| Klasse zum Erstellen der zu zeichnenden Tabelle                  |
//+------------------------------------------------------------------+
class CTable : public CElement
  {
public:
...
   //--- Sortieren der Daten nach einer Spalte
   void              SortData(const uint column_index=0,const int direction=WRONG_VALUE);
   //--- (1) Aktuelle Sortierrichtung, (2) indes des Sortierarrays
   int               IsSortDirection(void)             const { return(m_last_sort_direction);    }
   int               IsSortedColumnIndex(void)         const { return(m_is_sorted_column_index); }
...
  };
//+------------------------------------------------------------------+
//| Daten entspr. der angegebenen Spalte sortieren                   |
//+------------------------------------------------------------------+
void CTable::SortData(const uint column_index=0,const int direction=WRONG_VALUE)
  {
//--- Exit wenn die Tabellengrenzen überschritten werden
   if(column_index>=m_columns_total)
      return;
//--- Index des Sortierens, von
   uint first_index=0;
//--- Letzter Index
   uint last_index=m_rows_total-1;
//--- Richtung ist nicht vom Nutzer bestimmt
   if(direction==WRONG_VALUE)
     {
      //--- Erstes Sortieren ist aufsteigend Danach wird in der Gegenrichtung sortiert
      if(m_is_sorted_column_index==WRONG_VALUE || column_index!=m_is_sorted_column_index || m_last_sort_direction==SORT_DESCEND)
         m_last_sort_direction=SORT_ASCEND;
      else
         m_last_sort_direction=SORT_DESCEND;
     }
   else
     {
      m_last_sort_direction=(ENUM_SORT_MODE)direction;
     }
//--- Sichern des Index der letzten sortierten Datenspalte
   m_is_sorted_column_index=(int)column_index;
//--- Sortieren
   QuickSort(first_index,last_index,column_index,m_last_sort_direction);
  }

Ein weiterer kleiner Zusatz wurde gemacht zur CKeysKlasse der CKeys::KeySymbol() Methode. Der Ziffernblock (ein separater Tastenblock auf der rechten Seite der Tastatur) wurde bisher nicht unterstützt. Jetzt können Sie auch Zahlen und Sonderzeichen aus diesem Bereich der Tastatur verwenden.

//+------------------------------------------------------------------+
//| Rückgabe des Symbols der gedrückten Taste                        |
//+------------------------------------------------------------------+
string CKeys::KeySymbol(const long key_code)
  {
   string key_symbol="";
//--- Falls ein Leerzeichen benötigt wird
   if(key_code==KEY_SPACE)
     {
      key_symbol=" ";
     }
//--- Wenn (1) ein Buchstabe, (2) eine Zahl oder (3) ein spezielles Zeichen benötigt wird
   else if((key_code>=KEY_A && key_code<=KEY_Z) ||
           (key_code>=KEY_0 && key_code<=KEY_9) ||
           (key_code>=KEY_NUMLOCK_0 && key_code<=KEY_NUMLOCK_SLASH) ||
           (key_code>=KEY_SEMICOLON && key_code<=KEY_SINGLE_QUOTE))
     {
      key_symbol=::ShortToString(::TranslateKey((int)key_code));
     }
//--- Rückgabe eines Symbols
   return(key_symbol);
  }

Neue Versionen der Klassen CTable und CKeys können am Ende des Artikels heruntergeladen werden.

Schlussfolgerung

Dies war der erste Teil des Artikels. Wir haben diskutiert, wie man GUIs für Programme beliebiger Komplexität ohne großen Aufwand entwickelt. Sie können dieses Programm weiter entwickeln und für Ihre eigenen Zwecke nutzen. Im zweiten Teil des Artikels werde ich zeigen, wie man mit dem GUI arbeitet, und vor allem - wie man es mit Funktionalität füllt. 

Nachfolgend können Sie die Dateien zum Testen und detaillierten Studium des im Artikel enthaltenen Codes herunterladen.

Dateiname Kommentar
Nachfolgend können die Dateien zum Testen und detaillierten Studium des im Artikel enthaltenen Codes heruntergeladen werden. Der EA für eine manuelles Handeln mit dem GUI
MQL5\Experts\TradePanel\Program.mqh Datei mit den Klassen des Programms
MQL5\Experts\TradePanel\CreateGUI.mqh Datei mit den implementierte Methoden für die Entwicklung des GUI aus der Programmklasse aus Program.mqh
MQL5\Include\EasyAndFastGUI\Controls\Table.mqh Aktualisierte Klasse CTable
MQL5\Include\EasyAndFastGUI\Keys.mqh Aktualisierte Klasse CKeys


Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/4715

Beigefügte Dateien |
MQL5.zip (48 KB)
Mit der Monte-Carlo-Methode Handelsstrategien optimieren Mit der Monte-Carlo-Methode Handelsstrategien optimieren
Bevor wir einen Roboter auf einem Handelskonto starten, testen und optimieren wir ihn in der Regel anhand der Kurshistorie. Es stellt sich jedoch die berechtigte Frage: Wie können uns die Ergebnisse der Vergangenheit in Zukunft helfen? Der Artikel beschreibt die Anwendung der Monte-Carlo-Methode, um benutzerdefinierte Kriterien für die Optimierung der Handelsstrategie zu erstellen. Zusätzlich werden die EA-Stabilitätskriterien berücksichtigt.
Panels verbessern: Transparenz hinzufügen, Hintergrundfarbe ändern und von CAppDialog/CWndClient übernehmen Panels verbessern: Transparenz hinzufügen, Hintergrundfarbe ändern und von CAppDialog/CWndClient übernehmen
In diesem Artikel beschäftigen wir uns weiter mit dem Einsatz von CAppDialog. Hier lernen wir, wie man die Farbe für den Hintergrund, die Ränder und die Überschrift der Dialogbox einstellt. Außerdem wird in diesem Artikel Schritt für Schritt beschrieben, wie ein Anwendungsfenster beim Ziehen innerhalb des Diagramms transparent gemacht werden kann. Wir werden überlegen, wie man Unterklassen von CAppDialog oder CWndClient erstellt und neue Besonderheiten bei der Arbeit mit Steuerelementen analysiert. Schließlich werden wir neue Projekte aus einer neuen Perspektive betrachten.
Wie man Trades des ausgewählten Signals im Chart analysiert Wie man Trades des ausgewählten Signals im Chart analysiert
Der Signale-Service entwickelt sich mit Riesenschritten. Wenn man eigenes Geld einem Signalanbieter anvertraut, möchte man das Verlustrisiko minimieren. Wie kommt man in diesem Wald von Handelssignalen zurecht? Wie findet man ein profitables Signal? In diesem Artikel wird vorgeschlagen, ein Tool für die visuelle Analyse der Handelshistorie von Signalen auf dem Chart eines Finanzinstruments zu erstellen.
Tiefe Neuronale Netzwerke (Teil VI). Gruppen von Klassifikatoren von Neuronalen Netzen: Bagging Tiefe Neuronale Netzwerke (Teil VI). Gruppen von Klassifikatoren von Neuronalen Netzen: Bagging
Der Artikel beschreibt die Methoden des Aufbaus und Trainings von Gruppen von Neuronalen Netzen mit einer Struktur für das Bagging, einer Methode, um Vorhersagen aus verschiedenen Regressions- oder Klassifikationsmodellen zu kombinieren. Es bestimmt auch die Besonderheiten der Hyperparameter-Optimierung für einzelne Neuronale Netzwerk-Klassifikatoren, aus denen sich das Ensemble zusammensetzt. Die Qualität des optimierten Neuronalen Netzes, das im vorherigen Artikel der Serie erhalten wurde, wird mit der Qualität des erzeugten Ensembles Neuronaler Netze verglichen. Möglichkeiten, die Qualität der Klassifizierung des Ensembles weiter zu verbessern, werden geprüft.