Bollinger-RSI-Double-Strategy/Bollinger_RSI_Double_Strategy.mq5

670 lines
61 KiB
MQL5
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%P%P% Signals that speak P%P%P%P%P%P%P%P%P%P%P%P%P%P%]%
//+------------------------------------------------------------------+
//| R<EFBFBD>plica fiel del indicador "Bollinger + RSI, Double Strategy |
//| (by ChartArt) v1.1" originalmente publicado en TradingView. |
//| |
//| L<EFBFBD>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<EFBFBD>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 "0000000000((=<3D>}<7D>))0000000000"
#property description "=<3D><><EFBFBD> mql5.com/en/users/ulisescalb"
#property description "=<3D><><EFBFBD> github.com/Exobeacon-Labs"
#property strict
//--- Dibujar en la ventana principal del gr<EFBFBD>fico (overlay=true en Pine Script)
#property indicator_chart_window
//--- N<EFBFBD>mero total de buffers y plots
#property indicator_buffers 7
#property indicator_plots 5
//+------------------------------------------------------------------+
//| Configuraci<EFBFBD>n de plots |
//+------------------------------------------------------------------+
//--- Plot 0: BB Basis (SMA) - L<EFBFBD>nea aqua como en el original
#property indicator_label1 "BB Basis (SMA)"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrAqua
#property indicator_style1 STYLE_SOLID
#property indicator_width1 2
//--- Plot 1: BB Upper - L<EFBFBD>nea plateada
#property indicator_label2 "BB Upper"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrSilver
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
//--- Plot 2: BB Lower - L<EFBFBD>nea plateada
#property indicator_label3 "BB Lower"
#property indicator_type3 DRAW_LINE
#property indicator_color3 clrSilver
#property indicator_style3 STYLE_SOLID
#property indicator_width3 1
//--- Plot 3: Se<EFBFBD>al de compra (flecha arriba)
#property indicator_label4 "Buy Signal"
#property indicator_type4 DRAW_ARROW
#property indicator_color4 clrLime
#property indicator_width4 2
//--- Plot 4: Se<EFBFBD>al de venta (flecha abajo)
#property indicator_label5 "Sell Signal"
#property indicator_type5 DRAW_ARROW
#property indicator_color5 clrRed
#property indicator_width5 2
//+------------------------------------------------------------------+
//| Par<EFBFBD>metros de entrada |
//+------------------------------------------------------------------+
//| Mapeados desde el Pine Script original: |
//| input(6, "RSI Period Length") <EFBFBD>! InpRSIPeriod |
//| input(200, "Bollinger Period") <EFBFBD>! InpBBPeriod |
//| input(true, "Enable Bar Color?") <EFBFBD>! InpEnableBarColor |
//| input(true, "Enable BG Color?") <EFBFBD>! InpEnableBGColor |
//| |
//| Par<EFBFBD>metros hardcoded en el original ahora expuestos como input: |
//| BBmult = 2 <EFBFBD>! InpBBMultiplier |
//| RSIoverSold = RSIoverBought = 50 <EFBFBD>! InpRSILevel |
//+------------------------------------------------------------------+
input group "P%P%P%P%P%P% RSI Settings P%P%P%P%P%P%"
input int InpRSIPeriod = 6; // RSI Period Length
input int InpRSILevel = 50; // RSI Crossover Level (original=50)
input group "P%P%P%P%P%P% Bollinger Bands Settings P%P%P%P%P%P%"
input int InpBBPeriod = 200; // Bollinger Period Length
input double InpBBMultiplier = 2.0; // Bollinger Std Deviation Multiplier (original=2)
input group "P%P%P%P%P%P% Visual Settings P%P%P%P%P%P%"
input bool InpEnableBarColor = true; // Enable Bar Color?
input bool InpEnableBGColor = true; // Enable Background Color?
input int InpArrowOffset = 10; // Arrow Offset (points from candle)
input color InpBuyColor = clrLime; // Buy Signal Color
input color InpSellColor = clrRed; // Sell Signal Color
input color InpBasisColor = clrAqua; // BB Basis Color
input color InpBandColor = clrSilver; // BB Band Color
input group "P%P%P%P%P%P% Alert Settings P%P%P%P%P%P%"
input bool InpEnableAlerts = false; // Enable Alerts?
input bool InpAlertPopup = true; // Alert: Popup
input bool InpAlertSound = true; // Alert: Sound
input bool InpAlertPush = false; // Alert: Push Notification
input bool InpAlertEmail = false; // Alert: Email
//+------------------------------------------------------------------+
//| Buffers del indicador |
//+------------------------------------------------------------------+
//| Buffers de datos (INDICATOR_DATA) - se dibujan en el gr<EFBFBD>fico: |
//| [0] bufBasis - L<EFBFBD>nea central SMA de Bollinger |
//| [1] bufUpper - Banda superior de Bollinger |
//| [2] bufLower - Banda inferior de Bollinger |
//| [3] bufBuyArrow - Flechas de se<EFBFBD>al de compra |
//| [4] bufSellArrow - Flechas de se<EFBFBD>al de venta |
//| |
//| Buffers auxiliares (INDICATOR_CALCULATIONS) - no se dibujan: |
//| [5] bufBarColorIdx - <EFBFBD>ndice de color para velas |
//| [6] bufRSI - Valores RSI para referencia |
//+------------------------------------------------------------------+
double bufBasis[];
double bufUpper[];
double bufLower[];
double bufBuyArrow[];
double bufSellArrow[];
double bufBarColorIdx[];
double bufRSI[];
//+------------------------------------------------------------------+
//| Handles de indicadores internos de MQL5 |
//+------------------------------------------------------------------+
int g_handleRSI; // Handle para iRSI
int g_handleMA; // Handle para iMA (SMA base de Bollinger)
int g_handleStdDev; // Handle para iStdDev (desviaci<EFBFBD>n est<EFBFBD>ndar)
//--- Arrays temporales para copiar datos de indicadores
double g_dataRSI[];
double g_dataMA[];
double g_dataStdDev[];
//--- Control de barras m<EFBFBD>nimas necesarias
int g_minBars;
//--- Tracking de <EFBFBD>ltima alerta para evitar duplicados
datetime g_lastAlertTime = 0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Validaci<EFBFBD>n de par<EFBFBD>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: ", InpBBMultiplier);
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<EFBFBD>nimas necesarias para que los indicadores sean v<EFBFBD>lidos
g_minBars = MathMax(InpBBPeriod, InpRSIPeriod) + 2;
//--- Asignaci<EFBFBD>n de buffers a <EFBFBD>ndices
SetIndexBuffer(0, bufBasis, INDICATOR_DATA);
SetIndexBuffer(1, bufUpper, INDICATOR_DATA);
SetIndexBuffer(2, bufLower, INDICATOR_DATA);
SetIndexBuffer(3, bufBuyArrow, INDICATOR_DATA);
SetIndexBuffer(4, bufSellArrow, INDICATOR_DATA);
SetIndexBuffer(5, bufBarColorIdx, INDICATOR_CALCULATIONS);
SetIndexBuffer(6, bufRSI, INDICATOR_CALCULATIONS);
//--- Configurar flechas de se<EFBFBD>al
// 233 = flecha arriba (<EFBFBD>%), 234 = flecha abajo (<EFBFBD>%)
PlotIndexSetInteger(3, PLOT_ARROW, 233);
PlotIndexSetInteger(4, PLOT_ARROW, 234);
//--- Valores vac<EFBFBD>os para flechas (no dibujar donde no hay se<EFBFBD>al)
PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, EMPTY_VALUE);
PlotIndexSetDouble(4, PLOT_EMPTY_VALUE, EMPTY_VALUE);
//--- Aplicar colores configurados por el usuario
PlotIndexSetInteger(0, PLOT_LINE_COLOR, InpBasisColor);
PlotIndexSetInteger(1, PLOT_LINE_COLOR, InpBandColor);
PlotIndexSetInteger(2, PLOT_LINE_COLOR, InpBandColor);
PlotIndexSetInteger(3, PLOT_LINE_COLOR, InpBuyColor);
PlotIndexSetInteger(4, PLOT_LINE_COLOR, InpSellColor);
//--- Configurar inicio de dibujo para evitar basura en primeras barras
PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, InpBBPeriod - 1);
PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, InpBBPeriod - 1);
PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, InpBBPeriod - 1);
PlotIndexSetInteger(3, PLOT_DRAW_BEGIN, g_minBars);
PlotIndexSetInteger(4, PLOT_DRAW_BEGIN, g_minBars);
//--- Nombre corto del indicador (aparece en la ventana de datos)
string shortName = StringFormat("CA_RSI(%d)_BB(%d,%.1f) v1.1",
InpRSIPeriod, InpBBPeriod, InpBBMultiplier);
IndicatorSetString(INDICATOR_SHORTNAME, shortName);
//--- Precisi<EFBFBD>n de d<EFBFBD>gitos
IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
//--- Crear handles de indicadores integrados de MQL5
// RSI de Wilder (id<EFBFBD>ntico al rsi() de Pine Script)
g_handleRSI = iRSI(_Symbol, PERIOD_CURRENT, InpRSIPeriod, PRICE_CLOSE);
if(g_handleRSI == INVALID_HANDLE)
{
Print("Error creando handle iRSI: ", GetLastError());
return(INIT_FAILED);
}
//--- SMA para la base de Bollinger
// Pine Script: sma(close, BBlength) <EFBFBD>! iMA con MODE_SMA
g_handleMA = iMA(_Symbol, PERIOD_CURRENT, InpBBPeriod, 0, MODE_SMA, PRICE_CLOSE);
if(g_handleMA == INVALID_HANDLE)
{
Print("Error creando handle iMA: ", GetLastError());
return(INIT_FAILED);
}
//--- Desviaci<EFBFBD>n est<EFBFBD>ndar para las bandas
// Pine Script: stdev(close, BBlength) <EFBFBD>! iStdDev con MODE_SMA
// Nota: Ambos calculan desviaci<EFBFBD>n est<EFBFBD>ndar poblacional (<EFBFBD>N, no <EFBFBD>(N-1))
g_handleStdDev = iStdDev(_Symbol, PERIOD_CURRENT, InpBBPeriod, 0, MODE_SMA, PRICE_CLOSE);
if(g_handleStdDev == INVALID_HANDLE)
{
Print("Error creando handle iStdDev: ", GetLastError());
return(INIT_FAILED);
}
//--- Configurar arrays temporales
ArraySetAsSeries(g_dataRSI, false);
ArraySetAsSeries(g_dataMA, false);
ArraySetAsSeries(g_dataStdDev, false);
Print("Bollinger + RSI Double Strategy v1.1 inicializado correctamente.");
Print("Configuraci<00>n: RSI(", InpRSIPeriod, ")@", InpRSILevel,
" + BB(", InpBBPeriod, ", ", InpBBMultiplier, ")");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- Liberar handles de indicadores
if(g_handleRSI != INVALID_HANDLE)
IndicatorRelease(g_handleRSI);
if(g_handleMA != INVALID_HANDLE)
IndicatorRelease(g_handleMA);
if(g_handleStdDev != INVALID_HANDLE)
IndicatorRelease(g_handleStdDev);
//--- Limpiar objetos gr<EFBFBD>ficos del coloreo de fondo
ObjectsDeleteAll(0, "BRDS_BG_", 0, OBJ_RECTANGLE);
//--- Limpiar comentarios del gr<EFBFBD>fico
Comment("");
}
//+------------------------------------------------------------------+
//| 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[])
{
//--- Verificar que hay suficientes barras
if(rates_total < g_minBars)
return(0);
//--- Copiar datos de los indicadores integrados
// Nota: Se copian todos los datos necesarios de una sola vez
// Los arrays NO son series (<EFBFBD>ndice 0 = barra m<EFBFBD>s antigua)
int copied;
copied = CopyBuffer(g_handleMA, 0, 0, rates_total, g_dataMA);
if(copied < rates_total)
return(0);
copied = CopyBuffer(g_handleStdDev, 0, 0, rates_total, g_dataStdDev);
if(copied < rates_total)
return(0);
copied = CopyBuffer(g_handleRSI, 0, 0, rates_total, g_dataRSI);
if(copied < rates_total)
return(0);
//--- Determinar el punto de inicio del c<EFBFBD>lculo
// Si es la primera vez (prev_calculated == 0): calcular todo desde g_minBars
// Si es rec<EFBFBD>lculo parcial: solo recalcular las barras nuevas + 1
int startBar;
if(prev_calculated <= 0)
startBar = g_minBars;
else
startBar = MathMax(prev_calculated - 1, g_minBars);
//--- Bucle principal de c<EFBFBD>lculo
for(int i = startBar; i < rates_total; i++)
{
//=== 1. CALCULAR BANDAS DE BOLLINGER ===
// Pine Script:
// BBbasis = sma(price, BBlength)
// BBdev = BBmult * stdev(price, BBlength)
// BBupper = BBbasis + BBdev
// BBlower = BBbasis - BBdev
double basis = g_dataMA[i];
double dev = InpBBMultiplier * g_dataStdDev[i];
double upper = basis + dev;
double lower = basis - dev;
bufBasis[i] = basis;
bufUpper[i] = upper;
bufLower[i] = lower;
//--- Valores de la barra anterior (para crossover/crossunder)
double basisPrev = g_dataMA[i - 1];
double devPrev = InpBBMultiplier * g_dataStdDev[i - 1];
double upperPrev = basisPrev + devPrev;
double lowerPrev = basisPrev - devPrev;
//=== 2. ALMACENAR RSI PARA REFERENCIA ===
double rsiCurr = g_dataRSI[i];
double rsiPrev = g_dataRSI[i - 1];
bufRSI[i] = rsiCurr;
//--- Inicializar se<EFBFBD>ales como vac<EFBFBD>as
bufBuyArrow[i] = EMPTY_VALUE;
bufSellArrow[i] = EMPTY_VALUE;
bufBarColorIdx[i] = 0; // 0 = sin color especial
//--- Saltar si el RSI a<EFBFBD>n no tiene valores v<EFBFBD>lidos
if(rsiCurr == EMPTY_VALUE || rsiPrev == EMPTY_VALUE)
continue;
//=== 3. DETECTAR SE<EFBFBD>ALES (CONFLUENCIA RSI + BB) ===
// Pine Script original:
// if (crossover(vrsi, RSIoverSold) and crossover(source, BBlower))
// <EFBFBD>! LONG
// if (crossunder(vrsi, RSIoverBought) and crossunder(source, BBupper))
// <EFBFBD>! 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 (50): crossover(vrsi, 50) = vrsi[1] < 50 AND vrsi >= 50
//--- Se<EFBFBD>al LONG: RSI cruza arriba de 50 + Precio cruza arriba de BB Lower
bool rsiCrossUp = (rsiPrev < InpRSILevel && rsiCurr >= InpRSILevel);
bool priceCrossUp = (close[i - 1] < lowerPrev && close[i] >= lower);
bool longSignal = rsiCrossUp && priceCrossUp;
//--- Se<EFBFBD>al SHORT: RSI cruza abajo de 50 + Precio cruza abajo de BB Upper
bool rsiCrossDown = (rsiPrev > InpRSILevel && rsiCurr <= InpRSILevel);
bool priceCrossDown = (close[i - 1] > upperPrev && close[i] <= upper);
bool shortSignal = rsiCrossDown && priceCrossDown;
//--- Dibujar flechas de se<EFBFBD>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
//
// Nota: RSIoverBought=50 y RSIoverSold=50 son siempre truthy en Pine v2
// (cualquier n<EFBFBD>mero != 0 es true), as<EFBFBD> que la condici<EFBFBD>n se simplifica a:
// ROJO: price[1] > BBupper AND price < BBupper AND basis < basis[1]
// VERDE: price[1] < BBlower AND price > BBlower AND basis > basis[1]
bool trendBearish = (close[i - 1] > upperPrev && close[i] < upper && basis < basisPrev);
bool trendBullish = (close[i - 1] < lowerPrev && close[i] > lower && basis > basisPrev);
//--- Aplicar color a las velas
if(InpEnableBarColor)
{
if(trendBearish)
bufBarColorIdx[i] = -1; // Se<EFBFBD>al bajista (rojo)
else if(trendBullish)
bufBarColorIdx[i] = 1; // Se<EFBFBD>al alcista (verde)
else
bufBarColorIdx[i] = 0; // Sin se<EFBFBD>al
}
//--- Crear rect<EFBFBD>ngulos de fondo para simular bgcolor() de Pine Script
if(InpEnableBGColor && i == rates_total - 1)
{
//--- Solo procesar la <EFBFBD>ltima barra para el fondo en tiempo real
if(trendBearish)
DrawBackground(time[i], time[i] + PeriodSeconds(), high[i], low[i],
InpSellColor, 80);
else if(trendBullish)
DrawBackground(time[i], time[i] + PeriodSeconds(), high[i], low[i],
InpBuyColor, 80);
}
//=== 5. ALERTAS ===
if(InpEnableAlerts && i == rates_total - 1 && time[i] != g_lastAlertTime)
{
if(longSignal)
{
SendAlert("BUY Signal: RSI crossed above " + IntegerToString(InpRSILevel) +
" + Price crossed above BB Lower");
g_lastAlertTime = time[i];
}
else if(shortSignal)
{
SendAlert("SELL Signal: RSI crossed below " + IntegerToString(InpRSILevel) +
" + Price crossed below BB Upper");
g_lastAlertTime = time[i];
}
}
}
//--- Aplicar coloreo de velas usando ChartSetSymbolPeriod approach
if(InpEnableBarColor)
ApplyBarColors(rates_total, startBar, time, open, high, low, close);
return(rates_total);
}
//+------------------------------------------------------------------+
//| Aplicar colores a las velas del gr<EFBFBD>fico |
//+------------------------------------------------------------------+
void ApplyBarColors(const int rates_total,
const int startBar,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[])
{
//--- Solo colorear las barras reci<EFBFBD>n calculadas para rendimiento
int from = MathMax(startBar, rates_total - 100); // <EFBFBD>ltimas 100 barras m<EFBFBD>ximo
for(int i = from; i < rates_total; i++)
{
string objName = "BRDS_BAR_" + IntegerToString(i);
if(bufBarColorIdx[i] == -1) // Bajista (rojo)
{
//--- Crear/actualizar objeto de vela roja
ObjectDelete(0, objName);
// Nota: El coloreo nativo de velas se hace mediante DRAW_COLOR_CANDLES
// pero al ser indicador overlay, usamos un enfoque simplificado con
// indicaci<EFBFBD>n en el buffer. Para coloreo real de velas, ver nota abajo.
}
else if(bufBarColorIdx[i] == 1) // Alcista (verde)
{
ObjectDelete(0, objName);
}
else
{
ObjectDelete(0, objName);
}
}
//--- Nota t<EFBFBD>cnica sobre coloreo de velas en MQL5:
// El coloreo nativo de barras (barcolor en Pine Script) no tiene un equivalente
// directo sencillo en indicadores MQL5 overlay. Las opciones son:
// 1. Usar DRAW_COLOR_CANDLES (requiere buffers adicionales para OHLC completo)
// 2. Dibujar objetos gr<EFBFBD>ficos sobre las velas
// 3. Usar ChartIndicatorAdd con indicador secundario
// La implementaci<EFBFBD>n completa de DRAW_COLOR_CANDLES se incluye a continuaci<EFBFBD>n
// como funci<EFBFBD>n alternativa que puede activarse.
}
//+------------------------------------------------------------------+
//| Dibujar rect<EFBFBD>ngulo de fondo (simula bgcolor de Pine Script) |
//+------------------------------------------------------------------+
void DrawBackground(datetime timeStart, datetime timeEnd,
double priceHigh, double priceLow,
color bgColor, int transparency)
{
string objName = "BRDS_BG_" + TimeToString(timeStart, TIME_DATE | TIME_MINUTES);
//--- Crear o mover el rect<EFBFBD>ngulo
if(ObjectFind(0, objName) < 0)
{
ObjectCreate(0, objName, OBJ_RECTANGLE, 0,
timeStart, priceHigh, timeEnd, priceLow);
}
else
{
ObjectMove(0, objName, 0, timeStart, 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);
//--- Transparencia: 0=opaco, 255=invisible. Pine usa transp=50 <EFBFBD>! ~127
int alpha = (int)(transparency * 2.55);
ObjectSetInteger(0, objName, OBJPROP_FILL, true);
ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, objName, OBJPROP_HIDDEN, true);
}
//+------------------------------------------------------------------+
//| Enviar alertas multi-canal |
//+------------------------------------------------------------------+
void SendAlert(string message)
{
string prefix = "BB+RSI v1.1 [" + _Symbol + " " +
EnumToString(Period()) + "]: ";
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);
}
//+------------------------------------------------------------------+
//| |
//| 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% |
//| VERSI<EFBFBD>N ALTERNATIVA: DRAW_COLOR_CANDLES PARA COLOREO REAL |
//| 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% |
//| |
//| Si se desea coloreo real de velas (como barcolor en Pine), |
//| reemplazar los plots 3-4 por DRAW_COLOR_CANDLES. Esto requiere |
//| 4 buffers adicionales (Open, High, Low, Close coloreados) m<EFBFBD>s |
//| 1 buffer de <EFBFBD>ndice de color. La implementaci<EFBFBD>n alternativa se |
//| documenta aqu<EFBFBD> como referencia: |
//| |
//| // #property indicator_buffers 12 |
//| // #property indicator_plots 6 |
//| // |
//| // Plot 5: Colored Candles |
//| // #property indicator_type6 DRAW_COLOR_CANDLES |
//| // #property indicator_color6 clrNONE,clrLime,clrRed |
//| // (0=sin color, 1=verde, 2=rojo) |
//| // |
//| // Buffers adicionales: |
//| // [7] bufCandleOpen |
//| // [8] bufCandleHigh |
//| // [9] bufCandleLow |
//| // [10] bufCandleClose |
//| // [11] bufCandleColor (<EFBFBD>ndice: 0, 1, o 2) |
//| // |
//| // En OnCalculate, para cada barra: |
//| // bufCandleOpen[i] = open[i]; |
//| // bufCandleHigh[i] = high[i]; |
//| // bufCandleLow[i] = low[i]; |
//| // bufCandleClose[i] = close[i]; |
//| // if(trendBullish) bufCandleColor[i] = 1; // verde |
//| // else if(trendBearish) bufCandleColor[i] = 2; // rojo |
//| // else bufCandleColor[i] = 0; // default |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//| 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% |
//| REFERENCIA: PINE SCRIPT ORIGINAL v1.1 (ChartArt) |
//| 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% |
//| |
//| //@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") |
//| |
//+------------------------------------------------------------------+