
Construindo um Modelo de Restrição de Tendência de Candlestick (Parte 7): Refinando nosso modelo para o desenvolvimento de EA
Seções de Interesse:
- Introdução
- Identificando limitações do sistema atual
- Revisitando o Gráfico
- Revisitando o Código
- Incorporando o Crossover de Média Móvel
- Desenhando Retângulos de Lucro e Risco
- Introduzindo Pontos de Saída
- Testes e Validação
- Conclusão
Introdução
É possível desenvolver um Expert Advisor baseado nos indicadores disponíveis. Existem duas maneiras que mencionarei neste artigo:
- Codificar as condições do indicador no algoritmo do Expert Advisor é eficiente e muito rápido, mesmo no Strategy Tester. Com esse método, o EA funciona sem a necessidade de um indicador ser usado separadamente.
- Preparar um algoritmo de Expert Advisor que preste atenção nos buffers do indicador é outra abordagem. Se o buffer for True ou False, o EA é programado para responder de uma determinada maneira. Existem dois arquivos necessários para o sistema funcionar na plataforma MetaTrader 5: tanto o EA quanto o indicador devem existir em diretórios específicos dentro do caminho da plataforma. É desafiador publicar um EA que funcione com um indicador personalizado, pois o sistema de validação não encontrará o seu indicador ao tentar publicar na comunidade MQL5. Eu certamente tentei e encontrei erros, então só consegui rodá-lo no meu computador sem publicar.
Antes de avançarmos, precisamos preparar nosso indicador para o trabalho do EA. Isso envolve garantir que os buffers do nosso indicador estejam bem organizados e entender seu funcionamento, para que seja mais fácil desenvolver o conceito em um EA. Ambas as abordagens mencionadas acima funcionam bem, cada uma com seus prós e contras, que discutiremos em escritos futuros. A principal vantagem de usar um indicador junto com o EA é que ele reduz a complexidade de escrever o algoritmo do EA. O desenvolvedor pode se concentrar em algumas partes específicas do algoritmo, pois as condições já estão codificadas no programa do indicador.
Na Parte 6, a versão Trend Constraint V1.08 foi nosso último avanço, combinando duas grandes integrações em um único programa. Estamos satisfeitos com esse progresso, pois agora podemos acessar facilmente os sinais no Telegram e WhatsApp. No entanto, há algumas perguntas a serem feitas:
- Sim, agora estamos recebendo os sinais, mas eles são os melhores?
- Podemos executar as negociações, mas quando devemos sair?
Essas perguntas só podem ser respondidas revisitando o gráfico para ver como o indicador está se comportando historicamente, e recodificando o código-fonte para adicionar novos recursos ou melhorar o sistema atual. Ao refinar o sistema atual para Expert Advisors, proponho:
- Entender o propósito de cada buffer o mais detalhadamente possível.
- Reintroduzir os cruzamentos de médias móveis para sinais de entrada.
- Usar proporções de risco-recompensa para desenhar retângulos: verde para ilustrar a faixa de alvo de lucro e vermelho para a faixa de perda.
onde:
RRR é a Proporção de Risco-Recompensa;
Perda Potencial é a quantidade que você pode perder se a negociação ou o investimento se mover contra você;
Ganho Potencial é a quantidade que você espera ganhar se a negociação ou o investimento se mover a seu favor.
Deixe-me dar um exemplo:
Suponha que você esteja considerando comprar uma ação a $50. Você define seu stop-loss em $48 (indicando uma perda potencial de $2 por ação) e define um preço-alvo de $56 (indicando um ganho potencial de $6 por ação). Calcule a Proporção de Risco-Recompensa para a ação.
- Perda Potencial: $50 (preço de entrada) - $48 (stop-loss) = $2
- Ganho Potencial: $56 (preço-alvo) - $50 (preço de entrada) = $6
Substituindo os valores na fórmula: Proporção de Risco-Recompensa = 1/3
Em detalhes, isso significa que, para cada $1 que você arrisca, espera-se ganhar $3. Uma proporção mais baixa (por exemplo, 1:1 ou menos) indica mais risco em relação à recompensa potencial, enquanto uma proporção mais alta sugere um cenário de risco-recompensa mais favorável.
Com base no exemplo acima, aqui está uma ilustração usando retângulos: um retângulo vermelho para risco e um retângulo verde para recompensa.
Vamos discutir isso mais a fundo nas próximas seções do artigo. Ao final dessa discussão, nosso objetivo será focar em:
- Entender a importância da gestão de risco no trading algorítmico.
- Implementar proporções de risco-recompensa e suas fundações matemáticas.
- Desenvolver estratégias dinâmicas de saída para uma gestão ideal das negociações.
- Aprimorar indicadores visuais para uma melhor tomada de decisões nas negociações.
- Testar e validar o indicador para aplicação no mundo real.
Identificando limitações do sistema atual
Para avançar um sistema de indicador com novos recursos, é importante revisitar partes cruciais para identificar áreas onde o sistema atual apresenta deficiências. Para isso, considerei duas técnicas de acordo com minha abordagem, que me guiarão na identificação e resolução de problemas. São elas: - Revisitando o Gráfico: Isso envolve revisar o histórico da janela do gráfico do indicador, observando sua apresentação e identificando possíveis anomalias.
- Revisitando o Código: Esta é a segunda etapa: após concluir a etapa 1, examinaremos as áreas do código relacionadas aos problemas identificados para corrigi-los.
Revisitando o Gráfico
Aqui está uma imagem do gráfico do Índice Boom 500. Vou destacar os problemas conforme os percebo no gráfico:
- No diagrama, (A) representa um candlestick de pico. Neste caso, a seta é exibida abaixo da vela quando deveria estar acima dela. Esse problema ocorre porque a seta está representando a zona de sobrecompra do RSI, o que só acontece após o fechamento da vela.
- A funcionalidade de exibição DRAW_LINE está funcionando bem, permitindo que identifiquemos novas tendências ao observar as mudanças de cor na linha. Queremos que ela sinalize uma negociação swing, porque, tipicamente, quando o mercado muda de direção, ele frequentemente se move de forma significativa.
- Setas azuis de compra representam uma possível continuação de tendência e atualmente indicam a zona de Sobrevendido do RSI em uma tendência de alta predominante. Lembre-se de que nosso tema é restringir nossos sinais ao candle D1, ao sentimento do mercado. Embora os níveis extremos do Índice de Força Relativa (RSI) possam ser bons para entradas, eles geralmente indicam a zona do mercado em vez de uma reversão garantida. O mercado pode continuar predominando na tendência independentemente dos níveis de RSI. Sugiro reintroduzir o crossover de médias móveis para outras entradas, a fim de maximizar os ganhos, pois isso geralmente se alinha bem com a ação do preço.
- Também vejo o benefício de exibir retângulos para as proporções de risco-recompensa a serem desenhadas quando o indicador enviar sinais de entrada, conforme mencionado na introdução. Essa nova versão deve delinear os retângulos com precisão para apresentar o risco e as recompensas corretamente. Veja a ideia transmitida nos gráficos abaixo: o primeiro é EURUSD, e o segundo é Boom 500, consecutivamente.
EURUSD, M1: Euro vs US Dollar
Boom 500 Index, M1:
A partir desses diagramas, podemos observar claramente a nova abordagem. Queremos preparar nosso código do indicador para refletir exatamente o que foi demonstrado manualmente. De acordo com vários analistas técnicos e traders, os pivôs tradicionalmente têm sido respeitados como alvos para take profit e stop loss. Portanto, a ideia de uma proporção de risco-recompensa de 1:3 pode se tornar inaplicável em cenários como os mostrados no gráfico, onde às vezes o risco é muito maior do que o lucro potencial.
Resumindo, a partir das ilustrações acima:
- Os pivôs são usados como pontos de referência para definir pontos de saída, incluindo stop loss e take profit.
- Os preços para os níveis de entrada e saída podem ser usados posteriormente na lógica.
Na próxima seção, examinaremos as áreas críticas no código e abordaremos-as.
Revisitando o Código:
Aqui está um trecho onde podemos fazer alterações: #property indicator_type1 DRAW_ARROW #property indicator_width1 5 #property indicator_color1 0xFF3C00 #property indicator_label1 "Buy" // We are going to change it to "Buy Zone" #property indicator_type2 DRAW_ARROW #property indicator_width2 5 #property indicator_color2 0x0000FF #property indicator_label2 "Sell"// We are going to change it to "Sell Zone"
Esta seção do programa é onde fixamos a posição da seta no candlestick. Envolve a função de iteração do Buffer 2. O indicador deve exibir na máxima do candlestick, então vamos alterar de Low[i] para High[i];
//Indicator Buffer 2 // We are going to set the indicator to display at candlestick high by changing the highlighted text to High[i] if(RSI[i] > Overbought && RSI[i+1] < Overbought //Relative Strength Index crosses above fixed value && Open[barshift_M1[i]] <= Close[1+barshift_D1[i]] //Candlestick Open <= Candlestick Close && MA[i] < MA2[i] //Moving Average < Moving Average && MA3[i] < MA4[i] //Moving Average < Moving Average ) { Buffer2[i] = Low[i]; //Set indicator value at Candlestick Low // change to High[i] if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Sell Zone"); //Alert on next bar open time_alert = Time[1]; } else { Buffer2[i] = EMPTY_VALUE; }
Incorporando o Crossover de Média Móvel:
Vamos discutir os trechos de código abaixo para desvendar o processo de adicionar um novo recurso ao nosso programa. Além dos buffers existentes, vamos adicionar dois novos, que serão o Buffer 6 e o Buffer 7.
De acordo com a lógica do nosso programa inteligente, começaremos definindo suas propriedades. Como recentemente adotamos "Zona de Venda" e "Zona de Compra" para o indicador RSI, esses serão os novos sinais de "Venda" e "Compra" para o indicador.
#property indicator_type6 DRAW_ARROW #property indicator_width6 1 #property indicator_color6 0x0000FF #property indicator_label6 "Sell" #property indicator_type7 DRAW_ARROW #property indicator_width7 1 #property indicator_color7 0xFFAA00 #property indicator_label7 "Buy"
Precisamos definir entradas para personalização a fim de otimizar os melhores sinais. Usaremos uma média móvel de 7 e uma média móvel de 21.
input int Entry_MA_fast = 7 ; input int Entry_MA_slow = 21 ;
A função OnCalculate para os novos recursos está mostrada aqui. Ela detalha como o programa exibirá os resultados quando as condições forem atendidas.
SetIndexBuffer(5, Buffer6); PlotIndexSetDouble(5, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(5, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); PlotIndexSetInteger(5, PLOT_ARROW, 242); SetIndexBuffer(6, Buffer7); PlotIndexSetDouble(6, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(6, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); PlotIndexSetInteger(6, PLOT_ARROW, 241);
Esta etapa incorpora as condições para o crossover da média móvel. Neste cenário, as condições para o Buffer 7 refletem as do Buffer 6. Essencialmente, o processo é o mesmo, mas invertido para cada buffer.
//Indicator Buffer 6 if(MA8[i] < MA9[i] && MA8[i+1] > MA9[i+1] //Moving Average crosses below Moving Average && Open2[i] <= Close[1+barshift_D1[i]] //Candlestick Open <= Candlestick Close ) { Buffer6[i] = High[i]; //Set indicator value at Candlestick High if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Sell"); //Alert on next bar open time_alert = Time[1]; } else { Buffer6[i] = EMPTY_VALUE; } //Indicator Buffer 7 if(MA8[i] > MA9[i] && MA8[i+1] < MA9[i+1] //Moving Average crosses above Moving Average && Open2[i] >= Close[1+barshift_D1[i]] //Candlestick Open >= Candlestick Close ) { Buffer7[i] = Low[i]; //Set indicator value at Candlestick Low if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Buy"); //Alert on next bar open time_alert = Time[1]; } else { Buffer7[i] = EMPTY_VALUE; }
Desenhando Retângulos
Tive um bom tempo trabalhando com o código. Considerei expandir o programa existente, modificando os buffers recentemente incorporados para incluir a funcionalidade de colocar retângulos que marquem as zonas de risco e lucro. Além disso, comecei delineando a lógica no papel de como os objetos serão colocados e quais buffers estarão associados a eles, especificamente os Buffers 6 e 7.
Aqui está a lógica no papel antes da implementação real:
Em uma média móvel rápida, crossover abaixo de uma média móvel lenta:
Quando as condições do Buffer7 forem verdadeiras, queremos que um retângulo seja colocado abaixo da mínima do candlestick atual.- A largura do retângulo será de 5 barras ou mais.
- A altura do retângulo será X pips para baixo, onde X é o número de pips.
- O retângulo deve ser verde.
- No topo do retângulo verde, quando as condições do Buffer7 forem verdadeiras, coloque um retângulo vermelho que tenha 1/3 da altura do retângulo verde.
- Todos os parâmetros devem ser personalizáveis.
Em crossover de média móvel rápida acima de média móvel lenta, quando as condições do Buffer 6 forem verdadeiras, queremos colocar um retângulo acima da máxima do candlestick atual.
Aqui estão as especificações como segue:
- A largura do retângulo deve ser de 5 barras ou mais.
- A altura do retângulo deve ser X pips para cima, onde X é o número de pips.
- O retângulo deve ser verde.
- Abaixo do retângulo verde, quando as condições do Buffer 6 forem verdadeiras, coloque um retângulo vermelho que tenha 1/3 da altura do retângulo verde.
- Todos os parâmetros devem ser personalizáveis.
Primeiramente, precisamos da capacidade de inserir parâmetros para personalização. Aqui está o trecho de código mostrando a incorporação:
//--- new inputs for rectangles input int RectWidth = 5; // Width of the rectangle in bars input int RectHeightPointsBuy = 50; // Height of the profit rectangle in points for Buy input int RectHeightPointsSell = 50; // Height of the profit rectangle in points for Sell input color ProfitRectColor = clrGreen; // Color of the profit rectangle input color RiskRectColor = clrRed; // Color of the risk rectanglePor padrão, eu configurei os pontos para 50, mas esses podem ser ajustados para atender às suas necessidades e metas de lucro. Por padrão, eu configurei os pontos para 50, mas esses podem ser ajustados para atender às suas necessidades e metas de lucro. Isso é importante porque permite que o indicador se adapte a quaisquer mudanças na cor de fundo. Por exemplo, se você usar um fundo de gráfico verde, o retângulo verde pode se misturar e se tornar invisível, enquanto um fundo amarelo proporcionaria um contraste melhor. A personalização é crucial para garantir o controle total sobre nossas ferramentas.
Agora, vamos examinar a função OnCalculate para ver como a iteração está funcionando.
if(RSI[i] > Overbought) { if(close[i] > MA[i]) Buffer6[i] = close[i] - pips * myPoint; } if(RSI[i] < Oversold) { if(close[i] < MA[i]) Buffer7[i] = close[i] + pips * myPoint; } if(Buffer6[i] > 0) { Buffer1[i] = close[i] - pips * myPoint; Buffer3[i] = close[i] - pips * myPoint; if (Buffer6[i - 1] < 0) { myAlert("indicator", "Sell Signal Detected!"); if (Audible_Alerts) Alert(Symbol(), " ", Period(), ": Sell Signal Detected!"); // Create profit rectangle for Sell double highProfitRect = close[i]; double lowProfitRect = close[i] - RectHeightPointsSell * myPoint; string profitRectName = "SellProfitRect" + IntegerToString(i); if (ObjectFind(0, profitRectName) != 0) { ObjectCreate(0, profitRectName, OBJ_RECTANGLE, 0, time[i], highProfitRect, time[i + RectWidth], lowProfitRect); ObjectSetInteger(0, profitRectName, OBJPROP_COLOR, ProfitRectColor); ObjectSetInteger(0, profitRectName, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, profitRectName, OBJPROP_WIDTH, 2); } // Create risk rectangle for Sell double highRiskRect = close[i]; double lowRiskRect = close[i] + (RectHeightPointsSell / 3) * myPoint; string riskRectName = "SellRiskRect" + IntegerToString(i); if (ObjectFind(0, riskRectName) != 0) { ObjectCreate(0, riskRectName, OBJ_RECTANGLE, 0, time[i], highRiskRect, time[i + RectWidth], lowRiskRect); ObjectSetInteger(0, riskRectName, OBJPROP_COLOR, RiskRectColor); ObjectSetInteger(0, riskRectName, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, riskRectName, OBJPROP_WIDTH, 2); } } } if(Buffer7[i] > 0) { Buffer2[i] = close[i] + pips * myPoint; Buffer4[i] = close[i] + pips * myPoint; if (Buffer7[i - 1] < 0) { myAlert("indicator", "Buy Signal Detected!"); if (Audible_Alerts) Alert(Symbol(), " ", Period(), ": Buy Signal Detected!"); // Create profit rectangle for Buy double highProfitRect = close[i] + RectHeightPointsBuy * myPoint; double lowProfitRect = close[i]; string profitRectName = "BuyProfitRect" + IntegerToString(i); if (ObjectFind(0, profitRectName) != 0) { ObjectCreate(0, profitRectName, OBJ_RECTANGLE, 0, time[i], highProfitRect, time[i + RectWidth], lowProfitRect); ObjectSetInteger(0, profitRectName, OBJPROP_COLOR, ProfitRectColor); ObjectSetInteger(0, profitRectName, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, profitRectName, OBJPROP_WIDTH, 2); } // Create risk rectangle for Buy double highRiskRect = close[i] - (RectHeightPointsBuy / 3) * myPoint; double lowRiskRect = close[i]; string riskRectName = "BuyRiskRect" + IntegerToString(i); if (ObjectFind(0, riskRectName) != 0) { ObjectCreate(0, riskRectName, OBJ_RECTANGLE, 0, time[i], highRiskRect, time[i + RectWidth], lowRiskRect); ObjectSetInteger(0, riskRectName, OBJPROP_COLOR, RiskRectColor); ObjectSetInteger(0, riskRectName, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, riskRectName, OBJPROP_WIDTH, 2); } }
Aqui é onde a criação dos retângulos está acontecendo:
Retângulos de Lucro:
- Para sinais de venda, um retângulo verde se estende para baixo a partir do preço de fechamento.
- Para sinais de compra, um retângulo verde se estende para cima a partir do preço de fechamento.
Retângulos de Risco:
- Para sinais de venda, um retângulo vermelho se estende para cima a partir do preço de fechamento, com uma altura de 1/3 do retângulo de lucro.
- Para sinais de compra, um retângulo vermelho se estende para baixo a partir do preço de fechamento, com uma altura de 1/3 do retângulo de lucro.
Agora, vamos explicar brevemente as novas funções que estão sendo introduzidas;
- ObjectFind: Função usada para verificar se um objeto com um nome específico já existe no gráfico.
int ObjectFind( long chart_id, // Chart ID (0 means the current chart) string name // Name of the object to search for );
- ObjectCreate: Função usada para criar um novo objeto gráfico no gráfico. O tipo de objeto pode ser especificado (por exemplo, retângulo, linha de tendência, etc.).
bool ObjectCreate( long chart_id, // Chart ID (0 means the current chart) string name, // Name of the object to create ENUM_OBJECT type, // Type of the object (e.g., OBJ_RECTANGLE, OBJ_TREND, etc.) int sub_window, // Number of the subwindow (0 means the main chart window) datetime time1, // First coordinate time double price1, // First coordinate price ... // Additional coordinates depending on the object type );
- ObjectSetInteger: Função usada para definir propriedades inteiras de um objeto gráfico, como cor, estilo e largura.
bool ObjectSetInteger( long chart_id, // Chart ID (0 means the current chart) string name, // Name of the object int prop_id, // ID of the property to set (e.g., OBJPROP_COLOR, OBJPROP_STYLE, etc.) long value // Value of the property );
Essa função retorna um valor booleano;
- true: Se a propriedade foi definida com sucesso.
- false: Se a definição da propriedade falhou.
Por favor, para uma explicação mais aprofundada dessas funções, fique à vontade para consultar a documentação MQL5, que é rica em informações sobre a linguagem MQL5.
Introduzindo Pontos de Saída
A introdução dos pontos de saída é uma melhoria fundamental para o Trend Constraint V1.08. Uma estratégia de saída eficaz não apenas protege os lucros, mas também minimiza as perdas. Propomos integrar pontos de saída predefinidos com base em níveis-chave de suporte e resistência, que são cruciais para identificar zonas potenciais de reversão. A lógica anterior do sinal envolvia apenas o nome do par, mas o novo refinamento fornecerá todos os preços relevantes, incluindo Entrada, Stop Loss e Take Profit. Ao usar esses níveis, os traders podem determinar pontos de saída onde o preço provavelmente se reverterá ou encontrará resistência significativa, otimizando assim sua estratégia de saída. Aqui está a abordagem:
Para modificar o programa e inserir linhas de preço ao longo dos retângulos, adicionaremos três linhas em níveis de preços específicos:
- o preço do sinal (preço de fechamento do sinal),
- a meta de lucro,
- e a meta de risco.
Essas linhas serão colocadas imediatamente após o sinal ser detectado. Também configuraremos alertas para notificar o usuário sobre esses níveis específicos de preço.
Primeiro, definimos pontos de lucro e pontos de risco como entradas para torná-los personalizáveis.
input double profitPoints = 60; // Points for profit target input double riskPoints = 20; // Points for risk target
Neste ponto, deixe-me apresentar funções personalizadas para colocar linhas. O trecho abaixo mostra a definição dessas funções. Se você é novo em MQL5, observe que "void" é usado para indicar que uma função não retorna um valor.
void CreatePriceLine(string name, color lineColor, double price, datetime time) { if (ObjectFind(0, name) == -1) { ObjectCreate(0, name, OBJ_HLINE, 0, time, price); ObjectSetInteger(0, name, OBJPROP_COLOR, lineColor); ObjectSetInteger(0, name, OBJPROP_WIDTH, 2); } else { ObjectMove(0, name, 0, time, price); } } void PlaceSignalLines(double signalPrice, double profitTarget, double riskTarget, datetime time) { CreatePriceLine("SignalPriceLine", clrBlue, signalPrice, time); CreatePriceLine("ProfitTargetLine", clrGreen, profitTarget, time); CreatePriceLine("RiskTargetLine", clrRed, riskTarget, time); }
Finalmente, aqui está a lógica para detecção de sinais. Como você pode ver, temos alertas para indicar níveis de preço cruciais, que ajudarão o trader ao executar o programa manualmente.
void CheckSignalAndPlaceLines() { for (int i = rates_total - 2; i >= 0; i--) { if (Buffer6[i] != 0.0) { // Buy Signal Detected double signalPrice = Close[i]; double profitTarget = signalPrice + profitPoints * Point; double riskTarget = signalPrice - riskPoints * Point; PlaceSignalLines(signalPrice, profitTarget, riskTarget, Time[i]); Alert("Buy Signal: Signal Price = ", signalPrice, " Profit Target = ", profitTarget, " Risk Target = ", riskTarget); } if (Buffer7[i] != 0.0) { // Sell Signal Detected double signalPrice = Close[i]; double profitTarget = signalPrice - profitPoints * Point; double riskTarget = signalPrice + riskPoints * Point; PlaceSignalLines(signalPrice, profitTarget, riskTarget, Time[i]); Alert("Sell Signal: Signal Price = ", signalPrice, " Profit Target = ", profitTarget, " Risk Target = ", riskTarget); } } }
Em resumo, fizemos três mudanças importantes em nosso programa, que descreverei abaixo:
- Refinamos o Trend Constraint V1.08 e incluímos um cruzamento de média móvel para sinais de entrada.
- Discutimos a incorporação de retângulos para representar zonas de risco e lucro.
- Além disso, discutimos a importância dos pontos de saída em nosso programa.
A partir do resumo, a possibilidade de três versões do nosso programa surge à medida que continuamos refinando-o. Agora temos o Trend Constraint V1.09, V1.10 e V1.11. Em seguida, vamos proceder para discutir o desempenho dos testes e os resultados.
Testes e Validação
O teste e a compilação da versão V1.09 foram um sucesso, embora alguns problemas tenham sido encontrados e resolvidos completamente. Aqui estão algumas imagens mostrando um painel com o lançamento bem-sucedido, bem como um resumo do profiler detalhando o desempenho da função na CPU.
Resultado do perfil do testador:
Após ler o log de erro, ficou mais fácil revisar o programa e identificar o que estava faltando. Ao adicionar o cruzamento da Média Móvel, também precisávamos declarar os MA8, MA9, MA_handle8 e MA_handle9 para os novos buffers junto com os existentes. O código abaixo mostra as declarações feitas. As linhas destacadas indicam as que causaram os erros.
int RSI_handle; double RSI[]; double Open[]; double Close[]; int MA_handle; double MA[]; int MA_handle2; double MA2[]; int MA_handle3; double MA3[]; int MA_handle4; double MA4[]; double Low[]; double High[]; int MA_handle5; double MA5[]; int MA_handle6; double MA6[]; int MA_handle7; double MA7[]; int MA_handle8; double MA8[]; int MA_handle9; double MA9[]; double Open2[];
Após adicionar as declarações destacadas, o programa compilou com sucesso.
Passando para o V1.10, o programa compilou com sucesso após incorporar os retângulos, mas nada aparece no gráfico. É difícil determinar onde erramos, então continuaremos depurando linha por linha até que o problema seja resolvido e compartilharemos as descobertas nas próximas publicações.
O V1.11 encontrou erros de compilação, e compartilharei todo o processo de resolução na próxima publicação.
Um resumo dos buffers no programa é importante para o desenvolvimento do EA, pois nos ajuda a entender qual buffer executa as condições necessárias. Veja a tabela abaixo.
Buffer | Descrição |
---|---|
Buffer1. | Este buffer é usado para identificar se o RSI cruza acima de um valor fixo (sobrecomprado), o preço de abertura atual é maior ou igual ao preço de fechamento de uma barra específica, duas médias móveis (MA e MA3) são ambas maiores que suas respectivas médias móveis de comparação (MA2 e MA4), e marca uma "Zona de Compra" no gráfico. |
Buffer2. | Este buffer é usado para identificar se o RSI cruza acima de um valor fixo (sobrecomprado), o preço de abertura atual é menor ou igual ao preço de fechamento de uma barra específica, duas médias móveis (MA e MA3) são ambas menores que suas respectivas médias móveis de comparação (MA2 e MA4), e marca uma "Zona de Venda" no gráfico. |
Buffer3. | Este buffer é usado para identificar se a MA5 cruza acima da MA6 e marca uma "Swing de Compra" no gráfico. |
Buffer4. | Este buffer é usado para identificar se a MA5 cruza abaixo da MA6 e marca uma "Swing de Venda" no gráfico. |
Buffer5. | Este buffer rastreia se a MA3 é maior que a MA7. |
Buffer6. | Este buffer é usado para identificar se a MA8 cruza abaixo da MA9 e marca uma "Venda" no gráfico. |
Buffer7. | Este buffer é usado para identificar se a MA8 cruza acima da MA9 e marca uma "Compra" no gráfico. |
Buffer8. | Este buffer rastreia se a MA3 é menor que a MA7. |
Conclusão
Em conclusão, o desenvolvimento e aprimoramento do Trend Constraint representam um avanço significativo no trading algorítmico. Ao abordar as limitações do sistema atual e introduzir pontos de saída estratégicos, buscamos criar um indicador mais robusto e eficaz. A incorporação de níveis de stop-loss e take-profit, juntamente com representações visuais aprimoradas, garante que o indicador seja amigável ao usuário e adaptável às mudanças nas condições de mercado. Essas funcionalidades agora fornecem uma representação visual clara dos potenciais resultados de negociação, auxiliando na tomada de decisões mais eficazes.
Através de testes rigorosos e validação, demonstramos a confiabilidade e eficácia do indicador. Embora tenhamos encontrado erros, permanecemos persistentes e, através de pesquisa detalhada, resolvemos esses problemas. Usaremos a documentação e colaboraremos com a comunidade de desenvolvedores para resolver quaisquer problemas restantes.
No geral, o Trend Constraint aprimorado oferece uma solução abrangente para traders que buscam navegar pelas complexidades dos mercados financeiros com confiança e precisão. Suas características avançadas e abordagem estratégica para gestão de risco e otimização de lucros o tornam uma adição valiosa ao kit de ferramentas de qualquer trader.
Anexado abaixo estão os arquivos para o desenvolvimento posterior em seus projetos. Feliz desenvolvimento!
Nome do Arquivo | Descrição |
---|---|
Trend Constraint V1.09 | Programa refinado com sinais de cruzamento de MA. |
Trend Constraint V1.10 | Programa avançado com funções de desenho de objetos. Ainda na fase de depuração. |
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/15154





- 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