English Русский 中文 Deutsch 日本語 Português
preview
Desarrollamos el indicador True Strength Index personalizado utilizando MQL5

Desarrollamos el indicador True Strength Index personalizado utilizando MQL5

MetaTrader 5Trading | 6 octubre 2023, 15:43
701 0
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

Introducción

Si se usan correctamente, los indicadores técnicos pueden resultar muy útiles, ya que pueden ofrecer información adicional que resulta difícil de detectar simplemente observando la acción del precio. Existen muchos indicadores técnicos ya preparados que podemos usar, pero a veces necesitamos personalizarlos para que nos proporcionen información específica o bien tendremos que crear un nuevo indicador basado en nuestras ideas. Hay una manera de crear estos indicadores personalizados en MQL5 y utilizarlos en la plataforma comercial MetaTrader 5. En este artículo le mostraré cómo crear un TSI desde cero. Asimismo, estudiaremos los detalles de este indicador y veremos cómo calcularlo en nuestro código. También aprenderemos cómo podemos usar este indicador personalizado en un sistema comercial creando un asesor experto. Todas estas cuestiones se tratarán en los siguientes apartados:

Una vez dominemos los temas mencionados, podremos usar e interpretar el indicador True Strength Index, y también calcularlo y convertirlo en código como indicador personalizado en MQL5 para posteriormente usarlo en MetaTrader 5. Asimismo, podremos implementar el indicador en otros sistemas comerciales o asesores. Si desea desarrollar sus habilidades de programación, le animo a que escriba el código por sí mismo, ya que esta práctica supone un paso muy importante en cualquier proceso de aprendizaje. Usaremos MetaTrader 5 para escribir el código MQL5 en su IDE integrado en el terminal comercial MetaTrader 5. Si no tiene la plataforma o no sabe cómo descargarla y usarla, consulte la sección "Escribiendo el código MQL5 en el MetaEditor" en varios de mis artículos anteriores.

¡Atención! Toda la información del presente artículo se ofrece «tal cual», únicamente con fines ilustrativos, y no supone ningún tipo de recomendación. El artículo no garantiza ningún resultado en absoluto. Todo lo que ponga en práctica usando este artículo como base, lo hará bajo su propia cuenta y riesgo; el autor no garantiza resultado alguno.


Definición de True Strength Index (TSI)

En esta sección veremos el indicador técnico True Strength Index (TSI), diseñado en su día por William Blau. El indicador mide el impulso de la acción del precio, es decir, la fuerza del instrumento. Este oscila alrededor de la línea cero, por eso se trata de un oscilador de impulso. Podemos utilizar una línea de señal junto con él para generar señales de compra o venta adicionales basadas en la intersección de estas líneas. No obstante, solo podremos recibir señales desde la línea TSI, valiéndonos de su intersección con el nivel cero. Si está por encima de la línea cero, indicará un impulso alcista, y si está por debajo, indicará un impulso bajista. El indicador se puede usar para detectar áreas de sobrecompra y sobreventa, así como para detectar divergencias alcistas y bajistas. Como sabemos que necesitamos confirmar sus señales para aumentar el peso de las pruebas, será mejor usarlo en combinación con otras herramientas técnicas que deberíamos utilizar en el mismo contexto de la acción del precio para una mejor comprensión.

Veamos ahora cómo calcular este indicador. El cálculo se realiza en varias etapas, concretamente:

Cálculo del impulso doblemente suavizado:

  • Calculamos el impulso (cambio de precio) restando el precio anterior del actual
  • Calculamos el primer suavizado obteniendo la EMA de 25 periodos del impulso calculado
  • Calculamos el segundo suavizado obteniendo la EMA de 13 periodos del primer suavizado (EMA de 25 periodos del impulso calculado)

Cálculo del impulso absoluto doblemente suavizado:

  • Calculamos el impulso absoluto restando el precio absoluto anterior del precio absoluto actual
  • Calculamos el primer suavizado obteniendo la EMA de 25 periodos del impulso absoluto calculado
  • Calculamos el segundo suavizado obteniendo la EMA de 13 periodos del primer suavizado (EMA de 25 periodos del impulso absoluto calculado)

