MT4 iMAOnArray y iBandsOnArray efecto del número de elementos en los cálculos - página 2

 
Sergey Efimenko:
¿Qué quieres decir, qué espero? Escribí arriba, que necesito 300 últimos valores (actuales) reales, y no 300 primeros (iniciales), además, que accedo a un array en el offset 299-0, pero obtengo datos en el offset de los valores "array end" a "array end - 300" (en mi caso de 4999 a 4700), es decir, en el offset 299 está el valor que debería estar en el offset 4999 y de igual manera en el offset 0 está el valor, que debería estar en el offset 4700. La pregunta es: ¿para qué se calculan los valores antiguos, cuando no se calculan los valores actuales?

Si estuviera claro lo que has escrito, no habría preguntas.

double  iMAOnArray(
   double       array[],          // массив               // С этим понятно...
   int          total,            // количество элементов // Это у тебя 300
   int          ma_period,        // период               // Это ???
   int          ma_shift,         // сдвиг средней        // понятно
   int          ma_method,        // метод усреднения     // понятно
   int          shift             // сдвиг                // А здесь чему равна i???
   );

Se le pidió que mostrara una muestra de código, pero sólo mostró un fragmento de un ejemplo. Sobre el resto sólo se puede adivinar que está todo en el bucle. ¿A qué valor de i quieres obtener los últimos valores actuales? ¿En i = 4700 o dónde?

 
Alexey Viktorov:

Si estuviera claro en lo que escribiste, entonces no habría preguntas.

Se te pidió que mostraras un ejemplo de código y sólo mostraste un trozo de ejemplo. Sobre el resto sólo se puede adivinar que está todo en bucle. ¿A qué valor de i quieres obtener los últimos valores actuales? ¿En i = 4700 o dónde?

Si has utilizado estas funciones con limitación de longitud de matriz de cálculo en la práctica, entenderás lo que quiero decir, si no, ¿qué sentido tiene el razonamiento teórico...? ¿Y qué es lo que no está claro en mi trozo de código? He citado secciones absolutamente idénticas con la única diferencia de que en el primer caso no uso la limitación de longitud para el cálculo del array. En este caso no importa en absoluto el periodo de cálculo, la media de los turnos o el método de promediación, ya que son los mismos en ambos casos... El valor de shift, como escribí anteriormente, se utiliza de forma similar exactamente igual. Sustituye "i" por tu variable de desplazamiento en el bucle, sustituye la función GetValue(i) por al menos Open[i], haz que las tres matrices mencionadas sean 3 buffers de visualización del indicador y comprueba cómo funcionan la primera y la segunda. Sin embargo, aquí hay un ejemplo del código completo de la variante simple del indicador en dos variantes para una mejor comprensión del problema:

//esto funciona bien:
#property strict
#property indicator_separate_window
#property indicator_buffers 3
#property  indicator_color1 clrYellow
#property  indicator_color2 clrGreen
#property  indicator_color3 clrRed
double Buffer[],BufferMA[],BufferBMA[]; bool firstrun=true;
int init() { firstrun=true; SetIndexBuffer(0,Buffer); SetIndexBuffer(1,BufferMA); SetIndexBuffer(2,BufferBMA); return(0); }
int start() { int i,limit; int counted_bars=IndicatorCounted(); if(counted_bars<0) return(-1); if(counted_bars>0) counted_bars--; limit=Bars-counted_bars-1;
   if(firstrun) {ArrayInitialize(Buffer,Open[Bars-1]); ArrayInitialize(BufferMA,Open[Bars-1]); ArrayInitialize(BufferBMA,Open[Bars-1]); firstrun=false; }
   for(i=limit; i>=0; i--) { Buffer[i]=Open[i]; BufferMA[i]=iMAOnArray(Buffer,0,12,0,0,i); BufferBMA[i]=iBandsOnArray(Buffer,0,12,2,0,MODE_MAIN,i); }
return(0); }

//no funciona correctamente:

#property strict
#property indicator_separate_window
#property indicator_buffers 3
#property  indicator_color1 clrYellow
#property  indicator_color2 clrGreen
#property  indicator_color3 clrRed
double Buffer[],BufferMA[],BufferBMA[]; bool firstrun=true;
int init() { firstrun=true; SetIndexBuffer(0,Buffer); SetIndexBuffer(1,BufferMA); SetIndexBuffer(2,BufferBMA); return(0); }
int start() { int i,limit; int counted_bars=IndicatorCounted(); if(counted_bars<0) return(-1); if(counted_bars>0) counted_bars--; limit=Bars-counted_bars-1;
   if(firstrun) {ArrayInitialize(Buffer,Open[Bars-1]); ArrayInitialize(BufferMA,Open[Bars-1]); ArrayInitialize(BufferBMA,Open[Bars-1]); firstrun=false; }
   for(i=limit; i>=0; i--) { Buffer[i]=Open[i]; BufferMA[i]=iMAOnArray(Buffer,300,12,0,0,i); BufferBMA[i]=iBandsOnArray(Buffer,300,12,2,0,MODE_MAIN,i);  }
return(0); }

