Descargar MetaTrader 5

Mostrar los niveles de soporte/resistencia

11 mayo 2016, 10:37
Slobodov Gleb
0
472

Introducción

El artículo trata sobre la detección e indicación de los niveles de soporte/resistencia en el programa MetaTrader 4. Basado en un algoritmo simple, el indicador adecuado y universal FindLevels, crea líneas soporte horizontal en el gráfico del símbolo. Puede verlo a continuación.


El artículo también aborda el tema de la creación de un indicador simple que pueda mostrar los resultados de diferentes periodos de tiempo en un espacio de trabajo. Puede ver un ejemplo a continuación.


El primer indicador muestra los niveles de soporte (líneas gruesas de color beige) basados en cotizaciones de 30-minutos. El segundo indicador iniciado en la misma ventana, muestra los niveles basados en un periodo de tiempo de 15-minutos (líneas finas discontinuas de color morado) sobre niveles de 30-minutos. Vea la sección "Interacción de indicadores" para más detalles.

Este artículo es una continuación del artículo sobre la creación de un script para detectar los niveles de soporte, pero con la diferencia de que este artículo se ha escrito para aquellos que tienen un niven más avanzado en programación, y utilizan la plataforma MetaTrader 4. Por eso se recomienda a los principiantes y a todos aquellos que crean que este artículo es complicado, que empiecen con el artículo Un método de escritura de los niveles de soporte/resistencia.


Revisión teórica

Aquí se va a describir el algoritmo para detectar los niveles de soporte/resistencia, que se realizarán más adelante en el indicador FindLevels. El nivel de soporte/resistencia es un valor de precio que no se puede cruzar debido a algunas fuerzas. Pueden ser fuerzas inducidas por marcas psicológicas, la influencia de grandes jugadores, o una gran cantidad de órdenes StopLoss en este área. Es evidente que las cotizaciones cruzarán esta lína con bastante menos frecuencia que otras líneas que no son de soporte. Puede ver la prueba de este hecho en muchos libros de trading.

Para aprovechar este hecho, hay que calcular la cantidad de las barras que cruzan cada precio. Esto es el resultado de los cálculos que se describen en el artículo anterior:



Los ejes horizontales de esta imagen son el precio; los ejes verticales marcan la cantidad de barras que cruzan el precio. El gráfico tiene muchos mínimos locales, como se puede ver en la imagen. Un mínimo local es un punto que pertenece al intervalo no-cero, y representa el mínimo de este intervalo. Ahora hay que seleccionar los mínimos locales según ciertas características.



Primero, hay que establecer una constante, MaxR, que es el radio del área. Si un mínimo local no es el mínimo que pertenece al radio del área MaxR, no es adecuado para la tarea. Segundo, hay que establecer el parámetro MaxCrossesLevel. Si el máximo de funciones varía del mínimo menos que del MaxCrossesLevel en el área MaxR, no se mostrará este mínimo local, ya que no es suficientemente importante. Este es el mecanismo para detectar los niveles de soporte/resistencia. Siguiendo este simple algoritmo, se escribirá el indicador.


Funciones auxiliares

Como se ha descrito arriba, el indicador FindLevels está diseñado para trabajar con cotizaciones de cualquier periodo de tiempo. El periodo de tiempo se establece por el usuario (la variable TimePeriod). Para más simplicidad del código, se establecerán dos funciones sencillas que no requieren explicaciones adicionales:


double prLow(int i)
  {
    return (iLow(NULL,TimePeriod,i));
  }
 
double prHigh(int i)
  {
    return (iHigh(NULL,TimePeriod,i));
  }
-->

Las funciones tercera y cuarta son necesarias para mostrar adecuadamente los niveles de soporte, su profundidad, color y modo de indicación, que dependerá del periodo de tiempo:


int Period2Int(int TmPeriod)
  {
    switch(TmPeriod)
      {
        case PERIOD_M1  : return(0);
        case PERIOD_M5  : return(1);
        case PERIOD_M15 : return(2);
        case PERIOD_M30 : return(3);
        case PERIOD_H1  : return(4);
        case PERIOD_H4  : return(5);
        case PERIOD_D1  : return(6);
        case PERIOD_W1  : return(7);
        case PERIOD_MN1 : return(8);
      }      
    return (0);
  }
 
string Period2AlpthabetString(int TmPeriod)
  {
    return(Alphabet[Period2Int(TmPeriod)]); 
  }
        



El sentido de establecer la función Period2AlphabetString() se describe en la sección de "Interacción de indicadores", y el uso de la función Period2Int() se aclarará en la siguiente sección.



Escritura del indicador

Se empezará con las variables externas, que ya están establecidas por el usuario:

