Como criar um indicador personalizado True Strength Index usando MQL5

Mohamed Abdelmaaboud | 26 setembro, 2023

Introdução

Indicadores técnicos podem ser muito úteis se os usarmos corretamente, pois podem fornecer informações adicionais que são difíceis de detectar apenas olhando para a ação do preço. Existem muitos indicadores técnicos prontos que podemos usar, mas às vezes podemos achar que precisamos personalizá-los para indicar ou nos fornecer informações específicas, ou precisamos criar um novo com base em nossas ideias vencedoras. Existe uma maneira de criar esses indicadores personalizados no MQL5 e usá-los na plataforma de negociação MetaTrader 5. Neste artigo, vou compartilhar como você pode criar o Indicador True Strength Index do zero. Vamos aprender os detalhes deste indicador e ver como calculá-lo em nosso código. Não apenas isso, mas também aprenderemos como podemos usar este indicador personalizado em um sistema de negociação com base em uma estratégia, criando um Expert Advisor. Vamos abordar tudo isso nos tópicos a seguir:

Depois de dominar os tópicos mencionados, poderemos usar e interpretar o indicador True Strength Index, bem como calculá-lo e codificá-lo como um indicador personalizado em MQL5 para uso no MetaTrader 5. Você também será capaz de implementar o indicador em outros sistemas de negociação ou EAs. Se você deseja desenvolver suas habilidades de programação, aconselho a tentar codificar o conteúdo aqui por conta própria, pois essa prática é um passo muito importante em qualquer processo de aprendizado. Usaremos o MetaTrader 5 para escrever nosso código MQL5 em sua IDE, que está integrada ao terminal de negociação MetaTrader 5. Se você não possui a plataforma ou não sabe como baixá-la e usá-la, pode ler o tópico 'Como escrever código MQL5 no MetaEditor' em meus artigos anteriores.

Atenção! Todo o conteúdo deste artigo é apresentado "tal qual como está", apenas para fins educacionais e não constitui uma recomendação de trading. O artigo não fornece qualquer garantia de resultados. Tudo o que você colocar em prática com base neste artigo, você faz exclusivamente por sua conta e risco, o autor não garante nenhum resultado.


Definindo o True Strength Index (TSI)

Nesta seção, analisaremos o indicador técnico True Strength Index (TSI). Ele foi desenvolvido por William Blau como um indicador técnico que mede o momentum da ação do preço, ou seja, mede a força do instrumento, se é forte ou fraco. Ele oscila em torno da linha zero, sendo assim um indicador oscilador de momentum. Uma linha de sinal pode ser usada com ele para obter sinais adicionais de compra ou venda com base no cruzamento dessas linhas. No entanto, podemos obter sinais com base apenas na linha TSI, com base em seu cruzamento com o nível zero. Se estiver acima da linha zero, significa um momentum de alta, e se estiver abaixo de zero, significa um momentum de baixa. O indicador pode ser usado para detectar áreas de sobrecompra e sobrevenda, bem como divergências de alta e de baixa. Como sabemos que precisamos confirmar seus sinais para aumentar o peso das evidências, é melhor usá-lo acompanhado de outras ferramentas técnicas, que devemos usar no mesmo contexto da ação do preço para obter melhores insights.

Agora, vamos ver como calcular este indicador. O cálculo é realizado em várias etapas, que são:

Cálculo do momentum duplamente suavizado:

Cálculo do momentum absoluto duplamente suavizado:

Calcular TSI = 100 * (Momentum duplamente suavizado / Momentum absoluto duplamente suavizado)

Este cálculo resultará em uma linha oscilante ao redor de zero, medindo o momentum da ação do preço e detectando áreas de sobrecompra e sobrevenda, como mencionamos e outras.


Indicador personalizado TSI Simple

