English Русский 中文 Deutsch 日本語 Português
preview
Recordando una antigua estrategia de tendencia: dos osciladores estocásticos, MA y Fibonacci

Recordando una antigua estrategia de tendencia: dos osciladores estocásticos, MA y Fibonacci

MetaTrader 5Sistemas comerciales | 1 diciembre 2023, 12:17
832 0
Javier Santiago Gaston De Iriarte Cabrera
Javier Santiago Gaston De Iriarte Cabrera

Introducción a la estrategia

La estrategia es puramente técnica y usa varios indicadores y herramientas para ofrecer señales y niveles objetivo. Los componentes de la estrategia incluyen:

  • Un oscilador estocástico de 14 periodos.
  • Un oscilador estocástico de 5 periodos.
  • Una media móvil con un periodo 200.
  • Un proyección de Fibonacci (para fijar los niveles objetivo).

El oscilador estocástico es una popular herramienta de análisis técnico utilizada por tráders e inversores para medir el impulso y la fuerza del movimiento del precio de un instrumento financiero. Fue desarrollado por George Lane a finales de los años cincuenta del siglo pasado. El estocástico se limita a valores entre 0 y 100; se conocen por niveles de sobreventa (inclinación alcista) los valores próximos al límite inferior y por niveles de sobrecompra (inclinación bajista) los valores próximos al límite superior.

El oscilador estocástico de cinco periodos en el marco temporal diario se obtiene de la forma siguiente:

Stoch

donde High y Low son los precios más alto y más bajo de los últimos 5 días, respectivamente, mientras que %D es la media móvil de %K en N días (los últimos N valores de %K). Aunque suele ser una media móvil simple, también puede ser una media exponencial con una ponderación menos normalizada para los valores posteriores. Al trabajar exclusivamente con %D, solo hay una señal fiable: la discrepancia entre %D y el valor analizado.

Una media móvil es una herramienta estadística muy utilizada que ayuda a suavizar los datos de precio en un periodo temporal. Se usa ampliamente en diversos campos, como las finanzas, la economía y el procesamiento de señales. En el contexto de los mercados financieros, las medias móviles se usan con frecuencia en el análisis técnico para identificar tendencias y generar señales comerciales.

La media móvil se calcula utilizando la media de un conjunto de precios durante un periodo temporal y actualizando esta a medida que se dispone de nuevos datos. Cada vez que se añade un nuevo punto de datos, se elimina el más antiguo, con lo cual se obtiene una media "móvil" que refleja los precios más recientes.


Aplicación de la estrategia

Las reglas de la estrategia son las que siguen:

  • La señal de compra se genera siempre que ambos osciladores estocásticos alcancen simultáneamente un nivel de sobreventa, reboten y vuelvan a él (más o menos al mismo tiempo). Todo esto debería ocurrir mientras el mercado se encuentre por encima de la media móvil de 200 periodos. El primer nivel objetivo se establece usando una proyección de Fibonacci aplicada desde el mínimo de la primera vez que los osciladores estocásticos han tocado su fondo y el mínimo de la segunda vez que han tocado su fondo. Así, el primer objetivo será una proyección del 61,8% y el segundo del 100,0%.
  • La señal de venta se genera cuando ambos osciladores estocásticos alcancen simultáneamente un nivel de sobrecompra, reboten y vuelvan a él (más o menos al mismo tiempo). Todo ello mientras el mercado se encuentre por debajo de la media móvil de 200 periodos. El primer objetivo se fija usando la herramienta de proyección de Fibonacci, aplicada desde el máximo de la primera vez que los osciladores estocásticos han alcanzado su máximo y el máximo de la segunda vez que han alcanzado su máximo. Así, el primer objetivo será una proyección del 61,8% y el segundo del 100,0%.

(He modificado la estrategia para tener niveles stop en cada nivel de Fibonacci)

La siguiente figura muestra una señal bajista:

bearish


