Desarrollo de un kit de herramientas para el análisis de la acción del precio (Parte 25): Rompefractales de doble EMA
Contenido
Introducción
El objetivo de este artículo es presentar el desarrollo de una herramienta diseñada para facilitar el análisis de la evolución de los precios, proporcionando una evaluación más profunda y detallada mediante el indicador Fractals, creado originalmente por Bill Williams.
Bill M. Williams (1932-2019) fue un influyente trader y autor estadounidense, reconocido por sus contribuciones a la psicología del trading, el análisis técnico y la teoría del caos en los mercados financieros. A lo largo de su carrera, Williams estudió los mercados de valores, materias primas y divisas (Forex), y desarrolló una serie de innovadoras herramientas de análisis técnico para identificar tendencias y posibles puntos de reversión. Entre sus indicadores más destacados se encuentran el oscilador acelerador/desacelerador, el indicador Alligator, el oscilador Awesome, el indicador Fractals, el oscilador Gator y el índice de facilitación del mercado. Hoy en día, estos indicadores se utilizan ampliamente en los mercados de divisas, de valores y otros mercados financieros por su eficacia a la hora de analizar el comportamiento del mercado.
El indicador de fractales, un componente clave de la metodología de Williams, se combina en nuestro enfoque con las medias móviles exponenciales (EMA) de 14 y 200 períodos. Al integrar los patrones fractales con estos filtros de tendencia dinámicos, nuestro Asesor Experto (EA) está diseñado para identificar con precisión posibles cambios de tendencia en el mercado, al tiempo que garantiza la alineación con la dirección general de la tendencia. Esta estrategia combinada mejora la toma de decisiones de inversión al permitir la detección temprana de señales de reversión y confirmar la fuerza de la tendencia, lo que en última instancia conduce a puntos de entrada más fiables y con mayor probabilidad de éxito. La sinergia entre el análisis fractal y las medias móviles proporciona a los operadores una poderosa herramienta para interpretar la acción del precio con mayor profundidad, lo que ayuda a optimizar el momento oportuno y a mejorar los resultados de las operaciones.
Comprender la estrategia
Nuestro asesor experto (EA) utiliza tres indicadores técnicos clave: el indicador Fractal, EMA 14 y EMA 200. El indicador fractal, desarrollado por Bill Williams, es una herramienta popular en el análisis técnico para identificar posibles cambios de tendencia. Detecta patrones de precios específicos, denominados fractales, que aparecen como máximos o mínimos locales, lo que indica posibles puntos de inflexión en el mercado. Estos fractales sirven como niveles de soporte o resistencia, proporcionando a los operadores señales visuales que les ayudan a determinar con mayor precisión el momento de entrada y salida.
La media móvil exponencial (EMA) se diferencia fundamentalmente de la media móvil simple (SMA) al asignar mayor peso a los datos de precios más recientes, lo que da como resultado un indicador más sensible. Esta ponderación se logra mediante un factor de suavizado que enfatiza exponencialmente los precios recientes, lo que permite que la EMA reaccione con mayor rapidez a los cambios del mercado. En consecuencia, las EMA son muy eficaces para detectar tendencias emergentes y proporcionar señales tempranas de cambios de tendencia, especialmente en períodos más cortos.
La EMA 14 refleja el impulso del mercado a corto plazo en nuestra estrategia, reaccionando rápidamente a los movimientos recientes de los precios, lo que la hace adecuada para entrar en el mercado en el momento oportuno. Por el contrario, la EMA 200 es un indicador de tendencia a largo plazo que suaviza las fluctuaciones a corto plazo para revelar la dirección general del mercado. Cuando el precio se sitúa por encima de la EMA 200, indica una tendencia alcista a largo plazo; cuando está por debajo, implica una tendencia bajista. Además, la EMA 200 suele actuar como un nivel dinámico de soporte o resistencia, lo que ayuda a los operadores a filtrar las señales falsas y confirmar la validez de la tendencia.
Señal de compra (ruptura alcista):
Se activa una señal de compra cuando se cumplen simultáneamente varias condiciones, lo que indica un fuerte movimiento alcista. En primer lugar, el EA monitoriza el nivel del fractal mínimo más reciente (nivel de soporte). Busca un escenario en el que el precio actual del mercado supere este nivel de soporte fractal, lo que indicaría una posible ruptura. Para confirmar que el mercado está en una tendencia alcista, el EA comprueba si el precio actual está por encima de la EMA 14 y la EMA 200; si la EMA 14 está por encima de la EMA 200, indica una tendencia alcista. Cuando se dan estas condiciones, se genera una señal de compra. En el gráfico se colocan señales visuales, como una flecha hacia arriba y una etiqueta, y se puede activar una alerta para notificar al operador.
- El precio cruza por encima del nivel de soporte fractal más reciente.
- El precio actual está por encima de la EMA 14 y la EMA 200.
- La EMA 14 se sitúa por encima de la EMA 200, lo que confirma una tendencia alcista.

