last works on implementing Candlestick Patterns on Bar Analyser Class ...
This commit is contained in:
@@ -26,9 +26,6 @@
|
||||
//
|
||||
// Definitions ...
|
||||
|
||||
//
|
||||
#define X_PERCENTAGE_GOLDEN_MULTIPLIER 100000
|
||||
|
||||
//
|
||||
// Implementations ...
|
||||
class XCBarAnalyser : public XCBase
|
||||
@@ -423,7 +420,7 @@ class XCBarAnalyser : public XCBase
|
||||
for (int i = 0; i < uppersCount; i++)
|
||||
{
|
||||
//
|
||||
double iValue = uppers[i] - lowers[i];
|
||||
double iValue = lowers[i] + (uppers[i] - lowers[i]);
|
||||
|
||||
//
|
||||
Add(
|
||||
@@ -707,45 +704,48 @@ class XCBarAnalyser : public XCBase
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Actions ...
|
||||
|
||||
bool IsSpike(
|
||||
/**
|
||||
* Detect Big Price Change Happens or not ...
|
||||
*
|
||||
* @param bar: XOHCL instance reference, Start Bar ...
|
||||
* @param dir: ENUM_X_DIRECTION member, Event Direction ...
|
||||
* @param type: ENUM_X_PRICE member, Price Type ...
|
||||
* @param forcBodyInRange: bool, Use Body in Range Detection ...
|
||||
* @param rangeExtendMultiplier: double, a Multiplier for Checking Price Range ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool IsBigChange(
|
||||
XOHCL &bar,
|
||||
XOHCL &fromBar,
|
||||
XOHCL &toBar,
|
||||
ENUM_X_DIRECTION &dir,
|
||||
double minPriceChangePercent = 1.5,
|
||||
ENUM_X_PRICE type = X_PRICE_CLOSE,
|
||||
bool forcBodyInRange = true,
|
||||
double rangeExtendMultiplier = 2,
|
||||
int loopback = 14 //
|
||||
double rangeExtendMultiplier = 1.0 //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
toBar.Clean();
|
||||
fromBar.Clean();
|
||||
dir = X_DIRECTION_NONE;
|
||||
loopback = NormalizeInt(loopback, 1);
|
||||
rangeExtendMultiplier = NormalizeDouble(rangeExtendMultiplier, 1);
|
||||
minPriceChangePercent = NormalizeDouble(minPriceChangePercent, 1.5);
|
||||
|
||||
//
|
||||
int periodSeconds = PeriodSeconds(bar.period);
|
||||
double divider = X_PERCENTAGE_GOLDEN_MULTIPLIER;
|
||||
double periodMult = (periodSeconds / PeriodSeconds(PERIOD_M5)) * 0.2;
|
||||
minPriceChangePercent /= (divider / periodMult);
|
||||
|
||||
//
|
||||
result = bar.IsValid();
|
||||
result =
|
||||
bar.IsValid() &&
|
||||
IsValid(type);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
double minPriceChangePercent = 0;
|
||||
int loopback = GetPeriodSharpData(
|
||||
minPriceChangePercent,
|
||||
bar.period //
|
||||
);
|
||||
|
||||
//
|
||||
double ranges[];
|
||||
int rangesCount = GetPriceRange(
|
||||
@@ -765,6 +765,7 @@ class XCBarAnalyser : public XCBase
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate Ranges ...
|
||||
double rangeMax = GetMax(ranges);
|
||||
double rangeMin = GetMin(ranges);
|
||||
double rangeAverage = GetAverage(ranges);
|
||||
@@ -775,29 +776,54 @@ class XCBarAnalyser : public XCBase
|
||||
);
|
||||
|
||||
//
|
||||
static double maxPriceChange = 0;
|
||||
static double minPriceChange = 0;
|
||||
if (maxPriceChange == 0 || maxPriceChange < priceChangePercent)
|
||||
// Calculate HH and LL ...
|
||||
double hh = 0;
|
||||
double ll = 0;
|
||||
int hhIDX = -1;
|
||||
int llIDX = -1;
|
||||
result = CalculateLoopbackHLData(
|
||||
hhIDX,
|
||||
hh,
|
||||
llIDX,
|
||||
ll,
|
||||
bar,
|
||||
loopback //
|
||||
);
|
||||
result =
|
||||
result &&
|
||||
ll > 0 &&
|
||||
hh > ll &&
|
||||
IsValidIndex(llIDX) &&
|
||||
IsValidIndex(hhIDX);
|
||||
if (!result)
|
||||
{
|
||||
maxPriceChange = priceChangePercent;
|
||||
}
|
||||
if (minPriceChange == 0 || minPriceChange > priceChangePercent)
|
||||
{
|
||||
minPriceChange = priceChangePercent;
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
int hhDiff = (hhIDX - bar.Index());
|
||||
int llDiff = (llIDX - bar.Index());
|
||||
|
||||
//
|
||||
bool isBullish =
|
||||
//
|
||||
hhDiff <= 1 &&
|
||||
llIDX > hhIDX &&
|
||||
bar.close >= hh &&
|
||||
priceChangePercent > 0 &&
|
||||
priceChangePercent >= minPriceChangePercent
|
||||
priceChangePercent >= minPriceChangePercent &&
|
||||
bar.high > (rangeAverage * rangeExtendMultiplier)
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
bool isBearish =
|
||||
//
|
||||
llDiff <= 1 &&
|
||||
hhIDX > llIDX &&
|
||||
bar.close <= ll &&
|
||||
priceChangePercent < 0 &&
|
||||
bar.low < (rangeAverage * rangeExtendMultiplier) &&
|
||||
MathAbs(priceChangePercent) >= minPriceChangePercent
|
||||
//
|
||||
;
|
||||
@@ -823,6 +849,504 @@ class XCBarAnalyser : public XCBase
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Actions ...
|
||||
|
||||
/**
|
||||
* Detect Spike ...
|
||||
*
|
||||
* @param bar: XOHCL instance reference, Start Bar ...
|
||||
* @param dir: ENUM_X_DIRECTION member, Event Direction ...
|
||||
* @param type: ENUM_X_PRICE member, Price Type ...
|
||||
* @param forcBodyInRange: bool, Use Body in Range Detection ...
|
||||
* @param rangeExtendMultiplier: double, a Multiplier for Checking Price Range ...
|
||||
* @param sameBars: int, Specified How Many Same Bars Required for an Spike ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool IsSpike(
|
||||
XOHCL &bar,
|
||||
ENUM_X_DIRECTION &dir,
|
||||
ENUM_X_PRICE type = X_PRICE_CLOSE,
|
||||
bool forcBodyInRange = true,
|
||||
double rangeExtendMultiplier = 1.0,
|
||||
int sameBars = 3 //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
dir = X_DIRECTION_NONE;
|
||||
sameBars = NormalizeInt(sameBars, 2);
|
||||
|
||||
//
|
||||
result = IsValid(type) &&
|
||||
bar.IsValid();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// First We Have to Has a Big Change ...
|
||||
result = IsBigChange(
|
||||
bar,
|
||||
dir,
|
||||
type,
|
||||
forcBodyInRange,
|
||||
rangeExtendMultiplier //
|
||||
);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Check Has Same Bars ...
|
||||
int sameBarsIndex = -1;
|
||||
ENUM_X_DIRECTION sameBarsDir;
|
||||
result = HasSameBars(
|
||||
bar,
|
||||
sameBarsDir,
|
||||
sameBarsIndex,
|
||||
sameBars //
|
||||
);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Check Same Bars Direction sames To Price Change ...
|
||||
result = sameBarsDir == dir;
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Candlestick ...
|
||||
|
||||
/**
|
||||
* Check Specified Bar is Doji Pattern or not ...
|
||||
*
|
||||
* @param bar: XOHCL instance reference, Specified Bar to Check ...
|
||||
* @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ...
|
||||
* @param shadowMultiplier: double, Specified Shadow Multiplier ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool IsDoji(
|
||||
XOHCL &bar,
|
||||
ENUM_X_DIRECTION &dir,
|
||||
double shadowMultiplier = 1.5 //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
dir = X_DIRECTION_NONE;
|
||||
shadowMultiplier = NormalizeDouble(shadowMultiplier, 1.5, 3);
|
||||
|
||||
//
|
||||
result = bar.IsValid();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
double body = bar.GetBody();
|
||||
double range = bar.GetRange();
|
||||
|
||||
//
|
||||
result =
|
||||
body > 0 &&
|
||||
range > 0
|
||||
? (body / range < 0.1)
|
||||
: false;
|
||||
if (result)
|
||||
{
|
||||
//
|
||||
dir =
|
||||
bar.GetLowShadow() >= (bar.GetHighShadow() * shadowMultiplier)
|
||||
? X_DIRECTION_BULLISH
|
||||
: bar.GetHighShadow() >= (bar.GetLowShadow() * shadowMultiplier)
|
||||
? X_DIRECTION_BEARISH
|
||||
: X_DIRECTION_NONE;
|
||||
//
|
||||
result = HasDirection(dir);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Specified Bar is Hammer Pattern or not ...
|
||||
*
|
||||
* @param bar: XOHCL instance reference, Specified Bar to Check ...
|
||||
* @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ...
|
||||
* @param bodyMultiplier: double, Specified Body Multiplier ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool IsHammer(
|
||||
XOHCL &bar,
|
||||
ENUM_X_DIRECTION &dir,
|
||||
double bodyMultiplier = 2.0 //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
dir = X_DIRECTION_NONE;
|
||||
bodyMultiplier = NormalizeDouble(bodyMultiplier, 1.5, 3);
|
||||
|
||||
//
|
||||
result = bar.IsValid();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
double body = bar.GetBody();
|
||||
double lShadow = bar.GetLowShadow();
|
||||
double hShadow = bar.GetHighShadow();
|
||||
|
||||
//
|
||||
bool isBullish =
|
||||
hShadow < body &&
|
||||
lShadow > (bodyMultiplier * body);
|
||||
|
||||
//
|
||||
bool isBearish =
|
||||
lShadow < body &&
|
||||
hShadow > (bodyMultiplier * body);
|
||||
|
||||
//
|
||||
result = isBullish ||
|
||||
isBearish;
|
||||
if (result)
|
||||
{
|
||||
//
|
||||
dir =
|
||||
isBullish
|
||||
? X_DIRECTION_BULLISH
|
||||
: X_DIRECTION_BEARISH;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Specified Bar is Engulfed Prev Bar or not ...
|
||||
*
|
||||
* @param bar: XOHCL instance reference, Specified Bar to Check ...
|
||||
* @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool IsEngulfed(
|
||||
XOHCL &bar,
|
||||
ENUM_X_DIRECTION &dir //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
dir = X_DIRECTION_NONE;
|
||||
|
||||
//
|
||||
result = bar.IsValid();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
XOHCL pBar;
|
||||
result = bar.GetPreviousBar(pBar);
|
||||
if (!result)
|
||||
{
|
||||
//
|
||||
pBar.Clean();
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result = bar.GetBody() > pBar.GetBody();
|
||||
if (!result)
|
||||
{
|
||||
//
|
||||
pBar.Clean();
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
bool isBullish =
|
||||
bar.IsBullish() &&
|
||||
pBar.IsBearish() &&
|
||||
bar.GetDown() <= pBar.GetDown() &&
|
||||
bar.GetUp() > pBar.GetUp();
|
||||
|
||||
//
|
||||
bool isBearish =
|
||||
bar.IsBearish() &&
|
||||
pBar.IsBullish() &&
|
||||
bar.GetUp() >= pBar.GetUp() &&
|
||||
bar.GetDown() < pBar.GetDown();
|
||||
|
||||
//
|
||||
result = isBullish ||
|
||||
isBearish;
|
||||
if (result)
|
||||
{
|
||||
//
|
||||
dir =
|
||||
isBullish
|
||||
? X_DIRECTION_BULLISH
|
||||
: X_DIRECTION_BEARISH;
|
||||
}
|
||||
|
||||
//
|
||||
// Cleanup Resources ...
|
||||
|
||||
//
|
||||
pBar.Clean();
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Specified Bar is Momentum Bar or not ...
|
||||
*
|
||||
* @param bar: XOHCL instance reference, Specified Bar to Check ...
|
||||
* @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ...
|
||||
* @param loopback: int, Specified Loopback ...
|
||||
* @param rangeExtendMultiplier: double, a Multiplier for Checking Price Range ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool IsMomentum(
|
||||
XOHCL &bar,
|
||||
ENUM_X_DIRECTION &dir,
|
||||
int loopback = 2,
|
||||
double rangeExtendMultiplier = 1.5 //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
dir = X_DIRECTION_NONE;
|
||||
loopback = NormalizeInt(loopback, 1);
|
||||
rangeExtendMultiplier = NormalizeDouble(rangeExtendMultiplier, 1);
|
||||
|
||||
//
|
||||
result = bar.IsValid();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Check Bar Must Engulfed ...
|
||||
result = IsEngulfed(
|
||||
bar,
|
||||
dir //
|
||||
);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate HH and LL ...
|
||||
double hh = 0;
|
||||
double ll = 0;
|
||||
int hhIDX = -1;
|
||||
int llIDX = -1;
|
||||
result = CalculateLoopbackHLData(
|
||||
hhIDX,
|
||||
hh,
|
||||
llIDX,
|
||||
ll,
|
||||
bar,
|
||||
loopback //
|
||||
);
|
||||
result =
|
||||
result &&
|
||||
ll > 0 &&
|
||||
hh > ll &&
|
||||
IsValidIndex(llIDX) &&
|
||||
IsValidIndex(hhIDX);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
bool isBullish =
|
||||
bar.low > ll &&
|
||||
IsBullish(dir) &&
|
||||
bar.close >= hh;
|
||||
|
||||
//
|
||||
bool isBearish =
|
||||
bar.high < hh &&
|
||||
IsBearish(dir) &&
|
||||
bar.close <= ll;
|
||||
|
||||
//
|
||||
result = isBullish ||
|
||||
isBearish;
|
||||
if (result)
|
||||
{
|
||||
//
|
||||
dir =
|
||||
isBullish
|
||||
? X_DIRECTION_BULLISH
|
||||
: X_DIRECTION_BEARISH;
|
||||
}
|
||||
|
||||
//
|
||||
// Cleanup Resources ...
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Specified Bar is Pullback or not ...
|
||||
*
|
||||
* @param bar: XOHCL instance reference, Specified Bar to Check ...
|
||||
* @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ...
|
||||
* @param loopback: int, Specified Loopback ...
|
||||
* @param forceBody: bool, Force Using Body ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool IsPullback(
|
||||
XOHCL &bar,
|
||||
ENUM_X_DIRECTION &dir,
|
||||
int loopback = 3,
|
||||
bool forceBody = false //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
dir = X_DIRECTION_NONE;
|
||||
loopback = NormalizeInt(loopback, 3);
|
||||
|
||||
//
|
||||
result = bar.IsValid();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Check Bar Must Engulfed ...
|
||||
result = IsEngulfed(
|
||||
bar,
|
||||
dir //
|
||||
);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate HH and LL ...
|
||||
double hh = 0;
|
||||
double ll = 0;
|
||||
int hhIDX = -1;
|
||||
int llIDX = -1;
|
||||
result = CalculateLoopbackHLData(
|
||||
hhIDX,
|
||||
hh,
|
||||
llIDX,
|
||||
ll,
|
||||
bar,
|
||||
loopback //
|
||||
);
|
||||
result =
|
||||
result &&
|
||||
ll > 0 &&
|
||||
hh > ll &&
|
||||
IsValidIndex(llIDX) &&
|
||||
IsValidIndex(hhIDX);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
bool isBullish =
|
||||
bar.high > hh &&
|
||||
bar.low > ll;
|
||||
|
||||
//
|
||||
bool isBearish =
|
||||
bar.high < hh &&
|
||||
bar.low < ll;
|
||||
|
||||
//
|
||||
result = isBullish ||
|
||||
isBearish;
|
||||
if (result)
|
||||
{
|
||||
//
|
||||
if (forceBody)
|
||||
{
|
||||
//
|
||||
isBullish =
|
||||
isBullish &&
|
||||
bar.GetUp() > hh &&
|
||||
bar.GetDown() > ll &&
|
||||
llIDX == bar.Index() + 1;
|
||||
|
||||
//
|
||||
isBearish =
|
||||
isBearish &&
|
||||
bar.GetUp() < hh &&
|
||||
bar.GetDown() < ll &&
|
||||
hhIDX == bar.Index() + 1;
|
||||
|
||||
//
|
||||
result = isBullish ||
|
||||
isBearish;
|
||||
}
|
||||
|
||||
//
|
||||
if (result)
|
||||
{
|
||||
//
|
||||
dir =
|
||||
isBullish
|
||||
? X_DIRECTION_BULLISH
|
||||
: X_DIRECTION_BEARISH;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
protected:
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user