A linguagem de programação MQL5 possui muitos indicadores técnicos predefinidos, e podemos usá-los em nossos sistemas usando uma função predefinida. á falamos sobre muitos desses indicadores em artigos anteriores desta série, discutindo como podemos projetar um sistema de negociação com base nesses indicadores técnicos populares. Você pode examinar os artigos anteriores e talvez encontrar algo útil. A pergunta agora é como podemos criar um indicador se ele não existir no pacote padrão da plataforma ou mesmo se existir, como podemos criar um indicador personalizado para obter os sinais ou triggers desejados. A resposta curta é criar um indicador personalizado usando a linguagem de programação principal, e é isso que faremos nesta parte.

Vamos aprender como criar nosso indicador personalizado True Strength Index usando MQL5. Em seguida, usaremos suas características em outros sistemas ou EAs. As seguintes etapas são para a criação deste indicador personalizado.

Criamos parâmetros adicionais usando #property e ao lado dele especificaremos o valor do identificador e os seguintes são esses parâmetros que precisamos especificar:

#property indicator_separate_window
#property indicator_buffers 8
#property indicator_plots   1
#property indicator_label1  "TSI"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  3

Precisamos incluir o arquivo MovingAverage.mqh para usar seu componente em nosso cálculo, e este arquivo está presente no arquivo Include, usando o comando #include. Verifique se os nomes dos arquivos correspondem.

#include <MovingAverages.mqh>

Precisamos definir dois valores de períodos de suavização que usaremos no cálculo do indicador, usando a classe de entrada para que o usuário possa inserir esses valores, caso ele queira atualizar os valores padrão especificados no programa. Após isso, determinaremos o tipo de dados das variáveis (InpSmPeriod1, InpSmPeriod2) que precisamos declarar, usando uint, que é um número inteiro não assinado. Em seguida, atribuiremos (25) a InpSmPeriod1 e (13) a InpSmPeriod2 como valores padrão. 

input uint     InpSmPeriod1   =  25;    // Smoothing period 1
input uint     InpSmPeriod2   =  13;   // Smoothing period 2

Criamos duas variáveis inteiras para os períodos de suavização (smperiod1, smperiod2).

int            smperiod1;
int            smperiod2;

Criamos sete arrays para os buffers do indicador.

double         indBuff[];
double         momBuff[];
double         momSmBuff1[];
double         momSmBuff2[];
double         absMomBuff[];
double         absMomSmBuff1[];
double         absMomSmBuff2[];

Dentro da função OnInit (), realizaremos as seguintes etapas:

Declaramos variáveis (smperiod1, smperiod2) retornando o valor 2 se os parâmetros de entrada do usuário de InpSmPeriod1 e InpSmPeriod2 forem menores que 2, ou retornamos os valores de InpSmPeriod1 e InpSmPeriod2 se houver algo diferente.

   smperiod1=int(InpSmPeriod1<2 ? 2 : InpSmPeriod1);
   smperiod2=int(InpSmPeriod2<2 ? 2 : InpSmPeriod2);

Vinculamos os buffers do indicador com os arrays usando a função (SetIndexBuffer). Seus parâmetros são:

index: define o número do buffer do indicador e os números começam com 0 a 7 em nosso programa.

buffer[]: especifica o array declarado no indicador personalizado.

data_type: especifica o tipo de dados armazenado no array do indicador.

   SetIndexBuffer(0,indBuff,INDICATOR_DATA);
   SetIndexBuffer(2,momBuff,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,momSmBuff1,INDICATOR_CALCULATIONS);
   SetIndexBuffer(4,momSmBuff2,INDICATOR_CALCULATIONS);
   SetIndexBuffer(5,absMomBuff,INDICATOR_CALCULATIONS);
   SetIndexBuffer(6,absMomSmBuff1,INDICATOR_CALCULATIONS);
   SetIndexBuffer(7,absMomSmBuff2,INDICATOR_CALCULATIONS);

