540 lines
No EOL
43 KiB
MQL4
540 lines
No EOL
43 KiB
MQL4
//╔════════════════════════════════════════════════════════════════════════╗
|
|
//║ ██████╗██╗ ██╗ █████╗ ██████╗ ██████╗ █████╗ █████╗ █████╗ ███╗ ██╗ ║
|
|
//║ ██╔═══╝╚██╗██╔╝██╔══██╗██╔══██╗██╔═══╝██╔══██╗██╔═══╝██╔══██╗████╗ ██║ ║
|
|
//║ █████╗ ╚███╔╝ ██║ ██║██████╔╝█████╗ ███████║██║ ██║ ██║██╔██╗██║ ║
|
|
//║ ██╔══╝ ██╔██╗ ██║ ██║██╔══██╗██╔══╝ ██╔══██║██║ ██║ ██║██║╚████║ ║
|
|
//║ ██████╗██╔╝ ██╗╚█████╔╝██████╔╝██████╗██║ ██║╚█████╗╚█████╔╝██║ ╚███║ ║
|
|
//║ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚════╝ ╚═╝ ╚══╝ ║
|
|
//╚═══════ Algorithms that observe ════ Signals that speak ════════════════╝
|
|
//+------------------------------------------------------------------+
|
|
//| 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 |
|
|
//| |
|
|
//+------------------------------------------------------------------+ |