Files
MQL5Data/Classes/x-saherelm.x-market.pattern.class.mq5
T
2025-10-01 12:06:18 +03:30

2051 lines
45 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Class Library
// ----------------------------------------------
// Name: XCMarketPatternDetector
// Description: provides all Alerts requirements ...
//
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
//
// Global Properties ...
#property library
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://www.saherelm.ir"
#property version "1.00"
#property strict
//
// Imports ...
#include "../Classes/x-saherelm.base.class.mq5"
#include "../Classes/x-saherelm.x-bar.analyser.class.mq5"
#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5"
#include "../Libraries/x-saherelm.x-poi.lib.mq5"
//
// Definitions ...
//
// Implementation ...
class XCMarketPatternDetector : public XCBase
{
//
// Public ...
public:
//
// Props ...
//
// Constructor ...
XCMarketPatternDetector()
{
barAnalyser = new XCBarAnalyser();
}
//
// Deconstructor ...
~XCMarketPatternDetector()
{
//
delete barAnalyser;
ZeroMemory(barAnalyser);
}
//
// Actions / Helpers ...
//
// Analysers ...
/**
* Check for Price Touch Support Level ...
*
* @param bar: XOHCL, Specified Bar ...
* @param supportBar: XOHCL, reference to holds Zone Bar ...
* @param supportBox: XBoxZone, reference to holds Zone Box ...
* @param validationLength: int, Validation Length ...
* @param maxAllowedLoopback: int, Max Allowed Loopback to Detection ...
*
* @return ( bool )
*/
bool IsSupportTouched(
XOHCL &bar,
XOHCL &supportBar,
XBoxZone &supportBox,
int validationLength = 21,
int maxAllowedLoopback = 1500 //
)
{
//
bool result = false;
//
// Prepare ...
supportBar.Clean();
supportBox.Clean();
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Check Support Exists ...
result = HasSupport(
bar,
supportBar,
validationLength,
maxAllowedLoopback //
);
if (!result)
{
//
supportBar.Clean();
return result;
}
//
// Extract Support Box ...
result = ToSupportBox(
supportBar,
supportBox //
);
//
// Retrieve Previous Bar ...
XOHCL pBar;
result =
result &&
bar.GetPreviousBar(pBar);
//
// Chekc Price of Bar ...
result =
result &&
pBar.low < supportBox.upper;
//
// Cleanup Resources ...
if (!result)
{
//
supportBar.Clean();
supportBox.Clean();
}
pBar.Clean();
//
return result;
}
/**
* Check for Price Touch Resistance Level ...
*
* @param bar: XOHCL, Specified Bar ...
* @param supportBar: XOHCL, reference to holds Zone Bar ...
* @param supportBox: XBoxZone, reference to holds Zone Box ...
* @param validationLength: int, Validation Length ...
* @param maxAllowedLoopback: int, Max Allowed Loopback to Detection ...
*
* @return ( bool )
*/
bool IsResistanceTouched(
XOHCL &bar,
XOHCL &resistanceBar,
XBoxZone &resistanceBox,
int validationLength = 21,
int maxAllowedLoopback = 1500 //
)
{
//
bool result = false;
//
// Prepare ...
resistanceBar.Clean();
resistanceBox.Clean();
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Check Resistance Exists ...
result = HasResistance(
bar,
resistanceBar,
validationLength,
maxAllowedLoopback //
);
if (!result)
{
//
resistanceBar.Clean();
return result;
}
//
// Extract Resistance Box ...
result = ToResistanceBox(
resistanceBar,
resistanceBox //
);
//
// Retrieve Previous Bar ...
XOHCL pBar;
result =
result &&
bar.GetPreviousBar(pBar);
//
// Chekc Price of Bar ...
result =
result &&
pBar.high > resistanceBox.lower;
//
// Cleanup Resources ...
if (!result)
{
//
resistanceBar.Clean();
resistanceBox.Clean();
}
pBar.Clean();
//
return result;
}
//
// Detectors ...
/**
* Check Specified Bar is Momentum Bar or not ...
*
* @param bar: XOHCL, Specified Bar ...
* @param dir: ENUM_X_DIRECTION a reference for Direction ...
* @param requiredBars: int, bar range for approve Momentum ...
* @param approvedMultiplier: double, a Multipler for approve Momentum ...
*
* @return ( bool )
*/
bool IsMomentumBar(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
int requiredBars = 3,
double approvedMultiplier = 2 //
)
{
//
bool result = false;
//
// Prepare ...
CleanDirection(dir);
//
// Normalizing ...
requiredBars = NormalizeInt(requiredBars, 3, 10);
approvedMultiplier = NormalizeDouble(approvedMultiplier, 2, 5);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Calculate Requirements ...
//
XOHCL iBar;
bool has = false;
double rangeBody = 0;
int start = bar.Index() + 1;
int end = start + requiredBars;
for (int i = start; i < end; i++)
{
//
// Initialized Bar ...
has = iBar.Init(
bar.symbol,
bar.period,
i //
);
//
// Summarize Body Sizes ...
if (has)
{
rangeBody += iBar.GetBody();
}
//
iBar.Clean();
}
//
// Calculate Body Approvement ...
result = bar.GetBody() >= (approvedMultiplier * rangeBody);
if (!result)
{
return result;
}
//
// Check Direction ...
dir = bar.GetDirection();
//
// Get Result ...
result = HasDirection(dir);
//
// Cleanup Resources ...
iBar.Clean();
//
return result;
}
/**
* Check Specified Bar is Engulfed Bar or not ...
*
* @param bar: XOHCL, Specified Bar ...
* @param dir: ENUM_X_DIRECTION a reference for Direction ...
*
* @return ( bool )
*/
bool IsEngulfedBar(
XOHCL &bar,
ENUM_X_DIRECTION &dir //
)
{
//
bool result = false;
//
// Prepare ...
CleanDirection(dir);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Calculate Requirements ...
//
XOHCL iBar;
result = bar.GetPreviousBar(iBar);
if (!result)
{
//
iBar.Clean();
return result;
}
//
// Check Prev Bar Must Inside Bar ...
result = bar.GetUp() > iBar.GetUp() &&
bar.GetDown() < iBar.GetDown();
if (!result)
{
//
iBar.Clean();
return result;
}
//
// Check Directions ...
bool isBullish =
iBar.IsBearish() &&
bar.IsBullish();
bool isBearish =
iBar.IsBullish() &&
bar.IsBearish();
result = isBullish || isBearish;
if (!result)
{
//
iBar.Clean();
return result;
}
//
dir = bar.GetDirection();
//
// Get Result ...
result = HasDirection(dir);
//
// Cleanup Resources ...
iBar.Clean();
//
return result;
}
/**
* Check Specified Bar is True Gapped Bar or not ...
*
* @param bar: XOHCL, Specified Bar ...
* @param dir: ENUM_X_DIRECTION a reference for Direction ...
* @param approvedPointMultiplier: double, Gap Validation Multiplier in Point ...
*
* @return ( bool )
*/
bool IsTrueGapedBar(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
double approvedPointMultiplier = 1 //
)
{
//
bool result = false;
//
// Prepare ...
CleanDirection(dir);
//
// Normalizing ...
approvedPointMultiplier = NormalizeDouble(approvedPointMultiplier, 1, 100);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Calculate Requirements ...
//
XOHCL iBar;
result = bar.GetPreviousBar(iBar);
if (!result)
{
//
iBar.Clean();
return result;
}
//
// Check Directions ...
bool isBullish =
iBar.IsBullish() &&
bar.IsBullish();
bool isBearish =
iBar.IsBearish() &&
bar.IsBearish();
result = isBullish || isBearish;
if (!result)
{
//
iBar.Clean();
return result;
}
//
double point = GetPoints(bar.symbol);
double approvedGapSize = approvedPointMultiplier * point;
//
// Check Gap Exists ...
result =
isBullish
? bar.low > iBar.high
: iBar.low > bar.high;
if (!result)
{
//
iBar.Clean();
return result;
}
//
// Validate Gap Size ...
double gapSize = isBullish
? bar.low - iBar.high
: iBar.low - bar.high;
result = gapSize >= approvedGapSize;
if (!result)
{
//
iBar.Clean();
return result;
}
//
dir = bar.GetDirection();
//
// Get Result ...
result = HasDirection(dir);
//
// Cleanup Resources ...
iBar.Clean();
//
return result;
}
/**
* Check Specified Bar is Pinned Bar or not ...
*
* @param bar: XOHCL, Specified Bar ...
* @param dir: ENUM_X_DIRECTION a reference for Direction ...
* @param shadowApprovedMultiplier: double, Shadow Size Approve Multiplier ...
* @param minimumPinBarRangeMultiplier: doubble, Range Size Approve Multiplier in Point ...
* @param forceDirection: bool, Apply Force Bar Type ...
*
* @return ( bool )
*/
bool IsPinnedBar(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
double shadowApprovedMultiplier = 3,
double minimumPinBarRangeMultiplier = 4,
bool forceDirection = false //
)
{
//
bool result = false;
//
// Prepare ...
CleanDirection(dir);
//
// Normalizing ...
shadowApprovedMultiplier = NormalizeDouble(shadowApprovedMultiplier, 2, 5);
minimumPinBarRangeMultiplier = NormalizeDouble(minimumPinBarRangeMultiplier, 2, 100);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Calculate Requirements ...
double body = bar.GetBody();
double lowShadow = bar.GetLowShadow();
double highShadow = bar.GetHighShadow();
//
// Check Directions ...
bool isBullish =
lowShadow > body &&
lowShadow > highShadow &&
lowShadow >= (body * shadowApprovedMultiplier);
bool isBearish =
highShadow > body &&
highShadow > lowShadow &&
highShadow > (body * shadowApprovedMultiplier);
result = isBullish || isBearish;
if (!result)
{
return result;
}
//
// Checking Force Bar Type ...
if (forceDirection)
{
//
result =
isBullish
? bar.IsBullish()
: bar.IsBearish();
}
if (!result)
{
return result;
}
//
// Check Range Validation ...
double point = GetPoints(bar.symbol);
double approvedRange = minimumPinBarRangeMultiplier * point;
result = bar.GetRange() >= approvedRange;
if (!result)
{
return result;
}
//
// Setting Direction ...
dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
result = HasDirection(dir);
//
return result;
}
/**
* Check Specified Bar has Star Pattern or not ...
* Morning Star => Bullish
* Evening Star => Bearish
*
* @param bar: XOHCL, Specified Bar ...
* @param dir: ENUM_X_DIRECTION a reference for Direction ...
*
* @return ( bool )
*/
bool IsStartPattern(
XOHCL &bar,
ENUM_X_DIRECTION &dir //
)
{
//
bool result = false;
//
// Prepare ...
CleanDirection(dir);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Get Requirements ...
XOHCL pBar, p2Bar;
result = bar.GetPreviousBar(pBar);
result = result &&
pBar.GetPreviousBar(p2Bar);
if (!result)
{
//
pBar.Clean();
p2Bar.Clean();
//
return result;
}
//
// Check Directions ...
bool isBullish =
bar.IsBullish() &&
p2Bar.IsBearish();
bool isBearish =
bar.IsBearish() &&
p2Bar.IsBullish();
result = isBullish || isBearish;
if (!result)
{
//
pBar.Clean();
p2Bar.Clean();
//
return result;
}
//
// Checking Gap Exists Between Bars ...
result =
isBullish
? p2Bar.GetDown() > pBar.GetUp() &&
pBar.GetUp() < bar.GetDown()
: p2Bar.GetUp() < pBar.GetDown() &&
pBar.GetDown() > bar.GetUp();
if (!result)
{
//
pBar.Clean();
p2Bar.Clean();
//
return result;
}
//
// Check Bar Close Validation ...
double barClosedApprovedPrice = p2Bar.GetDown() + ((p2Bar.GetUp() - p2Bar.GetDown()) / 2);
result =
isBullish
? bar.close > barClosedApprovedPrice
: bar.close < barClosedApprovedPrice;
if (!result)
{
//
pBar.Clean();
p2Bar.Clean();
//
return result;
}
//
// Validating PBar Body and Shadow ...
double body = pBar.GetBody();
double lowShadow = pBar.GetLowShadow();
double highShadow = pBar.GetHighShadow();
result =
body < bar.GetBody() &&
body < p2Bar.GetBody() &&
(isBullish
? lowShadow > body &&
lowShadow > highShadow
: highShadow > body &&
highShadow > lowShadow);
if (!result)
{
//
pBar.Clean();
p2Bar.Clean();
//
return result;
}
//
dir = bar.GetDirection();
//
// Get Result ...
result = HasDirection(dir);
//
// Cleanup Resources ...
pBar.Clean();
p2Bar.Clean();
//
return result;
}
/**
* Check Specified Bar has Pirecing Pattern or not ...
* Piercing => Bullish
* Dark Cloud Cover => Bearish
*
* @param bar: XOHCL, Specified Bar ...
* @param dir: ENUM_X_DIRECTION a reference for Direction ...
*
* @return ( bool )
*/
bool IsPiercingPattern(
XOHCL &bar,
ENUM_X_DIRECTION &dir //
)
{
//
bool result = false;
//
// Prepare ...
CleanDirection(dir);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
XOHCL pBar;
result = bar.GetPreviousBar(pBar);
if (!result)
{
//
pBar.Clean();
return result;
}
//
// Check Directions ...
bool isBullish =
bar.IsBullish() &&
pBar.IsBearish();
bool isBearish =
bar.IsBearish() &&
pBar.IsBullish();
result = isBullish || isBearish;
if (!result)
{
//
pBar.Clean();
return result;
}
//
// Check Bar Close ...
double barCloseApprovedPrice = pBar.GetDown() + ((pBar.GetUp() - pBar.GetDown()) / 2);
result =
isBullish
? bar.close > barCloseApprovedPrice
: bar.close < barCloseApprovedPrice;
if (!result)
{
//
pBar.Clean();
return result;
}
//
dir = bar.GetDirection();
//
// Get Result ...
result = HasDirection(dir);
//
// Cleanup Resources ...
pBar.Clean();
//
return result;
}
/**
* Check Specified Bar has Rising Pattern or not ...
*
* @param bar: XOHCL, Specified Bar ...
* @param dir: ENUM_X_DIRECTION a reference for Direction ...
*
* @return ( bool )
*/
bool IsRisingPattern(
XOHCL &bar,
ENUM_X_DIRECTION &dir //
)
{
//
bool result = false;
//
// Prepare ...
CleanDirection(dir);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Reading Required Bars ...
XOHCL iBar;
XOHCL bars[];
bool has = false;
int start = bar.Index();
int end = start + 5;
for (int i = start; i < end; i++)
{
//
// Initialized Bar ...
has = iBar.Init(
bar.symbol,
bar.period,
i //
);
if (has)
{
//
AddRef(
iBar,
bars //
);
}
//
iBar.Clean();
}
result = ArraySize(bars) == 5;
if (!result)
{
//
iBar.Clean();
SpecifiedClean(bars);
//
return result;
}
//
// Check Directions ...
bool isBullish =
bars[0].IsBullish() &&
bars[4].IsBullish() &&
bars[1].IsBearish() &&
bars[2].IsBearish() &&
bars[3].IsBearish();
bool isBearish =
bars[0].IsBearish() &&
bars[4].IsBearish() &&
bars[1].IsBullish() &&
bars[2].IsBullish() &&
bars[3].IsBullish();
result = isBullish || isBearish;
if (!result)
{
//
iBar.Clean();
SpecifiedClean(bars);
//
return result;
}
//
// Check Range Validation ...
double upper = bars[4].GetUp();
double lower = bars[4].GetDown();
//
double max = MathMax(bars[1].GetUp(), bars[2].GetUp());
max = MathMax(max, bars[3].GetUp());
//
double min = MathMin(bars[1].GetDown(), bars[2].GetDown());
min = MathMin(min, bars[3].GetDown());
//
result =
max < upper &&
min > lower &&
(isBullish
? bars[0].close > bars[4].GetUp()
: bars[0].close < bars[4].GetDown());
if (!result)
{
//
iBar.Clean();
SpecifiedClean(bars);
//
return result;
}
//
dir = bar.GetDirection();
//
// Get Result ...
result = HasDirection(dir);
//
// Cleanup Resources ...
iBar.Clean();
SpecifiedClean(bars);
//
return result;
}
/**
* Check Specified Bar has Flag Pattern or not ...
*
* @param bar: XOHCL, Specified Bar ...
* @param dir: ENUM_X_DIRECTION a reference for Direction ...
* @param swingBar: XOHCL, Detected Swing Bar ...
* @param minimumPullbackBars: int, Minimum Shoulders of Swing Bar ...
* @param minimumPullbackBars: int, Minimum Shoulders of Swing Bar ...
*
* @return ( bool )
*/
bool IsFlagPattern(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
XOHCL &swingBar,
int minimumPullbackBars = 3 //
)
{
//
bool result = false;
//
// Prepare ...
swingBar.Clean();
CleanDirection(dir);
//
// Normalizing ...
minimumPullbackBars = NormalizeInt(minimumPullbackBars, 3, 10);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Reading Previous Bar ...
XOHCL pBar;
result = bar.GetPreviousBar(pBar);
if (!result)
{
//
pBar.Clean();
return result;
}
//
// Check Directions ...
bool isBullish =
bar.IsBullish() &&
bar.close > pBar.GetUp();
bool isBearish =
bar.IsBearish() &&
bar.close < pBar.GetDown();
result = isBullish || isBearish;
if (!result)
{
//
pBar.Clean();
return result;
}
//
// Detect Swing Bar ...
ENUM_X_SWING_TYPE swingType =
isBullish
? X_SWING_HIGH
: X_SWING_LOW;
result =
result &&
IsXValid(swingType) &&
bar.FindNextSwingBar(
swingType,
swingBar,
minimumPullbackBars //
) &&
(isBullish
? swingBar.IsBullish() &&
swingBar.high > pBar.high
: swingBar.IsBearish() &&
swingBar.low < pBar.low);
if (!result)
{
//
pBar.Clean();
swingBar.Clean();
//
return result;
}
//
dir = bar.GetDirection();
//
// Get Result ...
result = HasDirection(dir);
//
// Cleanup Resources ...
pBar.Clean();
if (!result)
{
swingBar.Clean();
}
//
return result;
}
/**
* Check Specified Bar has SignalKey Bar Pattern or not ...
*
* @param bar: XOHCL, Specified Bar ...
* @param dir: ENUM_X_DIRECTION a reference for Direction ...
* @param shadowApprovedMultiplier: double, Shadow Size Approve Multiplier ...
* @param minimumPinBarRangeMultiplier: doubble, Range Size Approve Multiplier in Point ...
* @param forceDirection: bool, Apply Force Bar Type ...
*
* @return ( bool )
*/
bool IsSignalKeyBarPattern(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
double shadowApprovedMultiplier = 3,
double minimumPinBarRangeMultiplier = 4,
bool forceDirection = false //
)
{
//
bool result = false;
//
// Prepare ...
CleanDirection(dir);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Get Requirements ...
XOHCL pBar;
result = bar.GetPreviousBar(pBar);
if (!result)
{
return result;
}
//
// Chck Previous Bar must Pinned ...
result = IsPinnedBar(
pBar,
dir,
shadowApprovedMultiplier,
minimumPinBarRangeMultiplier,
forceDirection //
);
if (!result)
{
//
pBar.Clean();
return result;
}
//
// Check Direction ...
bool isBullish =
bar.IsBullish() &&
IsSpecifiedBullish(dir) &&
bar.close > pBar.high;
bool isBearish =
bar.IsBearish() &&
IsSpecifiedBearish(dir) &&
bar.close < pBar.low;
result = isBullish || isBearish;
if (!result)
{
//
pBar.Clean();
return result;
}
//
dir = bar.GetDirection();
//
result = HasDirection(dir);
//
// Cleanup Resources ...
pBar.Clean();
//
return result;
}
//
// FVG ...
/**
* Check For FVG Exists in Specified Loopback Period ...
*
* @param bar: XOHCL, Specified Bar ...
* @param dir: ENUM_X_DIRECTION a reference for Direction ...
* @param fvg: XBoxZone, reference for Holding FVG ...
* @param maxLoopback: int, Max Allowed Loopback to Lookup FVG ...
*
* @return ( bool )
*/
bool HasFVG(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
XBoxZone &fvg,
int maxLoopback = 5 //
)
{
//
bool result = false;
//
// Prepare ...
fvg.Clean();
CleanDirection(dir);
//
// Normalize ...
maxLoopback = NormalizeInt(maxLoopback, 3);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
XOHCL iBar;
bool has = false;
int start = bar.Index();
int end = start + maxLoopback;
for (int i = start; i < end; i++)
{
//
// Initialize iBar ...
has = iBar.Init(
bar.symbol,
bar.period,
i //
);
if (!has)
{
continue;
}
//
// Check iBar is FVG or not ...
has = barAnalyser.IsFVG(
iBar,
fvg,
true // Force Bar Type ...
);
if (!has)
{
//
fvg.Clean();
iBar.Clean();
CleanDirection(dir);
//
continue;
}
//
iBar.Clean();
dir = fvg.dir;
//
break;
}
//
// Check FVG Exists ...
result = fvg.IsValid();
//
// Check Direction Exists ...
result =
result &&
HasDirection(dir);
//
// Cleanup Resources ...
if (!result)
{
//
fvg.Clean();
CleanDirection(dir);
}
iBar.Clean();
//
return result;
}
//
// OB ...
/**
* Check For OB Exists in Specified Loopback Period ...
*
* @param bar: XOHCL, Specified Bar ...
* @param dir: ENUM_X_DIRECTION a reference for Direction ...
* @param ob: XBoxZone, reference for Holding OB ...
* @param maxLoopback: int, Max Allowed Loopback to Lookup OB ...
*
* @return ( bool )
*/
bool HasOB(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
XBoxZone &ob,
int maxLoopback = 5 //
)
{
//
bool result = false;
//
// Prepare ...
ob.Clean();
CleanDirection(dir);
//
// Normalize ...
maxLoopback = NormalizeInt(maxLoopback, 3);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
XOHCL iBar;
bool has = false;
int start = bar.Index();
int end = start + maxLoopback;
for (int i = start; i < end; i++)
{
//
// Initialize iBar ...
has = iBar.Init(
bar.symbol,
bar.period,
i //
);
if (!has)
{
continue;
}
//
// Check iBar is OB or not ...
has = barAnalyser.IsOB(
iBar,
ob,
true, // Force FVG Bar Type ...
true // Force OB First Two Bar InDirection ...
);
if (!has)
{
//
ob.Clean();
iBar.Clean();
CleanDirection(dir);
//
continue;
}
//
iBar.Clean();
dir = ob.dir;
//
break;
}
//
// Check OB Exists ...
result = ob.IsValid();
//
// Check Direction Exists ...
result =
result &&
HasDirection(dir);
//
// Cleanup Resources ...
if (!result)
{
//
ob.Clean();
CleanDirection(dir);
}
iBar.Clean();
//
return result;
}
//
// Trending ...
/**
* Check Trend Exists Based on Swings ...
*
* @param bar: XOHCL, Specified Bar ...
* @param dir: ENUM_X_DIRECTION a reference for Direction ...
* @param swings: XOHCL Array, Holds Swings ...
* @param numberOfSwings: int, Number of Swing Points for Detect Trend ...
* @param swingShoulders: int, Swing Shoulders Approvement Length ...
*
* @return ( bool )
*/
bool HasSwingTrend(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
XOHCL &swings[],
int numberOfSwings = 3,
int swingShoulders = 7 //
)
{
//
bool result = false;
//
// Prepare ...
CleanDirection(dir);
SpecifiedClean(swings);
//
// Normalizing ...
numberOfSwings = NormalizeInt(numberOfSwings, 3, 10);
swingShoulders = NormalizeInt(swingShoulders, 3);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Check Trend Direction ...
XOHCL iSwing;
int idx = -1;
bool has = false;
XOHCL swingLows[];
XOHCL swingHighs[];
int lastSwingLowIndex = bar.Index();
int lastSwingHighIndex = bar.Index();
while (ArraySize(swingLows) < numberOfSwings || ArraySize(swingHighs) < numberOfSwings)
{
//
bool canLookupSwingLow = ArraySize(swingLows) < numberOfSwings;
bool canLookupSwingHigh = ArraySize(swingHighs) < numberOfSwings;
if (!canLookupSwingLow && !canLookupSwingHigh)
{
break;
}
//
// Handle Swing Lows ...
if (canLookupSwingLow)
{
//
iSwing.Clean();
idx = FindXSwing(
X_SWING_LOW,
bar.symbol,
bar.period,
lastSwingLowIndex + 1,
swingShoulders //
);
has = IsValidIndex(idx);
if (has)
{
//
has = iSwing.Init(
bar.symbol,
bar.period,
idx //
);
if (has)
{
//
AddRef(
iSwing,
swingLows //
);
//
lastSwingLowIndex = idx;
}
}
}
//
// Handle Swing Highs ...
if (canLookupSwingHigh)
{
//
iSwing.Clean();
idx = FindXSwing(
X_SWING_HIGH,
bar.symbol,
bar.period,
lastSwingHighIndex + 1,
swingShoulders //
);
has = IsValidIndex(idx);
if (has)
{
//
has = iSwing.Init(
bar.symbol,
bar.period,
idx //
);
if (has)
{
//
AddRef(
iSwing,
swingHighs //
);
//
lastSwingHighIndex = idx;
}
}
}
}
//
// Check Trend Based On Swings ...
//
// Check Directions ...
//
bool isBullish = false;
bool isBearish = false;
//
datetime oldestSwingLow = NULL;
datetime oldestSwingHigh = NULL;
//
// Checking Bullish Trend based on Swing Lows ...
int count = ArraySize(swingLows);
for (int i = 0; i < count - 1; i++)
{
//
has = swingLows[i].low > swingLows[i + 1].low;
isBullish =
!isBullish
? has
: isBullish && has;
if (!isBullish)
{
break;
}
//
datetime oldeTime = MathMin(swingLows[i].time, swingLows[i + 1].time);
oldestSwingLow =
!IsSpecifiedValid(oldestSwingLow)
? oldeTime
: MathMin(oldestSwingLow, oldeTime);
}
//
// Checking Bearish Trend based on Swing Highs ...
count = ArraySize(swingHighs);
for (int i = 0; i < count - 1; i++)
{
//
has = swingHighs[i].high < swingHighs[i + 1].high;
isBearish =
!isBearish
? has
: isBearish && has;
if (!isBearish)
{
break;
}
//
datetime oldeTime = MathMin(swingHighs[i].time, swingHighs[i + 1].time);
oldestSwingHigh =
!IsSpecifiedValid(oldestSwingHigh)
? oldeTime
: MathMin(oldestSwingHigh, oldeTime);
}
//
result = isBullish || isBearish;
if (!result)
{
//
iSwing.Clean();
SpecifiedClean(swingLows);
SpecifiedClean(swingHighs);
//
return result;
}
//
if (isBullish &&
isBearish &&
IsSpecifiedValid(oldestSwingLow) &&
IsSpecifiedValid(oldestSwingHigh))
{
//
// Here we Have to Detect Newest Trend or Oldest Trend ...
isBullish = oldestSwingLow < oldestSwingHigh;
isBearish = oldestSwingHigh < oldestSwingLow;
}
//
result = (isBullish && !isBearish) ||
(isBearish && !isBullish);
if (!result)
{
//
iSwing.Clean();
SpecifiedClean(swingLows);
SpecifiedClean(swingHighs);
//
return result;
}
//
if (isBullish)
{
//
Copy(
swingLows,
swings //
);
//
dir = X_DIRECTION_BULLISH;
}
else
{
//
Copy(
swingHighs,
swings //
);
//
dir = X_DIRECTION_BEARISH;
}
//
iSwing.Clean();
SpecifiedClean(swingLows);
SpecifiedClean(swingHighs);
//
return result;
}
/**
* Check Specified Bar Has Support or not ...
*
* @param bar: XOHCL, Specified Bar ...
* @param support: XOHCL, Supported Bar ...
* @param validationLength: int, Validation Length ...
* @param maxAllowedLoopback: int, Max Allowed Loopback to Detection ...
*
* @return ( bool )
*/
bool HasSupport(
XOHCL &bar,
XOHCL &support,
int validationLength = 21,
int maxAllowedLoopback = 1500 //
)
{
//
bool result = false;
//
// Prepare ...
support.Clean();
//
// Normalizing ...
validationLength = NormalizeInt(validationLength, 7);
maxAllowedLoopback = NormalizeInt(maxAllowedLoopback, 21, 1500);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Find Support Swing ...
int idx = -1;
bool has = false;
int lookupIDX = bar.Index();
while (!IsValidIndex(idx) &&
lookupIDX < maxAllowedLoopback)
{
//
// Detect Swing ...
idx = FindXSwing(
X_SWING_LOW,
bar.symbol,
bar.period,
lookupIDX,
validationLength //
);
has = IsValidIndex(idx);
if (!has)
{
//
lookupIDX++;
continue;
}
//
// Retrieve Swing Bar ...
has = support.Init(
bar.symbol,
bar.period,
idx //
);
if (!has)
{
//
idx = -1;
lookupIDX++;
support.Clean();
continue;
}
//
// Check Suppor Low Shadow ...
has = support.GetDown() < bar.low;
if (!has)
{
//
idx = -1;
lookupIDX++;
support.Clean();
continue;
}
//
if (IsValidIndex(idx))
{
break;
}
}
//
result = support.IsValid();
//
return result;
}
/**
* Check Specified Bar Has Resistance or not ...
*
* @param bar: XOHCL, Specified Bar ...
* @param resistence: XOHCL, Resistanced Bar ...
* @param validationLength: int, Validation Length ...
* @param maxAllowedLoopback: int, Max Allowed Loopback to Detection ...
*
* @return ( bool )
*/
bool HasResistance(
XOHCL &bar,
XOHCL &resistence,
int validationLength = 21,
int maxAllowedLoopback = 1500 //
)
{
//
bool result = false;
//
// Prepare ...
resistence.Clean();
//
// Normalizing ...
validationLength = NormalizeInt(validationLength, 7);
maxAllowedLoopback = NormalizeInt(maxAllowedLoopback, 21, 1500);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Find Support Swing ...
int idx = -1;
bool has = false;
int lookupIDX = bar.Index();
while (!IsValidIndex(idx) &&
lookupIDX < maxAllowedLoopback)
{
//
// Detect Swing ...
idx = FindXSwing(
X_SWING_HIGH,
bar.symbol,
bar.period,
lookupIDX,
validationLength //
);
has = IsValidIndex(idx);
if (!has)
{
//
lookupIDX++;
continue;
}
//
// Retrieve Swing Bar ...
has = resistence.Init(
bar.symbol,
bar.period,
idx //
);
if (!has)
{
//
idx = -1;
lookupIDX++;
resistence.Clean();
continue;
}
//
// Check Resistance High Shadow ...
has = resistence.GetUp() > bar.high;
if (!has)
{
//
idx = -1;
lookupIDX++;
resistence.Clean();
continue;
}
//
if (IsValidIndex(idx))
{
break;
}
}
//
result = resistence.IsValid();
//
return result;
}
//
// Protected ...
protected:
//
//
// Tools / Actions ...
/**
* Check Zones and Manage them ...
*
* @param forBar: XOHCL, reference to Specified Bar ...
* @param zones: XBoxZone, reference to Specified Zone Collection ...
* @param sortBy: X_SORT_BY_DATE, Sort Zones by ...
* @param sortDir: ENUM_X_DIRECTION, Sort Zones in Direction ...
* @param maxAllowed: int, Specified Max Allowed Zones ...
*/
void CheckZones(
XOHCL &forBar,
XBoxZone &zones[],
ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE,
ENUM_X_DIRECTION sortDir = X_DIRECTION_BEARISH,
int maxAllowed = 50 //
)
{
//
// Normalize ...
maxAllowed = NormalizeInt(maxAllowed, 0);
//
// Validate ...
bool has = forBar.IsValid() &&
HasChild(zones);
if (!has)
{
return;
}
//
// Looping Through Zones ...
int count = ArraySize(zones);
for (int i = 0; i < count; i++)
{
//
// Check Break ...
has = IsXValid(zones[i].breakAt);
if (has)
{
continue;
}
//
zones[i].to = forBar.time;
//
// Check for Test ...
has = IsTested(
forBar,
zones[i] //
);
if (has)
{
//
Add(
forBar.time,
zones[i].tests //
);
}
//
// Check for Inside ...
has = IsInside(
forBar,
zones[i] //
);
if (has)
{
//
Add(
forBar.time,
zones[i].insides //
);
}
//
// Check for Break ...
has = IsBreaked(
forBar,
zones[i] //
);
if (has)
{
//
Add(
forBar.time,
zones[i].breaks //
);
}
//
// Check for Act ...
has = IsActed(
forBar,
zones[i] //
);
if (has)
{
//
Add(
forBar.time,
zones[i].acteds //
);
}
//
// Check for FakeBreakes ...
has = IsFakeBreaked(
forBar,
zones[i] //
);
if (has)
{
//
Add(
forBar.time,
zones[i].fakeBreaks //
);
}
//
// Check for Valid Breakes ...
has = IsValidBreaked(
forBar,
zones[i] //
);
if (has)
{
zones[i].breakAt = forBar.time;
}
}
//
// Apply Sort and Cleanup ...
Sort(
zones,
sortBy,
sortDir,
maxAllowed //
);
}
//
// Private ...
private:
//
// Props ...
XCBarAnalyser *barAnalyser;
//
// Helpers ...
/**
* Clean Specified Referenced Direction ...
*
* @param dir: ENUM_X_DIRECTION
*/
void CleanDirection(ENUM_X_DIRECTION &dir)
{
dir = X_DIRECTION_NONE;
}
};
//