Configuramos o valor da propriedade do indicador correspondente. Essa propriedade do indicador (valor prop) deve ser do tipo string, mediante a função (IndicatorSetString) com a variante de chamada especificando apenas o identificador da propriedade. Essa etapa é para definir um nome curto para o indicador e determinar os períodos a serem exibidos na parte superior esquerda da janela do indicador. Seus parâmetros são:

IndicatorSetString(INDICATOR_SHORTNAME,"True Strength Index ("+(string)smperiod1+","+(string)smperiod2+")");

Configuramos outro valor da propriedade do indicador como inteiro para normalizar o valor do indicador de acordo com as casas decimais, mediante a função (IndicatorSetInteger) com a variante de chamada especificando apenas o identificador da propriedade. Seus parâmetros são: 

IndicatorSetInteger(INDICATOR_DIGITS,Digits());

Configuramos a flag AS_SERIES para o array, usando a função (ArraySetAsSeries).

   ArraySetAsSeries(indBuff,true);
   ArraySetAsSeries(momBuff,true);
   ArraySetAsSeries(momSmBuff1,true);
   ArraySetAsSeries(momSmBuff2,true);
   ArraySetAsSeries(absMomBuff,true);
   ArraySetAsSeries(absMomSmBuff1,true);
   ArraySetAsSeries(absMomSmBuff2,true);

Após a função OnCalculate,

   ArraySetAsSeries(close,true);
   if(rates_total<2)
      return 0;

   int limit=rates_total-prev_calculated;
   if(limit>1)
     {
      limit=rates_total-2;
      ArrayInitialize(indBuff,EMPTY_VALUE);
      ArrayInitialize(momBuff,0);
      ArrayInitialize(momSmBuff1,0);
      ArrayInitialize(momSmBuff2,0);
      ArrayInitialize(absMomBuff,0);
      ArrayInitialize(absMomSmBuff1,0);
      ArrayInitialize(absMomSmBuff2,0);
     }

Criamos um laço para atualizar o momBuff[i], absMomBuff[i]. As novas funções usadas nesta etapa são:

   for(int i=limit; i>=0 && !IsStopped(); i--)
     {
      momBuff[i]=close[i]-close[i+1];
      absMomBuff[i]=MathAbs(momBuff[i]);
     }

Verificamos o seguinte usando a função ExponentialMAOnBuffer do arquivo Include (MovingAverage).

   if(ExponentialMAOnBuffer(rates_total,prev_calculated,0,smperiod1,momBuff,momSmBuff1)==0)
      return 0;
   if(ExponentialMAOnBuffer(rates_total,prev_calculated,0,smperiod1,absMomBuff,absMomSmBuff1)==0)
      return 0;
   if(ExponentialMAOnBuffer(rates_total,prev_calculated,smperiod1,smperiod2,momSmBuff1,momSmBuff2)==0)
      return 0;
   if(ExponentialMAOnBuffer(rates_total,prev_calculated,smperiod1,smperiod2,absMomSmBuff1,absMomSmBuff2)==0)
      return 0;

Criamos outro laço para atualizar a variável indBuff[i] usando a função for.

   for(int i=limit; i>=0 && !IsStopped(); i--)
      indBuff[i]=(absMomSmBuff2[i]!=0 ? 100.0*momSmBuff2[i]/absMomSmBuff2[i] : 0);

No final do programa, temos a função return (rates_total).

   return(rates_total);

Desse modo, agora concluímos o código para criar nosso indicador personalizado TSI, e você também pode editar suas preferências em seu código para obter mais personalizações. O código completo do indicador tem a seguinte aparência:

