English Русский 中文 Español 日本語 Português
Grafische Interfaces XI: Integration der graphischen Standardbibliothek (build 16)

Grafische Interfaces XI: Integration der graphischen Standardbibliothek (build 16)

MetaTrader 5Beispiele | 23 Oktober 2017, 09:41
863 7
Anatoli Kazharski
Anatoli Kazharski

Inhalt


Einführung

Der erste Artikel Grafische Interfaces I: Vorbereitung der Bibliotheksstruktur (Kapitel 1) erklärt detailliert, wofür die Bibliothek gedacht ist. Sie finden eine Liste von Artikeln mit Verweisen am Ende jeden Kapitels. Dort können Sie auch die komplette, aktuelle Version der Bibliothek zum derzeitigen Entwicklungsstand herunterladen. Die Dateien müssen in die gleichen Verzeichnisse wie im beigefügten Archiv kopiert werden.

Das zweite Kapitel des neunten Teils der Serie, Grafische Interfaces IX: Die Fortschrittsanzeige und das Linienchart-Control (Kapitel 2), zeigte an einem Beispiel, wie eine Klasse zur Erstellung von Liniendiagrammen in die Bibliothek integriert werden kann. Das war eine vorübergehende Lösung, da die Fähigkeiten dieses Teils der Bibliothek sehr mangelhaft waren. Eine neue Version der Grafikbibliothek zur Erstellung wissenschaftlicher Diagramme (die Klasse CGraphic) wurde kürzlich vorgestellt. Einige Funktionen dieser Klasse wurden in Visualisierung! Eine grafische MQL5 Bibliothek ähnlich 'plot' der Sprache R beschrieben. Mit dieser Aktualisierung der weiterentwickelten Bibliothek, um grafische Interfaces zu erstellen, wird eine Version mit neuem Steuerelemente zur Erstellung von Diagrammen eingeführt. Jetzt ist es noch einfacher, Daten verschiedener Typen zu visualisieren.


Veränderungen im Schema der Bibliothek

Früher verwendete die entwickelte Bibliothek zum Zeichnen eine Kopie der Klasse CCanvas. Aufgrund der kürzlich erfolgten globalen Überarbeitung des Bibliothekscodes wird diese Kopie nicht mehr benötigt und kann durch die Originalversion aus der Standardbibliothek ersetzt werden. Dies reduzierte den Umfang der Bibliothek um etwa 10% und um fast 40% gegenüber der vor der Überarbeitungen in den Artikeln Graphische Interfaces XI: Überarbeitung des Bibliothekscodes (build 14.1) und Graphisches Interface XI: Gezeichnete Steuerelemente (build 14.2).

Die Klasse CGraphic wird nun zum Erstellen von Diagrammen verwendet, daher sollte die Datei Graphic.mqh in die Datei Objects.mqh geladen werden. Da die Datei mit der Klasse CCanvas bereits in einer der in der Datei Graphic.mqh enthaltenen Dateien enthalten ist, steht sie somit der gesamten Bibliothek zur Verfügung.

//+------------------------------------------------------------------+
//|                                                      Objects.mqh |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include "Enums.mqh"
#include "Defines.mqh"
#include "Fonts.mqh"
#include "Colors.mqh"
#include <Graphics\Graphic.mqh>
#include <ChartObjects\ChartObjectSubChart.mqh>
...

Die Klasse CLineChart wurde in CGraph umbenannt, deren Inhalt auch überarbeitet wurde. Diese Klasse enthält nun nur noch die Methoden zur Verwaltung der allgemeinen Eigenschaften und Zustände des Steuerelements.  

class CGraph : public CElement
  {
public:
   //--- Handler der Chartereignisse
   virtual void      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
   //--- Verschieben des Steuerelementes
   virtual void      Moving(const bool only_visible=true);
   //--- Management
   virtual void      Show(void);
   virtual void      Hide(void);
   virtual void      Reset(void);
   virtual void      Delete(void);
   //--- Anwenden der letzten Änderungen
   virtual void      Update(const bool redraw=false);
   //---
private:
   //--- Größenänderung
   void              Resize(const int width,const int height);
   //--- Ändern der Breite mit dem rechten Rand des Fensters
   virtual void      ChangeWidthByRightWindowSide(void);
   //--- Ändern der Höhe mit dem unteren Rand des Fensters
   virtual void      ChangeHeightByBottomWindowSide(void);
  };

Die Eigenschaften des Diagramms können mit der Methode CGraphic::GetGraphicPointer() verwaltet werden, um den Pointer auf eine Instanz der Klasse CGraphic zu erhalten:

class CGraph : public CElement
  {
private:
   //--- Objekte zum Erstellen des Steuerelementes
   CGraphic          m_graph;
   //---
public:
   //--- Rückgabe des Pointers zum Chart
   CGraphic         *GetGraphicPointer(void) { return(::GetPointer(m_graph)); }
  };

Zusätzliche Klassen wurden in die Klasse CGraphic geladen, um die Eigenschaften der Achsen (CAxis) und Kurven (CCurve) des Diagramms zu handhaben. Die Klasse CColorGenerator dient zur Erzeugung der Kurvenfarben. Alle diese Klassen sind in separaten Dateien, die von der Datei Graphic.mqh geladen werden:

//+------------------------------------------------------------------+
//|                                                      Graphic.mqh |
//|                   Copyright 2016-2017, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Arrays\ArrayObj.mqh>
#include "Curve.mqh"
#include "Axis.mqh"
#include "ColorGenerator.mqh"
...

Die Datei mit der Klasse CCanvas wird in der Datei Curve.mqh geladen, und steht daher danach der ganzen Bibliothek zur Verfügung.

