8203 lines
143 KiB
Plaintext
8203 lines
143 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;
|
|
}
|
|
|
|
/**
|
|
* Is Zone Activated ...
|
|
*
|
|
* @param forDir: ENUM_X_DIRECTION member, Specified Action Direction ...
|
|
* @param activatedBar: XOHCL instance Reference ...
|
|
* @param activatedDir: ENUM_X_DIRECTION member ...
|
|
* @param forPeriod: ENUM_TIMEFRAMES member, Specified Rejection Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsActivated(
|
|
ENUM_X_DIRECTION forDir,
|
|
XOHCL &activatedBar,
|
|
ENUM_X_DIRECTION &activatedDir,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
activatedBar.Clean();
|
|
activatedDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
if (!IsSpecifiedValid(forPeriod))
|
|
{
|
|
forPeriod = GetPeriod();
|
|
}
|
|
|
|
//
|
|
result = IsValid() &&
|
|
HasDirection(forDir) &&
|
|
IsSpecifiedValid(forPeriod);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL startedBar;
|
|
ENUM_X_DIRECTION startedDir;
|
|
bool isStarted = IsStarted(
|
|
forDir,
|
|
startedBar,
|
|
startedDir,
|
|
forPeriod //
|
|
);
|
|
result = isStarted;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(forDir);
|
|
bool isBearish = IsBearish(forDir);
|
|
|
|
//
|
|
int startIndex = startedBar.Index() - 1;
|
|
|
|
//
|
|
for (int i = startIndex; i >= 0; i--)
|
|
{
|
|
//
|
|
XOHCL iBar;
|
|
bool isInited = iBar.Init(
|
|
GetSymbol(),
|
|
forPeriod,
|
|
i //
|
|
);
|
|
result = isInited;
|
|
if (!result)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
XOHCL iPBar;
|
|
isInited = iBar.GetPreviousBar(iPBar);
|
|
result = isInited;
|
|
if (!result)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isActivedFromUpper =
|
|
//
|
|
isBullish &&
|
|
//
|
|
(
|
|
//
|
|
(iPBar.low > Upper() &&
|
|
iBar.low <= Upper())
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isActivedFromLower =
|
|
//
|
|
isBearish &&
|
|
//
|
|
(
|
|
//
|
|
(iPBar.high < Lower() &&
|
|
iBar.high >= Lower())
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isActivated =
|
|
isActivedFromUpper ||
|
|
isActivedFromLower;
|
|
if (isActivated)
|
|
{
|
|
//
|
|
result = isActivated;
|
|
activatedBar = iBar;
|
|
activatedDir =
|
|
isActivedFromUpper
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_BULLISH;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = activatedBar.IsValid() &&
|
|
HasDirection(activatedDir);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Is Zone Breaked ...
|
|
*
|
|
* @param forDir: ENUM_X_DIRECTION member, Specified Action Direction ...
|
|
* @param breakerBar: XOHCL instance Reference ...
|
|
* @param breakerDir: ENUM_X_DIRECTION member ...
|
|
* @param ignoreActivation: ignore Zone Activation and Used Start ...
|
|
* @param forPeriod: ENUM_TIMEFRAMES member, Specified Rejection Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBreaked(
|
|
ENUM_X_DIRECTION forDir,
|
|
XOHCL &breakerBar,
|
|
ENUM_X_DIRECTION &breakerDir,
|
|
bool ignoreActivation = false,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
breakerBar.Clean();
|
|
breakerDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
if (!IsSpecifiedValid(forPeriod))
|
|
{
|
|
forPeriod = GetPeriod();
|
|
}
|
|
|
|
//
|
|
result = IsValid() &&
|
|
HasDirection(forDir) &&
|
|
IsSpecifiedValid(forPeriod);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(forDir);
|
|
bool isBearish = IsBearish(forDir);
|
|
int activatedIndex = -1;
|
|
|
|
//
|
|
if (!ignoreActivation)
|
|
{
|
|
//
|
|
XOHCL activatedBar;
|
|
ENUM_X_DIRECTION activatedDir;
|
|
bool isActivated = IsActivated(
|
|
forDir,
|
|
activatedBar,
|
|
activatedDir,
|
|
forPeriod //
|
|
);
|
|
result = isActivated;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
activatedIndex = activatedBar.Index();
|
|
}
|
|
else
|
|
{
|
|
//
|
|
XOHCL startedBar;
|
|
ENUM_X_DIRECTION startedDir;
|
|
bool isStarted = IsActivated(
|
|
forDir,
|
|
startedBar,
|
|
startedDir,
|
|
forPeriod //
|
|
);
|
|
result = isStarted;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
activatedIndex = startedBar.Index();
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(activatedIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
activatedIndex--;
|
|
|
|
//
|
|
for (int i = activatedIndex; i >= 0; i--)
|
|
{
|
|
//
|
|
XOHCL iBar;
|
|
bool isInited = iBar.Init(
|
|
GetSymbol(),
|
|
forPeriod,
|
|
i //
|
|
);
|
|
result = isInited;
|
|
if (!result)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
XOHCL iPBar;
|
|
isInited = iBar
|
|
.GetPreviousBar(iPBar);
|
|
result = isInited;
|
|
if (!result)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isBreakedFromUpper =
|
|
//
|
|
isBullish &&
|
|
//
|
|
(
|
|
//
|
|
iBar.low > Upper() ||
|
|
(iBar.low <= Upper() &&
|
|
iBar.high > Upper())
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isBreakedFromLower =
|
|
//
|
|
isBearish &&
|
|
//
|
|
(
|
|
//
|
|
iBar.low < Lower() ||
|
|
(iBar.high >= Lower() &&
|
|
iBar.low < Lower())
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isBreaked =
|
|
isBreakedFromUpper ||
|
|
isBreakedFromLower;
|
|
if (isBreaked)
|
|
{
|
|
//
|
|
result = isBreaked;
|
|
breakerBar = iBar;
|
|
breakerDir =
|
|
isBreakedFromUpper
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = breakerBar.IsValid() &&
|
|
HasDirection(breakerDir);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Is Zone Started ...
|
|
*
|
|
* @param forDir: ENUM_X_DIRECTION member, Specified Action Direction ...
|
|
* @param breakerBar: XOHCL instance Reference ...
|
|
* @param breakerDir: ENUM_X_DIRECTION member ...
|
|
* @param forPeriod: ENUM_TIMEFRAMES member, Specified Rejection Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsStarted(
|
|
ENUM_X_DIRECTION forDir,
|
|
XOHCL &startedBar,
|
|
ENUM_X_DIRECTION &startedDir,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
startedBar.Clean();
|
|
startedDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
if (!IsSpecifiedValid(forPeriod))
|
|
{
|
|
forPeriod = GetPeriod();
|
|
}
|
|
|
|
//
|
|
result = IsValid() &&
|
|
HasDirection(forDir) &&
|
|
IsSpecifiedValid(forPeriod);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(forDir);
|
|
bool isBearish = IsBearish(forDir);
|
|
|
|
//
|
|
// 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)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isBreakedFromUpper =
|
|
//
|
|
isBullish &&
|
|
//
|
|
(
|
|
//
|
|
iBar.low > Upper() ||
|
|
(iBar.low <= Upper() &&
|
|
iBar.high > Upper())
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isBreakedFromLower =
|
|
//
|
|
isBearish &&
|
|
//
|
|
(
|
|
//
|
|
iBar.low < Lower() ||
|
|
(iBar.high >= Lower() &&
|
|
iBar.low < Lower())
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isBreaked =
|
|
isBreakedFromUpper ||
|
|
isBreakedFromLower;
|
|
if (isBreaked)
|
|
{
|
|
//
|
|
result = isBreaked;
|
|
startedBar = iBar;
|
|
startedDir =
|
|
isBreakedFromUpper
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = startedBar.IsValid() &&
|
|
HasDirection(startedDir);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Is Zone Rejected/Sweeped ...
|
|
*
|
|
* @param forDir: ENUM_X_DIRECTION member, Specified Action Direction ...
|
|
* @param rejectedBar: XOHCL instance Reference ...
|
|
* @param rejectedDir: ENUM_X_DIRECTION member, Provides Rejection Direction ...
|
|
* @param from: datetime start checking optional ...
|
|
* @param forceSweep: bool, Specified Force Sweep Rejection ...
|
|
* @param forPeriod: ENUM_TIMEFRAMES member, Specified Rejection Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsRejected(
|
|
ENUM_X_DIRECTION forDir,
|
|
XOHCL &rejectedBar,
|
|
ENUM_X_DIRECTION &rejectedDir,
|
|
datetime from = NULL,
|
|
bool forceSweep = false,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
rejectedBar.Clean();
|
|
rejectedDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
if (!IsSpecifiedValid(forPeriod))
|
|
{
|
|
forPeriod = GetPeriod();
|
|
}
|
|
|
|
//
|
|
if (!IsSpecifiedValid(from))
|
|
{
|
|
from = From();
|
|
}
|
|
|
|
//
|
|
result = IsValid() &&
|
|
HasDirection(forDir) &&
|
|
IsSpecifiedValid(forPeriod);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(forDir);
|
|
bool isBearish = IsBearish(forDir);
|
|
|
|
//
|
|
int fromIndex = iBarShift(
|
|
GetSymbol(),
|
|
forPeriod,
|
|
from //
|
|
);
|
|
fromIndex--;
|
|
|
|
//
|
|
for (int i = fromIndex; i >= 0; i--)
|
|
{
|
|
//
|
|
XOHCL iBar;
|
|
bool isInited = iBar.Init(
|
|
GetSymbol(),
|
|
forPeriod,
|
|
i //
|
|
);
|
|
result = isInited;
|
|
if (!result)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isRejectedFromUpper =
|
|
//
|
|
isBullish &&
|
|
//
|
|
(
|
|
//
|
|
(iBar.low <= Upper() &&
|
|
iBar.high > Upper() &&
|
|
iBar.GetUp() > Upper())
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isRejectedFromLower =
|
|
//
|
|
isBearish &&
|
|
//
|
|
(
|
|
//
|
|
(iBar.high >= Lower() &&
|
|
iBar.low < Lower() &&
|
|
iBar.GetDown() < Lower())
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isSweepedFromUpper =
|
|
//
|
|
isBullish &&
|
|
//
|
|
(
|
|
//
|
|
(iBar.low <= Lower() &&
|
|
iBar.high > Upper() &&
|
|
iBar.GetUp() > Upper())
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isSweepedFromLower =
|
|
//
|
|
isBearish &&
|
|
//
|
|
(
|
|
//
|
|
(iBar.high >= Upper() &&
|
|
iBar.low < Lower() &&
|
|
iBar.GetDown() < Lower())
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isRejected = isRejectedFromUpper ||
|
|
isRejectedFromLower;
|
|
|
|
//
|
|
bool isSweeped = isSweepedFromUpper ||
|
|
isSweepedFromLower;
|
|
|
|
//
|
|
bool fromUpper = isRejectedFromUpper ||
|
|
isSweepedFromUpper;
|
|
|
|
//
|
|
bool fromLower = isRejectedFromLower ||
|
|
isSweepedFromLower;
|
|
|
|
//
|
|
// Prepare Result ...
|
|
bool isPassed =
|
|
isSweeped ||
|
|
isRejected;
|
|
if (forceSweep)
|
|
{
|
|
isPassed = isSweeped;
|
|
}
|
|
|
|
//
|
|
if (isPassed)
|
|
{
|
|
//
|
|
result = isPassed;
|
|
rejectedBar = iBar;
|
|
rejectedDir =
|
|
fromUpper
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = rejectedBar.IsValid() &&
|
|
HasDirection(rejectedDir);
|
|
|
|
//
|
|
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,
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* Is Zone Activated ...
|
|
*
|
|
* @param forDir: ENUM_X_DIRECTION member, Specified Action Direction ...
|
|
* @param activatedBar: XOHCL instance Reference ...
|
|
* @param activatedDir: ENUM_X_DIRECTION member ...
|
|
* @param forPeriod: ENUM_TIMEFRAMES member, Specified Rejection Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsActivated(
|
|
ENUM_X_DIRECTION forDir,
|
|
XOHCL &activatedBar,
|
|
ENUM_X_DIRECTION &activatedDir,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
activatedBar.Clean();
|
|
activatedDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
if (!IsSpecifiedValid(forPeriod))
|
|
{
|
|
forPeriod = GetPeriod();
|
|
}
|
|
|
|
//
|
|
result = IsValid() &&
|
|
HasDirection(forDir) &&
|
|
IsSpecifiedValid(forPeriod);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL startedBar;
|
|
ENUM_X_DIRECTION startedDir;
|
|
bool isStarted = IsStarted(
|
|
forDir,
|
|
startedBar,
|
|
startedDir,
|
|
forPeriod //
|
|
);
|
|
result = isStarted;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(forDir);
|
|
bool isBearish = IsBearish(forDir);
|
|
|
|
//
|
|
int startIndex = startedBar.Index() - 1;
|
|
|
|
//
|
|
for (int i = startIndex; i >= 0; i--)
|
|
{
|
|
//
|
|
XOHCL iBar;
|
|
bool isInited = iBar.Init(
|
|
GetSymbol(),
|
|
forPeriod,
|
|
i //
|
|
);
|
|
result = isInited;
|
|
if (!result)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
XOHCL iPBar;
|
|
isInited = iBar.GetPreviousBar(iPBar);
|
|
result = isInited;
|
|
if (!result)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isActivedFromUpper =
|
|
//
|
|
isBullish &&
|
|
//
|
|
(
|
|
//
|
|
(iPBar.low > Upper() &&
|
|
iBar.low <= Upper())
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isActivedFromLower =
|
|
//
|
|
isBearish &&
|
|
//
|
|
(
|
|
//
|
|
(iPBar.high < Lower() &&
|
|
iBar.high >= Lower())
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isActivated =
|
|
isActivedFromUpper ||
|
|
isActivedFromLower;
|
|
if (isActivated)
|
|
{
|
|
//
|
|
result = isActivated;
|
|
activatedBar = iBar;
|
|
activatedDir =
|
|
isActivedFromUpper
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_BULLISH;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = activatedBar.IsValid() &&
|
|
HasDirection(activatedDir);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Is Zone Breaked ...
|
|
*
|
|
* @param forDir: ENUM_X_DIRECTION member, Specified Action Direction ...
|
|
* @param breakerBar: XOHCL instance Reference ...
|
|
* @param breakerDir: ENUM_X_DIRECTION member ...
|
|
* @param forPeriod: ENUM_TIMEFRAMES member, Specified Rejection Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBreaked(
|
|
ENUM_X_DIRECTION forDir,
|
|
XOHCL &breakerBar,
|
|
ENUM_X_DIRECTION &breakerDir,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
breakerBar.Clean();
|
|
breakerDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
if (!IsSpecifiedValid(forPeriod))
|
|
{
|
|
forPeriod = GetPeriod();
|
|
}
|
|
|
|
//
|
|
result = IsValid() &&
|
|
HasDirection(forDir) &&
|
|
IsSpecifiedValid(forPeriod);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL activatedBar;
|
|
ENUM_X_DIRECTION activatedDir;
|
|
bool isActivated = IsActivated(
|
|
forDir,
|
|
activatedBar,
|
|
activatedDir,
|
|
forPeriod //
|
|
);
|
|
result = isActivated;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int activatedIndex = activatedBar.Index();
|
|
activatedIndex--;
|
|
|
|
//
|
|
for (int i = activatedIndex; i >= 0; i--)
|
|
{
|
|
//
|
|
XOHCL iBar;
|
|
bool isInited = iBar.Init(
|
|
GetSymbol(),
|
|
forPeriod,
|
|
i //
|
|
);
|
|
result = isInited;
|
|
if (!result)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
XOHCL iPBar;
|
|
isInited = iBar
|
|
.GetPreviousBar(iPBar);
|
|
result = isInited;
|
|
if (!result)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isBreakedFromUpper =
|
|
//
|
|
(iPBar.high <= Upper() &&
|
|
iBar.low > Upper())
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isBreakedFromLower =
|
|
//
|
|
(iPBar.low >= Lower() &&
|
|
iBar.low < Lower())
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isBreaked =
|
|
isBreakedFromUpper ||
|
|
isBreakedFromLower;
|
|
if (isBreaked)
|
|
{
|
|
//
|
|
result = isBreaked;
|
|
breakerBar = iBar;
|
|
breakerDir =
|
|
isBreakedFromUpper
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = breakerBar.IsValid() &&
|
|
HasDirection(breakerDir);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Is Zone Started ...
|
|
*
|
|
* @param forDir: ENUM_X_DIRECTION member, Specified Action Direction ...
|
|
* @param breakerBar: XOHCL instance Reference ...
|
|
* @param breakerDir: ENUM_X_DIRECTION member ...
|
|
* @param forPeriod: ENUM_TIMEFRAMES member, Specified Rejection Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsStarted(
|
|
ENUM_X_DIRECTION forDir,
|
|
XOHCL &startedBar,
|
|
ENUM_X_DIRECTION &startedDir,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
startedBar.Clean();
|
|
startedDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
if (!IsSpecifiedValid(forPeriod))
|
|
{
|
|
forPeriod = GetPeriod();
|
|
}
|
|
|
|
//
|
|
result = IsValid() &&
|
|
HasDirection(forDir) &&
|
|
IsSpecifiedValid(forPeriod);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(forDir);
|
|
bool isBearish = IsBearish(forDir);
|
|
|
|
//
|
|
// 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)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isBreakedFromUpper =
|
|
//
|
|
isBullish &&
|
|
//
|
|
(
|
|
//
|
|
iBar.low > Upper() ||
|
|
(iBar.low <= Upper() &&
|
|
iBar.high > Upper())
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isBreakedFromLower =
|
|
//
|
|
isBearish &&
|
|
//
|
|
(
|
|
//
|
|
iBar.low < Lower() ||
|
|
(iBar.high >= Lower() &&
|
|
iBar.low < Lower())
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isBreaked =
|
|
isBreakedFromUpper ||
|
|
isBreakedFromLower;
|
|
if (isBreaked)
|
|
{
|
|
//
|
|
result = isBreaked;
|
|
startedBar = iBar;
|
|
startedDir =
|
|
isBreakedFromUpper
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = startedBar.IsValid() &&
|
|
HasDirection(startedDir);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Is Zone Rejected/Sweeped ...
|
|
*
|
|
* @param forDir: ENUM_X_DIRECTION member, Specified Action Direction ...
|
|
* @param rejectedBar: XOHCL instance Reference ...
|
|
* @param rejectedDir: ENUM_X_DIRECTION member, Provides Rejection Direction ...
|
|
* @param from: datetime start checking optional ...
|
|
* @param forceSweep: bool, Specified Force Sweep Rejection ...
|
|
* @param forPeriod: ENUM_TIMEFRAMES member, Specified Rejection Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsRejected(
|
|
ENUM_X_DIRECTION forDir,
|
|
XOHCL &rejectedBar,
|
|
ENUM_X_DIRECTION &rejectedDir,
|
|
datetime from = NULL,
|
|
bool forceSweep = false,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
rejectedBar.Clean();
|
|
rejectedDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
if (!IsSpecifiedValid(forPeriod))
|
|
{
|
|
forPeriod = GetPeriod();
|
|
}
|
|
|
|
//
|
|
if (!IsSpecifiedValid(from))
|
|
{
|
|
from = From();
|
|
}
|
|
|
|
//
|
|
result = IsValid() &&
|
|
HasDirection(forDir) &&
|
|
IsSpecifiedValid(forPeriod);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(forDir);
|
|
bool isBearish = IsBearish(forDir);
|
|
|
|
//
|
|
int fromIndex = iBarShift(
|
|
GetSymbol(),
|
|
forPeriod,
|
|
from //
|
|
);
|
|
fromIndex--;
|
|
|
|
//
|
|
for (int i = fromIndex; i >= 0; i--)
|
|
{
|
|
//
|
|
XOHCL iBar;
|
|
bool isInited = iBar.Init(
|
|
GetSymbol(),
|
|
forPeriod,
|
|
i //
|
|
);
|
|
result = isInited;
|
|
if (!result)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isRejectedFromUpper =
|
|
//
|
|
isBullish &&
|
|
//
|
|
(
|
|
//
|
|
(iBar.low <= Upper() &&
|
|
iBar.high > Upper() &&
|
|
iBar.GetUp() > Upper())
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isRejectedFromLower =
|
|
//
|
|
isBearish &&
|
|
//
|
|
(
|
|
//
|
|
(iBar.high >= Lower() &&
|
|
iBar.low < Lower() &&
|
|
iBar.GetDown() < Lower())
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isSweepedFromUpper =
|
|
//
|
|
isBullish &&
|
|
//
|
|
(
|
|
//
|
|
(iBar.low <= Lower() &&
|
|
iBar.high > Upper() &&
|
|
iBar.GetUp() > Upper())
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isSweepedFromLower =
|
|
//
|
|
isBearish &&
|
|
//
|
|
(
|
|
//
|
|
(iBar.high >= Upper() &&
|
|
iBar.low < Lower() &&
|
|
iBar.GetDown() < Lower())
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool isRejected = isRejectedFromUpper ||
|
|
isRejectedFromLower;
|
|
|
|
//
|
|
bool isSweeped = isSweepedFromUpper ||
|
|
isSweepedFromLower;
|
|
|
|
//
|
|
bool fromUpper = isRejectedFromUpper ||
|
|
isSweepedFromUpper;
|
|
|
|
//
|
|
bool fromLower = isRejectedFromLower ||
|
|
isSweepedFromLower;
|
|
|
|
//
|
|
// Prepare Result ...
|
|
bool isPassed =
|
|
isSweeped ||
|
|
isRejected;
|
|
if (forceSweep)
|
|
{
|
|
isPassed = isSweeped;
|
|
}
|
|
|
|
//
|
|
if (isPassed)
|
|
{
|
|
//
|
|
result = isPassed;
|
|
rejectedBar = iBar;
|
|
rejectedDir =
|
|
fromUpper
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = rejectedBar.IsValid() &&
|
|
HasDirection(rejectedDir);
|
|
|
|
//
|
|
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 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;
|
|
}
|
|
|
|
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;
|
|
|
|
//
|
|
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;
|
|
}
|
|
|
|
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 //
|
|
)
|
|
{
|
|
//
|
|
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);
|
|
|
|
//
|
|
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:
|
|
//
|
|
|
|
//
|
|
};
|
|
|
|
//
|
|
//
|
|
// 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);
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
//
|
|
bool HasSwingHighs()
|
|
{
|
|
return IsValidSize(CountSwingHighs());
|
|
}
|
|
|
|
//
|
|
int CountSwingLows()
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ArraySize(swingLows);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasSwingLows()
|
|
{
|
|
return IsValidSize(CountSwingLows());
|
|
}
|
|
|
|
//
|
|
int CountBullishMomentumBars()
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ArraySize(bullishMomentumBars);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasBullishMomentumBars()
|
|
{
|
|
return IsValidSize(CountBullishMomentumBars());
|
|
}
|
|
|
|
//
|
|
int CountBearishMomentumBars()
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ArraySize(bearishMomentumBars);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasBearishMomentumBars()
|
|
{
|
|
return IsValidSize(CountBearishMomentumBars());
|
|
}
|
|
|
|
//
|
|
int CountBullishRejectionBars()
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ArraySize(bullishRejectionBars);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasBullishRejectionBars()
|
|
{
|
|
return IsValidSize(CountBullishRejectionBars());
|
|
}
|
|
|
|
//
|
|
int CountBearishRejectionBars()
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ArraySize(bearishRejectionBars);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasBearishRejectionBars()
|
|
{
|
|
return IsValidSize(CountBearishRejectionBars());
|
|
}
|
|
|
|
//
|
|
int CountSupportZones()
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ArraySize(supportZones);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasSupportZones()
|
|
{
|
|
return IsValidSize(CountSupportZones());
|
|
}
|
|
|
|
//
|
|
int CountResistanceZones()
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ArraySize(resistanceZones);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasResistanceZones()
|
|
{
|
|
return IsValidSize(CountResistanceZones());
|
|
}
|
|
|
|
//
|
|
int CountSupplyZones()
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ArraySize(supplyZones);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasSupplyZones()
|
|
{
|
|
return IsValidSize(CountSupplyZones());
|
|
}
|
|
|
|
//
|
|
int CountDemandZones()
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ArraySize(demandZones);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasDemandZones()
|
|
{
|
|
return IsValidSize(CountDemandZones());
|
|
}
|
|
|
|
//
|
|
int CountBullishOrderBlocks()
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ArraySize(bullishOrderBlocks);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasBullishOrderBlocks()
|
|
{
|
|
return IsValidSize(CountBullishOrderBlocks());
|
|
}
|
|
|
|
//
|
|
int CountBearishOrderBlocks()
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ArraySize(bearishOrderBlocks);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasBearishOrderBlocks()
|
|
{
|
|
return IsValidSize(CountBearishOrderBlocks());
|
|
}
|
|
|
|
//
|
|
int CountBullishFairValueGaps()
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ArraySize(bullishFairValueGaps);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasBullishFairValueGaps()
|
|
{
|
|
return IsValidSize(CountBullishFairValueGaps());
|
|
}
|
|
|
|
//
|
|
int CountBearishFairValueGaps()
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ArraySize(bearishFairValueGaps);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasBearishFairValueGaps()
|
|
{
|
|
return IsValidSize(CountBearishFairValueGaps());
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
//
|
|
// 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;
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
};
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
/**
|
|
* 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 //
|
|
);
|
|
|
|
//
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
template <typename T>
|
|
bool ToBox(
|
|
T *&source[],
|
|
XBoxZone &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)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
bool hasBox = ToBox(
|
|
iBox,
|
|
item //
|
|
);
|
|
|
|
//
|
|
if (hasBox)
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
dest //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
int destCount = ArraySize(dest);
|
|
result = IsValidSize(destCount);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
int GetOldest(
|
|
T *&sourec[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone boxes[];
|
|
bool isConverted = ToBox(
|
|
source,
|
|
boxes //
|
|
);
|
|
if (!isConverted)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int boxesCount = ArraySize(boxes);
|
|
|
|
//
|
|
if (count != boxesCount)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = GetOldest(boxes);
|
|
|
|
//
|
|
Clean(boxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
int GetYoungest(
|
|
T *&source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone boxes[];
|
|
bool isConverted = ToBox(
|
|
source,
|
|
boxes //
|
|
);
|
|
if (!isConverted)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int boxesCount = ArraySize(boxes);
|
|
|
|
//
|
|
if (count != boxesCount)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = GetYoungest(boxes);
|
|
|
|
//
|
|
Clean(boxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsSame(
|
|
T *source,
|
|
T *dest //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = sourceBox.IsSame(destBox);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T, typename F>
|
|
bool IsSameDiff(
|
|
T *source,
|
|
F *dest //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = sourceBox.IsSame(destBox);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsBelow(
|
|
T *source,
|
|
T *dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxBelow(
|
|
sourceBox,
|
|
destBox,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T, typename F>
|
|
bool IsBelowDiff(
|
|
T *source,
|
|
F *dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxBelow(
|
|
sourceBox,
|
|
destBox,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsAbove(
|
|
T *source,
|
|
T *dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxAbove(
|
|
sourceBox,
|
|
destBox,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T, typename F>
|
|
bool IsAboveDiff(
|
|
T *source,
|
|
F *dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxAbove(
|
|
sourceBox,
|
|
destBox,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsInside(
|
|
T *source,
|
|
T *dest //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxInside(
|
|
sourceBox,
|
|
destBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T, typename F>
|
|
bool IsInsideDiff(
|
|
T *source,
|
|
F *dest //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxInside(
|
|
sourceBox,
|
|
destBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool FindIndex(
|
|
int &index,
|
|
T *item,
|
|
T *&items[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
index = -1;
|
|
|
|
//
|
|
XBoxZone itemBox;
|
|
result = ToBox(
|
|
itemBox,
|
|
item //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone itemsBox[];
|
|
result = ToBox(
|
|
items,
|
|
itemsBox //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = FindBoxIndex(
|
|
index,
|
|
itemBox,
|
|
itemsBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsInside(
|
|
double value,
|
|
T *source //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsInsideBox(
|
|
value,
|
|
sourceBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsAbove(
|
|
double value,
|
|
T *source //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsAboveBox(
|
|
value,
|
|
sourceBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsBelow(
|
|
double value,
|
|
T *source //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBelowBox(
|
|
value,
|
|
sourceBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
void UpdateTo(
|
|
T *&source[],
|
|
datetime time = NULL //
|
|
)
|
|
{
|
|
//
|
|
if (!IsValid(time))
|
|
{
|
|
time = TimeCurrent();
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
source[i].To(time);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Find Specified Box Index inside a Collection of Boxes ...
|
|
*
|
|
* @param box: XBoxZone instance Reference ...
|
|
* @param boxes: XBoxZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
bool FindBoxIndex(
|
|
int &index,
|
|
XBoxZone &box,
|
|
XBoxZone &boxes[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
index = -1;
|
|
|
|
//
|
|
int count = ArraySize(boxes);
|
|
result = box.IsValid() &&
|
|
IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = boxes[i];
|
|
|
|
//
|
|
bool isSame = box.IsSame(iBox);
|
|
if (isSame)
|
|
{
|
|
//
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Source Box is Below Dest ...
|
|
*
|
|
* @param source: XBoxZone instance Reference ...
|
|
* @param dest: XBoxZone instance Reference ...
|
|
* @param ignoreInside: bool ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxBelow(
|
|
XBoxZone &source,
|
|
XBoxZone &dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = source.IsValid() &&
|
|
dest.IsValid() &&
|
|
!source.IsSame(dest);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!ignoreInside)
|
|
{
|
|
result = source.upper < dest.lower;
|
|
}
|
|
else
|
|
{
|
|
result = (source.upper < dest.lower ||
|
|
source.upper >= dest.upper) &&
|
|
source.lower < dest.lower;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Source Box is Above Dest ...
|
|
*
|
|
* @param source: XBoxZone instance Reference ...
|
|
* @param dest: XBoxZone instance Reference ...
|
|
* @param ignoreInside: bool ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxAbove(
|
|
XBoxZone &source,
|
|
XBoxZone &dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = source.IsValid() &&
|
|
dest.IsValid() &&
|
|
!source.IsSame(dest);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!ignoreInside)
|
|
{
|
|
result = source.lower > dest.upper;
|
|
}
|
|
else
|
|
{
|
|
result = (source.lower > dest.upper ||
|
|
source.lower <= dest.upper) &&
|
|
source.upper > dest.upper;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Source Box is Inside Dest ...
|
|
*
|
|
* @param source: XBoxZone instance Reference ...
|
|
* @param dest: XBoxZone instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxInside(
|
|
XBoxZone &source,
|
|
XBoxZone &dest //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = source.IsValid() &&
|
|
dest.IsValid() &&
|
|
!source.IsSame(dest);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = source.lower >= dest.lower &&
|
|
source.upper <= dest.upper;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Value is Inside Specified Box ...
|
|
*
|
|
* @param value: double ...
|
|
* @param box: XCBozZone instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsInsideBox(
|
|
double value,
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = value > 0 &&
|
|
box.IsValid() &&
|
|
value <= box.upper &&
|
|
value >= box.lower;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Value is Above Specified Box ...
|
|
*
|
|
* @param value: double ...
|
|
* @param box: XCBozZone instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsAboveBox(
|
|
double value,
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = value > 0 &&
|
|
box.IsValid() &&
|
|
value > box.upper;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Value is Below Specified Box ...
|
|
*
|
|
* @param value: double ...
|
|
* @param box: XCBozZone instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBelowBox(
|
|
double value,
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = value > 0 &&
|
|
box.IsValid() &&
|
|
value < box.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;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XCOrderBlock *item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item != NULL &&
|
|
item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.To();
|
|
box.from = item.From();
|
|
box.upper = item.Upper();
|
|
box.lower = item.Lower();
|
|
box.symbol = item.GetSymbol();
|
|
box.period = item.GetPeriod();
|
|
box.type = item.TypeAsString();
|
|
box.dir = item.IsBullish()
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XCFVG *item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item != NULL &&
|
|
item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.To();
|
|
box.from = item.From();
|
|
box.upper = item.Upper();
|
|
box.lower = item.Lower();
|
|
box.symbol = item.GetSymbol();
|
|
box.period = item.GetPeriod();
|
|
box.type = item.TypeAsString();
|
|
box.dir = item.IsBullish()
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XCSupportZone *item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item != NULL &&
|
|
item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.To();
|
|
box.from = item.From();
|
|
box.upper = item.Upper();
|
|
box.lower = item.Lower();
|
|
box.symbol = item.GetSymbol();
|
|
box.period = item.GetPeriod();
|
|
box.type = item.TypeAsString();
|
|
box.dir = X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XCResistanceZone *item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item != NULL &&
|
|
item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.To();
|
|
box.from = item.From();
|
|
box.upper = item.Upper();
|
|
box.lower = item.Lower();
|
|
box.symbol = item.GetSymbol();
|
|
box.period = item.GetPeriod();
|
|
box.type = item.TypeAsString();
|
|
box.dir = X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XCSupplyZone *item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item != NULL &&
|
|
item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.To();
|
|
box.from = item.From();
|
|
box.upper = item.Upper();
|
|
box.lower = item.Lower();
|
|
box.symbol = item.GetSymbol();
|
|
box.period = item.GetPeriod();
|
|
box.type = item.TypeAsString();
|
|
box.dir = X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XCDemandZone *item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = item != NULL &&
|
|
item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = item.To();
|
|
box.from = item.From();
|
|
box.upper = item.Upper();
|
|
box.lower = item.Lower();
|
|
box.symbol = item.GetSymbol();
|
|
box.period = item.GetPeriod();
|
|
box.type = item.TypeAsString();
|
|
box.dir = X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* Get Oldest Box Index ...
|
|
*
|
|
* @param source: XBoxZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetOldest(
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.from > iBox.from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Youngest Box Index ...
|
|
*
|
|
* @param source: XBoxZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetYoungest(
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.from < iBox.from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
typedef void (*TOnPOIEvent)(ENUM_XPOI_EVENTS event,
|
|
XCBasePOI *param //
|
|
);
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
/**
|
|
* Extract UnActivated Order Blocks ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractUnActivatedOrderBlocks(
|
|
XCOrderBlock *&source[],
|
|
XCOrderBlock *&dest[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(dest);
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
int hasChild = IsValidSize(count);
|
|
if (!hasChild)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCOrderBlock *iChild = source[i];
|
|
ENUM_X_DIRECTION iChildForDir = iChild.GetDirection();
|
|
|
|
//
|
|
// Validate Started Zones ...
|
|
XOHCL iChildStartedBar;
|
|
ENUM_X_DIRECTION iChildStartedDir;
|
|
bool isStarted = iChild.IsStarted(
|
|
iChildForDir,
|
|
iChildStartedBar,
|
|
iChildStartedDir //
|
|
);
|
|
if (!isStarted)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Validate InActive Zone ...
|
|
XOHCL iChildActivatedBar;
|
|
ENUM_X_DIRECTION iChildActivatedDir;
|
|
bool isActivated = iChild.IsActivated(
|
|
iChildForDir,
|
|
iChildActivatedBar,
|
|
iChildActivatedDir //
|
|
);
|
|
if (isActivated)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Validate Zone Iverse Breake ...
|
|
XOHCL iChildBreakedBar;
|
|
ENUM_X_DIRECTION iChildBreakedDir;
|
|
bool isBreaked = iChild.IsBreaked(
|
|
Opposit(iChildForDir),
|
|
iChildBreakedBar,
|
|
iChildBreakedDir,
|
|
true // Ignore Activation ...
|
|
);
|
|
if (isBreaked)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
int iChildIDX = -1;
|
|
bool isIChildExists = FindIndex(
|
|
iChildIDX,
|
|
iChild,
|
|
dest //
|
|
);
|
|
if (isIChildExists)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
iChild,
|
|
dest //
|
|
);
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extract Directinal Based Order Blocks ...
|
|
*
|
|
* @param forDir: ENUM_X_DIRECTION member ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractDirectionalOrderBlocks(
|
|
ENUM_X_DIRECTION forDir,
|
|
XCOrderBlock *&source[],
|
|
XCOrderBlock *&dest[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(dest);
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count) ||
|
|
!HasDirection(forDir))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCOrderBlock *iOB = source[i];
|
|
|
|
//
|
|
ENUM_X_DIRECTION iForDir = iOB.GetDirection();
|
|
if (forDir == iForDir)
|
|
{
|
|
//
|
|
Add(
|
|
iOB,
|
|
dest //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Sort Order Blocks based on Place and Remove unused ...
|
|
*/
|
|
void OrderedSortOrderBlocks(
|
|
XCOrderBlock *youngest,
|
|
XCOrderBlock *&orderBlocks[] //
|
|
)
|
|
{
|
|
//
|
|
int count = ArraySize(orderBlocks);
|
|
if (youngest == NULL ||
|
|
!youngest.IsValid() ||
|
|
!IsValidSize(count))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION dir = youngest.GetDirection();
|
|
bool isBullish = IsBullish(dir);
|
|
|
|
//
|
|
XCOrderBlock *tmp[];
|
|
XCOrderBlock *lastOB = youngest;
|
|
while (IsValidSize(count))
|
|
{
|
|
//
|
|
// Detect Youngest of Collection ...
|
|
int idx = GetYoungest(orderBlocks);
|
|
XCOrderBlock *iOB = orderBlocks[idx];
|
|
ArrayRemove(
|
|
orderBlocks,
|
|
idx,
|
|
1 //
|
|
);
|
|
count = ArraySize(orderBlocks);
|
|
|
|
//
|
|
// Check Direction Must be Same ...
|
|
ENUM_X_DIRECTION iDir = iOB.GetDirection();
|
|
bool isSameDir = dir == iDir;
|
|
if (!isSameDir)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check Creation time Sequence ...
|
|
bool isFromPassed = lastOB.From() > iOB.From();
|
|
if (!isFromPassed)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check Order Block Place ...
|
|
bool isPlacePassed =
|
|
isBullish
|
|
? IsBelow(
|
|
iOB,
|
|
lastOB,
|
|
true // Ignore Inside ...
|
|
)
|
|
: IsAbove(
|
|
iOB,
|
|
lastOB,
|
|
true // Ignore Inside ...
|
|
);
|
|
if (!isPlacePassed)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Update Last OB ...
|
|
lastOB = iOB;
|
|
Add(
|
|
iOB,
|
|
tmp //
|
|
);
|
|
|
|
//
|
|
}
|
|
|
|
//
|
|
// Update Ordered Sorted Order Blocks ...
|
|
count = ArraySize(tmp);
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
Copy(
|
|
tmp,
|
|
orderBlocks //
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Extract Order Flows Swing Points ...
|
|
*
|
|
* @param type: ENUM_X_SWING_TYPE member ...
|
|
* @param swings: double Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractSwingPoints(
|
|
ENUM_X_SWING_TYPE type,
|
|
XCOrderBlock *&orderBlocks[],
|
|
XSwingPoint &swings[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(swings);
|
|
|
|
//
|
|
int count = ArraySize(orderBlocks);
|
|
|
|
//
|
|
if (type == X_NO_SWING ||
|
|
!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool lookingForSwingLows = type == X_SWING_LOW;
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCOrderBlock *iOB = orderBlocks[i];
|
|
|
|
//
|
|
string iSymbol = iOB.GetSymbol();
|
|
ENUM_TIMEFRAMES iPeriod = iOB.GetPeriod();
|
|
|
|
//
|
|
int fromIndex = iBarShift(
|
|
iSymbol,
|
|
iPeriod,
|
|
iOB.From() //
|
|
);
|
|
|
|
//
|
|
fromIndex++;
|
|
|
|
//
|
|
double iValue = 0;
|
|
datetime iVTime = NULL;
|
|
if (lookingForSwingLows)
|
|
{
|
|
//
|
|
int idx = iLowest(
|
|
iSymbol,
|
|
iPeriod,
|
|
MODE_LOW,
|
|
fromIndex //
|
|
);
|
|
|
|
//
|
|
if (IsValidIndex(idx))
|
|
{
|
|
//
|
|
iValue = iLow(
|
|
iSymbol,
|
|
iPeriod,
|
|
idx //
|
|
);
|
|
|
|
//
|
|
iVTime = iTime(
|
|
iSymbol,
|
|
iPeriod,
|
|
idx //
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
int idx = iHighest(
|
|
iSymbol,
|
|
iPeriod,
|
|
MODE_HIGH,
|
|
fromIndex //
|
|
);
|
|
|
|
//
|
|
if (IsValidIndex(idx))
|
|
{
|
|
//
|
|
iValue = iHigh(
|
|
iSymbol,
|
|
iPeriod,
|
|
idx //
|
|
);
|
|
|
|
//
|
|
iVTime = iTime(
|
|
iSymbol,
|
|
iPeriod,
|
|
idx //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
if (iValue > 0)
|
|
{
|
|
//
|
|
XSwingPoint iSwingP;
|
|
|
|
//
|
|
iSwingP.type = type;
|
|
iSwingP.time = iVTime;
|
|
iSwingP.swing = iValue;
|
|
iSwingP.symbol = iSymbol;
|
|
iSwingP.period = iPeriod;
|
|
|
|
//
|
|
if (iSwingP.IsValid())
|
|
{
|
|
//
|
|
AddRef(
|
|
iSwingP,
|
|
swings //
|
|
);
|
|
}
|
|
|
|
//
|
|
iSwingP.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(swings);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
// |