Desarrollo de un kit de herramientas para el análisis de la acción del precio (Parte 17): Asesor experto TrendLoom Tool
Contenido
- Introducción
- Descripción general de la estrategia
- Implementación en MQL5
- Código MQL5
- Resultados
- Conclusión
Introducción
Los métodos de análisis de mercado y de confirmación de entrada difieren entre los analistas de tendencias. Muchos traders revisan múltiples marcos temporales como M1, M5 y M15 o H1, H4 y W1 para validar sus entradas y aumentar la confiabilidad de la señal. En lugar de cambiar los períodos de tiempo para medir la tendencia general, simplemente presiona un botón y recibes una actualización a tiempo o te actualizas automáticamente. ¿Alguna vez has visto una venta en un marco de tiempo inferior, has entrado en una operación y luego has abierto un gráfico en un marco de tiempo superior solo para descubrir una tendencia de compra?
TrendLoom Tool está diseñado para evitar ese problema. Cuenta con un panel con siete botones que representan varios estilos de negociación. Cada botón muestra tres marcos temporales que se analizan conjuntamente utilizando medias móviles para generar señales como COMPRAR, VENDER o NEUTRAL. Esta sólida herramienta proporciona actualizaciones de confirmación rápidas y se actualiza continuamente con señales relevantes a medida que se detectan.
Descripción general de la estrategia
TrendLoom Tool está estructurado como una interfaz gráfica (panel). El panel contiene siete botones, cada uno de los cuales corresponde a una estrategia comercial específica.- Enfoque a corto plazo (M1, M5, M15)
- Scalping/Intradía (M5, M15, H1)
- Operaciones de swing trading (M15, H1, H4)
- Operaciones con tendencias (H1, H4, D1)
- Confirmación de tendencia MTF (H1, H4, W1)
- Scalper corto/Tendencia media (M5, H1, D1)
- Tendencia a largo plazo (H1, D1, W1)
Veamos cómo el EA genera una señal de COMPRA, VENTA o NEUTRAL cuando se pulsa un botón.
- Recopilación de datos: Para cada uno de los tres marcos temporales (por ejemplo, M1, M5 y M15), el EA recupera el precio de cierre de la última vela completamente completada.
- Cálculo de la SMA: Para cada intervalo de tiempo, el EA calcula una media móvil simple (SMA) de 50 períodos. Este SMA actúa como referencia para el precio actual.
- Si el precio está por encima de la SMA, lo considera una señal alcista y le asigna un valor de +1.
- Si el precio está por debajo de la SMA, lo considera una señal bajista y le asigna un valor de -1.
- Cuando el precio es igual al SMA, la señal es neutral (0).
Combinación de las señales
- Las tres señales individuales (una de cada intervalo de tiempo) se suman.
- Determinación de la señal final:
- Si la suma es 2 o más, indica un fuerte impulso alcista. El EA devuelve una señal de «COMPRA».
- Si la suma es -2 o menos, indica un fuerte impulso bajista. El EA devuelve una señal de «VENTA».
- De lo contrario, las señales son mixtas o neutras, por lo que el EA devuelve «NEUTRAL».
Revisemos el siguiente diagrama para comprender mejor el proceso.

