642 lines
12 KiB
Plaintext
642 lines
12 KiB
Plaintext
// //
|
|
// // Detect At lease Two PEAK and Two Vale ...
|
|
// XZigZagPoint tmpPoints[];
|
|
// Copy(
|
|
// points,
|
|
// tmpPoints //
|
|
// );
|
|
|
|
// //
|
|
// // Detect Highs ...
|
|
|
|
// //
|
|
// // Highest High ...
|
|
|
|
// //
|
|
// XZigZagPoint iZGPeak1;
|
|
// XZigZagPoint iZGPeak2;
|
|
|
|
// //
|
|
// // First ...
|
|
// int idx = GetHighest(
|
|
// tmpPoints,
|
|
// X_ZIGZAG_POINT_TYPE_PEAK //
|
|
// );
|
|
// result = IsValidIndex(idx);
|
|
// if (!result)
|
|
// {
|
|
// //
|
|
// Clean();
|
|
// iZGPeak1.Clean();
|
|
// iZGPeak2.Clean();
|
|
// SpecifiedClean(tmpPoints);
|
|
|
|
// //
|
|
// return result;
|
|
// }
|
|
// iZGPeak1 = tmpPoints[idx];
|
|
// ArrayRemove(
|
|
// tmpPoints,
|
|
// idx,
|
|
// 1 //
|
|
// );
|
|
|
|
// //
|
|
// // Second ...
|
|
// idx = GetHighest(
|
|
// tmpPoints,
|
|
// X_ZIGZAG_POINT_TYPE_PEAK //
|
|
// );
|
|
// result = IsValidIndex(idx);
|
|
// if (!result)
|
|
// {
|
|
// //
|
|
// Clean();
|
|
// iZGPeak1.Clean();
|
|
// iZGPeak2.Clean();
|
|
// SpecifiedClean(tmpPoints);
|
|
|
|
// //
|
|
// return result;
|
|
// }
|
|
// iZGPeak2 = tmpPoints[idx];
|
|
// ArrayRemove(
|
|
// tmpPoints,
|
|
// idx,
|
|
// 1 //
|
|
// );
|
|
|
|
// //
|
|
// // Detect Lows ...
|
|
|
|
// //
|
|
// XZigZagPoint iZGVale1;
|
|
// XZigZagPoint iZGVale2;
|
|
|
|
// //
|
|
// // First ...
|
|
// idx = GetLowest(
|
|
// tmpPoints,
|
|
// X_ZIGZAG_POINT_TYPE_VALE //
|
|
// );
|
|
// result = IsValidIndex(idx);
|
|
// if (!result)
|
|
// {
|
|
// //
|
|
// Clean();
|
|
// iZGPeak1.Clean();
|
|
// iZGPeak2.Clean();
|
|
// iZGVale1.Clean();
|
|
// iZGVale2.Clean();
|
|
// SpecifiedClean(tmpPoints);
|
|
|
|
// //
|
|
// return result;
|
|
// }
|
|
// iZGVale1 = tmpPoints[idx];
|
|
// ArrayRemove(
|
|
// tmpPoints,
|
|
// idx,
|
|
// 1 //
|
|
// );
|
|
|
|
// //
|
|
// // Second ...
|
|
// idx = GetLowest(
|
|
// tmpPoints,
|
|
// X_ZIGZAG_POINT_TYPE_VALE //
|
|
// );
|
|
// result = IsValidIndex(idx);
|
|
// if (!result)
|
|
// {
|
|
// //
|
|
// Clean();
|
|
// iZGPeak1.Clean();
|
|
// iZGPeak2.Clean();
|
|
// iZGVale1.Clean();
|
|
// iZGVale2.Clean();
|
|
// SpecifiedClean(tmpPoints);
|
|
|
|
// //
|
|
// return result;
|
|
// }
|
|
// iZGVale2 = tmpPoints[idx];
|
|
// ArrayRemove(
|
|
// tmpPoints,
|
|
// idx,
|
|
// 1 //
|
|
// );
|
|
|
|
// //
|
|
// // Check Directions ...
|
|
// bool isBullish =
|
|
// //
|
|
// (iZGPeak1.time > iZGPeak2.time &&
|
|
// iZGVale1.time < iZGVale2.time)
|
|
// //
|
|
// ;
|
|
// bool isBearish =
|
|
// //
|
|
// (iZGPeak1.time < iZGPeak2.time &&
|
|
// iZGVale1.time > iZGVale2.time)
|
|
// //
|
|
// ;
|
|
// result =
|
|
// (isBullish && !isBearish) ||
|
|
// (isBearish && !isBullish);
|
|
// if (!result)
|
|
// {
|
|
// //
|
|
// Clean();
|
|
// iZGPeak1.Clean();
|
|
// iZGPeak2.Clean();
|
|
// iZGVale1.Clean();
|
|
// iZGVale2.Clean();
|
|
// SpecifiedClean(tmpPoints);
|
|
|
|
// //
|
|
// return result;
|
|
// }
|
|
|
|
// //
|
|
// // Setting Direction ...
|
|
// dir =
|
|
// isBullish
|
|
// ? X_DIRECTION_BULLISH
|
|
// : isBearish
|
|
// ? X_DIRECTION_BEARISH
|
|
// : X_DIRECTION_NONE;
|
|
|
|
// //
|
|
// // Setting Points ...
|
|
// Copy(
|
|
// points,
|
|
// pivots //
|
|
// );
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
// iZGPeak1.Clean();
|
|
// iZGPeak2.Clean();
|
|
// iZGVale1.Clean();
|
|
// iZGVale2.Clean();
|
|
// SpecifiedClean(tmpPoints);
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
//
|
|
// AssignSymbol and Period ...
|
|
time = bar.time;
|
|
symbol = bar.symbol;
|
|
period = bar.period;
|
|
Copy(_pivots, pivots);
|
|
|
|
//
|
|
// Calculate Peaks and Vales Regressions ...
|
|
|
|
//
|
|
// Peaks Processing ...
|
|
double mPeak = 0;
|
|
double bPeak = 0;
|
|
result = ValidateZigZagPivots(
|
|
mPeak,
|
|
bPeak,
|
|
_pivots,
|
|
X_ZIGZAG_PIVOT_TYPE_PEAK //
|
|
);
|
|
|
|
//
|
|
// Vales Processing ...
|
|
double mVale = 0;
|
|
double bVale = 0;
|
|
result =
|
|
result &&
|
|
ValidateZigZagPivots(
|
|
mVale,
|
|
bVale,
|
|
_pivots,
|
|
X_ZIGZAG_PIVOT_TYPE_VALE //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
Clean();
|
|
// SpecifiedClean(recentPeaks);
|
|
// SpecifiedClean(recentVales);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
// //
|
|
// // Extracting Pivots ...
|
|
// int numberOfPivots = 2;
|
|
|
|
// //
|
|
// // Reading Recent Peaks ...
|
|
// XZigZagPivot recentPeaks[];
|
|
// int recentPeaksCount = GetRecent(
|
|
// _pivots,
|
|
// recentPeaks,
|
|
// numberOfPivots,
|
|
// X_ZIGZAG_PIVOT_TYPE_PEAK //
|
|
// );
|
|
|
|
// //
|
|
// // Reading Recent Vales ...
|
|
// XZigZagPivot recentVales[];
|
|
// int recentValesCount = GetRecent(
|
|
// _pivots,
|
|
// recentVales,
|
|
// numberOfPivots,
|
|
// X_ZIGZAG_PIVOT_TYPE_VALE //
|
|
// );
|
|
|
|
// //
|
|
// // Validate Pivots ...
|
|
// result =
|
|
// recentPeaksCount >= numberOfPivots &&
|
|
// recentValesCount >= numberOfPivots;
|
|
// if (!result)
|
|
// {
|
|
// //
|
|
// Clean();
|
|
// SpecifiedClean(recentPeaks);
|
|
// SpecifiedClean(recentVales);
|
|
|
|
// //
|
|
// return result;
|
|
// }
|
|
|
|
// //
|
|
// // Detect Direction ...
|
|
|
|
// //
|
|
// int zIdx = 0;
|
|
// int pIdx = numberOfPivots - 1;
|
|
|
|
// //
|
|
// bool isBullish =
|
|
// recentPeaks[zIdx].value > recentPeaks[pIdx].value &&
|
|
// recentVales[zIdx].value > recentVales[pIdx].value;
|
|
|
|
// //
|
|
// bool isBearish =
|
|
// recentPeaks[zIdx].value < recentPeaks[pIdx].value &&
|
|
// recentVales[zIdx].value < recentVales[pIdx].value;
|
|
|
|
// //
|
|
// result = isBullish || isBearish;
|
|
// if (!result)
|
|
// {
|
|
// //
|
|
// Clean();
|
|
// SpecifiedClean(recentPeaks);
|
|
// SpecifiedClean(recentVales);
|
|
|
|
// //
|
|
// return result;
|
|
// }
|
|
|
|
// //
|
|
// dir =
|
|
// isBullish
|
|
// ? X_DIRECTION_BULLISH
|
|
// : X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
// Calculate Support and Resistance ...
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// SpecifiedClean(recentPeaks);
|
|
// SpecifiedClean(recentVales);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool ValidateZigZagPivots(
|
|
double &_pivot,
|
|
double &_processed,
|
|
XZigZagPivot &_pivots[],
|
|
ENUM_X_ZIGZAG_POINT_TYPE _type //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
_pivot = 0;
|
|
_processed = 0;
|
|
|
|
//
|
|
// Validate ...
|
|
result = HasChild(_pivots);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Define Required Variables for Calculations ...
|
|
double sumT = 0;
|
|
double sumP = 0;
|
|
double sumTP = 0;
|
|
double sumT2 = 0;
|
|
bool has = false;
|
|
int typeCount = 0;
|
|
|
|
//
|
|
// Loop Through Pivots to Calculate Specified
|
|
// Type Pivots Summaries ...
|
|
int count = ArraySize(_pivots);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
// Check Type Passed ...
|
|
has =
|
|
!IsXValid(_type)
|
|
? true
|
|
: _type == _pivots[i].type;
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
typeCount++;
|
|
double iP = _pivots[i].value;
|
|
double iT = (double)_pivots[i].time;
|
|
|
|
//
|
|
sumT += iT;
|
|
sumP += iP;
|
|
sumTP += iT * iP;
|
|
sumT2 += iT * iP;
|
|
}
|
|
|
|
//
|
|
// Calculate Process Values ...
|
|
double denominator = typeCount * sumT2 - sumT * sumT;
|
|
if (denominator != 0)
|
|
{
|
|
//
|
|
_pivot = (typeCount * sumTP - sumT * sumP) / denominator;
|
|
_processed = (sumP - _pivot * sumT) / typeCount;
|
|
}
|
|
else
|
|
{
|
|
_processed = sumP / typeCount;
|
|
}
|
|
|
|
//
|
|
// Validating Result ...
|
|
result = _pivot > 0 &&
|
|
_processed > 0;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* 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_ZIGZAG_PIVOT_TYPE_PEAK);
|
|
int oldestValeIdx = GetOldest(pivots, X_ZIGZAG_PIVOT_TYPE_VALE);
|
|
int youngestPeakIdx = GetYoungest(pivots, X_ZIGZAG_PIVOT_TYPE_PEAK);
|
|
int youngestValeIdx = GetYoungest(pivots, X_ZIGZAG_PIVOT_TYPE_VALE);
|
|
|
|
//
|
|
// Calculate Peaks and Vales Regressions ...
|
|
|
|
//
|
|
// Peaks Processing ...
|
|
double mPeak = 0;
|
|
double bPeak = 0;
|
|
bool hasPeak = ValidateZigZagPivots(
|
|
mPeak,
|
|
bPeak,
|
|
pivots,
|
|
X_ZIGZAG_PIVOT_TYPE_PEAK //
|
|
);
|
|
|
|
//
|
|
// Vales Processing ...
|
|
double mVale = 0;
|
|
double bVale = 0;
|
|
bool hasVale = ValidateZigZagPivots(
|
|
mVale,
|
|
bVale,
|
|
pivots,
|
|
X_ZIGZAG_PIVOT_TYPE_VALE //
|
|
);
|
|
|
|
//
|
|
// Validate Calculated requirements ...
|
|
result =
|
|
(hasPeak || hasVale) &&
|
|
(IsValidIndex(oldestPeakIdx) &&
|
|
IsValidIndex(oldestValeIdx) &&
|
|
IsValidIndex(youngestPeakIdx) &&
|
|
IsValidIndex(youngestValeIdx));
|
|
if (!result)
|
|
{
|
|
//
|
|
Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculating Values ...
|
|
|
|
//
|
|
peakToTime = pivots[youngestPeakIdx].time;
|
|
peakFromTime = pivots[oldestPeakIdx].time;
|
|
|
|
//
|
|
valeToTime = pivots[youngestValeIdx].time;
|
|
valeFromTime = pivots[oldestValeIdx].time;
|
|
|
|
//
|
|
// Check Different Senarios ...
|
|
// 1-Valid Peak and Valid Vale Exists ...
|
|
if (hasPeak && hasVale)
|
|
{
|
|
//
|
|
// When Slopes Have same Sign, Use Average Slope for Parallel Lines ...
|
|
if (mPeak * mVale > 0)
|
|
{
|
|
//
|
|
// Calculating Parallel Slopes ...
|
|
double slopeParallel = (mPeak + mVale) / 2;
|
|
double bParallelPeak = pivots[youngestPeakIdx].value - slopeParallel * (double)peakToTime;
|
|
double bParallelVale = pivots[youngestValeIdx].value - slopeParallel * (double)valeToTime;
|
|
|
|
//
|
|
// Peak ...
|
|
peakTo = slopeParallel * (double)peakToTime + bParallelPeak;
|
|
peakFrom = slopeParallel * (double)peakFromTime + bParallelPeak;
|
|
|
|
//
|
|
// Vale ...
|
|
valeTo = slopeParallel * (double)valeToTime + bParallelVale;
|
|
valeFrom = slopeParallel * (double)valeFromTime + bParallelVale;
|
|
}
|
|
else
|
|
//
|
|
// separate trendlines if slopes differ ...
|
|
{
|
|
//
|
|
// Peak ...
|
|
peakTo = mPeak * (double)peakToTime + bPeak;
|
|
peakFrom = mPeak * (double)peakFromTime + bPeak;
|
|
|
|
//
|
|
// Vale ...
|
|
valeTo = mVale * (double)valeToTime + bVale;
|
|
valeFrom = mVale * (double)valeFromTime + bVale;
|
|
}
|
|
}
|
|
else
|
|
//
|
|
// Only one of them Exists ...
|
|
{
|
|
//
|
|
// Valid Peak ...
|
|
if (hasPeak)
|
|
{
|
|
//
|
|
// Peak ...
|
|
peakTo = mPeak * (double)peakToTime + bPeak;
|
|
peakFrom = mPeak * (double)peakFromTime + bPeak;
|
|
}
|
|
|
|
//
|
|
// Valid Vale ...
|
|
if (hasVale)
|
|
{
|
|
//
|
|
// Vale ...
|
|
valeTo = mVale * (double)valeToTime + bVale;
|
|
valeFrom = mVale * (double)valeFromTime + bVale;
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|