Donchian-Channels-Trend/Donchian_Channels_Trend.mq4

302 lines
22 KiB
MQL4
Raw Permalink Normal View History

<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: Donchian_Channels_Trend.mq4 |
//| Origen: Replicaci<EFBFBD>n del "Donchian Channels Trend" de TradingView |
//| Autor Original: holdon_to_profits |
//| Descripci<EFBFBD>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<EFBFBD>FERES GLOBALES (Buffers) |
//+------------------------------------------------------------------+
// B<EFBFBD>feres visuales (separados por color para simular l<EFBFBD>nea din<EFBFBD>mica en MQL4)
double ExtUpperBull[]; // <EFBFBD>ndice 0
double ExtLowerBull[]; // <EFBFBD>ndice 1
double ExtUpperBear[]; // <EFBFBD>ndice 2
double ExtLowerBear[]; // <EFBFBD>ndice 3
double ExtBasis[]; // <EFBFBD>ndice 4
// B<EFBFBD>feres ocultos l<EFBFBD>gicos (DRAW\_NONE obligatorio)
double ExtTrend[]; // <EFBFBD>ndice 5: Memoria de tendencia (1 = Bull, -1 = Bear)
double ExtRawUpper[]; // <EFBFBD>ndice 6: Canal crudo superior
double ExtRawLower[]; // <EFBFBD>ndice 7: Canal crudo inferior
//+------------------------------------------------------------------+
//| VARIABLES GLOBALES AUXILIARES |
//+------------------------------------------------------------------+
datetime g_lastAlertTime = 0;
//+------------------------------------------------------------------+
//| INIT FUNCTION |
//+------------------------------------------------------------------+
int OnInit()
{
// 1. Validaci<EFBFBD>n estricta de par<EFBFBD>metros
if(InpLength < 1)
{
Print("[Exobeacon] Error: Lookback Period must be greater than 0.");
return INIT_PARAMETERS_INCORRECT;
}
// 2. Mapeo de b<EFBFBD>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<EFBFBD>citos (Crucial en MQL4 para evitar l<EFBFBD>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<EFBFBD>feres de c<EFBFBD>lculo ocultos
SetIndexStyle(5, DRAW_NONE);
SetIndexStyle(6, DRAW_NONE);
SetIndexStyle(7, DRAW_NONE);
// 4. Configuraci<EFBFBD>n de valores vac<EFBFBD>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<EFBFBD>lculos si no hay suficientes barras
if(Bars <= InpLength) return 0;
// L<EFBFBD>gica de barras a procesar en MQL4 (Indexaci<EFBFBD>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<EFBFBD>mite de seguridad para el lookback
if(limit > Bars - InpLength - 1)
limit = Bars - InpLength - 1;
// Iteraci<EFBFBD>n principal (direcci<EFBFBD>n MQL4: de pasado a presente, <EFBFBD>ndice disminuye)
for(int i = limit; i >= 0; i--)
{
// 1. Encontrar M<EFBFBD>ximos y M<EFBFBD>nimos en la ventana N usando funciones nativas
// Nota: iHighest/iLowest retorna el <EFBFBD>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<EFBFBD>quina de Estados (Trend Memory FSM)
int current_trend = 1; // Asumir alcista por defecto al inicio
// Si no estamos en la barra m<EFBFBD>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<EFBFBD>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<EFBFBD>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<EFBFBD>fer oculto
ExtTrend[i] = current_trend;
// 3. Ruteo de Colores (Transformaci<EFBFBD>n visual en m<EFBFBD>ltiples b<EFBFBD>feres)
// MQL4 no permite coloreado din<EFBFBD>mico por segmento f<EFBFBD>cilmente sin dividir b<EFBFBD>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<EFBFBD>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 <EFBFBD>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<EFBFBD>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<EFBFBD>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")
*/