Cálculo del TSI = 100*(Impulso doble suavizado / Impulso absoluto doble suavizado)

El resultado de este cálculo será una línea que fluctuará alrededor de cero, midiendo el impulso de la acción del precio e identificando las áreas de sobrecompra y sobreventa.


Indicador TSI simple personalizado

El lenguaje de programación MQL5 tiene muchos indicadores técnicos predefinidos que podemos usar en nuestros sistemas utilizando la función predefinida. Ya hemos mencionado muchos de estos indicadores en artículos anteriores de la serie al analizar cómo podemos desarrollar un sistema comercial. Puede consultar los artículos anteriores para buscar información útil. Ahora la pregunta es cómo podemos crear un indicador si no existe en el paquete de entrega estándar de la plataforma, e incluso si existe, cómo podemos crear un indicador personalizado para obtener las señales o activadores deseados. La respuesta corta es que debemos crear nuestro propio indicador utilizando un lenguaje de programación básico. Eso es lo que haremos aquí:

aprenderemos a crear un indicador TSI personalizado usando MQL5. Luego utilizaremos sus capacidades en otros sistemas o asesores. Para crear este indicador personalizado, deberemos cumplir las siguientes etapas.

Al crear parámetros adicionales usando #property, indicaremos al lado el valor del identificador. Tendremos que especificar los siguientes parámetros:

  • (indicator_separate_window) — muestra el indicador en una ventana aparte.
  • (indicator_buffers) — número de búferes del indicador. Indicaremos (8).
  • (indicator_plots) — especifica el número de series gráficas del indicador. Indicaremos (1).
  • (indicator_label1) — para establecer la etiqueta del número de serie gráfica, especificaremos (TSI).
  • (indicator_type1) — para indicar el tipo de construcción gráfica especificando un valor de los valores ENUM_DRAW_TYPE, especificaremos (DRAW_LINE).
  • (indicator_color1) — para especificar el color de la línea del indicador mostrada, especificaremos (clrBlue).
  • (indicator_style1) — para especificar el estilo de la línea del indicador, especificaremos (STYLE_SOLID).
  • (indicator_width1) — para especificar el grosor de la línea del indicador, especificaremos (3).
#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

Asimismo, necesitaremos incluir el archivo MovingAverage.mqh para utilizar su componente en nuestros cálculos. Este archivo se activará en Include usando el comando #include. Asegúrese de que los nombres de los archivos coincidan.

#include <MovingAverages.mqh>

También necesitaremos establecer los dos periodos de suavizado que usaremos al calcular el indicador, utilizando la clase de datos de entrada para que el usuario introduzca estos valores si necesita actualizar los valores predeterminados que están especificados en el programa. Después de esto, definiremos el tipo de datos de las variables (InpSmPeriod1, InpSmPeriod2) que necesitamos declarar usando uint, que es un número entero sin signo. Luego estableceremos (25) InpSmPeriod1 y (13) InpSmPeriod2 como valores predeterminados. 

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

A continuación, crearemos dos variables enteras para los periodos de suavizado (smperiod1,smperiod2),

int            smperiod1;
int            smperiod2;

y crearemos siete arrays para los búferes de indicador

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

Realizaremos los siguientes pasos dentro de la función OnInit():

Primero declararemos las variables (smperiod1,smperiod2), retornando el valor 2 si los parámetros de entrada del usuario InpSmPeriod1 e InpSmPeriod2 son menores que 2, o devolviendo los valores InpSmPeriod1 e InpSmPeriod2 en caso contrario.

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

Luego conectaremos los búferes de indicador a los arrays usando la función (SetIndexBuffer). Los parámetros serán los siguientes:

index: número del búfer del indicador, y números del 0 al 7 en el programa.

buffer[]: array declarado en el indicador personalizado.

