1401 lines
28 KiB
Plaintext
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;
|
|
}
|
|
|
|
// |