297 lines
No EOL
20 KiB
MQL5
297 lines
No EOL
20 KiB
MQL5
//╔════════════════════════════════════════════════════════════════════════╗
|
|
//║ ██████╗██╗ ██╗ █████╗ ██████╗ ██████╗ █████╗ █████╗ █████╗ ███╗ ██╗ ║
|
|
//║ ██╔═══╝╚██╗██╔╝██╔══██╗██╔══██╗██╔═══╝██╔══██╗██╔═══╝██╔══██╗████╗ ██║ ║
|
|
//║ █████╗ ╚███╔╝ ██║ ██║██████╔╝█████╗ ███████║██║ ██║ ██║██╔██╗██║ ║
|
|
//║ ██╔══╝ ██╔██╗ ██║ ██║██╔══██╗██╔══╝ ██╔══██║██║ ██║ ██║██║╚████║ ║
|
|
//║ ██████╗██╔╝ ██╗╚█████╔╝██████╔╝██████╗██║ ██║╚█████╗╚█████╔╝██║ ╚███║ ║
|
|
//║ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚════╝ ╚═╝ ╚══╝ ║
|
|
//╚═══════ Algorithms that observe ══════ Signals that speak ══════════════╝
|
|
|
|
// Indicador técnico SuperTrend
|
|
// Basado en el concepto original de Olivier Seban.
|
|
// Inspirado en la visualización popularizada por KivancOzbilgic.
|
|
// Implementación para MetaTrader por Ulises Calderón Bautista.
|
|
|
|
#property copyright "Exobeacon Labs"
|
|
#property link "https://www.exobeacon.com/"
|
|
#property version "1.3"
|
|
#property description "SuperTrend — Adaptive Trend-Following Indicator"
|
|
#property description "ATR-based dynamic support/resistance overlay that adapts to volatility in real time."
|
|
#property description " "
|
|
#property description "〰〰〰〰〰((👽))〰〰〰〰〰"
|
|
#property description "🛸 mql5.com/en/users/ulisescalb"
|
|
#property description "🛸 github.com/Exobeacon-Labs"
|
|
|
|
#property indicator_chart_window
|
|
#property indicator_buffers 4
|
|
#property indicator_plots 2
|
|
|
|
// Propiedades de las líneas
|
|
#property indicator_label1 "SuperTrend Up"
|
|
#property indicator_type1 DRAW_LINE
|
|
#property indicator_color1 clrLime
|
|
#property indicator_style1 STYLE_SOLID
|
|
#property indicator_width1 2
|
|
|
|
#property indicator_label2 "SuperTrend Down"
|
|
#property indicator_type2 DRAW_LINE
|
|
#property indicator_color2 clrRed
|
|
#property indicator_style2 STYLE_SOLID
|
|
#property indicator_width2 2
|
|
|
|
// Parámetros de entrada
|
|
input int InpAtrPeriod = 10; // ATR Length
|
|
input double InpFactor = 3.0; // Factor
|
|
input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_MEDIAN; // Applied Price
|
|
|
|
// Buffers del indicador
|
|
double UpTrendBuffer[];
|
|
double DownTrendBuffer[];
|
|
double SuperTrendBuffer[];
|
|
double DirectionBuffer[];
|
|
|
|
// Handle del ATR
|
|
int atrHandle;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Custom indicator initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
// Validación de parámetros
|
|
if(InpAtrPeriod <= 0)
|
|
{
|
|
Print("Error: ATR Period debe ser mayor que 0");
|
|
return(INIT_PARAMETERS_INCORRECT);
|
|
}
|
|
|
|
if(InpFactor <= 0)
|
|
{
|
|
Print("Error: Factor debe ser mayor que 0");
|
|
return(INIT_PARAMETERS_INCORRECT);
|
|
}
|
|
|
|
// Asignación de buffers
|
|
SetIndexBuffer(0, UpTrendBuffer, INDICATOR_DATA);
|
|
SetIndexBuffer(1, DownTrendBuffer, INDICATOR_DATA);
|
|
SetIndexBuffer(2, SuperTrendBuffer, INDICATOR_CALCULATIONS);
|
|
SetIndexBuffer(3, DirectionBuffer, INDICATOR_CALCULATIONS);
|
|
|
|
// Configuración de valores vacíos
|
|
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);
|
|
PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0.0);
|
|
|
|
// Inicializar arrays como series
|
|
ArraySetAsSeries(UpTrendBuffer, true);
|
|
ArraySetAsSeries(DownTrendBuffer, true);
|
|
ArraySetAsSeries(SuperTrendBuffer, true);
|
|
ArraySetAsSeries(DirectionBuffer, true);
|
|
|
|
// Crear handle del ATR
|
|
atrHandle = iATR(_Symbol, _Period, InpAtrPeriod);
|
|
if(atrHandle == INVALID_HANDLE)
|
|
{
|
|
Print("Error al crear el indicador ATR");
|
|
return(INIT_FAILED);
|
|
}
|
|
|
|
// Nombre del indicador
|
|
string priceLabel = "";
|
|
switch(InpAppliedPrice)
|
|
{
|
|
case PRICE_CLOSE: priceLabel = "Close"; break;
|
|
case PRICE_OPEN: priceLabel = "Open"; break;
|
|
case PRICE_HIGH: priceLabel = "High"; break;
|
|
case PRICE_LOW: priceLabel = "Low"; break;
|
|
case PRICE_MEDIAN: priceLabel = "Median"; break;
|
|
case PRICE_TYPICAL: priceLabel = "Typical"; break;
|
|
case PRICE_WEIGHTED: priceLabel = "Weighted"; break;
|
|
}
|
|
|
|
IndicatorSetString(INDICATOR_SHORTNAME,
|
|
StringFormat("SuperTrend(%d,%.2f,%s)", InpAtrPeriod, InpFactor, priceLabel));
|
|
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Custom indicator deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
if(atrHandle != INVALID_HANDLE)
|
|
IndicatorRelease(atrHandle);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Función auxiliar para obtener el precio aplicado |
|
|
//+------------------------------------------------------------------+
|
|
double GetAppliedPrice(const int pos,
|
|
const double &open[],
|
|
const double &high[],
|
|
const double &low[],
|
|
const double &close[])
|
|
{
|
|
switch(InpAppliedPrice)
|
|
{
|
|
case PRICE_CLOSE:
|
|
return close[pos];
|
|
|
|
case PRICE_OPEN:
|
|
return open[pos];
|
|
|
|
case PRICE_HIGH:
|
|
return high[pos];
|
|
|
|
case PRICE_LOW:
|
|
return low[pos];
|
|
|
|
case PRICE_MEDIAN:
|
|
return (high[pos] + low[pos]) / 2.0;
|
|
|
|
case PRICE_TYPICAL:
|
|
return (high[pos] + low[pos] + close[pos]) / 3.0;
|
|
|
|
case PRICE_WEIGHTED:
|
|
return (high[pos] + low[pos] + close[pos] + close[pos]) / 4.0;
|
|
|
|
default:
|
|
return (high[pos] + low[pos]) / 2.0; // Default a Median
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Custom indicator iteration 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[])
|
|
{
|
|
if(rates_total < InpAtrPeriod)
|
|
return(0);
|
|
|
|
// Configurar arrays como series
|
|
ArraySetAsSeries(open, true);
|
|
ArraySetAsSeries(high, true);
|
|
ArraySetAsSeries(low, true);
|
|
ArraySetAsSeries(close, true);
|
|
|
|
// Obtener valores del ATR
|
|
double atr[];
|
|
ArraySetAsSeries(atr, true);
|
|
|
|
int to_copy = rates_total - prev_calculated + InpAtrPeriod + 1;
|
|
if(prev_calculated == 0)
|
|
to_copy = rates_total;
|
|
|
|
if(CopyBuffer(atrHandle, 0, 0, to_copy, atr) <= 0)
|
|
{
|
|
Print("Error al copiar datos del ATR");
|
|
return(0);
|
|
}
|
|
|
|
// Determinar desde dónde calcular
|
|
int start;
|
|
if(prev_calculated == 0)
|
|
start = InpAtrPeriod;
|
|
else
|
|
start = prev_calculated - 1;
|
|
|
|
// Calcular SuperTrend
|
|
for(int i = start; i < rates_total; i++)
|
|
{
|
|
int pos = rates_total - 1 - i;
|
|
|
|
// Calcular línea central usando el precio aplicado seleccionado
|
|
double basePrice = GetAppliedPrice(pos, open, high, low, close);
|
|
|
|
// Calcular bandas básicas
|
|
double upperBand = basePrice + InpFactor * atr[pos];
|
|
double lowerBand = basePrice - InpFactor * atr[pos];
|
|
|
|
// Ajustar bandas según la barra anterior
|
|
if(i > InpAtrPeriod)
|
|
{
|
|
int prevPos = pos + 1;
|
|
|
|
// Ajustar banda superior
|
|
if(upperBand < SuperTrendBuffer[prevPos] || close[prevPos] > SuperTrendBuffer[prevPos])
|
|
upperBand = upperBand;
|
|
else
|
|
upperBand = SuperTrendBuffer[prevPos];
|
|
|
|
// Ajustar banda inferior
|
|
if(lowerBand > SuperTrendBuffer[prevPos] || close[prevPos] < SuperTrendBuffer[prevPos])
|
|
lowerBand = lowerBand;
|
|
else
|
|
lowerBand = SuperTrendBuffer[prevPos];
|
|
}
|
|
|
|
// Determinar dirección y valor del SuperTrend
|
|
if(i == InpAtrPeriod)
|
|
{
|
|
SuperTrendBuffer[pos] = upperBand;
|
|
DirectionBuffer[pos] = 1; // Tendencia bajista
|
|
}
|
|
else
|
|
{
|
|
int prevPos = pos + 1;
|
|
|
|
// Verificar cambio de tendencia
|
|
if(DirectionBuffer[prevPos] == 1) // Estaba en tendencia bajista
|
|
{
|
|
if(close[pos] > SuperTrendBuffer[prevPos])
|
|
{
|
|
// Cambio a tendencia alcista
|
|
DirectionBuffer[pos] = -1;
|
|
SuperTrendBuffer[pos] = lowerBand;
|
|
}
|
|
else
|
|
{
|
|
// Continúa bajista
|
|
DirectionBuffer[pos] = 1;
|
|
SuperTrendBuffer[pos] = upperBand;
|
|
}
|
|
}
|
|
else // Estaba en tendencia alcista
|
|
{
|
|
if(close[pos] < SuperTrendBuffer[prevPos])
|
|
{
|
|
// Cambio a tendencia bajista
|
|
DirectionBuffer[pos] = 1;
|
|
SuperTrendBuffer[pos] = upperBand;
|
|
}
|
|
else
|
|
{
|
|
// Continúa alcista
|
|
DirectionBuffer[pos] = -1;
|
|
SuperTrendBuffer[pos] = lowerBand;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Asignar valores a los buffers de plot
|
|
if(DirectionBuffer[pos] < 0)
|
|
{
|
|
// Tendencia alcista
|
|
UpTrendBuffer[pos] = SuperTrendBuffer[pos];
|
|
DownTrendBuffer[pos] = 0.0;
|
|
}
|
|
else
|
|
{
|
|
// Tendencia bajista
|
|
UpTrendBuffer[pos] = 0.0;
|
|
DownTrendBuffer[pos] = SuperTrendBuffer[pos];
|
|
}
|
|
}
|
|
|
|
return(rates_total);
|
|
}
|
|
//+------------------------------------------------------------------+ |