extern int MaxLimit = 1000;
extern int MaxCrossesLevel = 10;
extern double MaxR = 0.001;
extern int TimePeriod = 0;
extern color LineColor = White;
extern int LineWidth = 0;
extern int LineStyle = 0;        


  • MaxLimit - la cantidad de barras de historial en uso;
  • MaxCrossedLevel – la diferencia mínima entre el máximo local y el mínimo local (ver la descripción detallada en la sección "Revisión teórica".
  • MaxR – el radio del área en el que se detecta el mínimo;
  • TimePeriod – el periodo de tiempo para detectar los niveles de soporte. Por defecto, es el periodo de tiempo de la ventana de asignación;
  • LineColor – el color de las líneas mostradas;
  • LineWidth – la profuncidad de la línea, por defecto 0.
  • LineStyle – el estilo de la línea, por defecto 0.

Si el usuario establece los valores del LineColor, LineWidth o LineStyle por defecto, durante el funcionamiento del proceso Init se cambiarán a otros que dependan del periodo de tiempo. De este modo, la vista de las líneas desde diferentes periodos de tiempo no serán idénticas y se podrán diferenciar con facilidad.

int init()
  {
    if(TimePeriod == 0)
        TimePeriod = Period();
 
    if(TimePeriod != 0 && LineWidth == 0)
        if(Period2Int(TimePeriod) - Period2Int(Period()) >= 0)
            LineWidth = Widths[Period2Int(TimePeriod) - Period2Int(Period())];
        else
          {
            LineWidth = 0;
            if(LineStyle == 0)
                LineStyle = STYLE_DASH;
          }
 
    if(TimePeriod != 0 && LineColor == White)
        LineColor = Colors[Period2Int(TimePeriod)];
 
    return(0);
  }



En la primera línea se establece el valor de TimePeriod si se ha establecido por defecto. Luego se determina la profundidad de la línea. Cuanto más en relación esté el valor de TimePeriod con el periodo de tiempo del gráfico (ventana de asignación), más profundas serán las líneas. Si el TimePeriod es menor que el periodo del gráfico, la profundidad de la línea será igual a 0 y será discontinua. Cada periodo de tiempo tiene su propio color.


La gama de Colores[] y Profundidad[] se definen de la siguiente manera:

color  Colors[] = {Red,Maroon, Sienna, OrangeRed, Purple,I ndigo,
                   DarkViolet, MediumBlue, DarkSlateGray};
int    Widths[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};


Se van a definir las variables restantes:

int CrossBarsNum[];
bool CrossBarsMin[];
double d1Num = 0.0, d2Num = 0.0;
datetime TMaxI = 0;


  • La gama de CrossBarsNum[] – la gama que indican la cantidad de barras para cada precio;
  • CrossBarsMin[] – la gama correspondiente al hecho de si la línea con el precio establecido es un mínimo local o no;
  • d1Num y d2Num – los precios mínimo y máximo que corresponden al intervalo de la barra desde 0 a MaxLimit;
  • TMaxI – indica el tiempo de la última barra procesada.
#define MaxLines 1000
string LineName[MaxLines];
int LineIndex = 0;



  • MaxLines – la cantidad máxima de líneas que se pueden crear;

  • LineName[] – la gama de sus nombres;

  • LineIndex – el índice de celdas vacías en la gama LineName[].


Pasemos a la función start():


int counted_bars = IndicatorCounted();
int limit = MathMin(Bars - counted_bars, MaxLimit);
 
double d1 = prLow(iLowest(NULL, TimePeriod, MODE_LOW, limit, 0));
double d2 = prHigh(iHighest(NULL, TimePeriod, MODE_HIGH, limit, 0));


Se calcula el límite variable utilizando la cantidad de barras que no se han cambiado desde la última búsqueda del indicador. d1 y d2 son el mínimo y el máximo del precio en el intertvalo de 0 al límite.

if(d1Num != d1 || d2Num != d2)
  {
    ArrayResize(CrossBarsNum, (d2 - d1)*10000);
    ArrayResize(CrossBarsMin, (d2 - d1)*10000);
 
    if(d1Num != d1 && d1Num != 0.0)
      {
        ArrayCopy(CrossBarsNum, CrossBarsNum, 0, (d1Num - d1)*10000);
        ArrayCopy(CrossBarsMin, CrossBarsMin, 0, (d1Num - d1)*10000);
      }
 
    d1Num = d1;
    d2Num = d2;
  }


Durante el funcionamiento del indicador, los espacios de precio cubiertos con las gamas CrossBarsNum[] y CrossBarsMin[] pueden cambiar. Cada vez que esto pasa, hay que incrementar la calidad de celdas en esta gama y moverlas a la derecha si es necesario. Suele pasar si las nuevas variables d1 y d2 no coinciden con las variables d1Num y d2Num, que se pueden hacer obtenido en el inicio anterior de la función start().

for(double d = d1; d <= d2; d += 0.0001)
  {
    int di = (d - d1)*10000;
    for(int i = 1; i < limit; i++)
        if(d > prLow(i) && d < prHigh(i))
            CrossBarsNum[di]++;
    if(Time[limit] != TMaxI&&TMaxI != 0)
        if(d > prLow(iBarShift(NULL, 0, TMaxI)) && 
           d < prHigh(iBarShift(NULL, 0, TMaxI)))
            CrossBarsNum[di]--;
  }
TMaxI = Time[limit] - 1;


Después de asegurar que las gamas encajan las dimensiones necesarias, se empieza a calcular las nuevas barras para cada precio y se incrementa el valor de CrossBarNum[] cuando la barra cruza el nivel del precio. Como hay barras nuevas apareciendo constantemente, las barras viejas se excluirán del intervalo [0 : límite]. Por este motivo, hay que comprobar cada tipo de barra y reducir el valor de CrossBarNum[] en caso de intersección. Luego se le asigna el tiempo de la última barra calculada a la variable Tmaxl.

double l = MaxR*10000;
for(d = d1 + MaxR; d <= d2 - MaxR; d += 0.0001)
  {
    di = (d - d1)*10000;
    if(!CrossBarsMin[di] && CrossBarsNum[ArrayMaximum(CrossBarsNum, 2*l, di - l)] - 
       CrossBarsNum[ArrayMinimum(CrossBarsNum, 2*l, di - l)] > MaxCrossesLevel &&
       CrossBarsNum[di] == CrossBarsNum[ArrayMinimum(CrossBarsNum, 2*l, di - l)] &&
       CrossBarsNum[di-1] != CrossBarsNum[ArrayMinimum(CrossBarsNum, 2*l, di - l)])
      {
        CrossBarsMin[di] = true;
        LineName[LineIndex] = Period2AlpthabetString(TimePeriod) + TimePeriod + "_" + d;
        ObjectCreate(LineName[LineIndex], OBJ_HLINE, 0, 0, d);
        ObjectSet(LineName[LineIndex], OBJPROP_COLOR, LineColor);
        ObjectSet(LineName[LineIndex], OBJPROP_WIDTH, LineWidth);
        ObjectSet(LineName[LineIndex], OBJPROP_STYLE, LineStyle);
        LineIndex++;
      }
    if(CrossBarsMin[di] && CrossBarsNum[di] != 
       CrossBarsNum[ArrayMinimum(CrossBarsNum, 2*l, di - l)])
      {
        CrossBarsMin[di] = false;
        ObjectDelete(Period2AlpthabetString(TimePeriod) + TimePeriod + "_" + d);
      }          
  }



Al final del proceso start(), se supervisa de nuevo la gama CrossBarsMin[] una vez más, para determinar los nuevos mínimos locales y borrar los antiguos, que no ya no son mínimos locales. Como es posible que haya más de un mínimo local (hay varios valores que coinciden en la gama CrossBarsMin[] y todos son mínimos locales), tenemos que elegir uno de ellos. Utilizaremos el mínimo local con el precio más bajo.



CrossBarsNum[di] == CrossBarsNum[ArrayMinimum(CrossBarsNum, 2*l, di - l)] &&
CrossBarsNum[di-1]!= CrossBarsNum[ArrayMinimum(CrossBarsNum, 2*l, di - l)]



No hay ninguna complicación a la hora de crear un objeto gráfico nuevo – línea horizontal. Establecemos las características para esta línea: la profundidad, el estilo, el color... que se ha diseñado previamente en el proceso. No hay ningúna complicación a la hora de eliminar los niveles que ya no se soportan. No hay nada que no quede claro: por qué y para qué utilizamos la función Period2AlpthabetString(TimePeriod) en el nombre del objeto. El siguiente párrafo descubre este tema, que se ha mencionado varias veces.



Interacción de indicadores

Como se mencionó al principio del artículo, el indicador FindLevels está diseñado para indicar los niveles de soporte de varios periodos de tiempo en un gráfico. Para conseguirlo, se necesita lo siguiente:

  1. Tiene que se posible iniciar el indicador varias veces, y el indicador debe tener los datos de entrada con el periodo de tiempo;

  2. Las líneas deben ser diferentes y se debe poder definir fácilmente el periodo de tiempo al que pertenece cada nivel de soporte;

  3. Todas las líneas deben trazarse tanto para un periodo largo como para uno corto.

El primer punto no causa ningún problema. No hay variables globales. Hay diferentes nombres de objetos gráficos para cada periodo de tiempo, ya que el periodo está en el nombre del objeto (por ejemplo, "f30_1.25600000", 30 es el periodo de tiempo), por lo que no habrá conflictos cuando se inicien varios indicadores.

El segundo punto se ha realizado con éxito, ya que cada línea tiene su color dependiendo del periodo (LineColor=Colors[Period2Int(TimePeriod)]).

Ahora queda el tercer punto. Es bastante lógico que, si una línea resulta ser la línea de soporte para un gráfico de 5-minutos, también será la línea de soporte para un gráfico de 30-minutos. Si el precio de estas líneas desciende y tienen la misma profundidad, ¡no se verán ninguna de las dos! Es por eso por lo que las líneas de diferentes periodos de tiempo deben tener una profundidad distinta. Se harán los niveles de soporte de los periodos de tiempo más largos y profundos, en lugar de los de las líneas con los periodos de tiempo más cortos. Tiene sentido, porque todas las líneas que pertenezcan a intervalos largos son más importantes.

Hay que establecer la prioridad adecuada para mostrar las líneas. Las más finas se deben mostrar al final y deben estar superpuestas a las finas, para que puedan verse claramente. En el programa MetaTrader 4, los objetos se muestran en orden alfabético. Por lo que es necesario que los nombres de las líneas de los periodos más largos aparezcan antes que los de las líneas de periodos más cortos. Por eso se ha creado la función que otorga una línea del alfabeto latino dependiendo del periodo:


string Period2AlpthabetString(int TmPeriod)
  {
    return (Alphabet[Period2Int(TmPeriod)]);
  }



El alfabeto es la gama de letras latinas en orden contrario. El nombre completo de cada nivel de soporte es el siguiente: Period2AlpthabetString(TimePeriod)+TimePeriod+"_"+d.

Para una mejor comprensión, voy a hacer referencia a la captura de pantalla del principio del artículo.


Resumen

La prueba del indicador mostró que funciona bien. Es fácil de utilizar porque puede mostrar los datos desde diferentes periodos de tiempo. El periodo de prueba mostró que es mejor si el indicador muestra 3-10 niveles de soporte para cada TimePeriod. Para conseguirlo, hay que seleccionar las entradas correspondientes MaxR y MaxCrossesLevel. Durante la prueba, MaxR varió de 0.0003 para los periodos de tiempo más cortos, a 0.002 para los más largos. MaxCrossesLevel varió de 3 a 20. Puede que sea de ayuda configurar el indicador, para que pueda mostrar cierta cantidad de los niveles de soporte más importantes, pero si se hace, haría el código más complicado. Creo que a los que les guste mi indicador, pueden hacerlo fácilmente ellos mismos.


Traducción del ruso hecha por MetaQuotes Software Corp.
Artículo original: https://www.mql5.com/ru/articles/1440

Archivos adjuntos |
FindLevels.mq4 (5.21 KB)
Un método de escritura de los niveles de soporte/resistencia Un método de escritura de los niveles de soporte/resistencia

Este artículo describe el proceso de crear un script simple para detectar los niveles de soporte/resistencia. Está escrito para principiantes, y tiene una explicación detallada de cada fase del proceso. Sin embargo, aunque el guión es muy simple, el artículo también será útil para traders más avanzados y para los usuarios de la plataforma MetaTrader 4. Contiene ejemplos de la exportación de datos en formato tabular, la importación de la tabla a Microsoft Excel, y la esquematización de gráficos para su futuro análisis más detallado.

Price Action. Automatización de la estrategia del patrón envolvente (Engulfing) Price Action. Automatización de la estrategia del patrón envolvente (Engulfing)

Este artículo describe el proceso de creación de un Asesor Experto para MetaTrader 4 basado en el patrón Engulfing, además del principio de reconocimiento del patrón, las reglas para colocar las órdenes pendientes y las órdenes Stop. Se proporcionan los resultados de la prueba y optimización.

Filtrado por Historial Filtrado por Historial

El artículo describe el uso del trading virtual como una parte integral del filtro del trade abierto.

Modelado de las recotizaciones en el Tester y análisis de estabilidad del Asesor Experto Modelado de las recotizaciones en el Tester y análisis de estabilidad del Asesor Experto

La recotización es una lacra para muchos Asesores Expertos, especialmente para aquellos que tienen condiciones más bien sensibles de entrada/salida de un trade. En el artículo, se ofrece una manera para controlar al Asesor Externo en la estabilidad de las recotizaciones.