Add support for Golden Zone inside XPV indicator and it's Helper ...

This commit is contained in:
2025-03-08 22:00:36 +03:30
parent e0e081628a
commit 3b7ce3816a
9 changed files with 682 additions and 132 deletions
+275
View File
@@ -0,0 +1,275 @@
//+------------------------------------------------------------------+
//| OrderBlockDetector.mq5|
//| Copyright 2023, MetaQuotes Software Corp. |
//| https://www.mql5.com|
//+------------------------------------------------------------------+
#property strict
//
// Input Parameters
input int ConsolidationPeriod = 20; // Bars for consolidation detection
input int AtrPeriod = 14; // ATR period for volatility
input double AtrMultiplier = 2.0; // Threshold multiplier (ATR * multiplier)
input int VolumeThreshold = 1000; // Minimum volume for breakout
input bool RequireRetest = true; // Retest confirmation required?
input int VpvrBars = 50; // Bars for VPVR calculation
input int TrendCheckPeriod = 30; // Bars for trend structure analysis
input int MACDFast = 12; // MACD Fast EMA period
input int MACDSlow = 26; // MACD Slow EMA period
input int MACDSignal = 9; // MACD Signal period
input int RSIPeriod = 14; // RSI period
input double RSILevel = 50; // RSI threshold level
// Global Variables
int ObjectId = 0;
string Prefix = "OrderBlock_";
//
enum ENUM_X_DIRECTION
{
X_DIRECTION_NONE,
X_DIRECTION_BULISH,
X_DIRECTION_BEARISH,
};
//
int atrHandler = INVALID_HANDLE;
double atrBuffer[];
//
int rsiHandler = INVALID_HANDLE;
double rsiBuffer[];
//
int macdHandler = INVALID_HANDLE;
double macdMainBuffer[];
double macdSignalBuffer[];
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//
ArraySetAsSeries(atrBuffer, true);
atrHandler = iATR(_Symbol, _Period, AtrPeriod);
//
ArraySetAsSeries(rsiBuffer, true);
rsiHandler = iRSI(_Symbol, _Period, RSIPeriod, PRICE_CLOSE);
//
ArraySetAsSeries(macdMainBuffer, true);
ArraySetAsSeries(macdSignalBuffer, true);
macdHandler = iMACD(_Symbol, _Period, MACDFast, MACDSlow, MACDSignal, PRICE_CLOSE);
//
ObjectsDeleteAll(0, Prefix);
return (INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//
IndicatorRelease(atrHandler);
ObjectsDeleteAll(0, Prefix);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
DetectOrderBlocks();
}
//+------------------------------------------------------------------+
//| Detect Order Blocks with ATR Dynamic Threshold |
//+------------------------------------------------------------------+
void DetectOrderBlocks()
{
double high, low, vpvrPrice, atr, dynamicThreshold;
datetime startTime, endTime;
bool isBullish, isBearish;
int bars = Bars(_Symbol, _Period);
for (int i = ConsolidationPeriod; i < bars; i++)
{
//
// Get consolidation range
high = iHigh(_Symbol, _Period, iHighest(_Symbol, _Period, MODE_HIGH, ConsolidationPeriod, i));
low = iLow(_Symbol, _Period, iLowest(_Symbol, _Period, MODE_LOW, ConsolidationPeriod, i));
double range = high - low;
//
// Calculate dynamic threshold using ATR
CopyBuffer(atrHandler, MAIN_LINE, i, 2, atrBuffer);
atr = atrBuffer[0];
dynamicThreshold = atr * AtrMultiplier;
// Check if consolidation range is within ATR-based threshold
if (range <= dynamicThreshold)
{
// VPVR Integration
vpvrPrice = CalculateVPVR(i, ConsolidationPeriod);
bool validVPVR = (vpvrPrice > low && vpvrPrice < high);
// Check breakout direction
isBullish = iClose(_Symbol, _Period, i - ConsolidationPeriod) > high;
isBearish = iClose(_Symbol, _Period, i - ConsolidationPeriod) < low;
// Trend Verification
ENUM_X_DIRECTION trend = CheckTrendStructure(TrendCheckPeriod);
// MACD/RSI Verification
bool macdValid = CheckMACD(trend);
bool rsiValid = CheckRSI(trend);
// Validate all conditions
if ((isBullish || isBearish) && validVPVR &&
(trend != -1) && macdValid && rsiValid)
{
double breakoutVolume = (double)iVolume(_Symbol, _Period, i - ConsolidationPeriod);
if (breakoutVolume < VolumeThreshold)
continue;
// Define order block time window
startTime = iTime(_Symbol, _Period, i);
endTime = iTime(_Symbol, _Period, i + ConsolidationPeriod);
// Check retest (if required)
if (RequireRetest)
{
bool retestFound = false;
for (int j = i - ConsolidationPeriod; j > 0; j--)
{
if ((isBullish && iLow(_Symbol, _Period, j) <= low && iLow(_Symbol, _Period, j) >= high) ||
(isBearish && iHigh(_Symbol, _Period, j) >= high && iHigh(_Symbol, _Period, j) <= low))
{
retestFound = true;
break;
}
}
if (!retestFound)
continue;
}
// Draw order block with ATR annotation
string name = Prefix + IntegerToString(ObjectId++);
DrawOrderBlock(name, startTime, endTime, low, high,
isBullish ? clrGreen : clrRed, vpvrPrice, dynamicThreshold);
}
}
}
}
//+------------------------------------------------------------------+
//| Trend Detection using Price Structure |
//+------------------------------------------------------------------+
ENUM_X_DIRECTION CheckTrendStructure(int period)
{
int currentStart = 1;
int previousStart = period + 1;
double currentHigh = iHigh(_Symbol, _Period, iHighest(_Symbol, _Period, MODE_HIGH, period, currentStart));
double previousHigh = iHigh(_Symbol, _Period, iHighest(_Symbol, _Period, MODE_HIGH, period, previousStart));
double currentLow = iLow(_Symbol, _Period, iLowest(_Symbol, _Period, MODE_LOW, period, currentStart));
double previousLow = iLow(_Symbol, _Period, iLowest(_Symbol, _Period, MODE_LOW, period, previousStart));
if (currentHigh > previousHigh && currentLow > previousLow)
return (X_DIRECTION_BULISH); // Uptrend
else if (currentHigh < previousHigh && currentLow < previousLow)
return (X_DIRECTION_BEARISH); // Downtrend
else
return (X_DIRECTION_NONE); // No clear trend
}
//+------------------------------------------------------------------+
//| MACD Trend Verification |
//+------------------------------------------------------------------+
bool CheckMACD(ENUM_X_DIRECTION trend)
{
//
CopyBuffer(macdHandler, MAIN_LINE, 0, 1, macdMainBuffer);
CopyBuffer(macdHandler, SIGNAL_LINE, 0, 1, macdSignalBuffer);
double macdMain = macdMainBuffer[0];
double macdSignal = macdSignalBuffer[0];
//
if (trend == X_DIRECTION_BULISH)
return (macdMain > macdSignal);
if (trend == X_DIRECTION_BEARISH)
return (macdMain < macdSignal);
return (false);
}
//+------------------------------------------------------------------+
//| RSI Trend Verification |
//+------------------------------------------------------------------+
bool CheckRSI(ENUM_X_DIRECTION trend)
{
//
CopyBuffer(rsiHandler, MAIN_LINE, 0, 1, rsiBuffer);
double rsiValue = rsiBuffer[0];
//
if (trend == X_DIRECTION_BULISH)
return (rsiValue > RSILevel);
if (trend == X_DIRECTION_BEARISH)
return (rsiValue < RSILevel);
return (false);
}
//+------------------------------------------------------------------+
//| Calculate VPVR High Volume Node |
//+------------------------------------------------------------------+
double CalculateVPVR(int startIdx, int period)
{
double maxVolume = 0;
double vpvrPrice = 0;
double price, volume;
for (int i = startIdx; i < startIdx + period; i++)
{
price = (iHigh(_Symbol, _Period, i) + iLow(_Symbol, _Period, i)) / 2;
volume = (double)iVolume(_Symbol, _Period, i);
if (volume > maxVolume)
{
maxVolume = volume;
vpvrPrice = price;
}
}
return (vpvrPrice);
}
//+------------------------------------------------------------------+
//| Draw Order Block with ATR Annotation |
//+------------------------------------------------------------------+
void DrawOrderBlock(string name, datetime startTime, datetime endTime,
double bottom, double top, color clr, double vpvrPrice, double atrThreshold)
{
// Draw rectangle
ObjectCreate(0, name + "_rect", OBJ_RECTANGLE, 0, startTime, top, endTime, bottom);
ObjectSetInteger(0, name + "_rect", OBJPROP_COLOR, clr);
ObjectSetInteger(0, name + "_rect", OBJPROP_FILL, true);
ObjectSetInteger(0, name + "_rect", OBJPROP_BACK, true);
ObjectSetInteger(0, name + "_rect", OBJPROP_WIDTH, 2);
// Draw VPVR marker
if (vpvrPrice > 0)
{
ObjectCreate(0, name + "_vpvr", OBJ_HLINE, 0, 0, vpvrPrice);
ObjectSetInteger(0, name + "_vpvr", OBJPROP_COLOR, clrYellow);
ObjectSetInteger(0, name + "_vpvr", OBJPROP_WIDTH, 1);
}
// Add ATR threshold label
string atrLabel = StringFormat("ATR Threshold: %.5f", atrThreshold);
ObjectCreate(0, name + "_atr", OBJ_TEXT, 0, startTime, top);
ObjectSetString(0, name + "_atr", OBJPROP_TEXT, atrLabel);
ObjectSetInteger(0, name + "_atr", OBJPROP_COLOR, clrWhite);
}
//+------------------------------------------------------------------+