Files
MQL5Data/XFIMAEA/Classes/x-saherelm.xfima.x-poi.detector.class.mq5
T

1459 lines
35 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Class
// -------------------------------------------------
// Name: XCXFIMAPoiDetector ...
// Description: XFIMA POI Detector Class ...
//
//
// 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 XFIMA POI Detector Class"
#property strict
//
// Imports ...
#include "../../Classes/x-saherelm.base.class.mq5"
#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5"
#include "../../Classes/x-saherelm.x-market.pattern.class.mq5"
#include "../Libraries/x-saherelm.xfima.lib.mq5"
//
// Definitions ...
enum ENUM_XFIMA_PIVOTS
{
XFIMA_PIVOT_NONE = 0,
XFIMA_PIVOT_PV = 1,
XFIMA_PIVOT_ZIGZAG = 2,
XFIMA_PIVOT_MA_CROSS = 3,
XFIMA_PIVOT_HK_SWITCH = 4,
XFIMA_PIVOT_SAR_SWITCH = 5,
XFIMA_PIVOT_BOUNDARY_SWITCH = 6,
};
bool IsXValid(ENUM_XFIMA_PIVOTS value)
{
//
bool result = false;
//
result = value != XFIMA_PIVOT_NONE;
//
return result;
}
string ToXString(ENUM_XFIMA_PIVOTS value)
{
//
string result = NULL;
//
if (!IsXValid(value))
{
return result;
}
//
switch (value)
{
//
case XFIMA_PIVOT_NONE:
result = "NONE";
break;
//
case XFIMA_PIVOT_PV:
result = "XPV";
break;
//
case XFIMA_PIVOT_ZIGZAG:
result = "XZGP";
break;
//
case XFIMA_PIVOT_MA_CROSS:
result = "XMACRS";
break;
//
case XFIMA_PIVOT_HK_SWITCH:
result = "XHKSWCH";
break;
//
case XFIMA_PIVOT_SAR_SWITCH:
result = "XSARSWCH";
break;
//
case XFIMA_PIVOT_BOUNDARY_SWITCH:
result = "XBNDSWCH";
break;
}
//
return result;
}
ENUM_XFIMA_PIVOTS ToXFIMAPivots(string value)
{
//
ENUM_XFIMA_PIVOTS result = XFIMA_PIVOT_NONE;
//
if (!IsXValid(value))
{
return result;
}
//
if (value == ToXString(XFIMA_PIVOT_NONE))
{
result = XFIMA_PIVOT_NONE;
}
else if (value == ToXString(XFIMA_PIVOT_PV))
{
result = XFIMA_PIVOT_PV;
}
else if (value == ToXString(XFIMA_PIVOT_ZIGZAG))
{
result = XFIMA_PIVOT_ZIGZAG;
}
else if (value == ToXString(XFIMA_PIVOT_MA_CROSS))
{
result = XFIMA_PIVOT_MA_CROSS;
}
else if (value == ToXString(XFIMA_PIVOT_HK_SWITCH))
{
result = XFIMA_PIVOT_HK_SWITCH;
}
else if (value == ToXString(XFIMA_PIVOT_SAR_SWITCH))
{
result = XFIMA_PIVOT_SAR_SWITCH;
}
else if (value == ToXString(XFIMA_PIVOT_BOUNDARY_SWITCH))
{
result = XFIMA_PIVOT_BOUNDARY_SWITCH;
}
//
return result;
}
//
// Implementation ...
class XCXFIMAPOIDetector : public XCMarketPatternDetector
{
//
// Public ...
public:
//
// Props ...
//
string symbol;
ENUM_TIMEFRAMES period;
//
XCBarAnalyser *barAnalyser; // Bar Analyser ...
XCXFIMAHelper *fimaHelper; // XFIMA Helper ...
XCXFIMAHelperParser *fimaParser; // XFIMA Helper Parser ...
//
// Constructor ...
XCXFIMAPOIDetector(
XCXFIMAHelper *_fimaHelper,
XCXFIMAHelperParser *_fimaParser //
) : XCMarketPatternDetector()
{
//
barAnalyser = new XCBarAnalyser();
fimaHelper = _fimaHelper;
fimaParser = _fimaParser;
//
symbol = fimaHelper.GetSymbol();
period = fimaHelper.GetPeriod();
}
//
// Deconstructor ...
~XCXFIMAPOIDetector()
{
Destroy();
}
//
// Actions and Tools ...
//
// Detectors ...
//
// XPV ...
/**
* Check Conditions to Detecte XPV based Consolidation Zone ...
*
* @param zone: XBoxZone, reference to holds detected zone ...
* @param barIndex: int, Specified Bar Index ...
* @param forcePVBreak: bool, force to has PV Side Break ...
* @param forceHasSarSwitch: bool, force to has SAR Switche ...
*
* @return ( bool )
*/
bool DetectPVConsolidationZone(
XBoxZone &zone,
int barIndex = 0,
bool forcePVBreak = false,
bool forceHasSarSwitch = false //
)
{
//
bool result = false;
//
// Prepare ...
zone.Clean();
//
// Normalize ...
barIndex = fimaParser.NormalizeBarIndex(barIndex);
//
// Validate ...
result = fimaParser.IsValid();
if (!result)
{
return result;
}
//
// Do ...
//
bool isPeakSame = fimaParser.IsPeakSame(barIndex);
bool isValeSame = fimaParser.IsValeSame(barIndex);
result = !(isPeakSame &&
isValeSame);
if (!result)
{
return result;
}
//
double iPeak = EMPTY_VALUE;
double iVale = EMPTY_VALUE;
//
int idx = barIndex;
bool canLookup = true;
while (canLookup)
{
//
idx++;
isPeakSame = fimaParser.IsPeakSame(idx);
isValeSame = fimaParser.IsValeSame(idx);
result = isPeakSame &&
isValeSame;
if (!result)
{
//
zone.from = GetBarTime(symbol, period, idx);
break;
}
//
if (idx == barIndex + 1)
{
//
zone.to = GetBarTime(
symbol,
period,
idx //
);
}
//
zone.from = GetBarTime(
symbol,
period,
idx //
);
//
iPeak = fimaHelper.GetPeak(idx);
iVale = fimaHelper.GetVale(idx);
//
zone.lower =
!NotEmptyZero(zone.lower)
? iVale
: MathMin(zone.lower, iVale);
//
zone.upper =
!NotEmptyZero(zone.upper)
? iPeak
: MathMax(zone.upper, iPeak);
}
//
// Validating Zone Params ...
result =
//
IsXValid(zone.to) &&
IsXValid(zone.from) &&
zone.from < zone.to &&
//
NotEmptyZero(zone.lower) &&
NotEmptyZero(zone.upper) &&
zone.upper > zone.lower
//
;
//
// Prepare Zone ...
if (result)
{
//
iPeak = fimaHelper.GetPeak(barIndex);
iVale = fimaHelper.GetVale(barIndex);
bool isPeakOverLast = fimaParser.IsPeakOverLast(barIndex);
bool isValeUnderLast = fimaParser.IsValeUnderLast(barIndex);
bool isValeBreak = iVale < zone.lower;
bool isPeakBreak = iPeak > zone.upper;
bool isPVBreak = isPeakBreak ||
isValeBreak;
//
zone.at = GetBarTime(symbol, period, barIndex);
zone.symbol = symbol;
zone.period = period;
zone.dir = (isPeakOverLast && !isValeUnderLast && isPVBreak)
? X_DIRECTION_BULLISH
: (isValeUnderLast && !isPeakOverLast && isPVBreak)
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
zone.type = ToXString(X_BAR_PATTERN_CONSOLIDATION);
//
// Refine Zone Upper and Lower ...
if (zone.IsValid())
{
//
XOHCL iBar;
int zoneLoopback = zone.FromIndex() - zone.ToIndex();
result = zone.ToBar(iBar) &&
IsValidSize(zoneLoopback);
if (result)
{
//
double zoneLL = iBar.FindLowest(zoneLoopback, MODE_LOW);
double zoneHH = iBar.FindHighest(zoneLoopback, MODE_HIGH);
result = NotEmptyZero(zoneLL) &&
NotEmptyZero(zoneHH);
if (result)
{
//
zone.lower = zone.lower == zoneLL
? zone.lower
: MathMax(zone.lower, zoneLL);
//
zone.upper = zone.upper == zoneHH
? zone.upper
: MathMin(zone.upper, zoneHH);
}
}
//
iBar.Clean();
}
//
// Validate ...
result = zone.IsValid();
}
//
// Validate Zones From ...
if (result)
{
//
int idx = zone.FromIndex();
//
iPeak = fimaHelper.GetPeak(idx);
iVale = fimaHelper.GetVale(idx);
//
bool isValeOverLast = fimaParser.IsValeOverLast(idx);
bool isPeakUnderLast = fimaParser.IsPeakUnderLast(idx);
//
result =
result &&
(zone.IsBullish()
? !isPeakUnderLast
: zone.IsBearish()
? !isValeOverLast
: false);
}
//
// Apply Forces ...
//
// PV Break ...
// Peak or Vale must Breaked at Bar ...
if (result && forcePVBreak)
{
//
bool isPVBreaked =
(zone.IsBullish() && fimaParser.IsPeakOverLast(barIndex)) ||
(zone.IsBearish() && fimaParser.IsValeUnderLast(barIndex));
//
result = result &&
isPVBreaked;
}
//
// Other Loop based Forces ...
if (result && (forceHasSarSwitch))
{
//
bool hasSarSwitch = false;
//
int start = zone.ToIndex();
int end = zone.FromIndex();
for (int i = start; i <= end; i++)
{
//
// Check Sar Switches ...
if (forceHasSarSwitch && !hasSarSwitch)
{
//
hasSarSwitch =
zone.IsBullish()
? fimaParser.IsSARSwitchedToBullish(i)
: fimaParser.IsSARSwitchedToBearish(i);
}
}
//
// Validate Forces ...
if (forceHasSarSwitch)
{
//
result =
result &&
hasSarSwitch;
}
}
//
// Cleanup ...
if (!result)
{
zone.Clean();
}
//
return result;
}
//
// Analysors ...
/**
* Analyse Market ...
*
* @param structure: XFIMAMarketStructure, reference to holds Market Strucutre ...
* @param config: XFIMAMarketStructureConfig, reference to Provide Structure Analyse Config ...
* @param barIndex: int, Specified Bar Index ...
*
* @return ( bool )
*/
bool AnalyseMarket(
XFIMAMarketStructure &structure,
XFIMAMarketStructureConfig &config,
int barIndex = 0 //
)
{
//
bool result = false;
//
// Prepare ...
structure.Clean();
//
// Normalize ...
barIndex = fimaParser.NormalizeBarIndex(barIndex);
//
// Validate ...
result = fimaParser.IsValid();
if (!result)
{
return result;
}
//
// Do ...
int idx = -1;
XOHCL tmpBar;
datetime fromTime = NULL;
XPatternAnalysis tmpBarAnalysis;
//
// Initialize Indexed Bar ...
result = structure.bar.Init(symbol, period, barIndex);
//
// Analyse Bar Patterns ...
if (result)
{
//
result = AnalyseBarPatterns(
structure.bar,
structure.barAnalysis,
config.barsAnalysisConfig //
);
}
//
// Analyse Pivots ...
//
// XPV ...
CollectPVPivots(
structure.pvPivots,
barIndex,
config.requiredPivots,
config.loopback //
);
//
// XMA ...
CollectMAPivots(
structure.maPivots,
barIndex,
config.requiredPivots,
config.loopback //
);
//
// XZG ...
CollectZGPivots(
structure.zgPivots,
barIndex,
config.requiredPivots,
config.loopback //
);
//
// XHK ...
CollectHKPivots(
structure.hkPivots,
barIndex,
config.requiredPivots,
config.loopback //
);
//
// XSAR ...
CollectSARPivots(
structure.sarPivots,
barIndex,
config.requiredPivots,
config.loopback //
);
//
// XPV Analysis ...
if (result && config.analysePVPivots)
{
//
result = HasChild(structure.pvPivots);
//
// Check Oldest ...
idx = GetOldest(structure.pvPivots);
result = IsValidIndex(idx);
if (result)
{
//
fromTime =
!IsXValid(fromTime)
? structure.pvPivots[idx].time
: MathMin(fromTime, structure.pvPivots[idx].time);
}
//
// Initialize Analysis ...
if (result)
{
//
result = structure.pvAnalysis.Init(
ToXString(XFIMA_PIVOT_PV),
symbol,
period,
structure.pvPivots //
);
}
}
//
// XZG Analysis ...
if (result && config.analyseZGPivots)
{
//
result = HasChild(structure.zgPivots);
//
// Check Oldest ...
idx = GetOldest(structure.zgPivots);
result = IsValidIndex(idx);
if (result)
{
//
fromTime =
!IsXValid(fromTime)
? structure.zgPivots[idx].time
: MathMin(fromTime, structure.zgPivots[idx].time);
}
//
// Initialize Analysis ...
if (result)
{
//
result = structure.zgAnalysis.Init(
ToXString(XFIMA_PIVOT_ZIGZAG),
symbol,
period,
structure.zgPivots //
);
}
}
//
// XHK Analysis ...
if (result && config.analyseHKPivots)
{
//
result = HasChild(structure.hkPivots);
//
// Check Oldest ...
idx = GetOldest(structure.hkPivots);
result = IsValidIndex(idx);
if (result)
{
//
fromTime =
!IsXValid(fromTime)
? structure.hkPivots[idx].time
: MathMin(fromTime, structure.hkPivots[idx].time);
}
//
// Initialize Analysis ...
if (result)
{
//
result = structure.hkAnalysis.Init(
ToXString(XFIMA_PIVOT_HK_SWITCH),
symbol,
period,
structure.hkPivots //
);
}
}
//
// XMA Analysis ...
if (result && config.analyseMAPivots)
{
result = HasChild(structure.maPivots);
//
// Check Oldest ...
idx = GetOldest(structure.maPivots);
result = IsValidIndex(idx);
if (result)
{
//
fromTime =
!IsXValid(fromTime)
? structure.maPivots[idx].time
: MathMin(fromTime, structure.maPivots[idx].time);
}
//
// Initialize Analysis ...
if (result)
{
//
result = structure.maAnalysis.Init(
ToXString(XFIMA_PIVOT_MA_CROSS),
symbol,
period,
structure.maPivots //
);
}
}
//
// XSAR Analysis ...
if (result && config.analyseSARPivots)
{
//
result = HasChild(structure.sarPivots);
//
// Check Oldest ...
idx = GetOldest(structure.sarPivots);
result = IsValidIndex(idx);
if (result)
{
//
fromTime =
!IsXValid(fromTime)
? structure.sarPivots[idx].time
: MathMin(fromTime, structure.sarPivots[idx].time);
}
//
// Initialize Analysis ...
if (result)
{
//
result = structure.sarAnalysis.Init(
ToXString(XFIMA_PIVOT_SAR_SWITCH),
symbol,
period,
structure.sarPivots //
);
}
}
//
// Order Flow ...
if (result && config.detectOrderFlow)
{
//
HasOrderFlow(
structure.bar,
structure.orderFlowDir,
structure.orderFlow,
config.orderFlowValidation,
config.orderFlowUseOB,
config.orderFlowUseFVG,
config.orderFlowUseSupportAndResistance,
config.barsAnalysisConfig.supportAndResistanceLoopbackLength,
config.barsAnalysisConfig.supportAndResistanceValidationLength,
config.loopback //
);
}
//
// Analyse Bar Patterns ...
if (result && config.analyseBarPatterns)
{
//
// Collect Pivots ...
XPivot tmps[];
Copy(structure.pvPivots, tmps, false);
Copy(structure.zgPivots, tmps, false);
Copy(structure.hkPivots, tmps, false);
Copy(structure.maPivots, tmps, false);
Copy(structure.sarPivots, tmps, false);
//
XPivot sames[];
XPivot tmpPivot;
int samesCount = 0;
while (HasChild(tmps))
{
//
tmpPivot.Clean();
tmpPivot = tmps[0];
ArrayRemove(tmps, 0, 1);
//
XClean(sames);
samesCount = ExtractSameTimePivots(tmpPivot, sames, tmps);
if (HasChild(sames))
{
//
tmpBar.Clean();
if (sames[0].GetBar(tmpBar))
{
//
tmpBarAnalysis.Clean();
if (AnalyseBarPatterns(tmpBar, tmpBarAnalysis, config.barsAnalysisConfig))
{
//
AddRef(tmpBarAnalysis, structure.barsAnalysis);
}
}
//
Removes(sames, tmps);
}
}
//
// Bars Analysis Exists ...
result = HasChild(structure.barsAnalysis);
//
// Cleanup ...
XClean(tmps);
XClean(sames);
tmpPivot.Clean();
}
//
// Cleanup ...
if (!result)
{
structure.Clean();
}
//
return result;
}
//
// Collectors ...
/**
* Collect ZigZag Pivots ...
*
* @param pivots: XPivot, reference collection to holds Detected Pivots ...
* @param barIndex: int, Specified Start Bar Index ...
* @param count: int, Specified number of required Pivots ...
* @param loopback: int, Max Allowed Loopback length for Detection ...
*
* @return ( int )
*/
int CollectZGPivots(
XPivot &pivots[],
int barIndex = 0,
int count = 50,
int loopback = 500 //
)
{
//
int result = 0;
//
// Prepare ...
XClean(pivots);
//
// Normalize ...
count = NormalizeInt(count, 0);
loopback = NormalizeInt(loopback, 50);
barIndex = fimaParser.NormalizeBarIndex(barIndex);
//
// Validate ...
bool has = fimaParser.IsValid();
if (!has)
{
return result;
}
//
// Do ...
XOHCL bar;
XPivot pivot;
int start = barIndex;
bool isBullish = false;
bool isBearish = false;
int end = start + loopback;
ENUM_X_DIRECTION dir = X_DIRECTION_NONE;
for (int i = start; i < end; i++)
{
//
isBullish = fimaParser.IsZGLow(i);
isBearish = fimaParser.IsZGHigh(i);
//
has = isBullish || isBearish;
if (has)
{
//
// Specified Direction ...
dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
// Initialize Indexed Bar ...
// Validate it, and Converts it to Pivot ...
bar.Clean();
has = bar.Init(symbol, period, i);
has = has &&
ToPivot(
bar,
pivot,
dir,
ToXString(XFIMA_PIVOT_ZIGZAG) //
);
if (has)
{
//
// Add Detected Pivot ...
AddIfNotExists(pivot, pivots);
}
//
has = count <= 0
? false
: ArraySize(pivots) >= count;
if (has)
{
break;
}
}
//
// Cleanup ...
bar.Clean();
pivot.Clean();
}
//
result = ArraySize(pivots);
//
// Cleanup ...
bar.Clean();
pivot.Clean();
//
return result;
}
/**
* Collect MA Pivots ...
*
* @param pivots: XPivot, reference collection to holds Detected Pivots ...
* @param barIndex: int, Specified Start Bar Index ...
* @param count: int, Specified number of required Pivots ...
* @param loopback: int, Max Allowed Loopback length for Detection ...
*
* @return ( int )
*/
int CollectMAPivots(
XPivot &pivots[],
int barIndex = 0,
int count = 50,
int loopback = 500 //
)
{
//
int result = 0;
//
// Prepare ...
XClean(pivots);
//
// Normalize ...
count = NormalizeInt(count, 0);
loopback = NormalizeInt(loopback, 50);
barIndex = fimaParser.NormalizeBarIndex(barIndex);
//
// Validate ...
bool has = fimaParser.IsValid();
if (!has)
{
return result;
}
//
// Do ...
XOHCL bar;
XPivot pivot;
int start = barIndex;
bool isBullish = false;
bool isBearish = false;
int end = start + loopback;
ENUM_X_DIRECTION dir = X_DIRECTION_NONE;
for (int i = start; i < end; i++)
{
//
isBullish = fimaParser.IsMAFastCrossedOverSlow(i);
isBearish = fimaParser.IsMAFastCrossedUnderSlow(i);
//
has = isBullish || isBearish;
if (has)
{
//
// Specified Direction ...
dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
// Initialize Indexed Bar ...
// Validate it, and Converts it to Pivot ...
bar.Clean();
has = bar.Init(symbol, period, i);
has = has &&
ToPivot(
bar,
pivot,
dir,
ToXString(XFIMA_PIVOT_MA_CROSS) //
);
if (has)
{
//
// Replace MA Values ...
pivot.value =
isBullish
? fimaHelper.GetMASlow(barIndex)
: fimaHelper.GetMAFast(barIndex);
//
// Add Detected Pivot ...
AddIfNotExists(pivot, pivots);
}
//
has = count <= 0
? false
: ArraySize(pivots) >= count;
if (has)
{
break;
}
}
//
// Cleanup ...
bar.Clean();
pivot.Clean();
}
//
result = ArraySize(pivots);
//
// Cleanup ...
bar.Clean();
pivot.Clean();
//
return result;
}
/**
* Collect HK Pivots ...
*
* @param pivots: XPivot, reference collection to holds Detected Pivots ...
* @param barIndex: int, Specified Start Bar Index ...
* @param count: int, Specified number of required Pivots ...
* @param loopback: int, Max Allowed Loopback length for Detection ...
*
* @return ( int )
*/
int CollectHKPivots(
XPivot &pivots[],
int barIndex = 0,
int count = 50,
int loopback = 500 //
)
{
//
int result = 0;
//
// Prepare ...
XClean(pivots);
//
// Normalize ...
count = NormalizeInt(count, 0);
loopback = NormalizeInt(loopback, 50);
barIndex = fimaParser.NormalizeBarIndex(barIndex);
//
// Validate ...
bool has = fimaParser.IsValid();
if (!has)
{
return result;
}
//
// Do ...
XOHCL bar;
XPivot pivot;
int start = barIndex;
bool isBullish = false;
bool isBearish = false;
int end = start + loopback;
ENUM_X_DIRECTION dir = X_DIRECTION_NONE;
for (int i = start; i < end; i++)
{
//
isBullish = fimaParser.IsHKSwitchedToBullish(i);
isBearish = fimaParser.IsHKSwitchedToBearish(i);
//
has = isBullish || isBearish;
if (has)
{
//
// Specified Direction ...
dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
// Initialize Indexed Bar ...
// Validate it, and Converts it to Pivot ...
bar.Clean();
has = bar.Init(symbol, period, i);
has = has &&
ToPivot(
bar,
pivot,
dir,
ToXString(XFIMA_PIVOT_HK_SWITCH) //
);
if (has)
{
//
// Replace Value ...
pivot.value =
isBullish
? fimaHelper.GetHKLow(i)
: fimaHelper.GetHKHigh(i);
//
// Add Detected Pivot ...
AddIfNotExists(pivot, pivots);
}
//
has = count <= 0
? false
: ArraySize(pivots) >= count;
if (has)
{
break;
}
}
//
// Cleanup ...
bar.Clean();
pivot.Clean();
}
//
result = ArraySize(pivots);
//
// Cleanup ...
bar.Clean();
pivot.Clean();
//
return result;
}
/**
* Collect PV Pivots ...
*
* @param pivots: XPivot, reference collection to holds Detected Pivots ...
* @param barIndex: int, Specified Start Bar Index ...
* @param count: int, Specified number of required Pivots ...
* @param loopback: int, Max Allowed Loopback length for Detection ...
*
* @return ( int )
*/
int CollectPVPivots(
XPivot &pivots[],
int barIndex = 0,
int count = 50,
int loopback = 500 //
)
{
//
int result = 0;
//
// Prepare ...
XClean(pivots);
//
// Normalize ...
count = NormalizeInt(count, 0);
loopback = NormalizeInt(loopback, 50);
barIndex = fimaParser.NormalizeBarIndex(barIndex);
//
// Validate ...
bool has = fimaParser.IsValid();
if (!has)
{
return result;
}
//
// Do ...
XOHCL bar;
XPivot pivot;
int start = barIndex;
bool isBullish = false;
bool isBearish = false;
int end = start + loopback;
ENUM_X_DIRECTION dir = X_DIRECTION_NONE;
for (int i = start; i < end; i++)
{
//
isBullish = fimaParser.IsPeakOverLast(i);
isBearish = fimaParser.IsValeUnderLast(i);
//
has = isBullish || isBearish;
if (has)
{
//
// Specified Direction ...
dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
// Initialize Indexed Bar ...
// Validate it, and Converts it to Pivot ...
bar.Clean();
has = bar.Init(symbol, period, i);
has = has &&
ToPivot(
bar,
pivot,
dir,
ToXString(XFIMA_PIVOT_PV) //
);
if (has)
{
//
// Replace Value ...
pivot.value =
isBullish
? fimaHelper.GetHKLow(i)
: fimaHelper.GetHKHigh(i);
//
// Add Detected Pivot ...
AddIfNotExists(pivot, pivots);
}
//
has = count <= 0
? false
: ArraySize(pivots) >= count;
if (has)
{
break;
}
}
//
// Cleanup ...
bar.Clean();
pivot.Clean();
}
//
result = ArraySize(pivots);
//
// Cleanup ...
bar.Clean();
pivot.Clean();
//
return result;
}
/**
* Collect SAR Pivots ...
*
* @param pivots: XPivot, reference collection to holds Detected Pivots ...
* @param barIndex: int, Specified Start Bar Index ...
* @param count: int, Specified number of required Pivots ...
* @param loopback: int, Max Allowed Loopback length for Detection ...
*
* @return ( int )
*/
int CollectSARPivots(
XPivot &pivots[],
int barIndex = 0,
int count = 50,
int loopback = 500 //
)
{
//
int result = 0;
//
// Prepare ...
XClean(pivots);
//
// Normalize ...
count = NormalizeInt(count, 0);
loopback = NormalizeInt(loopback, 50);
barIndex = fimaParser.NormalizeBarIndex(barIndex);
//
// Validate ...
bool has = fimaParser.IsValid();
if (!has)
{
return result;
}
//
// Do ...
XOHCL bar;
XPivot pivot;
int start = barIndex;
bool isBullish = false;
bool isBearish = false;
int end = start + loopback;
ENUM_X_DIRECTION dir = X_DIRECTION_NONE;
for (int i = start; i < end; i++)
{
//
isBullish = fimaParser.IsSARSwitchedToBullish(i);
isBearish = fimaParser.IsSARSwitchedToBearish(i);
//
has = isBullish || isBearish;
if (has)
{
//
// Specified Direction ...
dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
// Initialize Indexed Bar ...
// Validate it, and Converts it to Pivot ...
bar.Clean();
has = bar.Init(symbol, period, i);
has = has &&
ToPivot(
bar,
pivot,
dir,
ToXString(XFIMA_PIVOT_SAR_SWITCH) //
);
if (has)
{
//
// Add Detected Pivot ...
AddIfNotExists(pivot, pivots);
}
//
has = count <= 0
? false
: ArraySize(pivots) >= count;
if (has)
{
break;
}
}
//
// Cleanup ...
bar.Clean();
pivot.Clean();
}
//
result = ArraySize(pivots);
//
// Cleanup ...
bar.Clean();
pivot.Clean();
//
return result;
}
//
// Others ...
/**
* Destroy ...
*/
void Destroy()
{
//
delete barAnalyser;
ZeroMemory(barAnalyser);
//
ZeroMemory(fimaHelper);
ZeroMemory(fimaParser);
}
//
// Testers ...
//
// Protected ...
protected:
//
// Props ...
//
// Private ...
private:
//
//
};
//