HeikinAshi-Trend/HeikinAshi_Trend.mq4

540 lines
43 KiB
MQL4
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.mq4 |
//| 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 |
//| |
//| Nota MQL4: DRAW_COLOR_LINE/ARROW no existen en MQL4. |
//| - Lineas: 4 buffers DRAW_LINE independientes |
//| - Marcadores: 4 buffers DRAW_ARROW independientes |
//| Cada buffer = 1 color (bull, bull-sqz, bear, bear-sqz) |
//+------------------------------------------------------------------+
#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 "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 visibles: solo 4 plots
//--- Los 28 buffers internos (HA + T3) se declaran con IndicatorBuffers() en OnInit
#property indicator_buffers 4
//--- Colores por defecto para los 4 plots visibles
#property indicator_color1 clrDeepSkyBlue // Bull fuerte
#property indicator_color2 clrLightBlue // Bull squeeze
#property indicator_color3 clrDeepPink // Bear fuerte
#property indicator_color4 clrPink // Bear squeeze
#property indicator_width1 2
#property indicator_width2 2
#property indicator_width3 2
#property indicator_width4 2
//+------------------------------------------------------------------+
//| ENUMERACIONES |
//+------------------------------------------------------------------+
//--- Estilos visuales disponibles en MQL4
//--- Solo linea solida para estilos de linea (limitacion MQL4)
enum ENUM_HAT_STYLE
{
HAT_STYLE_CROSS = 0, // Crosses (x)
HAT_STYLE_DOT = 1, // Dots
HAT_STYLE_LINE = 2, // Solid Line
HAT_STYLE_ARROW = 3, // Arrows
HAT_STYLE_DIAMOND = 4, // Large dots
HAT_STYLE_SQUARE = 5, // Squares
HAT_STYLE_CIRCLE = 6, // Empty squares
HAT_STYLE_STAR = 7, // Diamonds
HAT_STYLE_THUMBS = 8, // Thumbs
};
//+------------------------------------------------------------------+
//| PARAMETROS DE ENTRADA |
//+------------------------------------------------------------------+
//--- Tilson T3
extern int InpT3Period = 8; // T3 Period
extern double InpVolumeFactor = 0.59; // T3 Volume Factor (0.0-1.0)
//--- Squeeze
extern double InpPercentSqueeze = 0.066; // Squeeze Threshold (%) [0=disabled]
//--- Estilo visual
extern ENUM_HAT_STYLE InpStyle = HAT_STYLE_DOT; // Drawing Style
extern color InpBullColor = clrDeepSkyBlue; // Bull Color (strong)
extern color InpBullSqzColor = clrLightBlue; // Bull Color (squeeze)
extern color InpBearColor = clrDeepPink; // Bear Color (strong)
extern color InpBearSqzColor = clrPink; // Bear Color (squeeze)
extern bool InpUseBarColor = false; // Color Chart Bars
//--- Alertas
extern bool InpEnableAlerts = false; // Enable Alerts
extern bool InpAlertPopup = true; // Alert: Popup
extern bool InpAlertSound = false; // Alert: Sound
extern bool InpAlertPush = false; // Alert: Push Notification
extern bool InpAlertEmail = false; // Alert: Email
//+------------------------------------------------------------------+
//| BUFFERS GLOBALES |
//+------------------------------------------------------------------+
//--- 4 buffers de salida (uno por color/estado)
double BuffBullStrong[]; // Index 0: Bull fuerte
double BuffBullSqueeze[]; // Index 1: Bull squeeze
double BuffBearStrong[]; // Index 2: Bear fuerte
double BuffBearSqueeze[]; // Index 3: Bear squeeze
//--- 4 buffers Heikin Ashi
double BuffHaOpen[]; // Index 4
double BuffHaClose[]; // Index 5
double BuffHaHigh[]; // Index 6
double BuffHaLow[]; // Index 7
//--- T3 para haClose: 6 EMAs (indices 8-13)
double e1c[], e2c[], e3c[], e4c[], e5c[], e6c[];
//--- T3 para haOpen: 6 EMAs (indices 14-19)
double e1o[], e2o[], e3o[], e4o[], e5o[], e6o[];
//--- T3 para haHigh: 6 EMAs (indices 20-25)
double e1h[], e2h[], e3h[], e4h[], e5h[], e6h[];
//--- T3 para haLow: 6 EMAs (indices 26-31)
double e1l[], e2l[], e3l[], e4l[], e5l[], e6l[];
//+------------------------------------------------------------------+
//| VARIABLES GLOBALES |
//+------------------------------------------------------------------+
//--- Coeficientes T3
double g_c1 = 0.0;
double g_c2 = 0.0;
double g_c3 = 0.0;
double g_c4 = 0.0;
//--- Factor EMA
double g_alpha = 0.0;
//--- Control de alertas
datetime g_lastAlertTime = 0;
//--- Flag de estilo linea
bool g_isLineStyle = false;
//+------------------------------------------------------------------+
//| OnInit |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Reservar 32 buffers en total (4 visibles + 28 internos)
IndicatorBuffers(32);
//--- Validar parametros
if(InpT3Period < 1)
{
Print("Error: T3 Period must be >= 1. Current: ", InpT3Period);
return(INIT_PARAMETERS_INCORRECT);
}
if(InpVolumeFactor < 0.0 || InpVolumeFactor > 1.0)
{
Print("Error: Volume Factor must be 0.0-1.0. Current: ", DoubleToString(InpVolumeFactor, 2));
return(INIT_PARAMETERS_INCORRECT);
}
if(InpPercentSqueeze < 0.0)
{
Print("Error: Squeeze must be >= 0. Current: ", DoubleToString(InpPercentSqueeze, 2));
return(INIT_PARAMETERS_INCORRECT);
}
//=== ASIGNAR BUFFERS ===
//--- 4 buffers de salida visibles
SetIndexBuffer(0, BuffBullStrong);
SetIndexBuffer(1, BuffBullSqueeze);
SetIndexBuffer(2, BuffBearStrong);
SetIndexBuffer(3, BuffBearSqueeze);
//--- 4 buffers HA (internos)
SetIndexBuffer(4, BuffHaOpen);
SetIndexBuffer(5, BuffHaClose);
SetIndexBuffer(6, BuffHaHigh);
SetIndexBuffer(7, BuffHaLow);
//--- T3 haClose
SetIndexBuffer(8, e1c); SetIndexBuffer(9, e2c);
SetIndexBuffer(10, e3c); SetIndexBuffer(11, e4c);
SetIndexBuffer(12, e5c); SetIndexBuffer(13, e6c);
//--- T3 haOpen
SetIndexBuffer(14, e1o); SetIndexBuffer(15, e2o);
SetIndexBuffer(16, e3o); SetIndexBuffer(17, e4o);
SetIndexBuffer(18, e5o); SetIndexBuffer(19, e6o);
//--- T3 haHigh
SetIndexBuffer(20, e1h); SetIndexBuffer(21, e2h);
SetIndexBuffer(22, e3h); SetIndexBuffer(23, e4h);
SetIndexBuffer(24, e5h); SetIndexBuffer(25, e6h);
//--- T3 haLow
SetIndexBuffer(26, e1l); SetIndexBuffer(27, e2l);
SetIndexBuffer(28, e3l); SetIndexBuffer(29, e4l);
SetIndexBuffer(30, e5l); SetIndexBuffer(31, e6l);
//--- Ocultar todos los buffers internos (indices 4-31)
//--- Sin esto, MQL4 los dibuja como lineas negras por defecto
for(int b = 4; b < 32; b++)
SetIndexStyle(b, DRAW_NONE);
//=== CONFIGURAR ESTILO VISUAL ===
g_isLineStyle = (InpStyle == HAT_STYLE_LINE);
if(g_isLineStyle)
{
//--- Modo linea: 4 buffers DRAW_LINE (bull, bull-sqz, bear, bear-sqz)
SetIndexStyle(0, DRAW_LINE, STYLE_SOLID, 2, InpBullColor);
SetIndexStyle(1, DRAW_LINE, STYLE_SOLID, 2, InpBullSqzColor);
SetIndexStyle(2, DRAW_LINE, STYLE_SOLID, 2, InpBearColor);
SetIndexStyle(3, DRAW_LINE, STYLE_SOLID, 2, InpBearSqzColor);
}
else
{
//--- Modo marcador: 4 buffers DRAW_ARROW
SetIndexStyle(0, DRAW_ARROW, EMPTY, 2, InpBullColor);
SetIndexStyle(1, DRAW_ARROW, EMPTY, 2, InpBullSqzColor);
SetIndexStyle(2, DRAW_ARROW, EMPTY, 2, InpBearColor);
SetIndexStyle(3, DRAW_ARROW, EMPTY, 2, InpBearSqzColor);
//--- Seleccionar simbolos Wingdings
int bullCode = 251;
int bearCode = 251;
switch(InpStyle)
{
case HAT_STYLE_CROSS: bullCode = 251; bearCode = 251; break;
case HAT_STYLE_DOT: bullCode = 159; bearCode = 159; break;
case HAT_STYLE_ARROW: bullCode = 233; bearCode = 234; break;
case HAT_STYLE_DIAMOND: bullCode = 108; bearCode = 108; break;
case HAT_STYLE_SQUARE: bullCode = 110; bearCode = 110; break;
case HAT_STYLE_CIRCLE: bullCode = 113; bearCode = 113; break;
case HAT_STYLE_STAR: bullCode = 117; bearCode = 117; break;
case HAT_STYLE_THUMBS: bullCode = 67; bearCode = 68; break;
}
SetIndexArrow(0, bullCode);
SetIndexArrow(1, bullCode);
SetIndexArrow(2, bearCode);
SetIndexArrow(3, bearCode);
}
//--- Etiquetas para la ventana de datos
SetIndexLabel(0, "HAT Bull");
SetIndexLabel(1, "HAT Bull Sqz");
SetIndexLabel(2, "HAT Bear");
SetIndexLabel(3, "HAT Bear Sqz");
//--- Ocultar buffers internos de la ventana de datos
for(int b = 4; b < 32; b++)
SetIndexLabel(b, NULL);
//--- Evitar basura en las primeras barras
const int drawBegin = InpT3Period * 6;
SetIndexDrawBegin(0, drawBegin);
SetIndexDrawBegin(1, drawBegin);
SetIndexDrawBegin(2, drawBegin);
SetIndexDrawBegin(3, drawBegin);
//--- Valor vacio
SetIndexEmptyValue(0, EMPTY_VALUE);
SetIndexEmptyValue(1, EMPTY_VALUE);
SetIndexEmptyValue(2, EMPTY_VALUE);
SetIndexEmptyValue(3, EMPTY_VALUE);
//=== COEFICIENTES T3 ===
double a = InpVolumeFactor;
double a2 = a * a;
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;
g_alpha = 2.0 / (InpT3Period + 1.0);
//--- Nombre corto
IndicatorShortName("HAT(" + IntegerToString(InpT3Period) + ", " +
DoubleToString(InpVolumeFactor, 2) + ")");
IndicatorDigits(Digits);
g_lastAlertTime = 0;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| OnCalculate |
//+------------------------------------------------------------------+
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[])
{
if(rates_total < InpT3Period + 1)
return(0);
const double w1 = g_alpha;
const double w2 = 1.0 - g_alpha;
int limit;
if(prev_calculated == 0)
{
//--- Inicializar barra mas antigua (indice rates_total-1 en modo series)
//--- MQL4 buffers son series por defecto: indice 0 = barra mas reciente
//--- Pero OnCalculate con arrays pasa datos como no-series (0=mas antigua)
//--- Trabajamos con indexacion 0=mas antigua (igual que MQL5)
int first = 0;
BuffHaClose[first] = (open[first] + high[first] + low[first] + close[first]) / 4.0;
BuffHaOpen[first] = (open[first] + close[first]) / 2.0;
BuffHaHigh[first] = MathMax(high[first], MathMax(BuffHaOpen[first], BuffHaClose[first]));
BuffHaLow[first] = MathMin(low[first], MathMin(BuffHaOpen[first], BuffHaClose[first]));
e1c[first] = e2c[first] = e3c[first] = e4c[first] = e5c[first] = e6c[first] = BuffHaClose[first];
e1o[first] = e2o[first] = e3o[first] = e4o[first] = e5o[first] = e6o[first] = BuffHaOpen[first];
e1h[first] = e2h[first] = e3h[first] = e4h[first] = e5h[first] = e6h[first] = BuffHaHigh[first];
e1l[first] = e2l[first] = e3l[first] = e4l[first] = e5l[first] = e6l[first] = BuffHaLow[first];
BuffBullStrong[first] = EMPTY_VALUE;
BuffBullSqueeze[first] = EMPTY_VALUE;
BuffBearStrong[first] = EMPTY_VALUE;
BuffBearSqueeze[first] = EMPTY_VALUE;
limit = 1;
}
else
{
limit = prev_calculated - 1;
}
//--- === BUCLE PRINCIPAL ===
for(int i = limit; i < rates_total; i++)
{
//=== ETAPA 1: Heikin Ashi ===
BuffHaClose[i] = (open[i] + high[i] + low[i] + close[i]) / 4.0;
BuffHaOpen[i] = (BuffHaOpen[i - 1] + BuffHaClose[i - 1]) / 2.0;
BuffHaHigh[i] = MathMax(high[i], MathMax(BuffHaOpen[i], BuffHaClose[i]));
BuffHaLow[i] = MathMin(low[i], MathMin(BuffHaOpen[i], BuffHaClose[i]));
//=== ETAPA 2: T3 haClose ===
e1c[i] = w1 * BuffHaClose[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];
double t3Close = g_c1 * e6c[i] + g_c2 * e5c[i] + g_c3 * e4c[i] + g_c4 * e3c[i];
//=== ETAPA 3: T3 haOpen ===
e1o[i] = w1 * BuffHaOpen[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];
double t3Open = g_c1 * e6o[i] + g_c2 * e5o[i] + g_c3 * e4o[i] + g_c4 * e3o[i];
//=== ETAPA 4: T3 haHigh ===
e1h[i] = w1 * BuffHaHigh[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];
double t3High = g_c1 * e6h[i] + g_c2 * e5h[i] + g_c3 * e4h[i] + g_c4 * e3h[i];
//=== ETAPA 5: T3 haLow ===
e1l[i] = w1 * BuffHaLow[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];
double t3Low = g_c1 * e6l[i] + g_c2 * e5l[i] + g_c3 * e4l[i] + g_c4 * e3l[i];
//=== ETAPA 6: Tendencia ===
bool isBullish = (t3Close > t3Open);
bool isBearish = (t3Open > t3Close);
//=== ETAPA 7: Squeeze ===
bool isSqueeze = false;
if(InpPercentSqueeze > 0.0)
{
double diff = MathAbs(t3Close - t3Open);
double avgVal = (t3Close + t3Open) / 2.0;
if(avgVal != 0.0)
isSqueeze = ((diff / avgVal) * 100.0) < InpPercentSqueeze;
}
//=== ETAPA 8: Asignar a los 4 buffers de salida ===
//--- Limpiar todos primero
BuffBullStrong[i] = EMPTY_VALUE;
BuffBullSqueeze[i] = EMPTY_VALUE;
BuffBearStrong[i] = EMPTY_VALUE;
BuffBearSqueeze[i] = EMPTY_VALUE;
if(isBullish)
{
if(isSqueeze)
BuffBullSqueeze[i] = t3Low; // Bull squeeze: debajo del precio
else
BuffBullStrong[i] = t3Low; // Bull fuerte: debajo del precio
}
else if(isBearish)
{
if(isSqueeze)
BuffBearSqueeze[i] = t3High; // Bear squeeze: encima del precio
else
BuffBearStrong[i] = t3High; // Bear fuerte: encima del precio
}
//=== ETAPA 9: Coloreo de velas ===
if(InpUseBarColor)
{
//--- En MQL4 no hay forma nativa de colorear velas individuales
//--- desde un indicador. Se requeriria un objeto grafico por vela.
//--- Omitido por rendimiento.
}
}
//--- === ALERTAS ===
if(InpEnableAlerts && rates_total >= 3)
{
int last = rates_total - 2;
int prev = last - 1;
if(time[last] != g_lastAlertTime)
{
double prevT3C = g_c1 * e6c[prev] + g_c2 * e5c[prev]
+ g_c3 * e4c[prev] + g_c4 * e3c[prev];
double prevT3O = g_c1 * e6o[prev] + g_c2 * e5o[prev]
+ g_c3 * e4o[prev] + g_c4 * e3o[prev];
double lastT3C = g_c1 * e6c[last] + g_c2 * e5c[last]
+ g_c3 * e4c[last] + g_c4 * e3c[last];
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)
{
string prefix = "HAT(" + IntegerToString(InpT3Period) + ") ";
string tf = "";
switch(Period())
{
case PERIOD_M1: tf = "M1"; break;
case PERIOD_M5: tf = "M5"; break;
case PERIOD_M15: tf = "M15"; break;
case PERIOD_M30: tf = "M30"; break;
case PERIOD_H1: tf = "H1"; break;
case PERIOD_H4: tf = "H4"; break;
case PERIOD_D1: tf = "D1"; break;
case PERIOD_W1: tf = "W1"; break;
case PERIOD_MN1: tf = "MN"; break;
default: tf = IntegerToString(Period()); break;
}
string msg = prefix + signal + " signal on " +
Symbol() + " " + tf + " 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: Algoritmo original de dman103 |
//| https://www.tradingview.com/script/OULfXjkq-Heikin-Ashi-Trend- |
//| Indicator/ |
//| |
//| 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 |
//| |
//| DIFERENCIAS MQL4 vs MQL5: |
//| - No existe DRAW_COLOR_LINE/ARROW en MQL4 |
//| - Se usan 4 buffers independientes (1 por color/estado) |
//| - En modo linea con squeeze, si la tendencia cambia entre |
//| fuerte y squeeze, la linea se interrumpe brevemente |
//| (limitacion de usar buffers separados por color) |
//| - extern en vez de input group |
//| - Coloreo de velas no disponible nativamente en MQL4 |
//| - EnumToString(Period()) no existe; se usa switch manual |
//| |
//+------------------------------------------------------------------+