//╔════════════════════════════════════════════════════════════════════════╗ //║ ██████╗██╗ ██╗ █████╗ ██████╗ ██████╗ █████╗ █████╗ █████╗ ███╗ ██╗ ║ //║ ██╔═══╝╚██╗██╔╝██╔══██╗██╔══██╗██╔═══╝██╔══██╗██╔═══╝██╔══██╗████╗ ██║ ║ //║ █████╗ ╚███╔╝ ██║ ██║██████╔╝█████╗ ███████║██║ ██║ ██║██╔██╗██║ ║ //║ ██╔══╝ ██╔██╗ ██║ ██║██╔══██╗██╔══╝ ██╔══██║██║ ██║ ██║██║╚████║ ║ //║ ██████╗██╔╝ ██╗╚█████╔╝██████╔╝██████╗██║ ██║╚█████╗╚█████╔╝██║ ╚███║ ║ //║ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚════╝ ╚═╝ ╚══╝ ║ //╚═══════ 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�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�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 (solo los 2 de plot como buffers oficiales) SetIndexBuffer(0, UpTrendBuffer); SetIndexBuffer(1, DownTrendBuffer); // Configuraci�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�n de valores vac�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�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�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�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�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�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); } //+------------------------------------------------------------------+