English Русский 中文 Español 日本語 Português 한국어 Français Italiano Türkçe
preview
Einen handelnden Expert Advisor von Grund auf neu entwickeln (Teil 13): Times and Trade (II)

Einen handelnden Expert Advisor von Grund auf neu entwickeln (Teil 13): Times and Trade (II)

MetaTrader 5Handelssysteme | 7 Juli 2022, 16:08
254 0
Daniel Jose
Daniel Jose

Einführung

Im vorangegangenen Artikel „Times & Trade (I)“ haben wir eine alternative Chartorganisation besprochen, die Voraussetzung für die Erstellung eines Indikators ist, der die schnellstmögliche Interpretation der am Markt getätigten Geschäfte ermöglicht. Aber wir haben dieses System noch nicht fertiggestellt: Es fehlt noch die Möglichkeit, zu zeigen, wie man auf bestimmte Informationen zugreifen kann, und ein solcher Zugriff würde helfen, besser zu verstehen, was geschieht. Solche Informationen können nicht direkt auf dem Chart dargestellt werden. Eine solche Darstellung ließe sich zwar realisieren, doch wäre die Interpretation sehr verwirrend. Daher ist es am besten, wenn die Daten auf klassische Weise dargestellt werden, d.h. Werte im Textformat. Unser Expert Advisor verfügt nicht über ein System, das diese Aufgabe übernehmen kann. Wir müssen sie also umsetzen.

Um den vorangegangenen Artikel nicht zu verkomplizieren, indem ich Informationen hinzufüge, die einige Leser vielleicht gar nicht brauchen (da das System auch verwendet werden kann, ohne in solche Details einzutauchen), habe ich mich entschlossen, das System hier zu erweitern und vollständiger zu machen, aber ich habe einige der Dinge, die im vorangegangenen Artikel vorgeschlagen wurden, nicht in das System aufgenommen. Aber diese Informationen können manchmal notwendig sein, um zu verstehen, was tatsächlich auf dem Markt passiert.


Planung

Dabei ist es wichtig, eines zu verstehen. Es sind nur Details, aber wie man so schön sagt, der Teufel steckt im Detail. Schauen Sie sich also bitte das folgende Bild an:

Fällt Ihnen etwas Merkwürdiges an diesem Bild auf? Etwas, das vielleicht nicht viel Sinn ergibt, aber es ist da, also schauen Sie genau hin.

Wenn Ihnen immer noch nichts aufgefallen ist, sehen Sie sich den unten hervorgehobenen Bereich an.


Und, sehen Sie, was hier passiert? Zu diesem Zeitpunkt gab es Änderungen bei den BID- und ASK-Werten, aber es wurde nur ein Handel durchgeführt. Selbst wenn sich der BID- oder ASK-Wert ändert, macht es keinen Sinn, nur einen Handel zu haben. Aber so etwas kommt häufiger vor, als Sie vielleicht denken. Das Problem ist, dass man so etwas normalerweise nicht sehen kann, wenn man den unten gezeigten Lesemodus verwendet:

Bei dieser Marktanalysemethode können wir die Bewegung der BID- und ASK-Werte nicht sehen. Es scheint, dass der Markt immer funktioniert, dass jeder versucht, das Geschäft abzuschließen, aber das ist nicht wahr. Eigentlich platzieren die Marktteilnehmer ihre Positionen an bestimmten Punkten und warten auf die Marktbewegung. Wenn die Position getroffen wird, versuchen sie, den Vorteil zu nutzen und von der Bewegung zu profitieren — deshalb bewegen sich die BID- oder ASK-Werte, ohne dass ein Handel stattfindet. Dies ist eine reale Tatsache, die auf der Plattform zu sehen ist, die jedoch von den meisten Menschen ignoriert wird, die glauben, dass diese Informationen nicht sehr wichtig sind.

Die folgende Abbildung zeigt, wie unser Times & Trade-System aussehen wird:

Wenn Sie genau hinsehen, werden Sie feststellen, dass es vier Kerzen-Konfigurationen auf dem Chart gibt. Eigentlich sollten es fünf sein, aber Direktaufträge sind vom System ausgeschlossen, weil sie den Markt nicht wirklich bewegen. Wir haben also eigentlich vier Konfigurationen. Es handelt sich um die folgenden Formationen:

Der Schatten berührt manchmal nicht den Körper der Kerze. Warum ist das so? Der Schatten wird durch den Wert des Spreads gebildet, der wiederum die Differenz zwischen BID und ASK ist, aber wenn eine Operation innerhalb dieses Spreads stattfindet, wie sieht dann die Kerze aus? Dies ist der fünfte Typ, der unten gezeigt wird:

