Files
MQL5Data/Libraries/x-saherelm.x-poi.lib.mq5
T
2025-03-17 15:24:18 +03:30

5428 lines
98 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 ...
//
// 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 ...
//
X_BULLISH_CONSOLIDATION_ZONE,
X_BEARISH_CONSOLIDATION_ZONE,
//
X_BULLISH_SHARP,
X_BEARISH_SHARP,
//
X_BULLISH_SPIKE,
X_BEARISH_SPIKE,
//
X_BULLISH_PULLBACK,
X_BEARISH_PULLBACK,
};
//
// Event Types ...
enum ENUM_XPOI_EVENTS
{
//
X_POI_EVENT_NONE,
//
// 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ّ ...
X_BULLISH_CONSOLIDATION_ZONE_DETECTED,
X_BEARISH_CONSOLIDATION_ZONE_DETECTED,
X_BULLISH_SHARP_DETECTED,
X_BEARISH_SHARP_DETECTED,
X_BULLISH_SPIKE_DETECTED,
X_BEARISH_SPIKE_DETECTED,
X_BULLISH_PULLBACK_DETECTED,
X_BEARISH_PULLBACK_DETECTED,
};
//
enum ENUM_XZONE_STATE
{
XZONE_STATE_NONE,
XZONE_STATE_PASSED,
XZONE_STATE_FAILED,
XZONE_STATE_IGNORED,
};
//
// Forext Sessions ...
enum ENUM_XSESSION
{
X_TOKYO,
X_SYDNEY,
X_LONDON,
X_NEW_YORK,
X_FRANKFORT,
};
/**
* 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;
//
case X_BULLISH_CONSOLIDATION_ZONE:
result = "XBULLCZ";
break;
//
case X_BEARISH_CONSOLIDATION_ZONE:
result = "XBEARCZ";
break;
//
case X_BULLISH_SPIKE:
result = "XBULLSPK";
break;
//
case X_BEARISH_SPIKE:
result = "XBEARSPK";
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;
}
//
// 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:
//
};
//
typedef void (*TOnPOIEvent)(ENUM_XPOI_EVENTS event,
XCBasePOI *param //
);
//
// 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;
}
/**
* Check Zone Started or not ...
* First Exit in Direction of Zone after From ...
*
* @param forDir: exit direction ...
* @param startedBar: specified Start Bar ...
* @param isBodyOut: specified Start Bar Close is Out of Zone or not ...
* @param forPeriod: specified Period ...
*
* @return ( bool )
*/
bool IsStarted(
ENUM_X_DIRECTION forDir,
XOHCL &startedBar,
bool &isBodyOut,
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
bool result = false;
//
isBodyOut = false;
startedBar.Clean();
//
result = HasDirection(forDir) &&
IsValidBarZone();
if (!result)
{
return result;
}
//
bool isBullish = IsBullish(forDir);
//
if (!IsSpecifiedValid(forPeriod))
{
forPeriod = GetPeriod();
}
//
// Detect From Bar Index ...
int fromIndex = iBarShift(
GetSymbol(),
forPeriod,
From() //
);
//
for (int i = fromIndex; i >= 0; i--)
{
//
XOHCL iBar;
bool isInited = iBar.Init(
GetSymbol(),
forPeriod,
i //
);
result = isInited;
if (!result)
{
//
iBar.Clean();
continue;
}
//
bool isBreakedFromUpper =
//
iBar.low > Upper() ||
(iBar.low <= Upper() &&
iBar.high > Upper() &&
iBar.close > Upper())
//
;
//
bool isBreakedFromLower =
//
iBar.low < Lower() ||
(iBar.high >= Lower() &&
iBar.low < Lower() &&
iBar.close < Lower())
//
;
//
bool isBreaked =
isBreakedFromUpper ||
isBreakedFromLower;
if (isBreaked)
{
//
result = isBreaked &&
isBullish
? isBreakedFromUpper
: isBreakedFromLower;
if (result)
{
//
startedBar = iBar;
iBar.Clean();
break;
}
}
//
iBar.Clean();
}
//
result = startedBar.IsValid();
if (result)
{
//
isBodyOut =
isBullish
? startedBar.IsBullish() &&
startedBar.GetUp() > Upper()
: startedBar.IsBearish() &&
startedBar.GetDown() < Lower();
}
//
return result;
}
/**
* Check Zone Activated or not ...
* First Enter in Opposit Direction of Zone after Start ...
*
* @param forDir: exit direction ...
* @param activatedBar: specified Activation Bar ...
* @param isBodyIn: specified Activation Bar Close is Inside of Zone or not ...
* @param forPeriod: specified Period ...
*
* @return ( bool )
*/
bool IsActivated(
ENUM_X_DIRECTION forDir,
XOHCL &activatedBar,
bool &isBodyIn,
bool forceBodyOutStarted = true,
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
bool result = false;
//
isBodyIn = false;
activatedBar.Clean();
//
result = HasDirection(forDir) &&
IsValidBarZone();
if (!result)
{
return result;
}
//
bool isBullish = IsBullish(forDir);
//
if (!IsSpecifiedValid(forPeriod))
{
forPeriod = GetPeriod();
}
//
XOHCL startedBar;
bool isBodyOut = false;
bool isStarted = IsStarted(
forDir,
startedBar,
isBodyOut,
forPeriod //
);
result =
!forceBodyOutStarted
? isStarted
: isStarted &&
isBodyOut;
if (!result)
{
//
startedBar.Clean();
return result;
}
//
int fromIndex = startedBar.Index() - 1;
//
for (int i = fromIndex; i >= 0; i--)
{
//
XOHCL iBar;
bool isInited = iBar.Init(
GetSymbol(),
forPeriod,
i //
);
result = isInited;
if (!result)
{
//
iBar.Clean();
continue;
}
//
bool isInsideFromUpper =
//
iBar.high < Upper() ||
(iBar.high > Upper() &&
iBar.low <= Upper() &&
iBar.close <= Upper())
//
;
//
bool isInsideFromLower =
//
iBar.low > Lower() ||
(iBar.low < Lower() &&
iBar.high >= Lower() &&
iBar.close >= Lower())
//
;
//
bool isInside =
isInsideFromUpper ||
isInsideFromLower;
if (isInside)
{
//
result = isInside &&
isBullish
? isInsideFromUpper
: isInsideFromLower;
if (result)
{
//
activatedBar = iBar;
iBar.Clean();
startedBar.Clean();
break;
}
}
//
iBar.Clean();
startedBar.Clean();
}
//
result = activatedBar.IsValid();
if (result)
{
//
isBodyIn =
isBullish
? activatedBar.IsBearish() &&
activatedBar.GetDown() < Upper()
: activatedBar.IsBullish() &&
activatedBar.GetUp() > Lower();
}
//
return result;
}
/**
* Check Zone Breaked or not ...
*
* @param forDir: exit direction ...
* @param breakedBar: specified Breaked Bar ...
* @param isBodyOut: specified Breaked Bar Close is Out of Zone or not ...
* @param ignoreStart: Ignore Zone Start (Calculate from From()) ...
* @param startedBodyOut: Started Bar Body Close State, if use Start for Calculation ...
* @param forPeriod: specified Period ...
*
* @return ( bool )
*/
bool IsBreaked(
ENUM_X_DIRECTION forDir,
XOHCL &breakedBar,
bool &isBodyOut,
bool ignoreStart = false,
bool startedBodyOut = false,
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
bool result = false;
//
isBodyOut = false;
breakedBar.Clean();
//
result = HasDirection(forDir) &&
IsValidBarZone();
if (!result)
{
return result;
}
//
bool isBullish = IsBullish(forDir);
//
if (!IsSpecifiedValid(forPeriod))
{
forPeriod = GetPeriod();
}
//
int fromIndex = -1;
if (!ignoreStart)
{
//
XOHCL startedBar;
bool isBodyOut = false;
bool isStarted = IsStarted(
forDir,
startedBar,
isBodyOut,
forPeriod //
);
//
bool isStartPassed =
!startedBodyOut
? isStarted
: isStarted &&
isBodyOut;
if (isStartPassed)
{
fromIndex = startedBar.Index() - 1;
}
//
startedBar.Clean();
}
else
{
//
fromIndex = iBarShift(
GetSymbol(),
forPeriod,
From() //
);
}
//
result = IsValidIndex(fromIndex);
if (!result)
{
return result;
}
//
for (int i = fromIndex; i >= 0; i--)
{
//
XOHCL iBar;
bool isInited = iBar.Init(
GetSymbol(),
forPeriod,
i //
);
result = isInited;
if (!result)
{
//
iBar.Clean();
continue;
}
//
bool isBreakedFromUpper =
//
iBar.low > Upper() ||
(iBar.low <= Upper() &&
iBar.high > Upper() &&
iBar.close > Upper())
//
;
//
bool isBreakedFromLower =
//
iBar.low < Lower() ||
(iBar.high >= Lower() &&
iBar.low < Lower() &&
iBar.close < Lower())
//
;
//
bool isBreaked =
isBreakedFromUpper ||
isBreakedFromLower;
if (isBreaked)
{
//
result = isBreaked &&
(isBullish
? isBreakedFromLower
: isBreakedFromUpper);
if (result)
{
//
breakedBar = iBar;
iBar.Clean();
break;
}
}
//
iBar.Clean();
}
//
result = breakedBar.IsValid();
if (result)
{
//
isBodyOut =
isBullish
? breakedBar.IsBearish() &&
breakedBar.GetDown() < Lower()
: breakedBar.IsBullish() &&
breakedBar.GetUp() > Upper();
}
//
return result;
}
/**
* Check Zone Worked or not ...
*
* @param forDir: exit direction ...
* @param workedBar: specified Worked Bar ...
* @param isBodyOut: specified Worked Bar Close is Out of Zone or not ...
* @param ignoreActivation: Ignore Zone Activation (Calculate from From()) ...
* @param activationStartedOut: Specified Zone Start Bar State ...
* @param activationBodyIn: Specified Zone Activation Bar State ...
* @param forPeriod: specified Period ...
*
* @return ( bool )
*/
bool IsWorked(
ENUM_X_DIRECTION forDir,
XOHCL &workedBar,
bool &isBodyOut,
bool ignoreActivation = false,
bool activationStartedOut = false,
bool activationBodyIn = false,
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
bool result = false;
//
isBodyOut = false;
workedBar.Clean();
//
result = HasDirection(forDir) &&
IsValidBarZone();
if (!result)
{
return result;
}
//
bool isBullish = IsBullish(forDir);
//
if (!IsSpecifiedValid(forPeriod))
{
forPeriod = GetPeriod();
}
//
int fromIndex = -1;
if (!ignoreActivation)
{
//
XOHCL activatedBar;
bool isBodyIn = false;
bool isActivated = IsActivated(
forDir,
activatedBar,
isBodyIn,
activationStartedOut,
forPeriod //
);
//
bool isActivationPassed =
!activationBodyIn
? isActivated
: isActivated &&
isBodyIn;
if (isActivationPassed)
{
fromIndex = activatedBar.Index() - 1;
}
//
activatedBar.Clean();
}
else
{
//
fromIndex = iBarShift(
GetSymbol(),
forPeriod,
From() //
);
}
//
result = IsValidIndex(fromIndex);
if (!result)
{
return result;
}
//
for (int i = fromIndex; i >= 0; i--)
{
//
XOHCL iBar;
bool isInited = iBar.Init(
GetSymbol(),
forPeriod,
i //
);
result = isInited;
if (!result)
{
//
iBar.Clean();
continue;
}
//
bool isBreakedFromUpper =
//
iBar.low > Upper() ||
(iBar.low <= Upper() &&
iBar.high > Upper() &&
iBar.close > Upper())
//
;
//
bool isBreakedFromLower =
//
iBar.low < Lower() ||
(iBar.high >= Lower() &&
iBar.low < Lower() &&
iBar.close < Lower())
//
;
//
bool isBreaked =
isBreakedFromUpper ||
isBreakedFromLower;
if (isBreaked)
{
//
result = isBreaked &&
isBullish
? isBreakedFromUpper
: isBreakedFromLower;
if (result)
{
//
workedBar = iBar;
iBar.Clean();
break;
}
}
//
iBar.Clean();
}
//
result = workedBar.IsValid();
if (result)
{
//
isBodyOut =
isBullish
? workedBar.IsBullish() &&
workedBar.GetUp() > Upper()
: workedBar.IsBearish() &&
workedBar.GetDown() < Lower();
}
//
return result;
}
/**
* Check to Find Nearest Bar which Breakes Upper ...
*
* @param bar: XOHCL instance Reference, Breaker Bar ...
* @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ...
*
* @return ( bool )
*/
bool FindNearestInsideBarFromUpper(
XOHCL &bar,
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
bool result = false;
//
bar.Clean();
//
if (!IsSpecifiedValid(forPeriod))
{
forPeriod = GetPeriod();
}
//
result = IsValid();
if (!result)
{
return result;
}
//
int from = 1;
int to = iBarShift(
GetSymbol(),
forPeriod,
From() //
);
//
for (int i = from; i < to; i++)
{
//
XOHCL iBar;
bool isInited = iBar.Init(
GetSymbol(),
forPeriod,
i //
);
if (!isInited)
{
break;
}
//
bool isInside = iBar.low < Upper();
if (isInside)
{
//
bar = iBar;
break;
}
}
//
result = bar.IsValid();
//
return result;
}
/**
* Check to Find Nearest Bar which Breakes Lower ...
*
* @param bar: XOHCL instance Reference, Breaker Bar ...
* @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ...
*
* @return ( bool )
*/
bool FindNearestInsideBarFromLower(
XOHCL &bar,
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
bool result = false;
//
bar.Clean();
//
if (!IsSpecifiedValid(forPeriod))
{
forPeriod = GetPeriod();
}
//
result = IsValid();
if (!result)
{
return result;
}
//
int from = 1;
int to = iBarShift(
GetSymbol(),
forPeriod,
From() //
);
//
for (int i = from; i < to; i++)
{
//
XOHCL iBar;
bool isInited = iBar.Init(
GetSymbol(),
forPeriod,
i //
);
if (!isInited)
{
break;
}
//
bool isInside = iBar.high > Lower();
if (isInside)
{
//
bar = iBar;
break;
}
}
//
result = bar.IsValid();
//
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,
ENUM_X_PRICE startPrice,
ENUM_X_PRICE endPrice //
)
{
//
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;
//
int startIndex = startBar.Index();
int endIndex = endBar.Index();
//
double mStartPrice = startBar.GetPrice(startPrice);
double mEndPrice = endBar.GetPrice(endPrice);
bool isStartOverEnd = mStartPrice > mEndPrice;
//
if (isStartOverEnd)
{
//
mUpperPrice = startPrice;
mLowerPrice = endPrice;
}
else
{
//
mUpperPrice = endPrice;
mLowerPrice = startPrice;
}
//
mUpper = MathMax(mStartPrice, mEndPrice);
mLower = MathMin(mStartPrice, mEndPrice);
//
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;
}
/**
* Check Zone Started or not ...
* First Exit in Direction of Zone after From ...
*
* @param forDir: exit direction ...
* @param startedBar: specified Start Bar ...
* @param isBodyOut: specified Start Bar Close is Out of Zone or not ...
* @param forPeriod: specified Period ...
*
* @return ( bool )
*/
bool IsStarted(
ENUM_X_DIRECTION forDir,
XOHCL &startedBar,
bool &isBodyOut,
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
bool result = false;
//
isBodyOut = false;
startedBar.Clean();
//
result = HasDirection(forDir) &&
IsValidTwoBarZone();
if (!result)
{
return result;
}
//
bool isBullish = IsBullish(forDir);
//
if (!IsSpecifiedValid(forPeriod))
{
forPeriod = GetPeriod();
}
//
// Detect From Bar Index ...
int fromIndex = iBarShift(
GetSymbol(),
forPeriod,
From() //
);
//
for (int i = fromIndex; i >= 0; i--)
{
//
XOHCL iBar;
bool isInited = iBar.Init(
GetSymbol(),
forPeriod,
i //
);
result = isInited;
if (!result)
{
//
iBar.Clean();
continue;
}
//
bool isBreakedFromUpper =
//
iBar.low > Upper() ||
(iBar.low <= Upper() &&
iBar.high > Upper() &&
iBar.close > Upper())
//
;
//
bool isBreakedFromLower =
//
iBar.low < Lower() ||
(iBar.high >= Lower() &&
iBar.low < Lower() &&
iBar.close < Lower())
//
;
//
bool isBreaked =
isBreakedFromUpper ||
isBreakedFromLower;
if (isBreaked)
{
//
result = isBreaked &&
isBullish
? isBreakedFromUpper
: isBreakedFromLower;
if (result)
{
//
startedBar = iBar;
iBar.Clean();
break;
}
}
//
iBar.Clean();
}
//
result = startedBar.IsValid();
if (result)
{
//
isBodyOut =
isBullish
? startedBar.IsBullish() &&
startedBar.GetUp() > Upper()
: startedBar.IsBearish() &&
startedBar.GetDown() < Lower();
}
//
return result;
}
/**
* Check Zone Activated or not ...
* First Enter in Opposit Direction of Zone after Start ...
*
* @param forDir: exit direction ...
* @param activatedBar: specified Activation Bar ...
* @param isBodyIn: specified Activation Bar Close is Inside of Zone or not ...
* @param forPeriod: specified Period ...
*
* @return ( bool )
*/
bool IsActivated(
ENUM_X_DIRECTION forDir,
XOHCL &activatedBar,
bool &isBodyIn,
bool forceBodyOutStarted = true,
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
bool result = false;
//
isBodyIn = false;
activatedBar.Clean();
//
result = HasDirection(forDir) &&
IsValidTwoBarZone();
if (!result)
{
return result;
}
//
bool isBullish = IsBullish(forDir);
//
if (!IsSpecifiedValid(forPeriod))
{
forPeriod = GetPeriod();
}
//
XOHCL startedBar;
bool isBodyOut = false;
bool isStarted = IsStarted(
forDir,
startedBar,
isBodyOut,
forPeriod //
);
result =
!forceBodyOutStarted
? isStarted
: isStarted &&
isBodyOut;
if (!result)
{
//
startedBar.Clean();
return result;
}
//
int fromIndex = startedBar.Index() - 1;
//
for (int i = fromIndex; i >= 0; i--)
{
//
XOHCL iBar;
bool isInited = iBar.Init(
GetSymbol(),
forPeriod,
i //
);
result = isInited;
if (!result)
{
//
iBar.Clean();
continue;
}
//
bool isInsideFromUpper =
//
iBar.high < Upper() ||
(iBar.high > Upper() &&
iBar.low <= Upper() &&
iBar.close <= Upper())
//
;
//
bool isInsideFromLower =
//
iBar.low > Lower() ||
(iBar.low < Lower() &&
iBar.high >= Lower() &&
iBar.close >= Lower())
//
;
//
bool isInside =
isInsideFromUpper ||
isInsideFromLower;
if (isInside)
{
//
result = isInside &&
isBullish
? isInsideFromUpper
: isInsideFromLower;
if (result)
{
//
activatedBar = iBar;
iBar.Clean();
startedBar.Clean();
break;
}
}
//
iBar.Clean();
startedBar.Clean();
}
//
result = activatedBar.IsValid();
if (result)
{
//
isBodyIn =
isBullish
? activatedBar.IsBearish() &&
activatedBar.GetDown() < Upper()
: activatedBar.IsBullish() &&
activatedBar.GetUp() > Lower();
}
//
return result;
}
/**
* Check Zone reaked or not ...
*
* @param forDir: exit direction ...
* @param breakedBar: specified Breaked Bar ...
* @param isBodyOut: specified Breaked Bar Close is Out of Zone or not ...
* @param ignoreStart: Ignore Zone Start (Calculate from From()) ...
* @param startedBodyOut: Started Bar Body Close State, if use Start for Calculation ...
* @param forPeriod: specified Period ...
*
* @return ( bool )
*/
bool IsBreaked(
ENUM_X_DIRECTION forDir,
XOHCL &breakedBar,
bool &isBodyOut,
bool ignoreStart = false,
bool startedBodyOut = false,
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
bool result = false;
//
isBodyOut = false;
breakedBar.Clean();
//
result = HasDirection(forDir) &&
IsValidTwoBarZone();
if (!result)
{
return result;
}
//
bool isBullish = IsBullish(forDir);
//
if (!IsSpecifiedValid(forPeriod))
{
forPeriod = GetPeriod();
}
//
int fromIndex = -1;
if (!ignoreStart)
{
//
XOHCL startedBar;
bool isBodyOut = false;
bool isStarted = IsStarted(
forDir,
startedBar,
isBodyOut,
forPeriod //
);
//
bool isStartPassed =
!startedBodyOut
? isStarted
: isStarted &&
isBodyOut;
if (isStartPassed)
{
fromIndex = startedBar.Index() - 1;
}
//
startedBar.Clean();
}
else
{
//
fromIndex = iBarShift(
GetSymbol(),
forPeriod,
From() //
);
}
//
result = IsValidIndex(fromIndex);
if (!result)
{
return result;
}
//
for (int i = fromIndex; i >= 0; i--)
{
//
XOHCL iBar;
bool isInited = iBar.Init(
GetSymbol(),
forPeriod,
i //
);
result = isInited;
if (!result)
{
//
iBar.Clean();
continue;
}
//
bool isBreakedFromUpper =
//
iBar.low > Upper() ||
(iBar.low <= Upper() &&
iBar.high > Upper() &&
iBar.close > Upper())
//
;
//
bool isBreakedFromLower =
//
iBar.low < Lower() ||
(iBar.high >= Lower() &&
iBar.low < Lower() &&
iBar.close < Lower())
//
;
//
bool isBreaked =
isBreakedFromUpper ||
isBreakedFromLower;
if (isBreaked)
{
//
result = isBreaked &&
(isBullish
? isBreakedFromLower
: isBreakedFromUpper);
if (result)
{
//
breakedBar = iBar;
iBar.Clean();
break;
}
}
//
iBar.Clean();
}
//
result = breakedBar.IsValid();
if (result)
{
//
isBodyOut =
isBullish
? breakedBar.IsBearish() &&
breakedBar.GetDown() < Lower()
: breakedBar.IsBullish() &&
breakedBar.GetUp() > Upper();
}
//
return result;
}
/**
* Check Zone Worked or not ...
*
* @param forDir: exit direction ...
* @param workedBar: specified Worked Bar ...
* @param isBodyOut: specified Worked Bar Close is Out of Zone or not ...
* @param ignoreActivation: Ignore Zone Activation (Calculate from From()) ...
* @param activationStartedOut: Specified Zone Start Bar State ...
* @param activationBodyIn: Specified Zone Activation Bar State ...
* @param forPeriod: specified Period ...
*
* @return ( bool )
*/
bool IsWorked(
ENUM_X_DIRECTION forDir,
XOHCL &workedBar,
bool &isBodyOut,
bool ignoreActivation = false,
bool activationStartedOut = false,
bool activationBodyIn = false,
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
bool result = false;
//
isBodyOut = false;
workedBar.Clean();
//
result = HasDirection(forDir) &&
IsValidTwoBarZone();
if (!result)
{
return result;
}
//
bool isBullish = IsBullish(forDir);
//
if (!IsSpecifiedValid(forPeriod))
{
forPeriod = GetPeriod();
}
//
int fromIndex = -1;
if (!ignoreActivation)
{
//
XOHCL activatedBar;
bool isBodyIn = false;
bool isActivated = IsActivated(
forDir,
activatedBar,
isBodyIn,
activationStartedOut,
forPeriod //
);
//
bool isActivationPassed =
!activationBodyIn
? isActivated
: isActivated &&
isBodyIn;
if (isActivationPassed)
{
fromIndex = activatedBar.Index() - 1;
}
//
activatedBar.Clean();
}
else
{
//
fromIndex = iBarShift(
GetSymbol(),
forPeriod,
From() //
);
}
//
result = IsValidIndex(fromIndex);
if (!result)
{
return result;
}
//
for (int i = fromIndex; i >= 0; i--)
{
//
XOHCL iBar;
bool isInited = iBar.Init(
GetSymbol(),
forPeriod,
i //
);
result = isInited;
if (!result)
{
//
iBar.Clean();
continue;
}
//
bool isBreakedFromUpper =
//
iBar.low > Upper() ||
(iBar.low <= Upper() &&
iBar.high > Upper() &&
iBar.close > Upper())
//
;
//
bool isBreakedFromLower =
//
iBar.low < Lower() ||
(iBar.high >= Lower() &&
iBar.low < Lower() &&
iBar.close < Lower())
//
;
//
bool isBreaked =
isBreakedFromUpper ||
isBreakedFromLower;
if (isBreaked)
{
//
result = isBreaked &&
isBullish
? isBreakedFromUpper
: isBreakedFromLower;
if (result)
{
//
workedBar = iBar;
iBar.Clean();
break;
}
}
//
iBar.Clean();
}
//
result = workedBar.IsValid();
if (result)
{
//
isBodyOut =
isBullish
? workedBar.IsBullish() &&
workedBar.GetUp() > Upper()
: workedBar.IsBearish() &&
workedBar.GetDown() < Lower();
}
//
return result;
}
/**
* Check to Find Nearest Bar which Breakes Upper ...
*
* @param bar: XOHCL instance Reference, Breaker Bar ...
* @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ...
*
* @return ( bool )
*/
bool FindNearestInsideBarFromUpper(
XOHCL &bar,
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
bool result = false;
//
bar.Clean();
//
if (!IsSpecifiedValid(forPeriod))
{
forPeriod = GetPeriod();
}
//
result = IsValid();
if (!result)
{
return result;
}
//
int from = 1;
int to = iBarShift(
GetSymbol(),
forPeriod,
From() //
);
//
for (int i = from; i < to; i++)
{
//
XOHCL iBar;
bool isInited = iBar.Init(
GetSymbol(),
forPeriod,
i //
);
if (!isInited)
{
break;
}
//
bool isInside = iBar.low < Upper();
if (isInside)
{
//
bar = iBar;
break;
}
}
//
result = bar.IsValid();
//
return result;
}
/**
* Check to Find Nearest Bar which Breakes Lower ...
*
* @param bar: XOHCL instance Reference, Breaker Bar ...
* @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ...
*
* @return ( bool )
*/
bool FindNearestInsideBarFromLower(
XOHCL &bar,
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
bool result = false;
//
bar.Clean();
//
if (!IsSpecifiedValid(forPeriod))
{
forPeriod = GetPeriod();
}
//
result = IsValid();
if (!result)
{
return result;
}
//
int from = 1;
int to = iBarShift(
GetSymbol(),
forPeriod,
From() //
);
//
for (int i = from; i < to; i++)
{
//
XOHCL iBar;
bool isInited = iBar.Init(
GetSymbol(),
forPeriod,
i //
);
if (!isInited)
{
break;
}
//
bool isInside = iBar.high > Lower();
if (isInside)
{
//
bar = iBar;
break;
}
}
//
result = bar.IsValid();
//
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 useRangeAsStart = false //
)
{
//
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 =
!useRangeAsStart
? (datetime)((int)time - (range * periodSeconds))
: time;
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 useRangeAsStart = false //
)
{
//
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 =
!useRangeAsStart
? (datetime)((int)time - (range * periodSeconds))
: time;
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 useRangeAsStart = false //
)
{
//
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 =
!useRangeAsStart
? (datetime)((int)time - (range * periodSeconds))
: time;
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 useRangeAsStart = false //
)
{
//
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 =
!useRangeAsStart
? (datetime)((int)time - (range * periodSeconds))
: time;
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;
}
ENUM_X_DIRECTION GetDirection()
{
//
ENUM_X_DIRECTION result = X_DIRECTION_NONE;
//
if (!IsValid())
{
return result;
}
//
result =
IsBullish()
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
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;
//
ENUM_X_PRICE startPrice = isDirBullish
? X_PRICE_HIGH
: X_PRICE_LOW;
ENUM_X_PRICE endPrice = isDirBullish
? X_PRICE_LOW
: X_PRICE_HIGH;
//
result = InitTwoBarZone(
startBar,
endBar,
mTT,
startPrice,
endPrice //
);
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;
}
ENUM_X_DIRECTION GetDirection()
{
//
ENUM_X_DIRECTION result = X_DIRECTION_NONE;
//
if (!IsValid())
{
return result;
}
//
result =
IsBullish()
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
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,
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
bool result = false;
//
result = endBar.IsValid() &&
startBar.IsValid();
if (!result)
{
return result;
}
//
if (!IsSpecifiedValid(forPeriod))
{
forPeriod = endBar.period;
}
//
// 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,
forPeriod,
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,
forPeriod,
to1M //
);
int from1MIndex = iBarShift(
symbol,
forPeriod,
from //
);
for (int i = from1MIndex; i > to1MIndex; i--)
{
//
XOHCL iBar;
bool isInited = iBar.Init(
symbol,
forPeriod,
i //
);
if (!isInited)
{
continue;
}
ulong iVolume = iTickVolume(
symbol,
forPeriod,
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);
//
if (mVolumes > 0)
{
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:
//
//
};
//
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;
//
ZeroMemory(this);
}
/**
* 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;
}
bool IsBullish()
{
return IsValid() &&
IsBullish(dir);
}
bool IsBearish()
{
return IsValid() &&
IsBearish(dir);
}
bool IsSameAs(XBoxZone &item)
{
//
return IsValid() &&
dir == item.dir &&
from == item.from &&
type == item.type &&
lower == item.lower &&
upper == item.upper &&
symbol == item.symbol &&
period == item.period;
}
/**
* Check Box is Same as another ...
*
* @param box: XBoxZone instance Reference ...
*
* @return ( bool )
*/
bool IsSame(XBoxZone &box)
{
//
bool result = false;
//
result = IsValid() &&
box.IsValid();
if (!result)
{
return result;
}
//
result =
//
dir == box.dir &&
from == box.from &&
type == box.type &&
upper == box.upper &&
lower == box.lower &&
symbol == box.symbol &&
period == box.period
//
;
//
return result;
}
/**
* Retrieve Box Age ...
*
* @param forPeriod: ENUM_TIMEFRAMES member ...
*
* @return ( int )
*/
int GetAge(
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
int result = 0;
//
if (!IsValid())
{
return result;
}
//
if (!IsValid(forPeriod))
{
forPeriod = period;
}
//
result = iBarShift(
symbol,
forPeriod,
from //
);
//
return result;
}
/**
* Retrieve Unique Identifier ...
*
* @return ( string )
*/
string GetTag()
{
//
string result =
//
"XBOX" + "_" +
ToString(dir) + "_" +
symbol + "_" +
ToString(period) + "_" +
ToString(upper) + "_" +
ToString(lower)
//
;
//
return result;
}
};
//