En última instancia, los resultados pueden variar de un mercado a otro y los resultados actuales pueden ser volátiles. Las estrategias funcionan en determinados periodos, pero pueden no resultar eficaces en otros.

La estrategia se detiene a la mitad del objetivo, de modo que se alcance una relación riesgo/recompensa de 2,0, o cuando el mercado rompa la línea de la media móvil.

En el trading, los niveles de corrección de Fibonacci son un método de análisis técnico para determinar los niveles de apoyo y resistencia. Recibe su nombre de la secuencia de números de Fibonacci, cuyos cocientes definen los niveles de precio a los que los mercados tienden a volver durante parte de un movimiento antes de que la tendencia continúe en la dirección original.

El pronóstico de la corrección de Fibonacci se crea utilizando dos puntos extremos del gráfico y dividiendo la distancia vertical por los coeficientes de Fibonacci. 0% se considera el comienzo de una corrección y 100% se considera un retroceso completo al precio original antes del movimiento. Las líneas horizontales se dibujan en el gráfico (no en este asesor) para estos niveles de precio, ofreciendo así los niveles de apoyo y resistencia.

Los niveles globales son 23,6%, 38,2%, 50% y 61,8%.


Resultados

Aunque se trata de una estrategia rentable, los resultados cambian de un mercado a otro y pueden ser volátiles. Las estrategias funcionan en determinados periodos, pero pueden no resultar eficaces en otros. Por favor, pruebe la estrategia antes de usarla y cambie los valores (como el marco temporal) según los mejores resultados.

Podemos usar el siguiente código para desplazar todos los datos 

   int Highest = iHighest(Symbol(),my_timeframe,MODE_CLOSE,shift,1);
   double High0=iHigh(Symbol(),my_timeframe,0);


   int Lowest = iLowest(Symbol(),my_timeframe,MODE_CLOSE,shift,1);
   double Low0=iLow(Symbol(),my_timeframe,0);

Pero para las pruebas, usaremos un valor de desplazamiento menor (por ejemplo, 300).

Estos son los resultados para el desplazamiento =300, marco temporal = 30 minutos, periodo - de 2013 a 2023 (20 de junio) y riesgo 2%.

Gráfico

data

En finanzas, el coeficiente de Sharpe (también conocido como índice de Sharpe o coeficiente recompensa/varianza) mide el rendimiento de una inversión, como un valor o un portafolio, en comparación con un activo sin riesgo, una vez ajustado su riesgo. Se define como la diferencia entre la rentabilidad de la inversión y la rentabilidad sin riesgo dividida por la desviación típica de la rentabilidad de la inversión. El ratio representa la cantidad adicional de rentabilidad que obtiene un inversor por unidad de aumento del riesgo.

sharpe



Código

En OnInit declararemos las características técnicas que vamos a utilizar, los manejadores:

void OnInit()
  {
   Stochastic_handle1 = iStochastic(_Symbol, PERIOD_CURRENT, Signal_0_Stoch_PeriodK, Signal_0_Stoch_PeriodD, Signal_0_Stoch_PeriodSlow, MODE_SMA, STO_LOWHIGH);
   Stochastic_handle2 = iStochastic(_Symbol, PERIOD_CURRENT, Signal_1_Stoch_PeriodK, Signal_1_Stoch_PeriodD, Signal_1_Stoch_PeriodSlow, MODE_SMA, STO_LOWHIGH);

//--- create handle of the indicator iMA
   handle_iMA=iMA(_Symbol,PERIOD_CURRENT,Inp_MA_ma_period,Inp_MA_ma_shift,
                  Inp_MA_ma_method,Inp_MA_applied_price);


//Test

   Alert("Expert Advisor has been launched");

  }

Este código crea un manejador del indicador Stochastic. El manejador se llama Stochastic_handle1. Para crearlo se utiliza la función iStochastic(). A la función se le transmiten los siguientes parámetros: el símbolo, el periodo actual, el periodo de la línea %K, el periodo de la línea %D, el periodo de la línea lenta, el modo de la línea lenta y el tipo de estocástico (bajo/alto).