Después de dibujar los indicadores en el gráfico, vaya al principio (a la izquierda) del gráfico y mire el indicador 1 a partir de 12 barras, es el comienzo del llenado "no vacío" de 2 y 3 de la matriz, aproximadamente recuerde los primeros valores que difieren de 0, luego mueva el gráfico a las cotizaciones actuales y mire los valores a partir de 300 barras, así los valores del indicador 2 (abajo) serán iguales a los que vio al principio del gráfico del indicador 1, mientras que en idea los valores deben coincidir con los actuales. Espero haberlo explicado claramente. Además, si pones los gráficos en un gráfico en línea, el primero funcionará bien y el segundo se "colgará solo".

 
Sergey Efimenko:


No sólo el código no tiene estilo, sino que se inserta el código como texto plano. Por favor, introduzca el código correctamente.
 

Presentaré su código de forma más legible y con una nueva notación (de verdad, ¿cuánto tiempo más podremos utilizar ese anacrónico int start() en los indicadores?)

Indicador 1:

//+------------------------------------------------------------------+
//|                                                         Test.mq4 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 3
#property  indicator_color1 clrYellow
#property  indicator_color2 clrGreen
#property  indicator_color3 clrRed
double Buffer[];
double BufferMA[];
double BufferBMA[];
bool firstrun=true;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   firstrun=true;
   SetIndexBuffer(0,Buffer,INDICATOR_DATA);
   SetIndexBuffer(1,BufferMA,INDICATOR_DATA);
   SetIndexBuffer(2,BufferBMA,INDICATOR_DATA);
