459 lines
12 KiB
Plaintext
459 lines
12 KiB
Plaintext
|
|
int CounteZoneTouches(
|
|
XBoxZone &zone,
|
|
double threshold = 10,
|
|
int loopback = 100 //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Normalize ...
|
|
loopback = NormalizeInt(loopback, 50);
|
|
threshold = NormalizeDouble(threshold, 10);
|
|
|
|
//
|
|
if (!zone.IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL tmpBar;
|
|
int start = zone.ToIndex();
|
|
bool isUpperTouched = false;
|
|
bool isLowerTouched = false;
|
|
double points = GetPoints(zone.symbol);
|
|
double distance = points * threshold;
|
|
int end = MathMin(start + loopback, zone.FromIndex());
|
|
for (int i = start; i < end; i++)
|
|
{
|
|
//
|
|
if (tmpBar.Init(zone.symbol, zone.period, i))
|
|
{
|
|
//
|
|
isUpperTouched = MathAbs(tmpBar.high - zone.upper) <= distance;
|
|
isLowerTouched = MathAbs(tmpBar.low - zone.lower) <= distance;
|
|
|
|
//
|
|
if (
|
|
(zone.IsBullish() &&
|
|
(isLowerTouched ||
|
|
MathAbs(tmpBar.close - zone.lower) <= distance)) ||
|
|
(zone.IsBearish() &&
|
|
(isUpperTouched ||
|
|
MathAbs(tmpBar.close - zone.upper) <= distance)))
|
|
{
|
|
//
|
|
result++;
|
|
Add(
|
|
tmpBar.time,
|
|
zone.tests //
|
|
);
|
|
}
|
|
|
|
//
|
|
tmpBar.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
tmpBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool HasNearZone(
|
|
int &index,
|
|
double price,
|
|
double threshold,
|
|
XBoxZone &zones[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
index = -1;
|
|
|
|
//
|
|
// Validate ...
|
|
result = HasChild(zones) &&
|
|
NotEmptyZero(price) &&
|
|
NotEmptyZero(threshold) &&
|
|
price > 0 &&
|
|
threshold > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double points = GetPoints(zones[0].symbol);
|
|
double distance = points * threshold;
|
|
for (int i = 0; i < ArraySize(zones); i++)
|
|
{
|
|
//
|
|
// Check Price Distance by Upper ...
|
|
result = price >= zones[i].lower - distance &&
|
|
price <= zones[i].upper + distance;
|
|
if (result)
|
|
{
|
|
//
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsNearZone(
|
|
double price,
|
|
XBoxZone &zone,
|
|
double threshold = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
zone.IsValid() &&
|
|
NotEmptyZero(price);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double points = GetPoints(zone.symbol);
|
|
double distance = points * threshold;
|
|
|
|
//
|
|
result = price >= zone.lower - distance &&
|
|
price <= zone.upper + distance;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
|
|
/*
|
|
* Check Recently Pattern Zone is Touched or not ...
|
|
*
|
|
* @param zone: XBoxZone, Touched Zone ...
|
|
* @param patterns: ENUM_X_BAR_PATTERN, Allowed to Check Patterns ...
|
|
* @param patternsDir: ENUM_X_DIRECTION, Allowed Directions ...
|
|
* @param price: double, a Price to Check Toch or Reject ...
|
|
* @param barIndex: int, Bar Index to Start Checking ...
|
|
* @param loopback: int, Loopback for Pattern Formations ...
|
|
* @param threshold: double, threshold for Pattern touch ...
|
|
* @param forPeriod: ENUM_TIMEFRAMES, Time Frame to Check Patterns ...
|
|
* @param forDir: ENUM_X_DIRECTION, Directions for Pattern's Formation Check ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasRecentPatternTouched(
|
|
XBoxZone &zone,
|
|
ENUM_X_BAR_PATTERN &patterns[],
|
|
ENUM_X_DIRECTION &patternsDir[],
|
|
double price,
|
|
int barIndex = 0,
|
|
int loopback = 5,
|
|
double threshold = 5,
|
|
ENUM_TIMEFRAMES forPeriod = NULL,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
zone.Clean();
|
|
|
|
//
|
|
// Validate ...
|
|
result =
|
|
HasChild(patterns) &&
|
|
NotEmptyZero(price) &&
|
|
HasChild(patternsDir) &&
|
|
ArraySize(patterns) == ArraySize(patternsDir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Normalize ...
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
if (IsXValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool has = false;
|
|
int iBullishIDX = -1;
|
|
int iBearishIDX = -1;
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
XBoxZone iBullishZones[];
|
|
XBoxZone iBearishZones[];
|
|
XPatternAnalysis iAnalysis;
|
|
XPatternAnalysisConfig iConfig;
|
|
|
|
//
|
|
// Preparing Pattern Analysis Config ...
|
|
iConfig.Default();
|
|
|
|
//
|
|
Copy(
|
|
patterns,
|
|
iConfig.allowedPatterns //
|
|
);
|
|
Copy(
|
|
patternsDir,
|
|
iConfig.allowedDirs //
|
|
);
|
|
|
|
//
|
|
// XAUUSD ...
|
|
iConfig.AddPattern(X_BAR_PATTERN_FVG);
|
|
iConfig.AddPattern(X_BAR_PATTERN_PIERCING);
|
|
|
|
//
|
|
// Looping Back ...
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
// Initialize Bar ...
|
|
has = iBar.Init(symbol, forPeriod, i);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Analyse Patterns ...
|
|
has = AnalyseBarPatterns(iBar, iAnalysis, iConfig);
|
|
if (!has)
|
|
{
|
|
//
|
|
iBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Bullish ...
|
|
has = iAnalysis.Count(X_DIRECTION_BULLISH) > 0;
|
|
if (has)
|
|
{
|
|
//
|
|
iAnalysis.GetPatterns(iBullishZones, X_DIRECTION_BULLISH);
|
|
has = HasChild(iBullishZones);
|
|
if (has)
|
|
{
|
|
//
|
|
has = HasNearZone(
|
|
iBullishIDX,
|
|
price,
|
|
threshold,
|
|
iBullishZones //
|
|
);
|
|
if (has)
|
|
{
|
|
isBullish = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
has = iAnalysis.Count(X_DIRECTION_BEARISH) > 0;
|
|
if (has)
|
|
{
|
|
//
|
|
iAnalysis.GetPatterns(iBearishZones, X_DIRECTION_BEARISH);
|
|
has = HasChild(iBearishZones);
|
|
if (has)
|
|
{
|
|
//
|
|
has = HasNearZone(
|
|
iBearishIDX,
|
|
price,
|
|
threshold,
|
|
iBearishZones //
|
|
);
|
|
if (has)
|
|
{
|
|
isBearish = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Summarizing Result ...
|
|
has =
|
|
HasDirection(forDir)
|
|
? (isBullish && !isBearish && IsXBullish(forDir)) ||
|
|
(isBearish && !isBullish && IsXBearish(forDir))
|
|
: (isBullish && !isBearish) || (isBearish && !isBullish);
|
|
if (has)
|
|
{
|
|
//
|
|
// Fill Zones ...
|
|
if (isBullish)
|
|
{
|
|
zone = iBullishZones[iBullishIDX];
|
|
}
|
|
else
|
|
{
|
|
zone = iBearishZones[iBearishIDX];
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Cleanup Resource ...
|
|
iBar.Clean();
|
|
iAnalysis.Clean();
|
|
XClean(iBullishZones);
|
|
XClean(iBearishZones);
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
iBar.Clean();
|
|
iConfig.Clean();
|
|
iAnalysis.Clean();
|
|
XClean(iBullishZones);
|
|
XClean(iBearishZones);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
|
|
void ValidateZones(
|
|
XBoxZone &zones[],
|
|
int barIndex = 0,
|
|
int minimumRetests = 2,
|
|
double retestThreshold = 10,
|
|
int retestLoopback = 100,
|
|
ENUM_X_BOUNDARY_PRICE forPriceType = X_BOUNDARY_PRICE_UP_DOWN //
|
|
)
|
|
{
|
|
//
|
|
bool has = false;
|
|
|
|
//
|
|
// Validation ...
|
|
has = HasChild(zones) &&
|
|
IsXValid(forPriceType);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Normalizetion ...
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
minimumRetests = NormalizeInt(minimumRetests, 0);
|
|
retestLoopback = NormalizeInt(retestLoopback, 50);
|
|
retestThreshold = NormalizeDouble(retestThreshold, 5, 10);
|
|
|
|
//
|
|
XOHCL tmpBar;
|
|
XBoxZone tmp;
|
|
XBoxZone tmps[];
|
|
double tmpValue = 0;
|
|
for (int i = 0; i < ArraySize(zones); i++)
|
|
{
|
|
//
|
|
tmp = zones[i];
|
|
|
|
//
|
|
if (minimumRetests > 0)
|
|
{
|
|
//
|
|
int retests = CounteZoneTouches(tmp, retestThreshold, retestLoopback);
|
|
if (retests < minimumRetests)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate Zone ...
|
|
has = false;
|
|
for (int j = barIndex; j < tmp.FromIndex(); j++)
|
|
{
|
|
//
|
|
// Initial Bar ...
|
|
if (tmpBar.Init(tmp.symbol, tmp.period, j))
|
|
{
|
|
//
|
|
tmpValue = forPriceType == X_BOUNDARY_PRICE_UP_DOWN
|
|
? tmp.IsBullish()
|
|
? tmpBar.GetDown()
|
|
: tmpBar.GetUp()
|
|
: forPriceType == X_BOUNDARY_PRICE_HIGH_LOW
|
|
? tmp.IsBullish()
|
|
? tmpBar.low
|
|
: tmpBar.high
|
|
: EMPTY_VALUE;
|
|
if (NotEmptyZero(tmpValue))
|
|
{
|
|
//
|
|
// Check Break ...
|
|
has = tmp.IsBullish()
|
|
? tmpValue < tmp.lower
|
|
: tmpValue > tmp.upper;
|
|
|
|
//
|
|
// If Breakes ...
|
|
if (has)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
tmpBar.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Not Breaked ...
|
|
if (!has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
tmp,
|
|
tmps //
|
|
);
|
|
}
|
|
|
|
//
|
|
tmp.Clean();
|
|
}
|
|
|
|
//
|
|
// Update Zones ...
|
|
XClean(zones);
|
|
Copy(
|
|
tmps,
|
|
zones //
|
|
);
|
|
XClean(tmps);
|
|
}
|