//+------------------------------------------------------------------+
//|                                                        Curve.mqh |
//|                   Copyright 2016-2017, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Object.mqh>
#include <Canvas\Canvas.mqh>
...

Alle oben erwähnten Beziehung zwischen den Dateien und den Klassen zeigt das Bild unten:

 Abb. 1. Die Beziehungen zwischen der standardmäßigen und der weiterentwickelten Bibliothek der Klassen.

Abb. 1. Die Beziehungen zwischen der standardmäßigen und der weiterentwickelten Bibliothek der Klassen.


Damit stehen die Klassen der Standardbibliothek für das Arbeiten mit Arrays und Dateien automatisch für die Bibliothek und Dateien der Anwendung, in der sie verwendet werden, zur Verfügung. Einige Testanwendungen in MQL werden in dem Artikel weiter unten vorgestellt, um zu verstehen, welche neuen Funktionen nun verfügbar sind.


Testanwendung für die Eigenschaften von Diagrammen

Die erste Testanwendung in MQL wird eine grafische Benutzeroberfläche mit Steuerelementen für die Verwaltung bestimmter Eigenschaften eines Diagramms des Typs CGraphic implementieren. Am oberen Rand des Formulars befindet sich eine Steuerung vom Typ CTabs. In diesem Fall handelt es sich um eine Gruppe von vier Karteireiter. Im Arbeitsbereich der Karteireiter befindet sich ein Diagramm mit zwei Kurven mit zufällig generierten Werten.

Hinter der ersten Karteireiter (Hintergrund) befinden sich die Steuerelemente zur Verwaltung der folgenden Diagrammeigenschaften:

  • Hintergrundfarbe.
  • Haupttext des Diagramms (oben).
  • Hilfstext des Diagramms (unten).
  • Farbe des Haupttextes.
  • Farbe des Hilfstextes.
  • Schriftgröße des Haupttextes.
  • Schriftgröße des Hilfstextes.

Um diese Eigenschaften festzulegen und abzurufen, stellt die Klasse CGraphic die entsprechenden 'public' Methoden zur Verfügung:

//+------------------------------------------------------------------+
//| Structure CBackground                                            |
//| Verwendung: Hintergrund der zweidimensionalen Grafik             |
//+------------------------------------------------------------------+
struct CBackground
  {
   uint              clr;
   uint              clr_main;
   uint              clr_sub;
   string            main;
   string            sub;
   int               size_main;
   int               size_sub;
  };
//+------------------------------------------------------------------+
//| Class CGraphic                                                   |
//| Verwendung: Klasse für zweidimensionale Grafiken                 |
//+------------------------------------------------------------------+
class CGraphic
  {
protected:
   //--- Elemente der Grafik
   CBackground       m_background;           // background
   //---
public:
   //--- Abfragen der Eigenschaften des Hintergrundes
   uint              BackgroundColor(void)       const { return(m_background.clr);       }
   uint              BackgroundMainColor(void)   const { return(m_background.clr_main);  }
   uint              BackgroundSubColor(void)    const { return(m_background.clr_sub);   }
   string            BackgroundMain(void)        const { return(m_background.main);      }
   string            BackgroundSub(void)         const { return(m_background.sub);       }
   int               BackgroundMainSize(void)    const { return(m_background.size_main); }
   int               BackgroundSubSize(void)     const { return(m_background.size_sub);  }
   //--- Festlegen der Eigenschaften des Hintergrund
   void              BackgroundColor(const uint clr)      { m_background.clr=clr;        }
   void              BackgroundMainColor(const uint clr)  { m_background.clr_main=clr;   }
   void              BackgroundSubColor(const uint clr)   { m_background.clr_sub=clr;    }
   void              BackgroundMain(const string main)    { m_background.main=main;      }
   void              BackgroundSub(const string sub)      { m_background.sub=sub;        }
   void              BackgroundMainSize(const int size)   { m_background.size_main=size; }
   void              BackgroundSubSize(const int size)    { m_background.size_sub=size;  }
  };

Und so sieht das Ganze aus:

 Abb. 2. Steuerelemente des ersten Karteireiters (Background) der Testanwendung in MQL.

Abb. 2. Steuerelemente des ersten Karteireiters (Background) der Testanwendung in MQL.


Die zweite Karteireiter (Indents & history) enthält die Steuerelemente zur Einstellung der folgenden Eigenschaften:

  • Einzüge (links, rechts, oben, unten).
  • Breite der Legende.
  • Schriftgröße der Legende.
  • Größe des Markers der Legende.
  • Allgemeine Einzüge für alle Elemente des Diagramms.
  • Größe des Markers des Skalierung der Achsen. 

Die in der folgenden Auflistung aufgeführten Methoden von CGraphic können für die Ermittlung und Einstellung dieser Eigenschaften verwendet werden:

//+------------------------------------------------------------------+
//| Structure CCurveHistory                                          |
//| Verwendung: Historie der Kurven einer zweidimensionalen Grafik   |
//+------------------------------------------------------------------+
struct CCurveHistory
  {
   int               name_width;
   int               name_size;
   int               symbol_size;
   int               count_total;
   int               count_points;
   int               count_lines;
   int               count_histogram;
   int               count_custom;
  };