//---
   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 i,limit;
   limit=rates_total-prev_calculated-1;
   if(prev_calculated==0)
     {
      ArrayInitialize(Buffer,open[rates_total-1]);
      ArrayInitialize(BufferMA,open[rates_total-1]);
      ArrayInitialize(BufferBMA,open[rates_total-1]);
     }
   for(i=limit; i>=0; i--)
     {
      Buffer[i]=open[i];
      BufferMA[i]=iMAOnArray(Buffer,0,12,0,MODE_SMA,i);
      BufferBMA[i]=iBandsOnArray(Buffer,0,12,2,0,MODE_MAIN,i);
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+

Indicador 2:

//+------------------------------------------------------------------+
//|                                                         Test.mq4 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 3
#property  indicator_color1 clrYellow
#property  indicator_color2 clrGreen
#property  indicator_color3 clrRed
double Buffer[];
double BufferMA[];
double BufferBMA[];
bool firstrun=true;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   firstrun=true;
   SetIndexBuffer(0,Buffer,INDICATOR_DATA);
   SetIndexBuffer(1,BufferMA,INDICATOR_DATA);
   SetIndexBuffer(2,BufferBMA,INDICATOR_DATA);
//---
   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 i,limit;
   limit=rates_total-prev_calculated-1;
   if(prev_calculated==0)
     {
      ArrayInitialize(Buffer,open[rates_total-1]);
      ArrayInitialize(BufferMA,open[rates_total-1]);
      ArrayInitialize(BufferBMA,open[rates_total-1]);
     }
   for(i=limit; i>=0; i--)
     {
      Buffer[i]=open[i];
      BufferMA[i]=iMAOnArray(Buffer,300,12,0,MODE_SMA,i);
      BufferBMA[i]=iBandsOnArray(Buffer,300,12,2,0,MODE_MAIN,i);
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+

Y el resultado de la ejecución:

Resultado

о

Archivos adjuntos:
Test.mq4  3 kb
Test300.mq4  3 kb
 
Sergey Efimenko:

Si ha utilizado estas funciones

Si no lo hubiera hecho, no estaría haciendo preguntas para sugerir la solución adecuada.

¿De qué sirve tomar 300 barras si hay que calcular un periodo de 12? Aunque lo necesites "porque sí", debes entender cuáles serían los 12 elementos que intervienen en el cálculo de la media. Y la sugerencia sobre la dirección de la indexación del array era muy correcta.

Para entenderlo, haz experimentos con cálculos manuales en papel o en una calculadora, o en Excel.

 

Cuando miro las respuestas me doy cuenta de que sólo estoy perdiendo el tiempo aquí, tratando de mostrar la esencia del problema, y obteniendo como respuesta la "belleza" del código (gracias por supuesto, pero el código propuesto fue escrito en dos minutos sólo para mostrar la esencia del problema y no requiere ninguna legibilidad u otras conversiones)...

Y especialmente encantado con la respuesta anterior a mi post... ¿Qué calculadora, qué cálculos manuales, qué indexación? Estimados usuarios, por favor, comprendan la esencia de la situación para no perder no sólo su tiempo sino también el de otros. Por favor, vuelva a leer mis mensajes con cuidado, pero si es difícil, voy a responder brevemente: la dirección de la indexación de la matriz en ambos casos es correcta, el tamaño de los cálculos necesarios y otros parámetros cambiables, como se muestra en el código primario se establece con las variables externas, la variante de la creación de la propia función se discutió anteriormente (y en realidad es la única solución correcta), pero quiero repetir, quiero conseguirlo desde el built-in MT4.

En general gracias a todos, voy a resumir: o servicedesk o análogos propios de las funciones.

 

Y me desanima la respuesta antes de mi post...

Si eres tan cabezota, => servicedesk, y sólo responden a esas preguntas por aburrimiento, y rara vez se aburren.

Déjame intentarlo de nuevo...

iMAOnArray() toma, en su caso, 300 barras y calcula el valor medio de las últimas 12 barras de entre trescientas. Para promediar las primeras 12 barras, debe invertir la indexación del array, ArraySetAsSeries(BufferMA, false); o tomar sólo 12 barras.

BufferMA[i]=iMAOnArray(Buffer,12,12,0,MODE_SMA,i);

Así que resulta que en vez de intentar entender cómo funciona y cómo se usa, simplemente afirmaste que no funciona o que funciona mal. Y no es correcto en su opinión.

Lo siguiente es la belleza del código: ¿Crees que es interesante que alguien se rompa los ojos leyendo tu código cuando está todo escrito en una línea? No es así. No lo he leído personalmente. Gracias al pequeño baterista por su paciencia varias veces al día para dirigir a todos... al lugar equivocado.

 

Quise responder muy "detalladamente", pero luego, tras releer de nuevo los posts, borré mi respuesta, y finalmente me di cuenta de que sólo estaba perdiendo el tiempo aquí, explicando lo mismo varias veces con diferentes palabras...

PS Todas las gracias y realmente gracias "Barabashke" (Vladimir), lo hizo bien, pero toda esta situación no valía la pena su trabajo, voy a ser aún más agradecidos si no será difícil de hacer, una captura de pantalla en una clave anterior, la adición de una tercera opción y mostrando lo que sucedería si usted sigue el consejo de cambiar la dirección de la indexación. Para acabar con la cuestión de cómo funciona.

 
Sergey Efimenko:

Quise responder muy "detalladamente", pero luego, tras releer de nuevo los posts, borré mi respuesta, y finalmente me di cuenta de que sólo estaba perdiendo el tiempo aquí, explicando lo mismo varias veces con diferentes palabras...

PS Todas las gracias y realmente gracias "Barabashke" (Vladimir), lo hizo bien, pero toda esta situación no valía la pena su trabajo, voy a ser aún más agradecidos si no será difícil de hacer, una captura de pantalla en una clave anterior, la adición de una tercera opción y mostrando lo que sucedería si usted sigue el consejo de cambiar la dirección de la indexación. Para acabar con la cuestión de cómo funciona.

Opción 3:

//+------------------------------------------------------------------+
//|                                         Test300AsSeriesFalse.mq4 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 3
#property  indicator_color1 clrYellow
#property  indicator_color2 clrGreen
#property  indicator_color3 clrRed
double Buffer[];
double BufferMA[];
double BufferBMA[];
bool firstrun=true;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   firstrun=true;
   SetIndexBuffer(0,Buffer,INDICATOR_DATA);
   SetIndexBuffer(1,BufferMA,INDICATOR_DATA);
   SetIndexBuffer(2,BufferBMA,INDICATOR_DATA);
//---
   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[])
  {
//---
   ArraySetAsSeries(open,false);
//---
   int i,limit;
   limit=rates_total-prev_calculated-1;
   if(prev_calculated==0)
     {
      ArrayInitialize(Buffer,open[rates_total-1]);
      ArrayInitialize(BufferMA,open[rates_total-1]);
      ArrayInitialize(BufferBMA,open[rates_total-1]);
     }
   for(i=limit; i>=0; i--)
     {
      Buffer[i]=open[i];
      BufferMA[i]=iMAOnArray(Buffer,300,12,0,MODE_SMA,i);
      BufferBMA[i]=iBandsOnArray(Buffer,300,12,2,0,MODE_MAIN,i);
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+

Y el resultado global:

Opciones 1, 2 y 3

Archivos adjuntos:
 

No, Vladimir. Está un poco mal.

En este caso, debe aplicar ArraySetAsSeries(array, false); a un array de trescientos elementos entre los que se considera iMAOnArray(). Pero es mejor que usemos CopyOpen() en lugar del bucle de llenado del array.

Según tengo entendido, en esta variante será mejor

   for(i=limit; i>=0; i--)
     {
      Buffer[i]=open[i];
      BufferMA[i]=iMAOnArray(Buffer,12,12,0,MODE_SMA,i);
      BufferBMA[i]=iBandsOnArray(Buffer,12,12,2,0,MODE_MAIN,i);
     }