English Русский 中文 Español 日本語 Português Italiano Türkçe
preview
Einen handelnden Expert Advisor von Grund auf neu entwickeln (Teil 29): Die sprechende Plattform

Einen handelnden Expert Advisor von Grund auf neu entwickeln (Teil 29): Die sprechende Plattform

MetaTrader 5Beispiele | 17 November 2022, 15:53
335 0
Daniel Jose
Daniel Jose

Einführung

Was wäre, wenn ein Expert Advisor mehr Spaß machen würde? Der Handel an den Finanzmärkten ist oft zu langweilig und eintönig, aber wir können diesen Job weniger anstrengend machen. Bitte beachten Sie, dass dieses Projekt für Menschen mit Suchtneigung gefährlich sein kann. Aber im Allgemeinen macht es die Dinge einfach weniger langweilig.

Warnung: Verwenden Sie die in diesem Artikel beschriebenen Modifikationen NICHT, wenn Sie den Markt als Glücksspiel betrachten, denn es besteht ein reales Risiko von sehr großen Verlusten.

Obwohl die obige Warnung wie ein Scherz klingt, ist es in Wahrheit so, dass einige Änderungen am EA ihn für diejenigen gefährlich machen, die generell spielsüchtig sind.

Einige der Änderungen, die hier vorgenommen werden, zielen darauf ab, die allgemeine Stabilität und Leistung des EA zu verbessern. Wenn Sie einige der Dinge, die wir in diesem Artikel löschen, behalten wollen, ist das nicht schwer. Dank des Ordnungssystems, das im EA vorhanden ist, können Sie einige Dinge ohne Schaden entfernen. Es liegt also an Ihnen, ob Sie die Dinge akzeptieren und nutzen oder sie löschen wollen.


2.0. Chart Trade löschen

Chart Trade ist etwas, das in einem einfachen Auftragssystem, das weniger komplex ist als das in unserem EA verwendete, noch Sinn macht. Aber für unseren EA im derzeitigen Entwicklungsstadium macht es keinen Sinn, Chart Trade auf dem Chart zu haben, also können wir es entfernen. Sie können es beibehalten, indem Sie einfach einen Befehl bearbeiten. Es stimmt, ich halte die Dinge gerne einfach, sodass ich sie später sehr schnell ändern (oder nicht ändern) kann, sodass die Änderungen keinen Stress verursachen, wie Probleme oder katastrophale Ausfälle an kritischen Punkten.

Um die Steuerung sehr schnell und gleichzeitig sicher zu machen, wurde dem EA-Code die folgende Definition hinzugefügt:

#define def_INTEGRATION_CHART_TRADER            // Chart trader integration with the EA ...

Wenn diese Definition nicht existiert oder zu einem Kommentar wird, dann wird CHART TRADE nicht mit dem EA kompiliert. Schauen wir uns die von dieser Definition betroffenen Punkte an. Die erste und offensichtlichste ist die folgende:

#ifdef def_INTEGRATION_CHART_TRADER
        #include <NanoEA-SIMD\SubWindow\C_TemplateChart.mqh>
#endif 

Obwohl sich der obige Code nicht in der EA-Datei, sondern in der Datei C_IndicatorTradeView.mqh befindet, ist die Definition für den Compiler überall im Code sichtbar, sodass wir uns nicht um die Korrektur des Codes kümmern müssen. Hier legen wir die Definition einfach an einer leicht zugänglichen Stelle an, in diesem Fall im EA-Code, und verwenden sie bei Bedarf.

Fahren wir jedoch mit der Datei C_IndicatorTradeView.mqh fort. Da wir den EA ohne Chart Trade kompilieren können, müssen wir den Zugriff auf die Daten implementieren, die in der EA-Initialisierungsnachrichtenbox definiert sind, die im folgenden Bild zu sehen ist:

Denken Sie daran, dass wir auf diese Daten zugreifen müssen. Früher haben wir sie an Chart Trade weitergegeben, und, wenn wir sie benötigen, haben wir uns von Chart Trade geholt. Aber jetzt, ohne Chart Trade, müssen wir einen anderen Weg gehen, um auf dieselben Daten zuzugreifen.

