245 lines
7.8 KiB
Plaintext
245 lines
7.8 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| Valid_Break_Detector |
|
|
//| Copyright 2023, MetaQuotes Software Corp. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2023, MetaQuotes Software Corp."
|
|
#property link "https://www.mql5.com"
|
|
#property version "1.00"
|
|
#property description "Detects Valid Breakouts of Zones with Rejection Confirmation"
|
|
|
|
// Input Parameters
|
|
input double LotSize = 0.1; // Lot size for trades
|
|
input int StopLoss = 50; // Stop Loss in points
|
|
input int TakeProfit = 100; // Take Profit in points
|
|
input bool RequireVolumeSpike = true; // Enable volume spike filter
|
|
input double VolumeThreshold = 1.5; // Minimum volume increase factor
|
|
input bool RequireCloseBeyond = true; // Require candle close beyond the zone
|
|
input int RejectionConfirmationCandles = 2; // Number of candles to confirm rejection
|
|
|
|
// Global Variables
|
|
int MagicNumber = 789101;
|
|
|
|
//
|
|
double _Ask = 0;
|
|
double _Bid = 0;
|
|
|
|
// Zone Boundaries
|
|
double ZoneHigh = 0;
|
|
double ZoneLow = 0;
|
|
|
|
//
|
|
double maBuffer[];
|
|
int maHandler = INVALID_HANDLE;
|
|
|
|
// Breakout Status
|
|
bool BullishBreakoutDetected = false;
|
|
bool BearishBreakoutDetected = false;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
//
|
|
ArraySetAsSeries(maBuffer, true);
|
|
maHandler = iMA(
|
|
_Symbol,
|
|
_Period,
|
|
14,
|
|
0,
|
|
MODE_SMA,
|
|
VOLUME_TICK //
|
|
);
|
|
if (maHandler == INVALID_HANDLE)
|
|
{
|
|
return (INIT_FAILED);
|
|
}
|
|
|
|
//
|
|
Print("Valid Break Detector EA Initialized");
|
|
return (INIT_SUCCEEDED);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
//
|
|
IndicatorRelease(maHandler);
|
|
Print("Valid Break Detector EA Deinitialized");
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert tick function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
//
|
|
_Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
|
_Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
|
CopyBuffer(maHandler, MAIN_LINE, 0, 14, maBuffer);
|
|
|
|
// Define the zone dynamically (e.g., based on recent highs/lows)
|
|
DefineZone();
|
|
|
|
// Check for valid break of the zone
|
|
CheckValidBreak();
|
|
|
|
// Confirm rejection after breakout
|
|
if (BullishBreakoutDetected || BearishBreakoutDetected)
|
|
ConfirmRejection();
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Function to define the zone dynamically |
|
|
//+------------------------------------------------------------------+
|
|
void DefineZone()
|
|
{
|
|
// Example: Define zone based on recent highs and lows
|
|
ZoneHigh = iHigh(_Symbol, _Period, 1); // Recent high
|
|
ZoneLow = iLow(_Symbol, _Period, 2); // Recent low
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Function to check for a valid break of the zone |
|
|
//+------------------------------------------------------------------+
|
|
void CheckValidBreak()
|
|
{
|
|
double currentPrice = _Bid;
|
|
|
|
// Check if price breaks above the zone
|
|
if (!BullishBreakoutDetected && currentPrice > ZoneHigh)
|
|
{
|
|
if (IsValidBreak(ZoneHigh, true))
|
|
{
|
|
Print("Potential Bullish Break Above Zone Detected at ", TimeToString(TimeCurrent(), TIME_DATE));
|
|
BullishBreakoutDetected = true;
|
|
}
|
|
}
|
|
|
|
// Check if price breaks below the zone
|
|
if (!BearishBreakoutDetected && currentPrice < ZoneLow)
|
|
{
|
|
if (IsValidBreak(ZoneLow, false))
|
|
{
|
|
Print("Potential Bearish Break Below Zone Detected at ", TimeToString(TimeCurrent(), TIME_DATE));
|
|
BearishBreakoutDetected = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Function to validate the breakout |
|
|
//+------------------------------------------------------------------+
|
|
bool IsValidBreak(double zoneLevel, bool isAbove)
|
|
{
|
|
// Check if the candle closed beyond the zone
|
|
if (RequireCloseBeyond)
|
|
{
|
|
double closePrice = iClose(_Symbol, _Period, 1);
|
|
if ((isAbove && closePrice <= zoneLevel) || (!isAbove && closePrice >= zoneLevel))
|
|
return false;
|
|
}
|
|
|
|
// Check for a volume spike
|
|
if (RequireVolumeSpike)
|
|
{
|
|
double currentVolume = (double) iVolume(_Symbol, _Period, 1);
|
|
double averageVolume = maBuffer[1];
|
|
if (currentVolume < VolumeThreshold * averageVolume)
|
|
return false;
|
|
}
|
|
|
|
// All conditions met, valid breakout
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Function to confirm rejection |
|
|
//+------------------------------------------------------------------+
|
|
void ConfirmRejection()
|
|
{
|
|
double currentPrice = _Bid;
|
|
|
|
if (BullishBreakoutDetected)
|
|
{
|
|
// Check if price rejects lower levels and confirms bullish breakout
|
|
bool confirmed = true;
|
|
for (int i = 1; i <= RejectionConfirmationCandles; i++)
|
|
{
|
|
double closePrice = iClose(_Symbol, _Period, i);
|
|
if (closePrice < ZoneHigh)
|
|
{
|
|
confirmed = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (confirmed)
|
|
{
|
|
Print("Bullish Breakout Confirmed at ", TimeToString(TimeCurrent(), TIME_DATE));
|
|
PlaceTrade(ORDER_TYPE_BUY, "Confirmed Bullish Breakout Buy");
|
|
BullishBreakoutDetected = false; // Reset breakout status
|
|
}
|
|
}
|
|
|
|
if (BearishBreakoutDetected)
|
|
{
|
|
// Check if price rejects higher levels and confirms bearish breakout
|
|
bool confirmed = true;
|
|
for (int i = 1; i <= RejectionConfirmationCandles; i++)
|
|
{
|
|
double closePrice = iClose(_Symbol, _Period, i);
|
|
if (closePrice > ZoneLow)
|
|
{
|
|
confirmed = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (confirmed)
|
|
{
|
|
Print("Bearish Breakout Confirmed at ", TimeToString(TimeCurrent(), TIME_DATE));
|
|
PlaceTrade(ORDER_TYPE_SELL, "Confirmed Bearish Breakout Sell");
|
|
BearishBreakoutDetected = false; // Reset breakout status
|
|
}
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Function to place a trade |
|
|
//+------------------------------------------------------------------+
|
|
void PlaceTrade(int orderType, string comment)
|
|
{
|
|
double price = (orderType == ORDER_TYPE_BUY) ? _Ask : _Bid;
|
|
double sl = (orderType == ORDER_TYPE_BUY) ? price - StopLoss * Point() : price + StopLoss * Point();
|
|
double tp = (orderType == ORDER_TYPE_BUY) ? price + TakeProfit * Point() : price - TakeProfit * Point();
|
|
|
|
MqlTradeRequest request;
|
|
MqlTradeResult result;
|
|
|
|
ZeroMemory(request);
|
|
ZeroMemory(result);
|
|
|
|
request.action = TRADE_ACTION_DEAL;
|
|
request.symbol = _Symbol;
|
|
request.volume = LotSize;
|
|
request.type = orderType;
|
|
request.price = price;
|
|
request.sl = sl;
|
|
request.tp = tp;
|
|
request.deviation = 10;
|
|
request.magic = MagicNumber;
|
|
request.comment = comment;
|
|
|
|
if (!OrderSend(request, result))
|
|
{
|
|
Print("Error placing order: ", result.retcode);
|
|
}
|
|
else
|
|
{
|
|
Print(comment, " Order placed successfully.");
|
|
}
|
|
} |