data_type: tipo de datos almacenados en el array de indicadores.

   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);

Al establecer el valor de la propiedad de indicador correspondiente, esta propiedad del indicador (valor prop) deberá ser de tipo string usando la función (IndicatorSetString) con una opción de llamada que especifique solo el identificador de la propiedad. Este paso consiste en establecer un nombre breve para el indicador y definir los periodos que se mostrarán en la parte superior izquierda de la ventana del indicador. Sus parámetros son:

  • prop_id: identificador de la propiedad de indicador incluida en la enumeración (ENUM_CUSTOMIND_PROPERTY_STRING). En nuestro programa será (INDICATOR_SHORTNAME).
  • prop_value: valor de propiedad, será de tipo string. En nuestro caso, este será "True Strength Index ("+(string)smperiod1+","+(string)smperiod2+")".
IndicatorSetString(INDICATOR_SHORTNAME,"True Strength Index ("+(string)smperiod1+","+(string)smperiod2+")");

Luego estableceremos otro valor de la propiedad de indicador en un tipo de datos entero para normalizar el valor de indicador según el número de decimales usando (IndicatorSetInteger) con una opción de compra que especifique solo el identificador de propiedad. Parámetros: 

  • prop_id: identificador de propiedad de indicador incluida en la enumeración (ENUM_CUSTOMIND_PROPERTY_INTEGER). En nuestro programa será (INDICATOR_DIGITS).
  • prop_value: valor de propiedad, será un tipo de datos entero. Será Digits().
IndicatorSetInteger(INDICATOR_DIGITS,Digits());

A continuación estableceremos el indicador AS_SERIES para el array usando (ArraySetAsSeries).

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

Después de la función OnCalculate

  • Después configuraremos el indicador AS_SERIES para el array cerrado de OnCalculate y verificaremos si rate_total es menor que 2 para retornar 0,
  • y crearemos una variable entera (limit) igual a (rates_total-prev_calculated).
  • Luego comprobaremos si la variable límite es mayor que 1. En este caso, deberemos los pasos siguientes:
  • Actualizaremos la variable limit con el resultado (rates_total - 2).
  • Después inicializaremos los arrays numéricos de tipo double con un valor dado usando la función (ArrayInitialize). Sus parámetros serán array[] para indicar el array numérico que se inicializará, y el parámetro value para indicar el nuevo valor establecido.
   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);
     }

Luego crearemos un ciclo para actualizar momBuff[i], absMomBuff[i]. Nuevas funciones utilizadas en esta etapa:

  • una operación de ciclo (for) con tres expresiones y una declaración ejecutable.
  • IsStopped() para comprobar si el programa mql5 ha sido forzado a finalizar.
  • MathAbs retorna el valor absoluto (módulo) y podemos usar la función febs() para obtener el mismo resultado.
   for(int i=limit; i>=0 && !IsStopped(); i--)
     {
      momBuff[i]=close[i]-close[i+1];
      absMomBuff[i]=MathAbs(momBuff[i]);
     }

Realizaremos la comprobación usando la función ExponentialMAOnBuffer del archivo de inclusión (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;

Luego crearemos otro ciclo para actualizar la variable indBuff[i] usando la función for

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

Al final del programa existe una función de retorno (rates_total).

   return(rates_total);

Ya hemos completado el código para crear nuestro indicador TSI personalizado: usted también podrá editar sus preferencias en su código para lograr configuraciones adicionales. El código completo del indicador tiene el aspecto siguiente:

//+------------------------------------------------------------------+
//|                                                   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);
  }

Tras compilar este código sin errores, encontraremos el indicador entre los disponibles en la carpeta "Indicadores" del navegador. Al arrastrarlo al gráfico deseado, veremos la ventana de parámetros del indicador:

simpleTSI inputs win

Entonces tendremos dos parámetros de entrada que el usuario podrá definir, además de los valores predeterminados: 25 para el periodo de suavizado 1, y 13 para el periodo de suavizado 2. Sin embargo, como ya hemos mencionado, el usuario podrá editarlos según sus preferencias.

 simpleTSI colors win

