983 lines
20 KiB
Plaintext
983 lines
20 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 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 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;
|
||
|
||
//
|
||
// 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 //
|
||
);
|
||
}
|
||
|
||
//
|
||
// Check Conditions For Signal ...
|
||
virtual bool HasSignal(
|
||
XSignal &signal,
|
||
X121SMCStrategyConditions &conditions //
|
||
)
|
||
{
|
||
//
|
||
bool result = false;
|
||
|
||
//
|
||
signal.Clean();
|
||
conditions.Clean();
|
||
|
||
//
|
||
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;
|
||
}
|
||
|
||
//
|
||
// Prepare Conditions ...
|
||
|
||
//
|
||
conditions.symbol = mSymbol;
|
||
conditions.period = mPeriod;
|
||
conditions.time = cBar.time;
|
||
|
||
//
|
||
int pushers = 0;
|
||
string signallers[];
|
||
|
||
//
|
||
// Define Conditions ...
|
||
MqlTick ticks[];
|
||
int ticksCount = CopyTicks(
|
||
mSymbol,
|
||
ticks,
|
||
COPY_TICKS_ALL,
|
||
0,
|
||
5 //
|
||
);
|
||
|
||
//
|
||
bool isTicksBullishForLong = false;
|
||
bool isTicksBearishForLong = false;
|
||
bool isTicksBullishForShort = false;
|
||
bool isTicksBearishForShort = false;
|
||
if (ticksCount == 5)
|
||
{
|
||
//
|
||
isTicksBullishForLong =
|
||
//
|
||
GetTickEntry(ticks[0], POSITION_TYPE_BUY, mSymbol) > GetTickEntry(ticks[1], POSITION_TYPE_BUY, mSymbol) &&
|
||
GetTickEntry(ticks[1], POSITION_TYPE_BUY, mSymbol) > GetTickEntry(ticks[2], POSITION_TYPE_BUY, mSymbol) &&
|
||
GetTickEntry(ticks[2], POSITION_TYPE_BUY, mSymbol) > GetTickEntry(ticks[3], POSITION_TYPE_BUY, mSymbol)
|
||
//
|
||
;
|
||
|
||
//
|
||
isTicksBearishForLong =
|
||
//
|
||
GetTickEntry(ticks[0], POSITION_TYPE_BUY, mSymbol) < GetTickEntry(ticks[1], POSITION_TYPE_BUY, mSymbol) &&
|
||
GetTickEntry(ticks[1], POSITION_TYPE_BUY, mSymbol) < GetTickEntry(ticks[2], POSITION_TYPE_BUY, mSymbol) &&
|
||
GetTickEntry(ticks[2], POSITION_TYPE_BUY, mSymbol) < GetTickEntry(ticks[3], POSITION_TYPE_BUY, mSymbol)
|
||
//
|
||
;
|
||
|
||
//
|
||
isTicksBullishForShort =
|
||
//
|
||
GetTickEntry(ticks[0], POSITION_TYPE_SELL, mSymbol) > GetTickEntry(ticks[1], POSITION_TYPE_SELL, mSymbol) &&
|
||
GetTickEntry(ticks[1], POSITION_TYPE_SELL, mSymbol) > GetTickEntry(ticks[2], POSITION_TYPE_SELL, mSymbol) &&
|
||
GetTickEntry(ticks[2], POSITION_TYPE_SELL, mSymbol) > GetTickEntry(ticks[3], POSITION_TYPE_SELL, mSymbol)
|
||
//
|
||
;
|
||
|
||
//
|
||
isTicksBearishForShort =
|
||
//
|
||
GetTickEntry(ticks[0], POSITION_TYPE_SELL, mSymbol) < GetTickEntry(ticks[1], POSITION_TYPE_SELL, mSymbol) &&
|
||
GetTickEntry(ticks[1], POSITION_TYPE_SELL, mSymbol) < GetTickEntry(ticks[2], POSITION_TYPE_SELL, mSymbol) &&
|
||
GetTickEntry(ticks[2], POSITION_TYPE_SELL, mSymbol) < GetTickEntry(ticks[3], POSITION_TYPE_SELL, mSymbol)
|
||
//
|
||
;
|
||
}
|
||
|
||
//
|
||
// Reading POI(s) ...
|
||
|
||
//
|
||
// 4H ...
|
||
XPOIState _4HState;
|
||
m4HPOI.GetState(_4HState);
|
||
|
||
//
|
||
// 15M ...
|
||
XPOIState _15MState;
|
||
m15MPOI.GetState(_15MState);
|
||
|
||
//
|
||
// 5M ...
|
||
XPOIState _5MState;
|
||
m5MPOI.GetState(_5MState);
|
||
|
||
//
|
||
// 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 ...
|
||
XZone _4hSupplyZone;
|
||
XZone _4HDemandZone;
|
||
DetectSupplyAndDemandZones(
|
||
_4HState,
|
||
_4hSupplyZone,
|
||
_4HDemandZone //
|
||
);
|
||
|
||
//
|
||
if (_4hSupplyZone.IsValid())
|
||
{
|
||
//
|
||
// Update Supply Zone Time ...
|
||
string iName = _4hSupplyZone.GetTag();
|
||
_4hSupplyZone.to = zBar.time;
|
||
|
||
//
|
||
int count = mDrawnObjects.Total();
|
||
if (IsValidSize(count))
|
||
{
|
||
//
|
||
int idx = -1;
|
||
for (int i = 0; i < count; i++)
|
||
{
|
||
//
|
||
int type = ((CChartObject *)mDrawnObjects.At(i)).Type();
|
||
if (type == (int)X_SUPPLY_ZONE)
|
||
{
|
||
//
|
||
string objName = ((XCZoneObject *)mDrawnObjects.At(i)).ObjName();
|
||
if (objName == iName)
|
||
{
|
||
//
|
||
idx = i;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
if (IsValidIndex(idx))
|
||
{
|
||
mDrawnObjects.Delete(idx);
|
||
}
|
||
}
|
||
|
||
//
|
||
iName = _4hSupplyZone.GetTag();
|
||
XCZoneObject *iObj;
|
||
bool isCreated = iObj.CreateByZone(
|
||
ChartID(),
|
||
iName,
|
||
0,
|
||
_4hSupplyZone,
|
||
NULL,
|
||
true //
|
||
);
|
||
}
|
||
|
||
//
|
||
// LONGS ...
|
||
|
||
//
|
||
bool hasLong1 =
|
||
//
|
||
false
|
||
//
|
||
;
|
||
if (hasLong1)
|
||
{
|
||
//
|
||
pushers++;
|
||
Add(
|
||
"LONG_1",
|
||
signallers //
|
||
);
|
||
|
||
//
|
||
// TODO: Implement SL/TP Calculation based on R2R ...
|
||
|
||
//
|
||
// sl = 0;
|
||
type = POSITION_TYPE_BUY;
|
||
}
|
||
|
||
//
|
||
// SHORTS ...
|
||
|
||
//
|
||
bool hasShort1 =
|
||
//
|
||
// TODO: Implement Long Conditions ...
|
||
false
|
||
//
|
||
;
|
||
if (hasShort1)
|
||
{
|
||
//
|
||
pushers++;
|
||
Add(
|
||
"SHORT_1",
|
||
signallers //
|
||
);
|
||
|
||
//
|
||
// TODO: Implement SL/TP Calculation based on R2R ...
|
||
|
||
//
|
||
// sl = 0;
|
||
type = POSITION_TYPE_SELL;
|
||
}
|
||
|
||
//
|
||
// Combine Signals ...
|
||
|
||
//
|
||
hasLong =
|
||
//
|
||
hasLong1 ||
|
||
//
|
||
// TODO: Attach other Conditions ...
|
||
false
|
||
//
|
||
;
|
||
|
||
//
|
||
hasShort =
|
||
//
|
||
hasShort1 ||
|
||
//
|
||
// TODO: Attach other Conditions ...
|
||
false
|
||
//
|
||
;
|
||
|
||
//
|
||
result = hasLong || hasShort;
|
||
if (!result)
|
||
{
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// Retrieve Entry Price based on Position Type ...
|
||
entry = GetEntry(mSymbol, type);
|
||
|
||
//
|
||
// Calculate TP and SL ...
|
||
// based on Strategy ...
|
||
// only when on of TP or SL Provides, using provided R2R ...
|
||
if ((tp <= 0 && sl > 0) || (tp > 0 && sl <= 0))
|
||
{
|
||
//
|
||
CalculateTPSLByPrice(
|
||
sl,
|
||
tp,
|
||
type,
|
||
entry,
|
||
r2r //
|
||
);
|
||
}
|
||
|
||
//
|
||
// Prepare Signal ...
|
||
result = signal.Prepare(
|
||
mSymbol,
|
||
signallers[0],
|
||
mPeriod,
|
||
type,
|
||
mode,
|
||
entry,
|
||
volume,
|
||
sl,
|
||
tp //
|
||
);
|
||
if (!result)
|
||
{
|
||
return result;
|
||
}
|
||
|
||
//
|
||
signal.pushers = pushers;
|
||
|
||
//
|
||
// Prepare and Normalize Signal for Execution in Strategy ...
|
||
result = PrepareSignal(signal);
|
||
if (!result)
|
||
{
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// Attach Strategy Lebel ...
|
||
signal.provider = X121SMCStrategyToken;
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// Overrides ...
|
||
|
||
//
|
||
// Customize Strategy Identifier ...
|
||
string GetTag() override
|
||
{
|
||
return X121SMCStrategyToken;
|
||
}
|
||
|
||
//
|
||
// Protected ...
|
||
protected:
|
||
//
|
||
|
||
//
|
||
// Props ...
|
||
|
||
//
|
||
// 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 ...
|
||
|
||
//
|
||
MqlTick mLastTick; // Last Issued Tick ...
|
||
XBarTracker mBarTracker; // Strategy Time Tracker ...
|
||
|
||
//
|
||
// Point Of Interests ...
|
||
XCPOI *m4HPOI;
|
||
XCPOI *m15MPOI;
|
||
XCPOI *m5MPOI;
|
||
|
||
//
|
||
// Collect all Drawn Objects ...
|
||
CArrayObj mDrawnObjects;
|
||
|
||
//
|
||
// Actions ...
|
||
|
||
/**
|
||
* Install all Helpers and Prepare all Configurations for required Indicators ...
|
||
*/
|
||
void Init()
|
||
{
|
||
//
|
||
mForceDisabled = false;
|
||
|
||
//
|
||
string symbol = Symbol();
|
||
ENUM_TIMEFRAMES period = Period();
|
||
|
||
//
|
||
// Initialize Bar Tracker ...
|
||
mBarTracker.Init(
|
||
symbol,
|
||
period //
|
||
);
|
||
|
||
//
|
||
// Initialize POIs ...
|
||
|
||
//
|
||
// 4H Period ...
|
||
m4HPOI = new XCPOI(
|
||
symbol,
|
||
PERIOD_H4 //
|
||
);
|
||
|
||
//
|
||
m4HPOI.Window(0);
|
||
m4HPOI.DisableDrawPOIs();
|
||
m4HPOI.ChartID(ChartID());
|
||
m4HPOI.MaxNumberOfRequiredPOIs(0);
|
||
m4HPOI.SupplyZonePeriod(PERIOD_H4);
|
||
m4HPOI.DemandZonePeriod(PERIOD_H4);
|
||
|
||
//
|
||
m4HPOI.Init();
|
||
|
||
//
|
||
// 15M Period ...
|
||
m15MPOI = new XCPOI(
|
||
symbol,
|
||
PERIOD_M15 //
|
||
);
|
||
|
||
//
|
||
m15MPOI.Window(0);
|
||
m15MPOI.DisableDrawPOIs();
|
||
m15MPOI.ChartID(ChartID());
|
||
m15MPOI.MaxNumberOfRequiredPOIs(2);
|
||
m15MPOI.SupplyZonePeriod(PERIOD_M15);
|
||
m15MPOI.DemandZonePeriod(PERIOD_M15);
|
||
|
||
//
|
||
m15MPOI.Init();
|
||
|
||
//
|
||
// Trigger Period ...
|
||
m5MPOI = new XCPOI(
|
||
symbol,
|
||
period //
|
||
);
|
||
|
||
//
|
||
m5MPOI.Window(0);
|
||
m5MPOI.DisableDrawPOIs();
|
||
m5MPOI.ChartID(ChartID());
|
||
m5MPOI.MaxNumberOfRequiredPOIs(2);
|
||
m5MPOI.SupplyZonePeriod(PERIOD_M5);
|
||
m5MPOI.DemandZonePeriod(PERIOD_M5);
|
||
|
||
//
|
||
m5MPOI.Init();
|
||
|
||
//
|
||
}
|
||
|
||
/**
|
||
* De Initialize all Tools ...
|
||
*/
|
||
void DeInit()
|
||
{
|
||
//
|
||
delete m4HPOI;
|
||
delete m5MPOI;
|
||
delete m15MPOI;
|
||
}
|
||
|
||
/**
|
||
* Reste Bar Tracker ...
|
||
*/
|
||
void ResetBarTracker()
|
||
{
|
||
mBarTracker.Clean();
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/**
|
||
* Detect Supply and Demand Zones ...
|
||
*
|
||
* @param state: Argument 1
|
||
* @param supplyZone: Argument 2
|
||
* @param demandZone: Argument 3
|
||
*/
|
||
void DetectSupplyAndDemandZones(
|
||
XPOIState &state,
|
||
XZone &supplyZone,
|
||
XZone &demandZone //
|
||
)
|
||
{
|
||
//
|
||
supplyZone.Clean();
|
||
demandZone.Clean();
|
||
|
||
//
|
||
int supplyZonesCount = ArraySize(state.supplyZones);
|
||
int demandZonesCount = ArraySize(state.demandZones);
|
||
if (!IsValidSize(supplyZonesCount) &&
|
||
!IsValidSize(demandZonesCount))
|
||
{
|
||
return;
|
||
}
|
||
|
||
//
|
||
XOHCL zBar;
|
||
bool isInited = zBar.Init(
|
||
Symbol(),
|
||
Period(),
|
||
0 //
|
||
);
|
||
if (!isInited)
|
||
{
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Detect Supply Zone ...
|
||
for (int i = 0; i < supplyZonesCount; i++)
|
||
{
|
||
//
|
||
XZone iZone = state.supplyZones[i];
|
||
|
||
//
|
||
// Retrieve Zone From Index Based On Current Period ...
|
||
int iZoneStartBarIndex = iBarShift(
|
||
Symbol(),
|
||
Period(),
|
||
iZone.from //
|
||
);
|
||
|
||
//
|
||
// Check Zone is Fresh Or Not ...
|
||
bool isFreshZone = true;
|
||
for (int j = iZoneStartBarIndex - 1; j >= 0; j++)
|
||
{
|
||
//
|
||
XOHCL jBar;
|
||
bool isInited = jBar.Init(
|
||
Symbol(),
|
||
Period(),
|
||
j //
|
||
);
|
||
if (!isInited)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
//
|
||
if (jBar.high > iZone.lower)
|
||
{
|
||
//
|
||
isFreshZone = false;
|
||
break;
|
||
}
|
||
|
||
//
|
||
}
|
||
|
||
//
|
||
if (!isFreshZone)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
//
|
||
supplyZone = iZone;
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
// On X121 Signal Recieved Event Handler(s) ...
|
||
TOnX121SMCSignal mSignalEventHandlers[];
|
||
|
||
//
|
||
/**
|
||
* 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 //
|
||
);
|
||
}
|
||
}
|
||
|
||
//
|
||
};
|
||
|
||
// |