//+------------------------------------------------------------------+
//| Class CGraphic                                                   |
//| Verwendung: Klasse zum Zeichen zweidimensionaler Grafiken        |
//+------------------------------------------------------------------+
class CGraphic
  {
protected:
   //--- Elemente der Grafik
   CCurveHistory     m_history;              // Historie
   //---
public:
   //--- Abfragen oder Festlegen der Einzüge
   int               IndentUp(void)               const { return(m_up0);     }
   void              IndentUp(const int up)             { m_up0=up;          }
   int               IndentDown(void)             const { return(m_down0);   }
   void              IndentDown(const int down)         { m_down0=down;      }
   int               IndentLeft(void)             const { return(m_left0);   }
   void              IndentLeft(const int left)         { m_left0=left;      }
   int               IndentRight(void)            const { return(m_right0);  }
   void              IndentRight(const int right)       { m_right0=right;    }
   //--- Abfragen oder Festlegen des Abstands
   int               GapSize(void)           const { return(m_gap); }
   void              GapSize(const int size)       { m_gap=size;    }
   //--- Abfragen oder Festlegen der Größe des Hauptmarkers
   int               MajorMarkSize(void)           const { return(m_mark_size); }
   void              MajorMarkSize(const int size)       { m_mark_size=size;    }
   //--- Abfragen der Eigenschaften der Historie der Kurve
   int               HistoryNameWidth(void)            const { return(m_history.name_width);  }
   int               HistoryNameSize(void)             const { return(m_history.name_size);   }
   int               HistorySymbolSize(void)           const { return(m_history.symbol_size); }
   //--- Festlegen der Eigenschaften der Historie der Kurve
   void              HistoryNameWidth(const int width) { m_history.name_width=width; }
   void              HistoryNameSize(const int size)   { m_history.name_size=size;   }
   void              HistorySymbolSize(const int size) { m_history.symbol_size=size; }
  };

Und so schaut jetzt das Grafische Interface der Testanwendung für MQL aus:

 Abb. 3. Steuerelement des zweiten Karteireiters (Indents & history) der Testanwendung in MQL.

Abb. 3. Steuerelement des zweiten Karteireiters (Indents & history) der Testanwendung in MQL.


Der dritte Karteireiter (Grid) verfügt über die Steuerelemente der unten aufgeführten Eigenschaften des Rasters:

  • Farbe der Rasterlinien.
  • Farbe der Nulllinie.
  • Farbe des Hintergrunds des Rasters.
  • Zeichnung von Punkten in den Rasterknoten
  • Radius der Punkte.
  • Farbe der Punkte.

Die entsprechenden Methoden sind in der Klasse CGraphic vorhanden, um diese Eigenschaften abzufragen und festzulegen (siehe den Code unten):

//+------------------------------------------------------------------+
//| Structure CGrid                                                  |
//| Verwendung: Raster einer zweidimensionalen Grafik              |
//+------------------------------------------------------------------+
struct CGrid
  {
   uint              clr_line;
   uint              clr_background;
   uint              clr_circle;
   uint              clr_axis_line;
   uint              clr_frame;
   int               r_circle;
   bool              has_circle;
  };
//+------------------------------------------------------------------+
//| Class CGraphic                                                   |
//| Verwendung: Klasse zum Zeichnen einer zweidimensionalen Grafik   |
//+------------------------------------------------------------------+
class CGraphic
  {
protected:
   //--- Elemente der Grafik
   CGrid             m_grid;                 // grid
   //---
public:
   //--- Abfrage der Eigenschaften des Rasters
   uint              GridLineColor(void)        const { return(m_grid.clr_line);       }
   uint              GridAxisLineColor(void)    const { return(m_grid.clr_axis_line);  }
   uint              GridBackgroundColor(void)  const { return(m_grid.clr_background); }
   int               GridCircleRadius(void)     const { return(m_grid.r_circle);       }
   uint              GridCircleColor(void)      const { return(m_grid.clr_circle);     }
   bool              GridHasCircle(void)        const { return(m_grid.has_circle);     }
   //--- Festlegen der Eigenschaften des Rasters
   void              GridLineColor(const uint clr)        { m_grid.clr_line=clr;       }
   void              GridAxisLineColor(const uint clr)    { m_grid.clr_axis_line=clr;  }
   void              GridBackgroundColor(const uint clr)  { m_grid.clr_background=clr; }
   void              GridCircleRadius(const int r)        { m_grid.r_circle=r;         }
   void              GridCircleColor(const uint clr)      { m_grid.clr_circle=clr;     }
   void              GridHasCircle(const bool has)        { m_grid.has_circle=has;     }
  };

Und so schaut es dann aus:

 Abb. 4. Steuerelemente des dritten Karteireiters (Grid) der Testanwendung in MQL.

Abb. 4. Steuerelemente des dritten Karteireiters (Grid) der Testanwendung in MQL.


Die Steuerelemente zur Verwaltung der Eigenschaften von Diagrammachsen sind über den vierten Karteireiter (Axes) erreichbar. Die Optionstasten im linken Teil des Arbeitsbereichs der Karteireiter ermöglichen das Umschalten zwischen den Konfiguration einer bestimmten Achse. Diese Tasten sind durch eine Trennlinie von den anderen Elementen des Karteireiter Axes getrennt.

Hier sind die veränderbaren Eigenschaften:

  • Automatische Skalierung.
  • Minimaler Achsenwert.
  • Maximaler Achsenwert.
  • Toleranzwert für das Achsenminimum.
  • Toleranzwert für das Achsenmaximum.
  • Größe der Zahlen der Achsen.
  • Maximal angezeigte Länge der Zahlen der Achsen.
  • Schriftgröße der Achsennamen.
  • Anfangsschrittweite für die Achse.
  • Maximale Anzahl von Zahlen auf der Achse.
  • Achsenname.
  • Textfarbe des Achsennamnes.

Die folgende Auflistung zeigt die Namen der Methoden der Klasse CAxis zur Abfrage und Festlegen der oben genannten Eigenschaften:

//+------------------------------------------------------------------+
//| Class CAxis                                                      |
//| Verwendung: Klasse zum Erstellen der Achsen einer zweidim. Grafik|
//+------------------------------------------------------------------+
class CAxis
  {
private:
   double            m_min;
   double            m_max;
   uint              m_clr;
   string            m_name;
   int               m_name_size;
   int               m_values_size;
   int               m_values_width;
   bool              m_auto_scale;
   double            m_default_step;   // Standardschrittweite
   double            m_max_labels;     // Maximalzahl der Marker
   double            m_min_grace;      // "grace" Wert für den die minimalen Datenbereich
   double            m_max_grace;      // "grace" Wert für den die maximalen Datenbereich
   //---
public:
                     CAxis(void);
                    ~CAxis(void);
   //--- Eigenschaften
   double            Min(void)                  const { return(m_min);  }
   void              Min(const double min)            { m_min=min;      }
   double            Max(void)                  const { return(m_max);  }
   void              Max(const double max)            { m_max=max;      }
   string            Name(void)                 const { return(m_name); }
   void              Name(const string name)          { m_name=name;    }
   //--- Standardeigenschaften
   uint              Color(void)                        const { return(m_clr);            }
   void              Color(const uint clr)                    { m_clr=clr;                }
   bool              AutoScale(void)                    const { return(m_auto_scale);     }
   void              AutoScale(const bool auto)               { m_auto_scale=auto;        }
   int               ValuesSize(void)                   const { return(m_values_size);    }
   void              ValuesSize(const int size)               { m_values_size=size;       }
   int               ValuesWidth(void)                  const { return(m_values_width);   }
   void              ValuesWidth(const int width)             { m_values_width=width;     }
   int               NameSize(void)                     const { return(m_name_size);      }
   void              NameSize(const int size)                 { m_name_size=size;         }
   double            DefaultStep(void)                  const { return(m_default_step);   }
   void              DefaultStep(const double value)          { m_default_step=value;     }
   double            MaxLabels(void)                    const { return(m_max_labels);     }
   void              MaxLabels(const double value)            { m_max_labels=value;       }
   double            MinGrace(void)                     const { return(m_min_grace);      }
   void              MinGrace(const double value)             { m_min_grace=value;        }
   double            MaxGrace(void)                     const { return(m_max_grace);      }
   void              MaxGrace(const double value)             { m_max_grace=value;        }
  };

Das Ergebnis ist unten dargestellt:

 Abb. 5. Steuerelemente des vierten Karteireiters (Axes) der Testanwendung in MQL.

Abb. 5. Steuerelemente des vierten Karteireiters (Axes) der Testanwendung in MQL.


Die Testanwendung dieses Artikels kann mittels des Links unten heruntergeladen werden, für ein weiteres Studium.


Testanwendung für die Eigenschaften der Darstellung von Kurven

Eine eigene MQL-Anwendung wurde geschrieben, um bestimmte Eigenschaften von Kurven auf einem Diagramm des Typs CGraphic zu testen. Steuerelemente für die Verwaltung der Eigenschaften für das Zeichnen von Kurven befinden sich am oberen Rand des Formulars dieser Anwendung, darunter befinden sich zwei Diagramme des Typs CGraphic (das Steuerelement CGraph). Das erste Diagramm zeigt eine Reihe zufälliger Daten, das zweite die Ableitungen, die anhand der Formel des Momentum-Indikators berechnet werden.

Hier sind die Steuerelemente zum Verwalten der Eigenschaften um Kurven zu zeichnen:

  • Animate Ankreuzkästchen - Starten der automatische Dateneingabe in das Diagramm.
  • Array size Spin-Bearbeitungsfeld – Die aktuelle Anzahl der Elemente im Datenarray, die auf dem Chart angezeigt werden.
  • Random Taste – Erzeugen einer zufällige Datenabfolge auf dem Chart.
  • Period Spin-Bearbeitungsfeld – Wert der Variablen für die Berechnung des Indikators Momentum.
  • Curve type Kombinationsfeld – Kurventyp auf dem Diagramm.
  • Point type Kombinationsfeld – Typ der Datenpunkte zum Zeichnen der Kurve.

Die nutzerdefinierte Klasse der Anwendung (CProgram) implementiert Methoden, die sich auf die oben genannten Steuerelemente beziehen und die folgenden Aufgaben ausführen:

  • Festlegen der darzustellenden Arraygröße.
  • Initialisieren des Arrays mit Daten.
  • Aktualisieren des Diagramms mit den letzten Änderungen.
  • Hinzufügen einen Elementes am Ende des Arrays.
  • Löschen eines Elements vom Ende des Arrays.
  • Zeit gesteuertes aktualisieren des Diagramms.
  • Animierte Diagramme mit automatischem Eingang neuer Daten.

Nachfolgend ist der Code für alle Methoden angeführt, die diese Funktionen implementieren. Laden Sie die Dateien am Ende des Artikels herunter, wenn Sie mehr Details über den Code dieser Methoden wissen wollen.

