7168 lines
150 KiB
Plaintext
7168 lines
150 KiB
Plaintext
//
|
|
int minRequiredRange = 20;
|
|
if (barIndex > maxBarIndex - minRequiredRange - 4)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
double iP2SCLL = sLLBuffer[barIndex + 2];
|
|
double iP2SCHH = sHHBuffer[barIndex + 2];
|
|
|
|
//
|
|
double iP3SCLL = sLLBuffer[barIndex + 3];
|
|
double iP3SCHH = sHHBuffer[barIndex + 3];
|
|
|
|
//
|
|
double iP4SCLL = sLLBuffer[barIndex + 4];
|
|
double iP4SCHH = sHHBuffer[barIndex + 4];
|
|
|
|
//
|
|
double iP2MCLL = mLLBuffer[barIndex + 2];
|
|
double iP2MCHH = mHHBuffer[barIndex + 2];
|
|
|
|
//
|
|
double iP3MCLL = mLLBuffer[barIndex + 3];
|
|
double iP3MCHH = mHHBuffer[barIndex + 3];
|
|
|
|
//
|
|
double iP4MCLL = mLLBuffer[barIndex + 4];
|
|
double iP4MCHH = mHHBuffer[barIndex + 4];
|
|
|
|
//
|
|
double iP2LCLL = lLLBuffer[barIndex + 2];
|
|
double iP2LCHH = lHHBuffer[barIndex + 2];
|
|
|
|
//
|
|
double iP3LCLL = lLLBuffer[barIndex + 3];
|
|
double iP3LCHH = lHHBuffer[barIndex + 3];
|
|
|
|
//
|
|
double iP4LCLL = lLLBuffer[barIndex + 4];
|
|
double iP4LCHH = lHHBuffer[barIndex + 4];
|
|
|
|
//
|
|
double iP2HCLL = hLLBuffer[barIndex + 2];
|
|
double iP2HCHH = hHHBuffer[barIndex + 2];
|
|
|
|
//
|
|
double iP3HCLL = hLLBuffer[barIndex + 3];
|
|
double iP3HCHH = hHHBuffer[barIndex + 3];
|
|
|
|
//
|
|
double iP4HCLL = hLLBuffer[barIndex + 4];
|
|
double iP4HCHH = hHHBuffer[barIndex + 4];
|
|
|
|
//
|
|
// Cycle States ...
|
|
|
|
//
|
|
// Create Conditions ...
|
|
|
|
//
|
|
bool isSCMaOverMCMa = iSCMa > iMCMa;
|
|
bool isPSCMaOverMCMa = iPSCMa > iPMCMa;
|
|
|
|
//
|
|
bool isSCMaUnderMCMa = iSCMa < iMCMa;
|
|
bool isPSCMaUnderMCMa = iPSCMa < iPMCMa;
|
|
|
|
//
|
|
bool isSCMaCrossedOverMCMa =
|
|
isSCMaOverMCMa &&
|
|
!isPSCMaOverMCMa;
|
|
|
|
//
|
|
bool isSCMaCrossedUnderMCMa =
|
|
isSCMaUnderMCMa &&
|
|
!isPSCMaUnderMCMa;
|
|
|
|
//
|
|
bool isLCMaOverHCMa = iLCMa > iHCMa;
|
|
bool isPLCMaOverHCMa = iPLCMa > iPHCMa;
|
|
|
|
//
|
|
bool isLCMaUnderHCMa = iLCMa < iHCMa;
|
|
bool isPLCMaUnderHCMa = iPLCMa < iPHCMa;
|
|
|
|
//
|
|
bool isLCMaCrossedOverHCMa =
|
|
isLCMaOverHCMa &&
|
|
!isPLCMaOverHCMa;
|
|
|
|
//
|
|
bool isLCMaCrossedUnderHCMa =
|
|
isLCMaUnderHCMa &&
|
|
!isPLCMaUnderHCMa;
|
|
|
|
//
|
|
// SC State ...
|
|
|
|
//
|
|
bool isSCMaBullish =
|
|
iSCMaState == bullishState;
|
|
bool isPSCMaBullish =
|
|
iPSCMaState == bullishState;
|
|
|
|
//
|
|
bool isSCMaBearish =
|
|
iSCMaState == bearishState;
|
|
bool isPSCMaBearish =
|
|
iPSCMaState == bearishState;
|
|
|
|
//
|
|
bool isSCMaSwitchedToBullish =
|
|
isSCMaBullish &&
|
|
!isPSCMaBullish;
|
|
|
|
//
|
|
bool isSCMaSwitchedToBearish =
|
|
isSCMaBearish &&
|
|
!isPSCMaBearish;
|
|
|
|
//
|
|
bool isSCLLOverMCLL =
|
|
iSCLL > iMCLL;
|
|
bool isPSCLLOverMCLL =
|
|
iPSCLL > iPMCLL;
|
|
bool isP2SCLLOverMCLL =
|
|
iP2SCLL > iP2MCLL;
|
|
bool isP3SCLLOverMCLL =
|
|
iP3SCLL > iP3MCLL;
|
|
bool isP4SCLLOverMCLL =
|
|
iP4SCLL > iP4MCLL;
|
|
|
|
//
|
|
bool isSCHHUnderMCHH =
|
|
iSCHH < iMCHH;
|
|
bool isPSCHHUnderMCHH =
|
|
iPSCHH < iPMCHH;
|
|
bool isP2SCHHUnderMCHH =
|
|
iP2SCHH < iP2MCHH;
|
|
bool isP3SCHHUnderMCHH =
|
|
iP3SCHH < iP3MCHH;
|
|
bool isP4SCHHUnderMCHH =
|
|
iP4SCHH < iP4MCHH;
|
|
|
|
//
|
|
bool isSCLLCrossedOverMCLL =
|
|
isSCLLOverMCLL &&
|
|
!isPSCLLOverMCLL;
|
|
bool isPSCLLCrossedOverMCLL =
|
|
isPSCLLOverMCLL &&
|
|
!isP2SCLLOverMCLL;
|
|
bool isP2SCLLCrossedOverMCLL =
|
|
isP2SCLLOverMCLL &&
|
|
!isP3SCLLOverMCLL;
|
|
bool isP3SCLLCrossedOverMCLL =
|
|
isP3SCLLOverMCLL &&
|
|
!isP4SCLLOverMCLL;
|
|
|
|
//
|
|
bool isSCHHCrossedUnderMCHH =
|
|
isSCHHUnderMCHH &&
|
|
!isPSCHHUnderMCHH;
|
|
bool isPSCHHCrossedUnderMCHH =
|
|
isPSCHHUnderMCHH &&
|
|
!isP2SCHHUnderMCHH;
|
|
bool isP2SCHHCrossedUnderMCHH =
|
|
isP2SCHHUnderMCHH &&
|
|
!isP3SCHHUnderMCHH;
|
|
bool isP3SCHHCrossedUnderMCHH =
|
|
isP3SCHHUnderMCHH &&
|
|
!isP4SCHHUnderMCHH;
|
|
|
|
//
|
|
// MC State ...
|
|
|
|
//
|
|
bool isMCMaBullish =
|
|
iMCMaState == bullishState;
|
|
bool isPMCMaBullish =
|
|
iPMCMaState == bullishState;
|
|
|
|
//
|
|
bool isMCMaBearish =
|
|
iMCMaState == bearishState;
|
|
bool isPMCMaBearish =
|
|
iPMCMaState == bearishState;
|
|
|
|
//
|
|
bool isMCMaSwitchedToBullish =
|
|
isMCMaBullish &&
|
|
!isPMCMaBullish;
|
|
|
|
//
|
|
bool isMCMaSwitchedToBearish =
|
|
isMCMaBearish &&
|
|
!isPMCMaBearish;
|
|
|
|
//
|
|
bool isMCLLOverLCLL =
|
|
iMCLL > iLCLL;
|
|
bool isPMCLLOverLCLL =
|
|
iPMCLL > iPLCLL;
|
|
bool isP2MCLLOverLCLL =
|
|
iP2MCLL > iP2LCLL;
|
|
bool isP3MCLLOverLCLL =
|
|
iP3MCLL > iP3LCLL;
|
|
bool isP4MCLLOverLCLL =
|
|
iP4MCLL > iP4LCLL;
|
|
|
|
//
|
|
bool isMCHHUnderLCHH =
|
|
iMCHH < iLCHH;
|
|
bool isPMCHHUnderLCHH =
|
|
iPMCHH < iPLCHH;
|
|
bool isP2MCHHUnderLCHH =
|
|
iP2MCHH < iP2LCHH;
|
|
bool isP3MCHHUnderLCHH =
|
|
iP3MCHH < iP3LCHH;
|
|
bool isP4MCHHUnderLCHH =
|
|
iP4MCHH < iP4LCHH;
|
|
|
|
//
|
|
bool isMCLLCrossedOverLCLL =
|
|
isMCLLOverLCLL &&
|
|
!isPMCLLOverLCLL;
|
|
bool isPMCLLCrossedOverLCLL =
|
|
isPMCLLOverLCLL &&
|
|
!isP2MCLLOverLCLL;
|
|
bool isP2MCLLCrossedOverLCLL =
|
|
isP2MCLLOverLCLL &&
|
|
!isP3MCLLOverLCLL;
|
|
bool isP3MCLLCrossedOverLCLL =
|
|
isP3MCLLOverLCLL &&
|
|
!isP4MCLLOverLCLL;
|
|
|
|
//
|
|
bool isMCHHCrossedUnderLCHH =
|
|
isMCHHUnderLCHH &&
|
|
!isPMCHHUnderLCHH;
|
|
bool isPMCHHCrossedUnderLCHH =
|
|
isPMCHHUnderLCHH &&
|
|
!isP2MCHHUnderLCHH;
|
|
bool isP2MCHHCrossedUnderLCHH =
|
|
isP2MCHHUnderLCHH &&
|
|
!isP3MCHHUnderLCHH;
|
|
bool isP3MCHHCrossedUnderLCHH =
|
|
isP3MCHHUnderLCHH &&
|
|
!isP4MCHHUnderLCHH;
|
|
|
|
//
|
|
// LC State ...
|
|
|
|
//
|
|
bool isLCMaBullish =
|
|
iLCMaState == bullishState;
|
|
bool isPLCMaBullish =
|
|
iPLCMaState == bullishState;
|
|
|
|
//
|
|
bool isLCMaBearish =
|
|
iLCMaState == bearishState;
|
|
bool isPLCMaBearish =
|
|
iPLCMaState == bearishState;
|
|
|
|
//
|
|
bool isLCMaSwitchedToBullish =
|
|
isLCMaBullish &&
|
|
!isPLCMaBullish;
|
|
|
|
//
|
|
bool isLCMaSwitchedToBearish =
|
|
isLCMaBearish &&
|
|
!isPLCMaBearish;
|
|
|
|
//
|
|
bool isLCLLOverHCLL =
|
|
iLCLL > iHCLL;
|
|
bool isPLCLLOverHCLL =
|
|
iPLCLL > iPHCLL;
|
|
bool isP2LCLLOverHCLL =
|
|
iP2LCLL > iP2HCLL;
|
|
bool isP3LCLLOverHCLL =
|
|
iP3LCLL > iP3HCLL;
|
|
bool isP4LCLLOverHCLL =
|
|
iP4LCLL > iP4HCLL;
|
|
|
|
//
|
|
bool isLCHHUnderHCHH =
|
|
iLCHH < iHCHH;
|
|
bool isPLCHHUnderHCHH =
|
|
iPLCHH < iPHCHH;
|
|
bool isP2LCHHUnderHCHH =
|
|
iP2LCHH < iP2HCHH;
|
|
bool isP3LCHHUnderHCHH =
|
|
iP3LCHH < iP3HCHH;
|
|
bool isP4LCHHUnderHCHH =
|
|
iP4LCHH < iP4HCHH;
|
|
|
|
//
|
|
bool isLCLLCrossedOverHCLL =
|
|
isLCLLOverHCLL &&
|
|
!isPLCLLOverHCLL;
|
|
bool isPLCLLCrossedOverHCLL =
|
|
isPLCLLOverHCLL &&
|
|
!isP2LCLLOverHCLL;
|
|
bool isP2LCLLCrossedOverHCLL =
|
|
isP2LCLLOverHCLL &&
|
|
!isP3LCLLOverHCLL;
|
|
bool isP3LCLLCrossedOverHCLL =
|
|
isP3LCLLOverHCLL &&
|
|
!isP4LCLLOverHCLL;
|
|
|
|
//
|
|
bool isLCHHCrossedUnderHCHH =
|
|
isLCHHUnderHCHH &&
|
|
!isPLCHHUnderHCHH;
|
|
bool isPLCHHCrossedUnderHCHH =
|
|
isPLCHHUnderHCHH &&
|
|
!isP2LCHHUnderHCHH;
|
|
bool isP2LCHHCrossedUnderHCHH =
|
|
isP2LCHHUnderHCHH &&
|
|
!isP3LCHHUnderHCHH;
|
|
bool isP3LCHHCrossedUnderHCHH =
|
|
isP3LCHHUnderHCHH &&
|
|
!isP4LCHHUnderHCHH;
|
|
|
|
//
|
|
// HC State ...
|
|
|
|
//
|
|
bool isHCMaBullish =
|
|
iHCMaState == bullishState;
|
|
bool isPHCMaBullish =
|
|
iPHCMaState == bullishState;
|
|
|
|
//
|
|
bool isHCMaBearish =
|
|
iHCMaState == bearishState;
|
|
bool isPHCMaBearish =
|
|
iPHCMaState == bearishState;
|
|
|
|
//
|
|
bool isHCMaSwitchedToBullish =
|
|
isHCMaBullish &&
|
|
!isPHCMaBullish;
|
|
|
|
//
|
|
bool isHCMaSwitchedToBearish =
|
|
isHCMaBearish &&
|
|
!isPHCMaBearish;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// HK Signal Bar ...
|
|
|
|
//
|
|
double iHKSOpen = hkSBarOpenBuffer[barIndex];
|
|
double iHKSClose = hkSBarCloseBuffer[barIndex];
|
|
|
|
//
|
|
double iHKSMax = MathMax(iHKSOpen, iHKSClose);
|
|
double iHKSMin = MathMin(iHKSOpen, iHKSClose);
|
|
|
|
//
|
|
bool isHKSBullish = hkSBarOpenBuffer[barIndex] < hkSBarCloseBuffer[barIndex];
|
|
bool isPHKSBullish = hkSBarOpenBuffer[barIndex + 1] < hkSBarCloseBuffer[barIndex + 1];
|
|
|
|
//
|
|
bool isHKSBearish = hkSBarOpenBuffer[barIndex] > hkSBarCloseBuffer[barIndex];
|
|
bool isPHKSBearish = hkSBarOpenBuffer[barIndex + 1] > hkSBarCloseBuffer[barIndex + 1];
|
|
|
|
//
|
|
bool isHKSSwitchedToBullish =
|
|
isHKSBullish &&
|
|
!isPHKSBullish;
|
|
|
|
//
|
|
bool isHKSSwitchedToBearish =
|
|
isHKSBearish &&
|
|
!isPHKSBearish;
|
|
|
|
//
|
|
// TREND ...
|
|
|
|
//
|
|
double iTrend = trendBuffer[barIndex];
|
|
bool isTrendBullish = trendStateBuffer[barIndex] > 0;
|
|
bool isTrendBearish = trendStateBuffer[barIndex] < 0;
|
|
bool isTrendSwitchedToBullish =
|
|
trendStateBuffer[barIndex] > 0 &&
|
|
trendStateBuffer[barIndex + 1] <= 0;
|
|
bool isTrendSwitchedToBearish =
|
|
trendStateBuffer[barIndex] < 0 &&
|
|
trendStateBuffer[barIndex + 1] >= 0;
|
|
|
|
//
|
|
// RSI ...
|
|
|
|
//
|
|
bool isRSIOverOB = rsiBuffer[barIndex] > rsiOBLevel;
|
|
bool isPRSIOverOB = rsiBuffer[barIndex + 1] > rsiOBLevel;
|
|
|
|
//
|
|
bool isRSIUnderOB = rsiBuffer[barIndex] < rsiOBLevel;
|
|
bool isPRSIUnderOB = rsiBuffer[barIndex + 1] < rsiOBLevel;
|
|
|
|
//
|
|
bool isRSICrossedOverOB =
|
|
isRSIOverOB &&
|
|
!isPRSIOverOB;
|
|
|
|
//
|
|
bool isRSICrossedUnderOB =
|
|
isRSIUnderOB &&
|
|
!isPRSIUnderOB;
|
|
|
|
//
|
|
bool isRSIOverOS = rsiBuffer[barIndex] > rsiOSLevel;
|
|
bool isPRSIOverOS = rsiBuffer[barIndex + 1] > rsiOSLevel;
|
|
|
|
//
|
|
bool isRSIUnderOS = rsiBuffer[barIndex] < rsiOSLevel;
|
|
bool isPRSIUnderOS = rsiBuffer[barIndex + 1] < rsiOSLevel;
|
|
|
|
//
|
|
bool isRSICrossedOverOS =
|
|
isRSIOverOS &&
|
|
!isPRSIOverOS;
|
|
|
|
//
|
|
bool isRSICrossedUnderOS =
|
|
isRSIUnderOS &&
|
|
!isPRSIUnderOS;
|
|
|
|
//
|
|
// ADX ...
|
|
|
|
//
|
|
bool isADXOverThreshold = adxBuffer[barIndex] > adxThreshold;
|
|
bool isPADXOverThreshold = adxBuffer[barIndex + 1] > adxThreshold;
|
|
|
|
//
|
|
bool isADXUnderThreshold = adxBuffer[barIndex] < adxThreshold;
|
|
bool isPADXUnderThreshold = adxBuffer[barIndex + 1] < adxThreshold;
|
|
|
|
//
|
|
bool isADXCrossedOverThreshold =
|
|
isADXOverThreshold &&
|
|
!isPADXOverThreshold;
|
|
|
|
//
|
|
bool isADXCrossedUnderThreshold =
|
|
isADXUnderThreshold &&
|
|
!isPADXUnderThreshold;
|
|
|
|
//
|
|
bool isADXBullish = adxpBuffer[barIndex] > adxnBuffer[barIndex];
|
|
bool isPADXBullish = adxpBuffer[barIndex + 1] > adxnBuffer[barIndex + 1];
|
|
|
|
//
|
|
bool isADXBearish = adxpBuffer[barIndex] < adxnBuffer[barIndex];
|
|
bool isPADXBearish = adxpBuffer[barIndex + 1] < adxnBuffer[barIndex + 1];
|
|
|
|
//
|
|
bool isADXSwitchedToBullish =
|
|
isADXBullish &&
|
|
!isPADXBullish;
|
|
|
|
//
|
|
bool isADXSwitchedToBearish =
|
|
isADXBearish &&
|
|
!isPADXBearish;
|
|
|
|
//
|
|
bool isADXFullySwitchedToBullish =
|
|
isADXSwitchedToBullish &&
|
|
isADXCrossedOverThreshold;
|
|
|
|
//
|
|
bool isADXFullySwitchedToBearish =
|
|
isADXSwitchedToBearish &&
|
|
isADXCrossedUnderThreshold;
|
|
|
|
//
|
|
bool isTriggerBarOverHKS =
|
|
iBar.low > iHKSMax;
|
|
bool isTriggerBarUnderHKS =
|
|
iBar.high < iHKSMin;
|
|
|
|
//
|
|
// KI ...
|
|
|
|
//
|
|
bool isKIBullish = kiStateBuffer[barIndex] > 0;
|
|
bool isPKIBullish = kiStateBuffer[barIndex + 1] > 0;
|
|
|
|
//
|
|
bool isKIBearish = kiStateBuffer[barIndex] < 0;
|
|
bool isPKIBearish = kiStateBuffer[barIndex = 1] < 0;
|
|
|
|
// //
|
|
// bool isKIOverHKS =
|
|
// kiBuffer[barIndex] > iHKSMax;
|
|
|
|
// //
|
|
// bool isKIUnderHKS =
|
|
// kiBuffer[barIndex] < iHKSMin;
|
|
|
|
//
|
|
bool isKISwitchedToBullish =
|
|
isKIBullish &&
|
|
!isPKIBullish;
|
|
|
|
//
|
|
bool isKISwitchedToBearish =
|
|
isKIBearish &&
|
|
!isPKIBearish;
|
|
|
|
//
|
|
// Detecting Signal ...
|
|
|
|
//
|
|
// Bullish ...
|
|
isBullish =
|
|
//
|
|
false
|
|
// Conditions Validation ...
|
|
// isKIOverHKS &&
|
|
// isHKSBullish &&
|
|
// isKISwitchedToBullish
|
|
// &&
|
|
//
|
|
// Bar Validation ...
|
|
// iBar.IsBullish() &&
|
|
// iBar.close > kiBuffer[barIndex]
|
|
//
|
|
;
|
|
|
|
//
|
|
// Bearish ...
|
|
isBearish =
|
|
//
|
|
false
|
|
// Conditions Validation ...
|
|
// isKIUnderHKS &&
|
|
// isHKSBearish &&
|
|
// isKISwitchedToBearish
|
|
// &&
|
|
//
|
|
// Bar Validation ...
|
|
// iBar.IsBearish() &&
|
|
// iBar.close < kiBuffer[barIndex]
|
|
//
|
|
;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
int mSameKICount = 0;
|
|
int mSameKIBullishCount = 0;
|
|
int mSameKIBearishCount = 0;
|
|
|
|
//
|
|
int mSamePeakCount = 0;
|
|
int mSameValeCount = 0;
|
|
|
|
//
|
|
double mSamePeaksGoldenMin = 0;
|
|
double mSamePeaksGoldenMax = 0;
|
|
|
|
//
|
|
double mSameValesGoldenMin = 0;
|
|
double mSameValesGoldenMax = 0;
|
|
|
|
//
|
|
int mSamePeakGoldenCount = 0;
|
|
int mSameValeGoldenCount = 0;
|
|
|
|
//
|
|
bool mDrawLiquidities = false;
|
|
bool mDrawRangeBreakes = false;
|
|
|
|
//
|
|
bool mDetectLiquidities = true;
|
|
bool mDetectRangeBreakes = true;
|
|
|
|
//
|
|
XBoxZone mBullishLiquidities[];
|
|
XBoxZone mBearishLiquidities[];
|
|
XBoxZone mBullishRangeBreakes[];
|
|
XBoxZone mBearishRangeBreakes[];
|
|
|
|
//
|
|
// POI(s) Handlers ...
|
|
//
|
|
|
|
/**
|
|
* Detect POI(s) ...
|
|
*
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param prevCalculated: int, Provides Previous Calculated Bars ...
|
|
* @param ratesTotal: int, Provides All Availabled Bars ...
|
|
* @param open: double Collection, Provides Open Prices Time Series ...
|
|
* @param high: double Collection, Provides High Prices Time Series ...
|
|
* @param close: double Collection, Provides Close Prices Time Series ...
|
|
* @param low: double Collection, Provides Low Prices Time Series ...
|
|
* @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ...
|
|
*/
|
|
void DetectPOIs(
|
|
int barIndex,
|
|
const int prevCalculated,
|
|
const int ratesTotal,
|
|
const double &open[],
|
|
const double &high[],
|
|
const double &close[],
|
|
const double &low[],
|
|
const long &tickVolume[] //
|
|
)
|
|
{
|
|
//
|
|
// Check Some Requirements ...
|
|
int lastBarIndex = barIndex + 1;
|
|
int maxBarIndex = startCalculationForLastBars > 0
|
|
? startCalculationForLastBars
|
|
: ratesTotal;
|
|
bool isFirstBar =
|
|
startCalculationForLastBars > 0
|
|
? barIndex == startCalculationForLastBars
|
|
: barIndex == firstBarIndex;
|
|
|
|
//
|
|
// Handle Minimum Required Bars ...
|
|
bool isPassedRequiredBars = barIndex < maxBarIndex - 3;
|
|
if (!isPassedRequiredBars)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Recieve Bar ...
|
|
XOHCL iBar;
|
|
XOHCL iPBar;
|
|
bool has = iBar.Init(
|
|
_Symbol,
|
|
_Period,
|
|
barIndex
|
|
//
|
|
);
|
|
has =
|
|
has &&
|
|
iBar.GetPreviousBar(iPBar);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
int maxAllowedPOIs = 50;
|
|
|
|
//
|
|
ENUM_X_DIRECTION iDir;
|
|
|
|
//
|
|
// Detecting Liquidity ...
|
|
if (mDetectLiquidities)
|
|
{
|
|
//
|
|
bool isLiquidity =
|
|
mBarAnalyser
|
|
.IsRejected(
|
|
iBar,
|
|
iDir,
|
|
true,
|
|
true //
|
|
);
|
|
bool isBullishLiquiditySweeped =
|
|
isLiquidity &&
|
|
IsBullish(iDir);
|
|
bool isBearishLiquiditySweeped =
|
|
isLiquidity &&
|
|
IsBearish(iDir);
|
|
if (isLiquidity)
|
|
{
|
|
//
|
|
XBoxZone iLiq;
|
|
|
|
//
|
|
iLiq.dir = iDir;
|
|
iLiq.type = "XLIQ";
|
|
iLiq.upper =
|
|
isBullishLiquiditySweeped
|
|
? iBar.GetDown()
|
|
: iBar.high;
|
|
iLiq.lower =
|
|
isBullishLiquiditySweeped
|
|
? iBar.low
|
|
: iBar.GetUp();
|
|
iLiq.at = iBar.time;
|
|
iLiq.from = iBar.time;
|
|
iLiq.symbol = _Symbol;
|
|
iLiq.period = _Period;
|
|
iLiq.to = ((datetime)((int)iBar.time + (PeriodSeconds(_Period))));
|
|
|
|
//
|
|
if (iLiq.IsValid())
|
|
{
|
|
//
|
|
if (isBullishLiquiditySweeped)
|
|
{
|
|
//
|
|
has = AddBoxIfNotExists(
|
|
iLiq,
|
|
mBullishLiquidities //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
SortBoxes(
|
|
mBullishLiquidities,
|
|
maxAllowedPOIs //
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
has = AddBoxIfNotExists(
|
|
iLiq,
|
|
mBearishLiquidities //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
SortBoxes(
|
|
mBearishLiquidities,
|
|
maxAllowedPOIs //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
iLiq.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Detecting Bullish and Bearish Breakes ...
|
|
|
|
//
|
|
bool isPeakSame = peakBuffer[barIndex] == peakBuffer[barIndex + 1];
|
|
bool isPPeakSame = peakBuffer[barIndex + 1] == peakBuffer[barIndex + 2];
|
|
|
|
//
|
|
bool isPeakOverLast = peakBuffer[barIndex] > peakBuffer[barIndex + 1];
|
|
bool isPPeakOverLast = peakBuffer[barIndex + 1] > peakBuffer[barIndex + 2];
|
|
|
|
//
|
|
bool isPeakUnderLast = peakBuffer[barIndex] < peakBuffer[barIndex + 1];
|
|
bool isPPeakUnderLast = peakBuffer[barIndex + 1] < peakBuffer[barIndex + 2];
|
|
|
|
//
|
|
bool isSamePeakOverLast =
|
|
isPPeakSame &&
|
|
isPeakOverLast;
|
|
bool isSamePeakUnderLast =
|
|
isPPeakSame &&
|
|
isPeakUnderLast;
|
|
|
|
//
|
|
bool isValeSame = valeBuffer[barIndex] == valeBuffer[barIndex + 1];
|
|
bool isPValeSame = valeBuffer[barIndex + 1] == valeBuffer[barIndex + 2];
|
|
|
|
//
|
|
bool isValeOverLast = valeBuffer[barIndex] > valeBuffer[barIndex + 1];
|
|
bool isPValeOverLast = valeBuffer[barIndex + 1] > valeBuffer[barIndex + 2];
|
|
|
|
//
|
|
bool isValeUnderLast = valeBuffer[barIndex] < valeBuffer[barIndex + 1];
|
|
bool isPValeUnderLast = valeBuffer[barIndex + 1] < valeBuffer[barIndex + 2];
|
|
|
|
//
|
|
bool isSameValeOverLast =
|
|
isPValeSame &&
|
|
isValeOverLast;
|
|
bool isSameValeUnderLast =
|
|
isPValeSame &&
|
|
isValeUnderLast;
|
|
|
|
//
|
|
// Detecting Range Breakes ...
|
|
if (mDetectRangeBreakes)
|
|
{
|
|
//
|
|
isBullish = isSamePeakOverLast
|
|
// || isSameValeOverLast
|
|
;
|
|
isBearish =
|
|
isSameValeUnderLast
|
|
// || isSamePeakUnderLast
|
|
;
|
|
|
|
//
|
|
bool basedOnPeak =
|
|
isSamePeakOverLast
|
|
// || isSamePeakUnderLast
|
|
;
|
|
|
|
//
|
|
bool basedOnVale =
|
|
isSameValeUnderLast
|
|
// isSameValeOverLast ||
|
|
;
|
|
|
|
//
|
|
has = isBullish ||
|
|
isBearish;
|
|
|
|
//
|
|
if (has)
|
|
{
|
|
//
|
|
XBoxZone iRNGBreak;
|
|
|
|
//
|
|
iDir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
|
|
//
|
|
iRNGBreak.dir = iDir;
|
|
iRNGBreak.at = iBar.time;
|
|
iRNGBreak.type = "XRNGB";
|
|
iRNGBreak.to = iBar.time;
|
|
iRNGBreak.symbol = _Symbol;
|
|
iRNGBreak.period = _Period;
|
|
|
|
//
|
|
int fromIDX =
|
|
iBar.Index() +
|
|
(basedOnPeak
|
|
? mSamePeakCount
|
|
: basedOnVale
|
|
? mSameValeCount
|
|
: 0);
|
|
datetime from = GetBarTime(
|
|
_Symbol,
|
|
_Period,
|
|
fromIDX //
|
|
);
|
|
iRNGBreak.from = from;
|
|
|
|
//
|
|
double upper =
|
|
isBullish
|
|
? basedOnPeak
|
|
? peakBuffer[barIndex]
|
|
: basedOnVale
|
|
? mSameValeGoldenCount
|
|
: 0
|
|
: isBearish
|
|
? basedOnPeak
|
|
? peakBuffer[barIndex]
|
|
: basedOnVale
|
|
? mSameValeGoldenCount
|
|
: 0
|
|
: 0;
|
|
|
|
//
|
|
double lower =
|
|
isBullish
|
|
? basedOnPeak
|
|
? mSamePeakGoldenCount
|
|
: basedOnVale
|
|
? valeBuffer[barIndex]
|
|
: 0
|
|
: isBearish
|
|
? basedOnPeak
|
|
? mSamePeakGoldenCount
|
|
: basedOnVale
|
|
? valeBuffer[barIndex]
|
|
: 0
|
|
: 0;
|
|
|
|
//
|
|
iRNGBreak.upper = upper;
|
|
iRNGBreak.lower = lower;
|
|
|
|
//
|
|
// Adding POI ...
|
|
has = iRNGBreak.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
has = AddBoxIfNotExists(
|
|
iRNGBreak,
|
|
mBullishRangeBreakes //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
SortBoxes(
|
|
mBullishRangeBreakes,
|
|
maxAllowedPOIs //
|
|
);
|
|
}
|
|
}
|
|
else if (isBearish)
|
|
{
|
|
//
|
|
has = AddBoxIfNotExists(
|
|
iRNGBreak,
|
|
mBearishRangeBreakes //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
SortBoxes(
|
|
mBearishRangeBreakes,
|
|
maxAllowedPOIs //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
if (isPeakSame)
|
|
{
|
|
//
|
|
mSamePeakGoldenCount =
|
|
mSamePeakGoldenCount == 0
|
|
? iBar.GetUp()
|
|
: MathMax(mSamePeakGoldenCount, iBar.GetUp());
|
|
mSamePeakCount++;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
mSamePeakCount = 0;
|
|
mSamePeakGoldenCount = 0;
|
|
}
|
|
|
|
//
|
|
if (isValeSame)
|
|
{
|
|
//
|
|
mSameValeGoldenCount =
|
|
mSameValeGoldenCount == 0
|
|
? iBar.GetDown()
|
|
: MathMin(mSameValeGoldenCount, iBar.GetDown());
|
|
mSameValeCount++;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
mSameValeCount = 0;
|
|
mSameValeGoldenCount = 0;
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
|
|
//
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
}
|
|
|
|
/**
|
|
* Validate Detected POI(s) ...
|
|
*
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param prevCalculated: int, Provides Previous Calculated Bars ...
|
|
* @param ratesTotal: int, Provides All Availabled Bars ...
|
|
* @param open: double Collection, Provides Open Prices Time Series ...
|
|
* @param high: double Collection, Provides High Prices Time Series ...
|
|
* @param close: double Collection, Provides Close Prices Time Series ...
|
|
* @param low: double Collection, Provides Low Prices Time Series ...
|
|
* @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ...
|
|
*/
|
|
void ValidatePOIs(
|
|
int barIndex,
|
|
const int prevCalculated,
|
|
const int ratesTotal,
|
|
const double &open[],
|
|
const double &high[],
|
|
const double &close[],
|
|
const double &low[],
|
|
const long &tickVolume[] //
|
|
)
|
|
{
|
|
//
|
|
int count = 0;
|
|
bool has = false;
|
|
int barsLength = 3;
|
|
datetime to = GetBarTime(
|
|
_Symbol,
|
|
_Period,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
// Liquidities ...
|
|
|
|
//
|
|
// Bullish Liquidities ...
|
|
count = ArraySize(mBullishLiquidities);
|
|
has = IsValidSize(count);
|
|
if (has)
|
|
{
|
|
//
|
|
ValidateBoxes(
|
|
mBullishLiquidities,
|
|
barIndex,
|
|
barsLength //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Bearish Liquidities ...
|
|
count = ArraySize(mBearishLiquidities);
|
|
has = IsValidSize(count);
|
|
if (has)
|
|
{
|
|
//
|
|
ValidateBoxes(
|
|
mBearishLiquidities,
|
|
barIndex,
|
|
barsLength //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Range Breaks ...
|
|
|
|
//
|
|
// Bullish ...
|
|
count = ArraySize(mBullishRangeBreakes);
|
|
has = IsValidSize(count);
|
|
if (has)
|
|
{
|
|
//
|
|
ValidateBoxes(
|
|
mBullishRangeBreakes,
|
|
barIndex,
|
|
barsLength //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
count = ArraySize(mBearishRangeBreakes);
|
|
has = IsValidSize(count);
|
|
if (has)
|
|
{
|
|
//
|
|
ValidateBoxes(
|
|
mBearishRangeBreakes,
|
|
barIndex,
|
|
barsLength //
|
|
);
|
|
}
|
|
|
|
//
|
|
}
|
|
|
|
/**
|
|
* Draw Detected POI(s) ...
|
|
*
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param prevCalculated: int, Provides Previous Calculated Bars ...
|
|
* @param ratesTotal: int, Provides All Availabled Bars ...
|
|
* @param open: double Collection, Provides Open Prices Time Series ...
|
|
* @param high: double Collection, Provides High Prices Time Series ...
|
|
* @param close: double Collection, Provides Close Prices Time Series ...
|
|
* @param low: double Collection, Provides Low Prices Time Series ...
|
|
* @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ...
|
|
*/
|
|
void DrawPOIs(
|
|
int barIndex,
|
|
const int prevCalculated,
|
|
const int ratesTotal,
|
|
const double &open[],
|
|
const double &high[],
|
|
const double &close[],
|
|
const double &low[],
|
|
const long &tickVolume[] //
|
|
)
|
|
{
|
|
//
|
|
int count = 0;
|
|
XBoxZone iBox;
|
|
bool has = false;
|
|
datetime to = GetBarTime(
|
|
_Symbol,
|
|
_Period,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
// Liquidities ...
|
|
if (mDrawLiquidities)
|
|
{
|
|
//
|
|
count = ArraySize(mBullishLiquidities);
|
|
has = IsValidSize(count);
|
|
if (has)
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
iBox = mBullishLiquidities[i];
|
|
iBox.to = to;
|
|
|
|
//
|
|
XCBoxObject *iObj;
|
|
has = mDrawer.DrawBox(
|
|
iBox,
|
|
iObj //
|
|
);
|
|
if (has)
|
|
{
|
|
mObjects.Add(iObj);
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
count = ArraySize(mBearishLiquidities);
|
|
has = IsValidSize(count);
|
|
if (has)
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
iBox = mBearishLiquidities[i];
|
|
iBox.to = to;
|
|
|
|
//
|
|
XCBoxObject *iObj;
|
|
has = mDrawer.DrawBox(
|
|
iBox,
|
|
iObj //
|
|
);
|
|
if (has)
|
|
{
|
|
mObjects.Add(iObj);
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Range Breaks ...
|
|
if (mDrawRangeBreakes)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
count = ArraySize(mBullishRangeBreakes);
|
|
has = IsValidSize(count);
|
|
if (has)
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
iBox = mBullishRangeBreakes[i];
|
|
iBox.to = to;
|
|
|
|
//
|
|
XCBoxObject *iObj;
|
|
has = mDrawer.DrawBox(
|
|
iBox,
|
|
iObj //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
XPOIStyle iStyle;
|
|
iStyle.width = 1;
|
|
iStyle.clr = clrAqua;
|
|
iStyle.style = STYLE_DOT;
|
|
|
|
//
|
|
mDrawer.ApplyStyle(
|
|
iObj,
|
|
iStyle //
|
|
);
|
|
|
|
//
|
|
mObjects.Add(iObj);
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
count = ArraySize(mBearishRangeBreakes);
|
|
has = IsValidSize(count);
|
|
if (has)
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
iBox = mBearishRangeBreakes[i];
|
|
iBox.to = to;
|
|
|
|
//
|
|
XCBoxObject *iObj;
|
|
has = mDrawer.DrawBox(
|
|
iBox,
|
|
iObj //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
XPOIStyle iStyle;
|
|
iStyle.width = 1;
|
|
iStyle.clr = clrMagenta;
|
|
iStyle.style = STYLE_DOT;
|
|
|
|
//
|
|
mDrawer.ApplyStyle(
|
|
iObj,
|
|
iStyle //
|
|
);
|
|
|
|
//
|
|
mObjects.Add(iObj);
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
}
|
|
|
|
/**
|
|
* Process Custom Analysing Senarios ...
|
|
*
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param prevCalculated: int, Provides Previous Calculated Bars ...
|
|
* @param ratesTotal: int, Provides All Availabled Bars ...
|
|
* @param open: double Collection, Provides Open Prices Time Series ...
|
|
* @param high: double Collection, Provides High Prices Time Series ...
|
|
* @param close: double Collection, Provides Close Prices Time Series ...
|
|
* @param low: double Collection, Provides Low Prices Time Series ...
|
|
* @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ...
|
|
*/
|
|
void DoProcess(
|
|
int barIndex,
|
|
const int prevCalculated,
|
|
const int ratesTotal,
|
|
const double &open[],
|
|
const double &high[],
|
|
const double &close[],
|
|
const double &low[],
|
|
const long &tickVolume[] //
|
|
)
|
|
{
|
|
//
|
|
// Check Some Requirements ...
|
|
int lastBarIndex = barIndex + 1;
|
|
int maxBarIndex = startCalculationForLastBars > 0
|
|
? startCalculationForLastBars
|
|
: ratesTotal;
|
|
bool isFirstBar =
|
|
startCalculationForLastBars > 0
|
|
? barIndex == startCalculationForLastBars
|
|
: barIndex == firstBarIndex;
|
|
|
|
//
|
|
// Recieve Bar ...
|
|
XOHCL iBar;
|
|
XOHCL iPBar;
|
|
bool has = iBar.Init(
|
|
_Symbol,
|
|
_Period,
|
|
barIndex
|
|
//
|
|
);
|
|
has =
|
|
has &&
|
|
iBar.GetPreviousBar(iPBar);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Do Process ...
|
|
|
|
//
|
|
// Detecting Trigger Bar ...
|
|
|
|
//
|
|
bool hasSignal = false;
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
string namePrefix = NULL;
|
|
int triggerBarPushers = 0;
|
|
ENUM_X_DIRECTION triggerDir;
|
|
|
|
//
|
|
// Detecting Trigger Bars ...
|
|
|
|
//
|
|
bool isCond1Trigger =
|
|
mBarAnalyser
|
|
.IsValidForTrigger(
|
|
iPBar,
|
|
triggerDir,
|
|
true, // Cond 1 ...
|
|
false, // Cond 2 ...
|
|
false, // Cond 3 ...
|
|
false, // Cond 4 ...
|
|
false, // Cond 5 ...
|
|
false, // Cond 6 ...
|
|
false // Cond 7 ...
|
|
);
|
|
bool isCond1BullishTrigger =
|
|
isCond1Trigger &&
|
|
IsBullish(triggerDir);
|
|
bool isCond1BearishTrigger =
|
|
isCond1Trigger &&
|
|
IsBearish(triggerDir);
|
|
if (isCond1Trigger)
|
|
{
|
|
//
|
|
triggerBarPushers++;
|
|
namePrefix += "Cond1";
|
|
}
|
|
|
|
//
|
|
bool isCond2Trigger =
|
|
mBarAnalyser
|
|
.IsValidForTrigger(
|
|
iPBar,
|
|
triggerDir,
|
|
false, // Cond 1 ...
|
|
true, // Cond 2 ...
|
|
false, // Cond 3 ...
|
|
false, // Cond 4 ...
|
|
false, // Cond 5 ...
|
|
false, // Cond 6 ...
|
|
false // Cond 7 ...
|
|
);
|
|
bool isCond2BullishTrigger =
|
|
isCond2Trigger &&
|
|
IsBullish(triggerDir);
|
|
bool isCond2BearishTrigger =
|
|
isCond2Trigger &&
|
|
IsBearish(triggerDir);
|
|
if (isCond2Trigger)
|
|
{
|
|
//
|
|
triggerBarPushers++;
|
|
namePrefix += "Cond2";
|
|
}
|
|
|
|
//
|
|
bool isCond3Trigger =
|
|
mBarAnalyser
|
|
.IsValidForTrigger(
|
|
iPBar,
|
|
triggerDir,
|
|
false, // Cond 1 ...
|
|
false, // Cond 2 ...
|
|
true, // Cond 3 ...
|
|
false, // Cond 4 ...
|
|
false, // Cond 5 ...
|
|
false, // Cond 6 ...
|
|
false // Cond 7 ...
|
|
);
|
|
bool isCond3BullishTrigger =
|
|
isCond3Trigger &&
|
|
IsBullish(triggerDir);
|
|
bool isCond3BearishTrigger =
|
|
isCond3Trigger &&
|
|
IsBearish(triggerDir);
|
|
if (isCond3Trigger)
|
|
{
|
|
//
|
|
triggerBarPushers++;
|
|
namePrefix += "Cond3";
|
|
}
|
|
|
|
//
|
|
bool isCond4Trigger =
|
|
mBarAnalyser
|
|
.IsValidForTrigger(
|
|
iPBar,
|
|
triggerDir,
|
|
false, // Cond 1 ...
|
|
false, // Cond 2 ...
|
|
false, // Cond 3 ...
|
|
true, // Cond 4 ...
|
|
false, // Cond 5 ...
|
|
false, // Cond 6 ...
|
|
false // Cond 7 ...
|
|
);
|
|
bool isCond4BullishTrigger =
|
|
isCond4Trigger &&
|
|
IsBullish(triggerDir);
|
|
bool isCond4BearishTrigger =
|
|
isCond4Trigger &&
|
|
IsBearish(triggerDir);
|
|
if (isCond4Trigger)
|
|
{
|
|
//
|
|
triggerBarPushers++;
|
|
namePrefix += "Cond4";
|
|
}
|
|
|
|
//
|
|
bool isCond5Trigger =
|
|
mBarAnalyser
|
|
.IsValidForTrigger(
|
|
iPBar,
|
|
triggerDir,
|
|
false, // Cond 1 ...
|
|
false, // Cond 2 ...
|
|
false, // Cond 3 ...
|
|
false, // Cond 4 ...
|
|
true, // Cond 5 ...
|
|
false, // Cond 6 ...
|
|
false // Cond 7 ...
|
|
);
|
|
bool isCond5BullishTrigger =
|
|
isCond5Trigger &&
|
|
IsBullish(triggerDir);
|
|
bool isCond5BearishTrigger =
|
|
isCond5Trigger &&
|
|
IsBearish(triggerDir);
|
|
if (isCond5Trigger)
|
|
{
|
|
//
|
|
triggerBarPushers++;
|
|
namePrefix += "Cond5";
|
|
}
|
|
|
|
//
|
|
bool isCond6Trigger =
|
|
mBarAnalyser
|
|
.IsValidForTrigger(
|
|
iPBar,
|
|
triggerDir,
|
|
false, // Cond 1 ...
|
|
false, // Cond 2 ...
|
|
false, // Cond 3 ...
|
|
false, // Cond 4 ...
|
|
false, // Cond 5 ...
|
|
true, // Cond 6 ...
|
|
false // Cond 7 ...
|
|
);
|
|
bool isCond6BullishTrigger =
|
|
isCond6Trigger &&
|
|
IsBullish(triggerDir);
|
|
bool isCond6BearishTrigger =
|
|
isCond6Trigger &&
|
|
IsBearish(triggerDir);
|
|
if (isCond6Trigger)
|
|
{
|
|
//
|
|
triggerBarPushers++;
|
|
namePrefix += "Cond6";
|
|
}
|
|
|
|
//
|
|
bool isCond7Trigger =
|
|
mBarAnalyser
|
|
.IsValidForTrigger(
|
|
iPBar,
|
|
triggerDir,
|
|
false, // Cond 1 ...
|
|
false, // Cond 2 ...
|
|
false, // Cond 3 ...
|
|
false, // Cond 4 ...
|
|
false, // Cond 5 ...
|
|
false, // Cond 6 ...
|
|
true // Cond 7 ...
|
|
);
|
|
bool isCond7BullishTrigger =
|
|
isCond7Trigger &&
|
|
IsBullish(triggerDir);
|
|
bool isCond7BearishTrigger =
|
|
isCond7Trigger &&
|
|
IsBearish(triggerDir);
|
|
if (isCond7Trigger)
|
|
{
|
|
//
|
|
triggerBarPushers++;
|
|
namePrefix += "Cond7";
|
|
}
|
|
|
|
//
|
|
// Summarizing Trigger Bars ...
|
|
|
|
//
|
|
bool isBullishTriggerBar =
|
|
//
|
|
isCond1BullishTrigger ||
|
|
isCond2BullishTrigger ||
|
|
isCond3BullishTrigger ||
|
|
isCond4BullishTrigger ||
|
|
isCond5BullishTrigger ||
|
|
isCond6BullishTrigger ||
|
|
isCond7BullishTrigger
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isBearishTriggerBar =
|
|
//
|
|
isCond1BearishTrigger ||
|
|
isCond2BearishTrigger ||
|
|
isCond3BearishTrigger ||
|
|
isCond4BearishTrigger ||
|
|
isCond5BearishTrigger ||
|
|
isCond6BearishTrigger ||
|
|
isCond7BearishTrigger
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isTriggerBar =
|
|
//
|
|
triggerBarPushers >= 1 &&
|
|
(isBullishTriggerBar ||
|
|
isBearishTriggerBar)
|
|
//
|
|
;
|
|
|
|
//
|
|
// Reading Required Condiions ...
|
|
|
|
//
|
|
int pIndex = barIndex + 1;
|
|
int ppIndex = barIndex + 2;
|
|
|
|
//
|
|
// PV ...
|
|
|
|
//
|
|
bool isSamePeak = peakBuffer[pIndex] == peakBuffer[ppIndex];
|
|
bool isSameVale = valeBuffer[pIndex] == valeBuffer[ppIndex];
|
|
|
|
//
|
|
bool isPeakOverLast = peakBuffer[pIndex] > peakBuffer[ppIndex];
|
|
bool isPeakUnderLast = peakBuffer[pIndex] < peakBuffer[ppIndex];
|
|
|
|
//
|
|
bool isValeOverLast = valeBuffer[pIndex] > valeBuffer[ppIndex];
|
|
bool isValeUnderLast = valeBuffer[pIndex] < valeBuffer[ppIndex];
|
|
|
|
//
|
|
bool isSamePeakGolden = peakGoldenBuffer[pIndex] == peakGoldenBuffer[ppIndex];
|
|
bool isSameValeGolden = valeGoldenBuffer[pIndex] == valeGoldenBuffer[ppIndex];
|
|
|
|
//
|
|
bool isPeakGoldeOverLast = peakGoldenBuffer[pIndex] > peakGoldenBuffer[ppIndex];
|
|
bool isPeakGoldenUnderLast = peakGoldenBuffer[pIndex] < peakGoldenBuffer[ppIndex];
|
|
|
|
//
|
|
bool isValeGoldenOverLast = valeGoldenBuffer[pIndex] > valeGoldenBuffer[ppIndex];
|
|
bool isValeGoldenUnderLast = valeGoldenBuffer[pIndex] < valeGoldenBuffer[ppIndex];
|
|
|
|
//
|
|
if (isSamePeak)
|
|
{
|
|
mSamePeakCount++;
|
|
}
|
|
else
|
|
{
|
|
mSamePeakCount = 0;
|
|
}
|
|
|
|
//
|
|
if (isSameVale)
|
|
{
|
|
mSameValeCount++;
|
|
}
|
|
else
|
|
{
|
|
mSameValeCount = 0;
|
|
}
|
|
|
|
//
|
|
if (isSamePeakGolden)
|
|
{
|
|
mSamePeakGoldenCount++;
|
|
}
|
|
else
|
|
{
|
|
mSamePeakGoldenCount = 0;
|
|
}
|
|
|
|
//
|
|
if (isSameValeGolden)
|
|
{
|
|
mSameValeGoldenCount++;
|
|
}
|
|
else
|
|
{
|
|
mSameValeGoldenCount = 0;
|
|
}
|
|
|
|
//
|
|
// SAR ...
|
|
|
|
//
|
|
bool isSarBullish = sarStateBuffer[pIndex] > 0;
|
|
bool isPSarBullish = sarStateBuffer[ppIndex] > 0;
|
|
|
|
//
|
|
bool isSarBearish = sarStateBuffer[pIndex] < 0;
|
|
bool isPSarBearish = sarStateBuffer[ppIndex] < 0;
|
|
|
|
//
|
|
bool isSarSwitchedToBullish =
|
|
isSarBullish &&
|
|
!isPSarBullish;
|
|
|
|
//
|
|
bool isSarSwitchedToBearish =
|
|
isSarBearish &&
|
|
!isPSarBearish;
|
|
|
|
//
|
|
// HKS ...
|
|
|
|
//
|
|
bool isHKSBullish = hkSBarCloseBuffer[pIndex] > hkSBarOpenBuffer[pIndex];
|
|
bool isPHKSBullish = hkSBarCloseBuffer[ppIndex] > hkSBarOpenBuffer[ppIndex];
|
|
|
|
//
|
|
bool isHKSBearish = hkSBarCloseBuffer[pIndex] < hkSBarOpenBuffer[pIndex];
|
|
bool isPHKSBearish = hkSBarCloseBuffer[ppIndex] < hkSBarOpenBuffer[ppIndex];
|
|
|
|
//
|
|
bool isHKSSwitchedToBullish =
|
|
isHKSBullish &&
|
|
!isPHKSBullish;
|
|
|
|
//
|
|
bool isHKSSwitchedToBearish =
|
|
isHKSBearish &&
|
|
!isPHKSBearish;
|
|
|
|
//
|
|
// SB ...
|
|
|
|
//
|
|
bool isSBullish = sBarCloseBuffer[pIndex] > sBarOpenBuffer[pIndex];
|
|
bool isPSBullish = sBarCloseBuffer[ppIndex] > sBarOpenBuffer[ppIndex];
|
|
|
|
//
|
|
bool isSBearish = sBarCloseBuffer[pIndex] < sBarOpenBuffer[pIndex];
|
|
bool isPSBearish = sBarCloseBuffer[ppIndex] < sBarOpenBuffer[ppIndex];
|
|
|
|
//
|
|
bool isSSwitchedToBullish =
|
|
isSBullish &&
|
|
!isPSBullish;
|
|
|
|
//
|
|
bool isSSwitchedToBearish =
|
|
isSBearish &&
|
|
!isPSBearish;
|
|
|
|
//
|
|
// KI ...
|
|
|
|
//
|
|
bool isKIBullish = kiStateBuffer[pIndex] > 0;
|
|
bool isPKIBullish = kiStateBuffer[ppIndex] > 0;
|
|
|
|
//
|
|
bool isKIBearish = kiStateBuffer[pIndex] < 0;
|
|
bool isPKIBearish = kiStateBuffer[ppIndex] < 0;
|
|
|
|
//
|
|
bool isKISwitchedToBullish =
|
|
isKIBullish &&
|
|
!isPKIBullish;
|
|
|
|
//
|
|
bool isKISwitchedToBearish =
|
|
isKIBearish &&
|
|
!isPKIBearish;
|
|
|
|
//
|
|
bool isKIBullishBreaked =
|
|
iPBar.IsBreaked(
|
|
kiBuffer[pIndex],
|
|
X_DIRECTION_BULLISH,
|
|
X_FIBO_LEVEL_500,
|
|
X_BOUNDARY_PRICE_UP_DOWN //
|
|
);
|
|
|
|
//
|
|
bool isKIBearishBreaked =
|
|
iPBar.IsBreaked(
|
|
kiBuffer[pIndex],
|
|
X_DIRECTION_BEARISH,
|
|
X_FIBO_LEVEL_500,
|
|
X_BOUNDARY_PRICE_UP_DOWN //
|
|
);
|
|
|
|
//
|
|
bool isKISame = kiBuffer[pIndex] == kiBuffer[ppIndex];
|
|
bool isKIBullishSame =
|
|
isKISame &&
|
|
isKIBullish;
|
|
bool isKIBearishSame =
|
|
isKISame &&
|
|
isKIBearish;
|
|
|
|
//
|
|
if (isKISame)
|
|
{
|
|
mSameKICount++;
|
|
}
|
|
else
|
|
{
|
|
mSameKICount = 0;
|
|
}
|
|
|
|
//
|
|
if (isKIBullishSame)
|
|
{
|
|
mSameKIBullishCount++;
|
|
}
|
|
else
|
|
{
|
|
mSameKIBullishCount = 0;
|
|
}
|
|
|
|
//
|
|
if (isKIBearishSame)
|
|
{
|
|
mSameKIBearishCount++;
|
|
}
|
|
else
|
|
{
|
|
mSameKIBearishCount = 0;
|
|
}
|
|
|
|
//
|
|
// Validating Trigger Bar based on Conditions ...
|
|
if (isTriggerBar)
|
|
{
|
|
//
|
|
// TODO: Remove this if required ...
|
|
isTriggerBar = false;
|
|
isBullishTriggerBar = false;
|
|
isBearishTriggerBar = false;
|
|
}
|
|
|
|
//
|
|
// Detecting Signal ...
|
|
|
|
//
|
|
// Bullish ...
|
|
isBullish =
|
|
//
|
|
// Conditions Validation ...
|
|
isKIBullishBreaked
|
|
// isSSwitchedToBullish
|
|
// isKISwitchedToBullish
|
|
// isSarSwitchedToBullish
|
|
// isHKSSwitchedToBullish
|
|
//
|
|
// Bar Validation ...
|
|
//
|
|
;
|
|
|
|
//
|
|
// Bearish ...
|
|
isBearish =
|
|
//
|
|
// Conditions Validation ...
|
|
isKIBearishBreaked
|
|
// isSSwitchedToBearish
|
|
// isKISwitchedToBearish
|
|
// isSarSwitchedToBearish
|
|
// isHKSSwitchedToBearish
|
|
//
|
|
// Bar Validation ...
|
|
//
|
|
;
|
|
|
|
//
|
|
// Summarizing Signal ...
|
|
hasSignal =
|
|
isBullish ||
|
|
isBearish;
|
|
|
|
//
|
|
// Draw Requirements ...
|
|
|
|
//
|
|
// Draw Trigger Bar ...
|
|
if (isTriggerBar)
|
|
{
|
|
//
|
|
int triggerBullishArrowCode = 225;
|
|
int triggerBearishArrowCode = 226;
|
|
|
|
//
|
|
color triggerBarBullishColor = clrLime;
|
|
color triggerBarBearishColor = clrRed;
|
|
|
|
//
|
|
ENUM_ARROW_ANCHOR triggerBullishAnchor = ANCHOR_TOP;
|
|
ENUM_ARROW_ANCHOR triggerBearishAnchor = ANCHOR_BOTTOM;
|
|
|
|
//
|
|
int arrowWidth = 3;
|
|
int arrowCode =
|
|
isBullishTriggerBar
|
|
? triggerBullishArrowCode
|
|
: triggerBearishArrowCode;
|
|
ENUM_X_PRICE arrowPriceType =
|
|
isBullishTriggerBar
|
|
? X_PRICE_LOW
|
|
: X_PRICE_HIGH;
|
|
color arrowColor =
|
|
isBullishTriggerBar
|
|
? triggerBarBullishColor
|
|
: triggerBarBearishColor;
|
|
ENUM_ARROW_ANCHOR arrowAnchor =
|
|
isBullishTriggerBar
|
|
? triggerBullishAnchor
|
|
: triggerBearishAnchor;
|
|
|
|
//
|
|
XCBarArrowObject *iObj;
|
|
has = mDrawer.CreateBarArrow(
|
|
iBar,
|
|
iObj,
|
|
arrowPriceType,
|
|
arrowCode,
|
|
arrowColor,
|
|
arrowWidth,
|
|
arrowAnchor,
|
|
namePrefix //
|
|
);
|
|
if (has)
|
|
{
|
|
mObjects.Add(iObj);
|
|
}
|
|
|
|
//
|
|
// Converts to Box ...
|
|
XBoxZone iBox;
|
|
iBox.type = "XTRB";
|
|
iBox.to = iBar.time;
|
|
iBox.symbol = _Symbol;
|
|
iBox.period = _Period;
|
|
iBox.lower = iPBar.low;
|
|
iBox.from = iPBar.time;
|
|
iBox.upper = iPBar.high;
|
|
iBox.dir =
|
|
isBullishTriggerBar
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
if (iBox.IsValid())
|
|
{
|
|
//
|
|
// XCBoxObject *iObj;
|
|
// has = mDrawer.DrawBox(
|
|
// iBox,
|
|
// iObj //
|
|
// );
|
|
// if (has)
|
|
// {
|
|
// mObjects.Add(iObj);
|
|
// }
|
|
|
|
//
|
|
XSignal iSignal;
|
|
double iRewardRatios[] = {
|
|
1,
|
|
1.5,
|
|
2 //
|
|
};
|
|
has = ToSignal(
|
|
iBox,
|
|
iSignal,
|
|
iRewardRatios,
|
|
0 // Additional SL ...
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
XCSignalObject *iObj;
|
|
has = mDrawer.DrawSignal(
|
|
iSignal,
|
|
iObj,
|
|
4 //
|
|
);
|
|
if (has)
|
|
{
|
|
mObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
}
|
|
|
|
//
|
|
// Draw Signal ...
|
|
if (hasSignal)
|
|
{
|
|
//
|
|
int bullishArrowCode = 225;
|
|
int bearishArrowCode = 226;
|
|
|
|
//
|
|
color bullishColor = clrLime;
|
|
color bearishColor = clrRed;
|
|
|
|
//
|
|
ENUM_ARROW_ANCHOR bullishAnchor = ANCHOR_TOP;
|
|
ENUM_ARROW_ANCHOR bearishAnchor = ANCHOR_BOTTOM;
|
|
|
|
//
|
|
int arrowWidth = 3;
|
|
int arrowCode =
|
|
isBullish
|
|
? bullishArrowCode
|
|
: bearishArrowCode;
|
|
ENUM_X_PRICE arrowPriceType =
|
|
isBullish
|
|
? X_PRICE_LOW
|
|
: X_PRICE_HIGH;
|
|
color arrowColor =
|
|
isBullish
|
|
? bullishColor
|
|
: bearishColor;
|
|
ENUM_ARROW_ANCHOR arrowAnchor =
|
|
isBullish
|
|
? bullishAnchor
|
|
: bearishAnchor;
|
|
|
|
//
|
|
XCBarArrowObject *iObj;
|
|
has = mDrawer.CreateBarArrow(
|
|
iBar,
|
|
iObj,
|
|
arrowPriceType,
|
|
arrowCode,
|
|
arrowColor,
|
|
arrowWidth,
|
|
arrowAnchor,
|
|
namePrefix //
|
|
);
|
|
if (has)
|
|
{
|
|
mObjects.Add(iObj);
|
|
}
|
|
|
|
//
|
|
// Converts to Box ...
|
|
XBoxZone iBox;
|
|
iBox.type = "XSG";
|
|
iBox.to = iBar.time;
|
|
iBox.symbol = _Symbol;
|
|
iBox.period = _Period;
|
|
iBox.lower = iPBar.low;
|
|
iBox.from = iPBar.time;
|
|
iBox.upper = iPBar.high;
|
|
iBox.dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
if (iBox.IsValid())
|
|
{
|
|
//
|
|
XSignal iSignal;
|
|
double iRewardRatios[] = {
|
|
1,
|
|
1.5,
|
|
2 //
|
|
};
|
|
has = ToSignal(
|
|
iBox,
|
|
iSignal,
|
|
iRewardRatios,
|
|
0 // Additional SL ...
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
XCSignalObject *iObj;
|
|
has = mDrawer.DrawSignal(
|
|
iSignal,
|
|
iObj,
|
|
4 //
|
|
);
|
|
if (has)
|
|
{
|
|
mObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
|
|
//
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* Analyse Market based on Specified Kind of Pivots ...
|
|
*
|
|
* @param analysis: XPivotAnalysis, reference to hold result ...
|
|
* @param barIndex: int, Bar Index ...
|
|
* @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ...
|
|
* @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ...
|
|
* @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool AnalysePVPivots(
|
|
XPivotAnalysis &analysis,
|
|
int barIndex = 0,
|
|
int requiredNumberOFPivots = 50,
|
|
int maxAllowedLoopbackLength = 1500,
|
|
int validationLength = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
analysis.Clean();
|
|
|
|
//
|
|
// Reading Pivots ...
|
|
XPivot pivots[];
|
|
int count = fimaHelper.ExtractPVPivots(
|
|
pivots, // Result ...
|
|
barIndex, // Bar Index ...
|
|
requiredNumberOFPivots, // Required Number of Pivots ...
|
|
maxAllowedLoopbackLength, // Max Allowed Loopback ...
|
|
validationLength // Validation Length ...
|
|
);
|
|
result = IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
//
|
|
SpecifiedClean(pivots);
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string symbol = fimaHelper.GetSymbol();
|
|
ENUM_TIMEFRAMES period = fimaHelper.GetPeriod();
|
|
|
|
//
|
|
// Initialize Analysis ...
|
|
result = analysis.Init(
|
|
"XFIMA_XPV",
|
|
symbol,
|
|
period,
|
|
pivots //
|
|
);
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
if (!result)
|
|
{
|
|
analysis.Clean();
|
|
}
|
|
SpecifiedClean(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Analyse Market based on Specified Kind of Pivots ...
|
|
*
|
|
* @param analysis: XPivotAnalysis, reference to hold result ...
|
|
* @param barIndex: int, Bar Index ...
|
|
* @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ...
|
|
* @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ...
|
|
* @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool AnalyseMAPivots(
|
|
XPivotAnalysis &analysis,
|
|
int barIndex = 0,
|
|
int requiredNumberOFPivots = 50,
|
|
int maxAllowedLoopbackLength = 1500,
|
|
int validationLength = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
analysis.Clean();
|
|
|
|
//
|
|
// Reading Pivots ...
|
|
XPivot pivots[];
|
|
int count = fimaHelper.ExtractMAPivots(
|
|
pivots, // Result ...
|
|
barIndex, // Bar Index ...
|
|
requiredNumberOFPivots, // Required Number of Pivots ...
|
|
maxAllowedLoopbackLength, // Max Allowed Loopback ...
|
|
validationLength // Validation Length ...
|
|
);
|
|
result = IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
//
|
|
SpecifiedClean(pivots);
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string symbol = fimaHelper.GetSymbol();
|
|
ENUM_TIMEFRAMES period = fimaHelper.GetPeriod();
|
|
|
|
//
|
|
// Initialize Analysis ...
|
|
result = analysis.Init(
|
|
"XFIMA_XMA",
|
|
symbol,
|
|
period,
|
|
pivots //
|
|
);
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
if (!result)
|
|
{
|
|
analysis.Clean();
|
|
}
|
|
SpecifiedClean(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Analyse Market based on Specified Kind of Pivots ...
|
|
*
|
|
* @param analysis: XPivotAnalysis, reference to hold result ...
|
|
* @param barIndex: int, Bar Index ...
|
|
* @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ...
|
|
* @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool AnalyseSARPivots(
|
|
XPivotAnalysis &analysis,
|
|
int barIndex = 0,
|
|
int requiredNumberOFPivots = 50,
|
|
int maxAllowedLoopbackLength = 1500 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
analysis.Clean();
|
|
|
|
//
|
|
// Reading Pivots ...
|
|
XPivot pivots[];
|
|
int count = fimaHelper.ExtractSARPivots(
|
|
pivots, // Result ...
|
|
barIndex, // Bar Index ...
|
|
requiredNumberOFPivots, // Required Number of Pivots ...
|
|
maxAllowedLoopbackLength // Max Allowed Loopback ...
|
|
);
|
|
result = IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
//
|
|
SpecifiedClean(pivots);
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string symbol = fimaHelper.GetSymbol();
|
|
ENUM_TIMEFRAMES period = fimaHelper.GetPeriod();
|
|
|
|
//
|
|
// Initialize Analysis ...
|
|
result = analysis.Init(
|
|
"XFIMA_XSAR",
|
|
symbol,
|
|
period,
|
|
pivots //
|
|
);
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
if (!result)
|
|
{
|
|
analysis.Clean();
|
|
}
|
|
SpecifiedClean(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Analyse Market based on Specified Kind of Pivots ...
|
|
*
|
|
* @param analysis: XPivotAnalysis, reference to hold result ...
|
|
* @param barIndex: int, Bar Index ...
|
|
* @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ...
|
|
* @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool AnalyseZigZagPivots(
|
|
XPivotAnalysis &analysis,
|
|
int barIndex = 0,
|
|
int requiredNumberOFPivots = 50,
|
|
int maxAllowedLoopbackLength = 1500 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
analysis.Clean();
|
|
|
|
//
|
|
// Reading Pivots ...
|
|
XPivot pivots[];
|
|
int count = fimaHelper.ExtractZigZagPivots(
|
|
pivots, // Result ...
|
|
barIndex, // Bar Index ...
|
|
requiredNumberOFPivots, // Required Number of Pivots ...
|
|
maxAllowedLoopbackLength // Max Allowed Loopback ...
|
|
);
|
|
result = IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
//
|
|
SpecifiedClean(pivots);
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Initialize Analysis ...
|
|
result = analysis.Init(
|
|
"XFIMA_XZG",
|
|
symbol,
|
|
period,
|
|
pivots //
|
|
);
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
if (!result)
|
|
{
|
|
analysis.Clean();
|
|
}
|
|
SpecifiedClean(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Analyse Market based on Specified Bar ...
|
|
*
|
|
* @param structure: XFIMAMarketStructure, reference to holds result ...
|
|
* @param config: XFIMAMarketStructureConfig, reference to Configure Detector ...
|
|
* @param barIndex: int, Bar Index ...
|
|
*/
|
|
void AnalyseMarket(
|
|
XFIMAMarketStructure &structure,
|
|
XFIMAMarketStructureConfig &config,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
// Prepare ...
|
|
structure.Clean();
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
|
|
//
|
|
bool has = false;
|
|
|
|
//
|
|
has = structure.bar.Init(
|
|
symbol,
|
|
period,
|
|
barIndex //
|
|
);
|
|
if (!has)
|
|
{
|
|
//
|
|
structure.Clean();
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Reading Bar Patterns ...
|
|
XOHCL iBar;
|
|
XPatternAnalysis iPatternAnalysis;
|
|
for (int i = barIndex; i < barIndex + config.loopback; i++)
|
|
{
|
|
//
|
|
// Cleanup ...
|
|
iBar.Clean();
|
|
iPatternAnalysis.Clean();
|
|
|
|
//
|
|
// Initialize Indexed Bar ...
|
|
//
|
|
has = structure.bar.BarAt(i, iBar);
|
|
if (!has)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Analyse Indexed Bar ...
|
|
has = AnalyseBarPatterns(iBar, iPatternAnalysis, config.barsAnalysisConfig);
|
|
if (has)
|
|
{
|
|
//
|
|
AddRef(
|
|
iPatternAnalysis,
|
|
structure.barsAnalysis //
|
|
);
|
|
|
|
//
|
|
if (i == barIndex)
|
|
{
|
|
structure.barAnalysis = iPatternAnalysis;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Satisfied ...
|
|
has = ArraySize(structure.barsAnalysis) >= config.requiredPivots;
|
|
if (has)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Handle Pivot Analysis ...
|
|
|
|
//
|
|
// XPV ...
|
|
if (config.analysePVPivots)
|
|
{
|
|
//
|
|
// Reading Pivots ...
|
|
has = AnalysePVPivots(
|
|
structure.pvAnalysis,
|
|
barIndex,
|
|
config.requiredPivots,
|
|
config.loopback,
|
|
config.pvPivotsValidationLength //
|
|
);
|
|
if (!has)
|
|
{
|
|
structure.pvAnalysis.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// XZG ...
|
|
if (config.analyseZGPivots)
|
|
{
|
|
//
|
|
// Reading Pivots ...
|
|
has = AnalyseZigZagPivots(
|
|
structure.zgAnalysis,
|
|
barIndex,
|
|
config.requiredPivots,
|
|
config.loopback //
|
|
);
|
|
if (!has)
|
|
{
|
|
structure.zgAnalysis.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
iBar.Clean();
|
|
iPatternAnalysis.Clean();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* Check Specified Bar has MA Cross or not ...
|
|
*
|
|
* @param dir: reference for holds cross Direction ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param validCrossDiffMultiplier: double, validate diff between MAs on Cross happens ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasMACross(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0,
|
|
double validCrossDiffMultiplier = 1 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
validCrossDiffMultiplier = NormalizeDouble(validCrossDiffMultiplier, 0);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double fast[];
|
|
int fastCount = CopyMAFast(barIndex, 2, fast);
|
|
|
|
//
|
|
double slow[];
|
|
int slowCount = CopyMASlow(barIndex, 2, slow);
|
|
|
|
//
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
// Validate Readed Values ...
|
|
int count = MathMin(fastCount, slowCount);
|
|
result = IsValidSize(count) && count >= 2;
|
|
if (result)
|
|
{
|
|
//
|
|
// Detect Direction Change ...
|
|
|
|
//
|
|
bool notEmpty =
|
|
NotEmptyZero(fast[0]) &&
|
|
NotEmptyZero(fast[1]) &&
|
|
NotEmptyZero(slow[0]) &&
|
|
NotEmptyZero(slow[1]);
|
|
|
|
//
|
|
isBullish =
|
|
notEmpty &&
|
|
fast[0] > slow[0] &&
|
|
fast[1] < slow[1];
|
|
|
|
//
|
|
isBearish =
|
|
notEmpty &&
|
|
fast[0] < slow[0] &&
|
|
fast[1] > slow[1];
|
|
|
|
//
|
|
result =
|
|
isBullish ||
|
|
isBearish;
|
|
|
|
//
|
|
// Validate Direction Change ...
|
|
if (result &&
|
|
validCrossDiffMultiplier > 0)
|
|
{
|
|
//
|
|
double _points = GetPoints(GetSymbol());
|
|
double diff = MathAbs(fast[0] - slow[0]);
|
|
|
|
//
|
|
result = diff >= (validCrossDiffMultiplier * _points);
|
|
}
|
|
}
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
// Setting Direction ...
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
XClean(fast);
|
|
XClean(slow);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar Price is In Boundary or not ...
|
|
*
|
|
* @param priceType: ENUM_X_PRICE, Specified Price type of Bar ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsInBoundary(
|
|
ENUM_X_PRICE priceType = X_PRICE_CLOSE,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
if (!IsXValid(priceType))
|
|
{
|
|
priceType = X_PRICE_CLOSE;
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Bar ...
|
|
XOHCL bar;
|
|
result = bar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
return result;
|
|
}
|
|
double value = bar.GetPrice(priceType);
|
|
|
|
//
|
|
// Read Boundary Values ...
|
|
double min;
|
|
double max;
|
|
result = GetBoundaryValues(min, max, barIndex);
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = value < max &&
|
|
value > min;
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar Price is Over Boundary Min ...
|
|
*
|
|
* @param priceType: ENUM_X_PRICE, Specified Price type of Bar ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsOverBoundaryMin(
|
|
ENUM_X_PRICE priceType = X_PRICE_CLOSE,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
if (!IsXValid(priceType))
|
|
{
|
|
priceType = X_PRICE_CLOSE;
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Boundary ...
|
|
double min;
|
|
double max;
|
|
result = GetBoundaryValues(min, max, barIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Bar ....
|
|
XOHCL bar;
|
|
result = bar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
return result;
|
|
}
|
|
double value = bar.GetPrice(priceType);
|
|
|
|
//
|
|
result = value > min;
|
|
|
|
//
|
|
// Cleanup ...
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar Price is Under Boundary Max ...
|
|
*
|
|
* @param priceType: ENUM_X_PRICE, Specified Price type of Bar ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsUnderBoundaryMax(
|
|
ENUM_X_PRICE priceType = X_PRICE_CLOSE,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
if (!IsXValid(priceType))
|
|
{
|
|
priceType = X_PRICE_CLOSE;
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Boundary ...
|
|
double min;
|
|
double max;
|
|
result = GetBoundaryValues(min, max, barIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Bar ....
|
|
XOHCL bar;
|
|
result = bar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
return result;
|
|
}
|
|
double value = bar.GetPrice(priceType);
|
|
|
|
//
|
|
result = value < max;
|
|
|
|
//
|
|
// Cleanup ...
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Boundary Fake Breaked or not ...
|
|
*
|
|
* @param dir: reference for holds cross Direction ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param overMaxPriceType: ENUM_X_PRICE, which price of Specified bar to Check ...
|
|
* @param underMinPriceType: ENUM_X_PRICE, which price of Specified bar to Check ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoundaryFakeBreaked(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0,
|
|
ENUM_X_PRICE overMaxPriceType = X_PRICE_NONE,
|
|
ENUM_X_PRICE underMinPriceType = X_PRICE_NONE //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
if (!IsXValid(overMaxPriceType))
|
|
{
|
|
overMaxPriceType = X_PRICE_CLOSE;
|
|
}
|
|
if (!IsXValid(underMinPriceType))
|
|
{
|
|
underMinPriceType = X_PRICE_CLOSE;
|
|
}
|
|
|
|
//
|
|
// Initial Bars ...
|
|
XOHCL bar;
|
|
XOHCL pBar;
|
|
double min;
|
|
double max;
|
|
double pMin;
|
|
double pMax;
|
|
double boundaryValues[];
|
|
result =
|
|
bar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
) &&
|
|
bar.GetPreviousBar(pBar) &&
|
|
GetBoundaryValues(min, max, barIndex) &&
|
|
GetBoundaryValues(pMin, pMax, barIndex + 1) &&
|
|
FillBoundaryValues(boundaryValues, barIndex) > 0;
|
|
|
|
//
|
|
bool isBullish =
|
|
result &&
|
|
pBar.IsBearish() &&
|
|
bar.IsBullish() &&
|
|
pBar.GetPrice(underMinPriceType) < pMin &&
|
|
bar.GetPrice(underMinPriceType) > min &&
|
|
(bar.GetPrice(underMinPriceType) > FindLesserThan(max, boundaryValues) ||
|
|
bar.GetPrice(underMinPriceType) > FindBiggerThan(min + ((max - min) / 2), boundaryValues));
|
|
|
|
//
|
|
bool isBearish =
|
|
result &&
|
|
pBar.IsBullish() &&
|
|
bar.IsBearish() &&
|
|
pBar.GetPrice(overMaxPriceType) > pMax &&
|
|
bar.GetPrice(overMaxPriceType) < max &&
|
|
(bar.GetPrice(overMaxPriceType) < FindBiggerThan(min, boundaryValues) ||
|
|
bar.GetPrice(overMaxPriceType) < FindLesserThan(min + ((max - min) / 2), boundaryValues));
|
|
|
|
//
|
|
result = isBullish ||
|
|
isBearish;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
// Cleanup ...
|
|
bar.Clean();
|
|
pBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar's Price in Hot Place or Not ...
|
|
*
|
|
* @param dir: reference for holds cross Direction ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param overMaxPriceType: ENUM_X_PRICE, which price of Specified bar to Check ...
|
|
* @param underMinPriceType: ENUM_X_PRICE, which price of Specified bar to Check ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsInHotPlace(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0,
|
|
ENUM_X_PRICE overMaxPriceType = X_PRICE_NONE,
|
|
ENUM_X_PRICE underMinPriceType = X_PRICE_NONE //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
if (!IsXValid(overMaxPriceType))
|
|
{
|
|
overMaxPriceType = X_PRICE_LOW;
|
|
}
|
|
if (!IsXValid(underMinPriceType))
|
|
{
|
|
underMinPriceType = X_PRICE_HIGH;
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Initialize Bar ...
|
|
XOHCL bar;
|
|
result = bar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex);
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double overMaxPrice = bar.GetPrice(overMaxPriceType);
|
|
double underMinPrice = bar.GetPrice(underMinPriceType);
|
|
|
|
//
|
|
// Reading Boundary Value ...
|
|
double min;
|
|
double max;
|
|
result = GetBoundaryValues(
|
|
min,
|
|
max,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = underMinPrice < min;
|
|
bool isBearish = overMaxPrice > max;
|
|
|
|
//
|
|
result = (isBullish && !isBearish) ||
|
|
(isBearish && !isBullish);
|
|
if (result)
|
|
{
|
|
//
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar price Crossed in Boundary or not ...
|
|
*
|
|
* @param dir: ENUM_X_DIRECTION, reference to hold Crossed in Dir ...
|
|
* @param priceType: ENUM_X_PRICE, Specified Price type of Bar ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsCrossedInBoundary(
|
|
ENUM_X_DIRECTION &dir,
|
|
ENUM_X_PRICE priceType = X_PRICE_CLOSE,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
int pBarIndex = barIndex + 1;
|
|
|
|
//
|
|
if (!IsXValid(priceType))
|
|
{
|
|
priceType = X_PRICE_CLOSE;
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check PrevBar Is in Hot Place ...
|
|
result = IsInHotPlace(
|
|
dir,
|
|
pBarIndex,
|
|
X_PRICE_LOW,
|
|
X_PRICE_HIGH //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsXBullish(dir);
|
|
bool isBearish = IsXBearish(dir);
|
|
|
|
//
|
|
// Current Bar must Into Boundary ...
|
|
result = IsInBoundary(priceType, barIndex);
|
|
if (!result)
|
|
{
|
|
dir = X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
result = HasDirection(dir);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar price Crossed out Boundary or not ...
|
|
*
|
|
* @param dir: ENUM_X_DIRECTION, reference to hold Crossed in Dir ...
|
|
* @param priceType: ENUM_X_PRICE, Specified Price type of Bar ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsCrossedOutBoundary(
|
|
ENUM_X_DIRECTION &dir,
|
|
ENUM_X_PRICE priceType = X_PRICE_CLOSE,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
int pBarIndex = barIndex + 1;
|
|
|
|
//
|
|
if (!IsXValid(priceType))
|
|
{
|
|
priceType = X_PRICE_CLOSE;
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prev Bar Must in Boundary ...
|
|
bool isBullish = IsInBoundary(X_PRICE_LOW, pBarIndex);
|
|
bool isBearish = IsInBoundary(X_PRICE_HIGH, pBarIndex);
|
|
result = isBullish ||
|
|
isBearish;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Current Bar must Out of Boundary ...
|
|
|
|
XOHCL bar;
|
|
result = bar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
isBullish =
|
|
result &&
|
|
isBullish &&
|
|
bar.IsBullish() &&
|
|
!IsInBoundary(priceType, barIndex);
|
|
|
|
//
|
|
isBearish =
|
|
result &&
|
|
isBearish &&
|
|
bar.IsBearish() &&
|
|
!IsInBoundary(priceType, barIndex);
|
|
|
|
//
|
|
result = isBullish ||
|
|
isBearish;
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
dir = isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = HasDirection(dir);
|
|
|
|
//
|
|
// Cleanup ...
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar has Boundary Trend or not ...
|
|
*
|
|
* @param dir: reference for holds cross Direction ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasBoundaryTrend(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double fast = GetMAFast(barIndex);
|
|
double slow = GetMASlow(barIndex);
|
|
|
|
//
|
|
double maBandUpper = GetMABandUpper(barIndex);
|
|
double maBandLower = GetMABandLower(barIndex);
|
|
|
|
//
|
|
double pbBandUpper = GetPBBandUpper(barIndex);
|
|
double pbBandLower = GetPBBandLower(barIndex);
|
|
|
|
//
|
|
double hkBandUpper = GetHKBandUpper(barIndex);
|
|
double hkBandLower = GetHKBandLower(barIndex);
|
|
|
|
//
|
|
result =
|
|
NotEmptyZero(fast) &&
|
|
NotEmptyZero(slow) &&
|
|
NotEmptyZero(maBandUpper) &&
|
|
NotEmptyZero(maBandLower) &&
|
|
NotEmptyZero(hkBandUpper) &&
|
|
NotEmptyZero(hkBandLower) &&
|
|
NotEmptyZero(pbBandUpper) &&
|
|
NotEmptyZero(pbBandLower);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish =
|
|
fast > hkBandLower &&
|
|
slow > hkBandLower &&
|
|
maBandUpper > hkBandLower &&
|
|
maBandLower > hkBandLower &&
|
|
pbBandUpper > hkBandLower &&
|
|
pbBandLower > hkBandLower;
|
|
bool isBearish =
|
|
fast < hkBandUpper &&
|
|
slow < hkBandUpper &&
|
|
maBandUpper < hkBandUpper &&
|
|
maBandLower < hkBandUpper &&
|
|
pbBandUpper < hkBandUpper &&
|
|
pbBandLower < hkBandUpper;
|
|
|
|
//
|
|
result = (isBullish && !isBearish) ||
|
|
(isBearish && !isBullish);
|
|
if (result)
|
|
{
|
|
//
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar has Boundary Trend Switched or not ...
|
|
*
|
|
* @param dir: reference for holds cross Direction ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasBoundarySwitch(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = HasBoundaryTrend(
|
|
dir,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
bool isBullish = IsXBullish(dir);
|
|
bool isBearish = IsXBearish(dir);
|
|
|
|
//
|
|
result = HasBoundaryTrend(
|
|
dir,
|
|
barIndex + 1 //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
bool isPBullish = IsXBullish(dir);
|
|
bool isPBearish = IsXBearish(dir);
|
|
|
|
//
|
|
bool isSwitchedToBullish =
|
|
isBullish && !isPBullish;
|
|
bool isSwitchedToBearish =
|
|
isBearish && !isPBearish;
|
|
result = isSwitchedToBullish ||
|
|
isSwitchedToBearish;
|
|
if (result)
|
|
{
|
|
//
|
|
dir = isSwitchedToBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Fibo Section is Changed or not ...
|
|
*
|
|
* @param dir: reference to hold section change direction ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsFiboSectionChanged(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
// Reading Values ...
|
|
|
|
//
|
|
double iFiboUpper = GetFiboUpper(barIndex);
|
|
double pFiboUpper = GetFiboUpper(barIndex + 1);
|
|
|
|
//
|
|
double iFiboMiddle = GetFiboMiddle(barIndex);
|
|
double pFiboMiddle = GetFiboMiddle(barIndex + 1);
|
|
|
|
//
|
|
double iFiboLower = GetFiboLower(barIndex);
|
|
double pFiboLower = GetFiboLower(barIndex + 1);
|
|
|
|
//
|
|
isBullish = iFiboLower >= pFiboMiddle &&
|
|
iFiboMiddle >= pFiboUpper;
|
|
isBearish = iFiboUpper <= pFiboMiddle &&
|
|
iFiboMiddle <= pFiboLower;
|
|
result = (isBullish && !isBearish) ||
|
|
(isBearish && !isBullish);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check for Fibo Push Exists or not ...
|
|
*
|
|
* @param dir: ENUM_X_DIRECTION, reference to hold result ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param validationLength: int, Validation Length ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasFiboPush(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0,
|
|
int validationLength = 5 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
validationLength = NormalizeInt(validationLength, 3);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Define Requirements ...
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
double iFiboUpper = EMPTY_VALUE;
|
|
double pFiboUpper = EMPTY_VALUE;
|
|
|
|
//
|
|
double iFiboMiddle = EMPTY_VALUE;
|
|
double pFiboMiddle = EMPTY_VALUE;
|
|
|
|
//
|
|
double iFiboLower = EMPTY_VALUE;
|
|
double pFiboLower = EMPTY_VALUE;
|
|
|
|
//
|
|
// Check Zone Validation ...
|
|
int start = barIndex;
|
|
int end = start + validationLength;
|
|
for (int i = start; i < end; i++)
|
|
{
|
|
//
|
|
// Reading Values ...
|
|
|
|
//
|
|
iFiboUpper = GetFiboUpper(i);
|
|
pFiboUpper = GetFiboUpper(i + 1);
|
|
|
|
//
|
|
iFiboMiddle = GetFiboMiddle(i);
|
|
pFiboMiddle = GetFiboMiddle(i + 1);
|
|
|
|
//
|
|
iFiboLower = GetFiboLower(i);
|
|
pFiboLower = GetFiboLower(i + 1);
|
|
|
|
//
|
|
result = iFiboUpper == pFiboUpper;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
result = iBar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
iFiboUpper = GetFiboUpper(barIndex);
|
|
iFiboMiddle = GetFiboMiddle(barIndex);
|
|
iFiboLower = GetFiboLower(barIndex);
|
|
|
|
//
|
|
isBullish = iBar.IsBullish() &&
|
|
iBar.close > iFiboLower &&
|
|
iBar.low < iFiboLower;
|
|
isBearish = iBar.IsBearish() &&
|
|
iBar.close < iFiboUpper &&
|
|
iBar.high > iFiboUpper;
|
|
result = (isBullish && !isBearish) ||
|
|
(isBearish && !isBullish);
|
|
if (result)
|
|
{
|
|
//
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
iBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Has Higher Low Based On ZigZag ...
|
|
*
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param forceBarValidation: bool, Force Bar Price based on Pivot ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasZigZagHigherLow(
|
|
int barIndex = 0,
|
|
bool forceBarValidation = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
XOHCL bar;
|
|
result = IsValid() &&
|
|
bar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract Pivots ...
|
|
XPivot pivots[];
|
|
int count = ExtractZigZagPivots(
|
|
pivots,
|
|
barIndex,
|
|
10,
|
|
200 //
|
|
);
|
|
|
|
//
|
|
// Validate Pivots and Nearest Pivot is Low ...
|
|
result = IsValidSize(count) &&
|
|
pivots[0].IsVale();
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
XClean(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract Directional Pivots ...
|
|
XPivot vales[];
|
|
count = ExtractPivots(
|
|
vales,
|
|
pivots,
|
|
X_PIVOT_TYPE_VALE //
|
|
);
|
|
result = IsValidSize(count) &&
|
|
count >= 2;
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
XClean(vales);
|
|
XClean(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Result ...
|
|
result =
|
|
vales[0].value > vales[1].value;
|
|
if (forceBarValidation)
|
|
{
|
|
//
|
|
result =
|
|
result &&
|
|
bar.open > vales[0].value &&
|
|
bar.close > vales[0].value;
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
bar.Clean();
|
|
XClean(vales);
|
|
XClean(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Has Lower Low Based On ZigZag ...
|
|
*
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param forceBarValidation: bool, Force Bar Price based on Pivot ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasZigZagLowerLow(
|
|
int barIndex = 0,
|
|
bool forceBarValidation = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
XOHCL bar;
|
|
result = IsValid() &&
|
|
bar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract Pivots ...
|
|
XPivot pivots[];
|
|
int count = ExtractZigZagPivots(
|
|
pivots,
|
|
barIndex,
|
|
10,
|
|
200 //
|
|
);
|
|
|
|
//
|
|
// Validate Pivots and Nearest Pivot is Low ...
|
|
result = IsValidSize(count) &&
|
|
pivots[0].IsVale();
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
XClean(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract Directional Pivots ...
|
|
XPivot vales[];
|
|
count = ExtractPivots(
|
|
vales,
|
|
pivots,
|
|
X_PIVOT_TYPE_VALE //
|
|
);
|
|
result = IsValidSize(count) &&
|
|
count >= 2;
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
XClean(vales);
|
|
XClean(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Result ...
|
|
result =
|
|
vales[0].value < vales[1].value;
|
|
if (forceBarValidation)
|
|
{
|
|
//
|
|
result =
|
|
result &&
|
|
bar.open < vales[0].value &&
|
|
bar.close < vales[0].value;
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
bar.Clean();
|
|
XClean(vales);
|
|
XClean(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Has Higher High Based On ZigZag ...
|
|
*
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param forceBarValidation: bool, Force Bar Price based on Pivot ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasZigZagHigherHigh(
|
|
int barIndex = 0,
|
|
bool forceBarValidation = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
XOHCL bar;
|
|
result = IsValid() &&
|
|
bar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract Pivots ...
|
|
XPivot pivots[];
|
|
int count = ExtractZigZagPivots(
|
|
pivots,
|
|
barIndex,
|
|
10,
|
|
200 //
|
|
);
|
|
|
|
//
|
|
// Validate Pivots and Nearest Pivot is Low ...
|
|
result = IsValidSize(count) &&
|
|
pivots[0].IsPeak();
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
XClean(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract Directional Pivots ...
|
|
XPivot peaks[];
|
|
count = ExtractPivots(
|
|
peaks,
|
|
pivots,
|
|
X_PIVOT_TYPE_PEAK //
|
|
);
|
|
result = IsValidSize(count) &&
|
|
count >= 2;
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
XClean(peaks);
|
|
XClean(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Result ...
|
|
result =
|
|
peaks[0].value > peaks[1].value;
|
|
if (forceBarValidation)
|
|
{
|
|
//
|
|
result =
|
|
result &&
|
|
bar.open > peaks[0].value &&
|
|
bar.close > peaks[0].value;
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
bar.Clean();
|
|
XClean(peaks);
|
|
XClean(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Has Lower High Based On ZigZag ...
|
|
*
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param forceBarValidation: bool, Force Bar Price based on Pivot ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasZigZagLowerHigh(
|
|
int barIndex = 0,
|
|
bool forceBarValidation = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
XOHCL bar;
|
|
result = IsValid() &&
|
|
bar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract Pivots ...
|
|
XPivot pivots[];
|
|
int count = ExtractZigZagPivots(
|
|
pivots,
|
|
barIndex,
|
|
10,
|
|
200 //
|
|
);
|
|
|
|
//
|
|
// Validate Pivots and Nearest Pivot is Low ...
|
|
result = IsValidSize(count) &&
|
|
pivots[0].IsPeak();
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
XClean(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract Directional Pivots ...
|
|
XPivot peaks[];
|
|
count = ExtractPivots(
|
|
peaks,
|
|
pivots,
|
|
X_PIVOT_TYPE_PEAK //
|
|
);
|
|
result = IsValidSize(count) &&
|
|
count >= 2;
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
XClean(peaks);
|
|
XClean(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Result ...
|
|
result =
|
|
peaks[0].value < peaks[1].value;
|
|
if (forceBarValidation)
|
|
{
|
|
//
|
|
result =
|
|
result &&
|
|
bar.open < peaks[0].value &&
|
|
bar.close < peaks[0].value;
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
bar.Clean();
|
|
XClean(peaks);
|
|
XClean(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// SAR ...
|
|
|
|
/**
|
|
* Check Specified Bar has SAR Switch or not ...
|
|
*
|
|
* @param dir: reference for holds cross Direction ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasSARSwitch(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double sars[];
|
|
int count = CopySarState(barIndex, 2, sars);
|
|
|
|
//
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
// Validate Readed Values ...
|
|
result = IsValidSize(count) && count >= 2;
|
|
if (result)
|
|
{
|
|
//
|
|
// Detect Direction Change ...
|
|
|
|
//
|
|
isBullish =
|
|
sars[0] >= 1 &&
|
|
sars[1] <= -1;
|
|
|
|
//
|
|
isBearish =
|
|
sars[0] <= -1 &&
|
|
sars[1] >= 1;
|
|
|
|
//
|
|
result =
|
|
isBullish ||
|
|
isBearish;
|
|
}
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
// Setting Direction ...
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
XClean(sars);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// PV ...
|
|
|
|
//
|
|
// HK ...
|
|
|
|
/**
|
|
* Check Specified Bar has HK Switch or not ...
|
|
*
|
|
* @param dir: reference for holds cross Direction ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasHKSwitch(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
|
|
//
|
|
double open[];
|
|
int openCount = CopyHKOpen(barIndex, 2, open);
|
|
|
|
//
|
|
double close[];
|
|
int closeCount = CopyHKClose(barIndex, 2, close);
|
|
|
|
//
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
// Validate Readed Values ...
|
|
int count = MathMin(openCount, closeCount);
|
|
result = IsValidSize(count) && count >= 2;
|
|
if (result)
|
|
{
|
|
//
|
|
// Detect Direction Change ...
|
|
|
|
//
|
|
bool notEmpty =
|
|
NotEmptyZero(open[0]) &&
|
|
NotEmptyZero(open[1]) &&
|
|
NotEmptyZero(close[0]) &&
|
|
NotEmptyZero(close[1]);
|
|
|
|
//
|
|
isBullish =
|
|
notEmpty &&
|
|
open[0] < close[0] &&
|
|
open[1] > close[1];
|
|
|
|
//
|
|
isBearish =
|
|
notEmpty &&
|
|
open[0] > close[0] &&
|
|
open[1] < close[1];
|
|
|
|
//
|
|
result =
|
|
isBullish ||
|
|
isBearish;
|
|
}
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
// Setting Direction ...
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
XClean(open);
|
|
XClean(close);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar has HK Band Based Trend or not ...
|
|
*
|
|
* @param dir: ENUM_X_DIRECTION, reference to holds trend direction, if exists ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param validationLength: int, validation of trend ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasHKBasedTrend(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0,
|
|
int validationLength = 5 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
validationLength = NormalizeInt(validationLength, 1);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
// Define Requirements ...
|
|
XOHCL iBar;
|
|
double hkUpper;
|
|
double hkLower;
|
|
bool has = false;
|
|
int bullishCount = 0;
|
|
int bearishCount = 0;
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
// Count Bullish/Bearish Directions ...
|
|
int start = barIndex + 1;
|
|
int end = start + validationLength;
|
|
for (int i = start; i < end; i++)
|
|
{
|
|
//
|
|
// Reading Requirements ...
|
|
|
|
//
|
|
// Read Indexed Bar ...
|
|
iBar.Clean();
|
|
result = iBar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
i //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Reading Values ...
|
|
hkUpper = GetHKBandUpper(i);
|
|
hkLower = GetHKBandLower(i);
|
|
result = NotEmptyZero(hkUpper) &&
|
|
NotEmptyZero(hkLower);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Trend ...
|
|
|
|
//
|
|
// Bullish ...
|
|
isBullish = iBar.low > hkLower;
|
|
if (isBullish)
|
|
{
|
|
bullishCount++;
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
isBearish = iBar.high < hkUpper;
|
|
if (isBearish)
|
|
{
|
|
bearishCount++;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
|
|
//
|
|
}
|
|
|
|
//
|
|
// Validate Results ...
|
|
isBullish =
|
|
bullishCount >= validationLength;
|
|
isBearish =
|
|
bearishCount >= validationLength;
|
|
|
|
//
|
|
result = (isBullish && !isBearish) ||
|
|
(isBearish && !isBullish);
|
|
|
|
//
|
|
// Setting Direction if Has Trend ...
|
|
if (result)
|
|
{
|
|
//
|
|
dir = isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
iBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Specified Bar has HK Band Based Trend Switch or not ...
|
|
*
|
|
* @param dir: ENUM_X_DIRECTION, reference to holds trend direction, if exists ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param validationLength: int, validation of trend ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsHKBasedTrendSwitch(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0,
|
|
int validationLength = 5 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
validationLength = NormalizeInt(validationLength, 1);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
bool hasTrend = HasHKBasedTrend(
|
|
dir,
|
|
barIndex,
|
|
validationLength //
|
|
);
|
|
bool isBullish = hasTrend &&
|
|
IsXBullish(dir);
|
|
bool isBearish = hasTrend &&
|
|
IsXBearish(dir);
|
|
|
|
//
|
|
bool hasPTrend = HasHKBasedTrend(
|
|
dir,
|
|
barIndex + 1,
|
|
validationLength //
|
|
);
|
|
bool isPBullish = hasPTrend &&
|
|
IsXBullish(dir);
|
|
bool isPBearish = hasPTrend &&
|
|
IsXBearish(dir);
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Checking Result ...
|
|
isBullish = isBullish && !isPBullish;
|
|
isBearish = isBearish && !isPBearish;
|
|
|
|
//
|
|
result =
|
|
(isBullish && !isBearish) ||
|
|
(isBearish && !isBullish);
|
|
if (result)
|
|
{
|
|
//
|
|
dir = isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check if Price Over HK Band Upper or not ...
|
|
*
|
|
* @param priceType: ENUM_X_PRICE, Specified Price type ...
|
|
* @param barIndex: int, Specified Bar index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsOverHKBandUpper(
|
|
ENUM_X_PRICE priceType = X_PRICE_LOW,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid() &&
|
|
IsXValid(priceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
XOHCL bar;
|
|
result = bar.Init(mSymbol, mPeriod, barIndex);
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double price = bar.GetPrice(priceType);
|
|
double value = GetHKBandUpper(barIndex);
|
|
result = NotEmptyZero(price) &&
|
|
NotEmptyZero(value) &&
|
|
price > value;
|
|
|
|
//
|
|
// Cleanup ...
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check if Price Over HK Band Lower or not ...
|
|
*
|
|
* @param priceType: ENUM_X_PRICE, Specified Price type ...
|
|
* @param barIndex: int, Specified Bar index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsOverHKBandLower(
|
|
ENUM_X_PRICE priceType = X_PRICE_LOW,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid() &&
|
|
IsXValid(priceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
XOHCL bar;
|
|
result = bar.Init(mSymbol, mPeriod, barIndex);
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double price = bar.GetPrice(priceType);
|
|
double value = GetHKBandLower(barIndex);
|
|
result = NotEmptyZero(price) &&
|
|
NotEmptyZero(value) &&
|
|
price > value;
|
|
|
|
//
|
|
// Cleanup ...
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check if Price Under HK Band Upper or not ...
|
|
*
|
|
* @param priceType: ENUM_X_PRICE, Specified Price type ...
|
|
* @param barIndex: int, Specified Bar index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsUnderHKBandUpper(
|
|
ENUM_X_PRICE priceType = X_PRICE_HIGH,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid() &&
|
|
IsXValid(priceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
XOHCL bar;
|
|
result = bar.Init(mSymbol, mPeriod, barIndex);
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double price = bar.GetPrice(priceType);
|
|
double value = GetHKBandUpper(barIndex);
|
|
result = NotEmptyZero(price) &&
|
|
NotEmptyZero(value) &&
|
|
price < value;
|
|
|
|
//
|
|
// Cleanup ...
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check if Price Under HK Band Lower or not ...
|
|
*
|
|
* @param priceType: ENUM_X_PRICE, Specified Price type ...
|
|
* @param barIndex: int, Specified Bar index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsUnderHKBandLower(
|
|
ENUM_X_PRICE priceType = X_PRICE_HIGH,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid() &&
|
|
IsXValid(priceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
XOHCL bar;
|
|
result = bar.Init(mSymbol, mPeriod, barIndex);
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double price = bar.GetPrice(priceType);
|
|
double value = GetHKBandLower(barIndex);
|
|
result = NotEmptyZero(price) &&
|
|
NotEmptyZero(value) &&
|
|
price < value;
|
|
|
|
//
|
|
// Cleanup ...
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Price Switched Over HK Band Upper or not ...
|
|
*
|
|
* @param priceType: ENUM_X_PRICE, Specified Price type ...
|
|
* @param barIndex: int, Specified Bar index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsSwitchedOverHKBandUpper(
|
|
ENUM_X_PRICE priceType = X_PRICE_HIGH,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid() &&
|
|
IsXValid(priceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
int pBarIndex = barIndex + 1;
|
|
bool isBarPassed = IsOverHKBandUpper(priceType, barIndex);
|
|
bool isPBarPassed = !IsOverHKBandUpper(priceType, pBarIndex);
|
|
|
|
//
|
|
result = isBarPassed && isPBarPassed;
|
|
|
|
//
|
|
// Cleanup ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Price Switched Under HK Band Upper or not ...
|
|
*
|
|
* @param priceType: ENUM_X_PRICE, Specified Price type ...
|
|
* @param barIndex: int, Specified Bar index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsSwitchedUnderHKBandUpper(
|
|
ENUM_X_PRICE priceType = X_PRICE_LOW,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid() &&
|
|
IsXValid(priceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
int pBarIndex = barIndex + 1;
|
|
bool isBarPassed = IsUnderHKBandUpper(priceType, barIndex);
|
|
bool isPBarPassed = !IsUnderHKBandUpper(priceType, pBarIndex);
|
|
|
|
//
|
|
result = isBarPassed && isPBarPassed;
|
|
|
|
//
|
|
// Cleanup ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Price Switched Over HK Band Lower or not ...
|
|
*
|
|
* @param priceType: ENUM_X_PRICE, Specified Price type ...
|
|
* @param barIndex: int, Specified Bar index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsSwitchedOverHKBandLower(
|
|
ENUM_X_PRICE priceType = X_PRICE_LOW,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid() &&
|
|
IsXValid(priceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
int pBarIndex = barIndex + 1;
|
|
bool isBarPassed = IsOverHKBandLower(priceType, barIndex);
|
|
bool isPBarPassed = !IsOverHKBandLower(priceType, pBarIndex);
|
|
|
|
//
|
|
result = isBarPassed && isPBarPassed;
|
|
|
|
//
|
|
// Cleanup ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Price Switched Under HK Band Lower or not ...
|
|
*
|
|
* @param priceType: ENUM_X_PRICE, Specified Price type ...
|
|
* @param barIndex: int, Specified Bar index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsSwitchedUnderHKBandLower(
|
|
ENUM_X_PRICE priceType = X_PRICE_HIGH,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid() &&
|
|
IsXValid(priceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
int pBarIndex = barIndex + 1;
|
|
bool isBarPassed = IsUnderHKBandLower(priceType, barIndex);
|
|
bool isPBarPassed = !IsUnderHKBandLower(priceType, pBarIndex);
|
|
|
|
//
|
|
result = isBarPassed && isPBarPassed;
|
|
|
|
//
|
|
// Cleanup ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Previous HK Band ...
|
|
*
|
|
* @param index: int, reference to holds index ...
|
|
* @param priceType: ENUM_X_PRICE, Specified Price Type ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param loopback: int, Max Allowed Loopback Length ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool FindLastOverHKBandUpper(
|
|
int &index,
|
|
ENUM_X_PRICE priceType = X_PRICE_HIGH,
|
|
int barIndex = 0,
|
|
int loopback = 500 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
index = -1;
|
|
|
|
//
|
|
// Normalize ...
|
|
loopback = NormalizeInt(loopback, 50);
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid() &&
|
|
IsXValid(priceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
int idx = barIndex;
|
|
while (idx < barIndex + loopback)
|
|
{
|
|
//
|
|
idx++;
|
|
result = IsOverHKBandUpper(priceType, idx);
|
|
if (result)
|
|
{
|
|
//
|
|
index = idx - 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
// Cleanup ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Previous HK Band ...
|
|
*
|
|
* @param index: int, reference to holds index ...
|
|
* @param priceType: ENUM_X_PRICE, Specified Price Type ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param loopback: int, Max Allowed Loopback Length ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool FindLastUnderHKBandUpper(
|
|
int &index,
|
|
ENUM_X_PRICE priceType = X_PRICE_HIGH,
|
|
int barIndex = 0,
|
|
int loopback = 500 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
index = -1;
|
|
|
|
//
|
|
// Normalize ...
|
|
loopback = NormalizeInt(loopback, 50);
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid() &&
|
|
IsXValid(priceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
int idx = barIndex;
|
|
while (idx < barIndex + loopback)
|
|
{
|
|
//
|
|
idx++;
|
|
result = IsUnderHKBandUpper(priceType, idx);
|
|
if (result)
|
|
{
|
|
//
|
|
index = idx - 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
// Cleanup ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Previous HK Band ...
|
|
*
|
|
* @param index: int, reference to holds index ...
|
|
* @param priceType: ENUM_X_PRICE, Specified Price Type ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param loopback: int, Max Allowed Loopback Length ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool FindLastOverHKBandLower(
|
|
int &index,
|
|
ENUM_X_PRICE priceType = X_PRICE_HIGH,
|
|
int barIndex = 0,
|
|
int loopback = 500 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
index = -1;
|
|
|
|
//
|
|
// Normalize ...
|
|
loopback = NormalizeInt(loopback, 50);
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid() &&
|
|
IsXValid(priceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
int idx = barIndex;
|
|
while (idx < barIndex + loopback)
|
|
{
|
|
//
|
|
idx++;
|
|
result = IsOverHKBandLower(priceType, idx);
|
|
if (result)
|
|
{
|
|
//
|
|
index = idx - 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
// Cleanup ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Previous HK Band ...
|
|
*
|
|
* @param index: int, reference to holds index ...
|
|
* @param priceType: ENUM_X_PRICE, Specified Price Type ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param loopback: int, Max Allowed Loopback Length ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool FindLastUnderHKBandLower(
|
|
int &index,
|
|
ENUM_X_PRICE priceType = X_PRICE_HIGH,
|
|
int barIndex = 0,
|
|
int loopback = 500 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
index = -1;
|
|
|
|
//
|
|
// Normalize ...
|
|
loopback = NormalizeInt(loopback, 50);
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid() &&
|
|
IsXValid(priceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
int idx = barIndex;
|
|
while (idx < barIndex + loopback)
|
|
{
|
|
//
|
|
idx++;
|
|
result = IsUnderHKBandLower(priceType, idx);
|
|
if (result)
|
|
{
|
|
//
|
|
index = idx - 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
// Cleanup ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Previous HK Band Switch ...
|
|
*
|
|
* @param index: int, reference to holds switched index ...
|
|
* @param priceType: ENUM_X_PRICE, Specified Price Type ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param loopback: int, Max Allowed Loopback Length ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool FindLastSwitchedOverHKBandUpper(
|
|
int &index,
|
|
ENUM_X_PRICE priceType = X_PRICE_HIGH,
|
|
int barIndex = 0,
|
|
int loopback = 500 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
index = -1;
|
|
|
|
//
|
|
// Normalize ...
|
|
loopback = NormalizeInt(loopback, 50);
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid() &&
|
|
IsXValid(priceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
int idx = barIndex;
|
|
while (idx < barIndex + loopback)
|
|
{
|
|
//
|
|
idx++;
|
|
result = IsSwitchedOverHKBandUpper(priceType, idx);
|
|
if (result)
|
|
{
|
|
//
|
|
index = idx - 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
// Cleanup ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Previous HK Band Switch ...
|
|
*
|
|
* @param index: int, reference to holds switched index ...
|
|
* @param priceType: ENUM_X_PRICE, Specified Price Type ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param loopback: int, Max Allowed Loopback Length ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool FindLastSwitchedUnderHKBandUpper(
|
|
int &index,
|
|
ENUM_X_PRICE priceType = X_PRICE_HIGH,
|
|
int barIndex = 0,
|
|
int loopback = 500 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
index = -1;
|
|
|
|
//
|
|
// Normalize ...
|
|
loopback = NormalizeInt(loopback, 50);
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid() &&
|
|
IsXValid(priceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
int idx = barIndex;
|
|
while (idx < barIndex + loopback)
|
|
{
|
|
//
|
|
idx++;
|
|
result = IsSwitchedUnderHKBandUpper(priceType, idx);
|
|
if (result)
|
|
{
|
|
//
|
|
index = idx - 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
// Cleanup ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Previous HK Band Switch ...
|
|
*
|
|
* @param index: int, reference to holds switched index ...
|
|
* @param priceType: ENUM_X_PRICE, Specified Price Type ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param loopback: int, Max Allowed Loopback Length ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool FindLastSwitchedOverHKBandLower(
|
|
int &index,
|
|
ENUM_X_PRICE priceType = X_PRICE_HIGH,
|
|
int barIndex = 0,
|
|
int loopback = 500 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
index = -1;
|
|
|
|
//
|
|
// Normalize ...
|
|
loopback = NormalizeInt(loopback, 50);
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid() &&
|
|
IsXValid(priceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
int idx = barIndex;
|
|
while (idx < barIndex + loopback)
|
|
{
|
|
//
|
|
idx++;
|
|
result = IsSwitchedOverHKBandLower(priceType, idx);
|
|
if (result)
|
|
{
|
|
//
|
|
index = idx - 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
// Cleanup ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Previous HK Band Switch ...
|
|
*
|
|
* @param index: int, reference to holds switched index ...
|
|
* @param priceType: ENUM_X_PRICE, Specified Price Type ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param loopback: int, Max Allowed Loopback Length ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool FindLastSwitchedUnderHKBandLower(
|
|
int &index,
|
|
ENUM_X_PRICE priceType = X_PRICE_HIGH,
|
|
int barIndex = 0,
|
|
int loopback = 500 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
index = -1;
|
|
|
|
//
|
|
// Normalize ...
|
|
loopback = NormalizeInt(loopback, 50);
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid() &&
|
|
IsXValid(priceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
int idx = barIndex;
|
|
while (idx < barIndex + loopback)
|
|
{
|
|
//
|
|
idx++;
|
|
result = IsSwitchedUnderHKBandLower(priceType, idx);
|
|
if (result)
|
|
{
|
|
//
|
|
index = idx - 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
// Cleanup ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// ZigZag Pivots With Liquidity ...
|
|
|
|
/**
|
|
* Check ZigZag has Lower Low by Liquidity or Not ...
|
|
*
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param forceBarValidation: bool, Force Bar Price based on Pivot ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasZigZagLowerLowByLiquidity(
|
|
int barIndex = 0,
|
|
bool forceBarValidation = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
XOHCL bar;
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid() &&
|
|
bar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract Pivots ...
|
|
XPivot pivots[];
|
|
int count = ExtractZigZagPivots(
|
|
pivots,
|
|
barIndex,
|
|
10,
|
|
200 //
|
|
);
|
|
|
|
//
|
|
// Validate Pivots and Nearest Pivot is Low ...
|
|
result = IsValidSize(count) &&
|
|
pivots[0].IsVale();
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
XClean(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract Directional Pivots ...
|
|
XPivot selected[];
|
|
count = ExtractPivots(
|
|
selected,
|
|
pivots,
|
|
X_PIVOT_TYPE_VALE //
|
|
);
|
|
result = IsValidSize(count) &&
|
|
count >= 3;
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
XClean(pivots);
|
|
XClean(selected);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do Calculations ...
|
|
result =
|
|
//
|
|
// Check Pivot ...
|
|
selected[0].value < selected[1].value &&
|
|
//
|
|
// Check Liquidity ...
|
|
selected[1].value > selected[2].value &&
|
|
//
|
|
// Check Bar Place ...
|
|
(!forceBarValidation
|
|
? true
|
|
: bar.open > selected[0].value &&
|
|
bar.close > selected[0].value);
|
|
|
|
//
|
|
// Cleanup ...
|
|
bar.Clean();
|
|
XClean(pivots);
|
|
XClean(selected);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check ZigZag has Higher High by Liquidity or Not ...
|
|
*
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param forceBarValidation: bool, Force Bar Price based on Pivot ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasZigZagHigherHighByLiquidity(
|
|
int barIndex = 0,
|
|
bool forceBarValidation = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
XOHCL bar;
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid() &&
|
|
bar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract Pivots ...
|
|
XPivot pivots[];
|
|
int count = ExtractZigZagPivots(
|
|
pivots,
|
|
barIndex,
|
|
10,
|
|
200 //
|
|
);
|
|
|
|
//
|
|
// Validate Pivots and Nearest Pivot is Low ...
|
|
result = IsValidSize(count) &&
|
|
pivots[0].IsPeak();
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
XClean(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract Directional Pivots ...
|
|
XPivot selected[];
|
|
count = ExtractPivots(
|
|
selected,
|
|
pivots,
|
|
X_PIVOT_TYPE_PEAK //
|
|
);
|
|
result = IsValidSize(count) &&
|
|
count >= 3;
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
XClean(pivots);
|
|
XClean(selected);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do Calculations ...
|
|
result =
|
|
//
|
|
// Check Pivot ...
|
|
selected[0].value > selected[1].value &&
|
|
//
|
|
// Check Liquidity ...
|
|
selected[1].value < selected[2].value &&
|
|
//
|
|
// Check Bar Place ...
|
|
(!forceBarValidation
|
|
? true
|
|
: bar.open < selected[0].value &&
|
|
bar.close < selected[0].value);
|
|
|
|
//
|
|
// Cleanup ...
|
|
bar.Clean();
|
|
XClean(pivots);
|
|
XClean(selected);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extractions ...
|
|
|
|
/**
|
|
* Extract Specified Kind of Pivots ...
|
|
*
|
|
* @param pivots: XPivot, refrence Collection to hold Extracted pivots ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ...
|
|
* @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ...
|
|
* @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractPVPivots(
|
|
XPivot &pivots[],
|
|
int barIndex = 0,
|
|
int requiredNumberOFPivots = 50,
|
|
int maxAllowedLoopbackLength = 1500,
|
|
int validationLength = 0 //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
SpecifiedClean(pivots);
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
validationLength = NormalizeInt(validationLength, 0);
|
|
requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2);
|
|
maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50);
|
|
|
|
//
|
|
// Validate ...
|
|
if (mHandler == INVALID_HANDLE)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool lookupPeaks = true;
|
|
bool lookupVales = true;
|
|
|
|
//
|
|
XOHCL iBar;
|
|
XPivot iPivot;
|
|
bool has = false;
|
|
int idx = barIndex - 1;
|
|
int samePeaksCount = 0;
|
|
int sameValesCount = 0;
|
|
double tmpPeaksBuffer[];
|
|
double tmpValesBuffer[];
|
|
string symbol = GetSymbol();
|
|
double iPValue = EMPTY_VALUE;
|
|
double iVValue = EMPTY_VALUE;
|
|
double pPValue = EMPTY_VALUE;
|
|
double pVValue = EMPTY_VALUE;
|
|
ENUM_TIMEFRAMES period = GetPeriod();
|
|
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
|
|
ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE;
|
|
int maxAllowed = barIndex + maxAllowedLoopbackLength - 1;
|
|
while (idx < maxAllowed &&
|
|
ArraySize(pivots) < requiredNumberOFPivots)
|
|
{
|
|
//
|
|
idx++;
|
|
|
|
//
|
|
// Prepare ...
|
|
iBar.Clean();
|
|
iPivot.Clean();
|
|
SpecifiedClean(tmpPeaksBuffer);
|
|
SpecifiedClean(tmpValesBuffer);
|
|
|
|
//
|
|
// Ignore First Item ...
|
|
if (idx == barIndex)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Initialize Bar ...
|
|
has = iBar.Init(
|
|
symbol,
|
|
period,
|
|
idx //
|
|
);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Detecting ...
|
|
|
|
//
|
|
// Peak ...
|
|
if (lookupPeaks)
|
|
{
|
|
//
|
|
// Reading Buffer ...
|
|
CopyBuffer(
|
|
mHandler, // Handler ...
|
|
XFIMA_PEAK_LINE, // Handler Buffer Number ...
|
|
idx, // Bar Index ...
|
|
2, // Number of Requirements ...
|
|
tmpPeaksBuffer // Buffer ...
|
|
);
|
|
ArraySetAsSeries(tmpPeaksBuffer, true);
|
|
|
|
//
|
|
// Reading Values ...
|
|
iPValue = tmpPeaksBuffer[0];
|
|
pPValue = tmpPeaksBuffer[1];
|
|
|
|
//
|
|
// Validate Value ...
|
|
if (NotEmptyZero(iPValue))
|
|
{
|
|
//
|
|
// Check New Peak ...
|
|
has =
|
|
!NotEmptyZero(pPValue)
|
|
? true
|
|
: iPValue != pPValue;
|
|
if (has)
|
|
{
|
|
//
|
|
// Calculate and Validate Type ...
|
|
// Peaks Only Valid when Confirmed by Bar High ...
|
|
iType =
|
|
iPValue == iBar.high
|
|
? X_PIVOT_TYPE_PEAK
|
|
: X_PIVOT_TYPE_NONE;
|
|
has = IsXValid(iType);
|
|
|
|
//
|
|
// Calculate and Validate Dir ...
|
|
iDir = IsXPeak(iType)
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
has = has &&
|
|
HasDirection(iDir);
|
|
|
|
//
|
|
// Check Validation Length ...
|
|
has =
|
|
has &&
|
|
(validationLength <= 0
|
|
? true
|
|
: samePeaksCount >= validationLength);
|
|
if (has)
|
|
{
|
|
//
|
|
// Initialize and Validate Pivot ...
|
|
has = iPivot.Init(
|
|
iPValue,
|
|
iBar.time,
|
|
symbol,
|
|
iDir,
|
|
period,
|
|
iType //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
iPivot.prefix = ToXString(XFIMA_PIVOT_PV);
|
|
|
|
//
|
|
// Add Pivot to Collection only if not Exists ...
|
|
AddIfNotExists(
|
|
iPivot,
|
|
pivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
iPivot.Clean();
|
|
samePeaksCount = 0;
|
|
}
|
|
else if (iPValue == pPValue)
|
|
{
|
|
samePeaksCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Vale ...
|
|
if (lookupVales)
|
|
{
|
|
//
|
|
// Reading Buffer ...
|
|
CopyBuffer(
|
|
mHandler, // Handler ...
|
|
XFIMA_VALE_LINE, // Handler Buffer Number ...
|
|
idx, // Bar Index ...
|
|
2, // Number of Requirements ...
|
|
tmpValesBuffer // Buffer ...
|
|
);
|
|
ArraySetAsSeries(tmpValesBuffer, true);
|
|
|
|
//
|
|
// Reading Values ...
|
|
iVValue = tmpValesBuffer[0];
|
|
pVValue = tmpValesBuffer[1];
|
|
|
|
//
|
|
// Validate Value ...
|
|
if (NotEmptyZero(iVValue))
|
|
{
|
|
//
|
|
// Check New Vale ...
|
|
has =
|
|
!NotEmptyZero(pVValue)
|
|
? true
|
|
: iVValue != pVValue;
|
|
if (has)
|
|
{
|
|
//
|
|
// Calculate and Validate Type ...
|
|
// Vales Only Valid when Confirmed by Bar Low ...
|
|
iType =
|
|
iVValue == iBar.low
|
|
? X_PIVOT_TYPE_VALE
|
|
: X_PIVOT_TYPE_NONE;
|
|
has = IsXValid(iType);
|
|
|
|
//
|
|
// Calculate and Validate Dir ...
|
|
iDir = IsXVale(iType)
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_NONE;
|
|
has = has &&
|
|
HasDirection(iDir);
|
|
|
|
//
|
|
// Check Validation Length ...
|
|
has =
|
|
has &&
|
|
(validationLength <= 0
|
|
? true
|
|
: sameValesCount >= validationLength);
|
|
if (has)
|
|
{
|
|
//
|
|
// Initialize and Validate Pivot ...
|
|
has = iPivot.Init(
|
|
iVValue,
|
|
iBar.time,
|
|
symbol,
|
|
iDir,
|
|
period,
|
|
iType //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
iPivot.prefix = ToXString(XFIMA_PIVOT_PV);
|
|
|
|
//
|
|
// Add Pivot to Collection only if not Exists ...
|
|
AddIfNotExists(
|
|
iPivot,
|
|
pivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
iPivot.Clean();
|
|
sameValesCount = 0;
|
|
}
|
|
else if (iVValue == pVValue)
|
|
{
|
|
sameValesCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
iBar.Clean();
|
|
iPivot.Clean();
|
|
SpecifiedClean(tmpPeaksBuffer);
|
|
SpecifiedClean(tmpValesBuffer);
|
|
|
|
//
|
|
// Check Moving Forward Condition ...
|
|
has =
|
|
idx < maxAllowed &&
|
|
ArraySize(pivots) < requiredNumberOFPivots;
|
|
if (!has)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(pivots);
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
iBar.Clean();
|
|
iPivot.Clean();
|
|
SpecifiedClean(tmpPeaksBuffer);
|
|
SpecifiedClean(tmpValesBuffer);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extract Specified Kind of Pivots ...
|
|
*
|
|
* @param pivots: XPivot, refrence Collection to hold Extracted pivots ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ...
|
|
* @param validCrossDiffMultiplier: double, validate diff between MAs on Cross happens ...
|
|
* @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractMAPivots(
|
|
XPivot &pivots[],
|
|
int barIndex = 0,
|
|
int requiredNumberOFPivots = 50,
|
|
double validCrossDiffMultiplier = 1,
|
|
int maxAllowedLoopbackLength = 1500 //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
SpecifiedClean(pivots);
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2);
|
|
maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50);
|
|
validCrossDiffMultiplier = NormalizeDouble(validCrossDiffMultiplier, 0);
|
|
|
|
//
|
|
// Validate ...
|
|
if (mHandler == INVALID_HANDLE)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double fast[];
|
|
double slow[];
|
|
XPivot iPivot;
|
|
int count = 0;
|
|
bool has = false;
|
|
int idx = barIndex - 1;
|
|
datetime iPivotTime = NULL;
|
|
string symbol = GetSymbol();
|
|
double iFValue = EMPTY_VALUE;
|
|
double pFValue = EMPTY_VALUE;
|
|
double iSValue = EMPTY_VALUE;
|
|
double pSValue = EMPTY_VALUE;
|
|
bool isSwitchedToBullish = false;
|
|
bool isSwitchedToBearish = false;
|
|
double iSelectedValue = EMPTY_VALUE;
|
|
ENUM_TIMEFRAMES period = GetPeriod();
|
|
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
|
|
ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE;
|
|
int maxAllowed = barIndex + maxAllowedLoopbackLength - 1;
|
|
while (idx < maxAllowed &&
|
|
ArraySize(pivots) < requiredNumberOFPivots)
|
|
{
|
|
//
|
|
idx++;
|
|
|
|
//
|
|
// Prepare ...
|
|
XClean(fast);
|
|
XClean(slow);
|
|
iPivot.Clean();
|
|
|
|
//
|
|
// Ignore First Item ...
|
|
if (idx == barIndex)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Reading Buffer ...
|
|
int fastCount = CopyMAFast(idx, 2, fast);
|
|
int slowCount = CopyMASlow(idx, 2, slow);
|
|
count = MathMin(fastCount, slowCount);
|
|
has = IsValidSize(count);
|
|
|
|
//
|
|
// Reading Values ...
|
|
|
|
//
|
|
iFValue = fast[0];
|
|
pFValue = fast[1];
|
|
|
|
//
|
|
iSValue = slow[0];
|
|
pSValue = slow[1];
|
|
|
|
//
|
|
// Validate Value ...
|
|
has =
|
|
HasMACross(
|
|
iDir,
|
|
idx,
|
|
validCrossDiffMultiplier //
|
|
) &&
|
|
NotEmptyZero(iFValue) &&
|
|
NotEmptyZero(iSValue) &&
|
|
NotEmptyZero(pFValue) &&
|
|
NotEmptyZero(pSValue);
|
|
if (has)
|
|
{
|
|
//
|
|
// Check Direction Changed ...
|
|
isSwitchedToBullish = IsXBullish(iDir);
|
|
isSwitchedToBearish = IsXBearish(iDir);
|
|
has =
|
|
isSwitchedToBullish ||
|
|
isSwitchedToBearish;
|
|
if (has)
|
|
{
|
|
//
|
|
// Calculate and Validate Type ...
|
|
// Peaks Only Valid when Confirmed by Bar High ...
|
|
iType =
|
|
isSwitchedToBearish
|
|
? X_PIVOT_TYPE_PEAK
|
|
: isSwitchedToBullish
|
|
? X_PIVOT_TYPE_VALE
|
|
: X_PIVOT_TYPE_NONE;
|
|
has = IsXValid(iType);
|
|
|
|
//
|
|
// Calculate and Validate Dir ...
|
|
iDir = IsXPeak(iType)
|
|
? X_DIRECTION_BEARISH
|
|
: IsXVale(iType)
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_NONE;
|
|
has = has &&
|
|
HasDirection(iDir);
|
|
|
|
//
|
|
if (has)
|
|
{
|
|
//
|
|
iPivotTime = GetBarTime(
|
|
symbol,
|
|
period,
|
|
idx //
|
|
);
|
|
|
|
//
|
|
// Select Value based on Pivot Type ...
|
|
iSelectedValue = IsXPeak(iType)
|
|
? MathMax(iFValue, iSValue)
|
|
: MathMin(iFValue, iSValue);
|
|
|
|
//
|
|
// Initialize and Validate Pivot ...
|
|
has = iPivot.Init(
|
|
iSelectedValue,
|
|
iPivotTime,
|
|
symbol,
|
|
iDir,
|
|
period,
|
|
iType //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
iPivot.prefix = ToXString(XFIMA_PIVOT_MA_CROSS);
|
|
|
|
//
|
|
// Add Pivot to Collection only if not Exists ...
|
|
AddIfNotExists(
|
|
iPivot,
|
|
pivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
iPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
XClean(fast);
|
|
XClean(slow);
|
|
iPivot.Clean();
|
|
|
|
//
|
|
// Check Moving Forward Condition ...
|
|
has =
|
|
idx < maxAllowed &&
|
|
ArraySize(pivots) < requiredNumberOFPivots;
|
|
if (!has)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(pivots);
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
XClean(fast);
|
|
XClean(slow);
|
|
iPivot.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extract Specified Kind of Pivots ...
|
|
*
|
|
* @param pivots: XPivot, refrence Collection to hold Extracted pivots ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ...
|
|
* @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractHKPivots(
|
|
XPivot &pivots[],
|
|
int barIndex = 0,
|
|
int requiredNumberOFPivots = 50,
|
|
int maxAllowedLoopbackLength = 1500 //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
SpecifiedClean(pivots);
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2);
|
|
maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50);
|
|
|
|
//
|
|
// Validate ...
|
|
if (mHandler == INVALID_HANDLE)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double open[];
|
|
XPivot iPivot;
|
|
int count = 0;
|
|
double close[];
|
|
bool has = false;
|
|
int idx = barIndex - 1;
|
|
datetime iPivotTime = NULL;
|
|
string symbol = GetSymbol();
|
|
bool isSwitchedToBullish = false;
|
|
bool isSwitchedToBearish = false;
|
|
double iSelectedValue = EMPTY_VALUE;
|
|
ENUM_TIMEFRAMES period = GetPeriod();
|
|
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
|
|
ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE;
|
|
int maxAllowed = barIndex + maxAllowedLoopbackLength - 1;
|
|
while (idx < maxAllowed &&
|
|
ArraySize(pivots) < requiredNumberOFPivots)
|
|
{
|
|
//
|
|
idx++;
|
|
|
|
//
|
|
// Prepare ...
|
|
XClean(open);
|
|
XClean(close);
|
|
iPivot.Clean();
|
|
|
|
//
|
|
// Ignore First Item ...
|
|
if (idx == barIndex)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Reading Buffer ...
|
|
int openCount = CopyHKOpen(idx, 2, open);
|
|
int closeCount = CopyHKClose(idx, 2, close);
|
|
count = MathMin(openCount, closeCount);
|
|
has = IsValidSize(count);
|
|
|
|
//
|
|
// Validate Value ...
|
|
has =
|
|
HasHKSwitch(
|
|
iDir,
|
|
idx //
|
|
) &&
|
|
NotEmptyZero(open[0]) &&
|
|
NotEmptyZero(open[1]) &&
|
|
NotEmptyZero(close[0]) &&
|
|
NotEmptyZero(close[1]);
|
|
if (has)
|
|
{
|
|
//
|
|
// Check Direction Changed ...
|
|
isSwitchedToBullish = IsXBullish(iDir);
|
|
isSwitchedToBearish = IsXBearish(iDir);
|
|
has =
|
|
isSwitchedToBullish ||
|
|
isSwitchedToBearish;
|
|
if (has)
|
|
{
|
|
//
|
|
// Calculate and Validate Type ...
|
|
// Peaks Only Valid when Confirmed by Bar High ...
|
|
iType =
|
|
isSwitchedToBearish
|
|
? X_PIVOT_TYPE_PEAK
|
|
: isSwitchedToBullish
|
|
? X_PIVOT_TYPE_VALE
|
|
: X_PIVOT_TYPE_NONE;
|
|
has = IsXValid(iType);
|
|
|
|
//
|
|
// Calculate and Validate Dir ...
|
|
iDir = IsXPeak(iType)
|
|
? X_DIRECTION_BEARISH
|
|
: IsXVale(iType)
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_NONE;
|
|
has = has &&
|
|
HasDirection(iDir);
|
|
|
|
//
|
|
if (has)
|
|
{
|
|
//
|
|
iPivot.prefix = ToXString(XFIMA_PIVOT_HK);
|
|
|
|
//
|
|
iPivotTime = GetBarTime(
|
|
symbol,
|
|
period,
|
|
idx //
|
|
);
|
|
|
|
//
|
|
// Select Value based on Pivot Type ...
|
|
iSelectedValue = IsXPeak(iType)
|
|
? MathMax(open[0], close[0])
|
|
: MathMin(open[0], close[0]);
|
|
|
|
//
|
|
// Initialize and Validate Pivot ...
|
|
has = iPivot.Init(
|
|
iSelectedValue,
|
|
iPivotTime,
|
|
symbol,
|
|
iDir,
|
|
period,
|
|
iType //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
// Add Pivot to Collection only if not Exists ...
|
|
AddIfNotExists(
|
|
iPivot,
|
|
pivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
iPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
XClean(open);
|
|
XClean(close);
|
|
iPivot.Clean();
|
|
|
|
//
|
|
// Check Moving Forward Condition ...
|
|
has =
|
|
idx < maxAllowed &&
|
|
ArraySize(pivots) < requiredNumberOFPivots;
|
|
if (!has)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(pivots);
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
XClean(open);
|
|
XClean(close);
|
|
iPivot.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extract Specified Kind of Pivots ...
|
|
*
|
|
* @param pivots: XPivot, refrence Collection to hold Extracted pivots ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ...
|
|
* @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractSARPivots(
|
|
XPivot &pivots[],
|
|
int barIndex = 0,
|
|
int requiredNumberOFPivots = 50,
|
|
int maxAllowedLoopbackLength = 1500 //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
SpecifiedClean(pivots);
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2);
|
|
maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50);
|
|
|
|
//
|
|
// Validate ...
|
|
if (mHandler == INVALID_HANDLE)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL iBar;
|
|
XOHCL pBar;
|
|
XPivot iPivot;
|
|
bool has = false;
|
|
double tmpSarBuffer[];
|
|
int idx = barIndex - 1;
|
|
string symbol = GetSymbol();
|
|
double iValue = EMPTY_VALUE;
|
|
double pValue = EMPTY_VALUE;
|
|
bool isSwitchedToBullish = false;
|
|
bool isSwitchedToBearish = false;
|
|
ENUM_TIMEFRAMES period = GetPeriod();
|
|
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
|
|
ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE;
|
|
int maxAllowed = barIndex + maxAllowedLoopbackLength - 1;
|
|
while (idx < maxAllowed &&
|
|
ArraySize(pivots) < requiredNumberOFPivots)
|
|
{
|
|
//
|
|
idx++;
|
|
|
|
//
|
|
// Prepare ...
|
|
iBar.Clean();
|
|
pBar.Clean();
|
|
iPivot.Clean();
|
|
SpecifiedClean(tmpSarBuffer);
|
|
|
|
//
|
|
// Ignore First Item ...
|
|
if (idx == barIndex)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Initialize Bar ...
|
|
has = iBar.Init(
|
|
symbol,
|
|
period,
|
|
idx //
|
|
);
|
|
has =
|
|
has &&
|
|
iBar.GetPreviousBar(pBar);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Reading Buffer ...
|
|
CopyBuffer(
|
|
mHandler, // Handler ...
|
|
XFIMA_SAR_LINE, // Handler Buffer Number ...
|
|
idx, // Bar Index ...
|
|
2, // Number of Requirements ...
|
|
tmpSarBuffer // Buffer ...
|
|
);
|
|
ArraySetAsSeries(tmpSarBuffer, true);
|
|
|
|
//
|
|
// Reading Values ...
|
|
iValue = tmpSarBuffer[0];
|
|
pValue = tmpSarBuffer[1];
|
|
|
|
//
|
|
// Validate Value ...
|
|
if (NotEmptyZero(iValue))
|
|
{
|
|
//
|
|
// Check Sar Direction Changed ...
|
|
isSwitchedToBullish = iValue < iBar.low &&
|
|
pValue > pBar.high;
|
|
isSwitchedToBearish = iValue > iBar.high &&
|
|
pValue < pBar.low;
|
|
has =
|
|
isSwitchedToBullish ||
|
|
isSwitchedToBearish;
|
|
if (has)
|
|
{
|
|
//
|
|
// Calculate and Validate Type ...
|
|
// Peaks Only Valid when Confirmed by Bar High ...
|
|
iType =
|
|
isSwitchedToBearish
|
|
? X_PIVOT_TYPE_PEAK
|
|
: isSwitchedToBullish
|
|
? X_PIVOT_TYPE_VALE
|
|
: X_PIVOT_TYPE_NONE;
|
|
has = IsXValid(iType);
|
|
|
|
//
|
|
// Calculate and Validate Dir ...
|
|
iDir = IsXPeak(iType)
|
|
? X_DIRECTION_BEARISH
|
|
: IsXVale(iType)
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_NONE;
|
|
has = has &&
|
|
HasDirection(iDir);
|
|
|
|
//
|
|
if (has)
|
|
{
|
|
//
|
|
// Initialize and Validate Pivot ...
|
|
has = iPivot.Init(
|
|
iValue,
|
|
iBar.time,
|
|
symbol,
|
|
iDir,
|
|
period,
|
|
iType //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
iPivot.prefix = ToXString(XFIMA_PIVOT_SAR_SWITCH);
|
|
|
|
//
|
|
// Add Pivot to Collection only if not Exists ...
|
|
AddIfNotExists(
|
|
iPivot,
|
|
pivots //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
iPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
iBar.Clean();
|
|
pBar.Clean();
|
|
iPivot.Clean();
|
|
SpecifiedClean(tmpSarBuffer);
|
|
|
|
//
|
|
// Check Moving Forward Condition ...
|
|
has =
|
|
idx < maxAllowed &&
|
|
ArraySize(pivots) < requiredNumberOFPivots;
|
|
if (!has)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(pivots);
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
iBar.Clean();
|
|
pBar.Clean();
|
|
iPivot.Clean();
|
|
SpecifiedClean(tmpSarBuffer);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extract Specified Kind of Pivots ...
|
|
*
|
|
* @param pivots: XPivot, refrence Collection to hold Extracted pivots ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ...
|
|
* @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractZigZagPivots(
|
|
XPivot &pivots[],
|
|
int barIndex = 0,
|
|
int requiredNumberOFPivots = 50,
|
|
int maxAllowedLoopbackLength = 1500 //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
SpecifiedClean(pivots);
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2);
|
|
maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50);
|
|
|
|
//
|
|
// Validate ...
|
|
if (mHandler == INVALID_HANDLE)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL iBar;
|
|
XPivot iPivot;
|
|
bool has = false;
|
|
int idx = barIndex - 1;
|
|
double tmpZigZagBuffer[];
|
|
double iValue = EMPTY_VALUE;
|
|
string symbol = GetSymbol();
|
|
ENUM_TIMEFRAMES period = GetPeriod();
|
|
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
|
|
ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE;
|
|
int maxAllowed = barIndex + maxAllowedLoopbackLength - 1;
|
|
while (idx < maxAllowed &&
|
|
ArraySize(pivots) < requiredNumberOFPivots)
|
|
{
|
|
//
|
|
idx++;
|
|
|
|
//
|
|
// Prepare ...
|
|
iBar.Clean();
|
|
iPivot.Clean();
|
|
SpecifiedClean(tmpZigZagBuffer);
|
|
|
|
//
|
|
// Ignore First Item ...
|
|
if (idx == barIndex)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Initialize Bar ...
|
|
has = iBar.Init(
|
|
symbol,
|
|
period,
|
|
idx //
|
|
);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Reading Buffer ...
|
|
CopyBuffer(
|
|
mHandler, // Handler ...
|
|
XFIMA_ZIGZAG_LINE, // Handler Buffer Number ...
|
|
idx, // Bar Index ...
|
|
1, // Number of Requirements ...
|
|
tmpZigZagBuffer // Buffer ...
|
|
);
|
|
ArraySetAsSeries(tmpZigZagBuffer, true);
|
|
|
|
//
|
|
// Read and Validate Value ...
|
|
iValue = tmpZigZagBuffer[0];
|
|
has = NotEmptyZero(iValue);
|
|
if (!has)
|
|
{
|
|
//
|
|
iBar.Clean();
|
|
SpecifiedClean(tmpZigZagBuffer);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Calculate and Validate Type ...
|
|
iType =
|
|
iValue == iBar.high
|
|
? X_PIVOT_TYPE_PEAK
|
|
: iValue == iBar.low
|
|
? X_PIVOT_TYPE_VALE
|
|
: X_PIVOT_TYPE_NONE;
|
|
has = IsXValid(iType);
|
|
if (!has)
|
|
{
|
|
//
|
|
iBar.Clean();
|
|
SpecifiedClean(tmpZigZagBuffer);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Calculate and Validate Dir ...
|
|
iDir =
|
|
IsXVale(iType)
|
|
? X_DIRECTION_BULLISH
|
|
: IsXPeak(iType)
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
has = HasDirection(iDir);
|
|
if (!has)
|
|
{
|
|
//
|
|
iBar.Clean();
|
|
SpecifiedClean(tmpZigZagBuffer);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Initialize and Validate Pivot ...
|
|
has = iPivot.Init(
|
|
iValue,
|
|
iBar.time,
|
|
symbol,
|
|
iDir,
|
|
period,
|
|
iType //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
iPivot.prefix = ToXString(XFIMA_PIVOT_ZIGZAG);
|
|
|
|
//
|
|
// Add Pivot to Collection only if not Exists ...
|
|
AddIfNotExists(
|
|
iPivot,
|
|
pivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
iBar.Clean();
|
|
iPivot.Clean();
|
|
SpecifiedClean(tmpZigZagBuffer);
|
|
|
|
//
|
|
// Check Moving Forward Condition ...
|
|
has =
|
|
idx < maxAllowed &&
|
|
ArraySize(pivots) < requiredNumberOFPivots;
|
|
if (!has)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(pivots);
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
iBar.Clean();
|
|
iPivot.Clean();
|
|
SpecifiedClean(tmpZigZagBuffer);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extract Validated Zones ...
|
|
*
|
|
* @param zones: XBoxZone, collection reference to holds results ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param requiredNumberOFZones: int, required Number of Zones ...
|
|
* @param breakValidLength: int, Breake Validation Length of Zones ...
|
|
* @param validateFakeBreakes: bool, Validation Fake Breaked Zones ...
|
|
* @param shadowMultiplier: double a Shadow Multiplier for Validation ...
|
|
* @param validationStrength: double, Minimum Strngth Multiplier in Point to Validate ...
|
|
* @param validationLength: int, Validation Length of Zones ...
|
|
* @param maxAllowedLoopbackLength: int, max Allowed Loopback Length ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractHKZones(
|
|
XBoxZone &zones[],
|
|
int barIndex = 0,
|
|
int requiredNumberOFZones = 50,
|
|
int breakValidLength = 3,
|
|
bool validateFakeBreakes = true,
|
|
double shadowMultiplier = 3,
|
|
double validationStrength = 1,
|
|
int validationLength = 21,
|
|
int maxAllowedLoopbackLength = 1500 //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
SpecifiedClean(zones);
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
validationLength = NormalizeInt(validationLength, 7);
|
|
shadowMultiplier = NormalizeDouble(shadowMultiplier, 1);
|
|
validationStrength = NormalizeDouble(validationStrength, 1);
|
|
requiredNumberOFZones = NormalizeInt(requiredNumberOFZones, 5);
|
|
maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 100);
|
|
|
|
//
|
|
// Reading Values ...
|
|
|
|
//
|
|
string symbol = GetSymbol();
|
|
ENUM_TIMEFRAMES period = GetPeriod();
|
|
double minAllowedStrength = (validationStrength * GetPoints(symbol));
|
|
|
|
//
|
|
int count = 0;
|
|
XBoxZone zone;
|
|
bool has = false;
|
|
int start = barIndex;
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
double up = EMPTY_VALUE;
|
|
double low = EMPTY_VALUE;
|
|
double open = EMPTY_VALUE;
|
|
double high = EMPTY_VALUE;
|
|
double down = EMPTY_VALUE;
|
|
double body = EMPTY_VALUE;
|
|
double close = EMPTY_VALUE;
|
|
double range = EMPTY_VALUE;
|
|
bool lowShadowPassed = false;
|
|
bool highShadowPassed = false;
|
|
double lowShadow = EMPTY_VALUE;
|
|
double highShadow = EMPTY_VALUE;
|
|
double startHKLow = EMPTY_VALUE;
|
|
double startHKOpen = EMPTY_VALUE;
|
|
double startHKHigh = EMPTY_VALUE;
|
|
double startHKClose = EMPTY_VALUE;
|
|
ENUM_X_DIRECTION dir = X_DIRECTION_NONE;
|
|
int end = start + maxAllowedLoopbackLength;
|
|
for (int i = start; i < end; i++)
|
|
{
|
|
//
|
|
// Cleanup ...
|
|
zone.Clean();
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Reading HK Buffesr ...
|
|
low = GetHKLow(i);
|
|
open = GetHKOpen(i);
|
|
high = GetHKHigh(i);
|
|
close = GetHKClose(i);
|
|
|
|
//
|
|
// Initialized Start Bar ...
|
|
if (i == start)
|
|
{
|
|
//
|
|
startHKLow = low;
|
|
startHKOpen = open;
|
|
startHKHigh = high;
|
|
startHKClose = close;
|
|
}
|
|
|
|
//
|
|
// Check Direction ...
|
|
isBullish = open < close;
|
|
isBearish = open > close;
|
|
dir =
|
|
(isBullish && !isBearish)
|
|
? X_DIRECTION_BULLISH
|
|
: (isBearish && !isBullish)
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
has = HasDirection(dir);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Calculate Requirements for Processing ...
|
|
up = isBullish
|
|
? close
|
|
: open;
|
|
down = isBullish
|
|
? open
|
|
: close;
|
|
body = MathAbs(up - down);
|
|
range = high - low;
|
|
highShadow = high - up;
|
|
lowShadow = down - low;
|
|
|
|
//
|
|
// Detecting Shadows ...
|
|
|
|
//
|
|
// Low Shadow ...
|
|
lowShadowPassed = lowShadow >= (shadowMultiplier * highShadow);
|
|
|
|
//
|
|
// High Shadow ...
|
|
highShadowPassed = highShadow >= (shadowMultiplier * lowShadow);
|
|
|
|
//
|
|
has = (lowShadowPassed && !highShadowPassed) ||
|
|
(highShadowPassed && !lowShadowPassed);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Filling Zone ...
|
|
|
|
//
|
|
zone.symbol = symbol;
|
|
zone.period = period;
|
|
zone.from = GetBarTime(
|
|
zone.symbol,
|
|
zone.period,
|
|
i //
|
|
);
|
|
zone.dir = lowShadowPassed
|
|
? X_DIRECTION_BULLISH
|
|
: highShadowPassed
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
|
|
//
|
|
zone.upper =
|
|
IsXBullish(zone.dir)
|
|
? down
|
|
: IsXBearish(zone.dir)
|
|
? high
|
|
: EMPTY_VALUE;
|
|
|
|
//
|
|
zone.lower =
|
|
IsXBullish(zone.dir)
|
|
? low
|
|
: IsXBearish(zone.dir)
|
|
? up
|
|
: EMPTY_VALUE;
|
|
|
|
//
|
|
zone.to = TimeCurrent();
|
|
zone.type = ToXString(XFIMA_PIVOT_HK) + "_" + (IsXBullish(zone.dir) ? "Support" : IsXBearish(zone.dir) ? "Resistance"
|
|
: "");
|
|
|
|
//
|
|
// Validate ...
|
|
has =
|
|
zone.IsValid() &&
|
|
HasDirection(zone.dir) &&
|
|
NotEmptyZero(zone.upper) &&
|
|
NotEmptyZero(zone.lower) &&
|
|
(zone.IsBullish()
|
|
? startHKLow > zone.upper
|
|
: startHKHigh < zone.lower) &&
|
|
(zone.upper - zone.lower) >= minAllowedStrength &&
|
|
ValidateHKZone(zone, validationLength, breakValidLength, validateFakeBreakes);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
zone,
|
|
zones //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
zone.Clean();
|
|
|
|
//
|
|
// Validating ...
|
|
result = ArraySize(zones);
|
|
has = IsValidSize(result) &&
|
|
result >= requiredNumberOFZones;
|
|
if (has)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
zone.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Values Retrievers ...
|
|
|
|
/**
|
|
* Filling Specified Bar index Boundary Values ...
|
|
*
|
|
* @param dest: double, reference collection to hold boundary Values ...
|
|
* @param barIndex: int, Specified Bar's Index ...
|
|
* @param containsFastSlow: bool, Contains XMA Fast / Slow ...
|
|
* @param containsMABand: bool, Contains XMA Boundary Upper / Lower ...
|
|
* @param containsHKBound: bool, Contains XHK Boundary Upper / Lower ...
|
|
* @param containsPBBand: bool, Contains XPB Boundary Upper / Lower ...
|
|
* @param containsFiboLevels: nool, Contains XFIBO Levels ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int FillBoundaryValues(
|
|
double &dest[],
|
|
int barIndex = 0,
|
|
bool containsFastSlow = true,
|
|
bool containsMABand = true,
|
|
bool containsHKBound = true,
|
|
bool containsPBBand = true,
|
|
bool containsFiboLevels = false //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Prepare ...
|
|
XClean(dest);
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
bool has = IsValid();
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Read and Validate Values ...
|
|
|
|
//
|
|
double fast = GetMAFast(barIndex);
|
|
double slow = GetMASlow(barIndex);
|
|
|
|
//
|
|
double maBandUpper = GetMABandUpper(barIndex);
|
|
double maBandLower = GetMABandLower(barIndex);
|
|
|
|
//
|
|
double pbBandUpper = GetPBBandUpper(barIndex);
|
|
double pbBandLower = GetPBBandLower(barIndex);
|
|
|
|
//
|
|
double hkBandUpper = GetHKBandUpper(barIndex);
|
|
double hkBandLower = GetHKBandLower(barIndex);
|
|
|
|
//
|
|
double fiboUpper = GetFiboUpper(barIndex);
|
|
double fiboLower = GetFiboLower(barIndex);
|
|
double fiboMiddle = GetFiboMiddle(barIndex);
|
|
|
|
//
|
|
has =
|
|
NotEmptyZero(fast) &&
|
|
NotEmptyZero(slow) &&
|
|
NotEmptyZero(fiboLower) &&
|
|
NotEmptyZero(fiboUpper) &&
|
|
NotEmptyZero(fiboMiddle) &&
|
|
NotEmptyZero(maBandUpper) &&
|
|
NotEmptyZero(maBandLower) &&
|
|
NotEmptyZero(pbBandUpper) &&
|
|
NotEmptyZero(pbBandLower) &&
|
|
NotEmptyZero(hkBandUpper) &&
|
|
NotEmptyZero(hkBandLower);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Fill Dest ...
|
|
|
|
//
|
|
// XMA Fast / Slow ...
|
|
if (containsFastSlow)
|
|
{
|
|
//
|
|
Add(fast, dest);
|
|
Add(slow, dest);
|
|
}
|
|
|
|
//
|
|
// XMA Bound ...
|
|
if (containsMABand)
|
|
{
|
|
//
|
|
Add(maBandUpper, dest);
|
|
Add(maBandLower, dest);
|
|
}
|
|
|
|
//
|
|
// XHK Band ...
|
|
if (containsHKBound)
|
|
{
|
|
//
|
|
Add(hkBandUpper, dest);
|
|
Add(hkBandLower, dest);
|
|
}
|
|
|
|
//
|
|
// XPB Band ...
|
|
if (containsPBBand)
|
|
{
|
|
//
|
|
Add(pbBandUpper, dest);
|
|
Add(pbBandLower, dest);
|
|
}
|
|
|
|
//
|
|
// XFIBO Zones ...
|
|
if (containsFiboLevels)
|
|
{
|
|
//
|
|
Add(fiboLower, dest);
|
|
Add(fiboUpper, dest);
|
|
Add(fiboMiddle, dest);
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieve Fast, Slow, MA Band Upper/Lower, HK Band Upper/Lower and PB Band Upper/Lower Min/Max ...
|
|
*
|
|
* @param min: double, minimum value ...
|
|
* @param max: double, maximum value ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool GetBoundaryValues(
|
|
double &min,
|
|
double &max,
|
|
int barIndex = 0,
|
|
bool containsFastSlow = true,
|
|
bool containsMABand = true,
|
|
bool containsHKBound = true,
|
|
bool containsPBBand = true,
|
|
bool containsFiboLevels = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
min = EMPTY_VALUE;
|
|
max = EMPTY_VALUE;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double fast = GetMAFast(barIndex);
|
|
double slow = GetMASlow(barIndex);
|
|
|
|
//
|
|
double maBandUpper = GetMABandUpper(barIndex);
|
|
double maBandLower = GetMABandLower(barIndex);
|
|
|
|
//
|
|
double pbBandUpper = GetPBBandUpper(barIndex);
|
|
double pbBandLower = GetPBBandLower(barIndex);
|
|
|
|
//
|
|
double hkBandUpper = GetHKBandUpper(barIndex);
|
|
double hkBandLower = GetHKBandLower(barIndex);
|
|
|
|
//
|
|
double fiboUpper = GetFiboUpper(barIndex);
|
|
double fiboLower = GetFiboLower(barIndex);
|
|
double fiboMiddle = GetFiboMiddle(barIndex);
|
|
|
|
//
|
|
result =
|
|
NotEmptyZero(fast) &&
|
|
NotEmptyZero(slow) &&
|
|
NotEmptyZero(fiboLower) &&
|
|
NotEmptyZero(fiboUpper) &&
|
|
NotEmptyZero(fiboMiddle) &&
|
|
NotEmptyZero(maBandUpper) &&
|
|
NotEmptyZero(maBandLower) &&
|
|
NotEmptyZero(pbBandUpper) &&
|
|
NotEmptyZero(pbBandLower) &&
|
|
NotEmptyZero(hkBandUpper) &&
|
|
NotEmptyZero(hkBandLower);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double values[];
|
|
|
|
//
|
|
if (containsFastSlow)
|
|
{
|
|
//
|
|
Add(fast, values);
|
|
Add(slow, values);
|
|
}
|
|
|
|
//
|
|
if (containsMABand)
|
|
{
|
|
//
|
|
Add(maBandUpper, values);
|
|
Add(maBandLower, values);
|
|
}
|
|
|
|
//
|
|
if (containsHKBound)
|
|
{
|
|
//
|
|
Add(hkBandUpper, values);
|
|
Add(hkBandLower, values);
|
|
}
|
|
|
|
//
|
|
if (containsPBBand)
|
|
{
|
|
//
|
|
Add(pbBandUpper, values);
|
|
Add(pbBandLower, values);
|
|
}
|
|
|
|
//
|
|
if (containsFiboLevels)
|
|
{
|
|
//
|
|
Add(fiboLower, values);
|
|
Add(fiboUpper, values);
|
|
Add(fiboMiddle, values);
|
|
}
|
|
|
|
//
|
|
result = HasChild(values);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
min = GetMin(values);
|
|
max = GetMax(values);
|
|
|
|
//
|
|
result =
|
|
NotEmptyZero(min) &&
|
|
NotEmptyZero(max) &&
|
|
min < max;
|
|
|
|
//
|
|
return result;
|
|
}
|