1927 lines
49 KiB
Plaintext
1927 lines
49 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Indicator
|
|
// -------------------------------------------------
|
|
// Name: XCXCAEAPOIDetector ...
|
|
// Description: Class for XCAEA POI Detector ...
|
|
//
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
|
#property link "https://saherelm.ir"
|
|
#property version "1.00"
|
|
#property description "SaherElm Class for XCAEA POI Detector"
|
|
#property strict
|
|
|
|
//
|
|
// Imports ...
|
|
#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5"
|
|
#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5"
|
|
#include "../Helpers/xcaea.helper.mq5"
|
|
|
|
//
|
|
// Definitions ...
|
|
|
|
//
|
|
enum ENUM_XCA_PIVOTS
|
|
{
|
|
XCA_NONE, // None
|
|
XCA_SWL, // SWL
|
|
XCA_SWH, // SWH
|
|
XCA_VALE, // VALE
|
|
XCA_PEAK, // PEAK
|
|
XCA_KI_BULL, // KIBull
|
|
XCA_KI_BEAR, // KIBear
|
|
XCA_TKI_BULL, // TKIBull
|
|
XCA_TKI_BEAR, // TKIBear
|
|
XCA_PEAKSWHRES, // PeakSWHRes
|
|
XCA_VALESWLSUP, // ValeSWLSup
|
|
XCA_TREND_BULL, // Trend Bullish
|
|
XCA_TREND_BEAR, // Trend Bearish
|
|
};
|
|
|
|
//
|
|
bool IsValid(ENUM_XCA_PIVOTS value)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = value != XCA_NONE;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string ToString(ENUM_XCA_PIVOTS value)
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
result = EnumToString(value);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
struct XCAPivot
|
|
{
|
|
//
|
|
// Props ...
|
|
datetime to;
|
|
double value;
|
|
string symbol;
|
|
datetime from;
|
|
double reserve;
|
|
ENUM_XCA_PIVOTS type;
|
|
ENUM_TIMEFRAMES period;
|
|
|
|
//
|
|
double values[];
|
|
|
|
//
|
|
// Constructor ...
|
|
XCAPivot()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
/**
|
|
* Cleanup ...
|
|
*/
|
|
void Clean()
|
|
{
|
|
//
|
|
value = 0;
|
|
to = NULL;
|
|
reserve = 0;
|
|
from = NULL;
|
|
symbol = NULL;
|
|
period = NULL;
|
|
type = XCA_NONE;
|
|
|
|
//
|
|
Clean(values);
|
|
}
|
|
|
|
/**
|
|
* Validate ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
from < to &&
|
|
value != 0 &&
|
|
IsValid(to) &&
|
|
IsValid(from) &&
|
|
IsValid(type) &&
|
|
IsValid(symbol) &&
|
|
IsValid(period);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Model is Same as this or not ...
|
|
*
|
|
* @param pivot: XCAPivot ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsSameAs(XCAPivot &pivot)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
IsValid() &&
|
|
pivot.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
to == pivot.to &&
|
|
from == pivot.from &&
|
|
type == pivot.type &&
|
|
value == pivot.value &&
|
|
symbol == pivot.symbol &&
|
|
period == pivot.period;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieve To Index ...
|
|
*
|
|
* @param forPeriod: ENUM_TIMEFRAMES, Specified Period ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ToIndex(
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
result = GetBarIndex(
|
|
symbol,
|
|
forPeriod,
|
|
to //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieve From Index ...
|
|
*
|
|
* @param forPeriod: ENUM_TIMEFRAMES, Specified Period ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int FromIndex(
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
result = GetBarIndex(
|
|
symbol,
|
|
forPeriod,
|
|
from //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieve Age of Pivot ...
|
|
*
|
|
* @param forPeriod: ENUM_TIMEFRAMES, Specified Period ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetAge(
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
int toIDX = ToIndex(forPeriod);
|
|
int fromIDX = FromIndex(forPeriod);
|
|
|
|
//
|
|
result = fromIDX - toIDX;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts Pivot to Box ...
|
|
*
|
|
* @param box: XBoxZone instance reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool AsBox(
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
|
|
switch (type)
|
|
{
|
|
//
|
|
case XCA_SWL:
|
|
case XCA_VALE:
|
|
case XCA_KI_BULL:
|
|
case XCA_TKI_BULL:
|
|
case XCA_TREND_BULL:
|
|
case XCA_VALESWLSUP:
|
|
iDir = X_DIRECTION_BULLISH;
|
|
break;
|
|
|
|
//
|
|
case XCA_SWH:
|
|
case XCA_PEAK:
|
|
case XCA_KI_BEAR:
|
|
case XCA_TKI_BEAR:
|
|
case XCA_TREND_BEAR:
|
|
case XCA_PEAKSWHRES:
|
|
iDir = X_DIRECTION_BEARISH;
|
|
break;
|
|
}
|
|
|
|
//
|
|
result = HasDirection(iDir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish =
|
|
IsBullish(iDir) &&
|
|
value < reserve;
|
|
|
|
//
|
|
bool isBearish =
|
|
IsBearish(iDir) &&
|
|
value > reserve;
|
|
|
|
//
|
|
result = isBullish ||
|
|
isBearish;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box.to = to;
|
|
box.dir = iDir;
|
|
box.from = from;
|
|
box.symbol = symbol;
|
|
box.period = period;
|
|
|
|
//
|
|
string typeStr = ToString(type);
|
|
if (type == XCA_KI_BULL ||
|
|
type == XCA_KI_BEAR)
|
|
{
|
|
//
|
|
typeStr = "XCA_KI";
|
|
}
|
|
else if (type == XCA_TKI_BULL ||
|
|
type == XCA_TKI_BEAR)
|
|
{
|
|
//
|
|
typeStr = "XCA_TKI";
|
|
}
|
|
else if (type == XCA_TREND_BULL ||
|
|
type == XCA_TREND_BEAR)
|
|
{
|
|
//
|
|
typeStr = "XCA_TREND";
|
|
}
|
|
box.type = typeStr;
|
|
|
|
//
|
|
box.upper =
|
|
isBullish
|
|
? reserve
|
|
: value;
|
|
box.lower =
|
|
isBullish
|
|
? value
|
|
: reserve;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
box.Clean();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
/**
|
|
* Find Specified Pivot Index inside a Collection of Pivots ...
|
|
*
|
|
* @param pivot: XCAPivot instance Reference ...
|
|
* @param pivots: XCAPivot instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
bool FindPivotIndex(
|
|
int &index,
|
|
XCAPivot &pivot,
|
|
XCAPivot &pivots[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
index = -1;
|
|
|
|
//
|
|
int count = ArraySize(pivots);
|
|
result = pivot.IsValid() &&
|
|
IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCAPivot iPivot = pivots[i];
|
|
|
|
//
|
|
bool isSame = pivot.IsSameAs(iPivot);
|
|
if (isSame)
|
|
{
|
|
//
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Implementations ...
|
|
class XCXCAEAPOIDetector : public XCBase
|
|
{
|
|
//
|
|
// Public ...
|
|
public:
|
|
//
|
|
// Props ...
|
|
XCAPivot swhPivots[];
|
|
XCAPivot swlPivots[];
|
|
XCAPivot peakPivots[];
|
|
XCAPivot valePivots[];
|
|
XCAPivot kiBullishPivots[];
|
|
XCAPivot kiBearishPivots[];
|
|
XCAPivot tkiBullishPivots[];
|
|
XCAPivot tkiBearishPivots[];
|
|
XCAPivot peakSWHResPivots[];
|
|
XCAPivot valeSWLSupPivots[];
|
|
XCAPivot trendBullishPivots[];
|
|
XCAPivot trendBearishPivots[];
|
|
|
|
//
|
|
// Constructors ...
|
|
XCXCAEAPOIDetector(
|
|
XCXCAEAHelper *_helper //
|
|
)
|
|
{
|
|
//
|
|
helper = _helper;
|
|
drawer = new XCPOIDrawer();
|
|
barAnalyser = new XCBarAnalyser();
|
|
|
|
//
|
|
Default();
|
|
}
|
|
|
|
//
|
|
// De Constructors ...
|
|
~XCXCAEAPOIDetector()
|
|
{
|
|
//
|
|
peakPivot.Clean();
|
|
Clean(peakPivots);
|
|
|
|
//
|
|
valePivot.Clean();
|
|
Clean(valePivots);
|
|
|
|
//
|
|
peakSWHResPivot.Clean();
|
|
Clean(peakSWHResPivots);
|
|
|
|
//
|
|
valeSWLSupPivot.Clean();
|
|
Clean(valeSWLSupPivots);
|
|
|
|
//
|
|
ZeroMemory(helper);
|
|
ZeroMemory(drawer);
|
|
ZeroMemory(barAnalyser);
|
|
}
|
|
|
|
//
|
|
// Properties ...
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
virtual void Default()
|
|
{
|
|
//
|
|
maxAllowedPivots = 50;
|
|
pivotVerifications = 5;
|
|
}
|
|
|
|
//
|
|
void Update(
|
|
int barIndex = 0,
|
|
int loopback = 400 //
|
|
)
|
|
{
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 400);
|
|
|
|
//
|
|
int count = 0;
|
|
bool has = false;
|
|
|
|
//
|
|
int zIDX = 0;
|
|
int cIDX = zIDX + 1;
|
|
int pIDX = cIDX + 1;
|
|
int p2IDX = pIDX + 1;
|
|
|
|
//
|
|
int index = barIndex;
|
|
int start = index;
|
|
int end = index + loopback;
|
|
while (start < end)
|
|
{
|
|
//
|
|
// Retrieve Conditions ...
|
|
XCAEAConditions iConditions;
|
|
has = helper.GetConditions(
|
|
iConditions,
|
|
start,
|
|
5 //
|
|
);
|
|
|
|
//
|
|
// Retrieve Bars ...
|
|
XOHCL zBar;
|
|
XOHCL cBar;
|
|
XOHCL pBar;
|
|
XOHCL p2Bar;
|
|
has = zBar.Init(
|
|
iConditions.symbol,
|
|
iConditions.period,
|
|
start //
|
|
);
|
|
has =
|
|
has &&
|
|
zBar.GetPreviousBar(cBar);
|
|
has =
|
|
has &&
|
|
cBar.GetPreviousBar(pBar);
|
|
has =
|
|
has &&
|
|
pBar.GetPreviousBar(p2Bar);
|
|
if (!has)
|
|
{
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
iConditions.Clean();
|
|
|
|
//
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Provide Some Conditions ...
|
|
|
|
//
|
|
double points = GetPoints(zBar.symbol);
|
|
|
|
//
|
|
// PEAK ...
|
|
|
|
//
|
|
double cPeak = iConditions.peakBuffer[cIDX];
|
|
double pPeak = iConditions.peakBuffer[pIDX];
|
|
double p2Peak = iConditions.peakBuffer[p2IDX];
|
|
|
|
//
|
|
bool isPeakStartSameLast =
|
|
cPeak == pPeak &&
|
|
pPeak != p2Peak;
|
|
|
|
//
|
|
bool isPeakFinishedSameLast =
|
|
cPeak != pPeak &&
|
|
pPeak == p2Peak;
|
|
|
|
//
|
|
// VALE ...
|
|
|
|
//
|
|
double cVale = iConditions.valeBuffer[cIDX];
|
|
double pVale = iConditions.valeBuffer[pIDX];
|
|
double p2Vale = iConditions.valeBuffer[p2IDX];
|
|
|
|
//
|
|
bool isValeStartSameLast =
|
|
cVale == pVale &&
|
|
pVale != p2Vale;
|
|
|
|
//
|
|
bool isValeFinishedSameLast =
|
|
cVale != pVale &&
|
|
pVale == p2Vale;
|
|
|
|
//
|
|
// SWH ...
|
|
|
|
//
|
|
double cSWH = iConditions.swingHighBuffer[cIDX];
|
|
double pSWH = iConditions.swingHighBuffer[pIDX];
|
|
double p2SWH = iConditions.swingHighBuffer[p2IDX];
|
|
|
|
//
|
|
bool isSWHStartSameLast =
|
|
cSWH == pSWH &&
|
|
pSWH != p2SWH;
|
|
|
|
//
|
|
bool isSWHFinishedSameLast =
|
|
cSWH != pSWH &&
|
|
pSWH == p2SWH;
|
|
|
|
//
|
|
// SWL ...
|
|
|
|
//
|
|
double pSWL = iConditions.swingLowBuffer[pIDX];
|
|
double cSWL = iConditions.swingLowBuffer[cIDX];
|
|
double p2SWL = iConditions.swingLowBuffer[p2IDX];
|
|
|
|
//
|
|
bool isSWLStartSameLast =
|
|
cSWL == pSWL &&
|
|
pSWL != p2SWL;
|
|
|
|
//
|
|
bool isSWLFinishedSameLast =
|
|
cSWL != pSWL &&
|
|
pSWL == p2SWL;
|
|
|
|
//
|
|
// SUPPORT ...
|
|
|
|
//
|
|
double cSupport = iConditions.supportBuffer[cIDX];
|
|
double pSupport = iConditions.supportBuffer[pIDX];
|
|
double p2Support = iConditions.supportBuffer[p2IDX];
|
|
|
|
//
|
|
bool isSupportStartSameLast =
|
|
cSupport == pSupport &&
|
|
pSupport != p2Support;
|
|
|
|
//
|
|
bool isSupportFinishedSameLast =
|
|
cSupport != pSupport &&
|
|
pSupport == p2Support;
|
|
|
|
//
|
|
// RESISTANCE ...
|
|
|
|
//
|
|
double pResistance = iConditions.resistanceBuffer[pIDX];
|
|
double cResistance = iConditions.resistanceBuffer[cIDX];
|
|
double p2Resistance = iConditions.resistanceBuffer[p2IDX];
|
|
|
|
//
|
|
bool isResistanceStartSameLast =
|
|
cResistance == pResistance &&
|
|
pResistance != p2Resistance;
|
|
|
|
//
|
|
bool isResistanceFinishedSameLast =
|
|
cResistance != pResistance &&
|
|
pResistance == p2Resistance;
|
|
|
|
//
|
|
// Checking Pivots ...
|
|
|
|
//
|
|
bool detectSWHPivot = true;
|
|
bool detectSWLPivot = true;
|
|
bool detectPeakPivot = true;
|
|
bool detectValePivot = true;
|
|
bool detectKIBullishPivot = true;
|
|
bool detectKIBearishPivot = true;
|
|
bool detectTKIBullishPivot = true;
|
|
bool detectTKIBearishPivot = true;
|
|
bool detectPeakSWHResPivot = true;
|
|
bool detectValeSWLSupPivot = true;
|
|
bool detectTrendBullishPivot = true;
|
|
bool detectTrendBearishPivot = true;
|
|
|
|
//
|
|
// Peak Pivot ...
|
|
if (detectPeakPivot)
|
|
{
|
|
//
|
|
if (!peakPivot.IsValid())
|
|
{
|
|
//
|
|
peakPivot.type = XCA_PEAK;
|
|
peakPivot.symbol = iConditions.symbol;
|
|
peakPivot.period = iConditions.period;
|
|
|
|
//
|
|
if (isPeakFinishedSameLast)
|
|
{
|
|
//
|
|
peakPivot.Clean();
|
|
|
|
//
|
|
peakPivot.type = XCA_PEAK;
|
|
peakPivot.symbol = iConditions.symbol;
|
|
peakPivot.period = iConditions.period;
|
|
|
|
//
|
|
peakPivot.to = pBar.time;
|
|
peakPivot.from = pBar.time;
|
|
peakPivot.value = iConditions.peakBuffer[pIDX];
|
|
peakPivot.reserve = iConditions.peakGoldenBuffer[pIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
if (iConditions.isPeakSameLast)
|
|
{
|
|
//
|
|
peakPivot.from = pBar.time;
|
|
|
|
//
|
|
peakPivot.reserve =
|
|
peakPivot.reserve == 0
|
|
? iConditions.peakGoldenBuffer[cIDX]
|
|
: MathMax(peakPivot.reserve, iConditions.peakGoldenBuffer[cIDX]);
|
|
}
|
|
|
|
//
|
|
if (isPeakStartSameLast)
|
|
{
|
|
//
|
|
has =
|
|
peakPivot.IsValid() &&
|
|
peakPivot.GetAge() >= pivotVerifications;
|
|
if (has)
|
|
{
|
|
//
|
|
AddPivot(
|
|
peakPivot,
|
|
peakPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
peakPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Vale Pivot ...
|
|
if (detectValePivot)
|
|
{
|
|
//
|
|
if (!valePivot.IsValid())
|
|
{
|
|
//
|
|
valePivot.type = XCA_VALE;
|
|
valePivot.symbol = iConditions.symbol;
|
|
valePivot.period = iConditions.period;
|
|
|
|
//
|
|
if (isValeFinishedSameLast)
|
|
{
|
|
//
|
|
valePivot.Clean();
|
|
|
|
//
|
|
valePivot.type = XCA_VALE;
|
|
valePivot.symbol = iConditions.symbol;
|
|
valePivot.period = iConditions.period;
|
|
|
|
//
|
|
valePivot.to = pBar.time;
|
|
valePivot.from = pBar.time;
|
|
valePivot.value = iConditions.valeBuffer[pIDX];
|
|
valePivot.reserve = iConditions.valeGoldenBuffer[pIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
if (iConditions.isValeSameLast)
|
|
{
|
|
//
|
|
valePivot.from = pBar.time;
|
|
|
|
//
|
|
valePivot.reserve =
|
|
valePivot.reserve == 0
|
|
? iConditions.valeGoldenBuffer[cIDX]
|
|
: MathMin(valePivot.reserve, iConditions.valeGoldenBuffer[cIDX]);
|
|
}
|
|
|
|
//
|
|
if (isValeStartSameLast)
|
|
{
|
|
//
|
|
has = valePivot.IsValid() &&
|
|
valePivot.GetAge() >= pivotVerifications;
|
|
if (has)
|
|
{
|
|
//
|
|
AddPivot(
|
|
valePivot,
|
|
valePivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
valePivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// SWH Pivot ...
|
|
if (detectSWHPivot)
|
|
{
|
|
//
|
|
if (!swhPivot.IsValid())
|
|
{
|
|
//
|
|
swhPivot.type = XCA_SWH;
|
|
swhPivot.symbol = iConditions.symbol;
|
|
swhPivot.period = iConditions.period;
|
|
|
|
//
|
|
if (isSWHFinishedSameLast)
|
|
{
|
|
//
|
|
swhPivot.Clean();
|
|
|
|
//
|
|
swhPivot.type = XCA_SWH;
|
|
swhPivot.symbol = iConditions.symbol;
|
|
swhPivot.period = iConditions.period;
|
|
|
|
//
|
|
swhPivot.to = pBar.time;
|
|
swhPivot.from = pBar.time;
|
|
swhPivot.value = iConditions.swingHighBuffer[pIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
if (iConditions.isSwingHighSameLast)
|
|
{
|
|
//
|
|
swhPivot.from = pBar.time;
|
|
|
|
//
|
|
double reserve = swhPivot.reserve;
|
|
if (pBar.high == pSWH)
|
|
{
|
|
//
|
|
reserve =
|
|
reserve == 0
|
|
? pBar.GetUp()
|
|
: MathMin(reserve, pBar.GetUp());
|
|
}
|
|
swhPivot.reserve = reserve;
|
|
}
|
|
|
|
//
|
|
if (isSWHStartSameLast)
|
|
{
|
|
//
|
|
double reserve = swhPivot.reserve;
|
|
if (cBar.high == cSWH)
|
|
{
|
|
//
|
|
reserve =
|
|
reserve == 0
|
|
? cBar.GetUp()
|
|
: MathMin(reserve, cBar.GetUp());
|
|
}
|
|
if (pBar.high == pSWH)
|
|
{
|
|
//
|
|
reserve =
|
|
reserve == 0
|
|
? pBar.GetUp()
|
|
: MathMin(reserve, pBar.GetUp());
|
|
}
|
|
if (reserve == 0 || reserve == swhPivot.value)
|
|
{
|
|
reserve = swhPivot.value - (5 * points);
|
|
}
|
|
swhPivot.reserve = reserve;
|
|
|
|
//
|
|
has =
|
|
swhPivot.IsValid() &&
|
|
swhPivot.GetAge() >= pivotVerifications;
|
|
if (has)
|
|
{
|
|
//
|
|
AddPivot(
|
|
swhPivot,
|
|
swhPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
swhPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// SWL Pivot ...
|
|
if (detectSWLPivot)
|
|
{
|
|
//
|
|
if (!swlPivot.IsValid())
|
|
{
|
|
//
|
|
swlPivot.type = XCA_SWL;
|
|
swlPivot.symbol = iConditions.symbol;
|
|
swlPivot.period = iConditions.period;
|
|
|
|
//
|
|
if (isSWLFinishedSameLast)
|
|
{
|
|
//
|
|
swlPivot.Clean();
|
|
|
|
//
|
|
swlPivot.type = XCA_SWL;
|
|
swlPivot.symbol = iConditions.symbol;
|
|
swlPivot.period = iConditions.period;
|
|
|
|
//
|
|
swlPivot.to = cBar.time;
|
|
swlPivot.from = pBar.time;
|
|
swlPivot.value = iConditions.swingLowBuffer[cIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
if (iConditions.isSwingLowSameLast)
|
|
{
|
|
//
|
|
swlPivot.from = pBar.time;
|
|
|
|
//
|
|
double reserve = swlPivot.reserve;
|
|
if (pBar.low == pSWL)
|
|
{
|
|
//
|
|
reserve =
|
|
reserve == 0
|
|
? pBar.GetDown()
|
|
: MathMax(reserve, pBar.GetDown());
|
|
}
|
|
swlPivot.reserve = reserve;
|
|
}
|
|
|
|
//
|
|
if (isSWLStartSameLast)
|
|
{
|
|
//
|
|
double reserve = swlPivot.reserve;
|
|
if (cBar.low == cSWL)
|
|
{
|
|
//
|
|
reserve =
|
|
reserve == 0
|
|
? cBar.GetDown()
|
|
: MathMax(reserve, cBar.GetDown());
|
|
}
|
|
if (pBar.low == pSWL)
|
|
{
|
|
//
|
|
reserve =
|
|
reserve == 0
|
|
? pBar.GetDown()
|
|
: MathMax(reserve, pBar.GetDown());
|
|
}
|
|
if (reserve == 0 || reserve == swlPivot.value)
|
|
{
|
|
reserve = swlPivot.value + (5 * points);
|
|
}
|
|
swlPivot.reserve = reserve;
|
|
|
|
//
|
|
has =
|
|
swlPivot.IsValid() &&
|
|
swlPivot.GetAge() >= pivotVerifications;
|
|
if (has)
|
|
{
|
|
//
|
|
AddPivot(
|
|
swlPivot,
|
|
swlPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
swlPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Peak SWH Res Pivot ...
|
|
if (detectPeakSWHResPivot)
|
|
{
|
|
//
|
|
if (!peakSWHResPivot.IsValid())
|
|
{
|
|
//
|
|
peakSWHResPivot.type = XCA_PEAKSWHRES;
|
|
peakSWHResPivot.symbol = iConditions.symbol;
|
|
peakSWHResPivot.period = iConditions.period;
|
|
|
|
//
|
|
if (iConditions.isPeakIsPivot && iConditions.isPeakSameLast)
|
|
{
|
|
//
|
|
peakSWHResPivot.to = cBar.time;
|
|
peakSWHResPivot.from = pBar.time;
|
|
peakSWHResPivot.value = iConditions.peakBuffer[cIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
if (iConditions.isPeakIsPivot && iConditions.isPeakSameLast)
|
|
{
|
|
//
|
|
peakSWHResPivot.from = pBar.time;
|
|
peakSWHResPivot.reserve =
|
|
peakSWHResPivot.reserve == 0
|
|
? iConditions.peakGoldenBuffer[cIDX]
|
|
: MathMax(peakSWHResPivot.reserve, iConditions.peakGoldenBuffer[cIDX]);
|
|
}
|
|
|
|
//
|
|
if (!(iConditions.isPeakIsPivot && iConditions.isPeakSameLast))
|
|
{
|
|
//
|
|
has = peakSWHResPivot.IsValid() &&
|
|
peakSWHResPivot.GetAge() >= pivotVerifications;
|
|
if (has)
|
|
{
|
|
//
|
|
AddPivot(
|
|
peakSWHResPivot,
|
|
peakSWHResPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
peakSWHResPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Vale SWL Sup Pivot ...
|
|
if (detectValeSWLSupPivot)
|
|
{
|
|
//
|
|
if (!valeSWLSupPivot.IsValid())
|
|
{
|
|
//
|
|
valeSWLSupPivot.type = XCA_VALESWLSUP;
|
|
valeSWLSupPivot.symbol = iConditions.symbol;
|
|
valeSWLSupPivot.period = iConditions.period;
|
|
|
|
//
|
|
if (iConditions.isValeIsPivot && iConditions.isValeSameLast)
|
|
{
|
|
//
|
|
valeSWLSupPivot.to = cBar.time;
|
|
valeSWLSupPivot.from = pBar.time;
|
|
valeSWLSupPivot.value = iConditions.valeBuffer[cIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
if (iConditions.isValeIsPivot && iConditions.isValeSameLast)
|
|
{
|
|
//
|
|
valeSWLSupPivot.from = pBar.time;
|
|
valeSWLSupPivot.reserve =
|
|
valeSWLSupPivot.reserve == 0
|
|
? iConditions.valeGoldenBuffer[cIDX]
|
|
: MathMin(valeSWLSupPivot.reserve, iConditions.valeGoldenBuffer[cIDX]);
|
|
}
|
|
|
|
//
|
|
if (!(iConditions.isValeIsPivot && iConditions.isValeSameLast))
|
|
{
|
|
//
|
|
has = valeSWLSupPivot.IsValid() &&
|
|
valeSWLSupPivot.GetAge() >= pivotVerifications;
|
|
if (has)
|
|
{
|
|
//
|
|
AddPivot(
|
|
valeSWLSupPivot,
|
|
valeSWLSupPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
valeSWLSupPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// KI Bullish ...
|
|
if (detectKIBullishPivot)
|
|
{
|
|
//
|
|
if (!kiBullishPivot.IsValid())
|
|
{
|
|
//
|
|
kiBullishPivot.type = XCA_KI_BULL;
|
|
kiBullishPivot.symbol = iConditions.symbol;
|
|
kiBullishPivot.period = iConditions.period;
|
|
|
|
//
|
|
if (iConditions.isKISwitchedToBearish)
|
|
{
|
|
//
|
|
kiBullishPivot.Clean();
|
|
|
|
//
|
|
kiBullishPivot.type = XCA_KI_BULL;
|
|
kiBullishPivot.symbol = iConditions.symbol;
|
|
kiBullishPivot.period = iConditions.period;
|
|
|
|
//
|
|
kiBullishPivot.to = pBar.time;
|
|
kiBullishPivot.from = pBar.time;
|
|
kiBullishPivot.value = iConditions.kiBuffer[pIDX];
|
|
kiBullishPivot.reserve = iConditions.kiBuffer[pIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
if (iConditions.isKIBullish)
|
|
{
|
|
//
|
|
kiBullishPivot.from = cBar.time;
|
|
|
|
//
|
|
Add(
|
|
iConditions.kiBuffer[cIDX],
|
|
kiBullishPivot.values //
|
|
);
|
|
|
|
//
|
|
kiBullishPivot.value =
|
|
kiBullishPivot.value == 0
|
|
? iConditions.kiBuffer[cIDX]
|
|
: MathMin(iConditions.kiBuffer[cIDX], kiBullishPivot.value);
|
|
|
|
//
|
|
kiBullishPivot.reserve =
|
|
kiBullishPivot.reserve == 0
|
|
? iConditions.kiBuffer[cIDX]
|
|
: MathMax(iConditions.kiBuffer[cIDX], kiBullishPivot.reserve);
|
|
}
|
|
|
|
//
|
|
if (iConditions.isKISwitchedToBullish)
|
|
{
|
|
//
|
|
has =
|
|
kiBullishPivot.IsValid() &&
|
|
kiBullishPivot.GetAge() >= pivotVerifications;
|
|
if (has)
|
|
{
|
|
//
|
|
AddPivot(
|
|
kiBullishPivot,
|
|
kiBullishPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
kiBullishPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// KI Bearish ...
|
|
if (detectKIBearishPivot)
|
|
{
|
|
//
|
|
if (!kiBearishPivot.IsValid())
|
|
{
|
|
//
|
|
kiBearishPivot.type = XCA_KI_BEAR;
|
|
kiBearishPivot.symbol = iConditions.symbol;
|
|
kiBearishPivot.period = iConditions.period;
|
|
|
|
//
|
|
if (iConditions.isKISwitchedToBullish)
|
|
{
|
|
//
|
|
kiBearishPivot.Clean();
|
|
|
|
//
|
|
kiBearishPivot.type = XCA_KI_BEAR;
|
|
kiBearishPivot.symbol = iConditions.symbol;
|
|
kiBearishPivot.period = iConditions.period;
|
|
|
|
//
|
|
kiBearishPivot.to = pBar.time;
|
|
kiBearishPivot.from = pBar.time;
|
|
kiBearishPivot.value = iConditions.kiBuffer[pIDX];
|
|
kiBearishPivot.reserve = iConditions.kiBuffer[pIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
if (iConditions.isKIBearish)
|
|
{
|
|
//
|
|
kiBearishPivot.from = cBar.time;
|
|
|
|
//
|
|
Add(
|
|
iConditions.kiBuffer[cIDX],
|
|
kiBearishPivot.values //
|
|
);
|
|
|
|
//
|
|
kiBearishPivot.value =
|
|
kiBearishPivot.value == 0
|
|
? iConditions.kiBuffer[cIDX]
|
|
: MathMax(iConditions.kiBuffer[cIDX], kiBearishPivot.value);
|
|
|
|
//
|
|
kiBearishPivot.reserve =
|
|
kiBearishPivot.reserve == 0
|
|
? iConditions.kiBuffer[cIDX]
|
|
: MathMin(iConditions.kiBuffer[cIDX], kiBearishPivot.reserve);
|
|
}
|
|
|
|
//
|
|
if (iConditions.isKISwitchedToBearish)
|
|
{
|
|
//
|
|
has =
|
|
kiBearishPivot.IsValid() &&
|
|
kiBearishPivot.GetAge() >= pivotVerifications;
|
|
if (has)
|
|
{
|
|
//
|
|
AddPivot(
|
|
kiBearishPivot,
|
|
kiBearishPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
kiBearishPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// TKI Bullish ...
|
|
if (detectTKIBullishPivot)
|
|
{
|
|
//
|
|
if (!tkiBullishPivot.IsValid())
|
|
{
|
|
//
|
|
tkiBullishPivot.type = XCA_TKI_BULL;
|
|
tkiBullishPivot.symbol = iConditions.symbol;
|
|
tkiBullishPivot.period = iConditions.period;
|
|
|
|
//
|
|
if (iConditions.isTKISwitchedToBearish)
|
|
{
|
|
//
|
|
tkiBullishPivot.Clean();
|
|
|
|
//
|
|
tkiBullishPivot.type = XCA_TKI_BULL;
|
|
tkiBullishPivot.symbol = iConditions.symbol;
|
|
tkiBullishPivot.period = iConditions.period;
|
|
|
|
//
|
|
tkiBullishPivot.to = pBar.time;
|
|
tkiBullishPivot.from = pBar.time;
|
|
tkiBullishPivot.value = iConditions.tkiBuffer[pIDX];
|
|
tkiBullishPivot.reserve = iConditions.tkiBuffer[pIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
if (iConditions.isTKIBullish)
|
|
{
|
|
//
|
|
tkiBullishPivot.from = cBar.time;
|
|
|
|
//
|
|
Add(
|
|
iConditions.tkiBuffer[cIDX],
|
|
tkiBullishPivot.values //
|
|
);
|
|
|
|
//
|
|
tkiBullishPivot.value =
|
|
tkiBullishPivot.value == 0
|
|
? iConditions.tkiBuffer[cIDX]
|
|
: MathMin(iConditions.tkiBuffer[cIDX], tkiBullishPivot.value);
|
|
|
|
//
|
|
tkiBullishPivot.reserve =
|
|
tkiBullishPivot.reserve == 0
|
|
? iConditions.tkiBuffer[cIDX]
|
|
: MathMax(iConditions.tkiBuffer[cIDX], tkiBullishPivot.reserve);
|
|
}
|
|
|
|
//
|
|
if (iConditions.isTKISwitchedToBullish)
|
|
{
|
|
//
|
|
has =
|
|
tkiBullishPivot.IsValid() &&
|
|
tkiBullishPivot.GetAge() >= pivotVerifications;
|
|
if (has)
|
|
{
|
|
//
|
|
AddPivot(
|
|
tkiBullishPivot,
|
|
tkiBullishPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
tkiBullishPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// TKI Bearish ...
|
|
if (detectTKIBearishPivot)
|
|
{
|
|
//
|
|
if (!tkiBearishPivot.IsValid())
|
|
{
|
|
//
|
|
tkiBearishPivot.type = XCA_TKI_BEAR;
|
|
tkiBearishPivot.symbol = iConditions.symbol;
|
|
tkiBearishPivot.period = iConditions.period;
|
|
|
|
//
|
|
if (iConditions.isTKISwitchedToBullish)
|
|
{
|
|
//
|
|
tkiBearishPivot.Clean();
|
|
|
|
//
|
|
tkiBearishPivot.type = XCA_TKI_BEAR;
|
|
tkiBearishPivot.symbol = iConditions.symbol;
|
|
tkiBearishPivot.period = iConditions.period;
|
|
|
|
//
|
|
tkiBearishPivot.to = pBar.time;
|
|
tkiBearishPivot.from = pBar.time;
|
|
tkiBearishPivot.value = iConditions.tkiBuffer[pIDX];
|
|
tkiBearishPivot.reserve = iConditions.tkiBuffer[pIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
if (iConditions.isTKIBearish)
|
|
{
|
|
//
|
|
tkiBearishPivot.from = cBar.time;
|
|
|
|
//
|
|
Add(
|
|
iConditions.tkiBuffer[cIDX],
|
|
tkiBearishPivot.values //
|
|
);
|
|
|
|
//
|
|
tkiBearishPivot.value =
|
|
tkiBearishPivot.value == 0
|
|
? iConditions.tkiBuffer[cIDX]
|
|
: MathMax(iConditions.tkiBuffer[cIDX], tkiBearishPivot.value);
|
|
|
|
//
|
|
tkiBearishPivot.reserve =
|
|
tkiBearishPivot.reserve == 0
|
|
? iConditions.tkiBuffer[cIDX]
|
|
: MathMin(iConditions.tkiBuffer[cIDX], tkiBearishPivot.reserve);
|
|
}
|
|
|
|
//
|
|
if (iConditions.isTKISwitchedToBearish)
|
|
{
|
|
//
|
|
has =
|
|
tkiBearishPivot.IsValid() &&
|
|
tkiBearishPivot.GetAge() >= pivotVerifications;
|
|
if (has)
|
|
{
|
|
//
|
|
AddPivot(
|
|
tkiBearishPivot,
|
|
tkiBearishPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
tkiBearishPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// TREND Bullish ...
|
|
if (detectTrendBullishPivot)
|
|
{
|
|
//
|
|
if (!trendBullishPivot.IsValid())
|
|
{
|
|
//
|
|
trendBullishPivot.type = XCA_TREND_BULL;
|
|
trendBullishPivot.symbol = iConditions.symbol;
|
|
trendBullishPivot.period = iConditions.period;
|
|
|
|
//
|
|
if (iConditions.isTrendSwitchedToBearish)
|
|
{
|
|
//
|
|
trendBullishPivot.Clean();
|
|
|
|
//
|
|
trendBullishPivot.type = XCA_TREND_BULL;
|
|
trendBullishPivot.symbol = iConditions.symbol;
|
|
trendBullishPivot.period = iConditions.period;
|
|
|
|
//
|
|
trendBullishPivot.to = pBar.time;
|
|
trendBullishPivot.from = pBar.time;
|
|
trendBullishPivot.value = iConditions.trendBuffer[pIDX];
|
|
trendBullishPivot.reserve = iConditions.trendBuffer[pIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
if (iConditions.isTrendBullish)
|
|
{
|
|
//
|
|
trendBullishPivot.from = cBar.time;
|
|
|
|
//
|
|
Add(
|
|
iConditions.trendBuffer[cIDX],
|
|
trendBullishPivot.values //
|
|
);
|
|
|
|
//
|
|
trendBullishPivot.value =
|
|
trendBullishPivot.value == 0
|
|
? iConditions.trendBuffer[cIDX]
|
|
: MathMin(iConditions.trendBuffer[cIDX], trendBullishPivot.value);
|
|
|
|
//
|
|
trendBullishPivot.reserve =
|
|
trendBullishPivot.reserve == 0
|
|
? iConditions.trendBuffer[cIDX]
|
|
: MathMax(iConditions.trendBuffer[cIDX], trendBullishPivot.reserve);
|
|
}
|
|
|
|
//
|
|
if (iConditions.isTrendSwitchedToBullish)
|
|
{
|
|
//
|
|
has =
|
|
trendBullishPivot.IsValid() &&
|
|
trendBullishPivot.GetAge() >= pivotVerifications;
|
|
if (has)
|
|
{
|
|
//
|
|
AddPivot(
|
|
trendBullishPivot,
|
|
trendBullishPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
trendBullishPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// TREND Bearish ...
|
|
if (detectTrendBearishPivot)
|
|
{
|
|
//
|
|
if (!trendBearishPivot.IsValid())
|
|
{
|
|
//
|
|
trendBearishPivot.type = XCA_TREND_BEAR;
|
|
trendBearishPivot.symbol = iConditions.symbol;
|
|
trendBearishPivot.period = iConditions.period;
|
|
|
|
//
|
|
if (iConditions.isTrendSwitchedToBullish)
|
|
{
|
|
//
|
|
trendBearishPivot.Clean();
|
|
|
|
//
|
|
trendBearishPivot.type = XCA_TREND_BEAR;
|
|
trendBearishPivot.symbol = iConditions.symbol;
|
|
trendBearishPivot.period = iConditions.period;
|
|
|
|
//
|
|
trendBearishPivot.to = pBar.time;
|
|
trendBearishPivot.from = pBar.time;
|
|
trendBearishPivot.value = iConditions.trendBuffer[pIDX];
|
|
trendBearishPivot.reserve = iConditions.trendBuffer[pIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
if (iConditions.isTrendBearish)
|
|
{
|
|
//
|
|
trendBearishPivot.from = cBar.time;
|
|
|
|
//
|
|
Add(
|
|
iConditions.trendBuffer[cIDX],
|
|
trendBearishPivot.values //
|
|
);
|
|
|
|
//
|
|
trendBearishPivot.value =
|
|
trendBearishPivot.value == 0
|
|
? iConditions.trendBuffer[cIDX]
|
|
: MathMax(iConditions.trendBuffer[cIDX], trendBearishPivot.value);
|
|
|
|
//
|
|
trendBearishPivot.reserve =
|
|
trendBearishPivot.reserve == 0
|
|
? iConditions.trendBuffer[cIDX]
|
|
: MathMin(iConditions.trendBuffer[cIDX], trendBearishPivot.reserve);
|
|
}
|
|
|
|
//
|
|
if (iConditions.isTrendSwitchedToBearish)
|
|
{
|
|
//
|
|
has =
|
|
trendBearishPivot.IsValid() &&
|
|
trendBearishPivot.GetAge() >= pivotVerifications;
|
|
if (has)
|
|
{
|
|
//
|
|
AddPivot(
|
|
trendBearishPivot,
|
|
trendBearishPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
trendBearishPivot.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
start++;
|
|
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
iConditions.Clean();
|
|
}
|
|
|
|
//
|
|
}
|
|
|
|
//
|
|
// POI Handlers ...
|
|
|
|
//
|
|
// Peaks ...
|
|
|
|
//
|
|
bool HasPeakPivots()
|
|
{
|
|
return HasChild(peakPivots);
|
|
}
|
|
|
|
//
|
|
int CountPeakPivots()
|
|
{
|
|
return ArraySize(peakPivots);
|
|
}
|
|
|
|
//
|
|
// Peak SWH Res ...
|
|
|
|
//
|
|
bool HasPeakSWHResPivots()
|
|
{
|
|
return HasChild(peakSWHResPivots);
|
|
}
|
|
|
|
//
|
|
int CountPeakSWHResPivots()
|
|
{
|
|
return ArraySize(peakSWHResPivots);
|
|
}
|
|
|
|
//
|
|
// Vale ...
|
|
|
|
//
|
|
bool HasValePivots()
|
|
{
|
|
return HasChild(valePivots);
|
|
}
|
|
|
|
//
|
|
int CountValePivots()
|
|
{
|
|
return ArraySize(valePivots);
|
|
}
|
|
|
|
//
|
|
// ValeSWLSup ...
|
|
|
|
//
|
|
bool HasValeSWLSupPivots()
|
|
{
|
|
return HasChild(valeSWLSupPivots);
|
|
}
|
|
|
|
//
|
|
int CountValeSWLSupPivots()
|
|
{
|
|
return ArraySize(valeSWLSupPivots);
|
|
}
|
|
|
|
//
|
|
// Swing High ...
|
|
|
|
//
|
|
bool HasSWHPivots()
|
|
{
|
|
return HasChild(swhPivots);
|
|
}
|
|
|
|
//
|
|
int CountSWHPivots()
|
|
{
|
|
return ArraySize(swhPivots);
|
|
}
|
|
|
|
//
|
|
// Swing Low ...
|
|
|
|
//
|
|
bool HasSWLPivots()
|
|
{
|
|
return HasChild(swlPivots);
|
|
}
|
|
|
|
//
|
|
int CountSWLPivots()
|
|
{
|
|
return ArraySize(swlPivots);
|
|
}
|
|
|
|
//
|
|
// KI ...
|
|
|
|
//
|
|
bool HasKIBullishPivots()
|
|
{
|
|
return HasChild(kiBullishPivots);
|
|
}
|
|
|
|
//
|
|
int CountKIBullishPivots()
|
|
{
|
|
return ArraySize(kiBullishPivots);
|
|
}
|
|
|
|
//
|
|
bool HasKIBearishPivots()
|
|
{
|
|
return HasChild(kiBearishPivots);
|
|
}
|
|
|
|
//
|
|
int CountKIBearishPivots()
|
|
{
|
|
return ArraySize(kiBearishPivots);
|
|
}
|
|
|
|
//
|
|
// TKI ...
|
|
|
|
//
|
|
bool HasTKIBullishPivots()
|
|
{
|
|
return HasChild(tkiBullishPivots);
|
|
}
|
|
|
|
//
|
|
int CountTKIBullishPivots()
|
|
{
|
|
return ArraySize(tkiBullishPivots);
|
|
}
|
|
|
|
//
|
|
bool HasTKIBearishPivots()
|
|
{
|
|
return HasChild(tkiBearishPivots);
|
|
}
|
|
|
|
//
|
|
int CountTKIBearishPivots()
|
|
{
|
|
return ArraySize(tkiBearishPivots);
|
|
}
|
|
|
|
//
|
|
// TREND ...
|
|
|
|
//
|
|
bool HasTrendBullishPivots()
|
|
{
|
|
return HasChild(trendBullishPivots);
|
|
}
|
|
|
|
//
|
|
int CountTrendBullishPivots()
|
|
{
|
|
return ArraySize(trendBullishPivots);
|
|
}
|
|
|
|
//
|
|
bool HasTrendBearishPivots()
|
|
{
|
|
return HasChild(trendBearishPivots);
|
|
}
|
|
|
|
//
|
|
int CountTrendBearishPivots()
|
|
{
|
|
return ArraySize(trendBearishPivots);
|
|
}
|
|
|
|
//
|
|
// Protected ...
|
|
protected:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
// Prrivate ...
|
|
private:
|
|
//
|
|
// Props ...
|
|
int pivotVerifications; // Pivots Verifications ...
|
|
int maxAllowedPivots; // Max Allowed Holding Pibots ...
|
|
|
|
//
|
|
XCAPivot swhPivot;
|
|
XCAPivot swlPivot;
|
|
XCAPivot peakPivot;
|
|
XCAPivot valePivot;
|
|
XCAPivot kiBullishPivot;
|
|
XCAPivot kiBearishPivot;
|
|
XCAPivot tkiBullishPivot;
|
|
XCAPivot tkiBearishPivot;
|
|
XCAPivot peakSWHResPivot;
|
|
XCAPivot valeSWLSupPivot;
|
|
XCAPivot trendBullishPivot;
|
|
XCAPivot trendBearishPivot;
|
|
|
|
//
|
|
XCPOIDrawer *drawer;
|
|
XCXCAEAHelper *helper;
|
|
XCBarAnalyser *barAnalyser;
|
|
|
|
//
|
|
void AddPivot(
|
|
XCAPivot &pivot,
|
|
XCAPivot &pivots[] //
|
|
)
|
|
{
|
|
//
|
|
bool has = pivot.IsValid();
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
has = FindPivotIndex(
|
|
idx,
|
|
pivot,
|
|
pivots //
|
|
);
|
|
if (has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
int updateIDX = -1;
|
|
int count = ArraySize(pivots);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCAPivot iPivot = pivots[i];
|
|
|
|
//
|
|
has =
|
|
iPivot.to > pivot.to &&
|
|
iPivot.from == pivot.from &&
|
|
iPivot.value == pivot.value &&
|
|
iPivot.symbol == pivot.symbol &&
|
|
iPivot.period == pivot.period;
|
|
if (has)
|
|
{
|
|
//
|
|
updateIDX = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
has = IsValidIndex(updateIDX);
|
|
if (!has)
|
|
{
|
|
//
|
|
AddRef(
|
|
pivot,
|
|
pivots //
|
|
);
|
|
}
|
|
else
|
|
{
|
|
pivots[updateIDX].to = pivot.to;
|
|
}
|
|
|
|
//
|
|
// Apply Max Allowed ...
|
|
CleanupArray(
|
|
pivots,
|
|
maxAllowedPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
// |