0% found this document useful (0 votes)
6 views25 pages

EA Rupturas y Reversiones

The document is a script for an automated trading bot (AdvancedSRBot) developed in MQL4 for MetaTrader 4, which incorporates various trading strategies based on technical indicators such as ADX, DMI, Stochastic, and Moving Average. It includes settings for trading parameters, risk management, and support/resistance detection, allowing users to customize their trading approach. The bot executes buy and sell trades based on specific market conditions and indicators, aiming to optimize trading performance.

Uploaded by

Kike Villarroel
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views25 pages

EA Rupturas y Reversiones

The document is a script for an automated trading bot (AdvancedSRBot) developed in MQL4 for MetaTrader 4, which incorporates various trading strategies based on technical indicators such as ADX, DMI, Stochastic, and Moving Average. It includes settings for trading parameters, risk management, and support/resistance detection, allowing users to customize their trading approach. The bot executes buy and sell trades based on specific market conditions and indicators, aiming to optimize trading performance.

Uploaded by

Kike Villarroel
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

//+------------------------------------------------------------------+

//| AdvancedSRBot.mq4 |

//| Copyright 2023, MetaQuotes Software Corp. |

//| [Link] |

//+------------------------------------------------------------------+

#property copyright "Copyright 2023, MetaQuotes Software Corp."

#property link "[Link]

#property version "2.00"

#property strict

//+------------------------------------------------------------------+

//| Input Parameters |

//+------------------------------------------------------------------+

// Trading Settings

input double LotSize = 0.1; // Tamaño del lote

input int MagicNumber = 12345; // Número mágico

input int Slippage = 3; // Deslizamiento (pips)

// Indicator Settings

input int ADX_Period = 14; // Período ADX

input int ADX_Threshold = 25; // Umbral ADX

input int DMI_Period = 14; // Período DMI

input int Stoch_PeriodK = 5; // Período %K Estocástico

input int Stoch_PeriodD = 3; // Período %D Estocástico

input int Stoch_Slowing = 3; // Ralentización Estocástico


input int MA_Period = 50; // Periodo Media Móvil (filtro tendencia)

// Volume Settings

input int Volume_Lookback = 20; // Periodo comparación volumen

input double Volume_Multiplier= 1.5; // Multiplicador volumen alto

// S/R Detection Settings

input int S_R_Lookback = 200; // Velas para analizar S/R

input int S_R_MinTouches = 3; // Mínimo toques para zona S/R

input double S_R_ZoneWidthPips= 30; // Ancho zona S/R en pips

input bool ShowZones = true; // Mostrar zonas en gráfico

input color SupportColor = clrBlue; // Color soportes

input color ResistanceColor = clrRed; // Color resistencias

// Risk Management

input double RiskPercent = 1.0; // Riesgo por operación (%)

input bool UseAtrSL = true; // Usar ATR para Stop Loss

input int AtrPeriod = 14; // Periodo ATR

input double AtrMultiplier = 2.0; // Multiplicador ATR

input double RewardRatio = 1.5; // Ratio Take Profit

// Time Filters

input int StartHour = 8; // Hora inicio trading

input int EndHour = 20; // Hora fin trading

input bool Monday = true; // Operar Lunes


input bool Tuesday = true; // Operar Martes

input bool Wednesday = true; // Operar Miércoles

input bool Thursday = true; // Operar Jueves

input bool Friday = true; // Operar Viernes

//+------------------------------------------------------------------+

//| Global Variables |

//+------------------------------------------------------------------+

int adxHandle, dmiPlusHandle, dmiMinusHandle, stochHandle, maHandle, atrHandle;

S_R_Zone supports[], resistances[];

datetime lastTradeTime;

//+------------------------------------------------------------------+

//| Estructura para zonas S/R |

//+------------------------------------------------------------------+

struct S_R_Zone

double price;

int touches;

datetime lastTouch;

bool isSupport;