Figura 1. Diagrama de flujo
Implementación en MQL5
En la parte superior, verás los comentarios del encabezado y las definiciones de propiedades del EA. Estas líneas sirven como metadatos para la EA, especificando sus derechos de autor, versión y vinculándola a su fuente. La directiva #property strict se utiliza para aplicar reglas de compilación más estrictas, lo que ayuda a evitar errores comunes de codificación.
//+------------------------------------------------------------------+ //| TrendLoom EA.mq5 | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com/en/users/lynnchris" #property version "1.00" #property strict
A continuación, el código incluye varios archivos de encabezado que proporcionan controles de diálogo, botones, etiquetas y paneles. También incorpora controles de objetos de gráfico para mostrar texto en el gráfico. Esta inclusión modular permite al EA utilizar clases preconstruidas para la interfaz de usuario.
Estas incluyen librerías de referencia de directivas en la carpeta «Include» de tu MetaEditor. Los archivos de la subcarpeta Controls ofrecen clases integradas para cuadros de diálogo y botones. También ofrecen clases para etiquetas y paneles. Este diseño simplifica la creación de una interfaz interactiva sin necesidad de reescribir el código. El archivo de la subcarpeta ChartObjects (ChartObjectsTxtControls.mqh) permite mostrar texto dinámico en el gráfico.
#include <Controls/Dialog.mqh> #include <Controls/Button.mqh> #include <Controls/Label.mqh> #include <Controls/Panel.mqh> #include <ChartObjects/ChartObjectsTxtControls.mqh> // Adjusted include path (singular folder)
A continuación, se definen las constantes para la alineación del texto y un valor de color. Esta práctica mejora la claridad y la facilidad de mantenimiento del código.
#ifndef ALIGN_LEFT #define ALIGN_LEFT 0 #endif #ifndef ALIGN_CENTER #define ALIGN_CENTER 1 #endif #ifndef ALIGN_RIGHT #define ALIGN_RIGHT 2 #endif #define clrSilver 0xC0C0C0
El EA declara los parámetros de entrada que ajustan la apariencia y la posición del panel y sus botones. PanelX, PanelY y PanelWidth establecen la geometría del panel, mientras que las entradas de color definen el tema visual. Las dimensiones de los botones se controlan con btnWidth, btnHeight y btnSpacing, y el EA te permite personalizar tanto el diseño como los colores. Esta configuración ofrece flexibilidad para adaptar la interfaz de usuario a sus necesidades.
//---- Input parameters ----------------------------------------------- input int PanelX = 10; input int PanelY = 10; input int PanelWidth = 250; input int btnWidth = 220; input int btnHeight = 30; input int btnSpacing = 5; input color PanelBackgroundColor = clrDimGray; input color PanelHeaderColor = clrBlueViolet; input color ButtonBgColor = clrBlack; input color ButtonTextColor = clrBlueViolet; input color AnalysisTextColor = clrLime;
Las matrices almacenan los nombres y los textos de los botones, lo que hace que actualizar o añadir nuevos botones sea rápido y sencillo. Este diseño centraliza toda la información relacionada con los botones en un solo lugar, por lo que las modificaciones solo requieren pequeños ajustes. También mejora la coherencia en toda la interfaz de usuario y reduce la posibilidad de errores. El método ofrece flexibilidad para futuras mejoras y mantiene el código limpio y organizado.
//---- Button Names and Texts (7 analysis options) -------------------- string buttonNames[7] = { "btnShortTerm", "btnScalping", "btnSwing", "btnTrend", "btnMTFTrend", "btnShortScalper", "btnLongTerm" }; string buttonTexts[7] = { "Short Term Focus\n(M1, M5, M15)", "Scalping/Intraday\n(M5, M15, H1)", "Swing Trading\n(M15, H1, H4)", "Trend Trading\n(H1, H4, D1)", "MTF Trend Confirm\n(H1, H4, W1)", "Short Scalper/Mid Trend\n(M5, H1, D1)", "Long Term Trend\n(H1, D1, W1)" };
Las macros globales definen los nombres del encabezado del panel y la etiqueta de análisis. Estas macros garantizan la coherencia en todo el código y actúan como fuente única para estos identificadores. Al centralizar estos nombres, las actualizaciones de los componentes del panel se vuelven más fáciles y se reduce el riesgo de errores tipográficos. Este enfoque simplifica el mantenimiento y garantiza un código coherente y claro.
// Global object names for panel header and analysis label #define PANEL_BG "PanelBG" #define PANEL_HEADER "PanelHeader" #define ANALYSIS_LABEL "AnalysisResult"
A continuación, el código declara dos funciones auxiliares: GetSMA calcula la media móvil simple y AnalyzeTimeframes realiza un análisis de mercado en múltiples marcos temporales. Estas funciones constituyen la lógica central del análisis de mercado.
//--- Helper function declarations double GetSMA(string symbol, ENUM_TIMEFRAMES timeframe, int period, int shift); string AnalyzeTimeframes(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3);
La clase personalizada CTrendLoomPanel hereda de CAppDialog. Agrupa todos los elementos de la interfaz de usuario, como la etiqueta del encabezado, el panel principal, los botones y la etiqueta de resultados. Este diseño crea una interfaz modular que es más fácil de gestionar y ampliar.
Creación del panel
El método CreateTrendPanel crea primero una ventana de diálogo. A continuación, configura una etiqueta de encabezado con texto, color, tamaño y estilo de fuente personalizados. La alineación se establece mediante la función ObjectSetInteger.
bool CreateTrendPanel(const long chart, const string name, const int x1, const int y1, const int x2, const int y2) { if(!CAppDialog::Create(chart, name, 0, x1, y1, x2, y2)) { Print("Failed to create TrendLoom dialog."); return false; } if(!m_lblHeader.Create(0, "TrendLoomHeader", 0, 10, 10, x2 - x1 - 20, 30)) { Print("Failed to create header label."); return false; } m_lblHeader.Text("TrendLoom EA"); m_lblHeader.Color(PanelHeaderColor); m_lblHeader.FontSize(14); m_lblHeader.Font("Segoe UI"); Add(m_lblHeader); if(!ObjectSetInteger(0L, m_lblHeader.Name(), OBJPROP_ALIGN, (long)ALIGN_CENTER)) Print("Failed to set header alignment");
El método continúa creando el panel principal y calcula dinámicamente sus dimensiones. A continuación, crea cada botón y los coloca uno tras otro. Por último, se añade una etiqueta de resultados debajo de los botones para mostrar el resultado del análisis.
Gestión de eventos
El método OnEvent procesa las interacciones del usuario. Cuando se hace clic en un botón, se llama a AnalyzeTimeframes con los parámetros de marco temporal adecuados. El resultado del análisis se actualiza en el panel y se muestra una alerta.
bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if(sparam == "btnShortTerm") { string res = AnalyzeTimeframes(PERIOD_M1, PERIOD_M5, PERIOD_M15); string out = "Short Term Focus: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnScalping") { string res = AnalyzeTimeframes(PERIOD_M5, PERIOD_M15, PERIOD_H1); string out = "Scalping/Intraday: " + res; UpdateResults(out); Alert(out); return true; } // Additional conditions for other buttons return false; }
Actualización de la interfaz de usuario
El método UpdateResults actualiza la etiqueta de resultados con nuevos datos de análisis. A continuación, llama a ChartRedraw para que la información actualizada aparezca inmediatamente.
void UpdateResults(const string &result) { m_lblResults.Text("Analysis Result: " + result); ChartRedraw(); }
Funciones básicas de análisis
Cálculo de la media móvil simple (SMA)
La función GetSMA calcula la SMA creando un identificador de indicador con la función iMA. Copia los valores SMA del búfer del indicador y, a continuación, libera el identificador para liberar recursos.
double GetSMA(string symbol, ENUM_TIMEFRAMES timeframe, int period, int shift) { int handle = iMA(symbol, timeframe, period, 0, MODE_SMA, PRICE_CLOSE); if(handle == INVALID_HANDLE) { Print("Failed to create iMA handle for timeframe ", timeframe); return 0.0; } double sma[]; if(CopyBuffer(handle, 0, shift, 1, sma) <= 0) { Print("Failed to copy buffer for timeframe ", timeframe); IndicatorRelease(handle); return 0.0; } double result = sma[0]; IndicatorRelease(handle); return result; }
Análisis de múltiples marcos temporales
La función AnalyzeTimeframes recupera el precio de cierre y la SMA para tres marcos temporales y asigna una señal alcista cuando el precio supera la SMA o una señal bajista cuando cae por debajo. Suma las señales individuales para generar una recomendación final: COMPRAR cuando la suma es 2 o superior, VENDER cuando es -2 o inferior y NEUTRAL en los demás casos. Cada intervalo de tiempo se evalúa de forma independiente para obtener una visión equilibrada de las tendencias del mercado, mientras que el parámetro de cambio garantiza que solo se utilice la última vela completada para el análisis. La combinación de señales de múltiples marcos temporales reduce el impacto del ruido transitorio del mercado y el ajuste del período SMA refina aún más la sensibilidad de las señales de trading.
string AnalyzeTimeframes(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3) { int period = 50; int shift = 1; // last completed candle double price1 = iClose(_Symbol, tf1, shift); double sma1 = GetSMA(_Symbol, tf1, period, shift); int signal1 = (price1 > sma1) ? 1 : (price1 < sma1 ? -1 : 0); double price2 = iClose(_Symbol, tf2, shift); double sma2 = GetSMA(_Symbol, tf2, period, shift); int signal2 = (price2 > sma2) ? 1 : (price2 < sma2 ? -1 : 0); double price3 = iClose(_Symbol, tf3, shift); double sma3 = GetSMA(_Symbol, tf3, period, shift); int signal3 = (price3 > sma3) ? 1 : (price3 < sma3 ? -1 : 0); int sum = signal1 + signal2 + signal3; if(sum >= 2) return "BUY"; else if(sum <= -2) return "SELL"; else return "NEUTRAL"; }Las funciones del ciclo de vida de EA se encargan de la inicialización, la limpieza y el procesamiento de eventos. La función OnInit crea el panel utilizando los parámetros de entrada. Si falla la creación del panel, el EA devuelve un error de inicialización.
int OnInit() { if(!TrendPanel.CreateTrendPanel(0, "TrendLoom Panel", PanelX, PanelY, PanelX + PanelWidth + 20, PanelY + 400)) { Print("Failed to create TrendLoom Panel."); return INIT_FAILED; } return INIT_SUCCEEDED; }
La función OnDeinit limpia destruyendo el panel cuando se elimina el EA o se cierra el gráfico.
void OnDeinit(const int reason) { TrendPanel.Destroy(reason); }
Por último, la función OnChartEvent reenvía los eventos del gráfico al controlador de eventos del panel para que la interfaz siga respondiendo.
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { TrendPanel.ChartEvent(id, lparam, dparam, sparam); }
En MetaEditor, los archivos necesarios se almacenan en la carpeta «Include». Para acceder a los archivos especificados tal y como se muestra en el fragmento, consulte las subcarpetas tal y como se muestra en los diagramas siguientes. Esta organización garantiza que el compilador encuentre los archivos de control de cuadros de diálogo, botones, etiquetas y paneles en la carpeta Include/Controls, y los controles de objetos de gráficos en la carpeta Include/ChartObjects.
#include <Controls/Dialog.mqh> #include <Controls/Button.mqh> #include <Controls/Label.mqh> #include <Controls/Panel.mqh> #include <ChartObjects/ChartObjectsTxtControls.mqh> // Adjusted include path (singular folder)
Paso 1

Figura 2. Paso 1
Paso 2

Figura 3. Paso 2
Código MQL5
//+------------------------------------------------------------------+ //| TrendLoom EA.mq5 | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com/en/users/lynnchris" #property version "1.00" #property strict #include <Controls/Dialog.mqh> #include <Controls/Button.mqh> #include <Controls/Label.mqh> #include <Controls/Panel.mqh> #include <ChartObjects/ChartObjectsTxtControls.mqh> // Adjusted include path (singular folder) // Define alignment constants if not already defined #ifndef ALIGN_LEFT #define ALIGN_LEFT 0 #endif #ifndef ALIGN_CENTER #define ALIGN_CENTER 1 #endif #ifndef ALIGN_RIGHT #define ALIGN_RIGHT 2 #endif #define clrSilver 0xC0C0C0 //---- Input parameters ----------------------------------------------- input int PanelX = 10; // Top-left X coordinate of panel input int PanelY = 10; // Top-left Y coordinate of panel input int PanelWidth = 250; // Panel width (for longer text) input int btnWidth = 220; // Button width input int btnHeight = 30; // Button height input int btnSpacing = 5; // Spacing between buttons input color PanelBackgroundColor = clrDimGray; // Panel background color input color PanelHeaderColor = clrBlueViolet; // Panel header text color input color ButtonBgColor = clrBlack; // Button background color input color ButtonTextColor = clrBlueViolet; // Button text color input color AnalysisTextColor = clrLime; // Analysis result text color //---- Button Names and Texts (7 analysis options) -------------------- string buttonNames[7] = { "btnShortTerm", "btnScalping", "btnSwing", "btnTrend", "btnMTFTrend", "btnShortScalper", "btnLongTerm" }; string buttonTexts[7] = { "Short Term Focus\n(M1, M5, M15)", "Scalping/Intraday\n(M5, M15, H1)", "Swing Trading\n(M15, H1, H4)", "Trend Trading\n(H1, H4, D1)", "MTF Trend Confirm\n(H1, H4, W1)", "Short Scalper/Mid Trend\n(M5, H1, D1)", "Long Term Trend\n(H1, D1, W1)" }; // Global object names for panel header and analysis label #define PANEL_BG "PanelBG" #define PANEL_HEADER "PanelHeader" #define ANALYSIS_LABEL "AnalysisResult" //--- Helper function declarations double GetSMA(string symbol, ENUM_TIMEFRAMES timeframe, int period, int shift); string AnalyzeTimeframes(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3); //------------------------------------------------------------------------------ // CTrendLoomPanel class - A modern, modular panel for TrendLoom EA //------------------------------------------------------------------------------ class CTrendLoomPanel : public CAppDialog { private: CLabel m_lblHeader; CPanel m_panelMain; CButton m_btnShortTerm; CButton m_btnScalping; CButton m_btnSwing; CButton m_btnTrend; CButton m_btnMTFTrend; CButton m_btnShortScalper; CButton m_btnLongTerm; CLabel m_lblResults; public: // Create the TrendLoom Panel dialog bool CreateTrendPanel(const long chart, const string name, const int x1, const int y1, const int x2, const int y2) { if(!CAppDialog::Create(chart, name, 0, x1, y1, x2, y2)) { Print("Failed to create TrendLoom dialog."); return false; } // Create header label if(!m_lblHeader.Create(0, "TrendLoomHeader", 0, 10, 10, x2 - x1 - 20, 30)) { Print("Failed to create header label."); return false; } m_lblHeader.Text("TrendLoom EA"); m_lblHeader.Color(PanelHeaderColor); m_lblHeader.FontSize(14); m_lblHeader.Font("Segoe UI"); Add(m_lblHeader); // Set header text alignment to center using ObjectSetInteger if(!ObjectSetInteger(0L, m_lblHeader.Name(), OBJPROP_ALIGN, (long)ALIGN_CENTER)) Print("Failed to set header alignment"); // Create main panel background int panelBottom = 50 + (btnHeight + btnSpacing) * 7 + btnSpacing; if(!m_panelMain.Create(0, "TrendLoomPanel", 0, 10, 50, x2 - x1 - 10, panelBottom)) { Print("Failed to create main panel."); return false; } m_panelMain.Color(PanelBackgroundColor); m_panelMain.BorderType(BORDER_RAISED); m_panelMain.ColorBorder(clrSilver); Add(m_panelMain); // Starting coordinates for buttons int btnX = 20; // relative to dialog int btnY = 60; int buttonWidth = btnWidth; int buttonHeight = btnHeight; // Create each button with a modern look if(!m_btnShortTerm.Create(0, buttonNames[0], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnShortTerm.Text(buttonTexts[0]); m_btnShortTerm.Font("Segoe UI"); m_btnShortTerm.FontSize(12); m_btnShortTerm.Color(ButtonBgColor); Add(m_btnShortTerm); btnY += buttonHeight + btnSpacing; if(!m_btnScalping.Create(0, buttonNames[1], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnScalping.Text(buttonTexts[1]); m_btnScalping.Font("Segoe UI"); m_btnScalping.FontSize(12); m_btnScalping.Color(ButtonBgColor); Add(m_btnScalping); btnY += buttonHeight + btnSpacing; if(!m_btnSwing.Create(0, buttonNames[2], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnSwing.Text(buttonTexts[2]); m_btnSwing.Font("Segoe UI"); m_btnSwing.FontSize(12); m_btnSwing.Color(ButtonBgColor); Add(m_btnSwing); btnY += buttonHeight + btnSpacing; if(!m_btnTrend.Create(0, buttonNames[3], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnTrend.Text(buttonTexts[3]); m_btnTrend.Font("Segoe UI"); m_btnTrend.FontSize(12); m_btnTrend.Color(ButtonBgColor); Add(m_btnTrend); btnY += buttonHeight + btnSpacing; if(!m_btnMTFTrend.Create(0, buttonNames[4], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnMTFTrend.Text(buttonTexts[4]); m_btnMTFTrend.Font("Segoe UI"); m_btnMTFTrend.FontSize(12); m_btnMTFTrend.Color(ButtonBgColor); Add(m_btnMTFTrend); btnY += buttonHeight + btnSpacing; if(!m_btnShortScalper.Create(0, buttonNames[5], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnShortScalper.Text(buttonTexts[5]); m_btnShortScalper.Font("Segoe UI"); m_btnShortScalper.FontSize(12); m_btnShortScalper.Color(ButtonBgColor); Add(m_btnShortScalper); btnY += buttonHeight + btnSpacing; if(!m_btnLongTerm.Create(0, buttonNames[6], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnLongTerm.Text(buttonTexts[6]); m_btnLongTerm.Font("Segoe UI"); m_btnLongTerm.FontSize(12); m_btnLongTerm.Color(ButtonBgColor); Add(m_btnLongTerm); btnY += buttonHeight + btnSpacing; // Create results label below the buttons if(!m_lblResults.Create(0, "TrendResults", 0, btnX, btnY, btnX + buttonWidth, btnY + 30)) return false; m_lblResults.Text("Analysis Result: [Waiting for Input]"); m_lblResults.Font("Segoe UI"); m_lblResults.FontSize(12); m_lblResults.Color(AnalysisTextColor); Add(m_lblResults); // Set results text alignment to left using ObjectSetInteger if(!ObjectSetInteger(0L, m_lblResults.Name(), OBJPROP_ALIGN, (long)ALIGN_LEFT)) Print("Failed to set results alignment"); Show(); return true; } // Process events (button clicks) bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if(sparam == "btnShortTerm") { string res = AnalyzeTimeframes(PERIOD_M1, PERIOD_M5, PERIOD_M15); string out = "Short Term Focus: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnScalping") { string res = AnalyzeTimeframes(PERIOD_M5, PERIOD_M15, PERIOD_H1); string out = "Scalping/Intraday: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnSwing") { string res = AnalyzeTimeframes(PERIOD_M15, PERIOD_H1, PERIOD_H4); string out = "Swing Trading: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnTrend") { string res = AnalyzeTimeframes(PERIOD_H1, PERIOD_H4, PERIOD_D1); string out = "Trend Trading: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnMTFTrend") { string res = AnalyzeTimeframes(PERIOD_H1, PERIOD_H4, PERIOD_W1); string out = "MTF Trend Confirm: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnShortScalper") { string res = AnalyzeTimeframes(PERIOD_M5, PERIOD_H1, PERIOD_D1); string out = "Short Scalper/Mid Trend: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnLongTerm") { string res = AnalyzeTimeframes(PERIOD_H1, PERIOD_D1, PERIOD_W1); string out = "Long Term Trend: " + res; UpdateResults(out); Alert(out); return true; } return false; } bool ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { return OnEvent(id, lparam, dparam, sparam); } // Update the results label and refresh the chart void UpdateResults(const string &result) { m_lblResults.Text("Analysis Result: " + result); ChartRedraw(); } }; // Global instance of the TrendLoom Panel CTrendLoomPanel TrendPanel; //------------------------------------------------------------------------------ // Helper functions (core analysis logic) //------------------------------------------------------------------------------ double GetSMA(string symbol, ENUM_TIMEFRAMES timeframe, int period, int shift) { int handle = iMA(symbol, timeframe, period, 0, MODE_SMA, PRICE_CLOSE); if(handle == INVALID_HANDLE) { Print("Failed to create iMA handle for timeframe ", timeframe); return 0.0; } double sma[]; // dynamic array to store SMA values if(CopyBuffer(handle, 0, shift, 1, sma) <= 0) { Print("Failed to copy buffer for timeframe ", timeframe); IndicatorRelease(handle); return 0.0; } double result = sma[0]; IndicatorRelease(handle); return result; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string AnalyzeTimeframes(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3) { int period = 50; int shift = 1; // last completed candle double price1 = iClose(_Symbol, tf1, shift); double sma1 = GetSMA(_Symbol, tf1, period, shift); int signal1 = (price1 > sma1) ? 1 : (price1 < sma1 ? -1 : 0); double price2 = iClose(_Symbol, tf2, shift); double sma2 = GetSMA(_Symbol, tf2, period, shift); int signal2 = (price2 > sma2) ? 1 : (price2 < sma2 ? -1 : 0); double price3 = iClose(_Symbol, tf3, shift); double sma3 = GetSMA(_Symbol, tf3, period, shift); int signal3 = (price3 > sma3) ? 1 : (price3 < sma3 ? -1 : 0); int sum = signal1 + signal2 + signal3; if(sum >= 2) return "BUY"; else if(sum <= -2) return "SELL"; else return "NEUTRAL"; } //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { if(!TrendPanel.CreateTrendPanel(0, "TrendLoom Panel", PanelX, PanelY, PanelX + PanelWidth + 20, PanelY + 400)) { Print("Failed to create TrendLoom Panel."); return INIT_FAILED; } return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { TrendPanel.Destroy(reason); } //+------------------------------------------------------------------+ //| Chart Event Handler | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { TrendPanel.ChartEvent(id, lparam, dparam, sparam); } //+------------------------------------------------------------------+
Resultados
Es de vital importancia que todos los operadores prueben exhaustivamente sus sistemas antes de utilizarlos en operaciones reales. Las pruebas implican realizar pruebas retrospectivas con datos históricos para ver cómo habría funcionado el sistema sin arriesgar ningún capital. También puede utilizar cuentas demo en vivo para observar el rendimiento real en tiempo real. Este proceso le ayuda a perfeccionar y desarrollar una herramienta más fiable que podrá utilizar con confianza en una cuenta real. Personalmente, prefiero dedicar mucho tiempo a probar y perfeccionar el EA para obtener resultados más sólidos.
En esta sección, presento los resultados de las pruebas del EA ejecutado en el gráfico. Lo probé con una volatilidad de 75 (1s) y obtuvo resultados maravillosos y rentables. Todos los botones funcionan correctamente y los análisis se actualizan casi al instante cuando pulsas un botón. Repasemos la primera prueba a continuación.

Figura 4. Prueba de volatilidad 75 (1s)
A continuación se muestra un diagrama que ilustra cómo se comportó el mercado tras ejecutar una operación basada en la señal proporcionada. Este diagrama continúa la operación mostrada en el GIF anterior. Utilicé el marco temporal M1 para ofrecer una visión más amplia de las operaciones.

Figura 5. Prueba de volatilidad 75 (1s)
Conclusión
Tras haber creado y probado el EA, puedo confirmar con total seguridad que tiene un impacto positivo en el análisis del mercado. Su rápido procesamiento de señales y su evaluación general de tendencias han producido resultados muy potentes en los índices de volatilidad. Sin embargo, esta herramienta sirve como ayuda complementaria y no como proveedor definitivo de señales. Te recomiendo que lo pruebes a fondo y ajustes los parámetros según tus preferencias. También puedes modificarlo aún más para personalizar la apariencia de los botones. Úsalo para confirmar tu estrategia general, he visto que es eficaz en ese sentido.
| Fecha | Nombre de la herramienta | Descripción | Versión | Actualizaciones | Notas |
|---|---|---|---|---|---|
| 01/10/24 | Chart Projector | Script para superponer la acción del precio del día anterior con efecto fantasma. | 1.0 | Lanzamiento inicial | Herramienta número 1 |
| 18/11/24 | Analytical Comment | Proporciona información del día anterior en formato tabular y anticipa la dirección futura del mercado. | 1.0 | Lanzamiento inicial | Herramienta número 2 |
| 27/11/24 | Analytics Master | Actualización periódica de las métricas del mercado cada dos horas. | 1.01 | Segundo lanzamiento | Herramienta número 3 |
| 02/12/24 | Analytics Forecaster | Actualización periódica de las métricas del mercado cada dos horas con integración de Telegram. | 1.1 | Tercera edición | Herramienta número 4 |
| 09/12/24 | Volatility Navigator | EA que analiza las condiciones del mercado utilizando los indicadores Bandas de Bollinger, RSI y ATR. | 1.0 | Lanzamiento inicial | Herramienta número 5 |
| 19/12/24 | Mean Reversion Signal Reaper | Analiza el mercado utilizando la estrategia de reversión a la media y proporciona señales. | 1.0 | Lanzamiento inicial | Herramienta número 6 |
| 09/01/25 | Signal Pulse | Analizador de múltiples marcos temporales. | 1.0 | Lanzamiento inicial | Herramienta número 7 |
| 17/01/25 | Metrics Board | Panel con botón para análisis. | 1.0 | Lanzamiento inicial | Herramienta número 8 |
| 21/01/25 | External Flow | Análisis mediante librerías externas. | 1.0 | Lanzamiento inicial | Herramienta número 9 |
| 27/01/25 | VWAP | Volume Weighted Average Price (Precio medio ponderado por volumen). | 1.3 | Lanzamiento inicial | Herramienta número 10 |
| 02/02/25 | Heikin Ashi | Suavización de tendencias e identificación de señales de reversión. | 1.0 | Lanzamiento inicial | Herramienta número 11 |
| 04/02/25 | FibVWAP | Generación de señales mediante análisis de Python. | 1.0 | Lanzamiento inicial | Herramienta número 12 |
| 14/02/25 | RSI DIVERGENCE | Acción del precio frente a divergencias del RSI. | 1.0 | Lanzamiento inicial | Herramienta número 13 |
| 17/02/25 | Parabolic Stop and Reverse (PSAR) | Automatización de la estrategia PSAR. | 1.0 | Lanzamiento inicial | Herramienta número 14 |
| 20/02/25 | Quarters Drawer Script | Dibuja los niveles de los cuartos en el gráfico. | 1.0 | Lanzamiento inicial | Herramienta número 15 |
| 27/02/25 | Intrusion Detector | Detectar y alertar cuando el precio alcanza niveles de cuartos. | 1.0 | Lanzamiento inicial | Herramienta número 16 |
| 27/02/25 | TrendLoom Tool | Panel de análisis de múltiples marcos temporales. | 1.0 | Lanzamiento inicial | Herramienta número 17 |
Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/17329
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.
Utilizando redes neuronales en MetaTrader
Desarrollo de un kit de herramientas para el análisis de la acción del precio (Parte 16): Introducción a la teoría de los cuartos (II) - Intrusion Detector EA
Particularidades del trabajo con números del tipo double en MQL4
Un nuevo enfoque para los criterios personalizados en las optimizaciones (Parte 1): Ejemplos de funciones de activación
- 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
Wow Fantástico, puedo ver que hay un montón de esfuerzo puesto en esto, gracias por compartir su enfoque y el código.