Last Works ...
This commit is contained in:
@@ -22,9 +22,9 @@
|
||||
//
|
||||
// Imports ...
|
||||
#include "../../Classes/x-saherelm.base.class.mq5"
|
||||
#include "../../Helpers/x-saherelm.xpv.helper.mq5"
|
||||
#include "../../Helpers/x-saherelm.x3ma.helper.mq5"
|
||||
#include "../../Helpers/x-saherelm.x3vwap.helper.mq5"
|
||||
#include "../../Helpers/x-saherelm.xpv.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"
|
||||
@@ -34,6 +34,339 @@
|
||||
|
||||
const string X121SMCStrategyToken = "X121SMC";
|
||||
|
||||
enum ENUM_XPV_PIVOTS
|
||||
{
|
||||
XPV_NONE,
|
||||
XPV_PEAK,
|
||||
XPV_VALE,
|
||||
};
|
||||
|
||||
struct XPVPivot
|
||||
{
|
||||
//
|
||||
string symbol;
|
||||
ENUM_TIMEFRAMES period;
|
||||
|
||||
//
|
||||
double upper;
|
||||
double lower;
|
||||
|
||||
//
|
||||
datetime from;
|
||||
datetime to;
|
||||
|
||||
//
|
||||
int repetition;
|
||||
|
||||
//
|
||||
ENUM_XPV_PIVOTS type;
|
||||
|
||||
//
|
||||
XPVPivot()
|
||||
{
|
||||
Clean();
|
||||
}
|
||||
|
||||
//
|
||||
// Tools ...
|
||||
|
||||
/**
|
||||
* Cleanup ...
|
||||
*/
|
||||
void Clean()
|
||||
{
|
||||
//
|
||||
upper = 0;
|
||||
lower = 0;
|
||||
|
||||
//
|
||||
to = NULL;
|
||||
from = NULL;
|
||||
symbol = NULL;
|
||||
period = NULL;
|
||||
|
||||
//
|
||||
repetition = 0;
|
||||
|
||||
//
|
||||
type = XPV_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validation ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool IsValid()
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result =
|
||||
//
|
||||
IsValid(to) &&
|
||||
IsValid(from) &&
|
||||
IsValid(symbol) &&
|
||||
IsValid(period) &&
|
||||
repetition > 0 &&
|
||||
type != XPV_NONE &&
|
||||
(upper > 0 || lower > 0)
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Pivot is Peak ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool IsPeak()
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result = IsValid() &&
|
||||
type == XPV_PEAK;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Pivot is Vale ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool IsVale()
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result = IsValid() &&
|
||||
type == XPV_VALE;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate Lower for Peaks ...
|
||||
*
|
||||
* @return ( double )
|
||||
*/
|
||||
double CalculateLower()
|
||||
{
|
||||
//
|
||||
double result = 0;
|
||||
|
||||
//
|
||||
if (!IsValid() ||
|
||||
!IsPeak())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
int fromIndex = iBarShift(
|
||||
symbol,
|
||||
period,
|
||||
from //
|
||||
);
|
||||
|
||||
//
|
||||
int toIndex = iBarShift(
|
||||
symbol,
|
||||
period,
|
||||
to //
|
||||
);
|
||||
|
||||
//
|
||||
int count =
|
||||
fromIndex - toIndex;
|
||||
|
||||
//
|
||||
int llIDX = iLowest(
|
||||
symbol,
|
||||
period,
|
||||
MODE_LOW,
|
||||
count,
|
||||
toIndex //
|
||||
);
|
||||
|
||||
//
|
||||
result =
|
||||
iLow(
|
||||
symbol,
|
||||
period,
|
||||
llIDX //
|
||||
);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate Upper for Vales ...
|
||||
*
|
||||
* @return ( double )
|
||||
*/
|
||||
double CalculateUpper()
|
||||
{
|
||||
//
|
||||
double result = 0;
|
||||
|
||||
//
|
||||
if (!IsValid() ||
|
||||
!IsVale())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
int fromIndex = iBarShift(
|
||||
symbol,
|
||||
period,
|
||||
from //
|
||||
);
|
||||
|
||||
//
|
||||
int toIndex = iBarShift(
|
||||
symbol,
|
||||
period,
|
||||
to //
|
||||
);
|
||||
|
||||
//
|
||||
int count =
|
||||
fromIndex - toIndex;
|
||||
|
||||
//
|
||||
int hhIDX = iHighest(
|
||||
symbol,
|
||||
period,
|
||||
MODE_HIGH,
|
||||
count,
|
||||
toIndex //
|
||||
);
|
||||
|
||||
//
|
||||
result =
|
||||
iHigh(
|
||||
symbol,
|
||||
period,
|
||||
hhIDX //
|
||||
);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate Range of Pivot ...
|
||||
*
|
||||
* @return ( double )
|
||||
*/
|
||||
double CalculateRange()
|
||||
{
|
||||
//
|
||||
double result = 0;
|
||||
|
||||
//
|
||||
if (!IsValid() ||
|
||||
upper <= 0 ||
|
||||
lower <= 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result = upper - lower;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate Middle of Pivot ...
|
||||
* Used for
|
||||
* @return ( double )
|
||||
*/
|
||||
double CalculateMid()
|
||||
{
|
||||
//
|
||||
double result = 0;
|
||||
|
||||
//
|
||||
double range = CalculateRange();
|
||||
if (range <= 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result = lower + (range / 2);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
/**
|
||||
* Get Unique Identifier ...
|
||||
*
|
||||
* @return ( string )
|
||||
*/
|
||||
string GetTag()
|
||||
{
|
||||
//
|
||||
string result = NULL;
|
||||
|
||||
//
|
||||
if (!IsValid())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
string hash = symbol + "_" +
|
||||
ToString(period) + "_" +
|
||||
ToString(upper) + "," +
|
||||
ToString(lower) + "_" +
|
||||
ToString(from) + "," +
|
||||
ToString(to);
|
||||
hash = ToMD5(hash);
|
||||
|
||||
//
|
||||
string typeStr =
|
||||
type == XPV_PEAK
|
||||
? "Peak"
|
||||
: "Vale";
|
||||
|
||||
//
|
||||
result =
|
||||
//
|
||||
"XPV_" +
|
||||
typeStr + "_" +
|
||||
symbol + "_" +
|
||||
ToString(period) +
|
||||
"_" + hash
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
};
|
||||
|
||||
//
|
||||
// Model Signalling Conditions ...
|
||||
struct X121SMCStrategyConditions
|
||||
@@ -43,6 +376,9 @@ struct X121SMCStrategyConditions
|
||||
ENUM_TIMEFRAMES period;
|
||||
datetime time;
|
||||
|
||||
//
|
||||
XPVPivot orderFlow[];
|
||||
|
||||
//
|
||||
XPVConditions xpvConditions;
|
||||
X3MAConditions x3maConditions;
|
||||
@@ -163,6 +499,9 @@ struct X121SMCStrategyConditions
|
||||
x3maConditions.Clean();
|
||||
x3vwapConditions.Clean();
|
||||
|
||||
//
|
||||
Clean(orderFlow);
|
||||
|
||||
//
|
||||
// D1 ...
|
||||
|
||||
@@ -519,4 +858,357 @@ typedef void (*TOnX121SMCSignal)(
|
||||
X121SMCStrategyConditions &conditions //
|
||||
);
|
||||
|
||||
//
|
||||
// Extentions ...
|
||||
|
||||
/**
|
||||
* Find Oldest Pivot Index ...
|
||||
*
|
||||
* @param pivots: XPVPivot instance ...
|
||||
* @return ( int )
|
||||
*/
|
||||
int FindOldestPivotIndex(
|
||||
XPVPivot &pivots[] //
|
||||
)
|
||||
{
|
||||
//
|
||||
int result = -1;
|
||||
|
||||
//
|
||||
int count = ArraySize(pivots);
|
||||
if (!IsValidSize(count))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
//
|
||||
XPVPivot iPivot = pivots[i];
|
||||
|
||||
//
|
||||
bool isOldest = true;
|
||||
for (int j = 0; j < count; j++)
|
||||
{
|
||||
//
|
||||
XPVPivot jPivot = pivots[j];
|
||||
|
||||
//
|
||||
isOldest = iPivot.from <= jPivot.from;
|
||||
if (!isOldest)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
if (isOldest)
|
||||
{
|
||||
//
|
||||
result = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort Pivots Based On From Date ...
|
||||
*
|
||||
* @param pivots: XPVPivot instance Collection reference ...
|
||||
*/
|
||||
void SortPivots(
|
||||
XPVPivot &pivots[] //
|
||||
)
|
||||
{
|
||||
//
|
||||
XPVPivot tmp[];
|
||||
Copy(
|
||||
pivots,
|
||||
tmp //
|
||||
);
|
||||
|
||||
//
|
||||
Clean(pivots);
|
||||
|
||||
//
|
||||
while (ArraySize(tmp) > 0)
|
||||
{
|
||||
//
|
||||
if (ArraySize(tmp) == 1)
|
||||
{
|
||||
//
|
||||
AddRef(
|
||||
tmp[0],
|
||||
pivots //
|
||||
);
|
||||
|
||||
//
|
||||
ArrayRemove(
|
||||
tmp,
|
||||
0,
|
||||
1);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
int idx = FindOldestPivotIndex(tmp);
|
||||
if (IsValidIndex(idx))
|
||||
{
|
||||
//
|
||||
AddRef(
|
||||
tmp[idx],
|
||||
pivots //
|
||||
);
|
||||
|
||||
//
|
||||
ArrayRemove(
|
||||
tmp,
|
||||
idx,
|
||||
1 //
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
Clean(tmp);
|
||||
}
|
||||
|
||||
bool IsPivotBreaked(
|
||||
XPVPivot &pivot,
|
||||
XPVPivot &pivots[] //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result = pivot.IsValid();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
int count = ArraySize(pivots);
|
||||
result = IsValidSize(pivots);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// For Peaks Highs Must not Broked ...
|
||||
// For Vales Lows Must not Broked ...
|
||||
bool isPeak = pivot.IsPeak();
|
||||
|
||||
//
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
//
|
||||
XPVPivot iPivot = pivots[i];
|
||||
|
||||
//
|
||||
result = isPeak
|
||||
? iPivot.upper > pivot.upper
|
||||
: iPivot.lower < pivot.lower;
|
||||
if (result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter Broken Pivots for Detect Order Flow ...
|
||||
*
|
||||
* @param pivots: XPVPivot instance Collection reference ...
|
||||
*/
|
||||
void FilterBrokenPivots(
|
||||
XPVPivot &pivots[] //
|
||||
)
|
||||
{
|
||||
//
|
||||
XPVPivot tmp[];
|
||||
Copy(
|
||||
pivots,
|
||||
tmp //
|
||||
);
|
||||
|
||||
//
|
||||
Clean(pivots);
|
||||
|
||||
//
|
||||
while (ArraySize(tmp) > 0)
|
||||
{
|
||||
//
|
||||
if (ArraySize(tmp) == 1)
|
||||
{
|
||||
//
|
||||
AddRef(
|
||||
tmp[0],
|
||||
pivots //
|
||||
);
|
||||
|
||||
//
|
||||
ArrayRemove(
|
||||
tmp,
|
||||
0,
|
||||
1 //
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
XPVPivot pivot = tmp[0];
|
||||
|
||||
//
|
||||
ArrayRemove(
|
||||
tmp,
|
||||
0,
|
||||
1 //
|
||||
);
|
||||
|
||||
//
|
||||
bool isBreaked = IsPivotBreaked(
|
||||
pivot,
|
||||
tmp //
|
||||
);
|
||||
if (!isBreaked)
|
||||
{
|
||||
//
|
||||
AddRef(
|
||||
pivot,
|
||||
pivots //
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
Clean(tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate Order Flow Direction ...
|
||||
*
|
||||
* @param orderFlow: XPVPivot instance Collection reference ...
|
||||
* @param dir: ENUM_X_DIRECTION member reference, Hold's Calculated Direction ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool DetectPivotDirection(
|
||||
XPVPivot &orderFlow[],
|
||||
ENUM_X_DIRECTION &dir //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
dir = X_DIRECTION_NONE;
|
||||
|
||||
//
|
||||
int count = ArraySize(orderFlow);
|
||||
result = IsValidSize(count);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// For Bullish Direction all Exists lowers must be Greater or Equal Prev ...
|
||||
bool isBullish = false;
|
||||
bool canLookupForBullish = true;
|
||||
|
||||
//
|
||||
// For Bearish Direction all Exists uppers must be Lesser or Equal Prev ...
|
||||
bool isBearish = false;
|
||||
bool canLookupForBearish = true;
|
||||
|
||||
//
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
//
|
||||
XPVPivot iPivot = orderFlow[i];
|
||||
|
||||
//
|
||||
XPVPivot tmp[];
|
||||
Copy(
|
||||
orderFlow,
|
||||
tmp //
|
||||
);
|
||||
ArrayRemove(
|
||||
tmp,
|
||||
0,
|
||||
i + 1 //
|
||||
);
|
||||
|
||||
//
|
||||
int tmpCount = ArraySize(tmp);
|
||||
if (IsValidSize(tmpCount))
|
||||
{
|
||||
//
|
||||
for (int j = 0; j < tmpCount; j++)
|
||||
{
|
||||
//
|
||||
XPVPivot jPivot = tmp[j];
|
||||
|
||||
//
|
||||
// Check Bullish Direction ...
|
||||
isBullish =
|
||||
canLookupForBullish &&
|
||||
jPivot.lower >= iPivot.lower;
|
||||
if (!isBullish)
|
||||
{
|
||||
canLookupForBullish = false;
|
||||
}
|
||||
|
||||
//
|
||||
// Check Bearish Direction ...
|
||||
isBearish =
|
||||
canLookupForBearish &&
|
||||
jPivot.upper <= iPivot.upper;
|
||||
if (!isBearish)
|
||||
{
|
||||
canLookupForBearish = false;
|
||||
}
|
||||
|
||||
//
|
||||
if (!canLookupForBullish &&
|
||||
!canLookupForBearish)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Clean(tmp);
|
||||
}
|
||||
|
||||
//
|
||||
if (isBullish &&
|
||||
!isBearish)
|
||||
{
|
||||
dir = X_DIRECTION_BULLISH;
|
||||
}
|
||||
else if (isBearish &&
|
||||
!isBullish)
|
||||
{
|
||||
dir = X_DIRECTION_BEARISH;
|
||||
}
|
||||
|
||||
//
|
||||
result = dir != X_DIRECTION_NONE;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
Reference in New Issue
Block a user