Ação do Preço: Automatizando a Estratégia de Negociação "Inside Bar"
Introdução
Todos os traders de Forex se deparam com a Ação do Preço em algum ponto. Esta não é uma mera técnica de análise gráfica, mas todo um sistema para definir a possível orientação do movimento do preço no futuro. Neste artigo vamos olhar para o padrão "Inside Bar" em detalhes e desenvolver um EA para o rastreamento e realizaçao de operações de negociação neste padrão.
Sobre a Ação do Preço
A ação do preço é um método de detecção de movimento de preços sem indicador, usando padrões simples e complexos, bem como elementos auxiliares gráfico (linhas verticais e de tendências, níveis Fibo, níveis horizontais, suporte/resistência, etc).
À primeira vista o método pode parecer um pouco complicado, mas na verdade não é. O método está ganhando popularidade de ano para ano, pois as suas vantagens são evidentes, por exemplo: quando comparado com os métodos que envolvem indicadores técnicos.
"Inside Bar" (Barra Envolvida)
O padrão "Inside Bar" é uma barra que tem o seu corpo e as sombras envolvidos inteiramente dentro do intervalo da barra anterior (mãe). A "Inside Bar" de Alta encontra-se envolvida pela barra mãe, formando um padrão altista. A "Inside Bar" de Baixa encontra-se envolvida pela barra mãe, formando um padrão baixista. Estes padrões formados são considerados como um potencial sinal de entrada.
Este é um padrão de dois lados, pois pode indicar tanto uma reversão como uma continuação de tendência.
Fig. 1. "Inside Bar" (Barra Envolvida)
Fig. 2. Layout do padrão "Inside Bar"
Regras da "Inside Bar" (Barra Envolvida):- O padrão "Inside Bar" é significativo nos timeframes maiores, como H4 ou D1.
- O padrão pode indicar uma reversão de tendência ou uma continuação.
- Se faz necessário aplicar ferramentas de análise gráficas adicionais para uma entrada mais precisa, tais como: linhas de tendência, os níveis de suporte/resistência, níveis Fibo outros padrões de ação do preço, etc.
- Usar ordens pendentes para evitar as entradas prematuras ou falsas no mercado.
- Não usar barras internas repetidas que ocorrem no mercado lateral como sinais de entrada no mercado.
Fig. 3. Definindo uma genuína "Inside Bar" no GBPUSD D1
Tendo isto em mente, vamos tentar definir uma verdadeira "Inside Bar". No gráfico acima podemos ver que uma barra de alta foi formada após um acentuado movimento descendente, esta barra encontra-se completamente envolvida dentro dos limites da anterior. O padrão é confirmado pelo fato de ter sido formado no nível de suporte. A terceira confirmação é a ausência de plano lateral das outras barras. Uma vez que o padrão satisfaça as regras, pode ser considerado genuíno.
Definindo Pontos de Entrada e Ordens Stop
Então, nós encontramos uma verdadeira "Inside Bar" no gráfico (Fig. 3). Como devemos entrar no mercado e onde devemos definir nossas Ordens de Stop? Vamos examinar a Figura 4.
Fig. 4. Definir Buy Stop e Ordens Stop
Primeiro, vamos considerar o exemplo acima para definir as regras do nível stop:
- Definir uma ordem pendente Buy Stop ligeiramente acima Máxima do preço da Barra Mãe (apenas alguns pontos a mais, para confirmação).
- Definir um nível de Stop Loss abaixo do nível de suporte, mais ou menos na mínima de preço da Barra Mãe. Esta é uma proteção adicional no caso de uma ordem pendente ser acionada.
- Definir um nível de Take Profit ligeiramente menor do que o nível de resistência mais próximo.
Fig. 5. Definindo Sell Stop e Ordens Stop
Primeiro, vamos considerar o exemplo acima para definir as regras do nível stop:
- Definir uma ordem pendente Sell Stop ligeiramente abaixo da Mínima de Preço da Barra Mãe (apenas alguns pontos abaixo, para confirmação).
- Definir um nível de Stop Loss acima da Máxima de preço da Barra Mãe.
- Definir um nível de Take Profit ligeiramente menor do que o nível de suporte mais próximo.
Desenvolver um Expert Advisor de Negociação Baseado na "Inside Bar"
Agora que sabemos todas as regras necessárias para definir uma verdadeira "Inside Bar", entrar no mercado e definir ordens stop, podemos finalmente implementar o Expert Advisor apropriado a fim de operar com o padrão "Inside Bar".
Vamos abrir o MetaEditor do terminal MetaTrader 4 e criar um novo Expert Advisor (eu acredito que não necessito entrar nesta área, uma vez que o site oferece muitas informações sobre como criar um Expert Advisor). Todos os parâmetros são deixados em branco nesta fase. Você pode nomeá-los como quiser. O código resultante ficará da seguinte forma:
//+------------------------------------------------------------------+ //| InsideBar.mq4 | //| Copyright 2015, Iglakov Dmitry. | //| cjdmitri@gmail.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Iglakov Dmitry." #property link "cjdmitri@gmail.com" #property version "1.00" #property strict //+------------------------------------------------------------------+ //| Função de inicialização do expert | //+------------------------------------------------------------------+ int OnInit() { //--- //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Função desinicialização do expert | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Função tick do Expert | //+------------------------------------------------------------------+ void OnTick() { //--- } //+------------------------------------------------------------------+
Convertendo o Padrão em MQL4 Algorithm
Depois de ter criado o EA, precisamos definir uma "Inside Bar" após uma outra barra ser fechada. Para fazer isso, vamos introduzir novas variáveis e atribuir valores a elas. Veja o código abaixo:
//+------------------------------------------------------------------+ //| InsideBar.mq4 | //| Copyright 2015, Iglakov Dmitry. | //| cjdmitri@gmail.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Iglakov Dmitry." #property link "cjdmitri@gmail.com" #property version "1.00" #property strict double open1,//Abertura do preço da primeira barra open2, //Abertura do preço da Segunda barra close1, //Fechamento do preço da primeira barra close2, //Fechamento do preço da segunda barra low1, //Mínima do preço da primeira barra low2, //Mínima do preço da segunda barra high1, //Máxima do preço da primeira barra high2; //Máxima do preço da segunda barra //+------------------------------------------------------------------+ //| Função de inicialização do expert | //+------------------------------------------------------------------+ int OnInit() { return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Função desinicialização do expert | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { } //+------------------------------------------------------------------+ //| Função tick do Expert | //+------------------------------------------------------------------+ void OnTick() { //--- Definir os preços das barras necessárias open1 = NormalizeDouble(iOpen(Symbol(), Period(), 1), Digits); open2 = NormalizeDouble(iOpen(Symbol(), Period(), 2), Digits); close1 = NormalizeDouble(iClose(Symbol(), Period(), 1), Digits); close2 = NormalizeDouble(iClose(Symbol(), Period(), 2), Digits); low1 = NormalizeDouble(iLow(Symbol(), Period(), 1), Digits); low2 = NormalizeDouble(iLow(Symbol(), Period(), 2), Digits); high1 = NormalizeDouble(iHigh(Symbol(), Period(), 1), Digits); high2 = NormalizeDouble(iHigh(Symbol(), Period(), 2), Digits); } //+------------------------------------------------------------------+
Como exemplo, vamos considerar que uma Barra Mãe é de baixa(barra 2), enquanto uma Inside Bar é de alta(barra 1). Vamos adicionar uma série de condições para o corpo da função OnTick():
void OnTick() { //--- Definir os preços das barras necessárias open1 = NormalizeDouble(iOpen(Symbol(), Period(), 1), Digits); open2 = NormalizeDouble(iOpen(Symbol(), Period(), 2), Digits); close1 = NormalizeDouble(iClose(Symbol(), Period(), 1), Digits); close2 = NormalizeDouble(iClose(Symbol(), Period(), 2), Digits); low1 = NormalizeDouble(iLow(Symbol(), Period(), 1), Digits); low2 = NormalizeDouble(iLow(Symbol(), Period(), 2), Digits); high1 = NormalizeDouble(iHigh(Symbol(), Period(), 1), Digits); high2 = NormalizeDouble(iHigh(Symbol(), Period(), 2), Digits); // --- Se a segunda barra é de baixa, enquanto a primeira é de alta if(open2>close2 && //Segunda barra é de baixa close1>open1 && //Primeira barra é de alta high2>high1 && //Máxima da segunda barra excede a Máxima da primeira open2>close1 && //Abertura da segunda barra excede o Fechamento da primeira barra low2<low1) //Mínima da segunda barra e menor do que a Mínima da primeira barra { //--- Listamos todas as condições que definem que a primeira barra está completamente envolvida pela segunda } }
- Criar variáveis personalizáveis: ordens stop, desvio (slippage), o tempo de expiração da ordem, número mágico do EA, lote de negociação. O stop loss pode ser omitido, uma vez que será definido de acordo com as regras da "Inside Bar".
- Digite as variáveis locais para normalizar a aparência das variáveis.
- As ordens são ajustados a uma certa distância a partir dos valores dos preços das barras. Para implementar isso, adicione a níveis da variavel Interval responsável pelo intervalo entre as Máximas/Mínimas dos preços das barras e nível das ordens, bem como níveis de ordens pendentes.
- Adicione a variável timeBarInside para evitar reabertura de ordens neste padrão.
- Adicione a variável bar2size para assegurar que a Barra Mãe seja suficientemente grande, o que será um bom sinal quando o mercado em andamento não é lateral.
Como resultado, obtém-se o seguinte código:
//+------------------------------------------------------------------+ //| InsideBar.mq4 | //| Copyright 2015, Iglakov Dmitry. | //| cjdmitri@gmail.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Iglakov Dmitry." #property link "cjdmitri@gmail.com" #property version "1.00" #property strict extern int interval = 20; //Intervalos extern double lot = 0.1; //Tamanho do Lote extern int TP = 300; //Take Profit extern int magic = 555124; //Número mágico extern int slippage = 2; //Desvio extern int ExpDate = 48; //Hora de Expiração da Ordem extern int bar2size = 800; //Tamanho da Barra 2 double buyPrice,//Definir o preço da ordem BuyStop buyTP, //Take Profit da ordem BuyStop buySL, //Stop Loss da ordem BuyStop sellPrice, //Definir o preço da ordem SellStop sellTP, //Take Profit da ordem SellStop sellSL; //Stop Loss da ordem SellStop double open1,//Abertura do preço da primeira barra open2, //Abertura do preço da Segunda barra close1, //Fechamento do preço da primeira barra close2, //Fechamento do preço da segunda barra low1, //Mínima do preço da primeira barra low2, //Mínima do preço da segunda barra high1, //Máxima do preço da primeira barra high2; //Máxima do preço da segunda barra datetime _ExpDate=0; //variável local para definir um tempo de expiração da ordem pendente double _bar2size; datetime timeBarInside; //tempo da barra em que a ordem da "Inside Bar" foi aberta, para evitar uma reabertura //+------------------------------------------------------------------+ //| Função de inicialização do expert | //+------------------------------------------------------------------+ int OnInit() { return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Função desinicialização do expert | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { } //+------------------------------------------------------------------+ //| Função tick do Expert | //+------------------------------------------------------------------+ void OnTick() { double _bid = NormalizeDouble(MarketInfo(Symbol(), MODE_BID), Digits); //define um preço menor double _ask = NormalizeDouble(MarketInfo(Symbol(), MODE_ASK), Digits); //define um preço maior double _point = MarketInfo(Symbol(), MODE_POINT); //--- Definir os preços das barras necessárias open1 = NormalizeDouble(iOpen(Symbol(), Period(), 1), Digits); open2 = NormalizeDouble(iOpen(Symbol(), Period(), 2), Digits); close1 = NormalizeDouble(iClose(Symbol(), Period(), 1), Digits); close2 = NormalizeDouble(iClose(Symbol(), Period(), 2), Digits); low1 = NormalizeDouble(iLow(Symbol(), Period(), 1), Digits); low2 = NormalizeDouble(iLow(Symbol(), Period(), 2), Digits); high1 = NormalizeDouble(iHigh(Symbol(), Period(), 1), Digits); high2 = NormalizeDouble(iHigh(Symbol(), Period(), 2), Digits); //--- _bar2size=NormalizeDouble(((high2-low2)/_point),0); // --- Se a segunda barra é de baixa, enquanto a primeira é de alta if(timeBarInside!=iTime(Symbol(),Period(),1) && //Sem ordens abertas ainda neste padrão _bar2size>bar2size && //a segunda barra tem de ser grande o suficiente, de modo que o mercado não seja lateral open2>close2 && //Segunda barra é de baixa close1>open1 && //Primeira barra é de alta high2>high1 && //Máxima da segunda barra excede a Máxima da primeira open2>close1 && //Abertura da segunda barra excede o Fechamento da primeira barra low2<low1) //Mínima da segunda barra é menor do que a Mínima da primeira barra { //--- Listamos todas as condições que definem que a primeira barra está completamente envolvida pela segunda timeBarInside=iTime(Symbol(),Period(),1); //indica que as ordens já estão colocados neste padrão } } //+------------------------------------------------------------------+
Definindo níveis de Stop Order
Agora que todos os preparativos estão completos, nós só temos que definir os níveis de ordem de parada e preços de encomenda. Além disso, não se esqueça de um cálculo de tempo de validade da ordem.
Vamos adicionar o código a seguir ao corpo da função OnTick():
buyPrice=NormalizeDouble(high2+interval*_point,Digits); //define um preço da ordem considerando o intervalo buySL=NormalizeDouble(low2-interval*_point,Digits); //definir um stop loss considerando o intervalo buyTP=NormalizeDouble(buyPrice+TP*_point,Digits); //define um take profit _ExpDate=TimeCurrent()+ExpDate*60*60; //o cálculo do tempo de expiração da ordem pendente sellPrice=NormalizeDouble(low2-interval*_point,Digits); sellSL=NormalizeDouble(high2+interval*_point,Digits); sellTP=NormalizeDouble(sellPrice-TP*_point,Digits);
Correção de Erros de Execução
Se você já se dedica ao desenvolvimento de Expert Advisors, você provavelmente sabe que os erros acontecem muitas vezes ao fechar e definir as ordens, incluindo o tempo de espera, paradas incorretas, etc. Para eliminar esses erros, devemos escrever uma função separada com um pequeno manipulador "built-in" de erros básicos.
//+----------------------------------------------------------------------------------------------------------------------+ //| A função abre ou define uma ordem | //| symbol - símbolo (ativo) onde uma operação de negociação é realizada. | //| cmd - uma operação (pode ser igual a qualquer um dos valores da negociação). | //| volume - quantidade de lotes. | //| price - Abertura do preço. | //| slippage - desvio máximo do preço para as ordens de compra ou venda do mercado. | //| stoploss - fechamento da posição quando um nível de perda é alcançado (0 se não há nível definido de perda). | //| takeprofit - fechamento da posição quando um nível de lucro é alcançado (0 se não há nível definido de lucro). | //| comment - ordem comentada. A última parte do comentário pode ser alterada pelo servidor de negociação. | //| magic - número mágico da ordem Ele pode ser usado como uma ID definida pelo usuário. | //| expiration - tempo de expiração da ordem pendente. | //| arrow_color - cor da seta aberta num gráfico. Se o parâmetro estiver ausente ou igual a CLR_NONE, | //| a seta aberta não é exibida num gráfico. | //+----------------------------------------------------------------------------------------------------------------------+ int OrderOpenF(string OO_symbol, int OO_cmd, double OO_volume, double OO_price, int OO_slippage, double OO_stoploss, double OO_takeprofit, string OO_comment, int OO_magic, datetime OO_expiration, color OO_arrow_color) { int result = -1; //resultado da abertura de uma ordem int Error = 0; //erro ao abrir uma ordem int attempt = 0; //quantidade de tentativas realizadas int attemptMax = 3; //quantidade máxima de tentativas bool exit_loop = false; //sair do loop string lang=TerminalInfoString(TERMINAL_LANGUAGE); //linguagem do terminal de negociação para definir o idioma das mensagens double stopllvl=NormalizeDouble(MarketInfo(OO_symbol,MODE_STOPLEVEL)*MarketInfo(OO_symbol,MODE_POINT),Digits); //stop loss mínimo/ nível do take profit, em pontos //o módulo fornece uma abertura de ordem segura. //--- Verificar ordens stop para comprar if(OO_cmd==OP_BUY || OO_cmd==OP_BUYLIMIT || OO_cmd==OP_BUYSTOP) { double tp = (OO_takeprofit - OO_price)/MarketInfo(OO_symbol, MODE_POINT); double sl = (OO_price - OO_stoploss)/MarketInfo(OO_symbol, MODE_POINT); if(tp>0 && tp<=stopllvl) { OO_takeprofit=OO_price+stopllvl+2*MarketInfo(OO_symbol,MODE_POINT); } if(sl>0 && sl<=stopllvl) { OO_stoploss=OO_price -(stopllvl+2*MarketInfo(OO_symbol,MODE_POINT)); } } //--- checar Ordens de stop para a venda if(OO_cmd==OP_SELL || OO_cmd==OP_SELLLIMIT || OO_cmd==OP_SELLSTOP) { double tp = (OO_price - OO_takeprofit)/MarketInfo(OO_symbol, MODE_POINT); double sl = (OO_stoploss - OO_price)/MarketInfo(OO_symbol, MODE_POINT); if(tp>0 && tp<=stopllvl) { OO_takeprofit=OO_price -(stopllvl+2*MarketInfo(OO_symbol,MODE_POINT)); } if(sl>0 && sl<=stopllvl) { OO_stoploss=OO_price+stopllvl+2*MarketInfo(OO_symbol,MODE_POINT); } } //--- enquanto no loop while(!exit_loop) { result=OrderSend(OO_symbol,OO_cmd,OO_volume,OO_price,OO_slippage,OO_stoploss,OO_takeprofit,OO_comment,OO_magic,OO_expiration,OO_arrow_color); //tentativa de abrir uma ordem usando os parâmetros especificados //--- Se houver um erro ao abrir uma ordem if(result<0) { Error = GetLastError(); //atribuir código a um erro switch(Error) //erro de enumeração { //erro de enumeração do fechamento ordem e uma tentativa de corrigi-la case 2: if(attempt<attemptMax) { attempt=attempt+1; //definir mais de uma tentativa Sleep(3000); //3 segundos de atraso RefreshRates(); break; //interruptor de saída } if(attempt==attemptMax) { attempt=0; //redefinir a quantidade de tentativas para zero exit_loop = true; //saída por enquanto break; //interruptor de saída } case 3: RefreshRates(); exit_loop = true; //saída por enquanto break; //interruptor de saída case 4: if(attempt<attemptMax) { attempt=attempt+1; //definir mais de uma tentativa Sleep(3000); //3 segundos de atraso RefreshRates(); break; //interruptor de saída } if(attempt==attemptMax) { attempt = 0; //redefinir a quantidade de tentativas para zero exit_loop = true; //saída por enquanto break; //interruptor de saída } case 5: exit_loop = true; //saída por enquanto break; //interruptor de saída case 6: if(attempt<attemptMax) { attempt=attempt+1; //definir mais de uma tentativa Sleep(5000); //3 segundos de atraso break; //interruptor de saída } if(attempt==attemptMax) { attempt = 0; //redefinir a quantidade de tentativas para zero exit_loop = true; //saída por enquanto break; //interruptor de saída } case 8: if(attempt<attemptMax) { attempt=attempt+1; //definir mais de uma tentativa Sleep(7000); //3 segundos de atraso break; //interruptor de saída } if(attempt==attemptMax) { attempt = 0; //redefinir a quantidade de tentativas para zero exit_loop = true; //saída por enquanto break; //interruptor de saída } case 64: exit_loop = true; //saída por enquanto break; //interruptor de saída case 65: exit_loop = true; //saída por enquanto break; //interruptor de saída case 128: Sleep(3000); RefreshRates(); continue; //interruptor de saída case 129: if(attempt<attemptMax) { attempt=attempt+1; //definir mais de uma tentativa Sleep(3000); //3 segundos de atraso RefreshRates(); break; //interruptor de saída } if(attempt==attemptMax) { attempt = 0; //redefinir a quantidade de tentativas para zero exit_loop = true; //saída por enquanto break; //interruptor de saída } case 130: exit_loop=true; //saída por enquanto break; case 131: exit_loop = true; //saída por enquanto break; //interruptor de saída case 132: Sleep(10000); //aguardar por 10 segundos RefreshRates(); //atualizar dados //exit_loop = true; //interruptor de saída break; //interruptor de saída case 133: exit_loop=true; //saída por enquanto break; //interruptor de saída case 134: exit_loop=true; //saída por enquanto break; //interruptor de saída case 135: if(attempt<attemptMax) { attempt=attempt+1; //definir mais de uma tentativa RefreshRates(); break; //interruptor de saída } if(attempt==attemptMax) { attempt = 0; // definir o número de tentativas para zero exit_loop = true; //saída por enquanto break; //interruptor de saída } case 136: if(attempt<attemptMax) { attempt=attempt+1; //definir mais de uma tentativa RefreshRates(); break; //interruptor de saída } if(attempt==attemptMax) { attempt = 0; //definir o número de tentativas para zero exit_loop = true; //saída por enquanto break; //interruptor de saída } case 137: if(attempt<attemptMax) { attempt=attempt+1; Sleep(2000); RefreshRates(); break; } if(attempt==attemptMax) { attempt=0; exit_loop=true; break; } case 138: if(attempt<attemptMax) { attempt=attempt+1; Sleep(1000); RefreshRates(); break; } if(attempt==attemptMax) { attempt=0; exit_loop=true; break; } case 139: exit_loop=true; break; case 141: Sleep(5000); exit_loop=true; break; case 145: exit_loop=true; break; case 146: if(attempt<attemptMax) { attempt=attempt+1; Sleep(2000); RefreshRates(); break; } if(attempt==attemptMax) { attempt=0; exit_loop=true; break; } case 147: if(attempt<attemptMax) { attempt=attempt+1; OO_expiration=0; break; } if(attempt==attemptMax) { attempt=0; exit_loop=true; break; } case 148: exit_loop=true; break; default: Print("Error: ",Error); exit_loop=true; //saída por enquanto break; //outras opções } } //--- Se não houver erros detectados else { if(lang == "Russian") {Print("Ордер успешно открыт. ", result);} if(lang == "English") {Print("The order is successfully opened.", result);} Error = 0; //redefinir o código de erro para zero break; //saída por enquanto //errorCount =0; //redefinir a quantidade de tentativas para zero } } return(result); } //+------------------------------------------------------------------+
Como resultado, obtém-se o seguinte código:
//+------------------------------------------------------------------+ //| InsideBar.mq4 | //| Copyright 2015, Iglakov Dmitry. | //| cjdmitri@gmail.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Iglakov Dmitry." #property link "cjdmitri@gmail.com" #property version "1.00" #property strict extern int interval = 20; //Intervalos extern double lot = 0.1; //Tamanho do Lote extern int TP = 300; //Take Profit extern int magic = 555124; //Número mágico extern int slippage = 2; //Desvio extern int ExpDate = 48; //Hora de Expiração da Ordem extern int bar2size = 800; //Tamanho da Barra 2 double buyPrice,//Definir o preço da ordem BuyStop buyTP, //Take Profit da ordem BuyStop buySL, //Stop Loss da ordem BuyStop sellPrice, //Definir o preço da ordem SellStop sellTP, //Take Profit da ordem SellStop sellSL; //Stop Loss da ordem SellStop double open1,//Abertura do preço da primeira barra open2, //Abertura do preço da Segunda barra close1, //Fechamento do preço da primeira barra close2, //Fechamento do preço da segunda barra low1, //Mínima do preço da primeira barra low2, //Mínima do preço da segunda barra high1, //Máxima do preço da primeira barra high2; //Máxima do preço da segunda barra datetime _ExpDate=0; //variável local para definir um tempo de expiração da ordem pendente double _bar2size; datetime timeBarInside; //tempo da barra da ordem "Inside Bar" que foi aberta, para evitar uma reabertura //+------------------------------------------------------------------+ //| Função de inicialização do expert | //+------------------------------------------------------------------+ int OnInit() { return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Função desinicialização do expert | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { } //+------------------------------------------------------------------+ //| Função tick do Expert | //+------------------------------------------------------------------+ void OnTick() { double _bid = NormalizeDouble(MarketInfo(Symbol(), MODE_BID), Digits); //define um preço menor double _ask = NormalizeDouble(MarketInfo(Symbol(), MODE_ASK), Digits); //define um preço maior double _point = MarketInfo(Symbol(), MODE_POINT); //--- Definir os preços das barras necessárias open1 = NormalizeDouble(iOpen(Symbol(), Period(), 1), Digits); open2 = NormalizeDouble(iOpen(Symbol(), Period(), 2), Digits); close1 = NormalizeDouble(iClose(Symbol(), Period(), 1), Digits); close2 = NormalizeDouble(iClose(Symbol(), Period(), 2), Digits); low1 = NormalizeDouble(iLow(Symbol(), Period(), 1), Digits); low2 = NormalizeDouble(iLow(Symbol(), Period(), 2), Digits); high1 = NormalizeDouble(iHigh(Symbol(), Period(), 1), Digits); high2 = NormalizeDouble(iHigh(Symbol(), Period(), 2), Digits); //--- _bar2size=NormalizeDouble(((high2-low2)/_point),0); // --- Se a segunda barra é de baixa, enquanto a primeira é de alta if(timeBarInside!=iTime(Symbol(),Period(),1) && //Sem ordens abertas ainda neste padrão _bar2size>bar2size && //a segunda barra tem de ser grande o suficiente, de modo que o mercado não seja lateral open2>close2 && //Segunda barra é de baixa close1>open1 && //Primeira barra é de alta high2>high1 && //Máxima da segunda barra excede a Máxima da primeira open2>close1 && //Abertura da segunda barra excede o Fechamento da primeira barra low2<low1) //Mínima da segunda barra é menor do que a Mínima da primeira barra { buyPrice=NormalizeDouble(high2+interval*_point,Digits); //define um preço da ordem considerando o intervalo buySL=NormalizeDouble(low2-interval*_point,Digits); //definir um stop loss considerando o intervalo buyTP=NormalizeDouble(buyPrice+TP*_point,Digits); //define um take profit _ExpDate=TimeCurrent()+ExpDate*60*60; //o cálculo do tempo de expiração da ordem pendente sellPrice=NormalizeDouble(low2-interval*_point,Digits); sellSL=NormalizeDouble(high2+interval*_point,Digits); sellTP=NormalizeDouble(sellPrice-TP*_point,Digits); OrderOpenF(Symbol(),OP_BUYSTOP,lot,buyPrice,slippage,buySL,buyTP,NULL,magic,_ExpDate,Blue); OrderOpenF(Symbol(),OP_SELLSTOP,lot,sellPrice,slippage,sellSL,sellTP,NULL,magic,_ExpDate,Blue); //--- listamos todas as condições que definem que a primeira barra está completamente envolvida pela segunda timeBarInside=iTime(Symbol(),Period(),1); //indica que as ordens já estão colocadas neste padrão } } //+------------------------------------------------------------------+
Agora, vamos realizar a compilação e verificar se há mensagens de erro no arquivo de registro (log).
Testando o Expert Advisor
É hora de testar o nosso Expert Advisor. Vamos lançar no Testador de Estratégia e definir os parâmetros de entrada. Eu especifiquei os parâmetros da seguinte forma:
Fig. 6. Parâmetros de entrada para teste
- Selecione um símbolo (neste exemplo é o CADJPY).
- Certifique-se de definir o teste no modo "Cada tick" e definir que o teste deve ser realizado com dados do histórico. Eu selecionei todo o ano de 2014.
- Defina o prazo D1.
- Lançar o teste.
- Após a conclusão do teste, verifique o log. Como podemos ver, nenhum erro de execução ocorreu no processo.
Abaixo é a diário de teste do EA:
Fig. 7. Diário de teste do Expert Advisor
Certifique-se de que não existem erros e otimize o EA.
Otimização
Eu selecionei os seguintes parâmetros para a otimização:
Fig. 8. Parâmetros de otimização
Fig. 9. Configurações de otimização
Assim temos agora o robô pronto para uso.
Otimização e Resultados dos Testes
Fig. 10. Resultados do teste
Fig. 11. Grafico com os resultados do teste
Conclusão
- Nós desenvolvemos um Expert Advisor padrão pronto para ser usado, operando com o padrão "Inside Bar".
- Temos a certeza de que os padrões Ação de Preço podem trabalhar mesmo sem filtros adicionais na entrada do mercado.
- Nenhum truque (como Martingale ou média) foi utilizado.
- O Rebaixamento foi minimizado através da definição correta das ordens de Stop Loss.
- Nao foram utilizados indicadores técnicos. O robô de negociação é baseado exclusivamente na leitura de um gráfico de "barras".
Obrigado por ler! Espero que este artigo tenha sido útil.
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/1771
- 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