class CProgram : public CWndEvents
  {
protected:
   //--- Array der Daten zur Ausgabe auf den Chart
   double            data1[];
   double            data2[];
   //---
   double            data3[];
   double            data4[];
   //---
private:
   //--- Größenänderung des Arrays
   void              ResizeGraph1Arrays(void);
   void              ResizeGraph2Arrays(void);
   void              ResizeGraph1Arrays(const int new_size);
   void              ResizeGraph2Arrays(const int new_size);
   //--- Initialisierung des Arrays
   void              InitGraph1Arrays(void);
   void              InitGraph2Arrays(void);
   //--- Arrays auf Null setzten
   void              ZeroGraph1Arrays(void);
   void              ZeroGraph2Arrays(void);
   //--- Setzen von Zufallswerte am angegebenen Index
   void              SetGraph1Value(const int index);
   void              SetGraph2Value(const int index);
   //--- Aktualisieren der Werte auf dem Chart
   void              UpdateGraph(void);
   void              UpdateGraph1(void);
   void              UpdateGraph2(void);
   
   //--- Neuberechnen der Werte für den Chart
   void              RecalculatingSeries(void);
   //--- Hinzufügen eines neuen Wertes am Ende des Arrays
   void              AddValue(void);
   //--- Entfernen des Wertes am Ende des Arrays
   void              DeleteValue(void);

   //--- Aktualisieren des Charts durch den Timer
   void              UpdateGraphByTimer(void);
   //--- Animieren der Werte des Charts
   void              AnimateGraphSeries(void);
  };

Hier ist, wie es aussieht:

 Abb. 6. Grafisches Interface der Testanwendung zum Zeichnen von Kurven.

Abb. 6. Grafisches Interface der Testanwendung zum Zeichnen von Kurven.


Die Testanwendung dieses Artikels kann mittels des Links unten heruntergeladen werden, für ein weiteres Studium.


Testanwendung für die Eigenschaften der Darstellung animierter Hypozykloide

In einem seiner Bücher über VBA-Programmierung in Microsoft Excel stellt John Walkenbach dem Leser eine CD mit Testdateien zur Verfügung. Eine der Dateien implementiert ein Diagramm, in dem eine unendliche Anzahl von Hypozykloiden erzeugt wird. 

Als Referenz: Wikipedia gibt folgende Definition an

Ein Hypozykloid (griechisch ὑπό — unten, unter und κύκλος — Kreis, Kreisumfang) ist eine spezielle, ebene Kurve, die durch die Bewegung eines Mittelpunktes eines kleinen Kreis, der auf größeren Kreises rollt, erzeugt wird.

Die Definition von John Walkenbach aus seinem Buch:

Hypozykloid - die Bahn, die durch einen Punkt auf einem Kreis gebildet wird, der sich innerhalb eines anderen Kreises rollt.

Wir implementieren eine ähnliche Anwendung in MQL und fügen ein grafisches Interface der Verwaltung der Parameter hinzu. Lassen Sie uns im Detail sehen, wie es funktioniert.

Aus drei Parametern wird ein neues Hypozykloid erzeugt, mit dem die numerischen Sequenzen mit dem angegebenen Schritt initialisiert werden. Dann werden Berechnungen auf der Grundlage der Werte in diesen Sequenzen durchgeführt, um die Koordinaten der Punkte auf dem Diagramm zu erhalten. Danach werden die erhaltenen Ergebnisse normalisiert.

In der nutzerdefinierten Klasse deklarieren wir mehrere Arrays, um die Sequenzen und Felder zur Berechnung des Mittelwerts und der Standardabweichung zu berechnen.

