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

1064 lines
25 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) ...
//
// 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,
int requiredPOIS = 50 //
)
{
//
bool result = false;
//
if (requiredPOIS < 10) {
requiredPOIS = 10;
}
//
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(requiredPOIS);
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();
//
return result;
}
/**
* Detect Market Structure ...
*
* @param model: XMarketStructure instance Reference ...
*
* @return ( bool )
*/
bool DetectMarketStructure(
XMarketStructure &model //
)
{
//
bool result = false;
//
model.Clean();
//
int barIndex = 0;
//
string symbol = GetSymbol();
ENUM_TIMEFRAMES period = GetPeriod();
//
model.symbol = symbol;
model.period = period;
//
int highestPeakIndex = -1;
double highestPeakVale = 0;
double highestPeak =
mX121Helper
.xpvHelper
.GetHighestPeak(
barIndex,
highestPeakIndex,
highestPeakVale //
);
//
int lowestValeIndex = -1;
double lowestValePeak = 0;
double lowestVale =
mX121Helper
.xpvHelper
.GetLowestVale(
barIndex,
lowestValeIndex,
lowestValePeak //
);
//
result = IsValidIndex(highestPeakIndex) &&
IsValidIndex(lowestValeIndex);
if (!result)
{
return result;
}
//
model.bias =
highestPeakIndex < lowestValeIndex
? X_DIRECTION_BEARISH
: highestPeakIndex > lowestValeIndex
? X_DIRECTION_BULLISH
: X_DIRECTION_NONE;
//
result = HasDirection(model.bias);
if (!result)
{
return result;
}
//
bool isBullish = IsBullish(model.bias);
//
// Looking for Change Of Character Proved ...
//
// Bullish Bias:
// - Price Must Break Up Lowst Vale's Peak;
// - Create a Vale Above Lowest Vale's Peak;
//
// Bearish Bias:
// - Price Must Breake Down HighestPeak's Vale;
// - Create a Peak Under Highest Peak's Vale;
//
// Checking Peak Breake Up ...
int lowestValePeakBreakeUpIndex = -1;
for (int i = lowestValeIndex; i >= barIndex; i--)
{
//
XOHCL iBar;
result = GetBar(iBar, i);
if (!result)
{
continue;
}
//
bool isBreake = IsBarBreak(
lowestValePeak,
X_DIRECTION_BULLISH,
iBar //
);
if (isBreake)
{
//
lowestValePeakBreakeUpIndex = i;
break;
}
}
bool isValidBreakeUpLowestValePeak = IsValidIndex(lowestValePeakBreakeUpIndex) &&
lowestValePeakBreakeUpIndex <= lowestValeIndex;
//
// Checking Vale Breake Down ...
int highestPeakValeBreakeDownIndex = -1;
for (int i = highestPeakIndex; i >= barIndex; i--)
{
//
XOHCL iBar;
result = GetBar(iBar, i);
if (!result)
{
continue;
}
//
bool isBreake = IsBarBreak(
highestPeakVale,
X_DIRECTION_BEARISH,
iBar //
);
if (isBreake)
{
//
highestPeakValeBreakeDownIndex = i;
break;
}
}
bool isValidBreakeDownHighestPeakVale = IsValidIndex(highestPeakValeBreakeDownIndex) &&
highestPeakValeBreakeDownIndex <= highestPeakIndex;
//
result = isBullish
? isValidBreakeUpLowestValePeak
: isValidBreakeDownHighestPeakVale;
if (!result)
{
return result;
}
//
// Checking Create a Vale above Peak ...
int valeAboveLowestValePeakIndex = -1;
double valeAboveLowestValePeakPeak = 0;
for (int i = lowestValePeakBreakeUpIndex; i >= barIndex; i--)
{
//
double iVale = mX121Helper.xpvHelper.GetVale(i);
//
bool isValid =
iVale > 0 &&
iVale > lowestValePeak;
if (isValid)
{
//
valeAboveLowestValePeakIndex = i;
valeAboveLowestValePeakPeak = mX121Helper.xpvHelper.GetPeak(i);
break;
}
}
bool isValidValeAboveLowestValePeak = IsValidIndex(valeAboveLowestValePeakIndex) &&
valeAboveLowestValePeakIndex < lowestValePeakBreakeUpIndex;
//
// Checking Create a Peak below Vale ...
int peakBelowHighestPeakValeIndex = -1;
double peakBelowHighestPeakValeVale = 0;
for (int i = highestPeakValeBreakeDownIndex; i >= barIndex; i--)
{
//
double iPeak = mX121Helper.xpvHelper.GetPeak(i);
//
bool isValid =
iPeak > 0 &&
iPeak < highestPeakVale;
if (isValid)
{
//
peakBelowHighestPeakValeIndex = i;
peakBelowHighestPeakValeVale = mX121Helper.xpvHelper.GetVale(i);
break;
}
}
bool isValidPeakBelowHighestPeakVale = IsValidIndex(peakBelowHighestPeakValeIndex) &&
peakBelowHighestPeakValeIndex < highestPeakValeBreakeDownIndex;
//
result = isBullish ? isValidValeAboveLowestValePeak
: isValidPeakBelowHighestPeakVale;
if (!result)
{
return result;
}
//
// Now we Have to Detect Valid Peaks and Valid Vales Here ...
// based on Detected Range ...
//
XPVPivotPoint iPeakPoint;
XPVPivotPoint iValePoint;
XPriceZones peakPriceZone;
XPriceZones valePriceZone;
//
XPOIState state;
mPOIDetector.GetState(
state //
);
//
int minRepetition = 5;
//
int from =
isBullish
? valeAboveLowestValePeakIndex
: peakBelowHighestPeakValeIndex;
for (int i = from; i >= barIndex; i--)
{
//
XOHCL iBar;
bool isInited = GetBar(iBar, i);
//
double iPeak = mX121Helper.xpvHelper.GetPeak(i);
double iVale = mX121Helper.xpvHelper.GetVale(i);
//
bool hasPeakPriceInsideZone = CalculatePriceInsideZones(
peakPriceZone,
state,
iPeak //
);
bool hasValePriceInsideZone = CalculatePriceInsideZones(
valePriceZone,
state,
iVale //
);
//
if (hasPeakPriceInsideZone)
{
//
// Peak ...
if (!iPeakPoint.IsValid())
{
//
// Initialization ...
iPeakPoint.value = iPeak;
iPeakPoint.repetition = 1;
iPeakPoint.type = XPV_PEAK;
iPeakPoint.time = iBar.time;
}
else
{
//
if (iPeakPoint.value == iPeak)
{
iPeakPoint.repetition++;
}
else
{
//
if (iPeakPoint.repetition > minRepetition)
{
//
AddRef(
iPeakPoint,
model.peaks //
);
//
AddRef(
peakPriceZone,
model.peakPriceZones //
);
}
//
iPeakPoint.Clean();
peakPriceZone.Clean();
iPeakPoint.value = iPeak;
iPeakPoint.repetition = 1;
iPeakPoint.type = XPV_PEAK;
iPeakPoint.time = iBar.time;
}
}
}
//
if (hasValePriceInsideZone)
{
//
// Vale ...
if (!iValePoint.IsValid())
{
//
// Initialization ...
iValePoint.value = iVale;
iValePoint.repetition = 1;
iValePoint.type = XPV_VALE;
iValePoint.time = iBar.time;
}
else
{
//
if (iValePoint.value == iVale)
{
iValePoint.repetition++;
}
else
{
//
if (iValePoint.repetition > minRepetition)
{
//
AddRef(
iValePoint,
model.vales //
);
//
AddRef(
valePriceZone,
model.valePriceZones //
);
}
//
iValePoint.Clean();
valePriceZone.Clean();
iValePoint.value = iVale;
iValePoint.repetition = 1;
iValePoint.type = XPV_VALE;
iValePoint.time = iBar.time;
}
}
}
}
//
// in Bullish Bias we Looking for Vales Oder ...
// in Bearish Bias we Looking for Peaks Oder ...
//
// Bullish Bias Drawn ...
if (isBullish)
{
//
result = GetBar(
model.lowestValeBar,
lowestValeIndex //
);
if (!result)
{
return result;
}
//
if (isValidBreakeUpLowestValePeak)
{
//
result = GetBar(
model.lowestValePeakBreakeUpBar,
lowestValePeakBreakeUpIndex //
);
if (!result)
{
return result;
}
}
//
if (isValidValeAboveLowestValePeak)
{
//
result = GetBar(
model.valeAboveLowestValePeakBar,
valeAboveLowestValePeakIndex //
);
if (!result)
{
return result;
}
}
}
//
// Bearish Bias Drawn ...
if (!isBullish)
{
//
result = GetBar(
model.highestPeakBar,
highestPeakIndex //
);
if (!result)
{
return result;
}
//
if (isValidBreakeDownHighestPeakVale)
{
//
result = GetBar(
model.highestPeakValeBreakeDownBar,
highestPeakValeBreakeDownIndex //
);
if (!result)
{
return result;
}
}
//
if (isValidPeakBelowHighestPeakVale)
{
//
result = GetBar(
model.peakBelowHighestPeakValeBar,
peakBelowHighestPeakValeIndex //
);
if (!result)
{
return result;
}
}
}
//
result = model.IsValid();
//
return result;
}
//
// Tools ...
//
// Virtuals ...
/**
* Set Default Properties Values ...
*/
virtual void Default()
{
}
//
protected:
//
//
private:
//
// Props ...
//
// 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;
}
//
};