This commit is contained in:
2025-05-10 03:27:45 +03:30
parent f49231eeb2
commit c378ce4b4e
6 changed files with 1384 additions and 11 deletions
@@ -0,0 +1,96 @@
//
// Detect Block Based Trigger ...
XBoxZone ob;
XOHCL swing;
XOHCL breaker;
XOHCL outSide;
ENUM_X_DIRECTION passedDir;
bool isPassed = helper.IsBlockBasedTriggerBar(
ob,
swing,
breaker,
outSide,
passedDir,
1, // Bar Index ...
50, // Loopback ...
3 // Swing Length ...
);
if (isPassed)
{
//
// Draw Block Based Trigger ...
//
// Draw OB ...
XCBoxObject *obObject;
has = helper.poiDrawer.DrawBox(
ob,
obObject //
);
if (has)
{
//
obObject.BoxWidth(2);
obObject.BoxStyle(STYLE_SOLID);
//
color obColor =
ob.IsBullish()
? clrAqua
: clrMagenta;
obObject.BoxColor(obColor);
//
mObjects.Add(obObject);
//
ZeroMemory(obObject);
}
//
double breakPrice =
ob.IsBullish()
? swing.high
: swing.low;
//
// Draw Swing and Breake ...
CChartObjectTrend *tObj;
tObj = new CChartObjectTrend();
string tName = "Swing_For_" + ToString(ob.dir) + "_" + ToString(breakPrice);
has = tObj.Create(
0,
tName,
0,
swing.time,
breakPrice,
breaker.time,
breakPrice //
);
if (has)
{
//
tObj.Width(2);
tObj.Style(STYLE_SOLID);
//
color tColor = ob.IsBullish()
? clrRed
: clrLime;
tObj.Color(tColor);
//
mObjects.Add(tObj);
//
ZeroMemory(tObj);
}
//
Print("Passed Bar ...");
}
ob.Clean();
swing.Clean();
breaker.Clean();
outSide.Clean();
+317
View File
@@ -0,0 +1,317 @@
//+------------------------------------------------------------------+
//| RSI_Div.mq5 |
//| Copyright 2023, MetaQuotes Software Corp. |
//| https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Software Corp."
#property link "https://www.metaquotes.net/"
#property version "1.00"
#property indicator_separate_window
#property indicator_buffers 8
#property indicator_plots 2
#property indicator_label1 "RSI"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDodgerBlue
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
#property indicator_label2 "Signal"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrOrange
#property indicator_style2 STYLE_DOT
#property indicator_width2 1
//--- Input parameters
input int InpRSIPeriod = 14; // RSI Period
input ENUM_APPLIED_PRICE InpRSIPrice = PRICE_CLOSE; // RSI Applied Price
input int InpLeftBars = 5; // Left bars to check
input int InpRightBars = 5; // Right bars to check
input double InpMinDivergence = 5.0; // Minimum divergence in %
input bool ShowRegularBullish = true; // Show Regular Bullish
input bool ShowRegularBearish = true; // Show Regular Bearish
input bool ShowHiddenBullish = true; // Show Hidden Bullish
input bool ShowHiddenBearish = true; // Show Hidden Bearish
//--- Indicator buffers
double RSIBuffer[];
double SignalBuffer[];
double HighBuffer[];
double LowBuffer[];
double BullishDivBuffer[];
double BearishDivBuffer[];
double HiddenBullishDivBuffer[];
double HiddenBearishDivBuffer[];
//--- Handles
int rsiHandle;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Indicator buffers mapping
SetIndexBuffer(0, RSIBuffer, INDICATOR_DATA);
SetIndexBuffer(1, SignalBuffer, INDICATOR_DATA);
SetIndexBuffer(2, HighBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer(3, LowBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer(4, BullishDivBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer(5, BearishDivBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer(6, HiddenBullishDivBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer(7, HiddenBearishDivBuffer, INDICATOR_CALCULATIONS);
//--- Set accuracy
IndicatorSetInteger(INDICATOR_DIGITS, 2);
//--- Set first bar from what index will be drawn
PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, InpRSIPeriod);
//--- Create RSI handle
rsiHandle = iRSI(NULL, 0, InpRSIPeriod, InpRSIPrice);
if (rsiHandle == INVALID_HANDLE)
{
Print("Failed to create RSI handle");
return (INIT_FAILED);
}
//--- Set buffer names
string short_name = "RSI Divergence(" + string(InpRSIPeriod) + ")";
IndicatorSetString(INDICATOR_SHORTNAME, short_name);
//--- Set empty value
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);
PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0.0);
//--- Initialize arrays as series
ArraySetAsSeries(RSIBuffer, true);
ArraySetAsSeries(SignalBuffer, true);
ArraySetAsSeries(HighBuffer, true);
ArraySetAsSeries(LowBuffer, true);
ArraySetAsSeries(BullishDivBuffer, true);
ArraySetAsSeries(BearishDivBuffer, true);
ArraySetAsSeries(HiddenBullishDivBuffer, true);
ArraySetAsSeries(HiddenBearishDivBuffer, true);
return (INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| 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[])
{
//--- Check for data sufficiency
if (rates_total < InpRSIPeriod + InpLeftBars + InpRightBars)
return (0);
//--- Get RSI values
if (CopyBuffer(rsiHandle, 0, 0, rates_total, RSIBuffer) <= 0)
{
Print("Failed to copy RSI buffer");
return (0);
}
//--- Calculate signal line (just for visualization)
for (int i = 0; i < rates_total; i++)
SignalBuffer[i] = 30 + (70 - 30) / 2;
//--- Find divergences
FindDivergences(rates_total, prev_calculated, high, low, close, time);
return (rates_total);
}
//+------------------------------------------------------------------+
//| Find divergences between price and RSI |
//+------------------------------------------------------------------+
void FindDivergences(const int rates_total,
const int prev_calculated,
const double &high[],
const double &low[],
const double &close[],
const datetime &time[])
{
int start_bar = MathMax(InpRSIPeriod + InpLeftBars + InpRightBars, prev_calculated);
for (int i = start_bar; i < rates_total && !IsStopped(); i++)
{
//--- Reset buffers
BullishDivBuffer[i] = 0;
BearishDivBuffer[i] = 0;
HiddenBullishDivBuffer[i] = 0;
HiddenBearishDivBuffer[i] = 0;
//--- Check array boundaries
if (i - InpLeftBars < 0 || i + InpRightBars >= rates_total)
continue;
//--- Find highest high and lowest low in left bars
int highest_high_bar = Highest(high, i - InpLeftBars, InpLeftBars + InpRightBars + 1);
int lowest_low_bar = Lowest(low, i - InpLeftBars, InpLeftBars + InpRightBars + 1);
//--- Check for regular bullish divergence
if (ShowRegularBullish && lowest_low_bar >= 0)
{
int rsi_lowest_bar = LowestRSI(i - InpLeftBars, InpLeftBars + InpRightBars + 1);
if (rsi_lowest_bar >= 0 && rsi_lowest_bar != lowest_low_bar &&
low[i - lowest_low_bar] < low[i] &&
RSIBuffer[i - rsi_lowest_bar] > RSIBuffer[i] &&
MathAbs(RSIBuffer[i - rsi_lowest_bar] - RSIBuffer[i]) >= InpMinDivergence)
{
BullishDivBuffer[i] = RSIBuffer[i] - 5;
if (i < ArraySize(time) && i < ArraySize(low))
ObjectCreate(0, "BullDiv" + IntegerToString(i), OBJ_ARROW_UP, 0, time[i], low[i] - 50 * _Point);
}
}
//--- Check for regular bearish divergence
if (ShowRegularBearish && highest_high_bar >= 0)
{
int rsi_highest_bar = HighestRSI(i - InpLeftBars, InpLeftBars + InpRightBars + 1);
if (rsi_highest_bar >= 0 && rsi_highest_bar != highest_high_bar &&
high[i - highest_high_bar] > high[i] &&
RSIBuffer[i - rsi_highest_bar] < RSIBuffer[i] &&
MathAbs(RSIBuffer[i - rsi_highest_bar] - RSIBuffer[i]) >= InpMinDivergence)
{
BearishDivBuffer[i] = RSIBuffer[i] + 5;
if (i < ArraySize(time) && i < ArraySize(high))
ObjectCreate(0, "BearDiv" + IntegerToString(i), OBJ_ARROW_DOWN, 0, time[i], high[i] + 50 * _Point);
}
}
//--- Check for hidden bullish divergence
if (ShowHiddenBullish && lowest_low_bar >= 0)
{
int rsi_lowest_bar = LowestRSI(i - InpLeftBars, InpLeftBars + InpRightBars + 1);
if (rsi_lowest_bar >= 0 && rsi_lowest_bar != lowest_low_bar &&
low[i - lowest_low_bar] > low[i] &&
RSIBuffer[i - rsi_lowest_bar] < RSIBuffer[i] &&
MathAbs(RSIBuffer[i - rsi_lowest_bar] - RSIBuffer[i]) >= InpMinDivergence)
{
HiddenBullishDivBuffer[i] = RSIBuffer[i] - 8;
if (i < ArraySize(time) && i < ArraySize(low))
ObjectCreate(0, "HidBullDiv" + IntegerToString(i), OBJ_ARROW_UP, 0, time[i], low[i] - 80 * _Point);
}
}
//--- Check for hidden bearish divergence
if (ShowHiddenBearish && highest_high_bar >= 0)
{
int rsi_highest_bar = HighestRSI(i - InpLeftBars, InpLeftBars + InpRightBars + 1);
if (rsi_highest_bar >= 0 && rsi_highest_bar != highest_high_bar &&
high[i - highest_high_bar] < high[i] &&
RSIBuffer[i - rsi_highest_bar] > RSIBuffer[i] &&
MathAbs(RSIBuffer[i - rsi_highest_bar] - RSIBuffer[i]) >= InpMinDivergence)
{
HiddenBearishDivBuffer[i] = RSIBuffer[i] + 8;
if (i < ArraySize(time) && i < ArraySize(high))
ObjectCreate(0, "HidBearDiv" + IntegerToString(i), OBJ_ARROW_DOWN, 0, time[i], high[i] + 80 * _Point);
}
}
}
}
//+------------------------------------------------------------------+
//| Find bar with highest price in range |
//+------------------------------------------------------------------+
int Highest(const double &price[], int start_pos, int count)
{
if (start_pos < 0 || count <= 0 || start_pos + count > ArraySize(price))
return -1;
int highest_pos = start_pos;
double highest_val = price[start_pos];
for (int i = start_pos + 1; i < start_pos + count; i++)
{
if (price[i] > highest_val)
{
highest_val = price[i];
highest_pos = i;
}
}
return highest_pos - start_pos;
}
//+------------------------------------------------------------------+
//| Find bar with lowest price in range |
//+------------------------------------------------------------------+
int Lowest(const double &price[], int start_pos, int count)
{
if (start_pos < 0 || count <= 0 || start_pos + count > ArraySize(price))
return -1;
int lowest_pos = start_pos;
double lowest_val = price[start_pos];
for (int i = start_pos + 1; i < start_pos + count; i++)
{
if (price[i] < lowest_val)
{
lowest_val = price[i];
lowest_pos = i;
}
}
return lowest_pos - start_pos;
}
//+------------------------------------------------------------------+
//| Find bar with highest RSI in range |
//+------------------------------------------------------------------+
int HighestRSI(int start_pos, int count)
{
if (start_pos < 0 || count <= 0 || start_pos + count > ArraySize(RSIBuffer))
return -1;
int highest_pos = start_pos;
double highest_val = RSIBuffer[start_pos];
for (int i = start_pos + 1; i < start_pos + count; i++)
{
if (RSIBuffer[i] > highest_val)
{
highest_val = RSIBuffer[i];
highest_pos = i;
}
}
return highest_pos - start_pos;
}
//+------------------------------------------------------------------+
//| Find bar with lowest RSI in range |
//+------------------------------------------------------------------+
int LowestRSI(int start_pos, int count)
{
if (start_pos < 0 || count <= 0 || start_pos + count > ArraySize(RSIBuffer))
return -1;
int lowest_pos = start_pos;
double lowest_val = RSIBuffer[start_pos];
for (int i = start_pos + 1; i < start_pos + count; i++)
{
if (RSIBuffer[i] < lowest_val)
{
lowest_val = RSIBuffer[i];
lowest_pos = i;
}
}
return lowest_pos - start_pos;
}
+198
View File
@@ -0,0 +1,198 @@
//+------------------------------------------------------------------+
//| RSIDivergence.mq5|
//| Custom RSI Divergence Detection Indicator |
//+------------------------------------------------------------------+
#property strict
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 0
//--- Input parameters
input int RSI_Period = 14; // RSI Period
input double Deviation = 0.0001; // Minimum price move to consider a swing
input int MaxBarsBack = 300; // Number of bars to analyze
//--- Global handles
double rsiBuffer[];
int rsiHandle;
//--- For divergence detection
struct SwingPoint
{
int index;
double price;
double rsi;
};
SwingPoint priceSwings[];
SwingPoint rsiSwings[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
SetIndexBuffer(0, rsiBuffer, INDICATOR_DATA);
rsiHandle = iRSI(_Symbol, _Period, RSI_Period, PRICE_CLOSE);
if (rsiHandle == INVALID_HANDLE)
{
Print("Could not create RSI handle");
return (INIT_FAILED);
}
return (INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Main 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[])
{
//--- Get RSI values
ArraySetAsSeries(rsiBuffer, true);
CopyBuffer(rsiHandle, 0, 0, MaxBarsBack, rsiBuffer);
//--- Detect swings
DetectSwingPoints(close, priceSwings);
DetectSwingPoints(rsiBuffer, rsiSwings);
//--- Find and draw divergences
FindAndDrawDivergences(time, close);
return (rates_total);
}
//+------------------------------------------------------------------+
//| Detect swing highs/lows |
//+------------------------------------------------------------------+
void DetectSwingPoints(const double &values[], SwingPoint &swings[])
{
ArrayResize(swings, 0); // Clear previous swings
int count = 0;
int size = ArraySize(values);
if (size < 3)
return; // Not enough data
// Pre-allocate a safe amount of space
ArrayResize(swings, size / 2); // Max possible swings ~50% of total bars
for (int i = 2; i < size - 2; i++)
{
// Bounds check
if (i - 1 < 0 || i + 1 >= size)
continue;
// Check for swing high
if (values[i] > values[i - 1] && values[i] > values[i + 1])
{
// Ensure we have space in the swings array
if (count >= ArraySize(swings))
ArrayResize(swings, ArraySize(swings) + 10);
swings[count].index = i;
swings[count].price = values[i];
count++;
}
// Check for swing low
else if (values[i] < values[i - 1] && values[i] < values[i + 1])
{
// Ensure we have space in the swings array
if (count >= ArraySize(swings))
ArrayResize(swings, ArraySize(swings) + 10);
swings[count].index = i;
swings[count].price = values[i];
count++;
}
}
// Final resize to actual number of swings found
ArrayResize(swings, count);
}
//+------------------------------------------------------------------+
//| Find and draw divergence |
//+------------------------------------------------------------------+
void FindAndDrawDivergences(const datetime &time[], const double &close[])
{
static int lastAlertBar = 0;
int limit = MathMin(MaxBarsBack - 2, Bars(_Symbol, _Period));
for (int i = 0; i < ArraySize(priceSwings) - 1; i++)
{
for (int j = 0; j < ArraySize(rsiSwings) - 1; j++)
{
int p1 = priceSwings[i].index;
int p2 = priceSwings[i + 1].index;
int r1 = rsiSwings[j].index;
int r2 = rsiSwings[j + 1].index;
if (MathAbs(p1 - r1) < 3 && MathAbs(p2 - r2) < 3)
{
double price1 = close[p1];
double price2 = close[p2];
double rsi1 = rsiBuffer[r1];
double rsi2 = rsiBuffer[r2];
// Bullish Divergence
if (price2 < price1 && rsi2 > rsi1)
{
string name;
StringConcatenate(name, "BullishDiv", IntegerToString(p2));
DrawArrow(name, time[p2], close[p2], clrLime);
// DrawLine("BullishLineP" + IntegerToString(p2), time[p2], close[p2], time[p1], close[p1], clrLime);
// DrawLine("BullishLineR" + IntegerToString(p2), time[p2], rsi2, time[p1], rsi1, clrLime);
}
// Bearish Divergence
if (price2 > price1 && rsi2 < rsi1)
{
string name;
StringConcatenate(name, "BearishDiv", IntegerToString(p2));
DrawArrow(name, time[p2], close[p2], clrRed);
// DrawLine("BearishLineP" + IntegerToString(p2), time[p2], close[p2], time[p1], close[p1], clrRed);
// DrawLine("BearishLineR" + IntegerToString(p2), time[p2], rsi2, time[p1], rsi1, clrRed);
}
}
}
}
}
//+------------------------------------------------------------------+
//| Draw arrow on chart |
//+------------------------------------------------------------------+
void DrawArrow(string name, datetime time, double price, color col)
{
ObjectCreate(0, name, OBJ_ARROW, 0, time, price);
ObjectSetInteger(0, name, OBJPROP_ARROWCODE, 233); // Up arrow
ObjectSetInteger(0, name, OBJPROP_COLOR, col);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
}
//+------------------------------------------------------------------+
//| Draw line |
//+------------------------------------------------------------------+
void DrawLine(string name, datetime t1, double p1, datetime t2, double p2, color col)
{
// Delete existing object if any
ObjectDelete(0, name);
// Create trendline (use 1 for OBJ_TRENDLINE if undefined)
ObjectCreate(0, name, 1, 0, t1, p1, t2, p2);
ObjectSetInteger(0, name, OBJPROP_COLOR, col);
ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_DASHDOT);
ObjectSetInteger(0, name, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
}
//
+533
View File
@@ -4140,6 +4140,539 @@ class XCXCAEAHelper : XCBase
return result;
}
//
bool IsBlockBasedTriggerBar(
XBoxZone &ob,
XOHCL &swingBar,
XOHCL &breakerBar,
XOHCL &outSideBar,
ENUM_X_DIRECTION &dir,
int barIndex = 0,
int loopback = 40,
int swingLength = 3 //
)
{
//
bool result = false;
//
// Normalize Args ...
ob.Clean();
swingBar.Clean();
breakerBar.Clean();
outSideBar.Clean();
dir = X_DIRECTION_NONE;
barIndex = NormalizeInt(barIndex, 0);
loopback = NormalizeInt(loopback, 30);
//
// Initializing Current Bar ...
XOHCL bar;
result = bar.Init(
GetSymbol(),
GetPeriod(),
barIndex //
);
if (!result)
{
//
ob.Clean();
bar.Clean();
swingBar.Clean();
breakerBar.Clean();
outSideBar.Clean();
dir = X_DIRECTION_NONE;
//
return result;
}
//
// Detecting Newest Block ...
XOHCL iBar;
bool has = false;
for (int i = barIndex; i < barIndex + loopback; i++)
{
//
// Initialize iBar ...
has = iBar.Init(
bar.symbol,
bar.period,
i //
);
if (!has)
{
//
iBar.Clean();
//
continue;
}
//
// Check to Find OB ...
has = barAnalyser.IsOrderBlock(
iBar,
ob,
false,
true //
);
if (has)
{
//
iBar.Clean();
//
break;
}
//
ob.Clean();
iBar.Clean();
}
//
// Ensure We Have a Block ...
result = ob.IsValid();
if (!result)
{
//
ob.Clean();
bar.Clean();
iBar.Clean();
swingBar.Clean();
breakerBar.Clean();
outSideBar.Clean();
dir = X_DIRECTION_NONE;
//
return result;
}
//
// Set Direction ...
dir = ob.dir;
int toIDX = ob.ToIndex();
int fromIDX = ob.FromIndex();
bool isBullish = IsBullish(dir);
bool isBearish = IsBearish(dir);
//
// Ensure a Swing Breaked in Block Formation ...
// for Bullish we have to Breake a Swing High ...
// for Bearish we have to Detect a Swing Low ...
// this Breaktion must appear after Block ...
ENUM_X_DIRECTION swingDir = X_DIRECTION_NONE;
for (int i = barIndex + loopback; i > barIndex; i--)
{
//
// Initialize iBar ...
has = iBar.Init(
bar.symbol,
bar.period,
i //
);
if (!has)
{
//
iBar.Clean();
swingBar.Clean();
swingDir = X_DIRECTION_NONE;
//
continue;
}
//
// Detecting Swing ...
has = barAnalyser.IsSwing(
iBar,
swingDir //
);
if (!has)
{
//
iBar.Clean();
swingBar.Clean();
swingDir = X_DIRECTION_NONE;
//
continue;
}
//
// Validate Founded Swing ...
swingBar = iBar;
//
bool isValidSwingLow =
isBearish &&
IsBullish(swingDir);
//
bool isValidSwingHigh =
isBullish &&
IsBearish(swingDir);
//
has =
isValidSwingLow ||
isValidSwingHigh;
if (!has)
{
//
iBar.Clean();
swingBar.Clean();
swingDir = X_DIRECTION_NONE;
//
continue;
}
//
// Validating Swing Place ...
//
bool isSwingLowHasValidPlace =
isBearish &&
swingBar.low < ob.lower;
//
bool isSwingHighHasValidPlace =
isBullish &&
swingBar.high > ob.upper;
//
has =
isSwingLowHasValidPlace ||
isSwingHighHasValidPlace;
if (has)
{
//
iBar.Clean();
//
break;
}
//
iBar.Clean();
swingBar.Clean();
swingDir = X_DIRECTION_NONE;
}
//
result =
swingBar.IsValid() &&
HasDirection(swingDir);
if (!result)
{
//
ob.Clean();
bar.Clean();
iBar.Clean();
swingBar.Clean();
breakerBar.Clean();
outSideBar.Clean();
dir = X_DIRECTION_NONE;
//
return result;
}
//
// now We have Proper Swing ...
// Validate Swing Breaktion ...
double breakPrice =
IsBullish(swingDir)
? swingBar.low
: swingBar.high;
ENUM_X_DIRECTION breakedDir =
IsBullish(swingDir)
? X_DIRECTION_BEARISH
: X_DIRECTION_BULLISH;
for (int i = swingBar.Index(); i > barIndex; i--)
{
//
// Initialize iBar ...
has = iBar.Init(
bar.symbol,
bar.period,
i //
);
if (!has)
{
//
iBar.Clean();
breakerBar.Clean();
//
continue;
}
//
// Check for Breakes ...
has = iBar.IsBreaked(
breakPrice,
breakedDir //
);
if (!has)
{
//
iBar.Clean();
breakerBar.Clean();
//
continue;
}
//
// Validate Swing Break must be happens
// after Block Formation ...
has = iBar.time > ob.to;
if (has)
{
//
breakerBar = iBar;
//
iBar.Clean();
//
break;
}
//
iBar.Clean();
breakerBar.Clean();
}
//
result = breakerBar.IsValid();
if (!result)
{
//
ob.Clean();
bar.Clean();
iBar.Clean();
swingBar.Clean();
breakerBar.Clean();
outSideBar.Clean();
dir = X_DIRECTION_NONE;
//
return result;
}
//
// now we have a Valid Bloc ...
// which Breakes a Valid Swing ...
//
// find at least on out side of Block Bar ...
for (int i = toIDX; i > barIndex; i--)
{
//
// Initialize iBar ...
has = iBar.Init(
bar.symbol,
bar.period,
i //
);
if (!has)
{
//
iBar.Clean();
outSideBar.Clean();
//
continue;
}
//
bool isBullishOutside =
isBullish &&
iBar.high > ob.upper;
//
bool isBearishOutside =
isBearish &&
iBar.low < ob.lower;
//
has =
isBullishOutside ||
isBearishOutside;
if (has)
{
//
outSideBar = iBar;
//
iBar.Clean();
//
break;
}
//
iBar.Clean();
outSideBar.Clean();
}
//
result = outSideBar.IsValid();
if (!result)
{
//
ob.Clean();
bar.Clean();
iBar.Clean();
swingBar.Clean();
breakerBar.Clean();
outSideBar.Clean();
dir = X_DIRECTION_NONE;
//
return result;
}
//
// we Are Looking for Bar inside Block ...
//
bool isBullishInside =
isBullish &&
bar.low < ob.upper &&
bar.low > ob.lower;
//
bool isBearishInside =
isBearish &&
bar.high > ob.lower &&
bar.high < ob.upper;
//
result = isBullishInside ||
isBearishInside;
if (!result)
{
//
ob.Clean();
bar.Clean();
iBar.Clean();
swingBar.Clean();
breakerBar.Clean();
outSideBar.Clean();
dir = X_DIRECTION_NONE;
//
return result;
}
//
// Since we Ensure have an Inside Block Bar here ...
// must to detect a Bar Pattern verification for Triggering ...
//
// Check Bar Pattern for Position ...
ENUM_X_DIRECTION patternDir;
//
// Hammer ...
bool isHammer = barAnalyser.IsHammer(
bar,
patternDir //
);
bool isBullishHammer =
isHammer &&
IsBullish(patternDir);
bool isBearishHammer =
isHammer &&
IsBearish(patternDir);
//
// Reject ...
bool isReject = barAnalyser.IsRejected(
bar,
patternDir,
false, // Force Bar type ...
true // Force Fibo Pressure ...
);
bool isBullishReject =
isReject &&
IsBullish(patternDir);
bool isBearishReject =
isReject &&
IsBearish(patternDir);
//
// Engulf ...
bool isEngulf = barAnalyser.IsEngulfed(
bar,
patternDir //
);
bool isBullishEngulf =
isEngulf &&
IsBullish(patternDir);
bool isBearishEngulf =
isEngulf &&
IsBearish(patternDir);
//
bool isBarBullishPowered =
isBullishHammer ||
isBullishReject ||
isBullishEngulf;
//
bool isBarBearishPowered =
isBearishHammer ||
isBearishReject ||
isBearishEngulf;
//
// Summarizing Result ...
//
bool isBullishTriggered =
isBullish &&
isBullishInside &&
isBarBullishPowered;
//
bool isBearishTriggered =
isBearish &&
isBearishInside &&
isBarBearishPowered;
//
result = isBullishTriggered ||
isBearishTriggered;
//
if (!result)
{
//
ob.Clean();
bar.Clean();
iBar.Clean();
swingBar.Clean();
breakerBar.Clean();
outSideBar.Clean();
dir = X_DIRECTION_NONE;
//
return result;
}
//
bar.Clean();
//
return result;
}
//
// Protected ...
protected:
+121 -1
View File
@@ -962,7 +962,7 @@ bool DetectDecisionZone(
//
// Custom Senarios ...
//
bool isCond1Bullish =
//
@@ -1627,6 +1627,126 @@ bool CanTriggerCond2(
return result;
}
//
// Detect Trigger Based On Decision Zone's
// Block Based Triggering ...
bool CanTriggerCond3(
XCXCAEAHelper *helper,
XBoxZone &box,
ENUM_X_DIRECTION &dir,
double &sl,
double &tp,
int barIndex = 0,
int loopback = 10 //
)
{
//
bool result = false;
//
// Normalize Args ...
sl = 0;
tp = 0;
dir = X_DIRECTION_NONE;
loopback = NormalizeInt(loopback, 5);
barIndex = NormalizeInt(barIndex, 0);
//
// Validate Decision Box ...
result = box.IsValid() &&
helper != NULL;
if (!result)
{
return result;
}
//
// Detect At Least one Outside Bar ...
// TODO: Complete this ...
//
// Add Support for a Breaked Swing as Liquidity ...
// for Improve Validations ...
// TODO: Complete this ...
//
// Detect Block Based Trigger ...
XBoxZone ob;
XOHCL swing;
XOHCL breaker;
XOHCL outSide;
ENUM_X_DIRECTION passedDir;
bool isPassed = helper.IsBlockBasedTriggerBar(
ob,
swing,
breaker,
outSide,
passedDir,
barIndex + 1, // Bar Index ...
30, // Loopback ...
3 // Swing Length ...
);
bool isBullishPassed =
isPassed &&
ob.IsBullish() &&
box.IsBullish() &&
ob.upper < box.upper &&
ob.lower > box.lower;
bool isBearishPassed =
isPassed &&
ob.IsBearish() &&
box.IsBearish() &&
ob.upper < box.upper &&
ob.lower > box.lower;
//
// Summarizing ...
//
bool canTriggerLong =
isBullishPassed;
//
bool canTriggerShort =
isBearishPassed;
//
result = canTriggerLong ||
canTriggerShort;
if (result)
{
//
dir = canTriggerLong
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
// Preparing TP and SL ...
//
sl = canTriggerLong
? ob.lower
: ob.upper;
//
// Since Here TP Must Calculated
// Using R2R we Ignore Target ...
tp = 0;
}
//
// Cleanup Resources ...
//
ob.Clean();
swing.Clean();
breaker.Clean();
outSide.Clean();
//
return result;
}
//
// Helper Functions ...
+119 -10
View File
@@ -591,6 +591,7 @@ class XCXCAEASignaller : XCBase
int ppIndex = pIndex + 1;
//
bool has = false;
int loopback = 10;
//
@@ -618,16 +619,87 @@ class XCXCAEASignaller : XCBase
double tp = 0;
ENUM_X_DIRECTION triggerDir = X_DIRECTION_NONE;
//
// Detect All Inside Directional FVGs ...
XBoxZone fvgs[];
int toIDX = conditions.decisionZone.ToIndex();
int fromIDX = conditions.decisionZone.FromIndex();
for (int i = fromIDX; i > toIDX; i--)
{
//
XOHCL iBar;
XBoxZone iFVG;
//
// Initialize iBar ...
has = iBar.Init(
conditions.symbol,
conditions.period,
i //
);
if (!has)
{
//
iFVG.Clean();
iBar.Clean();
//
continue;
}
//
// Check iBar has FVG ...
has = helper
.barAnalyser
.IsFVG(
iBar,
iFVG,
true //
);
if (!has)
{
//
iBar.Clean();
iFVG.Clean();
//
continue;
}
//
// Check FVG Direction and Placement ...
has =
iFVG.dir == conditions.decisionZone.dir &&
iFVG.upper < conditions.decisionZone.upper &&
iFVG.lower > conditions.decisionZone.lower;
if (has)
{
//
iFVG.to = cTime;
AddRef(
iFVG,
fvgs //
);
}
//
iBar.Clean();
iFVG.Clean();
}
bool hasFVGs = HasChild(fvgs);
int fvgsCount = ArraySize(fvgs);
//
// Checking Trigger Cond 0 ...
bool canTriggerCond0 = CanTriggerCond0(
helper,
conditions.decisionZone,
triggerDir,
sl,
tp,
barIndex //
);
bool canTriggerCond0 = false;
// CanTriggerCond0(
// helper,
// conditions.decisionZone,
// triggerDir,
// sl,
// tp,
// barIndex //
// );
//
// Checking Trigger Cond 1 ...
@@ -653,13 +725,25 @@ class XCXCAEASignaller : XCBase
// barIndex //
// );
//
// Checking Trigger Cond 3 ...
bool canTriggerCond3 = CanTriggerCond3(
helper,
conditions.decisionZone,
triggerDir,
sl,
tp,
barIndex //
);
//
// Update Signal Box To ...
conditions.decisionZone.to = cTime;
//
// Draw Decision Zone ...
XCBoxObject *iObj;
bool has = helper.poiDrawer.DrawBox(
has = helper.poiDrawer.DrawBox(
conditions.decisionZone,
iObj //
);
@@ -669,12 +753,37 @@ class XCXCAEASignaller : XCBase
}
ZeroMemory(iObj);
//
// Draw FVGs ...
if (hasFVGs)
{
//
for (int i = 0; i < fvgsCount; i++)
{
//
fvgs[i].to = cTime;
//
XCBoxObject *iObj;
has = helper.poiDrawer.DrawBox(
fvgs[i],
iObj //
);
if (has)
{
mObjects.Add(iObj);
}
ZeroMemory(iObj);
}
}
//
// Summarizing Result ...
result =
canTriggerCond0 ||
canTriggerCond1 ||
canTriggerCond2;
canTriggerCond2 ||
canTriggerCond3;
//
isBullish = result &&