Files
MQL5Data/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5
T

3699 lines
85 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Class Library
// --------------------------------------
// Name: XC121SMCCycleHelper
// Description: provides all based classes for use ...
//
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
//
// Global Properties ...
#property library
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://www.saherelm.ir"
#property version "1.00"
#property strict
//
// Imports ...
#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5"
#include "../../Classes/x-saherelm.x-poi.class.mq5"
#include "../Libraries/x-121.smc.lib.mq5"
//
// Definitions ...
//
// Implementations ...
enum ENUM_X_CYCLES
{
X_CYCLE_NONE,
X_CYCLE_TRIGGER,
X_CYCLE_DECISION,
X_CYCLE_ANALYSE,
X_CYCLE_VERIFICATION,
X_CYCLE_CONSOLIDATION,
X_CYCLE_VISION,
};
string ToString(ENUM_X_CYCLES value)
{
//
string result = EnumToString(value);
//
StringReplace(result, "X_CYCLE_", "");
//
return result;
}
enum ENUM_X_CYCLE_EVENTS
{
SAR_CHANGE_DETECTED,
NEW_PEAK_DETECTED,
NEW_VALE_DETECTED,
PIVOT_POINT_DETECTED,
VWAP_ORDER_CHANGE_ETECTED,
VWAP_STATE_CHANGE_DETCTED,
CONSOLIDATION_BREAKED_DETECTED,
PEAK_PIVOT_STARTED,
PEAK_PIVOT_ENDED,
VALE_PIVOT_STARTED,
VALE_PIVOT_ENDED,
};
class XC121SMCCycleHelper : public XCBase
{
//
public:
//
// Props ...
//
// X121 ...
XCX121Helper *mX121Helper;
//
// POI Detector ...
XCPOIDetector *mPOIDetector;
//
// Bar Analyser
XCBarAnalyser *mBarAnalyser;
//
// Constructor(s) ...
XC121SMCCycleHelper()
{
Default();
}
//
// Deconstructor ...
~XC121SMCCycleHelper()
{
DeInit();
}
//
// Getter/Setter(s) ...
/**
* Get Max llowed Changes to Save ...
*
* @return ( int )
*/
int MaxAllowedSavedChanges()
{
return mMaxAllowedSavedChanges;
}
/**
* Set Max llowed Changes to Save ...
*
* @param value: Integer ...
*/
void MaxAllowedSavedChanges(int value)
{
//
if (value < 10)
{
value = 10;
}
//
mMaxAllowedSavedChanges = value;
}
/**
* Get Consolidation Loopback Length ...
*
* @return ( int )
*/
int ConsolidationLoopback()
{
return mConsolidationLoopback;
}
/**
* Set Consolidation Loopback Length ...
*
* @param value: Integer ...
*/
void ConsolidationLoopback(int value)
{
//
if (value < 7)
{
value = 7;
}
//
mConsolidationLoopback = value;
}
/**
* Get Valid Pivot Points Repetition Length ...
* min => 7
*
* @return ( int )
*/
int ValidPivotRepetition()
{
return mValidPivotRepetition;
}
/**
* Set Valid Pivot Points Repetition Length ...
*
* @param value: Integer ...
* min => 7
*/
void ValidPivotRepetition(int value)
{
//
if (value < 7)
{
value = 7;
}
//
mValidPivotRepetition = value;
}
//
// Actions ...
/**
* Initialize ...
*
* @param symbol: String ...
* @param period: ENUM_TIMEFRAMES member ...
* @param x121Inputs: X121Inputs instance ...
*
* @return ( bool )
*/
bool Init(
string symbol,
ENUM_TIMEFRAMES period,
X121Inputs &x121Inputs //
)
{
//
bool result = false;
//
result = IsValid(symbol) &&
IsValid(period);
if (!result)
{
return result;
}
//
// X121 ...
mX121Helper = new XCX121Helper();
result = mX121Helper.Init(
symbol,
period,
x121Inputs //
);
if (!result)
{
return result;
}
//
mPOIDetector = new XCPOIDetector(
symbol,
period //
);
mPOIDetector.MaxNumberOfRequiredPOIs(10);
mPOIDetector.Init();
//
// Initialize Bar Analyser Class Instance ...
mBarAnalyser = new XCBarAnalyser();
//
// Set Chart Style ...
ApplyChartStyle();
//
return result;
}
/**
* Retrieve Symbol ...
*
* @return ( string )
*/
string GetSymbol()
{
//
string result = NULL;
//
result = mX121Helper.GetSymbol();
//
return result;
}
/**
* Retrieve TimeFrame (Period) ...
*
* @return ( ENUM_TIMEFRAMES )
*/
ENUM_TIMEFRAMES GetPeriod()
{
//
ENUM_TIMEFRAMES result = NULL;
//
result = mX121Helper.GetPeriod();
//
return result;
}
/**
* Get Specified Bar ...
*
* @param source: XOHCL instance, Source Bar ...
* @param bar: XOHCL instance, Dest Bar ...
*
* @return ( bool )
*/
bool GetBar(
XOHCL &source,
XOHCL &bar //
)
{
//
bool result = false;
//
bar.Clean();
//
string symbol = GetSymbol();
ENUM_TIMEFRAMES period = GetPeriod();
//
result =
IsValid(symbol) &&
IsValid(period) &&
source.IsValid();
if (!result)
{
return result;
}
//
int index = iBarShift(
symbol,
period,
source.time //
);
result = bar.Init(
symbol,
period,
index //
);
if (!result)
{
//
bar.Clean();
return result;
}
//
return result;
}
/**
* Retrieve Specified Bar ...
*
* @param bar: XOHCL instance ...
* @param index: Integer ...
*
* @return ( bool )
*/
bool GetBar(
XOHCL &bar,
int index = 0 //
)
{
//
bool result = false;
//
bar.Clean();
//
if (index < 0)
{
index = 0;
}
//
string symbol = GetSymbol();
ENUM_TIMEFRAMES period = GetPeriod();
//
result = bar.Init(
symbol,
period,
index //
);
//
return result;
}
/**
* Retrieve Specified Bar ...
*
* @param bar: XOHCL instance ...
* @param time: Datetime ...
*
* @return ( bool )
*/
bool GetBar(
XOHCL &bar,
datetime time = NULL //
)
{
//
bool result = false;
//
int index = GetBarIndex(time);
result = GetBar(bar,
index //
);
//
return result;
}
/**
* Retrieve Specified Time Bar Index ...
*
* @param time: DateTime ...
*
* @return ( int )
*/
int GetBarIndex(datetime time = NULL)
{
//
int result = -1;
//
time = NormalizeTime(time);
//
string symbol = GetSymbol();
ENUM_TIMEFRAMES period = GetPeriod();
//
result = iBarShift(
symbol,
period,
time //
);
//
return result;
}
/**
* Retrieve Cycle Conditions ...
*
* @param events: ENUM_X_CYCLE_EVENTS member, Array ...
* @param conditions: X121SMCCycleConditions instance ...
* @param barIndex: Integer ...
* @param loopback: Integer ...
*
* @return ( bool )
*/
bool GetConditions(
ENUM_X_CYCLE_EVENTS &events[],
ENUM_XPOI_EVENTS &poiEvents[],
X121SMCCycleConditions &conditions,
int barIndex = 0,
int loopback = 7 //
)
{
//
bool result = false;
//
if (barIndex < 0)
{
barIndex = 0;
}
//
if (loopback < 5)
{
loopback = 5;
}
//
Clean(events);
Clean(poiEvents);
conditions.Clean();
//
result = mX121Helper.GetConditions(
conditions.x121Conditions,
barIndex,
loopback //
);
if (!result)
{
//
conditions.Clean();
return result;
}
//
mPOIDetector.Update(poiEvents);
mPOIDetector.GetState(conditions.state);
//
conditions.symbol = conditions.x121Conditions.symbol;
conditions.period = conditions.x121Conditions.period;
conditions.time = TimeCurrent();
//
result = conditions.IsValid();
//
if (result)
{
//
if (!IsValidSize(ArraySize(mPivots)))
{
Detect(barIndex);
}
//
Calculate(
barIndex,
events,
conditions //
);
}
//
return result;
}
//
// Tools ...
/**
* Get POI State of Specified Pivot ...
*
* @param pivot: XPVPivot instance Reference ...
* @param lookupSwingHighs: Boolean ...
* @param lookupSwingLows: Boolean ...
* @param lookupSupportZones: Boolean ...
* @param lookupResistanceZones: Boolean ...
* @param lookupSupplyZones: Boolean ...
* @param lookupDemandZones: Boolean ...
* @param lookupBullishOrderBlocks: Boolean ...
* @param lookupBearishOrderBlocks: Boolean ...
* @param lookupBullishFairValueGaps: Boolean ...
* @param lookupBearishFairValueGaps: Boolean ...
* @param lookupBullishRejectionBars: Boolean ...
* @param lookupBearishRejectionBars: Boolean ...
* @param lookupBullishMomentumBars: Boolean ...
* @param lookupBearishMomentumBars: Boolean ...
*
* @return ( bool )
*/
bool FillPivotState(
XPVPivot &pivot,
bool lookupSwingHighs = true,
bool lookupSwingLows = true,
bool lookupSupportZones = true,
bool lookupResistanceZones = true,
bool lookupSupplyZones = true,
bool lookupDemandZones = true,
bool lookupBullishOrderBlocks = true,
bool lookupBearishOrderBlocks = true,
bool lookupBullishFairValueGaps = true,
bool lookupBearishFairValueGaps = true,
bool lookupBullishRejectionBars = true,
bool lookupBearishRejectionBars = true,
bool lookupBullishMomentumBars = true,
bool lookupBearishMomentumBars = true //
)
{
//
bool result = false;
//
XPOIState state;
state.Clean();
//
result = pivot.IsValid();
if (!result)
{
return result;
}
//
XPOIState _state;
mPOIDetector.GetState(_state);
result = _state.IsValid() &&
_state.HasChild();
if (!result)
{
return result;
}
//
DetectPivotPOIs(
pivot,
_state,
state,
lookupSwingHighs,
lookupSwingLows,
lookupSupportZones,
lookupResistanceZones,
lookupSupplyZones,
lookupDemandZones,
lookupBullishOrderBlocks,
lookupBearishOrderBlocks,
lookupBullishFairValueGaps,
lookupBearishFairValueGaps,
lookupBullishRejectionBars,
lookupBearishRejectionBars,
lookupBullishMomentumBars,
lookupBearishMomentumBars //
);
//
result = state.IsValid() &&
state.HasChild();
if (result)
{
//
pivot.state = state;
//
CalculatePivotTickZone(pivot);
}
//
return result;
}
/**
* Validate Specified Pivot's State ...
*
* @param pivot: XPVPivot instance Reference ...
* @param barIndex: Integer ...
*/
void ValidatePivotState(
XPVPivot &pivot,
int barIndex = 0 //
)
{
//
if (!pivot.IsValid() ||
!pivot.state.IsValid() ||
!pivot.state.HasChild())
{
return;
}
//
double upperr = pivot.upper;
double lower = pivot.lower;
//
XOHCL cBar;
bool isInited = cBar.Init(
pivot.symbol,
pivot.period,
barIndex //
);
if (!isInited)
{
return;
}
//
int count = 0;
//
double ask = GetAsk(pivot.symbol);
double bid = GetBid(pivot.symbol);
//
double pivotMid = pivot.CalculateMid();
//
// Try to Validate States ...
//
bool isPriceInPremium =
//
ask > pivotMid &&
bid > pivotMid &&
cBar.low > pivotMid
//
;
//
bool isPriceInDiscount =
//
ask < pivotMid &&
bid < pivotMid &&
cBar.high < pivotMid
//
;
//
// Swings ...
XCSwing *tmpSwings[];
//
// Swing Highs ...
Clean(tmpSwings);
count = pivot.state.CountSwingHighs();
if (IsValidSize(count))
{
//
if (isPriceInPremium)
{
//
for (int i = 0; i < count; i++)
{
//
XCSwing *iSwing = pivot.state.swingHighs[i];
//
bool isValid =
//
iSwing.GetTime() >= pivot.from &&
iSwing.GetTime() <= pivot.to &&
iSwing.GetValue() > pivotMid
//
;
if (isValid)
{
//
Add(
iSwing,
tmpSwings //
);
}
}
//
Copy(
tmpSwings,
pivot.state.swingHighs //
);
}
}
//
// Swing Lows ...
Clean(tmpSwings);
count = pivot.state.CountSwingLows();
if (IsValidSize(count))
{
//
if (isPriceInDiscount)
{
//
for (int i = 0; i < count; i++)
{
//
XCSwing *iSwing = pivot.state.swingLows[i];
//
bool isValid =
//
iSwing.GetTime() >= pivot.from &&
iSwing.GetTime() <= pivot.to &&
iSwing.GetValue() < pivotMid
//
;
if (isValid)
{
//
Add(
iSwing,
tmpSwings //
);
}
}
//
Copy(
tmpSwings,
pivot.state.swingLows //
);
}
}
//
Clean(tmpSwings);
//
// Rejection Bars ...
XCRejectionBar *tmpRejections[];
//
// Bullish ...
Clean(tmpRejections);
count = pivot.state.CountBullishRejectionBars();
if (IsValidSize(count))
{
//
if (isPriceInDiscount)
{
//
for (int i = 0; i < count; i++)
{
//
XCRejectionBar *iRejection = pivot.state.bullishRejectionBars[i];
//
XOHCL iBar;
bool isFilled = iRejection.FillBar(iBar);
if (!isFilled)
{
continue;
}
//
bool isValid =
//
iRejection.BarTime() >= pivot.from &&
iBar.high < pivotMid
//
;
if (isValid)
{
//
Add(
iRejection,
tmpRejections //
);
}
}
//
Copy(
tmpRejections,
pivot.state.bullishRejectionBars //
);
}
}
//
// Bearish ...
Clean(tmpRejections);
count = pivot.state.CountBearishRejectionBars();
if (IsValidSize(count))
{
//
if (isPriceInPremium)
{
//
for (int i = 0; i < count; i++)
{
//
XCRejectionBar *iRejection = pivot.state.bearishRejectionBars[i];
//
XOHCL iBar;
bool isFilled = iRejection.FillBar(iBar);
if (!isFilled)
{
continue;
}
//
bool isValid =
//
iRejection.BarTime() >= pivot.from &&
iBar.low > pivotMid
//
;
if (isValid)
{
//
Add(
iRejection,
tmpRejections //
);
}
}
//
Copy(
tmpRejections,
pivot.state.bearishRejectionBars //
);
}
}
//
Clean(tmpRejections);
//
// Support Zone ...
XCSupportZone *tmpSupports[];
count = pivot.state.CountSupportZones();
if (IsValidSize(count))
{
//
if (isPriceInDiscount)
{
//
for (int i = 0; i < count; i++)
{
//
XCSupportZone *iZone = pivot.state.supportZones[i];
//
bool isValid =
//
iZone.Upper() < pivotMid
//
;
if (isValid)
{
//
Add(
iZone,
tmpSupports //
);
}
}
//
Copy(
tmpSupports,
pivot.state.supportZones //
);
}
}
//
Clean(tmpSupports);
//
// Resistance Zone ...
XCResistanceZone *tmpResistances[];
count = pivot.state.CountResistanceZones();
if (IsValidSize(count))
{
//
if (isPriceInPremium)
{
//
for (int i = 0; i < count; i++)
{
//
XCResistanceZone *iZone = pivot.state.resistanceZones[i];
//
bool isValid =
//
iZone.Lower() > pivotMid
//
;
if (isValid)
{
//
Add(
iZone,
tmpResistances //
);
}
}
//
Copy(
tmpResistances,
pivot.state.resistanceZones //
);
}
}
//
Clean(tmpResistances);
//
// Supply Zones ...
XCSupplyZone *tmpSupplies[];
count = pivot.state.CountSupplyZones();
if (IsValidSize(count))
{
//
if (isPriceInPremium)
{
//
for (int i = 0; i < count; i++)
{
//
XCSupplyZone *iZone = pivot.state.supplyZones[i];
//
bool isValid =
//
iZone.Lower() > pivotMid
//
;
if (isValid)
{
//
Add(
iZone,
tmpSupplies //
);
}
}
//
Copy(
tmpSupplies,
pivot.state.supplyZones //
);
}
}
//
Clean(tmpSupplies);
//
// Demand Zones ...
XCDemandZone *tmpDemands[];
count = pivot.state.CountDemandZones();
if (IsValidSize(count))
{
//
if (isPriceInDiscount)
{
//
for (int i = 0; i < count; i++)
{
//
XCDemandZone *iZone = pivot.state.demandZones[i];
//
bool isValid =
//
iZone.Upper() < pivotMid
//
;
if (isValid)
{
//
Add(
iZone,
tmpDemands //
);
}
}
//
Copy(
tmpDemands,
pivot.state.demandZones //
);
}
}
//
Clean(tmpDemands);
//
// Order Blocks ...
XCOrderBlock *tmpOrderBlocks[];
//
// Bullish ...
Clean(tmpOrderBlocks);
count = pivot.state.CountBullishOrderBlocks();
if (IsValidSize(count))
{
//
if (isPriceInDiscount)
{
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *iZone = pivot.state.bullishOrderBlocks[i];
//
bool isValid =
//
iZone.Upper() < pivotMid
//
;
if (isValid)
{
//
Add(
iZone,
tmpOrderBlocks //
);
}
}
//
Copy(
tmpOrderBlocks,
pivot.state.bullishOrderBlocks //
);
}
}
//
// Bearish ...
Clean(tmpOrderBlocks);
count = pivot.state.CountBearishOrderBlocks();
if (IsValidSize(count))
{
//
if (isPriceInPremium)
{
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *iZone = pivot.state.bearishOrderBlocks[i];
//
bool isValid =
//
iZone.Lower() > pivotMid
//
;
if (isValid)
{
//
Add(
iZone,
tmpOrderBlocks //
);
}
}
//
Copy(
tmpOrderBlocks,
pivot.state.bearishOrderBlocks //
);
}
}
//
Clean(tmpOrderBlocks);
//
// Fair Value Gaps ...
XCFVG *tmpFVGs[];
//
// Bullish ...
Clean(tmpFVGs);
count = pivot.state.CountBullishFairValueGaps();
if (IsValidSize(count))
{
//
if (isPriceInDiscount)
{
//
for (int i = 0; i < count; i++)
{
//
XCFVG *iZone = pivot.state.bullishFairValueGaps[i];
//
bool isValid =
//
iZone.Upper() < pivotMid
//
;
if (isValid)
{
//
Add(
iZone,
tmpFVGs //
);
}
}
//
Copy(
tmpFVGs,
pivot.state.bullishFairValueGaps //
);
}
}
//
// Bearish ...
Clean(tmpFVGs);
count = pivot.state.CountBearishFairValueGaps();
if (IsValidSize(count))
{
//
if (isPriceInPremium)
{
//
for (int i = 0; i < count; i++)
{
//
XCFVG *iZone = pivot.state.bearishFairValueGaps[i];
//
bool isValid =
//
iZone.Lower() > pivotMid
//
;
if (isValid)
{
//
Add(
iZone,
tmpFVGs //
);
}
}
//
Copy(
tmpFVGs,
pivot.state.bearishFairValueGaps //
);
}
}
//
Clean(tmpFVGs);
//
}
/**
* Detect Cycle Trend Based On Pivots ...
*
* @param dir: ENUM_X_DIRECTION member Reference ...
* @param numberOfPivots: Integer ...
* @param maxAllowedLoopback: Integer ...
* @param minRequiredPivotVerification: Integer ...
*
* @return ( bool )
*/
bool DetectTrend(
ENUM_X_DIRECTION &dir,
int numberOfPivots = 3,
int maxAllowedLoopback = 576,
int minRequiredPivotVerification = 5 //
)
{
//
bool result = false;
//
dir = X_DIRECTION_NONE;
//
if (numberOfPivots < 3)
{
numberOfPivots = 3;
}
//
int index = 0;
double peaks[];
double vales[];
double peak = 0;
double vale = 0;
int peaksVerified = 0;
int valesVerified = 0;
bool canContinue = true;
while (canContinue)
{
//
// Peak ...
bool lookupPeak = ArraySize(peaks) < numberOfPivots;
if (lookupPeak)
{
//
double iPeak = mX121Helper.GetPeak(index);
if (iPeak == peak)
{
peaksVerified++;
}
else
{
//
if (peaksVerified >= minRequiredPivotVerification)
{
//
Add(
iPeak,
peaks //
);
//
peaksVerified = 0;
lookupPeak = ArraySize(peaks) < numberOfPivots;
}
else
{
peak = iPeak;
}
}
}
//
// Vale ...
bool lookupVale = ArraySize(vales) < numberOfPivots;
if (lookupVale)
{
//
double iVale = mX121Helper.GetVale(index);
if (iVale == vale)
{
valesVerified++;
}
else
{
//
if (valesVerified >= minRequiredPivotVerification)
{
//
Add(
iVale,
vales //
);
//
valesVerified = 0;
lookupVale = ArraySize(vales) < numberOfPivots;
}
else
{
vale = iVale;
}
}
}
//
canContinue = index < maxAllowedLoopback &&
(lookupPeak ||
lookupVale);
if (canContinue)
{
index++;
}
}
//
int verifications = 0;
//
// Peaks ...
int peaksCount = ArraySize(peaks);
if (!result &&
peaksCount == numberOfPivots)
{
//
verifications = 0;
for (int i = 0; i < peaksCount - 1; i++)
{
//
double iValue = peaks[i];
double nValue = peaks[i + 1];
if (iValue < nValue)
{
verifications++;
}
}
//
result = verifications == numberOfPivots - 1;
if (result)
{
dir = X_DIRECTION_BEARISH;
}
}
//
// Vales ...
int valesCount = ArraySize(vales);
if (!result &&
valesCount == numberOfPivots)
{
//
verifications = 0;
for (int i = 0; i < valesCount - 1; i++)
{
//
double iValue = vales[i];
double nValue = vales[i + 1];
if (iValue > nValue)
{
verifications++;
}
}
//
result = verifications == numberOfPivots - 1;
if (result)
{
dir = X_DIRECTION_BULLISH;
}
}
//
return result;
}
/**
* Detect Market Structure based on Peaks and Vales ...
*
* @param dir: ENUM_X_DIRECTION member Reference ...
* @param minVerification: Integer ...
*
* @return ( bool )
*/
bool HasPVDirection(
ENUM_X_DIRECTION &dir,
int minVerification = 12 //
)
{
//
bool result = false;
//
if (minVerification < 7)
{
minVerification = 7;
}
//
dir = X_DIRECTION_NONE;
//
int bullishSum = mBullishPeaks + mBullishVales;
int bearishSum = mBearishPeaks + mBearishVales;
//
int diff = MathAbs(bullishSum - bearishSum);
bool isDiffPassed = diff >= minVerification;
result = isDiffPassed;
if (!result)
{
return result;
}
//
dir = bullishSum > bearishSum
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
return result;
}
//
// Change Values Actions ...
/**
* Count Saved Parabolic Sar Changes ...
*
* @return ( int )
*/
int CountSarChanges()
{
return ArraySize(mSarChanges);
}
/**
* Fill Saved Sar Changes ...
*
* @param changes: XValueChange instance Array Reference ...
*
* @return ( int )
*/
int FillSarChanges(
XValueChange &changes[] //
)
{
//
Clean(changes);
//
Copy(
mSarChanges,
changes //
);
//
int result = ArraySize(changes);
//
return result;
}
/**
* Retrieve Last Sar Changes ...
*
* @param change: XValueChange instance ...
*
* @return ( bool )
*/
bool GetLastSarChange(XValueChange &change)
{
//
bool result = false;
//
result = GetLastItem(
change,
mSarChanges //
);
//
return result;
}
/**
* Count Saved Peaks Changes ...
*
* @return ( int )
*/
int CountPeaksChanges()
{
return ArraySize(mPeaksChanges);
}
/**
* Fill Saved Peaks Changes ...
*
* @param changes: XValueChange instance Array Reference ...
*
* @return ( int )
*/
int FillPeaksChanges(
XValueChange &changes[] //
)
{
//
Clean(changes);
//
Copy(
mPeaksChanges,
changes //
);
//
int result = ArraySize(changes);
//
return result;
}
/**
* Retrieve Last Peak Changes ...
*
* @param change: XValueChange instance ...
*
* @return ( bool )
*/
bool GetLastPeakChange(XValueChange &change)
{
//
bool result = false;
//
result = GetLastItem(
change,
mPeaksChanges //
);
//
return result;
}
/**
* Count Saved Vales Changes ...
*
* @return ( int )
*/
int CountValesChanges()
{
return ArraySize(mValesChanges);
}
/**
* Fill Saved Vales Changes ...
*
* @param changes: XValueChange instance Array Reference ...
*
* @return ( int )
*/
int FillValesChanges(
XValueChange &changes[] //
)
{
//
Clean(changes);
//
Copy(
mValesChanges,
changes //
);
//
int result = ArraySize(changes);
//
return result;
}
/**
* Retrieve Last Vale Changes ...
*
* @param change: XValueChange instance ...
*
* @return ( bool )
*/
bool GetLastValeChange(XValueChange &change)
{
//
bool result = false;
//
result = GetLastItem(
change,
mValesChanges //
);
//
return result;
}
/**
* Count Saved VWap Order Changes ...
*
* @return ( int )
*/
int CountVWapOrderChanges()
{
return ArraySize(mVWapOrderChanges);
}
/**
* Fill Saved VWap Order Changes ...
*
* @param changes: XValueChange instance Array Reference ...
*
* @return ( int )
*/
int FillVWapOrderChanges(
XValueChange &changes[] //
)
{
//
Clean(changes);
//
Copy(
mVWapOrderChanges,
changes //
);
//
int result = ArraySize(changes);
//
return result;
}
/**
* Retrieve Last VWap Order Changes ...
*
* @param change: XValueChange instance ...
*
* @return ( bool )
*/
bool GetLastVWapOrderChange(XValueChange &change)
{
//
bool result = false;
//
result = GetLastItem(
change,
mVWapOrderChanges //
);
//
return result;
}
/**
* Count Saved VWap State Changes ...
*
* @return ( int )
*/
int CountVWapStateChanges()
{
return ArraySize(mVWapStateChanges);
}
/**
* Fill Saved VWap State Changes ...
*
* @param changes: XValueChange instance Array Reference ...
*
* @return ( int )
*/
int FillVWapStateChanges(
XValueChange &changes[] //
)
{
//
Clean(changes);
//
Copy(
mVWapStateChanges,
changes //
);
//
int result = ArraySize(changes);
//
return result;
}
/**
* Retrieve Last VWap State Changes ...
*
* @param change: XValueChange instance ...
*
* @return ( bool )
*/
bool GetLastVWapStateChange(XValueChange &change)
{
//
bool result = false;
//
result = GetLastItem(
change,
mVWapStateChanges //
);
//
return result;
}
/**
* Count Founded Consolidation Zones ...
*
* @return ( int )
*/
int CountConsolidationZones()
{
return ArraySize(mConsolidationZones);
}
/**
* Fill Broken Consolidations ...
*
* @param consolidations: XConsolidationZone instance Array Reference ...
*
* @return ( int )
*/
int FillConsolidationZones(
XConsolidationZone &consolidations[] //
)
{
//
Clean(consolidations);
//
Copy(
mConsolidationZones,
consolidations //
);
//
int result = ArraySize(consolidations);
//
return result;
}
/**
* Retrieve Last Consolidation Breaks ...
*
* @param change: XValueChange instance ...
*
* @return ( bool )
*/
bool GetLastConsolidationZone(XConsolidationZone &zone)
{
//
bool result = false;
//
result = GetLastItem(
zone,
mConsolidationZones //
);
//
return result;
}
/**
* Count Pivot Points Change ...
*
* @return ( int )
*/
int CountPivotPoints()
{
return ArraySize(mPivotPoints);
}
/**
* Retrieve All Pivot Point Changes as a Collection ...
*
* @param pivots: XPVPivotPoint instance Reference ...
*
* @return ( int )
*/
int FillPivotPoints(XPVPivotPoint &pivots[])
{
//
int result = 0;
//
Clean(pivots);
//
int count = CountPivotPoints();
if (!IsValidSize(pivots))
{
return result;
}
//
Copy(
mPivotPoints,
pivots //
);
//
result = ArraySize(pivots);
//
return result;
}
/**
* Retrieve All Peak Pivot Point Changes as a Collection ...
*
* @param pivots: XPVPivotPoint instance Reference ...
*
* @return ( int )
*/
int FillPeakPivotPoints(XPVPivotPoint &pivots[])
{
//
int result = 0;
//
Clean(pivots);
//
int count = CountPivotPoints();
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
XPVPivotPoint iPivot = mPivotPoints[i];
//
bool isValid = iPivot.IsPeak();
if (isValid)
{
//
AddRef(
iPivot,
pivots //
);
}
}
//
result = ArraySize(pivots);
//
return result;
}
/**
* Get Last Peaks Pivot Point ...
*
* @param pivot: XPVPivotPoint instance Reference ...
*
* @return ( bool )
*/
bool GetLastPeakPivotPoint(XPVPivotPoint &pivot)
{
//
bool result = false;
//
pivot.Clean();
//
XPVPivotPoint pivots[];
int count = FillPeakPivotPoints(pivots);
result = IsValidSize(count);
if (!result)
{
return result;
}
//
pivot = pivots[count - 1];
//
return result;
}
/**
* Retrieve All Vale Pivot Point Changes as a Collection ...
*
* @param pivots: XPVPivotPoint instance Reference ...
*
* @return ( int )
*/
int FillValePivotPoints(XPVPivotPoint &pivots[])
{
//
int result = 0;
//
Clean(pivots);
//
int count = CountPivotPoints();
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
XPVPivotPoint iPivot = mPivotPoints[i];
//
bool isValid = iPivot.IsVale();
if (isValid)
{
//
AddRef(
iPivot,
pivots //
);
}
}
//
result = ArraySize(pivots);
//
return result;
}
/**
* Get Last Vale Pivot Point ...
*
* @param pivot: XPVPivotPoint instance Reference ...
*
* @return ( bool )
*/
bool GetLastValePivotPoint(XPVPivotPoint &pivot)
{
//
bool result = false;
//
pivot.Clean();
//
XPVPivotPoint pivots[];
int count = FillValePivotPoints(pivots);
result = IsValidSize(count);
if (!result)
{
return result;
}
//
pivot = pivots[count - 1];
//
return result;
}
/**
* Count Calculated Pivots ...
*
* @return ( int )
*/
int CountPivots()
{
return ArraySize(mPivots);
}
/**
* Fill Pivots ...
*
* @param pivots: XPVPivot instance Reference Array ...
*
* @return ( int )
*/
int FillPivots(XPVPivot &pivots[])
{
//
int result = 0;
//
Clean(pivots);
//
Copy(
mPivots,
pivots //
);
//
result = ArraySize(pivots);
//
return result;
}
/**
* Retrieve Last Pivot ...
*
* @param pivot: XPVPivot instance Reference ...
*
* @return ( bool )
*/
bool GetLastPivot(XPVPivot &pivot)
{
//
bool result = false;
//
pivot.Clean();
//
XPVPivot pivots[];
int count = FillPivots(pivots);
if (IsValidSize(count))
{
pivot = pivots[count - 1];
}
//
result = pivot.IsValid();
//
return result;
}
/**
* Retrieve Active Peak Pivot ...
*
* @param pivot: XPVPivot instance Reference ...
*
* @return ( bool )
*/
bool GetActivePeakPivot(XPVPivot &pivot)
{
//
bool result = false;
//
pivot.Clean();
//
pivot = mActivePeakPivot;
//
result = pivot.IsValid();
//
return result;
}
/**
* Retrieve Active Vale Pivot ...
*
* @param pivot: XPVPivot instance Reference ...
*
* @return ( bool )
*/
bool GetActiveValePivot(XPVPivot &pivot)
{
//
bool result = false;
//
pivot.Clean();
//
pivot = mActiveValePivot;
//
result = pivot.IsValid();
//
return result;
}
//
// Virtuals ...
/**
* Set Default Properties Values ...
*/
virtual void Default()
{
//
ValidPivotRepetition(21);
ConsolidationLoopback(10);
MaxAllowedSavedChanges(50);
}
//
protected:
//
/**
* Calculate Requirements ...
*
* @param barIndex: Integer, Bar Index ...
* @param events: ENUM_X_CYCLE_EVENTS member, Array ...
* @param conditions: X121SMCCycleConditions instance ...
*/
void Calculate(
int barIndex,
ENUM_X_CYCLE_EVENTS &events[],
X121SMCCycleConditions &conditions //
)
{
//
Clean(events);
//
string symbol = GetSymbol();
datetime cTime = TimeCurrent();
ENUM_TIMEFRAMES period = GetPeriod();
//
XOHCL changeBar;
int index =
barIndex <= 0
? 1
: barIndex;
bool isInited = GetBar(
changeBar,
index //
);
if (!isInited)
{
return;
}
//
// Detect Sar Change ...
bool isSarSwitchedToBullish = conditions.x121Conditions.isSarSwitchedToBullish;
bool isSarSwitchedToBearish = conditions.x121Conditions.isSarSwitchedToBearish;
bool isSarChanged = isSarSwitchedToBullish ||
isSarSwitchedToBearish;
//
if (isSarChanged)
{
//
XValueChange sarChanged;
//
datetime time = changeBar.time;
double after = conditions.x121Conditions.sarBuffer[1];
double before = conditions.x121Conditions.sarBuffer[2];
ENUM_X_DIRECTION dir =
isSarSwitchedToBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
// Initialize Model ...
isInited = sarChanged.Init(
before,
after,
dir,
time //
);
if (isInited)
{
//
isInited = AddSarChange(sarChanged);
//
if (isInited)
{
//
Add(
SAR_CHANGE_DETECTED,
events //
);
}
}
}
//
// Detect Peaks Changes ...
//
bool isNewPeak = conditions.x121Conditions.isNewPeak;
double peak = conditions.x121Conditions.peaksBuffer[1];
double peakPrev = conditions.x121Conditions.peaksBuffer[2];
bool isPeakSameAsPrev = peak == peakPrev;
bool isNewPeakOverLast = conditions.x121Conditions.isNewPeakOverLast;
bool isNewPeakUnderLast = conditions.x121Conditions.isNewPeakUnderLast;
//
if (isNewPeak)
{
//
XValueChange peaksChanged;
//
datetime time = changeBar.time;
double after = conditions.x121Conditions.peaksBuffer[1];
double before = conditions.x121Conditions.peaksBuffer[2];
ENUM_X_DIRECTION dir =
isNewPeakOverLast
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
// Initialize Model ...
isInited = peaksChanged.Init(
before,
after,
dir,
time //
);
if (isInited)
{
//
isInited = AddPeaksChange(peaksChanged);
//
if (isInited)
{
//
Add(
NEW_PEAK_DETECTED,
events //
);
}
}
}
//
// Detect Vales Changes ...
//
bool isNewVale = conditions.x121Conditions.isNewVale;
double vale = conditions.x121Conditions.valesBuffer[1];
double valePrev = conditions.x121Conditions.valesBuffer[2];
bool isValeSameAsPrev = vale == valePrev;
bool isNewValeOverLast = conditions.x121Conditions.isNewValeOverLast;
bool isNewValeUnderLast = conditions.x121Conditions.isNewValeUnderLast;
//
if (isNewVale)
{
//
XValueChange valesChanged;
//
datetime time = changeBar.time;
double after = conditions.x121Conditions.valesBuffer[1];
double before = conditions.x121Conditions.valesBuffer[2];
ENUM_X_DIRECTION dir =
isNewValeUnderLast
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
// Initialize Model ...
isInited = valesChanged.Init(
before,
after,
dir,
time //
);
if (isInited)
{
//
isInited = AddValesChange(valesChanged);
//
if (isInited)
{
//
Add(
NEW_VALE_DETECTED,
events //
);
}
}
}
//
// Count Bullish / Bearish Peaks and Vales ...
//
// Peaks ...
//
if (isNewPeakOverLast)
{
//
mBullishPeaks++;
mIsLastPeakBullish = true;
}
//
if (isNewPeakUnderLast)
{
//
mBearishPeaks++;
mIsLastPeakBullish = false;
}
//
if (isPeakSameAsPrev)
{
//
if (mIsLastPeakBullish)
{
//
mBullishPeaks++;
mBearishPeaks--;
if (mBearishPeaks < 0)
{
mBearishPeaks = 0;
}
}
else
{
//
mBullishPeaks--;
mBearishPeaks++;
if (mBullishPeaks < 0)
{
mBullishPeaks = 0;
}
}
}
//
// Vales ...
//
if (isNewValeOverLast)
{
//
mBullishVales++;
mIsLastValeBullish = true;
}
//
if (isNewValeUnderLast)
{
//
mBearishVales++;
mIsLastValeBullish = false;
}
//
if (isValeSameAsPrev)
{
//
if (mIsLastValeBullish)
{
//
mBullishVales++;
mBearishVales--;
if (mBearishVales < 0)
{
mBearishVales = 0;
}
}
else
{
//
mBullishVales--;
mBearishVales++;
if (mBullishVales < 0)
{
mBullishVales = 0;
}
}
}
//
// VWap Direction Change ...
//
// Ordered Change ...
bool isVWapSwitchedToBullishOrdered =
conditions.x121Conditions.isVWapSwitchedToBullishOrdered;
bool isVWapSwitchedToBearishOrdered =
conditions.x121Conditions.isVWapSwitchedToBearishOrdered;
bool isVWAPOrderedChanged = isVWapSwitchedToBullishOrdered ||
isVWapSwitchedToBearishOrdered;
//
if (isVWAPOrderedChanged)
{
//
XValueChange vwapOrderChanged;
//
datetime time = changeBar.time;
ENUM_X_DIRECTION dir =
isVWapSwitchedToBullishOrdered
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
double after = 0;
double before = 0;
if (isVWapSwitchedToBullishOrdered)
{
//
// After Max ...
after = MathMax(
conditions.x121Conditions.vwapFastBuffer[1],
conditions.x121Conditions.vwapMidBuffer[1] //
);
after = MathMax(
after,
conditions.x121Conditions.vwapSlowBuffer[1] //
);
//
// Before Min ...
before = MathMin(
conditions.x121Conditions.vwapFastBuffer[1],
conditions.x121Conditions.vwapMidBuffer[1] //
);
before = MathMin(
before,
conditions.x121Conditions.vwapSlowBuffer[1] //
);
}
else
{
//
// After Min ...
after = MathMin(
conditions.x121Conditions.vwapFastBuffer[1],
conditions.x121Conditions.vwapMidBuffer[1] //
);
after = MathMin(
after,
conditions.x121Conditions.vwapSlowBuffer[1] //
);
//
// Before Max ...
before = MathMax(
conditions.x121Conditions.vwapFastBuffer[1],
conditions.x121Conditions.vwapMidBuffer[1] //
);
before = MathMax(
before,
conditions.x121Conditions.vwapSlowBuffer[1] //
);
}
//
// Initialize Model ...
isInited = vwapOrderChanged.Init(
before,
after,
dir,
time //
);
if (isInited)
{
//
isInited = AddVWapOrderChange(vwapOrderChanged);
//
if (isInited)
{
//
Add(
VWAP_ORDER_CHANGE_ETECTED,
events //
);
}
}
}
//
// States Changed ...
bool isVWapSwitchedToBullishState =
conditions.x121Conditions.isVWapSwitchedToBullishState;
bool isVWapSwitchedToBearishState =
conditions.x121Conditions.isVWapSwitchedToBearishState;
bool isVWapStatesChanged = isVWapSwitchedToBullishState ||
isVWapSwitchedToBearishState;
//
if (isVWapStatesChanged)
{
//
XValueChange vwapStateChanged;
//
datetime time = changeBar.time;
ENUM_X_DIRECTION dir =
isVWapSwitchedToBullishState
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
double after = 0;
double before = 0;
if (isVWapSwitchedToBullishState)
{
//
// After Max ...
after = MathMax(
conditions.x121Conditions.vwapFastBuffer[1],
conditions.x121Conditions.vwapMidBuffer[1] //
);
after = MathMax(
after,
conditions.x121Conditions.vwapSlowBuffer[1] //
);
//
// Before Min ...
before = MathMin(
conditions.x121Conditions.vwapFastBuffer[1],
conditions.x121Conditions.vwapMidBuffer[1] //
);
before = MathMin(
before,
conditions.x121Conditions.vwapSlowBuffer[1] //
);
}
else
{
//
// After Min ...
after = MathMin(
conditions.x121Conditions.vwapFastBuffer[1],
conditions.x121Conditions.vwapMidBuffer[1] //
);
after = MathMin(
after,
conditions.x121Conditions.vwapSlowBuffer[1] //
);
//
// Before Max ...
before = MathMax(
conditions.x121Conditions.vwapFastBuffer[1],
conditions.x121Conditions.vwapMidBuffer[1] //
);
before = MathMax(
before,
conditions.x121Conditions.vwapSlowBuffer[1] //
);
}
//
// Initialize Model ...
isInited = vwapStateChanged.Init(
before,
after,
dir,
time //
);
if (isInited)
{
//
isInited = AddVWapStateChange(vwapStateChanged);
//
if (isInited)
{
//
Add(
VWAP_STATE_CHANGE_DETCTED,
events //
);
}
}
}
//
// Detect Consolidations ...
//
int consolidationLoopback = ConsolidationLoopback();
if (IsValidSize(consolidationLoopback))
{
//
double upper = 0;
double lower = 0;
bool hasConsolidation =
mBarAnalyser.IsConsolidate(
changeBar,
upper,
lower,
consolidationLoopback //
);
//
if (hasConsolidation &&
!mActiveConsolidationZone.IsValid())
{
//
// Initialize Consolidation Zone ...
bool isInited = mActiveConsolidationZone.Init(
changeBar.symbol,
changeBar.period,
upper,
lower,
consolidationLoopback //
);
}
//
if (!hasConsolidation &&
mActiveConsolidationZone.IsValid())
{
//
mActiveConsolidationZone.Update();
bool isBreaked = mActiveConsolidationZone.IsBreaked();
//
if (isBreaked)
{
//
// Add Active to List ...
bool isInited = AddConsolidationZone(mActiveConsolidationZone);
if (isInited)
{
//
// Clean Active Zone ...
mActiveConsolidationZone.Clean();
//
Add(
CONSOLIDATION_BREAKED_DETECTED,
events //
);
}
}
}
//
// Draw ...
// if (mActiveConsolidationZone.IsValid())
// {
// //
// if (mActiveConsolidationZoneObj != NULL)
// {
// mActiveConsolidationZoneObj.Delete();
// }
// //
// bool isCreated = mPOIDetector.mDrawer.CreateConsolidationZone(
// mActiveConsolidationZone,
// mActiveConsolidationZoneObj //
// );
// }
}
//
// Check Valid Peaks and Vales ...
if (isNewPeak || isNewVale)
{
//
int count = 0;
double value = 0;
int repetition = 0;
ENUM_TIMEFRAMES period = GetPeriod();
int periodSeconds = PeriodSeconds(period);
int minRepetition = ValidPivotRepetition();
ENUM_XPV_PIVOTS type = isNewPeak
? XPV_PEAK
: XPV_VALE;
//
XValueChange lastChange;
XValueChange prevChange;
//
count = CountPeaksChanges();
if (isNewPeak && count >= 2)
{
//
lastChange = mPeaksChanges[count - 1];
prevChange = mPeaksChanges[count - 2];
}
//
count = CountValesChanges();
if (isNewVale && count >= 2)
{
//
lastChange = mValesChanges[count - 1];
prevChange = mValesChanges[count - 2];
}
//
if (lastChange.IsValid() &&
prevChange.IsValid())
{
//
value = prevChange.after;
int delayTime = ((int)lastChange.time - (int)prevChange.time);
repetition = delayTime / periodSeconds;
//
bool isValidPivot = repetition >= minRepetition;
if (isValidPivot)
{
//
XPVPivotPoint pivotPoint;
pivotPoint.type = type;
pivotPoint.value = value;
pivotPoint.time = prevChange.time;
pivotPoint.repetition = repetition;
//
bool isInited = AddPivotPoint(pivotPoint);
if (isInited)
{
//
Add(
PIVOT_POINT_DETECTED,
events //
);
}
}
}
}
//
// Calculate XPVPivot ...
int pvValidation = ValidPivotRepetition();
if (IsValidSize(pvValidation))
{
//
// Peak ...
mActivePeakPivot.symbol = symbol;
mActivePeakPivot.period = period;
mActivePeakPivot.type = XPV_PEAK;
//
if (mActivePeakPivot.upper == 0 && peak > 0)
{
//
mActivePeakPivot.upper = peak;
mActivePeakPivot.lower = vale;
mActivePeakPivot.from = changeBar.time;
//
Add(
PEAK_PIVOT_STARTED,
events //
);
}
else if (mActivePeakPivot.upper > 0 && mActivePeakPivot.upper == peak)
{
//
mActivePeakPivot.repetition++;
mActivePeakPivot.to = changeBar.time;
//
if (mActivePeakPivot.IsValid())
{
//
FillPivotState(mActivePeakPivot);
ValidatePivotState(mActivePeakPivot, barIndex);
}
}
else if (mActivePeakPivot.upper > 0 && mActivePeakPivot.upper != peak)
{
//
if (mActivePeakPivot.repetition >= pvValidation)
{
//
bool isInited = AddPivot(mActivePeakPivot);
if (isInited)
{
//
Add(
PEAK_PIVOT_ENDED,
events //
);
//
mActivePeakPivot.Clean();
}
}
else
{
//
mActivePeakPivot.upper = peak;
mActivePeakPivot.lower = vale;
mActivePeakPivot.repetition = 0;
mActivePeakPivot.from = changeBar.time;
//
Add(
PEAK_PIVOT_STARTED,
events //
);
}
}
//
// Vale ...
mActiveValePivot.symbol = symbol;
mActiveValePivot.period = period;
mActiveValePivot.type = XPV_VALE;
//
// Peak ...
if (mActiveValePivot.lower == 0 && vale > 0)
{
//
mActiveValePivot.lower = vale;
mActiveValePivot.upper = peak;
mActiveValePivot.from = changeBar.time;
//
Add(
VALE_PIVOT_STARTED,
events //
);
}
else if (mActiveValePivot.lower > 0 && mActiveValePivot.lower == vale)
{
//
mActiveValePivot.repetition++;
mActiveValePivot.to = changeBar.time;
//
if (mActiveValePivot.IsValid())
{
//
FillPivotState(mActiveValePivot);
ValidatePivotState(mActiveValePivot, barIndex);
}
}
else if (mActiveValePivot.lower > 0 && mActiveValePivot.lower != vale)
{
//
if (mActiveValePivot.repetition >= pvValidation)
{
//
bool isInited = AddPivot(mActiveValePivot);
if (isInited)
{
//
Add(
VALE_PIVOT_ENDED,
events //
);
//
mActiveValePivot.Clean();
}
}
else
{
//
mActiveValePivot.lower = vale;
mActiveValePivot.upper = peak;
mActiveValePivot.repetition = 0;
mActiveValePivot.from = changeBar.time;
//
Add(
VALE_PIVOT_STARTED,
events //
);
}
}
}
}
/**
* Detect Requirements ...
*/
void Detect(int barIndex)
{
//
if (isDetecting)
{
return;
}
//
int start = barIndex;
int max = 576;
int validPivotRepetition = ValidPivotRepetition();
//
string symbol = GetSymbol();
ENUM_TIMEFRAMES period = GetPeriod();
//
// Try To Detect Valid Peaks or Vales ...
double peak = 0;
double vale = 0;
int peakRepetition = 0;
int valeRepetition = 0;
//
int from = start;
int index = from;
int count = start + max;
//
bool canContinue = true;
//
// Loop Throug Peaks and Vales ...
while (canContinue)
{
//
datetime toTime = iTime(
symbol,
period,
index //
);
//
double iPeak = mX121Helper.GetPeak(index);
double iVale = mX121Helper.GetVale(index);
//
// Peak ...
if (peak == 0 && iPeak > 0)
{
//
peak = iPeak;
peakRepetition = 0;
}
else if (peak > 0 && iPeak > 0 && peak == iPeak)
{
peakRepetition++;
}
else if (peak > 0 && iPeak > 0 && peak != iPeak)
{
//
if (peakRepetition >= validPivotRepetition)
{
//
datetime fromTime = iTime(
symbol,
period,
index - peakRepetition //
);
//
// Create XPVPivotPoint ...
XPVPivotPoint pivotPoint;
pivotPoint.value = iPeak;
pivotPoint.time = toTime;
pivotPoint.type = XPV_PEAK;
pivotPoint.repetition = peakRepetition;
if (pivotPoint.IsValid())
{
//
AddRef(
pivotPoint,
mPivotPoints //
);
}
//
// Create XPVPivot ...
XPVPivot pivot;
pivot.symbol = symbol;
pivot.period = period;
pivot.from = fromTime;
pivot.to = toTime;
pivot.repetition = peakRepetition;
pivot.type = XPV_PEAK;
pivot.upper = peak;
pivot.lower = iVale;
FillPivotState(pivot);
//
if (pivot.IsValid())
{
//
AddRef(
pivot,
mPivots //
);
}
}
//
peak = iPeak;
peakRepetition = 0;
}
//
// Vale ...
if (vale == 0 && iVale > 0)
{
//
vale = iVale;
valeRepetition = 0;
}
else if (vale > 0 && iVale > 0 && vale == iVale)
{
valeRepetition++;
}
else if (vale > 0 && iVale > 0 && vale != iVale)
{
//
if (valeRepetition >= validPivotRepetition)
{
//
datetime fromTime = iTime(
symbol,
period,
index - valeRepetition //
);
//
// Create XPVPivotPoint ...
XPVPivotPoint pivotPoint;
pivotPoint.value = iVale;
pivotPoint.time = toTime;
pivotPoint.type = XPV_VALE;
pivotPoint.repetition = valeRepetition;
if (pivotPoint.IsValid())
{
//
AddRef(
pivotPoint,
mPivotPoints //
);
}
//
// Create XPVPivot ...
XPVPivot pivot;
pivot.symbol = symbol;
pivot.period = period;
pivot.from = fromTime;
pivot.to = toTime;
pivot.repetition = valeRepetition;
pivot.type = XPV_VALE;
pivot.upper = iPeak;
pivot.lower = vale;
FillPivotState(pivot);
//
if (pivot.IsValid())
{
//
AddRef(
pivot,
mPivots //
);
}
}
//
vale = iVale;
valeRepetition = 0;
}
//
index++;
canContinue = index < count;
}
//
int pivotsCount = ArraySize(mPivots);
if (IsValidSize(mPivots))
{
ArrayReverse(mPivots);
}
//
isDetecting = false;
}
//
private:
//
// Props ...
//
bool mIsLastPeakBullish;
int mBullishPeaks; // Count Bullish Peaks ...
int mBearishPeaks; // Count Bearish Peaks ...
//
bool mIsLastValeBullish;
int mBullishVales; // Count Bullish Vales ...
int mBearishVales; // Count Bearish Vales ...
//
// Change Holders ...
int mMaxAllowedSavedChanges; // Max llowed Changes to Save ...
XValueChange mSarChanges[]; // Holds Parabolic Sar Direction Changes ...
XValueChange mPeaksChanges[]; // Holds Peaks Changes ...
XValueChange mValesChanges[]; // Holds Vales Changes ...
XValueChange mVWapOrderChanges[]; // Holds Vales Changes ...
XValueChange mVWapStateChanges[]; // Holds Vales Changes ...
//
int mConsolidationLoopback; // Consolidation Loopback Length ...
XConsolidationZone mConsolidationZones[]; // Holds Consolidation Zones ...
XConsolidationZone mActiveConsolidationZone; // Holds Actiove Consolidation Zone ...
// XCConsolidationZoneObject *mActiveConsolidationZoneObj;
//
int mValidPivotRepetition; // Valid Pivot Point's Repetition ...
XPVPivotPoint mPivotPoints[]; // Holds Pivots ...
//
bool isDetecting;
XPVPivot mActivePeakPivot; // Active Pivots ...
XPVPivot mActiveValePivot; // Active Pivots ...
XPVPivot mPivots[]; // Holds Active Pivot ...
//
// Actions ...
/**
* Release All Resources ...
*/
void DeInit()
{
//
delete mX121Helper;
//
delete mBarAnalyser;
}
/**
* Apply Chart Style ...
*/
void ApplyChartStyle()
{
//
// Retrieve Current Chart ID ...
long chartId = ChartID();
//
ENUM_CHART_MODE mMode = CHART_CANDLES; // chart's mMode
bool mShowBidLine = true; // show bid line
bool mShowAskLine = true; // show ask line
bool mShowGrid = false; // show grids on chart
bool mShowVolumes = false; // show volumes
bool mShowTradeLevels = true; // Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders)
bool mAutoScroll = true; // chart autoscroll
bool mQuickNavigation = true; // chart quick navigation state
color mForeGroundColor = clrWhite; // chart's foreground color
color mBackGroundColor = clrBlack; // chart's background color
color mUpColor = clrGreen; // Up Color
color mDownColor = clrRed; // Down Color
color mBullishColor = clrGreen; // Bullish color
color mBearishColor = clrRed; // Bearish color
color mGridColor = clrGray; // grid color
color mBidLineColor = clrGray; // bid line color
color mAskLineColor = clrRed; // ask line color
color mLineColor = clrLime; // line mMode and doji candlestick color
color mStopColor = clrGold; // Color of stop order levels (Stop Loss and Take Profit)
color mVolumesColor = clrGreen; // volumes color
//
ChartSetInteger(chartId, CHART_MODE, mMode);
ChartSetInteger(chartId, CHART_SHOW_BID_LINE, mShowBidLine);
ChartSetInteger(chartId, CHART_SHOW_ASK_LINE, mShowAskLine);
ChartSetInteger(chartId, CHART_SHOW_GRID, mShowGrid);
ChartSetInteger(chartId, CHART_SHOW_VOLUMES, mShowVolumes);
ChartSetInteger(chartId, CHART_SHOW_TRADE_LEVELS, mShowTradeLevels);
ChartSetInteger(chartId, CHART_AUTOSCROLL, mAutoScroll);
ChartSetInteger(chartId, CHART_QUICK_NAVIGATION, mQuickNavigation);
ChartSetInteger(chartId, CHART_COLOR_FOREGROUND, mForeGroundColor);
ChartSetInteger(chartId, CHART_COLOR_BACKGROUND, mBackGroundColor);
ChartSetInteger(chartId, CHART_COLOR_CHART_UP, mUpColor);
ChartSetInteger(chartId, CHART_COLOR_CHART_DOWN, mDownColor);
ChartSetInteger(chartId, CHART_COLOR_CANDLE_BULL, mBullishColor);
ChartSetInteger(chartId, CHART_COLOR_CANDLE_BEAR, mBearishColor);
ChartSetInteger(chartId, CHART_COLOR_GRID, mGridColor);
ChartSetInteger(chartId, CHART_COLOR_BID, mBidLineColor);
ChartSetInteger(chartId, CHART_COLOR_ASK, mAskLineColor);
ChartSetInteger(chartId, CHART_COLOR_STOP_LEVEL, mStopColor);
ChartSetInteger(chartId, CHART_COLOR_CHART_LINE, mLineColor);
ChartSetInteger(chartId, CHART_COLOR_VOLUME, mVolumesColor);
}
/**
* Fill Pivot Tick Zone ...
*
* @param pivot: XPVPivot instance Reference ...
*/
void CalculatePivotTickZone(
XPVPivot &pivot //
)
{
//
string symbol = GetSymbol();
ENUM_TIMEFRAMES period = GetPeriod();
//
bool isInited = false;
//
datetime from = pivot.from;
XOHCL iFromBar;
int iFromBarIndex = iBarShift(
symbol,
period,
from //
);
isInited = iFromBar.Init(
symbol,
period,
iFromBarIndex //
);
if (!isInited)
{
return;
}
//
datetime to = pivot.to;
XOHCL iToBar;
int iToBarIndex = iBarShift(
symbol,
period,
to //
);
isInited = iToBar.Init(
symbol,
period,
iToBarIndex //
);
if (!isInited)
{
return;
}
//
if (iFromBarIndex <= iToBarIndex)
{
return;
}
//
XCTicksZone *iZone;
iZone = new XCTicksZone();
//
int ticksLevels = mPOIDetector.TicksRangeZoneLevel();
int ticksRange = mPOIDetector.TicksRangeZoneRange();
isInited = ticksLevels > 0 &&
ticksRange > 0;
if (!isInited)
{
return;
}
//
isInited = iZone.Init(
iFromBar,
iToBar //
);
if (!isInited)
{
return;
}
//
pivot.state.ticksZone = iZone;
}
//
// Change Values Actions ...
/**
* Add Specified Parabolic Sar Changed Item ...
*
* @param value: XValueChange instance Reference ...
*
* @return ( bool )
*/
bool AddSarChange(XValueChange &value)
{
//
bool result = false;
//
result = value.IsValid();
if (!result)
{
return result;
}
//
int beforeCount = CountSarChanges();
//
AddIfNotExists(
value,
mSarChanges //
);
//
int afterCount = CountSarChanges();
//
result = afterCount == beforeCount + 1;
if (result)
{
//
// Cleaning Up Unused Items ...
int maxAllowed = MaxAllowedSavedChanges();
CleanupArray(
mSarChanges,
maxAllowed //
);
}
//
return result;
}
/**
* Add Specified Peaks Changed Item ...
*
* @param value: XValueChange instance Reference ...
*
* @return ( bool )
*/
bool AddPeaksChange(XValueChange &value)
{
//
bool result = false;
//
result = value.IsValid();
if (!result)
{
return result;
}
//
int beforeCount = CountSarChanges();
//
AddIfNotExists(
value,
mPeaksChanges //
);
//
int afterCount = CountSarChanges();
//
result = afterCount == beforeCount + 1;
if (result)
{
//
// Cleaning Up Unused Items ...
int maxAllowed = MaxAllowedSavedChanges();
CleanupArray(
mPeaksChanges,
maxAllowed //
);
}
//
return result;
}
/**
* Add Specified Vales Changed Item ...
*
* @param value: XValueChange instance Reference ...
*
* @return ( bool )
*/
bool AddValesChange(XValueChange &value)
{
//
bool result = false;
//
result = value.IsValid();
if (!result)
{
return result;
}
//
int beforeCount = CountSarChanges();
//
AddIfNotExists(
value,
mValesChanges //
);
//
int afterCount = CountSarChanges();
//
result = afterCount == beforeCount + 1;
if (result)
{
//
// Cleaning Up Unused Items ...
int maxAllowed = MaxAllowedSavedChanges();
CleanupArray(
mValesChanges,
maxAllowed //
);
}
//
return result;
}
/**
* Add Specified VWap Order Changed Item ...
*
* @param value: XValueChange instance Reference ...
*
* @return ( bool )
*/
bool AddVWapOrderChange(XValueChange &value)
{
//
bool result = false;
//
result = value.IsValid();
if (!result)
{
return result;
}
//
int beforeCount = CountSarChanges();
//
AddIfNotExists(
value,
mVWapOrderChanges //
);
//
int afterCount = CountSarChanges();
//
result = afterCount == beforeCount + 1;
if (result)
{
//
// Cleaning Up Unused Items ...
int maxAllowed = MaxAllowedSavedChanges();
CleanupArray(
mVWapOrderChanges,
maxAllowed //
);
}
//
return result;
}
/**
* Add Specified VWap State Changed Item ...
*
* @param value: XValueChange instance Reference ...
*
* @return ( bool )
*/
bool AddVWapStateChange(XValueChange &value)
{
//
bool result = false;
//
result = value.IsValid();
if (!result)
{
return result;
}
//
int beforeCount = CountSarChanges();
//
AddIfNotExists(
value,
mVWapStateChanges //
);
//
int afterCount = CountSarChanges();
//
result = afterCount == beforeCount + 1;
if (result)
{
//
// Cleaning Up Unused Items ...
int maxAllowed = MaxAllowedSavedChanges();
CleanupArray(
mVWapStateChanges,
maxAllowed //
);
}
//
return result;
}
/**
* Add Specified Consolidation Zone to List ...
*
* @param zone: XConsolidationZone instance Reference ...
*
* @return ( bool )
*/
bool AddConsolidationZone(XConsolidationZone &zone)
{
//
bool result = false;
//
result = zone.IsValid();
//
int beforeCount = CountConsolidationZones();
//
AddRef(
zone,
mConsolidationZones //
);
//
int afterCount = CountConsolidationZones();
//
result = afterCount == beforeCount + 1;
if (result)
{
//
// Cleaning Up Unused Items ...
int maxAllowed = MaxAllowedSavedChanges();
CleanupArray(
mConsolidationZones,
maxAllowed //
);
}
//
return result;
}
/**
* Add Specified Pivot Point to List ...
*
* @param pivotPoint: XPVPivotPoint instance Reference ...
*
* @return ( bool )
*/
bool AddPivotPoint(XPVPivotPoint &pivotPoint)
{
//
bool result = false;
//
if (!pivotPoint.IsValid())
{
return result;
}
//
int beforeCount = CountPivotPoints();
//
AddRef(
pivotPoint,
mPivotPoints //
);
//
int afterCount = CountPivotPoints();
//
result = afterCount == beforeCount + 1;
if (result)
{
//
// Cleaning Up Unused Items ...
int maxAllowed = MaxAllowedSavedChanges();
CleanupArray(
mPivotPoints,
maxAllowed //
);
}
//
return result;
}
/**
* Add Specified Pivot to List ...
*
* @param pivot: XPVPivot instance Reference ...
*
* @return ( bool )
*/
bool AddPivot(XPVPivot &pivot)
{
//
bool result = false;
//
if (!pivot.IsValid())
{
return result;
}
//
int beforeCount = CountPivots();
//
AddRef(
pivot,
mPivots //
);
//
int afterCount = CountPivots();
//
result = afterCount == beforeCount + 1;
if (result)
{
//
// Cleaning Up Unused Items ...
int maxAllowed = MaxAllowedSavedChanges();
CleanupArray(
mPivots,
maxAllowed //
);
}
//
return result;
}
//
};