//+------------------------------------------------------------------+
//|                                                   simple TSI.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 8
#property indicator_plots   1
#property indicator_label1  "TSI"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  3
#include <MovingAverages.mqh>
input uint     InpSmPeriod1   =  25;    // Smoothing period 1
input uint     InpSmPeriod2   =  13;   // Smoothing period 2
int            smperiod1;
int            smperiod2;
double         indBuff[];
double         momBuff[];
double         momSmBuff1[];
double         momSmBuff2[];
double         absMomBuff[];
double         absMomSmBuff1[];
double         absMomSmBuff2[];
int OnInit()
  {
   smperiod1=int(InpSmPeriod1<2 ? 2 : InpSmPeriod1);
   smperiod2=int(InpSmPeriod2<2 ? 2 : InpSmPeriod2);
   SetIndexBuffer(0,indBuff,INDICATOR_DATA);
   SetIndexBuffer(2,momBuff,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,momSmBuff1,INDICATOR_CALCULATIONS);
   SetIndexBuffer(4,momSmBuff2,INDICATOR_CALCULATIONS);
   SetIndexBuffer(5,absMomBuff,INDICATOR_CALCULATIONS);
   SetIndexBuffer(6,absMomSmBuff1,INDICATOR_CALCULATIONS);
   SetIndexBuffer(7,absMomSmBuff2,INDICATOR_CALCULATIONS);
   IndicatorSetString(INDICATOR_SHORTNAME,"True Strength Index ("+(string)smperiod1+","+(string)smperiod2+")");
   IndicatorSetInteger(INDICATOR_DIGITS,Digits());
   ArraySetAsSeries(indBuff,true);
   ArraySetAsSeries(momBuff,true);
   ArraySetAsSeries(momSmBuff1,true);
   ArraySetAsSeries(momSmBuff2,true);
   ArraySetAsSeries(absMomBuff,true);
   ArraySetAsSeries(absMomSmBuff1,true);
   ArraySetAsSeries(absMomSmBuff2,true);
   return(INIT_SUCCEEDED);
  }
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[])
  {
   ArraySetAsSeries(close,true);
   if(rates_total<2)
      return 0;

   int limit=rates_total-prev_calculated;
   if(limit>1)
     {
      limit=rates_total-2;
      ArrayInitialize(indBuff,EMPTY_VALUE);
      ArrayInitialize(momBuff,0);
      ArrayInitialize(momSmBuff1,0);
      ArrayInitialize(momSmBuff2,0);
      ArrayInitialize(absMomBuff,0);
      ArrayInitialize(absMomSmBuff1,0);
      ArrayInitialize(absMomSmBuff2,0);
     }
   for(int i=limit; i>=0 && !IsStopped(); i--)
     {
      momBuff[i]=close[i]-close[i+1];
      absMomBuff[i]=MathAbs(momBuff[i]);
     }
   if(ExponentialMAOnBuffer(rates_total,prev_calculated,0,smperiod1,momBuff,momSmBuff1)==0)
      return 0;
   if(ExponentialMAOnBuffer(rates_total,prev_calculated,0,smperiod1,absMomBuff,absMomSmBuff1)==0)
      return 0;
   if(ExponentialMAOnBuffer(rates_total,prev_calculated,smperiod1,smperiod2,momSmBuff1,momSmBuff2)==0)
      return 0;
   if(ExponentialMAOnBuffer(rates_total,prev_calculated,smperiod1,smperiod2,absMomSmBuff1,absMomSmBuff2)==0)
      return 0;
   for(int i=limit; i>=0 && !IsStopped(); i--)
      indBuff[i]=(absMomSmBuff2[i]!=0 ? 100.0*momSmBuff2[i]/absMomSmBuff2[i] : 0);
   return(rates_total);
  }

Após compilar este código sem erros, encontraremos o indicador entre os disponíveis na pasta de Indicadores em seu navegador, arrastando-o e soltando-o no gráfico desejado. Encontraremos a janela do indicador e as seguintes entradas:

simpleTSI inputs win

Assim, temos duas entradas que o usuário pode determinar, e os valores padrão são 25 para o período de suavização 1 e 13 para o período de suavização 2. No entanto, o usuário ainda pode editá-los conforme suas preferências, como mencionamos.

 simpleTSI colors win