En la imagen anterior, en la pestaña de colores, podemos ver que el usuario puede seleccionar el color, la anchura y el estilo de la línea TSI. Tras configurar los parámetros necesarios y el estilo del indicador, este se verá así:

 simpleTSI attached

Como podemos ver en el gráfico anterior, la línea del indicador TSI se encuentra en una ventana aparte bajo de los precios y fluctúa alrededor de cero, y además tenemos la etiqueta del indicador, sus periodos de suavizado y el valor del indicador.


Asesor TSI personalizado

En esta sección, veremos lo sencillo que es utilizar un indicador en un sistema automatizado para que pueda generar una determinada señal o acción al activarse una determinada condición. Comenzaremos creando un asesor muy simple que generará un comentario en el gráfico con el valor TSI actual y luego desarrollaremos un asesor que ejecutará instrucciones más complejas.

A continuación detallaremos los pasos necesarios para crear un asesor:

  • Creamos una variable entera (TSI).
  • Definimos TSI utilizando la función iCustom para devolver el descriptor del indicador y sus parámetros:
    • symbol — nombre del símbolo; para nosotros será _Symbol, es decir, calcularemos el indicador según el símbolo del gráfico actual.
    • period — marco temporal para el cálculo; el valor _period significa que el indicador se calculará en el marco temporal actual.
    • name — ruta al indicador personalizado.
  • Mostrar el texto "TSI System Removed" en OnDeinit (TSI System eliminado) después de eliminar el asesor.
  • Crearemos el array tsiVal[]
  • Obtener los datos del búfer del indicador TSI usando la función CopyBuffer con la opción de llamar según la primera posición y el número de elementos requeridos. Los parámetros serán los siguientes:
    • indicator_handle — manejador de indicador retornado que usaremos (TSI).
    • buffer_num — número de búfer de indicador, lo estableceremos en (0).
    • start_pos — posición inicial para copiar, especificaremos (0).
    • count — cantidad de datos a copiar, especificaremos (1).
    • buffer[]: array a copiar, especificaremos (tsiVal).
  • Usando la función Comment para mostrar el valor TSI actual convertido a un valor string utilizando la función (DoubleToString) con parámetros value para indicar el valor TSI actual y para indicar el número de dígitos, nosotros usaremos (_Digits) para el valor actual.

El código completo de este sistema tendrá el aspecto siguiente:

//+------------------------------------------------------------------+
//|                                           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));
  }

Una vez que este código de error se compile y ejecute, se adjuntará al gráfico. Aquí tenemos un ejemplo de prueba de una señal basada en esta estrategia:

 Señal del asesor iCustom TSI

Como podemos ver, el valor TSI actual se indica en la esquina superior izquierda del gráfico. Si queremos asegurarnos de que la señal sea la misma que la nuestra según el indicador, podemos adjuntar un asesor y especificar el indicador como valores al mismo tiempo. Vamos a asegurarnos de que todo funcione:

Asesor iCustom TSI iniciado - misma señal

Como podemos ver en la esquina superior derecha, tenemos un asesor adjunto, y su señal aparece en la esquina superior izquierda con el valor TSI actual. Al mismo tiempo, tenemos el indicador TSI insertado en el gráfico como una ventana aparte debajo de los precios, y su valor es mayor. Su línea en la esquina izquierda coincide con la señal del asesor.


Asesor TSI System

En esta parte, desarrollaremos un asesor basado en el indicador TSI personalizado creado para recibir señales basadas en una estrategia específica. Tenga en cuenta que la estrategia que vamos a analizar tiene fines únicamente educativos. En cualquier caso, requerirá de una cierta optimización, como cualquier otra. Por consiguiente, deberá probarla antes de usarla en una cuenta real para asegurarse de que le resulte útil.

