HeikinAshi-Trend/HeikinAshi_Trend.mq5

653 lines
57 KiB
MQL5
Raw Permalink Normal View History

2026-02-27 21:06:40 -06:00
<EFBFBD><EFBFBD>//T%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%W%
//Q% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%W% Q%
//Q% <EFBFBD>%<EFBFBD>%T%P%P%P%]%Z%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%T%]%<EFBFBD>%<EFBFBD>%T%P%P%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%T%P%P%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%T%P%P%P%]%<EFBFBD>%<EFBFBD>%T%P%P%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%T%P%P%P%]%<EFBFBD>%<EFBFBD>%T%P%P%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%Q% Q%
//Q% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W% Z%<EFBFBD>%<EFBFBD>%<EFBFBD>%T%]% <EFBFBD>%<EFBFBD>%Q% <EFBFBD>%<EFBFBD>%Q%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%T%]%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%Q%<EFBFBD>%<EFBFBD>%Q% <EFBFBD>%<EFBFBD>%Q% <EFBFBD>%<EFBFBD>%Q%<EFBFBD>%<EFBFBD>%T%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%Q% Q%
//Q% <EFBFBD>%<EFBFBD>%T%P%P%]% <EFBFBD>%<EFBFBD>%T%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%Q% <EFBFBD>%<EFBFBD>%Q%<EFBFBD>%<EFBFBD>%T%P%P%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%T%P%P%]% <EFBFBD>%<EFBFBD>%T%P%P%<EFBFBD>%<EFBFBD>%Q%<EFBFBD>%<EFBFBD>%Q% <EFBFBD>%<EFBFBD>%Q% <EFBFBD>%<EFBFBD>%Q%<EFBFBD>%<EFBFBD>%Q%Z%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%Q% Q%
//Q% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%T%]% <EFBFBD>%<EFBFBD>%W%Z%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%T%]%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%T%]%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%Q% <EFBFBD>%<EFBFBD>%Q%Z%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W%Z%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%T%]%<EFBFBD>%<EFBFBD>%Q% Z%<EFBFBD>%<EFBFBD>%<EFBFBD>%Q% Q%
//Q% Z%P%P%P%P%P%]%Z%P%]% Z%P%]% Z%P%P%P%P%]% Z%P%P%P%P%P%]% Z%P%P%P%P%P%]%Z%P%]% Z%P%]% Z%P%P%P%P%]% Z%P%P%P%P%]% Z%P%]% Z%P%P%]% Q%
//Z%P%P%P%P%P%P%P% Algorithms that observe P%P%P%P% Signals that speak P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%]%
//+------------------------------------------------------------------+
//| 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 "~~~~~((=<3D>}<7D>))~~~~~"
#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). |
//| |
//+------------------------------------------------------------------+