1802 lines
38 KiB
Plaintext
1802 lines
38 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.xalert.class.mq5"
|
||
#include "../../Classes/x-saherelm.xtrade.class.mq5"
|
||
|
||
//
|
||
// Helper(s) ...
|
||
|
||
//
|
||
// Definitions ...
|
||
|
||
//
|
||
// Specific Identifier(s) of XStrategy ...
|
||
string X121SMCStrategyToken = "X121SMC";
|
||
|
||
//
|
||
// Condition Structure ...
|
||
struct XStrategyConditions
|
||
{
|
||
//
|
||
// Props ...
|
||
|
||
//
|
||
// Common ...
|
||
string symbol;
|
||
ENUM_TIMEFRAMES period;
|
||
datetime time;
|
||
|
||
//
|
||
// Important Ares attached ...
|
||
|
||
//
|
||
XOHCL support;
|
||
XOHCL resistance;
|
||
XOHCL bullishOB;
|
||
XOHCL bearishOB;
|
||
|
||
//
|
||
double bullishFVGUpper;
|
||
double bullishFVGLower;
|
||
XOHCL bullishFVG;
|
||
|
||
//
|
||
double bearishFVGUpper;
|
||
double bearishFVGLower;
|
||
XOHCL bearishFVG;
|
||
|
||
//
|
||
XOHCL bullishTrendSwingHighs[];
|
||
XOHCL bullishTrendSwingLows[];
|
||
XOHCL bullishTrend;
|
||
|
||
//
|
||
XOHCL bearishTrendSwingHighs[];
|
||
XOHCL bearishTrendSwingLows[];
|
||
XOHCL bearishTrend;
|
||
|
||
//
|
||
// Helper Conditions ...
|
||
|
||
//
|
||
// Constructor ...
|
||
void XStrategyConditions()
|
||
{
|
||
Clean();
|
||
}
|
||
|
||
//
|
||
// Tools ...
|
||
|
||
//
|
||
// Cleanup ...
|
||
void Clean()
|
||
{
|
||
//
|
||
symbol = NULL;
|
||
period = NULL;
|
||
time = NULL;
|
||
|
||
//
|
||
// Clean Helpers Conditions ...
|
||
}
|
||
|
||
//
|
||
// Validate ...
|
||
bool IsValid()
|
||
{
|
||
//
|
||
bool result = false;
|
||
|
||
//
|
||
result =
|
||
//
|
||
IsValid(time) &&
|
||
IsValid(symbol) &&
|
||
IsValid(period)
|
||
//
|
||
;
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// Generate Provided Scores ...
|
||
void GenerateScore(
|
||
double &bullishScore,
|
||
double &bearishScore //
|
||
)
|
||
{
|
||
//
|
||
bullishScore = 0;
|
||
bearishScore = 0;
|
||
|
||
//
|
||
if (!IsValid())
|
||
{
|
||
return;
|
||
}
|
||
|
||
//
|
||
double bullScore = 0;
|
||
double bearScore = 0;
|
||
|
||
//
|
||
// Generate Helpers Conitions Scores ...
|
||
}
|
||
|
||
//
|
||
// Generate Summary ...
|
||
string GenerateSummary(
|
||
bool onlyCommons = false,
|
||
bool onlyConditions = false,
|
||
bool includeScores = true,
|
||
bool ignoreFalseConditions = true,
|
||
string separator = "\n" //
|
||
)
|
||
{
|
||
//
|
||
string result = NULL;
|
||
|
||
//
|
||
double bullishScore = 0;
|
||
double bearishScore = 0;
|
||
GenerateScore(
|
||
bullishScore,
|
||
bearishScore //
|
||
);
|
||
|
||
//
|
||
string commonStr = GenerateSpecifiedCommonSummary(
|
||
this,
|
||
separator,
|
||
includeScores,
|
||
true //
|
||
);
|
||
|
||
//
|
||
// Generate Helpers Conditions Strings ...
|
||
|
||
//
|
||
// Combine Helpers Conditions Strings ...
|
||
string conditionsStr =
|
||
//
|
||
"" + separator +
|
||
""
|
||
//
|
||
;
|
||
|
||
//
|
||
result =
|
||
//
|
||
"[" + GetTag() + "]" + separator +
|
||
"----------" + separator +
|
||
(onlyConditions
|
||
? ""
|
||
: commonStr) +
|
||
" " + separator +
|
||
(onlyCommons
|
||
? ""
|
||
: conditionsStr) +
|
||
""
|
||
//
|
||
;
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
//
|
||
string GetTag()
|
||
{
|
||
return X121SMCStrategyToken;
|
||
}
|
||
|
||
//
|
||
};
|
||
|
||
//
|
||
// On Signal Event Handler ...
|
||
typedef void (*TOnXSignal)(
|
||
XSignal &signal,
|
||
XStrategyConditions &conditions //
|
||
);
|
||
|
||
//
|
||
// XStrategy Class Implementation(s) ...
|
||
class XCX121SMCStrategy : public XSCBaseAlert
|
||
{
|
||
//
|
||
// Public ...
|
||
public:
|
||
//
|
||
// Constructor(s) ...
|
||
void XCX121SMCStrategy(
|
||
//
|
||
// Base ...
|
||
string _symbol, // Trading Symbol
|
||
ENUM_TIMEFRAMES _period // Trading TimeFrame
|
||
)
|
||
{
|
||
//
|
||
SetAlertPrefix(GetTag());
|
||
|
||
//
|
||
PrepareRequirements();
|
||
}
|
||
|
||
//
|
||
// Deconstructor ...
|
||
void ~XCX121SMCStrategy()
|
||
{
|
||
}
|
||
|
||
//
|
||
// 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(TOnXSignal 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;
|
||
XStrategyConditions 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,
|
||
XStrategyConditions &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;
|
||
|
||
//
|
||
// Retrieve Helper Conditions ...
|
||
|
||
//
|
||
// Start Calculations ...
|
||
|
||
//
|
||
double points = GetPoints(mSymbol);
|
||
|
||
//
|
||
int zIndex = 0;
|
||
int cIndex = zIndex + 1;
|
||
int pIndex = cIndex + 1;
|
||
int ppIndex = pIndex + 1;
|
||
|
||
//
|
||
// Retrieve Bars ...
|
||
|
||
//
|
||
// 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;
|
||
|
||
//
|
||
// Attach Helpers Conditins ...
|
||
|
||
//
|
||
result = conditions.IsValid();
|
||
if (!result)
|
||
{
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// Previous Bar of Last Bar ...
|
||
XOHCL pBar;
|
||
result = cBar.GetPreviousBar(pBar);
|
||
if (!result)
|
||
{
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// Last Swing Low Bar ...
|
||
XOHCL lastSwingLow;
|
||
result = cBar.FindLastSwingLow(lastSwingLow);
|
||
if (!result)
|
||
{
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// Last Swing High Bar ...
|
||
XOHCL lastSwingHigh;
|
||
result = cBar.FindLastSwingHigh(lastSwingHigh);
|
||
if (!result)
|
||
{
|
||
return result;
|
||
}
|
||
|
||
//
|
||
int pushers = 0;
|
||
string signallers[];
|
||
|
||
//
|
||
// Retrieve all Helpers Based Configurations Here ...
|
||
|
||
//
|
||
// Common Conditions For Bullish and Bearish Powers ...
|
||
|
||
//
|
||
// For Trend ...
|
||
XOHCL tmpHSW[];
|
||
XOHCL tmpLSW[];
|
||
|
||
//
|
||
// Detect Bullish/Bearish Patterns and Trends ...
|
||
|
||
//
|
||
// Bullish ...
|
||
bool hasBullishPower = cBar.HasBullishPower();
|
||
bool hasBullishPattern = HasBullishPattern(cBar);
|
||
bool hasBullishPressure = cBar.HasBullishPressure();
|
||
bool isBullishTrend = cBar.HasBullishTrend(
|
||
tmpHSW,
|
||
tmpLSW,
|
||
true //
|
||
);
|
||
bool isBullishTrend1 = cBar.HasBullishTrend(
|
||
tmpHSW,
|
||
tmpLSW,
|
||
false //
|
||
);
|
||
bool hasBullishTrend =
|
||
//
|
||
isBullishTrend
|
||
//
|
||
||
|
||
//
|
||
isBullishTrend1
|
||
//
|
||
;
|
||
|
||
//
|
||
// Bearish ...
|
||
bool hasBearishPower = cBar.HasBearishPower();
|
||
bool hasBearishPattern = HasBearishPattern(cBar);
|
||
bool hasBearishPressure = cBar.HasBearishPressure();
|
||
bool isBearishTrend = cBar.HasBearishTrend(
|
||
tmpHSW,
|
||
tmpLSW,
|
||
true //
|
||
);
|
||
bool isBearishTrend1 = cBar.HasBearishTrend(
|
||
tmpHSW,
|
||
tmpLSW,
|
||
false //
|
||
);
|
||
bool hasBearishTrend =
|
||
//
|
||
isBearishTrend
|
||
//
|
||
||
|
||
//
|
||
isBearishTrend1
|
||
//
|
||
;
|
||
|
||
//
|
||
bool hasBearishDecision =
|
||
//
|
||
cBar.IsBearishDecision()
|
||
//
|
||
;
|
||
|
||
//
|
||
bool hasBullishDecision =
|
||
//
|
||
cBar.IsBullishDecision()
|
||
//
|
||
;
|
||
|
||
//
|
||
// 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)
|
||
//
|
||
;
|
||
}
|
||
|
||
//
|
||
// TODO: Complete this ...
|
||
bool notHaveBearishPower = false;
|
||
|
||
//
|
||
// TODO: Complete this ...
|
||
bool notHaveBullishPower = false;
|
||
|
||
//
|
||
// Detecting Signals ...
|
||
|
||
//
|
||
bool hasBaseLongConditions =
|
||
cBar.IsBullish() &&
|
||
hasBullishTrend &&
|
||
(hasBullishPower ||
|
||
hasBullishPattern ||
|
||
hasBullishPressure) &&
|
||
notHaveBearishPower &&
|
||
isTicksBullishForLong;
|
||
|
||
//
|
||
bool hasBaseShortConditions =
|
||
cBar.IsBearish() &&
|
||
hasBearishTrend &&
|
||
(hasBearishPower ||
|
||
hasBearishPattern ||
|
||
hasBearishPressure) &&
|
||
notHaveBullishPower &&
|
||
isTicksBullishForShort;
|
||
|
||
//
|
||
// LONGS ...
|
||
|
||
//
|
||
bool hasLong1 =
|
||
//
|
||
hasBaseLongConditions &&
|
||
//
|
||
// TODO: Implement Long Conditions ...
|
||
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 =
|
||
//
|
||
hasBaseShortConditions &&
|
||
//
|
||
// 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)
|
||
{
|
||
//
|
||
CheckImportantAreasValidation();
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
//
|
||
DestroyImportantAreas();
|
||
|
||
//
|
||
// 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 ...
|
||
|
||
//
|
||
// Helpers Inputs and Classes Instance ...
|
||
|
||
//
|
||
// 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 ...
|
||
|
||
//
|
||
// Actions ...
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
//
|
||
// On X121 Signal Recieved Event Handler(s) ...
|
||
TOnXSignal mSignalEventHandlers[];
|
||
|
||
//
|
||
/**
|
||
* Notified Signal Event Handler(s) ...
|
||
*
|
||
* @param signal: XSignal instance ...
|
||
* @param conditions: XStrategyConditions instance ...
|
||
*/
|
||
void NotifyOnSignalEventHandlers(
|
||
XSignal &signal,
|
||
XStrategyConditions &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 //
|
||
);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Install all Helpers and Prepare all Configurations for required Indicators ...
|
||
*/
|
||
void PrepareRequirements()
|
||
{
|
||
//
|
||
mForceDisabled = false;
|
||
|
||
//
|
||
support.Clean();
|
||
supportTime = NULL;
|
||
isSupportTested = false;
|
||
|
||
//
|
||
resistance.Clean();
|
||
resistanceTime = NULL;
|
||
isResistanceTested = false;
|
||
|
||
//
|
||
// Initialize Bar Tracker ...
|
||
//
|
||
// Initial Time Tracker ...
|
||
mBarTracker.Init(
|
||
mSymbol,
|
||
mPeriod //
|
||
);
|
||
|
||
//
|
||
SetAlertPrefix(GetTag());
|
||
|
||
//
|
||
// Prepare Default Inputs and Configure Indicator Helpers here ...
|
||
|
||
//
|
||
}
|
||
|
||
//
|
||
void FillConditionsImportantAreas(XStrategyConditions &conditions)
|
||
{
|
||
//
|
||
if (!conditions.IsValid())
|
||
{
|
||
return;
|
||
}
|
||
|
||
//
|
||
conditions.support = support;
|
||
conditions.resistance = resistance;
|
||
conditions.bullishOB = bullishOB;
|
||
conditions.bearishOB = bearishOB;
|
||
conditions.bullishFVG = bullishFVG;
|
||
conditions.bearishFVG = bearishFVG;
|
||
conditions.bullishTrend = bullishTrend;
|
||
conditions.bearishTrend = bearishTrend;
|
||
|
||
//
|
||
conditions.bullishFVGUpper = bullishFVGUpper;
|
||
conditions.bullishFVGLower = bullishFVGLower;
|
||
conditions.bearishFVGUpper = bearishFVGUpper;
|
||
conditions.bearishFVGLower = bearishFVGLower;
|
||
|
||
//
|
||
Copy(
|
||
bullishTrendSwingHighs,
|
||
conditions.bullishTrendSwingHighs,
|
||
true //
|
||
);
|
||
|
||
//
|
||
Copy(
|
||
bullishTrendSwingLows,
|
||
conditions.bullishTrendSwingLows,
|
||
true //
|
||
);
|
||
|
||
//
|
||
Copy(
|
||
bearishTrendSwingHighs,
|
||
conditions.bearishTrendSwingHighs,
|
||
true //
|
||
);
|
||
|
||
//
|
||
Copy(
|
||
bearishTrendSwingLows,
|
||
conditions.bearishTrendSwingLows,
|
||
true //
|
||
);
|
||
}
|
||
|
||
//
|
||
// Important Areas ...
|
||
|
||
//
|
||
bool mDrawImportantAreas; // Draw Important ...
|
||
|
||
//
|
||
XOHCL support;
|
||
XOHCL resistance;
|
||
XOHCL bullishOB;
|
||
XOHCL bearishOB;
|
||
|
||
//
|
||
double bullishFVGUpper;
|
||
double bullishFVGLower;
|
||
XOHCL bullishFVG;
|
||
|
||
//
|
||
double bearishFVGUpper;
|
||
double bearishFVGLower;
|
||
XOHCL bearishFVG;
|
||
|
||
//
|
||
XOHCL bullishTrendSwingHighs[];
|
||
XOHCL bullishTrendSwingLows[];
|
||
XOHCL bullishTrend;
|
||
|
||
//
|
||
XOHCL bearishTrendSwingHighs[];
|
||
XOHCL bearishTrendSwingLows[];
|
||
XOHCL bearishTrend;
|
||
|
||
//
|
||
void DetectImportantAreas()
|
||
{
|
||
// //
|
||
// int zIndex = 0;
|
||
// int cIndex = zIndex + 1;
|
||
|
||
// //
|
||
// // Last Bar ...
|
||
// XOHCL cBar;
|
||
// bool result = cBar.Init(
|
||
// mSymbol,
|
||
// mPeriod,
|
||
// cIndex //
|
||
// );
|
||
// if (!result)
|
||
// {
|
||
// return;
|
||
// }
|
||
|
||
// //
|
||
// // Analyzing Bar ...
|
||
// XOHCL aBar;
|
||
// if (IsValid(mAnalizePeriod))
|
||
// {
|
||
// //
|
||
// result = aBar.Init(
|
||
// mSymbol,
|
||
// mAnalizePeriod,
|
||
// cIndex //
|
||
// );
|
||
|
||
// //
|
||
// if (!result)
|
||
// {
|
||
// return;
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// aBar = cBar;
|
||
// }
|
||
|
||
// //
|
||
// // Support nad Resistance ...
|
||
|
||
// //
|
||
// // Check Support Exists or Find ...
|
||
// bool hasSupport = support.IsValid();
|
||
// if (!hasSupport)
|
||
// {
|
||
// //
|
||
// hasSupport =
|
||
// //
|
||
// aBar.HasSupport(support)
|
||
// //
|
||
// ;
|
||
|
||
// //
|
||
// if (hasSupport)
|
||
// {
|
||
// //
|
||
// if (mDrawImportantAreas)
|
||
// {
|
||
// //
|
||
// DrawSupport(
|
||
// support,
|
||
// ChartID() //
|
||
// );
|
||
// }
|
||
|
||
// //
|
||
// supportTime = aBar.time;
|
||
// }
|
||
// }
|
||
|
||
// //
|
||
// // Check Resistance Exists or Find ...
|
||
// bool hasResistance = resistance.IsValid();
|
||
// if (!hasResistance)
|
||
// {
|
||
// //
|
||
// hasResistance =
|
||
// //
|
||
// aBar.HasResistance(resistance)
|
||
// //
|
||
// ;
|
||
|
||
// //
|
||
// if (hasResistance)
|
||
// {
|
||
// //
|
||
// if (mDrawImportantAreas)
|
||
// {
|
||
// //
|
||
// DrawResistance(
|
||
// resistance,
|
||
// ChartID() //
|
||
// );
|
||
// }
|
||
|
||
// //
|
||
// resistanceTime = aBar.time;
|
||
// }
|
||
// }
|
||
|
||
// //
|
||
// // Order Blocks ...
|
||
|
||
// //
|
||
// bool hasBullishOB = bullishOB.IsValid();
|
||
// if (!hasBullishOB)
|
||
// {
|
||
// //
|
||
// hasBullishOB =
|
||
// //
|
||
// aBar.HasBullishOrderBlock(bullishOB)
|
||
// //
|
||
// ;
|
||
|
||
// //
|
||
// if (hasBullishOB)
|
||
// {
|
||
// //
|
||
// if (mDrawImportantAreas)
|
||
// {
|
||
// //
|
||
// DrawBullishOrderBlock(
|
||
// bullishOB,
|
||
// ChartID() //
|
||
// );
|
||
// }
|
||
|
||
// //
|
||
// bullishOBTime = aBar.time;
|
||
// }
|
||
// }
|
||
|
||
// //
|
||
// bool hasBearishOB = bearishOB.IsValid();
|
||
// if (!hasBearishOB)
|
||
// {
|
||
// //
|
||
// hasBearishOB =
|
||
// //
|
||
// aBar.HasBearishOrderBlock(bearishOB)
|
||
// //
|
||
// ;
|
||
|
||
// //
|
||
// if (hasBearishOB)
|
||
// {
|
||
// //
|
||
// if (mDrawImportantAreas)
|
||
// {
|
||
// //
|
||
// DrawBearishOrderBlock(
|
||
// bearishOB,
|
||
// ChartID() //
|
||
// );
|
||
// }
|
||
|
||
// //
|
||
// bearishOBTime = aBar.time;
|
||
// }
|
||
// }
|
||
|
||
// //
|
||
// // FVG ...
|
||
|
||
// //
|
||
// bool hasBullishFVG = bullishFVG.IsValid();
|
||
// if (!hasBullishFVG)
|
||
// {
|
||
// //
|
||
// hasBullishFVG =
|
||
// //
|
||
// aBar.HasBullishFVG(
|
||
// bullishFVGUpper,
|
||
// bullishFVGLower //
|
||
// )
|
||
// //
|
||
// ;
|
||
|
||
// //
|
||
// if (hasBullishFVG)
|
||
// {
|
||
// //
|
||
// bullishFVG = aBar;
|
||
|
||
// //
|
||
// if (mDrawImportantAreas)
|
||
// {
|
||
// //
|
||
// DrawBullishFVG(
|
||
// bullishFVG,
|
||
// bullishFVGUpper,
|
||
// bullishFVGLower,
|
||
// ChartID() //
|
||
// );
|
||
// }
|
||
|
||
// //
|
||
// bullishFVGTime = aBar.time;
|
||
// }
|
||
// }
|
||
|
||
// //
|
||
// bool hasBearishFVG = bearishFVG.IsValid();
|
||
// if (!hasBearishFVG)
|
||
// {
|
||
// //
|
||
// hasBearishFVG =
|
||
// //
|
||
// aBar.HasBearishFVG(
|
||
// bearishFVGUpper,
|
||
// bearishFVGLower //
|
||
// )
|
||
// //
|
||
// ;
|
||
|
||
// //
|
||
// if (hasBearishFVG)
|
||
// {
|
||
// //
|
||
// bearishFVG = aBar;
|
||
|
||
// //
|
||
// if (mDrawImportantAreas)
|
||
// {
|
||
// //
|
||
// DrawBearishFVG(
|
||
// bearishFVG,
|
||
// bearishFVGUpper,
|
||
// bearishFVGLower,
|
||
// ChartID() //
|
||
// );
|
||
// }
|
||
|
||
// //
|
||
// bearishFVGTime = aBar.time;
|
||
// }
|
||
// }
|
||
|
||
// //
|
||
// // TREND ...
|
||
|
||
// //
|
||
// bool hasBullishTrend = bullishTrend.IsValid();
|
||
// if (!hasBullishTrend)
|
||
// {
|
||
// //
|
||
// hasBullishTrend = aBar.HasBullishTrend(
|
||
// bullishTrendSwingHighs,
|
||
// bullishTrendSwingLows,
|
||
// false //
|
||
// );
|
||
|
||
// //
|
||
// if (hasBullishTrend)
|
||
// {
|
||
// //
|
||
// bullishTrend = aBar;
|
||
|
||
// //
|
||
// if (mDrawImportantAreas)
|
||
// {
|
||
// //
|
||
// DrawBullishTrend(
|
||
// bullishTrend,
|
||
// bullishTrendSwingHighs,
|
||
// bullishTrendSwingLows,
|
||
// ChartID() //
|
||
// );
|
||
// }
|
||
// }
|
||
// }
|
||
|
||
// //
|
||
// bool hasBearishTrend = bearishTrend.IsValid();
|
||
// if (!hasBearishTrend)
|
||
// {
|
||
// //
|
||
// hasBearishTrend = aBar.HasBearishTrend(
|
||
// bearishTrendSwingHighs,
|
||
// bearishTrendSwingLows,
|
||
// false //
|
||
// );
|
||
|
||
// //
|
||
// if (hasBearishTrend)
|
||
// {
|
||
// //
|
||
// bearishTrend = aBar;
|
||
|
||
// //
|
||
// if (mDrawImportantAreas)
|
||
// {
|
||
// //
|
||
// DrawBearishTrend(
|
||
// bearishTrend,
|
||
// bearishTrendSwingHighs,
|
||
// bearishTrendSwingLows,
|
||
// ChartID() //
|
||
// );
|
||
// }
|
||
// }
|
||
// }
|
||
|
||
//
|
||
}
|
||
|
||
//
|
||
void DestroyImportantAreas()
|
||
{
|
||
//
|
||
bool hasSupport = support.IsValid();
|
||
if (hasSupport)
|
||
{
|
||
//
|
||
supportTime = NULL;
|
||
isSupportTested = false;
|
||
RemoveSupport(support);
|
||
support.Clean();
|
||
}
|
||
|
||
//
|
||
bool hasResistance = resistance.IsValid();
|
||
if (hasResistance)
|
||
{
|
||
//
|
||
resistanceTime = NULL;
|
||
isResistanceTested = false;
|
||
RemoveResistance(resistance);
|
||
resistance.Clean();
|
||
}
|
||
|
||
//
|
||
bool hasBullishOB = bullishOB.IsValid();
|
||
if (hasBullishOB)
|
||
{
|
||
//
|
||
bullishOBTime = NULL;
|
||
RemoveBullishOrderBlock(bullishOB);
|
||
bullishOB.Clean();
|
||
}
|
||
|
||
//
|
||
bool hasBearishOB = bearishOB.IsValid();
|
||
if (hasBearishOB)
|
||
{
|
||
//
|
||
bearishOBTime = NULL;
|
||
RemoveBearishOrderBlock(bearishOB);
|
||
bearishOB.Clean();
|
||
}
|
||
|
||
//
|
||
bool hasBullishFVG = bullishFVG.IsValid();
|
||
if (hasBullishFVG)
|
||
{
|
||
//
|
||
bullishFVGUpper = 0;
|
||
bullishFVGLower = 0;
|
||
bullishFVGTime = NULL;
|
||
RemoveBullishFVG(bullishFVG);
|
||
bullishFVG.Clean();
|
||
}
|
||
|
||
//
|
||
bool hasBearishFVG = bearishFVG.IsValid();
|
||
if (hasBearishFVG)
|
||
{
|
||
//
|
||
bearishFVGUpper = 0;
|
||
bearishFVGLower = 0;
|
||
bearishFVGTime = NULL;
|
||
RemoveBullishFVG(bearishFVG);
|
||
bearishFVG.Clean();
|
||
}
|
||
|
||
//
|
||
bool hasBullishTrend = bullishTrend.IsValid();
|
||
if (hasBullishTrend)
|
||
{
|
||
//
|
||
RemoveBullishTrend(bullishTrend);
|
||
bullishTrend.Clean();
|
||
}
|
||
|
||
//
|
||
bool hasBearishTrend = bearishTrend.IsValid();
|
||
if (hasBearishTrend)
|
||
{
|
||
//
|
||
RemoveBearishTrend(bearishTrend);
|
||
bearishTrend.Clean();
|
||
}
|
||
}
|
||
|
||
//
|
||
void CheckImportantAreasValidation()
|
||
{
|
||
//
|
||
CheckSupportValidation();
|
||
CheckResistanceValidation();
|
||
|
||
//
|
||
CheckBullishOBValidation();
|
||
CheckBearishOBValidation();
|
||
|
||
//
|
||
CheckBullishFVGValidation();
|
||
CheckBearishFVgValidation();
|
||
|
||
//
|
||
CheckBullishTrendValidation();
|
||
CheckBearishTrendValidation();
|
||
}
|
||
|
||
//
|
||
bool isSupportTested;
|
||
datetime supportTime;
|
||
void CheckSupportValidation()
|
||
{
|
||
//
|
||
if (!isSupportTested)
|
||
{
|
||
//
|
||
if (support.IsValid() && IsValid(supportTime))
|
||
{
|
||
//
|
||
int age = (int)(((int)(TimeToSeconds(TimeCurrent()) - TimeToSeconds(supportTime))) / PeriodSeconds(mPeriod));
|
||
if (age >= 50)
|
||
{
|
||
//
|
||
isSupportTested = false;
|
||
supportTime = NULL;
|
||
RemoveSupport(support);
|
||
support.Clean();
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
//
|
||
XOHCL cBar;
|
||
bool isInited = cBar.Init(
|
||
mSymbol,
|
||
mPeriod,
|
||
1 //
|
||
);
|
||
if (!isInited)
|
||
{
|
||
return;
|
||
}
|
||
|
||
//
|
||
double points = GetPoints(mSymbol);
|
||
|
||
//
|
||
// Find Price Distance ...
|
||
double highDiff = MathAbs(cBar.high - support.high);
|
||
double lowDiff = MathAbs(cBar.low - support.high);
|
||
|
||
//
|
||
bool isBreaked = MathMax(highDiff, lowDiff) >= 100 * points;
|
||
if (!isBreaked)
|
||
{
|
||
return;
|
||
}
|
||
|
||
//
|
||
isSupportTested = false;
|
||
RemoveSupport(support);
|
||
supportTime = NULL;
|
||
support.Clean();
|
||
}
|
||
|
||
//
|
||
bool isResistanceTested;
|
||
datetime resistanceTime;
|
||
void CheckResistanceValidation()
|
||
{
|
||
//
|
||
if (!isResistanceTested)
|
||
{
|
||
//
|
||
if (resistance.IsValid() && IsValid(resistanceTime))
|
||
{
|
||
//
|
||
int age = (int)(((int)(TimeToSeconds(TimeCurrent()) - TimeToSeconds(resistanceTime))) / PeriodSeconds(mPeriod));
|
||
if (age >= 50)
|
||
{
|
||
//
|
||
isResistanceTested = false;
|
||
resistanceTime = NULL;
|
||
RemoveResistance(resistance);
|
||
resistance.Clean();
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
//
|
||
XOHCL cBar;
|
||
bool isInited = cBar.Init(
|
||
mSymbol,
|
||
mPeriod,
|
||
1 //
|
||
);
|
||
if (!isInited)
|
||
{
|
||
return;
|
||
}
|
||
|
||
//
|
||
double points = GetPoints(mSymbol);
|
||
|
||
//
|
||
// Find Price Distance ...
|
||
double highDiff = MathAbs(cBar.high - resistance.low);
|
||
double lowDiff = MathAbs(cBar.low - resistance.low);
|
||
|
||
//
|
||
bool isBreaked = MathMax(highDiff, lowDiff) >= 100 * points;
|
||
if (!isBreaked)
|
||
{
|
||
return;
|
||
}
|
||
|
||
//
|
||
isResistanceTested = false;
|
||
RemoveResistance(resistance);
|
||
resistanceTime = NULL;
|
||
resistance.Clean();
|
||
}
|
||
|
||
//
|
||
datetime bullishOBTime;
|
||
void CheckBullishOBValidation()
|
||
{
|
||
//
|
||
if (!IsValid(bullishOBTime))
|
||
{
|
||
return;
|
||
}
|
||
|
||
//
|
||
int age = (int)(((int)(TimeToSeconds(TimeCurrent()) - TimeToSeconds(bullishOBTime))) / PeriodSeconds(mPeriod));
|
||
if (age >= 50)
|
||
{
|
||
//
|
||
bullishOBTime = NULL;
|
||
RemoveBullishOrderBlock(bullishOB);
|
||
bullishOB.Clean();
|
||
}
|
||
}
|
||
|
||
//
|
||
datetime bearishOBTime;
|
||
void CheckBearishOBValidation()
|
||
{
|
||
//
|
||
if (!IsValid(bearishOBTime))
|
||
{
|
||
return;
|
||
}
|
||
|
||
//
|
||
int age = (int)(((int)(TimeToSeconds(TimeCurrent()) - TimeToSeconds(bearishOBTime))) / PeriodSeconds(mPeriod));
|
||
if (age >= 50)
|
||
{
|
||
//
|
||
bearishOBTime = NULL;
|
||
RemoveBearishOrderBlock(bearishOB);
|
||
bearishOB.Clean();
|
||
}
|
||
}
|
||
|
||
//
|
||
datetime bullishFVGTime;
|
||
void CheckBullishFVGValidation()
|
||
{
|
||
//
|
||
if (!IsValid(bullishFVGTime))
|
||
{
|
||
return;
|
||
}
|
||
|
||
//
|
||
int age = (int)(((int)(TimeToSeconds(TimeCurrent()) - TimeToSeconds(bullishFVGTime))) / PeriodSeconds(mPeriod));
|
||
if (age >= 50)
|
||
{
|
||
//
|
||
bullishFVGTime = NULL;
|
||
RemoveBullishFVG(bullishFVG);
|
||
bullishFVG.Clean();
|
||
}
|
||
}
|
||
|
||
//
|
||
datetime bearishFVGTime;
|
||
void CheckBearishFVgValidation()
|
||
{
|
||
//
|
||
if (!IsValid(bearishFVGTime))
|
||
{
|
||
return;
|
||
}
|
||
|
||
//
|
||
int age = (int)(((int)(TimeToSeconds(TimeCurrent()) - TimeToSeconds(bearishFVGTime))) / PeriodSeconds(mPeriod));
|
||
if (age >= 50)
|
||
{
|
||
//
|
||
bearishFVGTime = NULL;
|
||
RemoveBearishFVG(bearishFVG);
|
||
bearishFVG.Clean();
|
||
}
|
||
}
|
||
|
||
//
|
||
void CheckBullishTrendValidation()
|
||
{
|
||
//
|
||
// TODO: Complete this ...
|
||
}
|
||
|
||
//
|
||
void CheckBearishTrendValidation()
|
||
{
|
||
//
|
||
// TODO: Complete this ...
|
||
}
|
||
|
||
//
|
||
};
|
||
|
||
// |