302 lines
No EOL
22 KiB
MQL4
302 lines
No EOL
22 KiB
MQL4
//╔════════════════════════════════════════════════════════════════════════╗
|
|
//║ ██████╗██╗ ██╗ █████╗ ██████╗ ██████╗ █████╗ █████╗ █████╗ ███╗ ██╗ ║
|
|
//║ ██╔═══╝╚██╗██╔╝██╔══██╗██╔══██╗██╔═══╝██╔══██╗██╔═══╝██╔══██╗████╗ ██║ ║
|
|
//║ █████╗ ╚███╔╝ ██║ ██║██████╔╝█████╗ ███████║██║ ██║ ██║██╔██╗██║ ║
|
|
//║ ██╔══╝ ██╔██╗ ██║ ██║██╔══██╗██╔══╝ ██╔══██║██║ ██║ ██║██║╚████║ ║
|
|
//║ ██████╗██╔╝ ██╗╚█████╔╝██████╔╝██████╗██║ ██║╚█████╗╚█████╔╝██║ ╚███║ ║
|
|
//║ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚════╝ ╚═╝ ╚══╝ ║
|
|
//╚═══════ Algorithms that observe ════ Signals that speak ════════════════╝
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Archivo: Donchian_Channels_Trend.mq4 |
|
|
//| Origen: Replicación del "Donchian Channels Trend" de TradingView |
|
|
//| Autor Original: holdon_to_profits |
|
|
//| Descripción: Indicador de canales con memoria de estado (FSM). |
|
|
//| Reescrito nativamente para MQL4 respetando el |
|
|
//| ecosistema y la paleta de Exobeacon Labs. |
|
|
//+------------------------------------------------------------------+
|
|
|
|
#property copyright "Exobeacon Labs"
|
|
#property link "https://www.exobeacon.com"
|
|
#property version "1.00"
|
|
#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 "---------------------------------------"
|
|
#property description "mql5.com/en/users/ulisescalb"
|
|
#property description "github.com/Exobeacon-Labs"
|
|
#property strict
|
|
|
|
#property indicator_chart_window
|
|
#property indicator_buffers 8
|
|
|
|
// --- Mapeo de Colores del Ecosistema Exobeacon (Corregido a paleta definitiva) ---
|
|
// Upper/Lower Bullish Main (clrDeepSkyBlue)
|
|
#property indicator_color1 clrDeepSkyBlue
|
|
#property indicator_color2 clrDeepSkyBlue
|
|
// Upper/Lower Bearish Main (clrDeepPink)
|
|
#property indicator_color3 clrDeepPink
|
|
#property indicator_color4 clrDeepPink
|
|
// Basis Line Neutral (clrSilver)
|
|
#property indicator_color5 clrSilver
|
|
|
|
// Buffers 6, 7 y 8 seran ocultos (DRAW\_NONE)
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| ENTRADAS DEL USUARIO (Inputs) |
|
|
//+------------------------------------------------------------------+
|
|
input string s1 = "=== Donchian Settings ===";
|
|
input int InpLength = 20; // Lookback Period (Length)
|
|
|
|
input string s2 = "=== 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) |
|
|
//+------------------------------------------------------------------+
|
|
// Búferes visuales (separados por color para simular línea dinámica en MQL4)
|
|
double ExtUpperBull[]; // Índice 0
|
|
double ExtLowerBull[]; // Índice 1
|
|
double ExtUpperBear[]; // Índice 2
|
|
double ExtLowerBear[]; // Índice 3
|
|
double ExtBasis[]; // Índice 4
|
|
|
|
// Búferes ocultos lógicos (DRAW\_NONE obligatorio)
|
|
double ExtTrend[]; // Índice 5: Memoria de tendencia (1 = Bull, -1 = Bear)
|
|
double ExtRawUpper[]; // Índice 6: Canal crudo superior
|
|
double ExtRawLower[]; // Índice 7: Canal crudo inferior
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| VARIABLES GLOBALES AUXILIARES |
|
|
//+------------------------------------------------------------------+
|
|
datetime g_lastAlertTime = 0;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| INIT FUNCTION |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
// 1. Validación estricta de parámetros
|
|
if(InpLength < 1)
|
|
{
|
|
Print("[Exobeacon] Error: Lookback Period must be greater than 0.");
|
|
return INIT_PARAMETERS_INCORRECT;
|
|
}
|
|
|
|
// 2. Mapeo de búferes de indicador
|
|
SetIndexBuffer(0, ExtUpperBull);
|
|
SetIndexBuffer(1, ExtLowerBull);
|
|
SetIndexBuffer(2, ExtUpperBear);
|
|
SetIndexBuffer(3, ExtLowerBear);
|
|
SetIndexBuffer(4, ExtBasis);
|
|
SetIndexBuffer(5, ExtTrend);
|
|
SetIndexBuffer(6, ExtRawUpper);
|
|
SetIndexBuffer(7, ExtRawLower);
|
|
|
|
// 3. Estilos explícitos (Crucial en MQL4 para evitar líneas negras basura)
|
|
SetIndexStyle(0, DRAW_LINE, STYLE_SOLID, 2);
|
|
SetIndexStyle(1, DRAW_LINE, STYLE_SOLID, 2);
|
|
SetIndexStyle(2, DRAW_LINE, STYLE_SOLID, 2);
|
|
SetIndexStyle(3, DRAW_LINE, STYLE_SOLID, 2);
|
|
SetIndexStyle(4, DRAW_LINE, STYLE_DASHDOT, 1);
|
|
|
|
// Búferes de cálculo ocultos
|
|
SetIndexStyle(5, DRAW_NONE);
|
|
SetIndexStyle(6, DRAW_NONE);
|
|
SetIndexStyle(7, DRAW_NONE);
|
|
|
|
// 4. Configuración de valores vacíos y etiquetas
|
|
for(int i = 0; i < 8; i++)
|
|
{
|
|
SetIndexEmptyValue(i, EMPTY_VALUE);
|
|
}
|
|
|
|
SetIndexLabel(0, "Upper Bullish");
|
|
SetIndexLabel(1, "Lower Bullish");
|
|
SetIndexLabel(2, "Upper Bearish");
|
|
SetIndexLabel(3, "Lower Bearish");
|
|
SetIndexLabel(4, "Basis Neutral");
|
|
|
|
// Nombres cortos de ventana
|
|
string short_name = StringFormat("Donchian Trend (%d)", InpLength);
|
|
IndicatorShortName(short_name);
|
|
|
|
return INIT_SUCCEEDED;
|
|
|
|
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| DEINIT FUNCTION |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
// Limpieza estricta de recursos
|
|
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(Bars <= InpLength) return 0;
|
|
|
|
// Lógica de barras a procesar en MQL4 (Indexación inversa)
|
|
int counted_bars = IndicatorCounted();
|
|
if(counted_bars < 0) return -1;
|
|
if(counted_bars > 0) counted_bars--;
|
|
|
|
int limit = Bars - counted_bars - 1;
|
|
|
|
// Límite de seguridad para el lookback
|
|
if(limit > Bars - InpLength - 1)
|
|
limit = Bars - InpLength - 1;
|
|
|
|
// Iteración principal (dirección MQL4: de pasado a presente, índice disminuye)
|
|
for(int i = limit; i >= 0; i--)
|
|
{
|
|
// 1. Encontrar Máximos y Mínimos en la ventana N usando funciones nativas
|
|
// Nota: iHighest/iLowest retorna el índice de la barra (shift)
|
|
int highest_idx = iHighest(NULL, 0, MODE_HIGH, InpLength, i);
|
|
int lowest_idx = iLowest(NULL, 0, MODE_LOW, InpLength, i);
|
|
|
|
// Manejo seguro por si falla iHighest/iLowest
|
|
if(highest_idx == -1 || lowest_idx == -1) continue;
|
|
|
|
double upper_val = High[highest_idx];
|
|
double lower_val = Low[lowest_idx];
|
|
|
|
// Guardar valores crudos para referenciarlos en la siguiente vela [i+1]
|
|
ExtRawUpper[i] = upper_val;
|
|
ExtRawLower[i] = lower_val;
|
|
ExtBasis[i] = (upper_val + lower_val) / 2.0;
|
|
|
|
// 2. Máquina de Estados (Trend Memory FSM)
|
|
int current_trend = 1; // Asumir alcista por defecto al inicio
|
|
|
|
// Si no estamos en la barra más antigua, heredar memoria de la barra anterior (i+1)
|
|
if(i < Bars - 1)
|
|
{
|
|
current_trend = (int)ExtTrend[i+1];
|
|
|
|
// Regla 1: Ruptura alcista contra el borde dinámico de la vela pasada
|
|
if(ExtRawUpper[i+1] != EMPTY_VALUE && High[i] >= ExtRawUpper[i+1])
|
|
{
|
|
current_trend = 1;
|
|
}
|
|
// Regla 2: Ruptura bajista contra el borde dinámico de la vela pasada
|
|
else if(ExtRawLower[i+1] != EMPTY_VALUE && Low[i] <= ExtRawLower[i+1])
|
|
{
|
|
current_trend = -1;
|
|
}
|
|
}
|
|
|
|
// Guardar estado en el búfer oculto
|
|
ExtTrend[i] = current_trend;
|
|
|
|
// 3. Ruteo de Colores (Transformación visual en múltiples búferes)
|
|
// MQL4 no permite coloreado dinámico por segmento fácilmente sin dividir búferes
|
|
if(current_trend == 1) // Estado Alcista
|
|
{
|
|
ExtUpperBull[i] = upper_val;
|
|
ExtLowerBull[i] = lower_val;
|
|
ExtUpperBear[i] = EMPTY_VALUE;
|
|
ExtLowerBear[i] = EMPTY_VALUE;
|
|
}
|
|
else // Estado Bajista
|
|
{
|
|
ExtUpperBull[i] = EMPTY_VALUE;
|
|
ExtLowerBull[i] = EMPTY_VALUE;
|
|
ExtUpperBear[i] = upper_val;
|
|
ExtLowerBear[i] = lower_val;
|
|
}
|
|
|
|
// 4. Sistema de Alertas Estructuradas (Evaluado al cierre de la vela index 1)
|
|
if(InpEnableAlerts && i == 1)
|
|
{
|
|
// Detectar cambio de estado entre vela recién cerrada (1) y la anterior (2)
|
|
if(ExtTrend[1] != ExtTrend[2] && ExtTrend[2] != EMPTY_VALUE)
|
|
{
|
|
TriggerAlerts((int)ExtTrend[1], Time[1], Close[1]);
|
|
}
|
|
}
|
|
}
|
|
|
|
return rates_total;
|
|
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| FUNCIONES AUXILIARES |
|
|
//+------------------------------------------------------------------+
|
|
|
|
// Disparador multi-canal de alertas y logs estructurados en ASCII puro
|
|
void TriggerAlerts(int trend_state, datetime signal_time, double close_price)
|
|
{
|
|
// Filtrado estricto anti-repintado: solo una alerta por vela cerrada
|
|
if(signal_time <= g_lastAlertTime) return;
|
|
g_lastAlertTime = signal_time;
|
|
|
|
|
|
// Formateo de strings (ASCII únicamente para evitar problemas en log/MQL Market)
|
|
string trend_name = (trend_state == 1) ? "BUY" : "SELL";
|
|
|
|
// Log Estructurado Exobeacon
|
|
string msg = StringFormat("[Exobeacon] Signal=%s | Symbol=%s | TF=%d | Price=%s",
|
|
trend_name, Symbol(), Period(), DoubleToString(close_price, Digits));
|
|
|
|
// Distribución a canales habilitados
|
|
if(InpAlertPopup) Alert(msg);
|
|
if(InpAlertSound) PlaySound("alert.wav");
|
|
if(InpAlertPush) SendNotification(msg);
|
|
if(InpAlertEmail) SendMail("Exobeacon Breakout", msg);
|
|
|
|
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")
|
|
*/ |