1667 lines
36 KiB
Plaintext
1667 lines
36 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Class Library
|
|
// --------------------------------------
|
|
// Name: XSCX121SMCBaseStrategy
|
|
// 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-alert.class.mq5"
|
|
#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5"
|
|
#include "../../Classes/x-saherelm.x-poi.class.mq5"
|
|
#include "../../Classes/x-saherelm.x-trade.class.mq5"
|
|
#include "../Classes/x-121.smc.cobjects.class.mq5"
|
|
#include "../Libraries/x-121.smc.lib.mq5"
|
|
|
|
//
|
|
// Helper(s) ...
|
|
|
|
//
|
|
// XStrategy Class Implementation(s) ...
|
|
class XCX121SMCBaseStrategy : public XCBaseAlert
|
|
{
|
|
//
|
|
// Public ...
|
|
public:
|
|
//
|
|
|
|
//
|
|
// Constructor(s) ...
|
|
void XCX121SMCBaseStrategy(
|
|
//
|
|
// Base ...
|
|
string _symbol, // Trading Symbol
|
|
ENUM_TIMEFRAMES _period // Trading TimeFrame
|
|
)
|
|
{
|
|
//
|
|
mSymbol = _symbol;
|
|
mPeriod = _period;
|
|
|
|
//
|
|
Init();
|
|
}
|
|
|
|
//
|
|
// Deconstructor ...
|
|
void ~XCX121SMCBaseStrategy()
|
|
{
|
|
DeInit();
|
|
}
|
|
|
|
//
|
|
// Getter / Setter (s) ...
|
|
|
|
/**
|
|
* Retrieve Symbol ...
|
|
*
|
|
* @return ( string )
|
|
*/
|
|
string GetSymbol()
|
|
{
|
|
return mSymbol;
|
|
}
|
|
|
|
/**
|
|
* Retrieve TimeFrame ...
|
|
*
|
|
* @return ( ENUM_TIMEFRAMES )
|
|
*/
|
|
ENUM_TIMEFRAMES GetPeriod()
|
|
{
|
|
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 ...
|
|
|
|
/**
|
|
* Destroy All Class Implementations ...
|
|
*/
|
|
virtual void Destroy()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Handle Tick Processing ...
|
|
*/
|
|
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 ...
|
|
|
|
//
|
|
// Trigger ...
|
|
ENUM_XPOI_EVENTS triggerPOIEvents[];
|
|
mTriggerPOIDetector.Update(triggerPOIEvents);
|
|
mTriggerPOIDetector.GetState(mTriggerPOIState);
|
|
|
|
//
|
|
// Analyse ...
|
|
ENUM_XPOI_EVENTS analysePOIEvents[];
|
|
mAnalysePOIDetector.Update(analysePOIEvents);
|
|
mAnalysePOIDetector.GetState(mAnalysePOIState);
|
|
|
|
//
|
|
// Trigger ...
|
|
ENUM_XPOI_EVENTS visionPOIEvents[];
|
|
mVisionPOIDetector.Update(visionPOIEvents);
|
|
mVisionPOIDetector.GetState(mVisionPOIState);
|
|
|
|
//
|
|
// 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);
|
|
}
|
|
|
|
/**
|
|
* Check For Signal ...
|
|
*
|
|
* @param signal: XSignal instance ...
|
|
* @param conditions: X121SMCStrategyConditions instance ...
|
|
*
|
|
* @return ( virtual bool )
|
|
*/
|
|
virtual bool HasSignal(
|
|
XSignal &signal,
|
|
X121SMCStrategyConditions &conditions //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
signal.Clean();
|
|
conditions.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect SL Candidates based on Strategy and Conditions ...
|
|
*
|
|
* @param result: Double array reference ...
|
|
* @param entry: Double, Position Entry Price ...
|
|
* @param conditions: X121SMCStrategyConditions instance, Provides Configurations ...
|
|
* @param type: ENUM_X_POSITION_TYPES member, Specified Position Type ...
|
|
*/
|
|
virtual void DetectSLCandidates(
|
|
double &result[],
|
|
double entry,
|
|
X121SMCStrategyConditions &conditions,
|
|
ENUM_X_POSITION_TYPES type //
|
|
)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Customize Strategy Identifier ...
|
|
*
|
|
* @return ( virtual string )
|
|
*/
|
|
virtual string GetTag()
|
|
{
|
|
return X121SMCStrategyToken;
|
|
}
|
|
|
|
//
|
|
// Protected ...
|
|
protected:
|
|
//
|
|
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
// Point Of Interests ...
|
|
XCPOIDetector *mTriggerPOIDetector;
|
|
XCPOIDetector *mAnalysePOIDetector;
|
|
XCPOIDetector *mVisionPOIDetector;
|
|
|
|
//
|
|
XPOIState mTriggerPOIState;
|
|
XPOIState mAnalysePOIState;
|
|
XPOIState mVisionPOIState;
|
|
|
|
//
|
|
XCPOIDrawer *mPOIDrawer; // POI Drawer Class ...
|
|
CArrayObj mDrawnObjects;
|
|
|
|
//
|
|
XTick mTicks[]; // Hold Ticks Data ...
|
|
MqlTick mLastTick; // Last Issued Tick ...
|
|
|
|
//
|
|
XBarTracker mBarTracker; // Strategy Time Tracker ...
|
|
XCBarAnalyser mBarAnalyser; // Bar Analyser Instance
|
|
// X121SMCStrategyConditions mConditions; // Market Conditions ...
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
|
|
/**
|
|
* 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 Specified Signal ...
|
|
*
|
|
* @param signal: XSignal instance ...
|
|
*/
|
|
void DrawSignal(XSignal &signal)
|
|
{
|
|
//
|
|
if (!signal.IsValid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// DrawConditions(conditions);
|
|
|
|
//
|
|
string name = signal.GetTag();
|
|
RemoveObject(name);
|
|
|
|
//
|
|
XCSignalObject *iObj;
|
|
iObj = new XCSignalObject();
|
|
|
|
//
|
|
bool isCreated = iObj.Create(
|
|
ChartIdentification(),
|
|
name,
|
|
SubWindowIdentification(),
|
|
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);
|
|
}
|
|
|
|
/**
|
|
* Draw Specified State on Chart ...
|
|
*
|
|
* @param state: XPOIState instance ...
|
|
*/
|
|
void DrawState(
|
|
XPOIState &state,
|
|
bool forceUpdateTo = false,
|
|
bool drawSwingHighs = true,
|
|
bool drawSwingLows = true,
|
|
bool drawSupportZones = true,
|
|
bool drawResistanceZones = true,
|
|
bool drawSupplyZones = true,
|
|
bool drawDemandZones = true,
|
|
bool drawBullishOrderBlocks = true,
|
|
bool drawBearishOrderBlocks = true,
|
|
bool drawBullishFairValueGaps = true,
|
|
bool drawBearishFairValueGaps = true,
|
|
bool drawBullishRejectionBars = true,
|
|
bool drawBearishRejectionBars = true,
|
|
bool drawBullishMomentumBars = true,
|
|
bool drawBearishMomentumBars = true,
|
|
bool drawTicksZone = true //
|
|
)
|
|
{
|
|
//
|
|
int count = 0;
|
|
datetime cTime = TimeCurrent();
|
|
|
|
//
|
|
// Swings ...
|
|
|
|
//
|
|
// Swing Highs ...
|
|
if (drawSwingHighs)
|
|
{
|
|
//
|
|
count = ArraySize(state.swingHighs);
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCSwing item = state.swingHighs[i];
|
|
|
|
//
|
|
XCSwingHighObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateSwingHigh(
|
|
item,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
AddObjectIfNotExists(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Swing Lows ...
|
|
if (drawSwingLows)
|
|
{
|
|
//
|
|
count = ArraySize(state.swingLows);
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCSwing item = state.swingLows[i];
|
|
|
|
//
|
|
XCSwingLowObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateSwingLow(
|
|
item,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
AddObjectIfNotExists(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Support and Resistance Zones ...
|
|
|
|
//
|
|
// Support Zones ...
|
|
if (drawSupportZones)
|
|
{
|
|
//
|
|
count = ArraySize(state.supportZones);
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCSupportZone item = state.supportZones[i];
|
|
if (forceUpdateTo)
|
|
{
|
|
item.To(cTime);
|
|
}
|
|
|
|
//
|
|
XCSupportZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateSupportZone(
|
|
item,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
AddObjectIfNotExists(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Resistance Zones ...
|
|
if (drawResistanceZones)
|
|
{
|
|
//
|
|
count = ArraySize(state.resistanceZones);
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCResistanceZone item = state.resistanceZones[i];
|
|
if (forceUpdateTo)
|
|
{
|
|
item.To(cTime);
|
|
}
|
|
|
|
//
|
|
XCResistanceZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateResistanceZone(
|
|
item,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
AddObjectIfNotExists(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Supply and Demand Zones ...
|
|
|
|
//
|
|
// Supply Zones ...
|
|
if (drawSupplyZones)
|
|
{
|
|
//
|
|
count = ArraySize(state.supplyZones);
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCSupplyZone item = state.supplyZones[i];
|
|
if (forceUpdateTo)
|
|
{
|
|
item.To(cTime);
|
|
}
|
|
|
|
//
|
|
XCSupplyZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateSupplyZone(
|
|
item,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
AddObjectIfNotExists(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Demand Zones ...
|
|
if (drawDemandZones)
|
|
{
|
|
//
|
|
count = ArraySize(state.demandZones);
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCDemandZone item = state.demandZones[i];
|
|
if (forceUpdateTo)
|
|
{
|
|
item.To(cTime);
|
|
}
|
|
|
|
//
|
|
XCDemandZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateDemandZone(
|
|
item,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
AddObjectIfNotExists(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Order Blocks ...
|
|
|
|
//
|
|
// Bullish Order Blocks ...
|
|
if (drawBullishOrderBlocks)
|
|
{
|
|
//
|
|
count = ArraySize(state.bullishOrderBlocks);
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCOrderBlock item = state.bullishOrderBlocks[i];
|
|
if (forceUpdateTo)
|
|
{
|
|
item.To(cTime);
|
|
}
|
|
|
|
//
|
|
XCBullishOrderBlockObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBullishOrderBlock(
|
|
item,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
AddObjectIfNotExists(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish Order Blocks ...
|
|
if (drawBearishOrderBlocks)
|
|
{
|
|
//
|
|
count = ArraySize(state.bearishOrderBlocks);
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCOrderBlock item = state.bearishOrderBlocks[i];
|
|
if (forceUpdateTo)
|
|
{
|
|
item.To(cTime);
|
|
}
|
|
|
|
//
|
|
XCBearishOrderBlockObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBearishOrderBlock(
|
|
item,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
AddObjectIfNotExists(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fair Value Gaps ...
|
|
|
|
//
|
|
// Bullish Fair Value Gaps ...
|
|
if (drawBullishFairValueGaps)
|
|
{
|
|
//
|
|
count = ArraySize(state.bullishFairValueGaps);
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCFVG item = state.bullishFairValueGaps[i];
|
|
if (forceUpdateTo)
|
|
{
|
|
item.To(cTime);
|
|
}
|
|
|
|
//
|
|
XCBullishFairValueGapObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBullishFairValueGap(
|
|
item,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
AddObjectIfNotExists(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish Fair Value Gaps ...
|
|
if (drawBearishFairValueGaps)
|
|
{
|
|
//
|
|
count = ArraySize(state.bearishFairValueGaps);
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCFVG item = state.bearishFairValueGaps[i];
|
|
if (forceUpdateTo)
|
|
{
|
|
item.To(cTime);
|
|
}
|
|
|
|
//
|
|
XCBearishFairValueGapObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBearishFairValueGap(
|
|
item,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
AddObjectIfNotExists(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Rejection Bars ...
|
|
|
|
//
|
|
// Bullish Rejection Bars ...
|
|
if (drawBullishRejectionBars)
|
|
{
|
|
//
|
|
count = ArraySize(state.bullishRejectionBars);
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCRejectionBar item = state.bullishRejectionBars[i];
|
|
|
|
//
|
|
XCBullishRejectionBarObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBullishRejectionBar(
|
|
item,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
AddObjectIfNotExists(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish Rejection Bars ...
|
|
if (drawBearishRejectionBars)
|
|
{
|
|
//
|
|
count = ArraySize(state.bearishRejectionBars);
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCRejectionBar item = state.bearishRejectionBars[i];
|
|
|
|
//
|
|
XCBearishRejectionBarObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBearishRejectionBar(
|
|
item,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
AddObjectIfNotExists(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Momentum Bars ...
|
|
|
|
//
|
|
// Bullish Momentum Bars ...
|
|
if (drawBullishMomentumBars)
|
|
{
|
|
//
|
|
count = ArraySize(state.bullishMomentumBars);
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCMomentumBar item = state.bullishMomentumBars[i];
|
|
|
|
//
|
|
XCBullishMomentumBarObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBullishMomentumBar(
|
|
item,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
AddObjectIfNotExists(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish Momentum Bars ...
|
|
if (drawBearishMomentumBars)
|
|
{
|
|
//
|
|
count = ArraySize(state.bearishMomentumBars);
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCMomentumBar item = state.bearishMomentumBars[i];
|
|
|
|
//
|
|
XCBearishMomentumBarObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBearishMomentumBar(
|
|
item,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
AddObjectIfNotExists(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Ticks Zone ...
|
|
if (drawTicksZone &&
|
|
state.ticksZone != NULL)
|
|
{
|
|
//
|
|
XCTicksZone *iZone = state.ticksZone;
|
|
|
|
//
|
|
if (forceUpdateTo)
|
|
{
|
|
iZone.To(cTime);
|
|
}
|
|
|
|
//
|
|
XCTicksZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateTicksZone(
|
|
iZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
AddObjectIfNotExists(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add Specified Object to Drawn Objects if not Exists ...
|
|
*/
|
|
void AddObjectIfNotExists(XCBaseObject *object)
|
|
{
|
|
//
|
|
string name = object.ObjName();
|
|
|
|
//
|
|
bool canAdd = true;
|
|
int count = mDrawnObjects.Total();
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
string iName = ((XCBaseObject *)mDrawnObjects.At(i)).ObjName();
|
|
|
|
//
|
|
if (name == iName)
|
|
{
|
|
//
|
|
canAdd = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
if (canAdd)
|
|
{
|
|
mDrawnObjects.Add(object);
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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 ...
|
|
|
|
//
|
|
// 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);
|
|
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 ...
|
|
|
|
//
|
|
int poiRequired = 10;
|
|
|
|
//
|
|
// Trigger ...
|
|
mTriggerPOIDetector = new XCPOIDetector(
|
|
symbol,
|
|
period //
|
|
);
|
|
mTriggerPOIDetector.MaxNumberOfRequiredPOIs(poiRequired);
|
|
mTriggerPOIDetector.Init();
|
|
|
|
//
|
|
// Analyse ...
|
|
ENUM_TIMEFRAMES analysePeriod = GetAnalysePeriod(period);
|
|
mAnalysePOIDetector = new XCPOIDetector(
|
|
symbol,
|
|
analysePeriod //
|
|
);
|
|
mAnalysePOIDetector.MaxNumberOfRequiredPOIs(poiRequired);
|
|
mAnalysePOIDetector.Init();
|
|
|
|
//
|
|
// Vision ...
|
|
ENUM_TIMEFRAMES visionPeriod = GetVisionPeriod(period);
|
|
mVisionPOIDetector = new XCPOIDetector(
|
|
symbol,
|
|
visionPeriod //
|
|
);
|
|
mVisionPOIDetector.MaxNumberOfRequiredPOIs(poiRequired);
|
|
mVisionPOIDetector.Init();
|
|
|
|
//
|
|
}
|
|
|
|
/**
|
|
* De Initialize all Tools ...
|
|
*/
|
|
void DeInit()
|
|
{
|
|
//
|
|
delete mTriggerPOIDetector;
|
|
delete mAnalysePOIDetector;
|
|
delete mVisionPOIDetector;
|
|
|
|
//
|
|
delete mPOIDrawer;
|
|
|
|
//
|
|
Destroy();
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
// |