3334 lines
67 KiB
Plaintext
3334 lines
67 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"
|
|
|
|
//
|
|
#include <Arrays/ArrayObj.mqh>
|
|
|
|
//
|
|
// 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)
|
|
{
|
|
//
|
|
if (value < 1)
|
|
{
|
|
value = 1;
|
|
}
|
|
|
|
//
|
|
mSwingRange = value;
|
|
}
|
|
|
|
/**
|
|
* Get Momentum Bar Detection Extends Range ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int MomentumExtend()
|
|
{
|
|
return mMomentumExtend;
|
|
}
|
|
|
|
/**
|
|
* Set Momentum Bar Detection Extends Range ...
|
|
*
|
|
* @param value: int ...
|
|
*/
|
|
void MomentumExtend(int value)
|
|
{
|
|
//
|
|
if (value < 0)
|
|
{
|
|
value = 0;
|
|
}
|
|
|
|
//
|
|
mMomentumExtend = value;
|
|
}
|
|
|
|
/**
|
|
* Get Momentum Bar Detection Body Percent ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double MomentumBodyPercent()
|
|
{
|
|
return mMomentumBodyPercent;
|
|
}
|
|
|
|
/**
|
|
* Set Momentum Bar Detection Body Percent ...
|
|
*
|
|
* @param value: double ...
|
|
*/
|
|
void MomentumBodyPercent(double value)
|
|
{
|
|
//
|
|
if (value < 50)
|
|
{
|
|
value = 50;
|
|
}
|
|
|
|
//
|
|
if (value > 100)
|
|
{
|
|
value = 100;
|
|
}
|
|
|
|
//
|
|
mMomentumBodyPercent = value;
|
|
}
|
|
|
|
/**
|
|
* Get Rejection Bar Detection Extends Range ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int RejectionExtend()
|
|
{
|
|
return mRejectionExtend;
|
|
}
|
|
|
|
/**
|
|
* Set Rejection Bar Detection Extends Range ...
|
|
*
|
|
* @param value: int ...
|
|
*/
|
|
void RejectionExtend(int value)
|
|
{
|
|
//
|
|
if (value < 0)
|
|
{
|
|
value = 0;
|
|
}
|
|
|
|
//
|
|
mRejectionExtend = value;
|
|
}
|
|
|
|
/**
|
|
* Get Rejection Bar Detection Shadow Percent ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double RejectionShadowPercent()
|
|
{
|
|
return mRejectionShadowPercent;
|
|
}
|
|
|
|
/**
|
|
* Set Rejection Bar Detection Shadow Percent ...
|
|
*
|
|
* @param value: double ...
|
|
*/
|
|
void RejectionShadowPercent(double value)
|
|
{
|
|
//
|
|
if (value < 50)
|
|
{
|
|
value = 50;
|
|
}
|
|
|
|
//
|
|
if (value > 100)
|
|
{
|
|
value = 100;
|
|
}
|
|
|
|
//
|
|
mRejectionShadowPercent = 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)
|
|
{
|
|
//
|
|
if (value < 0)
|
|
{
|
|
value = 0;
|
|
}
|
|
|
|
//
|
|
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 OrderBlock Detection Same Bars ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int OrderBlockSameBars()
|
|
{
|
|
return mOrderBlockSameBars;
|
|
}
|
|
|
|
/**
|
|
* Set OrderBlock Detection Same Bars ...
|
|
*
|
|
* @param value: int ...
|
|
*/
|
|
void OrderBlockSameBars(int value)
|
|
{
|
|
//
|
|
if (value < 2)
|
|
{
|
|
value = 2;
|
|
}
|
|
|
|
//
|
|
mOrderBlockSameBars = value;
|
|
}
|
|
|
|
/**
|
|
* Get FairValueGap Detection Same Bars ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int FairValueGapSameBars()
|
|
{
|
|
return mFairValueGapSameBars;
|
|
}
|
|
|
|
/**
|
|
* Set FairValueGap Detection Same Bars ...
|
|
*
|
|
* @param value: int ...
|
|
*/
|
|
void FairValueGapSameBars(int value)
|
|
{
|
|
//
|
|
if (value < 2)
|
|
{
|
|
value = 2;
|
|
}
|
|
|
|
//
|
|
mFairValueGapSameBars = 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)
|
|
{
|
|
//
|
|
if (value < 1)
|
|
{
|
|
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)
|
|
{
|
|
//
|
|
if (value < 50)
|
|
{
|
|
value = 50;
|
|
}
|
|
|
|
//
|
|
mConsolidationZoneRangeInPoint = value;
|
|
}
|
|
|
|
/**
|
|
* Get Consolidation Zone Upper Applied To ...
|
|
*
|
|
* @return ( ENUM_APPLIED_PRICE )
|
|
*/
|
|
ENUM_APPLIED_PRICE ConsolidationZonesLowerAppliedTo()
|
|
{
|
|
return mConsolidationZonesLowerAppliedTo;
|
|
}
|
|
|
|
/**
|
|
* Set Consolidation Zone Upper Applied To ...
|
|
*
|
|
* @param value: ENUM_APPLIED_PRICE
|
|
*/
|
|
void ConsolidationZonesLowerAppliedTo(ENUM_APPLIED_PRICE value = PRICE_LOW)
|
|
{
|
|
mConsolidationZonesLowerAppliedTo = value;
|
|
}
|
|
|
|
/**
|
|
* Get Consolidation Zone Lower Applied To ...
|
|
*
|
|
* @return ( ENUM_APPLIED_PRICE )
|
|
*/
|
|
ENUM_APPLIED_PRICE ConsolidationZonesUpperAppliedTo()
|
|
{
|
|
return mConsolidationZonesUpperAppliedTo;
|
|
}
|
|
|
|
/**
|
|
* Set Consolidation Zone Lower Applied To ...
|
|
*
|
|
* @param value: ENUM_APPLIED_PRICE
|
|
*/
|
|
void ConsolidationZonesUpperAppliedTo(ENUM_APPLIED_PRICE value = PRICE_HIGH)
|
|
{
|
|
mConsolidationZonesUpperAppliedTo = value;
|
|
}
|
|
|
|
//
|
|
// Actions ...
|
|
|
|
/**
|
|
* Apply Default Configurations ...
|
|
*/
|
|
virtual void Default()
|
|
{
|
|
//
|
|
// Default Props ...
|
|
SwingRange(3);
|
|
SupResRange(21);
|
|
MomentumExtend(1);
|
|
RejectionExtend(1);
|
|
MaxRequiredPOIs(100);
|
|
OrderBlockSameBars(3);
|
|
FairValueGapSameBars(3);
|
|
MomentumBodyPercent(70);
|
|
SupResRangeAsStart(true);
|
|
RejectionShadowPercent(70);
|
|
MaxAllowedLoopbackForInit(578);
|
|
ConsolidationZoneMinLoopback(5);
|
|
ConsolidationZoneRangeInPoint(50);
|
|
ConsolidationZonesLowerAppliedTo(PRICE_LOW);
|
|
ConsolidationZonesUpperAppliedTo(PRICE_HIGH);
|
|
}
|
|
|
|
/**
|
|
* 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,
|
|
false //
|
|
);
|
|
|
|
//
|
|
// Rejection Bar ...
|
|
DetectRejectionBar(
|
|
iBar,
|
|
iEvent,
|
|
false //
|
|
);
|
|
//
|
|
// Momentum Bar ...
|
|
DetectMomentumBar(
|
|
iBar,
|
|
iEvent,
|
|
false //
|
|
);
|
|
|
|
//
|
|
// Support ...
|
|
DetectSupportZone(
|
|
iBar,
|
|
iEvent,
|
|
false //
|
|
);
|
|
|
|
//
|
|
// Demand ...
|
|
DetectDemandZone(
|
|
iBar,
|
|
iEvent,
|
|
false //
|
|
);
|
|
|
|
//
|
|
// Resistance ...
|
|
DetectResistanceZone(
|
|
iBar,
|
|
iEvent,
|
|
false //
|
|
);
|
|
|
|
//
|
|
// Supply ...
|
|
DetectSupplyZone(
|
|
iBar,
|
|
iEvent,
|
|
false //
|
|
);
|
|
|
|
//
|
|
// OrderBlock ...
|
|
DetectOrderBlock(
|
|
iBar,
|
|
iEvent,
|
|
false //
|
|
);
|
|
|
|
//
|
|
// FairValueGap ...
|
|
DetectFairValueGap(
|
|
iBar,
|
|
iEvent,
|
|
false //
|
|
);
|
|
|
|
//
|
|
// Consolidation Zone ...
|
|
DetectConsolidationZone(
|
|
iBar,
|
|
iEvent,
|
|
false //
|
|
);
|
|
|
|
//
|
|
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 //
|
|
);
|
|
|
|
//
|
|
XCBasePOI *item = NULL;
|
|
XCSwing *iSwing = NULL;
|
|
if (iEvent == X_SWING_LOW_DETECTED)
|
|
{
|
|
//
|
|
has = GetLastItem(
|
|
iSwing,
|
|
mSwingLows //
|
|
);
|
|
}
|
|
else if (iEvent == X_SWING_HIGH_DETECTED)
|
|
{
|
|
//
|
|
has = GetLastItem(
|
|
iSwing,
|
|
mSwingHighs //
|
|
);
|
|
}
|
|
if (has)
|
|
{
|
|
item = (XCBasePOI *)iSwing;
|
|
}
|
|
|
|
//
|
|
has = item != NULL;
|
|
if (has)
|
|
{
|
|
//
|
|
NotifyEventListeners(
|
|
iEvent,
|
|
item //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Momentum Bar ...
|
|
has = DetectMomentumBar(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
|
|
//
|
|
XCBasePOI *item = NULL;
|
|
XCMomentumBar *iMomentum = NULL;
|
|
if (iEvent == X_BULLISH_MOMENTUM_BAR_DETECTED)
|
|
{
|
|
//
|
|
has = GetLastItem(
|
|
iMomentum,
|
|
mBullishMomentumBars //
|
|
);
|
|
}
|
|
else if (iEvent == X_BEARISH_MOMENTUM_BAR_DETECTED)
|
|
{
|
|
//
|
|
has = GetLastItem(
|
|
iMomentum,
|
|
mBearishMomentumBars //
|
|
);
|
|
}
|
|
if (has)
|
|
{
|
|
item = (XCBasePOI *)iMomentum;
|
|
}
|
|
|
|
//
|
|
has = item != NULL;
|
|
if (has)
|
|
{
|
|
//
|
|
NotifyEventListeners(
|
|
iEvent,
|
|
item //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Rejection Bar ...
|
|
has = DetectRejectionBar(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
|
|
//
|
|
XCBasePOI *item = NULL;
|
|
XCRejectionBar *iRejection = NULL;
|
|
if (iEvent == X_BULLISH_REJECTION_BAR_DETECTED)
|
|
{
|
|
//
|
|
has = GetLastItem(
|
|
iRejection,
|
|
mBullishRejectionBars //
|
|
);
|
|
}
|
|
else if (iEvent == X_BEARISH_REJECTION_BAR_DETECTED)
|
|
{
|
|
//
|
|
has = GetLastItem(
|
|
iRejection,
|
|
mBearishRejectionBars //
|
|
);
|
|
}
|
|
if (has)
|
|
{
|
|
item = (XCBasePOI *)iRejection;
|
|
}
|
|
|
|
//
|
|
has = item != NULL;
|
|
if (has)
|
|
{
|
|
//
|
|
NotifyEventListeners(
|
|
iEvent,
|
|
item //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Support ...
|
|
has = DetectSupportZone(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
|
|
//
|
|
XCBasePOI *item = NULL;
|
|
XCSupportZone *iZone = NULL;
|
|
has = GetLastItem(
|
|
iZone,
|
|
mSupportZones //
|
|
);
|
|
if (has)
|
|
{
|
|
item = (XCBasePOI *)iZone;
|
|
}
|
|
|
|
//
|
|
has = item != NULL;
|
|
if (has)
|
|
{
|
|
//
|
|
NotifyEventListeners(
|
|
iEvent,
|
|
item //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Demand ...
|
|
has = DetectDemandZone(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
|
|
//
|
|
XCBasePOI *item = NULL;
|
|
XCDemandZone *iZone = NULL;
|
|
has = GetLastItem(
|
|
iZone,
|
|
mDemandZones //
|
|
);
|
|
if (has)
|
|
{
|
|
item = (XCBasePOI *)iZone;
|
|
}
|
|
|
|
//
|
|
has = item != NULL;
|
|
if (has)
|
|
{
|
|
//
|
|
NotifyEventListeners(
|
|
iEvent,
|
|
item //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Resistance ...
|
|
has = DetectResistanceZone(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
|
|
//
|
|
XCBasePOI *item = NULL;
|
|
XCResistanceZone *iZone = NULL;
|
|
has = GetLastItem(
|
|
iZone,
|
|
mResistanceZones //
|
|
);
|
|
if (has)
|
|
{
|
|
item = (XCBasePOI *)iZone;
|
|
}
|
|
|
|
//
|
|
has = item != NULL;
|
|
if (has)
|
|
{
|
|
//
|
|
NotifyEventListeners(
|
|
iEvent,
|
|
item //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Supply ...
|
|
has = DetectSupplyZone(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
|
|
//
|
|
XCBasePOI *item = NULL;
|
|
XCSupplyZone *iZone = NULL;
|
|
has = GetLastItem(
|
|
iZone,
|
|
mSupplyZones //
|
|
);
|
|
if (has)
|
|
{
|
|
item = (XCBasePOI *)iZone;
|
|
}
|
|
|
|
//
|
|
has = item != NULL;
|
|
if (has)
|
|
{
|
|
//
|
|
NotifyEventListeners(
|
|
iEvent,
|
|
item //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// OrderBlock ...
|
|
has = DetectOrderBlock(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
|
|
//
|
|
XCBasePOI *item = NULL;
|
|
XCOrderBlock *iZone = NULL;
|
|
if (iEvent == X_BULLISH_ORDERBLOCK_DETECTED)
|
|
{
|
|
//
|
|
has = GetLastItem(
|
|
iZone,
|
|
mBullishOrderBlocks //
|
|
);
|
|
}
|
|
else if (iEvent == X_BEARISH_ORDERBLOCK_DETECTED)
|
|
{
|
|
//
|
|
has = GetLastItem(
|
|
iZone,
|
|
mBearishOrderBlocks //
|
|
);
|
|
}
|
|
if (has)
|
|
{
|
|
item = (XCBasePOI *)iZone;
|
|
}
|
|
|
|
//
|
|
has = item != NULL;
|
|
if (has)
|
|
{
|
|
//
|
|
NotifyEventListeners(
|
|
iEvent,
|
|
item //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// FairValueGap ...
|
|
has = DetectFairValueGap(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
|
|
//
|
|
XCBasePOI *item = NULL;
|
|
XCFVG *iZone = NULL;
|
|
if (iEvent == X_BULLISH_FVG_DETECTED)
|
|
{
|
|
//
|
|
has = GetLastItem(
|
|
iZone,
|
|
mBullishFairValueGaps //
|
|
);
|
|
}
|
|
else if (iEvent == X_BEARISH_FVG_DETECTED)
|
|
{
|
|
//
|
|
has = GetLastItem(
|
|
iZone,
|
|
mBearishFairValueGaps //
|
|
);
|
|
}
|
|
if (has)
|
|
{
|
|
item = (XCBasePOI *)iZone;
|
|
}
|
|
|
|
//
|
|
has = item != NULL;
|
|
if (has)
|
|
{
|
|
//
|
|
NotifyEventListeners(
|
|
iEvent,
|
|
item //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
has = DetectConsolidationZone(
|
|
iBar,
|
|
iEvent //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
iEvent,
|
|
events //
|
|
);
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
mLock = false;
|
|
// mBarTracker.Waits();
|
|
|
|
//
|
|
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();
|
|
|
|
//
|
|
Copy(
|
|
mSwings,
|
|
state.swings //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mSwingHighs,
|
|
state.swingHighs //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mSwingLows,
|
|
state.swingLows //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mMomentumBars,
|
|
state.momentumBars //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBullishMomentumBars,
|
|
state.bullishMomentumBars //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBearishMomentumBars,
|
|
state.bearishMomentumBars //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mRejectionBars,
|
|
state.rejectionBars //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBullishRejectionBars,
|
|
state.bullishRejectionBars //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBearishRejectionBars,
|
|
state.bearishRejectionBars //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mSupportZones,
|
|
state.supportZones //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mResistanceZones,
|
|
state.resistanceZones //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mSupplyZones,
|
|
state.supplyZones //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mDemandZones,
|
|
state.demandZones //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mOrderBlocks,
|
|
state.orderBlocks //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBullishOrderBlocks,
|
|
state.bullishOrderBlocks //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBearishOrderBlocks,
|
|
state.bearishOrderBlocks //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mFairValueGaps,
|
|
state.fairValueGaps //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBullishFairValueGaps,
|
|
state.bullishFairValueGaps //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBearishFairValueGaps,
|
|
state.bearishFairValueGaps //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mConsolidationZones,
|
|
state.consolidationZones //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBullishConsolidationZones,
|
|
state.bullishConsolidationZones //
|
|
);
|
|
|
|
//
|
|
Copy(
|
|
mBearishConsolidationZones,
|
|
state.bearishConsolidationZones //
|
|
);
|
|
|
|
//
|
|
}
|
|
|
|
/**
|
|
* Destroy Instance ...
|
|
*/
|
|
void Destroy()
|
|
{
|
|
//
|
|
mBarTracker.Clean();
|
|
ZeroMemory(mBarAnalyser);
|
|
|
|
//
|
|
CleanCollections();
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
|
|
/**
|
|
* Detect Swing Bars ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param reversal: boolean reversal add to collection ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectSwing(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state,
|
|
bool reversal = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
state = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION iDir;
|
|
result = mBarAnalyser.IsSwing(
|
|
bar,
|
|
iDir,
|
|
mSwingRange //
|
|
);
|
|
|
|
//
|
|
result = result &&
|
|
HasDirection(iDir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(iDir);
|
|
bool isBearish = IsBearish(iDir);
|
|
|
|
//
|
|
ENUM_XPOIS type =
|
|
isBullish
|
|
? X_POI_SWING_LOW
|
|
: X_POI_SWING_HIGH;
|
|
|
|
//
|
|
// Swing Object ...
|
|
XCSwing *swing;
|
|
swing = new XCSwing();
|
|
result = swing.Init(
|
|
bar,
|
|
type //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Add ...
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
swing,
|
|
mSwings //
|
|
);
|
|
result = !IsValidIndex(idx);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mSwings);
|
|
|
|
//
|
|
Add(
|
|
swing,
|
|
mSwings //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mSwings);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
swing,
|
|
mSwings //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
// Add Swings ...
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mSwings);
|
|
|
|
//
|
|
Add(
|
|
swing,
|
|
mSwings //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mSwings);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
swing,
|
|
mSwingLows //
|
|
);
|
|
}
|
|
}
|
|
else if (isBearish)
|
|
{
|
|
//
|
|
// Add Swings ...
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mSwingHighs);
|
|
|
|
//
|
|
Add(
|
|
swing,
|
|
mSwingHighs //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mSwingHighs);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
swing,
|
|
mSwingHighs //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
state =
|
|
isBullish
|
|
? X_SWING_LOW_DETECTED
|
|
: X_SWING_HIGH_DETECTED;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Momentum Bars ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param reversal: boolean reversal add to collection ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectMomentumBar(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state,
|
|
bool reversal = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
state = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION iDir;
|
|
result = mBarAnalyser.IsMomentumBar(
|
|
bar,
|
|
iDir,
|
|
mMomentumExtend, // Extends ...
|
|
mMomentumBodyPercent // Body Percent ...
|
|
);
|
|
|
|
//
|
|
result = result &&
|
|
HasDirection(iDir);
|
|
if (!result)
|
|
{
|
|
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(
|
|
bar //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
momentum,
|
|
mMomentumBars //
|
|
);
|
|
result = !IsValidIndex(idx);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Add ...
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mMomentumBars);
|
|
|
|
//
|
|
Add(
|
|
momentum,
|
|
mMomentumBars //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mMomentumBars);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
momentum,
|
|
mMomentumBars //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
// Add Swings ...
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mBullishMomentumBars);
|
|
|
|
//
|
|
Add(
|
|
momentum,
|
|
mBullishMomentumBars //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mBullishMomentumBars);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
momentum,
|
|
mBullishMomentumBars //
|
|
);
|
|
}
|
|
}
|
|
else if (isBearish)
|
|
{
|
|
//
|
|
// Add Swings ...
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mBearishMomentumBars);
|
|
|
|
//
|
|
Add(
|
|
momentum,
|
|
mBearishMomentumBars //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mBearishMomentumBars);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
momentum,
|
|
mBearishMomentumBars //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
state =
|
|
isBullish
|
|
? X_BULLISH_MOMENTUM_BAR_DETECTED
|
|
: X_BEARISH_MOMENTUM_BAR_DETECTED;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Rejection Bars ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param reversal: boolean reversal add to collection ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectRejectionBar(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state,
|
|
bool reversal = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
state = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION iDir;
|
|
result = mBarAnalyser.IsRejectionBar(
|
|
bar,
|
|
iDir,
|
|
mRejectionExtend, // Extends ...
|
|
mRejectionShadowPercent // Shadow Percent ...
|
|
);
|
|
|
|
//
|
|
result = result &&
|
|
HasDirection(iDir);
|
|
if (!result)
|
|
{
|
|
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(
|
|
bar //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
rejection,
|
|
mRejectionBars //
|
|
);
|
|
result = !IsValidIndex(idx);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Add ...
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mRejectionBars);
|
|
|
|
//
|
|
Add(
|
|
rejection,
|
|
mRejectionBars //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mRejectionBars);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
rejection,
|
|
mRejectionBars //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
// Add Swings ...
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mBullishRejectionBars);
|
|
|
|
//
|
|
Add(
|
|
rejection,
|
|
mBullishRejectionBars //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mBullishRejectionBars);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
rejection,
|
|
mBullishRejectionBars //
|
|
);
|
|
}
|
|
}
|
|
else if (isBearish)
|
|
{
|
|
//
|
|
// Add Swings ...
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mBearishRejectionBars);
|
|
|
|
//
|
|
Add(
|
|
rejection,
|
|
mBearishRejectionBars //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mBearishRejectionBars);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
rejection,
|
|
mBearishRejectionBars //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
state =
|
|
isBullish
|
|
? X_BULLISH_REJECTION_BAR_DETECTED
|
|
: X_BEARISH_REJECTION_BAR_DETECTED;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Support Zone ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param reversal: boolean reversal add to collection ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectSupportZone(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state,
|
|
bool reversal = false,
|
|
bool forceActivation = false //
|
|
)
|
|
{
|
|
//
|
|
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 (forceActivation)
|
|
{
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mSupportZones);
|
|
|
|
//
|
|
Add(
|
|
supportZone,
|
|
mSupportZones //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mSupportZones);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
supportZone,
|
|
mSupportZones //
|
|
);
|
|
}
|
|
|
|
//
|
|
state = X_SUPPORT_ZONE_DETECTED;
|
|
|
|
//
|
|
supportBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Resistance Zone ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param reversal: boolean reversal add to collection ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectResistanceZone(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state,
|
|
bool reversal = false,
|
|
bool forceActivation = false //
|
|
)
|
|
{
|
|
//
|
|
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 (forceActivation)
|
|
{
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mResistanceZones);
|
|
|
|
//
|
|
Add(
|
|
resistanceZone,
|
|
mResistanceZones //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mResistanceZones);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
resistanceZone,
|
|
mResistanceZones //
|
|
);
|
|
}
|
|
|
|
//
|
|
state = X_RESISTANCE_ZONE_DETECTED;
|
|
|
|
//
|
|
resistanceBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Supply Zone ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param reversal: boolean reversal add to collection ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectSupplyZone(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state,
|
|
bool reversal = false,
|
|
bool forceActivation = false //
|
|
)
|
|
{
|
|
//
|
|
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 (forceActivation)
|
|
{
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mSupplyZones);
|
|
|
|
//
|
|
Add(
|
|
supplyZone,
|
|
mSupplyZones //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mSupplyZones);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
supplyZone,
|
|
mSupplyZones //
|
|
);
|
|
}
|
|
|
|
//
|
|
state = X_SUPPLY_ZONE_DETECTED;
|
|
|
|
//
|
|
supplyBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Demand Zone ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param reversal: boolean reversal add to collection ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectDemandZone(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state,
|
|
bool reversal = false,
|
|
bool forceActivation = false //
|
|
)
|
|
{
|
|
//
|
|
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 (forceActivation)
|
|
{
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mDemandZones);
|
|
|
|
//
|
|
Add(
|
|
demandZone,
|
|
mDemandZones //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mDemandZones);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
demandZone,
|
|
mDemandZones //
|
|
);
|
|
}
|
|
|
|
//
|
|
state = X_DEMAND_ZONE_DETECTED;
|
|
|
|
//
|
|
demandBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Order Blocks ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param reversal: boolean reversal add to collection ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectOrderBlock(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state,
|
|
bool reversal = false,
|
|
bool forceActivation = false //
|
|
)
|
|
{
|
|
//
|
|
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 //
|
|
);
|
|
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 (forceActivation)
|
|
{
|
|
//
|
|
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 ...
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mOrderBlocks);
|
|
|
|
//
|
|
Add(
|
|
ob,
|
|
mOrderBlocks //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mOrderBlocks);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
ob,
|
|
mOrderBlocks //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
// Add Swings ...
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mBullishOrderBlocks);
|
|
|
|
//
|
|
Add(
|
|
ob,
|
|
mBullishOrderBlocks //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mBullishOrderBlocks);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
ob,
|
|
mBullishOrderBlocks //
|
|
);
|
|
}
|
|
}
|
|
else if (isBearish)
|
|
{
|
|
//
|
|
// Add Swings ...
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mBearishOrderBlocks);
|
|
|
|
//
|
|
Add(
|
|
ob,
|
|
mBearishOrderBlocks //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mBearishOrderBlocks);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
ob,
|
|
mBearishOrderBlocks //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
state =
|
|
isBullish
|
|
? X_BULLISH_ORDERBLOCK_DETECTED
|
|
: X_BEARISH_ORDERBLOCK_DETECTED;
|
|
|
|
//
|
|
obBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Fair Value Gaps ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param reversal: boolean reversal add to collection ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectFairValueGap(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state,
|
|
bool reversal = false,
|
|
bool forceActivation = false //
|
|
)
|
|
{
|
|
//
|
|
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 (forceActivation)
|
|
{
|
|
//
|
|
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 ...
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mFairValueGaps);
|
|
|
|
//
|
|
Add(
|
|
fvg,
|
|
mFairValueGaps //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mFairValueGaps);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
fvg,
|
|
mFairValueGaps //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
// Add Swings ...
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mBullishFairValueGaps);
|
|
|
|
//
|
|
Add(
|
|
fvg,
|
|
mBullishFairValueGaps //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mBullishFairValueGaps);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
fvg,
|
|
mBullishFairValueGaps //
|
|
);
|
|
}
|
|
}
|
|
else if (isBearish)
|
|
{
|
|
//
|
|
// Add Swings ...
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mBearishFairValueGaps);
|
|
|
|
//
|
|
Add(
|
|
fvg,
|
|
mBearishFairValueGaps //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mBearishFairValueGaps);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
Add(
|
|
fvg,
|
|
mBearishFairValueGaps //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
state =
|
|
isBullish
|
|
? X_BULLISH_FVG_DETECTED
|
|
: X_BEARISH_FVG_DETECTED;
|
|
|
|
//
|
|
fvgEndBar.Clean();
|
|
fvgStartBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Consolidation Zones ...
|
|
*
|
|
* @param bar: XOHCL instance ...
|
|
* @param reversal: boolean reversal add to collection ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectConsolidationZone(
|
|
XOHCL &bar,
|
|
ENUM_XPOI_EVENTS &state,
|
|
bool reversal = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
state = X_POI_EVENT_NONE;
|
|
|
|
//
|
|
XConsolidationZone cZone;
|
|
result = mBarAnalyser.HasConsolidationZone(
|
|
bar,
|
|
cZone,
|
|
mConsolidationZoneMinLoopback,
|
|
mConsolidationZoneRangeInPoint,
|
|
mConsolidationZonesUpperAppliedTo,
|
|
mConsolidationZonesLowerAppliedTo //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
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)
|
|
{
|
|
//
|
|
cZone.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mConsolidationZones);
|
|
|
|
//
|
|
AddRef(
|
|
cZone,
|
|
mConsolidationZones //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mConsolidationZones);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
AddRef(
|
|
cZone,
|
|
mConsolidationZones //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
// Add Swings ...
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mBullishConsolidationZones);
|
|
|
|
//
|
|
AddRef(
|
|
cZone,
|
|
mBullishConsolidationZones //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mBullishConsolidationZones);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
AddRef(
|
|
cZone,
|
|
mBullishConsolidationZones //
|
|
);
|
|
}
|
|
}
|
|
else if (isBearish)
|
|
{
|
|
//
|
|
// Add Swings ...
|
|
if (reversal)
|
|
{
|
|
//
|
|
ArrayReverse(mBearishConsolidationZones);
|
|
|
|
//
|
|
AddRef(
|
|
cZone,
|
|
mBearishConsolidationZones //
|
|
);
|
|
|
|
//
|
|
ArrayReverse(mBearishConsolidationZones);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
AddRef(
|
|
cZone,
|
|
mBearishConsolidationZones //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
state =
|
|
IsBullish(cZone.dir)
|
|
? X_BULLISH_CONSOLIDATION_ZONE_DETECTED
|
|
: X_BEARISH_CONSOLIDATION_ZONE_DETECTED;
|
|
|
|
//
|
|
cZone.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
protected:
|
|
//
|
|
|
|
//
|
|
void CleanCollections()
|
|
{
|
|
//
|
|
Clean(mSwings);
|
|
Clean(mSwingLows);
|
|
Clean(mSwingHighs);
|
|
Clean(mDemandZones);
|
|
Clean(mSupplyZones);
|
|
Clean(mOrderBlocks);
|
|
Clean(mMomentumBars);
|
|
Clean(mSupportZones);
|
|
Clean(mRejectionBars);
|
|
Clean(mFairValueGaps);
|
|
Clean(mEventListeners);
|
|
Clean(mResistanceZones);
|
|
Clean(mBullishOrderBlocks);
|
|
Clean(mBearishOrderBlocks);
|
|
Clean(mConsolidationZones);
|
|
Clean(mBullishMomentumBars);
|
|
Clean(mBearishMomentumBars);
|
|
Clean(mBullishRejectionBars);
|
|
Clean(mBearishRejectionBars);
|
|
Clean(mBullishFairValueGaps);
|
|
Clean(mBearishFairValueGaps);
|
|
Clean(mBullishConsolidationZones);
|
|
Clean(mBearishConsolidationZones);
|
|
}
|
|
|
|
//
|
|
void ReverseCollections()
|
|
{
|
|
//
|
|
ArrayReverse(mSwings);
|
|
ArrayReverse(mSwingLows);
|
|
ArrayReverse(mSwingHighs);
|
|
ArrayReverse(mDemandZones);
|
|
ArrayReverse(mSupplyZones);
|
|
ArrayReverse(mOrderBlocks);
|
|
ArrayReverse(mMomentumBars);
|
|
ArrayReverse(mSupportZones);
|
|
ArrayReverse(mRejectionBars);
|
|
ArrayReverse(mFairValueGaps);
|
|
ArrayReverse(mEventListeners);
|
|
ArrayReverse(mResistanceZones);
|
|
ArrayReverse(mBullishOrderBlocks);
|
|
ArrayReverse(mBearishOrderBlocks);
|
|
ArrayReverse(mConsolidationZones);
|
|
ArrayReverse(mBullishMomentumBars);
|
|
ArrayReverse(mBearishMomentumBars);
|
|
ArrayReverse(mBullishRejectionBars);
|
|
ArrayReverse(mBearishRejectionBars);
|
|
ArrayReverse(mBullishFairValueGaps);
|
|
ArrayReverse(mBearishFairValueGaps);
|
|
ArrayReverse(mBullishConsolidationZones);
|
|
ArrayReverse(mBearishConsolidationZones);
|
|
}
|
|
|
|
//
|
|
void CleanupUnusedCollections(
|
|
int maxAllowed = 0 //
|
|
)
|
|
{
|
|
//
|
|
maxAllowed = MaxRequiredPOIs();
|
|
|
|
//
|
|
if (maxAllowed <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
CleanupArray(
|
|
mEventListeners,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mSwings,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mSwingLows,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mSwingHighs,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mMomentumBars,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mBullishMomentumBars,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mBearishMomentumBars,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mRejectionBars,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mBullishRejectionBars,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mBearishRejectionBars,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mSupportZones,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mDemandZones,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mSupplyZones,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mResistanceZones,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mFairValueGaps,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mBullishFairValueGaps,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mBearishFairValueGaps,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mOrderBlocks,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mBullishOrderBlocks,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mBearishOrderBlocks,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mConsolidationZones,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mBullishConsolidationZones,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
CleanupArray(
|
|
mBearishConsolidationZones,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
}
|
|
|
|
/**
|
|
* 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 ...
|
|
|
|
//
|
|
XCSwing *mSwings[]; // Holds Founded Swing ...
|
|
XCSwing *mSwingLows[]; // Holds Founded Swing Lows ...
|
|
XCSwing *mSwingHighs[]; // Holds Founded Swing Highs ...
|
|
int mSwingRange; // Swing Detection Range ...
|
|
|
|
//
|
|
XCMomentumBar *mMomentumBars[]; // Holds Founded Momentum Bars ...
|
|
XCMomentumBar *mBullishMomentumBars[]; // Holds Founded Bullish Momentum Bars ...
|
|
XCMomentumBar *mBearishMomentumBars[]; // Holds Founded Bearish Momentum Bars ...
|
|
int mMomentumExtend; // Momentum Bar Detection Extends Range ...
|
|
double mMomentumBodyPercent; // Momentum Bar Detection Body Percent ...
|
|
|
|
//
|
|
XCRejectionBar *mRejectionBars[]; // Holds Founded Rejection Bars ...
|
|
XCRejectionBar *mBullishRejectionBars[]; // Holds Founded Bullish Rejection Bars ...
|
|
XCRejectionBar *mBearishRejectionBars[]; // Holds Founded Bearish Rejection Bars ...
|
|
int mRejectionExtend; // Rejection Bar Detection Extends Range ...
|
|
double mRejectionShadowPercent; // Rejection Bar Detection Body Percent ...
|
|
|
|
//
|
|
XCSupplyZone *mSupplyZones[]; // Holds Detected Supply Zones ...
|
|
XCDemandZone *mDemandZones[]; // Holds Detected Demand Zones ...
|
|
|
|
//
|
|
int mSupResRange; // Support and Resistance Detection Range ...
|
|
bool mSupResRangeAsStart; // use Support and Resistance Range as Start ...
|
|
XCSupportZone *mSupportZones[]; // Holds Detected Support Zones ...
|
|
XCResistanceZone *mResistanceZones[]; // Holds Detected Resistance Zones ...
|
|
|
|
//
|
|
XCFVG *mFairValueGaps[]; // Holds Founded FairValueGaps ...
|
|
XCFVG *mBullishFairValueGaps[]; // Holds Founded Bullish FairValueGaps ...
|
|
XCFVG *mBearishFairValueGaps[]; // Holds Founded Bearish FairValueGaps ...
|
|
int mFairValueGapSameBars; // FairValueGap Detection Same Bars ...
|
|
|
|
//
|
|
XCOrderBlock *mOrderBlocks[]; // Holds Founded OrderBlocks ...
|
|
XCOrderBlock *mBullishOrderBlocks[]; // Holds Founded Bullish OrderBlocks ...
|
|
XCOrderBlock *mBearishOrderBlocks[]; // Holds Founded Bearish OrderBlocks ...
|
|
int mOrderBlockSameBars; // OrderBlock Detection Same Bars ...
|
|
|
|
//
|
|
int mConsolidationZoneMinLoopback; // Minimum Length of Cnsolidation Zone ...
|
|
double mConsolidationZoneRangeInPoint; // Consolidation Zone Range in Point ...
|
|
XConsolidationZone mConsolidationZones[]; // Holds Founded Consolidation Zones ...
|
|
XConsolidationZone mBullishConsolidationZones[]; // Holds Founded Bullish Consolidation Zones ...
|
|
XConsolidationZone mBearishConsolidationZones[]; // Holds Founded Bearish Consolidation Zones ...
|
|
ENUM_APPLIED_PRICE mConsolidationZonesLowerAppliedTo; // Consolidation Zone Upper Applied To ...
|
|
ENUM_APPLIED_PRICE mConsolidationZonesUpperAppliedTo; // Consolidation Zone Lower Applied To ...
|
|
|
|
//
|
|
};
|
|
|
|
// |