Files
MQL5Data/XFIMAEA/Libraries/x-saherelm.xfima.lib.mq5
T

1401 lines
28 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Library
// -------------------------------------------------
// Name: XCXFIMAEALib ...
// Description: XFIMAEA Library ...
//
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
//
// Global Properties ...
#property library
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://saherelm.ir"
#property version "1.00"
#property description "SaherElm XFIMAEA Library"
#property strict
//
// Imports ...
#include "../../Classes/x-saherelm.x-cobject.class.mq5"
#include "../../Helpers/x-saherelm.xfima.helper.mq5"
//
// Definitions ...
//
// Enumerations ...
//
// Point Type ...
//
// Structs ...
/**
* Specified ZigZag based Market Analysis ...
**/
struct XFIMAAnalysis
{
//
// Props ...
string symbol; // Symbol ...
datetime time; // Time ...
ENUM_TIMEFRAMES period; // Period ...
XZigZagPivot pivots[]; // ZigZag Pivots ...
//
// Calculated Values ...
double peakTo; // Recent Peak ..
double valeTo; // Recent Vale ...
double peakFrom; // Previous Peak ...
double valeFrom; // Previous Vale ...
double peakSlope; // Calculated Slope for Peak ...
double valeSlope; // Calculated Slope for Vale ...
datetime peakToTime; // Recent Peak Time ...
datetime valeToTime; // Recent Vale Time ...
double peakIntercept; // Calculated Intercept for Peak ...
double valeIntercept; // Calculated Intercept for Vale ...
ENUM_X_DIRECTION dir; // Direction ...
datetime peakFromTime; // Previous Peak Time ...
datetime valeFromTime; // Previous Vale Time ...
//
// Constructor ...
XZigZagAnalysis()
{
Clean();
}
//
// Initialize ...
/**
* Analyse Market Structure ...
*
* @param bar: XOHCL, Specified Bar ...
* @param _pivots: XZigZagPivot, Specified ZigZag Points Collection ...
*
* @return ( bool )
*/
bool Analyse(
XOHCL &bar,
XZigZagPivot &_pivots[] //
)
{
//
bool result = false;
//
// Validate ...
result = bar.IsValid() &&
HasChild(_pivots) &&
bar.symbol == _pivots[0].symbol;
if (!result)
{
//
Clean();
return result;
}
//
// Assign Requirements ...
//
time = bar.time;
symbol = bar.symbol;
period = bar.period;
Copy(_pivots, pivots);
//
int oldestPeakIdx = GetOldest(pivots, X_PIVOT_TYPE_PEAK);
int oldestValeIdx = GetOldest(pivots, X_ZIGZAG_PIVOT_TYPE_VALE);
int youngestPeakIdx = GetYoungest(pivots, X_PIVOT_TYPE_PEAK);
int youngestValeIdx = GetYoungest(pivots, X_ZIGZAG_PIVOT_TYPE_VALE);
//
// Calculate Peaks and Vales Regressions ...
//
// Peak Time ...
peakToTime = pivots[youngestPeakIdx].time;
peakFromTime = pivots[oldestPeakIdx].time;
//
// Vale Time ...
valeToTime = pivots[youngestValeIdx].time;
valeFromTime = pivots[oldestValeIdx].time;
//
// Validating Calculated Peaks and Vales Times ...
result =
(IsSpecifiedValid(valeToTime) &&
IsSpecifiedValid(valeFromTime)) ||
(IsSpecifiedValid(peakToTime) &&
IsSpecifiedValid(peakFromTime));
if (!result)
{
//
Clean();
return result;
}
//
// Calculate Slope and Intercepts ...
//
// Peaks ...
result = CalculateZigZagLinearRegression(
peakSlope,
peakIntercept,
pivots,
X_PIVOT_TYPE_PEAK //
);
if (!result)
{
//
Clean();
return result;
}
//
// Vales ...
result = CalculateZigZagLinearRegression(
valeSlope,
valeIntercept,
pivots,
X_ZIGZAG_PIVOT_TYPE_VALE //
);
if (!result)
{
//
Clean();
return result;
}
//
// Calculate Peaks and Vales ...
//
// Peaks ...
//
int iPeakToIDX = GetBarIndex(
symbol,
period,
peakToTime //
);
if (IsValidIndex(iPeakToIDX))
{
//
peakTo = CalculateValueBySlopeIntercept(
peakSlope,
peakIntercept,
iPeakToIDX //
);
}
//
int iPeakFromIDX = GetBarIndex(
symbol,
period,
peakFromTime //
);
if (IsValidIndex(iPeakFromIDX))
{
//
peakFrom = CalculateValueBySlopeIntercept(
peakSlope,
peakIntercept,
iPeakFromIDX //
);
}
//
// Vales ...
//
int iValeToIDX = GetBarIndex(
symbol,
period,
valeToTime //
);
if (IsValidIndex(iValeToIDX))
{
//
valeTo = CalculateValueBySlopeIntercept(
valeSlope,
valeIntercept,
iValeToIDX //
);
}
//
int iValeFromIDX = GetBarIndex(
symbol,
period,
valeFromTime //
);
if (IsValidIndex(iValeFromIDX))
{
//
valeFrom = CalculateValueBySlopeIntercept(
valeSlope,
valeIntercept,
iValeFromIDX //
);
}
//
// Validating Calculated Peaks and Vales ...
result =
(NotEmpty(valeTo) &&
NotEmpty(valeFrom) > 0) ||
(NotEmpty(peakTo) > 0 &&
NotEmpty(peakFrom) > 0);
if (!result)
{
//
Clean();
return result;
}
//
// Detecting Direction ...
//
bool isBullish =
valeTo > valeFrom ||
(valeTo > valeFrom &&
peakTo > peakFrom);
//
bool isBearish =
peakTo < peakFrom ||
(peakTo < peakFrom &&
valeTo < valeFrom);
//
// Validate When Only One Direction Exists ...
result =
(isBullish && !isBearish) ||
(isBearish && !isBullish);
if (!result)
{
//
Clean();
return result;
}
//
dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
// Calculate Support and Resistance ...
//
// Validate ...
result = IsValid();
if (!result)
{
Clean();
}
//
return result;
}
//
// Tools ...
/**
* Cleanup Model ...
*/
void Clean()
{
//
time = NULL;
symbol = NULL;
period = NULL;
dir = X_DIRECTION_NONE;
SpecifiedClean(pivots);
//
peakTo = 0;
valeTo = 0;
peakFrom = 0;
valeFrom = 0;
peakToTime = NULL;
valeToTime = NULL;
peakFromTime = NULL;
valeFromTime = NULL;
//
ZeroMemory(this);
}
/**
* Validate Model ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
//
HasChild(pivots) &&
HasDirection(dir) &&
IsSpecifiedValid(time) &&
IsSpecifiedValid(symbol) &&
IsSpecifiedValid(period)
//
&&
//
(
//
// Validate Peak ...
(peakTo > 0 &&
peakFrom > 0 &&
peakSlope != EMPTY_VALUE &&
peakIntercept != EMPTY_VALUE &&
IsSpecifiedValid(peakToTime) &&
IsSpecifiedValid(peakFromTime))
//
||
//
// Validate Vale ...
(valeTo > 0 &&
valeFrom > 0 &&
valeSlope != EMPTY_VALUE &&
valeIntercept != EMPTY_VALUE &&
IsSpecifiedValid(valeToTime) &&
IsSpecifiedValid(valeFromTime))
//
)
//
;
//
return result;
}
/**
* Calculate Analysis Age, based on Specified Time Frame ...
*
* @param forPeriod: ENUM_TIMEFRAMES, Specified Period ...
*
* @return ( int )
*/
int GetAge(
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
int result = -1;
//
// Validate ...
if (!IsValid())
{
return result;
}
//
// Normalize ...
if (!IsSpecifiedValid(forPeriod))
{
forPeriod = period;
}
//
result = GetBarIndex(
symbol,
forPeriod,
time //
);
//
return result;
}
/**
* Check Market Direction is Bullish or not ...
*
* @return ( bool )
*/
bool IsBullish()
{
//
bool result = false;
//
result = IsValid() &&
IsSpecifiedBullish(dir);
//
return result;
}
/**
* Check Market Direction is Bearish or not ...
*
* @return ( bool )
*/
bool IsBearish()
{
//
bool result = false;
//
result = IsValid() &&
IsSpecifiedBearish(dir);
//
return result;
}
/**
* Check two item is Same or not ...
*
* @param item: XZigZagAnalysis, dest model for Checking ...
*
* @return ( bool )
*/
bool IsSameAs(XZigZagAnalysis &item)
{
//
bool result = false;
//
result =
IsValid() &&
item.IsValid() &&
time == item.time &&
IsSameMarketAs(item);
//
return result;
}
/**
* Check to model Has Same Symbol ...
*
* @param item: XZigZagAnalysis, dest model for Checking ...
*
* @return ( bool )
*/
bool IsSameSymbolAs(XZigZagAnalysis &item)
{
//
bool result = false;
//
result =
IsValid() &&
item.IsValid() &&
symbol == item.symbol;
//
return result;
}
/**
* Check to model Has Same Period ...
*
* @param item: XZigZagAnalysis, dest model for Checking ...
*
* @return ( bool )
*/
bool IsSamePeriodAs(XZigZagAnalysis &item)
{
//
bool result = false;
//
result =
IsValid() &&
item.IsValid() &&
period == item.period;
//
return result;
}
/**
* Check to model Has Same Symbol/Period ...
*
* @param item: XZigZagAnalysis, dest model for Checking ...
*
* @return ( bool )
*/
bool IsSameMarketAs(XZigZagAnalysis &item)
{
//
bool result = false;
//
result =
IsValid() &&
item.IsValid() &&
IsSameSymbolAs(item) &&
IsSamePeriodAs(item);
//
return result;
}
/**
* Check to model Has Same Direction ...
*
* @param item: XZigZagAnalysis, dest model for Checking ...
*
* @return ( bool )
*/
bool IsSameDirectionAs(XZigZagAnalysis &item)
{
//
bool result = false;
//
result =
IsValid() &&
item.IsValid() &&
dir == item.dir;
//
return result;
}
/**
* Check to model Has Analysis Trend ...
*
* @param item: XZigZagAnalysis, dest model for Checking ...
*
* @return ( bool )
*/
bool IsSameTrendAs(XZigZagAnalysis &item)
{
//
bool result = false;
//
result =
IsValid() &&
item.IsValid() &&
IsSameMarketAs(item) &&
IsSameDirectionAs(item);
//
return result;
}
//
// Pivots Tools ...
/**
* Get Highest Specified Pivot ...
*
* @param type: ENUM_X_PIVOT_TYPE, Specified Pivot Type ...
*
* @return ( int )
*/
int GetHighestPivot(
ENUM_X_PIVOT_TYPE type = X_PIVOT_TYPE_NONE //
)
{
//
int result = -1;
//
if (!IsValid())
{
return result;
}
//
bool has = false;
XZigZagPivot iPivot;
int count = ArraySize(pivots);
for (int i = 0; i < count; i++)
{
//
// Check Type ...
has =
!IsXValid(type) ||
(IsXValid(type) &&
type == pivots[i].type);
if (!has)
{
continue;
}
//
// Check Relation based on last Detected Pivot ...
has = !iPivot.IsValid() ||
(iPivot.IsValid() &&
iPivot.value < pivots[i].value);
if (has)
{
//
result = i;
iPivot = pivots[i];
}
}
//
has =
iPivot.IsValid() &&
IsValidIndex(result);
iPivot.Clean();
//
return result;
}
/**
* Get Lowest Specified Pivot ...
*
* @param type: ENUM_X_PIVOT_TYPE, Specified Pivot Type ...
*
* @return ( int )
*/
int GetLowestPivot(
ENUM_X_PIVOT_TYPE type = X_PIVOT_TYPE_NONE //
)
{
//
int result = -1;
//
if (!IsValid())
{
return result;
}
//
bool has = false;
XZigZagPivot iPivot;
int count = ArraySize(pivots);
for (int i = 0; i < count; i++)
{
//
// Check Type ...
has =
!IsXValid(type) ||
(IsXValid(type) &&
type == pivots[i].type);
if (!has)
{
continue;
}
//
// Check Relation based on last Detected Pivot ...
has = !iPivot.IsValid() ||
(iPivot.IsValid() &&
iPivot.value > pivots[i].value);
if (has)
{
//
result = i;
iPivot = pivots[i];
}
}
//
has =
iPivot.IsValid() &&
IsValidIndex(result);
iPivot.Clean();
//
return result;
}
/**
* Get Oldest Specified Pivot ...
*
* @param type: ENUM_X_PIVOT_TYPE, Specified Pivot Type ...
*
* @return ( int )
*/
int GetOldestPivot(
ENUM_X_PIVOT_TYPE type = X_PIVOT_TYPE_NONE //
)
{
//
int result = -1;
//
if (!IsValid())
{
return result;
}
//
bool has = false;
XZigZagPivot iPivot;
int count = ArraySize(pivots);
for (int i = 0; i < count; i++)
{
//
// Check Type ...
has =
!IsXValid(type) ||
(IsXValid(type) &&
type == pivots[i].type);
if (!has)
{
continue;
}
//
// Check Relation based on last Detected Pivot ...
has = !iPivot.IsValid() ||
(iPivot.IsValid() &&
iPivot.time > pivots[i].time);
if (has)
{
//
result = i;
iPivot = pivots[i];
}
}
//
has =
iPivot.IsValid() &&
IsValidIndex(result);
iPivot.Clean();
//
return result;
}
/**
* Get Youngest Specified Pivot ...
*
* @param type: ENUM_X_PIVOT_TYPE, Specified Pivot Type ...
*
* @return ( int )
*/
int GetYoungestPivot(
ENUM_X_PIVOT_TYPE type = X_PIVOT_TYPE_NONE //
)
{
//
int result = -1;
//
// Validate ...
if (!IsValid())
{
return result;
}
//
bool has = false;
XZigZagPivot iPivot;
int count = ArraySize(pivots);
for (int i = 0; i < count; i++)
{
//
// Check Type ...
has =
!IsXValid(type) ||
(IsXValid(type) &&
type == pivots[i].type);
if (!has)
{
continue;
}
//
// Check Relation based on last Detected Pivot ...
has = !iPivot.IsValid() ||
(iPivot.IsValid() &&
iPivot.time > pivots[i].time);
if (has)
{
//
result = i;
iPivot = pivots[i];
}
}
//
has =
iPivot.IsValid() &&
IsValidIndex(result);
iPivot.Clean();
//
return result;
}
/**
* Get Recent Number of Specified Type of Pivots ...
*
* @param recent: XZigZagPivot, Collection reference as result ...
* @param numberOfRequiredPivots: int, required number of Pivots ...
* @param type: ENUM_X_PIVOT_TYPE, type of Pivot ...
*
* @return ( int )
*/
int GetRecentPivots(
XZigZagPivot &recent[],
int numberOfRequiredPivots = 2,
ENUM_X_PIVOT_TYPE type = X_PIVOT_TYPE_NONE //
)
{
//
int result = -1;
//
result = GetRecent(
pivots,
recent,
numberOfRequiredPivots,
type //
);
//
return result;
}
//
// Loggint Tools ...
/**
* Extract Specified Token of Struct ...
*
* @return ( string )
*/
string GetTag()
{
return GetToken(this);
}
/**
* Represent an String Unique Identifier for Chart Objects ...
*
* @return ( string )
*/
string GetObjectID()
{
//
string result = "";
//
if (!IsValid())
{
return result;
}
//
result = GetTag() + "_" + symbol + "_" + ToXString(period) + "_" + ToXString(dir) + "_" + ToXString(TimeToSeconds(time));
//
return result;
}
/**
* Represent a Point as String ...
*
* @param spacer: string, How to Represent Spaces ...
*
* @return ( string )
*/
string GetMessage(string spacer = NULL)
{
//
string result = "";
//
// Normalize Spacer ...
if (!IsSpecifiedValid(spacer))
{
spacer = " ";
}
//
// Validate ...
if (!IsValid())
{
return result;
}
//
result =
ToXString(dir) + spacer + GetTag() + ":" + spacer +
"Symbol: " + symbol + spacer +
"Period: " + ToXString(period) + spacer +
"Direction: " + ToXString(dir) + spacer +
"Time: " + ToXString(time) + spacer;
//
return result;
}
//
};
/**
* XZigZagAnalysis Chart Object ...
**/
class XCZigZagAnalysisObject : public XCBaseObject
{
//
public:
//
/**
* Create Object ...
*
* @param chart_id: Long, Specified Chart ID ...
* @param window: Integer, Specified Chart Window ID ...
* @param model: XZigZagAnalysis, reference model ...
*
* @return ( bool )
*/
bool CreateByRecent(
long chart_id,
int window,
XZigZagAnalysis &model,
int numberOfPivots = 2 //
)
{
//
bool result = false;
//
// Normalize ...
numberOfPivots = NormalizeInt(numberOfPivots, 2);
//
// Validate ...
result = model.IsValid();
if (!result)
{
return result;
}
//
// Generate Object ID ...
string objID = model.GetObjectID();
string upperName = "Upper_" + objID;
string lowerName = "Lower_" + objID;
//
// Extract Recent Pivots ...
//
// Peaks ...
XZigZagPivot rPeaks[];
int count = model.GetRecentPivots(
rPeaks,
numberOfPivots,
X_PIVOT_TYPE_PEAK //
);
//
// Vales ...
XZigZagPivot rVales[];
count = model.GetRecentPivots(
rVales,
numberOfPivots,
X_ZIGZAG_PIVOT_TYPE_VALE //
);
//
// Creating Upper ...
result = mUpper.Create(
chart_id,
upperName,
window,
rPeaks[numberOfPivots - 1].time,
rPeaks[numberOfPivots - 1].value,
rPeaks[0].time,
rPeaks[0].value //
);
if (!result)
{
return result;
}
//
// Create Lower ...
result = mLower.Create(
chart_id,
lowerName,
window,
rVales[numberOfPivots - 1].time,
rVales[numberOfPivots - 1].value,
rVales[0].time,
rVales[0].value //
);
if (!result)
{
//
mUpper.Detach();
mUpper.Delete();
//
return result;
}
//
// Setting Object Name ...
if (result)
{
ObjName(objID);
}
//
return result;
}
/**
* Create Object ...
*
* @param chart_id: Long, Specified Chart ID ...
* @param window: Integer, Specified Chart Window ID ...
* @param model: XZigZagAnalysis, reference model ...
*
* @return ( bool )
*/
bool CreateByPV(
long chart_id,
int window,
XZigZagAnalysis &model //
)
{
//
bool result = false;
//
// Validate ...
result = model.IsValid();
if (!result)
{
return result;
}
//
// Generate Object ID ...
string objID = model.GetObjectID();
string upperName = "Upper_" + objID;
string lowerName = "Lower_" + objID;
//
// Extract Recent Pivots ...
//
// Creating Upper ...
result = mUpper.Create(
chart_id,
upperName,
window,
model.peakFromTime,
model.peakFrom,
model.peakToTime,
model.peakTo //
);
if (!result)
{
return result;
}
//
// Create Lower ...
result = mLower.Create(
chart_id,
lowerName,
window,
model.valeFromTime,
model.valeFrom,
model.valeToTime,
model.valeTo //
);
if (!result)
{
//
mUpper.Detach();
mUpper.Delete();
//
return result;
}
//
// Setting Object Name ...
if (result)
{
ObjName(objID);
}
//
return result;
}
//
// Virtuals ...
/**
* Retrieve Object Type ...
*
* @return ( ENUM_XCHARTOBJECTS )
*/
virtual int Type()
{
return 9860;
}
//
// Styling ...
/**
* Set Width ...
*
* @param value: Integer ...
*/
void UpperWidth(int value)
{
//
if (value < 1)
{
value = 1;
}
//
mUpper.Width(value);
}
/**
* Set Color ...
*
* @param value: Color ...
*/
void UpperColor(color value)
{
//
mUpper.Color(value);
}
/**
* Set Style ...
*
* @param value: ENUM_LINE_STYLE member ...
*/
void UpperStyle(ENUM_LINE_STYLE value)
{
//
mUpper.Style(value);
}
/**
* Specified Upper Ray to Left or not ...
*
* @param value: bool
*/
void UpperRayLeft(bool value)
{
mUpper.RayLeft(value);
}
/**
* Specified Upper Ray to Right or not ...
*
* @param value: bool
*/
void UpperRayRight(bool value)
{
mUpper.RayRight(value);
}
/**
* Set Width ...
*
* @param value: Integer ...
*/
void LowerWidth(int value)
{
//
if (value < 1)
{
value = 1;
}
//
mLower.Width(value);
}
/**
* Set Color ...
*
* @param value: Color ...
*/
void LowerColor(color value)
{
//
mLower.Color(value);
}
/**
* Set Style ...
*
* @param value: ENUM_LINE_STYLE member ...
*/
void LowerStyle(ENUM_LINE_STYLE value)
{
//
mLower.Style(value);
}
/**
* Specified Lower Ray to Left or not ...
*
* @param value: bool
*/
void LowerRayLeft(bool value)
{
mLower.RayLeft(value);
}
/**
* Specified Lower Ray to Right or not ...
*
* @param value: bool
*/
void LowerRayRight(bool value)
{
mLower.RayRight(value);
}
//
private:
//
CChartObjectTrend mUpper;
CChartObjectTrend mLower;
};
//
// Extensions ...
bool CalculateZigZagLinearRegression(
double &_slope,
double &_intercept,
XZigZagPivot &_pivots[],
ENUM_X_PIVOT_TYPE _type //
)
{
//
bool result = false;
//
// Prepare ...
_slope = EMPTY_VALUE;
_intercept = EMPTY_VALUE;
//
// Validate ...
result =
IsXValid(_type) &&
HasChild(_pivots);
if (!result)
{
return result;
}
//
// Extracted Type Specific Valus ...
double values[];
XZigZagPivot tmp[];
XZigZagPivot iPivot;
Copy(
_pivots,
tmp //
);
int count = ArraySize(tmp);
while (HasChild(tmp))
{
//
// Get Model ...
iPivot = tmp[0];
//
// Remove Model ...
ArrayRemove(
tmp,
0,
1 //
);
//
// Validate Type ...
result = _type == iPivot.type;
if (result)
{
//
// Add Value if Type Passed ...
Add(
iPivot.value,
values //
);
}
//
iPivot.Clean();
}
//
// Validation Valus ...
result = HasChild(values);
if (result)
{
//
// Calculate Slope / Intercept ...
result = CalculateLinearRegression(
_slope,
_intercept,
values //
);
}
//
// Validate Result ...
result =
_slope != EMPTY_VALUE &&
_intercept != EMPTY_VALUE;
if (!result)
{
//
_slope = EMPTY_VALUE;
_intercept = EMPTY_VALUE;
}
//
// Cleanup Resources ...
iPivot.Clean();
SpecifiedClean(tmp);
SpecifiedClean(values);
//
return result;
}
//