//╔════════════════════════════════════════════════════════════════════════╗ //║ ██████╗██╗ ██╗ █████╗ ██████╗ ██████╗ █████╗ █████╗ █████╗ ███╗ ██╗ ║ //║ ██╔═══╝╚██╗██╔╝██╔══██╗██╔══██╗██╔═══╝██╔══██╗██╔═══╝██╔══██╗████╗ ██║ ║ //║ █████╗ ╚███╔╝ ██║ ██║██████╔╝█████╗ ███████║██║ ██║ ██║██╔██╗██║ ║ //║ ██╔══╝ ██╔██╗ ██║ ██║██╔══██╗██╔══╝ ██╔══██║██║ ██║ ██║██║╚████║ ║ //║ ██████╗██╔╝ ██╗╚█████╔╝██████╔╝██████╗██║ ██║╚█████╗╚█████╔╝██║ ╚███║ ║ //║ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚════╝ ╚═╝ ╚══╝ ║ //╚═══════ Algorithms that observe ══════ Signals that speak ══════════════╝ //+------------------------------------------------------------------+ //| Bollinger_RSI_Double_Strategy_v11.mq4 | //| Basado en: ChartArt - TradingView (Pine Script v2) | //| https://www.tradingview.com/script/uCV8I4xA/ | //+------------------------------------------------------------------+ //| Réplica fiel del indicador "Bollinger + RSI, Double Strategy | //| (by ChartArt) v1.1" originalmente publicado en TradingView. | //| | //| Lógica central: | //| BUY = crossover(RSI, 50) AND crossover(close, BB Lower) | //| SELL = crossunder(RSI, 50) AND crossunder(close, BB Upper) | //| | //| Particularidades del original: | //| - RSI periodo 6 con umbral 50 (filtro de momentum, no extremo) | //| - Bollinger Bands SMA 200, multiplicador 2 | //| - RSIoverSold = RSIoverBought = 50 (hardcoded) | //| - Coloreo de velas y fondo como confirmación visual | //+------------------------------------------------------------------+ #property copyright "Exobeacon Labs" #property link "https://www.exobeacon.com/" #property version "1.1" #property description "Bollinger + RSI, Double Strategy (by ChartArt) v1.1" #property description "Buy/Sell signals based on RSI(6)@50 + BB(200,2) confluence" #property description " " #property description "BUY: RSI crosses above 50 AND price crosses above BB Lower" #property description "SELL: RSI crosses below 50 AND price crosses below BB Upper" #property description " " #property description "———————————————————————" #property description "mql5.com/en/users/ulisescalb" #property description "github.com/Exobeacon-Labs" #property strict //--- Dibujar en la ventana principal del gráfico (overlay=true en Pine Script) #property indicator_chart_window //--- Número total de buffers #property indicator_buffers 5 //--- Colores por defecto de los plots #property indicator_color1 clrAqua // BB Basis #property indicator_color2 clrSilver // BB Upper #property indicator_color3 clrSilver // BB Lower #property indicator_color4 clrLime // Buy Arrow #property indicator_color5 clrRed // Sell Arrow //--- Anchos #property indicator_width1 2 #property indicator_width2 1 #property indicator_width3 1 #property indicator_width4 2 #property indicator_width5 2 //+------------------------------------------------------------------+ //| Parámetros de entrada | //+------------------------------------------------------------------+ //| Mapeados desde el Pine Script original: | //| input(6, "RSI Period Length") → InpRSIPeriod | //| input(200, "Bollinger Period") → InpBBPeriod | //| input(true, "Enable Bar Color?") → InpEnableBarColor | //| input(true, "Enable BG Color?") → InpEnableBGColor | //| | //| Parámetros hardcoded en el original ahora expuestos como input: | //| BBmult = 2 → InpBBMultiplier | //| RSIoverSold = RSIoverBought = 50 → InpRSILevel | //+------------------------------------------------------------------+ //--- RSI Settings extern int InpRSIPeriod = 6; // RSI Period Length extern int InpRSILevel = 50; // RSI Crossover Level (original=50) //--- Bollinger Bands Settings extern int InpBBPeriod = 200; // Bollinger Period Length extern double InpBBMultiplier = 2.0; // BB Std Deviation Multiplier (original=2) //--- Visual Settings extern bool InpEnableBarColor = true; // Enable Bar Color? extern bool InpEnableBGColor = true; // Enable Background Color? extern int InpArrowOffset = 10; // Arrow Offset (points from candle) extern color InpBuyColor = clrLime; // Buy Signal Color extern color InpSellColor = clrRed; // Sell Signal Color extern color InpBasisColor = clrAqua; // BB Basis Color extern color InpBandColor = clrSilver; // BB Band Color //--- Alert Settings extern bool InpEnableAlerts = false; // Enable Alerts? extern bool InpAlertPopup = true; // Alert: Popup extern bool InpAlertSound = true; // Alert: Sound extern bool InpAlertPush = false; // Alert: Push Notification extern bool InpAlertEmail = false; // Alert: Email //+------------------------------------------------------------------+ //| Buffers del indicador | //+------------------------------------------------------------------+ double bufBasis[]; // [0] Línea central SMA de Bollinger double bufUpper[]; // [1] Banda superior de Bollinger double bufLower[]; // [2] Banda inferior de Bollinger double bufBuyArrow[]; // [3] Flechas de señal de compra double bufSellArrow[]; // [4] Flechas de señal de venta //--- Control de barras mínimas necesarias int g_minBars; //--- Tracking de última alerta para evitar duplicados datetime g_lastAlertTime = 0; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Validación de parámetros de entrada if(InpRSIPeriod < 1) { Print("Error: RSI Period debe ser >= 1. Valor actual: ", InpRSIPeriod); return(INIT_PARAMETERS_INCORRECT); } if(InpBBPeriod < 1) { Print("Error: Bollinger Period debe ser >= 1. Valor actual: ", InpBBPeriod); return(INIT_PARAMETERS_INCORRECT); } if(InpBBMultiplier <= 0) { Print("Error: BB Multiplier debe ser > 0. Valor actual: ", DoubleToStr(InpBBMultiplier, 1)); return(INIT_PARAMETERS_INCORRECT); } if(InpRSILevel < 0 || InpRSILevel > 100) { Print("Error: RSI Level debe estar entre 0 y 100. Valor actual: ", InpRSILevel); return(INIT_PARAMETERS_INCORRECT); } //--- Barras mínimas necesarias g_minBars = MathMax(InpBBPeriod, InpRSIPeriod) + 2; //--- Asignación de buffers SetIndexBuffer(0, bufBasis); SetIndexBuffer(1, bufUpper); SetIndexBuffer(2, bufLower); SetIndexBuffer(3, bufBuyArrow); SetIndexBuffer(4, bufSellArrow); //--- Estilos de los plots //--- Plot 0: BB Basis (línea aqua) SetIndexStyle(0, DRAW_LINE, STYLE_SOLID, 2, InpBasisColor); SetIndexLabel(0, "BB Basis (SMA)"); //--- Plot 1: BB Upper (línea plateada) SetIndexStyle(1, DRAW_LINE, STYLE_SOLID, 1, InpBandColor); SetIndexLabel(1, "BB Upper"); //--- Plot 2: BB Lower (línea plateada) SetIndexStyle(2, DRAW_LINE, STYLE_SOLID, 1, InpBandColor); SetIndexLabel(2, "BB Lower"); //--- Plot 3: Flecha de compra (233 = flecha arriba ▲) SetIndexStyle(3, DRAW_ARROW, EMPTY, 2, InpBuyColor); SetIndexArrow(3, 233); SetIndexLabel(3, "Buy Signal"); //--- Plot 4: Flecha de venta (234 = flecha abajo ▼) SetIndexStyle(4, DRAW_ARROW, EMPTY, 2, InpSellColor); SetIndexArrow(4, 234); SetIndexLabel(4, "Sell Signal"); //--- Valores vacíos para flechas SetIndexEmptyValue(3, EMPTY_VALUE); SetIndexEmptyValue(4, EMPTY_VALUE); //--- Configurar inicio de dibujo SetIndexDrawBegin(0, InpBBPeriod); SetIndexDrawBegin(1, InpBBPeriod); SetIndexDrawBegin(2, InpBBPeriod); SetIndexDrawBegin(3, g_minBars); SetIndexDrawBegin(4, g_minBars); //--- Nombre corto del indicador string shortName = StringConcatenate("CA_RSI(", InpRSIPeriod, ")_BB(", InpBBPeriod, ",", DoubleToStr(InpBBMultiplier, 1), ") v1.1"); IndicatorShortName(shortName); //--- Precisión de dígitos IndicatorDigits(Digits); Print("Bollinger + RSI Double Strategy v1.1 (MQL4) inicializado correctamente."); Print("Configuración: RSI(", InpRSIPeriod, ")@", InpRSILevel, " + BB(", InpBBPeriod, ", ", DoubleToStr(InpBBMultiplier, 1), ")"); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Limpiar objetos gráficos del coloreo de fondo ObjectsDeleteAll(0, "BRDS_BG_"); //--- Limpiar comentarios del gráfico Comment(""); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ //| En MQL4, las series temporales tienen indexación inversa: | //| Índice 0 = barra actual (más reciente) | //| Índice N = barra más antigua | //| Los buffers de indicador siguen la misma convención. | //+------------------------------------------------------------------+ 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[]) { //--- Verificar que hay suficientes barras if(rates_total < g_minBars) return(0); //--- Determinar el rango de cálculo // En MQL4 con indexación inversa: 0=actual, rates_total-1=más antigua // counted_bars = prev_calculated; si es 0, calcular todo int limit; if(prev_calculated <= 0) limit = rates_total - g_minBars - 1; else limit = rates_total - prev_calculated + 1; //--- Asegurar que limit no exceda el rango válido if(limit > rates_total - g_minBars - 1) limit = rates_total - g_minBars - 1; if(limit < 0) limit = 0; //--- Bucle principal de cálculo // En MQL4, iteramos de la barra más antigua a la más reciente // (de índice alto a bajo) para respetar la convención de series for(int i = limit; i >= 0; i--) { //=== 1. OBTENER VALORES DE INDICADORES VÍA FUNCIONES NATIVAS MQL4 === // En MQL4, iRSI/iMA/iStdDev acceden directamente a los valores // sin necesidad de handles ni CopyBuffer. // // Mapeo desde Pine Script: // rsi(close, 6) → iRSI(NULL, 0, 6, PRICE_CLOSE, i) // sma(close, 200) → iMA(NULL, 0, 200, 0, MODE_SMA, PRICE_CLOSE, i) // stdev(close, 200) → iStdDev(NULL, 0, 200, 0, MODE_SMA, PRICE_CLOSE, i) //--- RSI actual y anterior double rsiCurr = iRSI(NULL, 0, InpRSIPeriod, PRICE_CLOSE, i); double rsiPrev = iRSI(NULL, 0, InpRSIPeriod, PRICE_CLOSE, i + 1); //--- SMA (base de Bollinger) actual y anterior double basis = iMA(NULL, 0, InpBBPeriod, 0, MODE_SMA, PRICE_CLOSE, i); double basisPrev = iMA(NULL, 0, InpBBPeriod, 0, MODE_SMA, PRICE_CLOSE, i + 1); //--- Desviación estándar actual y anterior // Nota: iStdDev en MQL4 calcula desviación poblacional (÷N), // idéntico a stdev() de Pine Script v2 double stdCurr = iStdDev(NULL, 0, InpBBPeriod, 0, MODE_SMA, PRICE_CLOSE, i); double stdPrev = iStdDev(NULL, 0, InpBBPeriod, 0, MODE_SMA, PRICE_CLOSE, i + 1); //=== 2. CALCULAR BANDAS DE BOLLINGER === // Pine Script: // BBbasis = sma(price, BBlength) // BBdev = BBmult * stdev(price, BBlength) // BBupper = BBbasis + BBdev // BBlower = BBbasis - BBdev double dev = InpBBMultiplier * stdCurr; double devPrev = InpBBMultiplier * stdPrev; double upper = basis + dev; double lower = basis - dev; double upperPrev = basisPrev + devPrev; double lowerPrev = basisPrev - devPrev; //--- Almacenar en buffers de dibujo bufBasis[i] = basis; bufUpper[i] = upper; bufLower[i] = lower; //--- Precios de cierre actual y anterior double closeCurr = Close[i]; double closePrev = Close[i + 1]; //--- Inicializar señales como vacías bufBuyArrow[i] = EMPTY_VALUE; bufSellArrow[i] = EMPTY_VALUE; //=== 3. DETECTAR SEÑALES (CONFLUENCIA RSI + BB) === // Pine Script original: // if (crossover(vrsi, RSIoverSold) and crossover(source, BBlower)) // → LONG // if (crossunder(vrsi, RSIoverBought) and crossunder(source, BBupper)) // → SHORT // // crossover(a, b) = a[1] < b[1] AND a[0] >= b[0] // crossunder(a, b) = a[1] > b[1] AND a[0] <= b[0] // // Para nivel fijo: crossover(vrsi, 50) = vrsi[1] < 50 AND vrsi >= 50 //--- Señal LONG: RSI cruza arriba de 50 + Precio cruza arriba de BB Lower bool rsiCrossUp = (rsiPrev < InpRSILevel && rsiCurr >= InpRSILevel); bool priceCrossUp = (closePrev < lowerPrev && closeCurr >= lower); bool longSignal = rsiCrossUp && priceCrossUp; //--- Señal SHORT: RSI cruza abajo de 50 + Precio cruza abajo de BB Upper bool rsiCrossDown = (rsiPrev > InpRSILevel && rsiCurr <= InpRSILevel); bool priceCrossDown = (closePrev > upperPrev && closeCurr <= upper); bool shortSignal = rsiCrossDown && priceCrossDown; //--- Dibujar flechas de señal if(longSignal) { bufBuyArrow[i] = Low[i] - InpArrowOffset * Point; } if(shortSignal) { bufSellArrow[i] = High[i] + InpArrowOffset * Point; } //=== 4. COLOREO DE VELAS (TrendColor del original) === // Pine Script original: // TrendColor = RSIoverBought and (price[1] > BBupper and price < BBupper) // and BBbasis < BBbasis[1] ? red // : RSIoverSold and (price[1] < BBlower and price > BBlower) // and BBbasis > BBbasis[1] ? green // : na // // RSIoverBought=50 y RSIoverSold=50 son truthy en Pine v2, simplificando: // ROJO: close[1] > BBupper[1] AND close < BBupper AND basis < basis[1] // VERDE: close[1] < BBlower[1] AND close > BBlower AND basis > basis[1] bool trendBearish = (closePrev > upperPrev && closeCurr < upper && basis < basisPrev); bool trendBullish = (closePrev < lowerPrev && closeCurr > lower && basis > basisPrev); //--- Aplicar color a las velas del gráfico if(InpEnableBarColor && i < 200) { string candleObj = "BRDS_CANDLE_" + IntegerToString(i); if(trendBullish) ColorCandle(i, InpBuyColor); else if(trendBearish) ColorCandle(i, InpSellColor); } //--- Crear rectángulos de fondo (simula bgcolor de Pine Script) if(InpEnableBGColor) { string bgName = "BRDS_BG_" + TimeToStr(Time[i], TIME_DATE | TIME_MINUTES); if(trendBearish) DrawBackground(bgName, Time[i], High[i], Low[i], InpSellColor); else if(trendBullish) DrawBackground(bgName, Time[i], High[i], Low[i], InpBuyColor); else { //--- Eliminar fondo si no hay señal de color if(ObjectFind(0, bgName) >= 0) ObjectDelete(0, bgName); } } //=== 5. ALERTAS (solo en la barra más reciente cerrada) === if(InpEnableAlerts && i == 1 && Time[i] != g_lastAlertTime) { if(longSignal) { SendAlertNotification("BUY Signal: RSI crossed above " + IntegerToString(InpRSILevel) + " + Price crossed above BB Lower"); g_lastAlertTime = Time[i]; } else if(shortSignal) { SendAlertNotification("SELL Signal: RSI crossed below " + IntegerToString(InpRSILevel) + " + Price crossed below BB Upper"); g_lastAlertTime = Time[i]; } } } return(rates_total); } //+------------------------------------------------------------------+ //| Colorear una vela individual del gráfico | //+------------------------------------------------------------------+ //| MQL4 no tiene DRAW_COLOR_CANDLES nativo como MQL5. La forma | //| más directa de colorear velas es usando objetos OBJ_RECTANGLE | //| o modificando el esquema de colores. Aquí usamos un approach | //| con objetos que simula el barcolor() de Pine Script. | //+------------------------------------------------------------------+ void ColorCandle(int shift, color candleColor) { if(shift < 0 || shift >= Bars) return; string objBody = "BRDS_BODY_" + IntegerToString(shift); string objWickH = "BRDS_WICK_H_" + IntegerToString(shift); string objWickL = "BRDS_WICK_L_" + IntegerToString(shift); datetime t1 = Time[shift]; //--- Calcular el ancho de la vela (mitad del período entre velas) datetime halfPeriod = 0; if(shift < Bars - 1) halfPeriod = (Time[shift] - Time[shift + 1]) / 3; else halfPeriod = PeriodSeconds() / 3; datetime tLeft = t1 - halfPeriod; datetime tRight = t1 + halfPeriod; double bodyTop = MathMax(Open[shift], Close[shift]); double bodyBottom = MathMin(Open[shift], Close[shift]); //--- Cuerpo de la vela if(ObjectFind(0, objBody) < 0) ObjectCreate(0, objBody, OBJ_RECTANGLE, 0, tLeft, bodyTop, tRight, bodyBottom); else { ObjectMove(0, objBody, 0, tLeft, bodyTop); ObjectMove(0, objBody, 1, tRight, bodyBottom); } ObjectSetInteger(0, objBody, OBJPROP_COLOR, candleColor); ObjectSetInteger(0, objBody, OBJPROP_FILL, true); ObjectSetInteger(0, objBody, OBJPROP_BACK, true); ObjectSetInteger(0, objBody, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, objBody, OBJPROP_HIDDEN, true); //--- Mecha superior if(ObjectFind(0, objWickH) < 0) ObjectCreate(0, objWickH, OBJ_TREND, 0, t1, High[shift], t1, bodyTop); else { ObjectMove(0, objWickH, 0, t1, High[shift]); ObjectMove(0, objWickH, 1, t1, bodyTop); } ObjectSetInteger(0, objWickH, OBJPROP_COLOR, candleColor); ObjectSetInteger(0, objWickH, OBJPROP_WIDTH, 1); ObjectSetInteger(0, objWickH, OBJPROP_RAY, false); ObjectSetInteger(0, objWickH, OBJPROP_BACK, true); ObjectSetInteger(0, objWickH, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, objWickH, OBJPROP_HIDDEN, true); //--- Mecha inferior if(ObjectFind(0, objWickL) < 0) ObjectCreate(0, objWickL, OBJ_TREND, 0, t1, bodyBottom, t1, Low[shift]); else { ObjectMove(0, objWickL, 0, t1, bodyBottom); ObjectMove(0, objWickL, 1, t1, Low[shift]); } ObjectSetInteger(0, objWickL, OBJPROP_COLOR, candleColor); ObjectSetInteger(0, objWickL, OBJPROP_WIDTH, 1); ObjectSetInteger(0, objWickL, OBJPROP_RAY, false); ObjectSetInteger(0, objWickL, OBJPROP_BACK, true); ObjectSetInteger(0, objWickL, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, objWickL, OBJPROP_HIDDEN, true); } //+------------------------------------------------------------------+ //| Dibujar rectángulo de fondo (simula bgcolor de Pine Script) | //+------------------------------------------------------------------+ void DrawBackground(string objName, datetime barTime, double priceHigh, double priceLow, color bgColor) { datetime timeEnd = barTime + PeriodSeconds(); if(ObjectFind(0, objName) < 0) { ObjectCreate(0, objName, OBJ_RECTANGLE, 0, barTime, priceHigh, timeEnd, priceLow); } else { ObjectMove(0, objName, 0, barTime, priceHigh); ObjectMove(0, objName, 1, timeEnd, priceLow); } ObjectSetInteger(0, objName, OBJPROP_COLOR, bgColor); ObjectSetInteger(0, objName, OBJPROP_FILL, true); ObjectSetInteger(0, objName, OBJPROP_BACK, true); ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, objName, OBJPROP_HIDDEN, true); } //+------------------------------------------------------------------+ //| Enviar alertas multi-canal | //+------------------------------------------------------------------+ void SendAlertNotification(string message) { string prefix = "BB+RSI v1.1 [" + Symbol() + " " + GetPeriodString() + "]: "; string fullMsg = prefix + message; if(InpAlertPopup) Alert(fullMsg); if(InpAlertSound) PlaySound("alert.wav"); if(InpAlertPush) SendNotification(fullMsg); if(InpAlertEmail) SendMail("BB+RSI Signal", fullMsg); Print(fullMsg); } //+------------------------------------------------------------------+ //| Obtener string del período actual | //+------------------------------------------------------------------+ string GetPeriodString() { switch(Period()) { case PERIOD_M1: return("M1"); case PERIOD_M5: return("M5"); case PERIOD_M15: return("M15"); case PERIOD_M30: return("M30"); case PERIOD_H1: return("H1"); case PERIOD_H4: return("H4"); case PERIOD_D1: return("D1"); case PERIOD_W1: return("W1"); case PERIOD_MN1: return("MN1"); default: return("??"); } } //+------------------------------------------------------------------+ //| | //| ═══════════════════════════════════════════════════════════ | //| NOTAS DE IMPLEMENTACIÓN MQL4 vs MQL5 | //| ═══════════════════════════════════════════════════════════ | //| | //| Diferencias clave con la versión MQL5: | //| | //| 1. ACCESO A INDICADORES: | //| MQL5: Usa handles (iRSI→handle) + CopyBuffer() | //| MQL4: Acceso directo iRSI(NULL,0,period,price,shift) | //| Sin handles ni buffers intermedios. | //| | //| 2. INDEXACIÓN DE SERIES: | //| MQL5: Por defecto 0=más antiguo (configurable con | //| ArraySetAsSeries) | //| MQL4: Siempre 0=barra actual (más reciente) | //| Los buffers se indexan igual automáticamente. | //| | //| 3. ARRAYS DE PRECIOS: | //| MQL5: Recibidos como parámetros en OnCalculate() | //| MQL4: Accesibles vía arrays predefinidos: | //| Open[], High[], Low[], Close[], Time[], Volume[] | //| | //| 4. COLOREO DE VELAS: | //| MQL5: DRAW_COLOR_CANDLES con buffers OHLC + color index | //| MQL4: No hay DRAW_COLOR_CANDLES nativo. Se simula con | //| objetos gráficos (OBJ_RECTANGLE + OBJ_TREND). | //| | //| 5. FUNCIONES DE INDICADOR: | //| MQL5: SetIndexBuffer(idx, buf, INDICATOR_DATA) | //| MQL4: SetIndexBuffer(idx, buf) + SetIndexStyle() | //| | //| 6. FIDELIDAD NUMÉRICA: | //| Ambos usan RSI de Wilder (RMA/SMMA) y desviación estándar | //| poblacional (÷N). Los resultados numéricos son idénticos | //| entre MQL4 y MQL5 con los mismos datos de entrada. | //| | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| | //| ═══════════════════════════════════════════════════════════ | //| REFERENCIA: PINE SCRIPT ORIGINAL v1.1 (ChartArt) | //| ═══════════════════════════════════════════════════════════ | //| | //| //@version=2 | //| strategy("Bollinger + RSI, Double Strategy (by ChartArt) v1.1", | //| shorttitle="CA_-_RSI_Bol_Strat_1.1", overlay=true) | //| | //| ///////////// RSI | //| RSIlength = input(6,title="RSI Period Length") | //| RSIoverSold = 50 | //| RSIoverBought = 50 | //| price = close | //| vrsi = rsi(price, RSIlength) | //| | //| ///////////// Bollinger Bands | //| BBlength = input(200, minval=1,title="Bollinger Period Length") | //| BBmult = 2 | //| BBbasis = sma(price, BBlength) | //| BBdev = BBmult * stdev(price, BBlength) | //| BBupper = BBbasis + BBdev | //| BBlower = BBbasis - BBdev | //| source = close | //| buyEntry = crossover(source, BBlower) | //| sellEntry = crossunder(source, BBupper) | //| plot(BBbasis, color=aqua,title="BB SMA Basis Line") | //| p1 = plot(BBupper, color=silver,title="BB Upper Line") | //| p2 = plot(BBlower, color=silver,title="BB Lower Line") | //| fill(p1, p2) | //| | //| ///////////// Colors | //| switch1=input(true, title="Enable Bar Color?") | //| switch2=input(true, title="Enable Background Color?") | //| TrendColor = RSIoverBought and (price[1] > BBupper and | //| price < BBupper) and BBbasis < BBbasis[1] ? red | //| : RSIoverSold and (price[1] < BBlower and | //| price > BBlower) and BBbasis > BBbasis[1] ? green | //| : na | //| barcolor(switch1?TrendColor:na) | //| bgcolor(switch2?TrendColor:na,transp=50) | //| | //| ///////////// RSI + Bollinger Bands Strategy | //| if (not na(vrsi)) | //| if (crossover(vrsi, RSIoverSold) and | //| crossover(source, BBlower)) | //| strategy.entry("RSI_BB_L", strategy.long, | //| stop=BBlower, oca_type=...cancel, | //| comment="RSI_BB_L") | //| else | //| strategy.cancel(id="RSI_BB_L") | //| if (crossunder(vrsi, RSIoverBought) and | //| crossunder(source, BBupper)) | //| strategy.entry("RSI_BB_S", strategy.short, | //| stop=BBupper, oca_type=...cancel, | //| comment="RSI_BB_S") | //| else | //| strategy.cancel(id="RSI_BB_S") | //| | //+------------------------------------------------------------------+