Podemos ver na imagem anterior na guia de cores que o usuário pode escolher a cor, largura e estilo da linha TSI. Após determinar nossas preferências de entrada e o estilo do indicador, como mencionamos, podemos encontrar o indicador no gráfico, igual ao seguinte:

 simpleTSI attached

Como podemos ver no gráfico anterior, temos a linha do indicador TSI em uma janela separada abaixo dos preços, e essa linha oscila em torno de zero. E temos o rótulo do indicador, seus períodos de suavização e o valor do indicador.


Um EA personalizado do TSI

Nesta parte, aprenderemos de maneira muito simples como usar nosso indicador personalizado em um sistema automatizado para que ele possa gerar um sinal ou ação específica quando uma condição específica for acionada. Começaremos por um sistema muito simples, criando um Expert Advisor, que gerará um comentário no gráfico com o valor atual do TSI, antes de desenvolver um EA que execute instruções mais complexas.

Bem, abaixo estão as etapas necessárias para criar nosso Expert Advisor:

O código completo será o mesmo que o seguinte:

//+------------------------------------------------------------------+
//|                                           customSimpleTSI-EA.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
int TSI;
int OnInit()
  {
   TSI=iCustom(_Symbol,_Period,"My Files\\TSI\\simpleTSI");
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   Print("TSI System Removed");
  }
void OnTick()
  {
   double tsiVal[];
   CopyBuffer(TSI,0,0,1,tsiVal);
   Comment("TSI Value ",DoubleToString(tsiVal[0],_Digits));
  }

Após compilar este código sem erros e executá-lo, ele será anexado ao gráfico. O seguinte é um exemplo de seu sinal com base nessa estratégia:

 Sinal do Expert Advisor iCustom TSI

Como podemos ver, temos um comentário no canto superior esquerdo do gráfico com o valor atual do TSI. Se quisermos ter certeza de que o sinal é o mesmo que temos com base no indicador, podemos anexar o EA e inserir o indicador ao mesmo tempo para verificar os valores. O seguinte é para garantir nosso trabalho:

Expert Advisor iCustom TSI iniciado - o sinal é o mesmo

Como podemos ver no canto superior direito, temos o EA anexado e seu sinal aparece no canto superior esquerdo com o valor atual do TSI ao mesmo tempo em que temos o indicador TSI inserido no gráfico como uma janela separada abaixo dos preços e seu valor acima. Sua linha no canto esquerdo coincide com o sinal do EA.


Um EA do TSI System

Nesta parte, desenvolveremos um EA com base no indicador TSI personalizado criado para obter sinais com base em uma estratégia específica. Por favor, observe que a estratégia que vamos discutir destina-se apenas a fins educacionais. Ela precisará de otimizações, assim como qualquer outra estratégia. Portanto, é necessário testá-la antes de usá-la em uma conta real para garantir que seja útil para você.

Usaremos o indicador TSI personalizado combinado com duas médias móveis para obter sinais de compra e venda com base em uma estratégia específica, conforme a seguir:

Usaremos duas médias móveis simples, uma rápida com um período de 10 e a outra lenta com um período de 20, além do nosso indicador TSI personalizado. Se o valor anterior da média móvel rápida for menor que o valor anterior da média móvel lenta e, ao mesmo tempo, a média móvel rápida atual for maior que a média móvel lenta atual, isso significa que temos uma cruzamento de média móvel de alta, então verificaremos se o valor atual do TSI é maior que zero para obter um sinal de compra como um comentário no gráfico. Se o valor anterior da média móvel rápida for maior que o valor anterior da média móvel lenta e, ao mesmo tempo, a média móvel rápida atual for menor que a média móvel lenta atual, isso significa que temos uma cruzamento de média móvel de baixa, então verificaremos se o valor atual do TSI é menor que zero para obter um sinal de venda como um comentário no gráfico.