double strength; // Fuerza de la zona (0-1)

};

//+------------------------------------------------------------------+
//| Expert initialization function |

//+------------------------------------------------------------------+

int OnInit()

// Crear handles para los indicadores

adxHandle = iADX(NULL, 0, ADX_Period);

dmiPlusHandle = iCustom(NULL, 0, "Examples\\ADX", ADX_Period, 0, MODE_PLUSDI, PRICE_CLOSE);

dmiMinusHandle = iCustom(NULL, 0, "Examples\\ADX", ADX_Period, 0, MODE_MINUSDI,


PRICE_CLOSE);

stochHandle = iStochastic(NULL, 0, Stoch_PeriodK, Stoch_PeriodD, Stoch_Slowing, MODE_SMA, 0,


MODE_MAIN, 0);

maHandle = iMA(NULL, 0, MA_Period, 0, MODE_SMA, PRICE_CLOSE);

atrHandle = iATR(NULL, 0, AtrPeriod);

if(adxHandle == INVALID_HANDLE || dmiPlusHandle == INVALID_HANDLE ||

dmiMinusHandle == INVALID_HANDLE || stochHandle == INVALID_HANDLE ||

maHandle == INVALID_HANDLE || atrHandle == INVALID_HANDLE)

Print("Error al crear handles de indicadores");

return(INIT_FAILED);

// Detectar zonas S/R iniciales

DetectSupportResistance();

return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+

//| Expert deinitialization function |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

// Liberar handles

IndicatorRelease(adxHandle);

IndicatorRelease(dmiPlusHandle);

IndicatorRelease(dmiMinusHandle);

IndicatorRelease(stochHandle);

IndicatorRelease(maHandle);

IndicatorRelease(atrHandle);

// Eliminar objetos de zonas si están visibles

if(ShowZones) DeleteZones();

//+------------------------------------------------------------------+

//| Expert tick function |

//+------------------------------------------------------------------+

void OnTick()

// Verificar condiciones básicas para trading


if(!IsTradingAllowed()) return;

// Actualizar zonas S/R cada hora

static datetime lastUpdate = 0;

if(TimeCurrent() - lastUpdate >= 3600)

DetectSupportResistance();

lastUpdate = TimeCurrent();

// Verificar si ya hay órdenes abiertas para este magic number

if(CountOrders() > 0) return;

// Obtener datos de los indicadores

MqlRates rates[];

double adx[], dmiPlus[], dmiMinus[], stochMain[], stochSignal[], volume[], ma[], atr[];

CopyRates(NULL, 0, 0, 2, rates);

CopyBuffer(adxHandle, 0, 0, 3, adx);

CopyBuffer(dmiPlusHandle, 0, 0, 3, dmiPlus);

CopyBuffer(dmiMinusHandle, 0, 0, 3, dmiMinus);

CopyBuffer(stochHandle, 0, 0, 3, stochMain);

CopyBuffer(stochHandle, 1, 0, 3, stochSignal);

CopyTickVolume(NULL, 0, 0, Volume_Lookback, volume);

CopyBuffer(maHandle, 0, 0, 3, ma);

CopyBuffer(atrHandle, 0, 0, 1, atr);
// Calcular volumen promedio

double avgVolume = ArrayAverage(volume);

// Verificar condiciones de compra

CheckBuyConditions(rates, avgVolume, adx, dmiPlus, dmiMinus, stochMain, stochSignal, ma, atr[0]);

// Verificar condiciones de venta

CheckSellConditions(rates, avgVolume, adx, dmiPlus, dmiMinus, stochMain, stochSignal, ma, atr[0]);

//+------------------------------------------------------------------+

//| Verificar condiciones de compra |

//+------------------------------------------------------------------+

void CheckBuyConditions(MqlRates &rates[], double avgVolume, double &adx[], double &dmiPlus[],

double &dmiMinus[], double &stochMain[], double &stochSignal[], double &ma[], double


atrValue)