In der Datei C_IndicatorTradeView.mqh werden diese Werte nur an einer Stelle verwendet — bei der Erstellung des Indikators 0, der anzeigt, wo sich der schwebende Auftrag befinden wird. Diese Stelle befindet sich innerhalb der Funktion DispatchMessage. Sie ist im folgenden Code dargestellt:

// ... Previous code ...

                                        case CHARTEVENT_MOUSE_MOVE:
                                                Mouse.GetPositionDP(dt, price);
                                                mKeys   = Mouse.GetButtonStatus();
                                                bEClick  = (mKeys & 0x01) == 0x01;    //Left mouse click
                                                bKeyBuy  = (mKeys & 0x04) == 0x04;    //SHIFT pressed
                                                bKeySell = (mKeys & 0x08) == 0x08;    //CTRL pressed
                                                if (bKeyBuy != bKeySell)
                                                {
                                                        if (!bMounting)
                                                        {
#ifdef def_INTEGRATION_CHART_TRADER
                                                                m_Selection.bIsDayTrade = Chart.GetBaseFinance(m_Selection.vol, valueTp, valueSl);
#else 
                                                                m_Selection.vol = EA_user20 * Terminal.GetVolumeMinimal();
                                                                valueTp = EA_user21;
                                                                valueSl = EA_user22;
                                                                m_Selection.bIsDayTrade = EA_user23;
#endif 
                                                                valueTp = Terminal.AdjustPrice(valueTp * Terminal.GetAdjustToTrade() / m_Selection.vol);
                                                                valueSl = Terminal.AdjustPrice(valueSl * Terminal.GetAdjustToTrade() / m_Selection.vol);
                                                                m_Selection.it = IT_PENDING;
                                                                m_Selection.pr = price;
                                                        }

// ... The rest of the code...

Achten Sie auf die hervorgehobenen Zeilen. Es ist nicht notwendig, diese Werte EA_userXX in der Datei zu suchen — sie sind nicht vorhanden, da sie aus dem EA-Code stammen, wie folgt:

#ifdef def_INTEGRATION_CHART_TRADER
        input group "Chart Trader"
#else 
        input group "Base Operacional do EA"
#endif 
input int       EA_user20   = 1;     //Levering factor
input double    EA_user21   = 100;   //Take Profit (financial)
input double    EA_user22   = 81.74; //Stop Loss (financial)
input bool      EA_user23   = true;  //Day Trade ?

Dies allein bietet bereits eine ähnliche Kontrolle wie Chart Trade auf dem Chart. Bitte beachten Sie, dass wir praktisch nichts am Code ändern. Wir verschieben einfach die vom Nutzer definierten erforderlichen Daten an die richtige Stelle. Manch einer mag diese Konfiguration auf Seiten des Händlers beim Laden des EAs für unnötig halten, und das ist in gewisser Weise auch richtig, denn das Auftragssystem erlaubt es, alle Variablen ohne Schwierigkeiten zu konfigurieren. Wir können also einfach den Mindestwert des Hebelfaktors, den Stop-Loss und den Take-Profit auf 0 und die anfänglichen Operationen als Day Trade festlegen — wir tun dies in der DispatchMessage-Funktion der C_IndicatorTradeView-Klasse. Dies hat keinerlei Auswirkungen auf das System, da der Händler den Auftrag auf dem Chart ändern und dann an den Server senden kann. Diese Art der Änderung bleibt Ihnen überlassen, da sie etwas sehr Persönliches ist.


2.0.1. Einige Anpassungen

Bevor wir zu dem Teil kommen, in dem wir den Chart Trade entfernen, müssen wir noch eine Sache tun, die die Stabilität des EA als Ganzes verbessern wird.

Wir tun Folgendes: In der Klasse C_IndicatorTradeView definieren wir eine private Datenstruktur, die unten zu sehen ist:

struct st01
{
        bool    ExistOpenPosition,
                SystemInitilized;
}m_InfoSystem;

Sie muss im folgenden Code initialisiert werden:

void Initilize(void)
{
        static int ot = 0, pt = 0;
                                
        m_InfoSystem.ExistOpenPosition = false;
        m_InfoSystem.SystemInitilized = false;
        ChartSetInteger(Terminal.Get_ID(), CHART_SHOW_TRADE_LEVELS, false);
        ChartSetInteger(Terminal.Get_ID(), CHART_DRAG_TRADE_LEVELS, false);                             
        if ((ot != OrdersTotal()) || (pt != PositionsTotal()))
        {
                ObjectsDeleteAll(Terminal.Get_ID(), def_NameObjectsTrade);
                ChartRedraw();
                for (int c0 = ot = OrdersTotal(); c0 >= 0; c0--)  IndicatorAdd(OrderGetTicket(c0));
                for (int c0 = pt = PositionsTotal(); c0 >= 0; c0--) IndicatorAdd(PositionGetTicket(c0));
        }
        m_InfoSystem.SystemInitilized = true;
}

Warum erstellen und initialisieren wir diese Daten hier? Denken Sie daran, dass MetaTrader 5 Ereignisse an den EA sendet, und eines dieser Ereignisse ist OnTick. Bei einfachen Systemen gibt es nicht viele Probleme. Aber je komplexer das System wird, desto mehr muss man darauf achten, dass alles funktioniert. Es kann vorkommen, dass MetaTrader 5 Ereignisse an den EA sendet, bevor der EA bereit ist, diese Ereignisse zu verarbeiten. Daher müssen wir sicherstellen, dass der EA bereit ist. Wir werden einige Variablen erstellen, die den Bereitschaftsstatus des EAs anzeigen. Wenn er noch nicht bereit ist, sollten die Ereignisse des MetaTrader 5 ignoriert werden, bis der EA angemessen auf die Ereignisse reagieren kann.

Der kritischste Punkt ist im nachstehenden Code zu sehen:

inline double SecureChannelPosition(void)
                        {
                                static int nPositions = 0;
                                double Res = 0;
                                ulong ticket;
                                int iPos = PositionsTotal();
                                
                                if (!m_InfoSystem.SystemInitilized) return 0;
                                if ((iPos != nPositions) || (m_InfoSystem.ExistOpenPosition))
                                {
                                        m_InfoSystem.ExistOpenPosition = false;
                                        for (int i0 = iPos - 1; i0 >= 0; i0--) if (PositionGetSymbol(i0) == Terminal.GetSymbol())
                                        {
                                                m_InfoSystem.ExistOpenPosition = true;
                                                ticket = PositionGetInteger(POSITION_TICKET);
                                                if (iPos != nPositions) IndicatorAdd(ticket);
                                                SetTextValue(ticket, IT_RESULT, PositionGetDouble(POSITION_VOLUME), Res += PositionGetDouble(POSITION_PROFIT), PositionGetDouble(POSITION_PRICE_OPEN));
                                        }
                                        nPositions = iPos;
                                }
                                return Res;
                        };

Hervorgehobene Punkte gab es vorher nicht, sodass manchmal seltsame Dinge passieren konnten. Aber jetzt haben wir die notwendigen Kontrollen, um sicherzustellen, dass nichts Ungewöhnliches unbemerkt bleibt.

Die Frage, ob man alles überprüfen sollte, ist ziemlich kompliziert, da mehrere Überprüfungen ein System sehr stabil machen können, aber auch die Wartung und Änderung des Codes erschweren können. Einige der Kontrollen müssen in einer logischen Reihenfolge durchgeführt werden, um tatsächlich wirksam zu sein, was eine ziemlich kostspielige Angelegenheit ist.

Aber beachten Sie, dass wir, wenn wir prüfen, ob es eine Position für ein vom EA überwachtes Symbol gibt oder nicht, eine gewisse Beweglichkeit geben können. Dies gilt umso mehr, wenn mehrere Vermögenswerte gehandelt werden, von denen jeder eine bestimmte Anzahl von Positionen hat, die im EA erscheinen werden. Indem wir dies hier filtern, eliminieren wir die Schleife, sodass der EA den Code innerhalb der Schleife nur ausführt, wenn er wirklich benötigt wird. Andernfalls reduzieren wir die vom EA benötigte Verarbeitungszeit ein wenig. Sie ist nicht lang, aber in sehr extremen Fällen kann sie einen großen Unterschied machen.


2.0.2. Den Chart-Trade aus dem EA entfernen

Nachdem wir nun Änderungen an der Klasse C_IndicatorTradeView vorgenommen haben, können wir uns auf den EA-Code konzentrieren und Chart Trade daraus löschen. Als Erstes müssen Sie sie aus dem Code von OnInit löschen:

int OnInit()
{       
        Terminal.Init();

#ifdef def_INTEGRATION_WITH_EA
        WallPaper.Init(user10, user12, user11);
        VolumeAtPrice.Init(user32, user33, user30, user31);
        TimesAndTrade.Init(user41);
        EventSetTimer(1);
#endif 

        Mouse.Init(user50, user51, user52);
        
#ifdef def_INTEGRATION_CHART_TRADER
        static string   memSzUser01 = "";
        if (memSzUser01 != user01)
        {
                Chart.ClearTemplateChart();
                Chart.AddThese(memSzUser01 = user01);
        }
        Chart.InitilizeChartTrade(EA_user20 * Terminal.GetVolumeMinimal(), EA_user21, EA_user22, EA_user23);
        TradeView.Initilize();
        OnTrade();
#else 
        TradeView.Initilize();
#endif 
   
        return INIT_SUCCEEDED;
}

Der grüne Code wird durch den blauen Code ersetzt. Wenn wir Chart Trade nicht verwenden, könnte es scheinen, dass der Unterschied gering ist, dass es sich nur um eine Änderung der Größe der ausführbaren Datei handelt. Aber es ist nicht nur das. Bitte beachten Sie, dass wir zusätzlich zum Chart Trade Code auch das OnTrade Ereignis entfernt haben. Der EA wird dieses Ereignis nicht mehr verarbeiten.

Sie könnten denken, dass mit mir etwas nicht stimmt. Wie kann ich das OnTrade-Ereignis aus einem EA entfernen? Wie werden wir jetzt mit Handelsereignissen umgehen? Diese Ereignisse werden durch das Ereignis OnTradeTransaction verarbeitet. Die Verarbeitungsmethode wird effizienter sein als bei OnTrade, was bedeutet, dass der EA einfacher und zuverlässiger sein wird.

Es gibt noch einen anderen Moment, der sich verändert:

void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
        Mouse.DispatchMessage(id, lparam, dparam, sparam);
#ifdef def_INTEGRATION_WITH_EA
        switch (id)
        {
                case CHARTEVENT_CHART_CHANGE:
                        Terminal.Resize();
                        WallPaper.Resize();
                        TimesAndTrade.Resize();
        break;
        }
        VolumeAtPrice.DispatchMessage(id, sparam);
#endif 

#ifdef def_INTEGRATION_CHART_TRADER
        Chart.DispatchMessage(id, lparam, dparam, sparam);
#endif 

        TradeView.DispatchMessage(id, lparam, dparam, sparam);  
}

