3722 lines
190 KiB
Plaintext
3722 lines
190 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Class Library
|
|
// --------------------------------------
|
|
// Name: XSCX121Strategy
|
|
// Description: provides all based classes for use ...
|
|
//
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property library
|
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
|
#property link "https://www.saherelm.ir"
|
|
#property version "1.00"
|
|
#property strict
|
|
|
|
//
|
|
// Imports ...
|
|
|
|
//
|
|
#include "../../Classes/x-saherelm.x-poi.class.mq5"
|
|
#include "../../Classes/x-saherelm.xalert.class.mq5"
|
|
#include "../../Classes/x-saherelm.xtrade.class.mq5"
|
|
#include "../Libraries/x-121.smc.lib.mq5"
|
|
|
|
//
|
|
// Helper(s) ...
|
|
|
|
//
|
|
// XStrategy Class Implementation(s) ...
|
|
class XCX121SMCStrategy : public XSCBaseAlert
|
|
{
|
|
//
|
|
// Public ...
|
|
public:
|
|
//
|
|
|
|
//
|
|
// Constructor(s) ...
|
|
void XCX121SMCStrategy(
|
|
//
|
|
// Base ...
|
|
string _symbol, // Trading Symbol
|
|
ENUM_TIMEFRAMES _period // Trading TimeFrame
|
|
)
|
|
{
|
|
//
|
|
mSymbol = _symbol;
|
|
mPeriod = _period;
|
|
|
|
//
|
|
Init();
|
|
}
|
|
|
|
//
|
|
// Deconstructor ...
|
|
void ~XCX121SMCStrategy()
|
|
{
|
|
DeInit();
|
|
}
|
|
|
|
//
|
|
// Getter / Setter (s) ...
|
|
|
|
/**
|
|
* Retrieve Symbol ...
|
|
*
|
|
* @return ( string )
|
|
*/
|
|
string Symbol()
|
|
{
|
|
return mSymbol;
|
|
}
|
|
|
|
/**
|
|
* Retrieve TimeFrame ...
|
|
*
|
|
* @return ( ENUM_TIMEFRAMES )
|
|
*/
|
|
ENUM_TIMEFRAMES Period()
|
|
{
|
|
return mPeriod;
|
|
}
|
|
|
|
/**
|
|
* Check Strategy is Disabled or not ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsDisabled()
|
|
{
|
|
return mForceDisabled;
|
|
}
|
|
|
|
/**
|
|
* Get Chart Id ...
|
|
*
|
|
* @return ( long )
|
|
*/
|
|
long ChartIdentification()
|
|
{
|
|
return mChartID;
|
|
}
|
|
|
|
/**
|
|
* Set Chart Id ...
|
|
*
|
|
* @param value: Long ...
|
|
*/
|
|
void ChartIdentification(long value)
|
|
{
|
|
//
|
|
if (value < 0)
|
|
{
|
|
value = 0;
|
|
}
|
|
|
|
//
|
|
mChartID = value;
|
|
if (mPOIDrawer != NULL)
|
|
{
|
|
mPOIDrawer.ChartIdentification(value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get Sub Window Id ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int SubWindowIdentification()
|
|
{
|
|
return mSubWindow;
|
|
}
|
|
|
|
/**
|
|
* Set Sub Window Id ...
|
|
*
|
|
* @param value: Integer ...
|
|
*/
|
|
void SubWindowIdentification(int value)
|
|
{
|
|
//
|
|
if (value < 0)
|
|
{
|
|
value = 0;
|
|
}
|
|
|
|
//
|
|
mSubWindow = value;
|
|
if (mPOIDrawer != NULL)
|
|
{
|
|
mPOIDrawer.SubWindowIdentification(value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get Signal Volume ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double Volume()
|
|
{
|
|
return mVolume;
|
|
}
|
|
|
|
/**
|
|
* Set Signal Volume ...
|
|
*
|
|
* @param value: Double ...
|
|
*/
|
|
void Volume(double value)
|
|
{
|
|
//
|
|
if (value < 0.01)
|
|
{
|
|
value = 0.01;
|
|
}
|
|
|
|
//
|
|
mVolume = value;
|
|
}
|
|
|
|
/**
|
|
* Get Risk/Reward Ratio ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double R2R()
|
|
{
|
|
return mR2R;
|
|
}
|
|
|
|
/**
|
|
* Set Risk/Reward Ratio ...
|
|
*
|
|
* @param value: Double ...
|
|
*/
|
|
void R2R(double value)
|
|
{
|
|
//
|
|
if (value < 0)
|
|
{
|
|
value = 1.5;
|
|
}
|
|
|
|
//
|
|
mR2R = value;
|
|
}
|
|
|
|
/**
|
|
* Get Max Allowed Spread ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double MaxAllowedSpread()
|
|
{
|
|
return mMaxAllowedSpread;
|
|
}
|
|
|
|
/**
|
|
* Set Max Allowed Spread ...
|
|
*
|
|
* @param value: Double ...
|
|
*/
|
|
void MaxAllowedSpread(double value)
|
|
{
|
|
mMaxAllowedSpread = value;
|
|
}
|
|
|
|
/**
|
|
* Get Long Signalling State ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool AllowLong()
|
|
{
|
|
return mAllowLong;
|
|
}
|
|
|
|
/**
|
|
* Set Long Signalling State ...
|
|
*
|
|
* @param value: Boolean ...
|
|
*/
|
|
void AllowLong(bool value)
|
|
{
|
|
mAllowLong = value;
|
|
}
|
|
|
|
/**
|
|
* Get Short Signalling State ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool AllowShort()
|
|
{
|
|
return mAllowShort;
|
|
}
|
|
|
|
/**
|
|
* Set Short Signalling State ...
|
|
*
|
|
* @param value: Argument 1
|
|
*/
|
|
void AllowShort(bool value)
|
|
{
|
|
mAllowShort = value;
|
|
}
|
|
|
|
//
|
|
// Actions ...
|
|
|
|
/**
|
|
* Disable Strategy ...
|
|
*/
|
|
void Disable()
|
|
{
|
|
mForceDisabled = true;
|
|
}
|
|
|
|
/**
|
|
* Enable Strategy ...
|
|
*/
|
|
void Enable()
|
|
{
|
|
mForceDisabled = false;
|
|
}
|
|
|
|
/**
|
|
* Register Signal Event Handler ...
|
|
*
|
|
* @param handler: an Instance of TOnXSignal ...
|
|
*/
|
|
void AddXSignalEventHandler(TOnX121SMCSignal handler)
|
|
{
|
|
//
|
|
Add(
|
|
handler,
|
|
mSignalEventHandlers //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Virtual Actions ...
|
|
|
|
//
|
|
// Check Conditions For Signal and Execute Signal ...
|
|
virtual void HandleTick()
|
|
{
|
|
//
|
|
// Check State ...
|
|
if (IsDisabled())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Check Signalling State ...
|
|
if (!AllowLong() && !AllowShort())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Check Bar Tracker State ...
|
|
if (!mBarTracker.CanProcessBar())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Retrieve Current Tick and Check it's Time
|
|
// by Last Issued Tick ...
|
|
MqlTick cTick;
|
|
bool hasTick = GetTick(
|
|
mSymbol,
|
|
cTick //
|
|
);
|
|
bool isSameAsLast = cTick.time == mLastTick.time;
|
|
if (isSameAsLast)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Update Last Issued Tick ...
|
|
mLastTick = cTick;
|
|
SaveTickData();
|
|
CleanupTicks();
|
|
|
|
//
|
|
// Update POIs ...
|
|
|
|
//
|
|
ENUM_XPOI_EVENTS _1DStates[];
|
|
m1DPOI.Update(_1DStates);
|
|
|
|
//
|
|
ENUM_XPOI_EVENTS _4HStates[];
|
|
m4HPOI.Update(_4HStates);
|
|
|
|
// //
|
|
// ENUM_XPOI_EVENTS _4HSupDemStates[];
|
|
// m4HSupDemPOI.Update(_4HSupDemStates);
|
|
|
|
//
|
|
ENUM_XPOI_EVENTS _15MStates[];
|
|
m15MPOI.Update(_15MStates);
|
|
|
|
//
|
|
ENUM_XPOI_EVENTS _5MStates[];
|
|
m5MPOI.Update(_5MStates);
|
|
|
|
//
|
|
ENUM_XPOI_EVENTS _1MStates[];
|
|
m1MPOI.Update(_1MStates);
|
|
|
|
//
|
|
// Check Current Processing Tick has Signal or not ...
|
|
XSignal signal;
|
|
X121SMCStrategyConditions conditions;
|
|
bool hasSignal = HasSignal(
|
|
signal,
|
|
conditions //
|
|
);
|
|
if (!hasSignal)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Waits Until Next Candle if Current Tick has Signal ...
|
|
mBarTracker.Waits();
|
|
|
|
//
|
|
// Notify Signal Event Handlers ...
|
|
NotifyOnSignalEventHandlers(
|
|
signal,
|
|
conditions //
|
|
);
|
|
|
|
//
|
|
DrawSignal(
|
|
signal,
|
|
conditions //
|
|
);
|
|
|
|
//
|
|
// ClearDraws();
|
|
}
|
|
|
|
//
|
|
// Check Conditions For Signal ...
|
|
virtual bool HasSignal(
|
|
XSignal &signal,
|
|
X121SMCStrategyConditions &conditions //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
signal.Clean();
|
|
conditions.Clean();
|
|
|
|
//
|
|
int pushers = 0;
|
|
|
|
//
|
|
double sl = 0;
|
|
double tp = 0;
|
|
double risk = 0;
|
|
double entry = 0;
|
|
double reward = 0;
|
|
double r2r = R2R();
|
|
double volume = Volume();
|
|
ENUM_POSITION_TYPE type = POSITION_TYPE_BUY;
|
|
ENUM_X_ORDER_MODES mode = X_ORDER_MODE_MARKET;
|
|
|
|
//
|
|
bool hasLong = false;
|
|
bool hasShort = false;
|
|
|
|
//
|
|
// Start Calculations ...
|
|
|
|
//
|
|
double points = GetPoints(mSymbol);
|
|
|
|
//
|
|
int zIndex = 0;
|
|
int cIndex = zIndex + 1;
|
|
int pIndex = cIndex + 1;
|
|
int ppIndex = pIndex + 1;
|
|
|
|
//
|
|
// Retrieve Bars ...
|
|
|
|
//
|
|
// Zero Bar ...
|
|
XOHCL zBar;
|
|
result = zBar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
zIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Last Bar ...
|
|
XOHCL cBar;
|
|
result = cBar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
cIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Previous Bar ...
|
|
XOHCL pBar;
|
|
result = pBar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
pIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isSpreadPassed = IsSpreadPass();
|
|
result = isSpreadPassed;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Reading POI(s) ...
|
|
|
|
//
|
|
// 1D ...
|
|
XPOIState _1DState;
|
|
m1DPOI.GetState(_1DState);
|
|
|
|
//
|
|
// 4H ...
|
|
XPOIState _4HState;
|
|
m4HPOI.GetState(_4HState);
|
|
|
|
//
|
|
// 15M ...
|
|
XPOIState _15MState;
|
|
m15MPOI.GetState(_15MState);
|
|
|
|
//
|
|
// 5M ...
|
|
XPOIState _5MState;
|
|
m5MPOI.GetState(_5MState);
|
|
|
|
//
|
|
// 1M ...
|
|
XPOIState _1MState;
|
|
m1MPOI.GetState(_1MState);
|
|
|
|
//
|
|
// Combine States ...
|
|
XPOIState _CState;
|
|
XPOIState _States[];
|
|
AddRef(
|
|
_1DState,
|
|
_States //
|
|
);
|
|
AddRef(
|
|
_4HState,
|
|
_States //
|
|
);
|
|
AddRef(
|
|
_15MState,
|
|
_States //
|
|
);
|
|
AddRef(
|
|
_5MState,
|
|
_States //
|
|
);
|
|
AddRef(
|
|
_1MState,
|
|
_States //
|
|
);
|
|
CombineStates(
|
|
_CState,
|
|
_States //
|
|
);
|
|
|
|
//
|
|
// Try to Implement SMC Based Conditions ...
|
|
|
|
//
|
|
// 1- First Step is Find a Supply and Demand Zone ...
|
|
// - [] this Zone must be Fresh ...
|
|
// - [] contains Engulfing ...
|
|
// - [] has Order Block ...
|
|
// - [] has FVG ...
|
|
bool isDetected = DetectImportantPOIs(
|
|
conditions,
|
|
_1DState,
|
|
_4HState,
|
|
_15MState,
|
|
_5MState,
|
|
_1MState //
|
|
);
|
|
if (isDetected)
|
|
{
|
|
//
|
|
// Check Conditions for Removing Exists ...
|
|
RemoveConditionsIfExists(conditions);
|
|
|
|
//
|
|
// Add New Condition ...
|
|
AddRef(
|
|
conditions,
|
|
mConditions //
|
|
);
|
|
}
|
|
|
|
//
|
|
conditions.Clean();
|
|
|
|
//
|
|
// Check Conditions for Signal ...
|
|
int conditionsCount = ArraySize(mConditions);
|
|
if (!IsValidSize(conditionsCount))
|
|
{
|
|
//
|
|
result = false;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop through Conditions for Filter Based on POIs ...
|
|
int conditionsIDX = -1;
|
|
for (int i = 0; i < conditionsCount; i++)
|
|
{
|
|
//
|
|
result = false;
|
|
hasLong = false;
|
|
hasShort = false;
|
|
X121SMCStrategyConditions iConditions = mConditions[i];
|
|
|
|
//
|
|
X121SMCMarketStructure structure;
|
|
DetectMarketStructure(
|
|
structure,
|
|
iConditions,
|
|
_1DState,
|
|
_4HState,
|
|
_15MState,
|
|
_5MState,
|
|
_1MState //
|
|
);
|
|
|
|
//
|
|
bool isAllowLong = AllowLong();
|
|
bool isAllowShort = AllowShort();
|
|
result = isAllowLong || isAllowShort;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
bool hasValidDemand = HasValidDemand(iConditions);
|
|
bool hasValidSupply = HasValidSupply(iConditions);
|
|
result = hasValidDemand || hasValidSupply;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
bool isPriceInsideDemandZone =
|
|
pBar.high < iConditions.demandZone.upper;
|
|
bool isPriceInsideSupplyZone =
|
|
pBar.low > iConditions.supplyZone.lower;
|
|
|
|
//
|
|
bool isTicksBullish = IsTicksBullish();
|
|
bool isTicksBearish = IsTicksBearish();
|
|
bool isTicksHasMomentum = IsTicksHasMomentum();
|
|
|
|
//
|
|
double _1Pip = GetPipPrice(iConditions.symbol);
|
|
|
|
//
|
|
// Longs ...
|
|
bool canCheckLong = isAllowLong &&
|
|
hasValidDemand &&
|
|
isTicksBullish &&
|
|
isTicksHasMomentum &&
|
|
isPriceInsideDemandZone;
|
|
if (canCheckLong)
|
|
{
|
|
//
|
|
hasLong = false;
|
|
type = POSITION_TYPE_BUY;
|
|
entry = GetEntry(mSymbol, type);
|
|
|
|
//
|
|
double slCandidates[];
|
|
int slCandidatesCount = DetectSLCandidates(
|
|
slCandidates,
|
|
entry,
|
|
iConditions,
|
|
X_POSITION_TYPE_LONG //
|
|
);
|
|
|
|
//
|
|
// Find Demand Zone ...
|
|
hasLong = slCandidatesCount > 2;
|
|
|
|
//
|
|
if (hasLong)
|
|
{
|
|
//
|
|
double selectedSL = GetMin(slCandidates);
|
|
sl = selectedSL - (5 * _1Pip);
|
|
risk = entry - sl;
|
|
reward = risk * r2r;
|
|
tp = entry + reward;
|
|
|
|
//
|
|
conditionsIDX = i;
|
|
mConditions[i].CleanDemand();
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Shorts ...
|
|
bool canCheckShort = isAllowShort &&
|
|
hasValidSupply &&
|
|
isTicksBearish &&
|
|
isTicksHasMomentum &&
|
|
isPriceInsideSupplyZone;
|
|
if (canCheckShort)
|
|
{
|
|
//
|
|
hasShort = false;
|
|
DrawMarketStructure(
|
|
structure,
|
|
X_POSITION_TYPE_SHORT //
|
|
);
|
|
DrawConditions(iConditions);
|
|
ClearDraws();
|
|
|
|
//
|
|
if (hasShort)
|
|
{
|
|
//
|
|
type = POSITION_TYPE_SELL;
|
|
entry = GetEntry(mSymbol, type);
|
|
sl = iConditions.supplyZone.upper + (10 * points);
|
|
risk = sl - entry;
|
|
reward = risk * r2r;
|
|
tp = entry - reward;
|
|
|
|
//
|
|
conditionsIDX = i;
|
|
mConditions[i].CleanSupply();
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
result = hasLong ||
|
|
hasShort;
|
|
|
|
//
|
|
// Rmove Signal Condition ...
|
|
if (result)
|
|
{
|
|
//
|
|
if (IsValidIndex(conditionsIDX))
|
|
{
|
|
//
|
|
conditions = mConditions[conditionsIDX];
|
|
|
|
//
|
|
bool hasValidDemand = HasValidDemand(mConditions[conditionsIDX]);
|
|
bool hasValidSupply = HasValidSupply(mConditions[conditionsIDX]);
|
|
|
|
//
|
|
if (!hasValidDemand &&
|
|
!hasValidSupply)
|
|
{
|
|
//
|
|
ArrayRemove(
|
|
mConditions,
|
|
conditionsIDX,
|
|
1 //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
signal.sl = sl;
|
|
signal.tp = tp;
|
|
signal.type = type;
|
|
signal.mode = mode;
|
|
signal.entry = entry;
|
|
signal.volume = volume;
|
|
signal.symbol = mSymbol;
|
|
signal.pushers = pushers;
|
|
signal.provider = GetTag();
|
|
signal.time = TimeCurrent();
|
|
signal.period = _5MState.period;
|
|
|
|
//
|
|
result = PrepareSignal(signal);
|
|
|
|
//
|
|
hasLong = false;
|
|
hasShort = false;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Overrides ...
|
|
|
|
//
|
|
// Customize Strategy Identifier ...
|
|
string GetTag() override
|
|
{
|
|
return X121SMCStrategyToken;
|
|
}
|
|
|
|
//
|
|
// Protected ...
|
|
protected:
|
|
//
|
|
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
// Actions ...
|
|
|
|
/**
|
|
* Check Spread Passed for Positions...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsSpreadPass()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int length = 5;
|
|
double pointValue = GetPoints(mSymbol);
|
|
double maxAllowedSpread = MaxAllowedSpread();
|
|
if (maxAllowedSpread > 0)
|
|
{
|
|
maxAllowedSpread *= pointValue;
|
|
}
|
|
else
|
|
{
|
|
maxAllowedSpread = 0;
|
|
}
|
|
|
|
//
|
|
int ticksCount = ArraySize(mTicks);
|
|
if (ticksCount <= length)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int start = -1;
|
|
int end = -1;
|
|
CalculateTicksParams(
|
|
start,
|
|
end,
|
|
length + 1 //
|
|
);
|
|
result = IsValidIndex(start) &&
|
|
IsValidIndex(end);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
end -= 1;
|
|
double spreadAVG = 0;
|
|
for (int i = start; i < end; i++)
|
|
{
|
|
spreadAVG += mTicks[i].spread;
|
|
}
|
|
spreadAVG /= length;
|
|
|
|
//
|
|
double lastSpread = mTicks[ticksCount - 1].spread;
|
|
|
|
//
|
|
result = lastSpread <= spreadAVG &&
|
|
(maxAllowedSpread <= 0
|
|
? true
|
|
: lastSpread <= maxAllowedSpread);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Ticks is Bullish or not ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsTicksBullish()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int start = -1;
|
|
int end = -1;
|
|
int requiredBullishTicks = 5;
|
|
CalculateTicksParams(
|
|
start,
|
|
end,
|
|
requiredBullishTicks //
|
|
);
|
|
result = IsValidIndex(start) &&
|
|
IsValidIndex(end);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = true;
|
|
for (int i = start + 1; i < end; i++)
|
|
{
|
|
//
|
|
XTick iTick = mTicks[i];
|
|
XTick prevTick = mTicks[i - 1];
|
|
|
|
//
|
|
bool isBullish = iTick.bid >= prevTick.bid;
|
|
result = result && isBullish;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Ticks is Bearish or not ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsTicksBearish()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int start = -1;
|
|
int end = -1;
|
|
int requiredBearishTicks = 5;
|
|
CalculateTicksParams(
|
|
start,
|
|
end,
|
|
requiredBearishTicks //
|
|
);
|
|
result = IsValidIndex(start) &&
|
|
IsValidIndex(end);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = true;
|
|
for (int i = start + 1; i < end; i++)
|
|
{
|
|
//
|
|
XTick iTick = mTicks[i];
|
|
XTick prevTick = mTicks[i - 1];
|
|
|
|
//
|
|
bool isBearish = iTick.bid <= prevTick.bid;
|
|
result = result && isBearish;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Ticks Has Momentum or not ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsTicksHasMomentum()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int start = -1;
|
|
int end = -1;
|
|
int requiredTicksForMomentum = 5;
|
|
CalculateTicksParams(
|
|
start,
|
|
end,
|
|
requiredTicksForMomentum //
|
|
);
|
|
result = IsValidIndex(start) &&
|
|
IsValidIndex(end);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = true;
|
|
int lastDiff = 0;
|
|
for (int i = start + 1; i < end; i++)
|
|
{
|
|
//
|
|
XTick iTick = mTicks[i];
|
|
XTick prevTick = mTicks[i - 1];
|
|
|
|
//
|
|
int timeDiff = MathAbs((int)iTick.time - (int)prevTick.bid);
|
|
if (lastDiff <= 0)
|
|
{
|
|
lastDiff = timeDiff;
|
|
}
|
|
result = result && timeDiff >= lastDiff;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
lastDiff = timeDiff;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Prepare and Normalize Signal for Execution in Strategy ...
|
|
*
|
|
* @param signal: XSignal instance ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool PrepareSignal(XSignal &signal)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Check Strategy Is Enables ...
|
|
result = !IsDisabled();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Validate Signal ...
|
|
result = signal.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isLong = IsLong(signal.type);
|
|
|
|
//
|
|
// TODO: Implement Signal Preparation Mechanism here ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Update Supply and Demand Zones ...
|
|
*
|
|
* @param conditions: X121SMCStrategyConditions instance ...
|
|
* @param d1State: XPOIState instance ...
|
|
* @param h4State: XPOIState instance ...
|
|
* @param m15State: XPOIState instance ...
|
|
* @param m5State: XPOIState instance ...
|
|
* @param m1State: XPOIState instance ...
|
|
*/
|
|
bool DetectImportantPOIs(
|
|
X121SMCStrategyConditions &conditions,
|
|
XPOIState &d1State,
|
|
XPOIState &h4State,
|
|
XPOIState &m15State,
|
|
XPOIState &m5State,
|
|
XPOIState &m1State //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare Conditions ...
|
|
|
|
//
|
|
datetime time = TimeCurrent();
|
|
|
|
//
|
|
conditions.Clean();
|
|
conditions.time = time;
|
|
conditions.symbol = mSymbol;
|
|
conditions.period = mPeriod;
|
|
|
|
// //
|
|
// bool d1HasBullishTrend = HasBullishTrend(d1State);
|
|
// bool d1HasBearishTrend = HasBearishTrend(d1State);
|
|
|
|
// //
|
|
// bool h4HasBullishTrend = HasBullishTrend(h4State);
|
|
// bool h4HasBearishTrend = HasBearishTrend(h4State);
|
|
|
|
// //
|
|
// bool m15HasBullishTrend = HasBullishTrend(m15State);
|
|
// bool m15HasBearishTrend = HasBearishTrend(m15State);
|
|
|
|
// //
|
|
// bool m5HasBullishTrend = HasBullishTrend(m5State);
|
|
// bool m5HasBearishTrend = HasBearishTrend(m5State);
|
|
|
|
// //
|
|
// bool m1HasBullishTrend = HasBullishTrend(m1State);
|
|
// bool m1HasBearishTrend = HasBearishTrend(m1State);
|
|
|
|
// //
|
|
// bool isBullishTrendValid = h4HasBullishTrend &&
|
|
// m15HasBullishTrend &&
|
|
// m1HasBullishTrend;
|
|
// if (isBullishTrendValid)
|
|
// {
|
|
// Print("isBullishTrendValid");
|
|
// }
|
|
|
|
// //
|
|
// bool isBearishTrendValid = h4HasBearishTrend &&
|
|
// m15HasBearishTrend &&
|
|
// m1HasBearishTrend;
|
|
// if (isBearishTrendValid)
|
|
// {
|
|
// Print("isBearishTrendValid");
|
|
// }
|
|
|
|
//
|
|
// Combine States ...
|
|
XPOIState states[];
|
|
AddRef(
|
|
d1State,
|
|
states //
|
|
);
|
|
AddRef(
|
|
h4State,
|
|
states //
|
|
);
|
|
AddRef(
|
|
m15State,
|
|
states //
|
|
);
|
|
AddRef(
|
|
m5State,
|
|
states //
|
|
);
|
|
AddRef(
|
|
m1State,
|
|
states //
|
|
);
|
|
XPOIState cState;
|
|
CombineStates(
|
|
cState,
|
|
states //
|
|
);
|
|
|
|
//
|
|
int supplyZonesCount = ArraySize(m15State.supplyZones);
|
|
int demandZonesCount = ArraySize(m15State.demandZones);
|
|
result =
|
|
IsValidSize(demandZonesCount) ||
|
|
IsValidSize(supplyZonesCount);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool checkDemands = true;
|
|
bool checkSupplies = true;
|
|
|
|
//
|
|
// Demand Zone ...
|
|
if (checkDemands)
|
|
{
|
|
//
|
|
for (int i = 0; i < demandZonesCount; i++)
|
|
{
|
|
//
|
|
// Demand Zone ...
|
|
XZone iDemandZone = m15State.demandZones[i];
|
|
iDemandZone.to = time;
|
|
conditions.demandZone = iDemandZone;
|
|
|
|
//
|
|
// Order Blocks ...
|
|
// CState ...
|
|
int orderBlocksCount = ArraySize(cState.bullishOrderBlocks);
|
|
if (IsValidSize(orderBlocksCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < orderBlocksCount; j++)
|
|
{
|
|
//
|
|
XZone jZone = cState.bullishOrderBlocks[j];
|
|
|
|
//
|
|
bool isInside = IsInside(
|
|
jZone,
|
|
iDemandZone,
|
|
X_ZONE_LOWER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
jZone.to = TimeCurrent();
|
|
|
|
//
|
|
AddIfNotExists(
|
|
jZone,
|
|
conditions.bullishOrderBlocks //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Support Zones ...
|
|
// CState ...
|
|
int supportsCount = ArraySize(cState.supportZones);
|
|
if (IsValidSize(supportsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < supportsCount; j++)
|
|
{
|
|
//
|
|
XOHCL jBar = cState.supportZones[j];
|
|
|
|
//
|
|
bool isInside = IsInside(
|
|
jBar,
|
|
iDemandZone,
|
|
X_ZONE_LOWER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
jBar,
|
|
conditions.supports //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fair Value Gaps ...
|
|
// CState ...
|
|
int fvgsCount = ArraySize(cState.bullishFVGs);
|
|
if (IsValidSize(fvgsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < fvgsCount; j++)
|
|
{
|
|
//
|
|
XZone jFVG = cState.bullishFVGs[j];
|
|
|
|
//
|
|
bool isInside = IsInside(
|
|
jFVG,
|
|
iDemandZone,
|
|
X_ZONE_LOWER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
jFVG.to = TimeCurrent();
|
|
|
|
//
|
|
AddIfNotExists(
|
|
jFVG,
|
|
conditions.bullishFVGs //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Swings ...
|
|
// CState ...
|
|
int swingsCount = ArraySize(cState.swingLows);
|
|
if (IsValidSize(swingsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < swingsCount; j++)
|
|
{
|
|
//
|
|
XOHCL jBar = cState.swingLows[j];
|
|
|
|
//
|
|
bool isInside = IsInside(
|
|
jBar,
|
|
iDemandZone,
|
|
X_ZONE_LOWER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
jBar,
|
|
conditions.swingLows //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Momentum Bars ...
|
|
// CState ...
|
|
int momentumBarsCount = ArraySize(cState.momentumBars);
|
|
if (IsValidSize(momentumBarsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < momentumBarsCount; j++)
|
|
{
|
|
//
|
|
XOHCL jBar = cState.momentumBars[j];
|
|
|
|
//
|
|
bool isInside =
|
|
jBar.IsBullish() &&
|
|
jBar.time > iDemandZone.from &&
|
|
IsInside(
|
|
jBar,
|
|
iDemandZone,
|
|
X_ZONE_LOWER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
jBar,
|
|
conditions.bullishMomentumBars //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Rejection Bars ...
|
|
// CState ...
|
|
int rejectionBarsCount = ArraySize(cState.rejectionBars);
|
|
if (IsValidSize(rejectionBarsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < rejectionBarsCount; j++)
|
|
{
|
|
//
|
|
XOHCL jBar = cState.rejectionBars[j];
|
|
|
|
//
|
|
bool isInside =
|
|
jBar.GetLowShadow() > jBar.GetHighShadow() &&
|
|
jBar.time > iDemandZone.from &&
|
|
IsInside(
|
|
jBar,
|
|
iDemandZone,
|
|
X_ZONE_LOWER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
jBar,
|
|
conditions.bullishRejectionBars //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
bool hasValidDemandZone = HasValidDemand(conditions);
|
|
if (!hasValidDemandZone)
|
|
{
|
|
conditions.CleanDemand();
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Supply Zone ...
|
|
if (checkSupplies)
|
|
{
|
|
//
|
|
for (int i = 0; i < supplyZonesCount; i++)
|
|
{
|
|
//
|
|
// Supply Zone ...
|
|
XZone iSupplyZone = m15State.supplyZones[i];
|
|
iSupplyZone.to = time;
|
|
conditions.supplyZone = iSupplyZone;
|
|
|
|
//
|
|
// Order Blocks ...
|
|
// CState ...
|
|
int orderBlocksCount = ArraySize(cState.bearishOrderBlocks);
|
|
if (IsValidSize(orderBlocksCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < orderBlocksCount; j++)
|
|
{
|
|
//
|
|
XZone jZone = cState.bearishOrderBlocks[j];
|
|
|
|
//
|
|
bool isInside = IsInside(
|
|
jZone,
|
|
iSupplyZone,
|
|
X_ZONE_UPPER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
jZone.to = TimeCurrent();
|
|
|
|
//
|
|
AddIfNotExists(
|
|
jZone,
|
|
conditions.bearishOrderBlocks //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Resistance Zones ...
|
|
// CState ...
|
|
int resistancesCount = ArraySize(cState.resistanceZones);
|
|
if (IsValidSize(resistancesCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < resistancesCount; j++)
|
|
{
|
|
//
|
|
XOHCL jBar = cState.resistanceZones[j];
|
|
|
|
//
|
|
bool isInside = IsInside(
|
|
jBar,
|
|
iSupplyZone,
|
|
X_ZONE_UPPER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
jBar,
|
|
conditions.resistances //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fair Value Gaps ...
|
|
// CState ...
|
|
int fvgsCount = ArraySize(cState.bearishFVGs);
|
|
if (IsValidSize(fvgsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < fvgsCount; j++)
|
|
{
|
|
//
|
|
XZone jFVG = cState.bearishFVGs[j];
|
|
|
|
//
|
|
bool isInside = IsInside(
|
|
jFVG,
|
|
iSupplyZone,
|
|
X_ZONE_UPPER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
jFVG.to = TimeCurrent();
|
|
|
|
//
|
|
AddIfNotExists(
|
|
jFVG,
|
|
conditions.bearishFVGs //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Swings ...
|
|
// CState ...
|
|
int swingsCount = ArraySize(cState.swingHighs);
|
|
if (IsValidSize(swingsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < swingsCount; j++)
|
|
{
|
|
//
|
|
XOHCL jBar = cState.swingHighs[j];
|
|
|
|
//
|
|
bool isInside = IsInside(
|
|
jBar,
|
|
iSupplyZone,
|
|
X_ZONE_UPPER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
jBar,
|
|
conditions.swingHighs //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Momentum Bars ...
|
|
// CState ...
|
|
int momentumBarsCount = ArraySize(cState.momentumBars);
|
|
if (IsValidSize(momentumBarsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < momentumBarsCount; j++)
|
|
{
|
|
//
|
|
XOHCL jBar = cState.momentumBars[j];
|
|
|
|
//
|
|
bool isInside =
|
|
jBar.IsBearish() &&
|
|
jBar.time > iSupplyZone.from &&
|
|
IsInside(
|
|
jBar,
|
|
iSupplyZone,
|
|
X_ZONE_UPPER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
jBar,
|
|
conditions.bearishMomentumBars //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Rejection Bars ...
|
|
// CState ...
|
|
int rejectionBarsCount = ArraySize(cState.rejectionBars);
|
|
if (IsValidSize(rejectionBarsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < rejectionBarsCount; j++)
|
|
{
|
|
//
|
|
XOHCL jBar = cState.rejectionBars[j];
|
|
|
|
//
|
|
bool isInside =
|
|
jBar.GetLowShadow() < jBar.GetHighShadow() &&
|
|
jBar.time > iSupplyZone.from &&
|
|
IsInside(
|
|
jBar,
|
|
iSupplyZone,
|
|
X_ZONE_UPPER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
jBar,
|
|
conditions.bearishRejectionBars //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
bool hasValidSupplyZone = HasValidSupply(conditions);
|
|
if (!hasValidSupplyZone)
|
|
{
|
|
conditions.CleanSupply();
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Demand ...
|
|
// Used for Long ...
|
|
bool hasValidDemandZone = HasValidDemand(conditions);
|
|
|
|
//
|
|
// Supply ...
|
|
// Used for Short ...
|
|
bool hasValidSupplyZone = HasValidSupply(conditions);
|
|
|
|
//
|
|
// Check Conditions is Valid or not ...
|
|
result = hasValidDemandZone ||
|
|
hasValidSupplyZone;
|
|
if (!result)
|
|
{
|
|
conditions.Clean();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Validate a Condition ...
|
|
*
|
|
* @param conditions: Argument 1
|
|
* @return ( bool )
|
|
*/
|
|
bool ValidateConditions(X121SMCStrategyConditions &conditions)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = conditions.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool hasValidDemnd = HasValidDemand(conditions);
|
|
bool hasValidSupply = HasValidSupply(conditions);
|
|
result = hasValidDemnd || hasValidSupply;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int zIndex = 0;
|
|
int cIndex = zIndex + 1;
|
|
int pIndex = cIndex + 1;
|
|
|
|
//
|
|
XOHCL zBar;
|
|
result = zBar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
zIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL cBar;
|
|
result = cBar.Init(
|
|
mSymbol,
|
|
mPeriod,
|
|
cIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
hasValidDemnd
|
|
? cBar.high < conditions.demandZone.upper &&
|
|
zBar.high < conditions.demandZone.upper &&
|
|
cBar.low > conditions.demandZone.lower &&
|
|
zBar.low > conditions.demandZone.lower
|
|
: hasValidSupply
|
|
? cBar.high < conditions.demandZone.upper &&
|
|
zBar.high < conditions.demandZone.upper &&
|
|
cBar.low > conditions.demandZone.lower &&
|
|
zBar.low > conditions.demandZone.lower
|
|
: false;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Conditions has Valid Demand ...
|
|
*
|
|
* @param conditions: X121SMCStrategyConditions instance ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasValidDemand(X121SMCStrategyConditions &conditions)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = conditions.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
conditions.demandZone.IsValid() &&
|
|
(ArraySize(conditions.supports) > 0 ||
|
|
ArraySize(conditions.swingLows) > 0 ||
|
|
ArraySize(conditions.bullishFVGs) > 0 ||
|
|
ArraySize(conditions.bullishOrderBlocks) > 0 ||
|
|
ArraySize(conditions.bullishMomentumBars) > 0 ||
|
|
ArraySize(conditions.bullishRejectionBars) > 0)
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Conditions has Valid Supply ...
|
|
*
|
|
* @param conditions: X121SMCStrategyConditions instance ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasValidSupply(X121SMCStrategyConditions &conditions)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = conditions.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
conditions.supplyZone.IsValid() &&
|
|
(ArraySize(conditions.swingHighs) > 0 ||
|
|
ArraySize(conditions.bearishFVGs) > 0 ||
|
|
ArraySize(conditions.resistances) > 0 ||
|
|
ArraySize(conditions.bearishOrderBlocks) > 0 ||
|
|
ArraySize(conditions.bearishMomentumBars) > 0 ||
|
|
ArraySize(conditions.bearishRejectionBars) > 0)
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Market Structure for Specified Conditions ...
|
|
*
|
|
* @param structure: X121SMCMarketStructure instance ...
|
|
* @param conditions: X121SMCStrategyConditions instance ...
|
|
* @param d1State: XPOIState instance ...
|
|
* @param h4State: XPOIState instance ...
|
|
* @param m15State: XPOIState instance ...
|
|
* @param m5State: XPOIState instance ...
|
|
* @param m1State: XPOIState instance ...
|
|
*/
|
|
void DetectMarketStructure(
|
|
X121SMCMarketStructure &structure,
|
|
X121SMCStrategyConditions &conditions,
|
|
XPOIState &d1State,
|
|
XPOIState &h4State,
|
|
XPOIState &m15State,
|
|
XPOIState &m5State,
|
|
XPOIState &m1State //
|
|
)
|
|
{
|
|
//
|
|
structure.Clean();
|
|
|
|
//
|
|
if (!conditions.IsValid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
bool hasValidDemand = HasValidDemand(conditions);
|
|
bool hasValidSupply = HasValidSupply(conditions);
|
|
if (!hasValidDemand && !hasValidSupply)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
structure.supplyZone = conditions.supplyZone;
|
|
structure.demandZone = conditions.demandZone;
|
|
|
|
//
|
|
// Combine States ...
|
|
XPOIState cState;
|
|
XPOIState states[];
|
|
AddRef(
|
|
d1State,
|
|
states //
|
|
);
|
|
AddRef(
|
|
h4State,
|
|
states //
|
|
);
|
|
AddRef(
|
|
m15State,
|
|
states //
|
|
);
|
|
// AddRef(
|
|
// m5State,
|
|
// states //
|
|
// );
|
|
// AddRef(
|
|
// m1State,
|
|
// states //
|
|
// );
|
|
CombineStates(
|
|
cState,
|
|
states //
|
|
);
|
|
|
|
//
|
|
datetime cTime = TimeCurrent();
|
|
|
|
//
|
|
// Supply Zones ...
|
|
int supplysCount = ArraySize(cState.supplyZones);
|
|
if (IsValidSize(supplysCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < supplysCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = cState.supplyZones[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iZone,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
iZone.to = cTime;
|
|
|
|
//
|
|
AddIfNotExists(
|
|
iZone,
|
|
structure.supplyZones //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Demand Zones ...
|
|
int demandsCount = ArraySize(cState.demandZones);
|
|
if (IsValidSize(demandsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < demandsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = cState.demandZones[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iZone,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
iZone.to = cTime;
|
|
|
|
//
|
|
AddIfNotExists(
|
|
iZone,
|
|
structure.demandZones //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Order Blocks ...
|
|
|
|
//
|
|
// Bullish OBs ...
|
|
int bullishOBsCount = ArraySize(cState.bullishOrderBlocks);
|
|
if (IsValidSize(bullishOBsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < bullishOBsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = cState.bullishOrderBlocks[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iZone,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
iZone.to = cTime;
|
|
|
|
//
|
|
AddIfNotExists(
|
|
iZone,
|
|
structure.bullishOrderBlocks //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish OBs ...
|
|
int bearishOBsCount = ArraySize(cState.bearishOrderBlocks);
|
|
if (IsValidSize(bearishOBsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < bearishOBsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = cState.bearishOrderBlocks[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iZone,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
iZone.to = cTime;
|
|
|
|
//
|
|
AddIfNotExists(
|
|
iZone,
|
|
structure.bearishOrderBlocks //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fair Value Gaps ...
|
|
|
|
//
|
|
// Bullish FVGs ...
|
|
int bullishFVGsCount = ArraySize(cState.bullishFVGs);
|
|
if (IsValidSize(bullishFVGsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < bullishFVGsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = cState.bullishFVGs[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iZone,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
iZone.to = cTime;
|
|
|
|
//
|
|
AddIfNotExists(
|
|
iZone,
|
|
structure.bullishFVGs //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish FVGs ...
|
|
int bearishFVGsCount = ArraySize(cState.bearishFVGs);
|
|
if (IsValidSize(bearishFVGsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < bearishFVGsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = cState.bearishFVGs[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iZone,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
iZone.to = cTime;
|
|
|
|
//
|
|
AddIfNotExists(
|
|
iZone,
|
|
structure.bearishFVGs //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Swing Highs ...
|
|
int swingHighsCount = ArraySize(cState.swingHighs);
|
|
if (IsValidSize(swingHighsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < swingHighsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = cState.swingHighs[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iBar,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
structure.swingHighs //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Swing Lows ...
|
|
int swingLowsCount = ArraySize(cState.swingLows);
|
|
if (IsValidSize(swingLowsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < swingLowsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = cState.swingLows[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iBar,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
structure.swingLows //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Support Zones ...
|
|
int supportsCount = ArraySize(cState.supportZones);
|
|
if (IsValidSize(supportsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < supportsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = cState.supportZones[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iBar,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
structure.supports //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Resistance Zones ...
|
|
int resistancesCount = ArraySize(cState.resistanceZones);
|
|
if (IsValidSize(resistancesCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < resistancesCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = cState.resistanceZones[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iBar,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
structure.resistances //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Momentum Bars ...
|
|
int momentumBarCount = ArraySize(cState.momentumBars);
|
|
if (IsValidSize(momentumBarCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < momentumBarCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = cState.momentumBars[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iBar,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
bool isBullish = iBar.IsBullish();
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
structure.bullishMomentumBars //
|
|
);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
structure.bearishMomentumBars //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Rejection Bars ...
|
|
int rejectionBarCount = ArraySize(cState.rejectionBars);
|
|
if (IsValidSize(rejectionBarCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < rejectionBarCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = cState.rejectionBars[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iBar,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
bool isBullish = iBar.GetLowShadow() > iBar.GetHighShadow();
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
structure.bullishRejectionBars //
|
|
);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
structure.bearishRejectionBars //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Search Conditions for Find SL Candidates ...
|
|
*
|
|
* @param candidates: Double Array ...
|
|
* @param entry: Double ...
|
|
* @param structure: X121SMCStrategyConditions instance ...
|
|
* @param type: ENUM_X_POSITION_TYPES member ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int DetectSLCandidates(
|
|
double &candidates[],
|
|
double entry,
|
|
X121SMCStrategyConditions &conditions,
|
|
ENUM_X_POSITION_TYPES type //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (type == X_POSITION_TYPE_NONE ||
|
|
type == X_POSITION_TYPE_ALL)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
Clean(candidates);
|
|
|
|
//
|
|
XOHCL candidateBars[];
|
|
if (type == X_POSITION_TYPE_LONG)
|
|
{
|
|
//
|
|
// Search Bullish Momentum, Rejection Bars and Swing Lows ...
|
|
|
|
//
|
|
// Swing Lows ...
|
|
Copy(
|
|
conditions.swingLows,
|
|
candidateBars,
|
|
false //
|
|
);
|
|
|
|
//
|
|
// Bullish Momentum Bars ...
|
|
Copy(
|
|
conditions.bullishMomentumBars,
|
|
candidateBars,
|
|
false //
|
|
);
|
|
|
|
//
|
|
// Bullish Rejection Bars ...
|
|
Copy(
|
|
conditions.bullishRejectionBars,
|
|
candidateBars,
|
|
false //
|
|
);
|
|
|
|
//
|
|
int count = ArraySize(candidateBars);
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = candidateBars[i];
|
|
|
|
//
|
|
if (iBar.low < entry)
|
|
{
|
|
//
|
|
Add(
|
|
iBar.low,
|
|
candidates //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (type == X_POSITION_TYPE_SHORT)
|
|
{
|
|
//
|
|
// Search Bearish Momentum, Rejection Bars and Swing Highs ...
|
|
|
|
//
|
|
// Swing Highs ...
|
|
Copy(
|
|
conditions.swingHighs,
|
|
candidateBars,
|
|
false //
|
|
);
|
|
|
|
//
|
|
// Bearish Momentum Bars ...
|
|
Copy(
|
|
conditions.bearishMomentumBars,
|
|
candidateBars,
|
|
false //
|
|
);
|
|
|
|
//
|
|
// Bearish Rejection Bars ...
|
|
Copy(
|
|
conditions.bearishRejectionBars,
|
|
candidateBars,
|
|
false //
|
|
);
|
|
|
|
//
|
|
int count = ArraySize(candidateBars);
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = candidateBars[i];
|
|
|
|
//
|
|
if (iBar.high > entry)
|
|
{
|
|
//
|
|
Add(
|
|
iBar.low,
|
|
candidates //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(candidateBars);
|
|
result = ArraySize(candidates);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Combine a Conditions by Conditions List and Remove it if Exists ...
|
|
*
|
|
* @param conditions: X121SMCStrategyConditions instance ...
|
|
*/
|
|
void RemoveConditionsIfExists(X121SMCStrategyConditions &conditions)
|
|
{
|
|
//
|
|
int count = ArraySize(mConditions);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
bool hasValidSupply = HasValidSupply(conditions);
|
|
bool hasValidDemand = HasValidDemand(conditions);
|
|
if (!hasValidSupply && !hasValidDemand)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
X121SMCStrategyConditions iConditions = mConditions[i];
|
|
|
|
//
|
|
bool isSupplySame =
|
|
hasValidSupply &&
|
|
HasValidSupply(iConditions) &&
|
|
conditions.supplyZone.from == iConditions.supplyZone.from &&
|
|
conditions.supplyZone.upper == iConditions.supplyZone.upper &&
|
|
conditions.supplyZone.lower == iConditions.supplyZone.lower;
|
|
bool isDemandSame =
|
|
hasValidDemand &&
|
|
HasValidDemand(iConditions) &&
|
|
conditions.demandZone.from == iConditions.demandZone.from &&
|
|
conditions.demandZone.upper == iConditions.demandZone.upper &&
|
|
conditions.demandZone.lower == iConditions.demandZone.lower;
|
|
|
|
//
|
|
if (isSupplySame || isDemandSame)
|
|
{
|
|
//
|
|
idx = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
if (IsValidIndex(idx))
|
|
{
|
|
//
|
|
ArrayRemove(
|
|
mConditions,
|
|
idx,
|
|
1 //
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear All Conditions ...
|
|
*/
|
|
void ClearConditions()
|
|
{
|
|
Clean(mConditions);
|
|
}
|
|
|
|
//
|
|
/**
|
|
* Notified Signal Event Handler(s) ...
|
|
*
|
|
* @param signal: XSignal instance ...
|
|
* @param conditions: XStrategyConditions instance ...
|
|
*/
|
|
void NotifyOnSignalEventHandlers(
|
|
XSignal &signal,
|
|
X121SMCStrategyConditions &conditions //
|
|
)
|
|
{
|
|
//
|
|
if (!signal.IsValid() || !conditions.IsValid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(mSignalEventHandlers);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
mSignalEventHandlers[i](
|
|
signal,
|
|
conditions //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Draw Functions ...
|
|
|
|
/**
|
|
* Clear all Drawn Objects ...
|
|
*/
|
|
void ClearDraws()
|
|
{
|
|
mDrawnObjects.Clear();
|
|
}
|
|
|
|
/**
|
|
* Remove Specified Drawn Object ...
|
|
*
|
|
* @param name: Object name ...
|
|
*/
|
|
void RemoveObject(string name)
|
|
{
|
|
//
|
|
if (!IsValid(name))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
int count = mDrawnObjects.Total();
|
|
if (!IsValidSize(count))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
string iName = ((CChartObject *)mDrawnObjects.At(i)).Name();
|
|
string iObjName = NULL;
|
|
if (!IsValid(iName))
|
|
{
|
|
iObjName = ((XCBaseObject *)mDrawnObjects.At(i)).ObjName();
|
|
}
|
|
|
|
//
|
|
if ((IsValid(iName) &&
|
|
iName == name) ||
|
|
(IsValid(iObjName) &&
|
|
iObjName == name))
|
|
{
|
|
//
|
|
idx = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
if (IsValidIndex(idx))
|
|
{
|
|
mDrawnObjects.Delete(idx);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Draw Specific Condition ...
|
|
*
|
|
* @param conditions: X121SMCStrategyConditions instance ...
|
|
*/
|
|
void DrawConditions(X121SMCStrategyConditions &conditions)
|
|
{
|
|
//
|
|
if (!conditions.IsValid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
datetime time = TimeCurrent();
|
|
bool hasValidDemand = HasValidDemand(conditions);
|
|
bool hasValidSupply = HasValidSupply(conditions);
|
|
if (!hasValidDemand && !hasValidSupply)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Demand Zone ...
|
|
if (hasValidDemand)
|
|
{
|
|
//
|
|
// Demand ...
|
|
XCDemandZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateDemandZone(
|
|
conditions.demandZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
// RemoveObject(iObj.ObjName());
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
|
|
//
|
|
// Order Blocks ...
|
|
int obsCount = ArraySize(conditions.bullishOrderBlocks);
|
|
if (IsValidSize(obsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < obsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = conditions.bullishOrderBlocks[i];
|
|
|
|
//
|
|
XCBullishOrderBlockObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBullishOrderBlock(
|
|
iZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
// RemoveObject(iObj.ObjName());
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fair Value Gaps ...
|
|
int fvgsCount = ArraySize(conditions.bullishFVGs);
|
|
if (IsValidSize(fvgsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < fvgsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = conditions.bullishFVGs[i];
|
|
|
|
//
|
|
XCBullishFVGObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBullishFVG(
|
|
iZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
// RemoveObject(iObj.ObjName());
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Supports ...
|
|
int supportsCount = ArraySize(conditions.supports);
|
|
if (IsValidSize(supportsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < supportsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = conditions.supports[i];
|
|
|
|
//
|
|
XCSupportZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateSupportZone(
|
|
iBar,
|
|
iObj,
|
|
time //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
// RemoveObject(iObj.ObjName());
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Swings ...
|
|
int swingsCount = ArraySize(conditions.swingLows);
|
|
if (IsValidSize(swingsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < swingsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = conditions.swingLows[i];
|
|
|
|
//
|
|
XCSwingLowObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateSwingLow(
|
|
iBar,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
// RemoveObject(iObj.ObjName());
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Momentum Bars ...
|
|
int momentumBarsCount = ArraySize(conditions.bullishMomentumBars);
|
|
if (IsValidSize(momentumBarsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < momentumBarsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = conditions.bullishMomentumBars[i];
|
|
|
|
//
|
|
XCBullishMomentumBarObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBullishMomentumBar(
|
|
iBar,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
// RemoveObject(iObj.ObjName());
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Rejection Bars ...
|
|
int rejectionBarsCount = ArraySize(conditions.bullishRejectionBars);
|
|
if (IsValidSize(rejectionBarsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < rejectionBarsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = conditions.bullishRejectionBars[i];
|
|
|
|
//
|
|
XCBullishRejectionBarObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBullishRejectionBar(
|
|
iBar,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
// RemoveObject(iObj.ObjName());
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Supply Zone ...
|
|
if (hasValidSupply)
|
|
{
|
|
//
|
|
// Supply ...
|
|
XCSupplyZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateSupplyZone(
|
|
conditions.supplyZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
// RemoveObject(iObj.ObjName());
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
|
|
//
|
|
// Order Blocks ...
|
|
int obsCount = ArraySize(conditions.bearishOrderBlocks);
|
|
if (IsValidSize(obsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < obsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = conditions.bearishOrderBlocks[i];
|
|
|
|
//
|
|
XCBearishOrderBlockObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBearishOrderBlock(
|
|
iZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
// RemoveObject(iObj.ObjName());
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fair Value Gaps ...
|
|
int fvgsCount = ArraySize(conditions.bearishFVGs);
|
|
if (IsValidSize(fvgsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < fvgsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = conditions.bearishFVGs[i];
|
|
|
|
//
|
|
XCBearishFVGObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBearishFVG(
|
|
iZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
// RemoveObject(iObj.ObjName());
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Resistances ...
|
|
int resistancesCount = ArraySize(conditions.resistances);
|
|
if (IsValidSize(resistancesCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < resistancesCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = conditions.resistances[i];
|
|
|
|
//
|
|
XCResistanceZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateResistanceZone(
|
|
iBar,
|
|
iObj,
|
|
time //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
// RemoveObject(iObj.ObjName());
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Swings ...
|
|
int swingsCount = ArraySize(conditions.swingHighs);
|
|
if (IsValidSize(swingsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < swingsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = conditions.swingHighs[i];
|
|
|
|
//
|
|
XCSwingHighObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateSwingHigh(
|
|
iBar,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
// RemoveObject(iObj.ObjName());
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Momentum Bars ...
|
|
int momentumBarsCount = ArraySize(conditions.bearishMomentumBars);
|
|
if (IsValidSize(momentumBarsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < momentumBarsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = conditions.bearishMomentumBars[i];
|
|
|
|
//
|
|
XCBearishMomentumBarObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBearishMomentumBar(
|
|
iBar,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
// RemoveObject(iObj.ObjName());
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Rejection Bars ...
|
|
int rejectionBarsCount = ArraySize(conditions.bearishRejectionBars);
|
|
if (IsValidSize(rejectionBarsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < rejectionBarsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = conditions.bearishRejectionBars[i];
|
|
|
|
//
|
|
XCBearishRejectionBarObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBearishRejectionBar(
|
|
iBar,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
// RemoveObject(iObj.ObjName());
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Draw Specified Market Struture ...
|
|
*
|
|
* @param structure: X121SMCMarketStructure instance ...
|
|
*/
|
|
void DrawMarketStructure(
|
|
X121SMCMarketStructure &structure,
|
|
ENUM_X_POSITION_TYPES type = X_POSITION_TYPE_ALL //
|
|
)
|
|
{
|
|
//
|
|
datetime cTime = TimeCurrent();
|
|
|
|
//
|
|
bool canAll = type == X_POSITION_TYPE_ALL;
|
|
bool canLong = type == X_POSITION_TYPE_LONG;
|
|
bool canShort = type == X_POSITION_TYPE_SHORT;
|
|
|
|
//
|
|
// Supply Zones ...
|
|
int supplysCount = ArraySize(structure.supplyZones);
|
|
if ((canAll || canLong) && IsValidSize(supplysCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < supplysCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = structure.supplyZones[i];
|
|
|
|
//
|
|
XCSupplyZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateSupplyZone(
|
|
iZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Demand Zones ...
|
|
int demandsCount = ArraySize(structure.demandZones);
|
|
if ((canAll || canShort) && IsValidSize(demandsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < demandsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = structure.demandZones[i];
|
|
|
|
//
|
|
XCDemandZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateDemandZone(
|
|
iZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Order Blocks ...
|
|
|
|
//
|
|
// Bullish OBs ...
|
|
int bullishOBsCount = ArraySize(structure.bullishOrderBlocks);
|
|
if ((canAll || canShort) && IsValidSize(bullishOBsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < bullishOBsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = structure.bullishOrderBlocks[i];
|
|
|
|
//
|
|
XCBullishOrderBlockObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBullishOrderBlock(
|
|
iZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish OBs ...
|
|
int bearishOBsCount = ArraySize(structure.bearishOrderBlocks);
|
|
if ((canAll || canLong) && IsValidSize(bearishOBsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < bearishOBsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = structure.bearishOrderBlocks[i];
|
|
|
|
//
|
|
XCBearishOrderBlockObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBearishOrderBlock(
|
|
iZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fair Value Gaps ...
|
|
|
|
//
|
|
// Bullish FVGs ...
|
|
int bullishFVGsCount = ArraySize(structure.bullishFVGs);
|
|
if ((canAll || canShort) && IsValidSize(bullishFVGsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < bullishFVGsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = structure.bullishFVGs[i];
|
|
|
|
//
|
|
XCBullishFVGObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBullishFVG(
|
|
iZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish FVGs ...
|
|
int bearishFVGsCount = ArraySize(structure.bearishFVGs);
|
|
if ((canAll || canLong) && IsValidSize(bearishFVGsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < bearishFVGsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = structure.bearishFVGs[i];
|
|
|
|
//
|
|
XCBearishFVGObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBearishFVG(
|
|
iZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Swing Highs ...
|
|
int swingHighsCount = ArraySize(structure.swingHighs);
|
|
if ((canAll || canLong) && IsValidSize(swingHighsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < swingHighsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = structure.swingHighs[i];
|
|
|
|
//
|
|
XCSwingHighObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateSwingHigh(
|
|
iBar,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Swing Lows ...
|
|
int swingLowsCount = ArraySize(structure.swingLows);
|
|
if ((canAll || canShort) && IsValidSize(swingLowsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < swingLowsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = structure.swingLows[i];
|
|
|
|
//
|
|
XCSwingLowObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateSwingLow(
|
|
iBar,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Support Zones ...
|
|
int supportsCount = ArraySize(structure.supports);
|
|
if ((canAll || canShort) && IsValidSize(supportsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < supportsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = structure.supports[i];
|
|
|
|
//
|
|
XCSupportZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateSupportZone(
|
|
iBar,
|
|
iObj,
|
|
cTime //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Resistance Zones ...
|
|
int resistancesCount = ArraySize(structure.resistances);
|
|
if ((canAll || canLong) && IsValidSize(resistancesCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < resistancesCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = structure.resistances[i];
|
|
|
|
//
|
|
XCResistanceZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateResistanceZone(
|
|
iBar,
|
|
iObj,
|
|
cTime //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Momentum Bars ...
|
|
|
|
//
|
|
// Bullish Momentum Bars ...
|
|
int momentumBarCount = ArraySize(structure.bullishMomentumBars);
|
|
if ((canAll || canShort) && IsValidSize(momentumBarCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < momentumBarCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = structure.bullishMomentumBars[i];
|
|
|
|
//
|
|
XCBullishMomentumBarObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBullishMomentumBar(
|
|
iBar,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish Momentum Bars ...
|
|
momentumBarCount = ArraySize(structure.bearishMomentumBars);
|
|
if ((canAll || canLong) && IsValidSize(momentumBarCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < momentumBarCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = structure.bearishMomentumBars[i];
|
|
|
|
//
|
|
XCBearishMomentumBarObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBearishMomentumBar(
|
|
iBar,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Rejection Bars ...
|
|
|
|
//
|
|
// Bullish Rejection Bars ...
|
|
int rejectionBarCount = ArraySize(structure.bullishRejectionBars);
|
|
if ((canAll || canShort) && IsValidSize(rejectionBarCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < rejectionBarCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = structure.bullishRejectionBars[i];
|
|
|
|
//
|
|
XCBullishRejectionBarObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBullishRejectionBar(
|
|
iBar,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish Rejection Bars ...
|
|
rejectionBarCount = ArraySize(structure.bearishRejectionBars);
|
|
if ((canAll || canLong) && IsValidSize(rejectionBarCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < rejectionBarCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = structure.bearishRejectionBars[i];
|
|
|
|
//
|
|
XCBearishRejectionBarObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBearishRejectionBar(
|
|
iBar,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Draw Specified Signal ...
|
|
*
|
|
* @param signal: XSignal instance ...
|
|
* @param conditions: X121SMCStrategyConditions instance ...
|
|
*/
|
|
void DrawSignal(
|
|
XSignal &signal,
|
|
X121SMCStrategyConditions &conditions //
|
|
)
|
|
{
|
|
//
|
|
if (!signal.IsValid() ||
|
|
!conditions.IsValid())
|
|
{
|
|
//
|
|
return;
|
|
}
|
|
|
|
//
|
|
// DrawConditions(conditions);
|
|
|
|
//
|
|
string name = signal.GetTag();
|
|
RemoveObject(name);
|
|
|
|
//
|
|
XCSignalObject *iObj;
|
|
iObj = new XCSignalObject();
|
|
|
|
//
|
|
bool isCreated = iObj.Create(
|
|
ChartID(),
|
|
name,
|
|
0,
|
|
signal //
|
|
);
|
|
if (!isCreated)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
iObj.TPWidth(1);
|
|
iObj.TPColor(clrGreen);
|
|
iObj.TPWidth(STYLE_DOT);
|
|
|
|
//
|
|
iObj.SLWidth(1);
|
|
iObj.SLColor(clrRed);
|
|
iObj.SLWidth(STYLE_DOT);
|
|
|
|
//
|
|
iObj.EntryWidth(1);
|
|
iObj.EntryColor(clrYellow);
|
|
iObj.EntryWidth(STYLE_DOT);
|
|
|
|
//
|
|
mDrawnObjects.Add(iObj);
|
|
|
|
//
|
|
bool drawConditions = true;
|
|
if (drawConditions)
|
|
{
|
|
DrawConditions(conditions);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Private ...
|
|
private:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
string mSymbol; // Trading Symbol ...
|
|
ENUM_TIMEFRAMES mPeriod; // Trading TimeFrame ...
|
|
bool mForceDisabled; // Force Disabled ...
|
|
bool mAllowLong; // Allow Long Signals
|
|
bool mAllowShort; // Allow Short Signals
|
|
double mR2R; // Risk/Rewar Ratio ...
|
|
double mVolume; // Static Volume Per Trades ...
|
|
double mMaxAllowedSpread; // Max Allowed Spread ...
|
|
|
|
//
|
|
long mChartID; // Chart ID ...
|
|
int mSubWindow; // Sub Window ID ...
|
|
XCPOIDrawer *mPOIDrawer; // POI Drawer Class ...
|
|
|
|
//
|
|
XTick mTicks[]; // Hold Ticks Data ...
|
|
MqlTick mLastTick; // Last Issued Tick ...
|
|
|
|
//
|
|
XBarTracker mBarTracker; // Strategy Time Tracker ...
|
|
|
|
//
|
|
// Point Of Interests ...
|
|
XCPOI *m1DPOI;
|
|
XCPOI *m4HPOI;
|
|
XCPOI *m15MPOI;
|
|
XCPOI *m5MPOI;
|
|
XCPOI *m1MPOI;
|
|
|
|
//
|
|
// Collect all Drawn Objects ...
|
|
CArrayObj mDrawnObjects;
|
|
|
|
//
|
|
XOHCL mSwingHigh;
|
|
CChartObjectHLine *mSwingHighObject;
|
|
|
|
//
|
|
XOHCL mSwingLow;
|
|
CChartObjectHLine *mSwingLowObject;
|
|
|
|
//
|
|
X121SMCStrategyConditions mConditions[];
|
|
|
|
//
|
|
// On X121 Signal Recieved Event Handler(s) ...
|
|
TOnX121SMCSignal mSignalEventHandlers[];
|
|
|
|
//
|
|
// Actions ...
|
|
|
|
/**
|
|
* Install all Helpers and Prepare all Configurations for required Indicators ...
|
|
*/
|
|
void Init()
|
|
{
|
|
//
|
|
mForceDisabled = false;
|
|
|
|
//
|
|
R2R(1.5);
|
|
Volume(0.01);
|
|
|
|
//
|
|
ChartIdentification(0);
|
|
SubWindowIdentification(0);
|
|
|
|
//
|
|
// Configure POI Drawer if Required ...
|
|
mPOIDrawer = new XCPOIDrawer();
|
|
mPOIDrawer.ChartIdentification(0);
|
|
mPOIDrawer.SubWindowIdentification(0);
|
|
|
|
//
|
|
mPOIDrawer.DemandZoneFill(false);
|
|
mPOIDrawer.SupplyZoneFill(false);
|
|
mPOIDrawer.BullishFVGFill(false);
|
|
mPOIDrawer.BearishFVGFill(false);
|
|
mPOIDrawer.SupportZoneFill(false);
|
|
mPOIDrawer.ResistanceZoneFill(false);
|
|
mPOIDrawer.BullishOrderBlockFill(false);
|
|
mPOIDrawer.BearishOrderBlockFill(false);
|
|
|
|
//
|
|
string symbol = Symbol();
|
|
ENUM_TIMEFRAMES period = Period();
|
|
|
|
//
|
|
// Initialize Bar Tracker ...
|
|
mBarTracker.Init(
|
|
symbol,
|
|
period //
|
|
);
|
|
|
|
//
|
|
// Initialize POIs ...
|
|
|
|
//
|
|
// 1D Period ...
|
|
// POI Detector ...
|
|
m1DPOI = new XCPOI(
|
|
symbol,
|
|
PERIOD_D1 //
|
|
);
|
|
|
|
//
|
|
m1DPOI.DisableDrawPOIs();
|
|
m1DPOI.SupplyZonePeriod(PERIOD_W1);
|
|
m1DPOI.DemandZonePeriod(PERIOD_W1);
|
|
m1DPOI.SubWindowIdentification(0);
|
|
m1DPOI.ChartIdentification(ChartID());
|
|
|
|
//
|
|
m1DPOI.Init();
|
|
|
|
//
|
|
// 4H Period ...
|
|
// POI Detector ...
|
|
m4HPOI = new XCPOI(
|
|
symbol,
|
|
PERIOD_H4 //
|
|
);
|
|
|
|
//
|
|
m4HPOI.DisableDrawPOIs();
|
|
m4HPOI.SupplyZonePeriod(PERIOD_D1);
|
|
m4HPOI.DemandZonePeriod(PERIOD_D1);
|
|
m4HPOI.SubWindowIdentification(0);
|
|
m4HPOI.ChartIdentification(ChartID());
|
|
|
|
//
|
|
m4HPOI.Init();
|
|
|
|
//
|
|
// 15M Period ...
|
|
// POI Detector ...
|
|
m15MPOI = new XCPOI(
|
|
symbol,
|
|
PERIOD_M15 //
|
|
);
|
|
|
|
//
|
|
m15MPOI.DisableDrawPOIs();
|
|
m15MPOI.MaxNumberOfRequiredPOIs(2);
|
|
m15MPOI.SupplyZonePeriod(PERIOD_H4);
|
|
m15MPOI.DemandZonePeriod(PERIOD_H4);
|
|
m15MPOI.SubWindowIdentification(0);
|
|
m15MPOI.ChartIdentification(ChartID());
|
|
|
|
//
|
|
m15MPOI.Init();
|
|
|
|
//
|
|
// 5M Period ...
|
|
// POI Detector ...
|
|
m5MPOI = new XCPOI(
|
|
symbol,
|
|
PERIOD_M5 //
|
|
);
|
|
|
|
//
|
|
m5MPOI.DisableDrawPOIs();
|
|
m5MPOI.MaxNumberOfRequiredPOIs(2);
|
|
m5MPOI.SupplyZonePeriod(PERIOD_M15);
|
|
m5MPOI.DemandZonePeriod(PERIOD_M15);
|
|
m5MPOI.SubWindowIdentification(0);
|
|
m5MPOI.ChartIdentification(ChartID());
|
|
|
|
//
|
|
m5MPOI.Init();
|
|
|
|
//
|
|
// 1M Period ...
|
|
// POI Detector ...
|
|
m1MPOI = new XCPOI(
|
|
symbol,
|
|
PERIOD_M1 //
|
|
);
|
|
|
|
//
|
|
m1MPOI.DisableDrawPOIs();
|
|
m1MPOI.SupplyZonePeriod(PERIOD_M5);
|
|
m1MPOI.DemandZonePeriod(PERIOD_M5);
|
|
m1MPOI.SubWindowIdentification(0);
|
|
m1MPOI.ChartIdentification(ChartID());
|
|
|
|
//
|
|
m1MPOI.Init();
|
|
|
|
//
|
|
}
|
|
|
|
/**
|
|
* De Initialize all Tools ...
|
|
*/
|
|
void DeInit()
|
|
{
|
|
//
|
|
delete m1DPOI;
|
|
delete m4HPOI;
|
|
delete m5MPOI;
|
|
delete m1MPOI;
|
|
delete m15MPOI;
|
|
|
|
//
|
|
delete mPOIDrawer;
|
|
|
|
//
|
|
ClearDraws();
|
|
}
|
|
|
|
/**
|
|
* Reste Bar Tracker ...
|
|
*/
|
|
void ResetBarTracker()
|
|
{
|
|
mBarTracker.Clean();
|
|
}
|
|
|
|
/**
|
|
* Cleanup Ticks Size ...
|
|
*/
|
|
void CleanupTicks()
|
|
{
|
|
//
|
|
int maxRequiredTicks = 50;
|
|
int ticksCount = ArraySize(mTicks);
|
|
if (!IsValidSize(ticksCount) ||
|
|
ticksCount <= maxRequiredTicks)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
int removeCount = ticksCount - maxRequiredTicks;
|
|
if (!IsValidSize(removeCount))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
ArrayRemove(
|
|
mTicks,
|
|
0,
|
|
removeCount //
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Add new Tick Data to Collection ...
|
|
*/
|
|
void SaveTickData()
|
|
{
|
|
//
|
|
XTick tick;
|
|
bool isInited = tick.Init(mSymbol);
|
|
if (!isInited)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
AddRef(
|
|
tick,
|
|
mTicks //
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Calculate Ticks Param for Looping through Last n items ...
|
|
*
|
|
* @param start: Integer Reference to Start ...
|
|
* @param end: Integer Reference to End ...
|
|
* @param numOfLastTicks: Integer Max Number of Required N Last Ticks ...
|
|
*/
|
|
void CalculateTicksParams(
|
|
int &start,
|
|
int &end,
|
|
int numOfLastTicks = 5 //
|
|
)
|
|
{
|
|
//
|
|
start = -1;
|
|
end = -1;
|
|
|
|
//
|
|
int count = ArraySize(mTicks);
|
|
|
|
//
|
|
start = count - numOfLastTicks;
|
|
if (start < 0)
|
|
{
|
|
start = 0;
|
|
}
|
|
|
|
//
|
|
end = start + numOfLastTicks;
|
|
if (end > count)
|
|
{
|
|
end = count;
|
|
}
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
// |