// Condición 1: Ruptura de resistencia con volumen alto, ADX > 25 y DMI+ > DMI-

if(IsResistanceBreak(rates) &&

rates[1].tick_volume > avgVolume * Volume_Multiplier &&

adx[1] > ADX_Threshold &&

dmiPlus[1] > dmiMinus[1] &&

rates[1].close > ma[1]) // Precio arriba de MA para tendencia alcista

double sl = CalculateStopLoss(true, rates, atrValue);


double tp = rates[1].close + (rates[1].close - sl) * RewardRatio;

double lotSize = CalculateLotSize(sl);

EnterTrade(OP_BUY, lotSize, sl, tp, "Compra por ruptura");

// Condición 2: Rechazo en soporte con envolvente alcista y cruce estocástico

if(IsSupportRejection(rates) &&

IsBullishEngulfing(rates) &&

stochMain[1] < stochSignal[1] && stochMain[0] > stochSignal[0] &&

rates[1].close > ma[1]) // Precio arriba de MA para tendencia alcista

double sl = CalculateStopLoss(true, rates, atrValue);

double tp = rates[1].close + (rates[1].close - sl) * RewardRatio;

double lotSize = CalculateLotSize(sl);

EnterTrade(OP_BUY, lotSize, sl, tp, "Compra por rechazo");

//+------------------------------------------------------------------+

//| Verificar condiciones de venta |

//+------------------------------------------------------------------+

void CheckSellConditions(MqlRates &rates[], double avgVolume, double &adx[], double &dmiPlus[],

double &dmiMinus[], double &stochMain[], double &stochSignal[], double &ma[], double


atrValue)

// Condición 1: Ruptura de soporte con volumen alto, ADX > 25 y DMI- > DMI+
if(IsSupportBreak(rates) &&

rates[1].tick_volume > avgVolume * Volume_Multiplier &&

adx[1] > ADX_Threshold &&

dmiMinus[1] > dmiPlus[1] &&

rates[1].close < ma[1]) // Precio abajo de MA para tendencia bajista

double sl = CalculateStopLoss(false, rates, atrValue);

double tp = rates[1].close - (sl - rates[1].close) * RewardRatio;

double lotSize = CalculateLotSize(sl);

EnterTrade(OP_SELL, lotSize, sl, tp, "Venta por ruptura");

// Condición 2: Rechazo en resistencia con envolvente bajista y cruce estocástico

if(IsResistanceRejection(rates) &&

IsBearishEngulfing(rates) &&

stochMain[1] > stochSignal[1] && stochMain[0] < stochSignal[0] &&

rates[1].close < ma[1]) // Precio abajo de MA para tendencia bajista

double sl = CalculateStopLoss(false, rates, atrValue);

double tp = rates[1].close - (sl - rates[1].close) * RewardRatio;

double lotSize = CalculateLotSize(sl);

EnterTrade(OP_SELL, lotSize, sl, tp, "Venta por rechazo");

}
//+------------------------------------------------------------------+

//| Funciones auxiliares mejoradas |

//+------------------------------------------------------------------+

// Detectar zonas de soporte y resistencia

void DetectSupportResistance()

ArrayResize(supports, 0);

ArrayResize(resistances, 0);

// Buscar mínimos locales para soportes

for(int i = 3; i < S_R_Lookback; i++)

double low1 = iLow(NULL, 0, i);

double low2 = iLow(NULL, 0, i+1);

double low3 = iLow(NULL, 0, i+2);

if(low2 < low1 && low2 < low3) // Mínimo local

AddToZoneArray(supports, low2, true);

// Buscar máximos locales para resistencias

for(int i = 3; i < S_R_Lookback; i++)


