3513 lines
70 KiB
Plaintext
3513 lines
70 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Class Library
|
|
// --------------------------------------
|
|
// Name: XPOI
|
|
// Description: Provides Point of Interests ...
|
|
// - Swing Highs;
|
|
// - Swing Lows;
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property library
|
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
|
#property link "https://www.saherelm.ir"
|
|
#property version "1.00"
|
|
#property strict
|
|
|
|
//
|
|
// Imports ...
|
|
|
|
//
|
|
#include "../Classes/x-saherelm.x-alert.class.mq5"
|
|
#include "../Classes/x-saherelm.x-bar.analyser.class.mq5"
|
|
#include "../Libraries/x-saherelm.x-poi.state.lib.mq5"
|
|
|
|
//
|
|
// Implementation ...
|
|
|
|
//
|
|
// POI Detector Class ...
|
|
class XCPOIDetector : public XCBaseAlert
|
|
{
|
|
//
|
|
public:
|
|
//
|
|
|
|
//
|
|
// Constructors ...
|
|
/**
|
|
* Create an Instance ...
|
|
*
|
|
* @param symbol: String ...
|
|
* @param period: ENUM_TIMEFRAMES member ...
|
|
*/
|
|
void XCPOIDetector(
|
|
string symbol,
|
|
ENUM_TIMEFRAMES period)
|
|
{
|
|
//
|
|
// Attach Required Properties ...
|
|
mSymbol = symbol;
|
|
mPeriod = period;
|
|
|
|
//
|
|
// Initialize Bar Tracker ...
|
|
mBarTracker.Init(
|
|
mSymbol,
|
|
mPeriod //
|
|
);
|
|
|
|
//
|
|
mBarAnalyser = new XCBarAnalyser();
|
|
|
|
//
|
|
// Apply Default Configurations ...
|
|
Default();
|
|
}
|
|
|
|
//
|
|
// Deconstructor ...
|
|
void ~XCPOIDetector()
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
//
|
|
// Getter(s) / Setter(s) ...
|
|
|
|
/**
|
|
* Retrieve Detector Symbol ...
|
|
*
|
|
* @return ( string )
|
|
*/
|
|
string GetSymbol()
|
|
{
|
|
return mSymbol;
|
|
}
|
|
|
|
/**
|
|
* Retrieve Detector Period ...
|
|
*
|
|
* @return ( ENUM_TIMEFRAMES )
|
|
*/
|
|
ENUM_TIMEFRAMES GetPeriod()
|
|
{
|
|
return mPeriod;
|
|
}
|
|
|
|
/**
|
|
* Get Max Required POI(s) allowed to Holds ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int MaxRequiredPOIs()
|
|
{
|
|
return mMaxRequiredPOIs;
|
|
}
|
|
|
|
/**
|
|
* Set Max Required POI(s) allowed to Holds ...
|
|
*
|
|
* @param value: int ...
|
|
*/
|
|
void MaxRequiredPOIs(int value)
|
|
{
|
|
//
|
|
if (value < 0)
|
|
{
|
|
value = 5;
|
|
}
|
|
|
|
//
|
|
mMaxRequiredPOIs = value;
|
|
}
|
|
|
|
/**
|
|
* Get Max Allowed Loopback for POI(s) Detection on Initialization Process ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int MaxAllowedLoopbackForInit()
|
|
{
|
|
return maxAllowedLoopbackForInit;
|
|
}
|
|
|
|
/**
|
|
* Set Max Allowed Loopback for POI(s) Detection on Initialization Process ...
|
|
*
|
|
* @param value: int ...
|
|
*/
|
|
void MaxAllowedLoopbackForInit(int value)
|
|
{
|
|
//
|
|
if (value < 0)
|
|
{
|
|
value = 578;
|
|
}
|
|
|
|
//
|
|
maxAllowedLoopbackForInit = value;
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
/**
|
|
* Get Swing Range Validation ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int SwingRange()
|
|
{
|
|
return mSwingRange;
|
|
}
|
|
|
|
/**
|
|
* Set Swing Range Validation ...
|
|
*
|
|
* @param value: int ...
|
|
*/
|
|
void SwingRange(int value)
|
|
{
|
|
//
|
|
value = NormalizeInt(value, 1);
|
|
|
|
//
|
|
mSwingRange = value;
|
|
}
|
|
|
|
/**
|
|
* Get Pullback Range Validation ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int PullbackRange()
|
|
{
|
|
return mPullbackRange;
|
|
}
|
|
|
|
/**
|
|
* Set Pullback Range Validation ...
|
|
*
|
|
* @param value: int ...
|
|
*/
|
|
void PullbackRange(int value)
|
|
{
|
|
//
|
|
value = NormalizeInt(value, 1);
|
|
|
|
//
|
|
mPullbackRange = value;
|
|
}
|
|
|
|
/**
|
|
* Get Momentum Detecting Loopback ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int MomentumLoopback()
|
|
{
|
|
return mMomentumLoopback;
|
|
}
|
|
|
|
/**
|
|
* Set Momentum Detecting Loopback ...
|
|
*
|
|
* @param value: int ...
|
|
*/
|
|
void MomentumLoopback(int value)
|
|
{
|
|
//
|
|
value = NormalizeInt(value, 1);
|
|
|
|
//
|
|
mMomentumLoopback = value;
|
|
}
|
|
|
|
/**
|
|
* Get Rejection Detecting Force Bar Type State ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool RejectionForceBarType()
|
|
{
|
|
return mRejectionForceBarType;
|
|
}
|
|
|
|
/**
|
|
* Set Rejection Detecting Force Bar Type State ...
|
|
*
|
|
* @param value: bool ...
|
|
*/
|
|
void RejectionForceBarType(bool value)
|
|
{
|
|
mRejectionForceBarType = value;
|
|
}
|
|
|
|
/**
|
|
* Get Rejection Detecting Force Fibo Pressure State ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool RejectionForceFiboPressure()
|
|
{
|
|
return mRejectionForceFiboPressure;
|
|
}
|
|
|
|
/**
|
|
* Set Rejection Detecting Force Fibo Pressure State ...
|
|
*
|
|
* @param value: bool ...
|
|
*/
|
|
void RejectionForceFiboPressure(bool value)
|
|
{
|
|
mRejectionForceFiboPressure = value;
|
|
}
|
|
|
|
/**
|
|
* Get Minimum Length of Cnsolidation Zone ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ConsolidationZoneMinLoopback()
|
|
{
|
|
return mConsolidationZoneMinLoopback;
|
|
}
|
|
|
|
/**
|
|
* Set Minimum Length of Cnsolidation Zone ...
|
|
*
|
|
* @param value: int ...
|
|
*/
|
|
void ConsolidationZoneMinLoopback(int value)
|
|
{
|
|
//
|
|
value = NormalizeInt(value, 1);
|
|
|
|
//
|
|
mConsolidationZoneMinLoopback = value;
|
|
}
|
|
|
|
/**
|
|
* Get Consolidation Zone Range in Point ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double ConsolidationZoneRangeInPoint()
|
|
{
|
|
return mConsolidationZoneRangeInPoint;
|
|
}
|
|
|
|
/**
|
|
* Set Consolidation Zone Range in Point ...
|
|
*
|
|
* @param value: double ...
|
|
*/
|
|
void ConsolidationZoneRangeInPoint(double value)
|
|
{
|
|
//
|
|
value = NormalizeDouble(value, 0);
|
|
|
|
//
|
|
mConsolidationZoneRangeInPoint = value;
|
|
}
|
|
|
|
/**
|
|
* Get Consolidation Zone Lower Applied To ...
|
|
*
|
|
* @return ( ENUM_X_PRICE )
|
|
*/
|
|
ENUM_X_PRICE ConsolidationZonesLowerAppliedTo()
|
|
{
|
|
return mConsolidationZonesLowerAppliedTo;
|
|
}
|
|
|
|
/**
|
|
* Get Consolidation Zone Lower Applied To ...
|
|
*
|
|
* @param value: ENUM_X_PRICE member ...
|
|
*/
|
|
void ConsolidationZonesLowerAppliedTo(ENUM_X_PRICE value)
|
|
{
|
|
mConsolidationZonesLowerAppliedTo = value;
|
|
}
|
|
|
|
/**
|
|
* Get Consolidation Zone Upper Applied To ...
|
|
*
|
|
* @return ( ENUM_X_PRICE )
|
|
*/
|
|
ENUM_X_PRICE ConsolidationZonesUpperAppliedTo()
|
|
{
|
|
return mConsolidationZonesUpperAppliedTo;
|
|
}
|
|
|
|
/**
|
|
* Get Consolidation Zone Upper Applied To ...
|
|
*
|
|
* @param value: ENUM_X_PRICE member ...
|
|
*/
|
|
void ConsolidationZonesUpperAppliedTo(ENUM_X_PRICE value)
|
|
{
|
|
mConsolidationZonesUpperAppliedTo = value;
|
|
}
|
|
|
|
/**
|
|
* Get Spike Detection Price Type ...
|
|
*
|
|
* @return ( ENUM_X_PRICE )
|
|
*/
|
|
ENUM_X_PRICE SpikePriceType()
|
|
{
|
|
return mSpikePriceType;
|
|
}
|
|
|
|
/**
|
|
* Set Spike Detection Price Type ...
|
|
*
|
|
* @param value: ENUM_X_PRICE member ...
|
|
*/
|
|
void SpikePriceType(ENUM_X_PRICE value)
|
|
{
|
|
mSpikePriceType = value;
|
|
}
|
|
|
|
/**
|
|
* Get Spike Detection Force Body In Range State ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool SpikeForcBodyInRange()
|
|
{
|
|
return mSpikeForcBodyInRange;
|
|
}
|
|
|
|
/**
|
|
* Set Spike Detection Force Body In Range State ...
|
|
*
|
|
* @param value: bool ...
|
|
*/
|
|
void SpikeForcBodyInRange(bool value)
|
|
{
|
|
mSpikeForcBodyInRange = value;
|
|
}
|
|
|
|
/**
|
|
* Get Spike Detection Range Extends Multiplier ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double SpikeRangeExtendMultiplier()
|
|
{
|
|
return mSpikeRangeExtendMultiplier;
|
|
}
|
|
|
|
/**
|
|
* Set Spike Detection Range Extends Multiplier ...
|
|
*
|
|
* @param value: double ...
|
|
*/
|
|
void SpikeRangeExtendMultiplier(double value)
|
|
{
|
|
//
|
|
value = NormalizeDouble(value, 1);
|
|
|
|
//
|
|
mSpikeRangeExtendMultiplier = value;
|
|
}
|
|
|
|
/**
|
|
* Get Spike Detection Same Bars ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int SpikeSameBars()
|
|
{
|
|
return mSpikeSameBars;
|
|
}
|
|
|
|
/**
|
|
* Set Spike Detection Same Bars ...
|
|
*
|
|
* @param value: int ...
|
|
*/
|
|
void SpikeSameBars(int value)
|
|
{
|
|
//
|
|
value = NormalizeInt(value, 1);
|
|
|
|
//
|
|
mSpikeSameBars = value;
|
|
}
|
|
|
|
/**
|
|
* Get Support and Resistance Detection Range ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int SupResRange()
|
|
{
|
|
return mSupResRange;
|
|
}
|
|
|
|
/**
|
|
* Set Support and Resistance Detection Range ...
|
|
*
|
|
* @param value: int ...
|
|
*/
|
|
void SupResRange(int value)
|
|
{
|
|
//
|
|
value = NormalizeInt(value, 5);
|
|
|
|
//
|
|
mSupResRange = value;
|
|
}
|
|
|
|
/**
|
|
* Get use Support and Resistance Range as Start ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool SupResRangeAsStart()
|
|
{
|
|
return mSupResRangeAsStart;
|
|
}
|
|
|
|
/**
|
|
* Set use Support and Resistance Range as Start ...
|
|
*
|
|
* @param value: bool ...
|
|
*/
|
|
void SupResRangeAsStart(bool value)
|
|
{
|
|
mSupResRangeAsStart = value;
|
|
}
|
|
|
|
/**
|
|
* Get Force Activations in Supply/Demand and Support/Resistance Detections State ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool SupResForceActivation()
|
|
{
|
|
return mSupResForceActivation;
|
|
}
|
|
|
|
/**
|
|
* Set Force Activations in Supply/Demand and Support/Resistance Detections State ...
|
|
*
|
|
* @param value: bool ...
|
|
*/
|
|
void SupResForceActivation(bool value)
|
|
{
|
|
mSupResForceActivation = value;
|
|
}
|
|
|
|
/**
|
|
* Get FairValueGap Detection Same Bars ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int FairValueGapSameBars()
|
|
{
|
|
return mFairValueGapSameBars;
|
|
}
|
|
|
|
/**
|
|
* Set FairValueGap Detection Same Bars ...
|
|
*
|
|
* @param value: int ...
|
|
*/
|
|
void FairValueGapSameBars(int value)
|
|
{
|
|
//
|
|
value = NormalizeInt(value, 2);
|
|
|
|
//
|
|
mFairValueGapSameBars = value;
|
|
}
|
|
|
|
/**
|
|
* Get FairValueGap Detection Force Check Activation State ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool FairValueGapForceActivation()
|
|
{
|
|
return mFairValueGapForceActivation;
|
|
}
|
|
|
|
/**
|
|
* Set FairValueGap Detection Force Check Activation State ...
|
|
*
|
|
* @param value: bool ...
|
|
*/
|
|
void FairValueGapForceActivation(bool value)
|
|
{
|
|
mFairValueGapForceActivation = value;
|
|
}
|
|
|
|
/**
|
|
* Get OrderBlock Detection Same Bars ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int OrderBlockSameBars()
|
|
{
|
|
return mOrderBlockSameBars;
|
|
}
|
|
|
|
/**
|
|
* Set OrderBlock Detection Same Bars ...
|
|
*
|
|
* @param value: int ...
|
|
*/
|
|
void OrderBlockSameBars(int value)
|
|
{
|
|
//
|
|
value = NormalizeInt(value, 1);
|
|
|
|
//
|
|
mOrderBlockSameBars = value;
|
|
}
|
|
|
|
/**
|
|
* Get Order Blocs Detection Force Spike State ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool OrderBlockForceSpike()
|
|
{
|
|
return mOrderBlockForceSpike;
|
|
}
|
|
|
|
/**
|
|
* Set Order Blocs Detection Force Spike State ...
|
|
*
|
|
* @param value: bool ...
|
|
*/
|
|
void OrderBlockForceSpike(bool value)
|
|
{
|
|
mOrderBlockForceSpike = value;
|
|
}
|
|
|
|
/**
|
|
* Get Order Blocs Detection Force Fair Value Gaps State ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool OrderBlockForceFairValueGap()
|
|
{
|
|
return mOrderBlockForceFairValueGap;
|
|
}
|
|
|
|
/**
|
|
* Set Order Blocs Detection Force Fair Value Gaps State ...
|
|
*
|
|
* @param value: bool ...
|
|
*/
|
|
void OrderBlockForceFairValueGap(bool value)
|
|
{
|
|
mOrderBlockForceFairValueGap = value;
|
|
}
|
|
|
|
/**
|
|
* Get Order Blocs Detection Force Support/Resisatnce ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool OrderBlockForceSupportResistance()
|
|
{
|
|
return mOrderBlockForceSupportResistance;
|
|
}
|
|
|
|
/**
|
|
* Set Order Blocs Detection Force Support/Resisatnce ...
|
|
*
|
|
* @param value: bool ...
|
|
*/
|
|
void OrderBlockForceSupportResistance(bool value)
|
|
{
|
|
mOrderBlockForceSupportResistance = value;
|
|
}
|
|
|
|
/**
|
|
* Get OrderBlock Detection Force Check Activation State ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool OrderBlockForceActivation()
|
|
{
|
|
return mOrderBlockForceActivation;
|
|
}
|
|
|
|
/**
|
|
* Set OrderBlock Detection Force Check Activation State ...
|
|
*
|
|
* @param value: bool ...
|
|
*/
|
|
void OrderBlockForceActivation(bool value)
|
|
{
|
|
mOrderBlockForceActivation = value;
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
|
|
//
|
|
// Actions ...
|
|
|
|
/**
|
|
* Apply Default Configurations ...
|
|
*/
|
|
virtual void Default()
|
|
{
|
|
//
|
|
// Default Props ...
|
|
MaxRequiredPOIs(100);
|
|
MaxAllowedLoopbackForInit(578);
|
|
|
|
//
|
|
SwingRange(7);
|
|
MomentumLoopback(2);
|
|
|
|
//
|
|
PullbackRange(3);
|
|
|
|
//
|
|
MomentumLoopback(2);
|
|
|
|
//
|
|
RejectionForceBarType(true);
|
|
RejectionForceFiboPressure(true);
|
|
|
|
//
|
|
ConsolidationZoneMinLoopback(7);
|
|
ConsolidationZoneRangeInPoint(50);
|
|
ConsolidationZonesLowerAppliedTo(X_PRICE_LOW);
|
|
ConsolidationZonesUpperAppliedTo(X_PRICE_HIGH);
|
|
|
|
//
|
|
SpikePriceType(X_PRICE_CLOSE);
|
|
SpikeForcBodyInRange(true);
|
|
SpikeRangeExtendMultiplier(2.0);
|
|
SpikeSameBars(3);
|
|
|
|
//
|
|
SupResRange(21);
|
|
SupResRangeAsStart(true);
|
|
SupResForceActivation(true);
|
|
|
|
//
|
|
FairValueGapSameBars(3);
|
|
|
|
//
|
|
OrderBlockSameBars(3);
|
|
OrderBlockForceSpike(true);
|
|
OrderBlockForceFairValueGap(true);
|
|
OrderBlockForceSupportResistance(true);
|
|
}
|
|
|
|
/**
|
|
* Add Event Listener ...
|
|
*
|
|
* @param listener: TOnPOIEvent instance ...
|
|
*/
|
|
void AddEventListener(TOnPOIEvent listener)
|
|
{
|
|
//
|
|
Add(
|
|
listener,
|
|
mEventListeners //
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Initialize Instance ...
|
|
*/
|
|
void Init(
|
|
int barIndex = 0,
|
|
bool ignoreMaxAllowed = true //
|
|
)
|
|
{
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
if (maxAllowedLoopbackForInit <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
mLock = true;
|
|
bool canContinue = true;
|
|
int index = barIndex + maxAllowedLoopbackForInit;
|
|
if (!IsValidIndex(index))
|
|
{
|
|
//
|
|
mLock = false;
|
|
return;
|
|
}
|
|
|
|
//
|
|
while (canContinue)
|
|
{
|
|
//
|
|
XOHCL iBar;
|
|
bool has = iBar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
index //
|
|
);
|
|
index--;
|
|
|
|
//
|
|
int count = 0;
|
|
ENUM_XPOI_EVENTS iEvent = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
// Swings ...
|
|
DetectSwing(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
|
|
//
|
|
// Momentum ...
|
|
DetectMomentum(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
|
|
//
|
|
// Rejection ...
|
|
DetectRejection(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
|
|
//
|
|
// Pullback ...
|
|
DetetctPullback(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
|
|
//
|
|
// Consolidation Zone ...
|
|
DetectConsolidationZone(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
|
|
//
|
|
// Spike ...
|
|
DetectSharp(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
|
|
//
|
|
// Spike ...
|
|
DetectSpike(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
|
|
//
|
|
// Support ...
|
|
DetectSupportZone(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
|
|
//
|
|
// Resistance ...
|
|
DetectResistanceZone(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
|
|
//
|
|
// Supply ...
|
|
// DetectSupplyZone(
|
|
// iBar,
|
|
// iEvent //
|
|
// );
|
|
|
|
//
|
|
// Demand ...
|
|
// DetectDemandZone(
|
|
// iBar,
|
|
// iEvent //
|
|
// );
|
|
|
|
//
|
|
// FairValueGap ...
|
|
// DetectFairValueGap(
|
|
// iBar,
|
|
// iEvent //
|
|
// );
|
|
|
|
//
|
|
// OrderBlock ...
|
|
// DetectOrderBlock(
|
|
// iBar,
|
|
// iEvent //
|
|
// );
|
|
|
|
//
|
|
canContinue =
|
|
has &&
|
|
index >= 0;
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
ReverseCollections();
|
|
|
|
//
|
|
mLock = false;
|
|
}
|
|
|
|
/**
|
|
* Update POI(s) ...
|
|
* @param events: ENUM_XPOI_EVENTS member Collection ...
|
|
*/
|
|
void Update(
|
|
ENUM_XPOI_EVENTS &events[],
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
Clean(events);
|
|
|
|
//
|
|
if (mLock)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Check Bar Tracker if Waits ...
|
|
if (!mBarTracker.IsNewBar())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
mLock = true;
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool has = iBar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
if (!has)
|
|
{
|
|
//
|
|
iBar.Clean();
|
|
|
|
//
|
|
return;
|
|
}
|
|
|
|
//
|
|
int count = 0;
|
|
ENUM_XPOI_EVENTS iEvent = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
// Swings ...
|
|
has = DetectSwing(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Momentum ...
|
|
has = DetectMomentum(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Rejection ...
|
|
has = DetectRejection(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Pullback ...
|
|
has = DetetctPullback(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Consolidation Zone ...
|
|
has = DetectConsolidationZone(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Sharp ...
|
|
has = DetectSharp(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Spike ...
|
|
has = DetectSpike(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Support ...
|
|
has = DetectSupportZone(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Resistance ...
|
|
has = DetectResistanceZone(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Supply ...
|
|
// has = DetectSupplyZone(
|
|
// iBar,
|
|
// iEvent //
|
|
// );
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Demand ...
|
|
// has = DetectDemandZone(
|
|
// iBar,
|
|
// iEvent //
|
|
// );
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
}
|
|
|
|
//
|
|
// FairValueGap ...
|
|
// has = DetectFairValueGap(
|
|
// iBar,
|
|
// iEvent //
|
|
// );
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
}
|
|
|
|
//
|
|
// OrderBlock ...
|
|
// has = DetectOrderBlock(
|
|
// iBar,
|
|
// iEvent //
|
|
// );
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
mLock = false;
|
|
|
|
//
|
|
if (HasChild(events))
|
|
{
|
|
CleanupUnusedCollections();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get Current State of POIs ...
|
|
*
|
|
* @param state: XPOIState instance ...
|
|
*/
|
|
void GetState(
|
|
XPOIState &state //
|
|
)
|
|
{
|
|
//
|
|
state.Clean();
|
|
|
|
//
|
|
state.symbol = mSymbol;
|
|
state.period = mPeriod;
|
|
state.time = TimeCurrent();
|
|
|
|
//
|
|
// Swings ...
|
|
|
|
//
|
|
Copy(
|
|
mSwings,
|
|
state.swings //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mSwingLows,
|
|
state.swingLows //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mSwingHighs,
|
|
state.swingHighs //
|
|
);
|
|
|
|
//
|
|
// Pullbacks ...
|
|
|
|
//
|
|
Copy(
|
|
mPullbacks,
|
|
state.pullbacks //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBullishPullbacks,
|
|
state.bullishPullbacks //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBearishPullbacks,
|
|
state.bearishPullbacks //
|
|
);
|
|
|
|
//
|
|
// Momentums ...
|
|
|
|
//
|
|
Copy(
|
|
mMomentums,
|
|
state.momentums //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBullishMomentums,
|
|
state.bullishMomentums //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBearishMomentums,
|
|
state.bearishMomentums //
|
|
);
|
|
|
|
//
|
|
// Rejections ...
|
|
|
|
//
|
|
Copy(
|
|
mRejections,
|
|
state.rejections //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBullishRejections,
|
|
state.bullishRejections //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBearishRejections,
|
|
state.bearishRejections //
|
|
);
|
|
|
|
//
|
|
// Support and Resistances ...
|
|
|
|
//
|
|
Copy(
|
|
mSupportZones,
|
|
state.supportZones //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mResistanceZones,
|
|
state.resistanceZones //
|
|
);
|
|
|
|
//
|
|
// Supply and Demand ...
|
|
|
|
//
|
|
Copy(
|
|
mSupplyZones,
|
|
state.supplyZones //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mDemandZones,
|
|
state.demandZones //
|
|
);
|
|
|
|
//
|
|
// Spikes ...
|
|
|
|
//
|
|
Copy(
|
|
mSpikes,
|
|
state.spikes //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBullishSpikes,
|
|
state.bullishSpikes //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBearishSpikes,
|
|
state.bearishSpikes //
|
|
);
|
|
|
|
//
|
|
// Sharps ...
|
|
|
|
//
|
|
Copy(
|
|
mSharps,
|
|
state.sharps //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBullishSharps,
|
|
state.bullishSharps //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBearishSharps,
|
|
state.bearishSharps //
|
|
);
|
|
|
|
//
|
|
// Consolidation Zones ...
|
|
|
|
//
|
|
Copy(
|
|
mConsolidationZones,
|
|
state.consolidationZones //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBullishConsolidationZones,
|
|
state.bullishConsolidationZones //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBearishConsolidationZones,
|
|
state.bearishConsolidationZones //
|
|
);
|
|
|
|
//
|
|
// Fair Value Gaps ...
|
|
|
|
//
|
|
Copy(
|
|
mFairValueGaps,
|
|
state.fairValueGaps //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBullishFairValueGaps,
|
|
state.bullishFairValueGaps //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBearishFairValueGaps,
|
|
state.bearishFairValueGaps //
|
|
);
|
|
|
|
//
|
|
// Order Blocks ...
|
|
|
|
//
|
|
Copy(
|
|
mOrderBlocks,
|
|
state.orderBlocks //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBullishOrderBlocks,
|
|
state.bullishOrderBlocks //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBearishOrderBlocks,
|
|
state.bearishOrderBlocks //
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Destroy Instance ...
|
|
*/
|
|
void Destroy()
|
|
{
|
|
//
|
|
mBarTracker.Clean();
|
|
ZeroMemory(mBarAnalyser);
|
|
|
|
//
|
|
CleanCollections();
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
|
|
/**
|
|
* Detect Swing ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param state: ENUM_XPOI_EVENTS member ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectSwing(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
state = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL sBar;
|
|
if (bar.Index() == 0)
|
|
{
|
|
//
|
|
result = bar.GetPreviousBar(sBar);
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
return result;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sBar = bar;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION iDir;
|
|
result = mBarAnalyser.IsSwing(
|
|
sBar,
|
|
iDir,
|
|
mSwingRange //
|
|
);
|
|
|
|
//
|
|
result = result &&
|
|
HasDirection(iDir);
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool checkBar = bar.Index() != sBar.Index();
|
|
|
|
//
|
|
bool isBullish =
|
|
IsBullish(iDir) &&
|
|
(!checkBar
|
|
? true
|
|
: bar.low > sBar.low);
|
|
bool isBearish =
|
|
IsBearish(iDir) &&
|
|
(!checkBar
|
|
? true
|
|
: bar.high < sBar.high);
|
|
result = isBullish ||
|
|
isBearish;
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL swingBar;
|
|
result = sBar.GetPreviousBar(swingBar);
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
swingBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ENUM_XPOIS type =
|
|
isBullish
|
|
? X_POI_SWING_LOW
|
|
: X_POI_SWING_HIGH;
|
|
|
|
//
|
|
// Swing Object ...
|
|
XCSwing *swing;
|
|
swing = new XCSwing();
|
|
result = swing.Init(
|
|
swingBar,
|
|
type //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
swingBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Add ...
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
swing,
|
|
mSwings //
|
|
);
|
|
result = !IsValidIndex(idx);
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
swingBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Add All Collection ...
|
|
Add(
|
|
swing,
|
|
mSwings //
|
|
);
|
|
|
|
//
|
|
// Bullish Swings (Swing Low) ...
|
|
if (isBullish)
|
|
{
|
|
//
|
|
Add(
|
|
swing,
|
|
mSwingLows //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Bearish Swings (Swing High) ...
|
|
if (isBearish)
|
|
{
|
|
//
|
|
Add(
|
|
swing,
|
|
mSwingHighs //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Prepare State ...
|
|
state =
|
|
isBullish
|
|
? X_SWING_LOW_DETECTED
|
|
: X_SWING_HIGH_DETECTED;
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
|
|
//
|
|
sBar.Clean();
|
|
swingBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Momentums ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param state: ENUM_XPOI_EVENTS member ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectMomentum(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
state = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL sBar;
|
|
if (bar.Index() == 0)
|
|
{
|
|
//
|
|
result = sBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
bar.Index() + 1 //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
return result;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sBar = bar;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION iDir;
|
|
result = mBarAnalyser.IsMomentum(
|
|
sBar,
|
|
iDir,
|
|
mMomentumLoopback //
|
|
);
|
|
|
|
//
|
|
result = result &&
|
|
HasDirection(iDir);
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(iDir);
|
|
bool isBearish = IsBearish(iDir);
|
|
|
|
//
|
|
ENUM_XPOIS type =
|
|
isBullish
|
|
? X_POI_MOMENTUM_BAR
|
|
: X_POI_MOMENTUM_BAR;
|
|
|
|
//
|
|
// Swing Object ...
|
|
XCMomentumBar *momentum;
|
|
momentum = new XCMomentumBar();
|
|
result = momentum.Init(
|
|
sBar //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
momentum,
|
|
mMomentums //
|
|
);
|
|
result = !IsValidIndex(idx);
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Momentums ...
|
|
Add(
|
|
momentum,
|
|
mMomentums //
|
|
);
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
Add(
|
|
momentum,
|
|
mBullishMomentums //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (isBearish)
|
|
{
|
|
//
|
|
Add(
|
|
momentum,
|
|
mBearishMomentums //
|
|
);
|
|
}
|
|
|
|
//
|
|
state =
|
|
isBullish
|
|
? X_BULLISH_MOMENTUM_BAR_DETECTED
|
|
: X_BEARISH_MOMENTUM_BAR_DETECTED;
|
|
|
|
//
|
|
sBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Rejections ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param state: ENUM_XPOI_EVENTS member ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectRejection(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
state = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL sBar;
|
|
if (bar.Index() == 0)
|
|
{
|
|
//
|
|
result = sBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
bar.Index() + 1 //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
return result;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sBar = bar;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION iDir;
|
|
result = mBarAnalyser.IsRejected(
|
|
sBar,
|
|
iDir,
|
|
mRejectionForceBarType,
|
|
mRejectionForceFiboPressure //
|
|
);
|
|
|
|
//
|
|
result = result &&
|
|
HasDirection(iDir);
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(iDir);
|
|
bool isBearish = IsBearish(iDir);
|
|
|
|
//
|
|
ENUM_XPOIS type =
|
|
isBullish
|
|
? X_POI_MOMENTUM_BAR
|
|
: X_POI_MOMENTUM_BAR;
|
|
|
|
//
|
|
// Swing Object ...
|
|
XCRejectionBar *rejection;
|
|
rejection = new XCRejectionBar();
|
|
result = rejection.Init(
|
|
sBar //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
rejection,
|
|
mRejections //
|
|
);
|
|
result = !IsValidIndex(idx);
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
rejection,
|
|
mRejections //
|
|
);
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
Add(
|
|
rejection,
|
|
mBullishRejections //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (isBearish)
|
|
{
|
|
//
|
|
Add(
|
|
rejection,
|
|
mBearishRejections //
|
|
);
|
|
}
|
|
|
|
//
|
|
state =
|
|
isBullish
|
|
? X_BULLISH_REJECTION_BAR_DETECTED
|
|
: X_BEARISH_REJECTION_BAR_DETECTED;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Pullback ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param state: ENUM_XPOI_EVENTS member ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetetctPullback(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
state = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL sBar;
|
|
if (bar.Index() == 0)
|
|
{
|
|
//
|
|
result = sBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
bar.Index() + 1 //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
return result;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sBar = bar;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION iDir;
|
|
result = mBarAnalyser.IsPullback(
|
|
sBar,
|
|
iDir,
|
|
mPullbackRange,
|
|
true // Force Body ...
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(iDir);
|
|
bool isBearish = IsBearish(iDir);
|
|
result = isBullish ||
|
|
isBearish;
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL fromBar;
|
|
result = fromBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
sBar.Index() + mPullbackRange //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
fromBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone box;
|
|
|
|
//
|
|
box.dir = iDir;
|
|
box.to = sBar.time;
|
|
box.from = fromBar.time;
|
|
box.symbol = fromBar.symbol;
|
|
box.period = fromBar.period;
|
|
box.lower = MathMin(sBar.low, fromBar.low);
|
|
box.upper = MathMax(sBar.high, fromBar.high);
|
|
box.type = ToString(iDir) + "_XPullBK" + box.symbol + "_" + ToString(box.period);
|
|
|
|
//
|
|
result = box.IsValid();
|
|
if (result)
|
|
{
|
|
//
|
|
AddRef(
|
|
box,
|
|
mPullbacks //
|
|
);
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
AddRef(
|
|
box,
|
|
mBullishPullbacks //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (isBearish)
|
|
{
|
|
//
|
|
AddRef(
|
|
box,
|
|
mBearishPullbacks //
|
|
);
|
|
}
|
|
|
|
//
|
|
state =
|
|
isBullish
|
|
? X_BULLISH_PULLBACK_DETECTED
|
|
: X_BEARISH_PULLBACK_DETECTED;
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
|
|
//
|
|
box.Clean();
|
|
sBar.Clean();
|
|
fromBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Consolidation Zones ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param state: ENUM_XPOI_EVENTS member ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectConsolidationZone(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
state = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
XOHCL sBar;
|
|
if (bar.Index() == 0)
|
|
{
|
|
//
|
|
result = sBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
bar.Index() + 1 //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
return result;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sBar = bar;
|
|
}
|
|
|
|
//
|
|
XConsolidationZone cZone;
|
|
result = mBarAnalyser.HasConsolidationZone(
|
|
sBar,
|
|
cZone,
|
|
mConsolidationZoneMinLoopback,
|
|
mConsolidationZoneRangeInPoint,
|
|
mConsolidationZonesUpperAppliedTo,
|
|
mConsolidationZonesLowerAppliedTo //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
cZone.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Add ...
|
|
|
|
//
|
|
bool isBullish = IsBullish(cZone.dir);
|
|
bool isBearish = IsBearish(cZone.dir);
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
cZone,
|
|
mConsolidationZones //
|
|
);
|
|
result = !IsValidIndex(idx);
|
|
if (!result)
|
|
{
|
|
//
|
|
sBar.Clean();
|
|
cZone.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
AddRef(
|
|
cZone,
|
|
mConsolidationZones //
|
|
);
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
AddRef(
|
|
cZone,
|
|
mBullishConsolidationZones //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (isBearish)
|
|
{
|
|
//
|
|
AddRef(
|
|
cZone,
|
|
mBearishConsolidationZones //
|
|
);
|
|
}
|
|
|
|
//
|
|
state =
|
|
IsBullish(cZone.dir)
|
|
? X_BULLISH_CONSOLIDATION_ZONE_DETECTED
|
|
: X_BEARISH_CONSOLIDATION_ZONE_DETECTED;
|
|
|
|
//
|
|
cZone.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Sharp Change ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param state: ENUM_XPOI_EVENTS member ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectSharp(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
state = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int sharpRootIDX = -1;
|
|
ENUM_X_DIRECTION iDir;
|
|
result = mBarAnalyser.IsSharp(
|
|
bar,
|
|
iDir,
|
|
sharpRootIDX,
|
|
mSpikePriceType,
|
|
mSpikeForcBodyInRange,
|
|
mSpikeRangeExtendMultiplier //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(iDir);
|
|
bool isBearish = IsBearish(iDir);
|
|
|
|
//
|
|
XOHCL fromBar;
|
|
result = fromBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
sharpRootIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
fromBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone box;
|
|
|
|
//
|
|
box.dir = iDir;
|
|
box.to = bar.time;
|
|
box.from = fromBar.time;
|
|
box.symbol = fromBar.symbol;
|
|
box.period = fromBar.period;
|
|
box.type = ToString(iDir) + "_XSharp" + box.symbol + "_" + ToString(box.period);
|
|
|
|
//
|
|
box.upper =
|
|
isBullish
|
|
? bar.high
|
|
: fromBar.high;
|
|
|
|
//
|
|
box.lower =
|
|
isBullish
|
|
? fromBar.low
|
|
: bar.low;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
if (result)
|
|
{
|
|
//
|
|
AddRef(
|
|
box,
|
|
mSharps //
|
|
);
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
AddRef(
|
|
box,
|
|
mBullishSharps //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (isBearish)
|
|
{
|
|
//
|
|
AddRef(
|
|
box,
|
|
mBearishSharps //
|
|
);
|
|
}
|
|
|
|
//
|
|
state =
|
|
isBullish
|
|
? X_BULLISH_SHARP_DETECTED
|
|
: X_BEARISH_SHARP_DETECTED;
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
|
|
//
|
|
box.Clean();
|
|
fromBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Spike ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param state: ENUM_XPOI_EVENTS member ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectSpike(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
state = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int rootIDX = -1;
|
|
ENUM_X_DIRECTION iDir;
|
|
result = mBarAnalyser.IsSpike(
|
|
bar,
|
|
iDir,
|
|
rootIDX,
|
|
mSpikePriceType,
|
|
mSpikeForcBodyInRange,
|
|
mSpikeRangeExtendMultiplier,
|
|
mSpikeSameBars //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Chek Same Bars ...
|
|
int sameBarsIndex = -1;
|
|
ENUM_X_DIRECTION sameBarsDir;
|
|
result = mBarAnalyser.HasSameBars(
|
|
bar,
|
|
sameBarsDir,
|
|
sameBarsIndex,
|
|
mSpikeSameBars //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Validate Same Bars Dir and Spike Dir ...
|
|
result = iDir == sameBarsDir;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(iDir);
|
|
bool isBearish = IsBearish(iDir);
|
|
|
|
//
|
|
XOHCL fromBar;
|
|
result = fromBar.Init(
|
|
bar.symbol,
|
|
bar.period,
|
|
rootIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
fromBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone box;
|
|
|
|
//
|
|
box.dir = iDir;
|
|
box.to = bar.time;
|
|
box.from = fromBar.time;
|
|
box.symbol = fromBar.symbol;
|
|
box.period = fromBar.period;
|
|
box.type = ToString(iDir) + "_XSpike_" + box.symbol + "_" + ToString(box.period);
|
|
|
|
//
|
|
box.upper =
|
|
isBullish
|
|
? bar.high
|
|
: fromBar.high;
|
|
|
|
//
|
|
box.lower =
|
|
isBullish
|
|
? fromBar.low
|
|
: bar.low;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
if (result)
|
|
{
|
|
//
|
|
AddRef(
|
|
box,
|
|
mSpikes //
|
|
);
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
AddRef(
|
|
box,
|
|
mBullishSpikes //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (isBearish)
|
|
{
|
|
//
|
|
AddRef(
|
|
box,
|
|
mBearishSpikes //
|
|
);
|
|
}
|
|
|
|
//
|
|
state =
|
|
isBullish
|
|
? X_BULLISH_SPIKE_DETECTED
|
|
: X_BEARISH_SPIKE_DETECTED;
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
|
|
//
|
|
box.Clean();
|
|
fromBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Support Zone ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param state: ENUM_XPOI_EVENTS member ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectSupportZone(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
state = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL supportBar;
|
|
result = mBarAnalyser
|
|
.HasSupport(
|
|
bar,
|
|
supportBar,
|
|
mSupResRange //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
supportBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XCSupportZone *supportZone;
|
|
supportZone = new XCSupportZone();
|
|
result = supportZone.Init(
|
|
supportBar,
|
|
mSupResRange,
|
|
mSupResRangeAsStart // Use Range As Start ...
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
supportBar.Clean();
|
|
ZeroMemory(supportZone);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Zone Not Activated ...
|
|
if (mSupResForceActivation)
|
|
{
|
|
//
|
|
XOHCL activationBar;
|
|
bool isActivationBarBodyIn = false;
|
|
bool isActivated = supportZone.IsActivated(
|
|
X_DIRECTION_BULLISH,
|
|
activationBar,
|
|
isActivationBarBodyIn,
|
|
false,
|
|
bar.period //
|
|
);
|
|
result = !isActivated;
|
|
if (!result)
|
|
{
|
|
//
|
|
supportBar.Clean();
|
|
activationBar.Clean();
|
|
ZeroMemory(supportZone);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
activationBar.Clean();
|
|
}
|
|
|
|
//
|
|
// Add ...
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
supportZone,
|
|
mSupportZones //
|
|
);
|
|
result = !IsValidIndex(idx);
|
|
if (!result)
|
|
{
|
|
//
|
|
supportBar.Clean();
|
|
ZeroMemory(supportZone);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
supportZone,
|
|
mSupportZones //
|
|
);
|
|
|
|
//
|
|
state = X_SUPPORT_ZONE_DETECTED;
|
|
|
|
//
|
|
supportBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Resistance Zone ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param state: ENUM_XPOI_EVENTS member ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectResistanceZone(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
state = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL resistanceBar;
|
|
result = mBarAnalyser
|
|
.HasResistance(
|
|
bar,
|
|
resistanceBar,
|
|
mSupResRange //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
resistanceBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XCResistanceZone *resistanceZone;
|
|
resistanceZone = new XCResistanceZone();
|
|
result = resistanceZone.Init(
|
|
resistanceBar,
|
|
mSupResRange,
|
|
mSupResRangeAsStart // Use Range As Start ...
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
resistanceBar.Clean();
|
|
ZeroMemory(resistanceZone);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Zone Not Activated ...
|
|
if (mSupResForceActivation)
|
|
{
|
|
//
|
|
XOHCL activationBar;
|
|
bool isActivationBarBodyIn = false;
|
|
bool isActivated = resistanceZone.IsActivated(
|
|
X_DIRECTION_BULLISH,
|
|
activationBar,
|
|
isActivationBarBodyIn,
|
|
false,
|
|
bar.period //
|
|
);
|
|
result = !isActivated;
|
|
if (!result)
|
|
{
|
|
//
|
|
resistanceBar.Clean();
|
|
activationBar.Clean();
|
|
ZeroMemory(resistanceZone);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
activationBar.Clean();
|
|
}
|
|
|
|
//
|
|
// Add ...
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
resistanceZone,
|
|
mResistanceZones //
|
|
);
|
|
result = !IsValidIndex(idx);
|
|
if (!result)
|
|
{
|
|
//
|
|
resistanceBar.Clean();
|
|
ZeroMemory(resistanceZone);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
resistanceZone,
|
|
mResistanceZones //
|
|
);
|
|
|
|
//
|
|
state = X_RESISTANCE_ZONE_DETECTED;
|
|
|
|
//
|
|
resistanceBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Supply Zone ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param state: ENUM_XPOI_EVENTS member ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectSupplyZone(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
state = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int mSupDemRange = mSupResRange * 2;
|
|
|
|
//
|
|
XOHCL supplyBar;
|
|
result = mBarAnalyser
|
|
.HasResistance(
|
|
bar,
|
|
supplyBar,
|
|
mSupDemRange //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
supplyBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XCSupplyZone *supplyZone;
|
|
supplyZone = new XCSupplyZone();
|
|
result = supplyZone.Init(
|
|
supplyBar,
|
|
mSupDemRange,
|
|
mSupResRangeAsStart // Use Range As Start ...
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
supplyBar.Clean();
|
|
ZeroMemory(supplyZone);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Zone Not Activated ...
|
|
if (mSupResForceActivation)
|
|
{
|
|
//
|
|
XOHCL activationBar;
|
|
bool isActivationBarBodyIn = false;
|
|
bool isActivated = supplyZone.IsActivated(
|
|
X_DIRECTION_BULLISH,
|
|
activationBar,
|
|
isActivationBarBodyIn,
|
|
false,
|
|
bar.period //
|
|
);
|
|
result = !isActivated;
|
|
if (!result)
|
|
{
|
|
//
|
|
supplyBar.Clean();
|
|
activationBar.Clean();
|
|
ZeroMemory(supplyZone);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
activationBar.Clean();
|
|
}
|
|
|
|
//
|
|
// Add ...
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
supplyZone,
|
|
mSupplyZones //
|
|
);
|
|
result = !IsValidIndex(idx);
|
|
if (!result)
|
|
{
|
|
//
|
|
supplyBar.Clean();
|
|
ZeroMemory(supplyZone);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
supplyZone,
|
|
mSupplyZones //
|
|
);
|
|
|
|
//
|
|
state = X_SUPPLY_ZONE_DETECTED;
|
|
|
|
//
|
|
supplyBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Demand Zone ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param state: ENUM_XPOI_EVENTS member ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectDemandZone(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
state = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int mSupDemRange = mSupResRange * 2;
|
|
|
|
//
|
|
XOHCL demandBar;
|
|
result = mBarAnalyser
|
|
.HasSupport(
|
|
bar,
|
|
demandBar,
|
|
mSupDemRange //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
demandBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XCDemandZone *demandZone;
|
|
demandZone = new XCDemandZone();
|
|
result = demandZone.Init(
|
|
demandBar,
|
|
mSupDemRange,
|
|
mSupResRangeAsStart // Use Range As Start ...
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
demandBar.Clean();
|
|
ZeroMemory(demandZone);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Zone Not Activated ...
|
|
if (mSupResForceActivation)
|
|
{
|
|
//
|
|
XOHCL activationBar;
|
|
bool isActivationBarBodyIn = false;
|
|
bool isActivated = demandZone.IsActivated(
|
|
X_DIRECTION_BULLISH,
|
|
activationBar,
|
|
isActivationBarBodyIn,
|
|
false,
|
|
bar.period //
|
|
);
|
|
result = !isActivated;
|
|
if (!result)
|
|
{
|
|
//
|
|
demandBar.Clean();
|
|
activationBar.Clean();
|
|
ZeroMemory(demandZone);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
activationBar.Clean();
|
|
}
|
|
|
|
//
|
|
// Add ...
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
demandZone,
|
|
mDemandZones //
|
|
);
|
|
result = !IsValidIndex(idx);
|
|
if (!result)
|
|
{
|
|
//
|
|
demandBar.Clean();
|
|
ZeroMemory(demandZone);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
demandZone,
|
|
mDemandZones //
|
|
);
|
|
|
|
//
|
|
state = X_DEMAND_ZONE_DETECTED;
|
|
|
|
//
|
|
demandBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Fair Value Gaps ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param state: ENUM_XPOI_EVENTS member ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectFairValueGap(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
state = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL fvgStartBar;
|
|
XOHCL fvgEndBar;
|
|
ENUM_X_DIRECTION fvgDir;
|
|
result = mBarAnalyser.HasFairValueGap(
|
|
bar,
|
|
fvgStartBar,
|
|
fvgEndBar,
|
|
fvgDir,
|
|
mFairValueGapSameBars //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
fvgEndBar.Clean();
|
|
fvgStartBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XCFVG *fvg;
|
|
fvg = new XCFVG();
|
|
result = fvg.Init(
|
|
fvgStartBar,
|
|
fvgEndBar,
|
|
fvgDir //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
ZeroMemory(fvg);
|
|
fvgEndBar.Clean();
|
|
fvgStartBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(fvgDir);
|
|
bool isBearish = IsBearish(fvgDir);
|
|
|
|
//
|
|
// Check Zone Not Activated ...
|
|
if (mFairValueGapForceActivation)
|
|
{
|
|
//
|
|
XOHCL activationBar;
|
|
bool isActivationBarBodyIn = false;
|
|
bool isActivated = fvg.IsActivated(
|
|
fvgDir,
|
|
activationBar,
|
|
isActivationBarBodyIn,
|
|
false,
|
|
bar.period //
|
|
);
|
|
result = !isActivated;
|
|
if (!result)
|
|
{
|
|
//
|
|
ZeroMemory(fvg);
|
|
fvgEndBar.Clean();
|
|
fvgStartBar.Clean();
|
|
activationBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
activationBar.Clean();
|
|
}
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
fvg,
|
|
mFairValueGaps //
|
|
);
|
|
result = !IsValidIndex(idx);
|
|
if (!result)
|
|
{
|
|
//
|
|
ZeroMemory(fvg);
|
|
fvgEndBar.Clean();
|
|
fvgStartBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
fvg,
|
|
mFairValueGaps //
|
|
);
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
Add(
|
|
fvg,
|
|
mBullishFairValueGaps //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (isBearish)
|
|
{
|
|
//
|
|
Add(
|
|
fvg,
|
|
mBearishFairValueGaps //
|
|
);
|
|
}
|
|
|
|
//
|
|
state =
|
|
isBullish
|
|
? X_BULLISH_FVG_DETECTED
|
|
: X_BEARISH_FVG_DETECTED;
|
|
|
|
//
|
|
fvgEndBar.Clean();
|
|
fvgStartBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Order Blocks ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param state: ENUM_XPOI_EVENTS member ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectOrderBlock(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
state = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL obBar;
|
|
ENUM_X_DIRECTION obDir;
|
|
result = mBarAnalyser.HasOrderBlock(
|
|
bar,
|
|
obBar,
|
|
obDir,
|
|
mOrderBlockSameBars,
|
|
mOrderBlockForceSpike,
|
|
mOrderBlockForceFairValueGap,
|
|
mOrderBlockForceSupportResistance //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
obBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XCOrderBlock *ob;
|
|
ob = new XCOrderBlock();
|
|
result = ob.Init(
|
|
obBar,
|
|
obDir //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
obBar.Clean();
|
|
ZeroMemory(ob);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(obDir);
|
|
bool isBearish = IsBearish(obDir);
|
|
|
|
//
|
|
// Check Zone Not Activated ...
|
|
if (mOrderBlockForceActivation)
|
|
{
|
|
//
|
|
XOHCL activationBar;
|
|
bool isActivationBarBodyIn = false;
|
|
bool isActivated = ob.IsActivated(
|
|
obDir,
|
|
activationBar,
|
|
isActivationBarBodyIn,
|
|
false,
|
|
bar.period //
|
|
);
|
|
result = !isActivated;
|
|
if (!result)
|
|
{
|
|
//
|
|
obBar.Clean();
|
|
activationBar.Clean();
|
|
ZeroMemory(ob);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
activationBar.Clean();
|
|
}
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
ob,
|
|
mOrderBlocks //
|
|
);
|
|
result = !IsValidIndex(idx);
|
|
if (!result)
|
|
{
|
|
//
|
|
obBar.Clean();
|
|
ZeroMemory(ob);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
ob,
|
|
mOrderBlocks //
|
|
);
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
Add(
|
|
ob,
|
|
mBullishOrderBlocks //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (isBearish)
|
|
{
|
|
//
|
|
Add(
|
|
ob,
|
|
mBearishOrderBlocks //
|
|
);
|
|
}
|
|
|
|
//
|
|
state =
|
|
isBullish
|
|
? X_BULLISH_ORDERBLOCK_DETECTED
|
|
: X_BEARISH_ORDERBLOCK_DETECTED;
|
|
|
|
//
|
|
obBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
protected:
|
|
//
|
|
|
|
/**
|
|
* Notify Event Listeners ...
|
|
*
|
|
* @param event: ENUM_XPOI_EVENTS member, Specified Occured Event ...
|
|
* @param param: XCBasePOI implementation, Specified Event Object ...
|
|
*/
|
|
void NotifyEventListeners(
|
|
ENUM_XPOI_EVENTS event,
|
|
XCBasePOI *param //
|
|
)
|
|
{
|
|
//
|
|
int count = ArraySize(mEventListeners);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
mEventListeners[i](
|
|
event,
|
|
param //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
private:
|
|
//
|
|
|
|
//
|
|
// Props ...
|
|
string mSymbol; // Market Symbol ...
|
|
ENUM_TIMEFRAMES mPeriod; // Market Period ...
|
|
XBarTracker mBarTracker; // Market Bar Tracker ...
|
|
XCBarAnalyser *mBarAnalyser; // Bar Analyser ...
|
|
|
|
//
|
|
bool mLock;
|
|
|
|
//
|
|
int mMaxRequiredPOIs; // Max Allowed Holds POI(s) ...
|
|
int maxAllowedLoopbackForInit; // Max Allowed Loopback for POI(s) Detection on Initialization Process ...
|
|
|
|
//
|
|
TOnPOIEvent mEventListeners[]; // Event Listeners ...
|
|
|
|
//
|
|
// Swings ...
|
|
XCSwing *mSwings[]; // Holds Founded Swing ...
|
|
XCSwing *mSwingLows[]; // Holds Founded Swing Lows ...
|
|
XCSwing *mSwingHighs[]; // Holds Founded Swing Highs ...
|
|
int mSwingRange; // Swing Detection Range ...
|
|
|
|
//
|
|
// Pullbacks ...
|
|
XBoxZone mPullbacks[]; // Holds Founded Pullbacks ...
|
|
XBoxZone mBullishPullbacks[]; // Holds Founded Bullish Pullbacks ...
|
|
XBoxZone mBearishPullbacks[]; // Holds Founded Bearish Pullbacks ...
|
|
int mPullbackRange; // Pullback Detection Range ...
|
|
|
|
//
|
|
// Momentums ...
|
|
XCMomentumBar *mMomentums[]; // Holds Founded Momentum Bars ...
|
|
XCMomentumBar *mBullishMomentums[]; // Holds Founded Bullish Momentum Bars ...
|
|
XCMomentumBar *mBearishMomentums[]; // Holds Founded Bearish Momentum Bars ...
|
|
int mMomentumLoopback; // Momentum Detecting Loopback ...
|
|
|
|
//
|
|
// Rejections ...
|
|
XCRejectionBar *mRejections[]; // Holds Founded Rejection Bars ...
|
|
XCRejectionBar *mBullishRejections[]; // Holds Founded Bullish Rejection Bars ...
|
|
XCRejectionBar *mBearishRejections[]; // Holds Founded Bearish Rejection Bars ...
|
|
bool mRejectionForceBarType; // Rejection Detecting Force Bar Type ...
|
|
bool mRejectionForceFiboPressure; // Rejection Detecting Force Fibo Pressure ...
|
|
|
|
//
|
|
// Consolidation Zones ...
|
|
XConsolidationZone mConsolidationZones[]; // Holds Founded Consolidation Zones ...
|
|
XConsolidationZone mBullishConsolidationZones[]; // Holds Founded Bullish Consolidation Zones ...
|
|
XConsolidationZone mBearishConsolidationZones[]; // Holds Founded Bearish Consolidation Zones ...
|
|
int mConsolidationZoneMinLoopback; // Minimum Length of Cnsolidation Zone ...
|
|
double mConsolidationZoneRangeInPoint; // Consolidation Zone Range in Point ...
|
|
ENUM_X_PRICE mConsolidationZonesLowerAppliedTo; // Consolidation Zone Upper Applied To ...
|
|
ENUM_X_PRICE mConsolidationZonesUpperAppliedTo; // Consolidation Zone Lower Applied To ...
|
|
|
|
//
|
|
// Spike/Sharp Zones ...
|
|
XBoxZone mSharps[]; // Holds Founded Sharps ...
|
|
XBoxZone mBullishSharps[]; // Holds Founded Bullish Sharps ...
|
|
XBoxZone mBearishSharps[]; // Holds Founded Bearish Sharps ...
|
|
XBoxZone mSpikes[]; // Holds Founded Spikes ...
|
|
XBoxZone mBullishSpikes[]; // Holds Founded Bullish Spikes ...
|
|
XBoxZone mBearishSpikes[]; // Holds Founded Bearish Spikes ...
|
|
ENUM_X_PRICE mSpikePriceType; // Spike Detection Price Type ...
|
|
bool mSpikeForcBodyInRange; // Spike Detection Force Body In Range ...
|
|
double mSpikeRangeExtendMultiplier; // Spike Detection Range Extends Multiplier ...
|
|
int mSpikeSameBars; // Spike Detection Same Bars ...
|
|
|
|
//
|
|
// Support and Resistance ...
|
|
// Supply and Demand ...
|
|
|
|
//
|
|
int mSupResRange; // Support and Resistance Detection Range ...
|
|
bool mSupResRangeAsStart; // use Support and Resistance Range as Start ...
|
|
bool mSupResForceActivation; // Force Activations in Supply/Demand and Support/Resistance Detections ...
|
|
|
|
//
|
|
XCSupplyZone *mSupplyZones[]; // Holds Detected Supply Zones ...
|
|
XCDemandZone *mDemandZones[]; // Holds Detected Demand Zones ...
|
|
|
|
//
|
|
XCSupportZone *mSupportZones[]; // Holds Detected Support Zones ...
|
|
XCResistanceZone *mResistanceZones[]; // Holds Detected Resistance Zones ...
|
|
|
|
//
|
|
// Fair Value Gaps ...
|
|
XCFVG *mFairValueGaps[]; // Holds Founded FairValueGaps ...
|
|
XCFVG *mBullishFairValueGaps[]; // Holds Founded Bullish FairValueGaps ...
|
|
XCFVG *mBearishFairValueGaps[]; // Holds Founded Bearish FairValueGaps ...
|
|
int mFairValueGapSameBars; // FairValueGap Detection Same Bars ...
|
|
bool mFairValueGapForceActivation; // FairValueGap Detection Force Check Activation ...
|
|
|
|
//
|
|
// Order Blocks ...
|
|
XCOrderBlock *mOrderBlocks[]; // Holds Founded OrderBlocks ...
|
|
XCOrderBlock *mBullishOrderBlocks[]; // Holds Founded Bullish OrderBlocks ...
|
|
XCOrderBlock *mBearishOrderBlocks[]; // Holds Founded Bearish OrderBlocks ...
|
|
int mOrderBlockSameBars; // OrderBlock Detection Same Bars ...
|
|
bool mOrderBlockForceSpike; // Order Blocs Detection Force Spike ...
|
|
bool mOrderBlockForceFairValueGap; // Order Blocs Detection Force Fair Value Gaps ...
|
|
bool mOrderBlockForceSupportResistance; // Order Blocs Detection Force Support/Resisatnce ...
|
|
bool mOrderBlockForceActivation; // Order Blocs Detection Force Check Activation ...
|
|
|
|
/**
|
|
* Clean All Collections ...
|
|
*/
|
|
void CleanCollections()
|
|
{
|
|
//
|
|
Clean(mSwings);
|
|
Clean(mSwingLows);
|
|
Clean(mSwingHighs);
|
|
Clean(mMomentums);
|
|
Clean(mBullishMomentums);
|
|
Clean(mBearishMomentums);
|
|
Clean(mRejections);
|
|
Clean(mBullishRejections);
|
|
Clean(mBearishRejections);
|
|
Clean(mConsolidationZones);
|
|
Clean(mBullishConsolidationZones);
|
|
Clean(mBearishConsolidationZones);
|
|
Clean(mSpikes);
|
|
Clean(mBullishSpikes);
|
|
Clean(mBearishSpikes);
|
|
Clean(mSupplyZones);
|
|
Clean(mDemandZones);
|
|
Clean(mSupportZones);
|
|
Clean(mResistanceZones);
|
|
Clean(mFairValueGaps);
|
|
Clean(mBullishFairValueGaps);
|
|
Clean(mBearishFairValueGaps);
|
|
Clean(mOrderBlocks);
|
|
Clean(mBullishOrderBlocks);
|
|
Clean(mBearishOrderBlocks);
|
|
}
|
|
|
|
/**
|
|
* Reverse Collections ...
|
|
*/
|
|
void ReverseCollections()
|
|
{
|
|
//
|
|
ArrayReverse(mSwings);
|
|
ArrayReverse(mSwingLows);
|
|
ArrayReverse(mSwingHighs);
|
|
ArrayReverse(mMomentums);
|
|
ArrayReverse(mBullishMomentums);
|
|
ArrayReverse(mBearishMomentums);
|
|
ArrayReverse(mRejections);
|
|
ArrayReverse(mBullishRejections);
|
|
ArrayReverse(mBearishRejections);
|
|
ArrayReverse(mConsolidationZones);
|
|
ArrayReverse(mBullishConsolidationZones);
|
|
ArrayReverse(mBearishConsolidationZones);
|
|
ArrayReverse(mSpikes);
|
|
ArrayReverse(mBullishSpikes);
|
|
ArrayReverse(mBearishSpikes);
|
|
ArrayReverse(mSupplyZones);
|
|
ArrayReverse(mDemandZones);
|
|
ArrayReverse(mSupportZones);
|
|
ArrayReverse(mResistanceZones);
|
|
ArrayReverse(mFairValueGaps);
|
|
ArrayReverse(mBullishFairValueGaps);
|
|
ArrayReverse(mBearishFairValueGaps);
|
|
ArrayReverse(mOrderBlocks);
|
|
ArrayReverse(mBullishOrderBlocks);
|
|
ArrayReverse(mBearishOrderBlocks);
|
|
}
|
|
|
|
/**
|
|
* Cleanup Unused Collection Items ...
|
|
*
|
|
* @param maxAllowed: int, Max Allowed ...
|
|
*/
|
|
void CleanupUnusedCollections(
|
|
int maxAllowed = 0 //
|
|
)
|
|
{
|
|
//
|
|
maxAllowed = MaxRequiredPOIs();
|
|
|
|
//
|
|
if (maxAllowed <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
CleanupArray(mSwings, maxAllowed);
|
|
CleanupArray(mSwingLows, maxAllowed);
|
|
CleanupArray(mSwingHighs, maxAllowed);
|
|
CleanupArray(mMomentums, maxAllowed);
|
|
CleanupArray(mBullishMomentums, maxAllowed);
|
|
CleanupArray(mBearishMomentums, maxAllowed);
|
|
CleanupArray(mRejections, maxAllowed);
|
|
CleanupArray(mBullishRejections, maxAllowed);
|
|
CleanupArray(mBearishRejections, maxAllowed);
|
|
CleanupArray(mConsolidationZones, maxAllowed);
|
|
CleanupArray(mBullishConsolidationZones, maxAllowed);
|
|
CleanupArray(mBearishConsolidationZones, maxAllowed);
|
|
CleanupArray(mSpikes, maxAllowed);
|
|
CleanupArray(mBullishSpikes, maxAllowed);
|
|
CleanupArray(mBearishSpikes, maxAllowed);
|
|
CleanupArray(mSupplyZones, maxAllowed);
|
|
CleanupArray(mDemandZones, maxAllowed);
|
|
CleanupArray(mSupportZones, maxAllowed);
|
|
CleanupArray(mResistanceZones, maxAllowed);
|
|
CleanupArray(mFairValueGaps, maxAllowed);
|
|
CleanupArray(mBullishFairValueGaps, maxAllowed);
|
|
CleanupArray(mBearishFairValueGaps, maxAllowed);
|
|
CleanupArray(mOrderBlocks, maxAllowed);
|
|
CleanupArray(mBullishOrderBlocks, maxAllowed);
|
|
CleanupArray(mBearishOrderBlocks, maxAllowed);
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
// |