267 lines
19 KiB
MQL4
267 lines
19 KiB
MQL4
//╔════════════════════════════════════════════════════════════════════════╗
|
||
//║ ██████╗██╗ ██╗ █████╗ ██████╗ ██████╗ █████╗ █████╗ █████╗ ███╗ ██╗ ║
|
||
//║ ██╔═══╝╚██╗██╔╝██╔══██╗██╔══██╗██╔═══╝██╔══██╗██╔═══╝██╔══██╗████╗ ██║ ║
|
||
//║ █████╗ ╚███╔╝ ██║ ██║██████╔╝█████╗ ███████║██║ ██║ ██║██╔██╗██║ ║
|
||
//║ ██╔══╝ ██╔██╗ ██║ ██║██╔══██╗██╔══╝ ██╔══██║██║ ██║ ██║██║╚████║ ║
|
||
//║ ██████╗██╔╝ ██╗╚█████╔╝██████╔╝██████╗██║ ██║╚█████╗╚█████╔╝██║ ╚███║ ║
|
||
//║ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚════╝ ╚═╝ ╚══╝ ║
|
||
//╚═══════ 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 strict
|
||
#property indicator_chart_window
|
||
#property indicator_buffers 2
|
||
#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<61>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[];
|
||
|
||
//+------------------------------------------------------------------+
|
||
//| Custom indicator initialization function |
|
||
//+------------------------------------------------------------------+
|
||
int OnInit()
|
||
{
|
||
// Validaci<63>n de par<61>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<63>n de buffers (solo los 2 de plot como buffers oficiales)
|
||
SetIndexBuffer(0, UpTrendBuffer);
|
||
SetIndexBuffer(1, DownTrendBuffer);
|
||
|
||
// Configuraci<63>n de estilos
|
||
SetIndexStyle(0, DRAW_LINE, STYLE_SOLID, 2, clrLime);
|
||
SetIndexStyle(1, DRAW_LINE, STYLE_SOLID, 2, clrRed);
|
||
|
||
// Etiquetas
|
||
SetIndexLabel(0, "SuperTrend Up");
|
||
SetIndexLabel(1, "SuperTrend Down");
|
||
|
||
// Configuraci<63>n de valores vac<61>os
|
||
SetIndexEmptyValue(0, 0.0);
|
||
SetIndexEmptyValue(1, 0.0);
|
||
|
||
// 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;
|
||
}
|
||
|
||
IndicatorShortName(StringFormat("SuperTrend(%d,%.2f,%s)", InpAtrPeriod, InpFactor, priceLabel));
|
||
IndicatorDigits(Digits);
|
||
|
||
return(INIT_SUCCEEDED);
|
||
}
|
||
|
||
//+------------------------------------------------------------------+
|
||
//| Funci<63>n auxiliar para obtener el precio aplicado |
|
||
//+------------------------------------------------------------------+
|
||
double GetAppliedPrice(const int shift)
|
||
{
|
||
switch(InpAppliedPrice)
|
||
{
|
||
case PRICE_CLOSE:
|
||
return Close[shift];
|
||
|
||
case PRICE_OPEN:
|
||
return Open[shift];
|
||
|
||
case PRICE_HIGH:
|
||
return High[shift];
|
||
|
||
case PRICE_LOW:
|
||
return Low[shift];
|
||
|
||
case PRICE_MEDIAN:
|
||
return (High[shift] + Low[shift]) / 2.0;
|
||
|
||
case PRICE_TYPICAL:
|
||
return (High[shift] + Low[shift] + Close[shift]) / 3.0;
|
||
|
||
case PRICE_WEIGHTED:
|
||
return (High[shift] + Low[shift] + Close[shift] + Close[shift]) / 4.0;
|
||
|
||
default:
|
||
return (High[shift] + Low[shift]) / 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(Bars < InpAtrPeriod)
|
||
return(0);
|
||
|
||
// Redimensionar arrays auxiliares (no son buffers oficiales)
|
||
if(ArraySize(SuperTrendBuffer) != Bars)
|
||
{
|
||
ArrayResize(SuperTrendBuffer, Bars);
|
||
ArrayResize(DirectionBuffer, Bars);
|
||
ArrayInitialize(SuperTrendBuffer, 0.0);
|
||
ArrayInitialize(DirectionBuffer, 0.0);
|
||
}
|
||
|
||
// Determinar desde d<>nde calcular
|
||
int start;
|
||
if(prev_calculated == 0)
|
||
start = Bars - InpAtrPeriod - 1;
|
||
else
|
||
start = Bars - prev_calculated;
|
||
|
||
// Calcular SuperTrend
|
||
for(int i = start; i >= 0; i--)
|
||
{
|
||
// Obtener ATR
|
||
double atr = iATR(NULL, 0, InpAtrPeriod, i);
|
||
|
||
if(atr == 0)
|
||
continue;
|
||
|
||
// Calcular l<>nea central usando el precio aplicado seleccionado
|
||
double basePrice = GetAppliedPrice(i);
|
||
|
||
// Calcular bandas b<>sicas
|
||
double upperBand = basePrice + InpFactor * atr;
|
||
double lowerBand = basePrice - InpFactor * atr;
|
||
|
||
// Ajustar bandas seg<65>n la barra anterior
|
||
if(i < Bars - InpAtrPeriod - 1)
|
||
{
|
||
int prevShift = i + 1;
|
||
|
||
// Ajustar banda superior
|
||
if(upperBand < SuperTrendBuffer[prevShift] || Close[prevShift] > SuperTrendBuffer[prevShift])
|
||
upperBand = upperBand;
|
||
else
|
||
upperBand = SuperTrendBuffer[prevShift];
|
||
|
||
// Ajustar banda inferior
|
||
if(lowerBand > SuperTrendBuffer[prevShift] || Close[prevShift] < SuperTrendBuffer[prevShift])
|
||
lowerBand = lowerBand;
|
||
else
|
||
lowerBand = SuperTrendBuffer[prevShift];
|
||
}
|
||
|
||
// Determinar direcci<63>n y valor del SuperTrend
|
||
if(i == Bars - InpAtrPeriod - 1)
|
||
{
|
||
SuperTrendBuffer[i] = upperBand;
|
||
DirectionBuffer[i] = 1; // Tendencia bajista
|
||
}
|
||
else
|
||
{
|
||
int prevShift = i + 1;
|
||
|
||
// Verificar cambio de tendencia
|
||
if(DirectionBuffer[prevShift] == 1) // Estaba en tendencia bajista
|
||
{
|
||
if(Close[i] > SuperTrendBuffer[prevShift])
|
||
{
|
||
// Cambio a tendencia alcista
|
||
DirectionBuffer[i] = -1;
|
||
SuperTrendBuffer[i] = lowerBand;
|
||
}
|
||
else
|
||
{
|
||
// Contin<69>a bajista
|
||
DirectionBuffer[i] = 1;
|
||
SuperTrendBuffer[i] = upperBand;
|
||
}
|
||
}
|
||
else // Estaba en tendencia alcista
|
||
{
|
||
if(Close[i] < SuperTrendBuffer[prevShift])
|
||
{
|
||
// Cambio a tendencia bajista
|
||
DirectionBuffer[i] = 1;
|
||
SuperTrendBuffer[i] = upperBand;
|
||
}
|
||
else
|
||
{
|
||
// Contin<69>a alcista
|
||
DirectionBuffer[i] = -1;
|
||
SuperTrendBuffer[i] = lowerBand;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Asignar valores a los buffers de plot
|
||
if(DirectionBuffer[i] < 0)
|
||
{
|
||
// Tendencia alcista
|
||
UpTrendBuffer[i] = SuperTrendBuffer[i];
|
||
DownTrendBuffer[i] = 0.0;
|
||
}
|
||
else
|
||
{
|
||
// Tendencia bajista
|
||
UpTrendBuffer[i] = 0.0;
|
||
DownTrendBuffer[i] = SuperTrendBuffer[i];
|
||
}
|
||
}
|
||
|
||
return(rates_total);
|
||
}
|
||
//+------------------------------------------------------------------+
|