Nosotros usaremos nuestro propio indicador TSI en combinación con dos medias móviles para generar señales de compra y venta basadas en una estrategia específica:

Además de nuestro indicador TSI personalizado, usaremos dos medias móviles simples (MA): una rápida con un periodo de 10 y otra lenta con un periodo de 20. Si el valor anterior de la MA rápida es menor que la MA lenta anterior y al mismo tiempo la MA rápida actual es mayor que la MA lenta actual, esto significará que tenemos un cruce de MA alcista. Luego comprobaremos si el valor TSI actual es superior a cero. Necesitaremos obtener la señal de compra como comentario en el gráfico. Si el valor anterior de la MA rápida es mayor que la MA lenta anterior y al mismo tiempo la MA rápida actual es menor que la MA lenta actual, esto significará que tenemos un cruce de MA bajista. Luego comprobaremos si el valor TSI actual es inferior a cero. Necesitaremos obtener la señal de venta como comentario en el gráfico.

Esquemáticamente:

Si fastMA[1]<slowMA[1] && fastMA[0]>slowMA[0] && tsiVal[0]>0 ==> Señal de compra
Si fastMA[1]>slowMA[1] && fastMA[0]<slowMA[0] && tsiVal[0]<0 ==> Señal de venta

El código completo para crear un sistema comercial de este tipo tendrá el aspecto que sigue:

//+------------------------------------------------------------------+
//|                                                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));
        }
     }
  }

Cuáles son las diferencias en este código:

Crearemos cuatro parámetros de entrada de usuario para el tipo de media móvil, el tipo de precio aplicado, el periodo de MA rápida y el periodo de MA lenta y les asignaremos valores por defecto.

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

Creando dos arrays para el array de la MA rápida y la MA lenta.

double fastMAarray[], slowMAarray[];

Definición de dos medias móviles utilizando una función iMA predefinida para retornar un identificador de media móvil y sus parámetros:

  • symbol — símbolo para los cálculos; _Symbol indica el símbolo del gráfico actual.
  • period — periodo para los cálculos, _Period indica el marco temporal actual.
  • ma_period — parámetros de entrada para las medias móviles rápidas y lentas.
  • ma_shift — especificaremos (0), ya que no se requiere ningún desplazamiento.
  • ma_method — tipo de MA.
  • applied _price — tipo de precio.
   int fastMA =iMA(_Symbol,_Period,inpFastMAPeriod,0,inpMAType,inpPriceType);
   int slowMA =iMA(_Symbol,_Period,inpSlowMAPeriod,0,inpMAType,inpPriceType);

Configuración del indicador AS_SERIES utilizando la función ArraySetAsSeries para MA lentas y rápidas

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

Recuperando los datos de un búfer de dos medias móviles utilizando la función CopyBuffer

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

Vamos a determinar las condiciones de la estrategia,

Si hay una señal de compra:

Si la MA rápida anterior (fastMA) es menor que la MA lenta anterior (slowMA), y la MA rápida actual es mayor que la MA lenta actual, y el tsiVal actual es superior a cero, entonces necesitaremos que el asesor retorne una señal de una compra como comentario en el gráfico en el siguiente orden:

  • Señal de compra
  • Valor de TSI
  • Valor de MA rápida
  • Valor de MA lenta
   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));
        }
     }

Si hay una señal de venta:

Si la MA rápida anterior es mayor que la MA lenta anterior, y la MA rápida actual es menor que la MA lenta actual, y el tsiVal actual es inferior a cero, entonces necesitaremos que el asesor retorne una señal de venta como comentario en el gráfico en el siguiente orden:

  • Señal de venta
  • Valor de TSI
  • Valor de MA rápida
  • Valor de MA lenta
   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));
        }
     }

Después de compilar este código sin errores y arrastrarlo al gráfico, se abrirá la ventana de datos de entrada:

Parámetros de entrada del asesor TSI System

