670 lines
No EOL
61 KiB
MQL5
670 lines
No EOL
61 KiB
MQL5
//╔════════════════════════════════════════════════════════════════════════╗
|
|
//║ ██████╗██╗ ██╗ █████╗ ██████╗ ██████╗ █████╗ █████╗ █████╗ ███╗ ██╗ ║
|
|
//║ ██╔═══╝╚██╗██╔╝██╔══██╗██╔══██╗██╔═══╝██╔══██╗██╔═══╝██╔══██╗████╗ ██║ ║
|
|
//║ █████╗ ╚███╔╝ ██║ ██║██████╔╝█████╗ ███████║██║ ██║ ██║██╔██╗██║ ║
|
|
//║ ██╔══╝ ██╔██╗ ██║ ██║██╔══██╗██╔══╝ ██╔══██║██║ ██║ ██║██║╚████║ ║
|
|
//║ ██████╗██╔╝ ██╗╚█████╔╝██████╔╝██████╗██║ ██║╚█████╗╚█████╔╝██║ ╚███║ ║
|
|
//║ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝ ╚════╝ ╚════╝ ╚═╝ ╚══╝ ║
|
|
//╚═══════ Algorithms that observe ══════ Signals that speak ══════════════╝
|
|
//+------------------------------------------------------------------+
|
|
//| 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 y plots
|
|
#property indicator_buffers 7
|
|
#property indicator_plots 5
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Configuración de plots |
|
|
//+------------------------------------------------------------------+
|
|
|
|
//--- Plot 0: BB Basis (SMA) - Lí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í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í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ñ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ñal de venta (flecha abajo)
|
|
#property indicator_label5 "Sell Signal"
|
|
#property indicator_type5 DRAW_ARROW
|
|
#property indicator_color5 clrRed
|
|
#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 |
|
|
//+------------------------------------------------------------------+
|
|
|
|
input group "══════ RSI Settings ══════"
|
|
input int InpRSIPeriod = 6; // RSI Period Length
|
|
input int InpRSILevel = 50; // RSI Crossover Level (original=50)
|
|
|
|
input group "══════ Bollinger Bands Settings ══════"
|
|
input int InpBBPeriod = 200; // Bollinger Period Length
|
|
input double InpBBMultiplier = 2.0; // Bollinger Std Deviation Multiplier (original=2)
|
|
|
|
input group "══════ Visual Settings ══════"
|
|
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 "══════ Alert Settings ══════"
|
|
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áfico: |
|
|
//| [0] bufBasis - Línea central SMA de Bollinger |
|
|
//| [1] bufUpper - Banda superior de Bollinger |
|
|
//| [2] bufLower - Banda inferior de Bollinger |
|
|
//| [3] bufBuyArrow - Flechas de señal de compra |
|
|
//| [4] bufSellArrow - Flechas de señal de venta |
|
|
//| |
|
|
//| Buffers auxiliares (INDICATOR_CALCULATIONS) - no se dibujan: |
|
|
//| [5] bufBarColorIdx - Í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ón estándar)
|
|
|
|
//--- Arrays temporales para copiar datos de indicadores
|
|
double g_dataRSI[];
|
|
double g_dataMA[];
|
|
double g_dataStdDev[];
|
|
|
|
//--- 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: ", 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ínimas necesarias para que los indicadores sean válidos
|
|
g_minBars = MathMax(InpBBPeriod, InpRSIPeriod) + 2;
|
|
|
|
//--- Asignación de buffers a í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ñal
|
|
// 233 = flecha arriba (▲), 234 = flecha abajo (▼)
|
|
PlotIndexSetInteger(3, PLOT_ARROW, 233);
|
|
PlotIndexSetInteger(4, PLOT_ARROW, 234);
|
|
|
|
//--- Valores vacíos para flechas (no dibujar donde no hay señ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ón de dígitos
|
|
IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
|
|
|
|
//--- Crear handles de indicadores integrados de MQL5
|
|
// RSI de Wilder (idé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) → 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ón estándar para las bandas
|
|
// Pine Script: stdev(close, BBlength) → iStdDev con MODE_SMA
|
|
// Nota: Ambos calculan desviación estándar poblacional (÷N, no ÷(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ó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áficos del coloreo de fondo
|
|
ObjectsDeleteAll(0, "BRDS_BG_", 0, OBJ_RECTANGLE);
|
|
|
|
//--- Limpiar comentarios del grá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 (índice 0 = barra má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álculo
|
|
// Si es la primera vez (prev_calculated == 0): calcular todo desde g_minBars
|
|
// Si es recá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á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ñales como vacías
|
|
bufBuyArrow[i] = EMPTY_VALUE;
|
|
bufSellArrow[i] = EMPTY_VALUE;
|
|
bufBarColorIdx[i] = 0; // 0 = sin color especial
|
|
|
|
//--- Saltar si el RSI aún no tiene valores válidos
|
|
if(rsiCurr == EMPTY_VALUE || rsiPrev == EMPTY_VALUE)
|
|
continue;
|
|
|
|
//=== 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 (50): 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 = (close[i - 1] < lowerPrev && close[i] >= 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 = (close[i - 1] > upperPrev && close[i] <= 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
|
|
//
|
|
// Nota: RSIoverBought=50 y RSIoverSold=50 son siempre truthy en Pine v2
|
|
// (cualquier número != 0 es true), así que la condició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ñal bajista (rojo)
|
|
else if(trendBullish)
|
|
bufBarColorIdx[i] = 1; // Señal alcista (verde)
|
|
else
|
|
bufBarColorIdx[i] = 0; // Sin señal
|
|
}
|
|
|
|
//--- Crear rectángulos de fondo para simular bgcolor() de Pine Script
|
|
if(InpEnableBGColor && i == rates_total - 1)
|
|
{
|
|
//--- Solo procesar la ú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á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én calculadas para rendimiento
|
|
int from = MathMax(startBar, rates_total - 100); // Últimas 100 barras má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ó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é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áficos sobre las velas
|
|
// 3. Usar ChartIndicatorAdd con indicador secundario
|
|
// La implementación completa de DRAW_COLOR_CANDLES se incluye a continuación
|
|
// como función alternativa que puede activarse.
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Dibujar rectá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á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 → ~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);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//| ═══════════════════════════════════════════════════════════ |
|
|
//| VERSIÓN ALTERNATIVA: DRAW_COLOR_CANDLES PARA COLOREO REAL |
|
|
//| ═══════════════════════════════════════════════════════════ |
|
|
//| |
|
|
//| 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ás |
|
|
//| 1 buffer de índice de color. La implementación alternativa se |
|
|
//| documenta aquí 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 (í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 |
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//| ═══════════════════════════════════════════════════════════ |
|
|
//| 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") |
|
|
//| |
|
|
//+------------------------------------------------------------------+ |