Wenn es keine Integration innerhalb des EA gibt, werden nur die markierten Zeilen kompiliert. Da diese Ereignisse in der Regel ziemlich konstant sind (je effizienter die Verarbeitung dieser Ereignisse, desto besser), konkurrieren sie oft mit einem anderen Ereignis, das MetaTrader 5 auslöst und das der EA verarbeiten muss. Dieses andere Ereignis ist unten dargestellt:

void OnTick()
{
#ifdef def_INTEGRATION_CHART_TRADER
        Chart.DispatchMessage(CHARTEVENT_CHART_CHANGE, 0, TradeView.SecureChannelPosition(), C_Chart_IDE::szMsgIDE[C_Chart_IDE::eRESULT]);
#else 
        TradeView.SecureChannelPosition();
#endif 

#ifdef def_INTEGRATION_WITH_EA
        TimesAndTrade.Update();
#endif 
}

Ein solches Ereignis ist ein echter Alptraum, weil es in der Regel mehrfach aufgerufen wird, und in einigen Fällen kann es in weniger als einer Sekunde mehrfach aufgerufen werden. Aber dank der Änderungen am Code der Klasse C_IndicatorTradeView ist die Verarbeitung dieses Ereignisses etwas effizienter geworden. Später werden wir diese Effizienz noch weiter verbessern, aber für den Moment ist das ausreichend.

