/////////////////////////////////////////////////////// // // 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; } // };