1360 lines
28 KiB
Plaintext
1360 lines
28 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Class Library
|
|
// --------------------------------------
|
|
// Name: XPOI
|
|
// Description: Bar Analysing ...
|
|
//
|
|
// 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 "../Libraries/x-saherelm.x-poi.lib.mq5"
|
|
|
|
//
|
|
// Definitions ...
|
|
|
|
//
|
|
// Implementations ...
|
|
class XCBarAnalyser : public XSCBase
|
|
{
|
|
//
|
|
public:
|
|
//
|
|
|
|
//
|
|
// Constructor(s) ...
|
|
void XCBarAnalyser()
|
|
{
|
|
}
|
|
|
|
//
|
|
// Deconstructor ...
|
|
void ~XCBarAnalyser()
|
|
{
|
|
}
|
|
|
|
//
|
|
// Getter(s) / Setter(s) ...
|
|
|
|
//
|
|
// Providers ...
|
|
|
|
//
|
|
// Actions ...
|
|
|
|
/**
|
|
* Calculate Loopback Data for Specific Bar ...
|
|
*
|
|
* @param index: Integer, Bar Current Index ...
|
|
* @param start: Integer, Start of Loopback ...
|
|
* @param end: Integer, End of Loopback ...
|
|
* @param count: Integer, Number of Calculating Bars ...
|
|
* @param bar: XOHCL instance, Specified Bar ...
|
|
* @param loopback: Integer, Loopback Length ...
|
|
* @return ( bool )
|
|
*/
|
|
bool CalculateLoopBackData(
|
|
int &index,
|
|
int &start,
|
|
int &end,
|
|
int &count,
|
|
XOHCL &bar,
|
|
int loopback = 1 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (loopback < 1)
|
|
{
|
|
loopback = 1;
|
|
}
|
|
|
|
//
|
|
index = -1;
|
|
start = -1;
|
|
end = -1;
|
|
count = -1;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
index = bar.Index();
|
|
start = index + 1;
|
|
end = start + loopback;
|
|
count = end - start;
|
|
result = count >= 1;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieve Loopback HH & LL Data ...
|
|
*
|
|
* @param hhIDX: Integer, HH Index ...
|
|
* @param hh: Double, HH Value ...
|
|
* @param llIDX: Integer, LL Index ...
|
|
* @param ll: Double, LL Value ...
|
|
* @param bar: XOHCL instance ...
|
|
* @param loopback: Integer, Loopback Length ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool CalculateLoopbackHLData(
|
|
int &hhIDX,
|
|
double &hh,
|
|
int &llIDX,
|
|
double &ll,
|
|
XOHCL &bar,
|
|
int loopback //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (loopback < 1)
|
|
{
|
|
loopback = 1;
|
|
}
|
|
|
|
//
|
|
int index = -1;
|
|
int start = -1;
|
|
int end = -1;
|
|
int count = -1;
|
|
result = CalculateLoopBackData(
|
|
index,
|
|
start,
|
|
end,
|
|
count,
|
|
bar,
|
|
loopback //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
hhIDX = iHighest(
|
|
bar.symbol,
|
|
bar.period,
|
|
MODE_HIGH,
|
|
count,
|
|
start //
|
|
);
|
|
result = IsValidIndex(hhIDX);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
llIDX = iLowest(
|
|
bar.symbol,
|
|
bar.period,
|
|
MODE_LOW,
|
|
count,
|
|
start //
|
|
);
|
|
result = IsValidIndex(llIDX);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
hh = iHigh(
|
|
bar.symbol,
|
|
bar.period,
|
|
hhIDX //
|
|
);
|
|
ll = iLow(
|
|
bar.symbol,
|
|
bar.period,
|
|
llIDX //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Calculate Bar Range ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double GetBarRangePercent(XOHCL &bar)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
result = bar.GetRange() / 100;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Commons ...
|
|
|
|
/**
|
|
* Check Specified Bar's Range is Extended or not ...
|
|
*
|
|
* @param bar: XOHCL instance, Specified Bar ...
|
|
* @param loopback: Integer, Loopback Length ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasExtendedRange(
|
|
XOHCL &bar,
|
|
int loopback = 3 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (loopback < 3)
|
|
{
|
|
loopback = 3;
|
|
}
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int index = bar.Index();
|
|
int start = index + 1;
|
|
int end = start + loopback;
|
|
int count = end - start;
|
|
result = count >= 1;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double sum = 0;
|
|
XOHCL iBar = bar;
|
|
for (int i = start; i < end; i++)
|
|
{
|
|
//
|
|
bool isRetrieved = iBar.GetPreviousBar(iBar);
|
|
if (!isRetrieved)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
sum += iBar.GetRange();
|
|
}
|
|
|
|
//
|
|
result = sum > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double avg = sum / count;
|
|
|
|
//
|
|
result = bar.GetRange() >= avg;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar's Body is Extended or not ...
|
|
*
|
|
* @param bar: XOHCL instance, Specified Bar ...
|
|
* @param loopback: Integer, Loopback Length ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasExtendedBody(
|
|
XOHCL &bar,
|
|
int loopback = 3 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (loopback < 3)
|
|
{
|
|
loopback = 3;
|
|
}
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int index = bar.Index();
|
|
int start = index + 1;
|
|
int end = start + loopback;
|
|
int count = end - start;
|
|
result = count >= 1;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double sum = 0;
|
|
XOHCL iBar = bar;
|
|
for (int i = start; i < end; i++)
|
|
{
|
|
//
|
|
bool isRetrieved = iBar.GetPreviousBar(iBar);
|
|
if (!isRetrieved)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
sum += iBar.GetBody();
|
|
}
|
|
|
|
//
|
|
result = sum > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double avg = sum / count;
|
|
|
|
//
|
|
result = bar.GetBody() >= avg;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar's Body and Range is Extended or not ...
|
|
*
|
|
* @param bar: XOHCL instance, Specified Bar ...
|
|
* @param loopback: Integer, Loopback Length ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsExtended(
|
|
XOHCL &bar,
|
|
int loopback = 3 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
bool hasExtendedBody = HasExtendedBody(bar, loopback);
|
|
bool hasExtendedRange = HasExtendedRange(bar, loopback);
|
|
result = hasExtendedBody &&
|
|
hasExtendedRange;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts an Specified Bar to Zone ...
|
|
*
|
|
* @param bar: XOHCL instance, Specified Bar ...
|
|
* @param zone: XZone instance, Converted Zone Reference ...
|
|
* @param dir: ENUM_X_DIRECTION member, Specified Bar Type to Convertion ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToZone(
|
|
XOHCL &bar,
|
|
XZone &zone,
|
|
ENUM_X_DIRECTION dir = X_DIRECTION_BULLISH //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
zone.Clean();
|
|
|
|
//
|
|
result = bar.IsValid() &&
|
|
(dir == X_DIRECTION_BULLISH ||
|
|
dir == X_DIRECTION_BEARISH);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = dir == X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
zone.from = bar.time;
|
|
zone.to = TimeCurrent();
|
|
zone.prefix = "XBarZone";
|
|
|
|
//
|
|
zone.upper = isBullish
|
|
? bar.high
|
|
: bar.GetDown();
|
|
|
|
//
|
|
zone.lower = isBullish
|
|
? bar.GetUp()
|
|
: bar.low;
|
|
|
|
//
|
|
result = zone.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Regular ...
|
|
|
|
/**
|
|
* Check a Zone is Rejected in Specified Direction or not ...
|
|
*
|
|
* @param bar: XOHCL instance, Specified Bar ...
|
|
* @param zone: XZone instance, Specified Zone ...
|
|
* @param dir: ENUM_X_DIRECTION member, Specified Rejection Direction ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsRejected(
|
|
XOHCL &bar,
|
|
XZone &zone,
|
|
ENUM_X_DIRECTION dir //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = bar.IsValid() &&
|
|
zone.IsValid() &&
|
|
(dir == X_DIRECTION_BULLISH ||
|
|
dir == X_DIRECTION_BEARISH);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = dir == X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
ENUM_X_DIRECTION rejectionDir;
|
|
bool isRejection = IsRejectionBar(
|
|
rejectionDir,
|
|
bar,
|
|
40 //
|
|
);
|
|
bool isBullishRejection = isRejection &&
|
|
rejectionDir == X_DIRECTION_BULLISH;
|
|
bool isBearishRejection = isRejection &&
|
|
rejectionDir == X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = isRejection &&
|
|
rejectionDir == dir &&
|
|
(isBullishRejection
|
|
? bar.low < zone.upper &&
|
|
bar.low > zone.lower
|
|
: bar.high > zone.lower &&
|
|
bar.high < zone.upper);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Zone is Breaked in Specified Direction or not ...
|
|
*
|
|
* @param bar: XOHCL instance, Specified Bar ...
|
|
* @param zone: XZone instance, Specified Zone ...
|
|
* @param dir: ENUM_X_DIRECTION member, Specified Rejection Direction ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBreaked(
|
|
XOHCL &bar,
|
|
XZone &zone,
|
|
ENUM_X_DIRECTION dir,
|
|
bool forceBody = true //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = bar.IsValid() &&
|
|
zone.IsValid() &&
|
|
(dir == X_DIRECTION_BULLISH ||
|
|
dir == X_DIRECTION_BEARISH);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = dir == X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
ENUM_X_DIRECTION momentumDir;
|
|
bool isMomentum = IsMomentumBar(
|
|
momentumDir,
|
|
bar,
|
|
50 //
|
|
);
|
|
bool isBullishBreaked = isMomentum &&
|
|
momentumDir == X_DIRECTION_BULLISH;
|
|
bool isBearishBreaked = isMomentum &&
|
|
momentumDir == X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = isMomentum &&
|
|
momentumDir == dir &&
|
|
(isBullishBreaked
|
|
? bar.IsBullish() &&
|
|
bar.low < zone.lower &&
|
|
bar.high > zone.upper
|
|
: bar.IsBearish() &&
|
|
bar.high > zone.lower &&
|
|
bar.low < zone.lower);
|
|
if (result &&
|
|
forceBody)
|
|
{
|
|
//
|
|
result = isBullishBreaked
|
|
? bar.IsBullish() &&
|
|
bar.GetUp() > zone.upper &&
|
|
bar.GetDown() < zone.lower
|
|
: bar.IsBearish() &&
|
|
bar.GetUp() > zone.upper &&
|
|
bar.GetDown() < zone.lower;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Rejection Bar ...
|
|
|
|
/**
|
|
* Check Specific Bar is Rejection Bar or not ...
|
|
*
|
|
* @param dir: ENUM_X_DIRECTION member, Specified Direction ...
|
|
* @param bar: XOHCL instance, Specified Bar ...
|
|
* @param strength: Double, Specified Shadow Percent Range ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsRejectionBar(
|
|
ENUM_X_DIRECTION &dir,
|
|
XOHCL &bar,
|
|
double strength //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (strength < 20)
|
|
{
|
|
strength = 20;
|
|
}
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double barLowShadow = bar.GetLowShadow();
|
|
double barHighShadow = bar.GetHighShadow();
|
|
double barRange = bar.GetRange();
|
|
double barRangePercent = barRange / 100;
|
|
|
|
//
|
|
bool isBullishRejectionBar =
|
|
barLowShadow > barHighShadow &&
|
|
barLowShadow > barRangePercent * strength;
|
|
|
|
//
|
|
bool isBearishRejectionBar =
|
|
barHighShadow > barLowShadow &&
|
|
barHighShadow > barRangePercent * strength;
|
|
|
|
//
|
|
result = isBullishRejectionBar ||
|
|
isBearishRejectionBar;
|
|
if (result)
|
|
{
|
|
//
|
|
dir = isBullishRejectionBar
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specific Bar is Bullish Rejection Bar or not ...
|
|
*
|
|
* @param bar: XOHCL instance, Specified Bar ...
|
|
* @param strength: Double, Specified Shadow Percent Range ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBullishRejectionBar(
|
|
XOHCL &bar,
|
|
double strength = 40 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
ENUM_X_DIRECTION dir;
|
|
result = IsRejectionBar(
|
|
dir,
|
|
bar,
|
|
strength //
|
|
);
|
|
result =
|
|
result &&
|
|
dir == X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specific Bar is Bearish Rejection Bar or not ...
|
|
*
|
|
* @param bar: XOHCL instance, Specified Bar ...
|
|
* @param strength: Double, Specified Shadow Percent Range ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBearishRejectionBar(
|
|
XOHCL &bar,
|
|
double strength = 40 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
ENUM_X_DIRECTION dir;
|
|
result = IsRejectionBar(
|
|
dir,
|
|
bar,
|
|
strength //
|
|
);
|
|
result =
|
|
result &&
|
|
dir == X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Momentum Bar ...
|
|
|
|
/**
|
|
* Check Specific Bar is Momentum Bar or not ...
|
|
*
|
|
* @param dir: ENUM_X_DIRECTION member, Specified Direction ...
|
|
* @param bar: XOHCL instance, Specified Bar ...
|
|
* @param strength: Double, Specified Shadow Percent Range ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsMomentumBar(
|
|
ENUM_X_DIRECTION &dir,
|
|
XOHCL &bar,
|
|
double strength //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (strength < 50)
|
|
{
|
|
strength = 50;
|
|
}
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
double rangePercent = GetBarRangePercent(bar);
|
|
bool isStrong = bar.GetBody() > rangePercent * strength;
|
|
|
|
//
|
|
result = isStrong;
|
|
if (result)
|
|
{
|
|
//
|
|
dir = bar.IsBullish()
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specific Bar is Bullish Momentum Bar or not ...
|
|
*
|
|
* @param bar: XOHCL instance, Specified Bar ...
|
|
* @param strength: Double, Specified Shadow Percent Range ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBullishMomentumBar(
|
|
XOHCL &bar,
|
|
double strength = 40 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
ENUM_X_DIRECTION dir;
|
|
result = IsMomentumBar(
|
|
dir,
|
|
bar,
|
|
strength //
|
|
);
|
|
result =
|
|
result &&
|
|
dir == X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specific Bar is Bearish Momentum Bar or not ...
|
|
*
|
|
* @param bar: XOHCL instance, Specified Bar ...
|
|
* @param strength: Double, Specified Shadow Percent Range ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBearishMomentumBar(
|
|
XOHCL &bar,
|
|
double strength = 40 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
ENUM_X_DIRECTION dir;
|
|
result = IsMomentumBar(
|
|
dir,
|
|
bar,
|
|
strength //
|
|
);
|
|
result =
|
|
result &&
|
|
dir == X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Engulfing ...
|
|
|
|
/**
|
|
* Check Bar is Engulfed or not ...
|
|
*
|
|
* @param dir: ENUM_X_DIRECTION member, Specified Direction ...
|
|
* @param bar: XOHCL instance, Speciied Bar ...
|
|
* @param loopback: Integer, loopback Length ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsEngulfed(
|
|
ENUM_X_DIRECTION &dir,
|
|
XOHCL &bar,
|
|
int loopback //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
int hhIDX = 0;
|
|
double hh = 0;
|
|
|
|
//
|
|
int llIDX = 0;
|
|
double ll = 0;
|
|
|
|
//
|
|
result = CalculateLoopbackHLData(
|
|
hhIDX,
|
|
hh,
|
|
llIDX,
|
|
ll,
|
|
bar,
|
|
loopback //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = bar.GetDown() < ll &&
|
|
bar.GetUp() > hh;
|
|
if (result)
|
|
{
|
|
//
|
|
dir = bar.IsBullish()
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Bar is Bullish Engulfed or not ...
|
|
*
|
|
* @param bar: XOHCL instance, Speciied Bar ...
|
|
* @param loopback: Integer, loopback Length ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBullishEngulfed(
|
|
XOHCL &bar,
|
|
int loopback = 2 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
ENUM_X_DIRECTION dir;
|
|
result = IsEngulfed(
|
|
dir,
|
|
bar,
|
|
loopback //
|
|
);
|
|
result =
|
|
result &&
|
|
dir == X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Bar is Bearish Engulfed or not ...
|
|
*
|
|
* @param bar: XOHCL instance, Speciied Bar ...
|
|
* @param loopback: Integer, loopback Length ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBearishEngulfed(
|
|
XOHCL &bar,
|
|
int loopback = 2 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
ENUM_X_DIRECTION dir;
|
|
result = IsEngulfed(
|
|
dir,
|
|
bar,
|
|
loopback //
|
|
);
|
|
result =
|
|
result &&
|
|
dir == X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Bar CHOCH ...
|
|
|
|
/**
|
|
* Check Specified Bar Has CHOCH or not ...
|
|
*
|
|
* @param dir: ENUM_X_DIRECTION member, Specified Direction ...
|
|
* @param bar: XOHCL instance, Speciied Bar ...
|
|
* @param loopback: Integer, loopback Length ...
|
|
* @param forceBody: Boolean, Specified Choch Happens only by Bar's Body ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasCHOCH(
|
|
ENUM_X_DIRECTION &dir,
|
|
XOHCL &bar,
|
|
int loopback = 2,
|
|
bool forceBody = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
if (loopback < 1)
|
|
{
|
|
loopback = 1;
|
|
}
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string symbol = bar.symbol;
|
|
ENUM_TIMEFRAMES period = bar.period;
|
|
|
|
//
|
|
// Calculate Loopback Data ...
|
|
int index = -1;
|
|
int start = -1;
|
|
int end = -1;
|
|
int count = -1;
|
|
result = CalculateLoopBackData(
|
|
index,
|
|
start,
|
|
end,
|
|
count,
|
|
bar,
|
|
loopback //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate Loopback HH and LL Data ...
|
|
int hhIDX = -1;
|
|
double hh = -1;
|
|
int llIDX = -1;
|
|
double ll = -1;
|
|
result = CalculateLoopbackHLData(
|
|
hhIDX,
|
|
hh,
|
|
llIDX,
|
|
ll,
|
|
bar,
|
|
loopback //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullishDirection =
|
|
bar.high > hh &&
|
|
bar.low > ll;
|
|
bool isBearishDirection =
|
|
bar.high < hh &&
|
|
bar.low < ll;
|
|
result = isBullishDirection ||
|
|
isBearishDirection;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (forceBody)
|
|
{
|
|
//
|
|
isBullishDirection =
|
|
bar.GetUp() > hh &&
|
|
bar.GetDown() > ll;
|
|
isBearishDirection =
|
|
bar.GetUp() < hh &&
|
|
bar.GetDown() < ll;
|
|
result = isBullishDirection ||
|
|
isBearishDirection;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Bar's Direction in related to CHOCH Direction ...
|
|
result =
|
|
isBullishDirection
|
|
? bar.IsBullish()
|
|
: bar.IsBearish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Set Direction ...
|
|
dir =
|
|
isBullishDirection
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
// Check Loopback End Bar ...
|
|
XOHCL endBar;
|
|
result = endBar.Init(
|
|
symbol,
|
|
period,
|
|
end - 1 //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// End Bar Must be InDirect by Specified Bar ...
|
|
result =
|
|
isBullishDirection
|
|
? endBar.IsBearish()
|
|
: endBar.IsBullish();
|
|
|
|
//
|
|
// Check Loopback for Directional Bars ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar Has Bullish CHOCH or not ...
|
|
*
|
|
* @param bar: XOHCL instance, Speciied Bar ...
|
|
* @param loopback: Integer, loopback Length ...
|
|
* @param forceBody: Boolean, Specified Choch Happens only by Bar's Body ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasBullishCHOCH(
|
|
XOHCL &bar,
|
|
int loopback = 2,
|
|
bool forceBody = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
ENUM_X_DIRECTION dir;
|
|
result = HasCHOCH(
|
|
dir,
|
|
bar,
|
|
loopback,
|
|
forceBody //
|
|
);
|
|
result =
|
|
result &&
|
|
dir == X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar Has Bearish CHOCH or not ...
|
|
*
|
|
* @param bar: XOHCL instance, Speciied Bar ...
|
|
* @param loopback: Integer, loopback Length ...
|
|
* @param forceBody: Boolean, Specified Choch Happens only by Bar's Body ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasBearishCHOCH(
|
|
XOHCL &bar,
|
|
int loopback = 2,
|
|
bool forceBody = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
ENUM_X_DIRECTION dir;
|
|
result = HasCHOCH(
|
|
dir,
|
|
bar,
|
|
loopback,
|
|
forceBody //
|
|
);
|
|
result =
|
|
result &&
|
|
dir == X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Directions ...
|
|
|
|
/**
|
|
* Check Specified Bar Possible Direction Pressure ...
|
|
*
|
|
* @param dir: ENUM_X_DIRECTION member ...
|
|
* @param bar: XOHCL instance, Specified Bar ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasDirection(
|
|
ENUM_X_DIRECTION &dir,
|
|
XOHCL &bar //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Bar isExtended or not ...
|
|
bool isExtended = IsExtended(
|
|
bar,
|
|
3 //
|
|
);
|
|
|
|
//
|
|
// Check Rejection ...
|
|
ENUM_X_DIRECTION rejectionDir;
|
|
bool isRejection = IsRejectionBar(rejectionDir, bar, 40);
|
|
bool isBullishRejection = isRejection &&
|
|
rejectionDir == X_DIRECTION_BULLISH;
|
|
bool isBearishRejection = isRejection &&
|
|
rejectionDir == X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
// Check Momentum ...
|
|
ENUM_X_DIRECTION momentumDir;
|
|
bool isMomentum = IsMomentumBar(momentumDir, bar, 40);
|
|
bool isBullisMomentumn = isMomentum &&
|
|
momentumDir == X_DIRECTION_BULLISH;
|
|
bool isBearishMomentum = isMomentum &&
|
|
momentumDir == X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
// Check Engulfing ...
|
|
ENUM_X_DIRECTION engulfDir;
|
|
bool isEngulfed = IsEngulfed(
|
|
engulfDir,
|
|
bar,
|
|
2 //
|
|
);
|
|
bool isBullishEngulfed = isEngulfed &&
|
|
engulfDir == X_DIRECTION_BULLISH;
|
|
bool isBearishEngulfed = isEngulfed &&
|
|
engulfDir == X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
// Check CHOCH ...
|
|
ENUM_X_DIRECTION chochDir;
|
|
bool hasCHOCH = HasCHOCH(
|
|
chochDir,
|
|
bar,
|
|
2,
|
|
false //
|
|
);
|
|
bool hasBullishCHOCH = hasCHOCH &&
|
|
chochDir == X_DIRECTION_BULLISH;
|
|
bool hasBearishCHOCH = hasCHOCH &&
|
|
chochDir == X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
bool hasBullishDirection =
|
|
//
|
|
isExtended &&
|
|
(hasBullishCHOCH ||
|
|
isBullishEngulfed) &&
|
|
(isBullisMomentumn ||
|
|
isBullishRejection)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool hasBearishDirection =
|
|
//
|
|
isExtended &&
|
|
(hasBearishCHOCH ||
|
|
isBearishEngulfed) &&
|
|
(isBearishMomentum ||
|
|
isBearishRejection)
|
|
//
|
|
;
|
|
|
|
//
|
|
result = hasBullishDirection ||
|
|
hasBearishDirection;
|
|
if (result)
|
|
{
|
|
//
|
|
dir = hasBullishDirection
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar has Possibly Bullish Direction ...
|
|
*
|
|
* @param bar: XOHCL instance, Specified Bar ...
|
|
*
|
|
* @return ( virtual bool )
|
|
*/
|
|
virtual bool HasBullishDirection(
|
|
XOHCL &bar //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
ENUM_X_DIRECTION dir;
|
|
result = HasDirection(dir, bar);
|
|
result =
|
|
result &&
|
|
dir == X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar has Possibly Bearish Direction ...
|
|
*
|
|
* @param bar: XOHCL instance, Specified Bar ...
|
|
*
|
|
* @return ( virtual bool )
|
|
*/
|
|
virtual bool HasBearishhDirection(
|
|
XOHCL &bar //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
ENUM_X_DIRECTION dir;
|
|
result = HasDirection(dir, bar);
|
|
result =
|
|
result &&
|
|
dir == X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
protected:
|
|
//
|
|
|
|
//
|
|
private:
|
|
//
|
|
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
// Actions ...
|
|
|
|
//
|
|
};
|
|
|
|
// |