Files
MQL5Data/Classes/x-saherelm.x-market.pattern.class.mq5
T
2025-10-08 00:44:29 +03:30

2633 lines
60 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-pivot.analysis.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 Peak or Vale ...
*
* @param bar: XOHCL, Specified Bar ...
* @param dir: ENUM_X_DIRECTION a reference for Direction ...
* @param validationLength: int, Validation Length ...
*
* @return ( bool )
*/
bool IsPV(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
int validationLength = 7,
ENUM_X_PRICE peakPriceType = X_PRICE_HIGH, //
ENUM_X_PRICE valePriceType = X_PRICE_LOW //
)
{
//
bool result = false;
//
// Prepare ...
CleanDirection(dir);
//
// Normalize ...
validationLength = NormalizeInt(validationLength, 2);
//
// Validate ...
result = bar.IsValid() &&
IsXValid(peakPriceType) &&
IsXValid(valePriceType);
if (!result)
{
return result;
}
//
int valeIndex = -1;
double vale = bar.FindLowest(
valeIndex,
validationLength,
valePriceType //
);
double barVale = bar.GetPrice(valePriceType);
bool isVale =
NotEmptyZero(vale) &&
NotEmptyZero(barVale) &&
IsValidIndex(valeIndex) &&
vale >= barVale;
//
int peakIndex = -1;
double peak = bar.FindHighest(
peakIndex,
validationLength,
peakPriceType //
);
double barPeak = bar.GetPrice(peakPriceType);
bool isPeak =
NotEmptyZero(peak) &&
NotEmptyZero(barPeak) &&
IsValidIndex(peakIndex) &&
peak <= barPeak;
//
result = (isVale && !isPeak) ||
(isPeak && !isVale);
if (result)
{
//
dir =
isVale
? X_DIRECTION_BULLISH
: isPeak
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
}
//
// Get Result ...
result = HasDirection(dir);
//
// Cleanup Resources ...
//
return result;
}
/**
* 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 IsStarPattern(
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 ...
*
* @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;
}
//
// Analysers ...
/**
* Analyse Specified Bar ...
*
* @param bar: XOHCL, reference to Specified Bar ...
* @param analysis: XPatternAnalysis, reference to holds Analysis result ...
* @param pvValidationLength: int, Validation Length for Peak and Vale Detection ...
* @param peakPriceType: ENUM_X_PRICE, Specified Price for Peak (High) Detection ...
* @param valePriceType: ENUM_X_PRICE, Specified Price for Vale (Low) Detection ...
* @param momentumBarValidationLength: int, bar range for approve Momentum ...
* @param momentumBarApprovedMultiplier: double, a Multipler for approve Momentum ...
* @param trueGapApprovedStrength: double, Gap Validation Multiplier in Point ...
* @param pinBarShadowApprovedMultiplier: double, PinBar Shadow Size Approve Multiplier ...
* @param pinBarRangeMultiplier: doubble, PinBar Range Size Approve Multiplier in Point ...
* @param pinBarForceDirection: bool, PinBar Apply Force Bar Type ...
* @param flagPatternPullbackLength: int, Minimum Shoulders of FlagPattern's Swing Bar ...
* @param fvgForceType: bool, Force FVG to Have Same type Bars ...
* @param obForceTwoBar: bool, Force OB to has atleast two indirectional Bars ...
* @param supportAndResistanceValidationLength: int, Support and Resistance Validation Length ...
* @param supportAndResistanceLoopbackLength: int, Support and Resistance Detection Loopback ...
*
* @return ( bool )
*/
bool AnalyseBarPatterns(
XOHCL &bar,
XPatternAnalysis &analysis,
//
// PV ...
int pvValidationLength = 7,
ENUM_X_PRICE peakPriceType = X_PRICE_HIGH,
ENUM_X_PRICE valePriceType = X_PRICE_LOW,
//
// Momentum ...
int momentumBarValidationLength = 3,
double momentumBarApprovedMultiplier = 3,
//
// TrueGap ...
double trueGapApprovedStrength = 1,
//
// Pin ...
double pinBarShadowApprovedMultiplier = 3,
double pinBarRangeMultiplier = 4,
bool pinBarForceDirection = false,
//
// Flag ...
int flagPatternPullbackLength = 3,
//
// FVG ...
bool fvgForceType = false,
//
// OB ...
bool obForceTwoBar = false,
//
// Support and Resistance ...
int supportAndResistanceValidationLength = 21,
int supportAndResistanceLoopbackLength = 50 //
//
)
{
//
bool result = false;
//
// Prepare ...
analysis.Clean();
//
// Normalize ...
//
pvValidationLength = NormalizeInt(pvValidationLength, 2);
//
momentumBarValidationLength = NormalizeInt(momentumBarValidationLength, 2);
momentumBarApprovedMultiplier = NormalizeDouble(momentumBarApprovedMultiplier, 1);
//
trueGapApprovedStrength = NormalizeDouble(trueGapApprovedStrength, 1);
//
pinBarRangeMultiplier = NormalizeDouble(pinBarRangeMultiplier, 4);
pinBarShadowApprovedMultiplier = NormalizeDouble(pinBarShadowApprovedMultiplier, 3);
//
flagPatternPullbackLength = NormalizeInt(flagPatternPullbackLength, 3);
//
supportAndResistanceLoopbackLength = NormalizeInt(supportAndResistanceLoopbackLength, 10);
supportAndResistanceValidationLength = NormalizeInt(supportAndResistanceValidationLength, 10);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
analysis.bar = bar;
analysis.time = TimeCurrent();
//
XOHCL iSwing;
XBoxZone iZone;
ENUM_X_DIRECTION iDir;
ENUM_X_BAR_PATTERN iPattern;
//
// Bars Detectors ...
//
// XPV High Low Detection ...
bool isPV = IsPV(
bar,
iDir,
pvValidationLength,
peakPriceType,
valePriceType //
);
bool isHigh = isPV &&
IsXBearish(iDir);
bool isLow = isPV &&
IsXBullish(iDir);
if (isPV)
{
//
iPattern =
isHigh
? X_BAR_PATTERN_HIGH
: X_BAR_PATTERN_LOW;
//
analysis.AddPattern(
iPattern,
iDir //
);
}
//
// Momentum ...
bool isMomentum = IsMomentumBar(
bar,
iDir,
momentumBarValidationLength,
momentumBarApprovedMultiplier //
);
bool isBullishMomentum = isMomentum &&
IsXBullish(iDir);
bool isBearishMomentum = isMomentum &&
IsXBearish(iDir);
if (isMomentum)
{
//
iPattern = X_BAR_PATTERN_MOMENTUM;
//
analysis.AddPattern(
iPattern,
iDir //
);
}
//
// Engulfed ...
bool isEngulfed = IsEngulfedBar(
bar,
iDir //
);
bool isBullishEngulfed = isEngulfed &&
IsXBullish(iDir);
bool isBearishEngulfed = isEngulfed &&
IsXBearish(iDir);
if (isEngulfed)
{
//
iPattern = X_BAR_PATTERN_ENGULFED;
//
analysis.AddPattern(
iPattern,
iDir //
);
}
//
// TrueGap ...
bool isTrueGaped = IsTrueGapedBar(
bar,
iDir,
trueGapApprovedStrength //
);
bool isBullishTrueGaped = isTrueGaped &&
IsXBullish(iDir);
bool isBearishTrueGaped = isTrueGaped &&
IsXBearish(iDir);
if (isTrueGaped)
{
//
iPattern = X_BAR_PATTERN_TRUE_GAPED;
//
analysis.AddPattern(
iPattern,
iDir //
);
}
//
// Pinned ...
bool isPinned = IsPinnedBar(
bar,
iDir,
pinBarShadowApprovedMultiplier,
pinBarRangeMultiplier,
pinBarForceDirection //
);
bool isBullishPinned = isPinned &&
IsXBullish(iDir);
bool isBearishPinned = isPinned &&
IsXBearish(iDir);
if (isPinned)
{
//
iPattern = X_BAR_PATTERN_PINNED;
//
analysis.AddPattern(
iPattern,
iDir //
);
}
//
// Pattern Detectors ...
//
// Star ...
bool isStar = IsStarPattern(
bar,
iDir //
);
bool isBullishStar = isStar &&
IsXBullish(iDir);
bool isBearishStar = isStar &&
IsXBearish(iDir);
if (isStar)
{
//
iPattern = X_BAR_PATTERN_STAR;
//
analysis.AddPattern(
iPattern,
iDir //
);
}
//
// Piercing ...
bool isPiercing = IsPiercingPattern(
bar,
iDir //
);
bool isBullishPiercing = isPiercing &&
IsXBullish(iDir);
bool isBearishPiercing = isPiercing &&
IsXBearish(iDir);
if (isPiercing)
{
//
iPattern = X_BAR_PATTERN_PIERCING;
//
analysis.AddPattern(
iPattern,
iDir //
);
}
//
// Rising ...
bool isRising = IsRisingPattern(
bar,
iDir //
);
bool isBullishRising = isRising &&
IsXBullish(iDir);
bool isBearishRising = isRising &&
IsXBearish(iDir);
if (isRising)
{
//
iPattern = X_BAR_PATTERN_RISING;
//
analysis.AddPattern(
iPattern,
iDir //
);
}
//
// Flag ...
bool isFlag = IsFlagPattern(
bar,
iDir,
iSwing,
flagPatternPullbackLength //
);
bool isBullishFlag = isFlag &&
IsXBullish(iDir);
bool isBearishFlag = isFlag &&
IsXBearish(iDir);
if (isFlag)
{
//
iPattern = X_BAR_PATTERN_FLAG;
//
analysis.AddPattern(
iPattern,
iDir //
);
//
analysis.flagSwing = iSwing;
}
//
// SignalKey ...
bool isSignalKey = IsSignalKeyBarPattern(
bar,
iDir,
pinBarShadowApprovedMultiplier,
pinBarRangeMultiplier,
pinBarForceDirection //
);
bool isBullishSignalKey = isSignalKey &&
IsXBullish(iDir);
bool isBearishSignalKey = isSignalKey &&
IsXBearish(iDir);
if (isSignalKey)
{
//
iPattern = X_BAR_PATTERN_SIGNALKEY;
//
analysis.AddPattern(
iPattern,
iDir //
);
}
//
// Zone Detectors ...
//
// OB ...
bool isOB = barAnalyser.IsOB(
bar,
iZone,
fvgForceType,
obForceTwoBar //
);
bool isBullishOB = isOB &&
iZone.IsBullish();
bool isBearishOB = isOB &&
iZone.IsBearish();
if (isOB)
{
//
iPattern = X_BAR_PATTERN_OB;
//
analysis.AddPattern(
iPattern,
iZone.dir //
);
//
analysis.ob = iZone;
}
//
// FVG ...
bool isFVG = barAnalyser.IsFVG(
bar,
iZone,
fvgForceType //
);
bool isBullishFVG = isFVG &&
iZone.IsBullish();
bool isBearishFVG = isFVG &&
iZone.IsBearish();
if (isFVG)
{
//
iPattern = X_BAR_PATTERN_FVG;
//
analysis.AddPattern(
iPattern,
iZone.dir //
);
//
analysis.fvg = iZone;
}
//
// Support ...
bool isSupport = HasSupport(
bar,
iSwing,
supportAndResistanceValidationLength,
supportAndResistanceLoopbackLength //
);
if (isSupport)
{
//
iPattern = X_BAR_PATTERN_SUPPORT;
//
bool has = ToSupportBox(
iSwing,
iZone,
bar.time,
supportAndResistanceValidationLength //
);
if (has)
{
//
analysis.AddPattern(
iPattern,
iZone.dir //
);
//
analysis.support = iZone;
}
}
//
// Resistance ...
bool isResistance = HasResistance(
bar,
iSwing,
supportAndResistanceValidationLength,
supportAndResistanceLoopbackLength //
);
if (isResistance)
{
//
iPattern = X_BAR_PATTERN_RESISTANCE;
//
bool has = ToResistanceBox(
iSwing,
iZone,
bar.time,
supportAndResistanceValidationLength //
);
if (has)
{
//
analysis.AddPattern(
iPattern,
iZone.dir //
);
//
analysis.resistance = iZone;
}
}
//
// Validate Analysis ...
result = analysis.IsValid();
//
// Cleanup Resources ...
iZone.Clean();
iSwing.Clean();
CleanDirection(iDir);
//
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;
}
};
//