4936 lines
112 KiB
Plaintext
4936 lines
112 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Indicator
|
|
// -------------------------------------------------
|
|
// Name: XCXCAEAPOIDetector ...
|
|
// Description: Class for XCAEA POI Detector ...
|
|
//
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property library
|
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
|
#property link "https://saherelm.ir"
|
|
#property version "1.00"
|
|
#property description "SaherElm Class for XCAEA POI Detector"
|
|
#property strict
|
|
|
|
//
|
|
// Imports ...
|
|
#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5"
|
|
#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5"
|
|
#include "../Helpers/xcaea.helper.mq5"
|
|
|
|
//
|
|
// Definitions ...
|
|
|
|
//
|
|
enum ENUM_XCA_PIVOTS
|
|
{
|
|
XCA_NONE, // None
|
|
XCA_TICK, // Tick
|
|
XCA_VOLUME, // Volume
|
|
XCA_FVG_BULL, // FVGBull
|
|
XCA_FVG_BEAR, // FVGBear
|
|
XCA_RSI_COOS, // RSICOOS
|
|
XCA_RSI_CUOB, // RSICUOB
|
|
XCA_RSI_PEAK, // RSIPeak
|
|
XCA_RSI_VALE, // RSIVale
|
|
XCA_CCI_COOS, // CCICOOS
|
|
XCA_CCI_CUOB, // CCICUOB
|
|
XCA_CCI_PEAK, // CCIPeak
|
|
XCA_CCI_VALE, // CCIVale
|
|
XCA_PEAKSWHRES, // PeakSWHRes
|
|
XCA_VALESWLSUP, // ValeSWLSup
|
|
XCA_TREND_BULL, // TrendBull
|
|
XCA_TREND_BEAR, // TrendBear
|
|
};
|
|
|
|
//
|
|
bool IsValid(ENUM_XCA_PIVOTS value)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = value != XCA_NONE;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string ToString(ENUM_XCA_PIVOTS value)
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
result = EnumToString(value);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION GetDirection(ENUM_XCA_PIVOTS value)
|
|
{
|
|
//
|
|
ENUM_X_DIRECTION result = X_DIRECTION_NONE;
|
|
|
|
//
|
|
switch (value)
|
|
{
|
|
//
|
|
case XCA_FVG_BULL:
|
|
case XCA_RSI_COOS:
|
|
case XCA_RSI_VALE:
|
|
case XCA_CCI_COOS:
|
|
case XCA_CCI_VALE:
|
|
case XCA_TREND_BULL:
|
|
case XCA_VALESWLSUP:
|
|
result = X_DIRECTION_BULLISH;
|
|
break;
|
|
|
|
//
|
|
case XCA_FVG_BEAR:
|
|
case XCA_RSI_CUOB:
|
|
case XCA_RSI_PEAK:
|
|
case XCA_CCI_CUOB:
|
|
case XCA_CCI_PEAK:
|
|
case XCA_TREND_BEAR:
|
|
case XCA_PEAKSWHRES:
|
|
result = X_DIRECTION_BEARISH;
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string GetBoxType(ENUM_XCA_PIVOTS value)
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
switch (value)
|
|
{
|
|
//
|
|
case XCA_TICK:
|
|
case XCA_VOLUME:
|
|
case XCA_RSI_COOS:
|
|
case XCA_RSI_VALE:
|
|
case XCA_CCI_COOS:
|
|
case XCA_CCI_VALE:
|
|
case XCA_RSI_CUOB:
|
|
case XCA_RSI_PEAK:
|
|
case XCA_CCI_CUOB:
|
|
case XCA_CCI_PEAK:
|
|
case XCA_VALESWLSUP:
|
|
case XCA_PEAKSWHRES:
|
|
result = ToString(value);
|
|
break;
|
|
//
|
|
case XCA_FVG_BULL:
|
|
case XCA_FVG_BEAR:
|
|
result = "XCA_FVG";
|
|
break;
|
|
|
|
//
|
|
case XCA_TREND_BULL:
|
|
case XCA_TREND_BEAR:
|
|
result = "XCA_TREND";
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ENUM_XCA_PIVOTS GetPivotType(XBoxZone &value)
|
|
{
|
|
//
|
|
ENUM_XCA_PIVOTS result = XCA_NONE;
|
|
|
|
//
|
|
bool has = value.IsValid();
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isTick = value.type == GetBoxType(XCA_TICK);
|
|
bool isVolume = value.type == GetBoxType(XCA_VOLUME);
|
|
bool isFVGBull = value.type == GetBoxType(XCA_FVG_BULL) &&
|
|
value.dir == GetDirection(XCA_FVG_BULL);
|
|
bool isFVGBear = value.type == GetBoxType(XCA_FVG_BEAR) &&
|
|
value.dir == GetDirection(XCA_FVG_BEAR);
|
|
bool isRSIPeak = value.type == GetBoxType(XCA_RSI_PEAK) &&
|
|
value.dir == GetDirection(XCA_RSI_PEAK);
|
|
bool isRSIVale = value.type == GetBoxType(XCA_RSI_VALE) &&
|
|
value.dir == GetDirection(XCA_RSI_VALE);
|
|
bool isCCIPeak = value.type == GetBoxType(XCA_CCI_PEAK) &&
|
|
value.dir == GetDirection(XCA_CCI_PEAK);
|
|
bool isCCIVale = value.type == GetBoxType(XCA_CCI_VALE) &&
|
|
value.dir == GetDirection(XCA_CCI_VALE);
|
|
bool isRSICrossedOverOS = value.type == GetBoxType(XCA_RSI_COOS) &&
|
|
value.dir == GetDirection(XCA_RSI_COOS);
|
|
bool isRSICrossedUnderOB = value.type == GetBoxType(XCA_RSI_CUOB) &&
|
|
value.dir == GetDirection(XCA_RSI_CUOB);
|
|
bool isCCICrossedOverOS = value.type == GetBoxType(XCA_CCI_COOS) &&
|
|
value.dir == GetDirection(XCA_CCI_COOS);
|
|
bool isCCICrossedUnderOB = value.type == GetBoxType(XCA_CCI_CUOB) &&
|
|
value.dir == GetDirection(XCA_CCI_CUOB);
|
|
bool isTrendBullish = value.type == GetBoxType(XCA_TREND_BULL) &&
|
|
value.dir == GetDirection(XCA_TREND_BULL);
|
|
bool isTrendBearish = value.type == GetBoxType(XCA_TREND_BEAR) &&
|
|
value.dir == GetDirection(XCA_TREND_BEAR);
|
|
bool isPeakSWHRes = value.type == GetBoxType(XCA_PEAKSWHRES) &&
|
|
value.dir == GetDirection(XCA_PEAKSWHRES);
|
|
bool isValeSWLSup = value.type == GetBoxType(XCA_VALESWLSUP) &&
|
|
value.dir == GetDirection(XCA_VALESWLSUP);
|
|
|
|
//
|
|
if (isTick)
|
|
{
|
|
result = XCA_TICK;
|
|
}
|
|
else if (isVolume)
|
|
{
|
|
result = XCA_VOLUME;
|
|
}
|
|
else if (isFVGBull)
|
|
{
|
|
result = XCA_FVG_BULL;
|
|
}
|
|
else if (isFVGBear)
|
|
{
|
|
result = XCA_FVG_BEAR;
|
|
}
|
|
else if (isRSIPeak)
|
|
{
|
|
result = XCA_RSI_PEAK;
|
|
}
|
|
else if (isRSIVale)
|
|
{
|
|
result = XCA_RSI_VALE;
|
|
}
|
|
else if (isCCIPeak)
|
|
{
|
|
result = XCA_CCI_PEAK;
|
|
}
|
|
else if (isCCIVale)
|
|
{
|
|
result = XCA_CCI_VALE;
|
|
}
|
|
else if (isRSICrossedOverOS)
|
|
{
|
|
result = XCA_RSI_COOS;
|
|
}
|
|
else if (isRSICrossedUnderOB)
|
|
{
|
|
result = XCA_RSI_CUOB;
|
|
}
|
|
else if (isCCICrossedOverOS)
|
|
{
|
|
result = XCA_CCI_COOS;
|
|
}
|
|
else if (isCCICrossedUnderOB)
|
|
{
|
|
result = XCA_CCI_CUOB;
|
|
}
|
|
else if (isTrendBullish)
|
|
{
|
|
result = XCA_TREND_BULL;
|
|
}
|
|
else if (isTrendBearish)
|
|
{
|
|
result = XCA_TREND_BEAR;
|
|
}
|
|
else if (isPeakSWHRes)
|
|
{
|
|
result = XCA_PEAKSWHRES;
|
|
}
|
|
else if (isValeSWLSup)
|
|
{
|
|
result = XCA_VALESWLSUP;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int ExtractPivots(
|
|
XBoxZone &extracted[],
|
|
ENUM_XCA_PIVOTS type,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(extracted);
|
|
|
|
//
|
|
bool has =
|
|
IsValid(type) &&
|
|
HasChild(source);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
ENUM_XCA_PIVOTS iType = GetPivotType(iBox);
|
|
|
|
//
|
|
has = iType == type;
|
|
if (has)
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
extracted //
|
|
);
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
result = ArraySize(extracted);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
struct XCAPivot
|
|
{
|
|
//
|
|
// Props ...
|
|
datetime to;
|
|
double value;
|
|
string symbol;
|
|
datetime from;
|
|
double reserve;
|
|
ENUM_XCA_PIVOTS type;
|
|
ENUM_TIMEFRAMES period;
|
|
|
|
//
|
|
double values[];
|
|
|
|
//
|
|
// Constructor ...
|
|
XCAPivot()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
/**
|
|
* Cleanup ...
|
|
*/
|
|
void Clean()
|
|
{
|
|
//
|
|
value = 0;
|
|
to = NULL;
|
|
reserve = 0;
|
|
from = NULL;
|
|
symbol = NULL;
|
|
period = NULL;
|
|
type = XCA_NONE;
|
|
|
|
//
|
|
Clean(values);
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
/**
|
|
* Validate ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
from < to &&
|
|
value != 0 &&
|
|
IsValid(to) &&
|
|
IsValid(from) &&
|
|
IsValid(type) &&
|
|
IsValid(symbol) &&
|
|
IsValid(period);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Model is Same as this or not ...
|
|
*
|
|
* @param pivot: XCAPivot ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsSameAs(XCAPivot &pivot)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
IsValid() &&
|
|
pivot.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
to == pivot.to &&
|
|
from == pivot.from &&
|
|
type == pivot.type &&
|
|
value == pivot.value &&
|
|
symbol == pivot.symbol &&
|
|
period == pivot.period;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieve To Index ...
|
|
*
|
|
* @param forPeriod: ENUM_TIMEFRAMES, Specified Period ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ToIndex(
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
result = GetBarIndex(
|
|
symbol,
|
|
forPeriod,
|
|
to //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieve From Index ...
|
|
*
|
|
* @param forPeriod: ENUM_TIMEFRAMES, Specified Period ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int FromIndex(
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
result = GetBarIndex(
|
|
symbol,
|
|
forPeriod,
|
|
from //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieve Age of Pivot ...
|
|
*
|
|
* @param forPeriod: ENUM_TIMEFRAMES, Specified Period ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetAge(
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
int toIDX = ToIndex(forPeriod);
|
|
int fromIDX = FromIndex(forPeriod);
|
|
|
|
//
|
|
result = fromIDX - toIDX;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts Pivot to Box ...
|
|
*
|
|
* @param box: XBoxZone instance reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool AsBox(
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION iDir = GetDirection(type);
|
|
|
|
//
|
|
result = HasDirection(iDir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish =
|
|
IsBullish(iDir) &&
|
|
value < reserve;
|
|
|
|
//
|
|
bool isBearish =
|
|
IsBearish(iDir) &&
|
|
value > reserve;
|
|
|
|
//
|
|
result = isBullish ||
|
|
isBearish;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = to;
|
|
box.dir = iDir;
|
|
box.from = from;
|
|
box.symbol = symbol;
|
|
box.period = period;
|
|
|
|
//
|
|
string typeStr = GetBoxType(type);
|
|
box.type = typeStr;
|
|
|
|
//
|
|
box.upper =
|
|
isBullish
|
|
? reserve
|
|
: value;
|
|
box.lower =
|
|
isBullish
|
|
? value
|
|
: reserve;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
box.Clean();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
//
|
|
struct XCATRENDFVG
|
|
{
|
|
//
|
|
XBoxZone trend;
|
|
XBoxZone fvgs[];
|
|
|
|
//
|
|
XCATRENDFVG()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
void Clean()
|
|
{
|
|
//
|
|
Clean(fvgs);
|
|
trend.Clean();
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
//
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = trend.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void AddFVG(XBoxZone &fvg)
|
|
{
|
|
//
|
|
bool has = trend.IsValid() &&
|
|
fvg.IsValid() &&
|
|
fvg.dir == trend.dir;
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
has = FindBoxIndex(
|
|
idx,
|
|
fvg,
|
|
fvgs //
|
|
);
|
|
if (has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
AddRef(
|
|
fvg,
|
|
fvgs //
|
|
);
|
|
}
|
|
|
|
//
|
|
bool IsBullish()
|
|
{
|
|
return IsValid() &&
|
|
trend.IsBullish();
|
|
}
|
|
|
|
//
|
|
bool IsBearish()
|
|
{
|
|
return IsValid() &&
|
|
trend.IsBearish();
|
|
}
|
|
|
|
//
|
|
bool GetSelectedFVG(XBoxZone &fvg)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
fvg.Clean();
|
|
|
|
//
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
if (IsBullish())
|
|
{
|
|
idx = GetLowest(fvgs);
|
|
}
|
|
else if (IsBearish())
|
|
{
|
|
idx = GetHighest(fvgs);
|
|
}
|
|
result = IsValidIndex(idx);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
fvg = fvgs[idx];
|
|
|
|
//
|
|
result = fvg.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
//
|
|
int ExtractTrendFVGs(
|
|
XBoxZone &extracteds[],
|
|
XBoxZone &trend,
|
|
XBoxZone &fvgs[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(extracteds);
|
|
|
|
//
|
|
bool has = HasChild(fvgs) &&
|
|
trend.IsValid();
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Trend Box Pivot is Valid Trend ...
|
|
ENUM_XCA_PIVOTS iType = GetPivotType(trend);
|
|
has = iType == XCA_TREND_BULL ||
|
|
iType == XCA_TREND_BEAR;
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(fvgs);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iFVG = fvgs[i];
|
|
|
|
//
|
|
bool isDirPassed = iFVG.dir == trend.dir;
|
|
bool isPricePassed = iFVG.upper <= trend.upper &&
|
|
iFVG.lower >= trend.lower;
|
|
bool isFromPassed = iFVG.from > trend.from;
|
|
has =
|
|
isDirPassed &&
|
|
isFromPassed &&
|
|
isPricePassed;
|
|
if (has)
|
|
{
|
|
//
|
|
AddRef(
|
|
iFVG,
|
|
extracteds //
|
|
);
|
|
}
|
|
|
|
//
|
|
iFVG.Clean();
|
|
}
|
|
|
|
//
|
|
result = ArraySize(extracteds);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int ExtractTrendPivots(
|
|
XCATRENDFVG &items[],
|
|
XBoxZone &boxes[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(items);
|
|
|
|
//
|
|
bool has = HasChild(boxes);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract Trend Boxes ...
|
|
XBoxZone tmp[];
|
|
XBoxZone trendBoxes[];
|
|
ExtractPivots(
|
|
tmp,
|
|
XCA_TREND_BULL,
|
|
boxes //
|
|
);
|
|
Copy(
|
|
tmp,
|
|
trendBoxes,
|
|
false //
|
|
);
|
|
Clean(tmp);
|
|
ExtractPivots(
|
|
tmp,
|
|
XCA_TREND_BEAR,
|
|
boxes //
|
|
);
|
|
Copy(
|
|
tmp,
|
|
trendBoxes,
|
|
false //
|
|
);
|
|
Clean(tmp);
|
|
|
|
//
|
|
// Check Trend Boxes Exists ...
|
|
has = HasChild(trendBoxes);
|
|
if (!has)
|
|
{
|
|
//
|
|
Clean(trendBoxes);
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract FVG Boxes ...
|
|
XBoxZone fvgBoxes[];
|
|
|
|
//
|
|
ExtractPivots(
|
|
tmp,
|
|
XCA_FVG_BULL,
|
|
boxes //
|
|
);
|
|
Copy(
|
|
tmp,
|
|
fvgBoxes,
|
|
false //
|
|
);
|
|
Clean(tmp);
|
|
ExtractPivots(
|
|
tmp,
|
|
XCA_FVG_BEAR,
|
|
boxes //
|
|
);
|
|
Copy(
|
|
tmp,
|
|
fvgBoxes,
|
|
false //
|
|
);
|
|
Clean(tmp);
|
|
bool hasFVGs = HasChild(fvgBoxes);
|
|
int fvgsCount = ArraySize(fvgBoxes);
|
|
|
|
//
|
|
// Loop through Trend Boxes to Extract XCATRENDFVG Models ...
|
|
int count = ArraySize(trendBoxes);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iTrendBox = trendBoxes[i];
|
|
|
|
//
|
|
XCATRENDFVG iTrendFVG;
|
|
iTrendFVG.trend = iTrendBox;
|
|
|
|
//
|
|
XBoxZone fvgs[];
|
|
if (hasFVGs)
|
|
{
|
|
//
|
|
int fvgsCount = ExtractTrendFVGs(
|
|
fvgs,
|
|
iTrendBox,
|
|
fvgBoxes //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
fvgs,
|
|
iTrendFVG.fvgs //
|
|
);
|
|
}
|
|
|
|
//
|
|
has = iTrendFVG.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
AddRef(
|
|
iTrendFVG,
|
|
items //
|
|
);
|
|
}
|
|
|
|
//
|
|
iTrendBox.Clean();
|
|
iTrendFVG.Clean();
|
|
}
|
|
|
|
//
|
|
Clean(tmp);
|
|
Clean(fvgBoxes);
|
|
Clean(trendBoxes);
|
|
|
|
//
|
|
result = ArraySize(items);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int GetOldest(XCATRENDFVG &items[])
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
bool has = HasChild(items);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XCATRENDFVG item;
|
|
int count = ArraySize(items);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCATRENDFVG iTrendFVG = items[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!item.IsValid()
|
|
? true
|
|
: item.trend.from > iTrendFVG.trend.from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
item = iTrendFVG;
|
|
}
|
|
|
|
//
|
|
iTrendFVG.Clean();
|
|
}
|
|
|
|
//
|
|
has = IsValidIndex(result);
|
|
item.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Implementations ...
|
|
class XCXCAEAPOIDetector : public XCBase
|
|
{
|
|
//
|
|
// Public ...
|
|
public:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
// Pivot Verifications and Max Allowed Holding Items ...
|
|
int maxAllowedPivots; // Max Allowed Holding Pibots ...
|
|
int pivotVerifications; // Pivots Verifications ...
|
|
int pivotDetectionLoopbac; // Pivots Detection Loopback ...
|
|
double ticksDividerInPoints; // Ticks and Volume Detection Divider in Point ...
|
|
ENUM_TIMEFRAMES ticksDetectionPerid; // Ticks and Volume Detection Loopback ...
|
|
|
|
//
|
|
// FVG Validations ...
|
|
int maxAllowedFVGsAge;
|
|
bool validateFVGsUsingPV;
|
|
bool validateFVGsUsingMANALYSER;
|
|
|
|
//
|
|
// TREND ...
|
|
XBoxZone trendPivotP; // Prev Pivot of Market Trend ...
|
|
XBoxZone trendPivotC; // Current Pivot of Market Trend ...
|
|
ENUM_X_DIRECTION trendDir; // Trend Direction ...
|
|
|
|
//
|
|
// Breaked Pivots ...
|
|
XBoxZone invalidPivots[];
|
|
|
|
//
|
|
// TICK Pivots ...
|
|
|
|
//
|
|
bool detectTickPivots;
|
|
XBoxZone tickPivots[];
|
|
|
|
//
|
|
// VOLUME Pivots ...
|
|
|
|
//
|
|
bool detectVolumePivots;
|
|
XBoxZone volumePivots[];
|
|
|
|
//
|
|
// RSI Peak Pivot ...
|
|
|
|
//
|
|
bool detectRSIPeakPivots;
|
|
XBoxZone rsiPeakPivots[];
|
|
bool newRSIPeakPivotDetected;
|
|
|
|
//
|
|
// RSI Vale Pivot ...
|
|
|
|
//
|
|
bool detectRSIValePivots;
|
|
XBoxZone rsiValePivots[];
|
|
bool newRSIValePivotDetected;
|
|
|
|
//
|
|
// CCI Peak Pivot ...
|
|
|
|
//
|
|
bool detectCCIPeakPivots;
|
|
XBoxZone cciPeakPivots[];
|
|
bool newCCIPeakPivotDetected;
|
|
|
|
//
|
|
// CCI Vale Pivot ...
|
|
|
|
//
|
|
bool detectCCIValePivots;
|
|
XBoxZone cciValePivots[];
|
|
bool newCCIValePivotDetected;
|
|
|
|
//
|
|
// FVG Bullish Pivots ...
|
|
|
|
//
|
|
bool detectFVGBullishPivots;
|
|
XBoxZone fvgBullishPivots[];
|
|
bool newFVGBullishPivotDetected;
|
|
|
|
//
|
|
// FVG Bearish Pivots ...
|
|
|
|
//
|
|
bool detectFVGBearishPivots;
|
|
XBoxZone fvgBearishPivots[];
|
|
bool newFVGBearishPivotDetected;
|
|
|
|
//
|
|
// VALE Pivot Support Swing Low ...
|
|
|
|
//
|
|
XCAPivot valeSupSWLPivot;
|
|
bool detectValeSupSWLPivots;
|
|
XBoxZone valeSupSWLPivots[];
|
|
bool newValeSupSWLPivotDetected;
|
|
|
|
//
|
|
// PEAK Pivot Resistance Swing High ...
|
|
|
|
//
|
|
XCAPivot peakResSWHPivot;
|
|
bool detectPeakResSWHPivots;
|
|
XBoxZone peakResSWHPivots[];
|
|
bool newPeakResSWHPivotDetected;
|
|
|
|
//
|
|
// TREND Bullish ...
|
|
|
|
//
|
|
XCAPivot trendBullishPivot;
|
|
XBoxZone trendBullishFVGs[];
|
|
bool detectTrendBullishPivots;
|
|
XCATRENDFVG trendBullishPivots[];
|
|
bool newTrendBullishPivotDetected;
|
|
|
|
//
|
|
// TREND Bearish ...
|
|
|
|
//
|
|
XCAPivot trendBearishPivot;
|
|
XBoxZone trendBearishFVGs[];
|
|
bool detectTrendBearishPivots;
|
|
XCATRENDFVG trendBearishPivots[];
|
|
bool newTrendBearishPivotDetected;
|
|
|
|
//
|
|
// RSI Crossed Over OS Pivot ...
|
|
|
|
//
|
|
bool detectRSICrossedOverOSPivots;
|
|
XBoxZone rsiCrossedOverOSPivots[];
|
|
bool newRSICrossedOverOSPivotDetected;
|
|
|
|
//
|
|
// RSI Crossed Under OB Pivot ...
|
|
|
|
//
|
|
bool detectRSICrossedUnderOBPivots;
|
|
XBoxZone rsiCrossedUnderOBPivots[];
|
|
bool newRSICrossedUnderOBPivotDetected;
|
|
|
|
//
|
|
// CCI Crossed Over OS Pivot ...
|
|
|
|
//
|
|
bool detectCCICrossedOverOSPivots;
|
|
XBoxZone cciCrossedOverOSPivots[];
|
|
bool newCCICrossedOverOSPivotDetected;
|
|
|
|
//
|
|
// CCI Crossed Under OB Pivot ...
|
|
|
|
//
|
|
bool detectCCICrossedUnderOBPivots;
|
|
XBoxZone cciCrossedUnderOBPivots[];
|
|
bool newCCICrossedUnderOBPivotDetected;
|
|
|
|
//
|
|
// Constructors ...
|
|
XCXCAEAPOIDetector(
|
|
XCXCAEAHelper *_helper //
|
|
)
|
|
{
|
|
//
|
|
helper = _helper;
|
|
drawer = new XCPOIDrawer();
|
|
barAnalyser = new XCBarAnalyser();
|
|
|
|
//
|
|
Default();
|
|
}
|
|
|
|
//
|
|
// De Constructors ...
|
|
~XCXCAEAPOIDetector()
|
|
{
|
|
//
|
|
valeSupSWLPivot.Clean();
|
|
peakResSWHPivot.Clean();
|
|
|
|
//
|
|
Clean(trendBullishFVGs);
|
|
trendBullishPivot.Clean();
|
|
|
|
//
|
|
Clean(trendBearishFVGs);
|
|
trendBearishPivot.Clean();
|
|
|
|
//
|
|
trendPivotP.Clean();
|
|
trendPivotC.Clean();
|
|
trendDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
CleanPivots();
|
|
|
|
//
|
|
ZeroMemory(helper);
|
|
ZeroMemory(drawer);
|
|
ZeroMemory(barAnalyser);
|
|
}
|
|
|
|
//
|
|
// Properties ...
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
virtual void Default()
|
|
{
|
|
//
|
|
maxAllowedPivots = 50;
|
|
pivotVerifications = 5;
|
|
ticksDividerInPoints = 15;
|
|
pivotDetectionLoopbac = 100;
|
|
ticksDetectionPerid = PERIOD_D1;
|
|
|
|
//
|
|
maxAllowedFVGsAge = 0;
|
|
validateFVGsUsingPV = false;
|
|
validateFVGsUsingMANALYSER = false;
|
|
|
|
//
|
|
detectTickPivots = true;
|
|
detectVolumePivots = true;
|
|
detectRSIPeakPivots = true;
|
|
detectRSIValePivots = true;
|
|
detectCCIPeakPivots = true;
|
|
detectCCIValePivots = true;
|
|
detectFVGBullishPivots = true;
|
|
detectFVGBearishPivots = true;
|
|
detectValeSupSWLPivots = true;
|
|
detectPeakResSWHPivots = true;
|
|
detectTrendBullishPivots = true;
|
|
detectTrendBearishPivots = true;
|
|
detectRSICrossedOverOSPivots = true;
|
|
detectRSICrossedUnderOBPivots = true;
|
|
detectCCICrossedOverOSPivots = true;
|
|
detectCCICrossedUnderOBPivots = true;
|
|
|
|
//
|
|
trendDir = X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
void Update(
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
int loopback = pivotDetectionLoopbac;
|
|
loopback = NormalizeInt(loopback, 50);
|
|
|
|
//
|
|
int idx = -1;
|
|
int count = 0;
|
|
bool has = false;
|
|
|
|
//
|
|
newRSIPeakPivotDetected = false;
|
|
newRSIValePivotDetected = false;
|
|
newCCIPeakPivotDetected = false;
|
|
newCCIValePivotDetected = false;
|
|
newFVGBullishPivotDetected = false;
|
|
newFVGBearishPivotDetected = false;
|
|
newValeSupSWLPivotDetected = false;
|
|
newPeakResSWHPivotDetected = false;
|
|
newTrendBullishPivotDetected = false;
|
|
newTrendBearishPivotDetected = false;
|
|
newRSICrossedOverOSPivotDetected = false;
|
|
newRSICrossedUnderOBPivotDetected = false;
|
|
newCCICrossedOverOSPivotDetected = false;
|
|
newCCICrossedUnderOBPivotDetected = false;
|
|
|
|
//
|
|
int zIDX = 0;
|
|
int cIDX = zIDX + 1;
|
|
int pIDX = cIDX + 1;
|
|
int p2IDX = pIDX + 1;
|
|
int p3IDX = p2IDX + 1;
|
|
|
|
//
|
|
int index = barIndex;
|
|
int start = index;
|
|
int end = index + loopback;
|
|
while (start < end)
|
|
{
|
|
//
|
|
// Retrieve Conditions ...
|
|
XCAEAConditions conditions;
|
|
has = helper.GetConditions(
|
|
conditions,
|
|
start,
|
|
10 //
|
|
);
|
|
if (!has)
|
|
{
|
|
conditions.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Retrieve Bars ...
|
|
XOHCL zBar;
|
|
XOHCL cBar;
|
|
XOHCL pBar;
|
|
XOHCL p2Bar;
|
|
has = zBar.Init(
|
|
conditions.symbol,
|
|
conditions.period,
|
|
start //
|
|
);
|
|
has =
|
|
has &&
|
|
zBar.GetPreviousBar(cBar);
|
|
has =
|
|
has &&
|
|
cBar.GetPreviousBar(pBar);
|
|
has =
|
|
has &&
|
|
pBar.GetPreviousBar(p2Bar);
|
|
if (!has)
|
|
{
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
conditions.Clean();
|
|
|
|
//
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Bars Conditions ...
|
|
|
|
//
|
|
// Bars Conditions ...
|
|
|
|
//
|
|
ENUM_X_DIRECTION cBarDir;
|
|
|
|
//
|
|
// Hammer ...
|
|
bool isCBarHammer = helper
|
|
.barAnalyser
|
|
.IsHammer(
|
|
cBar,
|
|
cBarDir //
|
|
);
|
|
bool isCBarBullishHammer =
|
|
isCBarHammer &&
|
|
IsBullish(cBarDir);
|
|
bool isCBarBearishHammer =
|
|
isCBarHammer &&
|
|
IsBearish(cBarDir);
|
|
|
|
//
|
|
// Rejected ...
|
|
bool isCBarRejected = helper
|
|
.barAnalyser
|
|
.IsRejected(
|
|
cBar,
|
|
cBarDir,
|
|
false, // Force Type ...
|
|
true // Force Fibo Pressure ...
|
|
);
|
|
bool isCBarBullishRejected =
|
|
isCBarRejected &&
|
|
IsBullish(cBarDir);
|
|
bool isCBarBearishRejected =
|
|
isCBarRejected &&
|
|
IsBearish(cBarDir);
|
|
|
|
//
|
|
// Engulfed ...
|
|
bool isCBarEngulfed = helper
|
|
.barAnalyser
|
|
.IsEngulfed(
|
|
cBar,
|
|
cBarDir //
|
|
);
|
|
bool isCBarBullishEngulfed =
|
|
isCBarEngulfed &&
|
|
IsBullish(cBarDir);
|
|
bool isCBarBearishEngulfed =
|
|
isCBarEngulfed &&
|
|
IsBearish(cBarDir);
|
|
|
|
//
|
|
// Momentum ...
|
|
bool isCBarMomentum = helper
|
|
.barAnalyser
|
|
.IsMomentum(
|
|
cBar,
|
|
cBarDir,
|
|
1 //
|
|
);
|
|
bool isCBarBullishMomentum =
|
|
isCBarMomentum &&
|
|
IsBullish(cBarDir);
|
|
bool isCBarBearishMomentum =
|
|
isCBarMomentum &&
|
|
IsBearish(cBarDir);
|
|
|
|
//
|
|
// FVG ...
|
|
|
|
//
|
|
XBoxZone fvgBox;
|
|
bool isFVG = barAnalyser.IsFVG(
|
|
cBar,
|
|
fvgBox //
|
|
);
|
|
bool isBullishFVG =
|
|
isFVG &&
|
|
fvgBox.IsBullish();
|
|
bool isBearishFVG =
|
|
isFVG &&
|
|
fvgBox.IsBearish();
|
|
|
|
//
|
|
bool isCBarHasBullishPower = isBullishFVG ||
|
|
isCBarBullishRejected ||
|
|
isCBarBullishEngulfed ||
|
|
isCBarBullishMomentum;
|
|
|
|
//
|
|
bool isCBarHasBearishPower = isBearishFVG ||
|
|
isCBarBearishRejected ||
|
|
isCBarBearishEngulfed ||
|
|
isCBarBearishMomentum;
|
|
|
|
//
|
|
// Reading Values from Conditions and
|
|
// Create Customized Conditions if required ...
|
|
|
|
//
|
|
// PEAK ...
|
|
double zPeak = conditions.peakBuffer[zIDX];
|
|
double cPeak = conditions.peakBuffer[cIDX];
|
|
double pPeak = conditions.peakBuffer[pIDX];
|
|
double p2Peak = conditions.peakBuffer[p2IDX];
|
|
|
|
//
|
|
// VALE ...
|
|
double zVale = conditions.valeBuffer[zIDX];
|
|
double cVale = conditions.valeBuffer[cIDX];
|
|
double pVale = conditions.valeBuffer[pIDX];
|
|
double p2Vale = conditions.valeBuffer[p2IDX];
|
|
|
|
//
|
|
// MANALYSER ...
|
|
|
|
//
|
|
// MAH ...
|
|
double zMAH = conditions.mahBuffer[zIDX];
|
|
double cMAH = conditions.mahBuffer[cIDX];
|
|
double pMAH = conditions.mahBuffer[pIDX];
|
|
double p2MAH = conditions.mahBuffer[p2IDX];
|
|
|
|
//
|
|
// MAL ...
|
|
double zMAL = conditions.malBuffer[zIDX];
|
|
double cMAL = conditions.malBuffer[cIDX];
|
|
double pMAL = conditions.malBuffer[pIDX];
|
|
double p2MAL = conditions.malBuffer[p2IDX];
|
|
|
|
//
|
|
// MAC ...
|
|
double zMAC = conditions.macBuffer[zIDX];
|
|
double cMAC = conditions.macBuffer[cIDX];
|
|
double pMAC = conditions.macBuffer[pIDX];
|
|
double p2MAC = conditions.macBuffer[p2IDX];
|
|
|
|
//
|
|
// RSI ...
|
|
|
|
//
|
|
double zRSI = conditions.rsiBuffer[zIDX];
|
|
double cRSI = conditions.rsiBuffer[cIDX];
|
|
double pRSI = conditions.rsiBuffer[pIDX];
|
|
double p2RSI = conditions.rsiBuffer[p2IDX];
|
|
|
|
//
|
|
bool isRSIPeak =
|
|
pRSI > cRSI &&
|
|
pRSI > p2RSI &&
|
|
pRSI > zRSI;
|
|
|
|
//
|
|
bool isRSIVale =
|
|
pRSI < cRSI &&
|
|
pRSI < p2RSI &&
|
|
pRSI < zRSI;
|
|
|
|
//
|
|
// CCI ...
|
|
|
|
//
|
|
double zCCI = conditions.cciBuffer[zIDX];
|
|
double cCCI = conditions.cciBuffer[cIDX];
|
|
double pCCI = conditions.cciBuffer[pIDX];
|
|
double p2CCI = conditions.cciBuffer[p2IDX];
|
|
|
|
//
|
|
bool isCCIPeak =
|
|
pCCI > cCCI &&
|
|
pCCI > p2CCI &&
|
|
pCCI > zCCI;
|
|
|
|
//
|
|
bool isCCIVale =
|
|
pCCI < cCCI &&
|
|
pCCI < p2CCI &&
|
|
pCCI < zCCI;
|
|
|
|
//
|
|
// ATR ...
|
|
double zATR = conditions.atrBuffer[zIDX];
|
|
double cATR = conditions.atrBuffer[cIDX];
|
|
double pATR = conditions.atrBuffer[pIDX];
|
|
double p2ATR = conditions.atrBuffer[p2IDX];
|
|
|
|
//
|
|
double atrSum = GetSum(conditions.atrBuffer);
|
|
double atrMax = GetMax(conditions.atrBuffer);
|
|
double atrMin = GetMin(conditions.atrBuffer);
|
|
double atrAvg = GetAverage(conditions.atrBuffer);
|
|
|
|
//
|
|
// Extracting Required Data about Trending ...
|
|
|
|
//
|
|
double zFast = conditions.fastBuffer[zIDX];
|
|
double cFast = conditions.fastBuffer[cIDX];
|
|
double pFast = conditions.fastBuffer[pIDX];
|
|
double p2Fast = conditions.fastBuffer[p2IDX];
|
|
|
|
//
|
|
double zMedium = conditions.mediumBuffer[zIDX];
|
|
double cMedium = conditions.mediumBuffer[cIDX];
|
|
double pMedium = conditions.mediumBuffer[pIDX];
|
|
double p2Medium = conditions.mediumBuffer[p2IDX];
|
|
|
|
//
|
|
double zSlow = conditions.slowBuffer[zIDX];
|
|
double cSlow = conditions.slowBuffer[cIDX];
|
|
double pSlow = conditions.slowBuffer[pIDX];
|
|
double p2Slow = conditions.slowBuffer[p2IDX];
|
|
|
|
//
|
|
double z3Mas[] = {
|
|
zFast,
|
|
zMedium,
|
|
zSlow,
|
|
};
|
|
double z3MasMin = GetMin(z3Mas);
|
|
double z3MasMax = GetMax(z3Mas);
|
|
|
|
//
|
|
double c3Mas[] = {
|
|
cFast,
|
|
cMedium,
|
|
cSlow,
|
|
};
|
|
double c3MasMin = GetMin(c3Mas);
|
|
double c3MasMax = GetMax(c3Mas);
|
|
|
|
//
|
|
double p3Mas[] = {
|
|
pFast,
|
|
pMedium,
|
|
pSlow,
|
|
};
|
|
double p3MasMin = GetMin(p3Mas);
|
|
double p3MasMax = GetMax(p3Mas);
|
|
|
|
//
|
|
double p23Mas[] = {
|
|
p2Fast,
|
|
p2Medium,
|
|
p2Slow,
|
|
};
|
|
double p23MasMin = GetMin(p23Mas);
|
|
double p23MasMax = GetMax(p23Mas);
|
|
|
|
//
|
|
// Try to Custom Mechanism for Trend Detection ...
|
|
|
|
//
|
|
bool is3MaBullish =
|
|
cFast > cSlow &&
|
|
cMedium > cSlow;
|
|
bool is3MaBullishPrev =
|
|
pFast > pSlow &&
|
|
pMedium > pSlow;
|
|
|
|
//
|
|
bool is3MaBearish =
|
|
cFast < cSlow &&
|
|
cMedium < cSlow;
|
|
bool is3MaBearishPrev =
|
|
pFast < pSlow &&
|
|
pMedium < pSlow;
|
|
|
|
//
|
|
bool is3MaSwitchedToBullish = is3MaBullish &&
|
|
!is3MaBullishPrev;
|
|
bool is3MaSwitchedToBearish = is3MaBearish &&
|
|
!is3MaBearishPrev;
|
|
|
|
//
|
|
bool is3MaFinishedFromBullish = !is3MaBullish &&
|
|
is3MaBullishPrev;
|
|
bool is3MaFinishedFromBearish = !is3MaBearish &&
|
|
is3MaBearishPrev;
|
|
|
|
//
|
|
// TREND BULLISH Conditions ...
|
|
|
|
//
|
|
bool trendBullishStartPivotCondition =
|
|
//
|
|
// One ...
|
|
// conditions.is3MaFinishedFromBullish
|
|
// //
|
|
// ||
|
|
//
|
|
// Two ...
|
|
is3MaFinishedFromBullish
|
|
//
|
|
;
|
|
|
|
//
|
|
bool trendBullishPivotContinuationCondition =
|
|
//
|
|
// One ...
|
|
// conditions.is3MaBullish
|
|
// //
|
|
// ||
|
|
//
|
|
// Two ...
|
|
is3MaBullish
|
|
//
|
|
;
|
|
|
|
//
|
|
bool trendBullisPivothFinishedCondition =
|
|
//
|
|
// One ...
|
|
// conditions.is3MaSwitchedToBullish
|
|
// //
|
|
// ||
|
|
//
|
|
// Two ...
|
|
is3MaSwitchedToBullish
|
|
//
|
|
;
|
|
|
|
//
|
|
// TREND BEARISH Conditions ...
|
|
|
|
//
|
|
bool trendBearishStartPivotCondition =
|
|
//
|
|
// One ...
|
|
// conditions.is3MaFinishedFromBearish
|
|
// //
|
|
// ||
|
|
//
|
|
// Two ...
|
|
is3MaFinishedFromBearish
|
|
//
|
|
;
|
|
|
|
//
|
|
bool trendBearishPivotContinuationCondition =
|
|
//
|
|
// One ...
|
|
// conditions.is3MaBearish
|
|
// //
|
|
// ||
|
|
//
|
|
// Two ...
|
|
is3MaBearish
|
|
//
|
|
;
|
|
|
|
//
|
|
bool trendBearishivothFinishedCondition =
|
|
//
|
|
// One ...
|
|
// conditions.is3MaSwitchedToBearish
|
|
// //
|
|
// ||
|
|
//
|
|
// Two ...
|
|
is3MaSwitchedToBearish
|
|
//
|
|
;
|
|
|
|
//
|
|
// Checking Pivots ...
|
|
|
|
//
|
|
// Detect TICK and VOLUME Pivots ...
|
|
if (detectTickPivots || detectVolumePivots)
|
|
{
|
|
//
|
|
XOHCL ticksToBar;
|
|
XOHCL ticksFromBar;
|
|
XCTicksZone *ticksZone = NULL;
|
|
|
|
//
|
|
datetime ticksTo = GetPeriodStartTime(
|
|
zBar.symbol,
|
|
ticksDetectionPerid,
|
|
zBar.time //
|
|
);
|
|
bool isTicksBarInited = ticksToBar.Init(
|
|
zBar.symbol,
|
|
zBar.period,
|
|
ticksTo //
|
|
);
|
|
datetime ticksFrom = ticksTo - PeriodSeconds(ticksDetectionPerid);
|
|
isTicksBarInited = isTicksBarInited &&
|
|
ticksFromBar.Init(
|
|
zBar.symbol,
|
|
zBar.period,
|
|
ticksFrom //
|
|
);
|
|
bool hasValidTicksTimeRange = IsValid(ticksTo) &&
|
|
isTicksBarInited &&
|
|
IsValid(ticksFrom) &&
|
|
ticksFrom < ticksTo;
|
|
|
|
//
|
|
bool isTickPivotExists =
|
|
hasValidTicksTimeRange &&
|
|
IsExistsTickPivot(
|
|
ticksTo,
|
|
ticksFrom //
|
|
);
|
|
|
|
//
|
|
bool isVolumePivotExists =
|
|
hasValidTicksTimeRange &&
|
|
IsExistsVolumePivot(
|
|
ticksTo,
|
|
ticksFrom //
|
|
);
|
|
|
|
//
|
|
bool isInitializedZone = !isTickPivotExists ||
|
|
!isVolumePivotExists;
|
|
if (isInitializedZone)
|
|
{
|
|
//
|
|
isInitializedZone = InitializeTicksZone(
|
|
ticksZone,
|
|
ticksToBar,
|
|
ticksFromBar //
|
|
);
|
|
}
|
|
|
|
//
|
|
// TICK Pivots ...
|
|
if (detectTickPivots)
|
|
{
|
|
//
|
|
// Check Current Zone Exists or Not ...
|
|
if (isInitializedZone && !isTickPivotExists)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
XCTickZone *iZone;
|
|
has = ticksZone.GetMaxTickZone(iZone);
|
|
if (has)
|
|
{
|
|
//
|
|
// Try to Converts a Tick Zone to XBoxZone ...
|
|
iBox.to = ticksTo;
|
|
iBox.from = ticksFrom;
|
|
iBox.lower = iZone.low;
|
|
iBox.upper = iZone.high;
|
|
iBox.symbol = iZone.symbol;
|
|
iBox.period = iZone.period;
|
|
iBox.type = GetBoxType(XCA_TICK);
|
|
iBox.dir = X_DIRECTION_BULLISH; // Temparory ...
|
|
|
|
//
|
|
has = iBox.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
AddBox(
|
|
iBox,
|
|
tickPivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
ZeroMemory(iZone);
|
|
}
|
|
}
|
|
|
|
//
|
|
// VOLUME Pivots ...
|
|
if (detectVolumePivots)
|
|
{
|
|
//
|
|
// Check Current Zone Exists or Not ...
|
|
if (isInitializedZone && !isVolumePivotExists)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
XCTickZone *iZone;
|
|
has = ticksZone.GetMaxVolumeZone(iZone);
|
|
if (has)
|
|
{
|
|
//
|
|
// Try to Converts a Tick Zone to XBoxZone ...
|
|
iBox.to = ticksTo;
|
|
iBox.from = ticksFrom;
|
|
iBox.lower = iZone.low;
|
|
iBox.upper = iZone.high;
|
|
iBox.symbol = iZone.symbol;
|
|
iBox.period = iZone.period;
|
|
iBox.type = GetBoxType(XCA_VOLUME);
|
|
iBox.dir = X_DIRECTION_BULLISH; // Temparory ...
|
|
|
|
//
|
|
has = iBox.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
AddBox(
|
|
iBox,
|
|
volumePivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
ZeroMemory(iZone);
|
|
}
|
|
}
|
|
|
|
//
|
|
ticksToBar.Clean();
|
|
ticksFromBar.Clean();
|
|
ZeroMemory(ticksZone);
|
|
|
|
//
|
|
}
|
|
|
|
//
|
|
// RSI Peak Pivot ...
|
|
if (detectRSIPeakPivots)
|
|
{
|
|
//
|
|
bool checkingCondition =
|
|
isRSIPeak &&
|
|
isCBarHasBearishPower // &&
|
|
// conditions.isRSICrossedUnderOB
|
|
;
|
|
|
|
//
|
|
if (checkingCondition)
|
|
{
|
|
//
|
|
XCAPivot iPivot;
|
|
|
|
//
|
|
iPivot.to = cBar.time;
|
|
iPivot.from = p2Bar.time;
|
|
iPivot.value = pBar.high;
|
|
iPivot.type = XCA_RSI_PEAK;
|
|
iPivot.symbol = cBar.symbol;
|
|
iPivot.period = cBar.period;
|
|
|
|
//
|
|
Add(
|
|
cBar.high,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
pBar.high,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
p2Bar.high,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
cBar.close,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
pBar.close,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
p2Bar.close,
|
|
iPivot.values //
|
|
);
|
|
|
|
//
|
|
iPivot.reserve = GetMin(iPivot.values);
|
|
|
|
//
|
|
XBoxZone iBox;
|
|
has = iPivot.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
has = iPivot.AsBox(iBox);
|
|
if (has)
|
|
{
|
|
//
|
|
newRSIPeakPivotDetected = AddBox(
|
|
iBox,
|
|
rsiPeakPivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
iPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// RSI Vale Pivot ...
|
|
if (detectRSIValePivots)
|
|
{
|
|
//
|
|
bool checkingCondition =
|
|
isRSIVale &&
|
|
isCBarHasBullishPower // &&
|
|
// conditions.isRSICrossedOverOS
|
|
;
|
|
|
|
//
|
|
if (checkingCondition)
|
|
{
|
|
//
|
|
XCAPivot iPivot;
|
|
|
|
//
|
|
iPivot.to = cBar.time;
|
|
iPivot.from = p2Bar.time;
|
|
iPivot.value = pBar.low;
|
|
iPivot.type = XCA_RSI_VALE;
|
|
iPivot.symbol = cBar.symbol;
|
|
iPivot.period = cBar.period;
|
|
|
|
//
|
|
Add(
|
|
cBar.low,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
pBar.low,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
p2Bar.low,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
cBar.close,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
pBar.close,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
p2Bar.close,
|
|
iPivot.values //
|
|
);
|
|
|
|
//
|
|
iPivot.reserve = GetMax(iPivot.values);
|
|
|
|
//
|
|
XBoxZone iBox;
|
|
has = iPivot.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
has = iPivot.AsBox(iBox);
|
|
if (has)
|
|
{
|
|
//
|
|
newRSIValePivotDetected = AddBox(
|
|
iBox,
|
|
rsiValePivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
iPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// CCI Peak Pivot ...
|
|
if (detectCCIPeakPivots)
|
|
{
|
|
//
|
|
bool checkingCondition =
|
|
isCCIPeak &&
|
|
isCBarHasBearishPower // &&
|
|
// conditions.isCCICrossedUnderOB
|
|
;
|
|
|
|
//
|
|
if (checkingCondition)
|
|
{
|
|
//
|
|
XCAPivot iPivot;
|
|
|
|
//
|
|
iPivot.to = cBar.time;
|
|
iPivot.from = p2Bar.time;
|
|
iPivot.value = pBar.high;
|
|
iPivot.type = XCA_CCI_PEAK;
|
|
iPivot.symbol = cBar.symbol;
|
|
iPivot.period = cBar.period;
|
|
|
|
//
|
|
Add(
|
|
cBar.high,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
pBar.high,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
p2Bar.high,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
cBar.close,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
pBar.close,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
p2Bar.close,
|
|
iPivot.values //
|
|
);
|
|
|
|
//
|
|
iPivot.reserve = GetMin(iPivot.values);
|
|
|
|
//
|
|
XBoxZone iBox;
|
|
has = iPivot.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
has = iPivot.AsBox(iBox);
|
|
if (has)
|
|
{
|
|
//
|
|
newCCIPeakPivotDetected = AddBox(
|
|
iBox,
|
|
cciPeakPivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
iPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// CCI Vale Pivot ...
|
|
if (detectCCIValePivots)
|
|
{
|
|
//
|
|
bool checkingCondition =
|
|
isCCIVale &&
|
|
isCBarHasBullishPower // &&
|
|
// conditions.isCCICrossedOverOS
|
|
;
|
|
|
|
//
|
|
if (checkingCondition)
|
|
{
|
|
//
|
|
XCAPivot iPivot;
|
|
|
|
//
|
|
iPivot.to = cBar.time;
|
|
iPivot.from = p2Bar.time;
|
|
iPivot.value = pBar.low;
|
|
iPivot.type = XCA_CCI_VALE;
|
|
iPivot.symbol = cBar.symbol;
|
|
iPivot.period = cBar.period;
|
|
|
|
//
|
|
Add(
|
|
cBar.low,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
pBar.low,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
p2Bar.low,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
cBar.close,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
pBar.close,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
p2Bar.close,
|
|
iPivot.values //
|
|
);
|
|
|
|
//
|
|
iPivot.reserve = GetMax(iPivot.values);
|
|
|
|
//
|
|
XBoxZone iBox;
|
|
has = iPivot.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
has = iPivot.AsBox(iBox);
|
|
if (has)
|
|
{
|
|
//
|
|
newCCIValePivotDetected = AddBox(
|
|
iBox,
|
|
cciValePivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
iPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// FVG Bullish ...
|
|
if (detectFVGBullishPivots)
|
|
{
|
|
//
|
|
bool checkingCondition =
|
|
//
|
|
isBullishFVG &&
|
|
//
|
|
fvgBox.upper < cMAL
|
|
//
|
|
// (cPeak > pPeak ||
|
|
// pPeak > p2Peak)
|
|
//
|
|
;
|
|
|
|
//
|
|
if (checkingCondition)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
XCAPivot iPivot;
|
|
|
|
//
|
|
iPivot.to = fvgBox.to;
|
|
iPivot.from = fvgBox.from;
|
|
iPivot.type = XCA_FVG_BULL;
|
|
iPivot.value = fvgBox.lower;
|
|
iPivot.reserve = fvgBox.upper;
|
|
iPivot.symbol = fvgBox.symbol;
|
|
iPivot.period = fvgBox.period;
|
|
|
|
//
|
|
has = iPivot.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
has = iPivot.AsBox(iBox);
|
|
if (has)
|
|
{
|
|
//
|
|
newFVGBullishPivotDetected = AddBox(
|
|
iBox,
|
|
fvgBullishPivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
iPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// FVG Bearish ...
|
|
if (detectFVGBearishPivots)
|
|
{
|
|
//
|
|
bool checkingCondition =
|
|
//
|
|
isBearishFVG &&
|
|
//
|
|
fvgBox.lower > cMAH
|
|
//
|
|
// (cVale < pVale ||
|
|
// pVale < p2Vale)
|
|
//
|
|
;
|
|
|
|
//
|
|
if (checkingCondition)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
XCAPivot iPivot;
|
|
|
|
//
|
|
iPivot.to = fvgBox.to;
|
|
iPivot.from = fvgBox.from;
|
|
iPivot.type = XCA_FVG_BEAR;
|
|
iPivot.value = fvgBox.upper;
|
|
iPivot.reserve = fvgBox.lower;
|
|
iPivot.symbol = fvgBox.symbol;
|
|
iPivot.period = fvgBox.period;
|
|
|
|
//
|
|
has = iPivot.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
has = iPivot.AsBox(iBox);
|
|
if (has)
|
|
{
|
|
//
|
|
newFVGBearishPivotDetected = AddBox(
|
|
iBox,
|
|
fvgBearishPivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
iPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// VALE Pivot Support Swing Low ...
|
|
if (detectValeSupSWLPivots)
|
|
{
|
|
//
|
|
if (conditions.isValeFinishedFromPivot)
|
|
{
|
|
//
|
|
valeSupSWLPivot.Clean();
|
|
|
|
//
|
|
valeSupSWLPivot.type = XCA_VALESWLSUP;
|
|
valeSupSWLPivot.symbol = conditions.symbol;
|
|
valeSupSWLPivot.period = conditions.period;
|
|
|
|
//
|
|
valeSupSWLPivot.to = pBar.time;
|
|
valeSupSWLPivot.from = pBar.time;
|
|
valeSupSWLPivot.value = conditions.valeBuffer[pIDX];
|
|
valeSupSWLPivot.reserve = conditions.valeGoldenBuffer[pIDX];
|
|
}
|
|
|
|
//
|
|
if (conditions.isValeIsPivot)
|
|
{
|
|
//
|
|
valeSupSWLPivot.from = pBar.time;
|
|
|
|
//
|
|
valeSupSWLPivot.reserve =
|
|
valeSupSWLPivot.reserve == 0
|
|
? conditions.valeGoldenBuffer[cIDX]
|
|
: MathMin(valeSupSWLPivot.reserve, conditions.valeGoldenBuffer[cIDX]);
|
|
}
|
|
|
|
//
|
|
if (conditions.isValeSwitchedToPivot)
|
|
{
|
|
//
|
|
has =
|
|
valeSupSWLPivot.IsValid() &&
|
|
valeSupSWLPivot.GetAge() >= pivotVerifications;
|
|
if (has)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
has = valeSupSWLPivot.AsBox(iBox);
|
|
if (has)
|
|
{
|
|
//
|
|
newValeSupSWLPivotDetected = AddBox(
|
|
iBox,
|
|
valeSupSWLPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
valeSupSWLPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// PEAK Pivot Resistance Swing High ...
|
|
if (detectPeakResSWHPivots)
|
|
{
|
|
//
|
|
if (conditions.isPeakFinishedFromPivot)
|
|
{
|
|
//
|
|
peakResSWHPivot.Clean();
|
|
|
|
//
|
|
peakResSWHPivot.type = XCA_PEAKSWHRES;
|
|
peakResSWHPivot.symbol = conditions.symbol;
|
|
peakResSWHPivot.period = conditions.period;
|
|
|
|
//
|
|
peakResSWHPivot.to = pBar.time;
|
|
peakResSWHPivot.from = pBar.time;
|
|
peakResSWHPivot.value = conditions.peakBuffer[pIDX];
|
|
peakResSWHPivot.reserve = conditions.peakGoldenBuffer[pIDX];
|
|
}
|
|
|
|
//
|
|
if (conditions.isPeakIsPivot)
|
|
{
|
|
//
|
|
peakResSWHPivot.from = pBar.time;
|
|
|
|
//
|
|
peakResSWHPivot.reserve =
|
|
peakResSWHPivot.reserve == 0
|
|
? conditions.peakGoldenBuffer[cIDX]
|
|
: MathMax(peakResSWHPivot.reserve, conditions.peakGoldenBuffer[cIDX]);
|
|
}
|
|
|
|
//
|
|
if (conditions.isPeakSwitchedToPivot)
|
|
{
|
|
//
|
|
has =
|
|
peakResSWHPivot.IsValid() &&
|
|
peakResSWHPivot.GetAge() >= pivotVerifications;
|
|
if (has)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
has = peakResSWHPivot.AsBox(iBox);
|
|
if (has)
|
|
{
|
|
//
|
|
newPeakResSWHPivotDetected = AddBox(
|
|
iBox,
|
|
peakResSWHPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
peakResSWHPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// TREND Bullish ...
|
|
if (detectTrendBullishPivots)
|
|
{
|
|
//
|
|
if (trendBullishStartPivotCondition)
|
|
{
|
|
//
|
|
Clean(trendBullishFVGs);
|
|
trendBullishPivot.Clean();
|
|
|
|
//
|
|
trendBullishPivot.type = XCA_TREND_BULL;
|
|
trendBullishPivot.symbol = conditions.symbol;
|
|
trendBullishPivot.period = conditions.period;
|
|
|
|
//
|
|
trendBullishPivot.to = pBar.time;
|
|
trendBullishPivot.from = pBar.time;
|
|
trendBullishPivot.value = p3MasMin;
|
|
trendBullishPivot.reserve = p3MasMax;
|
|
}
|
|
|
|
//
|
|
if (trendBullishPivotContinuationCondition)
|
|
{
|
|
//
|
|
trendBullishPivot.from = pBar.time;
|
|
|
|
//
|
|
Add(
|
|
p3MasMin,
|
|
trendBullishPivot.values //
|
|
);
|
|
Add(
|
|
p3MasMax,
|
|
trendBullishPivot.values //
|
|
);
|
|
|
|
//
|
|
trendBullishPivot.reserve =
|
|
trendBullishPivot.reserve == 0
|
|
? p3MasMax
|
|
: MathMax(trendBullishPivot.reserve, p3MasMax);
|
|
|
|
//
|
|
// Handling FVGs Here ...
|
|
if (isBullishFVG)
|
|
{
|
|
//
|
|
fvgBox.type = GetBoxType(XCA_FVG_BULL);
|
|
|
|
//
|
|
AddBox(
|
|
fvgBox,
|
|
trendBullishFVGs //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
if (trendBullisPivothFinishedCondition)
|
|
{
|
|
//
|
|
// Update Values ...
|
|
trendBullishPivot.value = GetMin(trendBullishPivot.values);
|
|
trendBullishPivot.reserve = GetMax(trendBullishPivot.values);
|
|
|
|
//
|
|
has =
|
|
trendBullishPivot.IsValid() &&
|
|
trendBullishPivot.GetAge() >= pivotVerifications;
|
|
if (has)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
has = trendBullishPivot.AsBox(iBox);
|
|
if (has)
|
|
{
|
|
//
|
|
XCATRENDFVG iTrendFVG;
|
|
|
|
//
|
|
iTrendFVG.trend = iBox;
|
|
Copy(
|
|
trendBullishFVGs,
|
|
iTrendFVG.fvgs //
|
|
);
|
|
|
|
//
|
|
newTrendBullishPivotDetected = iTrendFVG.IsValid();
|
|
if (newTrendBullishPivotDetected)
|
|
{
|
|
//
|
|
AddRef(
|
|
iTrendFVG,
|
|
trendBullishPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
iTrendFVG.Clean();
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
Clean(trendBullishFVGs);
|
|
trendBullishPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// TREND Bearish ...
|
|
if (detectTrendBearishPivots)
|
|
{
|
|
//
|
|
if (trendBearishStartPivotCondition)
|
|
{
|
|
//
|
|
Clean(trendBearishFVGs);
|
|
trendBearishPivot.Clean();
|
|
|
|
//
|
|
trendBearishPivot.type = XCA_TREND_BEAR;
|
|
trendBearishPivot.symbol = conditions.symbol;
|
|
trendBearishPivot.period = conditions.period;
|
|
|
|
//
|
|
trendBearishPivot.to = pBar.time;
|
|
trendBearishPivot.from = pBar.time;
|
|
trendBearishPivot.value = p3MasMax;
|
|
trendBearishPivot.reserve = p3MasMin;
|
|
}
|
|
|
|
//
|
|
if (trendBearishPivotContinuationCondition)
|
|
{
|
|
//
|
|
trendBearishPivot.from = pBar.time;
|
|
|
|
//
|
|
Add(
|
|
p3MasMin,
|
|
trendBearishPivot.values //
|
|
);
|
|
Add(
|
|
p3MasMax,
|
|
trendBearishPivot.values //
|
|
);
|
|
|
|
//
|
|
trendBearishPivot.reserve =
|
|
trendBearishPivot.reserve == 0
|
|
? p3MasMin
|
|
: MathMin(trendBearishPivot.reserve, p3MasMin);
|
|
|
|
//
|
|
// Handling FVGs Here ...
|
|
if (isBearishFVG)
|
|
{
|
|
//
|
|
fvgBox.type = GetBoxType(XCA_FVG_BEAR);
|
|
|
|
//
|
|
AddBox(
|
|
fvgBox,
|
|
trendBearishFVGs //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
if (trendBearishivothFinishedCondition)
|
|
{
|
|
//
|
|
// Update Values ...
|
|
trendBearishPivot.value = GetMax(trendBearishPivot.values);
|
|
trendBearishPivot.reserve = GetMin(trendBearishPivot.values);
|
|
|
|
//
|
|
has =
|
|
trendBearishPivot.IsValid() &&
|
|
trendBearishPivot.GetAge() >= pivotVerifications;
|
|
if (has)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
has = trendBearishPivot.AsBox(iBox);
|
|
if (has)
|
|
{
|
|
//
|
|
XCATRENDFVG iTrendFVG;
|
|
|
|
//
|
|
iTrendFVG.trend = iBox;
|
|
Copy(
|
|
trendBearishFVGs,
|
|
iTrendFVG.fvgs //
|
|
);
|
|
|
|
//
|
|
newTrendBearishPivotDetected = iTrendFVG.IsValid();
|
|
if (newTrendBearishPivotDetected)
|
|
{
|
|
//
|
|
AddRef(
|
|
iTrendFVG,
|
|
trendBearishPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
iTrendFVG.Clean();
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
Clean(trendBearishFVGs);
|
|
trendBearishPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// RSI Crossed Over OS ...
|
|
if (detectRSICrossedOverOSPivots)
|
|
{
|
|
//
|
|
bool checkingCondition =
|
|
// isRSIVale &&
|
|
// isCBarHasBullishPower &&
|
|
conditions.isRSICrossedOverOS;
|
|
|
|
//
|
|
if (checkingCondition)
|
|
{
|
|
//
|
|
XCAPivot iPivot;
|
|
|
|
//
|
|
iPivot.to = cBar.time;
|
|
iPivot.value = pBar.low;
|
|
iPivot.from = p2Bar.time;
|
|
iPivot.type = XCA_RSI_COOS;
|
|
iPivot.symbol = cBar.symbol;
|
|
iPivot.period = cBar.period;
|
|
|
|
//
|
|
Add(
|
|
cBar.high,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
pBar.high,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
p2Bar.high,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
cBar.low,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
pBar.low,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
p2Bar.low,
|
|
iPivot.values //
|
|
);
|
|
|
|
//
|
|
iPivot.value = GetMin(iPivot.values);
|
|
iPivot.reserve = GetMax(iPivot.values);
|
|
|
|
//
|
|
XBoxZone iBox;
|
|
has = iPivot.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
has = iPivot.AsBox(iBox);
|
|
if (has)
|
|
{
|
|
//
|
|
newRSICrossedOverOSPivotDetected = AddBox(
|
|
iBox,
|
|
rsiCrossedOverOSPivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
iPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// RSI Crossed Under OB ...
|
|
if (detectRSICrossedUnderOBPivots)
|
|
{
|
|
//
|
|
bool checkingCondition =
|
|
// isRSIPeak &&
|
|
// isCBarHasBearishPower &&
|
|
conditions.isRSICrossedUnderOB;
|
|
|
|
//
|
|
if (checkingCondition)
|
|
{
|
|
//
|
|
XCAPivot iPivot;
|
|
|
|
//
|
|
iPivot.to = cBar.time;
|
|
iPivot.from = p2Bar.time;
|
|
iPivot.value = pBar.high;
|
|
iPivot.type = XCA_RSI_CUOB;
|
|
iPivot.symbol = cBar.symbol;
|
|
iPivot.period = cBar.period;
|
|
|
|
//
|
|
Add(
|
|
cBar.high,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
pBar.high,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
p2Bar.high,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
cBar.low,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
pBar.low,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
p2Bar.low,
|
|
iPivot.values //
|
|
);
|
|
|
|
//
|
|
iPivot.value = GetMax(iPivot.values);
|
|
iPivot.reserve = GetMin(iPivot.values);
|
|
|
|
//
|
|
XBoxZone iBox;
|
|
has = iPivot.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
has = iPivot.AsBox(iBox);
|
|
if (has)
|
|
{
|
|
//
|
|
newRSICrossedUnderOBPivotDetected = AddBox(
|
|
iBox,
|
|
rsiCrossedUnderOBPivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
iPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// CCI Crossed Over OS ...
|
|
if (detectCCICrossedOverOSPivots)
|
|
{
|
|
//
|
|
bool checkingCondition =
|
|
isCCIVale &&
|
|
// isCBarHasBullishPower &&
|
|
conditions.isCCICrossedOverOS;
|
|
|
|
//
|
|
if (checkingCondition)
|
|
{
|
|
//
|
|
XCAPivot iPivot;
|
|
|
|
//
|
|
iPivot.to = cBar.time;
|
|
iPivot.value = pBar.low;
|
|
iPivot.from = p2Bar.time;
|
|
iPivot.type = XCA_CCI_COOS;
|
|
iPivot.symbol = cBar.symbol;
|
|
iPivot.period = cBar.period;
|
|
|
|
//
|
|
Add(
|
|
cBar.high,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
pBar.high,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
p2Bar.high,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
cBar.low,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
pBar.low,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
p2Bar.low,
|
|
iPivot.values //
|
|
);
|
|
|
|
//
|
|
iPivot.value = GetMin(iPivot.values);
|
|
iPivot.reserve = GetMax(iPivot.values);
|
|
|
|
//
|
|
XBoxZone iBox;
|
|
has = iPivot.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
has = iPivot.AsBox(iBox);
|
|
if (has)
|
|
{
|
|
//
|
|
newCCICrossedOverOSPivotDetected = AddBox(
|
|
iBox,
|
|
cciCrossedOverOSPivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
iPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// CCI Crossed Under OB ...
|
|
if (detectCCICrossedUnderOBPivots)
|
|
{
|
|
//
|
|
bool checkingCondition =
|
|
isCCIPeak &&
|
|
// isCBarHasBearishPower &&
|
|
conditions.isCCICrossedUnderOB;
|
|
|
|
//
|
|
if (checkingCondition)
|
|
{
|
|
//
|
|
XCAPivot iPivot;
|
|
|
|
//
|
|
iPivot.to = cBar.time;
|
|
iPivot.from = p2Bar.time;
|
|
iPivot.value = pBar.high;
|
|
iPivot.type = XCA_CCI_CUOB;
|
|
iPivot.symbol = cBar.symbol;
|
|
iPivot.period = cBar.period;
|
|
|
|
//
|
|
Add(
|
|
cBar.high,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
pBar.high,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
p2Bar.high,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
cBar.low,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
pBar.low,
|
|
iPivot.values //
|
|
);
|
|
Add(
|
|
p2Bar.low,
|
|
iPivot.values //
|
|
);
|
|
|
|
//
|
|
iPivot.value = GetMax(iPivot.values);
|
|
iPivot.reserve = GetMin(iPivot.values);
|
|
|
|
//
|
|
XBoxZone iBox;
|
|
has = iPivot.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
has = iPivot.AsBox(iBox);
|
|
if (has)
|
|
{
|
|
//
|
|
newCCICrossedUnderOBPivotDetected = AddBox(
|
|
iBox,
|
|
cciCrossedUnderOBPivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
iPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// SPIKE Bullish ...
|
|
|
|
//
|
|
bool detectSpikeBullisPivots = true;
|
|
if (detectSpikeBullisPivots)
|
|
{
|
|
//
|
|
// For Spike Detection ...
|
|
// [] 80% of Bars Must be Same as Direction ...
|
|
// [] Price Range of Bars Must be Passed of atr mult ...
|
|
// [] Required Volume Processing if Neccessary ...
|
|
|
|
//
|
|
bool startCondition = false;
|
|
bool continuationCondition = false;
|
|
bool endCondition = false;
|
|
|
|
//
|
|
// TODO: Complete this ...
|
|
}
|
|
|
|
//
|
|
start++;
|
|
|
|
//
|
|
Clean(z3Mas);
|
|
Clean(c3Mas);
|
|
Clean(p3Mas);
|
|
Clean(p23Mas);
|
|
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
fvgBox.Clean();
|
|
conditions.Clean();
|
|
}
|
|
|
|
//
|
|
SortPivots();
|
|
}
|
|
|
|
//
|
|
void Validate(
|
|
XBoxZone &unAvailableBoxes[],
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
// Do All Pivots Validation ...
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
bool has = false;
|
|
|
|
//
|
|
int zIDX = 0;
|
|
int cIDX = zIDX + 1;
|
|
int pIDX = cIDX + 1;
|
|
int p2IDX = pIDX + 1;
|
|
|
|
//
|
|
// Retrieve Conditions ...
|
|
XCAEAConditions conditions;
|
|
has = helper.GetConditions(
|
|
conditions,
|
|
barIndex,
|
|
5 //
|
|
);
|
|
if (!has)
|
|
{
|
|
conditions.Clean();
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Implement Validation Senarios ...
|
|
|
|
//
|
|
// TICK Pivots ...
|
|
|
|
//
|
|
// TODO: Complete this ...
|
|
has = HasTickPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
}
|
|
|
|
//
|
|
// VOLUME Pivots ...
|
|
|
|
//
|
|
// TODO: Complete this ...
|
|
has = HasVolumePivots();
|
|
if (has)
|
|
{
|
|
//
|
|
}
|
|
|
|
//
|
|
// RSI Peak Pivot ...
|
|
|
|
//
|
|
has = HasRSIPeakPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnBox(
|
|
rsiPeakPivots,
|
|
unAvailableBoxes,
|
|
barIndex //
|
|
);
|
|
}
|
|
|
|
//
|
|
// RSI Vale Pivot ...
|
|
|
|
//
|
|
has = HasRSIValePivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnBox(
|
|
rsiValePivots,
|
|
unAvailableBoxes,
|
|
barIndex //
|
|
);
|
|
}
|
|
|
|
//
|
|
// CCI Peak Pivot ...
|
|
|
|
//
|
|
has = HasCCIPeakPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnBox(
|
|
cciPeakPivots,
|
|
unAvailableBoxes,
|
|
barIndex //
|
|
);
|
|
}
|
|
|
|
//
|
|
// CCI Vale Pivot ...
|
|
|
|
//
|
|
has = HasCCIValePivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnBox(
|
|
cciValePivots,
|
|
unAvailableBoxes,
|
|
barIndex //
|
|
);
|
|
}
|
|
|
|
//
|
|
// FVG Bullish ...
|
|
|
|
//
|
|
has = HasFVGBullishPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnBox(
|
|
fvgBullishPivots,
|
|
unAvailableBoxes,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
// Validate FVG Ages ...
|
|
if (maxAllowedFVGsAge > 0)
|
|
{
|
|
//
|
|
ApplyAgeVerification(
|
|
fvgBullishPivots,
|
|
maxAllowedFVGsAge //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Validate FVG using PV ...
|
|
if (validateFVGsUsingPV)
|
|
{
|
|
//
|
|
ApplyFVGPVValidation(
|
|
fvgBullishPivots,
|
|
conditions //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Validating FVGs using MANALYSER ...
|
|
// if (validateFVGsUsingMANALYSER)
|
|
// {
|
|
// //
|
|
// ApplyManalyswerValidation(
|
|
// fvgBullishPivots,
|
|
// barIndex //
|
|
// );
|
|
// }
|
|
}
|
|
|
|
//
|
|
// FVG Bearish ...
|
|
|
|
//
|
|
has = HasFVGBearishPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnBox(
|
|
fvgBearishPivots,
|
|
unAvailableBoxes,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
// Validate FVG Ages ...
|
|
if (maxAllowedFVGsAge > 0)
|
|
{
|
|
//
|
|
ApplyAgeVerification(
|
|
fvgBearishPivots,
|
|
maxAllowedFVGsAge //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Validate FVG using PV ...
|
|
if (validateFVGsUsingPV)
|
|
{
|
|
//
|
|
ApplyFVGPVValidation(
|
|
fvgBearishPivots,
|
|
conditions //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Validating FVGs using MANALYSER ...
|
|
// if (validateFVGsUsingMANALYSER)
|
|
// {
|
|
// //
|
|
// ApplyManalyswerValidation(
|
|
// fvgBearishPivots,
|
|
// barIndex //
|
|
// );
|
|
// }
|
|
}
|
|
|
|
//
|
|
// VALE Pivot Support Swing Low ...
|
|
|
|
//
|
|
has = HasValeSupSWLPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnBox(
|
|
valeSupSWLPivots,
|
|
unAvailableBoxes,
|
|
barIndex //
|
|
);
|
|
}
|
|
|
|
//
|
|
// PEAK Pivot Resistance Swing High ...
|
|
|
|
//
|
|
has = HasPeakResSWHPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnBox(
|
|
peakResSWHPivots,
|
|
unAvailableBoxes,
|
|
barIndex //
|
|
);
|
|
}
|
|
|
|
//
|
|
// TREND Bullish ...
|
|
|
|
//
|
|
has = HasTrendBullishPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnTrendFVG(
|
|
trendBullishPivots,
|
|
unAvailableBoxes,
|
|
barIndex //
|
|
);
|
|
}
|
|
|
|
//
|
|
// TREND Bearish ...
|
|
|
|
//
|
|
has = HasTrendBearishPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnTrendFVG(
|
|
trendBearishPivots,
|
|
unAvailableBoxes,
|
|
barIndex //
|
|
);
|
|
}
|
|
|
|
//
|
|
// RSI Crossed Over OS ...
|
|
|
|
//
|
|
has = HasRSICrossedOverOSPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnBox(
|
|
rsiCrossedOverOSPivots,
|
|
unAvailableBoxes,
|
|
barIndex //
|
|
);
|
|
}
|
|
|
|
//
|
|
// RSI Crossed Under OB ...
|
|
|
|
//
|
|
has = HasRSICrossedUnderOBPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnBox(
|
|
rsiCrossedUnderOBPivots,
|
|
unAvailableBoxes,
|
|
barIndex //
|
|
);
|
|
}
|
|
|
|
//
|
|
// CCI Crossed Over OS ...
|
|
|
|
//
|
|
has = HasCCICrossedOverOSPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnBox(
|
|
cciCrossedOverOSPivots,
|
|
unAvailableBoxes,
|
|
barIndex //
|
|
);
|
|
}
|
|
|
|
//
|
|
// CCI Crossed Under OB ...
|
|
|
|
//
|
|
has = HasCCICrossedUnderOBPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
ApplyValidationOnBox(
|
|
cciCrossedUnderOBPivots,
|
|
unAvailableBoxes,
|
|
barIndex //
|
|
);
|
|
}
|
|
|
|
//
|
|
conditions.Clean();
|
|
|
|
//
|
|
SortPivots();
|
|
}
|
|
|
|
//
|
|
int FillPivots(
|
|
XBoxZone &pivots[],
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_ALL //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(pivots);
|
|
|
|
//
|
|
if (forDir == X_DIRECTION_NONE)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = 0;
|
|
bool has = false;
|
|
|
|
//
|
|
bool canFillBullish =
|
|
forDir == X_DIRECTION_ALL ||
|
|
forDir == X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
bool canFillBearish =
|
|
forDir == X_DIRECTION_ALL ||
|
|
forDir == X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
// Bullish ...
|
|
if (canFillBullish)
|
|
{
|
|
//
|
|
Copy(
|
|
rsiValePivots,
|
|
pivots,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
cciValePivots,
|
|
pivots,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
fvgBullishPivots,
|
|
pivots,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
valeSupSWLPivots,
|
|
pivots,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
rsiCrossedOverOSPivots,
|
|
pivots,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
cciCrossedOverOSPivots,
|
|
pivots,
|
|
false //
|
|
);
|
|
|
|
//
|
|
has = HasTrendBullishPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
count = CountTrendBullishPivots();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
AddRef(
|
|
trendBullishPivots[i].trend,
|
|
pivots //
|
|
);
|
|
|
|
//
|
|
XBoxZone iBox;
|
|
has = trendBullishPivots[i].GetSelectedFVG(iBox);
|
|
if (has)
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
pivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
if (canFillBearish)
|
|
{
|
|
//
|
|
Copy(
|
|
rsiPeakPivots,
|
|
pivots,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
cciPeakPivots,
|
|
pivots,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
fvgBearishPivots,
|
|
pivots,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
peakResSWHPivots,
|
|
pivots,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
rsiCrossedUnderOBPivots,
|
|
pivots,
|
|
false //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
cciCrossedUnderOBPivots,
|
|
pivots,
|
|
false //
|
|
);
|
|
|
|
//
|
|
has = HasTrendBearishPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
count = CountTrendBearishPivots();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
AddRef(
|
|
trendBearishPivots[i].trend,
|
|
pivots //
|
|
);
|
|
|
|
//
|
|
XBoxZone iBox;
|
|
has = trendBearishPivots[i].GetSelectedFVG(iBox);
|
|
if (has)
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
pivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool MarketTrend(ENUM_X_DIRECTION &trend)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Update Market Trend ...
|
|
DetectMarketTrend();
|
|
|
|
//
|
|
trend = trendDir;
|
|
result = HasDirection(trend);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Counters ...
|
|
|
|
//
|
|
// INVALID Pivots ...
|
|
|
|
//
|
|
bool HasInvalidPivots()
|
|
{
|
|
return HasChild(invalidPivots);
|
|
}
|
|
|
|
//
|
|
int CountInvalidPivots()
|
|
{
|
|
return ArraySize(invalidPivots);
|
|
}
|
|
|
|
//
|
|
// TICK Pivot ...
|
|
|
|
//
|
|
bool HasTickPivots()
|
|
{
|
|
return HasChild(tickPivots);
|
|
}
|
|
|
|
//
|
|
int CountTickPivots()
|
|
{
|
|
return ArraySize(tickPivots);
|
|
}
|
|
|
|
//
|
|
// VOLUME Pivots ...
|
|
|
|
//
|
|
bool HasVolumePivots()
|
|
{
|
|
return HasChild(volumePivots);
|
|
}
|
|
|
|
//
|
|
int CountVolumePivots()
|
|
{
|
|
return ArraySize(volumePivots);
|
|
}
|
|
|
|
//
|
|
// RSI Peak Pivot ...
|
|
|
|
//
|
|
bool HasRSIPeakPivots()
|
|
{
|
|
return HasChild(rsiPeakPivots);
|
|
}
|
|
|
|
//
|
|
int CountRSIPeakPivots()
|
|
{
|
|
return ArraySize(rsiPeakPivots);
|
|
}
|
|
|
|
//
|
|
// RSI Vale Pivot ...
|
|
|
|
//
|
|
bool HasRSIValePivots()
|
|
{
|
|
return HasChild(rsiValePivots);
|
|
}
|
|
|
|
//
|
|
int CountRSIValePivots()
|
|
{
|
|
return ArraySize(rsiValePivots);
|
|
}
|
|
|
|
//
|
|
// CCI Peak Pivot ...
|
|
|
|
//
|
|
bool HasCCIPeakPivots()
|
|
{
|
|
return HasChild(cciPeakPivots);
|
|
}
|
|
|
|
//
|
|
int CountCCIPeakPivots()
|
|
{
|
|
return ArraySize(cciPeakPivots);
|
|
}
|
|
|
|
//
|
|
// CCI Vale Pivot ...
|
|
|
|
//
|
|
bool HasCCIValePivots()
|
|
{
|
|
return HasChild(cciValePivots);
|
|
}
|
|
|
|
//
|
|
int CountCCIValePivots()
|
|
{
|
|
return ArraySize(cciValePivots);
|
|
}
|
|
|
|
//
|
|
// FVG Bullish ...
|
|
|
|
//
|
|
bool HasFVGBullishPivots()
|
|
{
|
|
return HasChild(fvgBullishPivots);
|
|
}
|
|
|
|
//
|
|
int CountFVGBullishPivots()
|
|
{
|
|
return ArraySize(fvgBullishPivots);
|
|
}
|
|
|
|
//
|
|
// FVG Bearish ...
|
|
|
|
//
|
|
bool HasFVGBearishPivots()
|
|
{
|
|
return HasChild(fvgBearishPivots);
|
|
}
|
|
|
|
//
|
|
int CountFVGBearishPivots()
|
|
{
|
|
return ArraySize(fvgBearishPivots);
|
|
}
|
|
|
|
//
|
|
// VALE Pivot Support Swing Low ...
|
|
|
|
//
|
|
bool HasValeSupSWLPivots()
|
|
{
|
|
return HasChild(valeSupSWLPivots);
|
|
}
|
|
|
|
//
|
|
int CountValeSupSWLPivots()
|
|
{
|
|
return ArraySize(valeSupSWLPivots);
|
|
}
|
|
|
|
//
|
|
// PEAK Pivot Resistance Swing High ...
|
|
|
|
//
|
|
bool HasPeakResSWHPivots()
|
|
{
|
|
return HasChild(peakResSWHPivots);
|
|
}
|
|
|
|
//
|
|
int CountPeakResSWHPivots()
|
|
{
|
|
return ArraySize(peakResSWHPivots);
|
|
}
|
|
|
|
//
|
|
// TREND Bullish ...
|
|
|
|
//
|
|
bool HasTrendBullishPivots()
|
|
{
|
|
return HasChild(trendBullishPivots);
|
|
}
|
|
|
|
//
|
|
int CountTrendBullishPivots()
|
|
{
|
|
return ArraySize(trendBullishPivots);
|
|
}
|
|
|
|
//
|
|
// TREND Bearish ...
|
|
|
|
//
|
|
bool HasTrendBearishPivots()
|
|
{
|
|
return HasChild(trendBearishPivots);
|
|
}
|
|
|
|
//
|
|
int CountTrendBearishPivots()
|
|
{
|
|
return ArraySize(trendBearishPivots);
|
|
}
|
|
|
|
//
|
|
// RSI Crossed Over OS Pivots ...
|
|
|
|
//
|
|
bool HasRSICrossedOverOSPivots()
|
|
{
|
|
return HasChild(rsiCrossedOverOSPivots);
|
|
}
|
|
|
|
//
|
|
int CountRSICrossedOverOSPivots()
|
|
{
|
|
return ArraySize(rsiCrossedOverOSPivots);
|
|
}
|
|
|
|
//
|
|
// RSI Crossed Under OB Pivots ...
|
|
|
|
//
|
|
bool HasRSICrossedUnderOBPivots()
|
|
{
|
|
return HasChild(rsiCrossedUnderOBPivots);
|
|
}
|
|
|
|
//
|
|
int CountRSICrossedUnderOBPivots()
|
|
{
|
|
return ArraySize(rsiCrossedUnderOBPivots);
|
|
}
|
|
|
|
//
|
|
// CCI Crossed Over OS Pivots ...
|
|
|
|
//
|
|
bool HasCCICrossedOverOSPivots()
|
|
{
|
|
return HasChild(cciCrossedOverOSPivots);
|
|
}
|
|
|
|
//
|
|
int CountCCICrossedOverOSPivots()
|
|
{
|
|
return ArraySize(rsiCrossedOverOSPivots);
|
|
}
|
|
|
|
//
|
|
// CCI Crossed Under OB Pivots ...
|
|
|
|
//
|
|
bool HasCCICrossedUnderOBPivots()
|
|
{
|
|
return HasChild(cciCrossedUnderOBPivots);
|
|
}
|
|
|
|
//
|
|
int CountCCICrossedUnderOBPivots()
|
|
{
|
|
return ArraySize(cciCrossedUnderOBPivots);
|
|
}
|
|
|
|
//
|
|
// Protected ...
|
|
protected:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
// Prrivate ...
|
|
private:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
XCPOIDrawer *drawer;
|
|
XCXCAEAHelper *helper;
|
|
XCBarAnalyser *barAnalyser;
|
|
|
|
//
|
|
bool AddBox(
|
|
XBoxZone &box,
|
|
XBoxZone &boxes[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
bool isExists = FindBoxIndex(
|
|
idx,
|
|
box,
|
|
boxes //
|
|
);
|
|
result = !isExists;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int before = ArraySize(boxes);
|
|
|
|
//
|
|
AddRef(
|
|
box,
|
|
boxes //
|
|
);
|
|
|
|
//
|
|
int after = ArraySize(boxes);
|
|
|
|
//
|
|
result = after > before;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool ValidateBox(
|
|
XBoxZone &box,
|
|
XBoxZone &unAvailableBoxes[],
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize Bar Index ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
|
|
//
|
|
// Ceck Input Box is Valid ...
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Input Box is Available ...
|
|
bool canCheckUnAvailableBoxes = HasChild(unAvailableBoxes);
|
|
if (canCheckUnAvailableBoxes)
|
|
{
|
|
//
|
|
int idx = -1;
|
|
bool isUnAvailable = FindBoxIndex(
|
|
idx,
|
|
box,
|
|
unAvailableBoxes //
|
|
);
|
|
result = !isUnAvailable;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Input Box is Breaked or not ...
|
|
|
|
//
|
|
// Check Bar Index must after Box To Index ...
|
|
int toIDX = box.ToIndex();
|
|
int fromIDX = box.FromIndex();
|
|
result = toIDX > barIndex &&
|
|
fromIDX > barIndex &&
|
|
fromIDX > toIDX;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Detect Box Applied Boundary Price ...
|
|
// For Checking Break of Box ...
|
|
bool isBullish = box.IsBullish();
|
|
double boundary =
|
|
isBullish
|
|
? box.lower
|
|
: box.upper;
|
|
|
|
//
|
|
// for validating Box Break we have to wait At Least 3 Bars Close
|
|
// out of Box Boundary ...
|
|
int barsLength = 3;
|
|
|
|
//
|
|
// Calculate Start Checking Bar Index ...
|
|
int startCheckBreaktionBarIndex = toIDX - barsLength;
|
|
bool isBarIndexValid = startCheckBreaktionBarIndex > 0 &&
|
|
barIndex < startCheckBreaktionBarIndex;
|
|
result = isBarIndexValid;
|
|
if (!result)
|
|
{
|
|
//
|
|
// Assume Box is Valid if Bar Index not Valid for Checking ...
|
|
result = true;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Try to Check Box Validation if Everything is OK ...
|
|
XOHCL cBar;
|
|
XOHCL pBar;
|
|
XOHCL p2Bar;
|
|
bool isValid = false;
|
|
bool isBreaked = false;
|
|
for (int i = barIndex; i < startCheckBreaktionBarIndex; i++)
|
|
{
|
|
//
|
|
// Initialize Bars ...
|
|
isValid = cBar.Init(
|
|
box.symbol,
|
|
box.period,
|
|
i + 1 //
|
|
);
|
|
isValid =
|
|
result &&
|
|
cBar.GetPreviousBar(pBar);
|
|
isValid =
|
|
result &&
|
|
pBar.GetPreviousBar(p2Bar);
|
|
if (!isValid)
|
|
{
|
|
//
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
|
|
//
|
|
result = false;
|
|
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Preparing Conditions ...
|
|
|
|
//
|
|
bool isBullishBreaked =
|
|
isBullish &&
|
|
cBar.close < boundary &&
|
|
pBar.close < boundary &&
|
|
p2Bar.close < boundary;
|
|
|
|
//
|
|
bool isBearishBreaked =
|
|
!isBullish &&
|
|
cBar.close > boundary &&
|
|
pBar.close > boundary &&
|
|
p2Bar.close > boundary;
|
|
|
|
//
|
|
// Calculate Result ...
|
|
isBreaked = isBullishBreaked ||
|
|
isBearishBreaked;
|
|
if (isBreaked)
|
|
{
|
|
//
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
|
|
//
|
|
result = false;
|
|
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
}
|
|
|
|
//
|
|
result = isValid &&
|
|
!isBreaked;
|
|
|
|
//
|
|
// Cleanup Resource ...
|
|
|
|
//
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void CleanPivots()
|
|
{
|
|
//
|
|
Clean(invalidPivots);
|
|
|
|
//
|
|
Clean(tickPivots);
|
|
Clean(volumePivots);
|
|
Clean(rsiPeakPivots);
|
|
Clean(rsiValePivots);
|
|
Clean(cciPeakPivots);
|
|
Clean(cciValePivots);
|
|
Clean(fvgBullishPivots);
|
|
Clean(fvgBearishPivots);
|
|
Clean(valeSupSWLPivots);
|
|
Clean(peakResSWHPivots);
|
|
Clean(trendBullishPivots);
|
|
Clean(trendBearishPivots);
|
|
Clean(rsiCrossedOverOSPivots);
|
|
Clean(rsiCrossedUnderOBPivots);
|
|
Clean(cciCrossedOverOSPivots);
|
|
Clean(cciCrossedUnderOBPivots);
|
|
}
|
|
|
|
//
|
|
void SortPivots()
|
|
{
|
|
//
|
|
bool has = false;
|
|
|
|
//
|
|
// RSI Peak ...
|
|
has = HasRSIPeakPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBox(rsiPeakPivots);
|
|
}
|
|
|
|
//
|
|
// RSI Vale ...
|
|
has = HasRSIValePivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBox(rsiValePivots);
|
|
}
|
|
|
|
//
|
|
// CCI Peak ...
|
|
has = HasCCIPeakPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBox(cciPeakPivots);
|
|
}
|
|
|
|
//
|
|
// CCI Vale ...
|
|
has = HasCCIValePivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBox(cciValePivots);
|
|
}
|
|
|
|
//
|
|
// FVG Bullish ...
|
|
has = HasFVGBullishPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBox(fvgBullishPivots);
|
|
}
|
|
|
|
//
|
|
// FVG Bearish ...
|
|
has = HasFVGBearishPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBox(fvgBearishPivots);
|
|
}
|
|
|
|
//
|
|
// VALE SUP SWL ...
|
|
has = HasValeSupSWLPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBox(valeSupSWLPivots);
|
|
}
|
|
|
|
//
|
|
// PEAK REs SWH ...
|
|
has = HasPeakResSWHPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBox(peakResSWHPivots);
|
|
}
|
|
|
|
//
|
|
// PVFVG Bullish ...
|
|
has = HasTrendBullishPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnTrendFVG(trendBullishPivots);
|
|
}
|
|
|
|
//
|
|
// PVFVG Bearish ...
|
|
has = HasTrendBearishPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnTrendFVG(trendBearishPivots);
|
|
}
|
|
|
|
//
|
|
// RSI Crossed Over OS ...
|
|
has = HasRSICrossedOverOSPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBox(rsiCrossedOverOSPivots);
|
|
}
|
|
|
|
//
|
|
// RSI Crossed Under OB ...
|
|
has = HasRSICrossedUnderOBPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBox(rsiCrossedUnderOBPivots);
|
|
}
|
|
|
|
//
|
|
// CCI Crossed Over OS ...
|
|
has = HasCCICrossedOverOSPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBox(cciCrossedOverOSPivots);
|
|
}
|
|
|
|
//
|
|
// CCI Crossed Under OB ...
|
|
has = HasCCICrossedUnderOBPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBox(cciCrossedUnderOBPivots);
|
|
}
|
|
|
|
//
|
|
// INVALID Pivots ...
|
|
has = HasInvalidPivots();
|
|
if (has)
|
|
{
|
|
ApplySortOnBox(invalidPivots);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Sorting ...
|
|
|
|
//
|
|
void ApplySortOnBox(
|
|
XBoxZone &items[] //
|
|
)
|
|
{
|
|
//
|
|
int idx = -1;
|
|
bool has = false;
|
|
|
|
//
|
|
has = HasChild(items);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XBoxZone tmp[];
|
|
Copy(
|
|
items,
|
|
tmp //
|
|
);
|
|
Clean(items);
|
|
|
|
//
|
|
while (HasChild(tmp))
|
|
{
|
|
//
|
|
idx = GetOldest(tmp);
|
|
has = IsValidIndex(idx);
|
|
if (!has)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
XBoxZone iBox = tmp[idx];
|
|
ArrayRemove(
|
|
tmp,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
items //
|
|
);
|
|
}
|
|
|
|
//
|
|
CleanupArray(
|
|
items,
|
|
maxAllowedPivots //
|
|
);
|
|
|
|
//
|
|
Clean(tmp);
|
|
}
|
|
|
|
//
|
|
void ApplySortOnTrendFVG(
|
|
XCATRENDFVG &items[] //
|
|
)
|
|
{
|
|
//
|
|
int idx = -1;
|
|
bool has = false;
|
|
|
|
//
|
|
has = HasChild(items);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XCATRENDFVG tmp[];
|
|
Copy(
|
|
items,
|
|
tmp //
|
|
);
|
|
Clean(items);
|
|
|
|
//
|
|
while (HasChild(tmp))
|
|
{
|
|
//
|
|
idx = GetOldest(tmp);
|
|
has = IsValidIndex(idx);
|
|
if (!has)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
XCATRENDFVG iTrendFVG = tmp[idx];
|
|
ArrayRemove(
|
|
tmp,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
AddRef(
|
|
iTrendFVG,
|
|
items //
|
|
);
|
|
}
|
|
|
|
//
|
|
CleanupArray(
|
|
items,
|
|
maxAllowedPivots //
|
|
);
|
|
|
|
//
|
|
Clean(tmp);
|
|
}
|
|
|
|
//
|
|
// Validators ...
|
|
|
|
//
|
|
void ApplyValidationOnBox(
|
|
XBoxZone &items[],
|
|
XBoxZone &unAvailableItems[],
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool has = false;
|
|
|
|
//
|
|
has = HasChild(items);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XBoxZone tmp[];
|
|
Copy(
|
|
items,
|
|
tmp //
|
|
);
|
|
Clean(items);
|
|
while (HasChild(tmp))
|
|
{
|
|
//
|
|
XBoxZone iBox = tmp[0];
|
|
ArrayRemove(
|
|
tmp,
|
|
0,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
has = ValidateBox(
|
|
iBox,
|
|
unAvailableItems,
|
|
barIndex //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
items //
|
|
);
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
//
|
|
}
|
|
|
|
//
|
|
Clean(tmp);
|
|
}
|
|
|
|
//
|
|
void ApplyAgeVerification(
|
|
XBoxZone &pivots[],
|
|
int maxAllowedAge //
|
|
)
|
|
{
|
|
//
|
|
bool has = HasChild(pivots) &&
|
|
maxAllowedAge > 0;
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XBoxZone tmp[];
|
|
Copy(
|
|
pivots,
|
|
tmp //
|
|
);
|
|
Clean(pivots);
|
|
|
|
//
|
|
while (HasChild(tmp))
|
|
{
|
|
//
|
|
XBoxZone iPivot = tmp[0];
|
|
ArrayRemove(
|
|
tmp,
|
|
0,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
iPivot.to = TimeCurrent();
|
|
|
|
//
|
|
int iAge = iPivot.GetAge();
|
|
has = iAge <= maxAllowedAge;
|
|
if (has)
|
|
{
|
|
//
|
|
AddRef(
|
|
iPivot,
|
|
pivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
iPivot.Clean();
|
|
}
|
|
|
|
//
|
|
Clean(tmp);
|
|
}
|
|
|
|
//
|
|
void ApplyFVGPVValidation(
|
|
XBoxZone &fvgs[],
|
|
XCAEAConditions &conditions //
|
|
)
|
|
{
|
|
//
|
|
int zIDX = 0;
|
|
int cIDX = zIDX + 1;
|
|
int pIDX = cIDX + 1;
|
|
int p2IDX = pIDX + 1;
|
|
|
|
//
|
|
bool has = HasChild(fvgs);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Reading Values ...
|
|
|
|
//
|
|
// PEAK ...
|
|
double zPeak = conditions.peakBuffer[zIDX];
|
|
double cPeak = conditions.peakBuffer[cIDX];
|
|
double pPeak = conditions.peakBuffer[pIDX];
|
|
double p2Peak = conditions.peakBuffer[p2IDX];
|
|
|
|
//
|
|
// VALE ...
|
|
double zVale = conditions.valeBuffer[zIDX];
|
|
double cVale = conditions.valeBuffer[cIDX];
|
|
double pVale = conditions.valeBuffer[pIDX];
|
|
double p2Vale = conditions.valeBuffer[p2IDX];
|
|
|
|
//
|
|
XBoxZone tmp[];
|
|
Copy(
|
|
fvgs,
|
|
tmp //
|
|
);
|
|
Clean(fvgs);
|
|
while (HasChild(tmp))
|
|
{
|
|
//
|
|
XBoxZone iBox = tmp[0];
|
|
ArrayRemove(
|
|
tmp,
|
|
0,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
bool isBullish = iBox.IsBullish();
|
|
|
|
//
|
|
bool isPVBreaked =
|
|
isBullish
|
|
? cVale > iBox.upper
|
|
: cPeak < iBox.lower;
|
|
|
|
//
|
|
has = !isPVBreaked;
|
|
if (has)
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
fvgs //
|
|
);
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
Clean(tmp);
|
|
}
|
|
|
|
//
|
|
void ApplyValidationOnTrendFVG(
|
|
XCATRENDFVG &items[],
|
|
XBoxZone &unAvailableItems[],
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool has = false;
|
|
|
|
//
|
|
has = HasChild(items);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XCATRENDFVG tmp[];
|
|
Copy(
|
|
items,
|
|
tmp //
|
|
);
|
|
Clean(items);
|
|
while (HasChild(tmp))
|
|
{
|
|
//
|
|
XCATRENDFVG iTrendFVG = tmp[0];
|
|
ArrayRemove(
|
|
tmp,
|
|
0,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
// Validate TMP Trend Box ...
|
|
has = ValidateBox(
|
|
iTrendFVG.trend,
|
|
unAvailableItems,
|
|
barIndex //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
// Now we Have to Validate FVGS ...
|
|
ApplyValidationOnBox(
|
|
iTrendFVG.fvgs,
|
|
unAvailableItems,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
has = iTrendFVG.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
AddRef(
|
|
iTrendFVG,
|
|
items //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
iTrendFVG.Clean();
|
|
}
|
|
|
|
//
|
|
Clean(tmp);
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
//
|
|
bool IsExistsTickPivot(
|
|
datetime to,
|
|
datetime from //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
result = IsValid(to) &&
|
|
IsValid(from) &&
|
|
to > from;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = HasTickPivots();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
int count = CountTickPivots();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = tickPivots[i];
|
|
|
|
//
|
|
result = iBox.to == to &&
|
|
iBox.from == from;
|
|
if (result)
|
|
{
|
|
//
|
|
idx = i;
|
|
iBox.Clean();
|
|
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(idx);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool IsExistsVolumePivot(
|
|
datetime to,
|
|
datetime from //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
result = IsValid(to) &&
|
|
IsValid(from) &&
|
|
to > from;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = HasVolumePivots();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
int count = CountVolumePivots();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = volumePivots[i];
|
|
|
|
//
|
|
result = iBox.to == to &&
|
|
iBox.from == from;
|
|
if (result)
|
|
{
|
|
//
|
|
idx = i;
|
|
iBox.Clean();
|
|
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(idx);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool InitializeTicksZone(
|
|
XCTicksZone *&zone,
|
|
XOHCL &toBar,
|
|
XOHCL &fromBar //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = zone == NULL;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int toIDX = toBar.Index();
|
|
int fromIDX = fromBar.Index();
|
|
int rangeLength = fromIDX - toIDX;
|
|
double rangeDivider = ticksDividerInPoints * GetPoints(toBar.symbol);
|
|
double rangeL = toBar.FindLowest(rangeLength, MODE_LOW);
|
|
double rangeH = toBar.FindHighest(rangeLength, MODE_HIGH);
|
|
double rangeDiff = (rangeH - rangeL);
|
|
int zoneLevels = (int)(rangeDiff / rangeDivider);
|
|
|
|
//
|
|
zone = new XCTicksZone();
|
|
zone.Levels(zoneLevels);
|
|
|
|
//
|
|
result = zone.Init(
|
|
fromBar,
|
|
toBar //
|
|
);
|
|
if (!result)
|
|
{
|
|
ZeroMemory(zone);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void DetectMarketTrend()
|
|
{
|
|
//
|
|
int idx = -1;
|
|
int count = 0;
|
|
bool has = false;
|
|
|
|
//
|
|
XBoxZone tmp[];
|
|
has = HasPeakResSWHPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
Copy(
|
|
peakResSWHPivots,
|
|
tmp,
|
|
false //
|
|
);
|
|
}
|
|
has = HasValeSupSWLPivots();
|
|
if (has)
|
|
{
|
|
//
|
|
Copy(
|
|
valeSupSWLPivots,
|
|
tmp,
|
|
false //
|
|
);
|
|
}
|
|
count = ArraySize(tmp);
|
|
has = HasChild(tmp);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
has = HasDirection(trendDir);
|
|
if (!has)
|
|
{
|
|
//
|
|
trendPivotC.Clean();
|
|
trendPivotP.Clean();
|
|
}
|
|
|
|
//
|
|
XBoxZone cPivot;
|
|
XBoxZone pPivot;
|
|
ENUM_X_DIRECTION dir = X_DIRECTION_NONE;
|
|
while (HasChild(tmp))
|
|
{
|
|
//
|
|
XBoxZone iPivot;
|
|
idx = GetYoungest(tmp);
|
|
has = IsValidIndex(idx);
|
|
if (!has)
|
|
{
|
|
//
|
|
iPivot.Clean();
|
|
break;
|
|
}
|
|
|
|
//
|
|
iPivot = tmp[idx];
|
|
ArrayRemove(
|
|
tmp,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
// Check Can Set CPivot ...
|
|
bool canSetCPivot =
|
|
!cPivot.IsValid()
|
|
? true
|
|
: iPivot.from > cPivot.from;
|
|
if (canSetCPivot)
|
|
{
|
|
//
|
|
if (cPivot.IsValid())
|
|
{
|
|
pPivot = cPivot;
|
|
}
|
|
|
|
//
|
|
cPivot = iPivot;
|
|
}
|
|
|
|
//
|
|
// Check Can Set PPivot ...
|
|
bool canSetPPivot =
|
|
!cPivot.IsValid()
|
|
? false
|
|
: iPivot.from < cPivot.from
|
|
? !pPivot.IsValid()
|
|
? true
|
|
: iPivot.from > pPivot.from
|
|
: false;
|
|
if (canSetPPivot)
|
|
{
|
|
pPivot = iPivot;
|
|
}
|
|
|
|
//
|
|
has = cPivot.IsValid() &&
|
|
pPivot.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
iPivot.Clean();
|
|
break;
|
|
}
|
|
|
|
//
|
|
iPivot.Clean();
|
|
}
|
|
|
|
//
|
|
// Check Resources for Detecting Conditions ...
|
|
bool hasTrend =
|
|
//
|
|
cPivot.IsValid() &&
|
|
pPivot.IsValid() &&
|
|
cPivot.dir == pPivot.dir &&
|
|
cPivot.from > pPivot.from &&
|
|
(IsBullish(cPivot.dir)
|
|
? cPivot.lower > pPivot.lower
|
|
: cPivot.upper < pPivot.upper);
|
|
//
|
|
;
|
|
if (hasTrend)
|
|
{
|
|
//
|
|
trendPivotC = cPivot;
|
|
trendPivotP = pPivot;
|
|
trendDir = cPivot.dir;
|
|
}
|
|
|
|
//
|
|
Clean(tmp);
|
|
cPivot.Clean();
|
|
pPivot.Clean();
|
|
|
|
//
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
// |