Nach dem Bildungstyp handelt es sich um DOJI. Dies ist der Grund, warum Direktaufträge nicht im System angezeigt werden. Das erklärt aber nicht, warum der Körper manchmal den Schatten nicht berührt. Ein solches Verhalten ist mit Situationen verbunden, in denen etwas passiert, das den Preis zu schnell in Bewegung setzt, wodurch ein Abstand zwischen dem Körper und dem Schatten entsteht. Man könnte meinen, dass es sich um einen Systemfehler handelt, denn es macht keinen Sinn, dass der Preis dies tut. Aber hier macht es Sinn, da dies genau dann geschieht, wenn Stopp-Orders ausgelöst werden. Um dies zu sehen, werfen Sie einen Blick auf das folgende Bild:

Es gibt eine Reihe von Fällen, in denen es zwar Aufträge gibt, aber weder BID noch Ask berührt werden. Alle diese Punkte stellen ausgelöste Stopp-Orders dar. Wenn dies geschieht, springt der Preis in der Regel in die Höhe, was auf dem Chart zu sehen ist. Dieselbe Tatsache kann auf Times & Trade nur sichtbar sein, wenn Sie den Chartmodus zur Bewertung der Bewegung verwenden. Andernfalls sehen Sie nicht, wie die Stopps ausgelöst werden, und denken vielleicht, dass die Bewegung an Stärke gewonnen hat, während sie in Wirklichkeit schnell wieder zurückkommen kann, und Sie werden von dem Stopp getroffen.

Nun, da Sie dies wissen, werden Sie verstehen, dass eine große Serie von Kerzen, die den Schatten nicht berühren, ausgelöste Stopp-Orders darstellen. In der Tat ist es unmöglich, diese Bewegung genau zu erfassen, wenn sie stattfindet, da alles sehr schnell geht. Aber Sie können die Interpretation der BID- und ASK-Werte nutzen, um herauszufinden, warum dies geschehen ist. Das hängt von Ihnen und Ihrer Markterfahrung ab. Ich werde nicht ins Detail gehen, aber dies ist etwas, auf das Sie sich konzentrieren sollten, wenn Sie das Bandmaß wirklich als Indikator verwenden wollen.

Jetzt kommt das Detail: Wenn diese Informationen nur mit Hilfe von Kerzen gesehen werden können und sie selbst ausreichen, um einige Informationen zu erfahren, warum ist es dann so notwendig, mehr Daten zu haben?

Das große Detail ist, dass es Zeiten gibt, in denen der Markt langsamer ist und auf einige Informationen wartet, die im Moment herauskommen können, aber wir können dies nicht wissen, indem wir einfach die Times & Trade mit Kerzen betrachten. Wir brauchen etwas mehr als das. Diese Informationen sind im System selbst vorhanden, aber es ist schwierig, sie so zu interpretieren, wie sie kommen. Die Daten sollten modelliert werden, damit sie leichter analysiert werden können.

Diese Modellierung ist der Grund, warum ich diesen Artikel schreibe: Nach der Modellierung wird Times & Trade wie folgt aussehen:

Mit anderen Worten, wir werden ein vollständiges Bild von den Geschehnissen haben. Außerdem wird alles schnell gehen, was für diejenigen wichtig ist, die das Ablesen von Bändern als Mittel zum Handel nutzen wollen.


Umsetzung

Um das System zu implementieren, müssen wir der Klasse C_TimesAndTrade mehrere neue Variablen hinzufügen. Sie werden durch den nachstehenden Code ausgeführt:

#include <NanoEA-SIMD\Auxiliar\C_FnSubWin.mqh>
#include <NanoEA-SIMD\Auxiliar\C_Canvas.mqh>
//+------------------------------------------------------------------+
class C_TimesAndTrade : private C_FnSubWin
{
//+------------------------------------------------------------------+
#define def_SizeBuff 
2048 
#define macro_Limits(A) (A & 0xFF)
#define def_MaxInfos 257
//+------------------------------------------------------------------+
        private :
                string          m_szCustomSymbol,
                                m_szObjName;
                char            m_ConnectionStatus;
                datetime        m_LastTime;
                ulong           m_MemTickTime;
                int             m_CountStrings;
                struct st0
                {
                        string  szTime;
                        int     flag;
                }m_InfoTrades[def_MaxInfos];
                struct st1
                {
                        C_Canvas Canvas;
                        int      WidthRegion,
                                 PosXRegion,
                                 MaxY;
                        string   szNameCanvas;
                }m_InfoCanvas;


Die Hervorhebung zeigt die Teile an, die dem Quellcode hinzugefügt wurden. Wie Sie sehen, müssen wir die Klasse C_Canvas verwenden, aber sie hat nicht alle Elemente, die wir brauchen. Tatsächlich müssen wir vier Unterprogramme zu dieser C_Canvas-Klasse hinzufügen. Diese Unterprogramme sind im folgenden Code dargestellt:

// ... C_Canvas class code

inline void FontSet(const string name, const int size, const uint flags = 0, const uint angle = 0)
{
        if(!TextSetFont(name, size, flags, angle)) return;
        TextGetSize("M", m_TextInfos.width, m_TextInfos.height);
}
//+------------------------------------------------------------------+
inline void TextOutFast(int x, int y, string text, const uint clr, uint alignment = 0)
{
        TextOut(text, x, y, alignment, m_Pixel, m_width, m_height, clr, COLOR_FORMAT_ARGB_NORMALIZE);
}
//+------------------------------------------------------------------+
inline int TextWidth(void) const { return m_TextInfos.width; }
//+------------------------------------------------------------------+
inline int TextHeight(void) const { return m_TextInfos.height; }
//+------------------------------------------------------------------+

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

Diese Zeilen erzeugen Text. Sehr einfach, nichts besonders Elegantes.

Die nächste erwähnenswerte Funktion in dieser Klasse ist C_TimesAndTrade:

void PrintTimeTrade(void)
{
        int ui1;
        
        m_InfoCanvas.Canvas.Erase(clrBlack, 220);
        for (int c0 = 0, c1 = m_CountStrings - 1, y = 2; (c0 <= 255) && (y < m_InfoCanvas.MaxY); c0++, c1--, y += m_InfoCanvas.Canvas.TextHeight())
        if (m_InfoTrades[macro_Limits(c1)].szTime == NULL) break; else
        {
                ui1 = m_InfoTrades[macro_Limits(c1)].flag;
                m_InfoCanvas.Canvas.TextOutFast(2, y, m_InfoTrades[macro_Limits(c1)].szTime, macroColorRGBA((ui1 == 0 ? clrLightSkyBlue : (ui1 > 0 ? clrForestGreen : clrFireBrick)), 220));
        }
        m_InfoCanvas.Canvas.Update();
}

Mit dieser Funktion werden die Werte in dem dafür reservierten Bereich angezeigt. Darüber hinaus wurde auch die Initialisierungsprozedur geringfügig geändert, was unten im hervorgehobenen Teil zu sehen ist:

void Init(const int iScale = 2)
{
        if (!ExistSubWin())
        {
                m_InfoCanvas.Canvas.FontSet("Lucida Console", 13);
                m_InfoCanvas.WidthRegion = (18 * m_InfoCanvas.Canvas.TextWidth()) + 4;
                CreateCustomSymbol();
                CreateChart();
                m_InfoCanvas.Canvas.Create(m_InfoCanvas.szNameCanvas, m_InfoCanvas.PosXRegion, 0, m_InfoCanvas.WidthRegion, TerminalInfoInteger(TERMINAL_SCREEN_HEIGHT), GetIdSubWinEA());
                Resize();
                m_ConnectionStatus = 0;
        }
        ObjectSetInteger(Terminal.Get_ID(), m_szObjName, OBJPROP_CHART_SCALE, (iScale > 5 ? 5 : (iScale < 0 ? 0 : iScale)));
}

Zusätzliche Änderungen waren auch bei der Substitutionsroutine in Times & Trade erforderlich. Die Änderungen sind wie folgt:

void Resize(void)
{
        static int MaxX = 0;
        int x = (int) ChartGetInteger(Terminal.Get_ID(), CHART_WIDTH_IN_PIXELS, GetIdSubWinEA());
        
        m_InfoCanvas.MaxY = (int) ChartGetInteger(Terminal.Get_ID(), CHART_HEIGHT_IN_PIXELS, GetIdSubWinEA());
        ObjectSetInteger(Terminal.Get_ID(), m_szObjName, OBJPROP_YSIZE, m_InfoCanvas.MaxY);
        if (MaxX != x)
        {
                MaxX = x;
                x -= m_InfoCanvas.WidthRegion;
                ObjectSetInteger(Terminal.Get_ID(), m_szObjName, OBJPROP_XSIZE, x);
                ObjectSetInteger(Terminal.Get_ID(), m_InfoCanvas.szNameCanvas, OBJPROP_XDISTANCE, x);
        }
        PrintTimeTrade();
}

Das System ist fast fertig, aber wir brauchen noch die Unterroutine, die das Herzstück des Systems ist. Sie wurde ebenfalls geändert:

inline void Update(void)
{
        MqlTick Tick[];
        MqlRates Rates[def_SizeBuff];
        int i0, p1, p2 = 0;
        int iflag;
        long lg1;
        static int nSwap = 0;
        static long lTime = 0;

        if (m_ConnectionStatus < 3) return;
        if ((i0 = CopyTicks(Terminal.GetFullSymbol(), Tick, COPY_TICKS_ALL, m_MemTickTime, def_SizeBuff)) > 0)
        {
                for (p1 = 0, p2 = 0; (p1 < i0) && (Tick[p1].time_msc == m_MemTickTime); p1++);
                for (int c0 = p1, c1 = 0; c0 < i0; c0++)
                {
                        lg1 = Tick[c0].time_msc - lTime;
                        nSwap++;
                        if (Tick[c0].volume == 0) continue;
                        iflag = 0;
                        iflag += ((Tick[c0].flags & TICK_FLAG_BUY) == TICK_FLAG_BUY ? 1 : 0);
                        iflag -= ((Tick[c0].flags & TICK_FLAG_SELL) == TICK_FLAG_SELL ? 1 : 0);
                        if (iflag == 0) continue;
                        Rates[c1].high = Tick[c0].ask;
                        Rates[c1].low = Tick[c0].bid;
                        Rates[c1].open = Tick[c0].last;
                        Rates[c1].close = Tick[c0].last + ((Tick[c0].volume > 200 ? 200 : Tick[c0].volume) * (Terminal.GetTypeSymbol() == C_Terminal::WDO ? 0.02 : 1.0) * iflag);
                        Rates[c1].time = m_LastTime;
                        m_InfoTrades[macro_Limits(m_CountStrings)].szTime = StringFormat("%02.d.%03d ~ %02.d <>%04.d", ((lg1 - (lg1 % 1000)) / 1000) % 60 , lg1 % 1000, nSwap, Tick[c0].volume);
                        m_InfoTrades[macro_Limits(m_CountStrings)].flag = iflag;
                        m_CountStrings++;
                        nSwap = 0;
			lTime = Tick[c0].time_msc;
                        p2++;
                        c1++;
                        m_LastTime += 60;
                }
                CustomRatesUpdate(m_szCustomSymbol, Rates, p2);
                m_MemTickTime = Tick[i0 - 1].time_msc;
        }
        PrintTimeTrade();
}

Die hervorgehobenen Zeilen stellen den Code dar, der dem Unterprogramm zur Modellierung der benötigten Daten hinzugefügt wurde. Der folgende Code

lg1 = Tick[c0].time_msc - lTime;
nSwap++;


prüft, wie viel Zeit zwischen den Abschlüssen in Millisekunden verstrichen ist und wie viele Abschlüsse, die nicht zu einer Preisänderung geführt haben, stattgefunden haben. Wenn diese Zahlen hoch sind, können Sie verstehen, dass der Umsatz sinkt. Mit dieser Funktion werden Sie dies früher als andere bemerken.

Im folgenden Teil

m_InfoTrades[macro_Limits(m_CountStrings)].szTime = StringFormat("%02.d.%03d ~ %02.d <>%04.d", ((lg1 - (lg1 % 1000)) / 1000) % 60 , lg1 % 1000, nSwap, Tick[c0].volume);
m_InfoTrades[macro_Limits(m_CountStrings)].flag = iflag;
m_CountStrings++;
nSwap = 0;                                      
lTime = Tick[c0].time_msc;

werden die Werte, die präsentiert werden sollen, bearbeitet. Bitte beachten Sie, dass wir den Zähler m_CountStrings aufgrund seiner begrenzten Verwendung nicht testen werden. Wir werden die Werte einfach erhöhen, wenn neue Informationen verfügbar werden. Dies ist ein Trick, der manchmal angewendet werden kann. Ich selbst verwende es, wenn es möglich ist, denn es ist effizient in der Verarbeitung, was wichtig ist, da das Handelssystem für den Einsatz in Echtzeit konzipiert ist. Sie sollten immer versuchen, das System zu optimieren, wann immer es möglich ist, auch wenn es nur ein wenig ist - am Ende macht es einen großen Unterschied.

Nachdem wir alles implementiert haben, kompilieren wir den Expert Advisor und erhalten in etwa folgendes Ergebnis:


Wenn Sie die oben beschriebenen Bewegungen auf dem Times & Trade-Chart beobachten, können Sie sehen, dass sich im Times & Trade selbst Mikrostrukturen bilden. Aber auch nach dem Studium dieser Mikrostrukturen konnte ich keinen Vorteil aus der Tatsache ziehen, dass es sie gibt. Allerdings bin ich kein so erfahrener Händler, also wer weiß, vielleicht kann es jemand mit mehr Erfahrung tun.

Dieser Indikator ist so aussagekräftig und informativ, dass ich mich entschlossen habe, ein Video zu drehen, das einen kleinen Vergleich zwischen seinen Werten und den realen Daten zeigt, die der Vermögenswert zum Zeitpunkt des Schreibens anzeigt. Ich möchte zeigen, dass es viele Informationen herausfiltert und es Ihnen ermöglicht, Daten viel schneller zu lesen und besser zu verstehen, was vor sich geht. Ich hoffe, dass Sie diesen fantastischen und leistungsstarken Indikator genießen und nutzen werden.




Schlussfolgerung

Das hier vorgeschlagene System ist einfach eine Abwandlung des in der MetaTrader 5-Plattform selbst verfügbaren Chart-Systems. Was sich geändert hat, ist die Methode der Datenmodellierung. Es kann interessant sein zu sehen, wie geschlossene Positionen die Preisrichtung beeinflussen, indem sie Mikrostrukturen im niedrigsten auf der Plattform verfügbaren Zeitrahmen, d.h. 1 Minute, bilden. Viele Leute sagen gerne, dass sie auf dem Minuten-Zeitrahmen handeln, als ob das bedeuten würde, dass sie ein hohes Maß an Marktkenntnis haben. Wenn man jedoch genauer hinsieht und die Handelsprozesse versteht, wird klar, dass innerhalb einer Minute sehr viel passiert. Obwohl diese Zeitspanne recht kurz erscheint, können wir dadurch viele potenziell profitable Geschäfte verpassen. Denken Sie daran, dass wir in diesem Times & Trade-System nicht das Geschehen innerhalb einer Minute betrachten - die Werte, die auf dem Bildschirm erscheinen, werden in Millisekunden angegeben.


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

Beigefügte Dateien |
EA_-_Times_m_Trade.zip (5983.76 KB)
Indikatoren mit interaktiven Steuerelementen auf dem Chart Indikatoren mit interaktiven Steuerelementen auf dem Chart
Der Artikel bietet eine neue Perspektive auf Indikatorschnittstellen. Ich werde mich auf die Bequemlichkeit konzentrieren. Nachdem ich im Laufe der Jahre Dutzende verschiedener Handelsstrategien ausprobiert und Hunderte verschiedener Indikatoren getestet habe, bin ich zu einigen Schlussfolgerungen gekommen, die ich Ihnen in diesem Artikel mitteilen möchte.
Einen handelnden Expert Advisor von Grund auf neu entwickeln (Teil 12): Times and Trade (I) Einen handelnden Expert Advisor von Grund auf neu entwickeln (Teil 12): Times and Trade (I)
Heute werden wir „Times and Trade“ (Zeiten und Handel) mit einer schnellen Interpretation erstellen, um den Auftragsfluss zu lesen. Es ist der erste Teil, in dem wir das System aufbauen werden. Im nächsten Artikel vervollständigen wir das System mit den fehlenden Informationen. Um diese neue Funktionsweisen zu implementieren, müssen wir dem Code unseres Expert Advisors mehrere neue Dinge hinzufügen.
Lernen Sie, wie man ein Handelssystem mit Williams PR entwirft Lernen Sie, wie man ein Handelssystem mit Williams PR entwirft
Ein neuer Artikel in unserer Serie über das Lernen, wie man ein Handelssystem durch die beliebtesten technischen Indikatoren von MQL5 zu entwerfen, um in den MetaTrader 5 verwendet werden. In diesem Artikel lernen wir, wie man ein Handelssystem mit Hilfe des Indikators Williams' %R entwickelt.
DoEasy. Steuerung (Teil 5): Basisobjekt von WinForms, Paneel-Steuerelement, Parameter AutoSize DoEasy. Steuerung (Teil 5): Basisobjekt von WinForms, Paneel-Steuerelement, Parameter AutoSize
In diesem Artikel werde ich das Basisobjekt aller Bibliotheks-WinForms-Objekte erstellen und mit der Implementierung der AutoSize-Eigenschaft des Paneel-Objekts für WinForms beginnen – automatische Größenanpassung zum Anpassen des internen Inhalts des Objekts.