Simplesmente:

Caso fastMA[1]<slowMA[1] && fastMA[0]>slowMA[0] && tsiVal[0]>0 ==> Sinal de compra
Caso fastMA[1]>slowMA[1] && fastMA[0]<slowMA[0] && tsiVal[0]<0 ==> Sinal de venda

O seguinte é o código completo para criar esse tipo de sistema:

//+------------------------------------------------------------------+
//|                                                TSI System EA.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
input ENUM_MA_METHOD inpMAType = MODE_SMA; //Moving Average Type
input ENUM_APPLIED_PRICE inpPriceType = PRICE_CLOSE; //Price type
input int inpFastMAPeriod = 10; // Fast moving average period
input int inpSlowMAPeriod = 20; //Slow moving average period
int tsi;
double fastMAarray[], slowMAarray[];
int OnInit()
  {
   tsi=iCustom(_Symbol,_Period,"My Files\\TSI\\simpleTSI");
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   Print("TSI System Removed");
  }
void OnTick()
  {
   double tsiVal[];
   CopyBuffer(tsi,0,0,1,tsiVal);
   int fastMA =iMA(_Symbol,_Period,inpFastMAPeriod,0,inpMAType,inpPriceType);
   int slowMA =iMA(_Symbol,_Period,inpSlowMAPeriod,0,inpMAType,inpPriceType);
   ArraySetAsSeries(fastMAarray,true);
   ArraySetAsSeries(slowMAarray,true);
   CopyBuffer(fastMA,0,0,3,fastMAarray);
   CopyBuffer(slowMA,0,0,3,slowMAarray);
   if(fastMAarray[1]<slowMAarray[1]&&fastMAarray[0]>slowMAarray[0])
     {
      if(tsiVal[0]>0)
        {

         Comment("Buy Signal",
                 "\nTSI Value ",DoubleToString(tsiVal[0],_Digits),
                 "\nfastMA ",DoubleToString(fastMAarray[0],_Digits),
                 "\nslowMA ",DoubleToString(slowMAarray[0],_Digits));
        }
     }
   if(fastMAarray[1]>slowMAarray[1]&&fastMAarray[0]<slowMAarray[0]&&tsiVal[0]<0)
     {
      if(tsiVal[0]<0)
        {
         Comment("Sell Signal",
                 "\nTSI Value ",DoubleToString(tsiVal[0],_Digits),
                 "\nfastMA ",DoubleToString(fastMAarray[0],_Digits),
                 "\nslowMA ",DoubleToString(slowMAarray[0],_Digits));
        }
     }
  }

As diferenças neste código são as seguintes:

Criamos quatro entradas pelo usuário para o tipo de média móvel, o tipo de preço aplicado, o período da MA rápida e o período da MA lenta, e atribuir valores padrão para eles.

input ENUM_MA_METHOD inpMAType = MODE_SMA; //Moving Average Type
input ENUM_APPLIED_PRICE inpPriceType = PRICE_CLOSE; //Price type
input int inpFastMAPeriod = 10; // Fast moving average period
input int inpSlowMAPeriod = 20; //Slow moving average period

Criamos dois arrays para a MA rápida e a MA lenta.

double fastMAarray[], slowMAarray[];

Definimos as duas médias móveis usando a função iMA predefinida para retornar o identificador da média móvel, e seus parâmetros são:

   int fastMA =iMA(_Symbol,_Period,inpFastMAPeriod,0,inpMAType,inpPriceType);
   int slowMA =iMA(_Symbol,_Period,inpSlowMAPeriod,0,inpMAType,inpPriceType);

Configuramos a flag AS_SERIES usando a função ArraySetAsSeries para as médias móveis lenta e rápida.

   ArraySetAsSeries(fastMAarray,true);
   ArraySetAsSeries(slowMAarray,true);

