Expert Advisors baseado em estratégias de trading populares e alquimia da otimização de robô de trading (Parte VI)
Introdução
No meu artigo anterior, dei uma descrição detalhada sobre a escrita de Expert Advisors que processam a informação que chega de dois timeframes diferentes. Entretanto, a questão é que essa informação geralmente é insuficiente para entrar com precisão no mercado. Por exemplo, se um timeframe menor é igual a H1, então entrar no mercado imediatamente durante a mudança de uma barra de uma hora geralmente não é a melhor solução, uma vez que a tendência no timeframe menor do que H1, e geralmente existente no ruído de preço, pode trabalhar contra a posição a ser aberta. Em muitos casos, essa tendência a curto prazo pode ser detectada mais facilmente. Em tal caso, se ela se move contra a posição a ser aberta, você deve adiar sua entrada no mercado até que essa tendência que age no menor timeframe mude sua direção para uma direção oposta. Ou, no pior dos casos, você pode entrar no mercado antes que a próxima barra de uma hora mude. É essa tarefa que tentarei resolver no meu artigo.
Sistema Triple Screen de Elder
Alexander Elder é conhecido por ser o autor de livros bastante populares na psicologia do trading e comportamento de massas. Foi ele quem inventou a ideia de usar os gráficos de três timeframes na análise financeira de mercados. Esses gráficos foram nomeados Triple Screen de Elder. Já aprendemos no meu artigo anterior a construir uma tela dupla. Agora temos que adicionar a terceira tela a ele. Como os exemplos da compilação de código seguinte, pudemos ver alguns EAs prontos do meu artigo anterior. Entretanto, no presente artigo, decidi construir outro EA (Exp_14.mq4) com base nos mesmos procedimentos, apenas para fazer algo diferente.
Como base inicial para escrever o código, tomo Exp_12.mq4, no qual eu substituo o alerta de média de movimento, JFatl.nq4, por oscilador JCCIX.mq4 e o indicador trend-following MAMA_NK.mq4 consistindo em dois MAs por indicador StepMA_Stoch_NK.mq4 consistindo em alguns osciladores estocásticos. No fim, o algoritmo inicial permanece o mesmo, apenas modifiquei as solicitações para os indicadores custom indicators, as variáveis externas do EA e a inicialização de constantes no bloco da função init() e também compliquei o código de blocos que tinha o objetivo de detectar os sinais de entrada no mercado. Apresento o algoritmo de funcionamento desse EA mais uma vez usando dois timeframes de uma forma geral, como fiz em meu artigo anterior. Entretanto, faço isso com um pouco mais de detalhes dessa vez.
Para posições longas, temos:
E para posições curtas:
Temos que realizar o algoritmo resultante no código do programa para usar os gráficos de três timeframes diferentes da forma mais racional possível como segue:
Para posições longas:
Para posições curtas:
A realização desse algoritmo em um código de programa com base em Exp_15.mq4 pode ser apresentado como segue:
//+==================================================================+ //| Exp_15.mq4 | //| Copyright © 2008, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+==================================================================+ #property copyright "Copyright © 2008, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //----+ +---------------------------------------------------------------------------+ //---- EXPERT ADVISORS INPUTS FOR BUY TRADES extern bool Test_Up = true;//filter of trade calculations direction extern double Money_Management_Up = 0.1; //---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + extern int TimeframeX_Up = 1440; extern int PeriodWATR_Up = 10; extern double Kwatr_Up = 1.0000; extern int HighLow_Up = 0; //---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + extern int Timeframe_Up = 240; extern int JJLength_Up = 8; // depth of JJMA smoothing for the entry price extern int JXLength_Up = 8; // depth of JurX smoothing for the obtained indicator extern int Phase_Up = 100;// the parameter ranging // from -100 to +100 influences the process quality; extern int IPC_Up = 0; /* Selecting price to calculate the indicator on (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 TimeframeN_Up = 15; extern int Noise_period_Up = 8; //extern int SmoothN_Up = 7; //extern int MaMethodN_Up = 1; //---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + extern int STOPLOSS_Up = 50; // StopLoss extern int TAKEPROFIT_Up = 100; // TakeProfit extern bool ClosePos_Up = true; // enable forcible closing the position //----+ +---------------------------------------------------------------------------+ //---- EXPERT ADVISORS INPUTS FOR SELL TRADES extern bool Test_Dn = true;//filter of trade calculations direction extern double Money_Management_Dn = 0.1; //---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + extern int TimeframeX_Dn = 1440; extern int PeriodWATR_Dn = 10; extern double Kwatr_Dn = 1.0000; extern int HighLow_Dn = 0; //---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + extern int Timeframe_Dn = 240; extern int JJLength_Dn = 8; // depth of JJMA smoothing for the entry price extern int JXLength_Dn = 8; // depth of JurX smoothing for the obtained indicator extern int Phase_Dn = 100;// the parameter ranging // from -100 to +100 influences the process quality; extern int IPC_Dn = 0; /* Selecting price to calculate the indicator on (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 TimeframeN_Dn = 15; extern int Noise_period_Dn = 8; //extern int SmoothN_Dn = 7; //extern int MaMethodN_Dn = 1; //---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + extern int STOPLOSS_Dn = 50; // StopLoss extern int TAKEPROFIT_Dn = 100; // TakeProfit extern bool ClosePos_Dn = true; // enable forcible closing the position //----+ +---------------------------------------------------------------------------+ //---- Integer variables for calling to custom indicators int SmoothN_Up = 7, SmoothN_Dn = 7, MaMethodN_Up = 1, MaMethodN_Dn = 1; //---- Integer variables for the minimum of reference bars int MinBar_Up, MinBar_Dn, MinBarX_Up, MinBarX_Dn, MinBarN_Up, MinBarN_Dn; //+==================================================================+ //| Custom Expert functions | //+==================================================================+ #include <Lite_EXPERT1.mqh> //+==================================================================+ //| TimeframeCheck() functions | //+==================================================================+ void TimeframeCheck(string Name, int Timeframe) { //----+ //---- Checking the value of variable Timeframe for correctness if (Timeframe != 1) if (Timeframe != 5) if (Timeframe != 15) if (Timeframe != 30) if (Timeframe != 60) if (Timeframe != 240) if (Timeframe != 1440) Print(StringConcatenate("Parameter ",Name, " cannot ", "be equal to ", Timeframe, "!!!")); //----+ } //+==================================================================+ //| Custom Expert initialization function | //+==================================================================+ int init() { //---- Checking the values of timeframe variables for correctness TimeframeCheck("TimeframeX_Up", TimeframeX_Up); TimeframeCheck("Timeframe_Up", Timeframe_Up); TimeframeCheck("TimeframeN_Up", TimeframeN_Up); //---- Checking the values of timeframe variables for correctness TimeframeCheck("TimeframeX_Dn", TimeframeX_Dn); TimeframeCheck("Timeframe_Dn", Timeframe_Dn); TimeframeCheck("TimeframeN_Dn", TimeframeN_Dn); //---- Initialization of variables MinBarX_Up = 2 + PeriodWATR_Up; MinBar_Up = 4 + 3 * JXLength_Up + 30; MinBarN_Up = 4 + Noise_period_Up + SmoothN_Up; //---- Initialization of variables MinBarX_Dn = 2 + PeriodWATR_Dn; MinBar_Dn = 4 + 3 * JXLength_Dn + 30; MinBarN_Dn = 4 + Noise_period_Dn + SmoothN_Dn; //---- initialization complete return(0); } //+==================================================================+ //| expert deinitialization function | //+==================================================================+ int deinit() { //----+ //---- EA deinitialization complete return(0); //----+ } //+==================================================================+ //| Custom Expert iteration function | //+==================================================================+ int start() { //----+ Declaration of local variables int bar; double JCCIX[2], Trend, Fast_StepMA, Slow_StepMA, MA1, MA2; //----+ Declaration of static variables static datetime StopTime_Up, StopTime_Dn; static double TrendX_Up, TrendX_Dn, OldTrend_Up, OldTrend_Dn; //--- static int LastBars_Up, LastBars_Dn; static int LastBarsX_Up, LastBarsX_Dn, LastBarsN_Up, LastBarsN_Dn; //--- static bool BUY_Sign, BUY_Stop, SELL_Sign, SELL_Stop; static bool SecondStart_Up, SecondStart_Dn, NoiseBUY_Sign, NoiseSELL_Sign; //----+ +---------------------------------------------------------------+ //----++ CODE FOR LONG POSITIONS | //----+ +---------------------------------------------------------------+ if (Test_Up) { int IBARS_Up = iBars(NULL, Timeframe_Up); int IBARSX_Up = iBars(NULL, TimeframeX_Up); int IBARSN_Up = iBars(NULL, TimeframeN_Up); //--- if (IBARS_Up >= MinBar_Up && IBARSX_Up >= MinBarX_Up && IBARSN_Up >= MinBarN_Up) { //----+ +----------------------+ //----+ DETECTING A TREND | //----+ +----------------------+ if (LastBarsX_Up != IBARSX_Up) { //----+ Initialization of variables LastBarsX_Up = IBARSX_Up; BUY_Sign = false; BUY_Stop = false; //----+ calculating the values of indicators Fast_StepMA = iCustom(NULL, TimeframeX_Up, "StepMA_Stoch_NK", PeriodWATR_Up, Kwatr_Up, HighLow_Up, 0, 1); //--- Slow_StepMA = iCustom(NULL, TimeframeX_Up, "StepMA_Stoch_NK", PeriodWATR_Up, Kwatr_Up, HighLow_Up, 1, 1); //----+ detecting a trend TrendX_Up = Fast_StepMA - Slow_StepMA; //----+ defining a signal to close trades if (TrendX_Up < 0) BUY_Stop = true; } //----+ +----------------------------------------+ //----+ DETECTING SIGNALS TO ENTER THE MARKET | //----+ +----------------------------------------+ if (LastBars_Up != IBARS_Up && TrendX_Up > 0) { //----+ Initialization of variables BUY_Sign = false; LastBars_Up = IBARS_Up; //----+ Initialization of noise variables NoiseBUY_Sign = false; StopTime_Up = iTime(NULL, Timeframe_Up, 0) + 50 * Timeframe_Up; //----+ Initialization of zero if (!SecondStart_Up) { //--- Search for trend direction at the first start for(bar = 2; bar < IBARS_Up - 1; bar++) { JCCIX[0] = iCustom(NULL, Timeframe_Up, "JCCIX", JJLength_Up, JXLength_Up, Phase_Up, IPC_Up, 0, bar); //--- JCCIX[1] = iCustom(NULL, Timeframe_Up, "JCCIX", JJLength_Up, JXLength_Up, Phase_Up, IPC_Up, 0, bar + 1); //--- OldTrend_Up = JCCIX[0] - JCCIX[1]; //--- if (OldTrend_Up != 0) { SecondStart_Up = true; break; } } } //----+ calculating the values of indicators and loading them to a buffer for(bar = 1; bar < 3; bar++) JCCIX[bar - 1] = iCustom(NULL, Timeframe_Up, "JCCIX", JJLength_Up, JXLength_Up, Phase_Up, IPC_Up, 0, bar); //----+ detecting signals for trades Trend = JCCIX[0] - JCCIX[1]; if (TrendX_Up > 0) if (OldTrend_Up < 0) if (Trend > 0) BUY_Sign = true; if (Trend != 0) OldTrend_Up = Trend; } //----+ +------------------------------------------------+ //----+ DETECTING NOISE SIGNALS TO ENTER THE MARKET | //----+ +------------------------------------------------+ if (BUY_Sign) if (LastBarsN_Up != IBARSN_Up) { NoiseBUY_Sign = false; LastBarsN_Up = IBARSN_Up; //--- MA1 = iCustom(NULL, TimeframeN_Up, "2Moving Avereges", Noise_period_Up, SmoothN_Up, MaMethodN_Up, MaMethodN_Up, PRICE_LOW, 0, 0, 1); //--- MA2 = iCustom(NULL, TimeframeN_Up, "2Moving Avereges", Noise_period_Up, SmoothN_Up, MaMethodN_Up, MaMethodN_Up, PRICE_LOW, 0, 0, 2); //--- if (MA1 > MA2 || TimeCurrent() > StopTime_Up) NoiseBUY_Sign = true; } //----+ +-------------------+ //----+ MAKING TRADES | //----+ +-------------------+ if (NoiseBUY_Sign) 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); int IBARSX_Dn = iBars(NULL, TimeframeX_Dn); int IBARSN_Dn = iBars(NULL, TimeframeN_Dn); //--- if (IBARS_Dn >= MinBar_Dn && IBARSX_Dn >= MinBarX_Dn && IBARSN_Dn >= MinBarN_Dn) { //----+ +----------------------+ //----+ DETECTING A TREND | //----+ +----------------------+ if (LastBarsX_Dn != IBARSX_Dn) { //----+ Initialization of variables LastBarsX_Dn = IBARSX_Dn; SELL_Sign = false; SELL_Stop = false; //----+ calculating the values of indicators Fast_StepMA = iCustom(NULL, TimeframeX_Dn, "StepMA_Stoch_NK", PeriodWATR_Dn, Kwatr_Dn, HighLow_Dn, 0, 1); //--- Slow_StepMA = iCustom(NULL, TimeframeX_Dn, "StepMA_Stoch_NK", PeriodWATR_Dn, Kwatr_Dn, HighLow_Dn, 1, 1); //----+ detecting a trend TrendX_Dn = Fast_StepMA - Slow_StepMA; //----+ defining a signal to close trades if (TrendX_Dn > 0) SELL_Stop = true; } //----+ +----------------------------------------+ //----+ DETECTING SIGNALS TO ENTER THE MARKET | //----+ +----------------------------------------+ if (LastBars_Dn != IBARS_Dn && TrendX_Dn < 0) { //----+ Initialization of variables SELL_Sign = false; LastBars_Dn = IBARS_Dn; //----+ Initialization of noise variables NoiseSELL_Sign = false; StopTime_Dn = iTime(NULL, Timeframe_Dn, 0) + 50 * Timeframe_Dn; //----+ Initialization of zero if (!SecondStart_Dn) { //--- Search for trend direction at the first start for(bar = 2; bar < IBARS_Dn - 1; bar++) { JCCIX[0] = iCustom(NULL, Timeframe_Dn, "JCCIX", JJLength_Dn, JXLength_Dn, Phase_Dn, IPC_Dn, 0, bar); //--- JCCIX[1] = iCustom(NULL, Timeframe_Dn, "JCCIX", JJLength_Dn, JXLength_Dn, Phase_Dn, IPC_Dn, 0, bar + 1); //--- OldTrend_Dn = JCCIX[0] - JCCIX[1]; //--- if (OldTrend_Dn != 0) { SecondStart_Dn = true; break; } } } //----+ calculating the values of indicators and loading them to a buffer for(bar = 1; bar < 3; bar++) JCCIX[bar - 1]= iCustom(NULL, Timeframe_Dn, "JCCIX", JJLength_Dn, JXLength_Dn, Phase_Dn, IPC_Dn, 0, bar); //----+ detecting signals for trades Trend = JCCIX[0] - JCCIX[1]; //--- if (TrendX_Dn < 0) if (OldTrend_Dn > 0) if (Trend < 0) SELL_Sign = true; if (Trend != 0) OldTrend_Dn = Trend; } //----+ +------------------------------------------------+ //----+ DETECTING NOISE SIGNALS TO ENTER THE MARKET | //----+ +------------------------------------------------+ if (SELL_Sign) if (LastBarsN_Dn != IBARSN_Dn) { NoiseSELL_Sign = false; LastBarsN_Dn = IBARSN_Dn; //--- MA1 = iCustom(NULL, TimeframeN_Dn, "2Moving Avereges", Noise_period_Dn, SmoothN_Dn, MaMethodN_Dn, MaMethodN_Dn, PRICE_HIGH, 0, 0, 1); //--- MA2 = iCustom(NULL, TimeframeN_Dn, "2Moving Avereges", Noise_period_Dn, SmoothN_Dn, MaMethodN_Dn, MaMethodN_Dn, PRICE_HIGH, 0, 0, 2); //--- if (MA1 < MA2 || TimeCurrent() > StopTime_Dn) NoiseSELL_Sign = true; } //----+ +-------------------+ //----+ MAKING TRADES | //----+ +-------------------+ if (NoiseSELL_Sign) 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); } //+------------------------------------------------------------------+
Agora devemos entrar em mais detalhes sobre transformar Exp_14.mq4 em Exp_15.mq4. Temos um novo módulo, "DETECTANDO SINAIS DE RUÍDO PARA ENTRAR NO MERCADO", em nosso código de programa. O ponto dessa operação de módulo pode ser expresso como segue (estou considerando o algoritmo apenas para posições longas):
O sinal NoiseBUY_Sign ocorre se a direção de tendência no menor timeframe coincidir com a direção de sinal de entrada do mercado, BUY_Sig. Ou, caso haja não correspondência dessa tendência, o sinal NoiseBUY_Sign ocorre antes da modificação regular da barra.
Como um MA trend-following, usei um indicador obtido por suavização dupla da sequência de preço por algoritmos de média padrão. Como um parâmetro externo para o EA desse módulo, usei apenas duas variáveis:
extern int TimeframeN_Up = 15; extern int Noise_period_Up = 8;
Fiz a maioria das varáveis externas do custom indicator 2Moving Avereges.mq4 fixas (inicialização de variáveis globais):
int SmoothN_Up = 7, SmoothN_Dn = 7, MaMethodN_Up = 1, MaMethodN_Dn = 1;
A lógica de adição de teste é absolutamente a mesma da que fiz em meu artigo anterior.
Ideia geral de construir Expert Advisors usando três timeframe
No geral, o código do EA está pronto e eu poderia parar nesse estágio. Entretanto, na minha opinião, a menor parte do trabalho realmente foi feita. O primeiro sistema de trading escrito com base nessa ideia dificilmente produziria bons resultados no trading real. Então, deveríamos ser motivados pelo fato de que temos que escrever o código de mais do que um ou dois EAs similares para escolher uma versão mais apropriada. Então agora estamos encarando a tarefa de abstrair os sinais de trading específicos calculando algoritmos e usando apenas o próprio algoritmo de triple screen. O que, em geral, não é um problema. O código resultante sem algoritmos aparecerá como segue:
//+==================================================================+ //| ThreeScreens.mqh | //| Copyright © 2008, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+==================================================================+ #property copyright "Copyright © 2008, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //----+ +---------------------------------------------------------------------------+ //---- EXPERT ADVISORS INPUTS FOR BUY TRADES extern bool Test_Up = true;//filter of trade calculations direction extern double Money_Management_Up = 0.1; //---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + extern int TimeframeX_Up = 1440; // Declarations and initializations of the EA external parameters for long positions for the largest timeframe //---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + extern int Timeframe_Up = 240; // Declarations and initializations of the EA external parameters for long positions for the middle timeframe //---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + extern int TimeframeN_Up = 15; // Declarations and initializations of the EA external parameters for long positions for the smallest timeframe //---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + extern int STOPLOSS_Up = 50; // StopLoss extern int TAKEPROFIT_Up = 100; // TakeProfit extern bool ClosePos_Up = true; // enable forcible closing the position //----+ +---------------------------------------------------------------------------+ //---- EXPERT ADVISORS INPUTS FOR SELL TRADES extern bool Test_Dn = true;//filter of trade calculations direction extern double Money_Management_Dn = 0.1; //---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + extern int TimeframeX_Dn = 1440; // Declarations and initializations of the EA external parameters for short positions for largest timeframe //---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + extern int Timeframe_Dn = 240; // Declarations and initializations of the EA external parameters for short positions for middle timeframe //---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + extern int TimeframeN_Dn = 15; // Declarations and initializations of the EA external parameters for short positions for the smallest timeframe //---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + extern int STOPLOSS_Dn = 50; // StopLoss extern int TAKEPROFIT_Dn = 100; // TakeProfit extern bool ClosePos_Dn = true; // enable forcible closing the position //----+ +---------------------------------------------------------------------------+ //---- Integer variables for the minimum of reference bars int MinBar_Up, MinBar_Dn, MinBarX_Up, MinBarX_Dn, MinBarN_Up, MinBarN_Dn; //+==================================================================+ //| Custom Expert functions | //+==================================================================+ #include <Lite_EXPERT1.mqh> //+==================================================================+ //| TimeframeCheck() functions | //+==================================================================+ void TimeframeCheck(string Name, int Timeframe) { //----+ //---- Checking the value of variable Timeframe for correctness if (Timeframe != 1) if (Timeframe != 5) if (Timeframe != 15) if (Timeframe != 30) if (Timeframe != 60) if (Timeframe != 240) if (Timeframe != 1440) Print(StringConcatenate("Parameter ",Name, " cannot ", "be equal to ", Timeframe, "!!!")); //----+ } //+==================================================================+ //| Custom Expert initialization function | //+==================================================================+ int init() { //---- Checking the values of timeframe variables for correctness TimeframeCheck("TimeframeX_Up", TimeframeX_Up); TimeframeCheck("Timeframe_Up", Timeframe_Up); TimeframeCheck("TimeframeN_Up", TimeframeN_Up); //---- Checking the values of timeframe variables for correctness TimeframeCheck("TimeframeX_Dn", TimeframeX_Dn); TimeframeCheck("Timeframe_Dn", Timeframe_Dn); TimeframeCheck("TimeframeN_Dn", TimeframeN_Dn); //---- Initialization of variables for long positions MinBarX_Up = // initialization of the variable for the minimum reference bars for largest timeframe MinBar_Up = // initialization of the variable for the minimum reference bars for middle timeframe MinBarN_Up = // initialization of the variable for the minimum reference bars for the smallest timeframe //---- Initialization of variables for short positions MinBarX_Dn = // initialization of the variable for the minimum reference bars for largest timeframe MinBar_Dn = // initialization of the variable for the minimum reference bars for middle timeframe MinBarN_Dn = // initialization of the variable for the minimum reference bars for the smallest timeframe //---- initialization complete return(0); } //+==================================================================+ //| expert deinitialization function | //+==================================================================+ int deinit() { //----+ //---- EA deinitialization complete return(0); //----+ } //+==================================================================+ //| Custom Expert iteration function | //+==================================================================+ int start() { //----+ Declaration of local variables of trading algorithms //----+ Declaration of static variables of trading algortihms //----+ Declaration of static variables static datetime StopTime_Up, StopTime_Dn; //--- static int LastBars_Up, LastBars_Dn; static int LastBarsX_Up, LastBarsX_Dn; static int LastBarsN_Up, LastBarsN_Dn; //--- static bool BUY_Sign, BUY_Stop; static bool SELL_Sign, SELL_Stop; static bool NoiseBUY_Sign, NoiseSELL_Sign; static double TrendX_Up, TrendX_Dn; //----+ +---------------------------------------------------------------+ //----++ CODE FOR LONG POSITIONS | //----+ +---------------------------------------------------------------+ if (Test_Up) { int IBARS_Up = iBars(NULL, Timeframe_Up); int IBARSX_Up = iBars(NULL, TimeframeX_Up); int IBARSN_Up = iBars(NULL, TimeframeN_Up); //--- if (IBARS_Up >= MinBar_Up && IBARSX_Up >= MinBarX_Up && IBARSN_Up >= MinBarN_Up) { //----+ +----------------------+ //----+ DETECTING A TREND | //----+ +----------------------+ if (LastBarsX_Up != IBARSX_Up) { //----+ Initialization of variables LastBarsX_Up = IBARSX_Up; BUY_Sign = false; BUY_Stop = false; // Trend direction detecting algorithm on the largest timeframe //(initializing variable TrendX_Up) //----+ defining a signal to close trades if (TrendX_Up < 0) BUY_Stop = true; } //----+ +----------------------------------------+ //----+ DETECTING SIGNALS TO ENTER THE MARKET | //----+ +----------------------------------------+ if (LastBars_Up != IBARS_Up && TrendX_Up > 0) { //----+ Initialization of variables BUY_Sign = false; LastBars_Up = IBARS_Up; //----+ Initialization of noise variables NoiseBUY_Sign = false; StopTime_Up = iTime(NULL, Timeframe_Up, 0) + 50 * Timeframe_Up; // Entering point determining algorithm on the middle timeframe //(Initializing variable BUY_Sign) } //----+ +------------------------------------------------+ //----+ DETECTING NOISE SIGNALS TO ENTER THE MARKET | //----+ +------------------------------------------------+ if (BUY_Sign) if (LastBarsN_Up != IBARSN_Up) { NoiseBUY_Sign = false; LastBarsN_Up = IBARSN_Up; //--- // Entering point precising algorithm on the smallest timeframe //(Initializing variable NoiseBUY_Sign) } //----+ +-------------------+ //----+ MAKING TRADES | //----+ +-------------------+ if (NoiseBUY_Sign) 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); int IBARSX_Dn = iBars(NULL, TimeframeX_Dn); int IBARSN_Dn = iBars(NULL, TimeframeN_Dn); //--- if (IBARS_Dn >= MinBar_Dn && IBARSX_Dn >= MinBarX_Dn && IBARSN_Dn >= MinBarN_Dn) { //----+ +----------------------+ //----+ DETECTING A TREND | //----+ +----------------------+ if (LastBarsX_Dn != IBARSX_Dn) { //----+ Initialization of variables LastBarsX_Dn = IBARSX_Dn; SELL_Sign = false; SELL_Stop = false; // Trend direction detecting algorithm on the largest timeframe //(initializing variable TrendX_Dn) //----+ defining a signal to close trades if (TrendX_Dn > 0) SELL_Stop = true; } //----+ +----------------------------------------+ //----+ DETECTING SIGNALS TO ENTER THE MARKET | //----+ +----------------------------------------+ if (LastBars_Dn != IBARS_Dn && TrendX_Dn < 0) { //----+ Initialization of variables SELL_Sign = false; LastBars_Dn = IBARS_Dn; //----+ Initialization of noise variables NoiseSELL_Sign = false; StopTime_Dn = iTime(NULL, Timeframe_Dn, 0) + 50 * Timeframe_Dn; // Entering point determining algorithm on the middle timeframe //(Initializing variable SELL_Sign) } //----+ +------------------------------------------------+ //----+ DETECTING NOISE SIGNALS TO ENTER THE MARKET | //----+ +------------------------------------------------+ if (SELL_Sign) if (LastBarsN_Dn != IBARSN_Dn) { NoiseSELL_Sign = false; LastBarsN_Dn = IBARSN_Dn; //--- // Entering point precising algorithm on the smallest timeframe //(Initializing variable NoiseSELL_Sign) } //----+ +-------------------+ //----+ MAKING TRADES | //----+ +-------------------+ if (NoiseSELL_Sign) 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); } //+------------------------------------------------------------------+
Se usarmos esse código como template para escrever EAs, deveríamos, antes de mais nada, inicializar variáveis nos blocos correspondentes: DETECTANDO UMA TENDÊNCIA" E "DETECTANDO SINAL DE RUÍDO PARA ENTRAR NO MERCADO":
TrendX_Up = 1; TrendX_Dn =-1; Noise8uy_Sign = true; NoiseSELL_Sign = true;
Depois disso, você pode adicionar seus próprios códigos nos blocos "DETECTANDO SINAIS PARA ENTRAR NO MERCADO" e ajustar o EA para funcionar com esse código. Você pode aprender como fazer isso no código de EA Exp_15_A.mq4, no qual há somente algoritmos para detectar sinais para entrar no mercado para o timeframe intermediário, enquanto não há algoritmos que se destinam a detectar a tendência do maior timeframe ou aqueles que se destinam a detectar a tendência de ruído para o menor timeframe. Você deve prestar atenção às inicializações de variáveis para a menor quantidade de barras no bloco int int(), nesse caso:
//---- Initialization of variables MinBarX_Up = 0; MinBar_Up = 4 + 3 * JXLength_Up + 30; MinBarN_Up = 0; //---- Initialization of variables MinBarX_Dn = 0; MinBar_Dn = 4 + 3 * JXLength_Dn + 30; MinBarN_Dn = 0;
No segundo passo, remova as inicializações dos blocos "DETECTANDO UMA TENDÊNCIA":
TrendX_Up = 1; TrendX_Dn =-1;
Adicione seu código para detectar a direção de tendência nesses blocos e ajuste o EA mais uma vez. Esse estágio de escrita de código é exibido em Exp_15_B.mq4. Por favor, não se esqueça de inicializar as variáveis MinBarX_Up e MinBarX_Dn no bloco init():
//---- Initialization of variables MinBarX_Up = 2 + PeriodWATR_Up; MinBar_Up = 4 + 3 * JXLength_Up + 30; MinBarN_Up = 0; //---- Initialization of variables MinBarX_Dn = 2 + PeriodWATR_Dn; MinBar_Dn = 4 + 3 * JXLength_Dn + 30; MinBarN_Dn = 0;
Como resultado, temos um EA funcionando em dois timeframes. No terceiro passo, absolutamente da mesma forma, como o código de EA nos blocos "DETECTANDO SINAIS DE RUÍDO PARA ENTRAR NO MERCADO", tendo removido previamente as inicializações
Noise8uy_Sign = true; NoiseSELL_Sign = true;
daqueles blocos e adicionado operações aritméticas para a inicialização de variáveis para a menor quantidade de barras no bloco int int(), nesse caso:
//---- Initialization of variables MinBarX_Up = 2 + PeriodWATR_Up; MinBar_Up = 4 + 3 * JXLength_Up + 30; MinBarN_Up = 4 + Noise_period_Up + SmoothN_Up; //---- Initialization of variables MinBarX_Dn = 2 + PeriodWATR_Dn; MinBar_Dn = 4 + 3 * JXLength_Dn + 30; MinBarN_Dn = 4 + Noise_period_Dn + SmoothN_Dn;
Assim, o código do EA é feito em três estágios. Entretanto, se você tentar construir esse código dentro de apenas um estágio, você pode cometer alguns erros nele que podem não ser facilmente detectados no futuro!
Conclusão
No presente artigo, apresentei minha versão de uma abordagem geral para escrever Expert Advisors usando três timeframes. Tecnicamente, essa ideia pode ser facilmente realizada no MQL4. Existem outras questões, entretanto: "Quais soluções ajudariam tal ideia a revelar seu certo sentido prático?"
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/1535
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso