Crear un Indicador Multidivisa Usando un Número de Buffers de Indicador Intermediarios

Alexey Klenov | 21 febrero, 2014

Introducción

Todo empezó cuando oí hablar por primera vez de los indicadores de conglomerados del artículo Base Teórica de Construcción de Indicadores de Conglomerados para FOREX. En aquel momento lo encontré muy interesante, y decidí escribir algo parecido en términos de análisis multimercado. Al principio implementé mi versión propia del indicador, llamado con el código MultiCurrencyIndex, en el que los valores calculados de los índices de divisas se usan para calcular los porcentajes de indicadores clásicos (RSI, MACD, CCI). 

Y ahora les explicaré cómo transferí este indicador a una nueva plataforma, MetaTrader 5 en conjunto con MQL5, excepto que en lugar de calcular el CCI, calcularé el indicador Stochastics (Oscilador Estocástico), que en mi opinión es más directo.

Empecemos con algunas definiciones.

Dollar Index (Índice de dólar) - - valor doble calculado por la fórmula, que adquirí gracias a la generosa aportación de Neutron.

La fórmula para calcular el índice USD,

donde hay USD / YYY - todas las cuotas directas, como USD / CHF, XXX / USD - todas al revés, como EUR / USD.

Otros índices se calculan de los valores de pares de divisas de Cierre que contienen USD.

Main lines (Líneas principales) - dos líneas del indicador que reflejan los datos calculados, relacionadas directamente con el gráfico actual. Por ejemplo, en el gráfico EURUSD mostrará líneas de divisas EUR y USD.

Supplementary lines (Líneas suplementarias) - otras líneas calculadas no relacionadas con el gráfico actual. Por ejemplo, para el mismo gráfico EURUSD serán líneas de divisas GBP, CHF, JPY, CAD, AUD y NZD.

Close (Cierre) - el valor del precio de cierre de la barra del intervalo actual (tipo doble) para el par de divisas necesario.

Empecemos.

La configuración del problema

Para empezar, deberemos configurar el problema.

  1. Sincronice los gráficos de los pares de divisas afectados de este intervalo.
  2. Obtenga acceso a los datos de Close (Cierre) de siete pares de divisas: EURUSD, GBPUSD, USDCHF, USDJPY, USDCAD, AUDUSD, NZDUSD, y colóquelos dentro de los buffers de indicador diseñados para cálculos auxiliares.
  3. Basándonos en los datos obtenidos en el elemento (2), calcule el índice de dólar para la barra actual.
  4. Sabiendo ya el índice de dólar para la barra actual, calcule los índices de divisa restantes.
  5. Realice cálculos de datos (elementos 3 y 4) el número de veces necesario para la longitud de historial seleccionada.
  6. Dependiendo del destino del indicador, calcule los valores de la divisa para caca uno de los índices seleccionados:
    • Índice de Fuerza Relativa (Relative Strength Index, RSI);
    • Convergencia o Divergencia de Medias Móviles (Moving Average Convergence / Divergence, MACD);
    • Oscilador Estocástico (Stochastic Oscillator);
    • En el futuro, puede ser que añadamos suplementos a la lista.

Para ello necesitaremos:

31 buffers de indicador:

Para seleccionar el destino de un indicador, haremos un tipo de enumeración enum :

enum Indicator_Type
  {
   Use_RSI_on_indexes             = 1, // RSI of the index  
   Use_MACD_on_indexes            = 2, // MACD from the index  
   Use_Stochastic_Main_on_indexes = 3  // Stochastic on the index
  };
A continuación, usando el comando input  en la ventana de preferencias del indicador, derivaremos hacia las selecciones del usuario de esta lista. 
input Indicator_Type ind_type=Use_RSI_on_indexes;  // type of the indicator from the index

Es posible crear una forma más sencilla de mostrar los nombres de los parámetros de entrada en la pestaña "Inputs" ("entradas"). Para ello, usaremos el propósito del comentario urgente, que se debe colocar tras la descripción del parámetro de entrada, en la misma fila. Por tanto, los parámetros de entrada se pueden comparar a nombres más fácilmente comprensibles para el usuario.

Las mismas reglas se pueden aplicar a los comandos de enumeración enum . Es decir, si el nombre mnemónico está asociado a un comentario, como se muestra en nuestro ejemplo, en lugar del nombre mnemónico se mostrarán los contenidos de este comentario. Esto facilita mayor flexibilidad para escribir programas con descripciones claras para los parámetros de entrada.

Los desarrolladores intentaron facilitar al usuario medios convenientes de trabajo con el programa MQL5, asegurándose de que lee nombres de parámetros comprensibles, en lugar de lo que se escribe en el código. Puede encontrar más información aquí.

Figura 1. Seleccionar el tipo de indicador

Figura 1. Seleccionar el tipo de indicador

Ahora facilitaremos al usuario una selección de divisas necesarias para reproducir el indicador y sus colores:

input bool USD=true;
input bool EUR=true;
input bool GBP=true;
input bool JPY=true;
input bool CHF=true;
input bool CAD=true;
input bool AUD=true;
input bool NZD=true;

input color Color_USD = Green;            // USD line color
input color Color_EUR = DarkBlue;         // EUR line color
input color Color_GBP = Red;              // GBP line color
input color Color_CHF = Chocolate;        // CHF line color
input color Color_JPY = Maroon;           // JPY line color
input color Color_AUD = DarkOrange;       // AUD line color
input color Color_CAD = Purple;           // CAD line color
input color Color_NZD = Teal;             // NZD line color

Figura 2. Seleccionar el color de las líneas del indicador

Figura 2. Seleccionar el color de las líneas del indicador

Otros parámetros configurables:

input string rem000        =  ""; // depending on the type of the indicator
input string rem0000       =  ""; // requires a value :
input int rsi_period       =   9; // period RSI
input int MACD_fast        =   5; // period MACD_fast
input int MACD_slow        =  34; // period MACD_slow
input int stoch_period_k   =   8; // period Stochastic %K
input int stoch_period_sma =   5; // period of smoothing for Stochastics %K
input int shiftbars        = 500; // number of bars for calculating the indicator

Figura 3. Parámetros de indicador

Figura 3. Parámetros de indicador

El límite de 500 barras para el cálculo del indicador es artificial, pero es suficiente para demostrar el concepto del cálculo. Pero debemos recordar que cada buffer del indicador requiere memoria, y que al mostrar un tamaño variable muy grande (en millones de barras) podríamos agotar la memoria del ordenador.

Buffers de indicador:

double  EURUSD[], // quotes
        GBPUSD[],
        USDCHF[],
        USDJPY[],
        AUDUSD[],
        USDCAD[],
        NZDUSD[];   
               
double    USDx[], // indexes
          EURx[],
          GBPx[],
          JPYx[],
          CHFx[],
          CADx[],
          AUDx[],
          NZDx[];
                         
double USDplot[], // results of currency lines
       EURplot[],
       GBPplot[],
       JPYplot[],
       CHFplot[],
       CADplot[],
       AUDplot[],
       NZDplot[]; 

double USDStoch[], // buffers of intermediate data schotastics by the close/close type without smoothing
       EURStoch[],
       GBPStoch[],
       JPYStoch[],
       CHFStoch[],
       CADStoch[],
       AUDStoch[],
       NZDStoch[];
Asimismo, necesitaremos algunas variables globales (nivel de indicador):
int              i,ii;
int           y_pos=0; // Y coordinate variable for the informatory objects  
datetime   arrTime[7]; // Array with the last known time of a zero valued bar (needed for synchronization)  
int        bars_tf[7]; // To check the number of available bars in different currency pairs  
int        countVal=0; // Number of executable Rates  
int           index=0;
datetime  tmp_time[1]; // Intermediate array for the time of the bar 

Y ahora llegamos al elemento de considerable longitud OnInit. Usándolo, distribuiremos los buffers de indicador según sus propósitos.

Puesto que los cálculos iniciales pasan a través del índice de dólar, para el USD simplemente estableceremos la posibilidad de desactivar la creación de los buffers de indicador de divisas.

Tiene este aspecto:

if(USD)
  {
   countVal++;
   SetIndexBuffer(0,USDplot,INDICATOR_DATA);               // array for rendering
   PlotIndexSetString(0,PLOT_LABEL,"USDplot");             // name of the indicator line (when selected with a mouse)
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,shiftbars);       // from which we begin rendering
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE);        // drawing style (line)
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,Color_USD);       // color of line rendering
   if(StringFind(Symbol(),"USD",0)!=-1)
     {PlotIndexSetInteger(0,PLOT_LINE_WIDTH,wid_main);}    // if the symbol name contains USD 
                                                           // then draw a line of appropriate width 
   else
     {PlotIndexSetInteger(0,PLOT_LINE_STYLE,style_slave);}
   ArraySetAsSeries(USDplot,true);                       // indexation of array as a timeseries   
   ArrayInitialize(USDplot,EMPTY_VALUE);                 // zero values 
   f_draw("USD",Color_USD);                              // rendering in the indicator information window 
  }
SetIndexBuffer(15,USDx,INDICATOR_CALCULATIONS);          // array of dollar index for calculations
                                                         // (is not displayed in the indicator as a line) 
ArraySetAsSeries(USDx,true);                             // indexation of an array as a time series
ArrayInitialize(USDx,EMPTY_VALUE);                       // zero values

if(ind_type==Use_Stochastic_Main_on_indexes)
  {
   SetIndexBuffer(23,USDstoch,INDICATOR_CALCULATIONS);     // if the destination of the indicator as a Use_Stochastic_Main_on_indexes,
                                                           // then this intermediate array is needed
   ArraySetAsSeries(USDstoch,true);                        // indexation of array as a time series
   ArrayInitialize(USDstoch,EMPTY_VALUE);                  // zero values
  }
Para la divisa EUR, el código de la función OnInit es así:
if(USD)
  {
   countVal++;
   SetIndexBuffer(0,USDplot,INDICATOR_DATA);              // array for rendering
   PlotIndexSetString(0,PLOT_LABEL,"USDplot");            // name of the indicator line (when selected with a mouse)
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,shiftbars);      // from which we begin rendering
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE);       // drawing style (line)
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,Color_USD);      // color of line rendering
   if(StringFind(Symbol(),"USD",0)!=-1)
     {PlotIndexSetInteger(0,PLOT_LINE_WIDTH,wid_main);}   // if the symbol name contains USD 
                                                          // then draw a line of appropriate width 
   else
     {PlotIndexSetInteger(0,PLOT_LINE_STYLE,style_slave);}
   ArraySetAsSeries(USDplot,true);                        // indexation of array as a timeseries
   ArrayInitialize(USDplot,EMPTY_VALUE);                  // zero values 
   f_draw("USD",Color_USD);                               // rendering in the indicator information window 
  }
SetIndexBuffer(15,USDx,INDICATOR_CALCULATIONS);           // array of dollar index for calculations
                                                          // (is not displayed in the indicator as a line) 
ArraySetAsSeries(USDx,true);                              // indexation of an array as a time series
ArrayInitialize(USDx,EMPTY_VALUE);                        // zero values

if(ind_type==Use_Stochastic_Main_on_indexes)
  {
   SetIndexBuffer(23,USDstoch,INDICATOR_CALCULATIONS);    // if the destination of the indicator as a Use_Stochastic_Main_on_indexes,
                                                          // then this intermediate array is needed
   ArraySetAsSeries(USDstoch,true);                       // indexation of array as a time series
   ArrayInitialize(USDstoch,EMPTY_VALUE);                 // zero values
  }

if(EUR)
  {
   countVal++;
   SetIndexBuffer(1,EURplot,INDICATOR_DATA);              // array for rendering
   PlotIndexSetString(1,PLOT_LABEL,"EURplot");            // name of the indicator line (when pointed to with a mouse)
   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,shiftbars);      // which we begin rendering from
   PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_LINE);       // drawing style (lines)
   PlotIndexSetInteger(1,PLOT_LINE_COLOR,Color_EUR);      // the color of rendering lines
   if(StringFind(Symbol(),"EUR",0)!=-1)
     {PlotIndexSetInteger(1,PLOT_LINE_WIDTH,wid_main);}   // if the symbol name contains EUR
                                                          // then we draw a line of the appropriate width 
   else
     {PlotIndexSetInteger(1,PLOT_LINE_STYLE,style_slave);}// if the symbol name does NOT contain EUR,
                                                          // then we draw a line of an appropriate style (on the crosses)
   ArraySetAsSeries(EURplot,true);                        // indexation of the array as a time series
   ArrayInitialize(EURplot,EMPTY_VALUE);                  // zero values
   SetIndexBuffer(8,EURUSD,INDICATOR_CALCULATIONS);       // data of Close currency pair EURUSD
   ArraySetAsSeries(EURUSD,true);                         // indexation of the array as a time series
   ArrayInitialize(EURUSD,EMPTY_VALUE);                   // zero values
   SetIndexBuffer(16,EURx,INDICATOR_CALCULATIONS);        // array of the EURO index for calculations
                                                          // (not displayed on the indicator as a line) 
   ArraySetAsSeries(EURx,true);
   ArrayInitialize(EURx,EMPTY_VALUE);
   if(ind_type==Use_Stochastic_Main_on_indexes)
     {
      SetIndexBuffer(24,EURstoch,INDICATOR_CALCULATIONS); // if the indicator destination as a Use_Stochastic_Main_on_indexes,
                                                          // then this intermediate array is needed
      ArraySetAsSeries(EURstoch,true);                    // indexation of the array as a time series
      ArrayInitialize(EURstoch,EMPTY_VALUE);              // zero values
     }
   f_draw("EUR",Color_EUR);                               // rendering in the indicator information window
  }
Por analogía con el EUR, el código buscará divisas similares, como GBP, JPY, CHF, CAD, AUD, y NZD, cambiando los índices de los buffers de indicador. El código para estas divisas se puede encontrar en el archivo adjunto del indicador.

Con esto hemos completado la descripción de la inicialización del indicador.

A continuación, necesitaremos algunos elementos personalizados del usuario:

Descripción breve de cada uno de ellos:

Parámetros de entrada:

double f_RSI(double &buf_in[], int period,int shift),

donde buf_in[] - array de tipo doble (como series cronológicas), period - período de indicador RSI, shift - para cuya barra de índice calculamos el indicador. Devuelve un valor de tipo doble.

Parámetros de entrada:

double f_MACD(double &buf_in[], int period_fast,int period_slow,int shift),

donde buf_in[]  - array de tipo doble (como series cronológicas), period_fast - período de МА (Media Móvil) rápido, period_slow - período de МА lento, shift - para cuya barra de índice calculamos el indicador. Devuelve un valor de tipo doble.

Parámetros de entrada:

double SimpleMA(const int position,const int period,const double &price[]),

donde position - para cuya barra de índice calculamos el indicador. period - período de indicador SMA, price[] - array de tipo doble (como series cronológicas). Devuelve un valor de tipo doble.

Parámetros de entrada:

double f_Stoch(double &price[], int period_k, int shift),

donde price[] - array de tipo doble (como series cronológicas), period_fast - período de línea de indicador %K, shift - para cuya barra de índice calculamos el indicador. Devuelve un valor de tipo doble.

Parámetros de entrada:

int f_draw(string name, color _color)

donde name - nombre de objeto, _color - color de objecto. La función tiene propósitos informativos. Empezando por arriba en la esquina derecha de la ventana y yendo hacia abajo, esta función muestra los nombres de las divisas afectadas. El texto de la divisa tiene el mismo color que la línea del indicador que se refiere a esta divisa.

Parámetros de entrada:

int f_comment(string text)

text - El texto que se debe colocar en la esquina inferior derecha del indicador. Un tipo de barra de estado del trabajo del indicador.

Finalmente, la función de conclusión, y una de las más importantes:

Sin parámetros de entrada.

Se almacena en el historial de MetaTrader 5 en forma de datos por minuto de TF para cada herramienta. Por tanto, antes de ejecutar el programa se construyen todos los gráficos necesarios (afectados), basados en la misma información por minuto TF, una vez que se abre el terminal. La construcción también tiene lugar cuando el tráfico TF actual cambia, o durante un intento de acceso al gráfico del TF a través del código del programa MQL5.

Por tanto:

La primera parte de esta tarea se implementa usando la función Bars incorporada, que devuelve el número de barras en el historial con el período correspondiente al símbolo. Basta con usar la versión de esta función que se muestra abajo.

int  Bars(
   string          symbol_name,   // symbol name
   ENUM_TIMEFRAMES   timeframe    // period
   );

En esta función, especialmente anunciada para este array, recopilaremos el número de barras disponibles para todos los pares de divisas afectados. Comprobamos cada valor para la cantidad mínima necesaria de historial (la variable "número de barras para calcular el indicador" en los parámetros del indicador). Si el número de barras disponible en el historial de cualquier instrumento es menor al valor de esta variable, entonces consideraremos que la construcción no tuvo éxito, y reexaminaremos el número de datos disponibles. Una vez que hay más historial disponible para todos los pares de divisas de lo que solicitó el usuario, podremos considerar que esta parte de la inicialización se completó con éxito.

La segunda parte de la tarea de sincronización se realiza con la función CopyTime.

 Debemos copiar la apertura de una barra cero de cada instrumento afectado en un array especialmente creado para este propósito. Si todos los elementos de este array son iguales y no equivalen a 0, consideremos que nuestra barra cero está sincronizada, y empecemos con los cálculos. Para entender cómo se implementa esto con más detalle, vea el código del indicador adjunto.

Con esto terminamos con la descripción de funciones adicionales, y procederemos a implementar la función OnCalculate. Puesto que este es un indicador multidivisa, necesitaremos la segunda versión de la solicitud de esta función.

int OnCalculate(const int     rates_total, // size of incoming time series
                const int prev_calculated, // processing of bars on the previous request
                const datetime&    time[], // Time
                const double&      open[], // Open
                const double&      high[], // High
                const double&       low[], // Low
                const double&     close[], // Close
                const long& tick_volume[], // Tick Volume
                const long&      volume[], // Real Volume
                const int&       spread[]  // Spread
   );

Determine la cantidad de barras requeridas para el cálculo:

   int limit=shiftbars;

   if(prev_calculated>0)
     {limit=1;}
   else
     {limit=shiftbars;}

Sincronice gráficos de pares de divisas:

   init_tf();

A continuación, usando la función CopyClose, copiaremos los datos de Close de todos los pares de divisas necesarios en los buffers de indicador, registrados especialmente para ello. (Para más datos sobre el acceso a datos de otros TF de la herramienta actual y/o otras herramientas, puede ir a Help (Ayuda) )

Si, por cualquier motivo, la función no copió los datos y devolvió como respuesta -1, entonces nos llegará un mensaje de error del par de divisas en el comentario, y deberemos esperar a que llegue un nuevo tick para el instrumento actual.

   if (EUR){copied=CopyClose("EURUSD",PERIOD_CURRENT,0,shiftbars,EURUSD); if (copied==-1){f_comment("Wait...EURUSD");return(0);}}
   if (GBP){copied=CopyClose("GBPUSD",PERIOD_CURRENT,0,shiftbars,GBPUSD); if (copied==-1){f_comment("Wait...GBPUSD");return(0);}}
   if (CHF){copied=CopyClose("USDCHF",PERIOD_CURRENT,0,shiftbars,USDCHF); if (copied==-1){f_comment("Wait...USDCHF");return(0);}}
   if (JPY){copied=CopyClose("USDJPY",PERIOD_CURRENT,0,shiftbars,USDJPY); if (copied==-1){f_comment("Wait...USDJPY");return(0);}}
   if (AUD){copied=CopyClose("AUDUSD",PERIOD_CURRENT,0,shiftbars,AUDUSD); if (copied==-1){f_comment("Wait...AUDUSD");return(0);}}
   if (CAD){copied=CopyClose("USDCAD",PERIOD_CURRENT,0,shiftbars,USDCAD); if (copied==-1){f_comment("Wait...USDCAD");return(0);}}
   if (NZD){copied=CopyClose("NZDUSD",PERIOD_CURRENT,0,shiftbars,NZDUSD); if (copied==-1){f_comment("Wait...NZDUSD");return(0);}}  

Después, produciremos en el ciclo (de 0 al límite):

for (i=limit-1;i>=0;i--)
   {
      //calculation of USD index
      USDx[i]=1.0;
      if (EUR){USDx[i]+=EURUSD[i];}         
      if (GBP){USDx[i]+=GBPUSD[i];}
      if (CHF){USDx[i]+=1/USDCHF[i];}
      if (JPY){USDx[i]+=1/USDJPY[i];}
      if (CAD){USDx[i]+=1/USDCAD[i];}
      if (AUD){USDx[i]+=AUDUSD[i];}
      if (NZD){USDx[i]+=NZDUSD[i];}
      USDx[i]=1/USDx[i];
      //calculation of other currency values
      if (EUR){EURx[i]=EURUSD[i]*USDx[i];}
      if (GBP){GBPx[i]=GBPUSD[i]*USDx[i];}
      if (CHF){CHFx[i]=USDx[i]/USDCHF[i];}
      if (JPY){JPYx[i]=USDx[i]/USDJPY[i];}
      if (CAD){CADx[i]=USDx[i]/USDCAD[i];}
      if (AUD){AUDx[i]=AUDUSD[i]*USDx[i];}
      if (NZD){NZDx[i]=NZDUSD[i]*USDx[i];}
   }

Los datos se colocan en los buffers de indicador correspondientes. Compruebe qué tipo de indicador seleccionó el usuario durante la inicialización, y en base a ello, produzca cálculos relevantes.

Si se demostró un deseo de ver los RSI de los índices, ejecute el código de abajo:

if (ind_type==Use_RSI_on_indexes)
   {
      if (limit>1){ii=limit - rsi_period - 1;}
      else{ii=limit - 1;}
      for(i=ii;i>=0;i--)
         {
            if (USD){USDplot[i]=f_RSI(USDx,rsi_period,i);}
            if (EUR){EURplot[i]=f_RSI(EURx,rsi_period,i);}
            if (GBP){GBPplot[i]=f_RSI(GBPx,rsi_period,i);}
            if (CHF){CHFplot[i]=f_RSI(CHFx,rsi_period,i);}
            if (JPY){JPYplot[i]=f_RSI(JPYx,rsi_period,i);}
            if (CAD){CADplot[i]=f_RSI(CADx,rsi_period,i);}
            if (AUD){AUDplot[i]=f_RSI(AUDx,rsi_period,i);}
            if (NZD){NZDplot[i]=f_RSI(NZDx,rsi_period,i);}                  
         }
   }  

Si queremos ver el MACD por sus índices, vaya aquí (pero hasta ahora solo se implementa en base a SimpleMA, y se implementará en base a EMA después):

if (ind_type==Use_MACD_on_indexes)
   {
      if (limit>1){ii=limit - MACD_slow - 1;}
      else{ii=limit - 1;}
      for(i=ii;i>=0;i--)
         {
           if (USD){USDplot[i]=f_MACD(USDx,MACD_fast,MACD_slow,i);}
           if (EUR){EURplot[i]=f_MACD(EURx,MACD_fast,MACD_slow,i);}
           if (GBP){GBPplot[i]=f_MACD(GBPx,MACD_fast,MACD_slow,i);}
           if (CHF){CHFplot[i]=f_MACD(CHFx,MACD_fast,MACD_slow,i);}
           if (JPY){JPYplot[i]=f_MACD(JPYx,MACD_fast,MACD_slow,i);}
           if (CAD){CADplot[i]=f_MACD(CADx,MACD_fast,MACD_slow,i);}
           if (AUD){AUDplot[i]=f_MACD(AUDx,MACD_fast,MACD_slow,i);}
           if (NZD){NZDplot[i]=f_MACD(NZDx,MACD_fast,MACD_slow,i);}                  
         }
   } 

