278 lines
No EOL
12 KiB
MQL5
278 lines
No EOL
12 KiB
MQL5
//╔════════════════════════════════════════════════════════════════════════╗
|
|
//║ ██████╗██╗ ██╗ █████╗ ██████╗ ██████╗ █████╗ █████╗ █████╗ ███╗ ██╗ ║
|
|
//║ ██╔═══╝╚██╗██╔╝██╔══██╗██╔══██╗██╔═══╝██╔══██╗██╔═══╝██╔══██╗████╗ ██║ ║
|
|
//║ █████╗ ╚███╔╝ ██║ ██║██████╔╝█████╗ ███████║██║ ██║ ██║██╔██╗██║ ║
|
|
//║ ██╔══╝ ██╔██╗ ██║ ██║██╔══██╗██╔══╝ ██╔══██║██║ ██║ ██║██║╚████║ ║
|
|
//║ ██████╗██╔╝ ██╗╚█████╔╝██████╔╝██████╗██║ ██║╚█████╗╚█████╔╝██║ ╚███║ ║
|
|
//║ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚════╝ ╚═╝ ╚══╝ ║
|
|
//╚═══════ Algorithms that observe ════ Signals that speak ════════════════╝
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Archivo: Donchian_Channels_Trend.mq5 |
|
|
//| Origen: Replicación del "Donchian Channels Trend" de TradingView |
|
|
//| Autor Original: holdon_to_profits |
|
|
//| Descripción: Indicador de canales con memoria de estado (FSM). |
|
|
//| Detecta la tendencia basándose en rupturas de la |
|
|
//| estructura previa y cambia de color dinámicamente. |
|
|
//+------------------------------------------------------------------+
|
|
|
|
#property copyright "Exobeacon Labs"
|
|
#property link "https://www.exobeacon.com/"
|
|
#property version "1.0"
|
|
#property description "Donchian Channels Trend (holdon_to_profits) v1.0"
|
|
#property description "Trend-following breakout indicator."
|
|
#property description "Dynamic coloring based on trend state memory."
|
|
#property description "Identifies directional bias and structural levels."
|
|
#property description " "
|
|
#property description "〰〰〰〰〰((👽))〰〰〰〰〰"
|
|
#property description "🛸 mql5.com/en/users/ulisescalb"
|
|
#property description "🛸 github.com/Exobeacon-Labs"
|
|
#property strict
|
|
|
|
#property indicator_chart_window
|
|
#property indicator_buffers 7
|
|
#property indicator_plots 3
|
|
|
|
// --- Configuración Plot 1: Upper Band ---
|
|
#property indicator_label1 "Upper Band"
|
|
#property indicator_type1 DRAW_COLOR_LINE
|
|
#property indicator_color1 clrLime, clrRed
|
|
#property indicator_style1 STYLE_SOLID
|
|
#property indicator_width1 2
|
|
|
|
// --- Configuración Plot 2: Lower Band ---
|
|
#property indicator_label2 "Lower Band"
|
|
#property indicator_type2 DRAW_COLOR_LINE
|
|
#property indicator_color2 clrLime, clrRed
|
|
#property indicator_style2 STYLE_SOLID
|
|
#property indicator_width2 2
|
|
|
|
// --- Configuración Plot 3: Basis Line ---
|
|
#property indicator_label3 "Basis Line"
|
|
#property indicator_type3 DRAW_COLOR_LINE
|
|
#property indicator_color3 clrLime, clrRed
|
|
#property indicator_style3 STYLE_DASHDOT
|
|
#property indicator_width3 1
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| ENTRADAS DEL USUARIO (Inputs) |
|
|
//+------------------------------------------------------------------+
|
|
input group "====== Donchian Settings ======"
|
|
input int InpLength = 20; // Lookback Period (Length)
|
|
|
|
input group "====== Alert Settings ======"
|
|
input bool InpEnableAlerts = false; // Enable All Alerts
|
|
input bool InpAlertPopup = true; // Popup Alerts
|
|
input bool InpAlertSound = true; // Sound Alerts
|
|
input bool InpAlertPush = false; // Push Notifications
|
|
input bool InpAlertEmail = false; // Email Alerts
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| BÚFERES GLOBALES (Buffers) |
|
|
//+------------------------------------------------------------------+
|
|
double BufferUpper[];
|
|
double BufferUpperColor[];
|
|
double BufferLower[];
|
|
double BufferLowerColor[];
|
|
double BufferBasis[];
|
|
double BufferBasisColor[];
|
|
double BufferTrend[]; // Búfer oculto para memoria de tendencia (1 = Bullish, -1 = Bearish)
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| VARIABLES GLOBALES AUXILIARES |
|
|
//+------------------------------------------------------------------+
|
|
datetime g_lastAlertTime = 0; // Control de tiempo para evitar spam de alertas
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| INIT FUNCTION |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
// 1. Validación estricta de parámetros
|
|
if(InpLength < 1)
|
|
{
|
|
Print("Error: Lookback Period must be greater than 0.");
|
|
return INIT_PARAMETERS_INCORRECT;
|
|
}
|
|
|
|
// 2. Mapeo de búferes de indicador
|
|
SetIndexBuffer(0, BufferUpper, INDICATOR_DATA);
|
|
SetIndexBuffer(1, BufferUpperColor, INDICATOR_COLOR_INDEX);
|
|
SetIndexBuffer(2, BufferLower, INDICATOR_DATA);
|
|
SetIndexBuffer(3, BufferLowerColor, INDICATOR_COLOR_INDEX);
|
|
SetIndexBuffer(4, BufferBasis, INDICATOR_DATA);
|
|
SetIndexBuffer(5, BufferBasisColor, INDICATOR_COLOR_INDEX);
|
|
SetIndexBuffer(6, BufferTrend, INDICATOR_CALCULATIONS);
|
|
|
|
// 3. Inicialización de valores vacíos y arrays
|
|
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
|
|
PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
|
|
PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE);
|
|
|
|
ArrayInitialize(BufferUpper, EMPTY_VALUE);
|
|
ArrayInitialize(BufferLower, EMPTY_VALUE);
|
|
ArrayInitialize(BufferBasis, EMPTY_VALUE);
|
|
ArrayInitialize(BufferTrend, 1.0); // Asume tendencia alcista inicialmente
|
|
|
|
// 4. Configuración visual para la ventana del indicador
|
|
IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
|
|
string short_name = StringFormat("Donchian Trend (%d)", InpLength);
|
|
IndicatorSetString(INDICATOR_SHORTNAME, short_name);
|
|
|
|
// Evitar renderizar basura visual en las primeras velas
|
|
PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, InpLength);
|
|
PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, InpLength);
|
|
PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, InpLength);
|
|
|
|
return INIT_SUCCEEDED;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| DEINIT FUNCTION |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
// Limpieza de objetos gráficos y comentarios si existieran
|
|
Comment("");
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| CALCULATION FUNCTION |
|
|
//+------------------------------------------------------------------+
|
|
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[])
|
|
{
|
|
// Evitar cálculos si no hay suficientes barras
|
|
if(rates_total < InpLength) return 0;
|
|
|
|
// Determinar el índice de inicio optimizado
|
|
int limit = prev_calculated == 0 ? InpLength - 1 : prev_calculated - 1;
|
|
if (limit < InpLength - 1) limit = InpLength - 1;
|
|
|
|
// Iteración principal (dirección estándar MQL5: de antiguo a reciente)
|
|
for(int i = limit; i < rates_total; i++)
|
|
{
|
|
// 1. Encontrar Máximos y Mínimos en la ventana N
|
|
double highest = high[i];
|
|
double lowest = low[i];
|
|
|
|
for(int j = 0; j < InpLength; j++)
|
|
{
|
|
if(high[i - j] > highest) highest = high[i - j];
|
|
if(low[i - j] < lowest) lowest = low[i - j];
|
|
}
|
|
|
|
// 2. Asignación de datos matemáticos a los búferes
|
|
BufferUpper[i] = highest;
|
|
BufferLower[i] = lowest;
|
|
BufferBasis[i] = (highest + lowest) / 2.0;
|
|
|
|
// 3. Máquina de Estados (Trend Memory FSM)
|
|
int current_trend = 1; // Valor por defecto
|
|
|
|
if (i > InpLength - 1)
|
|
{
|
|
// Heredar el estado de la barra anterior (Memoria)
|
|
current_trend = (int)BufferTrend[i-1];
|
|
|
|
// Regla 1: Ruptura alcista contra el borde dinámico de la iteración previa
|
|
if(BufferUpper[i-1] != EMPTY_VALUE && high[i] >= BufferUpper[i-1])
|
|
{
|
|
current_trend = 1;
|
|
}
|
|
// Regla 2: Ruptura bajista contra el borde dinámico de la iteración previa
|
|
else if(BufferLower[i-1] != EMPTY_VALUE && low[i] <= BufferLower[i-1])
|
|
{
|
|
current_trend = -1;
|
|
}
|
|
}
|
|
|
|
// Guardar estado
|
|
BufferTrend[i] = current_trend;
|
|
|
|
// 4. Transformación Gráfica (Color Routing)
|
|
// color_idx 0 = clrLime, 1 = clrRed
|
|
int color_idx = (current_trend == 1) ? 0 : 1;
|
|
|
|
BufferUpperColor[i] = color_idx;
|
|
BufferLowerColor[i] = color_idx;
|
|
BufferBasisColor[i] = color_idx;
|
|
|
|
// 5. Sistema de Alertas (Evaluado solo en el cierre de la vela para evitar repintado)
|
|
if(InpEnableAlerts && i == rates_total - 2 && i > limit)
|
|
{
|
|
if(BufferTrend[i] != BufferTrend[i-1])
|
|
{
|
|
TriggerAlerts(current_trend, time[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Retornar número de barras calculadas para la siguiente iteración
|
|
return rates_total;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| FUNCIONES AUXILIARES |
|
|
//+------------------------------------------------------------------+
|
|
|
|
// Disparador multi-canal de alertas
|
|
void TriggerAlerts(int trend_state, datetime signal_time)
|
|
{
|
|
// Filtrado de seguridad: solo una alerta por vela
|
|
if(signal_time <= g_lastAlertTime) return;
|
|
g_lastAlertTime = signal_time;
|
|
|
|
// Preparación del mensaje (ASCII únicamente)
|
|
string trend_name = (trend_state == 1) ? "BULLISH" : "BEARISH";
|
|
string msg = StringFormat("[Donchian Trend] %s %s - Trend shifted to %s",
|
|
_Symbol, EnumToString((ENUM_TIMEFRAMES)_Period), trend_name);
|
|
|
|
// Ejecución de rutas de salida
|
|
if(InpAlertPopup) Alert(msg);
|
|
if(InpAlertSound) PlaySound("alert.wav");
|
|
if(InpAlertPush) SendNotification(msg);
|
|
if(InpAlertEmail) SendMail("Donchian Trend Breakout", msg);
|
|
|
|
// Registro en Journal
|
|
Print(msg);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| REFERENCIA ORIGINAL PINE SCRIPT (DOCUMENTACIÓN INTERNA) |
|
|
//+------------------------------------------------------------------+
|
|
/*
|
|
//@version=5
|
|
indicator("Donchian Channels Trend", overlay=true)
|
|
|
|
// --- Inputs ---
|
|
length = input.int(20, title="Length")
|
|
|
|
// --- Core Calculations ---
|
|
upper = ta.highest(high, length)
|
|
lower = ta.lowest(low, length)
|
|
basis = math.avg(upper, lower)
|
|
|
|
// --- State Machine ---
|
|
var int trend = 1
|
|
|
|
if high >= upper[1]
|
|
trend := 1
|
|
else if low <= lower[1]
|
|
trend := -1
|
|
|
|
// --- Coloring Output ---
|
|
col = trend == 1 ? color.lime : color.red
|
|
|
|
plot(upper, color=col, linewidth=2, title="Upper Band")
|
|
plot(lower, color=col, linewidth=2, title="Lower Band")
|
|
plot(basis, color=col, style=plot.style_dashdot, title="Basis Line")
|
|
*/ |