
Expert Advisors Basierend auf Beliebten Handelssystemen und Alchemie der Handelsroboter Optimierung (Teil III)
Einführung
Ich habe ein Angebot von einem Leser des vorherigen Artikels erhalten, einen kleinen Prozess von Backtests zu automatisieren, um die Möglichkeit zu erhalten, die Ergebnisse aller Optimierungen gleichzeitig zu empfangen. Außerdem ist es nicht sehr komfortabel, den Testzeitraum manuell zu verschieben, dieser Prozess sollte ebenfalls automatisiert werden. Die Idee ist hervorragend. Umso mehr, weil MQL4 Mittel alle Möglichkeiten für ihre Umsetzung bieten. Also werde ich den Artikel von der Lösung des Problems beginnen.
Backtest Automatisierung
Was wir für die Lösung dieser Aufgabe benötigen:
1. Schreiben Sie in den notwendigen Expert Advisor unter seinem Header eine Zeile mit dem folgenden Inhalt:
//+==================================================================+ //| Custom BackTesting function | //+==================================================================+ #include <IsBackTestingTime.mqh>
Mit dieser Anweisung können wir die Funktion IsBackTestingTime() in den EA-Code einfügen. Und vergessen Sie nicht die Datei IsBackTestingTime.mqh in den Ordner INCLUDE einzufügen. Diese Funktion:
bool IsBackTestingTime()
{
}
wird zur Bestimmung des Zeitrahmens verwendet, in dem die Backtest-Optimierung oder der Backtest stattfinden wird. In diesem Zeitrahmen gibt die Funktion immer 'true' zurück, in anderen Zeiten immer 'false'. Neben dieser Funktion werden externe EA-Variablen durch diese Anweisung dem EA-Code hinzugefügt:
//---- Declaration of external variables for backtesting extern datetime Start_Time = D'2007.01.01'; // start time of zero optimization extern int Opt_Period = 3; // optimization period in months, if less than zero, parameters are in days extern int Test_Period = 2; // testing period in months extern int Period_Shift = 1; // step of optimization period shift in months extern int Opt_Number = 0; // optimization number
Ich hoffe die Bedeutung dieser Variablen ist für diejenigen klar, die meinen vorherigen Artikel gelesen haben, also ist es nicht notwendig sie noch einmal zu erklären.
2. In dem Block der Startfunktion, platzieren Sie vor dem EA-Code den einfachsten universellen Code des IsBackTestingTime() Aufrufs. Er begrenzt den EA-Betrieb auf bestimmte Zeitrahmen, abhängig von der Anzahl der Backtest-Optimierung.
//----+ Execution of backtesting conditions if (!IsBackTestingTime()) return(0);
Schematisch wird es wie folgt aussehen:
//+==================================================================+ //| Exp_BackTest.mq4 | //| Copyright © 2008, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+==================================================================+ #property copyright "Copyright © 2008, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //+==================================================================+ //| Custom BackTesting function | //+==================================================================+ #include <IsBackTestingTime.mqh> //---- INPUT PARAMETERS OF THE EA //---- GLOBAL VARIABLES OF THE EA //+==================================================================+ //| USER-DEFINED FUNCTIONS OF THE EA | //+==================================================================+ //+==================================================================+ //| Custom Expert initialization function | //+==================================================================+ int init() { //----+ +------------------------------------------------------------+ //---- CODE FOR THE EA INITIALIZATION //----+ +------------------------------------------------------------+ //---- end of initialization return(0); } //+==================================================================+ //| Custom Expert iteration function | //+==================================================================+ int start() { //----+ Execution of backtesting conditions if (!IsBackTestingTime()) return(0); //----+ +---------------------------------------------------------+ //----+ CODE OF THE EA ALGORITHM //----+ +---------------------------------------------------------+ //----+ return(0); } //+------------------------------------------------------------------+
Wenn Sie an der detaillierten Problemlösung an dem Beispiel eines fertigen EA interessiert sind, finden Sie diese in dem EA-Code Exp_5_1.mq4, welcher der EA aus dem vorherigen Aritkel ist, Exp_5.mq4 modifiziert für Backtests. Tatsächlich gibt es keinen großen Unterschied in der Optimierung dieses EA, verglichen mit einem einfachen Expert Advisor. Ich denke allerdings, Backtest-Variablen sollten nicht optimiert werden, ausgenommen Opt_Number, obwohl Sie anderer Meinung sein können.
Es ist wichtig daran zu denken, dass wir nach der Optimierung während des Testens die Ergebnisse nicht innerhalb des Optimierungs-Zeitraums erhalten, sondern danach, jenseits des rechten Rands! Es ist nicht die beste Entscheidung alle Backtest-Optimierungen innerhalb eines Durchlaufs mit genetischem Algorithmus zu machen, es ist viel interessanter jede Backtest-Optimierung einzeln tiefer zu analysieren, ohne die Optimierung der Eingabe-Variable Opt_Number.
Aber auch in diesem Fall erleichtert ein solcher Ansatz des Verständnis des EA-Verhaltens. Und es sollte daran gedacht werden, dass Sie den Wert der externen Variable Opt_Number von Null bis zu einem bestimmten Maximalwert ändern können, der auf die folgende Art festgelegt werden kann: von dem gesamten Zeitraum, in dem alle Backtest-Optimierungen durchgeführt werden (in Monaten), subtrahieren Sie den Zeitraum der Backtest-Optimierung (Opt_Period) und subtrahieren den Backtest-Zeitraum (Taet_Period). Fügen Sie dem erhaltenen Wert Eins hinzu. Das erhaltene Ergebnis wird das Maximum der Opt_Number Variable, wenn Period_Shift gleich Eins ist.
Handelssysteme basierend auf der Kreuzung von Zwei Bewegungen (Movings)
DIese Variante an Handelssystemen ist ziemlich bliebt. Untersuchen wir nun den zugrunde liegenden Algorithmus solcher Strategien. Für Long-Positionen sieht der Einstieg-Algorithmus fogendermaßen aus:
Für Short-Positionen ist er wie folgt:
Als Indikatoren können zwei identische Bewegungen (Movings) mit verschiedenen Parametern zur Bestimmung der Mittelung in den Indikatoren verwendet werden. Es wird angenommen, dass der Parameter zur Bestimmung der Mittelung der MovA Bewegung immer kleiner ist als der gleiche Parameter der MovB Bewegung. Somit ist in diesem Handelssystem MovA eine schnelle Bewegung, MovB ist eine langsame. Hier ist die Umsetzung der Variante des Handelssystems, basierend auf zwei JMA Bewegungen:
//+==================================================================+ //| Exp_6.mq4 | //| Copyright © 2007, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+==================================================================+ #property copyright "Copyright © 2007, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //----+ +-------------------------------------------------------------------------------+ //---- EA INPUT PARAMETERS FOR BUY TRADES extern bool Test_Up = true;//filter of trade calculations direction extern int Timeframe_Up = 240; extern double Money_Management_Up = 0.1; extern int LengthA_Up = 4; // smoothing depth of the quick moving extern int PhaseA_Up = 100; // parameter changing in the range //-100 ... +100, influences the quality of transient process of quick moving extern int IPCA_Up = 0;/* Selecting prices, on which the indicator will be calculated by the quick moving (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ extern int LengthB_Up = 4; // smoothing depth increment of slow moving to quick one extern int PhaseB_Up = 100; // parameter changing in the range //-100 ... +100, influences the quality of transient process of slow moving; extern int IPCB_Up = 0;/* Selecting prices, on which the indicator will be calculated by the slow moving (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ extern int STOPLOSS_Up = 50; // stop loss extern int TAKEPROFIT_Up = 100; // take profit extern bool ClosePos_Up = true; // forced position closing allowed //----+ +-------------------------------------------------------------------------------+ //---- EA INPUT PARAMETERS FOR SELL TRADES extern bool Test_Dn = true;//filter of trade calculations direction extern int Timeframe_Dn = 240; extern double Money_Management_Dn = 0.1; extern int LengthA_Dn = 4; // smoothing depth of the quick moving extern int PhaseA_Dn = 100; // parameter changing in the range // -100 ... +100, influences the quality of transient process of quick moving; extern int IPCA_Dn = 0;/* Selecting prices, on which the indicator will be calculated by the quick moving (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ extern int LengthB_Dn = 4; // smoothing depth increment of slow moving to quick one extern int PhaseB_Dn = 100; // parameter changing in the range // -100 ... +100, influences the quality of transient process of slow moving; extern int IPCB_Dn = 0;/* Selecting prices, on which the indicator will be calculated by the slow moving(0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ extern int STOPLOSS_Dn = 50; // stop loss extern int TAKEPROFIT_Dn = 100; // take profit extern bool ClosePos_Dn = true; // forced position closing allowed //----+ +-------------------------------------------------------------------------------+ //---- Integer variables for the minimum of calculation bars int MinBar_Up, MinBar_Dn; //+==================================================================+ //| Custom Expert functions | //+==================================================================+ #include <Lite_EXPERT1.mqh> //+==================================================================+ //| Custom Expert initialization function | //+==================================================================+ int init() { //---- Checking the correctness of Timeframe_Up variable value if (Timeframe_Up != 1) if (Timeframe_Up != 5) if (Timeframe_Up != 15) if (Timeframe_Up != 30) if (Timeframe_Up != 60) if (Timeframe_Up != 240) if (Timeframe_Up != 1440) Print(StringConcatenate("Parameter Timeframe_Up cannot ", "be equal to ", Timeframe_Up, "!!!")); //---- Checking the correctness of Timeframe_Dn variable value if (Timeframe_Dn != 1) if (Timeframe_Dn != 5) if (Timeframe_Dn != 15) if (Timeframe_Dn != 30) if (Timeframe_Dn != 60) if (Timeframe_Dn != 240) if (Timeframe_Dn != 1440) Print(StringConcatenate("Parameter Timeframe_Dn cannot ", "be equal to ", Timeframe_Dn, "!!!")); //---- Initialization of variables MinBar_Up = 4 + 30; MinBar_Dn = 4 + 30; //---- end of initialization return(0); } //+==================================================================+ //| expert deinitialization function | //+==================================================================+ int deinit() { //----+ //---- End of EA deinitialization return(0); //----+ } //+==================================================================+ //| Custom Expert iteration function | //+==================================================================+ int start() { //----+ Declaring local variables int bar; double MovA[2], MovB[2]; //----+ Declaring static variables static int LastBars_Up, LastBars_Dn; static bool BUY_Sign, BUY_Stop, SELL_Sign, SELL_Stop; //----++ CODE FOR LONG POSITIONS if (Test_Up) { int IBARS_Up = iBars(NULL, Timeframe_Up); if (IBARS_Up >= MinBar_Up) { if (LastBars_Up != IBARS_Up) { //----+ Initialization of variables BUY_Sign = false; BUY_Stop = false; LastBars_Up = IBARS_Up; //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS for(bar = 1; bar < 3; bar++) MovA[bar - 1] = iCustom(NULL, Timeframe_Up, "JJMA", LengthA_Up, PhaseA_Up, 0, IPCA_Up, 0, bar); for(bar = 1; bar < 3; bar++) MovB[bar - 1] = iCustom(NULL, Timeframe_Up, "JJMA", LengthA_Up + LengthB_Up, PhaseB_Up, 0, IPCB_Up, 0, bar); //----+ DEFINING SIGNALS FOR TRADES if ( MovA[1] < MovB[1]) if ( MovA[0] > MovB[0]) BUY_Sign = true; if ( MovA[0] > MovB[0]) BUY_Stop = true; } //----+ EXECUTION OF TRADES if (!OpenBuyOrder1(BUY_Sign, 1, Money_Management_Up, STOPLOSS_Up, TAKEPROFIT_Up)) return(-1); if (ClosePos_Up) if (!CloseOrder1(BUY_Stop, 1)) return(-1); } } //----++ CODE FOR SHORT POSITIONS if (Test_Dn) { int IBARS_Dn = iBars(NULL, Timeframe_Dn); if (IBARS_Dn >= MinBar_Dn) { if (LastBars_Dn != IBARS_Dn) { //----+ Initialization of variables SELL_Sign = false; SELL_Stop = false; LastBars_Dn = IBARS_Dn; //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS for(bar = 1; bar < 3; bar++) MovA[bar - 1] = iCustom(NULL, Timeframe_Dn, "JJMA", LengthA_Dn, PhaseA_Dn, 0, IPCA_Dn, 0, bar); for(bar = 1; bar < 3; bar++) MovB[bar - 1] = iCustom(NULL, Timeframe_Dn, "JJMA", LengthA_Dn + LengthB_Dn, PhaseB_Dn, 0, IPCB_Dn, 0, bar); //----+ DEFINING SIGNALS FOR TRADES if ( MovA[1] > MovB[1]) if ( MovA[0] < MovB[0]) SELL_Sign = true; if ( MovA[0] < MovB[0]) SELL_Stop = true; } //----+ EXECUTION OF TRADES if (!OpenSellOrder1(SELL_Sign, 2, Money_Management_Dn, STOPLOSS_Dn, TAKEPROFIT_Dn)) return(-1); if (ClosePos_Dn) if (!CloseOrder1(SELL_Stop, 2)) return(-1); } } //----+ return(0); } //+------------------------------------------------------------------+
Handelssystem basieren auf der Kreuzung von Zwei Oszillatoren
Das besagte Handelssystem kann nicht nur mir Movings verwendet werden, sondern auch mit Oszillatoren, aber in diesem Fall. wie im vorherigen Artikel beschrieben, ist es besser Pending Ordern zu platzieren, statt direkt nach dem Erhalt der Signale in den Markt einzusteigen. Als anschauliches Beispiel kann ein MACD Diagramm verwendet werden.
Zum Platzieren einer Pending BuyLimit Order, sieht der Algorithmus wie folgt aus:
Hier ist der Algorithmus für die Order des SellLimit Typs:
Der Code von diesem EA ist ähnlich zu dem Code des vorherigen EA:
//+==================================================================+ //| Exp_7.mq4 | //| Copyright © 2007, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+==================================================================+ #property copyright "Copyright © 2007, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //----+ +---------------------------------------------------------------------------+ //---- EA INPUT PARAMETERS FOR BUY TRADES extern bool Test_Up = true; //filter of trade calculations direction extern int Timeframe_Up = 240; extern double Money_Management_Up = 0.1; extern int FST_period_Up = 12; // period of the quick moving extern int SLO_period_Up = 22; // period increment of slow moving to quick one extern int SIGN_period_Up = 8; // period of the signal line extern int Price_Up = 0; // selecting prices, upon which MACD is calculated extern int STOPLOSS_Up = 50; // stop loss extern int TAKEPROFIT_Up = 100; // take profit extern int PriceLevel_Up =40; // difference between the current price and // price of pending order triggering extern bool ClosePos_Up = true; // forced position closing allowed //----+ +---------------------------------------------------------------------------+ //---- EA INPUT PARAMETERS FOR SELL TRADES extern bool Test_Dn = true; //filter of trade calculations direction extern int Timeframe_Dn = 240; extern double Money_Management_Dn = 0.1; extern int FST_period_Dn = 12; // period of the quick moving extern int SLO_period_Dn = 22; // period increment of slow moving to quick one extern int SIGN_period_Dn = 8; // period of the signal line extern int Price_Dn = 0; // selecting prices, upon which MACD is calculated extern int STOPLOSS_Dn = 50; // stop loss extern int TAKEPROFIT_Dn = 100; // take profit extern int PriceLevel_Dn =40; // difference between the current price and // price of pending order triggering extern bool ClosePos_Dn = true; // forced position closing allowed //----+ +---------------------------------------------------------------------------+ //---- Integer variables for the minimum of calculation bars int MinBar_Up, MinBar_Dn; //+==================================================================+ //| Custom Expert functions | //+==================================================================+ #include <Lite_EXPERT1.mqh> //+==================================================================+ //| Custom Expert initialization function | //+==================================================================+ int init() { //---- Checking the correctness of Timeframe_Up variable value if (Timeframe_Up != 1) if (Timeframe_Up != 5) if (Timeframe_Up != 15) if (Timeframe_Up != 30) if (Timeframe_Up != 60) if (Timeframe_Up != 240) if (Timeframe_Up != 1440) Print(StringConcatenate("Parameter Timeframe_Up cannot ", "be equal to ", Timeframe_Up, "!!!")); //---- Checking the correctness of Timeframe_Dn variable value if (Timeframe_Dn != 1) if (Timeframe_Dn != 5) if (Timeframe_Dn != 15) if (Timeframe_Dn != 30) if (Timeframe_Dn != 60) if (Timeframe_Dn != 240) if (Timeframe_Dn != 1440) Print(StringConcatenate("Parameter Timeframe_Dn cannot ", "be equal to ", Timeframe_Dn, "!!!")); //---- Initialization of variables MinBar_Up = 4 + FST_period_Up + SLO_period_Up + SIGN_period_Up; MinBar_Dn = 4 + FST_period_Dn + SLO_period_Dn + SIGN_period_Dn; //---- end of initialization return(0); } //+==================================================================+ //| expert deinitialization function | //+==================================================================+ int deinit() { //----+ //---- End of the EA deinitialization return(0); //----+ } //+==================================================================+ //| Custom Expert iteration function | //+==================================================================+ int start() { //----+ Declaring local variables int bar; double MovA[2], MovB[2]; //----+ Declaring static variables static int LastBars_Up, LastBars_Dn; static datetime StopTime_Up, StopTime_Dn; static bool BUY_Sign, BUY_Stop, SELL_Sign, SELL_Stop; //----++ CODE FOR LONG POSITIONS if (Test_Up) { int IBARS_Up = iBars(NULL, Timeframe_Up); if (IBARS_Up >= MinBar_Up) { if (LastBars_Up != IBARS_Up) { //----+ Initialization of variables BUY_Sign = false; BUY_Stop = false; LastBars_Up = IBARS_Up; StopTime_Up = iTime(NULL, Timeframe_Up, 0) + 60 * Timeframe_Up; //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS for(bar = 1; bar < 3; bar++) MovA[bar - 1] = iMACD(NULL, Timeframe_Up, FST_period_Up, FST_period_Up + SLO_period_Up, SIGN_period_Up, Price_Up, 0, bar); for(bar = 1; bar < 3; bar++) MovB[bar - 1] = iMACD(NULL, Timeframe_Up, FST_period_Up, FST_period_Up + SLO_period_Up, SIGN_period_Up, Price_Up, 1, bar); //----+ DEFINING SIGNALS FOR TRADES if ( MovA[1] < MovB[1]) if ( MovA[0] > MovB[0]) BUY_Sign = true; if ( MovA[0] > MovB[0]) BUY_Stop = true; } //----+ EXECUTION OF TRADES if (!OpenBuyLimitOrder1(BUY_Sign, 1, Money_Management_Up, STOPLOSS_Up, TAKEPROFIT_Up, PriceLevel_Up, StopTime_Up)) return(-1); if (ClosePos_Up) if (!CloseOrder1(BUY_Stop, 1)) return(-1); } } //----++ CODE FOR SHORT POSITIONS if (Test_Dn) { int IBARS_Dn = iBars(NULL, Timeframe_Dn); if (IBARS_Dn >= MinBar_Dn) { if (LastBars_Dn != IBARS_Dn) { //----+ Initialization of variables SELL_Sign = false; SELL_Stop = false; LastBars_Dn = IBARS_Dn; StopTime_Dn = iTime(NULL, Timeframe_Dn, 0) + 60 * Timeframe_Dn; //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS for(bar = 1; bar < 3; bar++) MovA[bar - 1] = iMACD(NULL, Timeframe_Dn, FST_period_Dn, FST_period_Dn + SLO_period_Dn, SIGN_period_Dn, Price_Dn, 0, bar); for(bar = 1; bar < 3; bar++) MovB[bar - 1] = iMACD(NULL, Timeframe_Dn, FST_period_Dn, FST_period_Dn + SLO_period_Dn, SIGN_period_Dn, Price_Dn, 1, bar); //----+ DEFINING SIGNALS FOR TRADES if ( MovA[1] > MovB[1]) if ( MovA[0] < MovB[0]) SELL_Sign = true; if ( MovA[0] < MovB[0]) SELL_Stop = true; } //----+ EXECUTION OF TRADES if (!OpenSellLimitOrder1(SELL_Sign, 2, Money_Management_Dn, STOPLOSS_Dn, TAKEPROFIT_Dn, PriceLevel_Dn, StopTime_Dn)) return(-1); if (ClosePos_Dn) if (!CloseOrder1(SELL_Stop, 2)) return(-1); } } //----+ return(0); } //+------------------------------------------------------------------+
Fazit
Ein weiterer Artikel ist zu Ende. Ein weiteres Handelssystem wurde in Expert Advisors umgesetzt, basierend auf absolut unterschiedlichen Varianten von Indikatoren. Ich hoffe, dieser Artikel ist nützlich für beginnende EA-Autoren bei der weiteren Entwicklung von Fähigkeiten der Umwandlung eines korrekt formalisierten Algorithmus in einen fertigen absoluten Bediencode Ihrer Expert Advisors
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/1521





- 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.