653 lines
No EOL
57 KiB
MQL5
653 lines
No EOL
57 KiB
MQL5
//╔════════════════════════════════════════════════════════════════════════╗
|
|
//║ ██████╗██╗ ██╗ █████╗ ██████╗ ██████╗ █████╗ █████╗ █████╗ ███╗ ██╗ ║
|
|
//║ ██╔═══╝╚██╗██╔╝██╔══██╗██╔══██╗██╔═══╝██╔══██╗██╔═══╝██╔══██╗████╗ ██║ ║
|
|
//║ █████╗ ╚███╔╝ ██║ ██║██████╔╝█████╗ ███████║██║ ██║ ██║██╔██╗██║ ║
|
|
//║ ██╔══╝ ██╔██╗ ██║ ██║██╔══██╗██╔══╝ ██╔══██║██║ ██║ ██║██║╚████║ ║
|
|
//║ ██████╗██╔╝ ██╗╚█████╔╝██████╔╝██████╗██║ ██║╚█████╗╚█████╔╝██║ ╚███║ ║
|
|
//║ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚════╝ ╚═╝ ╚══╝ ║
|
|
//╚═══════ 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). |
|
|
//| |
|
|
//+------------------------------------------------------------------+ |