Files
MQL5Data/Classes/x-saherelm.x-market.pattern.class.mq5
T
2025-09-16 10:55:50 +03:30

1069 lines
23 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"
//
// Definitions ...
//
// Implementation ...
class XCMarketPatternDetector : public XCBase
{
//
// Public ...
public:
//
// Props ...
//
// Constructor ...
XCMarketPatternDetector()
{
}
//
// Deconstructor ...
~XCMarketPatternDetector()
{
}
//
// Actions / Helpers ...
/**
* 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: int, a Multipler for approve Momentum ...
*
* @return ( bool )
*/
bool IsMomentumBar(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
int requiredBars = 3,
int approvedMultiplier = 2 //
)
{
//
bool result = false;
//
// Prepare ...
CleanDirection(dir);
//
// Normalizing ...
requiredBars = NormalizeInt(requiredBars, 3, 10);
approvedMultiplier = NormalizeInt(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: int, 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,
int shadowApprovedMultiplier = 3,
double minimumPinBarRangeMultiplier = 4,
bool forceDirection = false //
)
{
//
bool result = false;
//
// Prepare ...
CleanDirection(dir);
//
// Normalizing ...
shadowApprovedMultiplier = NormalizeInt(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;
}
bool HasTrend(
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 ...
//
iSwing.Clean();
SpecifiedClean(swingLows);
SpecifiedClean(swingHighs);
//
return result;
}
//
// Protected ...
protected:
//
//
// Private ...
private:
//
//
// Helpers ...
/**
* Clean Specified Referenced Direction ...
*
* @param dir: ENUM_X_DIRECTION
*/
void CleanDirection(ENUM_X_DIRECTION &dir)
{
dir = X_DIRECTION_NONE;
}
};
//