Este código se usa para calcular la media móvil (MA) del símbolo actual con los parámetros especificados. La variable handle_iMA almacena el resultado del cálculo de MA. Los parámetros utilizados en el cálculo son el símbolo, el periodo actual, el periodo de MA, el desplazamiento de MA, el método de MA y el precio aplicado. El símbolo es la pareja de divisas o el valor para el que se calcula la MA. El periodo actual es el marco temporal del gráfico para el que se calcula la MA. El periodo de la MA es el número de barras utilizadas para calcular la MA. El desplazamiento de la MA es el número de barras en que se desplaza el cálculo de la MA. El método de la MA es el tipo de cálculo de MA, como simple, exponencial, suavizado o linealmente ponderado. El precio aplicado es el tipo de precio utilizado en el cálculo de la MA, por ejemplo Close (cierre), Open (apertura), High (máximo), Low (mínimo), Median (mediano), Typical (típico) o Weighted (ponderado).

Tendremos que introducir todos estos parámetros declarados desde fuera, y antes de OnInit.


En OnTick, los usaremos para obtener los valores de cada tick.

   MqlTick tick;
   SymbolInfoTick(_Symbol,tick);

Este código se utiliza para recuperar los datos de ticks de un carácter determinado. La primera línea declara una variable MqlTick llamada tick. La segunda línea llama a la función SymbolInfoTick(), que toma dos parámetros, el nombre del símbolo y la variable tick. La función obtiene los datos de ticks para el símbolo dado y los almacena en la variable tick.


Utilizaremos el siguiente código para modelar los niveles de corrección de Fibonacci:

int Highest = iHighest(Symbol(),my_timeframe,MODE_CLOSE,shift,1);
   double High0=iHigh(Symbol(),my_timeframe,0);


   int Lowest = iLowest(Symbol(),my_timeframe,MODE_CLOSE,shift,1);
   double Low0=iLow(Symbol(),my_timeframe,0);



   double highestValue = iHigh(Symbol(),my_timeframe,Highest);


   double lowestValue = iLow(Symbol(),my_timeframe,Lowest);
// Obtener el valor más alto y más bajo de la barra actual
   double currentHigh = High0;
   double currentLow = Low0;

// Obtener el valor más alto y más bajo de la barra anterior
   double previousHigh = highestValue;
   double previousLow = lowestValue;


   double level0s = currentHigh;
   double level1s = currentHigh - (currentHigh - previousLow) * 0.236;
   double level2s = currentHigh - (currentHigh - previousLow) * 0.382;
   double level3s = currentHigh - (currentHigh - previousLow) * 0.618;
   double level4s = previousLow;

   double level0b = currentLow;
   double level1b = currentLow + (-currentLow + previousHigh) * 0.236;
   double level2b = currentLow + (-currentLow + previousHigh) * 0.382;
   double level3b = currentLow + (-currentLow + previousHigh) * 0.618;
   double level4b = previousHigh;

Este código en MQL5 se usa para determinar los valores máximo y mínimo de un símbolo y periodo dados. Las dos primeras líneas del código asignan el valor más alto del símbolo y del periodo a la variable Highest, asignando el valor más alto del símbolo y del periodo en el desplazamiento dado=0 a la variable High0 (vela actual). Las dos líneas de código siguientes asignan el valor más bajo del símbolo y del periodo a la variable Lowest, asignando el valor más bajo del símbolo y del periodo con un desplazamiento dado=0 a la variable Low0.


Usaremos el desplazamiento para elegir cuántas velas miraremos hacia atrás.

Para la media móvil usaremos lo siguiente:

//---
   double array_ma[];
   ArraySetAsSeries(array_ma,true);
   int start_pos=0,count=3;
   if(!iGetArray(handle_iMA,0,start_pos,count,array_ma))
      return;

