1756 lines
41 KiB
Plaintext
1756 lines
41 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_TRIGGER,
|
|
X_CYCLE_DECISION,
|
|
X_CYCLE_ANALYSE,
|
|
X_CYCLE_VERIFICATION,
|
|
X_CYCLE_CONSOLIDATION,
|
|
X_CYCLE_VISION,
|
|
};
|
|
|
|
enum ENUM_X_CYCLE_EVENTS
|
|
{
|
|
SAR_CHANGE_DETECTED,
|
|
NEW_PEAK_DETECTED,
|
|
NEW_VALE_DETECTED,
|
|
VWAP_ORDER_CHANGE_ETECTED,
|
|
VWAP_STATE_CHANGE_DETCTED,
|
|
CONSOLIDATION_BREAKED_DETECTED
|
|
};
|
|
|
|
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;
|
|
}
|
|
|
|
//
|
|
// 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(0);
|
|
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[],
|
|
X121SMCCycleConditions &conditions,
|
|
int barIndex = 0,
|
|
int loopback = 7 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
if (loopback < 5)
|
|
{
|
|
loopback = 5;
|
|
}
|
|
|
|
//
|
|
conditions.Clean();
|
|
|
|
//
|
|
result = mX121Helper.GetConditions(
|
|
conditions.x121Conditions,
|
|
barIndex,
|
|
loopback //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
conditions.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
conditions.symbol = conditions.x121Conditions.symbol;
|
|
conditions.period = conditions.x121Conditions.period;
|
|
conditions.time = TimeCurrent();
|
|
|
|
//
|
|
result = conditions.IsValid();
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
Calculate(
|
|
barIndex,
|
|
events,
|
|
conditions //
|
|
);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
/**
|
|
* Detect Nearest Supply/Demand Zones ...
|
|
*
|
|
* @param bar: XOHCL instance, Start Bar ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectValisSupplyZone(
|
|
XOHCL &bar,
|
|
XCSupplyZone *&supplyZone,
|
|
XCDemandZone *&demandZone //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int index = bar.Index();
|
|
|
|
//
|
|
double bid = GetBid(bar.symbol);
|
|
double ask = GetAsk(bar.symbol);
|
|
|
|
//
|
|
// Retrieve X121 Cnditions ...
|
|
int conditionsLoopback = 10;
|
|
X121Conditions x121Conditions;
|
|
result = mX121Helper.GetConditions(
|
|
x121Conditions,
|
|
index,
|
|
conditionsLoopback //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
int validPeaksCount = ArraySize(x121Conditions.validPeaksBuffer);
|
|
int validValesCount = ArraySize(x121Conditions.validValesBuffer);
|
|
|
|
//
|
|
XPOIState state;
|
|
ENUM_XPOI_EVENTS events[];
|
|
mPOIDetector.Update(events);
|
|
mPOIDetector.GetState(state);
|
|
result = state.IsValid() &&
|
|
state.HasChild();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Supply Zones ...
|
|
XCSupplyZone *supplies[];
|
|
int suppliesCount = state.CountSupplyZones();
|
|
|
|
//
|
|
// Select Bar Validated Supply Zones ...
|
|
if (IsValidSize(suppliesCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < suppliesCount; i++)
|
|
{
|
|
//
|
|
XCSupplyZone *iZone = state.supplyZones[i];
|
|
|
|
//
|
|
// Check Zone is Valid For Bar ...
|
|
bool isValid = bar.high < iZone.Lower() &&
|
|
ask < iZone.Lower() &&
|
|
bid < iZone.Lower();
|
|
if (isValid)
|
|
{
|
|
//
|
|
Add(
|
|
iZone,
|
|
supplies //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
suppliesCount = ArraySize(supplies);
|
|
|
|
//
|
|
// Select Valid Peaks Filtered Supplies ...
|
|
if (IsValidSize(suppliesCount))
|
|
{
|
|
//
|
|
// Check Valid Peaks ...
|
|
XCSupplyZone *tmp[];
|
|
if (IsValidSize(validPeaksCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < suppliesCount; i++)
|
|
{
|
|
//
|
|
XCSupplyZone *iZone = supplies[i];
|
|
|
|
//
|
|
for (int j = 0; j < validPeaksCount; j++)
|
|
{
|
|
//
|
|
double value = x121Conditions.validPeaksBuffer[j];
|
|
|
|
//
|
|
// Check Valid Peaks in Zone ...
|
|
bool isZoneContainsValidValue =
|
|
value >= iZone.Lower() &&
|
|
value <= iZone.Upper();
|
|
if (isZoneContainsValidValue)
|
|
{
|
|
//
|
|
Add(
|
|
iZone,
|
|
tmp //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(supplies);
|
|
Copy(
|
|
tmp,
|
|
supplies //
|
|
);
|
|
}
|
|
suppliesCount = ArraySize(supplies);
|
|
|
|
//
|
|
// Select Nearest Supply Zone ...
|
|
if (IsValidSize(suppliesCount))
|
|
{
|
|
//
|
|
// Check Nearest Supplies ...
|
|
for (int i = 0; i < suppliesCount; i++)
|
|
{
|
|
//
|
|
XCSupplyZone *iZone = supplies[i];
|
|
if (supplyZone == NULL)
|
|
{
|
|
supplyZone = iZone;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
bool canChange =
|
|
iZone.Lower() < supplyZone.Lower();
|
|
if (canChange)
|
|
{
|
|
supplyZone = iZone;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Demand Zones ...
|
|
XCDemandZone *demands[];
|
|
int demandsCount = state.CountDemandZones();
|
|
|
|
//
|
|
// Select Bar Validated Demand Zones ...
|
|
if (IsValidSize(demandsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < demandsCount; i++)
|
|
{
|
|
//
|
|
XCDemandZone *iZone = state.demandZones[i];
|
|
|
|
//
|
|
// Check Zone is Valid For Bar ...
|
|
bool isValid = bar.low > iZone.Upper() &&
|
|
ask > iZone.Upper() &&
|
|
bid > iZone.Upper();
|
|
if (isValid)
|
|
{
|
|
//
|
|
Add(
|
|
iZone,
|
|
demands //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
demandsCount = ArraySize(demands);
|
|
|
|
//
|
|
// Select Valid Vales Filtered Demands ...
|
|
if (IsValidSize(demandsCount))
|
|
{
|
|
//
|
|
// Check Valid Vales ...
|
|
XCDemandZone *tmp[];
|
|
if (IsValidSize(validValesCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < demandsCount; i++)
|
|
{
|
|
//
|
|
XCDemandZone *iZone = demands[i];
|
|
|
|
//
|
|
for (int j = 0; j < validValesCount; j++)
|
|
{
|
|
//
|
|
double value = x121Conditions.validValesBuffer[j];
|
|
|
|
//
|
|
// Check Valid Peaks in Zone ...
|
|
bool isZoneContainsValidValue =
|
|
value >= iZone.Lower() &&
|
|
value <= iZone.Upper();
|
|
if (isZoneContainsValidValue)
|
|
{
|
|
//
|
|
Add(
|
|
iZone,
|
|
tmp //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(demands);
|
|
Copy(
|
|
tmp,
|
|
demands //
|
|
);
|
|
}
|
|
demandsCount = ArraySize(demands);
|
|
|
|
//
|
|
// Select Nearest Demand Zone ...
|
|
if (IsValidSize(demandsCount))
|
|
{
|
|
//
|
|
// Check Nearest Demands ...
|
|
for (int i = 0; i < demandsCount; i++)
|
|
{
|
|
//
|
|
XCDemandZone *iZone = demands[i];
|
|
if (demandZone == NULL)
|
|
{
|
|
demandZone = iZone;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
bool canChange =
|
|
iZone.Upper() > demandZone.Upper();
|
|
if (canChange)
|
|
{
|
|
demandZone = iZone;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate Founded Zones ...
|
|
result = (supplyZone != NULL &&
|
|
supplyZone.IsValid()) &&
|
|
(demandZone != NULL &&
|
|
demandZone.IsValid());
|
|
|
|
//
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
//
|
|
// Virtuals ...
|
|
|
|
/**
|
|
* Set Default Properties Values ...
|
|
*/
|
|
virtual void Default()
|
|
{
|
|
//
|
|
ConsolidationLoopback(15);
|
|
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();
|
|
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);
|
|
|
|
//
|
|
Add(
|
|
SAR_CHANGE_DETECTED,
|
|
events //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Detect Peaks Changes ...
|
|
|
|
//
|
|
bool isNewPeak = conditions.x121Conditions.isNewPeak;
|
|
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);
|
|
|
|
//
|
|
Add(
|
|
NEW_PEAK_DETECTED,
|
|
events //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Detect Vales Changes ...
|
|
|
|
//
|
|
bool isNewVale = conditions.x121Conditions.isNewVale;
|
|
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);
|
|
|
|
//
|
|
Add(
|
|
NEW_VALE_DETECTED,
|
|
events //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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);
|
|
|
|
//
|
|
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);
|
|
|
|
//
|
|
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 &&
|
|
!mActioveConsolidationZone.IsValid())
|
|
{
|
|
//
|
|
// Initialize Consolidation Zone ...
|
|
bool isInited = mActioveConsolidationZone.Init(
|
|
changeBar.symbol,
|
|
changeBar.period,
|
|
upper,
|
|
lower,
|
|
consolidationLoopback //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (!hasConsolidation &&
|
|
mActioveConsolidationZone.IsValid())
|
|
{
|
|
//
|
|
// Check Consolidation Breaks ...
|
|
// Update Zone ...
|
|
// Add it ...
|
|
bool isBOSTop = changeBar.high > mActioveConsolidationZone.upper;
|
|
bool isBOSBottom = changeBar.low < mActioveConsolidationZone.lower;
|
|
|
|
//
|
|
// Calculate Break Direction ...
|
|
ENUM_X_DIRECTION bosDir = isBOSTop
|
|
? X_DIRECTION_BULLISH
|
|
: isBOSBottom
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Update Actiove Zone ...
|
|
mActioveConsolidationZone.breakerBar = changeBar;
|
|
mActioveConsolidationZone.breakDirection = bosDir;
|
|
|
|
//
|
|
// Add Active to List ...
|
|
AddRef(
|
|
mActioveConsolidationZone,
|
|
mConsolidationZones //
|
|
);
|
|
|
|
//
|
|
// Clean Active Zone ...
|
|
mActioveConsolidationZone.Clean();
|
|
|
|
//
|
|
Add(
|
|
CONSOLIDATION_BREAKED_DETECTED,
|
|
events //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
private:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
// 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 mActioveConsolidationZone; // Holds Actiove Consolidation Zone ...
|
|
|
|
//
|
|
// 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);
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
};
|