Nun, nach all diesen Änderungen wird Chart Trade nicht in den EA integriert werden. Wir können den Chart Trade in einen Indikator umwandeln, was einige Vorteile mit sich bringt, während sich die EA-Operation auf die Hauptaktivität konzentriert: Handhabung, Positionierung und Unterstützung des Auftragssystems. Aber die Umwandlung von Chart Trade in einen Indikator bringt einige zusätzliche Änderungen mit sich, sodass ich jetzt nicht zeigen werde, wie man das macht. Aber im Allgemeinen können wir den Chart Trade in einen Indikator verschieben und immer noch in der Lage sein, Aufträge über ihn zu senden.


3.0. Hinzufügen von Klängen

Oft schauen wir nicht auf den Chart, wollen aber trotzdem wissen, was gerade passiert. Eine der Möglichkeiten, über etwas benachrichtigt zu werden, ist der Empfang eines Tonsignals. Dies ist einer der besten Alarmtypen, weil er unsere Aufmerksamkeit sofort erregt. Manchmal wissen wir bereits, wie wir uns verhalten sollen, wenn wir die Meldung hören, ohne dass wir eine andere Nachricht überprüfen müssen.

Lassen Sie uns also lernen, wie man einige grundlegende akustische Warnungen einrichtet. In manchen Fällen wird dies ein Satz sein, der etwas Bestimmtes aussagt. Obwohl das, was ich jetzt zeige und was im Anhang verfügbar ist, nur grundlegende Funktionen bietet, kann es Sie vielleicht dazu motivieren, die Anzahl der vorhandenen Alarme und Warnungen zu erhöhen, sodass Sie keine Zeit mit dem Lesen von Nachrichten verschwenden müssen. Ein Geräusch kann auf ein bestimmtes Ereignis hinweisen und Ihnen in bestimmten Handelsmomenten einen Gewinn an Beweglichkeit verschaffen. Glauben Sie mir, das macht einen großen Unterschied.

