![Das Erstellen einer neuen Handelsstrategie und sich die Positionseröffnungen durch Indikatoren bestimmen lassen](https://c.mql5.com/i/articles/overlay.png)
Das Erstellen einer neuen Handelsstrategie und sich die Positionseröffnungen durch Indikatoren bestimmen lassen
Einführung
Es ist bekannt, dass nur 5% der Händler stabile Gewinne auf den Finanzmärkten erzielen, obwohl die alle 100% erreichen wollen.
Um erfolgreich zu handeln, braucht man eine profitable Handelsstrategie. Themenbezogene Webseiten und Fachliteratur zum Thema Handel beschreiben Hunderte von verschiedenen Handelsstrategien. Eine detaillierte Interpretation der Signale ist für allen Indikatoren erhältlich, aber die Statistik bleibt unverändert: Die 5% sind weder zu 100%, nicht einmal zu 10% geworden. Ideologen des Handels machen die Instabilität des Marktes verantwortlich, was zur Folge hat, dass frühere profitable Strategien auf einmal an Wirksamkeit verlieren.
In meinem vorherigen Artikel habe ich bereits über die Bestimmung der Eröffnungen durch Indikatoren geschrieben und ein Beispiel für die Verbesserung einer bestehenden Strategie gezeigt. Jetzt schlage ich vor, eine individuelle Strategie "auf einem leeren Blatt" und der angegebenen Technologie zu erstellen. Dies wird uns erlauben, die Indikatoren mit einem "ganz neuen Blick" zu betrachten, eigene Muster für Indikatoren zu sammeln und ihre Signale zu überdenken. Die Anwendung der vorgeschlagenen Technologie impliziert einen kreativen Ansatz zur Interpretation der Signale von Indikatoren, der es jedem Benutzer ermöglicht, eine eigene, einzigartige Strategie zu entwickeln.
1. Erstellung eines Modells für Tests und Analysen
Das erste, was wir in einem Handelsterminal sehen, ist eine kontinuierliche Kursentwicklung. Möglicherweise könnten wir, nachdem zu irgendeinem Zeitpunkt eine Position eröffnete wurde, einen Profit erzielen. Aber wie können wir erkennen, wohin und wie stark der Preis sich im nächsten Moment bewegt? Auf diese Frage versuchen Händler mit der technischen und fundamentalen Analysen eine Antwort zu finden. Für die Durchführung der technischen Analyse werden immer wieder die verschiedensten Indikatoren neu erfunden oder verbessert. Die Neuheit liegt hier in der Interpretation dieser Indikatorensignale, die sich von den üblichen unterscheiden können.
Die Methode, die Eröffnung sich von den Indikatoren bestimmen zu lassen, impliziert somit den Vergleich von eröffneten Positionen mit Indikatorwerten. Noch einmal, theoretisch, könnten wir jederzeit Profit erzielen. Auf der Grundlage dieser Eingangsdaten öffnen wir zu Beginn jeder bar zwei bidirektionale Positionen mit den festgelegten Parametern. Dann analysieren wir, wie der Profit jeder Position von den Indikatorwerten abhängt.
Um dieses Problem zu bewältigen, müssen wir ein paar Dinge vorbereiten.
1.1. Erstellen einer Klasse für virtuelle Aufträge
Es wird ein Netting-Konto verwendet. Um bidirektionale Aufträge zu eröffnen, werde ich daher virtuelle Aufträge erstellen, die nicht vom Terminal (je nach Kontoeinstellungen), sondern vom Expert Advisor verfolgt werden. Dazu wird die Klasse CDeal erstellt. Bei der Initialisierung wird einer Klasseninstanz übergeben: Symbolname, Positionstyp, Eröffnungszeit und Preis, sowie StopLoss und TakeProfit. Das Positionsvolumen wird bewusst weggelassen, da es hier nicht von Interesse ist. Das Wichtigste für uns ist die Preisbewegung, deshalb werden Gewinn und Verlust in 'points' anstatt in Geldbeträgen berechnet.
Der Vollständigkeit halber wurde die Klasse mit folgenden Funktionen zum Status versehen:
- IsClosed — Rückgabe eines booleschen Wertes zurück, je nachdem die Position geschlossen ist oder nicht;
- Type — Rückgabe des Typs der Position;
- GetProfit — Rückgabe des Gewinns einer geschlossenen Position (Verluste sind negative Werte);
- GetTime — Rückgabe der Eröffnungszeit.
class CDeal : public CObject { private: string s_Symbol; datetime dt_OpenTime; // Time of open position double d_OpenPrice; // Price of opened position double d_SL_Price; // Stop Loss of position double d_TP_Price; // Take Profit of position ENUM_POSITION_TYPE e_Direct; // Direct of opened position double d_ClosePrice; // Price of close position int i_Profit; // Profit of position in pips //--- double d_Point; public: CDeal(string symbol, ENUM_POSITION_TYPE type,datetime time,double open_price,double sl_price, double tp_price); ~CDeal(); //--- Check status bool IsClosed(void); ENUM_POSITION_TYPE Type(void) { return e_Direct; } double GetProfit(void); datetime GetTime(void) { return dt_OpenTime; } //--- void Tick(void); };
Eingehende Ticks werden in der Funktion Tick verarbeitet, die eine Position durch Stop-Loss oder Take-Profit überprüft und ggf. schließt und den kumulierten Gewinn speichert.
void CDeal::Tick(void) { if(d_ClosePrice>0) return; double price=0; switch(e_Direct) { case POSITION_TYPE_BUY: price=SymbolInfoDouble(s_Symbol,SYMBOL_BID); if(d_SL_Price>0 && d_SL_Price>=price) { d_ClosePrice=price; i_Profit=(int)((d_ClosePrice-d_OpenPrice)/d_Point); } else { if(d_TP_Price>0 && d_TP_Price<=price) { d_ClosePrice=price; i_Profit=(int)((d_ClosePrice-d_OpenPrice)/d_Point); } } break; case POSITION_TYPE_SELL: price=SymbolInfoDouble(s_Symbol,SYMBOL_ASK); if(d_SL_Price>0 && d_SL_Price<=price) { d_ClosePrice=price; i_Profit=(int)((d_OpenPrice-d_ClosePrice)/d_Point); } else { if(d_TP_Price>0 && d_TP_Price>=price) { d_ClosePrice=price; i_Profit=(int)((d_OpenPrice-d_ClosePrice)/d_Point); } } break; } }
1.2. Erstellen einer Klasse für die Indikatoren
Um die Werte der Indikatoren zu speichern und zu analysieren, habe ich die im vorherigen Artikel beschriebenen Klassen verwendet. Außerdem habe ich hier die Klasse CDealsToIndicators erstellt, die alle Indikatorklassen verallgemeinert. Sie speichert die Arrays der Indikatorklassen und organisiert deren Funktionieren.
class CDealsToIndicators { private: CADX *ADX[]; CAlligator *Alligator[]; COneBufferArray *OneBuffer[]; CMACD *MACD[]; CStaticOneBuffer *OneBufferStatic[]; CStaticMACD *MACD_Static[]; CStaticADX *ADX_Static[]; CStaticAlligator *Alligator_Static[]; template<typename T> void CleareArray(T *&array[]); public: CDealsToIndicators(); ~CDealsToIndicators(); //--- bool AddADX(string symbol, ENUM_TIMEFRAMES timeframe, int period, string name); bool AddADX(string symbol, ENUM_TIMEFRAMES timeframe, int period, string name, int &handle); bool AddAlligator(string symbol,ENUM_TIMEFRAMES timeframe,uint jaw_period, uint jaw_shift, uint teeth_period, uint teeth_shift, uint lips_period, uint lips_shift, ENUM_MA_METHOD method, ENUM_APPLIED_PRICE price, string name); bool AddAlligator(string symbol,ENUM_TIMEFRAMES timeframe,uint jaw_period, uint jaw_shift, uint teeth_period, uint teeth_shift, uint lips_period, uint lips_shift, ENUM_MA_METHOD method, ENUM_APPLIED_PRICE price, string name, int &handle); bool AddMACD(string symbol, ENUM_TIMEFRAMES timeframe, uint fast_ema, uint slow_ema, uint signal, ENUM_APPLIED_PRICE applied_price, string name); bool AddMACD(string symbol, ENUM_TIMEFRAMES timeframe, uint fast_ema, uint slow_ema, uint signal, ENUM_APPLIED_PRICE applied_price, string name, int &handle); bool AddOneBuffer(int handle, string name); //--- bool SaveNewValues(long ticket); //--- bool Static(CArrayObj *deals); };
1.3. Erstellen des Expert Advisors für die Tests
Alles ist vorbereitet. Fahren wir fort mit dem Erstellen des EAs, der im Strategietester laufen soll. Zuerst definieren wir die Liste der zu verwendeten Indikator mit ihren Parametern. Beispielsweise wurden folgende Indikatoren ausgewählt:
- ADX;
- Alligator;
- CCI;
- Chaikin;
- Force Index;
- MACD.
Für jeden werden drei Sätze von Parametern für 3 Zeitrahmen erstellt.
Stop-Loss und Take-Profit werden an den ATR gebunden und mittels des Verhältnisses von Gewinn und Risiko ermittelt.
//--- Eingabeparameter input double Reward_Risk = 1.0; input int ATR_Period = 288; input ENUM_TIMEFRAMES TimeFrame1 = PERIOD_M5; input ENUM_TIMEFRAMES TimeFrame2 = PERIOD_H1; input ENUM_TIMEFRAMES TimeFrame3 = PERIOD_D1; input string s1 = "ADX" ; //--- input uint ADX_Period1 = 14 ; input uint ADX_Period2 = 28 ; input uint ADX_Period3 = 56 ; input string s2 = "Alligator" ; //--- input uint JAW_Period1 = 13 ; input uint JAW_Shift1 = 8 ; input uint TEETH_Period1 = 8 ; input uint TEETH_Shift1 = 5 ; input uint LIPS_Period1 = 5 ; input uint LIPS_Shift1 = 3 ; input uint JAW_Period2 = 26 ; input uint JAW_Shift2 = 16 ; input uint TEETH_Period2 = 16 ; input uint TEETH_Shift2 = 10 ; input uint LIPS_Period2 = 10 ; input uint LIPS_Shift2 = 6 ; input uint JAW_Period3 = 42 ; input uint JAW_Shift3 = 32 ; input uint TEETH_Period3 = 32 ; input uint TEETH_Shift3 = 20 ; input uint LIPS_Period3 = 20 ; input uint LIPS_Shift3 = 12 ; input ENUM_MA_METHOD Alligator_Method = MODE_SMMA ; input ENUM_APPLIED_PRICE Alligator_Price = PRICE_MEDIAN ; input string s5 = "CCI" ; //--- input uint CCI_Period1 = 14 ; input uint CCI_Period2 = 28 ; input uint CCI_Period3 = 56 ; input ENUM_APPLIED_PRICE CCI_Price = PRICE_TYPICAL ; input string s6 = "Chaikin" ; //--- input uint Ch_Fast_Period1 = 3 ; input uint Ch_Slow_Period1 = 14 ; input uint Ch_Fast_Period2 = 6 ; input uint Ch_Slow_Period2 = 28 ; input uint Ch_Fast_Period3 = 12 ; input uint Ch_Slow_Period3 = 56 ; input ENUM_MA_METHOD Ch_Method = MODE_EMA ; input ENUM_APPLIED_VOLUME Ch_Volume = VOLUME_TICK ; input string s7 = "Force Index" ; //--- input uint Force_Period1 = 14 ; input uint Force_Period2 = 28 ; input uint Force_Period3 = 56 ; input ENUM_MA_METHOD Force_Method = MODE_SMA ; input ENUM_APPLIED_VOLUME Force_Volume = VOLUME_TICK ; input string s8 = "MACD" ; //--- input uint MACD_Fast1 = 12 ; input uint MACD_Slow1 = 26 ; input uint MACD_Signal1 = 9 ; input uint MACD_Fast2 = 24 ; input uint MACD_Slow2 = 52 ; input uint MACD_Signal2 = 18 ; input uint MACD_Fast3 = 48 ; input uint MACD_Slow3 = 104 ; input uint MACD_Signal3 = 36 ; input ENUM_APPLIED_PRICE MACD_Price = PRICE_CLOSE ;
Im Block der globalen Variablen deklarieren wir:
- Das Array zum Speichern der Klassen der Positionen "Deals",
- Für die Arbeit mit den Indikatoren die Instanz "IndicatorsStatic",
- Die Variable für das Handle zum ATR,
- Zwei Hilfsvariablen für die Zeit der letzten, bearbeiteten Bar (last_bar) und für die letzte geschlossene Position (last_closed_deal). Die letztere wird benötigt um nicht bei jedem Tick erneut durch alle geschlossenen Positionen zu gehen.
In der Funktion OnInit werden diese globalen Variablen und die benötigten Indikatoren initialisiert.
int OnInit() { //--- last_bar=0; last_closed_deal=0; //--- Deals = new CArrayObj(); if(CheckPointer(Deals)==POINTER_INVALID) return INIT_FAILED; //--- IndicatorsStatic = new CDealsToIndicators(); if(CheckPointer(IndicatorsStatic)==POINTER_INVALID) return INIT_FAILED; //--- atr=iATR(_Symbol,TimeFrame1,ATR_Period); if(atr==INVALID_HANDLE) return INIT_FAILED; //--- AddIndicators(TimeFrame1); AddIndicators(TimeFrame2); AddIndicators(TimeFrame3); //--- return(INIT_SUCCEEDED); }
Es werden dieselben Sätze der Indikatoren für alle drei Zeitrahmen verwendet. Darum ist es sinnvoll, die Initialisierung der Klassen der Indikatoren von einer eigenen Funktion durchführen zu lassen. Der Zeitrahmen wird als Parameter übergeben.
bool AddIndicators(ENUM_TIMEFRAMES timeframe) { if(CheckPointer(IndicatorsStatic)==POINTER_INVALID) { IndicatorsStatic = new CDealsToIndicators(); if(CheckPointer(IndicatorsStatic)==POINTER_INVALID) return false; } string tf_name=StringSubstr(EnumToString(timeframe),7); string name="ADX("+IntegerToString(ADX_Period1)+") "+tf_name; if(!IndicatorsStatic.AddADX(_Symbol, timeframe, ADX_Period1, name)) return false; name="ADX("+IntegerToString(ADX_Period2)+") "+tf_name; if(!IndicatorsStatic.AddADX(_Symbol, timeframe, ADX_Period2, name)) return false; name="ADX("+IntegerToString(ADX_Period3)+") "+tf_name; if(!IndicatorsStatic.AddADX(_Symbol, timeframe, ADX_Period3, name)) return false; name="Alligator("+IntegerToString(JAW_Period1)+","+IntegerToString(TEETH_Period1)+","+IntegerToString(LIPS_Period1)+") "+tf_name; if(!IndicatorsStatic.AddAlligator(_Symbol, timeframe, JAW_Period1, JAW_Shift1, TEETH_Period1, TEETH_Shift1, LIPS_Period1, LIPS_Shift1, Alligator_Method, Alligator_Price, name)) return false; name="Alligator("+IntegerToString(JAW_Period2)+","+IntegerToString(TEETH_Period2)+","+IntegerToString(LIPS_Period2)+") "+tf_name; if(!IndicatorsStatic.AddAlligator(_Symbol, timeframe, JAW_Period2, JAW_Shift2, TEETH_Period2, TEETH_Shift2, LIPS_Period2, LIPS_Shift2, Alligator_Method, Alligator_Price, name)) return false; name="Alligator("+IntegerToString(JAW_Period3)+","+IntegerToString(TEETH_Period3)+","+IntegerToString(LIPS_Period3)+") "+tf_name; if(!IndicatorsStatic.AddAlligator(_Symbol, timeframe, JAW_Period3, JAW_Shift3, TEETH_Period3, TEETH_Shift3, LIPS_Period3, LIPS_Shift3, Alligator_Method, Alligator_Price, name)) return false; name="MACD("+IntegerToString(MACD_Fast1)+","+IntegerToString(MACD_Slow1)+","+IntegerToString(MACD_Signal1)+") "+tf_name; if(!IndicatorsStatic.AddMACD(_Symbol, timeframe, MACD_Fast1, MACD_Slow1, MACD_Signal1, MACD_Price, name)) return false; name="MACD("+IntegerToString(MACD_Fast2)+","+IntegerToString(MACD_Slow2)+","+IntegerToString(MACD_Signal2)+") "+tf_name; if(!IndicatorsStatic.AddMACD(_Symbol, timeframe, MACD_Fast2, MACD_Slow2, MACD_Signal2, MACD_Price, name)) return false; name="MACD("+IntegerToString(MACD_Fast3)+","+IntegerToString(MACD_Slow3)+","+IntegerToString(MACD_Signal3)+") "+tf_name; if(!IndicatorsStatic.AddMACD(_Symbol, timeframe, MACD_Fast3, MACD_Slow3, MACD_Signal3, MACD_Price, name)) return false; name="CCI("+IntegerToString(CCI_Period1)+") "+tf_name; int handle = iCCI(_Symbol, timeframe, CCI_Period1, CCI_Price); if(handle<0 || !IndicatorsStatic.AddOneBuffer(handle, name) ) return false; name="CCI("+IntegerToString(CCI_Period2)+") "+tf_name; handle = iCCI(_Symbol, timeframe, CCI_Period2, CCI_Price); if(handle<0 || !IndicatorsStatic.AddOneBuffer(handle, name) ) return false; handle = iCCI(_Symbol, timeframe, CCI_Period3, CCI_Price); name="CCI("+IntegerToString(CCI_Period3)+") "+tf_name; if(handle<0 || !IndicatorsStatic.AddOneBuffer(handle, name) ) return false; handle = iForce(_Symbol, timeframe, Force_Period1, Force_Method, Force_Volume); name="Force("+IntegerToString(Force_Period1)+") "+tf_name; if(handle<0 || !IndicatorsStatic.AddOneBuffer(handle, name) ) return false; handle = iForce(_Symbol, timeframe, Force_Period2, Force_Method, Force_Volume); name="Force("+IntegerToString(Force_Period2)+") "+tf_name; if(handle<0 || !IndicatorsStatic.AddOneBuffer(handle, name) ) return false; handle = iForce(_Symbol, timeframe, Force_Period3, Force_Method, Force_Volume); name="Force("+IntegerToString(Force_Period3)+") "+tf_name; if(handle<0 || !IndicatorsStatic.AddOneBuffer(handle, name) ) return false; name="CHO("+IntegerToString(Ch_Slow_Period1)+","+IntegerToString(Ch_Fast_Period1)+") "+tf_name; handle = iChaikin(_Symbol, timeframe, Ch_Fast_Period1, Ch_Slow_Period1, Ch_Method, Ch_Volume); if(handle<0 || !IndicatorsStatic.AddOneBuffer(handle, name) ) return false; handle = iChaikin(_Symbol, timeframe, Ch_Fast_Period2, Ch_Slow_Period2, Ch_Method, Ch_Volume); name="CHO("+IntegerToString(Ch_Slow_Period2)+","+IntegerToString(Ch_Fast_Period2)+") "+tf_name; if(handle<0 || !IndicatorsStatic.AddOneBuffer(handle, name) ) return false; handle = iChaikin(_Symbol, timeframe, Ch_Fast_Period3, Ch_Slow_Period3, Ch_Method, Ch_Volume); name="CHO("+IntegerToString(Ch_Slow_Period3)+","+IntegerToString(Ch_Fast_Period3)+") "+tf_name; if(handle<0 || !IndicatorsStatic.AddOneBuffer(handle, name) ) return false; return true; }
Die in OnTick ausgeführten Operationen können in zwei Blöcke unterteilt werden: Überprüfen der offenen Positionen und Eröffnen neuer Positionen.
Der erste Block der Operationen wird bei jedem Tick ausgeführt. Darin wird für jede offenen Positionen im Array die Funktion Tick ausgeführt. Es wird das Schließen der Position durch Stop-Loss oder Take-Profit geprüft und, falls notwendig, wird eine Position zum aktuellen Kurs, um den Gewinn zu sichern, geschlossen. Um bereits geschlossene Positionen nicht erneut zu überprüfen, wird in der Variable last_closed_deal die Nummer der letzten Position gespeichert, die der ersten, noch offenen Position vorausgeht.
void OnTick() { //--- int total=Deals.Total(); CDeal *deal; bool found=false; for(int i=last_closed_deal;i<total;i++) { deal = Deals.At(i); if(CheckPointer(deal)==POINTER_INVALID) continue; if(!found) { if(deal.IsClosed()) { last_closed_deal=i; continue; } else found=true; } deal.Tick(); }
Der zweite Block beginnt mit der Überprüfung des Auftretens neuer Bars. Bei einer neuen Bar werden die Werte des ATR der gerade geschlossenen Bar abgefragt und die Stop-Loss und Take-Profit entsprechend den eingestellten Parametern angepasst und die virtuellen Positionen eröffnet. Für jede Position speichern wir die Indikatorwerte durch den Aufruf der Funktion SaveNewValues der Klasse für die Arbeit mit Indikatoren.
//--- datetime cur_bar=(datetime)SeriesInfoInteger(_Symbol,PERIOD_CURRENT,SERIES_LASTBAR_DATE); datetime cur_time=TimeCurrent(); if(cur_bar==last_bar || (cur_time-cur_bar)>10) return; double atrs[]; if(CopyBuffer(atr,0,1,1,atrs)<=0) return; last_bar=cur_bar; double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK); double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID); double stops=MathMax(2*atrs[0],SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL)*_Point); double sl=NormalizeDouble(stops,_Digits); double tp=NormalizeDouble(Reward_Risk*(stops+ask-bid),_Digits); deal = new CDeal(_Symbol,POSITION_TYPE_BUY,TimeCurrent(),ask,bid-sl,ask+tp); if(CheckPointer(deal)!=POINTER_INVALID) if(Deals.Add(deal)) IndicatorsStatic.SaveNewValues(Deals.Total()-1); deal = new CDeal(_Symbol,POSITION_TYPE_SELL,TimeCurrent(),bid,ask+sl,bid-tp); if(CheckPointer(deal)!=POINTER_INVALID) if(Deals.Add(deal)) IndicatorsStatic.SaveNewValues(Deals.Total()-1); return; }
In OnTester sammeln wir die Ergebnisse des Testlaufs und erstellen die Diagramme für die Analyse. Dazu wird die Funktion "Static" der Klasse für das Arbeiten mit den Indikatoren auf.
Es sollte nicht vergessen werden, den Speicher in der Funktion OnDeinit wieder freizugeben!
Der vollständige Code des EA und der Klassen findet sich im Anhang.
2. Analyse der Testergebnisse
So, der EA ist erstellt. Definieren wir nun den Zeitraum der Analyse. Bei der Wahl des Zeitraumes sollte berücksichtigt werden, dass sie lang genug sein sollte, um die Objektivität der Analyse zu gewährleisten. Und noch eine Anforderung an den Zeitraum: Es sollte nicht nur Bewegungen in Richtung sondern mehrere geben dazu auch Seitwärtsbewegungen. Dieser Ansatz wird eine Handelsstrategie schaffen, die in Zeiten einer Bewegung Gewinne generieren kann. Im vorliegenden Beispiel wurde für den EURUSD der Zeitraum vom 01.01.2016 bis zum 01.01.2017 analysiert.
Da unser Prozess iterativ ist, würde ich nach dem Speichern aller notwendigen Parameter des Test-Experten empfehlen, die Set-Datei der Parameter für die weitere Arbeit zu speichern.
Jede Testphase wird in 2 Durchläufen mit einem Verhältnis von Gewinn/Risiko von 1/1 und 15/1 durchgeführt. Im ersten Durchlauf schätzen wir die Wahrscheinlichkeit einer Richtung der Preisbewegung, und im zweiten Durchlauf - die Kraft der Bewegung.
Der Expert Advisor zeigt viele Diagramme für die Analyse an, daher sind sie nicht vollständig in dem Artikel aufgeführt - alle Berichte befinden sich im Anhang. Hier werde ich nur jene Diagramme zeigen, in denen Entscheidungen über die Verwendung von Indikatoren in der neuen Strategie getroffen wurden.
2.1. Stufe eins
Wie zu erwarten, zeigte die erste Testphase keine eindeutigen profitablen Bereiche. Gleichzeitig sollte man aber auch auf die den Indikator Force Index achten. Im Zeitrahmen von M5 sinkt die Abhängigkeit der Handelsgewinne von den Indikatorwerten gegen Null. Die Bedeutung dieser Beobachtung wird durch die Tatsache belegt, dass dieses Phänomen in analytischen Indikatordiagrammen mit allen für die Prüfung verwendeten Parametern auftritt. Für unser Muster wählen wir Parameter mit dem deutlichstem Charakter (maximaler Drawdown).
Vergrößern Sie den Maßstab des analysierten Diagramms. Wir sehen einen Effekt dieses Faktors im Bereich von -0,01 bis 0,01. Das beobachtete Phänomen gilt gleichermaßen für Kauf- und Verkaufstransaktionen.
Diese Beobachtung kann durch die fehlende Volatilität des beobachteten Wertebereichs erklärt werden. Wir sehen für unsere Strategie das Verbot der Eröffnung von Positionen in diesem Bereich.
Übernehmen wir diesen Filter in unseren EA. Dazu ergänzen wir als erstes eine globale Variable für das Handle dieses Indikators.
int force;
Da der Indikator, den wir als Filter benötigen, bereits im Expert Advisor verwendet wird, starten wir ihn nicht mehr auf dem Chart. Wir weisen einfach das Handle unserer globale Variablen in der Funktion AddIndicators zu. Vergessen wir aber nicht, dass diese Funktion dreimal aufgerufen wird, um die Indikatoren in verschiedenen Zeitrahmen zu initialisieren. Daher müssen wir vor der Zuweisung des Handles des Indikators die Übereinstimmung der Zeitrahmen überprüfen.
handle = iForce(_Symbol, timeframe, Force_Period3, Force_Method, Force_Volume); if(timeframe==TimeFrame1) force=handle;
Fügen wir nun den Filter direkt zur Funktion OnTick hinzu. Es darf nicht vergessen werden, dass die Daten in der Funktion zum Erstellen eines analytischen Diagramms gerundet wurden. Daher müssen wir beim Filtern der Positionen auch die Indikatorwerte runden.
double atrs[]; double force_data[]; if(CopyBuffer(atr,0,1,1,atrs)<=0 || CopyBuffer(force,0,1,1,force_data)<=0) return; // Some error of load indicator's data last_bar=cur_bar; double d_Step=_Point*1000; if(MathAbs(NormalizeDouble(force_data[0]/d_Step,0)*d_Step)<=0.01) return; // Filtered by Force Index
Der vollständige Code des EAs findet sich im Anhang des Artikels.
Nach dem Hinzufügen des Filters zum Expert Advisor führen wir die zweite Testphase durch. Vergessen wir vor dem Test nicht, die zuvor gespeicherten Einstellungen zu laden.
2.2. Stufe zwei
Nachdem ich den Expert Advisor erneut getestet habe, habe ich auf den MACD-Indikator geachtet. Die profitable Zonen zeigen sich auf dem Chart.
In der Grafik mit einem Verhältnis von Gewinn und Risiko von 15/1 sind diese Zonen ausgeprägter, was auf ein Signalpotential in diesen Bereichen hinweisen kann.
Diesen Filter sollten wir dem Code unseres Expert Advisors hinzufügen. Das Verfahren zum Hinzufügen dieses Filters ist ähnlich, wie es in der ersten Stufe beschrieben wurde.
Mit der globalen Variablen:
int macd;
Und der Funktion AddIndicators:
name="MACD("+IntegerToString(MACD_Fast2)+","+IntegerToString(MACD_Slow2)+","+IntegerToString(MACD_Signal2)+") "+tf_name; if(timeframe==TimeFrame1) { if(!IndicatorsStatic.AddMACD(_Symbol, timeframe, MACD_Fast2, MACD_Slow2, MACD_Signal2, MACD_Price, name, macd)) return false; } else { if(!IndicatorsStatic.AddMACD(_Symbol, timeframe, MACD_Fast2, MACD_Slow2, MACD_Signal2, MACD_Price, name)) return false; }
In der Funktion OnTick:
double macd_data[]; if(CopyBuffer(atr,0,1,1,atrs)<=0 || CopyBuffer(force,0,1,1,force_data)<=0 || CopyBuffer(macd,0,1,1,macd_data)<=0) return;
und
double macd_Step=_Point*50; macd_data[0]=NormalizeDouble(macd_data[0]/macd_Step,0)*macd_Step; if(macd_data[0]>=0.0015 && macd_data[0]<=0.0035) { deal = new CDeal(_Symbol,POSITION_TYPE_BUY,TimeCurrent(),ask,bid-sl,ask+tp); if(CheckPointer(deal)!=POINTER_INVALID) if(Deals.Add(deal)) IndicatorsStatic.SaveNewValues(Deals.Total()-1); } if(macd_data[0]<=(-0.0015) && macd_data[0]>=(-0.0035)) { deal = new CDeal(_Symbol,POSITION_TYPE_SELL,TimeCurrent(),bid,ask+sl,bid-tp); if(CheckPointer(deal)!=POINTER_INVALID) if(Deals.Add(deal)) IndicatorsStatic.SaveNewValues(Deals.Total()-1); }
Nachdem Sie den Filter hinzugefügt haben, wechseln Sie zur dritten Stufe.
2.3. Stufe drei
In der dritten Stufe wandte ich mich dem Chaikin-Oszillator zu. Auf den analytischen Diagrammen des Oszillators im Zeitrahmen D1 sehen wir einen Gewinnanstieg bei Kaufposition, wenn die Werte fallen und bei steigenden Werten steigt auch der Gewinn der Verkaufspositionen.
Die Beobachtungen bestätigen sich auch im Diagramm mit einen Gewinn/Risiko-Verhältnis von 15/1.
Fügen wir unsere Beobachtungen zum Code unseres EAs.
Mit der globalen Variablen:
int cho;
Und der Funktion AddIndicators:
handle = iChaikin(_Symbol, timeframe, Ch_Fast_Period2, Ch_Slow_Period2, Ch_Method, Ch_Volume); name="CHO("+IntegerToString(Ch_Slow_Period2)+","+IntegerToString(Ch_Fast_Period2)+") "+tf_name; if(handle<0 || !IndicatorsStatic.AddOneBuffer(handle, name) ) return false; if(timeframe==TimeFrame3) cho=handle;
In der Funktion OnTick:
double cho_data[]; if(CopyBuffer(atr,0,1,1,atrs)<=0 || CopyBuffer(force,0,1,1,force_data)<=0 || CopyBuffer(macd,0,1,1,macd_data)<=0 || CopyBuffer(cho,0,1,2,cho_data)<2) return;
und
if(macd_data[0]>=0.0015 && macd_data[0]<=0.0035 && (cho_data[1]-cho_data[0])<0) { deal = new CDeal(_Symbol,POSITION_TYPE_BUY,TimeCurrent(),ask,bid-sl,ask+tp); if(CheckPointer(deal)!=POINTER_INVALID) if(Deals.Add(deal)) IndicatorsStatic.SaveNewValues(Deals.Total()-1); } if(macd_data[0]<=(-0.0015) && macd_data[0]>=(-0.0035) && (cho_data[1]-cho_data[0])>0) { deal = new CDeal(_Symbol,POSITION_TYPE_SELL,TimeCurrent(),bid,ask+sl,bid-tp); if(CheckPointer(deal)!=POINTER_INVALID) if(Deals.Add(deal)) IndicatorsStatic.SaveNewValues(Deals.Total()-1); }
Kommen wir nun zur nächsten Stufe.
2.4. Stufe vier
Nach erneuten Tests des EAs drängte sich wieder der Zeitrahmen D1 in den Vordergrund. Diesmal aber der Indikator CCI. Seine analytischen Diagramme zeigten ein Gewinnwachstum bei Verkaufsposition, wenn die Indikatorwerte fallen und und ein Gewinnwachstum der Kaufposition, wenn sie steigen. Dieser Trend kann in in allen drei Testperioden beobachtet werden, der maximale Gewinn wurde jedoch mit der Periodenlänge 14, dem Standard dieses Oszillators, erreicht.
Das Diagramm zur Analyse nach dem Test mit dem Verhältnis Gewinn/Risiko = 15/1 bestätigt unsere Beobachtung.
Fügen wir diese Beobachtung auch zum Code unseres EAs.
Mit der globalen Variablen:
int cci;
Und der Funktion AddIndicators:
name="CCI("+IntegerToString(CCI_Period1)+") "+tf_name; int handle = iCCI(_Symbol, timeframe, CCI_Period1, CCI_Price); if(handle<0 || !IndicatorsStatic.AddOneBuffer(handle, name) ) return false; if(timeframe==TimeFrame3) cci=handle;
In der Funktion OnTick:
double cci_data[]; if(CopyBuffer(atr,0,1,1,atrs)<=0 || CopyBuffer(force,0,1,1,force_data)<=0 || CopyBuffer(macd,0,1,1,macd_data)<=0 || CopyBuffer(cho,0,1,2,cho_data)<2 || CopyBuffer(cci,0,1,2,cci_data)<2) return;
und
if(macd_data[0]>=0.0015 && macd_data[0]<=0.0035 && (cho_data[1]-cho_data[0])<0 && (cci_data[1]-cci_data[0])>0) { deal = new CDeal(_Symbol,POSITION_TYPE_BUY,TimeCurrent(),ask,bid-sl,ask+tp); if(CheckPointer(deal)!=POINTER_INVALID) if(Deals.Add(deal)) IndicatorsStatic.SaveNewValues(Deals.Total()-1); } if(macd_data[0]<=(-0.0015) && macd_data[0]>=(-0.0035) && (cho_data[1]-cho_data[0])>0 && (cci_data[1]-cci_data[0])<0) { deal = new CDeal(_Symbol,POSITION_TYPE_SELL,TimeCurrent(),bid,ask+sl,bid-tp); if(CheckPointer(deal)!=POINTER_INVALID) if(Deals.Add(deal)) IndicatorsStatic.SaveNewValues(Deals.Total()-1); }
Der vollständige Code der EAs aus allen Stufen findet sich im Anhang des Artikels.
3. Erstellen und Testen des Expert Advisors für ausgewählte Signale
Perfektion kennt keine Grenzen, man kann immer noch tiefer analysieren und noch mehr Filter hinzufügen, um den Profitfaktor der Strategie noch weiter zu erhöhen. Aber ich glaube, dass die vier vorgestellten Stufen für eine Demonstration der Technologie ausreichen. Im nächsten Schritt erstellen wir einen einfachen EA zur Überprüfung unserer Strategie im Tester. Dies wird es uns ermöglichen, den Gewinn und die Drawdowns unserer Strategie zu beurteilen, sowie die Schwankungen der Salden niedrig zu halten.
In der Strategie verwendeten wir vier Indikatoren, um eine Entscheidung über den Handel zu treffen, und den ATR, um Stop-Loss und Take-Profit zu setzen. Folglich sollten wir in den Eingabeparametern alle Variablen auflisten, die die Indikatoren benötigen. In diesem Stadium werden wir kein Geldmanagement durchführen, alle Positionen erhalten dasselbe, konstante Volumen.
//--- Eingabeparameter input double Lot = 0.1 ; input double Reward_Risk = 15.0 ; input ENUM_TIMEFRAMES ATR_TimeFrame = PERIOD_M5 ; input int ATR_Period = 288 ; input string s1 = "CCI" ; //--- input ENUM_TIMEFRAMES CCI_TimeFrame = PERIOD_D1 ; input uint CCI_Period = 14 ; input ENUM_APPLIED_PRICE CCI_Price = PRICE_TYPICAL ; input string s2 = "Chaikin" ; //--- input ENUM_TIMEFRAMES Ch_TimeFrame = PERIOD_D1 ; input uint Ch_Fast_Period = 6 ; input uint Ch_Slow_Period = 28 ; input ENUM_MA_METHOD Ch_Method = MODE_EMA ; input ENUM_APPLIED_VOLUME Ch_Volume = VOLUME_TICK ; input string s3 = "Force Index" ; //--- input ENUM_TIMEFRAMES Force_TimeFrame = PERIOD_M5 ; input uint Force_Period = 56 ; input ENUM_MA_METHOD Force_Method = MODE_SMA ; input ENUM_APPLIED_VOLUME Force_Volume = VOLUME_TICK ; input string s4 = "MACD" ; //--- input ENUM_TIMEFRAMES MACD_TimeFrame = PERIOD_M5 ; input uint MACD_Fast = 12 ; input uint MACD_Slow = 26 ; input uint MACD_Signal = 9 ; input ENUM_APPLIED_PRICE MACD_Price = PRICE_CLOSE ;
Als globale Variable deklarieren wir:
- eine Instanz der Klasse für die Durchführung des Handels,
- Variablen zur Speicherung der Handles zu den verwendeten Indikatoren,
- Hilfsvariablen zum Speichern der Daten der zuletzt bearbeiteten Bar und der letzten Position,
- Variablen zum Speichern des größten und des kleinsten Zeitrahmens.
In der Funktion OnInit werden die Indikatoren und die Variablen initialisiert.
int OnInit() { //--- last_bar=0; last_deal=0; //--- atr=iATR(_Symbol,ATR_TimeFrame,ATR_Period); if(atr==INVALID_HANDLE) return INIT_FAILED; //--- force=iForce(_Symbol,Force_TimeFrame,Force_Period,Force_Method,Force_Volume); if(force==INVALID_HANDLE) return INIT_FAILED; //--- macd=iMACD(_Symbol,MACD_TimeFrame,MACD_Fast,MACD_Slow,MACD_Signal,MACD_Price); if(macd==INVALID_HANDLE) return INIT_FAILED; //--- cho=iChaikin(_Symbol,Ch_TimeFrame,Ch_Fast_Period,Ch_Slow_Period,Ch_Method,Ch_Volume); if(cho==INVALID_HANDLE) return INIT_FAILED; //--- cci=iCCI(_Symbol,CCI_TimeFrame,CCI_Period,CCI_Price); if(cci==INVALID_HANDLE) return INIT_FAILED; //--- MaxPeriod=fmax(Force_TimeFrame,MACD_TimeFrame); MaxPeriod=fmax(MaxPeriod,Ch_TimeFrame); MaxPeriod=fmax(MaxPeriod,CCI_TimeFrame); MinPeriod=fmin(Force_TimeFrame,MACD_TimeFrame); MinPeriod=fmin(MinPeriod,Ch_TimeFrame); MinPeriod=fmin(MinPeriod,CCI_TimeFrame); //--- return(INIT_SUCCEEDED); }
In der Funktion OnDeinit werden die verwendeten Indikatoren wieder gelöscht.
void OnDeinit(const int reason) { //--- if(atr!=INVALID_HANDLE) IndicatorRelease(atr); //--- if(force==INVALID_HANDLE) IndicatorRelease(force); //--- if(macd==INVALID_HANDLE) IndicatorRelease(macd); //--- if(cho==INVALID_HANDLE) IndicatorRelease(cho); //--- if(cci==INVALID_HANDLE) IndicatorRelease(cci); }
Das Wesentliche geschieht in OnTick. Zu Beginn der Funktion wird die Eröffnung einer neuen Bar überprüft. Eine neue Position wird erst beim Erscheinen einer neuen Bar im kleinsten Zeitrahmen (ich begrenzt auf 10 Sekunden nach der Eröffnung der Bar) eröffnet, und nur, wenn keine Position innerhalb der aktuellen Bar durch den maximalen Zeitrahmen geöffnet wurde. Dadurch wird nur eine Position je Signal eröffnet.
void OnTick() { //--- datetime cur_bar=(datetime)SeriesInfoInteger(_Symbol,MinPeriod,SERIES_LASTBAR_DATE); datetime cur_max=(datetime)SeriesInfoInteger(_Symbol,MaxPeriod,SERIES_LASTBAR_DATE); datetime cur_time=TimeCurrent(); if(cur_bar<=last_bar || (cur_time-cur_bar)>10 || cur_max<=last_deal) return;
Als nächstes erhalten wir die Daten der verwendeten Indikatoren. Im Falle eines Fehlers beim Abrufen von Daten von mindestens einem der Indikatoren, wird die Funktion verlassen.
last_bar=cur_bar; double atrs[]; double force_data[]; double macd_data[]; double cho_data[]; double cci_data[]; if(CopyBuffer(atr,0,1,1,atrs)<=0 || CopyBuffer(force,0,1,1,force_data)<=0 || CopyBuffer(macd,0,1,1,macd_data)<=0 || CopyBuffer(cho,0,1,2,cho_data)<2 || CopyBuffer(cci,0,1,2,cci_data)<2) { return; }
Dann prüfen wir entsprechend unserer Strategie den Wert des Force Index. Wenn der Filter die Situation verwirft, wird die Funktion verlassen bis eine neue Bar erscheint.
double force_Step=_Point*1000; if(MathAbs(NormalizeDouble(force_data[0]/force_Step,0)*force_Step)<=0.01) return;
Der nächste Schritt besteht darin, das Signal zu überprüfen, um eine Kaufposition zu öffnen. Wenn ein positives Signal vorliegt, wird geprüft, ob bereits eine offene Position vorliegt. Wenn ja und es signalisiert einen Verkauf, wird es geschlossen. Wenn eine Kaufposition bereits geöffnet wurde, die sich in einem Verlust befindet, dann wird das Signal ignoriert und die Funktion verlassen.
Danach werden die Parameter der neuen Position berechnet und der Auftrag abgeschickt.
Ähnliche Operationen werden für eine Verkaufsposition durchgeführt.
double macd_Step=_Point*50; macd_data[0]=NormalizeDouble(macd_data[0]/macd_Step,0)*macd_Step; if(macd_data[0]>=0.0015 && macd_data[0]<=0.0035 && (cho_data[1]-cho_data[0])<0 && (cci_data[1]-cci_data[0])>0) { if(PositionSelect(_Symbol)) { switch((int)PositionGetInteger(POSITION_TYPE)) { case POSITION_TYPE_BUY: if(PositionGetDouble(POSITION_PROFIT)<=0) return; break; case POSITION_TYPE_SELL: Trade.PositionClose(_Symbol); break; } } last_deal=cur_max; double stops=MathMax(2*atrs[0],SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL)*_Point); double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK); double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID); double sl=NormalizeDouble(stops,_Digits); double tp=NormalizeDouble(Reward_Risk*(stops+ask-bid),_Digits); double SL=NormalizeDouble(bid-sl,_Digits); double TP=NormalizeDouble(ask+tp,_Digits); if(!Trade.Buy(Lot,_Symbol,ask,SL,TP,"New Strategy")) Print("Error of open BUY ORDER "+Trade.ResultComment()); } if(macd_data[0]<=(-0.0015) && macd_data[0]>=(-0.0035) && (cho_data[1]-cho_data[0])>0 && (cci_data[1]-cci_data[0])<0) { if(PositionSelect(_Symbol)) { switch((int)PositionGetInteger(POSITION_TYPE)) { case POSITION_TYPE_SELL: if(PositionGetDouble(POSITION_PROFIT)<=0) return; break; case POSITION_TYPE_BUY: Trade.PositionClose(_Symbol); break; } } last_deal=cur_max; double stops=MathMax(2*atrs[0],SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL)*_Point); double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK); double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID); double sl=NormalizeDouble(stops,_Digits); double tp=NormalizeDouble(Reward_Risk*(stops+ask-bid),_Digits); double SL=NormalizeDouble(ask+sl,_Digits); double TP=NormalizeDouble(bid-tp,_Digits); if(!Trade.Sell(Lot,_Symbol,bid,SL,TP,"New Strategy")) Print("Error of open SELL ORDER "+Trade.ResultComment()); } return; }
Der vollständige Code des EA findet sich im Anhang.
Nach der Vorbereitung des EAs können wir unsere Strategie testen. Um eine "Anpassung der Strategie an den Zeitraum" zu vermeiden, verlängern wir den Testzeitraum: Die Strategie wird vom 01.01.2015 bis zum 01.01.2017 getestet. Das Anfangskapital beträgt 10.000 USD, das konstante Volumen 1 Lot.
Gemäß den Testergebnissen erzielt der Berater einen Gewinn von 74,8% bei maximalen Salden-Drawdown von 12,4% und einem Eigenkapital von 23,8%. Insgesamt wurden 44 Positionen eröffnet (22 Kauf- und 22 Verkaufsposition). Der Anteil der profitablen Positionen beträgt 18,2% und ist für Kauf und Verkauf gleich. Solch ein geringer Prozentsatz von profitablen Positionen ist auf die Verwendung eines hohen Verhältnisses von Gewinn zu Risiko (15: 1) zurückzuführen und lässt Raum für eine weitere Verbesserung der Strategie.
Schlussfolgerung
Der Artikel demonstriert die Methode zur Erstellung von Handelsstrategien "auf einem leeren Blatt" unter Verwendung einer Methode, die die Positionsöffnung von Indikatoren bestimmen lässt. Die daraus resultierende Strategie ist in der Lage, über einen längeren Zeitraum Gewinne zu erwirtschaften, was durch Tests während drei jährigen Testperiode bewiesen wird. Ungeachtet der Tatsache, dass hier nur die Indikatoren aus dem Standardpaket des MetaTraders verwendet wurden, sind die Signale für die Eröffnung von Positionen weit entfernt von denen, die in der Literatur für getroffene Indikatoren beschrieben werden. Die vorgeschlagene Technologie ermöglicht die Verwendung von weiteren Indikatoren in Handelsstrategien, sie ist nicht durch die verwendeten Indikatoren begrenzt. Sie können beliebige, eigene Indikatoren und Varianten zur Beurteilung der Qualität ihrer Signale verwenden.
Referenzen
Die Programm dieses Artikels:
# |
Name |
Typ |
Beschreibung |
---|---|---|---|
New_Strategy_Gizlyk.zip | |||
1 | NewStrategy1.mq5 | EA | Der EA der Stufe eins der Strategie |
2 | NewStrategy2.mq5 | EA | Der EA der Stufe zwei der Strategie |
3 | NewStrategy3.mq5 | EA | Der EA der Stufe drei der Strategie |
4 | NewStrategy4.mq5 | EA |
Der EA der Stufe vier der Strategie |
5 | NewStrategy_Final.mq5 | EA |
Der EA für den Strategietester |
6 | DealsToIndicators.mqh | Klassenbibliothek | Die Klasse für die Klassen der Indikatoren |
7 | Deal.mqh | Klassenbibliothek | Die Klasse zum Sichern der Informationen der Positionen |
8 | Value.mqh | Klassenbibliothek | Die Klasse zum Sichern die Werte der Indikatorpuffer |
9 | OneBufferArray.mqh | Klassenbibliothek | Die Klasse zum Sichern der Werte der Ein-Puffer-Indikatoren |
10 | StaticOneBuffer.mqh | Klassenbibliothek | Die Klasse zum Sammeln und Analysieren der Ein-Puffer-Indikatoren |
11 | ADXValue.mqh | Klassenbibliothek | Die Klasse zum Speichern der Werte des ADX |
12 | ADX.mqh | Klassenbibliothek | Die Klasse zum Speichern historischen Daten des ADX |
13 | StaticADX.mqh | Klassenbibliothek | Die Klasse zum Sammeln und Analysieren der Statistik des ADX |
14 | AlligatorValue.mqh | Klassenbibliothek | Die Klasse zum Speichern der Werte des Alligators |
15 | Alligator.mqh | Klassenbibliothek | Die Klasse zum Speichern historischen Daten des Alligators |
16 | StaticAlligator.mqh | Klassenbibliothek | Die Klasse zum Sammeln und Analysieren der Statistik des Alligators |
17 | MACDValue.mqh | Klassenbibliothek | Die Klasse zum Speichern der Werte des MACD |
18 | MACD.mqh | Klassenbibliothek | Die Klasse zum Speichern historischen Daten des MACD |
19 | StaticMACD.mqh | Klassenbibliothek | Die Klasse zum Sammeln und Analysieren der Statistik des MACD |
Common.zip | |||
20 | NewStrategy1_Report_1to1_2016-17.html | Internetseite | Diagramm zur Analyse der ersten Stufe der Strategie, Gewinn/Risiko = 1/1 |
21 | NewStrategy1_Report_15to1_2016-17.html | Internetseite | Diagramm zur Analyse der ersten Stufe der Strategie, Gewinn/Risiko = 15/1 |
22 | NewStrategy2_Report_1to1_2016-17.html | Internetseite | Diagramm zur Analyse der zweiten Stufe der Strategie, Gewinn/Risiko = 1/1 |
23 | NewStrategy2_Report_15to1_2016-17.html | Internetseite | Diagramm zur Analyse der zweiten Stufe der Strategie, Gewinn/Risiko = 15/1 |
24 | NewStrategy3_Report_1to1_2016-17.html | Internetseite | Diagramm zur Analyse der dritten Stufe der Strategie, Gewinn/Risiko = 1/1 |
25 | NewStrategy3_Report_15to1_2016-17.html | Internetseite | Diagramm zur Analyse der dritten Stufe der Strategie, Gewinn/Risiko = 15/1 |
26 | NewStrategy4_Report_1to1_2016-17.html | Internetseite | Diagramm zur Analyse der vierten Stufe der Strategie, Gewinn/Risiko = 1/1 |
27 | NewStrategy4_Report_15to1_2016-17.html | Internetseite | Diagramm zur Analyse der vierten Stufe der Strategie, Gewinn/Risiko = 15/1 |
28 | NewStrategy_Final_Report.html | Internetseite | Bericht mit dem Testergebnis der Strategie |
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/4192
![Nachthandel während der asiatischen Handelszeit: wie man im Plus bleibt](https://c.mql5.com/2/30/timezone.png)
![Die Eröffnung durch Indikatoren bestimmen lassen](https://c.mql5.com/2/30/eagoh7z681u4_pdq0h_2f_8dqlderd9j5.png)
![Handeln nach den Ebenen von DiNapoli](https://c.mql5.com/2/30/MQL5-avatar-DiNapoli-001.png)
![Verwendung des Kalman-Filters für die Prognose der Preisrichtung](https://c.mql5.com/2/30/1hud7w_rw12bho.png)
![MQL5 - Sprache von Handelsstrategien, eingebaut ins Kundenterminal MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.