//╔════════════════════════════════════════════════════════════════════════╗ //║ ██████╗██╗ ██╗ █████╗ ██████╗ ██████╗ █████╗ █████╗ █████╗ ███╗ ██╗ ║ //║ ██╔═══╝╚██╗██╔╝██╔══██╗██╔══██╗██╔═══╝██╔══██╗██╔═══╝██╔══██╗████╗ ██║ ║ //║ █████╗ ╚███╔╝ ██║ ██║██████╔╝█████╗ ███████║██║ ██║ ██║██╔██╗██║ ║ //║ ██╔══╝ ██╔██╗ ██║ ██║██╔══██╗██╔══╝ ██╔══██║██║ ██║ ██║██║╚████║ ║ //║ ██████╗██╔╝ ██╗╚█████╔╝██████╔╝██████╗██║ ██║╚█████╗╚█████╔╝██║ ╚███║ ║ //║ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚════╝ ╚═╝ ╚══╝ ║ //╚═══════ Algorithms that observe ════ Signals that speak ════════════════╝ //+------------------------------------------------------------------+ //| Archivo: HeikinAshiTrendIndicator.mq5 | //| Origen: Port del indicador "Heikin Ashi Trend Indicator" | //| de dman103 (TradingView, Pine Script v4) | //| Referencia: https://www.tradingview.com/script/OULfXjkq- | //| Heikin-Ashi-Trend-Indicator/ | //| Algoritmo: 1) Calcula OHLC Heikin Ashi a partir de velas reales | //| 2) Suaviza los 4 componentes HA con Tilson T3 | //| 3) Compara T3(haClose) vs T3(haOpen) para tendencia | //| 4) Grafica marcadores por encima del precio (bajista) | //| o por debajo (alcista), estilo "Parabolic SAR" | //| 5) Detecta squeeze (convergencia) con colores claros | //| 6) Multiples estilos visuales configurables | //| | //| Arquitectura de plots: | //| Todos los estilos usan 2 plots (Bull + Bear): | //| - Estilos MARCADOR: DRAW_COLOR_ARROW con 2 colores c/u | //| Permite simbolos Wingdings distintos por direccion | //| - Estilos LINEA: DRAW_COLOR_LINE con 2 colores c/u | //| EMPTY_VALUE en plot inactivo interrumpe la linea | //| (comportamiento identico al SuperTrend) | //+------------------------------------------------------------------+ #property copyright "Exobeacon Labs" #property link "https://www.exobeacon.com/" #property version "2.1" #property description "Heikin Ashi Trend Indicator (dman103) v2.1" #property description "Smoothed HA + Tilson T3. Multiple visual styles:" #property description "Crosses, Dots, Lines, Arrows, Diamonds & more." #property description "SAR-style: above price (bear), below price (bull)." #property description " " #property description "~~~~~((👽))~~~~~" #property description "mql5.com/en/users/ulisescalb" #property description "github.com/Exobeacon-Labs" #property strict //--- Ventana del grafico principal #property indicator_chart_window //--- Buffers maximos necesarios: //--- Modo marcador: Plot0(2) + Plot1(2) + HA(4) + T3x4(24) = 32 //--- Modo linea: Plot0(2) + HA(4) + T3x4(24) = 30 (usa 32, sobra 2) //--- Usamos 32 para cubrir ambos modos #property indicator_buffers 32 #property indicator_plots 2 //--- Plot 0: Bull o LineaUnica (se configura dinamicamente en OnInit) #property indicator_label1 "HAT Bull" #property indicator_type1 DRAW_COLOR_ARROW #property indicator_color1 clrDeepSkyBlue, clrLightBlue #property indicator_style1 STYLE_SOLID #property indicator_width1 2 //--- Plot 1: Bear (solo activo en modo marcador; oculto en modo linea) #property indicator_label2 "HAT Bear" #property indicator_type2 DRAW_COLOR_ARROW #property indicator_color2 clrDeepPink, clrPink #property indicator_style2 STYLE_SOLID #property indicator_width2 2 //+------------------------------------------------------------------+ //| ENUMERACIONES PERSONALIZADAS | //+------------------------------------------------------------------+ //--- Enum para seleccionar el estilo visual del indicador enum ENUM_HAT_STYLE { HAT_STYLE_CROSS = 0, // Crosses (x) HAT_STYLE_DOT = 1, // Dots HAT_STYLE_LINE_SOLID = 2, // Solid Line HAT_STYLE_LINE_DASH = 3, // Dashed Line (- - -) HAT_STYLE_LINE_DASHDOTDOT = 4, // Dash-Dot Line (-.-.) HAT_STYLE_ARROW = 5, // Arrows HAT_STYLE_DIAMOND = 6, // Large dots HAT_STYLE_SQUARE = 7, // Squares HAT_STYLE_CIRCLE = 8, // Empty squares HAT_STYLE_STAR = 9, // Diamonds HAT_STYLE_THUMBS = 10, // Thumbs }; //+------------------------------------------------------------------+ //| PARAMETROS DE ENTRADA | //+------------------------------------------------------------------+ //--- Grupo: Configuracion Tilson T3 input group "====== Tilson T3 Settings ======" input int InpT3Period = 8; // T3 Period input double InpVolumeFactor = 0.59; // T3 Volume Factor (0.0-1.0) //--- Grupo: Deteccion de squeeze input group "====== Squeeze Detection ======" input double InpPercentSqueeze = 0.066; // Squeeze Threshold (%) [0=disabled] //--- Grupo: Estilo visual input group "====== Visual Style ======" input ENUM_HAT_STYLE InpStyle = HAT_STYLE_DOT; // Drawing Style input color InpBullColor = clrDeepSkyBlue; // Bull Color (strong trend) input color InpBullSqzColor = clrLightBlue; // Bull Color (squeeze) input color InpBearColor = clrDeepPink; // Bear Color (strong trend) input color InpBearSqzColor = clrPink; // Bear Color (squeeze) input bool InpUseBarColor = false; // Color Chart Bars //--- Grupo: Sistema de alertas input group "====== Alert System ======" input bool InpEnableAlerts = false; // Enable Alerts input bool InpAlertPopup = true; // Alert: Popup input bool InpAlertSound = false; // Alert: Sound input bool InpAlertPush = false; // Alert: Push Notification input bool InpAlertEmail = false; // Alert: Email //+------------------------------------------------------------------+ //| BUFFERS GLOBALES | //+------------------------------------------------------------------+ //--- Buffers de salida: siempre se reservan 4 slots (indices 0-3) //--- Modo marcador: Plot0 data[0] + color[1], Plot1 data[2] + color[3] //--- Modo linea: Plot0 data[0] + color[1], Plot1 data[2] + color[3] = NONE double BufferPlot0[]; // Plot 0: datos (precio) double BufferPlot0Color[]; // Plot 0: indice de color double BufferPlot1[]; // Plot 1: datos (precio) -- solo modo marcador double BufferPlot1Color[]; // Plot 1: indice de color -- solo modo marcador //--- Buffers Heikin Ashi: indices 4-7 double BufferHaOpen[]; double BufferHaClose[]; double BufferHaHigh[]; double BufferHaLow[]; //--- Buffers T3 para haClose: 6 EMAs en cascada (indices 8-13) double e1c[], e2c[], e3c[], e4c[], e5c[], e6c[]; //--- Buffers T3 para haOpen: 6 EMAs en cascada (indices 14-19) double e1o[], e2o[], e3o[], e4o[], e5o[], e6o[]; //--- Buffers T3 para haHigh: 6 EMAs en cascada (indices 20-25) double e1h[], e2h[], e3h[], e4h[], e5h[], e6h[]; //--- Buffers T3 para haLow: 6 EMAs en cascada (indices 26-31) double e1l[], e2l[], e3l[], e4l[], e5l[], e6l[]; //+------------------------------------------------------------------+ //| VARIABLES GLOBALES | //+------------------------------------------------------------------+ //--- Coeficientes T3 pre-calculados double g_c1 = 0.0; double g_c2 = 0.0; double g_c3 = 0.0; double g_c4 = 0.0; //--- Factor de suavizado EMA double g_alpha = 0.0; //--- Control de alertas: evitar duplicados en la misma vela datetime g_lastAlertTime = 0; //--- Flag: true si el estilo actual es de linea (DRAW_COLOR_LINE) bool g_isLineStyle = false; //+------------------------------------------------------------------+ //| OnInit - Inicializacion del indicador | //+------------------------------------------------------------------+ int OnInit() { //--- Validar parametros de entrada if(InpT3Period < 1) { Print("Error: T3 Period must be >= 1. Current value: ", InpT3Period); return(INIT_PARAMETERS_INCORRECT); } if(InpVolumeFactor < 0.0 || InpVolumeFactor > 1.0) { Print("Error: Volume Factor must be between 0.0 and 1.0. Current: ", DoubleToString(InpVolumeFactor, 2)); return(INIT_PARAMETERS_INCORRECT); } if(InpPercentSqueeze < 0.0) { Print("Error: Squeeze Threshold must be >= 0. Current: ", DoubleToString(InpPercentSqueeze, 2)); return(INIT_PARAMETERS_INCORRECT); } //=== ASIGNAR BUFFERS === //--- Slots de salida (indices 0-3): siempre asignados SetIndexBuffer(0, BufferPlot0, INDICATOR_DATA); SetIndexBuffer(1, BufferPlot0Color, INDICATOR_COLOR_INDEX); SetIndexBuffer(2, BufferPlot1, INDICATOR_DATA); SetIndexBuffer(3, BufferPlot1Color, INDICATOR_COLOR_INDEX); //--- Heikin Ashi OHLC (calculo interno) SetIndexBuffer(4, BufferHaOpen, INDICATOR_CALCULATIONS); SetIndexBuffer(5, BufferHaClose, INDICATOR_CALCULATIONS); SetIndexBuffer(6, BufferHaHigh, INDICATOR_CALCULATIONS); SetIndexBuffer(7, BufferHaLow, INDICATOR_CALCULATIONS); //--- T3 para haClose (6 EMAs) SetIndexBuffer(8, e1c, INDICATOR_CALCULATIONS); SetIndexBuffer(9, e2c, INDICATOR_CALCULATIONS); SetIndexBuffer(10, e3c, INDICATOR_CALCULATIONS); SetIndexBuffer(11, e4c, INDICATOR_CALCULATIONS); SetIndexBuffer(12, e5c, INDICATOR_CALCULATIONS); SetIndexBuffer(13, e6c, INDICATOR_CALCULATIONS); //--- T3 para haOpen (6 EMAs) SetIndexBuffer(14, e1o, INDICATOR_CALCULATIONS); SetIndexBuffer(15, e2o, INDICATOR_CALCULATIONS); SetIndexBuffer(16, e3o, INDICATOR_CALCULATIONS); SetIndexBuffer(17, e4o, INDICATOR_CALCULATIONS); SetIndexBuffer(18, e5o, INDICATOR_CALCULATIONS); SetIndexBuffer(19, e6o, INDICATOR_CALCULATIONS); //--- T3 para haHigh (6 EMAs) SetIndexBuffer(20, e1h, INDICATOR_CALCULATIONS); SetIndexBuffer(21, e2h, INDICATOR_CALCULATIONS); SetIndexBuffer(22, e3h, INDICATOR_CALCULATIONS); SetIndexBuffer(23, e4h, INDICATOR_CALCULATIONS); SetIndexBuffer(24, e5h, INDICATOR_CALCULATIONS); SetIndexBuffer(25, e6h, INDICATOR_CALCULATIONS); //--- T3 para haLow (6 EMAs) SetIndexBuffer(26, e1l, INDICATOR_CALCULATIONS); SetIndexBuffer(27, e2l, INDICATOR_CALCULATIONS); SetIndexBuffer(28, e3l, INDICATOR_CALCULATIONS); SetIndexBuffer(29, e4l, INDICATOR_CALCULATIONS); SetIndexBuffer(30, e5l, INDICATOR_CALCULATIONS); SetIndexBuffer(31, e6l, INDICATOR_CALCULATIONS); //=== CONFIGURAR ESTILO VISUAL DINAMICAMENTE === ConfigurePlotStyle(); //--- Valor vacio para ambos plots PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE); //--- Evitar basura visual en las primeras barras const int drawBegin = InpT3Period * 6; PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, drawBegin); PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, drawBegin); //=== PRE-CALCULAR COEFICIENTES T3 === //--- Formulas de Tim Tillson (TASC, Enero 1998) const double a = InpVolumeFactor; const double a2 = a * a; const double a3 = a2 * a; g_c1 = -a3; g_c2 = 3.0 * a2 + 3.0 * a3; g_c3 = -(6.0 * a2 + 3.0 * a + 3.0 * a3); g_c4 = 1.0 + 3.0 * a + a3 + 3.0 * a2; //--- Factor alfa EMA g_alpha = 2.0 / (InpT3Period + 1.0); //--- Nombre corto IndicatorSetString(INDICATOR_SHORTNAME, "HAT(" + IntegerToString(InpT3Period) + ", " + DoubleToString(InpVolumeFactor, 2) + ")"); IndicatorSetInteger(INDICATOR_DIGITS, _Digits); //--- Inicializar control de alertas g_lastAlertTime = 0; return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| ConfigurePlotStyle - Configura plots segun el estilo elegido | //| | //| ESTRATEGIA CLAVE: | //| Ambos modos usan 2 plots (Bull + Bear) con 2 colores c/u: | //| | //| Modo LINEA: Plot 0 = DRAW_COLOR_LINE (Bull, 2 colores) | //| Plot 1 = DRAW_COLOR_LINE (Bear, 2 colores) | //| EMPTY_VALUE interrumpe la linea al cambiar | //| tendencia (como SuperTrend) | //| | //| Modo MARCADOR: Plot 0 = DRAW_COLOR_ARROW (Bull, 2 colores) | //| Plot 1 = DRAW_COLOR_ARROW (Bear, 2 colores) | //| Permite simbolos distintos por direccion | //| | //| Codigos Wingdings usados: | //| 159 = circulo solido pequeno (dot SAR) | //| 108 = diamante solido | //| 110 = cuadrado solido | //| 113 = circulo vacio (anillo) | //| 117 = estrella gruesa de 6 puntas | //| 233 = flecha arriba solida | //| 234 = flecha abajo solida | //| 251 = cruz (x) clasica | //| 67 = pulgar arriba | //| 68 = pulgar abajo | //+------------------------------------------------------------------+ void ConfigurePlotStyle() { //--- Determinar si es estilo de linea g_isLineStyle = (InpStyle >= HAT_STYLE_LINE_SOLID && InpStyle <= HAT_STYLE_LINE_DASHDOTDOT); if(g_isLineStyle) { //=== MODO LINEA: 2 plots DRAW_COLOR_LINE (Bull + Bear) === //--- Cada plot tiene 2 colores (fuerte + squeeze) //--- El plot inactivo se pone en EMPTY_VALUE -> la linea se interrumpe //--- Esto replica el comportamiento visual del SuperTrend //--- Plot 0 (Bull): linea debajo del precio PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_COLOR_LINE); PlotIndexSetInteger(0, PLOT_COLOR_INDEXES, 2); PlotIndexSetInteger(0, PLOT_LINE_COLOR, 0, InpBullColor); PlotIndexSetInteger(0, PLOT_LINE_COLOR, 1, InpBullSqzColor); PlotIndexSetString(0, PLOT_LABEL, "HAT Bull"); //--- Plot 1 (Bear): linea encima del precio PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_COLOR_LINE); PlotIndexSetInteger(1, PLOT_COLOR_INDEXES, 2); PlotIndexSetInteger(1, PLOT_LINE_COLOR, 0, InpBearColor); PlotIndexSetInteger(1, PLOT_LINE_COLOR, 1, InpBearSqzColor); PlotIndexSetString(1, PLOT_LABEL, "HAT Bear"); //--- Seleccionar estilo de linea (aplicar a ambos plots) ENUM_LINE_STYLE lineStyle = STYLE_SOLID; switch(InpStyle) { case HAT_STYLE_LINE_SOLID: lineStyle = STYLE_SOLID; break; case HAT_STYLE_LINE_DASH: lineStyle = STYLE_DASH; break; case HAT_STYLE_LINE_DASHDOTDOT: lineStyle = STYLE_DASHDOTDOT; break; } PlotIndexSetInteger(0, PLOT_LINE_STYLE, lineStyle); PlotIndexSetInteger(1, PLOT_LINE_STYLE, lineStyle); } else { //=== MODO MARCADOR: 2 plots con 2 colores cada uno === //--- Plot 0 (Bull): DRAW_COLOR_ARROW con 2 colores PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_COLOR_ARROW); PlotIndexSetInteger(0, PLOT_COLOR_INDEXES, 2); PlotIndexSetInteger(0, PLOT_LINE_COLOR, 0, InpBullColor); PlotIndexSetInteger(0, PLOT_LINE_COLOR, 1, InpBullSqzColor); PlotIndexSetString(0, PLOT_LABEL, "HAT Bull"); //--- Plot 1 (Bear): DRAW_COLOR_ARROW con 2 colores PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_COLOR_ARROW); PlotIndexSetInteger(1, PLOT_COLOR_INDEXES, 2); PlotIndexSetInteger(1, PLOT_LINE_COLOR, 0, InpBearColor); PlotIndexSetInteger(1, PLOT_LINE_COLOR, 1, InpBearSqzColor); PlotIndexSetString(1, PLOT_LABEL, "HAT Bear"); //--- Codigos Wingdings para cada estilo de marcador int bullCode = 251; int bearCode = 251; switch(InpStyle) { case HAT_STYLE_CROSS: bullCode = 251; bearCode = 251; // Cruz (x) -- original break; case HAT_STYLE_DOT: bullCode = 159; bearCode = 159; // Punto solido (SAR) break; case HAT_STYLE_ARROW: bullCode = 233; bearCode = 234; // Flechas arriba/abajo break; case HAT_STYLE_DIAMOND: bullCode = 108; bearCode = 108; // Diamante solido break; case HAT_STYLE_SQUARE: bullCode = 110; bearCode = 110; // Cuadrado solido break; case HAT_STYLE_CIRCLE: bullCode = 113; bearCode = 113; // Circulo vacio break; case HAT_STYLE_STAR: bullCode = 117; bearCode = 117; // Estrella gruesa break; case HAT_STYLE_THUMBS: bullCode = 67; bearCode = 68; // Pulgares arriba/abajo break; } PlotIndexSetInteger(0, PLOT_ARROW, bullCode); PlotIndexSetInteger(1, PLOT_ARROW, bearCode); } } //+------------------------------------------------------------------+ //| OnDeinit - Limpieza de recursos | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { Comment(""); } //+------------------------------------------------------------------+ //| OnCalculate - Bucle principal de calculo | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { //--- Verificar minimo de barras necesarias if(rates_total < InpT3Period + 1) return(0); //--- Pesos EMA const double w1 = g_alpha; const double w2 = 1.0 - g_alpha; //--- Determinar el punto de inicio del calculo int limit; if(prev_calculated == 0) { //=== PRIMERA EJECUCION: Inicializar barra 0 === BufferHaClose[0] = (open[0] + high[0] + low[0] + close[0]) / 4.0; BufferHaOpen[0] = (open[0] + close[0]) / 2.0; BufferHaHigh[0] = MathMax(high[0], MathMax(BufferHaOpen[0], BufferHaClose[0])); BufferHaLow[0] = MathMin(low[0], MathMin(BufferHaOpen[0], BufferHaClose[0])); //--- Inicializar cadenas T3 e1c[0] = e2c[0] = e3c[0] = e4c[0] = e5c[0] = e6c[0] = BufferHaClose[0]; e1o[0] = e2o[0] = e3o[0] = e4o[0] = e5o[0] = e6o[0] = BufferHaOpen[0]; e1h[0] = e2h[0] = e3h[0] = e4h[0] = e5h[0] = e6h[0] = BufferHaHigh[0]; e1l[0] = e2l[0] = e3l[0] = e4l[0] = e5l[0] = e6l[0] = BufferHaLow[0]; //--- Limpiar buffers de salida en barra 0 BufferPlot0[0] = EMPTY_VALUE; BufferPlot0Color[0] = 0; BufferPlot1[0] = EMPTY_VALUE; BufferPlot1Color[0] = 0; limit = 1; } else { limit = prev_calculated - 1; } //--- === BUCLE PRINCIPAL === for(int i = limit; i < rates_total; i++) { //=== ETAPA 1: Heikin Ashi OHLC === BufferHaClose[i] = (open[i] + high[i] + low[i] + close[i]) / 4.0; BufferHaOpen[i] = (BufferHaOpen[i - 1] + BufferHaClose[i - 1]) / 2.0; BufferHaHigh[i] = MathMax(high[i], MathMax(BufferHaOpen[i], BufferHaClose[i])); BufferHaLow[i] = MathMin(low[i], MathMin(BufferHaOpen[i], BufferHaClose[i])); //=== ETAPA 2: T3 sobre haClose === e1c[i] = w1 * BufferHaClose[i] + w2 * e1c[i - 1]; e2c[i] = w1 * e1c[i] + w2 * e2c[i - 1]; e3c[i] = w1 * e2c[i] + w2 * e3c[i - 1]; e4c[i] = w1 * e3c[i] + w2 * e4c[i - 1]; e5c[i] = w1 * e4c[i] + w2 * e5c[i - 1]; e6c[i] = w1 * e5c[i] + w2 * e6c[i - 1]; const double t3Close = g_c1 * e6c[i] + g_c2 * e5c[i] + g_c3 * e4c[i] + g_c4 * e3c[i]; //=== ETAPA 3: T3 sobre haOpen === e1o[i] = w1 * BufferHaOpen[i] + w2 * e1o[i - 1]; e2o[i] = w1 * e1o[i] + w2 * e2o[i - 1]; e3o[i] = w1 * e2o[i] + w2 * e3o[i - 1]; e4o[i] = w1 * e3o[i] + w2 * e4o[i - 1]; e5o[i] = w1 * e4o[i] + w2 * e5o[i - 1]; e6o[i] = w1 * e5o[i] + w2 * e6o[i - 1]; const double t3Open = g_c1 * e6o[i] + g_c2 * e5o[i] + g_c3 * e4o[i] + g_c4 * e3o[i]; //=== ETAPA 4: T3 sobre haHigh === e1h[i] = w1 * BufferHaHigh[i] + w2 * e1h[i - 1]; e2h[i] = w1 * e1h[i] + w2 * e2h[i - 1]; e3h[i] = w1 * e2h[i] + w2 * e3h[i - 1]; e4h[i] = w1 * e3h[i] + w2 * e4h[i - 1]; e5h[i] = w1 * e4h[i] + w2 * e5h[i - 1]; e6h[i] = w1 * e5h[i] + w2 * e6h[i - 1]; const double t3High = g_c1 * e6h[i] + g_c2 * e5h[i] + g_c3 * e4h[i] + g_c4 * e3h[i]; //=== ETAPA 5: T3 sobre haLow === e1l[i] = w1 * BufferHaLow[i] + w2 * e1l[i - 1]; e2l[i] = w1 * e1l[i] + w2 * e2l[i - 1]; e3l[i] = w1 * e2l[i] + w2 * e3l[i - 1]; e4l[i] = w1 * e3l[i] + w2 * e4l[i - 1]; e5l[i] = w1 * e4l[i] + w2 * e5l[i - 1]; e6l[i] = w1 * e5l[i] + w2 * e6l[i - 1]; const double t3Low = g_c1 * e6l[i] + g_c2 * e5l[i] + g_c3 * e4l[i] + g_c4 * e3l[i]; //=== ETAPA 6: Determinar tendencia === const bool isBullish = (t3Close > t3Open); const bool isBearish = (t3Open > t3Close); //=== ETAPA 7: Detectar squeeze === bool isSqueeze = false; if(InpPercentSqueeze > 0.0) { const double diff = MathAbs(t3Close - t3Open); const double avgVal = (t3Close + t3Open) / 2.0; if(avgVal != 0.0) isSqueeze = ((diff / avgVal) * 100.0) < InpPercentSqueeze; } //=== ETAPA 8: Asignar valores a los buffers de salida === //--- Ambos modos (linea y marcador) usan la misma estrategia: //--- Plot 0 = Bull (debajo del precio en t3Low) //--- Plot 1 = Bear (encima del precio en t3High) //--- Solo un plot activo por barra; el otro en EMPTY_VALUE //--- En modo linea, EMPTY_VALUE interrumpe la linea (como SuperTrend) if(isBullish) { BufferPlot0[i] = t3Low; BufferPlot0Color[i] = isSqueeze ? 1 : 0; // 0=fuerte, 1=squeeze BufferPlot1[i] = EMPTY_VALUE; // Bear inactivo BufferPlot1Color[i] = 0; } else if(isBearish) { BufferPlot0[i] = EMPTY_VALUE; // Bull inactivo BufferPlot0Color[i] = 0; BufferPlot1[i] = t3High; BufferPlot1Color[i] = isSqueeze ? 1 : 0; // 0=fuerte, 1=squeeze } else { //--- Caso neutral (t3Close == t3Open exacto, muy raro) BufferPlot0[i] = t3Close; BufferPlot0Color[i] = 0; BufferPlot1[i] = EMPTY_VALUE; BufferPlot1Color[i] = 0; } //=== ETAPA 9: Coloreo de velas (opcional) === if(InpUseBarColor) { if(isBullish) { const color barCol = isSqueeze ? InpBullSqzColor : InpBullColor; ChartSetInteger(0, CHART_COLOR_CANDLE_BULL, barCol); ChartSetInteger(0, CHART_COLOR_CHART_UP, barCol); } else { const color barCol = isSqueeze ? InpBearSqzColor : InpBearColor; ChartSetInteger(0, CHART_COLOR_CANDLE_BEAR, barCol); ChartSetInteger(0, CHART_COLOR_CHART_DOWN, barCol); } } } //--- === SISTEMA DE ALERTAS === if(InpEnableAlerts && rates_total >= 3) { const int last = rates_total - 2; const int prev = last - 1; if(time[last] != g_lastAlertTime) { const double prevT3C = g_c1 * e6c[prev] + g_c2 * e5c[prev] + g_c3 * e4c[prev] + g_c4 * e3c[prev]; const double prevT3O = g_c1 * e6o[prev] + g_c2 * e5o[prev] + g_c3 * e4o[prev] + g_c4 * e3o[prev]; const double lastT3C = g_c1 * e6c[last] + g_c2 * e5c[last] + g_c3 * e4c[last] + g_c4 * e3c[last]; const double lastT3O = g_c1 * e6o[last] + g_c2 * e5o[last] + g_c3 * e4o[last] + g_c4 * e3o[last]; //--- Crossover alcista if((prevT3O > prevT3C) && (lastT3C > lastT3O)) { g_lastAlertTime = time[last]; SendAlertSignal("BUY", time[last]); } //--- Crossover bajista else if((prevT3C > prevT3O) && (lastT3O > lastT3C)) { g_lastAlertTime = time[last]; SendAlertSignal("SELL", time[last]); } } } return(rates_total); } //+------------------------------------------------------------------+ //| SendAlertSignal - Envia alerta multi-canal | //+------------------------------------------------------------------+ void SendAlertSignal(const string signal, const datetime barTime) { const string prefix = "HAT(" + IntegerToString(InpT3Period) + ") "; const string msg = prefix + signal + " signal on " + _Symbol + " " + EnumToString(Period()) + " at " + TimeToString(barTime, TIME_DATE | TIME_MINUTES); if(InpAlertPopup) Alert(msg); if(InpAlertSound) { if(signal == "BUY") PlaySound("alert.wav"); else PlaySound("alert2.wav"); } if(InpAlertPush) SendNotification(msg); if(InpAlertEmail) SendMail("HAT Alert: " + signal + " " + _Symbol, msg); } //+------------------------------------------------------------------+ //| | //| REFERENCIA: Codigo Pine Script Original (dman103) | //| https://www.tradingview.com/script/OULfXjkq-Heikin-Ashi-Trend- | //| Indicator/ | //| | //| Algoritmo reconstruido: | //| 1. haClose = (O+H+L+C)/4, haOpen = (haOpen[1]+haClose[1])/2 | //| 2. T3(src) = c1*e6 + c2*e5 + c3*e4 + c4*e3 (6 EMAs cascada) | //| 3. Bull = T3(haClose) > T3(haOpen) -> plot at T3(haLow) | //| 4. Bear = T3(haOpen) > T3(haClose) -> plot at T3(haHigh) | //| 5. Squeeze = |diff|/avg*100 < threshold -> lighter color | //| | //| NOTAS DE PORTEO v2.1: | //| | //| 1. Modo LINEA y MARCADOR usan la misma arquitectura de 2 plots | //| (Bull + Bear) con 2 colores cada uno. EMPTY_VALUE en el plot | //| inactivo interrumpe la linea (SuperTrend style) o no dibuja | //| el marcador. | //| | //| 2. Eliminado estilo Triangles (problemas de legibilidad). | //| | //| 3. Colores 100% personalizables: 4 inputs de color | //| (bull, bull-squeeze, bear, bear-squeeze). | //| | //+------------------------------------------------------------------+