Este código se utiliza para obtener un array de medias móviles de un manejador. La primera línea declara el array array_ma, que se utilizará para almacenar las medias móviles. La segunda línea especifica el array como una serie. Las líneas tercera y cuarta declaran dos variables enteras start_pos y count, que se utilizarán para indicar la posición inicial y el número de elementos que se extraerán del manejador. La quinta línea utiliza la función iGetArray para obtener las medias móviles del manejador y almacenarlas en array_ma. La función retorna false si no se han podido obtener las medias móviles.

El código será el siguiente (más allá de OnInit)

bool iGetArray(const int handle,const int buffer,const int start_pos,
               const int count,double &arr_buffer[])
  {
   bool result=true;
   if(!ArrayIsDynamic(arr_buffer))
     {
      //if(InpPrintLog)
      PrintFormat("ERROR! EA: %s, FUNCTION: %s, this a no dynamic array!",__FILE__,__FUNCTION__);
      return(false);
     }
   ArrayFree(arr_buffer);
//--- reset error code
   ResetLastError();
//--- fill a part of the iBands array with values from the indicator buffer
   int copied=CopyBuffer(handle,buffer,start_pos,count,arr_buffer);
   if(copied!=count)
     {
      //--- if the copying fails, tell the error code
      //if(InpPrintLog)
      PrintFormat("ERROR! EA: %s, FUNCTION: %s, amount to copy: %d, copied: %d, error code %d",
                  __FILE__,__FUNCTION__,count,copied,GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated
      return(false);
     }
   return(result);
  }

Este código se usa para copiar una parte del búfer de indicador en un array. Admite cinco parámetros: manejador, búfer, posición inicial, contador y búfer de array. Primero comprueba si el búfer de array es dinámico y, si no lo es, muestra un mensaje de error. A continuación, restablece el código de error y copia el búfer en el búfer de array. Si la cantidad copiada no es igual al contador, se imprime un mensaje de error y se retorna false. En caso opuesto, true.


Código para mostrar los resultados en un gráfico:

   string text="";
   for(int i=0; i<count; i++)
      text=text+IntegerToString(i)+": "+DoubleToString(array_ma[i],Digits()+1)+"\n";
//---
   Comment(text);

Este código se usa para mostrar los valores de un array de tipo double en MQL5. El código comienza declarando una variable de cadena llamada «text» y asignándole una cadena vacía. A continuación, se utiliza un ciclo for para iterar el array, con la variable i utilizada como contador del ciclo. En cada iteración, el valor i se convierte en una cadena mediante IntegerToString(), mientras que el valor del array en ese índice se convierte en una cadena mediante DoubleToString(). La función Digits() se utiliza para determinar el número de decimales utilizados al convertir un valor double en una cadena. A continuación, los valores convertidos se concatenan en la cadena «text», a la que se añade un nuevo símbolo de cadena después de cada valor. Por último, se utiliza la función Comment() para imprimir la cadena «text».


Haremos lo mismo con ambos estocásticos.

Estableceremos las condiciones para que no haya más de una orden abierta a la vez:

   int total = PositionsTotal();

   if(total==0)
{
...code
}

   if(total>0)
{
...code
}

Para abrir órdenes, utilizaremos el código:

if(!trade.Buy(get_lot(tick.bid),_Symbol,tick.bid,newStopLossLevelb1,newTakeProfitLevelb2))
                 {
                  //--- failure message
                  Print("Buy() method failed. Return code=",trade.ResultRetcode(),
                        ". Code description: ",trade.ResultRetcodeDescription());
                 }
               else
                 {
                  Print("Buy() method executed successfully. Return code=",trade.ResultRetcode(),
                        " (",trade.ResultRetcodeDescription(),")");
                 }

Aquí usaremos Ticket.bid consistentemente, así como SL y TP. El TP será el máximo más alto del periodo de cambio, mientras que el SL será el mínimo de la vela actual.

Para cerrar una orden cuando el precio cruce la MA, utilizaremos el siguiente código:

if(rates[1].close >array_ma22[0])
           {

            trade.PositionClose(_Symbol,5);
            Print("cerro");
            return;
           }
         else
            return;

        }