Figura 1. Ruptura alcista
Señal de venta (ruptura bajista):
Por el contrario, se genera una señal de venta cuando el precio cruza por debajo de un máximo fractal significativo (nivel de resistencia), lo que indica un posible movimiento a la baja. El EA observa el máximo fractal más reciente y espera a que el precio de mercado rompa a la baja este nivel. Para verificar que el mercado tiene una tendencia a la baja, se confirma que el precio actual está por debajo de ambas EMA, con la EMA 14 por debajo de la EMA 200, lo que indica una tendencia bajista. Cuando se cumplen estos criterios, es decir, cuando el precio cruza por debajo del nivel fractal de resistencia mientras la tendencia sigue siendo bajista, se emite una señal de venta. Se muestran marcadores visuales similares, como flechas hacia abajo y etiquetas, y se pueden activar alertas.
- El precio cruza por debajo del nivel fractal de resistencia más reciente.
- El precio actual está por debajo de la EMA 14 y la EMA 200.
- La EMA 14 se sitúa por debajo de la EMA 200, lo que confirma una tendencia a la baja.

Figura 2. Ruptura bajista
Desglose de los componentes del código
Este asesor experto integra el análisis fractal con filtros de tendencia de media móvil para identificar y visualizar posibles puntos de ruptura en el mercado. Al trazar niveles horizontales en los máximos y mínimos fractales recientes, se marcan zonas críticas de soporte y resistencia. Cuando el precio cruza estos niveles en la dirección confirmada por la tendencia de la EMA, el EA genera señales visuales (flechas y etiquetas) y alertas sonoras, lo que simplifica el proceso de toma de decisiones del operador. Su diseño modular, con funciones dedicadas al dibujo, la señalización y la gestión de datos, lo hace adaptable a diversos estilos y preferencias de negociación. Además, el énfasis en la gestión de recursos y la limpieza garantiza la estabilidad y la claridad durante la operación. En definitiva, esta sofisticada combinación de indicadores y señales visuales proporciona una herramienta completa para los operadores que buscan aprovechar las oportunidades de ruptura fractal dentro de un entorno de tendencia.Encabezado y metadatos
La sección inicial del código contiene metadatos que describen la autoría, la versión y la información de licencia del script. Los comentarios incluidos entre //+------------------------------------------------------------------+ sirven para identificar el propósito del script y proporcionar la atribución. Las directivas #property especifican el titular de los derechos de autor, un hipervínculo al perfil del autor en la comunidad de MetaTrader, el número de versión y imponen normas de compilación estrictas. La directiva #property strict es especialmente importante, ya que indica al compilador que se atenga a normas de codificación más estrictas, detectando posibles errores como variables no declaradas o discrepancias de tipos. Estos metadatos y directivas no influyen en la lógica de ejecución, sino que sirven como documentación y garantizan la calidad del código durante la compilación.
//+------------------------------------------------------------------+ //| Fractal Breakout, EMA 14 and EMA 200| //| Copyright 2025, MetaQuotes Ltd.| //| https://www.mql5.com/en/users/lynnchris| //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com/en/users/lynnchris" #property version "1.0" #property strict
Parámetros de entrada
Esta sección define todos los parámetros configurables que un usuario puede modificar sin alterar el código principal. Estos parámetros incluyen el intervalo de tiempo para el análisis (InpTimeframe), el número de barras que se van a examinar (InpHistoryBars) y los períodos de las dos medias móviles exponenciales (EMA), que sirven como filtros de tendencia (InpEMA14Period e InpEMA200Period).
Los parámetros de color (InpBullColor e InpBearColor) permiten personalizar el aspecto de las flechas y las líneas que indican las rupturas. Las etiquetas de texto (InpBullText e InpBearText) proporcionan anotaciones descriptivas para las señales, lo que mejora la claridad del gráfico. El desplazamiento de la flecha (InpArrowOffset) y el tamaño de la fuente (InpArrowFontSize) ofrecen un mayor control sobre la presentación visual, lo que permite al operador colocar las etiquetas de forma cómoda.
El sistema de alertas se controla mediante InpAlertsEnabled, que activa o desactiva las notificaciones emergentes, y InpAlertSoundFile, que especifica el archivo de sonido que se reproduce al detectar una alerta. Estos parámetros hacen que el EA sea flexible y adaptable a diferentes estilos de negociación y preferencias visuales, lo que permite a los usuarios adaptarlo a sus necesidades específicas.
input ENUM_TIMEFRAMES InpTimeframe = PERIOD_CURRENT; // chart TF input int InpHistoryBars = 200; // bars back to scan input int InpEMA14Period = 14; // fast EMA input int InpEMA200Period = 200; // slow EMA input color InpBullColor = clrLime; // bullish arrow color input color InpBearColor = clrRed; // bearish arrow color input string InpBullText = "BULL Break"; // bullish label input string InpBearText = "BEAR Break"; // bearish label input int InpArrowOffset = 20; // offset in points for label input int InpArrowFontSize = 12; // size of the arrow glyph input bool InpAlertsEnabled = true; // show pop-up alerts input string InpAlertSoundFile = "alert.wav"; // sound file in /Sounds/
Variables globales e identificadores de indicadores
Las variables declaradas fuera de las funciones sirven como almacenamiento para los identificadores de indicadores y las matrices de datos fractales. Los identificadores (hFractals, hEMA14, hEMA200) son referencias a las instancias de los indicadores creadas durante la inicialización. Son esenciales porque permiten que el EA interactúe con los búferes de los indicadores, obteniendo datos históricos y en tiempo real. Las matrices fractalUp[] y fractalDown[] son búferes asignados dinámicamente que almacenarán los puntos máximos y mínimos del fractal, respectivamente. Al gestionarlas como variables globales, se garantiza que se pueda acceder a ellas en todo el script, especialmente durante el procesamiento OnTick, donde se lleva a cabo el análisis en tiempo real.
int hFractals, hEMA14, hEMA200; double fractalUp[], fractalDown[];
Inicialización (OnInit)
Durante el inicio, se invoca la función OnInit para configurar los recursos necesarios. Crea manejadores de indicadores para fractales y medias móviles exponenciales (EMA) utilizando funciones como iFractals e iMA, especificando el símbolo y el intervalo de tiempo. Es fundamental que la creación de estos identificadores se realice correctamente; si alguno de ellos no es válido (por ejemplo, debido a parámetros incorrectos o a datos no disponibles), la inicialización fallará, lo que impedirá que el EA se ejecute correctamente.
A continuación, el código configura las matrices de datos fractales para que funcionen como series, lo que significa que los datos más recientes estarán en el índice 0, lo que simplifica el análisis retrospectivo. Al redimensionar estas matrices al número de barras especificado, se garantiza que los búferes de datos tengan el tamaño adecuado para un procesamiento eficiente. En general, este paso sienta las bases para una recuperación fiable de los datos, lo cual es fundamental para una detección precisa de las rupturas.
int OnInit() { hFractals = iFractals(_Symbol, InpTimeframe); hEMA14 = iMA(_Symbol, InpTimeframe, InpEMA14Period, 0, MODE_EMA, PRICE_CLOSE); hEMA200 = iMA(_Symbol, InpTimeframe, InpEMA200Period,0, MODE_EMA, PRICE_CLOSE); if(hFractals==INVALID_HANDLE || hEMA14==INVALID_HANDLE || hEMA200==INVALID_HANDLE) return(INIT_FAILED); ArraySetAsSeries(fractalUp, true); ArraySetAsSeries(fractalDown, true); ArrayResize(fractalUp, InpHistoryBars); ArrayResize(fractalDown, InpHistoryBars); return(INIT_SUCCEEDED); }
Desinicialización (OnDeinit)
Cuando se elimina el EA del gráfico o se cierra la terminal, se ejecuta OnDeinit para liberar los recursos. Libera los identificadores de los indicadores mediante IndicatorRelease, lo que libera la memoria asociada y evita fugas. Además, recorre todos los objetos presentes en el gráfico, identificando y eliminando aquellos que comienzan por «FB_», que son las señales visuales (flechas, etiquetas, líneas) creadas durante el funcionamiento. Esta limpieza garantiza que no queden objetos residuales que saturen el gráfico una vez desactivado el EA, lo que permite mantener un entorno de gráficos ordenado y evita posibles conflictos o confusiones durante los análisis posteriores.
void OnDeinit(const int reason) { if(hFractals!=INVALID_HANDLE) IndicatorRelease(hFractals); if(hEMA14 !=INVALID_HANDLE) IndicatorRelease(hEMA14); if(hEMA200 !=INVALID_HANDLE) IndicatorRelease(hEMA200); for(int i=ObjectsTotal(0)-1; i>=0; i--) { string n = ObjectName(0,i); if(StringFind(n,"FB_")>=0) ObjectDelete(0,n); } }
Procesamiento principal (OnTick)
La lógica principal se encuentra en la función OnTick, que se ejecuta cada vez que llega un nuevo tick del mercado. Empieza por recuperar los últimos valores de las dos medias móviles exponenciales (EMA) mediante CopyBuffer. Estos valores de la media móvil exponencial (EMA) sirven como filtros de tendencia: su posición relativa indica si el mercado se encuentra en una tendencia alcista o bajista, lo que ayuda a tomar la decisión sobre una ruptura. Si falla la recuperación de datos de la EMA, la función se detiene prematuramente para evitar señales erróneas. A continuación, la función recupera los búferes de datos fractales tanto del fractal máximo como del mínimo más recientes, de nuevo con comprobación de errores. A continuación, el código recorre estos búferes hacia atrás para encontrar los fractales válidos más recientes, ignorando cualquier marcador de posición EMPTY_VALUEs. Al identificar los puntos fractales significativos más recientes, el EA determina los niveles críticos de soporte o resistencia que podrían desencadenar rupturas. A continuación, dibuja líneas horizontales en estos niveles como referencia visual, utilizando una función auxiliar. La información de depuración del terminal proporciona información en tiempo real sobre los niveles, los precios y los estados de la EMA, lo que ayuda a los operadores a verificar la lógica.
Finalmente, el EA comprueba las condiciones de ruptura: una ruptura bajista se produce cuando el cierre anterior estuvo por encima del nivel inferior, el cierre actual lo cruza por debajo y el precio está por debajo de ambas EMA en una tendencia bajista. Por el contrario, se reconoce una ruptura alcista cuando el cierre anterior estuvo por debajo del nivel superior, el cruce actual está por encima de este y el precio está por encima de ambas EMA en una tendencia alcista. La detección de estas condiciones activa la función de señalización.
void OnTick() { // 1) Read current EMAs double ema14Arr[1], ema200Arr[1]; if(CopyBuffer(hEMA14,0,0,1,ema14Arr)<=0 || CopyBuffer(hEMA200,0,0,1,ema200Arr)<=0) return; double ema14_now = ema14Arr[0]; double ema200_now = ema200Arr[0]; // 2) Read fractal history (skip current bar) if(CopyBuffer(hFractals,0,1,InpHistoryBars,fractalUp)<=0 || CopyBuffer(hFractals,1,1,InpHistoryBars,fractalDown)<=0) return; // 3) Find most recent valid fractals (ignore EMPTY_VALUE) int upShift=-1, downShift=-1; for(int i=1; i<InpHistoryBars; i++) { if(fractalUp[i] != EMPTY_VALUE && upShift<0) upShift = i+1; if(fractalDown[i] != EMPTY_VALUE && downShift<0) downShift = i+1; if(upShift>0 && downShift>0) break; } // 4) Levels double lvlUp = (upShift>0) ? fractalUp[upShift-1] : 0.0; double lvlDown = (downShift>0) ? fractalDown[downShift-1] : 0.0; // 5) Draw level lines DrawHLine("FB_LevelUp", lvlUp, InpBullColor); DrawHLine("FB_LevelDown", lvlDown, InpBearColor); // 6) DEBUG print double prevC = iClose(_Symbol,InpTimeframe,1); double currC = iClose(_Symbol,InpTimeframe,0); PrintFormat( "DBG lvlUp=%.5f lvlDown=%.5f prevC=%.5f currC=%.5f EMA14=%.5f EMA200=%.5f", lvlUp, lvlDown, prevC, currC, ema14_now, ema200_now ); // 7) Breakouts on the last closed candle (shift=1) // Bearish breakout detection if(lvlDown>0 && prevC>=lvlDown && currC<lvlDown && currC<ema14_now && currC<ema200_now && ema200_now>ema14_now) { Print(">>> Bear breakout triggered"); Signal(false, 1, lvlDown, ema14_now, ema200_now); } // Bullish breakout detection if(lvlUp>0 && prevC<=lvlUp && currC>lvlUp && currC>ema14_now && currC>ema200_now && ema14_now>ema200_now) { Print(">>> Bull breakout triggered"); Signal(true, 1, lvlUp, ema14_now, ema200_now); } }
Dibujar líneas horizontales (DrawHLine)
Esta función de utilidad gestiona la creación y actualización de líneas horizontales en el gráfico. Al invocarse, comprueba si existe una línea con el nombre especificado; si no, crea una nueva línea punteada en el nivel de precio dado con el color especificado. Si la línea ya existe, simplemente actualiza su posición. Este método evita la superposición de varias líneas y garantiza que los niveles visuales se mantengan actualizados con el análisis fractal más reciente. El estilo punteado ayuda a distinguir estas líneas de otros elementos del gráfico, enfatizando su función como niveles de soporte o resistencia. Estas señales visuales son de gran valor para los operadores, ya que permiten reconocer rápidamente las zonas de ruptura y facilitan la toma de decisiones, ya sea manual o automatizada.
void DrawHLine(string name, double price, color clr) { if(price<=0) return; if(ObjectFind(0,name)<0) { ObjectCreate(0,name,OBJ_HLINE,0,0,price); ObjectSetInteger(0,name,OBJPROP_COLOR,clr); ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_DOT); ObjectSetInteger(0,name,OBJPROP_WIDTH,1); } else ObjectSetDouble(0,name,OBJPROP_PRICE,price); }
Señalización y visualización (Signal)
La función Signal engloba todas las acciones relacionadas con la señalización de un evento de ruptura. Comienza por recuperar la marca de tiempo de la barra en la que se produjo la señal, lo que garantiza la colocación precisa de los objetos visuales. A continuación, crea un objeto de flecha en el nivel de ruptura, que apunta hacia arriba o hacia abajo dependiendo de si la tendencia es alcista o bajista, con un código de colores que coincide con la tendencia. La apariencia de la flecha se personaliza con parámetros de ancho y tamaño para mayor claridad. Junto a la flecha, se añade una etiqueta de texto ligeramente desplazada verticalmente, en la que aparece un mensaje descriptivo como «BULL Break» o «BEAR Break», lo que refuerza la señal visual.
La función registra un mensaje detallado en la pestaña «Expertos», que incluye la hora exacta, el nivel, el precio de cierre y los valores de la media móvil exponencial (EMA), lo que proporciona un registro completo de las señales. Si las alertas están activadas, aparece un mensaje emergente y se reproduce un archivo de sonido para avisar al operador de inmediato. Esta combinación de señales visuales, auditivas y basadas en registros garantiza que los operadores sean informados de inmediato de posibles oportunidades de ruptura, lo que les permite actuar a tiempo.
void Signal(bool isBull, int shift, double level, double ema14, double ema200) { datetime t = iTime(_Symbol,InpTimeframe,shift); double price = level; string side = isBull ? "Bull" : "Bear"; // Arrow string arrowName = StringFormat("FB_%sArrow_%d", side, (int)t); ObjectCreate(0, arrowName, OBJ_ARROW, 0, t, price); ObjectSetInteger(0, arrowName, OBJPROP_ARROWCODE, isBull?233:234); ObjectSetInteger(0, arrowName, OBJPROP_COLOR, isBull?InpBullColor:InpBearColor); ObjectSetInteger(0, arrowName, OBJPROP_WIDTH, 2); ObjectSetInteger(0, arrowName, OBJPROP_FONTSIZE, InpArrowFontSize); // Label string lab = arrowName + "_L"; double offset = (isBull ? InpArrowOffset : -InpArrowOffset) * _Point; ObjectCreate(0, lab, OBJ_TEXT, 0, t, price + offset); ObjectSetString(0, lab, OBJPROP_TEXT, isBull?InpBullText:InpBearText); ObjectSetInteger(0, lab, OBJPROP_COLOR, isBull?InpBullColor:InpBearColor); ObjectSetInteger(0, lab, OBJPROP_FONTSIZE, 11); // Log message string msg = StringFormat( "%s breakout at %s | Level=%.5f | Close=%.5f | EMA14=%.5f | EMA200=%.5f", side, TimeToString(t, TIME_DATE|TIME_SECONDS), level, iClose(_Symbol,InpTimeframe,shift), ema14, ema200 ); Print(msg); // Alert and sound if(InpAlertsEnabled) { Alert(msg); if(StringLen(InpAlertSoundFile)>0) PlaySound(InpAlertSoundFile); } }
Código MQL5
//+------------------------------------------------------------------+ //| Fractal Breakout, EMA 14 and EMA 200| //| Copyright 2025, MetaQuotes Ltd.| //| https://www.mql5.com/en/users/lynnchris| //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com/en/users/lynnchris" #property version "1.0" #property strict //---inputs input ENUM_TIMEFRAMES InpTimeframe = PERIOD_CURRENT; // chart TF input int InpHistoryBars = 200; // bars back to scan input int InpEMA14Period = 14; // fast EMA input int InpEMA200Period = 200; // slow EMA input color InpBullColor = clrLime; // bullish arrow color input color InpBearColor = clrRed; // bearish arrow color input string InpBullText = "BULL Break"; // bullish label input string InpBearText = "BEAR Break"; // bearish label input int InpArrowOffset = 20; // offset in points for label input int InpArrowFontSize = 12; // size of the arrow glyph input bool InpAlertsEnabled = true; // show pop-up alerts input string InpAlertSoundFile = "alert.wav"; // sound file in /Sounds/ //---indicator handles & buffers int hFractals, hEMA14, hEMA200; double fractalUp[], fractalDown[]; //+------------------------------------------------------------------+ //| Expert initialization | //+------------------------------------------------------------------+ int OnInit() { hFractals = iFractals(_Symbol, InpTimeframe); hEMA14 = iMA(_Symbol, InpTimeframe, InpEMA14Period, 0, MODE_EMA, PRICE_CLOSE); hEMA200 = iMA(_Symbol, InpTimeframe, InpEMA200Period,0, MODE_EMA, PRICE_CLOSE); if(hFractals==INVALID_HANDLE || hEMA14==INVALID_HANDLE || hEMA200==INVALID_HANDLE) return(INIT_FAILED); ArraySetAsSeries(fractalUp, true); ArraySetAsSeries(fractalDown, true); ArrayResize(fractalUp, InpHistoryBars); ArrayResize(fractalDown, InpHistoryBars); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { if(hFractals!=INVALID_HANDLE) IndicatorRelease(hFractals); if(hEMA14 !=INVALID_HANDLE) IndicatorRelease(hEMA14); if(hEMA200 !=INVALID_HANDLE) IndicatorRelease(hEMA200); for(int i=ObjectsTotal(0)-1; i>=0; i--) { string n = ObjectName(0,i); if(StringFind(n,"FB_")>=0) ObjectDelete(0,n); } } //+------------------------------------------------------------------+ //| Tick handler | //+------------------------------------------------------------------+ void OnTick() { // 1) Read current EMAs double ema14Arr[1], ema200Arr[1]; if(CopyBuffer(hEMA14,0,0,1,ema14Arr)<=0 || CopyBuffer(hEMA200,0,0,1,ema200Arr)<=0) return; double ema14_now = ema14Arr[0]; double ema200_now = ema200Arr[0]; // 2) Read fractal history (skip current bar) if(CopyBuffer(hFractals,0,1,InpHistoryBars,fractalUp)<=0 || CopyBuffer(hFractals,1,1,InpHistoryBars,fractalDown)<=0) return; // 3) Find most recent valid fractals (ignore EMPTY_VALUE) int upShift=-1, downShift=-1; for(int i=1; i<InpHistoryBars; i++) { if(fractalUp[i] != EMPTY_VALUE && upShift<0) upShift = i+1; if(fractalDown[i] != EMPTY_VALUE && downShift<0) downShift = i+1; if(upShift>0 && downShift>0) break; } // 4) Levels double lvlUp = (upShift>0) ? fractalUp[upShift-1] : 0.0; double lvlDown = (downShift>0) ? fractalDown[downShift-1] : 0.0; // 5) Draw level lines DrawHLine("FB_LevelUp", lvlUp, InpBullColor); DrawHLine("FB_LevelDown", lvlDown, InpBearColor); // 6) DEBUG print double prevC = iClose(_Symbol,InpTimeframe,1); double currC = iClose(_Symbol,InpTimeframe,0); PrintFormat( "DBG lvlUp=%.5f lvlDown=%.5f prevC=%.5f currC=%.5f EMA14=%.5f EMA200=%.5f", lvlUp, lvlDown, prevC, currC, ema14_now, ema200_now ); // 7) Breakouts on the last closed candle (shift=1) // Bearish breakout if(lvlDown>0 && prevC>=lvlDown && currC<lvlDown && currC<ema14_now && currC<ema200_now && ema200_now>ema14_now) { Print(">>> Bear breakout triggered"); Signal(false, 1, lvlDown, ema14_now, ema200_now); } // Bullish breakout if(lvlUp>0 && prevC<=lvlUp && currC>lvlUp && currC>ema14_now && currC>ema200_now && ema14_now>ema200_now) { Print(">>> Bull breakout triggered"); Signal(true, 1, lvlUp, ema14_now, ema200_now); } } //+------------------------------------------------------------------+ //| Draw or update a dotted HLine | //+------------------------------------------------------------------+ void DrawHLine(string name, double price, color clr) { if(price<=0) return; if(ObjectFind(0,name)<0) { ObjectCreate(0,name,OBJ_HLINE,0,0,price); ObjectSetInteger(0,name,OBJPROP_COLOR,clr); ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_DOT); ObjectSetInteger(0,name,OBJPROP_WIDTH,1); } else ObjectSetDouble(0,name,OBJPROP_PRICE,price); } //+------------------------------------------------------------------+ //| Plot arrow, label, log & alert | //+------------------------------------------------------------------+ void Signal(bool isBull, int shift, double level, double ema14, double ema200) { datetime t = iTime(_Symbol,InpTimeframe,shift); double price = level; string side = isBull ? "Bull" : "Bear"; // Arrow string arrowName = StringFormat("FB_%sArrow_%d", side, (int)t); ObjectCreate(0, arrowName, OBJ_ARROW, 0, t, price); ObjectSetInteger(0, arrowName, OBJPROP_ARROWCODE, isBull?233:234); ObjectSetInteger(0, arrowName, OBJPROP_COLOR, isBull?InpBullColor:InpBearColor); ObjectSetInteger(0, arrowName, OBJPROP_WIDTH, 2); ObjectSetInteger(0, arrowName, OBJPROP_FONTSIZE, InpArrowFontSize); // Label string lab = arrowName + "_L"; double offset = (isBull ? InpArrowOffset : -InpArrowOffset) * _Point; ObjectCreate(0, lab, OBJ_TEXT, 0, t, price + offset); ObjectSetString(0, lab, OBJPROP_TEXT, isBull?InpBullText:InpBearText); ObjectSetInteger(0, lab, OBJPROP_COLOR, isBull?InpBullColor:InpBearColor); ObjectSetInteger(0, lab, OBJPROP_FONTSIZE, 11); // Expert log string msg = StringFormat( "%s breakout at %s | Level=%.5f | Close=%.5f | EMA14=%.5f | EMA200=%.5f", side, TimeToString(t, TIME_DATE|TIME_SECONDS), level, iClose(_Symbol,InpTimeframe,shift), ema14, ema200 ); Print(msg); // Pop-up alert + optional sound if(InpAlertsEnabled) { Alert(msg); if(StringLen(InpAlertSoundFile)>0) PlaySound(InpAlertSoundFile); } } //+------------------------------------------------------------------+
Resultados
Para probar el EA, primero compile el código usando MetaEditor. Una vez compilado, puede aplicarlo a un gráfico en MetaTrader 5 para realizar pruebas en tiempo real o ejecutarlo directamente a través del Probador de Estrategias para realizar pruebas retrospectivas. He realizado pruebas de este Asesor Experto tanto en condiciones de mercado reales como en pruebas retrospectivas históricas. Este proceso es esencial para ajustar con precisión los parámetros del EA, lograr el comportamiento de negociación deseado y optimizar su rendimiento.
El gráfico de la imagen inferior muestra cómo el EA identifica un cambio significativo en el mercado utilizando indicadores fractales y EMA. En concreto, el EA detecta una ruptura fractal bajista en un nivel de soporte clave, que se marca visualmente en el gráfico. El movimiento de precios posterior confirma el cambio de tendencia, ya que el mercado continúa a la baja, alineándose con la tendencia de la EMA, donde la EMA 14 cruza por debajo de la EMA 200, lo que indica un cambio hacia una tendencia bajista. Las señales visuales, como el indicador "BEAR Break", facilitan la toma de decisiones disciplinadas al entrar y salir de la zona. Este resultado demuestra la capacidad del EA para reconocer los primeros indicios de un cambio de tendencia, lo que permite a los operadores aprovechar las oportunidades de alta probabilidad y evitar las señales falsas.

Figura 3. Rompimiento bajista en el índice Step
El GIF que aparece a continuación muestra el proceso de detección y confirmación en tiempo real de un cambio de tendencia por parte del EA. Destaca cómo el sistema de indicadores identifica un nivel de soporte o resistencia fractal y señala una posible ruptura, lo que lleva al operador a plantearse abrir una posición. A medida que el mercado se mueve en la dirección prevista, las señales del EA se ven confirmadas por la alineación de las medias móviles exponenciales (EMA); la EMA de 14 cruza por debajo de la EMA de 200, lo que confirma la tendencia bajista. Las señales visuales, como las flechas y las alertas, muestran cómo el EA facilita la toma de decisiones oportuna. Este ejemplo pone de relieve la importancia de la detección temprana, combinada con la confirmación de la tendencia, lo que refuerza la confianza a la hora de operar y reduce la probabilidad de entrar en el mercado de forma errónea.

Figura 4. Backtesting en V75 (1 s)
Conclusión
Este Asesor Experto aprovecha el potencial del indicador Fractals de Bill Williams, junto con medias móviles exponenciales a corto y largo plazo, para identificar puntos de entrada con alta probabilidad de éxito. Al combinar estas herramientas, detecta señales tempranas de cambio de tendencia que se confirman en relación con la tendencia predominante del mercado, lo que mejora la precisión y la coherencia en la ejecución de las operaciones. Las rigurosas pruebas retrospectivas y las pruebas en tiempo real han demostrado su flexibilidad en diversas condiciones de mercado y, una vez ajustados, sus parámetros pueden adaptarse para obtener un rendimiento óptimo. Gracias a sus flechas y etiquetas intuitivas en el gráfico, además de la ejecución de órdenes totalmente automatizada, este EA aporta disciplina y rapidez a tu rutina de trading. En esencia, ofrece un marco sistemático y basado en reglas para el análisis de la evolución de los precios, ideal para los operadores que buscan combinar el rigor técnico con la automatización.
Echa un vistazo a nuestras herramientas destacadas en la tabla que aparece a continuación.
| Chart Projector | Analytical Comment | Analytics Master | Analytics Forecaster | Volatility Navigator | Mean Reversion Signal Reaper |
| Signal Pulse | Metrics Board | External Flow | VWAP | Heikin Ashi | FibVWAP |
| RSI DIVERGENCE | Parabolic Stop and Reverse (PSAR) | Quarters Drawer Script | Intrusion Detector | TrendLoom Tool | Quarters Board |
| ZigZag Analyzer | Correlation Pathfinder | Market Structure Flip Detector Tool | Correlation Dashboard | Currency Strength Meter | PAQ Analysis Tool |
| Barra de pines, patrón envolvente y divergencia del RSI | Rompefractales de doble EMA |
Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/18297
Advertencia: todos los derechos de estos materiales pertenecen a MetaQuotes Ltd. Queda totalmente prohibido el copiado total o parcial.
Este artículo ha sido escrito por un usuario del sitio web y refleja su punto de vista personal. MetaQuotes Ltd. no se responsabiliza de la exactitud de la información ofrecida, ni de las posibles consecuencias del uso de las soluciones, estrategias o recomendaciones descritas.
Aprendizaje automático y Data Science (Parte 42): Pronóstico de series temporales de Forex con ARIMA en Python, todo lo que necesitas saber
Dominando los registros (Parte 7): Cómo mostrar los registros en un gráfico
Particularidades del trabajo con números del tipo double en MQL4
Características del Wizard MQL5 que debe conocer (Parte 67): Uso de patrones de TRIX y Williams Percent Range (WPR)
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso
Interesante artículo, y gracias por el código fuente de EA. Lo probaré y daré mi opinión.