En el caso de Stochastis, primero debe calcular la línea % K, y después suavizarla con el método SimpleMA. La línea suavizada final se debe mostrar en el gráfico.

if (ind_type==Use_Stochastic_Main_on_indexes)
   {
      if (limit>1){ii=limit - stoch_period_k - 1;}
      else{ii=limit - 1;}
      for(i=ii;i>=0;i--)
         {
           if (USD){USDstoch[i]=f_Stoch(USDx,rsi_period,i);}
           if (EUR){EURstoch[i]=f_stoch(EURx,stoch_period_k,i);}
           if (GBP){GBPstoch[i]=f_stoch(GBPx,stoch_period_k,i);}
           if (CHF){CHFstoch[i]=f_stoch(CHFx,stoch_period_k,i);}
           if (JPY){JPYstoch[i]=f_stoch(JPYx,stoch_period_k,i);}
           if (CAD){CADstoch[i]=f_stoch(CADx,stoch_period_k,i);}
           if (AUD){AUDstoch[i]=f_stoch(AUDx,stoch_period_k,i);}
           if (NZD){NZDstoch[i]=f_stoch(NZDx,stoch_period_k,i);}                  
         }
      if (limit>1){ii=limit - stoch_period_sma - 1;}
      else{ii=limit - 1;}
      for(i=ii;i>=0;i--)
         {
            if (USD){USDplot[i]=SimpleMA(i,stoch_period_sma,USDstoch);}
            if (EUR){EURplot[i]=SimpleMA(i,stoch_period_sma,EURstoch);}
            if (GBP){GBPplot[i]=SimpleMA(i,stoch_period_sma,GBPstoch);}
            if (CHF){CHFplot[i]=SimpleMA(i,stoch_period_sma,CHFstoch);}
            if (JPY){JPYplot[i]=SimpleMA(i,stoch_period_sma,JPYstoch);}
            if (CAD){CADplot[i]=SimpleMA(i,stoch_period_sma,CADstoch);}
            if (AUD){AUDplot[i]=SimpleMA(i,stoch_period_sma,AUDstoch);}
            if (NZD){NZDplot[i]=SimpleMA(i,stoch_period_sma,NZDstoch);}                  
          }                     
   }       

Con esto hemos completado el cálculo de indicadores. Las Figuras 4-6 muestran diferentes tipos de indicadores.

Figura 4. RSI por los índices

Figura 4. RSI por los índices

Figura 5. MACD por los índices de divisas

Figura 5. MACD por los índices de divisas

Figura 6. Stochastis por los índices de divisas

Figura 6. Stochastis por los índices de divisas

Conclusión

Al implementar el indicador MultiCurrencyIndex, yo uso un número ilimitado de buffers de indicador en MQL5, lo que simplifica considerablemente el código. Este artículo es un ejemplo de tal maniobra. Para mostrar datos fiables de un indicador, he demostrado un algoritmo de sincronización de instrumentos diferentes relativos a la barra cero. También he demostrado uno de los posibles algoritmos para acceder a datos de otros instrumentos relativos al símbolo al cual se adjunta el indicador.

Puesto que el propósito del artículo era demostrar la posibilidad de trabajar con una gran cantidad de buffers de indicador, la función de arriba para calcular el indicador según los arrays de datos de los usuarios no era la mejor forma de evitar una sobrecarga en el ordenador. Pero ha sido suficiente para realizar los cálculos necesarios.

Hay muchas ventajas y desventajas de los análisis de conglomerados del mercado FOREX. Los sistemas de trading basados en este método son de acceso gratuito, y hay debates sobre él en varios foros, incluyendo la Comunidad MQL4. Por tanto, no hemos tratado los principios de trading con este indicador en este artículo.