Para cambiar los TP y SL, utilizaremos el código:

            //--- setting the operation parameters
            request.action  =TRADE_ACTION_SLTP; // type of trade operation
            request.position=position_ticket;   // ticket of the position
            request.symbol=position_symbol;     // symbol
            request.sl      =newStopLossLevelss;                  // Stop Loss of the position
            request.tp      =newTakeProfitLevelss;               // Take Profit of the position
            request.magic=Expert_MagicNumber;         // MagicNumber of the position
            //--- output information about the modification
            PrintFormat("Modify #%I64d %s %s",position_ticket,position_symbol,EnumToString(type));
            //--- send the request
            if(!OrderSend(request,result))
               PrintFormat("OrderSend error %d",GetLastError());  // if unable to send the request, output the error code
            //--- information about the operation
            PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);

No olvide utilizar el nivel de congelación y el nivel stop. Recuerde también cambiar tanto los TP como los SL, u obtendrá un error.

Hemos añadido niveles StopLoss a todos los niveles de Fibonacci, por lo que los resultados podrían diferir del inicio original. Después de leer este código, podrá modificarlo y cambiar estos niveles.


Conclusión

La estrategia presentada puede resultar rentable en algunos momentos, pero puede no ser eficaz en otras circunstancias. Durante la crisis de 2008-2014 y la crisis del Covid de 2020, la estrategia obtuvo malos resultados. 

La estrategia funciona bien en épocas sin crisis y en periodos de tendencia.

Produce un Ratio de Sharpe de alrededor de 4, lo cual significa que la estrategia es al menos fiable.

La estrategia puede utilizarse como complemento de otras.

Podrá modificarla como considere oportuno.

El objetivo del artículo es ayudar a comprender la estrategia presentada. Dicha estrategia no se ha diseñado para ser utilizada. El lector deberá aplicarla bajo su propia responsabilidad.

Le recomiendo que pruebe este robot en más marcos temporales y con otros símbolos.

Si se usan otros marcos temporales, es probable que los resultados sean distintos.

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

Archivos adjuntos |
2Stoch_1MA.mq5 (77.39 KB)
Teoría de categorías en MQL5 (Parte 13): Eventos del calendario con esquemas de bases de datos Teoría de categorías en MQL5 (Parte 13): Eventos del calendario con esquemas de bases de datos
El artículo analiza cómo se pueden incluir esquemas de bases de datos para la clasificación en MQL5. Vamos a repasar brevemente cómo los conceptos de esquema de base de datos pueden combinarse con la teoría de categorías para identificar información textual (cadenas) relevante para el comercio. La atención se centrará en los eventos del calendario.
Redes neuronales: así de sencillo (Parte 49): Soft Actor-Critic Redes neuronales: así de sencillo (Parte 49): Soft Actor-Critic
Continuamos nuestro análisis de los algoritmos de aprendizaje por refuerzo en problemas de espacio continuo de acciones. En este artículo, le propongo introducir el algoritmo Soft Astog-Critic (SAC). La principal ventaja del SAC es su capacidad para encontrar políticas óptimas que no solo maximicen la recompensa esperada, sino que también tengan la máxima entropía (diversidad) de acciones.
Analizamos PrintFormat() y tomamos ejemplos listos para usar Analizamos PrintFormat() y tomamos ejemplos listos para usar
El presente artículo resultará útil tanto a principiantes como a desarrolladores experimentados. En él veremos el funcionamiento de la función PrintFormat(), analizaremos ejemplos de formato string y escribiremos plantillas para enviar información diversa al registro del terminal.
Crear paneles gráficos en MQL5 es ahora más fácil Crear paneles gráficos en MQL5 es ahora más fácil
En este artículo, ofreceremos una guía sencilla y comprensible para cualquier usuario que quiera crear una de las herramientas más valiosas y útiles en el trading: un panel gráfico que facilite las tareas comerciales. Los paneles gráficos nos permiten ahorrar tiempo y centrarnos más en las operaciones en sí.