Expert Advisors baseado em sistemas de trading populares e alquimia da otimização de robô de trading (Parte III)
Introdução
Recebi uma oferta de um leitor do artigo anterior para automatizar um pouco o processo de simulação para obter a possibilidade de receber resultados de todas as otimizações ao mesmo tempo. Além do mais, não é muito conveniente mudar o período de teste manualmente, esse processo deve também ser automatizado. A ideia é ótima. Ainda mais porque os recursos do MQL4 oferecem todas as possibilidades para sua implementação. Então vou começar o artigo a partir da solução deste problema.
Automação de simulações
O que precisamos para a solução dessa tarefa:
1. Escreva no cabeçalho do Expert Advisor abaixo uma linha com o seguinte conteúdo:
//+==================================================================+ //| Custom BackTesting function | //+==================================================================+ #include <IsBackTestingTime.mqh>
Usando essa diretiva incluímos a função IsBackTestingTime() no código do EA. E não esqueça de colocar o arquivo IsBackTestingTime.mqh no diretório/pasta INCLUDE. Essa função:
bool IsBackTestingTime()
{
}
é usada para definir o período de tempo, dentro do qual a otimização de simulações ou simulações ocorrerão. Nesses períodos de tempo a função sempre retornará 'verdadeiro', em qualquer outro ela retornará 'falso'. Além desta função, variáveis externas do EA são adicionadas no código do EA por esta diretiva:
//---- 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
Espero que o significado dessas variáveis esteja claro para os que leram meu artigo anterior, de modo que não precisará ser explicado novamente.
2. No bloco da função inicial antes do código do EA coloque o código universal mais simples da chamada IsBackTestingTime(), ele limita a operação do EA para certos períodos de tempo, dependendo do número de otimização de simulações.
//----+ Execution of backtesting conditions if (!IsBackTestingTime()) return(0);
Esquematicamente terá a seguinte aparência:
//+==================================================================+ //| 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); } //+------------------------------------------------------------------+
Se você está interessado na solução detalhada do problema no exemplo de um EA já pronto, consulte o código de EA Exp_5_1.mq4, que é a forma do EA do artigo anterior Exp_5.mq4 modificado para simulações. Na verdade não há uma ampla diferença na otimização do EA similar, quando comparado a um Expert Advisor simples. Entretanto, acho que variáveis de testes de fundo não devem ser otimizadas, exceto por Opt_Number, embora você possa ter outra opinião.
É importante lembrar que após a otimização durante os testes obteremos resultados que não estão dentro do período de otimização e sim após ele, depois da sua borda direita! Não é uma boa decisão fazer todas as otimizações de testes de fundo dentro de uma execução usando um algoritmo genético, é muito mais interessante analisar profundamente cada otimização de simulações separadamente sem a otimização da variável de entrada do Opt_Number.
Mas mesmo neste caso tal abordagem facilita o entendimento do comportamento do EA. E deve ser lembrado que o valor da variável externa Opt_Number pode mudar de zero a um certo valor máximo que pode ser definido da seguinte forma: do período total no qual todas as otimizações de simulações são conduzidas (em meses) subtraindo o período de otimização de simulações em meses (Opt_Period) e subtraindo o período de simulações (Test_Period). Adicione um para o valor obtido. O resultado obtido será o máximo da variável Opt_Number se o Period_Shift é igual a um.
Sistemas de negociação baseados na correlação de duas móveis
Essa variação de sistemas de negociação é muito popular. Agora vamos analisar o algoritmo baseado nestas estratégias. Para posições longas o algoritmo de entrada se parece com isso:
Para posições curtas é o seguinte:
Como indicadores, duas móveis idênticas com diferentes parâmetros definindo a média nos indicadores podem ser usados. Presume-se que o parâmetro definindo a média de movimento MovA é sempre menor do que o mesmo parâmetro do movimento MovB. Deste modo, neste sistema de negociação MovA é um movimento rápido, MovB é um movimento lento. Aqui está a variação de implementação do sistema de negociação com base nos dois movimentos JMA:
//+==================================================================+ //| 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); } //+------------------------------------------------------------------+
Sistemas de negociação baseados em correlação de dois osciladores
A estratégia de negociação similar pode ser utilizada não somente com movimentos, mas também com osciladores, mas neste caso, como escrito no artigo anterior, é melhor colocar pedidos pendentes ao invés de entrar no mercado imediatamente após receber os sinais. Como um exemplo real o diagrama MACD pode ser usado.
Para colocar pedidos pendentes BuyLimit o algoritmo será como a seguir:
Aqui está o algoritmo para pedidos de tipo SellLimit:
O código deste EA é similar ao código do EA anterior:
//+==================================================================+ //| 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); } //+------------------------------------------------------------------+
Conclusão
Mais um artigo chega ao fim. Mais um sistema de negociação foi implementado nos Expert Advisors baseados em variantes absolutamente diferentes dos indicadores. Espero que esse artigo seja útil para escritores de EA iniciantes para desenvolverem ainda mais suas habilidades de converter um algoritmo corretamente formalizado a um código pronto e absolutamente operacional dos seus Expert Advisors.
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/1521
- 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