English Русский 中文 Español Deutsch 日本語
preview
Construindo um Modelo de Restrição de Tendência de Candlestick (Parte 4): Personalizando o Estilo de Exibição para Cada Onda de Tendência

Construindo um Modelo de Restrição de Tendência de Candlestick (Parte 4): Personalizando o Estilo de Exibição para Cada Onda de Tendência

MetaTrader 5Sistemas de negociação |
214 1
Clemence Benjamin
Clemence Benjamin

Conteúdo


Introdução

Estilos de exibição personalizados podem melhorar o apelo visual dos gráficos, tornando-os mais atraentes e fáceis de ler. Um gráfico bem projetado pode melhorar a experiência do usuário e reduzir a fadiga ocular durante longas sessões de negociação. Ao adaptar os estilos de exibição para necessidades específicas, os traders podem criar configurações de negociação mais eficientes e eficazes. Por exemplo, usar histogramas para representar dados de volume ou linhas para médias móveis pode facilitar a interpretação desses indicadores de forma rápida. Estilos de exibição como setas ou símbolos podem ser usados para marcar eventos específicos ou sinais no gráfico, como pontos de compra/venda, tornando mais fácil identificar oportunidades de negociação.

O MQL5 possui uma variedade de estilos de desenho para indicadores no MetaTrader 5. Esses elementos visuais fornecem aos traders uma vantagem analítica quando apresentados no gráfico do MetaTrader 5, ajudando na rápida adaptação ao sentimento do mercado. Incorporar esses diversos estilos de desenho não apenas melhora o apelo estético dos gráficos, mas também permite que os traders tomem decisões informadas com base em uma análise abrangente da dinâmica do mercado. Os traders podem interpretar movimentos de preços, identificar tendências e antecipar possíveis reversões com maior precisão. O MQL5 é rico com 18 tipos de gráficos. Neste artigo, queremos nos aprofundar e explorar como implementar um desses estilos de exibição em nosso modelo.

