Expert Advisors baseado em sistemas de trading populares e alquimia da otimização de robô de trading (Parte V)
Introdução
No meu artigo anterior desse ciclo (1, 2, 3, 4) , descrevi sistemas de trading mais simples, a diferença é que estávamos trabalhando com apenas um quadro. Como resultado, tal sistema de trading não tem absolutamente nenhuma reação às mudanças das tendências de mercado em uma escala de tempo mais global. Isso pode resultar em perdas nas condições de um mercado modificado, tais mudanças não são detectadas em um sistema daquele tipo. Na verdade, em sistemas de trading ao vivo com base em dados obtidos a partir de um gráfico de apenas um timeframe dificilmente pode ser usado. Geralmente, pelo menos dois timeframes são usados para uma operação normal. Uma tendência atual é geralmente identificada em um gráfico com timeframe maior, enquanto o ponto de mercado que entra na direção dessa tendência é calculado em um gráfico com timeframe menor. Na minha opinião, exemplos das estratégias de trading mais simples descritos em artigos anteriores são suficientes para o leitor aprender a projetar tais sistemas. Então agora vamos discutir métodos para melhorar tais sistemas de trading com base no raciocínio do que foi descrito acima.
Sistema de trading usando dois timeframes.
Do ponto de vista da lógica, não há diferença, com base no que o sistema de trading descreveu nos artigos anteriores, iremos construir um sistema mais complicado. Para sua essência inicial, cada sistema de trading mais simples pode ser apresentado da seguinte forma:
Para posições longas:
Para posições curtas:
Em nosso sistema de trading usando dois timeframes, essas condições para a entrada no mercado serão definidas com base nos indicadores calculados em um timeframe menor. A direção da tendência será identificada em um timeframe maior. Então, o algoritmo contendo essas condições irá ficar dessa forma:
Para posições longas:
Para posições curtas:
Nesse caso, a variável de Trend define somente a direção de uma tendência atual em um timeframe maior e a condição adicional de entrada no mercado limita as ações de trading de um Expert Advisor somente para a direção dessa tendência global. Do ponto de vista do código de programa, não faz diferença usar um certo algoritmo, a tendência atual será detectada em um timeframe maior. Então, cabe a um escritor de EA decidir quais algoritmos usar para calcular o ponto de entrada no mercado em um timeframe menor e detectar a tendência atual em um timeframe maior. Vamos analisar o algoritmo descrito anteriormente com o oscilador OsMA pelo EA Exp_5.mq4, para definir a tendência atual vamos usar o móvel J2JMA.mq4. Em tal caso, definir a condição de trade será muito simples:
Então, vamos adicionar alguns códigos ao Exp_5.mq4 existente, incluindo nele a lógica descrita acima. O código pronto ficará assim:
//For the EA operation Metatrader\EXPERTS\indicators folder must //contain indicators 5c_OsMA.mq4 and J2JMA.mq4 //+==================================================================+ //| Exp_11.mq4 | //| Copyright © 2008, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+==================================================================+ #property copyright "Copyright © 2008, 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 double Money_Management_Up = 0.1; //---- input parameters of the custom indicator J2JMA.mq4 extern int TimeframeX_Up = 240; extern int Length1X_Up = 4; // depth of the first smoothing extern int Phase1X_Up = 100; // parameter of the first smoothing //changing in the range -100 ... +100, influences the quality //of the transient process of averaging; extern int Length2X_Up = 4; // depth of the second smoothing extern int Phase2X_Up = 100; // parameter of the second smoothing, //changing in the range -100 ... +100, influences the quality //of the transient process of averaging; extern int IPCX_Up = 0;/* Selecting prices on which the indicator will be calculated (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.) */ //---- input parameters of the custom indicator 5c_OsMA.mq4 extern int Timeframe_Up = 60; extern double IndLevel_Up = 0; // breakout level of the indicator extern int FastEMA_Up = 12; // quick EMA period extern int SlowEMA_Up = 26; // slow EMA period extern int SignalSMA_Up = 9; // signal SMA period extern int STOPLOSS_Up = 50; // stop loss extern int TAKEPROFIT_Up = 100; // take profit extern int TRAILINGSTOP_Up = 0; // trailing stop extern int PriceLevel_Up =40; // difference between the current price and // the price of a 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 double Money_Management_Dn = 0.1; //---- input parameters of the custom indicator J2JMA.mq4 extern int TimeframeX_Dn = 240; extern int Length1X_Dn = 4; // smoothing depth extern int Phase1X_Dn = 100; // parameter of the first smoothing //changing in the range -100 ... +100, influences the quality //of the transient process of averaging; extern int Length2X_Dn = 4; // smoothing depth extern int Phase2X_Dn = 100; // parameter of the second smoothing //changing in the range -100 ... +100, influences the quality //of the transient process of averaging; extern int IPCX_Dn = 0;/* Selecting prices on which the indicator will be calculated (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.) */ //---- input parameters of the custom indicator 5c_OsMA.mq4 extern int Timeframe_Dn = 60; extern double IndLevel_Dn = 0; // breakout level of the indicator extern int FastEMA_Dn = 12; // quick EMA period extern int SlowEMA_Dn = 26; // slow EMA period extern int SignalSMA_Dn = 9; // signal SMA period extern int STOPLOSS_Dn = 50; // stop loss extern int TAKEPROFIT_Dn = 100; // take profit extern int TRAILINGSTOP_Dn = 0; // trailing stop extern int PriceLevel_Dn = 40; // difference between the current price and // the price of a pending order triggering extern bool ClosePos_Dn = true; // forced position closing allowed //----+ +--------------------------------------------------------------------------+ //---- Integer variables for the minimum of calculation bars int MinBarX_Up, MinBar_Up, MinBarX_Dn, MinBar_Dn; //+==================================================================+ //| TimeframeCheck() functions | //+==================================================================+ void TimeframeCheck(string Name, int Timeframe) { //----+ //---- Checking the correctness of Timeframe variable value if (Timeframe != 1) if (Timeframe != 5) if (Timeframe != 15) if (Timeframe != 30) if (Timeframe != 60) if (Timeframe != 240) if (Timeframe != 1440) Print(StringConcatenate("TimeframeCheck: Parameter ",Name, " cannot ", "be equal to ", Timeframe, "!!!")); //----+ } //+==================================================================+ //| Custom Expert functions | //+==================================================================+ #include <Lite_EXPERT1.mqh> //+==================================================================+ //| Custom Expert initialization function | //+==================================================================+ int init() { //---- Checking the correctness of Timeframe_Up variable value TimeframeCheck("Timeframe_Up", Timeframe_Up); //---- Checking the correctness of TimeframeX_Up variable value TimeframeCheck("TimeframeX_Up", TimeframeX_Up); //---- Checking the correctness of Timeframe_Dn variable value TimeframeCheck("Timeframe_Dn", Timeframe_Dn); //---- Checking the correctness of Timeframe_Dn variable value TimeframeCheck("TimeframeX_Dn", TimeframeX_Dn); //---- Initialization of variables MinBar_Up = 3 + MathMax(FastEMA_Up, SlowEMA_Up) + SignalSMA_Up; MinBarX_Up = 3 + 30 + 30; MinBar_Dn = 3 + MathMax(FastEMA_Dn, SlowEMA_Dn) + SignalSMA_Dn; MinBarX_Dn = 3 + 30 + 30; //---- 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 double J2JMA1, J2JMA2, Osc1, Osc2; //----+ Declaring static variables //----+ +---------------------------------------------------------------+ static double TrendX_Up, TrendX_Dn; static datetime StopTime_Up, StopTime_Dn; static int LastBars_Up, LastBarsX_Up, LastBarsX_Dn, 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); int IBARSX_Up = iBars(NULL, TimeframeX_Up); if (IBARS_Up >= MinBar_Up && IBARSX_Up >= MinBarX_Up) { //----+ +----------------------+ //----+ DEFINING TREND | //----+ +----------------------+ if (LastBarsX_Up != IBARSX_Up) { //----+ Initialization of variables LastBarsX_Up = IBARSX_Up; BUY_Stop = false; //----+ calculating indicator values for J2JMA J2JMA1 = iCustom(NULL, TimeframeX_Up, "J2JMA", Length1X_Up, Length2X_Up, Phase1X_Up, Phase2X_Up, 0, IPCX_Up, 0, 1); //--- J2JMA2 = iCustom(NULL, TimeframeX_Up, "J2JMA", Length1X_Up, Length2X_Up, Phase1X_Up, Phase2X_Up, 0, IPCX_Up, 0, 2); //----+ defining trend TrendX_Up = J2JMA1 - J2JMA2; //----+ defining a signal for closing trades if (TrendX_Up < 0) BUY_Stop = true; } //----+ +----------------------------------------+ //----+ DEFINING SIGNAL FOR MARKET ENTERING | //----+ +----------------------------------------+ if (LastBars_Up != IBARS_Up) { //----+ Initialization of variables BUY_Sign = false; LastBars_Up = IBARS_Up; StopTime_Up = iTime(NULL, Timeframe_Up, 0) + 60 * Timeframe_Up; //----+ calculating indicator values Osc1 = iCustom(NULL, Timeframe_Up, "5c_OsMA", FastEMA_Up, SlowEMA_Up, SignalSMA_Up, 5, 1); //--- Osc2 = iCustom(NULL, Timeframe_Up, "5c_OsMA", FastEMA_Up, SlowEMA_Up, SignalSMA_Up, 5, 2); //----+ defining signals for trades if (TrendX_Up > 0) if (Osc2 < IndLevel_Up) if (Osc1 > IndLevel_Up) BUY_Sign = 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); if (!Make_TreilingStop(1, TRAILINGSTOP_Up)) return(-1); } } //----+ +---------------------------------------------------------------+ //----++ CODE FOR SHORT POSITIONS | //----+ +---------------------------------------------------------------+ if (Test_Dn) { int IBARS_Dn = iBars(NULL, Timeframe_Dn); int IBARSX_Dn = iBars(NULL, TimeframeX_Dn); if (IBARS_Dn >= MinBar_Dn && IBARSX_Dn >= MinBarX_Dn) { //----+ +----------------------+ //----+ DEFINING TREND | //----+ +----------------------+ if (LastBarsX_Dn != IBARSX_Dn) { //--- Initialization of variables LastBarsX_Dn = IBARSX_Dn; SELL_Stop = false; //----+ calculating indicator values for J2JMA J2JMA1 = iCustom(NULL, TimeframeX_Dn, "J2JMA", Length1X_Dn, Length2X_Dn, Phase1X_Dn, Phase2X_Dn, 0, IPCX_Dn, 0, 1); //--- J2JMA2 = iCustom(NULL, TimeframeX_Dn, "J2JMA", Length1X_Dn, Length2X_Dn, Phase1X_Dn, Phase2X_Dn, 0, IPCX_Dn, 0, 2); //----+ defining trend TrendX_Dn = J2JMA1 - J2JMA2; //----+ defining a signal for closing trades if (TrendX_Dn > 0) SELL_Stop = true; } //----+ +----------------------------------------+ //----+ DEFINING SIGNAL FOR MARKET ENTERING | //----+ +----------------------------------------+ if (LastBars_Dn != IBARS_Dn) { //----+ Initialization of variables SELL_Sign = false; LastBars_Dn = IBARS_Dn; StopTime_Dn = iTime(NULL, Timeframe_Dn, 0) + 60 * Timeframe_Dn; //----+ calculating indicator values Osc1 = iCustom(NULL, Timeframe_Dn, "5c_OsMA", FastEMA_Dn, SlowEMA_Dn, SignalSMA_Dn, 5, 1); //--- Osc2 = iCustom(NULL, Timeframe_Dn, "5c_OsMA", FastEMA_Dn, SlowEMA_Dn, SignalSMA_Dn, 5, 2); //----+ defining signals for trades if (TrendX_Dn < 0) if (Osc2 > IndLevel_Dn) if (Osc1 < IndLevel_Dn) SELL_Sign = 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); if (!Make_TreilingStop(2, TRAILINGSTOP_Dn)) return(-1); } } //----+ +---------------------------------------------------------------+ //----+ return(0); } //+------------------------------------------------------------------+
Visualmente, esse código é duas vezes maior do que o código inicial Exp_5mq4, embora a ideia não fosse aparentemente tão grande! Agora, vamos discutir o resultado. Mais uma vez, irei analisar somente a parte do EA para posições longas, para as curtas, é análogo. O código fonte adicional para obter os valores necessários do indicador J2JMA fica assim:
//----+ calculating indicator values for J2JMA J2JMA1 = iCustom(NULL, TimeframeX_Up, "J2JMA", Length1X_Up, Phase1X_Up, Length2X_Up, Phase2X_Up, 0, IPCX_Up, 0, 1); //--- J2JMA2 = iCustom(NULL, TimeframeX_Up, "J2JMA", Length1X_Up, Phase1X_Up, Length2X_Up, Phase2X_Up, 0, IPCX_Up, 0, 2); //----+ defining trend Trend_Up = J2JMA1 - J2JMA2;
Nesse ponto, a parte principal do EA agora contém a declaração de seis variáveis externas novas correspondentes à solicitação do indicador J2JMA:
extern int TimeframeX_Up = 240; extern int Length1X_Up = 4; // depth of the first smoothing extern int Phase1X_Up = 100; // parameter of the first smoothing //changing in the range -100 ... +100, influences the quality //of the transient process of averaging; extern int Length2X_Up = 4; // depth of the second smoothing extern int Phase2X_Up = 100; // parameter of the second smoothing, //changing in the range -100 ... +100, influences the quality //of the transient process of averaging; extern int IPCX_Up = 0;/* Selecting prices on which the indicator will be calculated (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.) */
Uma nova variável análoga MinBarX_Up é adicionada à linha de declaração das variáveis globais para o calculo mínimo das barras, que segue as variáveis externas do EA:
//---- Integer variables for the minimum of calculation bars int MinBarX_Up, MinBar_Up, MinBarX_Dn, MinBar_Dn;
No bloco de inicialização do EA, a verificação adicional da correção da variável externa TimeframeX_Up é feita
//---- Checking the correctness of TimeframeX_Up variable value TimeframeCheck("TimeframeХ_Up", TimeframeX_Up);
No mesmo bloco, fazer inicialização das variáveis MinBarX_Up:
MinBarX_Up = 3 + 30 + 30;
Modificações adicionais dos códigos são realizadas no bloco de função de início() do EA. Duas novas variáveis são adicionadas na linha do local de declaração de variáveis. J2JMA1 e J2JMA2:
//----+ Declaring local variables double J2JMA1, J2JMA2, Osc1, Osc2;
A variável Trend_Up é declarada com uma variável estática, pois é inicializada apenas uma vez na mudança de barra, seu valor é usado em um tick adicional da função de início():
static double TrendX_Up, TrendX_Dn;
Por analogia, a variável LastBarsX_Up é declarada como estática:
static int LastBars_Up, LastBarsX_Up, LastBarsX_Dn, LastBars_Dn;
No código para posições longas, a verificação da suficiência para cálculos torna-se mais complicada:
if (Test_Up) { int IBARS_Up = iBars(NULL, Timeframe_Up); int IBARSX_Up = iBars(NULL, TimeframeX_Up); if (IBARS_Up >= MinBar_Up && IBARSX_Up >= MinBarX_Up) { // CODE FOR LONG POSITIONS } }
e um novo bloco é adicionado:
//----+ +----------------------+ //----+ DEFINING TREND | //----+ +----------------------+ if (LastBarsX_Up != IBARSX_Up) { //----+ Initialization of variables LastBarsX_Up = IBARSX_Up; BUY_Stop = false; //----+ calculating indicator values for J2JMA J2JMA1 = iCustom(NULL, TimeframeX_Up, "J2JMA", Length1X_Up, Phase1X_Up, Length2X_Up, Phase2X_Up, 0, IPCX_Up, 0, 1); //--- J2JMA2 = iCustom(NULL, TimeframeX_Up, "J2JMA", Length1X_Up, Phase1X_Up, Length2X_Up, Phase2X_Up, 0, IPCX_Up, 0, 2); //----+ defining trend TrendX_Up = J2JMA1 - J2JMA2; //----+ defining a signal for closing trades if (Trend_Up < 0) BUY_Stop = true; }
Nesse bloco, o necessário para nós é que a variável Trend_Up seja inicializada, além disso, sinais para o fechamento forçado das posições abertas são definidos aqui (inicialização da variável do BUY_Stop). Geralmente, no inicial Exp_5.mq4, a última variável foi inicializada no bloco “DEFININDO SINAIS PARA A ENTRADA NO MERCADO”, mas é mais lógico no novo EA colocar essa inicialização no bloco "DEFININDO TENDÊNCIA" e mudar o algoritmo da sua inicialização.
E o aspecto mais importante é uma pequena mudança de algoritmo de definição de sinal no bloco "DEFININDO SINAIS PARA A ENTRADA NO MERCADO":
//----+ defining signals for trades if (TrendX_Up > 0) if (Osc2 < IndLevel_Up) if (Osc1 > IndLevel_Up) BUY_Sign = true;
Depois de todas as modificações, esse algoritmo leva em consideração a direção de uma tendência atual com a ajuda da variável Trend_Up.
Agora, sobre alguns detalhes da otimização do EA. Naturalmente, o EA deve ser otimizado separadamente, apenas por posições longas ou curtas, e até mesmo, nesse caso, não há muitas variáveis externas para otimização. Provavelmente, não é sensato otimizar todas essas variáveis ao mesmo tempo. Além disso - o algoritmo genético de otimização não vai otimizar mais do que oito variáveis! A solução mais adequada nesse caso é fixar os valores de algumas variáveis e otimizar apenas a parte que permaneceu sem fixar - as variáveis mais urgentes. E depois da otimização, selecione a variante mais adequada e tente otimizar os parâmetros restantes.
Por exemplo, para posições longas, isso pode ficar assim:
Um arquivo com essas configurações para o testador Exp_11.ini está no arquivo TESTER.zip. Aqui não precisamos otimizar Money_Management_Up e nem TimeframeX_Up. Para a variável TimeframeX_Up, deve ser notado que, inicialmente, seu valor deve ser maior do que o da variável Timeframe_Up. Os valores de Length1X_Up podem ser modificados em uma faixa bem abrangente, os valores de Phase1X_Up na faixa de -100 a 100. Os parâmetros Length2X_Up, Phase2X_Up e IPCX_Up deve ser fixados da melhor forma na primeira otimização, os mesmo para o parâmetro IndLevel_Up descrito em meu artigo anterior que descreve Exp_5.mq4. Para os parâmetros FastEMA_Up e SlowEMA_Up , valores mais baixos de mudança de parâmetros não devem ser pequenos demais. Claro, eles podem mostrar resultados impressionantes, mas haverá sentido nesses resultados? A sensatez do uso de um trailing stop deve ser verificada depois da otimização. Mas a posição forçada, fechando pelas variáveis lógicas ClosePos_Up deve ser sempre aplicada nas mudanças de tendência. Seu valor deve ser fixado da melhor forma como igual a "verdadeiro".
Durante a otimização, o período do gráfico no testador de estratégia deve ser igual ao valor da variável Timeframe_Up ou Timeframe_Dn (dependendo da direção do trading durante a otimização) e no teste final ou na operação em uma conta, o período do gráfico deve ser configurado igual ao menor desses valores. Há mais um detalhe importante. Esse Expert Advisor usa, pelo menos, dois timeframes, então esteja atento ao baixar os dados de histórico para otimização, testar e operar em contas, especialmente se você usa várias contas abertas em dealers diferentes.
No quarto artigo, descrevi como exportar resultados de otimização para análise estatística mais abrangente no Microsoft Excel. Na minha opinião, o EA oferecido nesse artigo se adequa melhor para tais procedimentos. Se alguém quiser tentar, modifique o código do EA com a conta para recomendações desse artigo Exp_11_2.mq4). O código está anexado ao artigo.
Mais um exemplo de um EA usado para dados de cálculos de dois gráficos de diferentes timeframes.
Suponho que um exemplo de um EA baseado nessa ideia não seja suficiente para esse artigo, então, incluirei mais um Expert Advisor construído de acordo com esse princípio. Como base, vou usar meu primeiro EA Exp_1.mq4 do meu primeiro artigo. A parte do código responsável por definir as condições para a entrada no mercado e administrar posições está pronta. Agora, precisamos definir a tendência ativa do mercado para um timeframe maior. Nesse Expert Advisor, uso o indicador MAMA_NK.mq4:
A condição para definir uma direção de tendência, nesse caso, é diferente dos valores de dois móveis na primeira barra:
Vamos escrever um código por analogia, o código Exp_11.mq4 é usado como um template:
//+==================================================================+ //| Exp_12.mq4 | //| Copyright © 2008, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+==================================================================+ #property copyright "Copyright © 2008, 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 double Money_Management_Up = 0.1; //---- extern int TimeframeX_Up = 240; extern double FastLimitX_Up = 0.5; extern double SlowLimitX_Up = 0.05; extern int IPCX_Up = 9;/* Selecting prices, upon which the indicator will be calculated (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, 15-Heiken Ashi Open0.) */ //---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + extern int Timeframe_Up = 60; extern int Length_Up = 4; // smoothing depth extern int Phase_Up = 100; // parameter changing in the range //-100 ... +100, influences the quality of a transient process; extern int IPC_Up = 0;/* Selecting prices, upon which the indicator will be calculated (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 is allowed //----+ +---------------------------------------------------------------------------+ //---- EA INPUT PARAMETERS FOR SELL TRADES extern bool Test_Dn = true;//filter of trade calculations direction extern double Money_Management_Dn = 0.1; //---- extern int TimeframeX_Dn = 60; extern double FastLimitX_Dn = 0.5; extern double SlowLimitX_Dn = 0.05; extern int IPCX_Dn = 9;/* Selecting prices, upon which the indicator will be calculated (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, 15-Heiken Ashi Open0.) */ //---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + extern int Timeframe_Dn = 60; extern int Length_Dn = 4; // smoothing depth extern int Phase_Dn = 100; // parameter changing in the range // -100 ... +100, influences the quality of a transient process; extern int IPC_Dn = 0;/* Selecting prices, upon which the indicator will be calculated (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 is allowed //----+ +---------------------------------------------------------------------------+ //---- Integer variables for the minimum of counted bars int MinBar_Up, MinBar_Dn, MinBarX_Up, MinBarX_Dn; //+==================================================================+ //| Custom Expert functions | //+==================================================================+ #include <Lite_EXPERT1.mqh> //+==================================================================+ //| TimeframeCheck() functions | //+==================================================================+ void TimeframeCheck(string Name, int Timeframe) { //----+ //---- Checking the correctness of Timeframe variable value 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 correctness of Timeframe_Up variable value TimeframeCheck("TimeframeX_Up", TimeframeX_Up); //---- Checking the correctness of Timeframe_Up variable value TimeframeCheck("Timeframe_Up", Timeframe_Up); //---- Checking the correctness of Timeframe_Dn variable value TimeframeCheck("TimeframeX_Dn", TimeframeX_Dn); //---- Checking the correctness of Timeframe_Dn variable value TimeframeCheck("Timeframe_Dn", Timeframe_Dn); //---- Initialization of variables MinBarX_Up = 1 + 7; MinBar_Up = 4 + 39 + 30; MinBarX_Dn = 1 + 7; MinBar_Dn = 4 + 39 + 30; //---- end of initialization return(0); } //+==================================================================+ //| expert deinitialization function | //+==================================================================+ int deinit() { //----+ //---- End of the EA deinitialization return(0); //----+ } //+==================================================================+ //| Custom Expert iteration function | //+==================================================================+ int start() { //----+ Declaration of local variables int bar; double Mov[3], dMov12, dMov23, Mama1, Fama1; //----+ declaration of static variables static double TrendX_Up, TrendX_Dn; static int LastBars_Up, LastBars_Dn, LastBarsX_Up, LastBarsX_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); int IBARSX_Up = iBars(NULL, TimeframeX_Up); if (IBARS_Up >= MinBar_Up && IBARSX_Up >= MinBarX_Up) { //----+ +----------------------+ //----+ DEFINING TREND | //----+ +----------------------+ if (LastBarsX_Up != IBARSX_Up) { //----+ Initialization of variables LastBarsX_Up = IBARSX_Up; BUY_Stop = false; //----+ calculating indicator values Fama1 = iCustom(NULL, TimeframeX_Up, "MAMA_NK", FastLimitX_Up, SlowLimitX_Up, IPCX_Up, 0, 1); //--- Mama1 = iCustom(NULL, TimeframeX_Up, "MAMA_NK", FastLimitX_Up, SlowLimitX_Up, IPCX_Up, 1, 1); //----+ defining trend TrendX_Up = Mama1 - Fama1; //----+ defining signals for trade closing if (TrendX_Up < 0) BUY_Stop = true; } //----+ +----------------------------------------+ //----+ DEFINING SIGNAL FOR MARKET ENTERING | //----+ +----------------------------------------+ if (LastBars_Up != IBARS_Up) { //----+ Initialization of variables BUY_Sign = false; LastBars_Up = IBARS_Up; //----+ calculating indicator values and uploading them into buffer for(bar = 1; bar <= 3; bar++) Mov[bar - 1]= iCustom(NULL, Timeframe_Up, "JFatl", Length_Up, Phase_Up, 0, IPC_Up, 0, bar); //----+ defining signals for trades dMov12 = Mov[0] - Mov[1]; dMov23 = Mov[1] - Mov[2]; if (TrendX_Up > 0) if (dMov23 < 0) if (dMov12 > 0) BUY_Sign = 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); int IBARSX_Dn = iBars(NULL, TimeframeX_Dn); if (IBARS_Dn >= MinBar_Dn && IBARSX_Dn >= MinBarX_Dn) { //----+ +----------------------+ //----+ DEFINING TREND | //----+ +----------------------+ if (LastBarsX_Dn != IBARSX_Dn) { //----+ Initialization of variables LastBarsX_Dn = IBARSX_Dn; SELL_Stop = false; //----+ calculating indicator values Fama1 = iCustom(NULL, TimeframeX_Dn, "MAMA_NK", FastLimitX_Dn, SlowLimitX_Dn, IPCX_Dn, 0, 1); //--- Mama1 = iCustom(NULL, TimeframeX_Dn, "MAMA_NK", FastLimitX_Dn, SlowLimitX_Dn, IPCX_Dn, 1, 1); //----+ defining trend TrendX_Dn = Mama1 - Fama1; //----+ defining signals for trade closing if (TrendX_Dn > 0) SELL_Stop = true; } //----+ +----------------------------------------+ //----+ DEFINING SIGNAL FOR MARKET ENTERING | //----+ +----------------------------------------+ if (LastBars_Dn != IBARS_Dn) { //----+ Initialization of variables SELL_Sign = false; LastBars_Dn = IBARS_Dn; //----+ calculating indicator values and uploading them into buffer for(bar = 1; bar <= 3; bar++) Mov[bar - 1]= iCustom(NULL, Timeframe_Dn, "JFatl", Length_Dn, Phase_Dn, 0, IPC_Dn, 0, bar); //----+ defining signals for trades dMov12 = Mov[0] - Mov[1]; dMov23 = Mov[1] - Mov[2]; if (TrendX_Dn < 0) if (dMov23 > 0) if (dMov12 < 0) SELL_Sign = 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); } //+------------------------------------------------------------------+
Embora o algoritmo básico desse EA seja diferente daquele subjacente ao EA anterior, a ideia geral de uso de dois gráficos parece estar absolutamente operante nesse caso também.
Conclusão
Acredito que a abordagem de construir sistemas de trading automatizados descrita nesse artigo irá ajudar os leitores que já tem alguma experiência em escrever EA a construir Expert Advisors análogos com mínimos esforço. Também deve ser adicionado aqui que a utilidade prática de tais Advisors depende, em grande parte, da sua própria otimização.
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/1525
- 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