2525 lines
58 KiB
Plaintext
2525 lines
58 KiB
Plaintext
// //
|
|
// // Now we Have to Detect Spike Breake Ruls ...
|
|
// // for Bullish: bar.low goes Below of pBar.low ...
|
|
// // for Bearish: bar.high goes Above of pBar.high ...
|
|
// for (int i = toIDX; i > pBarIndex; i--)
|
|
// {
|
|
// //
|
|
// // Initialize iBar ...
|
|
// result = iBar.Init(
|
|
// bar.symbol,
|
|
// bar.period,
|
|
// i //
|
|
// );
|
|
// result =
|
|
// result &&
|
|
// iBar.GetPreviousBar(iPBar);
|
|
// if (result)
|
|
// {
|
|
// //
|
|
// if (isBullish)
|
|
// {
|
|
// result = iBar.low < iPBar.low;
|
|
// }
|
|
// else if (isBearish)
|
|
// {
|
|
// result = iBar.high > iPBar.high;
|
|
// }
|
|
|
|
// //
|
|
// if (result)
|
|
// {
|
|
// break;
|
|
// }
|
|
// }
|
|
|
|
// //
|
|
// iBar.Clean();
|
|
// iPBar.Clean();
|
|
// }
|
|
// if (!result)
|
|
// {
|
|
// //
|
|
// ob.Clean();
|
|
// fvg.Clean();
|
|
// box.Clean();
|
|
// pBar.Clean();
|
|
// iBar.Clean();
|
|
// iPBar.Clean();
|
|
// swingBar.Clean();
|
|
// liquidity.Clean();
|
|
|
|
// //
|
|
// return result;
|
|
// }
|
|
|
|
// //
|
|
// // Update Box ...
|
|
// if (isBullish)
|
|
// {
|
|
// box.upper = MathMax(box.upper, iBar.GetDown());
|
|
// }
|
|
// else if (isBearish)
|
|
// {
|
|
// box.lower = MathMin(box.lower, iBar.GetUp());
|
|
// }
|
|
|
|
bool IsTrigger(
|
|
XOHCL &bar,
|
|
XBoxZone &box,
|
|
XBoxZone &ob,
|
|
XBoxZone &fvg,
|
|
XBoxZone &liquidity,
|
|
XOHCL &swingBar,
|
|
int loopback = 10,
|
|
int hlDistance = 300,
|
|
double maxAlowedRange = 0.0,
|
|
bool forceOBOppositBar = true,
|
|
bool forceFVGBarType = true,
|
|
bool forceSwingBar = true,
|
|
bool forceGapBarBreakout = true,
|
|
bool forceCheckBarsSequence = true,
|
|
bool lookingEntry = false,
|
|
bool forceLiquidity = true,
|
|
bool forceLiquidityUsed = true,
|
|
bool forceEntryBar = true,
|
|
bool forceEntryBarPower = true
|
|
//
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize Args ...
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
loopback = NormalizeInt(loopback, 5);
|
|
|
|
//
|
|
// Validate Args ...
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL pBar;
|
|
XOHCL iBar;
|
|
XOHCL iPBar;
|
|
int barIndex;
|
|
int pBarIndex;
|
|
ENUM_X_DIRECTION iDir;
|
|
|
|
//
|
|
result = bar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
barIndex = bar.Index();
|
|
pBarIndex = pBar.Index();
|
|
|
|
//
|
|
// Loopback to Find a Block ...
|
|
for (int i = pBarIndex; i < pBarIndex + loopback; i++)
|
|
{
|
|
//
|
|
// Inital IBar ...
|
|
result = iBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
i //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Detect Block ...
|
|
result = IsOB(
|
|
iBar,
|
|
ob,
|
|
forceFVGBarType,
|
|
forceOBOppositBar //
|
|
);
|
|
if (result)
|
|
{
|
|
//
|
|
// Validate Block Last Bars ...
|
|
if (forceOBOppositBar)
|
|
{
|
|
//
|
|
XOHCL fromBar;
|
|
XOHCL fromBarPrev;
|
|
result = ob.FromBar(fromBar);
|
|
result =
|
|
result &&
|
|
fromBar.GetPreviousBar(fromBarPrev);
|
|
result =
|
|
result &&
|
|
(ob.IsBullish()
|
|
? fromBarPrev.IsBearish()
|
|
: fromBarPrev.IsBullish());
|
|
if (result)
|
|
{
|
|
//
|
|
// Detect FVG ...
|
|
result = IsFVG(
|
|
iBar,
|
|
fvg,
|
|
forceFVGBarType //
|
|
);
|
|
if (result)
|
|
{
|
|
//
|
|
box.Clone(ob);
|
|
box.type = "XTRG";
|
|
box.from = fromBarPrev.time;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
fromBar.Clean();
|
|
fromBarPrev.Clean();
|
|
}
|
|
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
iBar.Clean();
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Filter Using Max Allowed Range ...
|
|
if (maxAlowedRange > 0)
|
|
{
|
|
//
|
|
result = box.GetRange() <= (maxAlowedRange * GetPoints(bar.symbol));
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate Gap Bar ...
|
|
if (forceGapBarBreakout)
|
|
{
|
|
//
|
|
// We Have to Check Gap Bar's Breakout ...
|
|
result = fvg.ToBar(iBar);
|
|
result =
|
|
result &&
|
|
iBar.GetPreviousBar(iPBar);
|
|
result =
|
|
result &&
|
|
(box.IsBullish()
|
|
? iPBar.close > ob.upper
|
|
: iPBar.close < ob.lower);
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
}
|
|
|
|
//
|
|
// Validate HH LL Distance ...
|
|
if (hlDistance > 0)
|
|
{
|
|
//
|
|
result = ob.FromBar(iBar);
|
|
if (result)
|
|
{
|
|
//
|
|
double ll = iBar.FindLowest(iBar.Index() + hlDistance, MODE_LOW);
|
|
double hh = iBar.FindHighest(iBar.Index() + hlDistance, MODE_HIGH);
|
|
|
|
//
|
|
result =
|
|
ll > 0 &&
|
|
hh > 0 &&
|
|
ob.upper < hh &&
|
|
ob.lower > ll;
|
|
}
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
int toIDX = box.ToIndex();
|
|
int fromIDX = box.FromIndex();
|
|
bool isBullish = box.IsBullish();
|
|
bool isBearish = box.IsBearish();
|
|
|
|
//
|
|
// We Have to Make sure Bars until Spikes Closed ...
|
|
// for Bullish: bars must Close Above box.upper ...
|
|
// for Bearish: bars must Close Below box.lower ...
|
|
for (int i = pBarIndex; i < toIDX; i++)
|
|
{
|
|
//
|
|
// Initialize iBar ...
|
|
result = iBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
i //
|
|
);
|
|
result =
|
|
result &&
|
|
(isBullish
|
|
? iBar.close > box.upper
|
|
: iBar.close < box.lower);
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
iBar.Clean();
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Detect Swing Bar ...
|
|
int swingBarIDX = -1;
|
|
int swingLoopback = fromIDX - pBarIndex;
|
|
if (isBullish)
|
|
{
|
|
//
|
|
// Looking for Swing Low ...
|
|
swingBarIDX = pBar.FindLowestIndex(swingLoopback, MODE_LOW);
|
|
}
|
|
else if (isBearish)
|
|
{
|
|
//
|
|
// Looking for Swing High ...
|
|
swingBarIDX = pBar.FindHighestIndex(swingLoopback, MODE_LOW);
|
|
}
|
|
result = IsValidIndex(swingBarIDX);
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Initialize Swing Bar ...
|
|
result = swingBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
swingBarIDX //
|
|
);
|
|
if (forceSwingBar)
|
|
{
|
|
//
|
|
result =
|
|
result &&
|
|
IsSimpleSwing(
|
|
swingBar,
|
|
iDir //
|
|
) &&
|
|
iDir == fvg.dir;
|
|
}
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Update Trigger Box ...
|
|
if (isBullish)
|
|
{
|
|
box.lower = MathMin(box.lower, swingBar.GetDown());
|
|
}
|
|
else if (isBearish)
|
|
{
|
|
box.upper = MathMin(box.upper, swingBar.GetUp());
|
|
}
|
|
|
|
//
|
|
// Validating Bar Sequence ...
|
|
if (forceCheckBarsSequence)
|
|
{
|
|
//
|
|
// Now we Have to Check Spike from Swing Bar Next till Current Bar ...
|
|
// To Validate Highs and Lows ...
|
|
for (int i = pBarIndex; i < pBarIndex + (swingBarIDX - pBarIndex) - 1; i++)
|
|
{
|
|
//
|
|
// Initialize iBar ...
|
|
result = iBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
i //
|
|
);
|
|
result =
|
|
result &&
|
|
iBar.GetPreviousBar(iPBar);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Since we Go Backward Bars from Current Bar ...
|
|
// for Bullish: each Bar Low Must over Prev Bar Low ...
|
|
// for Bearish: each Bar High Must Under Prev Bar High ...
|
|
if (isBullish)
|
|
{
|
|
//
|
|
result =
|
|
result &&
|
|
iBar.low > iPBar.low;
|
|
}
|
|
else if (isBearish)
|
|
{
|
|
//
|
|
result =
|
|
result &&
|
|
iBar.high < iPBar.high;
|
|
}
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
}
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = pBar.time;
|
|
|
|
//
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
}
|
|
|
|
//
|
|
toIDX = box.ToIndex();
|
|
fromIDX = box.FromIndex();
|
|
|
|
//
|
|
// Liquidity ...
|
|
if (forceLiquidity)
|
|
{
|
|
//
|
|
// Checking Swing Bar is Liquidity ...
|
|
result = IsRejected(
|
|
swingBar,
|
|
iDir,
|
|
true, // Force Bar Type ...
|
|
true // Foce Fibo Pressure ...
|
|
) &&
|
|
iDir == fvg.dir;
|
|
if (result)
|
|
{
|
|
//
|
|
// Filling Liquidity ...
|
|
liquidity.dir = iDir;
|
|
liquidity.to = box.to;
|
|
liquidity.type = "XLQ";
|
|
liquidity.from = swingBar.time;
|
|
liquidity.symbol = swingBar.symbol;
|
|
liquidity.period = swingBar.period;
|
|
liquidity.upper = isBullish
|
|
? swingBar.GetDown()
|
|
: swingBar.high;
|
|
liquidity.lower = isBullish
|
|
? swingBar.low
|
|
: swingBar.GetUp();
|
|
|
|
//
|
|
result = liquidity.IsValid();
|
|
}
|
|
result = liquidity.IsValid();
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Liquidity Usage ...
|
|
if (forceLiquidityUsed)
|
|
{
|
|
//
|
|
// now We have to Ensure Detected Liqudity is Used ...
|
|
toIDX = box.ToIndex();
|
|
fromIDX = liquidity.FromIndex();
|
|
for (int i = fromIDX - 1; i >= toIDX; i--)
|
|
{
|
|
//
|
|
// Initialize iBar ...
|
|
result = iBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
i //
|
|
);
|
|
result =
|
|
result &&
|
|
(isBullish
|
|
? iBar.low < liquidity.upper
|
|
: iBar.high > liquidity.lower);
|
|
if (result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Looking for Entry ...
|
|
if (lookingEntry)
|
|
{
|
|
//
|
|
// Entry Bar ...
|
|
if (forceEntryBar)
|
|
{
|
|
//
|
|
// Validate Bar is Not Opposit Powered Bar ...
|
|
|
|
//
|
|
// Momentum ...
|
|
bool isMomentum = IsMomentum(
|
|
bar,
|
|
iDir,
|
|
1 //
|
|
);
|
|
bool isBullishMomentum =
|
|
isMomentum &&
|
|
IsBullish(iDir);
|
|
bool isBearishMomentum =
|
|
isMomentum &&
|
|
IsBearish(iDir);
|
|
|
|
//
|
|
// Engulfed ...
|
|
bool isEngulfed = IsEngulfed(
|
|
bar,
|
|
iDir //
|
|
);
|
|
bool isBullishEngulfed =
|
|
isEngulfed &&
|
|
IsBullish(iDir);
|
|
bool isBearishEngulfed =
|
|
isEngulfed &&
|
|
IsBearish(iDir);
|
|
|
|
//
|
|
// Rejected ...
|
|
bool isRejected = IsRejected(
|
|
bar,
|
|
iDir,
|
|
false,
|
|
true //
|
|
);
|
|
bool isBullishRejected =
|
|
isRejected &&
|
|
IsBullish(iDir);
|
|
bool isBearishRejected =
|
|
isRejected &&
|
|
IsBearish(iDir);
|
|
|
|
//
|
|
bool isBullishPowered =
|
|
isBullishMomentum ||
|
|
isBullishEngulfed ||
|
|
isBullishRejected;
|
|
|
|
//
|
|
bool isBearishPowered =
|
|
isBearishMomentum ||
|
|
isBearishEngulfed ||
|
|
isBearishRejected;
|
|
|
|
//
|
|
// Make Sure Entry Bar is a Valid Bar ...
|
|
result =
|
|
isBullish
|
|
? !isBearishPowered && (!forceEntryBarPower
|
|
? true
|
|
: isBullishPowered)
|
|
: !isBullishPowered && (!forceEntryBarPower
|
|
? true
|
|
: isBearishPowered);
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
pBar.Clean();
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Entry Bar Sequences ...
|
|
if (forceCheckBarsSequence)
|
|
{
|
|
//
|
|
// if Sequences is Important ...
|
|
// we have to detect sequence Breaker Bar ...
|
|
result =
|
|
result &&
|
|
(isBullish
|
|
? bar.low < pBar.low
|
|
: bar.high > pBar.high);
|
|
}
|
|
|
|
//
|
|
// Validate Bar Close ...
|
|
result =
|
|
result &&
|
|
(isBullish
|
|
? bar.close > box.lower
|
|
: bar.close < box.upper);
|
|
}
|
|
|
|
//
|
|
if (!lookingEntry)
|
|
{
|
|
result = fvg.to == pBar.time;
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
|
|
//
|
|
iBar.Clean();
|
|
pBar.Clean();
|
|
iPBar.Clean();
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
//
|
|
ob.Clean();
|
|
fvg.Clean();
|
|
box.Clean();
|
|
swingBar.Clean();
|
|
swingBar.Clean();
|
|
liquidity.Clean();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////
|
|
|
|
|
|
//
|
|
void DetectTriggerZone(
|
|
int bar_index, // Selected Bar Index
|
|
const int prevCalculated,
|
|
const int ratesTotal,
|
|
const double &open[],
|
|
const double &high[],
|
|
const double &close[],
|
|
const double &low[],
|
|
const long &tickVolume[] //
|
|
)
|
|
{
|
|
//
|
|
// Check Prev Bar ...
|
|
|
|
//
|
|
int lastBarIndex = bar_index + 1;
|
|
int maxBarIndex = startCalculationForLastBars > 0
|
|
? startCalculationForLastBars
|
|
: ratesTotal;
|
|
bool isFirstBar =
|
|
bar_index == maxBarIndex;
|
|
|
|
//
|
|
// Prevent Calculation ...
|
|
if (maxBarIndex - bar_index < minZoneLength)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
int zIDX = 0;
|
|
int cIDX = 0;
|
|
int pIDX = 0;
|
|
int p2IDX = 0;
|
|
int p3IDX = 0;
|
|
int p4IDX = 0;
|
|
double ll = 0;
|
|
double hh = 0;
|
|
bool has = false;
|
|
ENUM_X_DIRECTION iDir;
|
|
|
|
//
|
|
// Retrieve Required Bars ...
|
|
|
|
//
|
|
XOHCL zBar; // Current Start Checking Bar (Usually Used for Triggering) ...
|
|
XOHCL cBar; // Current Finished Bar which Start Detecting Structures based on it ( End of Block and FVG Bar ) ...
|
|
XOHCL pBar; // Determines Block Gap Bar (all Filtering must applied and Check using this Bar and it's Next Bar) ...
|
|
XOHCL p2Bar; // Determines FVG's Start Bar in a Block ...
|
|
XOHCL p3Bar; // First Verification of Block ...
|
|
XOHCL p4Bar; // Seccond Verification of Block ...
|
|
|
|
//
|
|
has = zBar.Init(
|
|
_Symbol,
|
|
_Period,
|
|
bar_index //
|
|
);
|
|
has =
|
|
has &&
|
|
zBar.GetPreviousBar(cBar);
|
|
has =
|
|
has &&
|
|
cBar.GetPreviousBar(pBar);
|
|
has =
|
|
has &&
|
|
pBar.GetPreviousBar(p2Bar);
|
|
has =
|
|
has &&
|
|
p2Bar.GetPreviousBar(p3Bar);
|
|
has =
|
|
has &&
|
|
p3Bar.GetPreviousBar(p4Bar);
|
|
if (!has)
|
|
{
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
p4Bar.Clean();
|
|
|
|
//
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Define Zone Structure ...
|
|
XBoxZone zone;
|
|
|
|
//
|
|
// Detect Based Order Block using CBar ...
|
|
has = barAnalyser.IsOB(
|
|
cBar,
|
|
zone,
|
|
true, // Force FVG Bar Type ...
|
|
true // Force Block Two Bar Checking ...
|
|
);
|
|
|
|
//
|
|
// Ensure a Block is Detected ...
|
|
if (!has)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
p4Bar.Clean();
|
|
|
|
//
|
|
return;
|
|
}
|
|
|
|
//
|
|
zIDX = zBar.Index();
|
|
cIDX = cBar.Index();
|
|
pIDX = pBar.Index();
|
|
p2IDX = p2Bar.Index();
|
|
p3IDX = p3Bar.Index();
|
|
p4IDX = p4Bar.Index();
|
|
|
|
//
|
|
bool isBullish =
|
|
has &&
|
|
zone.IsBullish();
|
|
|
|
//
|
|
bool isBearish =
|
|
has &&
|
|
zone.IsBearish();
|
|
|
|
//
|
|
int toIDX = zone.ToIndex();
|
|
int fromIDX = zone.FromIndex();
|
|
|
|
//
|
|
// Validating p2Bar and p3Bar Direction ...
|
|
if (has)
|
|
{
|
|
//
|
|
iDir = Opposit(zone.dir);
|
|
|
|
//
|
|
has =
|
|
iDir == p3Bar.GetDirection() ||
|
|
iDir == p4Bar.GetDirection();
|
|
if (!has)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
p4Bar.Clean();
|
|
|
|
//
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Start Validating Block based on
|
|
// Detected One ...
|
|
|
|
//
|
|
// Validating Using Max Range ...
|
|
has = maxZoneRangeInPoints > 0;
|
|
if (has)
|
|
{
|
|
//
|
|
double range = zone.GetRange();
|
|
has = range <= maxZoneRangeInPoints * mPoints;
|
|
if (!has)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
p4Bar.Clean();
|
|
|
|
//
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate Gap Endup with PinBar ...
|
|
has = forceHasPinBarEntry;
|
|
if (has)
|
|
{
|
|
//
|
|
bool isBullishRejected =
|
|
isBullish &&
|
|
cBar.IsBullish() &&
|
|
cBar.GetLowShadow() > cBar.GetHighShadow();
|
|
|
|
//
|
|
bool isBearishRejected =
|
|
isBearish &&
|
|
cBar.IsBearish() &&
|
|
cBar.GetLowShadow() < cBar.GetHighShadow();
|
|
|
|
//
|
|
has = isBullishRejected ||
|
|
isBearishRejected;
|
|
if (!has)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
p4Bar.Clean();
|
|
|
|
//
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validating Gap Bar must a Momentum Bar and
|
|
// Breakes out Zone's Directional Edge ...
|
|
// for Bullish: Upper
|
|
// for Bearish: Lower
|
|
has = forceGapBarsBreakout;
|
|
if (has)
|
|
{
|
|
//
|
|
// Gap Bar is PBar ...
|
|
|
|
//
|
|
// Check Gap Bar is Momentum Bar ...
|
|
has = barAnalyser.IsMomentum(
|
|
pBar,
|
|
iDir //
|
|
);
|
|
bool isBullishMomentum =
|
|
has &&
|
|
IsBullish(iDir);
|
|
bool isBearishMomentum =
|
|
has &&
|
|
IsBearish(iDir);
|
|
|
|
//
|
|
// Check Gap Bar's Breakout ...
|
|
|
|
//
|
|
bool isBullishBreakedout =
|
|
isBullish &&
|
|
pBar.IsBullish() &&
|
|
isBullishMomentum &&
|
|
pBar.GetUp() > zone.upper &&
|
|
pBar.GetDown() < zone.upper;
|
|
|
|
//
|
|
bool isBearishBreakedout =
|
|
isBearish &&
|
|
pBar.IsBearish() &&
|
|
isBearishMomentum &&
|
|
pBar.GetUp() > zone.lower &&
|
|
pBar.GetDown() < zone.lower;
|
|
|
|
//
|
|
has = isBullishBreakedout ||
|
|
isBearishBreakedout;
|
|
if (!has)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
p4Bar.Clean();
|
|
|
|
//
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate Zone Has Propper Swing ...
|
|
// for Bullish: p2Bar or p3Bar must be a Swing Low ...
|
|
// for Bearish: p2Bar or p3Bar must be a Swing High ...
|
|
has = forceHasSwing;
|
|
if (has)
|
|
{
|
|
//
|
|
// p2Bar ...
|
|
bool isP2BarSwing =
|
|
barAnalyser
|
|
.IsSimpleSwing(
|
|
p2Bar,
|
|
iDir //
|
|
);
|
|
bool isP2BarSwingLow =
|
|
isP2BarSwing &&
|
|
IsBullish(iDir);
|
|
bool isP2BarSwingHigh =
|
|
isP2BarSwing &&
|
|
IsBearish(iDir);
|
|
|
|
//
|
|
// p3Bar ...
|
|
bool isP3BarSwing =
|
|
barAnalyser
|
|
.IsSimpleSwing(
|
|
p3Bar,
|
|
iDir //
|
|
);
|
|
bool isP3BarSwingLow =
|
|
isP3BarSwing &&
|
|
IsBullish(iDir);
|
|
bool isP3BarSwingHigh =
|
|
isP3BarSwing &&
|
|
IsBearish(iDir);
|
|
|
|
//
|
|
bool hasSwingLow =
|
|
isBullish &&
|
|
(isP2BarSwingLow ||
|
|
isP3BarSwingLow);
|
|
|
|
//
|
|
bool hasSwingHigh =
|
|
isBearish &&
|
|
(isP2BarSwingHigh ||
|
|
isP3BarSwingHigh);
|
|
|
|
//
|
|
has =
|
|
hasSwingLow ||
|
|
hasSwingHigh;
|
|
if (!has)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
p4Bar.Clean();
|
|
|
|
//
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validating Using Swing Length ...
|
|
has = minZoneLength > 0;
|
|
if (has)
|
|
{
|
|
//
|
|
XOHCL fromBar;
|
|
has = zone.FromBar(fromBar);
|
|
if (has)
|
|
{
|
|
//
|
|
// Retrieve HH and LL ...
|
|
ll = fromBar.FindLowest(minZoneLength, MODE_LOW);
|
|
hh = fromBar.FindHighest(minZoneLength, MODE_HIGH);
|
|
|
|
//
|
|
// Validate Using HH and LL ...
|
|
|
|
//
|
|
bool isBullishValid =
|
|
isBullish &&
|
|
ll >= zone.lower;
|
|
|
|
//
|
|
bool isBearishValid =
|
|
isBearish &&
|
|
hh <= zone.upper;
|
|
|
|
//
|
|
has = isBullishValid ||
|
|
isBearishValid;
|
|
if (!has)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
p4Bar.Clean();
|
|
|
|
//
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Update Zone's From Time ...
|
|
zone.from = GetBarTime(
|
|
zone.symbol,
|
|
zone.period,
|
|
fromBar.Index() + minZoneLength //
|
|
);
|
|
}
|
|
|
|
//
|
|
fromBar.Clean();
|
|
}
|
|
|
|
//
|
|
// Validate Max Allowed Entry Distance ...
|
|
has = maxAllowedEntryDistance > 0;
|
|
if (has)
|
|
{
|
|
//
|
|
double base =
|
|
isBullish
|
|
? zone.upper
|
|
: zone.lower;
|
|
double entryDistance = MathAbs(zBar.open - base);
|
|
has = entryDistance <= maxAllowedEntryDistance * mPoints;
|
|
if (!has)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
p4Bar.Clean();
|
|
|
|
//
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Here we Ensure which have a Valid Zone using Different Applied Validations ...
|
|
// from now we are Going to Filtered Validate Zones ...
|
|
|
|
//
|
|
// Check Exists Filters or not ...
|
|
has = filterBasedOnSar ||
|
|
filterBasedOnRSI ||
|
|
filterBasedOnADX ||
|
|
filterBasedOnTrend;
|
|
if (has)
|
|
{
|
|
//
|
|
// Do Apply Several Exists Filters ...
|
|
|
|
//
|
|
// SAR Filter ...
|
|
if (filterBasedOnSar)
|
|
{
|
|
//
|
|
// Reading Conditions Values ...
|
|
|
|
//
|
|
double zSar = sarBuffer[zIDX];
|
|
double cSar = sarBuffer[cIDX];
|
|
double pSar = sarBuffer[pIDX];
|
|
double p2Sar = sarBuffer[p2IDX];
|
|
double p3Sar = sarBuffer[p3IDX];
|
|
double p4Sar = sarBuffer[p4IDX];
|
|
|
|
//
|
|
// Create Required Conditions ...
|
|
|
|
//
|
|
bool isZSarBullish = zSar < zBar.low;
|
|
bool isZSarBearish = zSar > zBar.high;
|
|
|
|
//
|
|
bool isCSarBullish = cSar < cBar.low;
|
|
bool isCSarBearish = cSar > cBar.high;
|
|
|
|
//
|
|
bool isPSarBullish = pSar < pBar.low;
|
|
bool isPSarBearish = pSar > pBar.high;
|
|
|
|
//
|
|
bool isP2SarBullish = p2Sar < p2Bar.low;
|
|
bool isP2SarBearish = p2Sar > p2Bar.high;
|
|
|
|
//
|
|
bool isCSarSwitchedToBullish =
|
|
isZSarBullish &&
|
|
isCSarBullish &&
|
|
!isPSarBullish &&
|
|
cBar.IsBullish() &&
|
|
cBar.GetUp() > pSar;
|
|
|
|
//
|
|
bool isCSarSwitchedToBearish =
|
|
isZSarBearish &&
|
|
isCSarBearish &&
|
|
!isPSarBearish &&
|
|
cBar.IsBearish() &&
|
|
cBar.GetDown() < pSar;
|
|
|
|
//
|
|
bool isPSarSwitchedToBullish =
|
|
isZSarBullish &&
|
|
isCSarBullish &&
|
|
isPSarBullish &&
|
|
!isP2SarBullish &&
|
|
pBar.IsBullish() &&
|
|
pBar.GetUp() > p2Sar;
|
|
|
|
//
|
|
bool isPSarSwitchedToBearish =
|
|
isZSarBearish &&
|
|
isCSarBearish &&
|
|
isPSarBearish &&
|
|
!isP2SarBearish &&
|
|
pBar.IsBearish() &&
|
|
pBar.GetDown() < p2Sar;
|
|
|
|
//
|
|
// Summarize Filtering ...
|
|
|
|
//
|
|
bool isBullishFiltered =
|
|
isBullish &&
|
|
(isCSarSwitchedToBullish ||
|
|
isPSarSwitchedToBullish);
|
|
|
|
//
|
|
bool isBearishFiltered =
|
|
isBearish &&
|
|
(isCSarSwitchedToBearish ||
|
|
isPSarSwitchedToBearish);
|
|
|
|
//
|
|
has =
|
|
isBullishFiltered ||
|
|
isBearishFiltered;
|
|
if (!has)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
p4Bar.Clean();
|
|
|
|
//
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// RSI Filter ...
|
|
if (filterBasedOnRSI)
|
|
{
|
|
//
|
|
// Reading Conditions Values ...
|
|
|
|
//
|
|
double rsiTrend = (rsiOBLevel + rsiOSLevel) / 2;
|
|
|
|
//
|
|
double zRSI = rsiBuffer[zIDX];
|
|
double cRSI = rsiBuffer[cIDX];
|
|
double pRSI = rsiBuffer[pIDX];
|
|
double p2RSI = rsiBuffer[p2IDX];
|
|
double p3RSI = rsiBuffer[p3IDX];
|
|
double p4RSI = rsiBuffer[p4IDX];
|
|
|
|
//
|
|
// Create Required Conditions ...
|
|
|
|
//
|
|
bool isZRSIBullish = zRSI > rsiTrend;
|
|
bool isZRSIBearish = zRSI < rsiTrend;
|
|
|
|
//
|
|
bool isCRSIBullish = cRSI > rsiTrend;
|
|
bool isCRSIBearish = cRSI < rsiTrend;
|
|
|
|
//
|
|
bool isPRSIBullish = pRSI > rsiTrend;
|
|
bool isPRSIBearish = pRSI < rsiTrend;
|
|
|
|
//
|
|
bool isP2RSIBullish = p2RSI > rsiTrend;
|
|
bool isP2RSIBearish = p2RSI < rsiTrend;
|
|
|
|
//
|
|
bool isP3RSIBullish = p3RSI > rsiTrend;
|
|
bool isP3RSIBearish = p3RSI < rsiTrend;
|
|
|
|
//
|
|
// Trending Conditions ...
|
|
|
|
//
|
|
bool isCRSISwitchedToBullish =
|
|
isZRSIBullish &&
|
|
isCRSIBullish &&
|
|
!isPRSIBullish;
|
|
|
|
//
|
|
bool isCRSISwitchedToBearish =
|
|
isZRSIBearish &&
|
|
isCRSIBearish &&
|
|
!isPRSIBearish;
|
|
|
|
//
|
|
bool isPRSISwitchedToBullish =
|
|
isZRSIBullish &&
|
|
isCRSIBullish &&
|
|
isPRSIBullish &&
|
|
!isP2RSIBullish;
|
|
|
|
//
|
|
bool isPRSISwitchedToBearish =
|
|
isZRSIBearish &&
|
|
isCRSIBearish &&
|
|
isPRSIBearish &&
|
|
!isP2RSIBearish;
|
|
|
|
//
|
|
bool isP2RSISwitchedToBullish =
|
|
isZRSIBullish &&
|
|
isCRSIBullish &&
|
|
isPRSIBullish &&
|
|
isP2RSIBullish &&
|
|
!isP3RSIBullish;
|
|
|
|
//
|
|
bool isP2RSISwitchedToBearish =
|
|
isZRSIBearish &&
|
|
isCRSIBearish &&
|
|
isPRSIBearish &&
|
|
isP2RSIBearish &&
|
|
!isP3RSIBearish;
|
|
|
|
//
|
|
// Crosses Conditions ...
|
|
|
|
//
|
|
bool isCBarCrossedOverOS =
|
|
zRSI > rsiOSLevel &&
|
|
cRSI > rsiOSLevel &&
|
|
pRSI <= rsiOSLevel;
|
|
|
|
//
|
|
bool isCBarCrossedUnderOB =
|
|
zRSI < rsiOBLevel &&
|
|
cRSI < rsiOBLevel &&
|
|
pRSI >= rsiOBLevel;
|
|
|
|
//
|
|
bool isPBarCrossedOverOS =
|
|
zRSI > rsiOSLevel &&
|
|
cRSI > rsiOSLevel &&
|
|
pRSI > rsiOSLevel &&
|
|
p2RSI <= rsiOSLevel;
|
|
|
|
//
|
|
bool isPBarCrossedUnderOB =
|
|
zRSI < rsiOBLevel &&
|
|
cRSI < rsiOBLevel &&
|
|
pRSI < rsiOBLevel &&
|
|
p2RSI >= rsiOBLevel;
|
|
|
|
//
|
|
// V Pattern Conditions ...
|
|
|
|
//
|
|
bool isCRSIHasVBullishPattern =
|
|
zRSI >= cRSI &&
|
|
cRSI > pRSI &&
|
|
p2RSI > pRSI &&
|
|
cRSI >= p2RSI;
|
|
|
|
//
|
|
bool isCRSIHasVBearishPattern =
|
|
zRSI <= cRSI &&
|
|
cRSI < pRSI &&
|
|
p2RSI < pRSI &&
|
|
cRSI <= p2RSI;
|
|
|
|
//
|
|
// Continuation Conditions ...
|
|
|
|
//
|
|
bool isRSIUp =
|
|
zRSI >= cRSI &&
|
|
(cRSI >= pRSI ||
|
|
pRSI >= p2RSI ||
|
|
p2RSI >= p3RSI);
|
|
|
|
//
|
|
bool isRSIDown =
|
|
zRSI <= cRSI &&
|
|
(cRSI <= pRSI ||
|
|
pRSI <= p2RSI ||
|
|
p2RSI <= p3RSI);
|
|
|
|
//
|
|
// Summarize Filtering ...
|
|
|
|
//
|
|
bool isBullishFiltered =
|
|
isBullish &&
|
|
(
|
|
//
|
|
// Grows ...
|
|
isRSIUp
|
|
//
|
|
||
|
|
//
|
|
// Crosses ...
|
|
(isCBarCrossedOverOS ||
|
|
isPBarCrossedOverOS)
|
|
//
|
|
||
|
|
//
|
|
// V Pattern ...
|
|
isCRSIHasVBullishPattern
|
|
//
|
|
||
|
|
//
|
|
// Trending ...
|
|
(isCRSISwitchedToBullish ||
|
|
isPRSISwitchedToBullish ||
|
|
isP2RSISwitchedToBullish)
|
|
//
|
|
);
|
|
|
|
//
|
|
bool isBearishFiltered =
|
|
isBearish &&
|
|
(
|
|
//
|
|
// Grows ...
|
|
isRSIDown
|
|
//
|
|
||
|
|
//
|
|
// Crosses ...
|
|
(isCBarCrossedUnderOB ||
|
|
isPBarCrossedUnderOB)
|
|
//
|
|
||
|
|
//
|
|
// V Pattern ...
|
|
isCRSIHasVBearishPattern
|
|
//
|
|
||
|
|
//
|
|
// Trending ...
|
|
(isCRSISwitchedToBearish ||
|
|
isPRSISwitchedToBearish ||
|
|
isP2RSISwitchedToBearish)
|
|
//
|
|
);
|
|
|
|
//
|
|
has =
|
|
isBullishFiltered ||
|
|
isBearishFiltered;
|
|
if (!has)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
p4Bar.Clean();
|
|
|
|
//
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// ADX Filter ...
|
|
if (filterBasedOnADX)
|
|
{
|
|
//
|
|
// Reading Conditions Values ...
|
|
|
|
//
|
|
// ADX ...
|
|
double zADX = adxBuffer[zIDX];
|
|
double cADX = adxBuffer[cIDX];
|
|
double pADX = adxBuffer[pIDX];
|
|
double p2ADX = adxBuffer[p2IDX];
|
|
double p3ADX = adxBuffer[p3IDX];
|
|
double p4ADX = adxBuffer[p4IDX];
|
|
|
|
//
|
|
// ADX +DI ...
|
|
double zADXP = adxpBuffer[zIDX];
|
|
double cADXP = adxpBuffer[cIDX];
|
|
double pADXP = adxpBuffer[pIDX];
|
|
double p2ADXP = adxpBuffer[p2IDX];
|
|
double p3ADXP = adxpBuffer[p3IDX];
|
|
double p4ADXP = adxpBuffer[p4IDX];
|
|
|
|
//
|
|
// ADX -DI ...
|
|
double zADXN = adxnBuffer[zIDX];
|
|
double cADXN = adxnBuffer[cIDX];
|
|
double pADXN = adxnBuffer[pIDX];
|
|
double p2ADXN = adxnBuffer[p2IDX];
|
|
double p3ADXN = adxnBuffer[p3IDX];
|
|
double p4ADXN = adxnBuffer[p4IDX];
|
|
|
|
//
|
|
// Create Required Conditions ...
|
|
|
|
//
|
|
// Grows ...
|
|
|
|
//
|
|
bool isADXUp =
|
|
zADX >= cADX &&
|
|
(cADX >= pADX ||
|
|
pADX >= p2ADX);
|
|
|
|
//
|
|
bool isADXDown =
|
|
zADX <= cADX &&
|
|
(cADX <= pADX ||
|
|
pADX <= p2ADX);
|
|
|
|
//
|
|
// Trending ...
|
|
|
|
//
|
|
bool isZADXBullish = zADX > adxThreshold;
|
|
bool isZADXBearish = zADX < adxThreshold;
|
|
|
|
//
|
|
bool isCADXBullish = cADX > adxThreshold;
|
|
bool isCADXBearish = cADX < adxThreshold;
|
|
|
|
//
|
|
bool isPADXBullish = pADX > adxThreshold;
|
|
bool isPADXBearish = pADX < adxThreshold;
|
|
|
|
//
|
|
bool isP2ADXBullish = p2ADX > adxThreshold;
|
|
bool isP2ADXBearish = p2ADX < adxThreshold;
|
|
|
|
//
|
|
bool isP3ADXBullish = p3ADX > adxThreshold;
|
|
bool isP3ADXBearish = p3ADX < adxThreshold;
|
|
|
|
//
|
|
bool isP4ADXBullish = p4ADX > adxThreshold;
|
|
bool isP4ADXBearish = p4ADX < adxThreshold;
|
|
|
|
//
|
|
bool isCADXSwitchedToBullish =
|
|
isZADXBullish &&
|
|
isCADXBullish &&
|
|
!isPADXBullish;
|
|
|
|
//
|
|
bool isCADXSwitchedToBearish =
|
|
isZADXBearish &&
|
|
isCADXBearish &&
|
|
!isPADXBearish;
|
|
|
|
//
|
|
bool isPADXSwitchedToBullish =
|
|
isZADXBullish &&
|
|
isCADXBullish &&
|
|
isPADXBullish &&
|
|
!isP2ADXBullish;
|
|
|
|
//
|
|
bool isPADXSwitchedToBearish =
|
|
isZADXBearish &&
|
|
isCADXBearish &&
|
|
isPADXBearish &&
|
|
!isP2ADXBearish;
|
|
|
|
//
|
|
// Powering ...
|
|
|
|
//
|
|
bool isZADXHasBullishPower = zADXP > zADXN;
|
|
bool isZADXHasBearishPower = zADXN > zADXP;
|
|
|
|
//
|
|
bool isCADXHasBullishPower = cADXP > cADXN;
|
|
bool isCADXHasBearishPower = cADXN > cADXP;
|
|
|
|
//
|
|
bool isPADXHasBullishPower = pADXP > pADXN;
|
|
bool isPADXHasBearishPower = pADXN > pADXP;
|
|
|
|
//
|
|
bool isP2ADXHasBullishPower = p2ADXP > p2ADXN;
|
|
bool isP2ADXHasBearishPower = p2ADXN > p2ADXP;
|
|
|
|
//
|
|
bool isP3ADXHasBullishPower = p3ADXP > p3ADXN;
|
|
bool isP3ADXHasBearishPower = p3ADXN > p3ADXP;
|
|
|
|
//
|
|
bool isP4ADXHasBullishPower = p4ADXP > p4ADXN;
|
|
bool isP4ADXHasBearishPower = p4ADXN > p4ADXP;
|
|
|
|
//
|
|
bool isCADXSwitchedToBullishPower =
|
|
isZADXHasBullishPower &&
|
|
isCADXHasBullishPower &&
|
|
!isPADXHasBullishPower;
|
|
|
|
//
|
|
bool isCADXSwitchedToBearishPower =
|
|
isZADXHasBearishPower &&
|
|
isCADXHasBearishPower &&
|
|
!isPADXHasBearishPower;
|
|
|
|
//
|
|
bool isPADXSwitchedToBullishPower =
|
|
isZADXHasBullishPower &&
|
|
isCADXHasBullishPower &&
|
|
isPADXHasBullishPower &&
|
|
!isP2ADXHasBullishPower;
|
|
|
|
//
|
|
bool isPADXSwitchedToBearishPower =
|
|
isZADXHasBearishPower &&
|
|
isCADXHasBearishPower &&
|
|
isPADXHasBearishPower &&
|
|
!isP2ADXHasBearishPower;
|
|
|
|
//
|
|
// Summarize Filtering ...
|
|
|
|
//
|
|
bool isBullishFiltered =
|
|
isBullish &&
|
|
(
|
|
//
|
|
// Grows ...
|
|
isADXUp
|
|
//
|
|
||
|
|
//
|
|
// Trending ...
|
|
(isCADXSwitchedToBullish ||
|
|
isPADXSwitchedToBullish)
|
|
//
|
|
||
|
|
//
|
|
// Powering ...
|
|
(isCADXSwitchedToBullishPower ||
|
|
isPADXSwitchedToBullishPower)
|
|
//
|
|
);
|
|
|
|
//
|
|
bool isBearishFiltered =
|
|
isBearish &&
|
|
(
|
|
//
|
|
// Grows ...
|
|
isADXDown
|
|
//
|
|
||
|
|
//
|
|
// Trending ...
|
|
(isCADXSwitchedToBearish ||
|
|
isPADXSwitchedToBearish)
|
|
//
|
|
||
|
|
//
|
|
// Powering ...
|
|
(isCADXSwitchedToBearishPower ||
|
|
isPADXSwitchedToBearishPower)
|
|
//
|
|
);
|
|
|
|
//
|
|
has =
|
|
isBullishFiltered ||
|
|
isBearishFiltered;
|
|
if (!has)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
p4Bar.Clean();
|
|
|
|
//
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// TREND Filter ...
|
|
if (filterBasedOnTrend)
|
|
{
|
|
//
|
|
// Reading Conditions Values ...
|
|
|
|
//
|
|
double zTrend = trendBuffer[zIDX];
|
|
double cTrend = trendBuffer[cIDX];
|
|
double pTrend = trendBuffer[pIDX];
|
|
double p2Trend = trendBuffer[p2IDX];
|
|
double p3Trend = trendBuffer[p3IDX];
|
|
double p4Trend = trendBuffer[p4IDX];
|
|
|
|
//
|
|
double trends[] = {
|
|
zTrend,
|
|
cTrend,
|
|
pTrend,
|
|
p2Trend,
|
|
p3Trend,
|
|
p4Trend //
|
|
};
|
|
double trendsMin = GetMin(trends);
|
|
double trendsMax = GetMax(trends);
|
|
double trendsAVG = GetAverage(trends);
|
|
|
|
//
|
|
double zTrendState = trendStateBuffer[zIDX];
|
|
double cTrendState = trendStateBuffer[cIDX];
|
|
double pTrendState = trendStateBuffer[pIDX];
|
|
double p2TrendState = trendStateBuffer[p2IDX];
|
|
double p3TrendState = trendStateBuffer[p3IDX];
|
|
double p4TrendState = trendStateBuffer[p4IDX];
|
|
|
|
//
|
|
// Create Required Conditions ...
|
|
|
|
//
|
|
// Grows ...
|
|
|
|
//
|
|
bool isTrendUp =
|
|
zTrend >= cTrend &&
|
|
cTrend >= trendsAVG &&
|
|
cTrend > trendsMin;
|
|
|
|
//
|
|
bool isTrendDown =
|
|
zTrend <= cTrend &&
|
|
cTrend <= trendsAVG &&
|
|
cTrend < trendsMax;
|
|
|
|
//
|
|
// Stating ...
|
|
|
|
//
|
|
bool isCTrendBullish =
|
|
zTrendState > 0 &&
|
|
cTrendState > 0;
|
|
|
|
//
|
|
bool isCTrendBearish =
|
|
zTrendState < 0 &&
|
|
cTrendState < 0;
|
|
|
|
//
|
|
bool isPTrendBullish =
|
|
zTrendState > 0 &&
|
|
cTrendState > 0 &&
|
|
pTrendState > 0;
|
|
|
|
//
|
|
bool isPTrendBearish =
|
|
zTrendState < 0 &&
|
|
cTrendState < 0 &&
|
|
pTrendState < 0;
|
|
|
|
//
|
|
bool isP2TrendBullish =
|
|
zTrendState > 0 &&
|
|
cTrendState > 0 &&
|
|
pTrendState > 0 &&
|
|
p2TrendState > 0;
|
|
|
|
//
|
|
bool isP2TrendBearish =
|
|
zTrendState < 0 &&
|
|
cTrendState < 0 &&
|
|
pTrendState < 0 &&
|
|
p2TrendState < 0;
|
|
|
|
//
|
|
bool isCTrendSwitchedToBullish =
|
|
isCTrendBullish &&
|
|
!isPTrendBullish;
|
|
|
|
//
|
|
bool isCTrendSwitchedToBearish =
|
|
isCTrendBearish &&
|
|
!isPTrendBearish;
|
|
|
|
//
|
|
bool isPTrendSwitchedToBullish =
|
|
isCTrendBullish &&
|
|
isPTrendBullish &&
|
|
!isP2TrendBullish;
|
|
|
|
//
|
|
bool isPTrendSwitchedToBearish =
|
|
isCTrendBearish &&
|
|
isPTrendBearish &&
|
|
!isP2TrendBearish;
|
|
|
|
//
|
|
// Summarize Filtering ...
|
|
|
|
//
|
|
bool isBullishFiltered =
|
|
isBullish &&
|
|
(
|
|
//
|
|
// Grows ...
|
|
isTrendUp
|
|
//
|
|
||
|
|
//
|
|
// Trend Stating ...
|
|
(isCTrendBullish &&
|
|
isPTrendBullish)
|
|
//
|
|
||
|
|
//
|
|
// Switching ...
|
|
(isCTrendSwitchedToBullish ||
|
|
isPTrendSwitchedToBullish)
|
|
//
|
|
);
|
|
|
|
//
|
|
bool isBearishFiltered =
|
|
isBearish &&
|
|
(
|
|
//
|
|
// Grows ...
|
|
isTrendDown
|
|
//
|
|
||
|
|
//
|
|
// Trend Stating ...
|
|
(isCTrendBearish &&
|
|
isPTrendBearish)
|
|
//
|
|
||
|
|
//
|
|
// Switching ...
|
|
(isCTrendSwitchedToBearish ||
|
|
isPTrendSwitchedToBearish)
|
|
//
|
|
);
|
|
|
|
//
|
|
has =
|
|
isBullishFiltered ||
|
|
isBearishFiltered;
|
|
if (!has)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
p4Bar.Clean();
|
|
|
|
//
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// SCORE Filter ...
|
|
|
|
//
|
|
// VOLUME Filter ...
|
|
}
|
|
|
|
//
|
|
// Detect Left Side of Box ...
|
|
XOHCL zoneLeftBar;
|
|
int idx = fromIDX + 1;
|
|
bool isBaseValid = true;
|
|
while (isBaseValid)
|
|
{
|
|
//
|
|
// Retrieve iteration Bar ...
|
|
has = zoneLeftBar.Init(
|
|
_Symbol,
|
|
_Period,
|
|
idx //
|
|
);
|
|
if (!has)
|
|
{
|
|
//
|
|
zoneLeftBar.Clean();
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Check Bar's Validation ...
|
|
|
|
//
|
|
bool isBullishPassed =
|
|
isBullish &&
|
|
zoneLeftBar.low >= zone.lower;
|
|
|
|
//
|
|
bool isBearishPassed =
|
|
isBearish &&
|
|
zoneLeftBar.high <= zone.upper;
|
|
|
|
//
|
|
// Summarize Conditions ...
|
|
has =
|
|
isBullishPassed ||
|
|
isBearishPassed;
|
|
if (!has)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
idx++;
|
|
}
|
|
|
|
//
|
|
// Ray to Left Side Zone, if Provided ...
|
|
if (rayLeft)
|
|
{
|
|
//
|
|
// Update Value ...
|
|
fromIDX = zone.FromIndex();
|
|
|
|
//
|
|
// Check Last Iteration Bar is Valid Bar ...
|
|
// then Update Zone from Time ...
|
|
has = zoneLeftBar.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
zone.from = zoneLeftBar.time;
|
|
fromIDX = zone.FromIndex();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Draw Detected Zone ...
|
|
if (drawZones)
|
|
{
|
|
//
|
|
XCBoxObject *iZoneObj;
|
|
has = drawer.DrawBox(
|
|
zone,
|
|
iZoneObj //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyStyle(iZoneObj, zone.dir);
|
|
|
|
//
|
|
mObjects.Add(iZoneObj);
|
|
|
|
//
|
|
// TODO: Enable This for Debugging ...
|
|
// string message = ToString(zone.dir) + " Zone Detected (" + cBar.time + ") ...";
|
|
// Print(message);
|
|
}
|
|
ZeroMemory(iZoneObj);
|
|
}
|
|
|
|
//
|
|
// Draw RR Tool ...
|
|
if (drawRRofZones)
|
|
{
|
|
//
|
|
double rr[]{
|
|
1,
|
|
1.5,
|
|
2,
|
|
3,
|
|
4,
|
|
5,
|
|
6,
|
|
7,
|
|
8,
|
|
9,
|
|
10 //
|
|
};
|
|
XCRRObject *iRRObj;
|
|
iRRObj = new XCRRObject();
|
|
has = iRRObj.CreateBoxRR(
|
|
drawer.ChartIdentification(),
|
|
drawer.SubWindowIdentification(),
|
|
zone,
|
|
rr,
|
|
rrZoneLength //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
int iWidth = 2;
|
|
ENUM_LINE_STYLE iStyle = STYLE_SOLID;
|
|
|
|
//
|
|
iRRObj.TPWidth(iWidth);
|
|
iRRObj.SLWidth(iWidth);
|
|
iRRObj.EntryWidth(iWidth);
|
|
iRRObj.TargetWidth(iWidth);
|
|
|
|
//
|
|
iRRObj.TPStyle(iStyle);
|
|
iRRObj.SLStyle(iStyle);
|
|
iRRObj.EntryStyle(iStyle);
|
|
iRRObj.TargetStyle(iStyle);
|
|
|
|
//
|
|
iRRObj.TPColor(clrLime);
|
|
iRRObj.SLColor(clrRed);
|
|
iRRObj.EntryColor(clrYellow);
|
|
iRRObj.TargetColor(clrLightBlue);
|
|
|
|
//
|
|
mObjects.Add(iRRObj);
|
|
}
|
|
ZeroMemory(iRRObj);
|
|
}
|
|
|
|
//
|
|
// Handle Alerst ...
|
|
bool canAlert =
|
|
mEnableAlerts &&
|
|
prevCalculated > 0;
|
|
bool canLogOnly =
|
|
mEnableAlerts &&
|
|
prevCalculated == 0;
|
|
if (canAlert || canLogOnly)
|
|
{
|
|
//
|
|
string message =
|
|
zone.symbol + "," +
|
|
ToString(zone.period) + "> " +
|
|
ToString(zone.dir) +
|
|
" Zone Detected at: " + ToString(zone.to);
|
|
|
|
//
|
|
if (canLogOnly)
|
|
{
|
|
alert.LogAlert(message);
|
|
}
|
|
else if (canAlert)
|
|
{
|
|
alert.SendAlert(message);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
|
|
//
|
|
zone.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
p4Bar.Clean();
|
|
zoneLeftBar.Clean();
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Detect Trigger Zone ...
|
|
// DetectTriggerZone(
|
|
// bar_index,
|
|
// prevCalculated,
|
|
// ratesTotal,
|
|
// open,
|
|
// high,
|
|
// close,
|
|
// low,
|
|
// tickVolume //
|
|
// );
|
|
|
|
|
|
|
|
//
|
|
// Implement all Volume and Delta Tests
|
|
// Here for Testing Purposes ...
|
|
void DoTest(int bar_index)
|
|
{
|
|
//
|
|
int lastBarIndex = bar_index + 1;
|
|
bool isFirstBar =
|
|
startCalculationForLastBars > 0
|
|
? bar_index == startCalculationForLastBars
|
|
: bar_index == firstBarIndex;
|
|
|
|
//
|
|
// Ignore Tests on First Bar ...
|
|
if (isFirstBar ||
|
|
bar_index == firstBarIndex - 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
bool has = false;
|
|
string iName = NULL;
|
|
color iClr = CLR_NONE;
|
|
datetime iTime = GetBarTime(
|
|
_Symbol,
|
|
_Period,
|
|
bar_index //
|
|
);
|
|
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Delta Testing ...
|
|
|
|
//
|
|
double iDelta = deltaBuffer[bar_index];
|
|
double iDeltaPrev = deltaBuffer[lastBarIndex];
|
|
double iDeltaP2 = deltaBuffer[lastBarIndex + 1];
|
|
|
|
//
|
|
bool isDeltaUp = iDelta > iDeltaPrev;
|
|
bool isDeltaDown = iDelta < iDeltaPrev;
|
|
|
|
//
|
|
double iDeltaSignal = deltaSignalBuffer[bar_index];
|
|
double iDeltaSignalPrev = deltaSignalBuffer[lastBarIndex];
|
|
|
|
//
|
|
bool isDeltaSignalUp = iDeltaSignal > iDeltaSignalPrev;
|
|
bool isDeltaSignalDown = iDeltaSignal < iDeltaSignalPrev;
|
|
|
|
//
|
|
bool isDeltaSwitchedToBullish =
|
|
isDeltaUp &&
|
|
isDeltaSignalUp &&
|
|
iDelta > iDeltaSignal &&
|
|
iDeltaPrev < iDeltaSignalPrev;
|
|
|
|
//
|
|
bool isDeltaSwitchedToBearish =
|
|
isDeltaDown &&
|
|
isDeltaSignalDown &&
|
|
iDelta < iDeltaSignal &&
|
|
iDeltaPrev > iDeltaSignalPrev;
|
|
|
|
//
|
|
if (false &&
|
|
(isDeltaSwitchedToBullish ||
|
|
isDeltaSwitchedToBearish))
|
|
{
|
|
//
|
|
iDir = isDeltaSwitchedToBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
iClr =
|
|
IsBullish(iDir)
|
|
? clrAqua
|
|
: clrMagenta;
|
|
|
|
//
|
|
iName = ToString(iDir) + "_Delta_" + ToFormatString(iTime);
|
|
|
|
//
|
|
CChartObjectVLine *iObj;
|
|
iObj = new CChartObjectVLine();
|
|
has = iObj.Create(
|
|
0,
|
|
iName,
|
|
0,
|
|
iTime //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
// Style Object ...
|
|
iObj.Color(iClr);
|
|
|
|
//
|
|
// Store Object ...
|
|
mObjects.Add(iObj);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Volume Testing ...
|
|
|
|
//
|
|
double iBullishVolumeSignal = bullishVolumeSignalBuffer[bar_index];
|
|
double iBullishVolumeSignalPrev = bullishVolumeSignalBuffer[lastBarIndex];
|
|
|
|
//
|
|
bool isBullishVolumeSignalUp = iBullishVolumeSignal > iBullishVolumeSignalPrev;
|
|
bool isBullishVolumeSignalDown = iBullishVolumeSignal < iBullishVolumeSignalPrev;
|
|
|
|
//
|
|
double iBearishVolumeSignal = bearishVolumeSignalBuffer[bar_index];
|
|
double iBearishVolumeSignalPrev = bearishVolumeSignalBuffer[lastBarIndex];
|
|
|
|
//
|
|
bool isBearishVolumeSignalUp = iBearishVolumeSignal > iBearishVolumeSignalPrev;
|
|
bool isBearishVolumeSignalDown = iBearishVolumeSignal < iBearishVolumeSignalPrev;
|
|
|
|
//
|
|
bool isVolumeSwitchdToBullish =
|
|
isBullishVolumeSignalUp &&
|
|
!isBearishVolumeSignalUp &&
|
|
iBullishVolumeSignal > iBearishVolumeSignal &&
|
|
iBullishVolumeSignalPrev < iBearishVolumeSignalPrev;
|
|
|
|
//
|
|
bool isVolumeSwitchdToBearish =
|
|
isBearishVolumeSignalUp &&
|
|
!isBullishVolumeSignalUp &&
|
|
iBearishVolumeSignal > iBullishVolumeSignal &&
|
|
iBearishVolumeSignalPrev < iBullishVolumeSignalPrev;
|
|
|
|
//
|
|
if (false &&
|
|
(isVolumeSwitchdToBullish ||
|
|
isVolumeSwitchdToBearish))
|
|
{
|
|
//
|
|
iDir = isVolumeSwitchdToBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
iClr =
|
|
IsBullish(iDir)
|
|
? clrAqua
|
|
: clrMagenta;
|
|
|
|
//
|
|
iName = ToString(iDir) + "_Volume_" + ToFormatString(iTime);
|
|
|
|
//
|
|
CChartObjectVLine *iObj;
|
|
iObj = new CChartObjectVLine();
|
|
has = iObj.Create(
|
|
0,
|
|
iName,
|
|
0,
|
|
iTime //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
// Style Object ...
|
|
iObj.Color(iClr);
|
|
|
|
//
|
|
// Store Object ...
|
|
mObjects.Add(iObj);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Signal Bar ...
|
|
|
|
//
|
|
double iSignalOpen = openSignalBuffer[bar_index];
|
|
double iSignalOpenPrev = openSignalBuffer[lastBarIndex];
|
|
|
|
//
|
|
double iSignalClose = closeSignalBuffer[bar_index];
|
|
double iSignalClosePrev = closeSignalBuffer[lastBarIndex];
|
|
|
|
//
|
|
bool isSignalBarBullish = iSignalOpen < iSignalClose;
|
|
bool isSignalBarBullishPrev = iSignalOpenPrev < iSignalClosePrev;
|
|
|
|
//
|
|
bool isSignalBarBearish = iSignalOpen > iSignalClose;
|
|
bool isSignalBarBearishPrev = iSignalOpenPrev > iSignalClosePrev;
|
|
|
|
//
|
|
bool isSignalBarSwitchedToBullish =
|
|
isSignalBarBullish &&
|
|
!isSignalBarBullishPrev;
|
|
|
|
//
|
|
bool isSignalBarSwitchedToBearish =
|
|
isSignalBarBearish &&
|
|
!isSignalBarBearishPrev;
|
|
|
|
//
|
|
// HK Signal Bar ...
|
|
|
|
//
|
|
double iHKSignalOpen = openHKSignalBuffer[bar_index];
|
|
double iHKSignalOpenPrev = openHKSignalBuffer[lastBarIndex];
|
|
|
|
//
|
|
double iHKSignalClose = closeHKSignalBuffer[bar_index];
|
|
double iHKSignalClosePrev = closeHKSignalBuffer[lastBarIndex];
|
|
|
|
//
|
|
bool isHKSignalBarBullish = iHKSignalOpen < iHKSignalClose;
|
|
bool isHKSignalBarBullishPrev = iHKSignalOpenPrev < iHKSignalClosePrev;
|
|
|
|
//
|
|
bool isHKSignalBarBearish = iHKSignalOpen > iHKSignalClose;
|
|
bool isHKSignalBarBearishPrev = iHKSignalOpenPrev > iHKSignalClosePrev;
|
|
|
|
//
|
|
bool isHKSignalBarSwitchedToBullish =
|
|
isHKSignalBarBullish &&
|
|
!isHKSignalBarBullishPrev;
|
|
|
|
//
|
|
bool isHKSignalBarSwitchedToBearish =
|
|
isHKSignalBarBearish &&
|
|
!isHKSignalBarBearishPrev;
|
|
|
|
//
|
|
// SAR ...
|
|
|
|
//
|
|
double iSarState = sarStateBuffer[bar_index];
|
|
double iSarStatePrev = sarStateBuffer[lastBarIndex];
|
|
|
|
//
|
|
bool isSarBullish = iSarState > 0;
|
|
bool isSarBullishPrev = iSarStatePrev > 0;
|
|
|
|
//
|
|
bool isSarBearish = iSarState < 0;
|
|
bool isSarBearishPrev = iSarStatePrev < 0;
|
|
|
|
//
|
|
bool isSarSwitchedToBullish =
|
|
isSarBullish &&
|
|
!isSarBullishPrev;
|
|
|
|
//
|
|
bool isSarSwitchedToBearish =
|
|
isSarBearish &&
|
|
!isSarBearishPrev;
|
|
|
|
//
|
|
// Full Testing Senario ...
|
|
|
|
//
|
|
bool isBullish =
|
|
isSarSwitchedToBullish &&
|
|
isDeltaSwitchedToBullish &&
|
|
isVolumeSwitchdToBullish &&
|
|
isSignalBarSwitchedToBullish &&
|
|
isHKSignalBarSwitchedToBullish;
|
|
|
|
//
|
|
bool isBearish =
|
|
isSarSwitchedToBearish &&
|
|
isDeltaSwitchedToBearish &&
|
|
isVolumeSwitchdToBearish &&
|
|
isSignalBarSwitchedToBearish &&
|
|
isHKSignalBarSwitchedToBearish;
|
|
|
|
//
|
|
if (true &&
|
|
(isBullish ||
|
|
isBearish))
|
|
{
|
|
//
|
|
iDir = isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
iClr =
|
|
IsBullish(iDir)
|
|
? clrAqua
|
|
: clrMagenta;
|
|
|
|
//
|
|
iName = ToString(iDir) + "_BSB_" + ToFormatString(iTime);
|
|
|
|
//
|
|
CChartObjectVLine *iObj;
|
|
iObj = new CChartObjectVLine();
|
|
has = iObj.Create(
|
|
0,
|
|
iName,
|
|
0,
|
|
iTime //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
// Style Object ...
|
|
iObj.Color(iClr);
|
|
|
|
//
|
|
// Store Object ...
|
|
mObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|