Em vez de apenas desenhar uma seta para nosso alerta, queremos criar um visual mais avançado no gráfico para torná-lo ainda mais fácil de entender. Lembre-se de que, nesta série, nosso objetivo é refinar nosso modelo de Restrição de Tendência para que ele siga o sentimento da forma do nosso candlestick D1 e apresente sinais visuais abrangentes no gráfico. Os estilos de desenho do MQL5 podem ser personalizados em termos de cor, espessura e estilo (por exemplo, linhas tracejadas ou sólidas), ajudando os traders a personalizarem seus gráficos de acordo com suas preferências e melhorarem a legibilidade. Estilos de exibição diferentes permitem que os traders representem dados de forma mais clara e precisa. Por exemplo, usar linhas, histogramas ou candles pode facilitar a interpretação de movimentos de preços e tendências de mercado.

    Os vários estilos de desenho disponíveis no MQL5 oferecem aos traders inúmeras vantagens. Eles ajudam a melhorar a clareza, precisão e personalização da visualização de dados. Esses estilos diversos expandem as capacidades da análise técnica, permitindo o uso de técnicas avançadas de criação de gráficos e facilitando atualizações dinâmicas em tempo real. Além disso, a adaptabilidade e engenhosidade inerentes aos estilos de desenho do MQL5 permitem que os traders criem indicadores e instrumentos de análise exclusivos, ampliando assim suas estratégias de negociação e a compreensão do cenário de mercado. Para um entendimento completo deste tópico, consulte a Referência MQL5 para uma exploração detalhada dos estilos de desenho.


    Recapitulação

    Nos artigos anteriores desta série (Parte 1, Parte 2 e Parte 3), o objetivo foi alinhar cada sinal ao sentimento do candle D1. O conceito é que, se o candle D1 for altista, normalmente a tendência geral do dia será de alta em prazos menores. Utilizando métodos analíticos avançados em prazos menores, podemos identificar pontos de entrada e gerar sinais que estejam alinhados com a tendência atual. Com cada fase, aprimoramos nosso código-fonte, incorporando novos recursos e melhorando nosso modelo. Na série de artigos, utilizamos setas como elemento de design para cada iteração do nosso indicador, explorando a utilização da fonte Wingdings para elementos de exibição opcionais.

    Adicionamos médias móveis de 200 e 100 a um ativo no gráfico do MQL5 para traçar estratégias. Analisando o comportamento desses indicadores embutidos, identificamos um evento significativo de cruzamento periódico. Subsequentemente, foi criado um indicador de cruzamento personalizado com um sistema de alerta para nos notificar sobre essas ocorrências, indicando uma possível reversão de tendência. Ajustar os valores das MAs para níveis mais altos pode ajudar a filtrar sinais durante as flutuações do mercado. Na Parte 3, aperfeiçoei ainda mais a abordagem, introduzindo entrada de período MA personalizável para explorar vários valores de período e determinar a configuração ideal para reversões de tendência.

    input int Slow_MA_period = 200;
    input int Fast_MA_period = 100;

    O software oferece a capacidade de ajuste instantâneo das configurações de entrada exibidas na representação visual. Para modificar seus atributos, utilize a combinação de teclas Ctrl + I ao visualizar o gráfico do MetaTrader 5 ou simplesmente clique com o botão direito do mouse para revelar o menu do indicador e localize Trend Constraint V1.03.

    Otimizando a MA para reversões de tendência

     Fig 1: Otimizando o período da MA para as melhores configurações de reversão de tendência.

    Após compilar o programa usando essas configurações de entrada, você encontrará o documento-fonte anexado logo abaixo da conclusão deste artigo. A seguir, apresentamos o código mais recente para Trend Constraint V1.03:

    /// Program after adding Moving Average optimization feature for reversals
    ///Indicator Name: Trend Constraint
    #property copyright "Clemence Benjamin"
    #property link      "https://mql5.com"
    #property version   "1.03"
    #property description "A model that seek to produce sell signal when D1 candle is Bearish only and  buy signal when it is Bullish"
    
    
    //--- indicator settings
    #property indicator_chart_window
    #property indicator_buffers 4
    #property indicator_plots 4
    
    #property indicator_type1 DRAW_ARROW
    #property indicator_width1 5
    #property indicator_color1 0xFF3C00
    #property indicator_label1 "Buy"
    
    #property indicator_type2 DRAW_ARROW
    #property indicator_width2 5
    #property indicator_color2 0x0000FF
    #property indicator_label2 "Sell"
    
    #property indicator_type3 DRAW_ARROW
    #property indicator_width3 1
    #property indicator_color3 0x04CC04
    #property indicator_label3 "Buy Reversal"
    
    #property indicator_type4 DRAW_ARROW
    #property indicator_width4 1
    #property indicator_color4 0xE81AC6
    #property indicator_label4 "Sell Reversal"
    
    #define PLOT_MAXIMUM_BARS_BACK 5000
    #define OMIT_OLDEST_BARS 50
    
    //--- indicator buffers
    double Buffer1[];
    double Buffer2[];
    double Buffer3[];
    double Buffer4[];
    
    input double Oversold = 30;
    input double Overbought = 70;
    input int Slow_MA_period = 200;
    input int Fast_MA_period = 100;
    datetime time_alert; //used when sending alert
    input bool Audible_Alerts = true;
    input bool Push_Notifications = true;
    double myPoint; //initialized in OnInit
    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[];
    
    void myAlert(string type, string message)
      {
       if(type == "print")
          Print(message);
       else if(type == "error")
         {
          Print(type+" | Trend Constraint V1.03 @ "+Symbol()+","+IntegerToString(Period())+" | "+message);
         }
       else if(type == "order")
         {
         }
       else if(type == "modify")
         {
         }
       else if(type == "indicator")
         {
          if(Audible_Alerts) Alert(type+" | Trend Constraint V1.03 @ "+Symbol()+","+IntegerToString(Period())+" | "+message);
          if(Push_Notifications) SendNotification(type+" | Trend Constraint V1.03 @ "+Symbol()+","+IntegerToString(Period())+" | "+message);
         }
      }
    
    //+------------------------------------------------------------------+
    //| Custom indicator initialization function                         |
    //+------------------------------------------------------------------+
    int OnInit()
      {   
       SetIndexBuffer(0, Buffer1);
       PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
       PlotIndexSetInteger(0, PLOT_ARROW, 241);
       SetIndexBuffer(1, Buffer2);
       PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
       PlotIndexSetInteger(1, PLOT_ARROW, 242);
       SetIndexBuffer(2, Buffer3);
       PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
       PlotIndexSetInteger(2, PLOT_ARROW, 236);
       SetIndexBuffer(3, Buffer4);
       PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       PlotIndexSetInteger(3, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
       PlotIndexSetInteger(3, PLOT_ARROW, 238);
       //initialize myPoint
       myPoint = Point();
       if(Digits() == 5 || Digits() == 3)
         {
          myPoint *= 10;
         }
       RSI_handle = iRSI(NULL, PERIOD_CURRENT, 14, PRICE_CLOSE);
       if(RSI_handle < 0)
         {
          Print("The creation of iRSI has failed: RSI_handle=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle = iMA(NULL, PERIOD_CURRENT, 7, 0, MODE_SMMA, PRICE_CLOSE);
       if(MA_handle < 0)
         {
          Print("The creation of iMA has failed: MA_handle=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle2 = iMA(NULL, PERIOD_CURRENT, 400, 0, MODE_SMA, PRICE_CLOSE);
       if(MA_handle2 < 0)
         {
          Print("The creation of iMA has failed: MA_handle2=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle3 = iMA(NULL, PERIOD_CURRENT, Fast_MA_period, 0, MODE_EMA, PRICE_CLOSE);
       if(MA_handle3 < 0)
         {
          Print("The creation of iMA has failed: MA_handle3=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle4 = iMA(NULL, PERIOD_CURRENT, Slow_MA_period, 0, MODE_SMA, PRICE_CLOSE);
       if(MA_handle4 < 0)
         {
          Print("The creation of iMA has failed: MA_handle4=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       return(INIT_SUCCEEDED);
      }
    
    //+------------------------------------------------------------------+
    //| Custom indicator iteration function                              |
    //+------------------------------------------------------------------+
    int OnCalculate(const int rates_total,
                    const int prev_calculated,
                    const datetime& time[],
                    const double& open[],
                    const double& high[],
                    const double& low[],
                    const double& close[],
                    const long& tick_volume[],
                    const long& volume[],
                    const int& spread[])
      {
       int limit = rates_total - prev_calculated;
       //--- counting from 0 to rates_total
       ArraySetAsSeries(Buffer1, true);
       ArraySetAsSeries(Buffer2, true);
       ArraySetAsSeries(Buffer3, true);
       ArraySetAsSeries(Buffer4, true);
       //--- initial zero
       if(prev_calculated < 1)
         {
          ArrayInitialize(Buffer1, EMPTY_VALUE);
          ArrayInitialize(Buffer2, EMPTY_VALUE);
          ArrayInitialize(Buffer3, EMPTY_VALUE);
          ArrayInitialize(Buffer4, EMPTY_VALUE);
         }
       else
          limit++;
       datetime Time[];
       
       datetime TimeShift[];
       if(CopyTime(Symbol(), PERIOD_CURRENT, 0, rates_total, TimeShift) <= 0) return(rates_total);
       ArraySetAsSeries(TimeShift, true);
       int barshift_M1[];
       ArrayResize(barshift_M1, rates_total);
       int barshift_D1[];
       ArrayResize(barshift_D1, rates_total);
       for(int i = 0; i < rates_total; i++)
         {
          barshift_M1[i] = iBarShift(Symbol(), PERIOD_M1, TimeShift[i]);
          barshift_D1[i] = iBarShift(Symbol(), PERIOD_D1, TimeShift[i]);
       }
       if(BarsCalculated(RSI_handle) <= 0) 
          return(0);
       if(CopyBuffer(RSI_handle, 0, 0, rates_total, RSI) <= 0) return(rates_total);
       ArraySetAsSeries(RSI, true);
       if(CopyOpen(Symbol(), PERIOD_M1, 0, rates_total, Open) <= 0) return(rates_total);
       ArraySetAsSeries(Open, true);
       if(CopyClose(Symbol(), PERIOD_D1, 0, rates_total, Close) <= 0) return(rates_total);
       ArraySetAsSeries(Close, true);
       if(BarsCalculated(MA_handle) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle, 0, 0, rates_total, MA) <= 0) return(rates_total);
       ArraySetAsSeries(MA, true);
       if(BarsCalculated(MA_handle2) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle2, 0, 0, rates_total, MA2) <= 0) return(rates_total);
       ArraySetAsSeries(MA2, true);
       if(BarsCalculated(MA_handle3) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle3, 0, 0, rates_total, MA3) <= 0) return(rates_total);
       ArraySetAsSeries(MA3, true);
       if(BarsCalculated(MA_handle4) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle4, 0, 0, rates_total, MA4) <= 0) return(rates_total);
       ArraySetAsSeries(MA4, true);
       if(CopyLow(Symbol(), PERIOD_CURRENT, 0, rates_total, Low) <= 0) return(rates_total);
       ArraySetAsSeries(Low, true);
       if(CopyHigh(Symbol(), PERIOD_CURRENT, 0, rates_total, High) <= 0) return(rates_total);
       ArraySetAsSeries(High, true);
       if(CopyTime(Symbol(), Period(), 0, rates_total, Time) <= 0) return(rates_total);
       ArraySetAsSeries(Time, true);
       //--- main loop
       for(int i = limit-1; i >= 0; i--)
         {
          if (i >= MathMin(PLOT_MAXIMUM_BARS_BACK-1, rates_total-1-OMIT_OLDEST_BARS)) continue; //omit some old rates to prevent "Array out of range" or slow calculation   
          
          if(barshift_M1[i] < 0 || barshift_M1[i] >= rates_total) continue;
          if(barshift_D1[i] < 0 || barshift_D1[i] >= rates_total) continue;
          
          //Indicator Buffer 1
          if(RSI[i] < Oversold
          && RSI[i+1] > Oversold //Relative Strength Index crosses below 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
          )
            {
             Buffer1[i] = Low[1+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
            {
             Buffer1[i] = EMPTY_VALUE;
            }
          //Indicator Buffer 2
          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] = High[1+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
            {
             Buffer2[i] = EMPTY_VALUE;
            }
          //Indicator Buffer 3
          if(MA3[i] > MA4[i]
          && MA3[i+1] < MA4[i+1] //Moving Average crosses above Moving Average
          )
            {
             Buffer3[i] = Low[i]; //Set indicator value at Candlestick Low
             if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Buy Reversal"); //Alert on next bar open
             time_alert = Time[1];
            }
          else
            {
             Buffer3[i] = EMPTY_VALUE;
            }
          //Indicator Buffer 4
          if(MA3[i] < MA4[i]
          && MA3[i+1] > MA4[i+1] //Moving Average crosses below Moving Average
          )
            {
             Buffer4[i] = High[i]; //Set indicator value at Candlestick High
             if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Sell Reversal"); //Alert on next bar open
             time_alert = Time[1];
            }
          else
            {
             Buffer4[i] = EMPTY_VALUE;
            }
         }
       return(rates_total);
      }
    //Thank you, friend. Você chegou a este estágio e pode fazer mais+


    Estilos de Exibição do MQL5

    O MQL5 oferece uma ampla gama de estilos de desenho para indicadores. Ao desenvolver indicadores, o objetivo principal geralmente é projetar sistemas que possam notificar os usuários por meio de alertas sonoros e visuais. Isso ajuda a simplificar as operações de negociação, reduzindo a necessidade de os traders monitorarem constantemente os gráficos, pois o computador cuida dessa responsabilidade. Vou dar uma breve visão geral de alguns estilos de desenho que podem ser utilizados no MQL5, como DRAW_ARROW, DRAW_LINE, DRAW_HISTOGRAM, DRAW_FILLING e DRAW_NONE. Consulte a tabela apresentada abaixo para um resumo conciso. Consulte a Referência MQL5 para informações detalhadas sobre os estilos de desenho.

    ESTILO DE DESENHO DESCRIÇÃO
    DRAW_ARROW Desenha setas em pontos específicos. Frequentemente usado para destacar sinais de compra/venda ou outros eventos importantes.
    DRAW_LINE Usado para desenhar uma linha conectando pontos de dados. Ideal para médias móveis, linhas de tendência e outros indicadores baseados em linhas.
    DRAW_HISTOGRAM Exibe os dados como barras ou histogramas. Útil para volume, histogramas MACD e outros indicadores de tipo de barra.
    DRAW_FILLING Usado para preencher a área entre duas linhas em um gráfico, fornecendo uma forma visualmente intuitiva de representar intervalos de dados, spread ou diferenças entre dois indicadores.
    DRAW_NONE Usado para definir um indicador que não desenha nenhuma representação visual no gráfico.


    Implementando o estilo DRAW_LINE em nosso sistema.

    Vamos utilizar a função DRAW_LINE para exibir nossas tendências de uma forma distinta no gráfico do MetaTrader 5. No passado, conseguimos configurar nosso indicador de forma eficaz para reconhecer reversões de tendência através dos cruzamentos de médias móveis de período mais alto. Nosso objetivo agora é melhorar a forma como apresentamos as informações visualmente, sem sobrecarregar o gráfico com muitos elementos. Essa nova adição nos permitirá desenhar uma linha única que mostra as tendências e altera automaticamente sua cor a cada nova direção. Com nossos atuais 4 buffers, estamos procurando ampliar nossas capacidades introduzindo o buffer 5 e o buffer 6 para a versão 1.04.

    • Buffer 5: Para desenhar uma linha azul quando MA 100 está acima da MA 200
    ///properties
    #property indicator_type5 DRAW_LINE
    #property indicator_style5 STYLE_SOLID
    #property indicator_width5 2
    #property indicator_color5 0xFFAA00
    #property indicator_label5 "Buy Trend"

    • Buffer 6: Para desenhar uma linha vermelha quando MA 100 está abaixo da MA 200

    #property indicator_type6 DRAW_LINE
    #property indicator_style6 STYLE_SOLID
    #property indicator_width6 2
    #property indicator_color6 0x0000FF
    #property indicator_label6 "Sell Trend"
    Nota: A seção acima serve como um espaço reservado para informações adicionais. Mais detalhes podem ser encontrados no código principal abaixo. A disposição dos buffers não é rígida, permitindo variações nos valores, desde que o intuito original seja mantido de forma consistente.

    Código principal para Trend Constraint v1.04

    ///Indicator Name: Trend Constraint
    #property copyright "Clemence Benjamin"
    #property link      "https://mql5.com"
    #property version   "1.04"
    #property description "A model that seek to produce sell signal when D1 candle is Bearish only and  buy signal when it is Bullish"
    //--- indicator settings
    #property indicator_chart_window
    #property indicator_buffers 6
    #property indicator_plots 6
    
    #property indicator_type1 DRAW_ARROW
    #property indicator_width1 5
    #property indicator_color1 0xFF3C00
    #property indicator_label1 "Buy"
    
    #property indicator_type2 DRAW_ARROW
    #property indicator_width2 5
    #property indicator_color2 0x0000FF
    #property indicator_label2 "Sell"
    
    #property indicator_type3 DRAW_ARROW
    #property indicator_width3 2
    #property indicator_color3 0xE8351A
    #property indicator_label3 "Buy Reversal"
    
    #property indicator_type4 DRAW_ARROW
    #property indicator_width4 2
    #property indicator_color4 0x1A1AE8
    #property indicator_label4 "Sell Reversal"
    
    #property indicator_type5 DRAW_LINE
    #property indicator_style5 STYLE_SOLID
    #property indicator_width5 2
    #property indicator_color5 0xFFAA00
    #property indicator_label5 "Buy Trend"
    
    #property indicator_type6 DRAW_LINE
    #property indicator_style6 STYLE_SOLID
    #property indicator_width6 2
    #property indicator_color6 0x0000FF
    #property indicator_label6 "Sell Trend"
    
    #define PLOT_MAXIMUM_BARS_BACK 5000
    #define OMIT_OLDEST_BARS 50
    
    //--- indicator buffers
    double Buffer1[];
    double Buffer2[];
    double Buffer3[];
    double Buffer4[];
    double Buffer5[];
    double Buffer6[];
    
    input double Oversold = 30;
    input double Overbought = 70;
    input int Slow_MA_period = 200;
    input int Fast_MA_period = 100;
    datetime time_alert; //used when sending alert
    input bool Audible_Alerts = true;
    input bool Push_Notifications = true;
    double myPoint; //initialized in OnInit
    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[];
    
    void myAlert(string type, string message)
      {
       if(type == "print")
          Print(message);
       else if(type == "error")
         {
          Print(type+" | Trend Constraint V1.04 @ "+Symbol()+","+IntegerToString(Period())+" | "+message);
         }
       else if(type == "order")
         {
         }
       else if(type == "modify")
         {
         }
       else if(type == "indicator")
         {
          if(Audible_Alerts) Alert(type+" | Trend Constraint V1.04 @ "+Symbol()+","+IntegerToString(Period())+" | "+message);
          if(Push_Notifications) SendNotification(type+" | Trend Constraint V1.04 @ "+Symbol()+","+IntegerToString(Period())+" | "+message);
         }
      }
    
    //+------------------------------------------------------------------+
    //| Custom indicator initialization function                         |
    //+------------------------------------------------------------------+
    int OnInit()
      {   
       SetIndexBuffer(0, Buffer1);
       PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
       PlotIndexSetInteger(0, PLOT_ARROW, 241);
       SetIndexBuffer(1, Buffer2);
       PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
       PlotIndexSetInteger(1, PLOT_ARROW, 242);
       SetIndexBuffer(2, Buffer3);
       PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
       PlotIndexSetInteger(2, PLOT_ARROW, 236);
       SetIndexBuffer(3, Buffer4);
       PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       PlotIndexSetInteger(3, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
       PlotIndexSetInteger(3, PLOT_ARROW, 238);
       SetIndexBuffer(4, Buffer5);
       PlotIndexSetDouble(4, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       PlotIndexSetInteger(4, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
       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));
       //initialize myPoint
       myPoint = Point();
       if(Digits() == 5 || Digits() == 3)
         {
          myPoint *= 10;
         }
       RSI_handle = iRSI(NULL, PERIOD_CURRENT, 14, PRICE_CLOSE);
       if(RSI_handle < 0)
         {
          Print("The creation of iRSI has failed: RSI_handle=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle = iMA(NULL, PERIOD_CURRENT, 7, 0, MODE_SMMA, PRICE_CLOSE);
       if(MA_handle < 0)
         {
          Print("The creation of iMA has failed: MA_handle=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle2 = iMA(NULL, PERIOD_CURRENT, 400, 0, MODE_SMA, PRICE_CLOSE);
       if(MA_handle2 < 0)
         {
          Print("The creation of iMA has failed: MA_handle2=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle3 = iMA(NULL, PERIOD_CURRENT, 100, 0, MODE_EMA, PRICE_CLOSE);
       if(MA_handle3 < 0)
         {
          Print("The creation of iMA has failed: MA_handle3=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle4 = iMA(NULL, PERIOD_CURRENT, 200, 0, MODE_SMA, PRICE_CLOSE);
       if(MA_handle4 < 0)
         {
          Print("The creation of iMA has failed: MA_handle4=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle5 = iMA(NULL, PERIOD_CURRENT, Fast_MA_period, 0, MODE_SMA, PRICE_CLOSE);
       if(MA_handle5 < 0)
         {
          Print("The creation of iMA has failed: MA_handle5=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       MA_handle6 = iMA(NULL, PERIOD_CURRENT, Slow_MA_period, 0, MODE_SMA, PRICE_CLOSE);
       if(MA_handle6 < 0)
         {
          Print("The creation of iMA has failed: MA_handle6=", INVALID_HANDLE);
          Print("Runtime error = ", GetLastError());
          return(INIT_FAILED);
         }
       
       return(INIT_SUCCEEDED);
      }
    
    //+------------------------------------------------------------------+
    //| Custom indicator iteration function                              |
    //+------------------------------------------------------------------+
    int OnCalculate(const int rates_total,
                    const int prev_calculated,
                    const datetime& time[],
                    const double& open[],
                    const double& high[],
                    const double& low[],
                    const double& close[],
                    const long& tick_volume[],
                    const long& volume[],
                    const int& spread[])
      {
       int limit = rates_total - prev_calculated;
       //--- counting from 0 to rates_total
       ArraySetAsSeries(Buffer1, true);
       ArraySetAsSeries(Buffer2, true);
       ArraySetAsSeries(Buffer3, true);
       ArraySetAsSeries(Buffer4, true);
       ArraySetAsSeries(Buffer5, true);
       ArraySetAsSeries(Buffer6, true);
       //--- initial zero
       if(prev_calculated < 1)
         {
          ArrayInitialize(Buffer1, EMPTY_VALUE);
          ArrayInitialize(Buffer2, EMPTY_VALUE);
          ArrayInitialize(Buffer3, EMPTY_VALUE);
          ArrayInitialize(Buffer4, EMPTY_VALUE);
          ArrayInitialize(Buffer5, EMPTY_VALUE);
          ArrayInitialize(Buffer6, EMPTY_VALUE);
         }
       else
          limit++;
       datetime Time[];
       
       datetime TimeShift[];
       if(CopyTime(Symbol(), PERIOD_CURRENT, 0, rates_total, TimeShift) <= 0) return(rates_total);
       ArraySetAsSeries(TimeShift, true);
       int barshift_M1[];
       ArrayResize(barshift_M1, rates_total);
       int barshift_D1[];
       ArrayResize(barshift_D1, rates_total);
       for(int i = 0; i < rates_total; i++)
         {
          barshift_M1[i] = iBarShift(Symbol(), PERIOD_M1, TimeShift[i]);
          barshift_D1[i] = iBarShift(Symbol(), PERIOD_D1, TimeShift[i]);
       }
       if(BarsCalculated(RSI_handle) <= 0) 
          return(0);
       if(CopyBuffer(RSI_handle, 0, 0, rates_total, RSI) <= 0) return(rates_total);
       ArraySetAsSeries(RSI, true);
       if(CopyOpen(Symbol(), PERIOD_M1, 0, rates_total, Open) <= 0) return(rates_total);
       ArraySetAsSeries(Open, true);
       if(CopyClose(Symbol(), PERIOD_D1, 0, rates_total, Close) <= 0) return(rates_total);
       ArraySetAsSeries(Close, true);
       if(BarsCalculated(MA_handle) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle, 0, 0, rates_total, MA) <= 0) return(rates_total);
       ArraySetAsSeries(MA, true);
       if(BarsCalculated(MA_handle2) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle2, 0, 0, rates_total, MA2) <= 0) return(rates_total);
       ArraySetAsSeries(MA2, true);
       if(BarsCalculated(MA_handle3) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle3, 0, 0, rates_total, MA3) <= 0) return(rates_total);
       ArraySetAsSeries(MA3, true);
       if(BarsCalculated(MA_handle4) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle4, 0, 0, rates_total, MA4) <= 0) return(rates_total);
       ArraySetAsSeries(MA4, true);
       if(CopyLow(Symbol(), PERIOD_CURRENT, 0, rates_total, Low) <= 0) return(rates_total);
       ArraySetAsSeries(Low, true);
       if(CopyHigh(Symbol(), PERIOD_CURRENT, 0, rates_total, High) <= 0) return(rates_total);
       ArraySetAsSeries(High, true);
       if(BarsCalculated(MA_handle5) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle5, 0, 0, rates_total, MA5) <= 0) return(rates_total);
       ArraySetAsSeries(MA5, true);
       if(BarsCalculated(MA_handle6) <= 0) 
          return(0);
       if(CopyBuffer(MA_handle6, 0, 0, rates_total, MA6) <= 0) return(rates_total);
       ArraySetAsSeries(MA6, true);
       if(CopyTime(Symbol(), Period(), 0, rates_total, Time) <= 0) return(rates_total);
       ArraySetAsSeries(Time, true);
       //--- main loop
       for(int i = limit-1; i >= 0; i--)
         {
          if (i >= MathMin(PLOT_MAXIMUM_BARS_BACK-1, rates_total-1-OMIT_OLDEST_BARS)) continue; //omit some old rates to prevent "Array out of range" or slow calculation   
          
          if(barshift_M1[i] < 0 || barshift_M1[i] >= rates_total) continue;
          if(barshift_D1[i] < 0 || barshift_D1[i] >= rates_total) continue;
          
          //Indicator Buffer 1
          if(RSI[i] < Oversold
          && RSI[i+1] > Oversold //Relative Strength Index crosses below 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
          )
            {
             Buffer1[i] = Low[1+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
            {
             Buffer1[i] = EMPTY_VALUE;
            }
          //Indicator Buffer 2
          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] = High[1+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
            {
             Buffer2[i] = EMPTY_VALUE;
            }
          //Indicator Buffer 3
          if(MA5[i] > MA6[i]
          && MA5[i+1] < MA6[i+1] //Moving Average crosses above Moving Average
          )
            {
             Buffer3[i] = Low[i]; //Set indicator value at Candlestick Low
             if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Buy Reversal"); //Alert on next bar open
             time_alert = Time[1];
            }
          else
            {
             Buffer3[i] = EMPTY_VALUE;
            }
          //Indicator Buffer 4
          if(MA5[i] < MA6[i]
          && MA5[i+1] > MA6[i+1] //Moving Average crosses below Moving Average
          )
            {
             Buffer4[i] = High[i]; //Set indicator value at Candlestick High
             if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Sell Reversal"); //Alert on next bar open
             time_alert = Time[1];
            }
          else
            {
             Buffer4[i] = EMPTY_VALUE;
            }
          //Indicator Buffer 5
          if(MA5[i] > MA6[i] //Moving Average > Moving Average
          )
            {
             Buffer5[i] = MA6[i]; //Set indicator value at Moving Average
             if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Buy Trend"); //Alert on next bar open
             time_alert = Time[1];
            }
          else
            {
             Buffer5[i] = EMPTY_VALUE;
            }
          //Indicator Buffer 6
          if(MA5[i] < MA6[i] //Moving Average < Moving Average
          )
            {
             Buffer6[i] = MA6[i]; //Set indicator value at Moving Average
             if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Sell Trend"); //Alert on next bar open
             time_alert = Time[1];
            }
          else
            {
             Buffer6[i] = EMPTY_VALUE;
            }
         }
       return(rates_total);
      }
    //You are the best coder


    Nosso programa inovador agora demonstra capacidades avançadas, ajustando a cor de uma única linha sempre que um novo curso é estabelecido. Essa funcionalidade simplifica o gráfico ao incorporar cores, melhorando assim o sistema de sinalização juntamente com outras notificações que são visuais e sonoras. As imagens abaixo fornecem uma representação visual do impacto desse último recurso.

    Trend Constraint V1.04 on USDJPY

    Fig 2: Trend Constraint V1.04 on USDJPY

    Trend Constraint V1.04 on Boom 500 Index

    Fig 3: Trend Constraint V1.04 on Boom 500 index

    Status do Meu Candle D1

    Para adicionar um novo recurso ao nosso modelo, queremos verificar rapidamente o status do candlestick D1 assim que mudarmos para o MetaTrader 5 e começarmos a usar nosso modelo. Decidi incluir um script aqui que mostra o status do candle D1 no gráfico, mesmo que o gráfico esteja em prazos diferentes de D1. Essa melhoria ajuda a identificar rapidamente o status do candle, especialmente ao trabalhar em prazos de M1, onde os separadores de período D1 podem não estar visíveis em certos níveis de zoom. Agora, vamos examinar o código do script MQL5 apresentado abaixo:

    //My_D1_candlestatus.mql5
    //Author: Clemence Benjamin
    //Link: https://www.mql5.com/en/users/billionaire2024/seller
    #property copyright "Copyright 2024, Clemence Benjamin"
    #property link      "https://www.mql5.com/en/users/billionaire2024/seller"
    #property version   "1.00"
    #property script_show_inputs
    #property strict
    
    //+------------------------------------------------------------------+
    //| Script program start function                                    |
    //+------------------------------------------------------------------+
    void OnStart()
      {
       //--- Get the opening and closing prices of the current D1 candle
       double openPrice = iOpen(NULL, PERIOD_D1, 0);
       double closePrice = iClose(NULL, PERIOD_D1, 0);
       
       //--- Determine if the candle is bullish or bearish
       string candleStatus;
       if(closePrice > openPrice)
         {
          candleStatus = " D1 candle is bullish.";
         }
       else if(closePrice < openPrice)
         {
          candleStatus = " D1 candle is bearish.";
         }
       else
         {
          candleStatus = " D1 candle is neutral.";// when open price is equal to close price
         
         }
       
       //--- Print the status on the chart
       Comment(candleStatus);
       
       //--- Also print the status in the Experts tab for logging
       Print(candleStatus);
      }
    //+------------------------------------------------------------------+
    
    


    Entendendo as funções e variáveis do Script My_D1_Candlestatus.mq5

    Funções e Variáveis Descrição
    OnStart() Esta é a função principal do script que é executada quando o script é acionado. Ela recupera os preços de abertura e fechamento do candle D1 atual, determina se o candle é altista, baixista ou neutro e, em seguida, exibe essa informação no gráfico usando Comment().
    iOpen() and iClose() Essas funções recuperam os preços de abertura e fechamento do candle D1 atual.

    candleStatus Uma variável string para armazenar a mensagem de status do candle D1 atual.
    Comment() Essa função exibe a mensagem de status no gráfico.
    Print() Essa função registra a mensagem de status na aba "Experts" para log adicional.

    Após compilar o código, você poderá localizar o script e executá-lo seguindo as instruções fornecidas na ilustração. O script exibirá um comentário que mostra o status do candle do dia atual.

    Executando o script My D1 Candle status

    Fig 4: Executando o script My_D1_candlestatus.mq5


    Outras alternativas para os estilos de desenho MQL5

    O MetaTrader 5 vem com uma ampla variedade de ferramentas de esboço para avaliação prática do mercado, como linhas, canais e figuras, todas convenientemente localizadas na plataforma MetaTrader. Ao explorar um conhecimento profundo da linguagem de Programação Orientada a Objetos MQL5 e suas conexões com Python e C++, os traders têm a capacidade de criar ferramentas personalizadas e expansões Os traders podem aproveitar essas ferramentas para melhorar suas capacidades de análise técnica e tomar decisões de negociação mais informadas. Com as opções de flexibilidade e personalização disponíveis no MetaTrader 5, os traders têm a oportunidade de adaptar sua experiência de negociação para atender às suas preferências e estratégias. 


    Conclusão

    Integrámos com sucesso um novo recurso em nosso programa, resultando em resultados positivos que têm o potencial de influenciar a próxima versão, à medida que progredimos de um indicador para um EA em artigos subsequentes. Os estilos de desenho no MQL5 apresentam benefícios notáveis para os traders, melhorando a clareza, precisão e personalização da visualização de dados. Esses estilos fortalecem as capacidades de análise técnica, facilitam técnicas avançadas de criação de gráficos e suportam atualizações interativas em tempo real. Além disso, a flexibilidade e a criatividade proporcionadas pelos estilos de desenho MQL5 permitem que os traders criem indicadores e ferramentas de análise distintas, enriquecendo suas abordagens de negociação e a compreensão geral do mercado.

    Nosso modelo está evoluindo com precisão refinada, oferecendo percepções visuais instantâneas com o clique de um botão. O script transmite prontamente o status do candle D1, enquanto o recurso DRAW_LINE destaca as tendências em um prazo menor de forma compreensível. Incluí os arquivos de origem para todos os recursos discutidos aqui. Confio que você está acompanhando o progresso e adquirindo conhecimentos; sinta-se à vontade para compartilhar seus comentários e participar das discussões.


    Traduzido do Inglês pela MetaQuotes Ltd.
    Artigo original: https://www.mql5.com/en/articles/14899

    Últimos Comentários | Ir para discussão (1)
    4641208
    4641208 | 13 jun. 2024 em 16:23
    Nos artigos:O MQL5 foi projetado de forma a ser forte no algoritmo de análise de dados e também poderoso no desenho de vários estilos de indicadores no Meta Trader 5.
    MQL5 Trading Toolkit (Parte 1): Desenvolvendo uma Biblioteca EX5 para Gerenciamento de Posições MQL5 Trading Toolkit (Parte 1): Desenvolvendo uma Biblioteca EX5 para Gerenciamento de Posições
    Aprenda a criar um kit de ferramentas para desenvolvedores para gerenciar várias operações de posição com MQL5. Neste artigo, vou demonstrar como criar uma biblioteca de funções (ex5) que realizará operações de gerenciamento de posições, de simples a avançadas, incluindo o tratamento automático e a geração de relatórios dos diferentes erros que surgem ao lidar com tarefas de gerenciamento de posições com MQL5.
    Um Guia Passo a Passo sobre a Estratégia de Quebra de Estrutura (BoS) Um Guia Passo a Passo sobre a Estratégia de Quebra de Estrutura (BoS)
    Um guia abrangente para desenvolver um algoritmo de negociação automatizado baseado na estratégia de Quebra de Estrutura (BoS). Informações detalhadas sobre todos os aspectos da criação de um consultor em MQL5 e testando-o no MetaTrader 5 — desde a análise de suporte e resistência de preços até a gestão de riscos.
    Desenvolvendo uma estratégia Martingale de Recuperação de Zona em MQL5 Desenvolvendo uma estratégia Martingale de Recuperação de Zona em MQL5
    O artigo discute, de forma detalhada, os passos que precisam ser implementados para a criação de um advisor especializado baseado no algoritmo de negociação de Recuperação de Zona. Isso ajuda a automatizar o sistema, economizando tempo para os negociadores algorítmicos.
    Redes neurais de maneira fácil (Parte 93): Previsão adaptativa nas áreas de frequência e tempo (Conclusão) Redes neurais de maneira fácil (Parte 93): Previsão adaptativa nas áreas de frequência e tempo (Conclusão)
    Neste artigo, continuamos a implementação das abordagens do ATFNet — um modelo que adapta e combina os resultados de 2 blocos (frequencial e temporal) de previsão de séries temporais.