//+------------------------------------------------------------------+
//|                                                      Program.mqh |
//|                        Copyright 2017, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Math\Stat\Stat.mqh>
#include <EasyAndFastGUI\WndEvents.mqh>
#include <EasyAndFastGUI\TimeCounter.mqh>
//+------------------------------------------------------------------+
//| Klassen zum Erstellen der Anwendung                              |
//+------------------------------------------------------------------+
class CProgram : public CWndEvents
  {
protected:
...
   //--- Array der Daten der Berechnung
   double            a_inc[];
   double            b_inc[];
   double            t_inc[];
   double            x_source[];
   double            y_source[];
   //--- Array der Daten zur Ausgabe auf dem Chart
   double            x_norm[];
   double            y_norm[];
   //--- Berechnen von Mittelwert und Standardabweichung
   double            x_mean;
   double            y_mean;
   double            x_sdev;
   double            y_sdev;
...
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CProgram::CProgram(void) : x_mean(0),
                           y_mean(0),
                           x_sdev(0),
                           y_sdev(0)
  {
...
  }

Die Werte werden in der Methode CProgram::InitArrays() berechnet. Der erste Zyklus berechnet hier die Ausgangsdaten. Danach werden Mittelwert und Standardabweichung ermittelt und der zweite Zyklus normalisiert die Daten. Die Größen der Arrays werden mit der Methode CProgram::ResizeArrays() festgelegt. Die Werte für die Größen des Arrays werden aus dem Textfeld des Steuerelementes (CTextEdit) des grafischen Interfaces der Anwendung übernommen.

class CProgram : public CWndEvents
  {
private:
   //--- Größenänderung des Arrays
   void              ResizeArrays(void);
   //--- Initialisieren des Hilfsarrays zur Berechnung
   void              InitArrays(void);
  };
//+------------------------------------------------------------------+
//| Größenänderung des Arrays                                        |
//+------------------------------------------------------------------+
void CProgram::ResizeArrays(void)
  {
   int array_size =::ArraySize(x_norm);
   int new_size   =(int)m_array_size.GetValue();
//--- Verlassen, wenn keine Größenänderung
   if(array_size==new_size)
      return;
//--- Festlegen der neuen Größe
   ::ArrayResize(a_inc,new_size);
   ::ArrayResize(b_inc,new_size);
   ::ArrayResize(t_inc,new_size);
   ::ArrayResize(x_source,new_size);
   ::ArrayResize(y_source,new_size);
   ::ArrayResize(x_norm,new_size);
   ::ArrayResize(y_norm,new_size);
  }
//+------------------------------------------------------------------+
//| Initialisierung der Arrays                                       |
//+------------------------------------------------------------------+
void CProgram::InitArrays(void)
  {
//--- Größenänderung der Arrays
   ResizeArrays();
//--- Berechnen der Werte mit der Formel
   int total=(int)m_array_size.GetValue();
   for(int i=0; i<total; i++)
     {
      if(i<1)
        {
         a_inc[i] =1+(double)m_animate.GetValue();
         b_inc[i] =1+(double)m_animate.GetValue();
         t_inc[i] =1+(double)m_animate.GetValue();
        }
      else
        {
         a_inc[i] =a_inc[i-1]+(double)m_a_inc.GetValue();
         b_inc[i] =b_inc[i-1]+(double)m_b_inc.GetValue();
         t_inc[i] =t_inc[i-1]+(double)m_t_inc.GetValue();
        }
      //---
      double a=a_inc[i];
      double b=b_inc[i];
      double t=t_inc[i];
      //---
      x_source[i] =(a-b)*cos(t)+b*cos((a/b-1)*t);
      y_source[i] =(a-b)*sin(t)+b*sin((a/b-1)*t);
     }
//--- Berechnen des Mittelwertes
   x_mean=MathMean(x_source);
   y_mean=MathMean(y_source);
//--- Berechnen der Standardabweichung
   x_sdev=MathStandardDeviation(x_source);
   y_sdev=MathStandardDeviation(y_source);
//--- Abfangen einer Division durch Null
   x_sdev =(x_sdev==0)? 1 : x_sdev;
   y_sdev =(y_sdev==0)? 1 : y_sdev;
//--- Normalisieren der Daten
   for(int i=0; i<total; i++)
     {
      x_norm[i] =(x_source[i]-x_mean)/x_sdev;
      y_norm[i] =(y_source[i]-y_mean)/y_sdev;
     }
  }

Die Klasse CGraphic enthält Methoden, die es erlauben, innerhalb des Arbeitsbereiches des erstellten Diagramms zusätzliche Ausschnitte, Linien und Texte zu den Achsenskalen hinzuzufügen.

In unserem Fall wird die Methode CProgram::TextAdd() verwendet, um die Werte des Mittelwerts und der Standardabweichung für X- und Y-Sequenzen in der linken oberen Ecke des Diagramms auszugeben. Die Methoden CGraphic::ScaleX() und CGraphic::ScaleY() werden verwendet, um die Koordinaten des äußersten linken Punktes (obere linke Ecke) des Diagramms zu erhalten. Sie dienen zur Skalierung der tatsächlichen Werte des Diagramms in Pixelkoordinaten. Hier werden das Minimum auf der X-Achse und das Minimum auf der Y-Achse als reale Werte angegeben.  

class CProgram : public CWndEvents
  {
private:
   //--- Schreiben von Text auf dem Chart
   void              TextAdd(void);
  };
//+------------------------------------------------------------------+
//| Schreiben von Text auf dem Chart                                 |
//+------------------------------------------------------------------+
void CProgram::TextAdd(void)
  {
//--- Abfragen des Pointers zum Chart
   CGraphic *graph=m_graph1.GetGraphicPointer();
//---  
   int  x     =graph.ScaleX(graph.XAxis().Min())+50;
   int  y     =graph.ScaleY(graph.YAxis().Max())+10;
   int  y2    =y+20;
   uint clr   =::ColorToARGB(clrBlack);
   uint align =TA_RIGHT;
//---
   string str[8];
   str[0] ="x mean:";
   str[1] ="y mean:";
   str[2] =::DoubleToString(x_mean,2);
   str[3] =::DoubleToString(y_mean,2);
   str[4] ="x sdev:";
   str[5] ="y sdev:";
   str[6] =::DoubleToString(x_sdev,2);
   str[7] =::DoubleToString(y_sdev,2);
//--- Berechnen der Koordinaten und Ausgabe des Textes auf den Chart
   int l_x=0,l_y=0;
   for(int i=0; i<8; i++)
     {
      if(i<2)
         l_x=x;
      else if(i<6)
         l_x=(i%2==0)? l_x+50 : l_x;
      else
         l_x=(i%2==0)? l_x+60 : l_x;
      //---
      l_y=(i%2==0)? y : y2;
      //---
      graph.TextAdd(l_x,l_y,str[i],clr,align);
     }
  }

Nachdem alle erforderlichen Daten auf dem Diagramm festgelegt sind, muss es neu gezeichnet werden, um die letzten Änderungen darzustellen. Das geschieht durch die Methode CProgram::UpdateSeries(). Hier wird zunächst geprüft, ob sich Serien auf dem Diagramm befinden. Wenn ja, werden die zuletzt berechneten Daten verwendet. Zusätzlich werden die Eigenschaften der Kurve über die Steuerelemente des grafischen Interface eingestellt. Hier sind dies (1) die Linienglättung, (2) die Art der Punkte und (3) die Art der Kurve. Es ist zu beachten, dass es notwendig ist, den Text in der Grafik zu implementieren, nachdem alle anderen Eigenschaften und Daten installiert und gezeichnet wurden. Am Ende ist es notwendig, das Diagramm zu aktualisieren, um das Ergebnis zu sehen.

class CProgram : public CWndEvents
  {
private:
   //--- Festlegen und Aktualisieren der Werte auf dem Chart
   void              UpdateSeries(void);
  };
//+------------------------------------------------------------------+
//| Festlegen und Aktualisieren der Werte auf dem Chart              |
//+------------------------------------------------------------------+
void CProgram::UpdateSeries(void)
  {
//--- Abfragen des Pointers auf den Chart
   CGraphic *graph=m_graph1.GetGraphicPointer();
//--- Aktualisieren aller Werte auf dem Chart
   int total=graph.CurvesTotal();
   if(total>0)
     {
      //--- Abfrage des Pointers auf die Kurve
      CCurve *curve=graph.CurveGetByIndex(0);
      //--- Festlegen der Datenarrays
      curve.Update(x_norm,y_norm);
      //--- Abfrage der Eigenschaften der Kurve
      ENUM_CURVE_TYPE curve_type =(ENUM_CURVE_TYPE)m_curve_type.GetListViewPointer().SelectedItemIndex();
      ENUM_POINT_TYPE point_type =(ENUM_POINT_TYPE)m_point_type.GetListViewPointer().SelectedItemIndex();
      //--- Festlegen der Eigenschaften
      curve.LinesSmooth(m_line_smooth.IsPressed());
      curve.PointsType(point_type);
      curve.Type(curve_type);
     }
//--- Anwenden 
   graph.Redraw(true);
//--- Textausgabe
   TextAdd();
//--- Aktualisieren des Charts
   graph.Update();
  }

Die Methode CProgram::RecalculatingSeries() wird zur Berechnung und Anwendung der erhaltenen Ergebnisse in einem einzigen Aufruf verwendet:

class CProgram : public CWndEvents
  {
private:
   //--- Neuberechnen der Werte des Charts
   void              RecalculatingSeries(void);
  };
//+------------------------------------------------------------------+
//| Neuberechnen der Werte des Charts                                |
//+------------------------------------------------------------------+
void CProgram::RecalculatingSeries(void)
  {
//--- Berechnen der Werte und Initialisierung der Arrays
   InitArrays();
//--- Aktualisieren der Werte
   UpdateSeries();
  }

Das Diagramm basiert auf diesen Formeln wird interessanter aussehen, wenn es animiert wird. Um die berechneten Sequenzen in Bewegung zu setzen, ist es notwendig, den Anfangswert dieser Sequenzen zu ändern. Dies kann durch Eingabe von Werten über das Spin-Bearbeitungsfeld oder durch die automatische Ausführen des Prozesses erreicht werden. Im automatischen Modus wird der Wert in diesem Eingabefeld in der Methode CProgram::AnimateGraphSeries() erhöht oder erniedrigt. Diese Methode wird in der Methode CProgram::UpdateGraphByTimer() aufgerufen, die ihrerseits im Timer der Anwendung aufgerufen wird.

class CProgram : public CWndEvents
  {
private:
   //--- Aktualisieren des Charts durch den Timer
   void              UpdateGraphByTimer(void);
   //--- Animieren der Werte des Charts
   void              AnimateGraphSeries(void);
  };
//+------------------------------------------------------------------+
//| Timer                                                            |
//+------------------------------------------------------------------+
void CProgram::OnTimerEvent(void)
  {
   CWndEvents::OnTimerEvent();
//---  Aktualisieren des Charts durch den Timer
   if(m_counter1.CheckTimeCounter())
     {
      UpdateGraphByTimer();
     }
...
  }
//+------------------------------------------------------------------+
//|  Aktualisieren des Charts durch den Timer                        |
//+------------------------------------------------------------------+
void CProgram::UpdateGraphByTimer(void)
  {
//--- Verlassen, wenn (1) Anzeige ist minimiert oder (2) Animation ist deaktiviert
   if(m_window.IsMinimized() || !m_animate.IsPressed())
      return;
//--- Animieren der Werte des Charts
   AnimateGraphSeries();
//--- Aktualisieren der Arrays und der Werte des Charts
   RecalculatingSeries();
  }
//+------------------------------------------------------------------+
//| Animieren der Werte des Charts                                   |
//+------------------------------------------------------------------+
void CProgram::AnimateGraphSeries(void)
  {
//--- Zur Richtungsangabe und Größenänderung der Arrays
   static bool counter_direction=false;
//--- Richtungswechsel, wenn das Minimum erreicht wurde
   if((double)m_animate.GetValue()<=(double)m_animate.MinValue())
      counter_direction=false;
//--- Richtungswechsel, wenn das Maximum erreiccht ist
   if((double)m_animate.GetValue()>=(double)m_animate.MaxValue())
      counter_direction=true;
//--- Größenänderung des Arrays in der angegebenen Richtung
   string value="";
   if(!counter_direction)
      value=string((double)m_animate.GetValue()+m_animate.StepValue());
   else
      value=string((double)m_animate.GetValue()-m_animate.StepValue());
//--- Fetslegen der neuen Werte und aktualisieren des Eingabefeldes
   m_animate.SetValue(value,false);
   m_animate.GetTextBoxPointer().Update(true);
  }

Das erhaltene Ergebnis ist unten dargestellt:

 Abb. 7. Demonstration eines animierten Hypozykloids.

Abb. 7. Demonstration eines animierten Hypozykloids.


Die Testanwendung dieses Artikels kann mittels des Links unten heruntergeladen werden, für ein weiteres Studium.


Neue Version der Testanwendung aus den vorherigen Aktualisierungen

Die im Artikel Grafische Interfaces IX: Die Fortschrittsanzeige und das Linienchart-Control (Kapitel 2) vorgestellte Testanwendung wurde entsprechend den Änderungen in diesem Update aktualisiert.

Die neue Version dieser MQL-Anwendung mit dem aktualisierten grafischen Interface ist unten dargestellt:

 Abb. 8. Neue Version der Testanwendung der vorhergehenden Aktualisierungen.

Abb. 8. Neue Version der Testanwendung der vorhergehenden Aktualisierungen.


Die Testanwendung dieses Artikels kann mittels des Links unten heruntergeladen werden, für ein weiteres Studium.


Schlussfolgerung

In diesem Artikel wurde ein Teil der Standardbibliothek zum Zeichnen von wissenschaftlichen Diagrammen in die entwickelte Bibliothek zur Erstellung von grafischen Interfaces integriert. Alle Beispiele können von den Dateien heruntergeladen werden, die diesem Artikel beigefügt sind, um den Quellcode genauer zu studieren.

Das Schema der Bibliothek im aktuellen Entwicklungsstadium sieht wie folgt aus:

 Abb. 9. Die Struktur der Bibliothek im aktuellen Zustand der Entwicklung

Abb. 9. Die Struktur der Bibliothek im aktuellen Zustand der Entwicklung


Der vorgestellte Code ist kostenfrei. Sie können ihn in Ihren, auch kommerziellen, Projekten verwenden, damit Artikel schreiben und ihn für eigene Aufträge verwenden.

Wenn Sie Fragen zur Verwendung des Materials aus dem Artikel haben, können Sie diese im Kommentarteil stellen.

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

Beigefügte Dateien |
Letzte Kommentare | Zur Diskussion im Händlerforum (7)
Otto Pauser
Otto Pauser | 27 Nov. 2017 in 17:31

"Wenn Sie Fragen zur Verwendung des Materials aus dem Artikel haben, können Sie diese im Kommentarteil stellen."

Heisst es am Ende des Artikels.


JA UND WAS HABE ICH DAVON WENN NIEMAND ANTWORTET ?


Der Autor meint er hat keine Zeit. Dieses .................

Carl Schreiber
Carl Schreiber | 28 Nov. 2017 in 09:20
Otto Pauser:

"Wenn Sie Fragen zur Verwendung des Materials aus dem Artikel haben, können Sie diese im Kommentarteil stellen."

Heisst es am Ende des Artikels.


JA UND WAS HABE ICH DAVON WENN NIEMAND ANTWORTET ?


Der Autor meint er hat keine Zeit. Dieses .................

Ich habe bisher weder mit mt5 noch gar mit dieser Bibliothek gearbeitet, aber:

  1. Ich würde aber denken, dass die letzte Version alle bisherigen ersetzt oder ersetzen soll - so wäre es jedenfalls meiner Meinung nach korrekt!
  2. Wenn Du hier keine Antwort kriegst schreibe auf der Kommentarseite des Originals (https://www.mql5.com/ru/forum/212721) mit Deinem Text in Deutsch, in Englisch und Russisch. Zur Übersetzung verwendest Du ganz einfach google-translate
(Kleiner Trick, ich habe mal gelesen google-translate übersetzt deutsch-russisch anscheinend immer über Englisch, also erst ins Englische, das eventuell korrigieren und dann ins Russische!)
WOLFRAM STEFFEN SIEGERT
WOLFRAM STEFFEN SIEGERT | 3 März 2018 in 14:30

Hallo Otto,

hat sich der Programmierer inzwischen dazu geäußert bzw. die Fehler korrigiert.

Das Dilemma beginnt bereits mit dem 1. Kapitel des Grafischen Interfaces I.

Das ist alles sehr schade, da sich der Programmierer mit den vielen Artikeln hier eine Menge Arbeit gemacht hat.

Nur wenn permant der Compiler Fehlermeldungen auswirft, dann verliert man schnell die Lust das nachzuproggen

und der Lerneffekt ist dann natürlich auch nicht gegeben.


VG


Steffen

Carl Schreiber
Carl Schreiber | 3 März 2018 in 14:58

Ich würde nur die letzte Version verwenden.

Eine Übersicht ist hier: https://www.mql5.com/en/code/19703

Christian
Christian | 3 März 2018 in 15:54

Ich hab das Thema auch aufgegeben.

Kenne das was Otto bemängelt.

Ich habe es aber fast immer wieder hinbekommen.Viel umprogrammiert aber danach lief es immer. Nur die Zeit geht verloren.


Der Ersteller müsste mal riesengroß BETA reinschreiben.


Denn nichts anderes ist das.

Universeller Expert Advisor: CUnIndicator und das Arbeiten mit Pending Orders (Teil 9) Universeller Expert Advisor: CUnIndicator und das Arbeiten mit Pending Orders (Teil 9)
Der Artikel beschreibt das Arbeiten mit Indikatoren anhand der universellen Klasse CUnIndicator. Darüber hinaus wurden im Artikel neue Arbeitsmethoden mit Pending Orders betrachtet. Bitte beachten Sie, dass die Struktur des CStrategy Projektes wesentlich verändert wurde. Jetzt sind alle seine Dateien in einem einheitlichen Verzeichnis für die Bequemlichkeit der Nutzer abgelegt.
Risikobewertung durch die Abfolge von Positionen von Finanzanlagen Risikobewertung durch die Abfolge von Positionen von Finanzanlagen
Dieser Artikel beschreibt den Verwendung von Methoden der Wahrscheinlichkeitstheorie und der mathematischen Statistik für die Analyse von Handelssystemen.
Cross-Plattform Expert Advisor: Eigene Stopps, Breakeven und Trailing Cross-Plattform Expert Advisor: Eigene Stopps, Breakeven und Trailing
Dieser Artikel beschreibt, wie nutzerdefinierte Stopps in einem plattformübergreifenden Expert Advisor eingerichtet werden können. Darüber hinaus wird eine eng verwandte Methode diskutiert, mit der das Nachziehen von Stopps für die Dauer einer Position entwickelt werden können.
Cross-Plattform Expert Advisor: Stopps Cross-Plattform Expert Advisor: Stopps
Dieser Artikel beschreibt eine Implementierung von Stopps in einem Experten Advisor, die mit den beiden Plattformen MetaTrader 4 und MetaTrader 5 kompatibel ist.