5210 lines
104 KiB
Plaintext
5210 lines
104 KiB
Plaintext
/**
|
|
* Detect Price Consolidation ...
|
|
*
|
|
* @param bar: XOHCL instance Reference, Start Bar ...
|
|
* @param loopback: Integer, Consolidation Length Finder ...
|
|
* @param consolidationRange: Integer, Consolidation Range Finder ...
|
|
* @param upper: Double Reference ...
|
|
* @param lower: Double Reference ...
|
|
* @param upperAppliedTo: ENUM_APPLIED_PRICE member, Upper Price ...
|
|
* @param lowerAppliedTo: ENUM_APPLIED_PRICE member, Lower Price ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsConsolidate(
|
|
XOHCL &bar,
|
|
double &upper,
|
|
double &lower,
|
|
int loopback = 30,
|
|
int consolidationRange = 50,
|
|
ENUM_APPLIED_PRICE upperAppliedTo = PRICE_HIGH,
|
|
ENUM_APPLIED_PRICE lowerAppliedTo = PRICE_LOW //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
upper = 0;
|
|
lower = 0;
|
|
|
|
//
|
|
if (loopback < 7)
|
|
{
|
|
loopback = 7;
|
|
}
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double points = GetPoints(bar.symbol);
|
|
int index = bar.Index();
|
|
|
|
//
|
|
double upperPrice[];
|
|
int upperPriceCount = FillPrice(
|
|
upperPrice,
|
|
upperAppliedTo,
|
|
bar.symbol,
|
|
bar.period,
|
|
index,
|
|
loopback //
|
|
);
|
|
|
|
//
|
|
double lowerPrice[];
|
|
int lowerPriceCount = FillPrice(
|
|
lowerPrice,
|
|
lowerAppliedTo,
|
|
bar.symbol,
|
|
bar.period,
|
|
index,
|
|
loopback //
|
|
);
|
|
|
|
//
|
|
result = upperPriceCount == lowerPriceCount &&
|
|
lowerPriceCount == loopback;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
upper = upperPrice[ArrayMaximum(upperPrice)];
|
|
lower = lowerPrice[ArrayMinimum(lowerPrice)];
|
|
|
|
//
|
|
double range = upper - lower;
|
|
result = range <= consolidationRange * points;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool HasConsolidationZone(
|
|
XOHCL &bar,
|
|
XConsolidationZone &zone,
|
|
int minLoopback = 3,
|
|
double range = 50,
|
|
ENUM_APPLIED_PRICE upperAppliedTo = PRICE_HIGH,
|
|
ENUM_APPLIED_PRICE lowerAppliedTo = PRICE_LOW //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
zone.Clean();
|
|
|
|
//
|
|
result = bar.IsValid() &&
|
|
minLoopback > 0 &&
|
|
range > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double points = GetPoints(bar.symbol);
|
|
int index = bar.Index() + 1;
|
|
int length = minLoopback;
|
|
|
|
//
|
|
double upperPrice[];
|
|
int upperPriceCount = FillPrice(
|
|
upperPrice,
|
|
upperAppliedTo,
|
|
bar.symbol,
|
|
bar.period,
|
|
index,
|
|
length //
|
|
);
|
|
|
|
//
|
|
double lowerPrice[];
|
|
int lowerPriceCount = FillPrice(
|
|
lowerPrice,
|
|
lowerAppliedTo,
|
|
bar.symbol,
|
|
bar.period,
|
|
index,
|
|
length //
|
|
);
|
|
|
|
//
|
|
result = upperPriceCount == lowerPriceCount &&
|
|
lowerPriceCount == length;
|
|
if (!result)
|
|
{
|
|
//
|
|
Clean(upperPrice);
|
|
Clean(lowerPrice);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double upper = upperPrice[ArrayMaximum(upperPrice)];
|
|
double lower = lowerPrice[ArrayMinimum(lowerPrice)];
|
|
|
|
//
|
|
bool isBullishBreake =
|
|
bar.low > lower &&
|
|
bar.high > upper &&
|
|
bar.GetUp() > upper;
|
|
bool isBearishBreake =
|
|
bar.high < upper &&
|
|
bar.low < lower &&
|
|
bar.GetDown() < lower;
|
|
result = isBullishBreake ||
|
|
isBearishBreake;
|
|
if (!result)
|
|
{
|
|
//
|
|
Clean(upperPrice);
|
|
Clean(lowerPrice);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double delta = upper - lower;
|
|
result = delta <= range * points;
|
|
if (!result)
|
|
{
|
|
//
|
|
Clean(upperPrice);
|
|
Clean(lowerPrice);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
while (delta <= range * points)
|
|
{
|
|
//
|
|
length++;
|
|
|
|
//
|
|
upperPriceCount = FillPrice(
|
|
upperPrice,
|
|
upperAppliedTo,
|
|
bar.symbol,
|
|
bar.period,
|
|
index,
|
|
length //
|
|
);
|
|
|
|
//
|
|
lowerPriceCount = FillPrice(
|
|
lowerPrice,
|
|
lowerAppliedTo,
|
|
bar.symbol,
|
|
bar.period,
|
|
index,
|
|
length //
|
|
);
|
|
|
|
//
|
|
bool isValid = upperPriceCount == lowerPriceCount &&
|
|
lowerPriceCount == length;
|
|
if (!isValid)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
double iUpper = upperPrice[ArrayMaximum(upperPrice)];
|
|
double iLower = lowerPrice[ArrayMinimum(lowerPrice)];
|
|
|
|
//
|
|
delta = iUpper - iLower;
|
|
if (delta <= range * points)
|
|
{
|
|
//
|
|
upper = iUpper;
|
|
lower = iLower;
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(upperPrice);
|
|
Clean(lowerPrice);
|
|
|
|
//
|
|
// Filling Zone ...
|
|
zone.upper = upper;
|
|
zone.lower = lower;
|
|
zone.symbol = bar.symbol;
|
|
zone.period = bar.period;
|
|
zone.to = iTime(
|
|
bar.symbol,
|
|
bar.period,
|
|
bar.Index() + 1 //
|
|
);
|
|
zone.from = iTime(
|
|
bar.symbol,
|
|
bar.period,
|
|
bar.Index() + length //
|
|
);
|
|
zone.dir = isBullishBreake
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = zone.IsValid();
|
|
if (!result)
|
|
{
|
|
zone.Clean();
|
|
}
|
|
|
|
//
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar is Swing High or not ...
|
|
*
|
|
* @param bar: XOHCL instnce ...
|
|
* @param range: Integer, Specified Range ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsSwingHigh(
|
|
XOHCL &bar,
|
|
int range = 2 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (range < 1)
|
|
{
|
|
range = 1;
|
|
}
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int index = bar.Index();
|
|
result = range > 0 &&
|
|
index >= range;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string symbol = bar.symbol;
|
|
ENUM_TIMEFRAMES period = bar.period;
|
|
|
|
//
|
|
for (int i = 1; i <= range; i++)
|
|
{
|
|
//
|
|
// Prev Bar ...
|
|
XOHCL iPrevBar;
|
|
result = iPrevBar.Init(
|
|
symbol,
|
|
period,
|
|
index + i //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Next Bar ...
|
|
XOHCL iNextBar;
|
|
result = iNextBar.Init(
|
|
symbol,
|
|
period,
|
|
index - i //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
result = bar.high >= iPrevBar.high &&
|
|
bar.high >= iNextBar.high;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar is Swing Low or not ...
|
|
*
|
|
* @param bar: XOHCL instnce ...
|
|
* @param range: Integer, Specified Range ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsSwingLow(
|
|
XOHCL &bar,
|
|
int range = 2 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (range < 1)
|
|
{
|
|
range = 1;
|
|
}
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int index = bar.Index();
|
|
result = range > 0 &&
|
|
index >= range;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string symbol = bar.symbol;
|
|
ENUM_TIMEFRAMES period = bar.period;
|
|
|
|
//
|
|
for (int i = 1; i <= range; i++)
|
|
{
|
|
//
|
|
// Prev Bar ...
|
|
XOHCL iPrevBar;
|
|
result = iPrevBar.Init(
|
|
symbol,
|
|
period,
|
|
index + i //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Next Bar ...
|
|
XOHCL iNextBar;
|
|
result = iNextBar.Init(
|
|
symbol,
|
|
period,
|
|
index - i //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
result = bar.low <= iPrevBar.low &&
|
|
bar.low <= iNextBar.low;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar is Swing or not ...
|
|
*
|
|
* @param bar: XOHCL instnce ...
|
|
* @param dir: ENUM_X_DIRECTION member ...
|
|
* @param range: Integer, Specified Range ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsSwing(
|
|
XOHCL &bar,
|
|
ENUM_X_DIRECTION &dir,
|
|
int range = 2 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
bool isSwingLow = IsSwingLow(bar, range);
|
|
bool isSwingHigh = IsSwingHigh(bar, range);
|
|
|
|
//
|
|
result = isSwingLow ||
|
|
isSwingHigh;
|
|
if (result)
|
|
{
|
|
//
|
|
if (isSwingLow)
|
|
{
|
|
dir = X_DIRECTION_BULLISH;
|
|
}
|
|
else
|
|
{
|
|
dir = X_DIRECTION_BEARISH;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Bar is Momentum Bar or not ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param dir: ENUM_X_DIRECTION member ...
|
|
* @param extend: Integer ...
|
|
* @param bodyPercent: Double ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsMomentumBar(
|
|
XOHCL &bar,
|
|
ENUM_X_DIRECTION &dir,
|
|
int extend = 1,
|
|
double bodyPercent = 70 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (extend < 0)
|
|
{
|
|
extend = 0;
|
|
}
|
|
|
|
//
|
|
if (bodyPercent < 50)
|
|
{
|
|
bodyPercent = 50;
|
|
}
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = bar.IsValid() &&
|
|
bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (extend > 0)
|
|
{
|
|
//
|
|
result = IsExtended(
|
|
bar,
|
|
extend //
|
|
);
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
double body = bar.GetBody();
|
|
double rp = GetBarRangePercent(bar);
|
|
|
|
//
|
|
result = body >= rp * bodyPercent;
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
dir =
|
|
bar.IsBullish()
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Bar is Rejection Bar or not ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param dir: ENUM_X_DIRECTION member ...
|
|
* @param extend: Integer ...
|
|
* @param shadowPercent: Double ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsRejectionBar(
|
|
XOHCL &bar,
|
|
ENUM_X_DIRECTION &dir,
|
|
int extend = 1,
|
|
double shadowPercent = 60 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (extend < 0)
|
|
{
|
|
extend = 0;
|
|
}
|
|
|
|
//
|
|
if (shadowPercent < 50)
|
|
{
|
|
shadowPercent = 50;
|
|
}
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = bar.IsValid() &&
|
|
bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (extend > 0)
|
|
{
|
|
//
|
|
result = IsExtended(
|
|
bar,
|
|
extend //
|
|
);
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
double body = bar.GetBody();
|
|
double range = bar.GetRange();
|
|
double shadows = bar.GetShadows();
|
|
double lowShadow = bar.GetLowShadow();
|
|
double highShadow = bar.GetHighShadow();
|
|
double rp = GetBarRangePercent(bar);
|
|
|
|
//
|
|
result = shadows >= rp * shadowPercent;
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
dir =
|
|
lowShadow > highShadow
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar is Engulfing Bar or not ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param dir: ENUM_X_DIRECTION member ...
|
|
* @param extend: Integer ...
|
|
* @param bodyPercent: Double ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsEngulfBar(
|
|
XOHCL &bar,
|
|
ENUM_X_DIRECTION &dir,
|
|
int extend = 1,
|
|
double bodyPercent = 60 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (extend < 0)
|
|
{
|
|
extend = 0;
|
|
}
|
|
|
|
//
|
|
if (bodyPercent < 50)
|
|
{
|
|
bodyPercent = 50;
|
|
}
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = bar.IsValid() &&
|
|
bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Previous Bar ...
|
|
XOHCL pBar;
|
|
result = bar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (extend > 0)
|
|
{
|
|
//
|
|
result = IsExtended(
|
|
pBar,
|
|
extend //
|
|
);
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Engulfig ...
|
|
result =
|
|
bar.GetUp() > pBar.GetUp() &&
|
|
bar.GetDown() < pBar.GetDown();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Engulfing Direction ...
|
|
bool isBullishEngulfed =
|
|
pBar.IsBearish() &&
|
|
bar.IsBullish();
|
|
bool isBearishEngulfed =
|
|
pBar.IsBullish() &&
|
|
bar.IsBearish();
|
|
|
|
//
|
|
result = isBullishEngulfed ||
|
|
isBearishEngulfed;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
dir = isBullishEngulfed
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar is Pin Bar or not ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param dir: ENUM_X_DIRECTION member ...
|
|
* @param extend: Integer ...
|
|
* @param shadowPercent: Double ...
|
|
* @param bodyPercent: Double ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsPinBar(
|
|
XOHCL &bar,
|
|
ENUM_X_DIRECTION &dir,
|
|
int extend = 1,
|
|
double shadowPercent = 65,
|
|
double bodyPercent = 25 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = bar.IsValid() &&
|
|
bar.Index() > 0 &&
|
|
bodyPercent > 0 &&
|
|
shadowPercent > 0 &&
|
|
bodyPercent < shadowPercent;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Chack Range Extends ...
|
|
if (extend > 0)
|
|
{
|
|
//
|
|
result = HasExtendedRange(
|
|
bar,
|
|
extend //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Body ...
|
|
double rangePercent = GetBarRangePercent(bar);
|
|
result = rangePercent > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double body = bar.GetBody();
|
|
double highShadow = bar.GetHighShadow();
|
|
double lowShadow = bar.GetLowShadow();
|
|
|
|
//
|
|
// Check Body ...
|
|
result = body / rangePercent >= bodyPercent;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isPassedHighShadow =
|
|
highShadow / rangePercent >= shadowPercent;
|
|
bool isPassedLowShadow =
|
|
lowShadow / rangePercent >= shadowPercent;
|
|
result =
|
|
isPassedLowShadow ||
|
|
isPassedHighShadow;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
dir = isPassedLowShadow
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Decision Bar (Pin, Momentum or Rejection) ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param dir: ENUM_X_DIRECTION member ...
|
|
* @param extend: Integer ...
|
|
* @param shadowForPinAndRejectionBarPercent: Double ...
|
|
* @param bodyForPinBarPercent: Double ...
|
|
* @param bodyForEngulfBarPercent: Double ...
|
|
* @param bodyForMomentumBarPercent: Double ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsDecisionBar(
|
|
XOHCL &bar,
|
|
ENUM_X_DIRECTION &dir,
|
|
int extend = 1,
|
|
double shadowForPinAndRejectionBarPercent = 65,
|
|
double bodyForPinBarPercent = 25,
|
|
double bodyForEngulfBarPercent = 65,
|
|
double bodyForMomentumBarPercent = 70 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = bar.IsValid() &&
|
|
bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Pin Bar ...
|
|
ENUM_X_DIRECTION pinDir;
|
|
bool isPiBar = IsPinBar(
|
|
bar,
|
|
pinDir,
|
|
extend,
|
|
shadowForPinAndRejectionBarPercent,
|
|
bodyForPinBarPercent //
|
|
);
|
|
|
|
//
|
|
// Engulfing Bar ...
|
|
ENUM_X_DIRECTION engulfDir;
|
|
bool isEngulfBar = IsEngulfBar(
|
|
bar,
|
|
engulfDir,
|
|
extend,
|
|
bodyForEngulfBarPercent //
|
|
);
|
|
|
|
//
|
|
// Momentum Bar ...
|
|
ENUM_X_DIRECTION momentumDir;
|
|
bool isMomentumBar = IsMomentumBar(
|
|
bar,
|
|
momentumDir,
|
|
extend,
|
|
bodyForMomentumBarPercent //
|
|
);
|
|
|
|
//
|
|
// Rejection Bar ...
|
|
ENUM_X_DIRECTION rejectionDir;
|
|
bool isRejectionBar = IsRejectionBar(
|
|
bar,
|
|
rejectionDir,
|
|
extend,
|
|
shadowForPinAndRejectionBarPercent //
|
|
);
|
|
|
|
//
|
|
result = isPiBar ||
|
|
isEngulfBar ||
|
|
isMomentumBar ||
|
|
isRejectionBar;
|
|
if (result)
|
|
{
|
|
//
|
|
if (isPiBar)
|
|
{
|
|
dir = pinDir;
|
|
}
|
|
else if (isEngulfBar)
|
|
{
|
|
dir = engulfDir;
|
|
}
|
|
else if (isMomentumBar)
|
|
{
|
|
dir = momentumDir;
|
|
}
|
|
else
|
|
{
|
|
dir = rejectionDir;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsBullish(dir) ||
|
|
IsBearish(dir);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
|
|
//
|
|
// Support and Resistance Zones ...
|
|
|
|
/**
|
|
* Check a Bar is Support Bar or not ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param range: Integer, Specified Verifiation Range ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsSupport(
|
|
XOHCL &bar,
|
|
int range = 21 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (range < 2)
|
|
{
|
|
range = 2;
|
|
}
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int index = bar.Index();
|
|
result = range > 0 &&
|
|
index >= range;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string symbol = bar.symbol;
|
|
ENUM_TIMEFRAMES period = bar.period;
|
|
|
|
//
|
|
for (int i = 1; i <= range; i++)
|
|
{
|
|
//
|
|
int prevIDX = index + i;
|
|
int nextIDX = index - 1;
|
|
|
|
//
|
|
// Prev Bar ...
|
|
XOHCL iPrevBar;
|
|
result = iPrevBar.Init(
|
|
symbol,
|
|
period,
|
|
prevIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Next Bar ...
|
|
XOHCL iNextBar;
|
|
result = iNextBar.Init(
|
|
symbol,
|
|
period,
|
|
nextIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
result = bar.low <= iPrevBar.low &&
|
|
bar.low <= iNextBar.low;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Bar Has Support or not ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param supportBar: XOHCL instance Specified Support Bar ...
|
|
* @param rage: int,
|
|
* @return ( bool )
|
|
*/
|
|
bool HasSupport(
|
|
XOHCL &bar,
|
|
XOHCL &supportBar,
|
|
int range = 21 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int barIndex = bar.Index() + range;
|
|
result = IsValidIndex(barIndex);
|
|
if (!result)
|
|
{
|
|
//
|
|
supportBar.Clean();
|
|
return result;
|
|
}
|
|
result = supportBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
result = supportBar.low < supportBar.GetDown();
|
|
if (!result)
|
|
{
|
|
//
|
|
supportBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double selectedValue = supportBar.GetDown();
|
|
|
|
//
|
|
int llIDX = bar.FindLowestIndex(range - 1, MODE_LOW);
|
|
result = IsValidIndex(llIDX);
|
|
if (!result)
|
|
{
|
|
//
|
|
supportBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double llValue = iLow(
|
|
bar.symbol,
|
|
bar.period,
|
|
llIDX //
|
|
);
|
|
|
|
//
|
|
result = llValue >= selectedValue;
|
|
if (!result)
|
|
{
|
|
//
|
|
supportBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = supportBar.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Bar is Resistance Bar or not ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param range: Integer, Specified Verifiation Range ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsResistance(
|
|
XOHCL &bar,
|
|
int range = 21 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (range < 2)
|
|
{
|
|
range = 2;
|
|
}
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int index = bar.Index();
|
|
result = range > 0 &&
|
|
index >= range;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string symbol = bar.symbol;
|
|
ENUM_TIMEFRAMES period = bar.period;
|
|
|
|
//
|
|
for (int i = 1; i <= range; i++)
|
|
{
|
|
//
|
|
int prevIDX = index + i;
|
|
int nextIDX = index - 1;
|
|
|
|
//
|
|
// Prev Bar ...
|
|
XOHCL iPrevBar;
|
|
result = iPrevBar.Init(
|
|
symbol,
|
|
period,
|
|
prevIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Next Bar ...
|
|
XOHCL iNextBar;
|
|
result = iNextBar.Init(
|
|
symbol,
|
|
period,
|
|
nextIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
result = bar.high >= iPrevBar.high &&
|
|
bar.high >= iNextBar.high;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Bar Has Resistance or not ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param resistanceBar: XOHCL instance Specified Resistance Bar ...
|
|
* @param rage: int,
|
|
* @return ( bool )
|
|
*/
|
|
bool HasResistance(
|
|
XOHCL &bar,
|
|
XOHCL &resistanceBar,
|
|
int range = 21 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int barIndex = bar.Index() + range;
|
|
result = IsValidIndex(barIndex);
|
|
if (!result)
|
|
{
|
|
//
|
|
resistanceBar.Clean();
|
|
return result;
|
|
}
|
|
result = resistanceBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
result = resistanceBar.low < resistanceBar.GetDown();
|
|
if (!result)
|
|
{
|
|
//
|
|
resistanceBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double selectedValue = resistanceBar.GetUp();
|
|
|
|
//
|
|
int hhIDX = bar.FindHighestIndex(range - 1, MODE_HIGH);
|
|
result = IsValidIndex(hhIDX);
|
|
if (!result)
|
|
{
|
|
//
|
|
resistanceBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double hhValue = iHigh(
|
|
bar.symbol,
|
|
bar.period,
|
|
hhIDX //
|
|
);
|
|
|
|
//
|
|
result = hhValue >= selectedValue;
|
|
if (!result)
|
|
{
|
|
//
|
|
resistanceBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = resistanceBar.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Order Blocks ...
|
|
|
|
/**
|
|
* Detect an Order Block Based on Given Bar ...
|
|
*
|
|
* @param bar: XOHCL instance, Specified Start Bar ...
|
|
* @param ob: XOHCL instance, Fill it if Order Block Found ...
|
|
* @param dir: ENUM_X_DIRECTION member, Specified Founded Order Block Direction ...
|
|
* @param sameBars: Integer, Specified Min Same Bars for Detecting Order Block ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasOrderBlock(
|
|
XOHCL &bar,
|
|
XOHCL &ob,
|
|
ENUM_X_DIRECTION &dir,
|
|
int sameBars = 3 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
ob.Clean();
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
if (sameBars < 1)
|
|
{
|
|
sameBars = 1;
|
|
}
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int index = 0;
|
|
result = HasSameBars(
|
|
bar,
|
|
dir,
|
|
index,
|
|
sameBars //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int obIndex = index + 1;
|
|
result = ob.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
obIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Fair Value Gaps ...
|
|
|
|
/**
|
|
* Detect a Fair Value Gap Based on Given Bar ...
|
|
*
|
|
* @param bar: XOHCL instance, Specified Start Bar ...
|
|
* @param dir: ENUM_X_DIRECTION member, Specified Founded Order Block Direction ...
|
|
* @param sameBars: Integer, Specified Min Same Bars for Detecting Order Block ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasFairValueGap(
|
|
XOHCL &bar,
|
|
XOHCL &prevBar,
|
|
XOHCL &nextBar,
|
|
ENUM_X_DIRECTION &dir,
|
|
int sameBars = 3 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
prevBar.Clean();
|
|
nextBar.Clean();
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
if (sameBars < 1)
|
|
{
|
|
sameBars = 1;
|
|
}
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int index = 0;
|
|
result = HasSameBars(
|
|
bar,
|
|
dir,
|
|
index,
|
|
sameBars //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(dir);
|
|
|
|
//
|
|
int to = bar.Index();
|
|
int from =
|
|
index > (to + sameBars)
|
|
? to + sameBars
|
|
: index;
|
|
for (int i = from; i > to; i--)
|
|
{
|
|
//
|
|
result = prevBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
i //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
result = nextBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
i - 2 //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
result = isBullish
|
|
? prevBar.high < nextBar.low
|
|
: prevBar.low > nextBar.high;
|
|
if (result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
//
|
|
prevBar.Clean();
|
|
nextBar.Clean();
|
|
dir = X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Bar CHOCH ...
|
|
|
|
/**
|
|
* Check Specified Bar Has PullBack 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 HasPullBack(
|
|
ENUM_X_DIRECTION &dir,
|
|
XOHCL &bar,
|
|
int loopback = 3,
|
|
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;
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
bool IsStrong(
|
|
XOHCL &bar,
|
|
double percent = 50 // Percent of Body
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = bar.IsValid() &&
|
|
bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
(bar.GetRange() * percent) / 100 <= bar.GetBody();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasStrongLowShadow(
|
|
XOHCL &bar,
|
|
double percent = 50, // Percent of Body
|
|
int __loopback = 2,
|
|
double _sharpRatio = 2.5 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = bar.IsValid() &&
|
|
bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
(bar.GetRange() * percent) / 100 <= bar.GetLowShadow();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (__loopback < 0)
|
|
{
|
|
__loopback = 2;
|
|
}
|
|
|
|
//
|
|
if (_sharpRatio < 0)
|
|
{
|
|
_sharpRatio = 2.5;
|
|
}
|
|
|
|
//
|
|
result = bar.Index() > __loopback;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Get Highest High and Lowest Low in loopback Range ...
|
|
int startIndex = bar.Index() - __loopback;
|
|
int endIndex = bar.Index() + __loopback;
|
|
int requiredBars = MathAbs(endIndex - startIndex);
|
|
|
|
//
|
|
// Highs ...
|
|
double highs[];
|
|
int copiedHighs = CopyHigh(
|
|
bar.symbol,
|
|
bar.period,
|
|
startIndex,
|
|
requiredBars,
|
|
highs //
|
|
);
|
|
|
|
//
|
|
result = copiedHighs == requiredBars;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int highestHighIDX = ArrayMaximum(highs);
|
|
result = IsValidIndex(highestHighIDX);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double highestHigh = highs[highestHighIDX];
|
|
|
|
//
|
|
// Lows ...
|
|
double lows[];
|
|
int copiedLows = CopyLow(
|
|
bar.symbol,
|
|
bar.period,
|
|
startIndex,
|
|
requiredBars,
|
|
lows //
|
|
);
|
|
|
|
//
|
|
result = copiedLows == requiredBars;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int lowestLowIDX = ArrayMinimum(lows);
|
|
result = IsValidIndex(lowestLowIDX);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double lowestLow = lows[lowestLowIDX];
|
|
|
|
//
|
|
result = bar.low == lowestLow &&
|
|
highestHigh > bar.high;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Try to Validate Sharp Ratio ...
|
|
|
|
//
|
|
Clean(highs);
|
|
Clean(lows);
|
|
|
|
//
|
|
// Left Side ...
|
|
startIndex = bar.Index() + 1;
|
|
endIndex = startIndex + (__loopback / 2) - 1;
|
|
requiredBars = MathAbs(endIndex - startIndex);
|
|
|
|
//
|
|
copiedHighs = CopyHigh(
|
|
bar.symbol,
|
|
bar.period,
|
|
startIndex,
|
|
requiredBars,
|
|
highs //
|
|
);
|
|
result = copiedHighs == requiredBars;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
highestHighIDX = ArrayMaximum(highs);
|
|
result = IsValidIndex(highestHighIDX);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
highestHigh = highs[highestHighIDX];
|
|
|
|
//
|
|
copiedLows = CopyLow(
|
|
bar.symbol,
|
|
bar.period,
|
|
startIndex,
|
|
requiredBars,
|
|
lows //
|
|
);
|
|
result = copiedLows == requiredBars;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
lowestLowIDX = ArrayMinimum(lows);
|
|
result = IsValidIndex(lowestLowIDX);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
lowestLow = lows[lowestLowIDX];
|
|
|
|
//
|
|
double leftDiff = highestHigh - lowestLow;
|
|
|
|
//
|
|
Clean(highs);
|
|
Clean(lows);
|
|
|
|
//
|
|
// Right Side ...
|
|
startIndex = bar.Index() - 1;
|
|
endIndex = startIndex - (__loopback / 2) + 1;
|
|
requiredBars = MathAbs(endIndex - startIndex);
|
|
|
|
//
|
|
copiedHighs = CopyHigh(
|
|
bar.symbol,
|
|
bar.period,
|
|
startIndex,
|
|
requiredBars,
|
|
highs //
|
|
);
|
|
result = copiedHighs == requiredBars;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
highestHighIDX = ArrayMaximum(highs);
|
|
result = IsValidIndex(highestHighIDX);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
highestHigh = highs[highestHighIDX];
|
|
|
|
//
|
|
copiedLows = CopyLow(
|
|
bar.symbol,
|
|
bar.period,
|
|
startIndex,
|
|
requiredBars,
|
|
lows //
|
|
);
|
|
result = copiedLows == requiredBars;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
lowestLowIDX = ArrayMinimum(lows);
|
|
result = IsValidIndex(lowestLowIDX);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
lowestLow = lows[lowestLowIDX];
|
|
|
|
//
|
|
double rightDiff = highestHigh - lowestLow;
|
|
double diff = MathMax(leftDiff, rightDiff);
|
|
result = bar.GetLowShadow() >= (diff / 100) * _sharpRatio;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasStrongHighShadow(
|
|
XOHCL &bar,
|
|
double percent = 50, // Percent of Body
|
|
int __loopback = 2,
|
|
double _sharpRatio = 2.5 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = bar.IsValid() && bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
(bar.GetRange() * percent) / 100 <= bar.GetHighShadow();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (__loopback < 0)
|
|
{
|
|
__loopback = 2;
|
|
}
|
|
|
|
//
|
|
if (_sharpRatio < 0)
|
|
{
|
|
_sharpRatio = 2.5;
|
|
}
|
|
|
|
//
|
|
result = bar.Index() > __loopback;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Get Highest High and Lowest Low in loopback Range ...
|
|
int startIndex = bar.Index() - __loopback;
|
|
int endIndex = bar.Index() + __loopback;
|
|
int requiredBars = MathAbs(endIndex - startIndex);
|
|
|
|
//
|
|
// Highs ...
|
|
double highs[];
|
|
int copiedHighs = CopyHigh(
|
|
bar.symbol,
|
|
bar.period,
|
|
startIndex,
|
|
requiredBars,
|
|
highs //
|
|
);
|
|
|
|
//
|
|
result = copiedHighs == requiredBars;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int highestHighIDX = ArrayMaximum(highs);
|
|
result = IsValidIndex(highestHighIDX);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double highestHigh = highs[highestHighIDX];
|
|
|
|
//
|
|
// Lows ...
|
|
double lows[];
|
|
int copiedLows = CopyLow(
|
|
bar.symbol,
|
|
bar.period,
|
|
startIndex,
|
|
requiredBars,
|
|
lows //
|
|
);
|
|
|
|
//
|
|
result = copiedLows == requiredBars;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int lowestLowIDX = ArrayMinimum(lows);
|
|
result = IsValidIndex(lowestLowIDX);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double lowestLow = lows[lowestLowIDX];
|
|
|
|
//
|
|
result = bar.high == highestHigh &&
|
|
lowestLow < bar.low;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Try to Validate Sharp Ratio ...
|
|
|
|
//
|
|
Clean(highs);
|
|
Clean(lows);
|
|
|
|
//
|
|
// Left Side ...
|
|
startIndex = bar.Index() + 1;
|
|
endIndex = startIndex + (__loopback / 2) - 1;
|
|
requiredBars = MathAbs(endIndex - startIndex);
|
|
|
|
//
|
|
copiedHighs = CopyHigh(
|
|
bar.symbol,
|
|
bar.period,
|
|
startIndex,
|
|
requiredBars,
|
|
highs //
|
|
);
|
|
result = copiedHighs == requiredBars;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
highestHighIDX = ArrayMaximum(highs);
|
|
result = IsValidIndex(highestHighIDX);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
highestHigh = highs[highestHighIDX];
|
|
|
|
//
|
|
copiedLows = CopyLow(
|
|
bar.symbol,
|
|
bar.period,
|
|
startIndex,
|
|
requiredBars,
|
|
lows //
|
|
);
|
|
result = copiedLows == requiredBars;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
lowestLowIDX = ArrayMinimum(lows);
|
|
result = IsValidIndex(lowestLowIDX);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
lowestLow = lows[lowestLowIDX];
|
|
|
|
//
|
|
double leftDiff = highestHigh - lowestLow;
|
|
|
|
//
|
|
Clean(highs);
|
|
Clean(lows);
|
|
|
|
//
|
|
// Right Side ...
|
|
startIndex = bar.Index() - 1;
|
|
endIndex = startIndex - (__loopback / 2) + 1;
|
|
requiredBars = MathAbs(endIndex - startIndex);
|
|
|
|
//
|
|
copiedHighs = CopyHigh(
|
|
bar.symbol,
|
|
bar.period,
|
|
startIndex,
|
|
requiredBars,
|
|
highs //
|
|
);
|
|
result = copiedHighs == requiredBars;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
highestHighIDX = ArrayMaximum(highs);
|
|
result = IsValidIndex(highestHighIDX);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
highestHigh = highs[highestHighIDX];
|
|
|
|
//
|
|
copiedLows = CopyLow(
|
|
bar.symbol,
|
|
bar.period,
|
|
startIndex,
|
|
requiredBars,
|
|
lows //
|
|
);
|
|
result = copiedLows == requiredBars;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
lowestLowIDX = ArrayMinimum(lows);
|
|
result = IsValidIndex(lowestLowIDX);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
lowestLow = lows[lowestLowIDX];
|
|
|
|
//
|
|
double rightDiff = highestHigh - lowestLow;
|
|
double diff = MathMax(leftDiff, rightDiff);
|
|
result = bar.GetHighShadow() >= (diff / 100) * _sharpRatio;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool IsStrongBullish(
|
|
XOHCL &bar,
|
|
double percent = 50 // Percent of Body
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
bar.IsValid() &&
|
|
bar.IsBullish() &&
|
|
IsStrong(bar, percent);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool IsStrongBearish(
|
|
XOHCL &bar,
|
|
double percent = 50 // Percent of Body
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
bar.IsValid() &&
|
|
bar.IsBearish() &&
|
|
IsStrong(bar, percent);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool IsSharpBullish(
|
|
XOHCL &bar,
|
|
int __loopback = 2,
|
|
double _sharpRatio = 2.5 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (__loopback < 0)
|
|
{
|
|
__loopback = 2;
|
|
}
|
|
|
|
//
|
|
if (_sharpRatio < 0)
|
|
{
|
|
_sharpRatio = 2.5;
|
|
}
|
|
|
|
//
|
|
int hIDX = bar.FindHighestIndex(
|
|
__loopback,
|
|
MODE_HIGH //
|
|
);
|
|
int lIDX = bar.FindLowestIndex(
|
|
__loopback,
|
|
MODE_LOW //
|
|
);
|
|
|
|
//
|
|
result =
|
|
//
|
|
hIDX >= 0 &&
|
|
lIDX >= 0 &&
|
|
MathAbs(hIDX - bar.Index()) < 2
|
|
//
|
|
;
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL hBar;
|
|
result = hBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
hIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL lBar;
|
|
result = lBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
lIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double lhDif = hBar.high - lBar.low;
|
|
|
|
//
|
|
int hhIDX = hBar.FindHighestIndex(
|
|
__loopback,
|
|
MODE_HIGH //
|
|
);
|
|
|
|
//
|
|
int llIDX = lBar.FindLowestIndex(
|
|
__loopback,
|
|
MODE_LOW //
|
|
);
|
|
|
|
//
|
|
XOHCL hhBar;
|
|
result = hhBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
hhIDX + hIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL llBar;
|
|
result = llBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
llIDX + lIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double llhhDif = hhBar.high - llBar.low;
|
|
|
|
//
|
|
result =
|
|
//
|
|
lBar.low > llBar.low &&
|
|
hBar.high > hhBar.high &&
|
|
lhDif >= llhhDif * _sharpRatio
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool IsSharpBearish(
|
|
XOHCL &bar,
|
|
int __loopback = 2,
|
|
double _sharpRatio = 2.5 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (__loopback < 0)
|
|
{
|
|
__loopback = 2;
|
|
}
|
|
|
|
//
|
|
if (_sharpRatio < 0)
|
|
{
|
|
_sharpRatio = 2.5;
|
|
}
|
|
|
|
//
|
|
int hIDX = bar.FindHighestIndex(
|
|
__loopback,
|
|
MODE_HIGH //
|
|
);
|
|
int lIDX = bar.FindLowestIndex(
|
|
__loopback,
|
|
MODE_LOW //
|
|
);
|
|
|
|
//
|
|
result =
|
|
//
|
|
hIDX >= 0 &&
|
|
lIDX >= 0 &&
|
|
MathAbs(hIDX - bar.Index()) < 2
|
|
//
|
|
;
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL hBar;
|
|
result = hBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
hIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL lBar;
|
|
result = lBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
lIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double lhDif = hBar.high - lBar.low;
|
|
|
|
//
|
|
int hhIDX = hBar.FindHighestIndex(
|
|
__loopback,
|
|
MODE_HIGH //
|
|
);
|
|
|
|
//
|
|
int llIDX = lBar.FindLowestIndex(
|
|
__loopback,
|
|
MODE_LOW //
|
|
);
|
|
|
|
//
|
|
XOHCL hhBar;
|
|
result = hhBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
hhIDX + hIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL llBar;
|
|
result = llBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
llIDX + lIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double llhhDif = hhBar.high - llBar.low;
|
|
|
|
//
|
|
result =
|
|
//
|
|
lBar.low < llBar.low &&
|
|
hBar.high < hhBar.high &&
|
|
lhDif >= llhhDif * _sharpRatio
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
//
|
|
// Retrieve Bullish Pressure ...
|
|
double GetBullishPressure(
|
|
XOHCL &bar,
|
|
int __loopback = 7 //
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
if (!bar.IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL bars[];
|
|
int barsCount = GetBars(
|
|
bars,
|
|
bar.symbol,
|
|
bar.period,
|
|
bar.Index(),
|
|
__loopback //
|
|
);
|
|
if (!IsValidSize(barsCount))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < barsCount; i++)
|
|
{
|
|
result += bars[i].GetLowShadow();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Bearish Pressure ...
|
|
double GetBearishPressure(
|
|
XOHCL &bar,
|
|
int __loopback = 7 //
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
if (!bar.IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL bars[];
|
|
int barsCount = GetBars(
|
|
bars,
|
|
bar.symbol,
|
|
bar.period,
|
|
bar.Index(),
|
|
__loopback //
|
|
);
|
|
if (!IsValidSize(barsCount))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < barsCount; i++)
|
|
{
|
|
result += bars[i].GetHighShadow();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasBullishPressure(
|
|
XOHCL &bar,
|
|
int __loopback = 7 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (__loopback < 0)
|
|
{
|
|
__loopback = 7;
|
|
}
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double bullishPressure = GetBullishPressure(bar, __loopback);
|
|
double bearishPressure = GetBearishPressure(bar, __loopback);
|
|
|
|
//
|
|
result =
|
|
//
|
|
bullishPressure > 0 &&
|
|
bearishPressure >= 0 &&
|
|
bullishPressure > bearishPressure
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasBearishPressure(
|
|
XOHCL &bar,
|
|
int __loopback = 7 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (__loopback < 0)
|
|
{
|
|
__loopback = 7;
|
|
}
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double bullishPressure = GetBullishPressure(bar, __loopback);
|
|
double bearishPressure = GetBearishPressure(bar, __loopback);
|
|
|
|
//
|
|
result =
|
|
//
|
|
bearishPressure > 0 &&
|
|
bullishPressure >= 0 &&
|
|
bearishPressure > bullishPressure
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Bullish Power ...
|
|
double GetBullishPower(
|
|
XOHCL &bar,
|
|
int __loopback = 7 //
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
if (!bar.IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL bars[];
|
|
int barsCount = GetBars(
|
|
bars,
|
|
bar.symbol,
|
|
bar.period,
|
|
bar.Index(),
|
|
__loopback //
|
|
);
|
|
if (!IsValidSize(barsCount))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < barsCount; i++)
|
|
{
|
|
//
|
|
if (bars[i].IsBullish())
|
|
{
|
|
result += bars[i].GetBody();
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Bearish Pressure ...
|
|
double GetBearishPower(
|
|
XOHCL &bar,
|
|
int __loopback = 7 //
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
if (!bar.IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL bars[];
|
|
int barsCount = GetBars(
|
|
bars,
|
|
bar.symbol,
|
|
bar.period,
|
|
bar.Index(),
|
|
__loopback //
|
|
);
|
|
if (!IsValidSize(barsCount))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < barsCount; i++)
|
|
{
|
|
//
|
|
if (bars[i].IsBearish())
|
|
{
|
|
result += bars[i].GetBody();
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasBullishPower(
|
|
XOHCL &bar,
|
|
int __loopback = 7 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (__loopback < 0)
|
|
{
|
|
__loopback = 7;
|
|
}
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double bullishPressure = GetBullishPower(bar, __loopback);
|
|
double bearishPressure = GetBearishPower(bar, __loopback);
|
|
|
|
//
|
|
result =
|
|
//
|
|
bullishPressure > 0 &&
|
|
bearishPressure >= 0 &&
|
|
bullishPressure > bearishPressure
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasBearishPower(
|
|
XOHCL &bar,
|
|
int __loopback = 7 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (__loopback < 0)
|
|
{
|
|
__loopback = 7;
|
|
}
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double bullishPressure = GetBullishPower(bar, __loopback);
|
|
double bearishPressure = GetBearishPower(bar, __loopback);
|
|
|
|
//
|
|
result =
|
|
//
|
|
bearishPressure > 0 &&
|
|
bullishPressure >= 0 &&
|
|
bearishPressure > bullishPressure
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Decisions ...
|
|
|
|
//
|
|
// Candlestic Patterns ...
|
|
|
|
//
|
|
// Check Doji ...
|
|
bool IsDoji(
|
|
XOHCL &bar //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Content and Ignore 0 Bar
|
|
// since it is not Completed ...
|
|
result = bar.IsValid() && bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = bar.open == bar.close;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Hammer ...
|
|
bool IsHammer(
|
|
XOHCL &bar,
|
|
double _upShadowFactor = 0.1,
|
|
double _downShadowFactor = 0.6,
|
|
bool applyFib382Check = true,
|
|
bool applyPrevShadowCheck = true //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Content and Ignore 0 Bar
|
|
// since it is not Completed ...
|
|
result = bar.IsValid() && bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (_upShadowFactor < 0)
|
|
{
|
|
_upShadowFactor = 0.1;
|
|
}
|
|
|
|
//
|
|
if (_downShadowFactor < 0)
|
|
{
|
|
_upShadowFactor = 0.6;
|
|
}
|
|
|
|
//
|
|
double range = bar.GetRange();
|
|
|
|
//
|
|
// Check Upper Shadow Must be 0 or Under 10% ...
|
|
double upShadow = bar.GetHighShadow();
|
|
result = upShadow < range * _upShadowFactor;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Down Shadow Must at least 60% ...
|
|
double downShadow = bar.GetLowShadow();
|
|
result = downShadow > range * _downShadowFactor;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Fib 382 ...
|
|
if (result && applyFib382Check)
|
|
{
|
|
//
|
|
double fib382 = GetFibonacciLevel(
|
|
bar.high,
|
|
bar.low,
|
|
0.382,
|
|
-1 //
|
|
);
|
|
result = bar.GetDown() > fib382;
|
|
}
|
|
|
|
//
|
|
// Check Shadow Based on Prev Bar ...
|
|
if (result && applyPrevShadowCheck)
|
|
{
|
|
//
|
|
XOHCL pBar;
|
|
result = bar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = bar.low < pBar.low;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Sgooting Star ...
|
|
// Reversal Hammer ...
|
|
bool IsShootingStar(
|
|
XOHCL &bar,
|
|
double _upShadowFactor = 0.6,
|
|
double _downShadowFactor = 0.1,
|
|
bool applyFib382Check = true,
|
|
bool applyPrevShadowCheck = true //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Content and Ignore 0 Bar
|
|
// since it is not Completed ...
|
|
result = bar.IsValid() && bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (_upShadowFactor < 0)
|
|
{
|
|
_upShadowFactor = 0.6;
|
|
}
|
|
|
|
//
|
|
if (_downShadowFactor < 0)
|
|
{
|
|
_upShadowFactor = 0.1;
|
|
}
|
|
|
|
//
|
|
double range = bar.GetRange();
|
|
|
|
//
|
|
// Check Upper Shadow Must be 0 or Under 10% ...
|
|
double upShadow = bar.GetHighShadow();
|
|
result = upShadow > range * _upShadowFactor;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Down Shadow Must at least 60% ...
|
|
double downShadow = bar.GetLowShadow();
|
|
result = downShadow < range * _downShadowFactor;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Fib 382 ...
|
|
if (result && applyFib382Check)
|
|
{
|
|
//
|
|
double fib382 = GetFibonacciLevel(
|
|
bar.high,
|
|
bar.low,
|
|
0.382,
|
|
1 //
|
|
);
|
|
result = bar.GetUp() < fib382;
|
|
}
|
|
|
|
//
|
|
// Check Shadow Based on Prev Bar ...
|
|
if (result && applyPrevShadowCheck)
|
|
{
|
|
//
|
|
XOHCL pBar;
|
|
result = bar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = bar.high > pBar.high;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Bullish Engulfing ...
|
|
bool IsBullishEngulfing(
|
|
XOHCL &bar,
|
|
double _engulfBarBodyFactor = 0.7 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Content and Ignore 0 Bar
|
|
// since it is not Completed ...
|
|
result = bar.IsValid() && bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (_engulfBarBodyFactor < 0)
|
|
{
|
|
_engulfBarBodyFactor = 0.7;
|
|
}
|
|
|
|
//
|
|
// Check Bar Is Bullish ...
|
|
result = bar.IsBullish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Previous Bar ...
|
|
XOHCL pBar;
|
|
result = bar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double range = bar.GetRange();
|
|
double body = bar.GetBody();
|
|
|
|
//
|
|
// Check Prev Bar Must Bearish ...
|
|
result = pBar.IsBearish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Shadows Engulf Prev Bar ...
|
|
result =
|
|
//
|
|
bar.high > pBar.high &&
|
|
bar.low <= pBar.low
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Engulfed Bar Must Inside Engulfer Body ...
|
|
result =
|
|
//
|
|
bar.GetUp() > pBar.GetUp() &&
|
|
bar.GetDown() < pBar.GetDown()
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Body of Engulfing Bar ...
|
|
if (result && _engulfBarBodyFactor > 0)
|
|
{
|
|
result = body >= range * _engulfBarBodyFactor;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Bearish Engulfing ...
|
|
bool IsBearishEngulfing(
|
|
XOHCL &bar,
|
|
double _engulfBarBodyFactor = 0.7 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Content and Ignore 0 Bar
|
|
// since it is not Completed ...
|
|
result = bar.IsValid() && bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (_engulfBarBodyFactor < 0)
|
|
{
|
|
_engulfBarBodyFactor = 0.7;
|
|
}
|
|
|
|
//
|
|
// Check Bar Is Bearish ...
|
|
result = bar.IsBearish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Previous Bar ...
|
|
XOHCL pBar;
|
|
result = bar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double range = bar.GetRange();
|
|
double body = bar.GetBody();
|
|
|
|
//
|
|
// Check Prev Bar Must Bullish ...
|
|
result = pBar.IsBullish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Shadows Engulf Prev Bar ...
|
|
result = bar.high >= pBar.high &&
|
|
bar.low < pBar.low;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Engulfed Bar Must Inside Engulfer Body ...
|
|
result =
|
|
//
|
|
bar.GetUp() > pBar.GetUp() &&
|
|
bar.GetDown() < pBar.GetDown()
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Body of Engulfing Bar ...
|
|
if (result && _engulfBarBodyFactor > 0)
|
|
{
|
|
result = body >= range * _engulfBarBodyFactor;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Morning Star Pattern ...
|
|
bool IsMorningStar(
|
|
XOHCL &bar,
|
|
double _middleRangeFactor = 0.3,
|
|
double _startBodyFactor = 0.6,
|
|
bool forceCheckMiddleBarDirection = true,
|
|
bool forceCheckStartBody = true //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Content and Ignore 0 Bar
|
|
// since it is not Completed ...
|
|
result = bar.IsValid() && bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (_middleRangeFactor < 0)
|
|
{
|
|
_middleRangeFactor = 0.3;
|
|
}
|
|
|
|
//
|
|
if (_startBodyFactor < 0)
|
|
{
|
|
_startBodyFactor = 0.6;
|
|
}
|
|
|
|
//
|
|
// Current Bar Must be Bullish ...
|
|
result = bar.IsBullish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Previous Bar ...
|
|
XOHCL pBar;
|
|
result = bar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prev Bar must be Bearish ...
|
|
if (result && forceCheckMiddleBarDirection)
|
|
{
|
|
//
|
|
result = pBar.IsBearish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Retrieve Previous Bar of Prev Bar ...
|
|
XOHCL ppBar;
|
|
result = pBar.GetPreviousBar(ppBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prev Of Prev Bar Must be Bearish ...
|
|
result = ppBar.IsBearish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double range = bar.GetRange();
|
|
double pRange = pBar.GetRange();
|
|
double ppRange = ppBar.GetRange();
|
|
|
|
//
|
|
// Middle Bar must be Smaller than Ratio of other ...
|
|
result =
|
|
//
|
|
pRange < range * _middleRangeFactor &&
|
|
pRange < ppRange * _middleRangeFactor
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (result && forceCheckStartBody)
|
|
{
|
|
//
|
|
result = ppBar.GetBody() > ppRange * _startBodyFactor;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Evening Star Pattern ...
|
|
bool IsEveningStar(
|
|
XOHCL &bar,
|
|
double _middleRangeFactor = 0.3,
|
|
double _startBodyFactor = 0.6,
|
|
bool forceCheckMiddleBarDirection = true,
|
|
bool forceCheckStartBody = true //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Content and Ignore 0 Bar
|
|
// since it is not Completed ...
|
|
result = bar.IsValid() && bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (_middleRangeFactor < 0)
|
|
{
|
|
_middleRangeFactor = 0.3;
|
|
}
|
|
|
|
//
|
|
if (_startBodyFactor < 0)
|
|
{
|
|
_startBodyFactor = 0.6;
|
|
}
|
|
|
|
//
|
|
// Current Bar Must be Bearish ...
|
|
result = bar.IsBearish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Previous Bar ...
|
|
XOHCL pBar;
|
|
result = bar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prev Bar must be Bullish ...
|
|
if (result && forceCheckMiddleBarDirection)
|
|
{
|
|
//
|
|
result = pBar.IsBullish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Retrieve Previous Bar of Prev Bar ...
|
|
XOHCL ppBar;
|
|
result = pBar.GetPreviousBar(ppBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prev Of Prev Bar Must be Bullish ...
|
|
result = ppBar.IsBullish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double range = bar.GetRange();
|
|
double pRange = pBar.GetRange();
|
|
double ppRange = ppBar.GetRange();
|
|
|
|
//
|
|
// Middle Bar must be Smaller than Ratio of other ...
|
|
result =
|
|
//
|
|
pRange < range * _middleRangeFactor &&
|
|
pRange < ppRange * _middleRangeFactor
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (result && forceCheckStartBody)
|
|
{
|
|
//
|
|
result = ppBar.GetBody() > ppRange * _startBodyFactor;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Bullish Marubozu ...
|
|
bool IsBullishMarubozu(XOHCL &bar)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = bar.IsValid() && bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = bar.IsBullish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
bar.GetUp() == bar.high &&
|
|
bar.GetDown() == bar.low
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Bearish Marubozu ...
|
|
bool IsBearishMarubozu(XOHCL &bar)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = bar.IsValid() && bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = bar.IsBearish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
bar.GetUp() == bar.high &&
|
|
bar.GetDown() == bar.low
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Contextual Patterns ...
|
|
|
|
//
|
|
// Check Swing High ...
|
|
bool IsBarSwingHigh(XOHCL &bar)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Content and Ignore 0 Bar
|
|
// since it is not Completed ...
|
|
result = bar.IsValid() && bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Current Bar Must be Bearish ...
|
|
result = bar.IsBearish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Prev Bar ...
|
|
XOHCL pBar;
|
|
result = bar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prev Bar Must be Bullish ...
|
|
result = pBar.IsBullish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Prev of Prev Bar ...
|
|
XOHCL ppBar;
|
|
result = pBar.GetPreviousBar(ppBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prev of Prev Bar Must be Bullish ...
|
|
result = ppBar.IsBullish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check All Highs ...
|
|
result =
|
|
//
|
|
bar.high < pBar.high &&
|
|
pBar.high > ppBar.high
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Simple 3 Candle Based Swing High ...
|
|
bool IsSimpleSwingHigh(
|
|
XOHCL &bar,
|
|
double thresholdInPoint = 1 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int index = bar.Index();
|
|
result = index > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL nextBar;
|
|
result = bar.GetNextBar(nextBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL prevBar;
|
|
result = bar.GetPreviousBar(prevBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double point = GetPoints(bar.symbol);
|
|
double requiredOffset = point * thresholdInPoint;
|
|
|
|
//
|
|
result =
|
|
bar.high > nextBar.high &&
|
|
bar.high > prevBar.high &&
|
|
(thresholdInPoint <= 0
|
|
? true
|
|
: MathAbs(
|
|
MathMax(
|
|
nextBar.high,
|
|
prevBar.high) -
|
|
bar.high) >= requiredOffset);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Last Swing High ...
|
|
bool FindLastSwingHigh(
|
|
XOHCL &bar,
|
|
XOHCL &swing //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
swing.Clean();
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int totalBars = iBars(
|
|
bar.symbol,
|
|
bar.period //
|
|
);
|
|
int maxAllowed = MathMin(100, (totalBars / 100));
|
|
|
|
//
|
|
int idx = bar.Index();
|
|
for (int i = idx; i <= idx + maxAllowed; i++)
|
|
{
|
|
//
|
|
swing.Clean();
|
|
result = swing.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
i //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
swing.Clean();
|
|
break;
|
|
}
|
|
|
|
//
|
|
result = IsBarSwingHigh(swing);
|
|
if (result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Swing Low ...
|
|
bool IsBarSwingLow(XOHCL &bar)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Content and Ignore 0 Bar
|
|
// since it is not Completed ...
|
|
result = bar.IsValid() && bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Current Bar Must be Bullish ...
|
|
result = bar.IsBullish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Prev Bar ...
|
|
XOHCL pBar;
|
|
result = bar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prev Bar Must be Bearish ...
|
|
result = pBar.IsBearish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Prev of Prev Bar ...
|
|
XOHCL ppBar;
|
|
result = pBar.GetPreviousBar(ppBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prev of Prev Bar Must be Bearish ...
|
|
result = ppBar.IsBearish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check All Lows ...
|
|
result =
|
|
//
|
|
bar.low > pBar.low &&
|
|
pBar.low < ppBar.low
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Simple 3 Candle Based Swing Low ...
|
|
bool IsSimpleSwingLow(
|
|
XOHCL &bar,
|
|
double thresholdInPoint = 1 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int index = bar.Index();
|
|
result = index > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL nextBar;
|
|
result = bar.GetNextBar(nextBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL prevBar;
|
|
result = bar.GetPreviousBar(prevBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double point = GetPoints(bar.symbol);
|
|
double requiredOffset = point * thresholdInPoint;
|
|
|
|
//
|
|
result =
|
|
bar.low < nextBar.low &&
|
|
bar.low < prevBar.low &&
|
|
(thresholdInPoint <= 0
|
|
? true
|
|
: MathAbs(
|
|
MathMax(
|
|
nextBar.low,
|
|
prevBar.low) -
|
|
bar.low) >= requiredOffset);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Last Swing Low ...
|
|
bool FindLastSwingLow(
|
|
XOHCL &bar,
|
|
XOHCL &swing //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
swing.Clean();
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int totalBars = iBars(
|
|
bar.symbol,
|
|
bar.period //
|
|
);
|
|
int maxAllowed = MathMin(100, (totalBars / 100));
|
|
|
|
//
|
|
int idx = bar.Index();
|
|
for (int i = idx; i <= idx + maxAllowed; i++)
|
|
{
|
|
//
|
|
swing.Clean();
|
|
result = swing.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
i //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
swing.Clean();
|
|
break;
|
|
}
|
|
|
|
//
|
|
result = IsBarSwingLow(swing);
|
|
if (result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Bullish FVG ...
|
|
bool HasBullishFVG(
|
|
XOHCL &bar,
|
|
double &upper,
|
|
double &lower,
|
|
datetime &start,
|
|
datetime &end,
|
|
bool forceMiddleBarCheck = true,
|
|
bool forceCheckLastBarDirection = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
upper = 0;
|
|
lower = 0;
|
|
|
|
//
|
|
end = NULL;
|
|
start = NULL;
|
|
|
|
//
|
|
// Validate Content and Ignore 0 Bar
|
|
// since it is not Completed ...
|
|
result = bar.IsValid() && bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Current Bar Must be Bullish ...
|
|
result =
|
|
!forceCheckLastBarDirection
|
|
? true
|
|
: bar.IsBullish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Prev Bar ...
|
|
XOHCL pBar;
|
|
result = bar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prev Bar Must be Bullish ...
|
|
result = pBar.IsBullish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Prev of Prev Bar ...
|
|
XOHCL ppBar;
|
|
result = pBar.GetPreviousBar(ppBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prev of Prev Bar Must be Bullish ...
|
|
result = ppBar.IsBullish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Other Conditions ...
|
|
result =
|
|
//
|
|
bar.low > ppBar.high
|
|
//
|
|
;
|
|
|
|
//
|
|
// Check Middle Bar Range ...
|
|
if (result && forceMiddleBarCheck)
|
|
{
|
|
//
|
|
result =
|
|
//
|
|
pBar.high > bar.low &&
|
|
pBar.low < ppBar.high
|
|
//
|
|
;
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
end = bar.time;
|
|
upper = bar.low;
|
|
lower = ppBar.high;
|
|
start = ppBar.time;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Bearish FVG ...
|
|
bool HasBearishFVG(
|
|
XOHCL &bar,
|
|
double &upper,
|
|
double &lower,
|
|
datetime &start,
|
|
datetime &end,
|
|
bool forceMiddleBarCheck = true,
|
|
bool forceCheckLastBarDirection = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
upper = 0;
|
|
lower = 0;
|
|
|
|
//
|
|
end = NULL;
|
|
start = NULL;
|
|
|
|
//
|
|
// Validate Content and Ignore 0 Bar
|
|
// since it is not Completed ...
|
|
result = bar.IsValid() && bar.Index() > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Current Bar Must be Bearish ...
|
|
result =
|
|
!forceCheckLastBarDirection
|
|
? true
|
|
: bar.IsBullish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Prev Bar ...
|
|
XOHCL pBar;
|
|
result = bar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prev Bar Must be Bearish ...
|
|
result = pBar.IsBearish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Prev of Prev Bar ...
|
|
XOHCL ppBar;
|
|
result = pBar.GetPreviousBar(ppBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prev of Prev Bar Must be Bearish ...
|
|
result = ppBar.IsBearish();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Other Conditions ...
|
|
result =
|
|
//
|
|
bar.high < ppBar.low
|
|
//
|
|
;
|
|
|
|
//
|
|
// Check Middle Bar Range ...
|
|
if (result && forceMiddleBarCheck)
|
|
{
|
|
//
|
|
result =
|
|
//
|
|
pBar.high > bar.low &&
|
|
pBar.low < ppBar.high
|
|
//
|
|
;
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
end = bar.time;
|
|
lower = bar.high;
|
|
upper = ppBar.low;
|
|
start = ppBar.time;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Support ...
|
|
bool HasSupport(
|
|
XOHCL &bar,
|
|
XOHCL &dest,
|
|
ENUM_X_PRICE type = X_PRICE_CLOSE,
|
|
int _loopback = 21,
|
|
int tries = 100 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dest.Clean();
|
|
|
|
//
|
|
if (_loopback < 0)
|
|
{
|
|
_loopback = 21;
|
|
}
|
|
|
|
//
|
|
if (tries < 0)
|
|
{
|
|
tries = 100;
|
|
}
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double price = bar.GetPrice(type);
|
|
|
|
//
|
|
for (int i = 1; i < tries; i++)
|
|
{
|
|
//
|
|
int _length = _loopback * i;
|
|
|
|
//
|
|
int lowestIDX = bar.FindLowestIndex(
|
|
_length,
|
|
MODE_LOW //
|
|
);
|
|
result = IsValidIndex(lowestIDX);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
XOHCL iLBar;
|
|
result = iLBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
lowestIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
price > iLBar.high
|
|
//
|
|
;
|
|
if (result)
|
|
{
|
|
//
|
|
dest = iLBar;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = dest.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Resistance ...
|
|
bool HasResistance(
|
|
XOHCL &bar,
|
|
XOHCL &dest,
|
|
ENUM_X_PRICE type = X_PRICE_CLOSE,
|
|
int _loopback = 21,
|
|
int tries = 100 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dest.Clean();
|
|
|
|
//
|
|
if (_loopback < 0)
|
|
{
|
|
_loopback = 21;
|
|
}
|
|
|
|
//
|
|
if (tries < 0)
|
|
{
|
|
tries = 100;
|
|
}
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double price = bar.GetPrice(type);
|
|
|
|
//
|
|
for (int i = 1; i < tries; i++)
|
|
{
|
|
//
|
|
int _length = _loopback * i;
|
|
|
|
//
|
|
int highestIDX = bar.FindHighestIndex(
|
|
_length,
|
|
MODE_LOW //
|
|
);
|
|
result = IsValidIndex(highestIDX);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
XOHCL iHBar;
|
|
result = iHBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
highestIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
price < iHBar.high
|
|
//
|
|
;
|
|
if (result)
|
|
{
|
|
//
|
|
dest = iHBar;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = dest.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Trend Detection ...
|
|
|
|
//
|
|
// Find Bullish Trend ...
|
|
bool HasBullishTrend(
|
|
XOHCL &bar,
|
|
XOHCL &highSwingBars[],
|
|
XOHCL &lowSwingBars[],
|
|
bool forceMethod2 = false,
|
|
int _loopback = 3,
|
|
int tries = 3,
|
|
ENUM_X_PRICE type = X_PRICE_CLOSE //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
Clean(lowSwingBars);
|
|
Clean(highSwingBars);
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double price = bar.GetPrice(type);
|
|
|
|
//
|
|
int lastIDX = bar.Index();
|
|
double lastH = 0;
|
|
double lastL = 0;
|
|
for (int i = 1; i < tries + 1; i++)
|
|
{
|
|
//
|
|
// Use Regular Method ...
|
|
if (!forceMethod2)
|
|
{
|
|
//
|
|
int iHIDX = FindSwing(
|
|
bar.symbol,
|
|
bar.period,
|
|
X_SWING_HIGH,
|
|
_loopback,
|
|
lastIDX //
|
|
);
|
|
result = IsValidIndex(iHIDX);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
XOHCL iHBar;
|
|
result = iHBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
iHIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
double iH = iHBar.high;
|
|
bool isIHAccepted =
|
|
//
|
|
iH > 0 &&
|
|
(
|
|
//
|
|
lastH == 0
|
|
? true
|
|
: iH < lastH
|
|
//
|
|
)
|
|
//
|
|
;
|
|
if (isIHAccepted)
|
|
{
|
|
//
|
|
AddRef(
|
|
iHBar,
|
|
highSwingBars //
|
|
);
|
|
|
|
//
|
|
lastH = iH;
|
|
lastIDX = iHIDX;
|
|
}
|
|
|
|
//
|
|
int iLIDX = FindSwing(
|
|
bar.symbol,
|
|
bar.period,
|
|
X_SWING_LOW,
|
|
_loopback,
|
|
lastIDX //
|
|
);
|
|
result = IsValidIndex(iLIDX);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
XOHCL iLBar;
|
|
result = iLBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
iLIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
double iL = iLBar.low;
|
|
bool isILAccepted =
|
|
//
|
|
iL > 0 &&
|
|
(
|
|
//
|
|
lastL == 0
|
|
? true
|
|
: iL < lastL
|
|
//
|
|
)
|
|
//
|
|
;
|
|
if (isILAccepted)
|
|
{
|
|
//
|
|
AddRef(
|
|
iLBar,
|
|
lowSwingBars //
|
|
);
|
|
|
|
//
|
|
lastL = iL;
|
|
lastIDX = iLIDX;
|
|
}
|
|
}
|
|
//
|
|
// Use Other MEthod ...
|
|
else
|
|
{
|
|
//
|
|
int _length = i * _loopback;
|
|
int start =
|
|
//
|
|
i == 1
|
|
? 1
|
|
: _length - _loopback
|
|
//
|
|
;
|
|
|
|
//
|
|
int iHIDX = iHighest(
|
|
bar.symbol,
|
|
bar.period,
|
|
MODE_HIGH,
|
|
_loopback,
|
|
start //
|
|
);
|
|
result = IsValidIndex(iHIDX);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
XOHCL iHBar;
|
|
result = iHBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
iHIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
double iH = iHBar.high;
|
|
bool isIHAccepted =
|
|
//
|
|
iH > 0 &&
|
|
(
|
|
//
|
|
lastH == 0
|
|
? true
|
|
: iH < lastH
|
|
//
|
|
)
|
|
//
|
|
;
|
|
if (isIHAccepted)
|
|
{
|
|
//
|
|
AddRef(
|
|
iHBar,
|
|
highSwingBars //
|
|
);
|
|
|
|
//
|
|
lastH = iH;
|
|
lastIDX = iHIDX;
|
|
}
|
|
|
|
//
|
|
int iLIDX = iLowest(
|
|
bar.symbol,
|
|
bar.period,
|
|
MODE_LOW,
|
|
_loopback,
|
|
start //
|
|
);
|
|
result = IsValidIndex(iLIDX);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
XOHCL iLBar;
|
|
result = iLBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
iLIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
double iL = iLBar.low;
|
|
bool isILAccepted =
|
|
//
|
|
iL > 0 &&
|
|
(
|
|
//
|
|
lastL == 0
|
|
? true
|
|
: iL < lastL
|
|
//
|
|
)
|
|
//
|
|
;
|
|
if (isILAccepted)
|
|
{
|
|
//
|
|
AddRef(
|
|
iLBar,
|
|
lowSwingBars //
|
|
);
|
|
|
|
//
|
|
lastL = iL;
|
|
lastIDX = iLIDX;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
result =
|
|
//
|
|
ArraySize(lowSwingBars) == tries &&
|
|
ArraySize(highSwingBars) == tries
|
|
//
|
|
;
|
|
}
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
//
|
|
Clean(lowSwingBars);
|
|
Clean(highSwingBars);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Bearish Trend ...
|
|
bool HasBearishTrend(
|
|
XOHCL &bar,
|
|
XOHCL &highSwingBars[],
|
|
XOHCL &lowSwingBars[],
|
|
bool forceMethod2 = false,
|
|
int _loopback = 3,
|
|
int tries = 3,
|
|
ENUM_X_PRICE type = X_PRICE_CLOSE //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
Clean(lowSwingBars);
|
|
Clean(highSwingBars);
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double price = bar.GetPrice(type);
|
|
|
|
//
|
|
int lastIDX = bar.Index();
|
|
double lastH = 0;
|
|
double lastL = 0;
|
|
for (int i = 1; i < tries + 1; i++)
|
|
{
|
|
//
|
|
// Use Regular Method ...
|
|
if (!forceMethod2)
|
|
{
|
|
//
|
|
int iHIDX = FindSwing(
|
|
bar.symbol,
|
|
bar.period,
|
|
X_SWING_HIGH,
|
|
_loopback,
|
|
lastIDX //
|
|
);
|
|
result = IsValidIndex(iHIDX);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
XOHCL iHBar;
|
|
result = iHBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
iHIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
double iH = iHBar.high;
|
|
bool isIHAccepted =
|
|
//
|
|
iH > 0 &&
|
|
(
|
|
//
|
|
lastH == 0
|
|
? true
|
|
: iH > lastH
|
|
//
|
|
)
|
|
//
|
|
;
|
|
if (isIHAccepted)
|
|
{
|
|
//
|
|
AddRef(
|
|
iHBar,
|
|
highSwingBars //
|
|
);
|
|
|
|
//
|
|
lastH = iH;
|
|
lastIDX = iHIDX;
|
|
}
|
|
|
|
//
|
|
int iLIDX = FindSwing(
|
|
bar.symbol,
|
|
bar.period,
|
|
X_SWING_LOW,
|
|
_loopback,
|
|
lastIDX //
|
|
);
|
|
result = IsValidIndex(iLIDX);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
XOHCL iLBar;
|
|
result = iLBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
iLIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
double iL = iLBar.low;
|
|
bool isILAccepted =
|
|
//
|
|
iL > 0 &&
|
|
(
|
|
//
|
|
lastL == 0
|
|
? true
|
|
: iL > lastL
|
|
//
|
|
)
|
|
//
|
|
;
|
|
if (isILAccepted)
|
|
{
|
|
//
|
|
AddRef(
|
|
iLBar,
|
|
lowSwingBars //
|
|
);
|
|
|
|
//
|
|
lastL = iL;
|
|
lastIDX = iLIDX;
|
|
}
|
|
}
|
|
//
|
|
// Use Other MEthod ...
|
|
else
|
|
{
|
|
//
|
|
int _length = i * _loopback;
|
|
int start =
|
|
//
|
|
i == 1
|
|
? 1
|
|
: _length - _loopback
|
|
//
|
|
;
|
|
|
|
//
|
|
int iHIDX = iHighest(
|
|
bar.symbol,
|
|
bar.period,
|
|
MODE_HIGH,
|
|
_loopback,
|
|
start //
|
|
);
|
|
result = IsValidIndex(iHIDX);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
XOHCL iHBar;
|
|
result = iHBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
iHIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
double iH = iHBar.high;
|
|
bool isIHAccepted =
|
|
//
|
|
iH > 0 &&
|
|
(
|
|
//
|
|
lastH == 0
|
|
? true
|
|
: iH > lastH
|
|
//
|
|
)
|
|
//
|
|
;
|
|
if (isIHAccepted)
|
|
{
|
|
//
|
|
AddRef(
|
|
iHBar,
|
|
highSwingBars //
|
|
);
|
|
|
|
//
|
|
lastH = iH;
|
|
lastIDX = iHIDX;
|
|
}
|
|
|
|
//
|
|
int iLIDX = iLowest(
|
|
bar.symbol,
|
|
bar.period,
|
|
MODE_LOW,
|
|
_loopback,
|
|
start //
|
|
);
|
|
result = IsValidIndex(iLIDX);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
XOHCL iLBar;
|
|
result = iLBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
iLIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
double iL = iLBar.low;
|
|
bool isILAccepted =
|
|
//
|
|
iL > 0 &&
|
|
(
|
|
//
|
|
lastL == 0
|
|
? true
|
|
: iL > lastL
|
|
//
|
|
)
|
|
//
|
|
;
|
|
if (isILAccepted)
|
|
{
|
|
//
|
|
AddRef(
|
|
iLBar,
|
|
lowSwingBars //
|
|
);
|
|
|
|
//
|
|
lastL = iL;
|
|
lastIDX = iLIDX;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
result =
|
|
//
|
|
ArraySize(lowSwingBars) == tries &&
|
|
ArraySize(highSwingBars) == tries
|
|
//
|
|
;
|
|
}
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
//
|
|
Clean(lowSwingBars);
|
|
Clean(highSwingBars);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Order Blocks ...
|
|
|
|
//
|
|
// Find Bullish Order Block ...
|
|
bool HasBullishOrderBlock(
|
|
XOHCL &bar,
|
|
XOHCL &orderBlock,
|
|
int _minimumSameBars = 4 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
orderBlock.Clean();
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (_minimumSameBars < 0)
|
|
{
|
|
_minimumSameBars = 4;
|
|
}
|
|
|
|
//
|
|
XOHCL cBar;
|
|
int founded = 0;
|
|
int cIDX = bar.Index();
|
|
bool isEnough = false;
|
|
while (!isEnough)
|
|
{
|
|
//
|
|
result = cBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
cIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
result = cBar.IsBullish();
|
|
if (!result && cBar.IsBearish())
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
cIDX++;
|
|
founded++;
|
|
}
|
|
|
|
//
|
|
// Here we have to check founded and if it's fill
|
|
// our requirements ...
|
|
// cIDX is Order Block Index ...
|
|
result =
|
|
//
|
|
cBar.IsValid() &&
|
|
bar.high > cBar.high &&
|
|
founded >= _minimumSameBars
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = orderBlock.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
cIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
orderBlock.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Bearish Order Block ...
|
|
bool HasBearishOrderBlock(
|
|
XOHCL &bar,
|
|
XOHCL &orderBlock,
|
|
int _minimumSameBars = 4 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
orderBlock.Clean();
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (_minimumSameBars < 0)
|
|
{
|
|
_minimumSameBars = 4;
|
|
}
|
|
|
|
//
|
|
XOHCL cBar;
|
|
int founded = 0;
|
|
int cIDX = bar.Index();
|
|
bool isEnough = false;
|
|
while (!isEnough)
|
|
{
|
|
//
|
|
bool isInited = cBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
cIDX //
|
|
);
|
|
|
|
//
|
|
result = cBar.IsBearish();
|
|
if (!result && cBar.IsBullish())
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
cIDX++;
|
|
founded++;
|
|
}
|
|
|
|
//
|
|
// Here we have to check founded and if it's fill
|
|
// our requirements ...
|
|
// cIDX is Order Block Index ...
|
|
result =
|
|
//
|
|
cBar.IsValid() &&
|
|
bar.high < cBar.low &&
|
|
founded >= _minimumSameBars
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = orderBlock.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
cIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
orderBlock.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|