Obtemos dados do buffer das duas médias móveis usando a função CopyBuffer.

   CopyBuffer(fastMA,0,0,3,fastMAarray);
   CopyBuffer(slowMA,0,0,3,slowMAarray);

Definimos as condições da estratégia:

No caso de sinal de compra:

Se a média móvel rápida anterior for menor que a média móvel lenta anterior e a média móvel rápida atual for maior que a média móvel lenta atual e ao mesmo tempo o valor atual do TSI for maior que zero, precisamos que o EA retorne o sinal de compra como um comentário no gráfico na seguinte ordem:

   if(fastMAarray[1]<slowMAarray[1]&&fastMAarray[0]>slowMAarray[0])
     {
      if(tsiVal[0]>0)
        {

         Comment("Buy Signal",
                 "\nTSI Value ",DoubleToString(tsiVal[0],_Digits),
                 "\nfastMA ",DoubleToString(fastMAarray[0],_Digits),
                 "\nslowMA ",DoubleToString(slowMAarray[0],_Digits));
        }
     }

No caso de sinal de venda:

Se a média móvel rápida anterior for maior que a média móvel lenta anterior e a média móvel rápida atual for menor que a média móvel lenta atual e ao mesmo tempo o valor atual do TSI for menor que zero, precisamos que o EA retorne o sinal de venda como um comentário no gráfico na seguinte ordem:

   if(fastMAarray[1]>slowMAarray[1]&&fastMAarray[0]<slowMAarray[0]&&tsiVal[0]<0)
     {
      if(tsiVal[0]<0)
        {
         Comment("Sell Signal",
                 "\nTSI Value ",DoubleToString(tsiVal[0],_Digits),
                 "\nfastMA ",DoubleToString(fastMAarray[0],_Digits),
                 "\nslowMA ",DoubleToString(slowMAarray[0],_Digits));
        }
     }

Depois de compilar esse código sem erros e arrastá-lo para o gráfico, será aberta a janela de dados de entrada:

Parâmetros de entrada do Expert Advisor TSI System

Como podemos ver, temos quatro parâmetros de entrada para o tipo de MA, tipo de preço, período da MA rápida e período da MA lenta. Depois de configurar nossas preferências e pressionar OK, podemos ver que o EA está anexado ao gráfico, e seus sinais serão iguais aos seguintes:

No caso de sinal de compra

 Expert Advisor TSI System - sinal de compra

Como podemos ver no gráfico anterior, temos um sinal de compra como um comentário no canto superior esquerdo, de acordo com nossas condições de estratégia, como mencionado anteriormente.

No caso de sinal de venda:

 Expert Advisor TSI System - sinal de venda

Como podemos ver no gráfico anterior, temos um sinal de venda como um comentário no canto superior esquerdo, de acordo com nossas condições de estratégia, como mostrado abaixo:

Considerações finais

Neste artigo, aprendemos como criar seu próprio indicador técnico True Strength Index para implementar suas configurações e preferências específicas. Vimos quais informações e insights este indicador fornece, o que pode ser muito útil na negociação. Também aprendemos como usar este indicador personalizado em um sistema de negociação simples para gerar o valor atual do indicador TSI como um comentário no gráfico. Também vimos como usar o indicador em um sistema de negociação automatizado, criando o EA que utiliza os dados do TSI combinados com outra ferramenta técnica, que, no nosso caso, é a média móvel. Essa combinação do TSI personalizado e duas médias móveis gerou sinais de compra e venda com base em uma estratégia específica, que detalhamos no tópico do EA do Sistema TSI.

Espero que este artigo seja útil para sua aprendizagem de negociação e programação. Se você quiser ler outros artigos sobre indicadores e aprender como criar sistemas de negociação com base nos indicadores técnicos mais populares, consulte meus artigos anteriores, nos quais cobri indicadores populares, como a média móvel, Bandas de Bollinger, RSI, MACD, Estocástico, Parabolic SAR, ATR e outros.