1743 lines
35 KiB
Plaintext
1743 lines
35 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Common Library
|
|
// --------------------------------------
|
|
// Name: X121SMCLib
|
|
// Description: provide all commonly used functions ...
|
|
//
|
|
//
|
|
// 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.base.class.mq5"
|
|
#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5"
|
|
#include "../../Helpers/x-saherelm.x121.helper.mq5"
|
|
#include "../../Libraries/x-saherelm.common.lib.mq5"
|
|
#include "../../Libraries/x-saherelm.x-poi.lib.mq5"
|
|
#include "../../Libraries/x-saherelm.x-trade.lib.mq5"
|
|
|
|
//
|
|
// Definitions ...
|
|
|
|
//
|
|
const string X121SMCStrategyToken = "X121SMC";
|
|
|
|
//
|
|
const string X121SMCXToken = "X121X";
|
|
const string X121SMCXOBSToken = "X121XOBS";
|
|
const string X121SMCXHKPVToken = "X121XHKPV";
|
|
const string X121SMCXOBPVToken = "X121XOBPV";
|
|
const string X121SMCXIOBPVToken = "X121XIOBPV";
|
|
|
|
//
|
|
// X121 SMC Providers ...
|
|
enum ENUM_X_121_SMC_PROVIDERS
|
|
{
|
|
//
|
|
X_121_SMC_PROVIDER_NONE,
|
|
X_121_SMC_PROVIDER_X,
|
|
X_121_SMC_PROVIDER_XOBS,
|
|
X_121_SMC_PROVIDER_XHKPV,
|
|
X_121_SMC_PROVIDER_XOBPV,
|
|
X_121_SMC_PROVIDER_XIOBPV,
|
|
};
|
|
|
|
//
|
|
// Guard Actions ...
|
|
enum ENUM_X_121_SMC_GUARD_ACTIONS
|
|
{
|
|
X_121_SMC_GUARD_ACTION_NONE, // Nothing to Do
|
|
X_121_SMC_GUARD_ACTION_CLOSE, // Close Specified Position
|
|
X_121_SMC_GUARD_ACTION_CLOSE_ALL, // Close All Positions
|
|
X_121_SMC_GUARD_ACTION_CLOSE_LONGS, // Close All Long Positions
|
|
X_121_SMC_GUARD_ACTION_CLOSE_SHORTS, // Close All Short Position
|
|
X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE, // Partial Close Specified Position
|
|
X_121_SMC_GUARD_ACTION_TRAIL_STOP, // Trail Stop of Specified Position
|
|
X_121_SMC_GUARD_ACTION_TRAIL_TARGET, // Trail Target of Specified Position
|
|
X_121_SMC_GUARD_ACTION_HEDGE, // Hedge Specified Positions
|
|
};
|
|
|
|
//
|
|
// Each Market Cycle (Time Frame) Conditions
|
|
// Model as this Structure ...
|
|
struct X121SMCCycleConditions
|
|
{
|
|
//
|
|
string symbol;
|
|
ENUM_TIMEFRAMES period;
|
|
datetime time;
|
|
|
|
//
|
|
X121Conditions x121Conditions;
|
|
|
|
//
|
|
XPOIState state;
|
|
|
|
//
|
|
void X121SMCStrategyConditions()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
/**
|
|
* Cleanup ...
|
|
*/
|
|
void Clean()
|
|
{
|
|
//
|
|
symbol = NULL;
|
|
period = NULL;
|
|
time = NULL;
|
|
|
|
//
|
|
state.Clean();
|
|
x121Conditions.Clean();
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
/**
|
|
* Validate ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = IsSpecifiedValid(symbol) &&
|
|
IsSpecifiedValid(period) &&
|
|
IsSpecifiedValid(time);
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Reporter Functions ...
|
|
|
|
/**
|
|
* Generate Provided Scores ...
|
|
*
|
|
* @param bullishScore: Integer, reference ...
|
|
* @param bearishScore: Integer, referenceF ...
|
|
*/
|
|
void GenerateScore(
|
|
double &bullishScore,
|
|
double &bearishScore //
|
|
)
|
|
{
|
|
//
|
|
bullishScore = 0;
|
|
bearishScore = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
double bullScore = 0;
|
|
double bearScore = 0;
|
|
}
|
|
|
|
/**
|
|
* Generate Summary ...
|
|
*
|
|
* @param onlyCommons: Boolean ...
|
|
* @param onlyConditions: Boolean ...
|
|
* @param includeScores: Boolean ...
|
|
* @param ignoreFalseConditions: Boolean ...
|
|
* @param separator: String ...
|
|
*
|
|
* @return ( string )
|
|
*/
|
|
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 //
|
|
);
|
|
|
|
//
|
|
string conditionsStr =
|
|
//
|
|
""
|
|
//
|
|
;
|
|
|
|
//
|
|
result =
|
|
//
|
|
"[" + GetTag() + "]" + separator +
|
|
"----------" + separator +
|
|
(onlyConditions
|
|
? ""
|
|
: commonStr) +
|
|
" " + separator +
|
|
(onlyCommons
|
|
? ""
|
|
: conditionsStr) +
|
|
""
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Unique Identifier ...
|
|
*
|
|
* @param forObject: Boolean ...
|
|
*
|
|
* @return ( string )
|
|
*/
|
|
string GetTag(
|
|
bool forObject = false //
|
|
)
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
string typeName = GetTypeName(this);
|
|
|
|
//
|
|
if (!forObject)
|
|
{
|
|
result = typeName;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
result = typeName + "_" +
|
|
symbol + "_" + ToString(period) + "_" +
|
|
ToMD5(time);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
//
|
|
// Model Signalling Conditions ...
|
|
struct X121SMCStrategyConditions
|
|
{
|
|
//
|
|
string symbol;
|
|
ENUM_TIMEFRAMES period;
|
|
datetime time;
|
|
|
|
//
|
|
double sl;
|
|
double tp;
|
|
double target;
|
|
string provider;
|
|
ENUM_X_DIRECTION signalDir;
|
|
|
|
//
|
|
X121Conditions conditions;
|
|
// XPriceZones priceZones;
|
|
// XPriceZones decisionZones;
|
|
// XMarketStructure marketStructure;
|
|
|
|
//
|
|
void X121SMCStrategyConditions()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
/**
|
|
* Cleanup ...
|
|
*/
|
|
void Clean()
|
|
{
|
|
//
|
|
symbol = NULL;
|
|
period = NULL;
|
|
time = NULL;
|
|
|
|
//
|
|
sl = 0;
|
|
tp = 0;
|
|
provider = NULL;
|
|
signalDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
conditions.Clean();
|
|
// priceZones.Clean();
|
|
// decisionZones.Clean();
|
|
// marketStructure.Clean();
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
/**
|
|
* Validate ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = IsSpecifiedValid(symbol) &&
|
|
IsSpecifiedValid(period) &&
|
|
IsSpecifiedValid(time);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Conditions Has Valid Bullish Signal ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasBullishSignal()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
(sl > 0 ||
|
|
tp > 0) &&
|
|
IsValid() &&
|
|
HasDirection(signalDir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
IsBullish(signalDir);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Conditions Has Valid Bearish Signal ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasBearishSignal()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
(sl > 0 ||
|
|
tp > 0) &&
|
|
IsValid() &&
|
|
HasDirection(signalDir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
IsBearish(signalDir);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Reporter Functions ...
|
|
|
|
/**
|
|
* Generate Provided Scores ...
|
|
*
|
|
* @param bullishScore: Integer, reference ...
|
|
* @param bearishScore: Integer, referenceF ...
|
|
*/
|
|
void GenerateScore(
|
|
double &bullishScore,
|
|
double &bearishScore //
|
|
)
|
|
{
|
|
//
|
|
bullishScore = 0;
|
|
bearishScore = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
double bullScore = 0;
|
|
double bearScore = 0;
|
|
}
|
|
|
|
/**
|
|
* Generate Summary ...
|
|
*
|
|
* @param onlyCommons: Boolean ...
|
|
* @param onlyConditions: Boolean ...
|
|
* @param includeScores: Boolean ...
|
|
* @param ignoreFalseConditions: Boolean ...
|
|
* @param separator: String ...
|
|
*
|
|
* @return ( string )
|
|
*/
|
|
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 //
|
|
);
|
|
|
|
//
|
|
string conditionsStr =
|
|
//
|
|
""
|
|
//
|
|
;
|
|
|
|
//
|
|
result =
|
|
//
|
|
"[" + GetTag() + "]" + separator +
|
|
"----------" + separator +
|
|
(onlyConditions
|
|
? ""
|
|
: commonStr) +
|
|
" " + separator +
|
|
(onlyCommons
|
|
? ""
|
|
: conditionsStr) +
|
|
""
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Unique Identifier ...
|
|
*
|
|
* @param forObject: Boolean ...
|
|
*
|
|
* @return ( string )
|
|
*/
|
|
string GetTag(
|
|
bool forObject = false //
|
|
)
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
string typeName = GetTypeName(this);
|
|
|
|
//
|
|
if (!forObject)
|
|
{
|
|
result = typeName;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
result = typeName + "_" +
|
|
symbol + "_" + ToString(period) + "_" +
|
|
ToMD5(time);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
//
|
|
// Model a Guard Action ...
|
|
struct X121SMCGuard
|
|
{
|
|
//
|
|
// Props ...
|
|
ENUM_X_121_SMC_GUARD_ACTIONS action;
|
|
datetime time;
|
|
|
|
//
|
|
string symbol;
|
|
string provider;
|
|
|
|
//
|
|
// Specified Position ...
|
|
ulong ticket;
|
|
|
|
//
|
|
// Partial Close ...
|
|
double volumeMultiplier;
|
|
|
|
//
|
|
// SL Trial ...
|
|
double sl;
|
|
|
|
//
|
|
// TP Trial ...
|
|
double tp;
|
|
|
|
//
|
|
// Constructor ...
|
|
X121SMCGuard()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
/**
|
|
* Cleanup ...
|
|
*/
|
|
void Clean()
|
|
{
|
|
//
|
|
time = NULL;
|
|
action = X_121_SMC_GUARD_ACTION_NONE;
|
|
|
|
//
|
|
symbol = NULL;
|
|
provider = NULL;
|
|
|
|
//
|
|
ticket = 0;
|
|
|
|
//
|
|
volumeMultiplier = 0;
|
|
|
|
//
|
|
sl = 0;
|
|
tp = 0;
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
/**
|
|
* Validate ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid(time) &&
|
|
IsValid(symbol) &&
|
|
IsValid(provider) &&
|
|
action != X_121_SMC_GUARD_ACTION_NONE
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Validate Model Based On Specified Guard Actions ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
};
|
|
|
|
//
|
|
// Model Cycle State ...
|
|
struct X121SMCCycleState
|
|
{
|
|
//
|
|
// Props ...
|
|
string symbol;
|
|
ENUM_TIMEFRAMES period;
|
|
|
|
//
|
|
// Bullish ...
|
|
XCFVG *bullishFVGs[];
|
|
XCOrderBlock *bullishOBs[];
|
|
XCDemandZone *demandZones[];
|
|
XCSupportZone *supportZones[];
|
|
|
|
//
|
|
// Bearish ...
|
|
XCFVG *bearishFVGs[];
|
|
XCOrderBlock *bearishOBs[];
|
|
XCSupplyZone *supplyZones[];
|
|
XCResistanceZone *resistanceZones[];
|
|
|
|
//
|
|
// Constructor ...
|
|
X121SMCCycleState()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
/**
|
|
* Cleanup Model ...
|
|
*/
|
|
void Clean()
|
|
{
|
|
//
|
|
symbol = NULL;
|
|
period = NULL;
|
|
|
|
//
|
|
Clean(bullishFVGs);
|
|
Clean(bullishOBs);
|
|
Clean(demandZones);
|
|
Clean(supportZones);
|
|
|
|
//
|
|
Clean(bearishFVGs);
|
|
Clean(bearishOBs);
|
|
Clean(supplyZones);
|
|
Clean(resistanceZones);
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
/**
|
|
* Validate Model ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid(symbol) &&
|
|
IsValid(period) &&
|
|
(
|
|
//
|
|
(HasBullishOBs() &&
|
|
(HasBullishFVGs() ||
|
|
HasSupportZones() ||
|
|
HasDemandZones()))
|
|
//
|
|
||
|
|
(HasBearishOBs() &&
|
|
(HasSupplyZones() ||
|
|
HasBearishFVGs() ||
|
|
HasResistanceZones()))
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int CountBullishOBs()
|
|
{
|
|
return ArraySize(bullishOBs);
|
|
}
|
|
|
|
//
|
|
bool HasBullishOBs()
|
|
{
|
|
return IsValidSize(CountBullishOBs());
|
|
}
|
|
|
|
//
|
|
int CountBearishOBs()
|
|
{
|
|
return ArraySize(bearishOBs);
|
|
}
|
|
|
|
//
|
|
bool HasBearishOBs()
|
|
{
|
|
return IsValidSize(CountBearishOBs());
|
|
}
|
|
|
|
//
|
|
int CountSupportZones()
|
|
{
|
|
return ArraySize(supportZones);
|
|
}
|
|
|
|
//
|
|
bool HasSupportZones()
|
|
{
|
|
return IsValidSize(CountSupportZones());
|
|
}
|
|
|
|
//
|
|
int CountResistanceZones()
|
|
{
|
|
return ArraySize(resistanceZones);
|
|
}
|
|
|
|
//
|
|
bool HasResistanceZones()
|
|
{
|
|
return IsValidSize(CountResistanceZones());
|
|
}
|
|
|
|
//
|
|
int CountDemandZones()
|
|
{
|
|
return ArraySize(demandZones);
|
|
}
|
|
|
|
//
|
|
bool HasDemandZones()
|
|
{
|
|
return IsValidSize(CountDemandZones());
|
|
}
|
|
|
|
//
|
|
int CountSupplyZones()
|
|
{
|
|
return ArraySize(supplyZones);
|
|
}
|
|
|
|
//
|
|
bool HasSupplyZones()
|
|
{
|
|
return IsValidSize(CountSupplyZones());
|
|
}
|
|
|
|
//
|
|
int CountBullishFVGs()
|
|
{
|
|
return ArraySize(bullishFVGs);
|
|
}
|
|
|
|
//
|
|
bool HasBullishFVGs()
|
|
{
|
|
return IsValidSize(CountBullishFVGs());
|
|
}
|
|
|
|
//
|
|
int CountBearishFVGs()
|
|
{
|
|
return ArraySize(bearishFVGs);
|
|
}
|
|
|
|
//
|
|
bool HasBearishFVGs()
|
|
{
|
|
return IsValidSize(CountBearishFVGs());
|
|
}
|
|
|
|
//
|
|
bool GetOldestOB(
|
|
XCOrderBlock *&orderBlock //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
orderBlock = NULL;
|
|
|
|
//
|
|
bool hasBullishOB = HasBullishOBs();
|
|
bool hasBearishOB = HasBearishOBs();
|
|
result = hasBullishOB ||
|
|
hasBearishOB;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int iBullOBIDX = -1;
|
|
bool iHasBullOB = false;
|
|
XCOrderBlock *iBullOB = NULL;
|
|
if (hasBullishOB)
|
|
{
|
|
//
|
|
XCZone* iZones[];
|
|
ToZone(
|
|
bullishOBs,
|
|
iZones //
|
|
);
|
|
|
|
//
|
|
iBullOBIDX = GetOldest(
|
|
iZones //
|
|
);
|
|
|
|
//
|
|
iHasBullOB = IsValidIndex(iBullOBIDX);
|
|
if (iHasBullOB)
|
|
{
|
|
iBullOB = bullishOBs[iBullOBIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
int iBearOBIDX = -1;
|
|
bool iHasBearOB = false;
|
|
XCOrderBlock *iBearOB = NULL;
|
|
if (hasBearishOB)
|
|
{
|
|
//
|
|
XCZone* iZones[];
|
|
ToZone(
|
|
bearishOBs,
|
|
iZones //
|
|
);
|
|
|
|
//
|
|
iBearOBIDX = GetOldest(
|
|
iZones //
|
|
);
|
|
|
|
//
|
|
iHasBearOB = IsValidIndex(iBearOBIDX);
|
|
if (iHasBearOB)
|
|
{
|
|
iBearOB = bearishOBs[iBearOBIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
if (iHasBullOB)
|
|
{
|
|
orderBlock = iBullOB;
|
|
}
|
|
|
|
//
|
|
if (iHasBearOB)
|
|
{
|
|
//
|
|
bool canSet = orderBlock == NULL ||
|
|
orderBlock.From() > iBearOB.From();
|
|
if (canSet)
|
|
{
|
|
orderBlock = iBearOB;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = orderBlock != NULL &&
|
|
orderBlock.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool GetYoungestOB(
|
|
XCOrderBlock *&orderBlock //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
orderBlock = NULL;
|
|
|
|
//
|
|
bool hasBullishOB = HasBullishOBs();
|
|
bool hasBearishOB = HasBearishOBs();
|
|
result = hasBullishOB ||
|
|
hasBearishOB;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int iBullOBIDX = -1;
|
|
bool iHasBullOB = false;
|
|
XCOrderBlock *iBullOB = NULL;
|
|
if (hasBullishOB)
|
|
{
|
|
//
|
|
XCZone* iZones[];
|
|
ToZone(
|
|
bullishOBs,
|
|
iZones //
|
|
);
|
|
|
|
//
|
|
iBullOBIDX = GetYoungest(
|
|
iZones //
|
|
);
|
|
|
|
//
|
|
iHasBullOB = IsValidIndex(iBullOBIDX);
|
|
if (iHasBullOB)
|
|
{
|
|
iBullOB = bullishOBs[iBullOBIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
int iBearOBIDX = -1;
|
|
bool iHasBearOB = false;
|
|
XCOrderBlock *iBearOB = NULL;
|
|
if (hasBearishOB)
|
|
{
|
|
//
|
|
XCZone* iZones[];
|
|
ToZone(
|
|
bearishOBs,
|
|
iZones //
|
|
);
|
|
|
|
//
|
|
iBearOBIDX = GetYoungest(
|
|
iZones //
|
|
);
|
|
|
|
//
|
|
iHasBearOB = IsValidIndex(iBearOBIDX);
|
|
if (iHasBearOB)
|
|
{
|
|
iBearOB = bearishOBs[iBearOBIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
if (iHasBullOB)
|
|
{
|
|
orderBlock = iBullOB;
|
|
}
|
|
|
|
//
|
|
if (iHasBearOB)
|
|
{
|
|
//
|
|
bool canSet = orderBlock == NULL ||
|
|
orderBlock.From() < iBearOB.From();
|
|
if (canSet)
|
|
{
|
|
orderBlock = iBearOB;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = orderBlock != NULL &&
|
|
orderBlock.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
/**
|
|
* Detect Price inside Box ...
|
|
*
|
|
* @param box: XBoxZone instance Reference, Founded Price Inside Box ...
|
|
* @param orderBlock: XCOrderBlock pointer Reference, Founded Price Inside Order Block ...
|
|
* @param xConditions: X121Conditions instance Reference, provides Market Conditions ...
|
|
* @param state: X121SMCCycleState instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectPriceInsideBox(
|
|
XBoxZone &box, // Price Inside Bo ...
|
|
XCOrderBlock *&orderBlock, // Price Inside Order Block ...
|
|
X121Conditions &xConditions, // X121Conditions for Validation ...
|
|
X121SMCCycleState &state // Cycle State ...
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
string symbol = state.symbol;
|
|
ENUM_TIMEFRAMES period = state.period;
|
|
|
|
//
|
|
box.symbol = symbol;
|
|
box.period = period;
|
|
|
|
//
|
|
result = state.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Detect Price Inside Order Block ...
|
|
|
|
//
|
|
bool hasBullishOBs = state.HasBullishOBs();
|
|
int bullishOBsCount = state.CountBullishOBs();
|
|
|
|
//
|
|
bool hasBearishOBs = state.HasBearishOBs();
|
|
int bearishOBsCount = state.CountBearishOBs();
|
|
|
|
//
|
|
bool hasOBs =
|
|
//
|
|
hasBullishOBs ||
|
|
hasBearishOBs
|
|
//
|
|
;
|
|
result = hasOBs;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool hasPriceInsideOB = false;
|
|
XCOrderBlock *priceInsideOB = NULL;
|
|
ENUM_X_DIRECTION boxDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
if (hasBullishOBs &&
|
|
!hasPriceInsideOB)
|
|
{
|
|
//
|
|
for (int i = 0; i < bullishOBsCount; i++)
|
|
{
|
|
//
|
|
XCOrderBlock *iOb = state.bullishOBs[i];
|
|
|
|
//
|
|
bool isInside = IsPriceInsideZone(
|
|
xConditions.valesBuffer[1],
|
|
(XCZone *)iOb //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
priceInsideOB = iOb;
|
|
hasPriceInsideOB = true;
|
|
boxDir = X_DIRECTION_BULLISH;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
if (hasBearishOBs &&
|
|
!hasPriceInsideOB)
|
|
{
|
|
//
|
|
for (int i = 0; i < bearishOBsCount; i++)
|
|
{
|
|
//
|
|
XCOrderBlock *iOb = state.bearishOBs[i];
|
|
|
|
//
|
|
bool isInside = IsPriceInsideZone(
|
|
xConditions.peaksBuffer[1],
|
|
(XCZone *)iOb //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
priceInsideOB = iOb;
|
|
hasPriceInsideOB = true;
|
|
boxDir = X_DIRECTION_BEARISH;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
if (hasPriceInsideOB)
|
|
{
|
|
//
|
|
orderBlock = priceInsideOB;
|
|
boxDir = priceInsideOB.IsBullish()
|
|
? X_DIRECTION_BULLISH
|
|
: priceInsideOB.IsBearish()
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
bool hasBullishFVGs = state.HasBullishFVGs();
|
|
bool hasBearishFVGs = state.HasBearishFVGs();
|
|
bool hasDemandZones = state.HasDemandZones();
|
|
bool hasSupplyZones = state.HasSupplyZones();
|
|
bool hasSupportZones = state.HasSupportZones();
|
|
bool hasResistanceZones = state.HasResistanceZones();
|
|
|
|
//
|
|
bool hasBullishZones =
|
|
//
|
|
hasBullishFVGs ||
|
|
hasDemandZones ||
|
|
hasSupportZones
|
|
//
|
|
;
|
|
|
|
//
|
|
bool hasBearishZones =
|
|
//
|
|
hasBearishFVGs ||
|
|
hasSupplyZones ||
|
|
hasResistanceZones
|
|
//
|
|
;
|
|
|
|
//
|
|
bool hasPropperZones =
|
|
//
|
|
IsBullish(boxDir)
|
|
? hasBullishZones
|
|
: IsBearish(boxDir)
|
|
? hasBearishZones
|
|
: false
|
|
//
|
|
;
|
|
|
|
//
|
|
if (!hasPropperZones &&
|
|
hasPriceInsideOB)
|
|
{
|
|
//
|
|
// Use Price Inside OB as Box ...
|
|
box.dir = boxDir;
|
|
box.to = priceInsideOB.To();
|
|
box.from = priceInsideOB.From();
|
|
box.upper = priceInsideOB.Upper();
|
|
box.lower = priceInsideOB.Lower();
|
|
}
|
|
else if (hasPropperZones &&
|
|
hasPriceInsideOB)
|
|
{
|
|
//
|
|
// Detect Validate Zones ...
|
|
int count = 0;
|
|
XBoxZone boxes[];
|
|
double upper = 0;
|
|
double lower = 0;
|
|
double price = 0;
|
|
datetime to = NULL;
|
|
datetime from = NULL;
|
|
ENUM_X_DIRECTION dir = X_DIRECTION_NONE;
|
|
if (IsBullish(boxDir))
|
|
{
|
|
//
|
|
double price = xConditions.valesBuffer[1];
|
|
dir = X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
// Bullish FVG ...
|
|
count = state.CountBullishFVGs();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCFVG *iFVG = state.bullishFVGs[i];
|
|
|
|
//
|
|
to = iFVG.To();
|
|
from = iFVG.From();
|
|
upper = iFVG.Upper();
|
|
lower = iFVG.Lower();
|
|
|
|
//
|
|
bool isInside = IsPriceInsideZone(
|
|
price,
|
|
upper,
|
|
lower //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
|
|
//
|
|
iBox.dir = dir;
|
|
iBox.symbol = symbol;
|
|
iBox.period = period;
|
|
|
|
//
|
|
iBox.to = to;
|
|
iBox.from = from;
|
|
iBox.upper = upper;
|
|
iBox.lower = lower;
|
|
|
|
//
|
|
if (iBox.IsValid())
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
boxes //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Demand Zones ...
|
|
count = state.CountDemandZones();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCDemandZone *iDemand = state.demandZones[i];
|
|
|
|
//
|
|
to = iDemand.To();
|
|
from = iDemand.From();
|
|
upper = iDemand.Upper();
|
|
lower = iDemand.Lower();
|
|
|
|
//
|
|
bool isInside = IsPriceInsideZone(
|
|
price,
|
|
upper,
|
|
lower //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
|
|
//
|
|
iBox.dir = dir;
|
|
iBox.symbol = symbol;
|
|
iBox.period = period;
|
|
|
|
//
|
|
iBox.to = to;
|
|
iBox.from = from;
|
|
iBox.upper = upper;
|
|
iBox.lower = lower;
|
|
|
|
//
|
|
if (iBox.IsValid())
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
boxes //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Support Zones ...
|
|
count = state.CountSupportZones();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCSupportZone *iSupport = state.supportZones[i];
|
|
|
|
//
|
|
to = iSupport.To();
|
|
from = iSupport.From();
|
|
upper = iSupport.Upper();
|
|
lower = iSupport.Lower();
|
|
|
|
//
|
|
bool isInside = IsPriceInsideZone(
|
|
price,
|
|
upper,
|
|
lower //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
|
|
//
|
|
iBox.dir = dir;
|
|
iBox.symbol = symbol;
|
|
iBox.period = period;
|
|
|
|
//
|
|
iBox.to = to;
|
|
iBox.from = from;
|
|
iBox.upper = upper;
|
|
iBox.lower = lower;
|
|
|
|
//
|
|
if (iBox.IsValid())
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
boxes //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
double price = xConditions.peaksBuffer[1];
|
|
dir = X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
// Bearish FVG ...
|
|
count = state.CountBearishFVGs();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCFVG *iFVG = state.bearishFVGs[i];
|
|
|
|
//
|
|
to = iFVG.To();
|
|
from = iFVG.From();
|
|
upper = iFVG.Upper();
|
|
lower = iFVG.Lower();
|
|
|
|
//
|
|
bool isInside = IsPriceInsideZone(
|
|
price,
|
|
upper,
|
|
lower //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
|
|
//
|
|
iBox.dir = dir;
|
|
iBox.symbol = symbol;
|
|
iBox.period = period;
|
|
|
|
//
|
|
iBox.to = to;
|
|
iBox.from = from;
|
|
iBox.upper = upper;
|
|
iBox.lower = lower;
|
|
|
|
//
|
|
if (iBox.IsValid())
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
boxes //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Supply Zones ...
|
|
count = state.CountSupplyZones();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCSupplyZone *iSupply = state.supplyZones[i];
|
|
|
|
//
|
|
to = iSupply.To();
|
|
from = iSupply.From();
|
|
upper = iSupply.Upper();
|
|
lower = iSupply.Lower();
|
|
|
|
//
|
|
bool isInside = IsPriceInsideZone(
|
|
price,
|
|
upper,
|
|
lower //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
|
|
//
|
|
iBox.dir = dir;
|
|
iBox.symbol = symbol;
|
|
iBox.period = period;
|
|
|
|
//
|
|
iBox.to = to;
|
|
iBox.from = from;
|
|
iBox.upper = upper;
|
|
iBox.lower = lower;
|
|
|
|
//
|
|
if (iBox.IsValid())
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
boxes //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Demand Zones ...
|
|
count = state.CountResistanceZones();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCResistanceZone *iResistance = state.resistanceZones[i];
|
|
|
|
//
|
|
to = iResistance.To();
|
|
from = iResistance.From();
|
|
upper = iResistance.Upper();
|
|
lower = iResistance.Lower();
|
|
|
|
//
|
|
bool isInside = IsPriceInsideZone(
|
|
price,
|
|
upper,
|
|
lower //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
|
|
//
|
|
iBox.dir = dir;
|
|
iBox.symbol = symbol;
|
|
iBox.period = period;
|
|
|
|
//
|
|
iBox.to = to;
|
|
iBox.from = from;
|
|
iBox.upper = upper;
|
|
iBox.lower = lower;
|
|
|
|
//
|
|
if (iBox.IsValid())
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
boxes //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
int boxesCount = ArraySize(boxes);
|
|
bool hasBoxes = IsValidSize(boxes);
|
|
if (hasBoxes)
|
|
{
|
|
//
|
|
// Filter Boxes ...
|
|
for (int i = 0; i < boxesCount; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = boxes[i];
|
|
|
|
//
|
|
// Direction ...
|
|
if (!HasDirection(box.dir) || box.dir != iBox.dir)
|
|
{
|
|
box.dir = iBox.dir;
|
|
}
|
|
|
|
//
|
|
// Upper ...
|
|
if (box.upper == 0 || box.upper < iBox.upper)
|
|
{
|
|
box.upper = iBox.upper;
|
|
}
|
|
|
|
//
|
|
// Lower ...
|
|
if (box.lower == 0 || box.lower < iBox.lower)
|
|
{
|
|
box.lower = iBox.lower;
|
|
}
|
|
|
|
//
|
|
// To ...
|
|
if (!IsValid(box.to) || box.to < iBox.to)
|
|
{
|
|
box.to = iBox.to;
|
|
}
|
|
|
|
//
|
|
// From ...
|
|
if (!IsValid(box.from) || box.from > iBox.from)
|
|
{
|
|
box.from = iBox.from;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Use Price Inside OB as Box ...
|
|
box.dir = boxDir;
|
|
box.to = priceInsideOB.To();
|
|
box.from = priceInsideOB.From();
|
|
box.upper = priceInsideOB.Upper();
|
|
box.lower = priceInsideOB.Lower();
|
|
}
|
|
}
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Add Guard to Collection ...
|
|
*
|
|
* @param guard: X121SMCGuard instance ...
|
|
* @param guards: X121SMCGuard instance Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int AddGuard(
|
|
X121SMCGuard &guard,
|
|
X121SMCGuard &guards[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!guard.IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
AddRef(
|
|
guard,
|
|
guards //
|
|
);
|
|
|
|
//
|
|
result = ArraySize(guards);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
typedef void (*TOnX121SMCSignal)(
|
|
XSignal &signal,
|
|
X121SMCStrategyConditions &conditions //
|
|
);
|
|
|
|
//
|
|
// Extentions ...
|
|
|
|
/**
|
|
* Validate a Signal Provider ...
|
|
*
|
|
* @param value: ENUM_X_121_SMC_PROVIDERS member ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsValid(ENUM_X_121_SMC_PROVIDERS value)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = value != X_121_SMC_PROVIDER_NONE;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts a Signal Provider to String ...
|
|
*
|
|
* @param value: ENUM_X_121_SMC_PROVIDERS member ...
|
|
*
|
|
* @return ( string )
|
|
*/
|
|
string ToString(ENUM_X_121_SMC_PROVIDERS value)
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
if (!IsValid(value))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
switch (value)
|
|
{
|
|
//
|
|
case X_121_SMC_PROVIDER_X:
|
|
result = X121SMCXToken;
|
|
break;
|
|
|
|
//
|
|
case X_121_SMC_PROVIDER_XOBS:
|
|
result = X121SMCXOBSToken;
|
|
break;
|
|
|
|
//
|
|
case X_121_SMC_PROVIDER_XHKPV:
|
|
result = X121SMCXHKPVToken;
|
|
break;
|
|
|
|
//
|
|
case X_121_SMC_PROVIDER_XOBPV:
|
|
result = X121SMCXOBPVToken;
|
|
break;
|
|
|
|
//
|
|
case X_121_SMC_PROVIDER_XIOBPV:
|
|
result = X121SMCXIOBPVToken;
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Parse Specified String as a Signal Provider ...
|
|
*
|
|
* @param value: String ...
|
|
*
|
|
* @return ( ENUM_X_121_SMC_PROVIDERS )
|
|
*/
|
|
ENUM_X_121_SMC_PROVIDERS ParseProvider(string value)
|
|
{
|
|
//
|
|
ENUM_X_121_SMC_PROVIDERS result = X_121_SMC_PROVIDER_NONE;
|
|
|
|
//
|
|
if (!IsValid(value))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (Contains(X121SMCXToken, value))
|
|
{
|
|
result = X_121_SMC_PROVIDER_X;
|
|
}
|
|
else if (Contains(X121SMCXOBSToken, value))
|
|
{
|
|
result = X_121_SMC_PROVIDER_XOBS;
|
|
}
|
|
else if (Contains(X121SMCXHKPVToken, value))
|
|
{
|
|
result = X_121_SMC_PROVIDER_XHKPV;
|
|
}
|
|
else if (Contains(X121SMCXOBPVToken, value))
|
|
{
|
|
result = X_121_SMC_PROVIDER_XOBPV;
|
|
}
|
|
else if (Contains(X121SMCXIOBPVToken, value))
|
|
{
|
|
result = X_121_SMC_PROVIDER_XIOBPV;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
// |