Files
MQL5Data/Libraries/x-saherelm.x-poi.lib.mq5
T
2025-01-26 20:10:44 +03:30

12277 lines
226 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Seriallize Library
// ---------------------------------------
// Name: XPOILib
// Description: All models related to POIs ...
//
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
//
// Global Properties ...
#property library
#property copyright "Copyright `023, SaherElm IT Center"
#property link "https://www.saherelm.ir"
#property version "1.00"
#property strict
//
// Imports ...
#include "../Classes/x-saherelm.base.class.mq5"
#include <Arrays/ArrayObj.mqh>
//
// Definitions ...
//
// Definitions ...
//
// All Available POI(s) ...
enum ENUM_XPOIS
{
//
X_POI_NONE,
//
X_POI_TICKS_ZONES, // Ticks Zone ...
//
// Trading Day ...
X_POI_TRADING_DAY, // Trading Day ...
//
// Market Session ...
X_POI_MARKET_SESSION, // Market Session ...
//
// Momentum Bar ...
X_POI_MOMENTUM_BAR, // Momentum Bar ...
//
// Rejection Bar ...
X_POI_REJECTION_BAR, // Rejection Bar ...
//
// Swings ...
X_POI_SWING_HIGH, // Simple Swing High ...
X_POI_SWING_LOW, // Simple Swing Low ...
//
// Support nad Resistance ...
X_POI_SUPPORT_ZONE, // Support Zone ...
X_POI_RESISTANCE_ZONE, // Resistance Zone ...
//
// Supply and Demand Zones ...
X_POI_SUPPLY_ZONE, // Supply Zone ...
X_POI_DEMAND_ZONE, // Demand Zone ...
//
// Order Blocks ...
X_POI_BULLISH_ORDERBLOCK, // Bullish Order Block ...
X_POI_BEARISH_ORDERBLOCK, // Bearish Order Block ...
//
// Fair Value Gaps ...
X_POI_BULLISH_FVG, // Bullish Order Block ...
X_POI_BEARISH_FVG, // Bearish Order Block ...
};
//
// Event Types ...
enum ENUM_XPOI_EVENTS
{
//
// Trading Days ...
X_TRADE_DAY_FIRST_BAR, // Trading Day First Bar ...
X_TRADE_DAY_LAST_BAR, // Trading Day Last Bar ...
//
// Session ...
X_SESSION_FIRST_BAR, // Session First Bar ...
X_SESSION_LAST_BAR, // Session Last Bar ...
//
// Momentum Bar ...
X_BULLISH_MOMENTUM_BAR_DETECTED,
X_BEARISH_MOMENTUM_BAR_DETECTED,
//
// Rejection Bar ...
X_BULLISH_REJECTION_BAR_DETECTED,
X_BEARISH_REJECTION_BAR_DETECTED,
//
// Swings ...
X_SWING_HIGH_DETECTED,
X_SWING_LOW_DETECTED,
//
// Support nad Resistance ...
X_SUPPORT_ZONE_DETECTED, // Support Zone ...
X_RESISTANCE_ZONE_DETECTED, // Resistance Zone ...
//
// Supply nad Demand ...
X_SUPPLY_ZONE_DETECTED, // Supply Zone ...
X_DEMAND_ZONE_DETECTED, // Demand Zone ...
//
// Order Blocks ...
X_BULLISH_ORDERBLOCK_DETECTED, // Bullish Order Block ...
X_BEARISH_ORDERBLOCK_DETECTED, // Bearish Order Block ...
//
// Fair Value Gaps ...
X_BULLISH_FVG_DETECTED, // Bullish Fair Value Gapّ ...
X_BEARISH_FVG_DETECTED, // Bearish Fair Value Gapّ ...
};
//
// Forext Sessions ...
enum ENUM_XSESSION
{
X_TOKYO,
X_SYDNEY,
X_LONDON,
X_NEW_YORK,
X_FRANKFORT,
};
//
// Implementation ...
//
// Base POI Model Class ...
class XCBasePOI : public XCBase
{
//
public:
//
//
// Constructor ...
void XCBasePOI()
{
//
Clean();
//
mSep = "_";
mLineSep = "\n";
}
//
// Deconstructor ...
void ~XCBasePOI()
{
Clean();
}
//
// Virtual ...
/**
* Cleanup ...
*/
virtual void Clean()
{
mType = X_POI_NONE;
}
/**
* Validate ...
*
* @return ( virtual bool )
*/
virtual bool IsValid()
{
return false;
}
/**
* Retrieve POI Type ...
*
* @return ( virtual ENUM_XPOIS member )
*/
virtual ENUM_XPOIS Type()
{
return mType;
}
/**
* Retrieve POI Type ...
*
* @return ( virtual string )
*/
virtual string TypeAsString()
{
return ToString(mType);
}
/**
* Retrieve POI Tag ...
*
* @return ( virtual string )
*/
virtual string GetTag()
{
return NULL;
}
/**
* Retrieve POI Tooltip ...
*
* @return ( virtual string )
*/
virtual string GetTooltip()
{
return NULL;
}
//
protected:
//
// Props ...
string mSep; // Separator ...
string mLineSep; // Line Separator ...
ENUM_XPOIS mType; // Type ...
//
private:
//
};
//
// Zone POI Class ...
class XCZone : public XCBasePOI
{
//
public:
//
//
// Constructor ...
void XCZone()
{
}
//
// Deconstructor ...
void ~XCZone()
{
}
//
// Tools ...
//
// Getter(s) / Setter(s) ...
/**
* Get Zone Upper Boundary ...
*
* @return ( double )
*/
double Upper()
{
return mUpper;
}
/**
* Set Zone Upper Boundary ...
*/
void Upper(double value)
{
mUpper = value;
}
/**
* Get Zone Lower Boundary ...
*
* @return ( double )
*/
double Lower()
{
return mLower;
}
/**
* Set Zone Lower Boundary ...
*/
void Lower(double value)
{
mLower = value;
}
/**
* Retrieve Zone Range ...
*
* @return ( double )
*/
double Range()
{
//
double result = 0;
//
double upper = Upper();
double lower = Lower();
//
if (upper > 0 && lower > 0 && upper > lower)
{
result = upper - lower;
}
//
return result;
}
double RangePercent()
{
//
double result = 0;
//
double range = Range();
if (range > 0)
{
result = range / 100;
}
//
return result;
}
//
// Virtuals ...
/**
* Get Zone Start Date ...
*
* @return ( virtual datetime )
*/
virtual datetime From()
{
return NULL;
}
/**
* Get Zone End Date ...
*
* @return ( virtual datetime )
*/
virtual datetime To()
{
return NULL;
}
//
// Getter(s) / Setter(s) ...
//
// Overrides ...
//
// Validators ...
/**
* Validate Upper and Lower of Zone ...
*
* @return ( bool )
*/
bool IsValidBoundary()
{
//
bool result = false;
//
result =
//
mUpper > 0 &&
mLower > 0 &&
mUpper >= mLower
//
;
//
return result;
}
/**
* Check From Date of Zone is Valid ...
*
* @return ( bool )
*/
bool IsValidFrom()
{
//
bool result = false;
//
datetime from = From();
result = IsSpecifiedValid(from);
//
return result;
}
//
protected:
//
// Props ...
double mUpper; // Zone Upper ...
double mLower; // Zone Lower ...
//
private:
//
// Props ...
//
};
//
// From To Zone ...
class XCFromToZone : public XCBasePOI
{
//
public:
//
//
// Constructor ...
void XCFromToZone()
{
}
//
// Deconstructor ...
void ~XCFromToZone()
{
}
//
// Tools ...
bool InitFromTo(
ENUM_XPOIS type,
string title,
datetime from //
)
{
//
bool result = false;
//
result = type != X_POI_NONE &&
IsSpecifiedValid(from) &&
IsSpecifiedValid(title);
//
mType = type;
mFrom = from;
mTitle = title;
mTo = TimeCurrent();
//
result = IsValid();
//
return result;
}
bool InitFromTo(
ENUM_XPOIS type,
string title,
datetime from,
datetime to //
)
{
//
bool result = false;
//
result = IsValid();
//
result = InitFromTo(
type,
title,
from //
);
if (!result)
{
return result;
}
//
to = NormalizeTime(to);
mTo = to;
//
result = IsValid();
//
return result;
}
//
// Getter(s) / Setter(s) ...
/**
* Get Zone Start Time ...
*
* @return ( datetime )
*/
datetime From()
{
return mFrom;
}
/**
* Set Zone Start Time ...
*
* @param value: Datetime
*/
void From(datetime value)
{
//
value = NormalizeTime(value);
//
mFrom = value;
}
/**
* Get Zone End Time ...
*
* @return ( datetime )
*/
datetime To()
{
return mTo;
}
/**
* Set Zone End Time ...
*
* @param value: Datetime
*/
void To(datetime value)
{
//
value = NormalizeTime(value);
//
mTo = value;
}
/**
* Get Title ...
*
* @return ( string )
*/
string Title()
{
return mTitle;
}
/**
* Set Title ...
*
* @param value: String ...
*/
// void Title(string value)
// {
// mTitle = value;
// }
//
// Overrides ...
void Clean() override
{
//
mTo = NULL;
mFrom = NULL;
mType = X_POI_NONE;
}
bool IsValid() override
{
//
bool result = false;
//
result =
//
mType != X_POI_NONE &&
IsSpecifiedValid(mTo) &&
IsSpecifiedValid(mFrom) &&
IsSpecifiedValid(mTitle)
//
;
//
return result;
}
string GetTag() override
{
//
string result = NULL;
//
if (!IsValid())
{
return result;
}
//
string hash = TypeAsString() + mSep + ToString(From()) + mSep + Title();
hash = ToMD5(hash);
//
result = TypeAsString() + "[" + Title() + "]" + mSep + hash;
//
return result;
}
//
protected:
//
//
private:
//
// Props ...
datetime mFrom; // Start Date
datetime mTo; // End Date
string mTitle; // Zone Title
//
};
//
// Bar Zone ...
class XCBarZone : public XCZone
{
//
public:
//
//
// Constructor ...
void XCBarZone()
{
}
//
// Deconstructor ...
void ~XCBarZone()
{
}
//
// Tools ...
/**
* Initialize POI ...
*
* @param bar: XOHCL instance ...
* @param type: ENUM_XPOIS member ...
* @param upperPrice: ENUM_X_PRICE member ...
* @param lowerPrice: ENUM_X_PRICE member ...
*
* @return ( bool )
*/
bool InitBarZone(
XOHCL &bar,
ENUM_XPOIS type,
ENUM_X_PRICE upperPrice,
ENUM_X_PRICE lowerPrice //
)
{
//
bool result = false;
//
result = bar.IsValid() &&
type != X_POI_NONE &&
upperPrice != lowerPrice;
if (!result)
{
return result;
}
//
mBar = bar;
mType = type;
mUpperPrice = upperPrice;
mLowerPrice = lowerPrice;
mUpper = bar.GetPrice(upperPrice);
mLower = bar.GetPrice(lowerPrice);
//
result = IsValidBarZone();
if (result)
{
//
From(bar.time);
To(TimeCurrent());
}
//
return result;
}
//
// Getter(s) / Setter(s) ...
/**
* Fill Bar as XOHCL struct ...
*
* @param bar: XOHCL instance ...
*
* @return ( bool )
*/
bool FillBar(
XOHCL &bar //
)
{
//
bool result = false;
//
result = IsValid();
if (!result)
{
return result;
}
//
bar = mBar;
result = mBar.IsValid();
//
return result;
}
/**
* Set From Date ...
*
* @param value: DateTime ...
*/
void From(datetime value)
{
//
if (!IsValidBarZone())
{
return;
}
//
value = NormalizeTime(value);
//
mFrom = value;
}
/**
* Set To Date ...
*
* @param value: DateTime ...
*/
void To(datetime value)
{
//
if (!IsValidBarZone())
{
return;
}
//
value = NormalizeTime(value);
//
mTo = value;
}
/**
* Retrieve Bar Time ...
*
* @return ( datetime )
*/
datetime BarTime()
{
return mBar.time;
}
/**
* Get Symbol ...
*
* @return ( string )
*/
string GetSymbol()
{
//
string result = NULL;
//
if (!mBar.IsValid())
{
return result;
}
//
return mBar.symbol;
//
return result;
}
/**
* Get Period ...
*
* @return ( int )
*/
ENUM_TIMEFRAMES GetPeriod()
{
//
ENUM_TIMEFRAMES result = NULL;
//
if (!mBar.IsValid())
{
return result;
}
//
return mBar.period;
//
return result;
}
//
// Overrides ...
void Clean() override
{
//
mBar.Clean();
mUpper = 0;
mLower = 0;
mType = X_POI_NONE;
}
datetime From() override
{
return mFrom;
}
datetime To() override
{
return mTo;
}
string GetTag() override
{
//
string result = NULL;
//
if (!IsValidBarZone())
{
return result;
}
//
string hash = ToMD5(mBar.GetTag());
//
result =
//
TypeAsString() + mSep +
ToString(mBar.period) + mSep +
hash
//
;
//
return result;
}
string GetTooltip() override
{
//
string result = NULL;
//
if (!IsValidBarZone())
{
return result;
}
//
return result;
}
//
protected:
//
// Props ...
XOHCL mBar; // Bar ...
ENUM_X_PRICE mUpperPrice; // Upper Price Selection
ENUM_X_PRICE mLowerPrice; // Lower Price Selection
/**
* Check Bar Zone Validation ...
*
* @return ( bool )
*/
bool IsValidBarZone()
{
//
bool result = false;
//
result = mBar.IsValid() &&
mType != X_POI_NONE &&
IsValidBoundary();
//
return result;
}
//
private:
//
// Props ...
datetime mFrom;
datetime mTo;
//
};
class XCTwoBarZone : public XCZone
{
//
public:
//
//
// Constructor ...
void XCTwoBarZone()
{
}
//
// Deconstructor ...
void ~XCTwoBarZone()
{
}
//
// Tools ...
/**
* Initialize POI ...
*
* @param bar: XOHCL instance ...
* @param type: ENUM_XPOIS member ...
* @param upperPrice: ENUM_X_PRICE member ...
* @param lowerPrice: ENUM_X_PRICE member ...
*
* @return ( bool )
*/
bool InitTwoBarZone(
XOHCL &startBar,
XOHCL &endBar,
ENUM_XPOIS type,
bool useStartBarForUpper,
ENUM_X_PRICE upperPrice,
ENUM_X_PRICE lowerPrice //
)
{
//
bool result = false;
//
result = startBar.IsValid() &&
endBar.IsValid() &&
startBar.symbol == endBar.symbol &&
startBar.period == endBar.period &&
startBar.time < endBar.time &&
type != X_POI_NONE;
if (!result)
{
return result;
}
//
mType = type;
mEndBar = endBar;
mStartBar = startBar;
mUpperPrice = upperPrice;
mLowerPrice = lowerPrice;
mUseStartBarForUpper = useStartBarForUpper;
mUpper =
useStartBarForUpper
? startBar.GetPrice(upperPrice)
: endBar.GetPrice(upperPrice);
mLower =
useStartBarForUpper
? endBar.GetPrice(lowerPrice)
: startBar.GetPrice(lowerPrice);
//
result = IsValidTwoBarZone();
if (result)
{
//
From(startBar.time);
To(endBar.time);
}
//
return result;
}
//
// Getter(s) / Setter(s) ...
/**
* Set From Date ...
*
* @param value: DateTime ...
*/
void From(datetime value)
{
//
if (!IsValidTwoBarZone())
{
return;
}
//
value = NormalizeTime(value);
//
mFrom = value;
}
/**
* Set To Date ...
*
* @param value: DateTime ...
*/
void To(datetime value)
{
//
if (!IsValidTwoBarZone())
{
return;
}
//
value = NormalizeTime(value);
//
mTo = value;
}
/**
* Fill Start Bar ...
*
* @param bar: XOHCL instance ...
*
* @return ( bool )
*/
bool FillStartBar(XOHCL &bar)
{
//
bool result = false;
//
result = IsValidTwoBarZone();
if (!result)
{
return result;
}
//
bar = mStartBar;
//
return result;
}
/**
* Fill End Bar ...
*
* @param bar: XOHCL instance ...
*
* @return ( bool )
*/
bool FillEndBar(XOHCL &bar)
{
//
bool result = false;
//
result = IsValidTwoBarZone();
if (!result)
{
return result;
}
//
bar = mEndBar;
//
return result;
}
/**
* Get Symbol ...
*
* @return ( string )
*/
string GetSymbol()
{
//
string result = NULL;
//
if (!mStartBar.IsValid())
{
return result;
}
//
return mStartBar.symbol;
//
return result;
}
/**
* Get Period ...
*
* @return ( int )
*/
ENUM_TIMEFRAMES GetPeriod()
{
//
ENUM_TIMEFRAMES result = NULL;
//
if (!mStartBar.IsValid())
{
return result;
}
//
return mStartBar.period;
//
return result;
}
//
// Overrides ...
void Clean() override
{
//
mStartBar.Clean();
mEndBar.Clean();
mUpper = 0;
mLower = 0;
mUseStartBarForUpper = false;
mType = X_POI_NONE;
}
datetime From() override
{
return mFrom;
}
datetime To() override
{
return mTo;
}
string GetTag() override
{
//
string result = NULL;
//
if (!IsValidTwoBarZone())
{
return result;
}
//
string hash = ToMD5(mStartBar.GetTag() + mSep + mEndBar.GetTag());
//
result =
//
TypeAsString() + mSep +
ToString(mStartBar.period) + mSep +
hash
//
;
//
return result;
}
string GetTooltip() override
{
//
string result = NULL;
//
if (!IsValidTwoBarZone())
{
return result;
}
//
return result;
}
//
protected:
//
// Props ...
XOHCL mStartBar; // Start (Oldest) Bar ...
XOHCL mEndBar; // End (Newest) Bar ...
bool mUseStartBarForUpper; // Use Start Bar for Upper Calculation ...
ENUM_X_PRICE mUpperPrice; // Upper Price Selection
ENUM_X_PRICE mLowerPrice; // Lower Price Selection
/**
* Check Two Bar Zone Validation ...
*
* @return ( bool )
*/
bool IsValidTwoBarZone()
{
//
bool result = false;
//
result = mStartBar.IsValid() &&
mEndBar.IsValid() &&
mStartBar.symbol == mEndBar.symbol &&
mStartBar.period == mEndBar.period &&
mStartBar.time < mEndBar.time &&
mType != X_POI_NONE &&
IsValidBoundary();
//
return result;
}
//
private:
//
// Props ...
datetime mFrom;
datetime mTo;
//
};
//
// Swing Class ...
class XCSwing : public XCBasePOI
{
//
public:
//
//
// Constructor ...
void XCSwing()
{
}
//
// Deconstructor ...
void ~XCSwing()
{
}
//
// Tools ...
/**
* Initialize POI ...
*
* @param bar: XOHCL instance ...
* @param type: ENUM_XPOIS member ...
*
* @return ( bool )
*/
bool Init(
XOHCL &bar,
ENUM_XPOIS type //
)
{
//
bool result = false;
//
result = bar.IsValid() &&
(type == X_POI_SWING_HIGH ||
type == X_POI_SWING_LOW);
if (!result)
{
return result;
}
//
mBar = bar;
mType = type;
//
result = IsValid();
//
return result;
}
//
// Getter(s) / Setter(s) ...
/**
* Fill Bar as XOHCL struct ...
*
* @param bar: XOHCL instance ...
*
* @return ( bool )
*/
bool FillBar(
XOHCL &bar //
)
{
//
bool result = false;
//
result = IsValid();
if (!result)
{
return result;
}
//
bar = mBar;
result = mBar.IsValid();
//
return result;
}
/**
* Get Time of Swing ...
*
* @return ( datetime )
*/
datetime GetTime()
{
//
datetime result = NULL;
//
if (!IsValid() || !mBar.IsValid())
{
return result;
}
//
result = mBar.time;
//
return result;
}
ENUM_TIMEFRAMES GetPeriod()
{
//
ENUM_TIMEFRAMES result = NULL;
//
XOHCL bar;
bool isFilled = FillBar(bar);
if (!isFilled)
{
return result;
}
//
result = bar.period;
//
return result;
}
/**
* Check Swing High or not ...
*
* @return ( bool )
*/
bool IsSwingHigh()
{
//
bool result = false;
//
result = IsValid();
if (!result)
{
return result;
}
//
result =
Type() == X_POI_SWING_HIGH;
//
return result;
}
/**
* Check Swing Low or not ...
*
* @return ( bool )
*/
bool IsSwingLow()
{
//
bool result = false;
//
result = IsValid();
if (!result)
{
return result;
}
//
result =
Type() == X_POI_SWING_LOW;
//
return result;
}
/**
* Get Swing Value ...
*
* @return ( double )
*/
double GetValue()
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result =
IsSwingHigh()
? mBar.high
: mBar.low;
//
return result;
}
//
// Overrides ...
void Clean() override
{
//
mBar.Clean();
mType = X_POI_NONE;
}
bool IsValid() override
{
//
bool result = false;
//
result = mBar.IsValid() &&
(mType == X_POI_SWING_HIGH ||
mType == X_POI_SWING_LOW);
//
return result;
}
string GetTag() override
{
//
string result = NULL;
//
if (!IsValid())
{
return result;
}
//
string hash = ToMD5(mBar.GetTag());
//
string subType = IsSwingHigh()
? "High"
: "Low";
//
result =
//
TypeAsString() + mSep +
subType + mSep +
ToString(mBar.period) + mSep +
hash
//
;
//
return result;
}
string GetTooltip() override
{
//
string result = NULL;
//
if (!IsValid())
{
return result;
}
//
return result;
}
//
protected:
//
// Props ...
XOHCL mBar; // Swing Bar ...
//
private:
//
};
//
// Supply Zone ...
class XCSupplyZone : public XCBarZone
{
//
public:
//
//
// Constructor ...
void XCSupplyZone()
{
}
//
// Deconstructor ...
void ~XCSupplyZone()
{
}
//
// Tools ...
/**
* Initialize POI ...
*
* @param bar: XOHCL instance ...
* @param range: Integer, Detection Range ...
*
* @return ( bool )
*/
bool Init(
XOHCL &bar,
int range = 0 //
)
{
//
bool result = false;
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
result = InitBarZone(
bar,
X_POI_SUPPLY_ZONE,
X_PRICE_HIGH,
X_PRICE_LOW //
);
if (!result)
{
return result;
}
//
result = IsValid();
if (result &&
range > 0)
{
//
datetime time = bar.time;
int periodSeconds = PeriodSeconds(bar.period);
//
datetime from = (datetime)((int)time - (range * periodSeconds));
datetime to = (datetime)((int)time + (range * periodSeconds));
//
From(from);
To(to);
}
//
return result;
}
//
// Getter(s) / Setter(s) ...
//
// Overrides ...
bool IsValid() override
{
//
bool result = false;
//
result = IsValidBarZone() &&
mType == X_POI_SUPPLY_ZONE;
//
return result;
}
//
protected:
//
//
private:
//
//
};
//
// Demand Zone ...
class XCDemandZone : public XCBarZone
{
//
public:
//
//
// Constructor ...
void XCDemandZone()
{
}
//
// Deconstructor ...
void ~XCDemandZone()
{
}
//
// Tools ...
/**
* Initialize POI ...
*
* @param bar: XOHCL instance ...
* @param range: Integer, Detection Range ...
*
* @return ( bool )
*/
bool Init(
XOHCL &bar,
int range = 0 //
)
{
//
bool result = false;
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
result = InitBarZone(
bar,
X_POI_DEMAND_ZONE,
X_PRICE_HIGH,
X_PRICE_LOW //
);
if (!result)
{
return result;
}
//
result = IsValid();
if (result &&
range > 0)
{
//
datetime time = bar.time;
int periodSeconds = PeriodSeconds(bar.period);
//
datetime from = (datetime)((int)time - (range * periodSeconds));
datetime to = (datetime)((int)time + (range * periodSeconds));
//
From(from);
To(to);
}
//
return result;
}
//
// Getter(s) / Setter(s) ...
//
// Overrides ...
bool IsValid() override
{
//
bool result = false;
//
result = IsValidBarZone() &&
mType == X_POI_DEMAND_ZONE;
//
return result;
}
//
protected:
//
//
private:
//
//
};
//
// Support Zone ...
class XCSupportZone : public XCBarZone
{
//
public:
//
//
// Constructor ...
void XCSupportZone()
{
}
//
// Deconstructor ...
void ~XCSupportZone()
{
}
//
// Tools ...
/**
* Initialize POI ...
*
* @param bar: XOHCL instance ...
* @param range: Integer, Detection Range ...
*
* @return ( bool )
*/
bool Init(
XOHCL &bar,
int range = 0 //
)
{
//
bool result = false;
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
result = InitBarZone(
bar,
X_POI_SUPPORT_ZONE,
X_PRICE_DOWN,
X_PRICE_LOW //
);
if (!result)
{
return result;
}
//
result = IsValid();
if (result &&
range > 0)
{
//
datetime time = bar.time;
int periodSeconds = PeriodSeconds(bar.period);
//
datetime from = (datetime)((int)time - (range * periodSeconds));
datetime to = (datetime)((int)time + (range * periodSeconds));
//
From(from);
To(to);
}
//
return result;
}
//
// Getter(s) / Setter(s) ...
//
// Overrides ...
bool IsValid() override
{
//
bool result = false;
//
result = IsValidBarZone() &&
mType == X_POI_SUPPORT_ZONE;
//
return result;
}
//
protected:
//
//
private:
//
//
};
//
// Resistance Zone ...
class XCResistanceZone : public XCBarZone
{
//
public:
//
//
// Constructor ...
void XCResistanceZone()
{
}
//
// Deconstructor ...
void ~XCResistanceZone()
{
}
//
// Tools ...
/**
* Initialize POI ...
*
* @param bar: XOHCL instance ...
* @param range: Integer, Detection Range ...
*
* @return ( bool )
*/
bool Init(
XOHCL &bar,
int range = 0 //
)
{
//
bool result = false;
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
result = InitBarZone(
bar,
X_POI_RESISTANCE_ZONE,
X_PRICE_HIGH,
X_PRICE_UP //
);
if (!result)
{
return result;
}
//
result = IsValid();
if (result &&
range > 0)
{
//
datetime time = bar.time;
int periodSeconds = PeriodSeconds(bar.period);
//
datetime from = (datetime)((int)time - (range * periodSeconds));
datetime to = (datetime)((int)time + (range * periodSeconds));
//
From(from);
To(to);
}
//
return result;
}
//
// Getter(s) / Setter(s) ...
//
// Overrides ...
bool IsValid() override
{
//
bool result = false;
//
result = IsValidBarZone() &&
mType == X_POI_RESISTANCE_ZONE;
//
return result;
}
//
protected:
//
//
private:
//
//
};
//
// Order Block ...
class XCOrderBlock : public XCBarZone
{
//
public:
//
//
// Constructor ...
void XCOrderBlock()
{
}
//
// Deconstructor ...
void ~XCOrderBlock()
{
}
//
// Tools ...
/**
* Initialize POI ...
*
* @param bar: XOHCL instance ...
* @param dir: ENUM_X_DIRECTION member ...
*
* @return ( bool )
*/
bool Init(
XOHCL &bar,
ENUM_X_DIRECTION dir //
)
{
//
bool result = false;
//
result = bar.IsValid() &&
(dir == X_DIRECTION_BULLISH ||
dir == X_DIRECTION_BEARISH);
if (!result)
{
return result;
}
//
ENUM_XPOIS mTT =
IsSpecifiedBullish(dir)
? X_POI_BULLISH_ORDERBLOCK
: X_POI_BEARISH_ORDERBLOCK;
//
result = InitBarZone(
bar,
mTT,
X_PRICE_HIGH,
X_PRICE_LOW //
);
if (!result)
{
return result;
}
//
result = IsValid();
//
return result;
}
//
// Getter(s) / Setter(s) ...
/**
* Check is Bullish ...
*
* @return ( bool )
*/
bool IsBullish()
{
//
bool result = false;
//
result = IsValid() &&
Type() == X_POI_BULLISH_ORDERBLOCK;
//
return result;
}
/**
* Check is Bearish ...
*
* @return ( bool )
*/
bool IsBearish()
{
//
bool result = false;
//
result = IsValid() &&
Type() == X_POI_BEARISH_ORDERBLOCK;
//
return result;
}
/**
* Detect Order Blocks Breaker Bar ...
*
* @param breakerBar: XOHCL instance Reference ...
*
* @return ( bool )
*/
bool DetectBreakerBar(XOHCL &breakerBar)
{
//
bool result = false;
//
breakerBar.Clean();
//
result = IsValid();
if (!result)
{
return result;
}
//
XOHCL fromBar;
result = FillBar(fromBar);
if (!result)
{
return result;
}
//
int fromIndex = fromBar.Index();
result = fromIndex > 0;
if (!result)
{
return result;
}
//
bool isBullish = IsBullish();
ENUM_X_DIRECTION dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
double value =
isBullish
? Upper()
: Lower();
//
for (int i = fromIndex - 1; i >= 0; i--)
{
//
XOHCL iBar;
bool isInited = iBar.Init(
fromBar.symbol,
fromBar.period,
i //
);
if (!isInited)
{
continue;
}
//
isInited = IsBarBreak(
value,
dir,
iBar //
);
if (isInited)
{
//
breakerBar = iBar;
break;
}
}
//
result = breakerBar.IsValid();
//
return result;
}
/**
* Check Order Block is Hunted or not ...
*
* @param huntedBar: XOHCL instance Reference ...
*
* @return ( bool )
*/
bool IsHunted(XOHCL &huntedBar)
{
//
bool result = false;
//
huntedBar.Clean();
//
result = IsValid();
if (!result)
{
return result;
}
//
XOHCL breakerBar;
result = DetectBreakerBar(breakerBar);
if (!result)
{
return result;
}
//
bool isBullish = IsBullish();
//
int breakerIndex = breakerBar.Index();
for (int i = breakerIndex - 1; i >= 0; i--)
{
//
XOHCL iBar;
result = iBar.Init(
breakerBar.symbol,
breakerBar.period,
i //
);
//
double price =
isBullish
? iBar.low
: iBar.high;
//
result = IsPriceInsideZone(
price,
Upper(),
Lower() //
);
if (result)
{
//
huntedBar = iBar;
break;
}
}
//
result = huntedBar.IsValid();
//
return result;
}
/**
* Check Order Block Validation ...
*
* @return ( bool )
*/
bool IsValidOrderBlock()
{
//
bool result = false;
//
result = IsValid();
if (!result)
{
return result;
}
//
XOHCL breakerBar;
result = DetectBreakerBar(breakerBar);
if (!result)
{
return result;
}
int breakerBarIndex = breakerBar.Index();
//
XOHCL huntedBar;
bool isHunted = IsHunted(huntedBar);
result = !isHunted;
if (!result)
{
return result;
}
//
bool isBullish = IsBullish();
//
for (int i = breakerBarIndex - 1; i >= 0; i--)
{
//
XOHCL iBar;
result = iBar.Init(
breakerBar.symbol,
breakerBar.period,
i //
);
if (!result)
{
continue;
}
//
double price =
isBullish
? iBar.low
: iBar.high;
//
result =
isBullish
? price > Upper()
: price < Lower();
if (!result)
{
return result;
}
}
//
return result;
}
//
// Overrides ...
bool IsValid() override
{
//
bool result = false;
//
result = IsValidBarZone() &&
(mType == X_POI_BULLISH_ORDERBLOCK ||
mType == X_POI_BEARISH_ORDERBLOCK);
//
return result;
}
//
protected:
//
//
private:
//
//
};
//
// Rejection Bar ...
class XCRejectionBar : public XCBarZone
{
//
public:
//
//
// Constructor ...
void XCRejectionBar()
{
}
//
// Deconstructor ...
void ~XCRejectionBar()
{
}
//
// Tools ...
/**
* Initialize POI ...
*
* @param bar: XOHCL instance ...
*
* @return ( bool )
*/
bool Init(
XOHCL &bar //
)
{
//
bool result = false;
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
bool isBullish =
bar.GetLowShadow() > bar.GetHighShadow();
bool isBearish =
bar.GetHighShadow() > bar.GetLowShadow();
result = isBullish ||
isBearish;
if (!result)
{
return result;
}
//
ENUM_X_PRICE upPrice = isBullish
? X_PRICE_HIGH
: X_PRICE_DOWN;
//
ENUM_X_PRICE loPrice = isBullish
? X_PRICE_UP
: X_PRICE_LOW;
//
result = InitBarZone(
bar,
X_POI_REJECTION_BAR,
upPrice,
loPrice //
);
if (!result)
{
return result;
}
//
result = IsValid();
//
return result;
}
//
// Getter(s) / Setter(s) ...
/**
* Check is Bullish ...
*
* @return ( bool )
*/
bool IsBullish()
{
//
bool result = false;
//
result = IsValid() &&
Type() == X_POI_REJECTION_BAR &&
mBar.GetLowShadow() > mBar.GetHighShadow();
//
return result;
}
/**
* Check is Bearish ...
*
* @return ( bool )
*/
bool IsBearish()
{
//
bool result = false;
//
result = IsValid() &&
Type() == X_POI_REJECTION_BAR &&
mBar.GetHighShadow() > mBar.GetLowShadow();
//
return result;
}
//
// Overrides ...
bool IsValid() override
{
//
bool result = false;
//
result = IsValidBarZone() &&
mType == X_POI_REJECTION_BAR;
//
return result;
}
//
protected:
//
//
private:
//
//
};
//
// Momentum Bar ...
class XCMomentumBar : public XCBarZone
{
//
public:
//
//
// Constructor ...
void XCMomentumBar()
{
}
//
// Deconstructor ...
void ~XCMomentumBar()
{
}
//
// Tools ...
/**
* Initialize POI ...
*
* @param bar: XOHCL instance ...
*
* @return ( bool )
*/
bool Init(
XOHCL &bar //
)
{
//
bool result = false;
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
bool isBullish = bar.IsBullish();
bool isBearish = bar.IsBearish();
result = isBullish ||
isBearish;
if (!result)
{
return result;
}
//
result = InitBarZone(
bar,
X_POI_MOMENTUM_BAR,
X_PRICE_HIGH,
X_PRICE_LOW //
);
if (!result)
{
return result;
}
//
result = IsValid();
//
return result;
}
//
// Getter(s) / Setter(s) ...
/**
* Check is Bullish ...
*
* @return ( bool )
*/
bool IsBullish()
{
//
bool result = false;
//
result = IsValid() &&
mBar.IsBullish() &&
Type() == X_POI_MOMENTUM_BAR;
//
return result;
}
/**
* Check is Bearish ...
*
* @return ( bool )
*/
bool IsBearish()
{
//
bool result = false;
//
result = IsValid() &&
mBar.IsBearish() &&
Type() == X_POI_MOMENTUM_BAR;
//
return result;
}
//
// Overrides ...
bool IsValid() override
{
//
bool result = false;
//
result = IsValidBarZone() &&
mType == X_POI_MOMENTUM_BAR;
//
return result;
}
//
protected:
//
//
private:
//
//
};
//
// Fair Value Gap ...
class XCFVG : public XCTwoBarZone
{
//
public:
//
//
// Constructor ...
void XCFVG()
{
}
//
// Deconstructor ...
void ~XCFVG()
{
}
//
// Tools ...
/**
* Initialize POI ...
*
* @param startBar: XOHCL instance ...
* @param endBar: XOHCL instance ...
* @param dir: ENUM_X_DIRECTION member ...
*
* @return ( bool )
*/
bool Init(
XOHCL &startBar,
XOHCL &endBar,
ENUM_X_DIRECTION dir //
)
{
//
bool result = false;
//
result = endBar.IsValid() &&
startBar.IsValid() &&
(dir == X_DIRECTION_BULLISH ||
dir == X_DIRECTION_BEARISH);
if (!result)
{
return result;
}
//
bool isDirBullish = IsSpecifiedBullish(dir);
ENUM_XPOIS mTT =
isDirBullish
? X_POI_BULLISH_FVG
: X_POI_BEARISH_FVG;
//
bool useFistForUpper = isDirBullish
? false
: true;
ENUM_X_PRICE upPrice = isDirBullish
? X_PRICE_LOW
: X_PRICE_HIGH;
ENUM_X_PRICE loPrice = isDirBullish
? X_PRICE_HIGH
: X_PRICE_LOW;
//
result = InitTwoBarZone(
startBar,
endBar,
mTT,
useFistForUpper,
upPrice,
loPrice //
);
if (!result)
{
return result;
}
//
result = IsValid();
//
return result;
}
//
// Getter(s) / Setter(s) ...
/**
* Check is Bullish ...
*
* @return ( bool )
*/
bool IsBullish()
{
//
bool result = false;
//
result = IsValid() &&
Type() == X_POI_BULLISH_FVG;
//
return result;
}
/**
* Check is Bearish ...
*
* @return ( bool )
*/
bool IsBearish()
{
//
bool result = false;
//
result = IsValid() &&
Type() == X_POI_BEARISH_FVG;
//
return result;
}
//
// Overrides ...
bool IsValid() override
{
//
bool result = false;
//
result = IsValidTwoBarZone() &&
(mType == X_POI_BULLISH_FVG ||
mType == X_POI_BEARISH_FVG);
//
return result;
}
//
protected:
//
//
private:
//
//
};
//
// Ticks Zones ...
//
class XCTickZone : public CObject
{
//
// Public ...
public:
//
// Props ...
string symbol;
ENUM_TIMEFRAMES period;
//
double high;
double low;
int ticks;
double percent;
//
ulong volume;
double volumePercent;
//
// Compare Two Zone With Each Other ...
virtual int Compare(
const CObject *node,
const int mode = 0 //
) const
{
//
const XCTickZone *other = (XCTickZone *)node;
//
return other.ticks - ticks;
}
//
bool IsValid()
{
//
bool result = false;
//
result = high > 0 &&
low > 0 &&
high > low &&
ticks > 0 &&
percent > 0;
//
return result;
}
//
// Protected ...
protected:
//
// Private ...
private:
//
};
//
class XCTicksZone : public XCTwoBarZone
{
//
public:
//
//
// Constructor ...
void XCTicksZone()
{
Default();
}
//
// Deconstructor ...
void ~XCTicksZone()
{
}
//
// Getter(s) / Setter(s) ...
/**
* Get Number of Ticks Levels ...
*
* @return ( int )
*/
int Levels()
{
return mLevels;
}
/**
* Set Number of Ticks Levels ...
*
* @return ( int )
*/
void Levels(int value)
{
//
if (value < 2)
{
value = 2;
}
//
mLevels = value;
}
/**
* Apply Default Config ...
*/
virtual void Default()
{
//
Levels(10);
}
//
// Tools ...
/**
* Initialize POI ...
*
* @param startBar: XOHCL instance ...
* @param endBar: XOHCL instance ...
*
* @return ( bool )
*/
bool Init(
XOHCL &startBar,
XOHCL &endBar //
)
{
//
bool result = false;
//
result = endBar.IsValid() &&
startBar.IsValid();
if (!result)
{
return result;
}
//
// Calculate Start and End Time ...
datetime from = startBar.time;
datetime to = endBar.time;
ulong fromM = ((ulong)startBar.time * 1000);
ulong toM = ((ulong)endBar.time * 1000);
//
// Symbol and Period ...
string symbol = startBar.symbol;
ENUM_TIMEFRAMES period = startBar.period;
//
// Prepare Zones Array ...
mZones.Clear();
//
// Retrieve Ticks between Times ...
SpecificClean(mTicks);
CopyTicksRange(
symbol,
mTicks,
COPY_TICKS_ALL,
fromM,
toM //
);
//
// Ticks Volumes ...
int ticksVolumeCount = CopyTickVolume(
symbol,
PERIOD_M1,
from,
to,
mTickVolumes //
);
if (IsValidSize(ticksVolumeCount))
{
//
mVolumes = 0;
for (int i = 0; i < ticksVolumeCount; i++)
{
mVolumes += mTickVolumes[i];
}
}
//
// Retrieve Highs ...
SpecificClean(mHighs);
CopyHigh(
symbol,
period,
from,
to,
mHighs //
);
//
// Retrieve Lows ...
SpecificClean(mLows);
CopyLow(
symbol,
period,
from,
to,
mLows //
);
//
// Find Highest Value in Range ...
int highIDX = ArrayMaximum(mHighs);
mRangeHigh = mHighs[highIDX];
//
// Find Lowest Value in Range ...
int lowIDX = ArrayMinimum(mLows);
mRangeLow = mLows[lowIDX];
//
datetime mTimes[];
CopyTime(
symbol,
period,
from,
to,
mTimes //
);
mRangeHighTime = mTimes[highIDX];
mRangeLowTime = mTimes[lowIDX];
//
double mRangeSize = mRangeHigh - mRangeLow;
//
// Create Zones ...
for (int i = 0; i < Levels(); i++)
{
//
// Instance a New Zone ...
XCTickZone *iZone = new XCTickZone();
//
iZone.symbol = symbol;
iZone.period = period;
//
// Calculate Each Zones High / Low based on Range ...
double iH = mRangeHigh - mRangeSize * i / Levels();
double iL = mRangeHigh - mRangeSize * (i + 1) / Levels();
//
// Set Zone High Low Properties ...
iZone.low = iL;
iZone.high = iH;
//
// Add Zone to Zone Array Objects ...
mZones.Add(iZone);
}
//
// Calculate Each Zone Ticks ...
int ticksCount = ArraySize(mTicks);
for (int i = 0; i < ticksCount; i++)
{
//
// Retrieve Tick ...
MqlTick iTick = mTicks[i];
//
// Loop through Zones ...
for (int j = 0; j < Levels(); j++)
{
//
// Rejrieve j indexed Zone Object ...
XCTickZone *jZone = mZones.At(j);
//
bool isInRange = IsTickInZoneRange(
iTick,
jZone //
);
if (isInRange)
{
//
jZone.ticks++;
break;
}
}
}
//
// Calculating Zone Percents ...
for (int i = 0; i < Levels(); i++)
{
//
XCTickZone *iZone = mZones.At(i);
//
double percent = CalculateZoneTickPercent(iZone);
iZone.percent = percent;
}
//
// Sort Zones Based on Percents ...
mZones.Sort();
//
mUpper = mRangeHigh;
mLower = mRangeLow;
mType = X_POI_TICKS_ZONES;
mEndBar = endBar;
mStartBar = startBar;
From(startBar.time);
To(endBar.time);
//
result = IsValid();
if (!result)
{
return result;
}
//
// Try to Find Out PERIOD_1M times in each zone ...
datetime to1M = (datetime)((int)endBar.time + PeriodSeconds(period) - 60);
int to1MIndex = iBarShift(
symbol,
PERIOD_M1,
to1M //
);
int from1MIndex = iBarShift(
symbol,
PERIOD_M1,
from //
);
for (int i = from1MIndex; i > to1MIndex; i--)
{
//
XOHCL iBar;
bool isInited = iBar.Init(
symbol,
PERIOD_M1,
i //
);
if (!isInited)
{
continue;
}
ulong iVolume = iTickVolume(
symbol,
PERIOD_M1,
i //
);
//
// Loop through Zones ...
for (int j = 0; j < Levels(); j++)
{
//
XCTickZone *jZone = mZones.At(j);
if (!jZone.IsValid())
{
continue;
}
//
// Check iBar is Inside jZone ...
bool isIBarInside =
iBar.GetUp() < jZone.high &&
iBar.GetDown() > jZone.low;
// iBar.low < jZone.high ||
// iBar.high > jZone.low;
if (isIBarInside)
{
jZone.volume += iVolume;
}
}
}
//
// Calculate Volume Percent ...
for (int i = 0; i < Levels(); i++)
{
//
XCTickZone *iZone = mZones.At(i);
//
iZone.volumePercent = (double)(iZone.volume * 100 / mVolumes);
}
//
return result;
}
//
// Getter(s) / Setter(s) ...
/**
* Retrieve Zones Count ...
*
* @return ( int )
*/
int Count()
{
return mZones.Total();
}
/**
* Retrieve Specified Sorted Zones ...
*
* @param index: Integer ...
*
* @return ( XCTickZone * )
*/
XCTickZone *GetZone(int index)
{
//
if (!IsValidIndex(index))
{
return NULL;
}
//
return mZones.At(index);
}
/**
* Calculate Liquidity Percent for Specified Direction ...
*
* @param forDirection: ENUM_X_DIRECTION member, Specified Liquidity ...
* @param price: Double, Specified Price ...
*
* @return ( double )
*/
double CalculateLiquidityPercent(
ENUM_X_DIRECTION forDirection,
double price //
)
{
//
double result = 0;
//
int count = Count();
if (price <= 0 ||
!IsValid() ||
!IsValidSize(count) ||
forDirection == X_DIRECTION_ALL ||
forDirection == X_DIRECTION_NONE)
{
return result;
}
//
bool isBullish = forDirection == X_DIRECTION_BULLISH;
//
for (int i = 0; i < count; i++)
{
//
XCTickZone *iZone = GetZone(i);
//
if (iZone.IsValid())
{
//
result += !isBullish &&
price > iZone.high
? iZone.percent
: isBullish &&
price < iZone.low
? iZone.percent
: 0;
}
}
//
return result;
}
//
// Overrides ...
bool IsValid() override
{
//
bool result = false;
//
result =
IsValidFrom() &&
IsValidTwoBarZone() &&
Levels() > 0 &&
mZones.Total() == Levels() &&
mRangeHigh > 0 &&
mRangeLow > 0;
//
return result;
}
//
protected:
//
//
private:
//
// Props ...
//
MqlTick mTicks[];
double mHighs[];
double mLows[];
ulong mVolumes;
ulong mTickVolumes[];
double mRangeHigh;
datetime mRangeHighTime;
double mRangeLow;
datetime mRangeLowTime;
//
int mLevels; // Number of Ticks Levels ...
//
CArrayObj mZones;
/**
* Check a Tick is in a Zone rage or not ...
*
* @param tick: MqlTick instance ...
* @param zone: XCTickZone instance ...
*
* @return ( bool )
*/
bool IsTickInZoneRange(
MqlTick &tick,
XCTickZone *zone //
)
{
//
bool result = false;
//
result =
//
tick.bid >= zone.low &&
tick.bid <= zone.high
//
;
//
return result;
}
/**
* Calculate Zone Tick Percent ...
*
* @param zone: XCTickZone instance ...
* @param normalizationDigits: Integer ...
*
* @return ( double )
*/
double CalculateZoneTickPercent(
XCTickZone *zone,
int normalizationDigits = 2 //
)
{
//
double result = 0;
//
if (normalizationDigits < 2 || normalizationDigits > 5)
{
normalizationDigits = 2;
}
//
int ticksCount = ArraySize(mTicks);
if (ticksCount <= 0)
{
return result;
}
//
result = (double)zone.ticks / ticksCount * 100;
result = NormalizeDouble(result, normalizationDigits);
//
return result;
}
//
};
//
// Trading Day ...
class XCDay : public XCFromToZone
{
//
public:
//
//
// Constructor ...
void XCDay()
{
}
//
// Deconstructor ...
void ~XCDay()
{
}
//
// Tools ...
/**
* Initialize POI ...
*
* @return ( bool )
*/
bool Init()
{
//
bool result = false;
//
result = IsValid();
//
return result;
}
//
// Getter(s) / Setter(s) ...
//
// Overrides ...
//
protected:
//
//
private:
//
//
};
//
// Trading Session ...
class XCSession : public XCFromToZone
{
//
public:
//
//
// Constructor ...
void XCSession()
{
}
//
// Deconstructor ...
void ~XCSession()
{
}
//
// Tools ...
/**
* Initialize POI ...
*
* @return ( bool )
*/
bool Init()
{
//
bool result = false;
//
result = IsValid();
//
return result;
}
//
// Getter(s) / Setter(s) ...
//
// Overrides ...
//
protected:
//
//
private:
//
//
};
//
//
// Model Exists Founded POIs ...
struct XPOIState
{
//
string symbol;
ENUM_TIMEFRAMES period;
datetime time;
//
XCTicksZone *ticksZone; // Ticks Zone ...
//
XCSwing *swingHighs[]; // Holds Founded Swing Highs ...
XCSwing *swingLows[]; // Holds Founded Swing Lows ...
XCMomentumBar *bullishMomentumBars[]; // Holds Founded Bullish Momentum Bars ...
XCMomentumBar *bearishMomentumBars[]; // Holds Founded Bearish Momentum Bars ...
XCRejectionBar *bullishRejectionBars[]; // Holds Founded Bullish Rejection Bars ...
XCRejectionBar *bearishRejectionBars[]; // Holds Founded Bearish Rejection Bars ...
XCSupportZone *supportZones[]; // Holds Founded Support Zones ...
XCResistanceZone *resistanceZones[]; // Holds Founded Resistance Zones ...
XCSupplyZone *supplyZones[]; // Holds Founded Supply Zones ...
XCDemandZone *demandZones[]; // Holds Founded Demand Zones ...
XCOrderBlock *bullishOrderBlocks[]; // Holds Founded Bullish Order Blocks ...
XCOrderBlock *bearishOrderBlocks[]; // Holds Founded Bearish Order Blocks ...
XCFVG *bullishFairValueGaps[]; // Holds Founded Bullish Fair Value Gaps ...
XCFVG *bearishFairValueGaps[]; // Holds Founded Bearish Fair Value Gaps ...
//
// Constructor ...
void XPOIState()
{
Clean();
}
//
// Actions ...
/**
* Cleanup all props ...
*/
void Clean()
{
//
symbol = NULL;
period = NULL;
time = NULL;
//
ticksZone = NULL;
//
Clean(swingHighs);
Clean(swingLows);
Clean(bullishMomentumBars);
Clean(bearishMomentumBars);
Clean(bullishRejectionBars);
Clean(bearishRejectionBars);
Clean(supportZones);
Clean(resistanceZones);
Clean(supplyZones);
Clean(demandZones);
Clean(bullishOrderBlocks);
Clean(bearishOrderBlocks);
Clean(bullishFairValueGaps);
Clean(bearishFairValueGaps);
}
/**
* Validate ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
IsSpecifiedValid(symbol) &&
IsSpecifiedValid(period) &&
IsSpecifiedValid(time);
//
return result;
}
/**
* Check State has Childs or not ...
*
* @return ( bool )
*/
bool HasChild()
{
//
bool result = false;
//
result =
//
IsValidSize(CountSwingHighs()) ||
IsValidSize(CountSwingLows()) ||
IsValidSize(CountBullishMomentumBars()) ||
IsValidSize(CountBearishMomentumBars()) ||
IsValidSize(CountBullishRejectionBars()) ||
IsValidSize(CountBearishRejectionBars()) ||
IsValidSize(CountSupportZones()) ||
IsValidSize(CountResistanceZones()) ||
IsValidSize(CountSupplyZones()) ||
IsValidSize(CountDemandZones()) ||
IsValidSize(CountBullishOrderBlocks()) ||
IsValidSize(CountBearishOrderBlocks()) ||
IsValidSize(CountBullishFairValueGaps()) ||
IsValidSize(CountBearishFairValueGaps())
//
;
//
return result;
}
/**
* Fill Dest State by Current State's Data ...
*
* @param dest: XPOIState instance, reference to specified dest ...
*
*/
void Fill(XPOIState &dest)
{
//
if (!IsValid() ||
!HasChild())
{
return;
}
//
dest.symbol = symbol;
dest.period = period;
dest.time = time;
//
Copy(
swingHighs,
dest.swingHighs,
false //
);
Copy(
swingLows,
dest.swingLows,
false //
);
Copy(
bullishMomentumBars,
dest.bullishMomentumBars,
false //
);
Copy(
bearishMomentumBars,
dest.bearishMomentumBars,
false //
);
Copy(
bullishRejectionBars,
dest.bullishRejectionBars,
false //
);
Copy(
bearishRejectionBars,
dest.bearishRejectionBars,
false //
);
Copy(
supportZones,
dest.supportZones,
false //
);
Copy(
resistanceZones,
dest.resistanceZones,
false //
);
Copy(
supplyZones,
dest.supplyZones,
false //
);
Copy(
demandZones,
dest.demandZones,
false //
);
Copy(
bullishOrderBlocks,
dest.bullishOrderBlocks,
false //
);
Copy(
bearishOrderBlocks,
dest.bearishOrderBlocks,
false //
);
Copy(
bullishFairValueGaps,
dest.bullishFairValueGaps,
false //
);
Copy(
bearishFairValueGaps,
dest.bearishFairValueGaps,
false //
);
//
}
/**
* Calculate Liquidity Percent for Specified Direction ...
*
* @param forDirection: ENUM_X_DIRECTION member, Specified Liquidity ...
* @param price: Double, Specified Price ...
*
* @return ( double )
*/
double CalculateLiquidityPercent(
ENUM_X_DIRECTION forDirection,
double price = 0 //
)
{
//
double result = 0;
//
if (!IsValid() ||
ticksZone == NULL)
{
return result;
}
//
// Normalize Price for Actions ...
if (price <= 0)
{
//
MqlTick mTick;
bool isTickRetrieved = GetTick(
symbol,
mTick //
);
if (isTickRetrieved)
{
price = mTick.bid;
}
}
//
result = ticksZone
.CalculateLiquidityPercent(
forDirection,
price //
);
//
return result;
}
//
// Counters ...
//
int CountSwingHighs()
{
//
int result = 0;
//
if (!IsValid())
{
return result;
}
//
result = ArraySize(swingHighs);
//
return result;
}
//
int CountSwingLows()
{
//
int result = 0;
//
if (!IsValid())
{
return result;
}
//
result = ArraySize(swingLows);
//
return result;
}
//
int CountBullishMomentumBars()
{
//
int result = 0;
//
if (!IsValid())
{
return result;
}
//
result = ArraySize(bullishMomentumBars);
//
return result;
}
//
int CountBearishMomentumBars()
{
//
int result = 0;
//
if (!IsValid())
{
return result;
}
//
result = ArraySize(bearishMomentumBars);
//
return result;
}
//
int CountBullishRejectionBars()
{
//
int result = 0;
//
if (!IsValid())
{
return result;
}
//
result = ArraySize(bullishRejectionBars);
//
return result;
}
//
int CountBearishRejectionBars()
{
//
int result = 0;
//
if (!IsValid())
{
return result;
}
//
result = ArraySize(bearishRejectionBars);
//
return result;
}
//
int CountSupportZones()
{
//
int result = 0;
//
if (!IsValid())
{
return result;
}
//
result = ArraySize(supportZones);
//
return result;
}
//
int CountResistanceZones()
{
//
int result = 0;
//
if (!IsValid())
{
return result;
}
//
result = ArraySize(resistanceZones);
//
return result;
}
//
int CountSupplyZones()
{
//
int result = 0;
//
if (!IsValid())
{
return result;
}
//
result = ArraySize(supplyZones);
//
return result;
}
//
int CountDemandZones()
{
//
int result = 0;
//
if (!IsValid())
{
return result;
}
//
result = ArraySize(demandZones);
//
return result;
}
//
int CountBullishOrderBlocks()
{
//
int result = 0;
//
if (!IsValid())
{
return result;
}
//
result = ArraySize(bullishOrderBlocks);
//
return result;
}
//
int CountBearishOrderBlocks()
{
//
int result = 0;
//
if (!IsValid())
{
return result;
}
//
result = ArraySize(bearishOrderBlocks);
//
return result;
}
//
int CountBullishFairValueGaps()
{
//
int result = 0;
//
if (!IsValid())
{
return result;
}
//
result = ArraySize(bullishFairValueGaps);
//
return result;
}
//
int CountBearishFairValueGaps()
{
//
int result = 0;
//
if (!IsValid())
{
return result;
}
//
result = ArraySize(bearishFairValueGaps);
//
return result;
}
//
};
//
//
//
//
// Pivot Types ...
enum ENUM_XPV_PIVOTS
{
XPV_NONE,
XPV_PEAK,
XPV_VALE,
};
//
// Model a Pivot structure ...
struct XPVPivot
{
//
string symbol;
ENUM_TIMEFRAMES period;
//
double upper;
double lower;
//
datetime from;
datetime to;
//
int repetition;
//
ENUM_XPV_PIVOTS type;
//
// Combined all States ...
XPOIState state;
//
XPVPivot()
{
Clean();
}
//
// Tools ...
/**
* Cleanup ...
*/
void Clean()
{
//
upper = 0;
lower = 0;
//
to = NULL;
from = NULL;
symbol = NULL;
period = NULL;
//
repetition = 0;
//
type = XPV_NONE;
//
state.Clean();
}
/**
* Validation ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
//
IsValid(to) &&
IsValid(from) &&
IsValid(symbol) &&
IsValid(period) &&
repetition > 0 &&
type != XPV_NONE &&
(upper > 0 || lower > 0)
//
;
//
return result;
}
/**
* Check Pivot is Peak ...
*
* @return ( bool )
*/
bool IsPeak()
{
//
bool result = false;
//
result = IsValid() &&
type == XPV_PEAK;
//
return result;
}
/**
* Check Pivot is Vale ...
*
* @return ( bool )
*/
bool IsVale()
{
//
bool result = false;
//
result = IsValid() &&
type == XPV_VALE;
//
return result;
}
/**
* Calculate Lower for Peaks ...
*
* @return ( double )
*/
double CalculateLower()
{
//
double result = 0;
//
if (!IsValid() ||
!IsPeak())
{
return result;
}
//
int fromIndex = iBarShift(
symbol,
period,
from //
);
//
int toIndex = iBarShift(
symbol,
period,
to //
);
//
int count =
fromIndex - toIndex;
//
int llIDX = iLowest(
symbol,
period,
MODE_LOW,
count,
toIndex //
);
//
result =
iLow(
symbol,
period,
llIDX //
);
//
return result;
}
/**
* Calculate Upper for Vales ...
*
* @return ( double )
*/
double CalculateUpper()
{
//
double result = 0;
//
if (!IsValid() ||
!IsVale())
{
return result;
}
//
int fromIndex = iBarShift(
symbol,
period,
from //
);
//
int toIndex = iBarShift(
symbol,
period,
to //
);
//
int count =
fromIndex - toIndex;
//
int hhIDX = iHighest(
symbol,
period,
MODE_HIGH,
count,
toIndex //
);
//
result =
iHigh(
symbol,
period,
hhIDX //
);
//
return result;
}
/**
* Calculate Range of Pivot ...
*
* @return ( double )
*/
double CalculateRange()
{
//
double result = 0;
//
if (!IsValid() ||
upper <= 0 ||
lower <= 0)
{
return result;
}
//
result = upper - lower;
//
return result;
}
/**
* Calculate Middle of Pivot ...
* Used for
* @return ( double )
*/
double CalculateMid()
{
//
double result = 0;
//
double range = CalculateRange();
if (range <= 0)
{
return result;
}
//
result = lower + (range / 2);
//
return result;
}
/**
* Calculate Liquidity Percent for Specified Direction ...
*
* @param forDirection: ENUM_X_DIRECTION member, Specified Liquidity ...
* @param price: Double, Specified Price ...
*
* @return ( double )
*/
double CalculateLiquidityPercent(
ENUM_X_DIRECTION forDirection,
double price = 0 //
)
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result = state
.CalculateLiquidityPercent(
forDirection,
price //
);
//
return result;
}
/**
* Check Price in Premium or not ...
*
* @return ( bool )
*/
bool IsPriceInPremium()
{
//
bool result = false;
//
result = IsValid();
if (!result)
{
return result;
}
//
double ask = GetAsk(symbol);
double bid = GetBid(symbol);
//
double mid = CalculateMid();
//
result =
//
ask > mid &&
bid > mid
//
;
//
return result;
}
/**
* Check Price in Discount or not ...
*
* @return ( bool )
*/
bool IsPriceInDiscount()
{
//
bool result = false;
//
result = IsValid();
if (!result)
{
return result;
}
//
double ask = GetAsk(symbol);
double bid = GetBid(symbol);
//
double mid = CalculateMid();
//
result =
//
ask > mid &&
bid > mid
//
;
//
return result;
}
//
/**
* Get Unique Identifier ...
*
* @return ( string )
*/
string GetTag()
{
//
string result = NULL;
//
if (!IsValid())
{
return result;
}
//
string hash = symbol + "_" +
ToString(period) + "_" +
ToString(upper) + "," +
ToString(lower) + "_" +
ToString(from) + "," +
ToString(to);
hash = ToMD5(hash);
//
string typeStr =
type == XPV_PEAK
? "Peak"
: "Vale";
//
result =
//
"XPV_" +
typeStr + "_" +
symbol + "_" +
ToString(period) +
"_" + hash
//
;
//
return result;
}
//
};
//
// Pivots ...
struct XPVPivotPoint
{
//
// Props ...
double value;
int repetition;
datetime time;
ENUM_XPV_PIVOTS type;
//
// Constructor ...
XPVPivotPoint()
{
Clean();
}
//
// Tools ...
/**
* Cleanup ...
*/
void Clean()
{
//
value = 0;
time = NULL;
repetition = 0;
type = XPV_NONE;
}
/**
* Validate ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
//
value > 0 &&
IsValid(time) &&
repetition > 0 &&
type != XPV_NONE
//
;
//
return result;
}
/**
* Check current Pivot Point is Peak or not ...
*
* @return ( bool )
*/
bool IsPeak()
{
//
bool result = false;
//
result = IsValid() &&
type == XPV_PEAK;
//
return result;
}
/**
* Check current Pivot Point is Vale or not ...
*
* @return ( bool )
*/
bool IsVale()
{
//
bool result = false;
//
result = IsValid() &&
type == XPV_VALE;
//
return result;
}
//
};
//
//
//
//
// Consolidation Zone ...
struct XConsolidationZone
{
//
// Props ...
//
string symbol; // Symbol ...
ENUM_TIMEFRAMES period; // Period ...
//
double upper; // Upper ...
double lower; // Lower ...
//
datetime initTime;
int loopback; // Loopback ...
//
ENUM_X_DIRECTION breakDirection; // Break Direction ...
XOHCL breakerBar; // Breaker Bar ...
//
// Constructor ...
XConsolidationZone()
{
Clean();
}
//
// Tools ...
/**
* Initialize Zone ...
*
* @param _symbol: String ...
* @param _period: ENUM_TIMEFRAMES member ...
* @param _upper: Double ...
* @param _lower: Double ...
* @param _loopback: Integer ...
*
* @return ( bool )
*/
bool Init(
string _symbol,
ENUM_TIMEFRAMES _period,
double _upper,
double _lower,
int _loopback //
)
{
//
bool result = false;
//
_symbol = NormalizeSymbol(_symbol);
_period = NormalizePeriod(_period);
//
result =
//
_upper > 0 &&
_lower > 0 &&
_loopback > 0
//
;
if (!result)
{
return result;
}
//
upper = _upper;
lower = _lower;
symbol = _symbol;
period = _period;
loopback = _loopback;
//
result = IsValid();
if (result)
{
initTime = TimeCurrent();
}
//
return result;
}
/**
* Update Breaked State ...
*/
void Update()
{
//
if (!IsValid())
{
return;
}
//
if (IsBreaked())
{
return;
}
//
XOHCL cBar;
bool isInited = cBar.Init(
symbol,
period,
0 //
);
if (!isInited)
{
return;
}
//
XOHCL pBar;
isInited = cBar.GetPreviousBar(pBar);
if (!isInited)
{
return;
}
//
// Check Consolidation Hounts ...
bool isHountTop = cBar.high > upper &&
cBar.low < upper &&
cBar.GetUp() < upper;
bool isHountBottom = cBar.low < lower &&
cBar.high > lower &&
cBar.GetDown() > lower;
bool isHounted = isHountTop ||
isHountBottom;
if (isHounted)
{
//
if (isHountTop)
{
upper = cBar.high;
}
//
if (isHountBottom)
{
lower = cBar.low;
}
//
return;
}
//
// Check Consolidation Breaks ...
bool isBreakTop = (cBar.GetUp() > upper &&
cBar.GetDown() < upper) ||
(cBar.low > upper &&
cBar.high > upper);
bool isBreakBottom = (cBar.GetDown() < lower &&
cBar.GetUp() > lower) ||
(cBar.high < lower &&
cBar.low < lower);
bool isBreaked = isBreakTop ||
isBreakBottom;
if (!isBreaked)
{
return;
}
//
// Calculate Break Direction ...
breakerBar = cBar;
breakDirection = isBreakTop
? X_DIRECTION_BULLISH
: isBreakBottom
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
}
/**
* Cleanup ...
*/
void Clean()
{
//
upper = 0;
lower = 0;
loopback = 0;
symbol = NULL;
period = NULL;
initTime = NULL;
breakerBar.Clean();
breakDirection = X_DIRECTION_NONE;
}
/**
* Validate ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
//
IsValid(symbol) &&
IsValid(period) &&
upper > 0 &&
lower > 0 &&
loopback > 0
//
;
//
return result;
}
/**
* Check Zone is Breaked or not ...
*
* @return ( bool )
*/
bool IsBreaked()
{
//
bool result = false;
//
result = breakerBar.IsValid() &&
HasDirection(breakDirection);
//
return result;
}
/**
* Detect Supply Zone if Exists ...
*
* @return ( bool )
*/
bool HasSupplyZone(
XCSupplyZone *&zone //
)
{
//
bool result = false;
//
result = IsBreaked() &&
breakDirection == X_DIRECTION_BEARISH;
if (!result)
{
return result;
}
//
// Implment Zone Finding ...
int index = breakerBar.Index();
int hhIDX = iHighest(
symbol,
period,
MODE_HIGH,
loopback,
index //
);
result = IsValidIndex(hhIDX);
if (!result)
{
return result;
}
//
XOHCL hhBar;
result = hhBar.Init(
symbol,
period,
hhIDX //
);
if (!result)
{
return result;
}
//
zone = new XCSupplyZone();
result = zone.Init(
hhBar,
loopback //
);
//
return result;
}
/**
* Detect Demand Zone if Exists ...
*
* @return ( bool )
*/
bool HasDemandZone(
XCDemandZone *&zone //
)
{
//
bool result = false;
//
result = IsBreaked() &&
breakDirection == X_DIRECTION_BULLISH;
if (!result)
{
return result;
}
//
// Implment Zone Finding ...
int index = breakerBar.Index();
int llIDX = iLowest(
symbol,
period,
MODE_LOW,
loopback,
index //
);
result = IsValidIndex(llIDX);
if (!result)
{
return result;
}
//
XOHCL llBar;
result = llBar.Init(
symbol,
period,
llIDX //
);
if (!result)
{
return result;
}
//
zone = new XCDemandZone();
result = zone.Init(
llBar,
loopback //
);
//
return result;
}
/**
* Retrieve Start Time ...
*
* @return ( datetime )
*/
datetime From()
{
//
datetime result = NULL;
//
if (!IsValid())
{
return result;
}
//
int startIndex = iBarShift(
symbol,
period,
initTime //
);
//
result = iTime(
symbol,
period,
loopback + startIndex //
);
//
return result;
}
/**
* Retrieve Unique Identifier ...
*
* @return ( string )
*/
string GetTag()
{
//
string result =
//
GetTypeName(this) + "_" +
symbol + "_" +
ToString(period) + "_" +
ToString(upper) + "_" +
ToString(lower)
//
;
//
return result;
}
//
};
/**
* Converts a Consolidation Zone ...
*
* @param zone: XConsolidationZone instance Reference ...
* @param dest: XCZone pointer Reference ...
*
* @return ( bool )
*/
bool ToZone(
XConsolidationZone &zone,
XCZone *&dest //
)
{
//
bool result = false;
//
dest = NULL;
//
result = zone.IsValid();
if (!result)
{
return result;
}
//
dest = new XCZone();
dest.Upper(zone.upper);
dest.Lower(zone.lower);
result = dest.IsValidBoundary();
//
return result;
}
//
// Model Value Changed ...
struct XValueChange
{
//
// Props ...
double before; // Before Change Value ...
double after; // After Change Value ...
datetime time; // Change Time ...
ENUM_X_DIRECTION dir; // Change Direction ...
//
// Constructor ...
XValueChange()
{
Clean();
}
//
// Tools ...
/**
* Initialize ...
*
* @param _before: Double, Value Before Change ...
* @param _after: Double, Value After Change ...
* @param _time: Datetime, Change Time ...
* @param _dir: ENUM_X_DIRECTION member, Specified Changed Direction ...
*
* @return ( bool )
*/
bool Init(
double _before, // Before Change Value ...
double _after, // After Change Value ...
ENUM_X_DIRECTION _dir, // Change Direction ...
datetime _time = NULL // Change Time ...
)
{
//
bool result = false;
//
_time = NormalizeTime(_time);
//
// Validate Inputs ...
result =
//
_after > 0 &&
_before > 0 &&
IsValid(_time) &&
_after != _before &&
HasDirection(_dir)
//
;
if (!result)
{
return result;
}
//
// Set Validated Values ...
dir = _dir;
time = _time;
after = _after;
before = _before;
//
result = IsValid();
//
return result;
}
/**
* Cleaning Up ...
*/
void Clean()
{
//
after = 0;
before = 0;
time = NULL;
dir = X_DIRECTION_NONE;
}
/**
* Validate Model ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
//
after > 0 &&
before > 0 &&
IsValid(time) &&
after != before &&
HasDirection(dir)
//
;
//
return result;
}
/**
* Fill Change Bar ...
*
* @param bar: XOHCL instance Reference, holds Change Bar ...
* @param _symbol: String, Specified Symbol ...
* @param _period: ENUM_TIMEFRAMES _period member, Specified Period ...
*
* @return ( bool )
*/
bool FillBar(
XOHCL &bar,
string _symbol = NULL,
ENUM_TIMEFRAMES _period = NULL //
)
{
//
bool result = false;
//
bar.Clean();
_symbol = NormalizeSymbol(_symbol);
_period = NormalizePeriod(_period);
//
result = IsValid() &&
IsValid(_symbol) &&
IsValid(_period);
if (!result)
{
return result;
}
//
result = bar.Init(
_symbol,
_period,
time //
);
//
return result;
}
//
};
//
// Price Zones Model ...
struct XPriceZones
{
//
XOHCL bar; // if Based On Bar it's Filled ...
double price; // if Based on Price, it's Filled ...
//
int count; // Exists Zones Count ...
//
XCFVG *fairValueGap; // Exists Fair Value Gap ...
XCSupplyZone *supplyZone; // Exists Supply Zone ...
XCDemandZone *demandZone; // Exists Demand Zone ...
XCOrderBlock *orderBlock; // Exists Order Block ...
XCSupportZone *supportZone; // Exists Support Zone ...
XCResistanceZone *resistanceZone; // Exists Resistance Zone ...ّ
//
// Constructor ...
XPriceZones()
{
Clean();
}
/**
* Cleanup ...
*/
void Clean()
{
//
bar.Clean();
price = 0;
//
supplyZone = NULL;
demandZone = NULL;
orderBlock = NULL;
supportZone = NULL;
fairValueGap = NULL;
resistanceZone = NULL;
}
/**
* Check Zone is Valid ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
//
(IsBasedOnBar() ||
IsBasedOnPrice()) &&
IsValidSize(count)
//
;
//
return result;
}
/**
* Check Zones Base on Bar ...
*
* @return ( bool )
*/
bool IsBasedOnBar()
{
return bar.IsValid();
}
/**
* Check Zones Based on Price ...
*
* @return ( bool )
*/
bool IsBasedOnPrice()
{
return price > 0;
}
/**
* Check Has Supply Zone ...
*
* @return ( bool )
*/
bool HasSupplyZone()
{
//
return IsValidSize(count) &&
supplyZone != NULL &&
supplyZone.IsValid();
}
/**
* Check Has Demand Zone ...
*
* @return ( bool )
*/
bool HasDemandZone()
{
//
return IsValidSize(count) &&
demandZone != NULL &&
demandZone.IsValid();
}
/**
* Check Has OrderBlock ...
*
* @return ( bool )
*/
bool HasOrderBlock()
{
//
return IsValidSize(count) &&
orderBlock != NULL &&
orderBlock.IsValid();
}
/**
* Check Has Support Zone ...
*
* @return ( bool )
*/
bool HasSupportZone()
{
//
return IsValidSize(count) &&
supportZone != NULL &&
supportZone.IsValid();
}
/**
* Check Has FairValueGap ...
*
* @return ( bool )
*/
bool HasFairValueGap()
{
//
return IsValidSize(count) &&
fairValueGap != NULL &&
fairValueGap.IsValid();
}
/**
* Check Has Resistance Zone ...
*
* @return ( bool )
*/
bool HasResistanceZone()
{
//
return IsValidSize(count) &&
resistanceZone != NULL &&
resistanceZone.IsValid();
}
/**
* Check Zones are Overal Bullish ...
*
* @return ( bool )
*/
bool IsBullish()
{
//
bool result = false;
//
result =
//
HasDemandZone()
//
||
//
HasSupportZone()
//
||
//
(HasOrderBlock() &&
orderBlock.IsBullish())
//
||
//
(HasFairValueGap() &&
fairValueGap.IsBullish())
//
;
//
return result;
}
/**
* Check Zones are Overal Bearish ...
*
* @return ( bool )
*/
bool IsBearish()
{
//
bool result = false;
//
result =
//
HasSupplyZone()
//
||
//
HasResistanceZone()
//
||
//
(HasOrderBlock() &&
orderBlock.IsBearish())
//
||
//
(HasFairValueGap() &&
fairValueGap.IsBearish())
//
;
//
return result;
}
/**
* Fill Zones Based On required Direction ...
*
* @param dir: ENUM_X_DIRECTION member ...
*
* @return ( int )
*/
int FillZones(
ENUM_X_DIRECTION dir,
XCZone *&zones[] //
)
{
//
int result = 0;
//
Clean(zones);
//
bool isBullish = IsBullish(dir);
bool isBoth = dir == X_DIRECTION_ALL ||
dir == X_DIRECTION_NONE;
//
if (isBoth || isBullish)
{
//
if (HasSupportZone())
{
//
Add(
(XCZone *)supportZone,
zones //
);
}
//
if (HasDemandZone())
{
//
Add(
(XCZone *)demandZone,
zones //
);
}
//
if (HasOrderBlock() &&
orderBlock.IsBullish())
{
//
Add(
(XCZone *)orderBlock,
zones //
);
}
//
if (HasFairValueGap() &&
fairValueGap.IsBullish())
{
//
Add(
(XCZone *)fairValueGap,
zones //
);
}
}
//
if (isBoth || !isBullish)
{
//
if (HasResistanceZone())
{
//
Add(
(XCZone *)resistanceZone,
zones //
);
}
//
if (HasSupplyZone())
{
//
Add(
(XCZone *)supplyZone,
zones //
);
}
//
if (HasOrderBlock() &&
orderBlock.IsBearish())
{
//
Add(
(XCZone *)orderBlock,
zones //
);
}
//
if (HasFairValueGap() &&
fairValueGap.IsBearish())
{
//
Add(
(XCZone *)fairValueGap,
zones //
);
}
}
// s
result = ArraySize(zones);
//
return result;
}
/**
* Calculate Boundary of Zones ...
*
* @param dir: ENUM_X_DIRECTION Member, Specified Direction ...
* @param upper: Double ...
* @param lower: Double ...
*
* @return ( bool )
*/
bool GetBoundary(
ENUM_X_DIRECTION dir,
double &upper,
double &lower //
)
{
//
bool result = false;
//
upper = 0;
lower = 0;
//
XCZone *zones[];
int mCount = FillZones(dir, zones);
result = IsValidSize(mCount);
if (!result)
{
return result;
}
//
for (int i = 0; i < mCount; i++)
{
//
XCZone *iZone = zones[i];
//
double iUpper = iZone.Upper();
double iLower = iZone.Lower();
//
upper =
upper == 0
? iUpper
: iUpper > upper
? iUpper
: upper;
//
lower =
lower == 0
? iLower
: iLower < lower
? iLower
: lower;
}
//
return result;
}
/**
* Calculate Lifetime of Zones ...
*
* @param dir: ENUM_X_DIRECTION Member, Specified Direction ...
* @param from: DateTime ...
* @param to: DateTime ...
*
* @return ( bool )
*/
bool GetLifetime(
ENUM_X_DIRECTION dir,
datetime &from,
datetime &to //
)
{
//
bool result = false;
//
to = NULL;
from = NULL;
//
XCZone *zones[];
int mCount = FillZones(dir, zones);
result = IsValidSize(mCount);
if (!result)
{
return result;
}
//
bool isBullish = IsBullish(dir);
bool isAll = dir == X_DIRECTION_NONE ||
dir == X_DIRECTION_ALL;
//
if (isAll || isBullish)
{
//
// Support Zone ...
bool hasSupportZone = HasSupportZone();
if (hasSupportZone)
{
//
XCSupportZone *zone = supportZone;
//
from =
!IsValid(from) ||
from > zone.From()
? zone.From()
: from;
//
to =
!IsValid(to) ||
to < zone.To()
? zone.To()
: from;
}
//
// Demand Zone ...
bool hasDemandZone = HasDemandZone();
if (hasDemandZone)
{
//
XCDemandZone *zone = demandZone;
//
from =
!IsValid(from) ||
from > zone.From()
? zone.From()
: from;
//
to =
!IsValid(to) ||
to < zone.To()
? zone.To()
: from;
}
//
// Order Block ...
bool hasOrderBlock = HasOrderBlock() &&
orderBlock.IsBullish();
if (hasOrderBlock)
{
//
XCOrderBlock *zone = orderBlock;
//
from =
!IsValid(from) ||
from > zone.From()
? zone.From()
: from;
//
to =
!IsValid(to) ||
to < zone.To()
? zone.To()
: from;
}
//
// Fair Value Gap ...
bool hasFairValueGap = HasFairValueGap() &&
fairValueGap.IsBullish();
if (hasFairValueGap)
{
//
XCFVG *zone = fairValueGap;
//
from =
!IsValid(from) ||
from > zone.From()
? zone.From()
: from;
//
to =
!IsValid(to) ||
to < zone.To()
? zone.To()
: from;
}
}
//
if (isAll || !isBullish)
{
//
// Resistance Zone ...
bool hasResistanceZone = HasResistanceZone();
if (hasResistanceZone)
{
//
XCResistanceZone *zone = resistanceZone;
//
from =
!IsValid(from) ||
from > zone.From()
? zone.From()
: from;
//
to =
!IsValid(to) ||
to < zone.To()
? zone.To()
: from;
}
//
// Supply Zone ...
bool hasSupplyZone = HasSupplyZone();
if (hasSupplyZone)
{
//
XCSupplyZone *zone = supplyZone;
//
from =
!IsValid(from) ||
from > zone.From()
? zone.From()
: from;
//
to =
!IsValid(to) ||
to < zone.To()
? zone.To()
: from;
}
//
// Order Block ...
bool hasOrderBlock = HasOrderBlock() &&
orderBlock.IsBearish();
if (hasOrderBlock)
{
//
XCOrderBlock *zone = orderBlock;
//
from =
!IsValid(from) ||
from > zone.From()
? zone.From()
: from;
//
to =
!IsValid(to) ||
to < zone.To()
? zone.To()
: from;
}
//
// Fair Value Gap ...
bool hasFairValueGap = HasFairValueGap() &&
fairValueGap.IsBearish();
if (hasFairValueGap)
{
//
XCFVG *zone = fairValueGap;
//
from =
!IsValid(from) ||
from > zone.From()
? zone.From()
: from;
//
to =
!IsValid(to) ||
to < zone.To()
? zone.To()
: from;
}
}
//
result =
to > from &&
IsValid(to) &&
IsValid(from);
//
return result;
}
/**
* Calculate Box Model Data ...
*
* @param dir: ENUM_X_DIRECTION Member, Specified Direction ...
* @param upper: Double ...
* @param lower: Double ...
* @param from: DateTime ...
* @param to: DateTime ...
*
* @return ( bool )
*/
bool GetBoxData(
ENUM_X_DIRECTION dir,
double &upper,
double &lower,
datetime &from,
datetime &to //
)
{
//
bool result = false;
//
bool hasBoundary = GetBoundary(
dir,
upper,
lower //
);
//
bool hasLifetime = GetLifetime(
dir,
from,
to //
);
//
result =
hasBoundary &&
hasLifetime;
//
return result;
}
//
};
//
// Market Strucutre Model ...
struct XMarketStructure
{
//
string symbol;
ENUM_TIMEFRAMES period;
//
ENUM_X_DIRECTION bias;
//
XPVPivotPoint vales[];
XPriceZones valePriceZones[];
//
XPVPivotPoint peaks[];
XPriceZones peakPriceZones[];
//
XOHCL lowestValeBar;
XOHCL lowestValePeakBreakeUpBar;
XOHCL valeAboveLowestValePeakBar;
//
XOHCL highestPeakBar;
XOHCL peakBelowHighestPeakValeBar;
XOHCL highestPeakValeBreakeDownBar;
//
XMarketStructure()
{
Clean();
}
/**
* Cleanup ...
*/
void Clean()
{
//
symbol = NULL;
period = NULL;
bias = X_DIRECTION_NONE;
//
Clean(vales);
Clean(peaks);
Clean(valePriceZones);
Clean(peakPriceZones);
//
lowestValeBar.Clean();
lowestValePeakBreakeUpBar.Clean();
valeAboveLowestValePeakBar.Clean();
//
highestPeakBar.Clean();
peakBelowHighestPeakValeBar.Clean();
highestPeakValeBreakeDownBar.Clean();
}
/**
* Validate Model ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
IsValid(symbol) &&
IsValid(period) &&
bias != X_DIRECTION_NONE;
//
return result;
}
/**
* Check Bullish Trend ...
*
* @return ( bool )
*/
bool IsBullish()
{
//
bool result = false;
//
result =
//
IsValid() &&
IsBullish(bias) &&
HasChild(peaks) &&
HasDirection(bias) &&
lowestValeBar.IsValid() &&
HasChild(peakPriceZones) &&
lowestValePeakBreakeUpBar.IsValid() &&
valeAboveLowestValePeakBar.IsValid()
//
;
//
return result;
}
/**
* Check Bearish Trend ...
*
* @return ( bool )
*/
bool IsBearish()
{
//
bool result = false;
//
result =
//
IsValid() &&
IsBearish(bias) &&
HasChild(vales) &&
HasDirection(bias) &&
highestPeakBar.IsValid() &&
HasChild(valePriceZones) &&
peakBelowHighestPeakValeBar.IsValid() &&
highestPeakValeBreakeDownBar.IsValid()
//
;
//
return result;
}
/**
* Check Has Trend ...
*
* @return ( bool )
*/
bool HasTrend()
{
//
bool result = false;
//
result = IsValid() &&
(IsBullish() ||
IsBearish());
//
return result;
}
//
};
struct XStateZones
{
//
XCSupportZone *supportZones[]; // Holds Founded Support Zones ...
XCResistanceZone *resistanceZones[]; // Holds Founded Resistance Zones ...
XCSupplyZone *supplyZones[]; // Holds Founded Supply Zones ...
XCDemandZone *demandZones[]; // Holds Founded Demand Zones ...
XCOrderBlock *bullishOrderBlocks[]; // Holds Founded Bullish Order Blocks ...
XCOrderBlock *bearishOrderBlocks[]; // Holds Founded Bearish Order Blocks ...
XCFVG *bullishFairValueGaps[]; // Holds Founded Bullish Fair Value Gaps ...
XCFVG *bearishFairValueGaps[]; // Holds Founded Bearish Fair Value Gaps ...
//
XStateZones()
{
Clean();
}
/**
* Cleaning Model ...
*/
void Clean()
{
//
Clean(supportZones);
Clean(resistanceZones);
Clean(supplyZones);
Clean(demandZones);
Clean(bullishOrderBlocks);
Clean(bearishOrderBlocks);
Clean(bullishFairValueGaps);
Clean(bearishFairValueGaps);
}
/**
* Validate Model ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
//
IsValidSize(CountSupportZones()) ||
IsValidSize(CountResistanceZones()) ||
IsValidSize(CountSupplyZones()) ||
IsValidSize(CountDemandZones()) ||
IsValidSize(CountBullishOrderBlocks()) ||
IsValidSize(CountBearishOrderBlocks()) ||
IsValidSize(CountBullishFairValueGaps()) ||
IsValidSize(CountBearishFairValueGaps())
//
;
//
return result;
}
//
// Tools ...
//
int CountSupportZones()
{
//
int result = 0;
//
result = ArraySize(supportZones);
//
return result;
}
//
int CountResistanceZones()
{
//
int result = 0;
//
result = ArraySize(resistanceZones);
//
return result;
}
//
int CountSupplyZones()
{
//
int result = 0;
//
result = ArraySize(supplyZones);
//
return result;
}
//
int CountDemandZones()
{
//
int result = 0;
//
result = ArraySize(demandZones);
//
return result;
}
//
int CountBullishOrderBlocks()
{
//
int result = 0;
//
result = ArraySize(bullishOrderBlocks);
//
return result;
}
//
int CountBearishOrderBlocks()
{
//
int result = 0;
//
result = ArraySize(bearishOrderBlocks);
//
return result;
}
//
int CountBullishFairValueGaps()
{
//
int result = 0;
//
result = ArraySize(bullishFairValueGaps);
//
return result;
}
//
int CountBearishFairValueGaps()
{
//
int result = 0;
//
result = ArraySize(bearishFairValueGaps);
//
return result;
}
};
struct XFVGOrderBlock
{
//
// Props ...
XCOrderBlock *orderBlock;
XCFVG *fairValueGap;
// XStateZones stateZones;
//
XFVGOrderBlock()
{
Clean();
}
/**
* Cleanup Model ...
*/
void Clean()
{
//
orderBlock = NULL;
fairValueGap = NULL;
}
/**
* Validate Model ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
//
orderBlock != NULL &&
fairValueGap != NULL &&
// stateZones.IsValid() &&
((orderBlock.IsBullish() &&
fairValueGap.IsBullish()) ||
((orderBlock.IsBearish() &&
fairValueGap.IsBearish())))
//
;
//
return result;
}
/**
* Get Model Direction ...
*
* @param dir: ENUM_X_DIRECTION member ...
*
* @return ( bool )
*/
bool GetDirection(
ENUM_X_DIRECTION &dir //
)
{
//
bool result = false;
//
dir = X_DIRECTION_NONE;
//
result = IsValid();
if (!result)
{
return result;
}
//
dir = orderBlock.IsBullish()
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
return result;
}
/**
* Retrieve Boundary of Zone ...
*
* @param upper: Upper Boundary ...ّ
* @param lower: Lower Bondary ...
* @return ( bool )
*/
bool GetBoundary(
double &upper,
double &lower //
)
{
//
bool result = false;
//
upper = 0;
lower = 0;
//
result = IsValid();
if (!result)
{
return result;
}
//
upper = orderBlock.Upper();
upper = MathMax(upper, fairValueGap.Upper());
//
lower = orderBlock.Lower();
lower = MathMax(lower, fairValueGap.Lower());
//
result = lower > 0 &&
upper > 0 &&
upper > lower;
//
return result;
}
/**
* Check Model is same as another Istance ...
*
* @param value: XFVGOrderBlock instance Reference ...
*
* @return ( bool )
*/
bool IsSameAs(XFVGOrderBlock &value)
{
//
bool result = false;
//
result =
IsValid() &&
value.IsValid();
if (!result)
{
return result;
}
//
ENUM_X_DIRECTION dir;
result = GetDirection(dir);
if (!result)
{
return result;
}
//
ENUM_X_DIRECTION valueDir;
result = value.GetDirection(valueDir);
if (!result)
{
return result;
}
//
result =
//
dir == valueDir
//
&&
//
orderBlock.From() == value.orderBlock.From() &&
orderBlock.Upper() == value.orderBlock.Upper() &&
orderBlock.Lower() == value.orderBlock.Lower()
//
&&
//
fairValueGap.From() == value.fairValueGap.From() &&
fairValueGap.Upper() == value.fairValueGap.Upper() &&
fairValueGap.Lower() == value.fairValueGap.Lower()
//
;
//
return result;
}
//
};
struct XBoxZone
{
//
// Props ...
string symbol;
ENUM_TIMEFRAMES period;
//
double upper;
double lower;
//
datetime from;
datetime to;
//
string type;
ENUM_X_DIRECTION dir;
//
// Constructor ...
XBoxZone()
{
Clean();
}
//
// Tools ...
/**
* Cleanup Model ...
*/
void Clean()
{
//
upper = 0;
lower = 0;
to = NULL;
from = NULL;
symbol = NULL;
period = NULL;
dir = X_DIRECTION_NONE;
}
/**
* Validate Model ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
//
upper > 0 &&
lower > 0 &&
from < to &&
IsValid(to) &&
upper > lower &&
IsValid(from) &&
IsValid(symbol) &&
IsValid(period)
//
;
//
return result;
}
};
//
// Extensions ...
/**
* Converts ENUM_XPOI value to String Representation ...
*
* @param value: ENUM_XPOI member ...
*
* @return ( string )
*/
string ToString(ENUM_XPOIS value)
{
//
string result = NULL;
//
switch (value)
{
//
case X_POI_TRADING_DAY:
result = "XTDAY";
break;
//
case X_POI_MARKET_SESSION:
result = "XMSESS";
break;
//
case X_POI_MOMENTUM_BAR:
result = "XMNTMB";
break;
//
case X_POI_REJECTION_BAR:
result = "XRJCTB";
break;
//
case X_POI_SWING_HIGH:
result = "XSPH";
break;
//
case X_POI_SWING_LOW:
result = "XSPL";
break;
//
case X_POI_SUPPORT_ZONE:
result = "XSUP";
break;
//
case X_POI_RESISTANCE_ZONE:
result = "XRES";
break;
//
case X_POI_SUPPLY_ZONE:
result = "XSUPPLY";
break;
//
case X_POI_DEMAND_ZONE:
result = "XDEMAND";
break;
//
case X_POI_BULLISH_ORDERBLOCK:
result = "XBULLOB";
break;
//
case X_POI_BEARISH_ORDERBLOCK:
result = "XBEAROB";
break;
//
case X_POI_BULLISH_FVG:
result = "XBULLFVG";
break;
//
case X_POI_BEARISH_FVG:
result = "XBEARFVG";
break;
//
case X_POI_TICKS_ZONES:
result = "XTKSZ";
break;
}
//
return result;
}
/**
* Converts ENUM_XSESSION value to String Representation ...
*
* @param value: ENUM_XSESSION member ...
*
* @return ( string )
*/
string ToString(ENUM_XSESSION value)
{
//
string result = NULL;
//
switch (value)
{
//
case X_SYDNEY:
result = "Sydney";
break;
//
case X_TOKYO:
result = "Tokyo";
break;
//
case X_FRANKFORT:
result = "FrankGurt";
break;
//
case X_LONDON:
result = "London";
break;
//
case X_NEW_YORK:
result = "NewYork";
break;
}
//
return result;
}
/**
* Generate General Event Messages ...
*
* @param value: ENUM_XPOI_EVENTS member ...
*
* @return ( string )
*/
string ToString(ENUM_XPOI_EVENTS value)
{
//
string result = NULL;
//
switch (value)
{
//
case X_TRADE_DAY_FIRST_BAR:
result = "First Bar of Day";
break;
//
case X_TRADE_DAY_LAST_BAR:
result = "Last Bar of Day";
break;
//
case X_SESSION_FIRST_BAR:
result = "First Bar of Session";
break;
//
case X_SESSION_LAST_BAR:
result = "Last Bar of Session";
break;
//
case X_BULLISH_MOMENTUM_BAR_DETECTED:
result = "Bullish Momentum Bar Detected";
break;
//
case X_BEARISH_MOMENTUM_BAR_DETECTED:
result = "Bearish Momentum Bar Detected";
break;
//
case X_BULLISH_REJECTION_BAR_DETECTED:
result = "Bullish Rejection Bar Detected";
break;
//
case X_BEARISH_REJECTION_BAR_DETECTED:
result = "Bearish Rejection Bar Detected";
break;
//
case X_SWING_HIGH_DETECTED:
result = "Swing High Detected";
break;
//
case X_SWING_LOW_DETECTED:
result = "Swing Low Detected";
break;
//
case X_SUPPORT_ZONE_DETECTED:
result = "Support Zone Detected";
break;
//
case X_RESISTANCE_ZONE_DETECTED:
result = "Resistance Zone Detected";
break;
//
case X_SUPPLY_ZONE_DETECTED:
result = "Supply Zone Detected";
break;
//
case X_DEMAND_ZONE_DETECTED:
result = "Demand Zone Detected";
break;
//
case X_BULLISH_ORDERBLOCK_DETECTED:
result = "Bullish Order Block Detected";
break;
//
case X_BEARISH_ORDERBLOCK_DETECTED:
result = "Bearish Orer Block Detected";
break;
//
case X_BULLISH_FVG_DETECTED:
result = "Bullish FVG Detected";
break;
//
case X_BEARISH_FVG_DETECTED:
result = "Bearish FVg Detected";
break;
}
//
return result;
}
//
//
//
/**
* Find Oldest Pivot Index ...
*
* @param pivots: XPVPivot instance ...
* @return ( int )
*/
int FindOldestPivotIndex(
XPVPivot &pivots[] //
)
{
//
int result = -1;
//
int count = ArraySize(pivots);
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
XPVPivot iPivot = pivots[i];
//
bool isOldest = true;
for (int j = 0; j < count; j++)
{
//
XPVPivot jPivot = pivots[j];
//
isOldest = iPivot.from <= jPivot.from;
if (!isOldest)
{
break;
}
}
//
if (isOldest)
{
//
result = i;
break;
}
}
//
return result;
}
/**
* Sort Pivots Based On From Date ...
*
* @param pivots: XPVPivot instance Collection reference ...
*/
void SortPivots(
XPVPivot &pivots[] //
)
{
//
XPVPivot tmp[];
Copy(
pivots,
tmp //
);
//
Clean(pivots);
//
while (ArraySize(tmp) > 0)
{
//
if (ArraySize(tmp) == 1)
{
//
AddRef(
tmp[0],
pivots //
);
//
ArrayRemove(
tmp,
0,
1);
}
else
{
//
int idx = FindOldestPivotIndex(tmp);
if (IsValidIndex(idx))
{
//
AddRef(
tmp[idx],
pivots //
);
//
ArrayRemove(
tmp,
idx,
1 //
);
}
}
}
//
Clean(tmp);
}
bool IsPivotBreaked(
XPVPivot &pivot,
XPVPivot &pivots[] //
)
{
//
bool result = false;
//
result = pivot.IsValid();
if (!result)
{
return result;
}
//
int count = ArraySize(pivots);
result = IsValidSize(pivots);
if (!result)
{
return result;
}
//
// For Peaks Highs Must not Broked ...
// For Vales Lows Must not Broked ...
bool isPeak = pivot.IsPeak();
//
for (int i = 0; i < count; i++)
{
//
XPVPivot iPivot = pivots[i];
//
result = isPeak
? iPivot.upper > pivot.upper
: iPivot.lower < pivot.lower;
if (result)
{
break;
}
}
//
return result;
}
/**
* Filter Broken Pivots for Detect Order Flow ...
*
* @param pivots: XPVPivot instance Collection reference ...
*/
void FilterBrokenPivots(
XPVPivot &pivots[] //
)
{
//
XPVPivot tmp[];
Copy(
pivots,
tmp //
);
//
Clean(pivots);
//
while (ArraySize(tmp) > 0)
{
//
if (ArraySize(tmp) == 1)
{
//
AddRef(
tmp[0],
pivots //
);
//
ArrayRemove(
tmp,
0,
1 //
);
}
else
{
//
XPVPivot pivot = tmp[0];
//
ArrayRemove(
tmp,
0,
1 //
);
//
bool isBreaked = IsPivotBreaked(
pivot,
tmp //
);
if (!isBreaked)
{
//
AddRef(
pivot,
pivots //
);
}
}
}
//
Clean(tmp);
}
/**
* Calculate Order Flow Direction ...
*
* @param orderFlow: XPVPivot instance Collection reference ...
* @param dir: ENUM_X_DIRECTION member reference, Hold's Calculated Direction ...
*
* @return ( bool )
*/
bool DetectPivotDirection(
XPVPivot &orderFlow[],
ENUM_X_DIRECTION &dir //
)
{
//
bool result = false;
//
dir = X_DIRECTION_NONE;
//
int count = ArraySize(orderFlow);
result = IsValidSize(count);
if (!result)
{
return result;
}
//
// For Bullish Direction all Exists lowers must be Greater or Equal Prev ...
bool isBullish = false;
bool canLookupForBullish = true;
//
// For Bearish Direction all Exists uppers must be Lesser or Equal Prev ...
bool isBearish = false;
bool canLookupForBearish = true;
//
for (int i = 0; i < count; i++)
{
//
XPVPivot iPivot = orderFlow[i];
//
XPVPivot tmp[];
Copy(
orderFlow,
tmp //
);
ArrayRemove(
tmp,
0,
i + 1 //
);
//
int tmpCount = ArraySize(tmp);
if (IsValidSize(tmpCount))
{
//
for (int j = 0; j < tmpCount; j++)
{
//
XPVPivot jPivot = tmp[j];
//
// Check Bullish Direction ...
isBullish =
canLookupForBullish &&
jPivot.lower >= iPivot.lower;
if (!isBullish)
{
canLookupForBullish = false;
}
//
// Check Bearish Direction ...
isBearish =
canLookupForBearish &&
jPivot.upper <= iPivot.upper;
if (!isBearish)
{
canLookupForBearish = false;
}
//
if (!canLookupForBullish &&
!canLookupForBearish)
{
break;
}
}
}
Clean(tmp);
}
//
if (isBullish &&
!isBearish)
{
dir = X_DIRECTION_BULLISH;
}
else if (isBearish &&
!isBullish)
{
dir = X_DIRECTION_BEARISH;
}
//
result = dir != X_DIRECTION_NONE;
//
return result;
}
/**
* Detect all POIs which inside a Pivot ...
*
* @param pivot: XPVPivot instance, Specified Pivot ...
* @param source: XPOIState instance, Reference to Source State ...
* @param state: XPOIState instance, Reference to Detected Pivots ...
* @param lookupSwingHighs: Boolean ...
* @param lookupSwingLows: Boolean ...
* @param lookupSupportZones: Boolean ...
* @param lookupResistanceZones: Boolean ...
* @param lookupSupplyZones: Boolean ...
* @param lookupDemandZones: Boolean ...
* @param lookupBullishOrderBlocks: Boolean ...
* @param lookupBearishOrderBlocks: Boolean ...
* @param lookupBullishFairValueGaps: Boolean ...
* @param lookupBearishFairValueGaps: Boolean ...
* @param lookupBullishRejectionBars: Boolean ...
* @param lookupBearishRejectionBars: Boolean ...
* @param lookupBullishMomentumBars: Boolean ...
* @param lookupBearishMomentumBars: Boolean ...
*/
void DetectPivotPOIs(
XPVPivot &pivot,
XPOIState &source,
XPOIState &state,
bool lookupSwingHighs = true,
bool lookupSwingLows = true,
bool lookupSupportZones = true,
bool lookupResistanceZones = true,
bool lookupSupplyZones = true,
bool lookupDemandZones = true,
bool lookupBullishOrderBlocks = true,
bool lookupBearishOrderBlocks = true,
bool lookupBullishFairValueGaps = true,
bool lookupBearishFairValueGaps = true,
bool lookupBullishRejectionBars = true,
bool lookupBearishRejectionBars = true,
bool lookupBullishMomentumBars = true,
bool lookupBearishMomentumBars = true //
)
{
//
state.Clean();
//
if (!pivot.IsValid())
{
return;
}
//
int count = 0;
//
state.symbol = pivot.symbol;
state.period = pivot.period;
state.time = TimeCurrent();
//
// Swings ...
//
// Swing High ...
if (lookupSwingHighs)
{
//
count = ArraySize(source.swingHighs);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCSwing *iSwing = source.swingHighs[i];
//
XOHCL iBar;
bool isFilled = iSwing.FillBar(iBar);
if (!isFilled)
{
continue;
}
//
bool isInside = iBar.high <= pivot.upper;
if (isInside)
{
//
// iSwing.To(pivot.to);
//
Add(
iSwing,
state.swingHighs //
);
}
}
}
}
//
// Swing Low ...
if (lookupSwingLows)
{
//
count = ArraySize(source.swingLows);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCSwing *iSwing = source.swingLows[i];
//
XOHCL iBar;
bool isFilled = iSwing.FillBar(iBar);
if (!isFilled)
{
continue;
}
//
bool isInside = iBar.low >= pivot.lower;
if (isInside)
{
//
// iSwing.To(pivot.to);
//
Add(
iSwing,
state.swingLows //
);
}
}
}
}
//
// Support and Resistance Zones ...
//
// Support Zones ...
if (lookupSupportZones)
{
//
count = ArraySize(source.supportZones);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCSupportZone *iZone = source.supportZones[i];
//
bool isInside =
iZone.Upper() <= pivot.upper &&
iZone.Lower() >= pivot.lower;
if (isInside)
{
//
iZone.To(pivot.to);
//
Add(
iZone,
state.supportZones //
);
}
}
}
}
//
// Resistance Zones ...
if (lookupResistanceZones)
{
//
count = ArraySize(source.resistanceZones);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCResistanceZone *iZone = source.resistanceZones[i];
//
bool isInside =
iZone.Upper() <= pivot.upper &&
iZone.Lower() >= pivot.lower;
if (isInside)
{
//
iZone.To(pivot.to);
//
Add(
iZone,
state.resistanceZones //
);
}
}
}
}
//
// Supply and Demand Zones ...
//
// Supply Zones ...
if (lookupSupplyZones)
{
//
count = ArraySize(source.supplyZones);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCSupplyZone *iZone = source.supplyZones[i];
//
bool isInside =
iZone.Upper() <= pivot.upper &&
iZone.Lower() >= pivot.lower;
if (isInside)
{
//
iZone.To(pivot.to);
//
Add(
iZone,
state.supplyZones //
);
}
}
}
}
//
// Demand Zones ...
if (lookupDemandZones)
{
//
count = ArraySize(source.demandZones);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCDemandZone *iZone = source.demandZones[i];
//
bool isInside =
iZone.Upper() <= pivot.upper &&
iZone.Lower() >= pivot.lower;
if (isInside)
{
//
iZone.To(pivot.to);
//
Add(
iZone,
state.demandZones //
);
}
}
}
}
//
// Order Blocks ...
//
// Bullish Order Blocks ...
if (lookupBullishOrderBlocks)
{
//
count = ArraySize(source.bullishOrderBlocks);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *iZone = source.bullishOrderBlocks[i];
//
bool isInside =
iZone.Upper() <= pivot.upper &&
iZone.Lower() >= pivot.lower;
if (isInside)
{
//
iZone.To(pivot.to);
//
Add(
iZone,
state.bullishOrderBlocks //
);
}
}
}
}
//
// Bearish Order Blocks ...
if (lookupBearishOrderBlocks)
{
//
count = ArraySize(source.bearishOrderBlocks);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *iZone = source.bearishOrderBlocks[i];
//
bool isInside =
iZone.Upper() <= pivot.upper &&
iZone.Lower() >= pivot.lower;
if (isInside)
{
//
iZone.To(pivot.to);
//
Add(
iZone,
state.bearishOrderBlocks //
);
}
}
}
}
//
// Fair Value Gaps ...
//
// Bullish Fair Value Gaps ...
if (lookupBullishFairValueGaps)
{
//
count = ArraySize(source.bullishFairValueGaps);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCFVG *iZone = source.bullishFairValueGaps[i];
//
bool isInside =
iZone.Upper() <= pivot.upper &&
iZone.Lower() >= pivot.lower;
if (isInside)
{
//
iZone.To(pivot.to);
//
Add(
iZone,
state.bullishFairValueGaps //
);
}
}
}
}
//
// Bearish Fair Value Gaps ...
if (lookupBearishFairValueGaps)
{
//
count = ArraySize(source.bearishFairValueGaps);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCFVG *iZone = source.bearishFairValueGaps[i];
//
bool isInside =
iZone.Upper() <= pivot.upper &&
iZone.Lower() >= pivot.lower;
if (isInside)
{
//
iZone.To(pivot.to);
//
Add(
iZone,
state.bearishFairValueGaps //
);
}
}
}
}
//
// Rejection Bars ...
//
// Bullish Rejection Bars ...
if (lookupBullishRejectionBars)
{
//
count = ArraySize(source.bullishRejectionBars);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCRejectionBar *iRejection = source.bullishRejectionBars[i];
//
XOHCL iBar;
bool isFilled = iRejection.FillBar(iBar);
if (!isFilled)
{
continue;
}
//
bool isInside = iBar.low <= pivot.upper &&
iBar.low >= pivot.lower;
if (isInside)
{
//
iRejection.To(pivot.to);
//
Add(
iRejection,
state.bullishRejectionBars //
);
}
}
}
}
//
// Bearish Rejection Bars ...
if (lookupBearishRejectionBars)
{
//
count = ArraySize(source.bearishRejectionBars);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCRejectionBar *iRejection = source.bearishRejectionBars[i];
//
XOHCL iBar;
bool isFilled = iRejection.FillBar(iBar);
if (!isFilled)
{
continue;
}
//
bool isInside = iBar.high <= pivot.upper &&
iBar.high >= pivot.lower;
if (isInside)
{
//
iRejection.To(pivot.to);
//
Add(
iRejection,
state.bearishRejectionBars //
);
}
}
}
}
//
// Momentum Bars ...
//
// Bullish Momentum Bars ...
if (lookupBullishMomentumBars)
{
//
count = ArraySize(source.bullishMomentumBars);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCMomentumBar *iMomentum = source.bullishMomentumBars[i];
//
XOHCL iBar;
bool isFilled = iMomentum.FillBar(iBar);
if (!isFilled)
{
continue;
}
//
bool isInside = iBar.low <= pivot.upper &&
iBar.low >= pivot.lower;
if (isInside)
{
//
iMomentum.To(pivot.to);
//
Add(
iMomentum,
state.bullishMomentumBars //
);
}
}
}
}
//
// Bearish Momenum Bars ...
if (lookupBearishMomentumBars)
{
//
count = ArraySize(source.bearishMomentumBars);
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCMomentumBar *iMomentum = source.bearishMomentumBars[i];
//
XOHCL iBar;
bool isFilled = iMomentum.FillBar(iBar);
if (!isFilled)
{
continue;
}
//
bool isInside = iBar.high <= pivot.upper &&
iBar.high >= pivot.lower;
if (isInside)
{
//
iMomentum.To(pivot.to);
//
Add(
iMomentum,
state.bearishMomentumBars //
);
}
}
}
}
}
/**
* Fill Pivot Tick Zone ...
*
* @param pivot: XPVPivot instance Reference ...
*/
void CalculatePivotTickZone(
XPVPivot &pivot,
int ticksLevels,
int ticksRange,
ENUM_TIMEFRAMES _period = NULL //
)
{
//
string symbol = pivot.symbol;
ENUM_TIMEFRAMES period = IsValid(_period)
? _period
: pivot.period;
//
bool isInited = false;
//
datetime from = pivot.from;
XOHCL iFromBar;
int iFromBarIndex = iBarShift(
symbol,
period,
from //
);
isInited = iFromBar.Init(
symbol,
period,
iFromBarIndex //
);
if (!isInited)
{
return;
}
//
datetime to = pivot.to;
XOHCL iToBar;
int iToBarIndex = iBarShift(
symbol,
period,
to //
);
isInited = iToBar.Init(
symbol,
period,
iToBarIndex //
);
if (!isInited)
{
return;
}
//
if (iFromBarIndex <= iToBarIndex)
{
return;
}
//
XCTicksZone *iZone;
iZone = new XCTicksZone();
//
isInited = ticksLevels > 0 &&
ticksRange > 0;
if (!isInited)
{
return;
}
//
isInited = iZone.Init(
iFromBar,
iToBar //
);
if (!isInited)
{
return;
}
//
pivot.state.ticksZone = iZone;
}
/**
* Filter State based on Pivot ...
*
* @param pivot: XPVPivot instance Reference ...
* @param state: XPOIState instance Reference ...
*/
void FilterPivotState(
XPVPivot &pivot,
XPOIState &state //
)
{
//
bool isValid =
pivot.IsValid() &&
state.IsValid() &&
state.HasChild();
if (!isValid)
{
return;
}
//
int count = 0;
//
double upper = pivot.upper;
double lower = pivot.lower;
//
//
//
//
// Resistance ...
count = state.CountResistanceZones();
if (IsValidSize(count))
{
//
XCResistanceZone *tmp[];
Copy(
state.resistanceZones,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCResistanceZone *item = tmp[i];
//
bool isValid = IsPriceInsideZone(
upper,
item //
);
if (!isValid)
{
//
ArrayRemove(
state.resistanceZones,
i,
1 //
);
}
}
//
ArrayFree(tmp);
}
//
// Supply ...
count = state.CountSupplyZones();
if (IsValidSize(count))
{
//
XCSupplyZone *tmp[];
Copy(
state.supplyZones,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCSupplyZone *item = tmp[i];
//
bool isValid = IsPriceInsideZone(
upper,
item //
);
if (!isValid)
{
//
ArrayRemove(
state.supplyZones,
i,
1 //
);
}
}
//
ArrayFree(tmp);
}
//
// Bearish Order Block ...
count = state.CountBearishOrderBlocks();
if (IsValidSize(count))
{
//
XCOrderBlock *tmp[];
Copy(
state.bearishOrderBlocks,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *item = tmp[i];
//
bool isValid = IsPriceInsideZone(
upper,
item //
);
if (!isValid)
{
//
ArrayRemove(
state.bearishOrderBlocks,
i,
1 //
);
}
}
//
ArrayFree(tmp);
}
//
// Bearish Fair Value Gap ...
count = state.CountBearishFairValueGaps();
if (IsValidSize(count))
{
//
XCFVG *tmp[];
Copy(
state.bearishFairValueGaps,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCFVG *item = tmp[i];
//
bool isValid = IsPriceInsideZone(
upper,
item //
);
if (!isValid)
{
//
ArrayRemove(
state.bearishFairValueGaps,
i,
1 //
);
}
}
//
ArrayFree(tmp);
}
//
//
//
//
// Support ...
count = state.CountSupportZones();
if (IsValidSize(count))
{
//
XCSupportZone *tmp[];
Copy(
state.supportZones,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCSupportZone *item = tmp[i];
//
bool isValid = IsPriceInsideZone(
lower,
item //
);
if (!isValid)
{
//
ArrayRemove(
state.supportZones,
i,
1 //
);
}
}
//
ArrayFree(tmp);
}
//
// Demand ...
count = state.CountDemandZones();
if (IsValidSize(count))
{
//
XCDemandZone *tmp[];
Copy(
state.demandZones,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCDemandZone *item = tmp[i];
//
bool isValid = IsPriceInsideZone(
lower,
item //
);
if (!isValid)
{
//
ArrayRemove(
state.demandZones,
i,
1 //
);
}
}
//
ArrayFree(tmp);
}
//
// Bullish Order Block ...
count = state.CountBullishOrderBlocks();
if (IsValidSize(count))
{
//
XCOrderBlock *tmp[];
Copy(
state.bullishOrderBlocks,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *item = tmp[i];
//
bool isValid = IsPriceInsideZone(
lower,
item //
);
if (!isValid)
{
//
ArrayRemove(
state.bullishOrderBlocks,
i,
1 //
);
}
}
//
ArrayFree(tmp);
}
//
// Bullish Fair Value Gap ...
count = state.CountBullishFairValueGaps();
if (IsValidSize(count))
{
//
XCFVG *tmp[];
Copy(
state.bullishFairValueGaps,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCFVG *item = tmp[i];
//
bool isValid = IsPriceInsideZone(
lower,
item //
);
if (!isValid)
{
//
ArrayRemove(
state.bullishFairValueGaps,
i,
1 //
);
}
}
//
ArrayFree(tmp);
}
}
/**
* Detect Box Date of Specified Pivot ...
*/
bool DetectPivotStateBoxData(
XPVPivot &pivot,
double &peakUpper,
double &peakLower,
datetime &peakFrom,
datetime &peakTo,
double &valeUpper,
double &valeLower,
datetime &valeFrom,
datetime &valeTo //
)
{
//
bool result = false;
//
peakUpper = 0;
peakLower = 0;
valeUpper = 0;
valeLower = 0;
//
peakFrom = NULL;
peakTo = NULL;
valeFrom = NULL;
valeTo = NULL;
//
result = pivot.IsValid();
if (!result)
{
return result;
}
//
int count = 0;
//
//
//
//
// Resistance ...
count = pivot.state.CountResistanceZones();
if (IsValidSize(count))
{
//
XCResistanceZone *tmp[];
Copy(
pivot.state.resistanceZones,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCResistanceZone *item = tmp[i];
//
if (peakUpper == 0 ||
peakUpper < item.Upper())
{
peakUpper = item.Upper();
}
//
if (peakLower == 0 ||
peakLower > item.Lower())
{
peakLower = item.Lower();
}
//
if (!IsValid(peakFrom) ||
peakFrom > item.From())
{
peakFrom = item.From();
}
//
if (!IsValid(peakTo) ||
peakTo < item.To())
{
peakTo = item.To();
}
}
//
ArrayFree(tmp);
}
//
// Supply ...
count = pivot.state.CountSupplyZones();
if (IsValidSize(count))
{
//
XCSupplyZone *tmp[];
Copy(
pivot.state.supplyZones,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCSupplyZone *item = tmp[i];
//
if (peakUpper == 0 ||
peakUpper < item.Upper())
{
peakUpper = item.Upper();
}
//
if (peakLower == 0 ||
peakLower > item.Lower())
{
peakLower = item.Lower();
}
//
if (!IsValid(peakFrom) ||
peakFrom > item.From())
{
peakFrom = item.From();
}
//
if (!IsValid(peakTo) ||
peakTo < item.To())
{
peakTo = item.To();
}
}
//
ArrayFree(tmp);
}
//
// Bearish Order Block ...
count = pivot.state.CountBearishOrderBlocks();
if (IsValidSize(count))
{
//
XCOrderBlock *tmp[];
Copy(
pivot.state.bearishOrderBlocks,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *item = tmp[i];
//
if (peakUpper == 0 ||
peakUpper < item.Upper())
{
peakUpper = item.Upper();
}
//
if (peakLower == 0 ||
peakLower > item.Lower())
{
peakLower = item.Lower();
}
//
if (!IsValid(peakFrom) ||
peakFrom > item.From())
{
peakFrom = item.From();
}
//
if (!IsValid(peakTo) ||
peakTo < item.To())
{
peakTo = item.To();
}
}
//
ArrayFree(tmp);
}
//
// Bearish Fair Value Gap ...
count = pivot.state.CountBearishFairValueGaps();
if (IsValidSize(count))
{
//
XCFVG *tmp[];
Copy(
pivot.state.bearishFairValueGaps,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCFVG *item = tmp[i];
//
if (peakUpper == 0 ||
peakUpper < item.Upper())
{
peakUpper = item.Upper();
}
//
if (peakLower == 0 ||
peakLower > item.Lower())
{
peakLower = item.Lower();
}
//
if (!IsValid(peakFrom) ||
peakFrom > item.From())
{
peakFrom = item.From();
}
//
if (!IsValid(peakTo) ||
peakTo < item.To())
{
peakTo = item.To();
}
}
//
ArrayFree(tmp);
}
//
//
//
//
// Support ...
count = pivot.state.CountSupportZones();
if (IsValidSize(count))
{
//
XCSupportZone *tmp[];
Copy(
pivot.state.supportZones,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCSupportZone *item = tmp[i];
//
if (valeUpper == 0 ||
valeUpper < item.Upper())
{
valeUpper = item.Upper();
}
//
if (valeLower == 0 ||
valeLower > item.Lower())
{
valeLower = item.Lower();
}
//
if (!IsValid(valeFrom) ||
valeFrom > item.From())
{
valeFrom = item.From();
}
//
if (!IsValid(valeTo) ||
valeTo < item.To())
{
valeTo = item.To();
}
}
//
ArrayFree(tmp);
}
//
// Demand ...
count = pivot.state.CountDemandZones();
if (IsValidSize(count))
{
//
XCDemandZone *tmp[];
Copy(
pivot.state.demandZones,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCDemandZone *item = tmp[i];
//
if (valeUpper == 0 ||
valeUpper < item.Upper())
{
valeUpper = item.Upper();
}
//
if (valeLower == 0 ||
valeLower > item.Lower())
{
valeLower = item.Lower();
}
//
if (!IsValid(valeFrom) ||
valeFrom > item.From())
{
valeFrom = item.From();
}
//
if (!IsValid(valeTo) ||
valeTo < item.To())
{
valeTo = item.To();
}
}
//
ArrayFree(tmp);
}
//
// Bullish Order Block ...
count = pivot.state.CountBullishOrderBlocks();
if (IsValidSize(count))
{
//
XCOrderBlock *tmp[];
Copy(
pivot.state.bullishOrderBlocks,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *item = tmp[i];
//
if (valeUpper == 0 ||
valeUpper < item.Upper())
{
valeUpper = item.Upper();
}
//
if (valeLower == 0 ||
valeLower > item.Lower())
{
valeLower = item.Lower();
}
//
if (!IsValid(valeFrom) ||
valeFrom > item.From())
{
valeFrom = item.From();
}
//
if (!IsValid(valeTo) ||
valeTo < item.To())
{
valeTo = item.To();
}
}
//
ArrayFree(tmp);
}
//
// Bullish Fair Value Gap ...
count = pivot.state.CountBullishFairValueGaps();
if (IsValidSize(count))
{
//
XCFVG *tmp[];
Copy(
pivot.state.bullishFairValueGaps,
tmp //
);
//
for (int i = 0; i < count; i++)
{
//
XCFVG *item = tmp[i];
//
if (valeUpper == 0 ||
valeUpper < item.Upper())
{
valeUpper = item.Upper();
}
//
if (valeLower == 0 ||
valeLower > item.Lower())
{
valeLower = item.Lower();
}
//
if (!IsValid(valeFrom) ||
valeFrom > item.From())
{
valeFrom = item.From();
}
//
if (!IsValid(valeTo) ||
valeTo < item.To())
{
valeTo = item.To();
}
}
//
ArrayFree(tmp);
}
//
result = peakUpper > 0 &&
peakLower > 0 &&
valeUpper > 0 &&
valeLower > 0 &&
IsValid(peakTo) &&
IsValid(valeTo) &&
IsValid(peakFrom) &&
IsValid(valeFrom) &&
peakTo > peakFrom &&
valeTo > valeFrom &&
peakUpper > peakLower &&
valeUpper > valeLower;
//
return result;
}
/**
* Detect Price Inside Zones ...
*
* @param state: XPOIState instance Reference ...
* @param bar: XOHCL instance Reference ...
* @param hasSupport: Boolean ...
* @param hasResistanceZone: Boolean ...
* @param hasSupplyZone: Boolean ...
* @param hasDemandZone: Boolean ...
* @param hasOrderBlock: Boolean ...
* @param hasFairValueGap: Boolean ...
* @return ( bool )
*/
bool DetectPriceInsideZones(
XPOIState &state,
XOHCL &bar,
int &zonesCount,
bool &hasSupportZone,
XCSupportZone *&supportZone,
bool &hasResistanceZone,
XCResistanceZone *&resistanceZone,
bool &hasSupplyZone,
XCSupplyZone *&supplyZone,
bool &hasDemandZone,
XCDemandZone *&demandZone,
bool &hasOrderBlock,
XCOrderBlock *&orderBlock,
bool &hasFairValueGap,
XCFVG *&fairValueGap //
)
{
//
bool result = false;
//
zonesCount = 0;
//
hasSupportZone = false;
hasResistanceZone = false;
hasSupplyZone = false;
hasDemandZone = false;
hasOrderBlock = false;
hasFairValueGap = false;
//
supportZone = NULL;
resistanceZone = NULL;
supplyZone = NULL;
demandZone = NULL;
orderBlock = NULL;
fairValueGap = NULL;
//
datetime cTime = TimeCurrent();
//
result = bar.IsValid() &&
state.IsValid() &&
state.HasChild();
if (!result)
{
return result;
}
//
int count = 0;
//
// Support Zone ...
count = state.CountSupportZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCSupportZone *iZone = state.supportZones[i];
//
bool isValid = IsPriceInsideZone(bar, iZone);
if (isValid)
{
//
supportZone = iZone;
}
}
//
hasSupportZone = supportZone != NULL &&
supportZone.IsValid();
if (hasSupportZone)
{
//
zonesCount++;
supportZone.To(cTime);
}
}
//
// Resistance Zone ...
count = state.CountResistanceZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCResistanceZone *iZone = state.resistanceZones[i];
//
bool isValid = IsPriceInsideZone(bar, iZone);
if (isValid)
{
//
resistanceZone = iZone;
}
}
//
hasResistanceZone = resistanceZone != NULL &&
resistanceZone.IsValid();
if (hasResistanceZone)
{
//
zonesCount++;
resistanceZone.To(cTime);
}
}
//
// Supply Zone ...
count = state.CountSupplyZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCSupplyZone *iZone = state.supplyZones[i];
//
bool isValid = IsPriceInsideZone(bar, iZone);
if (isValid)
{
//
supplyZone = iZone;
}
}
//
hasSupplyZone = supplyZone != NULL &&
supplyZone.IsValid();
if (hasSupplyZone)
{
//
zonesCount++;
supplyZone.To(cTime);
}
}
//
// Demand Zone ...
count = state.CountDemandZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCDemandZone *iZone = state.demandZones[i];
//
bool isValid = IsPriceInsideZone(bar, iZone);
if (isValid)
{
//
demandZone = iZone;
}
}
//
hasDemandZone = demandZone != NULL &&
demandZone.IsValid();
if (hasDemandZone)
{
//
zonesCount++;
demandZone.To(cTime);
}
}
//
// OrderBlock ...
count = state.CountBullishOrderBlocks();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCOrderBlock *iZone = state.bullishOrderBlocks[i];
//
bool isValid = IsPriceInsideZone(bar, iZone);
if (isValid)
{
//
orderBlock = iZone;
}
}
//
hasOrderBlock = orderBlock != NULL &&
orderBlock.IsValid();
if (hasOrderBlock)
{
//
zonesCount++;
orderBlock.To(cTime);
}
}
if (!hasOrderBlock)
{
//
count = state.CountBearishOrderBlocks();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCOrderBlock *iZone = state.bearishOrderBlocks[i];
//
bool isValid = IsPriceInsideZone(bar, iZone);
if (isValid)
{
//
orderBlock = iZone;
}
}
//
hasOrderBlock = orderBlock != NULL &&
orderBlock.IsValid();
if (hasOrderBlock)
{
//
zonesCount++;
orderBlock.To(cTime);
}
}
}
//
// Fair Value Gap ...
count = state.CountBullishFairValueGaps();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCFVG *iZone = state.bullishFairValueGaps[i];
//
bool isValid = IsPriceInsideZone(bar, iZone);
if (isValid)
{
//
fairValueGap = iZone;
}
}
//
hasFairValueGap = fairValueGap != NULL &&
fairValueGap.IsValid();
if (hasFairValueGap)
{
//
zonesCount++;
fairValueGap.To(cTime);
}
}
if (!hasFairValueGap)
{
//
count = state.CountBearishFairValueGaps();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCFVG *iZone = state.bearishFairValueGaps[i];
//
bool isValid = IsPriceInsideZone(bar, iZone);
if (isValid)
{
//
fairValueGap = iZone;
}
}
//
hasFairValueGap = fairValueGap != NULL &&
fairValueGap.IsValid();
if (hasFairValueGap)
{
//
zonesCount++;
fairValueGap.To(cTime);
}
}
}
//
result =
//
hasSupportZone ||
hasResistanceZone ||
hasSupplyZone ||
hasDemandZone ||
hasOrderBlock ||
hasFairValueGap
//
;
//
return result;
}
/**
* Detect Price Inside Zones ...
*
* @param state: XPOIState instance Reference ...
* @param price: Double ...
* @param hasSupport: Boolean ...
* @param hasResistanceZone: Boolean ...
* @param hasSupplyZone: Boolean ...
* @param hasDemandZone: Boolean ...
* @param hasOrderBlock: Boolean ...
* @param hasFairValueGap: Boolean ...
* @return ( bool )
*/
bool DetectPriceInsideZones(
XPOIState &state,
double price,
int &zonesCount,
bool &hasSupportZone,
XCSupportZone *&supportZone,
bool &hasResistanceZone,
XCResistanceZone *&resistanceZone,
bool &hasSupplyZone,
XCSupplyZone *&supplyZone,
bool &hasDemandZone,
XCDemandZone *&demandZone,
bool &hasOrderBlock,
XCOrderBlock *&orderBlock,
bool &hasFairValueGap,
XCFVG *&fairValueGap //
)
{
//
bool result = false;
//
zonesCount = 0;
//
hasSupportZone = false;
hasResistanceZone = false;
hasSupplyZone = false;
hasDemandZone = false;
hasOrderBlock = false;
hasFairValueGap = false;
//
supportZone = NULL;
resistanceZone = NULL;
supplyZone = NULL;
demandZone = NULL;
orderBlock = NULL;
fairValueGap = NULL;
//
datetime cTime = TimeCurrent();
//
result = price > 0 &&
state.IsValid() &&
state.HasChild();
if (!result)
{
return result;
}
//
int count = 0;
//
// Support Zone ...
count = state.CountSupportZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCSupportZone *iZone = state.supportZones[i];
//
bool isValid = IsPriceInsideZone(price, iZone);
if (isValid)
{
//
supportZone = iZone;
}
}
//
hasSupportZone = supportZone != NULL &&
supportZone.IsValid();
if (hasSupportZone)
{
//
zonesCount++;
supportZone.To(cTime);
}
}
//
// Resistance Zone ...
count = state.CountResistanceZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCResistanceZone *iZone = state.resistanceZones[i];
//
bool isValid = IsPriceInsideZone(price, iZone);
if (isValid)
{
//
resistanceZone = iZone;
}
}
//
hasResistanceZone = resistanceZone != NULL &&
resistanceZone.IsValid();
if (hasResistanceZone)
{
//
zonesCount++;
resistanceZone.To(cTime);
}
}
//
// Supply Zone ...
count = state.CountSupplyZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCSupplyZone *iZone = state.supplyZones[i];
//
bool isValid = IsPriceInsideZone(price, iZone);
if (isValid)
{
//
supplyZone = iZone;
}
}
//
hasSupplyZone = supplyZone != NULL &&
supplyZone.IsValid();
if (hasSupplyZone)
{
//
zonesCount++;
supplyZone.To(cTime);
}
}
//
// Demand Zone ...
count = state.CountDemandZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCDemandZone *iZone = state.demandZones[i];
//
bool isValid = IsPriceInsideZone(price, iZone);
if (isValid)
{
//
demandZone = iZone;
}
}
//
hasDemandZone = demandZone != NULL &&
demandZone.IsValid();
if (hasDemandZone)
{
//
zonesCount++;
demandZone.To(cTime);
}
}
//
// OrderBlock ...
count = state.CountBullishOrderBlocks();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCOrderBlock *iZone = state.bullishOrderBlocks[i];
//
bool isValid = IsPriceInsideZone(price, iZone);
if (isValid)
{
//
orderBlock = iZone;
}
}
//
hasOrderBlock = orderBlock != NULL &&
orderBlock.IsValid();
if (hasOrderBlock)
{
//
zonesCount++;
orderBlock.To(cTime);
}
}
if (!hasOrderBlock)
{
//
count = state.CountBearishOrderBlocks();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCOrderBlock *iZone = state.bearishOrderBlocks[i];
//
bool isValid = IsPriceInsideZone(price, iZone);
if (isValid)
{
//
orderBlock = iZone;
}
}
//
hasOrderBlock = orderBlock != NULL &&
orderBlock.IsValid();
if (hasOrderBlock)
{
//
zonesCount++;
orderBlock.To(cTime);
}
}
}
//
// Fair Value Gap ...
count = state.CountBullishFairValueGaps();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCFVG *iZone = state.bullishFairValueGaps[i];
//
bool isValid = IsPriceInsideZone(price, iZone);
if (isValid)
{
//
fairValueGap = iZone;
}
}
//
hasFairValueGap = fairValueGap != NULL &&
fairValueGap.IsValid();
if (hasFairValueGap)
{
//
zonesCount++;
fairValueGap.To(cTime);
}
}
if (!hasFairValueGap)
{
//
count = state.CountBearishFairValueGaps();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCFVG *iZone = state.bearishFairValueGaps[i];
//
bool isValid = IsPriceInsideZone(price, iZone);
if (isValid)
{
//
fairValueGap = iZone;
}
}
//
hasFairValueGap = fairValueGap != NULL &&
fairValueGap.IsValid();
if (hasFairValueGap)
{
//
zonesCount++;
fairValueGap.To(cTime);
}
}
}
//
result =
//
hasSupportZone ||
hasResistanceZone ||
hasSupplyZone ||
hasDemandZone ||
hasOrderBlock ||
hasFairValueGap
//
;
//
return result;
}
bool CalculatePriceInsideZones(
XPriceZones &zone,
XPOIState &state,
double price //
)
{
//
bool result = false;
//
zone.Clean();
//
int zonesCount = 0;
bool hasSupplyZone = false;
bool hasDemandZone = false;
bool hasOrderBlock = false;
bool hasSupportZone = false;
bool hasFairValueGap = false;
bool hasResistanceZone = false;
//
result = DetectPriceInsideZones(
state,
price,
zone.count,
hasSupportZone,
zone.supportZone,
hasResistanceZone,
zone.resistanceZone,
hasSupplyZone,
zone.supplyZone,
hasDemandZone,
zone.demandZone,
hasOrderBlock,
zone.orderBlock,
hasFairValueGap,
zone.fairValueGap //
);
if (!result)
{
return result;
}
//
zone.price = price;
//
result = zone.IsValid();
//
return result;
}
bool CalculatePriceInsideZones(
XPriceZones &zone,
XPOIState &state,
XOHCL &bar //
)
{
//
bool result = false;
//
zone.Clean();
//
int zonesCount = 0;
bool hasSupplyZone = false;
bool hasDemandZone = false;
bool hasOrderBlock = false;
bool hasSupportZone = false;
bool hasFairValueGap = false;
bool hasResistanceZone = false;
//
result = DetectPriceInsideZones(
state,
bar,
zone.count,
hasSupportZone,
zone.supportZone,
hasResistanceZone,
zone.resistanceZone,
hasSupplyZone,
zone.supplyZone,
hasDemandZone,
zone.demandZone,
hasOrderBlock,
zone.orderBlock,
hasFairValueGap,
zone.fairValueGap //
);
if (!result)
{
return result;
}
//
zone.bar = bar;
//
result = zone.IsValid();
//
return result;
}
/**
* Calculate Zone by Providing Specified Data ...
*
* @param zones: XStateZone instance Reference ...
* @param source: XPOIState instance Reference ...
* @param upper: Double ...
* @param lower: Double ...
* @param from: DateTime ...
*
* @return ( bool )
*/
bool CalculateStateZones(
XStateZones &zones,
XPOIState &source,
double upper,
double lower,
datetime from //
)
{
//
bool result = false;
//
zones.Clean();
//
datetime cTime = TimeCurrent();
//
result =
//
upper > 0 &&
lower > 0 &&
upper > lower &&
IsValid(from) &&
source.IsValid() &&
source.HasChild()
//
;
if (!result)
{
return result;
}
//
int count = 0;
//
// Support ...
count = source.CountSupportZones();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCSupportZone *iZone = source.supportZones[i];
//
double iUpper = iZone.Upper();
double iLower = iZone.Lower();
datetime iFrom = iZone.From();
//
bool isAbove = iUpper > upper &&
iLower <= upper;
//
bool isInside = iUpper <= upper &&
iLower >= lower;
//
bool isBelow = iUpper >= lower &&
iLower < lower;
//
bool isValid =
//
iFrom > from &&
(isAbove ||
isBelow ||
isInside)
//
;
if (isValid)
{
//
iZone.To(cTime);
Add(
iZone,
zones.supportZones //
);
}
}
}
//
// Resistance ...
count = source.CountResistanceZones();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCResistanceZone *iZone = source.resistanceZones[i];
//
double iUpper = iZone.Upper();
double iLower = iZone.Lower();
datetime iFrom = iZone.From();
//
bool isAbove = iUpper > upper &&
iLower <= upper;
//
bool isInside = iUpper <= upper &&
iLower >= lower;
//
bool isBelow = iUpper >= lower &&
iLower < lower;
//
bool isValid =
//
iFrom > from &&
(isAbove ||
isBelow ||
isInside)
//
;
if (isValid)
{
//
iZone.To(cTime);
Add(
iZone,
zones.resistanceZones //
);
}
}
}
//
// Supply ...
count = source.CountSupplyZones();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCSupplyZone *iZone = source.supplyZones[i];
//
double iUpper = iZone.Upper();
double iLower = iZone.Lower();
datetime iFrom = iZone.From();
//
bool isAbove = iUpper > upper &&
iLower <= upper;
//
bool isInside = iUpper <= upper &&
iLower >= lower;
//
bool isBelow = iUpper >= lower &&
iLower < lower;
//
bool isValid =
//
iFrom > from &&
(isAbove ||
isBelow ||
isInside)
//
;
if (isValid)
{
//
iZone.To(cTime);
Add(
iZone,
zones.supplyZones //
);
}
}
}
//
// Demand ...
count = source.CountDemandZones();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCDemandZone *iZone = source.demandZones[i];
//
double iUpper = iZone.Upper();
double iLower = iZone.Lower();
datetime iFrom = iZone.From();
//
bool isAbove = iUpper > upper &&
iLower <= upper;
//
bool isInside = iUpper <= upper &&
iLower >= lower;
//
bool isBelow = iUpper >= lower &&
iLower < lower;
//
bool isValid =
//
iFrom > from &&
(isAbove ||
isBelow ||
isInside)
//
;
if (isValid)
{
//
iZone.To(cTime);
Add(
iZone,
zones.demandZones //
);
}
}
}
//
// Bullish OrderBlocks ...
count = source.CountBullishOrderBlocks();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *iZone = source.bullishOrderBlocks[i];
//
double iUpper = iZone.Upper();
double iLower = iZone.Lower();
datetime iFrom = iZone.From();
//
bool isAbove = iUpper > upper &&
iLower <= upper;
//
bool isInside = iUpper <= upper &&
iLower >= lower;
//
bool isBelow = iUpper >= lower &&
iLower < lower;
//
bool isValid =
//
iFrom > from &&
(isAbove ||
isBelow ||
isInside)
//
;
if (isValid)
{
//
iZone.To(cTime);
Add(
iZone,
zones.bullishOrderBlocks //
);
}
}
}
//
// Bearish OrderBlocks ...
count = source.CountBearishOrderBlocks();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *iZone = source.bearishOrderBlocks[i];
//
double iUpper = iZone.Upper();
double iLower = iZone.Lower();
datetime iFrom = iZone.From();
//
bool isAbove = iUpper > upper &&
iLower <= upper;
//
bool isInside = iUpper <= upper &&
iLower >= lower;
//
bool isBelow = iUpper >= lower &&
iLower < lower;
//
bool isValid =
//
iFrom > from &&
(isAbove ||
isBelow ||
isInside)
//
;
if (isValid)
{
//
iZone.To(cTime);
Add(
iZone,
zones.bearishOrderBlocks //
);
}
}
}
//
// Bullish FairValueGaps ...
count = source.CountBullishFairValueGaps();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCFVG *iZone = source.bullishFairValueGaps[i];
//
double iUpper = iZone.Upper();
double iLower = iZone.Lower();
datetime iFrom = iZone.From();
//
bool isAbove = iUpper > upper &&
iLower <= upper;
//
bool isInside = iUpper <= upper &&
iLower >= lower;
//
bool isBelow = iUpper >= lower &&
iLower < lower;
//
bool isValid =
//
iFrom > from &&
(isAbove ||
isBelow ||
isInside)
//
;
if (isValid)
{
//
iZone.To(cTime);
Add(
iZone,
zones.bullishFairValueGaps //
);
}
}
}
//
// Bearish FairValueGaps ...
count = source.CountBearishFairValueGaps();
if (IsValidSize(count))
{
//
for (int i = 0; i < count; i++)
{
//
XCFVG *iZone = source.bearishFairValueGaps[i];
//
double iUpper = iZone.Upper();
double iLower = iZone.Lower();
datetime iFrom = iZone.From();
//
bool isAbove = iUpper > upper &&
iLower <= upper;
//
bool isInside = iUpper <= upper &&
iLower >= lower;
//
bool isBelow = iUpper >= lower &&
iLower < lower;
//
bool isValid =
//
iFrom > from &&
(isAbove ||
isBelow ||
isInside)
//
;
if (isValid)
{
//
iZone.To(cTime);
Add(
iZone,
zones.bearishFairValueGaps //
);
}
}
}
//
result = zones.IsValid();
//
return result;
}
/**
* Add Value Change instance to Exists Collection if it's not Exists ...
*
* @param item: XValueChange instance Reference ...
* @param items: XValueChange instance Array Reference ...
*
* @return ( int )
*/
int AddIfNotExists(
XValueChange &item,
XValueChange &items[] //
)
{
//
int result = 0;
//
result = item.IsValid();
if (!result)
{
return result;
}
//
bool canAdd = false;
int count = ArraySize(items);
if (!IsValidSize(count))
{
canAdd = true;
}
else
{
//
XValueChange last;
bool hasItem = GetLastItem(
last,
items //
);
if (!hasItem)
{
canAdd = true;
}
else
{
//
// Compare Last Item with Current ...
canAdd = item.time > last.time;
}
}
//
// Add Item if Allowed ...
if (canAdd)
{
//
AddRef(
item,
items //
);
}
//
result = ArraySize(items);
//
return result;
}
/**
* Combine a Collection of States into dest ...
*
* @param dest: XPOIState instance ...
* @param source: XPOIState Collection ...
*/
void CombineStates(
XPOIState &dest,
XPOIState &source[] //
)
{
//
dest.Clean();
//
int count = ArraySize(source);
if (!IsValidSize(count))
{
return;
}
//
for (int i = 0; i < count; i++)
{
//
XPOIState iState = source[i];
//
if (dest.ticksZone == NULL)
{
dest.ticksZone = iState.ticksZone;
}
//
Copy(
iState.swingHighs,
dest.swingHighs,
false //
);
//
Copy(
iState.swingLows,
dest.swingLows,
false //
);
//
Copy(
iState.bullishMomentumBars,
dest.bullishMomentumBars,
false //
);
//
Copy(
iState.bearishMomentumBars,
dest.bearishMomentumBars,
false //
);
//
Copy(
iState.bullishRejectionBars,
dest.bullishRejectionBars,
false //
);
//
Copy(
iState.bearishRejectionBars,
dest.bearishRejectionBars,
false //
);
//
Copy(
iState.supportZones,
dest.supportZones,
false //
);
//
Copy(
iState.resistanceZones,
dest.resistanceZones,
false //
);
//
Copy(
iState.supplyZones,
dest.supplyZones,
false //
);
//
Copy(
iState.demandZones,
dest.demandZones,
false //
);
//
Copy(
iState.bullishOrderBlocks,
dest.bullishOrderBlocks,
false //
);
//
Copy(
iState.bearishOrderBlocks,
dest.bearishOrderBlocks,
false //
);
//
Copy(
iState.bullishFairValueGaps,
dest.bullishFairValueGaps,
false //
);
//
Copy(
iState.bearishFairValueGaps,
dest.bearishFairValueGaps,
false //
);
//
}
}
/**
* Check Price Above Specified Zone ...
*
* @param bar: XOHCL instance Reference ...
*
* @return ( bool )
*/
bool IsPriceAboveZone(
XOHCL &bar,
XCZone *zone //
)
{
//
bool result = false;
//
result =
zone != NULL &&
bar.IsValid() &&
zone.IsValidBoundary();
if (!result)
{
return result;
}
//
result =
//
bar.low > zone.Upper()
//
;
//
return result;
}
/**
* Check Price Above Specified Zone ...
*
* @return ( bool )
*/
bool IsPriceAboveZone(
double price,
XCZone *zone //
)
{
//
bool result = false;
//
result =
price > 0 &&
zone != NULL &&
zone.IsValidBoundary();
if (!result)
{
return result;
}
//
result =
//
price > zone.Upper()
//
;
//
return result;
}
/**
* Check Price Below Specified Zone ...
*
* @param bar: XOHCL instance Reference ...
*
* @return ( bool )
*/
bool IsPriceBelowZone(
XOHCL &bar,
XCZone *zone //
)
{
//
bool result = false;
//
result =
zone != NULL &&
bar.IsValid() &&
zone.IsValidBoundary();
if (!result)
{
return result;
}
//
result =
//
bar.high < zone.Lower()
//
;
//
return result;
}
/**
* Check Price Below Specified Zone ...
*
* @return ( bool )
*/
bool IsPriceBelowZone(
double price,
XCZone *zone //
)
{
//
bool result = false;
//
result =
price > 0 &&
zone != NULL &&
zone.IsValidBoundary();
if (!result)
{
return result;
}
//
result =
//
price < zone.Lower()
//
;
//
return result;
}
/**
* Check Price Inside Specified Zone ...
*
* @param bar: XOHCL instance Reference ...
*
* @return ( bool )
*/
bool IsPriceInsideZone(
XOHCL &bar,
XCZone *zone //
)
{
//
bool result = false;
//
result =
zone != NULL &&
bar.IsValid() &&
zone.IsValidBoundary();
if (!result)
{
return result;
}
//
result =
//
bar.low <= zone.Upper()
//
&&
//
bar.low >= zone.Lower()
//
;
//
return result;
}
bool IsPriceInsideZone(
XOHCL &bar,
double upper,
double lower //
)
{
//
bool result = false;
//
result =
upper > 0 &&
lower > 0 &&
upper > lower &&
bar.IsValid();
if (!result)
{
return result;
}
//
result =
//
bar.low <= upper
//
&&
//
bar.low >= lower
//
;
//
return result;
}
/**
* Check Price Inside Specified Zone ...
*
* @return ( bool )
*/
bool IsPriceInsideZone(
double price,
XCZone *zone //
)
{
//
bool result = false;
//
result =
price > 0 &&
zone != NULL &&
zone.IsValidBoundary();
if (!result)
{
return result;
}
//
result =
//
price <= zone.Upper()
//
&&
//
price >= zone.Lower()
//
;
//
return result;
}
bool IsPriceInsideZone(
double price,
double upper,
double lower //
)
{
//
bool result = false;
//
result =
price > 0 &&
upper > 0 &&
lower > 0 &&
upper > lower;
if (!result)
{
return result;
}
//
result =
//
price <= upper
//
&&
//
price >= lower
//
;
//
return result;
}
/**
* Calculate Target for Specified Direction ...
*
* @param bar: XOHCL instance Reference ...
* @param state: XPOIState instance Reference ...
* @param forDir: ENUM_S_DIRECTION member ...
*
* @return ( double )
*/
double CalculateTarget(
XOHCL &bar,
XPOIState &state,
ENUM_X_DIRECTION forDir //
)
{
//
double result = 0;
//
if (!state.IsValid() ||
!state.HasChild() ||
!HasDirection(forDir))
{
return result;
}
//
XCFVG *iFVG = NULL;
XCOrderBlock *iOB = NULL;
XCSupplyZone *iSupply = NULL;
XCDemandZone *iDemand = NULL;
XCSupportZone *iSupport = NULL;
XCResistanceZone *iResistance = NULL;
//
bool hasOB = false;
bool hasFVG = false;
bool hasSupply = false;
bool hasDemand = false;
bool hasSupport = false;
bool hasResistance = false;
//
int count = 0;
//
if (IsBearish(forDir))
{
//
// FVG ...
count = state.CountBullishFairValueGaps();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCFVG *iZone = state.bullishFairValueGaps[i];
//
bool isValid = IsPriceAboveZone(
bar,
iZone //
);
if (isValid)
{
//
iFVG = iZone;
hasFVG = true;
break;
}
}
}
//
// OB ...
count = state.CountBullishOrderBlocks();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCOrderBlock *iZone = state.bullishOrderBlocks[i];
//
bool isValid = IsPriceAboveZone(
bar,
iZone //
);
if (isValid)
{
//
iOB = iZone;
hasOB = true;
break;
}
}
}
//
// SUPPORT ...
count = state.CountSupportZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCSupportZone *iZone = state.supportZones[i];
//
bool isValid = IsPriceAboveZone(
bar,
iZone //
);
if (isValid)
{
//
iSupport = iZone;
hasSupport = true;
break;
}
}
}
//
// DEMAND ...
count = state.CountDemandZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCDemandZone *iZone = state.demandZones[i];
//
bool isValid = IsPriceAboveZone(
bar,
iZone //
);
if (isValid)
{
//
iDemand = iZone;
hasDemand = true;
break;
}
}
}
//
// Summary ...
result =
hasFVG
? iFVG.Upper()
: hasOB
? iOB.Upper()
: hasSupport
? iSupport.Upper()
: hasDemand
? iDemand.Upper()
: 0;
if (hasFVG)
{
result = MathMax(result, iFVG.Upper());
}
if (hasOB)
{
result = MathMax(result, iOB.Upper());
}
if (hasSupport)
{
result = MathMax(result, iSupport.Upper());
}
if (hasDemand)
{
result = MathMax(result, iDemand.Upper());
}
}
//
if (IsBullish(forDir))
{
//
// FVG ...
count = state.CountBearishFairValueGaps();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCFVG *iZone = state.bearishFairValueGaps[i];
//
bool isValid = IsPriceBelowZone(
bar,
iZone //
);
if (isValid)
{
//
iFVG = iZone;
hasFVG = true;
break;
}
}
}
//
// OB ...
count = state.CountBearishOrderBlocks();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCOrderBlock *iZone = state.bearishOrderBlocks[i];
//
bool isValid = IsPriceBelowZone(
bar,
iZone //
);
if (isValid)
{
//
iOB = iZone;
hasOB = true;
break;
}
}
}
//
// RESISTANCE ...
count = state.CountResistanceZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCResistanceZone *iZone = state.resistanceZones[i];
//
bool isValid = IsPriceBelowZone(
bar,
iZone //
);
if (isValid)
{
//
iResistance = iZone;
hasResistance = true;
break;
}
}
}
//
// SUPPLY ...
count = state.CountSupplyZones();
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCSupplyZone *iZone = state.supplyZones[i];
//
bool isValid = IsPriceBelowZone(
bar,
iZone //
);
if (isValid)
{
//
iSupply = iZone;
hasSupply = true;
break;
}
}
}
//
// Summary ...
result =
hasFVG
? iFVG.Lower()
: hasOB
? iOB.Lower()
: hasSupport
? iSupport.Lower()
: hasDemand
? iDemand.Lower()
: 0;
if (hasFVG)
{
result = MathMin(result, iFVG.Lower());
}
if (hasOB)
{
result = MathMin(result, iOB.Lower());
}
if (hasSupport)
{
result = MathMin(result, iSupport.Lower());
}
if (hasDemand)
{
result = MathMin(result, iDemand.Lower());
}
}
//
return result;
}
/**
* Detect Valid Order Blocks ...
*
* @param forDir: ENUM_X_DIRECTION member ...
* @param source: XPOIState instance Reference ...
*
* @return ( int )
*/
int DetectValidOrderBlocks(
ENUM_X_DIRECTION forDir,
XPOIState &source,
XCOrderBlock *&orderBlocks[] //
)
{
//
int result = 0;
//
Clean(orderBlocks);
//
bool isValid =
//
source.IsValid() &&
source.HasChild() &&
HasDirection(forDir)
//
;
if (!isValid)
{
return result;
}
//
datetime cTime = TimeCurrent();
//
XOHCL cBar;
bool isInited = cBar.Init(
source.symbol,
source.period,
1 //
);
if (!isInited)
{
return result;
}
//
int count = 0;
//
// Bullish ...
count = source.CountBullishOrderBlocks();
isValid = IsValidSize(count) &&
IsBullish(forDir);
if (isValid)
{
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *iOB = source.bullishOrderBlocks[i];
//
// Update Order Block Time ...
iOB.To(cTime);
//
// Check Order Block Validation ...
isValid = IsValid(
forDir,
cBar.symbol,
cBar.period,
iOB.Upper(),
iOB.Lower(),
iOB.From(),
iOB.To() //
);
if (isValid)
{
//
Add(
iOB,
orderBlocks //
);
}
}
}
//
// Bearish ...
count = source.CountBearishOrderBlocks();
isValid = IsValidSize(count) &&
IsBearish(forDir);
if (isValid)
{
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *iOB = source.bearishOrderBlocks[i];
//
// Update Order Block Time ...
iOB.To(cTime);
//
// Check Order Block Validation ...
isValid = IsValid(
forDir,
cBar.symbol,
cBar.period,
iOB.Upper(),
iOB.Lower(),
iOB.From(),
iOB.To() //
);
if (isValid)
{
//
Add(
iOB,
orderBlocks //
);
}
}
}
//
result = ArraySize(orderBlocks);
//
return result;
}
/**
* Detect Valid Fair Value Gaps ...
*
* @param forDir: ENUM_X_DIRECTION member ...
* @param source: XPOIState instance Reference ...
*
* @return ( int )
*/
int DetectValidFairValueGaps(
ENUM_X_DIRECTION forDir,
XPOIState &source,
XCFVG *&fairValueGaps[] //
)
{
//
int result = 0;
//
Clean(fairValueGaps);
//
bool isValid =
//
source.IsValid() &&
source.HasChild() &&
HasDirection(forDir)
//
;
if (!isValid)
{
return result;
}
//
datetime cTime = TimeCurrent();
//
XOHCL cBar;
bool isInited = cBar.Init(
source.symbol,
source.period,
1 //
);
if (!isInited)
{
return result;
}
//
int count = 0;
//
// Bullish ...
count = source.CountBullishFairValueGaps();
isValid = IsValidSize(count) &&
IsBullish(forDir);
if (isValid)
{
//
for (int i = 0; i < count; i++)
{
//
XCFVG *iFVG = source.bullishFairValueGaps[i];
//
// Update FVG Time ...
iFVG.To(cTime);
//
// Check FVG Validation ...
isValid = IsValid(
forDir,
cBar.symbol,
cBar.period,
iFVG.Upper(),
iFVG.Lower(),
iFVG.From(),
iFVG.To() //
);
if (isValid)
{
//
Add(
iFVG,
fairValueGaps //
);
}
}
}
//
// Bearish ...
count = source.CountBearishFairValueGaps();
isValid = IsValidSize(count) &&
IsBearish(forDir);
if (isValid)
{
//
for (int i = 0; i < count; i++)
{
//
XCFVG *iFVG = source.bearishFairValueGaps[i];
//
// Update Order Block Time ...
iFVG.To(cTime);
//
// Check Order Block Validation ...
isValid = IsValid(
forDir,
cBar.symbol,
cBar.period,
iFVG.Upper(),
iFVG.Lower(),
iFVG.From(),
iFVG.To() //
);
if (isValid)
{
//
Add(
iFVG,
fairValueGaps //
);
}
}
}
//
result = ArraySize(fairValueGaps);
//
return result;
}
/**
* Detect Valid Support Zones ...
*
* @param source: XPOIState instance ...
*
* @return ( int )
*/
int DetectValidSupportZones(
XPOIState &source,
XCOrderBlock *&bullishOrderBlocks[],
XCFVG *&bullishFairValueGaps[],
XCSupportZone *&supportZones[] //
)
{
//
int result = 0;
//
Clean(supportZones);
//
int obsCount = ArraySize(bullishOrderBlocks);
int fvgsCount = ArraySize(bullishFairValueGaps);
//
bool isValid =
//
source.IsValid() &&
source.HasChild() &&
IsValidSize(obsCount + fvgsCount)
//
;
if (!isValid)
{
return result;
}
//
int count = source.CountSupportZones();
for (int i = 0; i < count; i++)
{
//
XCSupportZone *iZone = source.supportZones[i];
//
bool isAdded = false;
//
for (int j = 0; j < obsCount; j++)
{
//
XCOrderBlock *iOB = bullishOrderBlocks[j];
//
bool isValid =
//
IsPriceInsideZone(
iZone.Upper(),
iOB.Upper(),
iOB.Lower() //
)
//
||
//
IsPriceInsideZone(
iZone.Lower(),
iOB.Upper(),
iOB.Lower() //
)
//
;
if (isValid)
{
//
Add(
iZone,
supportZones //
);
//
isAdded = true;
break;
}
}
//
if (isAdded)
{
continue;
}
//
for (int j = 0; j < fvgsCount; j++)
{
//
XCFVG *iFVG = bullishFairValueGaps[j];
//
bool isValid =
//
IsPriceInsideZone(
iZone.Upper(),
iFVG.Upper(),
iFVG.Lower() //
)
//
||
//
IsPriceInsideZone(
iZone.Lower(),
iFVG.Upper(),
iFVG.Lower() //
)
//
;
if (isValid)
{
//
Add(
iZone,
supportZones //
);
//
isAdded = true;
break;
}
}
}
//
result = ArraySize(supportZones);
//
return result;
}
/**
* Detect Valid Resistance Zones ...
*
* @param source: XPOIState instance ...
*
* @return ( int )
*/
int DetectValidResistanceZones(
XPOIState &source,
XCOrderBlock *&bearishOrderBlocks[],
XCFVG *&bearishFairValueGaps[],
XCResistanceZone *&resistanceZones[] //
)
{
//
int result = 0;
//
Clean(resistanceZones);
//
int obsCount = ArraySize(bearishOrderBlocks);
int fvgsCount = ArraySize(bearishFairValueGaps);
//
bool isValid =
//
source.IsValid() &&
source.HasChild() &&
IsValidSize(obsCount + fvgsCount)
//
;
if (!isValid)
{
return result;
}
//
int count = source.CountResistanceZones();
for (int i = 0; i < count; i++)
{
//
XCResistanceZone *iZone = source.resistanceZones[i];
//
bool isAdded = false;
//
for (int j = 0; j < obsCount; j++)
{
//
XCOrderBlock *iOB = bearishOrderBlocks[j];
//
bool isValid =
//
IsPriceInsideZone(
iZone.Upper(),
iOB.Upper(),
iOB.Lower() //
)
//
||
//
IsPriceInsideZone(
iZone.Lower(),
iOB.Upper(),
iOB.Lower() //
)
//
;
if (isValid)
{
//
Add(
iZone,
resistanceZones //
);
//
isAdded = true;
break;
}
}
//
if (isAdded)
{
continue;
}
//
for (int j = 0; j < fvgsCount; j++)
{
//
XCFVG *iFVG = bearishFairValueGaps[j];
//
bool isValid =
//
IsPriceInsideZone(
iZone.Upper(),
iFVG.Upper(),
iFVG.Lower() //
)
//
||
//
IsPriceInsideZone(
iZone.Lower(),
iFVG.Upper(),
iFVG.Lower() //
)
//
;
if (isValid)
{
//
Add(
iZone,
resistanceZones //
);
//
isAdded = true;
break;
}
}
}
//
result = ArraySize(resistanceZones);
//
return result;
}
/**
* Detect Valid Support Zones ...
*
* @param source: XPOIState instance ...
*
* @return ( int )
*/
int DetectValidDemandZones(
XPOIState &source,
XCOrderBlock *&bullishOrderBlocks[],
XCFVG *&bullishFairValueGaps[],
XCDemandZone *&demandZones[] //
)
{
//
int result = 0;
//
Clean(demandZones);
//
int obsCount = ArraySize(bullishOrderBlocks);
int fvgsCount = ArraySize(bullishFairValueGaps);
//
bool isValid =
//
source.IsValid() &&
source.HasChild() &&
IsValidSize(obsCount + fvgsCount)
//
;
if (!isValid)
{
return result;
}
//
int count = source.CountDemandZones();
for (int i = 0; i < count; i++)
{
//
XCDemandZone *iZone = source.demandZones[i];
//
bool isAdded = false;
//
for (int j = 0; j < obsCount; j++)
{
//
XCOrderBlock *iOB = bullishOrderBlocks[j];
//
bool isValid =
//
IsPriceInsideZone(
iZone.Upper(),
iOB.Upper(),
iOB.Lower() //
)
//
||
//
IsPriceInsideZone(
iZone.Lower(),
iOB.Upper(),
iOB.Lower() //
)
//
;
if (isValid)
{
//
Add(
iZone,
demandZones //
);
//
isAdded = true;
break;
}
}
//
if (isAdded)
{
continue;
}
//
for (int j = 0; j < fvgsCount; j++)
{
//
XCFVG *iFVG = bullishFairValueGaps[j];
//
bool isValid =
//
IsPriceInsideZone(
iZone.Upper(),
iFVG.Upper(),
iFVG.Lower() //
)
//
||
//
IsPriceInsideZone(
iZone.Lower(),
iFVG.Upper(),
iFVG.Lower() //
)
//
;
if (isValid)
{
//
Add(
iZone,
demandZones //
);
//
isAdded = true;
break;
}
}
}
//
result = ArraySize(demandZones);
//
return result;
}
/**
* Detect Valid Resistance Zones ...
*
* @param source: XPOIState instance ...
*
* @return ( int )
*/
int DetectValidSupplyZones(
XPOIState &source,
XCOrderBlock *&bearishOrderBlocks[],
XCFVG *&bearishFairValueGaps[],
XCSupplyZone *&supplyZones[] //
)
{
//
int result = 0;
//
Clean(supplyZones);
//
int obsCount = ArraySize(bearishOrderBlocks);
int fvgsCount = ArraySize(bearishFairValueGaps);
//
bool isValid =
//
source.IsValid() &&
source.HasChild() &&
IsValidSize(obsCount + fvgsCount)
//
;
if (!isValid)
{
return result;
}
//
int count = source.CountSupplyZones();
for (int i = 0; i < count; i++)
{
//
XCSupplyZone *iZone = source.supplyZones[i];
//
bool isAdded = false;
//
for (int j = 0; j < obsCount; j++)
{
//
XCOrderBlock *iOB = bearishOrderBlocks[j];
//
bool isValid =
//
IsPriceInsideZone(
iZone.Upper(),
iOB.Upper(),
iOB.Lower() //
)
//
||
//
IsPriceInsideZone(
iZone.Lower(),
iOB.Upper(),
iOB.Lower() //
)
//
;
if (isValid)
{
//
Add(
iZone,
supplyZones //
);
//
isAdded = true;
break;
}
}
//
if (isAdded)
{
continue;
}
//
for (int j = 0; j < fvgsCount; j++)
{
//
XCFVG *iFVG = bearishFairValueGaps[j];
//
bool isValid =
//
IsPriceInsideZone(
iZone.Upper(),
iFVG.Upper(),
iFVG.Lower() //
)
//
||
//
IsPriceInsideZone(
iZone.Lower(),
iFVG.Upper(),
iFVG.Lower() //
)
//
;
if (isValid)
{
//
Add(
iZone,
supplyZones //
);
//
isAdded = true;
break;
}
}
}
//
result = ArraySize(supplyZones);
//
return result;
}
/**
* Test Market for Detect Order Block FVG ...
*
* @param forDir: Direction
* @param bullishOrderBlocks: Detected Bullish Order Blocks ...
* @param bearishOrderBlocks: Detected Bearish Order Blocks ...
* @param orderBlockState: Order Block Detection POIState ...
* @param fairValueGapState: Fair Value Gap Detection POIState ...
* @param barIndex: Bar Index ...
*
* @return ( bool )
*/
bool DetectFVGOB(
ENUM_X_DIRECTION &forDir, // Test For Specified Direction ...
XFVGOrderBlock &bullishOrderBlocks[], // Bullish Order Blocks ...
XFVGOrderBlock &bearishOrderBlocks[], // Bearish Order Blocks ...
XPOIState &orderBlockState, // Order Block Detection TF POI(s) ...
XPOIState &fairValueGapState, // Fair Value Gap Detection TF POI(s) ...
int barIndex = 0 // Bar Index ...
)
{
//
bool result = false;
//
if (barIndex < 0)
{
barIndex = 0;
}
//
forDir = X_DIRECTION_NONE;
//
// Validate Args ...
result =
orderBlockState.HasChild() &&
fairValueGapState.HasChild();
if (!result)
{
return result;
}
//
string symbol = orderBlockState.symbol;
ENUM_TIMEFRAMES period = orderBlockState.period;
//
// Retrieve Bars ...
XOHCL triggerCBar;
result = triggerCBar.Init(
symbol,
period,
barIndex //
);
//
// Select Order Blocks Which Has Big Changes ...
int count = 0;
datetime cTime = TimeCurrent();
//
XOHCL jBar;
result = jBar.Init(
fairValueGapState.symbol,
fairValueGapState.period,
barIndex //
);
if (!result)
{
return result;
}
double jBarLL = jBar.FindLowest(3, MODE_LOW);
double jBarHH = jBar.FindHighest(3, MODE_HIGH);
//
// Bullish ...
int bullishOrderBlocksCount = orderBlockState.CountBullishOrderBlocks();
count = bullishOrderBlocksCount;
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCFVG *iFVG = NULL;
XStateZones iStateZones;
XCOrderBlock *iOb = orderBlockState.bullishOrderBlocks[i];
iOb.To(cTime);
//
// Find Exit Bar of Bullish OrderBlock Upper ...
XOHCL breakerBar;
bool hasBreakerBar = iOb.DetectBreakerBar(breakerBar);
if (!hasBreakerBar)
{
continue;
}
//
// Detect Order Block is Hunted Or Not ...
XOHCL huntedBar;
bool isHunted = iOb.IsHunted(huntedBar);
if (isHunted)
{
continue;
}
//
// Check Validation of Order Block ...
bool isValid = iOb.IsValidOrderBlock();
if (!isValid)
{
continue;
}
//
// Check Order Block Has Fair Value Gap ...
int fvgsCount = fairValueGapState.CountBullishFairValueGaps();
bool hasFVG = IsValidSize(fvgsCount);
if (!hasFVG)
{
continue;
}
//
// Detect an FVG for Order Block ...
for (int j = fvgsCount - 1; j >= 0; j--)
{
//
XCFVG *jFVG = fairValueGapState.bullishFairValueGaps[j];
//
bool isValid =
//
jFVG.IsBullish() &&
jBarLL > jFVG.Upper() &&
jBar.low > jFVG.Upper() &&
jFVG.From() >= iOb.From() &&
((jFVG.Upper() > iOb.Upper() &&
jFVG.Lower() <= iOb.Upper()) ||
(jFVG.Upper() <= iOb.Upper() &&
jFVG.Lower() >= iOb.Lower()))
//
;
if (isValid)
{
//
jFVG.To(cTime);
iFVG = jFVG;
break;
}
}
//
hasFVG = iFVG != NULL;
result = hasFVG;
if (!result)
{
continue;
}
// //
// double upper = MathMax(iOb.Upper(), iFVG.Upper());
// double lower = MathMin(iOb.Lower(), iFVG.Lower());
// datetime from = iFVG.From();
// //
// // Detect Price Zones ...
// // Based On Decision State ...
// bool hasStateZones = CalculateStateZones(
// iStateZones,
// decisionState,
// upper,
// lower,
// from //
// );
// result = hasStateZones;
// if (!result)
// {
// continue;
// }
//
XFVGOrderBlock iModel;
iModel.orderBlock = iOb;
iModel.fairValueGap = iFVG;
// iModel.stateZones = iStateZones;
//
AddRef(
iModel,
bullishOrderBlocks //
);
}
}
//
// Bearish ...
int bearishOrderBlocksCount = orderBlockState.CountBearishOrderBlocks();
count = bearishOrderBlocksCount;
if (IsValidSize(count))
{
//
for (int i = count - 1; i >= 0; i--)
{
//
XCFVG *iFVG = NULL;
XStateZones iStateZones;
XCOrderBlock *iOb = orderBlockState.bearishOrderBlocks[i];
iOb.To(cTime);
//
// Find Exit Bar of Bullish OrderBlock Upper ...
XOHCL breakerBar;
bool hasBreakerBar = iOb.DetectBreakerBar(breakerBar);
if (!hasBreakerBar)
{
continue;
}
//
// Detect Order Block is Hunted Or Not ...
XOHCL huntedBar;
bool isHunted = iOb.IsHunted(huntedBar);
if (isHunted)
{
continue;
}
//
// Check Validation of Order Block ...
bool isValid = iOb.IsValidOrderBlock();
if (!isValid)
{
continue;
}
//
// Check Order Block Has Fair Value Gap ...
int fvgsCount = fairValueGapState.CountBearishFairValueGaps();
bool hasFVG = IsValidSize(fvgsCount);
if (!hasFVG)
{
continue;
}
//
// Detect an FVG for Order Block ...
for (int j = fvgsCount - 1; j >= 0; j--)
{
//
XCFVG *jFVG = fairValueGapState.bearishFairValueGaps[j];
//
bool isValid =
//
jFVG.IsBearish() &&
jBarHH < jFVG.Lower() &&
jBar.high < jFVG.Lower() &&
jFVG.From() >= iOb.From() &&
((jFVG.Upper() > iOb.Lower() &&
jFVG.Lower() <= iOb.Lower()) ||
(jFVG.Upper() <= iOb.Upper() &&
jFVG.Lower() >= iOb.Lower()))
//
;
if (isValid)
{
//
jFVG.To(cTime);
iFVG = jFVG;
break;
}
}
//
hasFVG = iFVG != NULL;
result = hasFVG;
if (!result)
{
continue;
}
//
double upper = MathMax(iOb.Upper(), iFVG.Upper());
double lower = MathMin(iOb.Lower(), iFVG.Lower());
datetime from = iFVG.From();
// //
// // Detect Price Zones ...
// // Based On Decision State ...
// bool hasStateZones = CalculateStateZones(
// iStateZones,
// decisionState,
// upper,
// lower,
// from //
// );
// result = hasStateZones;
// if (!result)
// {
// continue;
// }
//
XFVGOrderBlock iModel;
iModel.orderBlock = iOb;
iModel.fairValueGap = iFVG;
// iModel.stateZones = iStateZones;
//
AddRef(
iModel,
bearishOrderBlocks //
);
}
}
//
// Check Order Blocks ...
bullishOrderBlocksCount = ArraySize(bullishOrderBlocks);
bool hasBullishOrderBlocks = IsValidSize(bullishOrderBlocksCount);
//
// Check Order Blocks ...
bearishOrderBlocksCount = ArraySize(bearishOrderBlocks);
bool hasBearishOrderBlocks = IsValidSize(bearishOrderBlocksCount);
//
result =
//
hasBullishOrderBlocks ||
hasBearishOrderBlocks
//
;
if (!result)
{
return result;
}
//
bool isBullish = hasBullishOrderBlocks && !hasBearishOrderBlocks;
bool isBearish = hasBearishOrderBlocks && !hasBullishOrderBlocks;
//
forDir =
isBullish
? X_DIRECTION_BULLISH
: isBearish
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
//
result = forDir != X_DIRECTION_NONE;
if (!result)
{
return result;
}
//
return result;
}
/**
* Detect a Zone Breaker Bar ...
*
* @param toBar: XOHCL instance Reference ...
* @param fromBar: XOHCL instance Reference ...
* @param breakerBar: XOHCL instance Reference ...
* @param forDir: ENUM_X_DIRECTION member ...
* @param symbol: String ...
* @param period: ENUM_TIMEFRAMES member ...
*
* @return ( bool )
*/
bool HasBreakerBar(
XOHCL &toBar,
XOHCL &fromBar,
XOHCL &breakerBar,
ENUM_X_DIRECTION forDir,
string symbol,
ENUM_TIMEFRAMES period,
double upper,
double lower,
datetime from,
datetime to //
)
{
//
bool result = false;
//
toBar.Clean();
fromBar.Clean();
breakerBar.Clean();
//
result =
//
upper > 0 &&
lower > 0 &&
IsValid(to) &&
upper > lower &&
IsValid(from) &&
IsValid(symbol) &&
IsValid(period) &&
HasDirection(forDir)
//
;
if (!result)
{
return result;
}
//
result = fromBar.Init(
symbol,
period,
from //
);
if (!result)
{
return result;
}
//
result = toBar.Init(
symbol,
period,
to //
);
if (!result)
{
return result;
}
//
int toIndex = toBar.Index();
int fromIndex = fromBar.Index();
//
// Detect Zone BreakerBar ...
for (int i = fromIndex; i >= toIndex; i--)
{
//
XOHCL iBar;
result = iBar.Init(
symbol,
period,
i //
);
//
if (!result)
{
continue;
}
//
result =
//
IsBullish(forDir)
?
//
iBar.low < upper &&
iBar.high > upper &&
iBar.GetUp() > upper
//
:
//
iBar.high > lower &&
iBar.low < lower &&
iBar.GetDown() < lower
//
;
if (result)
{
//
breakerBar = iBar;
break;
}
}
//
result = breakerBar.IsValid();
//
return result;
}
/**
* Validate Specified Order Block ...
*
* @param forDir: ENUM_X_DIRECTION member ...
* @param symbol: String ...
* @param period: ENUM_TIMEFRAMES member ...
*
* @return ( bool )
*/
bool IsValid(
ENUM_X_DIRECTION forDir,
string symbol,
ENUM_TIMEFRAMES period,
double upper,
double lower,
datetime from,
datetime to,
bool ignoreBreakerBar = false //
)
{
//
bool result = false;
//
result =
upper > 0 &&
lower > 0 &&
IsValid(to) &&
upper > lower &&
IsValid(from) &&
IsValid(symbol) &&
IsValid(period) &&
HasDirection(forDir)
//
;
if (!result)
{
return result;
}
//
XOHCL toBar;
XOHCL fromBar;
XOHCL breakerBar;
//
if (!ignoreBreakerBar)
{
//
result = HasBreakerBar(
toBar,
fromBar,
breakerBar,
forDir,
symbol,
period,
upper,
lower,
from,
to //
);
if (!result)
{
return result;
}
}
else
{
//
result = toBar.Init(
symbol,
period,
to //
);
if (!result)
{
return result;
}
//
result = fromBar.Init(
symbol,
period,
from //
);
if (!result)
{
return result;
}
//
breakerBar = fromBar;
}
//
int toIndex = toBar.Index();
int fromIndex = fromBar.Index();
int breakerIndex = breakerBar.Index();
//
bool isBreaked = false;
for (int i = breakerIndex - 1; i >= toIndex; i--)
{
//
XOHCL iBar;
result = iBar.Init(
fromBar.symbol,
fromBar.period,
i //
);
//
if (!result)
{
continue;
}
//
isBreaked =
//
IsBullish(forDir)
//
?
//
iBar.low < upper
//
:
//
iBar.high > lower
//
;
if (isBreaked)
{
break;
}
}
//
result = !isBreaked;
//
return result;
}
/**
* Get Oldest Zone ...
*
* @return ( int )
*/
int GetOldest(
XCZone *&source[] //
)
{
//
int result = -1;
//
int count = ArraySize(source);
if (!IsValidSize(count))
{
return result;
}
//
XCZone *oldest = NULL;
for (int i = 0; i < count; i++)
{
//
XCZone *iZone = source[i];
//
bool canSet =
oldest == NULL ||
(oldest != NULL &&
oldest.From() > iZone.From());
if (canSet)
{
//
result = i;
oldest = iZone;
}
}
//
return result;
}
/**
* Get Youngest Zone ...
*
* @return ( int )
*/
int GetYoungest(
XCZone *&source[] //
)
{
//
int result = -1;
//
int count = ArraySize(source);
if (!IsValidSize(count))
{
return result;
}
//
XCZone *youngest = NULL;
for (int i = 0; i < count; i++)
{
//
XCZone *iZone = source[i];
//
bool canSet =
youngest == NULL ||
(youngest != NULL &&
youngest.From() < iZone.From());
if (canSet)
{
//
result = i;
youngest = iZone;
}
}
//
return result;
}
template <typename T>
bool ToZone(
T *&source[],
XCZone *&dest[] //
)
{
//
bool result = false;
//
Clean(dest);
//
int count = ArraySize(source);
result = IsValidSize(count);
if (!result)
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
T *item = source[i];
//
if (item != NULL)
{
//
Add(
(XCZone *)item,
dest //
);
}
}
//
int destCount = ArraySize(dest);
result = IsValidSize(destCount);
//
return result;
}
//
typedef void (*TOnPOIEvent)(ENUM_XPOI_EVENTS event,
XCBasePOI *param //
);
//