Como podemos ver, tenemos cuatro parámetros de entrada: tipo de MA, tipo de precio, periodo de MA rápida y periodo de MA lenta. Tras configurar nuestras preferencias y clicar en OK, el asesor se iniciará en el gráfico y sus señales serán las siguientes:

Si hay una señal de compra

 Asesor TSI System - señal de compra

Como podemos ver en el gráfico anterior, tenemos una señal de compra en forma de comentario en la esquina superior izquierda según las condiciones de nuestra estrategia, como se muestra a continuación:

  • Señal de compra
  • Valor de TSI
  • Valor de MA rápida
  • Valor de MA lenta

Si hay una señal de venta:

 Asesor TSI System - señal de venta

Como podemos ver en el gráfico anterior, tenemos una señal de venta en forma de comentario en la esquina superior izquierda según las condiciones de nuestra estrategia, como se muestra a continuación:

  • Señal de venta
  • Valor de TSI
  • Valor de MA rápida
  • Valor de MA lenta

Conclusión

En este artículo, hemos aprendido cómo crear nuestro propio indicador técnico True Strength Index según nuestras configuraciones y preferencias específicas. Hemos visto qué información y conocimientos ofrece este indicador que puedan resultarnos muy útiles en el comercio. También hemos aprendido cómo se puede utilizar este indicador personalizado en un sistema comercial simple para generar el valor actual del indicador TSI como comentario en el gráfico. Asimismo, hemos visto cómo utilizar el indicador en un sistema comercial automatizado mediante la creación de un asesor que utiliza los datos de TSI en combinación con otra herramienta técnica, que en nuestro caso, la media móvil. Esta combinación de un TSI personalizado y dos medias móviles genera señales de compra y venta basadas en una estrategia específica que hemos abarcado con detalle en la sección del asesor del sistema TSI.

Espero que este artículo le resulte útil para aprender más sobre trading y programación. Si desea leer otros artículos sobre indicadores y aprender cómo crear sistemas comerciales basados ​​en los indicadores técnicos más populares, puede leer mis artículos anteriores, en los que hablo sobre indicadores populares como la media móvil, las bandas de Bollinger, RSI, MACD, Stochastic y Parabolic SAR, ATR y otros.

Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/12570

Archivos adjuntos |
simpleTSI.mq5 (7.46 KB)
iCustomTSI_ea.mq5 (0.81 KB)
TSI_System_EA.mq5 (2.09 KB)
Comprensión y uso eficaz del simulador de estrategias MQL5 Comprensión y uso eficaz del simulador de estrategias MQL5
Para los desarrolladores de MQL5 resulta imperativo dominar herramientas importantes y valiosas. Una de esas herramientas es el simulador de estrategias. El presente artículo es una guía práctica para utilizar el simulador de estrategias MQL5.
Desarrollamos un indicador Heiken Ashi personalizado utilizando MQL5 Desarrollamos un indicador Heiken Ashi personalizado utilizando MQL5
En este artículo, aprenderemos cómo crear nuestro propio indicador usando MQL5 según nuestras preferencias. Dicho indicador se utilizará en MetaTrader 5 para interpretar gráficos o como parte de asesores expertos.
Redes neuronales: así de sencillo (Parte 44): Estudiamos las habilidades de forma dinámica Redes neuronales: así de sencillo (Parte 44): Estudiamos las habilidades de forma dinámica
En el artículo anterior, nos familiarizamos con el método DIAYN, que ofrece un algoritmo para el aprendizaje de diversas habilidades. El uso de las habilidades aprendidas puede aprovecharse en diversas tareas, pero estas habilidades pueden resultar bastante impredecibles, lo cual puede dificultar su uso. En este artículo, analizaremos un algoritmo para el aprendizaje de habilidades predecibles.
Cómo detectar tendencias y patrones de gráficos usando MQL5 Cómo detectar tendencias y patrones de gráficos usando MQL5
El artículo presenta un método para detectar automáticamente patrones de acción del precio usando MQL5, tales como tendencias (ascendentes, descendentes, laterales) y patrones de gráficos (pico doble, valle doble).