{

double high1 = iHigh(NULL, 0, i);

double high2 = iHigh(NULL, 0, i+1);

double high3 = iHigh(NULL, 0, i+2);

if(high2 > high1 && high2 > high3) // Máximo local

AddToZoneArray(resistances, high2, false);

// Filtrar y ordenar zonas

FilterAndSortZones(supports);

FilterAndSortZones(resistances);

// Dibujar zonas si está activado

if(ShowZones)

DeleteZones();

DrawZones(supports, SupportColor);

DrawZones(resistances, ResistanceColor);

// Añadir precio al array de zonas con cálculo de fuerza


void AddToZoneArray(S_R_Zone &zones[], double price, bool isSupport)

double zoneWidth = S_R_ZoneWidthPips * _Point;

for(int i = 0; i < ArraySize(zones); i++)

if(MathAbs(zones[i].price - price) <= zoneWidth)

zones[i].touches++;

zones[i].lastTouch = iTime(NULL, 0, 1);

// Calcular fuerza basada en toques y antigüedad

zones[i].strength = MathMin(zones[i].touches / 5.0, 1.0) *

(1 - (TimeCurrent() - zones[i].lastTouch) / (86400.0 * 30));

if(MathAbs(zones[i].price - price) < zoneWidth/2)

zones[i].price = (zones[i].price * zones[i].touches + price) / (zones[i].touches + 1);

return;

// Si no se encontró zona cercana, añadir nueva

int size = ArraySize(zones);

ArrayResize(zones, size+1);

zones[size].price = price;

zones[size].touches = 1;

zones[size].lastTouch = iTime(NULL, 0, 1);


zones[size].isSupport = isSupport;

zones[size].strength = 0.2; // Fuerza inicial

// Filtrar y ordenar zonas por relevancia

void FilterAndSortZones(S_R_Zone &zones[])

S_R_Zone tempZones[];

int count = 0;

// Filtrar por número mínimo de toques

for(int i = 0; i < ArraySize(zones); i++)

if(zones[i].touches >= S_R_MinTouches)

ArrayResize(tempZones, count+1);

tempZones[count] = zones[i];

count++;

// Ordenar por fuerza (más fuerte primero)

for(int i = 0; i < ArraySize(tempZones); i++)

for(int j = i+1; j < ArraySize(tempZones); j++)


{

if(tempZones[j].strength > tempZones[i].strength)

S_R_Zone temp = tempZones[i];

tempZones[i] = tempZones[j];

tempZones[j] = temp;

ArrayCopy(zones, tempZones);

// Verificar ruptura de resistencia mejorada

bool IsResistanceBreak(MqlRates &rates[])

double zoneWidth = S_R_ZoneWidthPips * _Point;

for(int i = 0; i < ArraySize(resistances); i++)

if(resistances[i].strength > 0.5) // Solo zonas con fuerza > 0.5

double zoneTop = resistances[i].price + zoneWidth;

double zoneBottom = resistances[i].price - zoneWidth;


// Verificar que el precio anterior estaba dentro de la zona

if(rates[1].high >= zoneBottom && rates[1].low <= zoneTop)

// Verificar ruptura por cierre fuera de la zona

if(rates[0].close > zoneTop && rates[0].open < zoneTop)

return true;

return false;

// Verificar rechazo en resistencia mejorado

bool IsResistanceRejection(MqlRates &rates[])

double zoneWidth = S_R_ZoneWidthPips * _Point;

for(int i = 0; i < ArraySize(resistances); i++)

if(resistances[i].strength > 0.5) // Solo zonas con fuerza > 0.5

double zoneTop = resistances[i].price + zoneWidth;

double zoneBottom = resistances[i].price - zoneWidth;


// Verificar que el precio tocó la zona pero cerró fuera

if(rates[0].high >= zoneBottom && rates[0].high <= zoneTop &&

rates[0].close < zoneBottom)

// Verificar volumen y sombra superior

if(rates[0].tick_volume > iVolume(NULL, 0, 1) &&

(rates[0].high - rates[0].close) > (rates[0].close - rates[0].low))

return true;

return false;

// Verificar ruptura de soporte mejorada

bool IsSupportBreak(MqlRates &rates[])

double zoneWidth = S_R_ZoneWidthPips * _Point;

for(int i = 0; i < ArraySize(supports); i++)

if(supports[i].strength > 0.5) // Solo zonas con fuerza > 0.5


{

double zoneTop = supports[i].price + zoneWidth;

double zoneBottom = supports[i].price - zoneWidth;

// Verificar que el precio anterior estaba dentro de la zona

if(rates[1].high >= zoneBottom && rates[1].low <= zoneTop)

// Verificar ruptura por cierre fuera de la zona

if(rates[0].close < zoneBottom && rates[0].open > zoneBottom)

return true;

return false;

// Verificar rechazo en soporte mejorado

bool IsSupportRejection(MqlRates &rates[])

double zoneWidth = S_R_ZoneWidthPips * _Point;

for(int i = 0; i < ArraySize(supports); i++)

{
if(supports[i].strength > 0.5) // Solo zonas con fuerza > 0.5

double zoneTop = supports[i].price + zoneWidth;

double zoneBottom = supports[i].price - zoneWidth;

// Verificar que el precio tocó la zona pero cerró fuera

if(rates[0].low >= zoneBottom && rates[0].low <= zoneTop &&

rates[0].close > zoneTop)

// Verificar volumen y sombra inferior

if(rates[0].tick_volume > iVolume(NULL, 0, 1) &&

(rates[0].close - rates[0].low) > (rates[0].high - rates[0].close))

return true;

return false;

// Verificar patrón envolvente alcista mejorado

bool IsBullishEngulfing(MqlRates &rates[])

// La vela anterior es bajista


if(rates[1].close >= rates[1].open) return false;

// La vela actual es alcista

if(rates[0].close <= rates[0].open) return false;

// El cuerpo actual engulle el cuerpo anterior

if(rates[0].open > rates[1].close || rates[0].close < rates[1].open) return false;

// Confirmación con volumen

if(rates[0].tick_volume < rates[1].tick_volume * 1.2) return false;

return true;

// Verificar patrón envolvente bajista mejorado

bool IsBearishEngulfing(MqlRates &rates[])

// La vela anterior es alcista

if(rates[1].close <= rates[1].open) return false;

// La vela actual es bajista

if(rates[0].close >= rates[0].open) return false;

// El cuerpo actual engulle el cuerpo anterior

if(rates[0].open < rates[1].close || rates[0].close > rates[1].open) return false;


// Confirmación con volumen

if(rates[0].tick_volume < rates[1].tick_volume * 1.2) return false;

return true;

// Calcular Stop Loss basado en estructura o ATR

double CalculateStopLoss(bool isBuy, MqlRates &rates[], double atrValue)

if(UseAtrSL)

return isBuy ? rates[0].close - atrValue * AtrMultiplier :

rates[0].close + atrValue * AtrMultiplier;

else

return isBuy ? iLow(NULL, 0, iLowest(NULL, 0, MODE_LOW, 20, 1)) :

iHigh(NULL, 0, iHighest(NULL, 0, MODE_HIGH, 20, 1));

// Calcular tamaño de lote basado en riesgo

double CalculateLotSize(double slPrice)

{
double riskAmount = AccountBalance() * RiskPercent / 100.0;

double pointValue = MarketInfo(Symbol(), MODE_TICKVALUE);

double pointsRisk = MathAbs(slPrice - (OrderType() == OP_BUY ? Bid : Ask)) / _Point;

if(pointValue == 0 || pointsRisk == 0) return LotSize;

double lots = riskAmount / (pointValue * pointsRisk);

lots = MathMin(lots, MarketInfo(Symbol(), MODE_MAXLOT));

lots = MathMax(lots, MarketInfo(Symbol(), MODE_MINLOT));

return NormalizeDouble(lots, 2);

// Entrar en una operación

void EnterTrade(int type, double lots, double sl, double tp, string comment)

double price = (type == OP_BUY) ? Ask : Bid;

double slPoints = MathAbs(price - sl) / _Point;

double tpPoints = MathAbs(price - tp) / _Point;

if(slPoints < MarketInfo(Symbol(), MODE_STOPLEVEL) ||

tpPoints < MarketInfo(Symbol(), MODE_STOPLEVEL))

Print("Stop Loss o Take Profit demasiado cerca. Operación cancelada.");

return;
}

int ticket = OrderSend(Symbol(), type, lots, price, Slippage, sl, tp, comment, MagicNumber, 0,

type == OP_BUY ? clrGreen : clrRed);

if(ticket < 0)

Print("Error al abrir orden: ", GetLastError());

else

lastTradeTime = TimeCurrent();

// Contar órdenes abiertas por este EA

int CountOrders()

int count = 0;

for(int i = 0; i < OrdersTotal(); i++)

if(OrderSelect(i, SELECT_BY_POS) && OrderMagicNumber() == MagicNumber &&

OrderSymbol() == Symbol())

count++;
}

return count;

// Verificar si el trading está permitido

bool IsTradingAllowed()

// Verificar horario de trading

int hour = TimeHour(TimeCurrent());

if(hour < StartHour || hour >= EndHour) return false;

// Verificar día de la semana

int weekday = TimeDayOfWeek(TimeCurrent());

if((weekday == 1 && !Monday) || (weekday == 2 && !Tuesday) ||

(weekday == 3 && !Wednesday) || (weekday == 4 && !Thursday) ||

(weekday == 5 && !Friday)) return false;

// Evitar operar justo después de una operación previa

if(TimeCurrent() - lastTradeTime < 60) return false;

// Verificar conexión y permisos de trading

if(!IsConnected() || !IsTradeAllowed()) return false;

return true;
}

// Dibujar zonas en el gráfico

void DrawZones(S_R_Zone &zones[], color zoneColor)

for(int i = 0; i < MathMin(ArraySize(zones), 5); i++) // Mostrar máximo 5 zonas más fuertes

string name = (zones[i].isSupport ? "Support_" : "Resistance_") + IntegerToString(i);

double upper = zones[i].price + S_R_ZoneWidthPips * _Point;

double lower = zones[i].price - S_R_ZoneWidthPips * _Point;

// Crear rectángulo para la zona

ObjectCreate(0, name, OBJ_RECTANGLE, 0, iTime(NULL, 0, 100), upper, TimeCurrent(), lower);

ObjectSetInteger(0, name, OBJPROP_COLOR, zoneColor);

ObjectSetInteger(0, name, OBJPROP_BACK, true);

ObjectSetInteger(0, name, OBJPROP_FILL, true);

ObjectSetInteger(0, name, OBJPROP_WIDTH, 1);

ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID);

// Añadir etiqueta con fuerza de la zona

string labelName = name + "_Label";

ObjectCreate(0, labelName, OBJ_TEXT, 0, TimeCurrent(), upper);

ObjectSetString(0, labelName, OBJPROP_TEXT,

StringFormat("%s %.2f (F:%.1f)", zones[i].isSupport ? "S" : "R",

zones[i].price, zones[i].strength));
ObjectSetInteger(0, labelName, OBJPROP_COLOR, zoneColor);

ObjectSetInteger(0, labelName, OBJPROP_ANCHOR, ANCHOR_RIGHT_UPPER);

// Eliminar objetos de zonas del gráfico

void DeleteZones()

for(int i = 0; i < ObjectsTotal(); i++)

string name = ObjectName(i);

if(StringFind(name, "Support_") == 0 || StringFind(name, "Resistance_") == 0)

ObjectDelete(name);

// Calcular promedio de un array

double ArrayAverage(double &arr[])

double sum = 0;

for(int i = 0; i < ArraySize(arr); i++) sum += arr[i];

return sum / ArraySize(arr);

You might also like