Als Erstes müssen wir eine neue Datei erstellen, die die neue Klasse enthält und die unser Soundsystem unterstützt und isoliert. Sobald dies geschehen ist, können wir damit beginnen, Dinge auf eine sehr stabile Weise zu produzieren. Die gesamte Klasse ist im nachstehenden Code zu sehen:

class C_Sounds
{
        protected:
                enum eTypeSound {TRADE_ALLOWED, OPERATION_BEGIN, OPERATION_END};
        public  :
//+------------------------------------------------------------------+
inline bool PlayAlert(const int arg)
                {
                        return PlaySound(StringFormat("NanoEA-SIMD\\RET_CODE\\%d.wav", arg));
                }
//+------------------------------------------------------------------+
inline bool PlayAlert(const eTypeSound arg)
                {
                        string str1;
        
                        switch (arg)
                        {
                                case TRADE_ALLOWED   : str1 = def_Sound00; break;
                                case OPERATION_BEGIN : str1 = def_Sound01; break;
                                case OPERATION_END   : str1 = def_Sound02; break;
                                defaultreturn false;
                        }
                        PlaySound("::" + str1);
                        
                        return true;
                }
//+------------------------------------------------------------------+
};

Trotz der extremen Einfachheit dieses Codes gibt es etwas Interessantes darin. Beachten Sie, dass wir die PlayAlert Funktion umschreiben, sodass wir zwei Versionen der gleichen Funktion haben. Und wozu? Die Art und Weise, wie das Soundsystem funktionieren wird, erfordert zwei Varianten. Bei der ersten Version der Funktion wird ein Sound aus einer Datei abgespielt; bei der zweiten Version wird der Sound abgespielt, der Teil des EA ist, d. h. seine Funktion. Nun gibt es etwas, was viele Leute nicht können: Sounds direkt aus Audiodateien abspielen. Aber keine Sorge, ich zeige Ihnen, wie es geht. Der Grund für die erste Version ist, dass manche Leute vielleicht ihre eigene Stimme oder einen anderen Ton als Warnmeldung einfügen und jederzeit ändern möchten, ohne den EA neu kompilieren zu müssen. Sie können diese Töne sogar ändern, wenn der EA in MetaTrader 5 ausgeführt wird. Von dem Moment an, in dem der Sound abgespielt werden soll, wird der EA die neueste Version verwenden, sodass Sie nur eine Audiodatei durch eine andere ersetzen müssen — der EA wird keinen Unterschied merken, das hilft sehr. Aber es gibt noch einen anderen Grund, der aus dem EA-Code ersichtlich ist.

Tatsächlich wird die erste Option an einer ganz bestimmten Stelle verwendet, wie im unten hervorgehobenen Klassencode zu sehen ist:

class C_Router
{
        protected:
        private  :
                MqlTradeRequest TradeRequest;
                MqlTradeResult  TradeResult;
//+------------------------------------------------------------------+
inline bool Send(void)
        {
                if (!OrderSend(TradeRequest, TradeResult))
                {
                        if (!Sound.PlayAlert(TradeResult.retcode))Terminal.MsgError(C_Terminal::FAILED_ORDER, StringFormat("Error Number: %d", TradeResult.retcode));
                        
                        return false;
                }
                return true;
        }

// ... The rest of the class code....

Stellen Sie sich vor, wie viel Arbeit es machen würde, alle möglichen Fehler, die vom Handelsserver zurückgegeben werden, zu bearbeiten. Wenn wir jedoch eine Audiodatei aufnehmen und sie nach dem Wert benennen, den der Handelsserver zurückgibt, weiß der EA, welche Datei er abspielen muss, was uns das Leben sehr erleichtert. Denn hier müssen wir nur angeben, welche Datei auf der Grundlage des vom Server zurückgegebenen Wertes verwendet werden soll — der EA wird diese Datei finden und abspielen und uns eine akustische Warnung oder eine Sprachnachricht geben, damit wir genau wissen, was passiert ist. Wunderbar, nicht wahr? Wenn jetzt beispielsweise eine Bestellung abgelehnt wird, informiert uns die Plattform sehr deutlich, was passiert ist oder was falsch ist. Dies wird in einer sehr angemessenen Art und Weise geschehen, die etwas Spezifisches für Sie darstellt, etwas, das exklusiv und einzigartig für die Art und Weise sein kann, wie Sie auf dem Markt handeln und agieren. Sie werden sehen, wie viel Beweglichkeit Sie gewinnen, weil Sie in derselben Audiodatei deutlich machen können, wie Sie das Problem lösen.

Es gibt aber auch eine zweite Betriebsart, bei der die Sounds in der ausführbaren EA-Datei gespeichert werden. Dies ist die zweite Version der gleichen Funktion, die in dieser Phase an drei verschiedenen Stellen verwendet wird, um drei verschiedene Arten von Ereignissen anzuzeigen. Die erste Stelle ist im unten stehenden Code zu sehen:

int OnInit()
{
        if (!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
        {
                Sound.PlayAlert(C_Sounds::TRADE_ALLOWED);
                return INIT_FAILED;
        }
        
        Terminal.Init();

// ... The rest of the code...

Dieser Code prüft, ob AlgoTrading in der Plattform aktiviert ist. Wenn wir vergessen haben, sie zu aktivieren, wird uns der EA mitteilen, dass sie nicht für den Handel verfügbar ist. Um zu überprüfen, ob die Option aktiviert ist oder nicht, genügt ein Blick auf die Markierung in der Plattform, wie in der folgenden Abbildung gezeigt:


Die zweite Stelle, an der wir ein Hilfsgeräusch verwenden werden, ist unten dargestellt:

void CreateIndicator(ulong ticket, eIndicatorTrade it)
{
        string sz0;
                                
        switch (it)
        {
                case IT_TAKE    : macroCreateIndicator(it, clrForestGreen, clrDarkGreen, clrNONE); break;
                case IT_STOP    : macroCreateIndicator(it, clrFireBrick, clrMaroon, clrNONE); break;
                case IT_PENDING:
                        macroCreateIndicator(it, clrCornflowerBlue, clrDarkGoldenrod, def_ColorVolumeEdit);
                        m_BtnCheck.Create(ticket, sz0 = macroMountName(ticket, it, EV_CHECK), def_BtnCheckEnabled, def_BtnCheckDisabled);
                        m_BtnCheck.SetStateButton(sz0, true);
                        macroInfoBase(IT_PENDING);
                        break;
                case IT_RESULT  :
                        macroCreateIndicator(it, clrSlateBlue, clrSlateBlue, def_ColorVolumeResult);
                        macroInfoBase(IT_RESULT);
                        Sound.PlayAlert(C_Sounds::OPERATION_BEGIN);
                        m_InfoSystem.ExistOpenPosition = true;
                        break;
        }
        m_BtnClose.Create(ticket, macroMountName(ticket, it, EV_CLOSE), def_BtnClose);
}

Jedes Mal, wenn ein Positionsanzeiger erstellt wird, wird ein Ton abgespielt. Dies wird uns das Leben sehr erleichtern, da wir wissen, dass der schwebende Auftrag zu einer Position geworden ist und dass wir anfangen müssen, ihm Aufmerksamkeit zu widmen.

Der dritte und letzte Punkt, an dem wir einen Hilfston haben, ist, wenn eine Stelle aus irgendeinem Grund geschlossen wird. Dies geschieht an einem ganz bestimmten Ort:

inline void RemoveIndicator(ulong ticket, eIndicatorTrade it = IT_NULL)
{
        ChartSetInteger(Terminal.Get_ID(), CHART_EVENT_OBJECT_DELETE, false);
        if ((it == IT_NULL) || (it == IT_PENDING) || (it == IT_RESULT))
        {
                if (macroGetPrice(ticket, IT_RESULT, EV_LINE) > 0) Sound.PlayAlert(C_Sounds::OPERATION_END);
                ObjectsDeleteAll(Terminal.Get_ID(), StringFormat("%s%c%llu%c", def_NameObjectsTrade, def_SeparatorInfo, ticket, (ticket > 1 ? '*' : def_SeparatorInfo)));
        } else ObjectsDeleteAll(Terminal.Get_ID(), StringFormat("%s%c%llu%c%c", def_NameObjectsTrade, def_SeparatorInfo, ticket, def_SeparatorInfo, (char)it));
        ChartSetInteger(Terminal.Get_ID(), CHART_EVENT_OBJECT_DELETE, true);
        m_Selection.ticket = 0;
        Mouse.Show();
        ChartRedraw();
}

Sie könnten denken, dass beim Entfernen des EA der Ton zum Schließen der Position abgespielt wird, aber nein. Das wird nicht passieren, weil die Kurslinie noch im System vorhanden sein wird. Aber wenn die Position geschlossen wird, geschieht etwas anderes, und die Positionspreislinie wird auf einem Preisniveau von 0 liegen — in diesem Moment wird ein Ton abgespielt, der anzeigt, dass die Position geschlossen wurde.

Da diese Klänge, die zu den Ressourcen des EA gehören, der ausführbaren Datei überallhin folgen und nicht verändert werden können, ohne den Code neu zu kompilieren, sind sie begrenzter, aber gleichzeitig helfen sie, den EA an andere Orte zu portieren, ohne dass wir Audiodateien mitnehmen müssen.

Bei den Tönen, die zur Warnung vor Ausfällen oder Fehlern eingesetzt werden, ist die Logik jedoch eine andere: Sie müssen separat bewegt und an einem vorher festgelegten Ort platziert werden, damit sie bei Bedarf funktionieren können.

Der Anhang enthält einen Ordner namens SOUNDS. Lassen Sie diesen Ordner nicht in demselben Ordner, in dem sich der Code befindet, da die in diesem Ordner enthaltenen Sounds nicht abgespielt werden. Bringen Sie es an einen anderen Ort, der leicht gefunden werden kann. Wenn Sie nicht wissen, wo es ist, machen Sie sich keine Sorgen — wir werden es später sehen:

#property copyright "Daniel Jose"
//+------------------------------------------------------------------+
void OnStart()
{
        Print(TerminalInfoString(TERMINAL_PATH));
}
//+------------------------------------------------------------------+

Wenn Sie dieses Skript ausführen, erhalten Sie in der Symbolleiste Informationen über den Standort, den wir verwenden werden. Ein Beispiel für das Ergebnis der Ausführung ist in der nachstehenden Abbildung dargestellt:

Sie sollten Folgendes tun:

  1. Öffnen Sie den Anhang
  2. Datei-Explorer öffnen
  3. Wechseln Sie zu dem in der Abbildung oben gezeigten Ordner
  4. Kopieren Sie den Inhalt des Ordners SOUNDS aus der angehängten Datei in den oben angegebenen Ordner
  5. Wenn Sie möchten, können Sie diese drei Dateien (WARRING, BEGIN, END) löschen, da sie zusammen mit dem EA kompiliert werden
  6. Wenn Sie möchten, können Sie den Inhalt von .WAV in etwas ändern, das Ihnen gefällt; stellen Sie nur sicher, dass Sie den Namen nicht ändern
  7. Verwenden Sie den EA in der MetaTrader 5 Plattform und seien Sie glücklich!
Aber denken Sie daran, dass Sie, damit die Sounds (WARRING, BEGIN, END) in den EA kompiliert werden können, den SOUNDS-Ordner mit denselben Sounds im MQL5-Code-Verzeichnis haben müssen, sonst werden sie nicht in den EA-Code integriert.


Schlussfolgerung

In diesem Artikel haben Sie gelernt, wie Sie dem EA-System eigene Sounds hinzufügen können. Hier haben wir ein sehr einfaches System verwendet, um zu demonstrieren, wie dies gemacht wird, aber Sie sind nicht nur auf einen EA beschränkt, sondern können es auch in Indikatoren oder sogar in Skripten verwenden.

Das Tolle daran ist, dass man mit den gleichen Konzepten und Ideen, die hier vorgeschlagen werden, auch Sprachnachrichten aufnehmen kann, die etwas sagen oder vor etwas warnen. Und wenn der EA oder ein anderer Prozess, der von MetaTrader 5 ausgeführt wird und das Soundsystem verwendet, durch die im Artikel gezeigten Auslöser aktiviert wird, erhalten Sie eine solche akustische Nachricht, die Sie über eine Aktion informiert oder warnt, die Sie bereits vorhergesehen haben und die Sie durchführen sollten.

Dabei handelt es sich nicht um einen Text, sondern um eine Sprachnachricht, was sehr viel effektiver ist, da Sie jedem, der das System nutzt, schnell erklären können, was zu tun ist oder was die Ursache für eine solche Nachricht war.

Dieses System ist nicht auf dieses Schema beschränkt, und Sie können über das hier Gezeigte hinausgehen. Die Idee ist genau das: dem Nutzer zu ermöglichen, einen Verbündeten auf der Plattform zu haben. Durch eine Sprachinteraktion mit dem Händler können wir eine Botschaft vermitteln, die vielleicht besser zu verstehen ist als reiner Text. Das einzige, was Sie hier einschränkt, ist Ihre Kreativität.
   


Übersetzt aus dem Portugiesischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/pt/articles/10664

Beigefügte Dateien |
EA_-_h_Parte_29_6.zip (14465.62 KB)
Datenwissenschaft und maschinelles Lernen (Teil 08): K-Means Clustering in reinem MQL5 Datenwissenschaft und maschinelles Lernen (Teil 08): K-Means Clustering in reinem MQL5
Data Mining ist für Datenwissenschaftler und Händler von entscheidender Bedeutung, da die Daten oft nicht so einfach sind, wie wir denken. Das menschliche Auge kann die kleinen zugrundeliegenden Muster und Beziehungen im Datensatz nicht erkennen, vielleicht kann uns der Algorithmus K-Means dabei helfen. Finden wir es heraus...
Lernen Sie, wie man ein Handelssystem mit dem Alligator entwickelt Lernen Sie, wie man ein Handelssystem mit dem Alligator entwickelt
In diesem Artikel schließen wir unsere Serie darüber ab, wie man ein Handelssystem auf der Grundlage des beliebtesten technischen Indikators entwickelt. Wir werden lernen, wie man ein Handelssystem auf der Grundlage des Alligator-Indikators erstellt.
DoEasy. Steuerung (Teil 20): Das WinForms-Objekt SplitContainer DoEasy. Steuerung (Teil 20): Das WinForms-Objekt SplitContainer
In diesem Artikel werde ich mit der Entwicklung des SplitContainer-Steuerelements aus dem MS Visual Studio-Toolkit beginnen. Diese Steuerelement besteht aus zwei Feldern, die durch eine vertikale oder horizontale bewegliche Trennwand getrennt sind.
Datenwissenschaft und maschinelles Lernen (Teil 07): Polynome Regression Datenwissenschaft und maschinelles Lernen (Teil 07): Polynome Regression
Im Gegensatz zur linearen Regression ist die polynome Regression ein flexibles Modell, das darauf abzielt, Aufgaben besser zu erfüllen, die das lineare Regressionsmodell nicht bewältigen kann. Lassen Sie uns herausfinden, wie man polynome Modelle in MQL5 erstellt und etwas Positives daraus macht.