/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class // ------------------------------------------------- // Name: XCXFIMASignaller ... // Description: XFIMA Signaller Class ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property library #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://saherelm.ir" #property version "1.00" #property description "SaherElm XFIMA Signaller Class" #property strict // // Imports ... #include "../../Classes/x-saherelm.x-signaller.class.mq5" #include "../../Helpers/x-saherelm.xfima.helper.mq5" #include "../Classes/x-saherelm.xfima.x-poi.detector.class.mq5" #include "../Classes/x-saherelm.xfima.x-poi.drawer.class.mq5" // // Implementation ... // // Base XFIMA base Signaller ... class XCXFIMABaseSignaller : public XCBaseSignaller { // // Public ... public: // // Props ... // XFIMAInputs fimaInputs; // XFIMA Inputs ... XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ... XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ... XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ... // // Constructor ... XCXFIMABaseSignaller( string _name, // Name ... string _symbol, // Symbol ... ENUM_TIMEFRAMES _period, // Period ... XFIMAInputs &_fimaInputs, // XFIMAInputs ... bool _processAllTicks = false, // Process All Ticks ... double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... double _defaultSignalVolume = 0.01 // Default Signal Volume ... ) : XCBaseSignaller(_name, _symbol, _period, _processAllTicks, _defaultSignalR2R, _defaultSignalRiskInPoint, _defaultSignalVolume // ) { // // Instantiating XFIMA Indicator Helper Class ... if (_fimaInputs.IsValid()) { // fimaHelper = new XCXFIMAHelper(); bool isInited = fimaHelper.Init( _symbol, _period, _fimaInputs // ); if (isInited) { fimaInputs = _fimaInputs; } else { // delete fimaHelper; ZeroMemory(fimaHelper); } } // poiDrawer = new XCXFIMAPOIDrawer(); poiDetector = new XCXFIMAPOIDetector(fimaHelper); } // // Deconstructor ... ~XCXFIMABaseSignaller() { Destroy(); } // // Overrides ... // // Actions ... /** * Destroy ... */ void Destroy() { // BeforeDestroy(); // fimaInputs.Clean(); // delete fimaHelper; ZeroMemory(fimaHelper); // delete poiDrawer; ZeroMemory(poiDrawer); // delete poiDetector; ZeroMemory(poiDetector); } // // Virtuals ... /** * Before Destroy ... */ void virtual BeforeDestroy() { } /** * Processing Tick ... * * @param barIndex: int, Specified Bar Index ... */ virtual void ProcessTick(int barIndex = 0) { } /** * Processing New Bar ... * * @param barIndex: int, Specified Bar Index ... */ virtual void ProcessNewBar(int barIndex = 0) { } /** * Check Guards Based on MarketConditions ... * * @param guards: XGuard[] * @param barIndex: int * * @return ( int ) */ int virtual CheckForGuard( XGuard &guards[], int barIndex = 0 // ) { // int result = 0; // SpecifiedClean(guards); // result = ArraySize(guards); // return result; } /** * Check Additional Validations on Childs Instances ... * * @return ( bool virtual ) */ bool virtual CheckAdditionslSignallerValidations() { // bool result = false; // // Validate Fima Helper Requirements ... result = fimaInputs.IsValid() && fimaHelper != NULL && poiDetector != NULL; // return result; } /** * Normalizing Signal by Signaller Custom Props ... * * @param signal: XSignal ... */ void virtual NormalizeSignal(XSignal &signal) { } // // Protected ... protected: // // // Private ... private: // }; // // XFIMA Strategy 1 Signaller Class ... class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller { // // Public ... public: // // Props ... int fvgLookupLenght; // Maximum Lenght for Looking up FVG before Crosses // // Constructor ... XCXFIMAStrategy1Signaller( string _symbol, // Symbol ... ENUM_TIMEFRAMES _period, // Period ... XFIMAInputs &_fimaInputs, // XFIMAInputs ... bool _processAllTicks = false, // Process All Ticks ... double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... double _defaultSignalVolume = 0.01 // Default Signal Volume ... ) : XCXFIMABaseSignaller("XFIMA1", _symbol, _period, _fimaInputs, _processAllTicks, _defaultSignalR2R, _defaultSignalRiskInPoint, _defaultSignalVolume // ) { // fvgLookupLenght = 5; } // // Overrides ... /** * Processing Tick ... * * @param barIndex: int, Specified Bar Index ... */ virtual void ProcessTick(int barIndex = 0) { } /** * Processing New Bar ... * * @param barIndex: int, Specified Bar Index ... */ virtual void ProcessNewBar(int barIndex = 0) { // // Normalize ... barIndex = NormalizeInt(barIndex, 0); // // Update Helper ... fimaHelper.Update(barIndex); // XOHCL bar; XSignal signal; bool has = false; int cIdx = barIndex + 1; int pIdx = cIdx + 1; ENUM_X_DIRECTION signalDir = X_DIRECTION_NONE; // // Initialize Bar as CBar ... has = bar.Init( symbol, period, cIdx // ); if (!has) { // bar.Clean(); return; } // // Retrieve Conditions ... XFIMAConditions fimaConditions; has = fimaHelper.GetConditions( fimaConditions, barIndex, 10 // Loopback ... ); if (!has) { // bar.Clean(); fimaConditions.Clean(); // return; } // // Analyse Conditions for Finding Signal ... // // TODO: Remove this ... // bool isFastCrossedOverSlow = fimaConditions.maFastBuffer[cIdx] > fimaConditions.maSlowBuffer[cIdx] && fimaConditions.maFastBuffer[pIdx] < fimaConditions.maSlowBuffer[pIdx]; // bool isFastCrossedUnderSlow = fimaConditions.maFastBuffer[cIdx] < fimaConditions.maSlowBuffer[cIdx] && fimaConditions.maFastBuffer[pIdx] > fimaConditions.maSlowBuffer[pIdx]; // has = isFastCrossedOverSlow || isFastCrossedUnderSlow; if (has) { // // Do Conditions Validating ... // TODO: Igmore All Validations for Testing Purposes ... // // Validate MA Positions ... double iFastMa = fimaConditions.maFastBuffer[cIdx]; double iSlowMa = fimaConditions.maSlowBuffer[cIdx]; double iFiboUpper = fimaConditions.fiboUpperBuffer[cIdx]; double iFiboLower = fimaConditions.fiboLowerBuffer[cIdx]; // // Checking Has FVG ... XBoxZone fvg; ENUM_X_DIRECTION fvgDir; bool hasFVG = patternDetector.HasFVG( bar, fvgDir, fvg, fvgLookupLenght // ); // // Checking Crossed On Shadow ... // bool isCrossedOverHappensOnShadow = isFastCrossedOverSlow && iFastMa <= bar.GetDown() && iFastMa >= bar.low; // bool isCrossedUnderHappensOnShadow = isFastCrossedUnderSlow && iFastMa <= bar.high && iFastMa >= bar.GetUp(); // // Bullish Validation ... bool isBullish = // // Has Cross ... isFastCrossedOverSlow // // && // // // // Cross Places Based on Fibo ... // MathMax(iFastMa, iSlowMa) < iFiboLower // // // && // // // ( // // // // Checking FVG ... // (hasFVG && // fvg.IsBullish()) // // // || // // // // Checking Crossed Place ... // isCrossedOverHappensOnShadow // // // ) // // ; // // Bearish Validation ... bool isBearish = // // Has Cross ... isFastCrossedUnderSlow // // && // // // // Cross Places Based on Fibo ... // MathMin(iFastMa, iSlowMa) > iFiboUpper // // // && // // // ( // // // // Checking FVG ... // (hasFVG && // fvg.IsBearish()) // // // || // // // // Checking Crossed Place ... // isCrossedUnderHappensOnShadow // // // ) // // ; // has = (isBullish && !isBearish) || (isBearish && !isBullish); if (has) { // signalDir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } } // // Check Signal Founded ... has = HasDirection(signalDir); if (has) { // // Prepare Founded Signal ... XTarget targets[]; has = PrepareSignal( signal, signalDir, targets // ); if (has) { // // Notify On Signal Event ... NotifySignalEventListeners(signal); } } // // Cleanup Resources ... bar.Clean(); signal.Clean(); fimaConditions.Clean(); } /** * Check Guards Based on MarketConditions ... * * @param guards: XGuard[] * @param barIndex: int * * @return ( int ) */ int virtual CheckForGuard( XGuard &guards[], int barIndex = 0 // ) { // int result = 0; // SpecifiedClean(guards); // result = ArraySize(guards); // return result; } // // Private ... private: // // Props ... // // Lookup FVG ... bool LookupFVG( XOHCL &bar, ENUM_X_DIRECTION &dir, XBoxZone &fvgBox // ) { // bool result = false; // return result; } // }; // // XFIMA Strategy 2 Signaller Class ... class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller { // // Public ... public: // // Props ... XFIMAPatternDetectorConfig analyserConfig; // // Constructor ... XCXFIMAStrategy2Signaller( string _symbol, // Symbol ... ENUM_TIMEFRAMES _period, // Period ... XFIMAInputs &_fimaInputs, // XFIMAInputs ... bool _processAllTicks = false, // Process All Ticks ... double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... double _defaultSignalVolume = 0.01 // Default Signal Volume ... ) : XCXFIMABaseSignaller("XFIMA2", _symbol, _period, _fimaInputs, _processAllTicks, _defaultSignalR2R, _defaultSignalRiskInPoint, _defaultSignalVolume // ) { // // Configure Detector ... analyserConfig.Default(); analyserConfig.FullDetect(); } // // Deconstructor ... ~XCXFIMAStrategy2Signaller() { // Destroy(); // analyserConfig.Clean(); } // // Overrides ... /** * Processing Tick ... * * @param barIndex: int, Specified Bar Index ... */ virtual void ProcessTick(int barIndex = 0) { } /** * Processing New Bar ... * * @param barIndex: int, Specified Bar Index ... */ void ProcessNewBarNKP(int barIndex = 0) { // // Normalize ... barIndex = NormalizeInt(barIndex, 0); // // Update Helper ... fimaHelper.Update(barIndex); // XOHCL bar; XSignal signal; XBoxZone iZone; int count = 0; bool has = false; int cIdx = barIndex + 1; int pIdx = cIdx + 1; string iName = NULL; XBoxZone supports[]; XBoxZone resistances[]; bool isBullish = false; bool isBearish = false; double iPrice = EMPTY_VALUE; XFIMAMarketStructure structure; XFIMAConditions fimaConditions; ENUM_X_PRICE iPriceType = X_PRICE_NONE; ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; // XPivot pvPivots[]; string pvTrendName = "XXIFMA2PVTrend"; CChartObjectTrend *pvTrendLine = NULL; ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE; // XPivot zgPivots[]; string zgTrendName = "XFIMA2ZGTrend"; CChartObjectTrend *zgTrendLine = NULL; ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE; // // Initialize Bar as CBar ... has = bar.Init( symbol, period, cIdx // ); if (!has) { // bar.Clean(); return; } // // Retrieve Conditions ... has = fimaHelper.GetConditions( fimaConditions, barIndex, 10 // Loopback ... ); if (!has) { // bar.Clean(); fimaConditions.Clean(); // return; } // // Analyse Market ... poiDetector.AnalyseMarket( bar, structure, analyserConfig // ); // // Check Required Pattern Exists ... bool hasPinnedBar = HasDirection(structure.pinnedDir); bool hasEngulfedBar = HasDirection(structure.engulfedDir); bool hasFlagPattern = HasDirection(structure.flagPatternDir); bool hasStarPattern = HasDirection(structure.starPatternDir); bool hasRisingPattern = HasDirection(structure.risingPatternDir); bool hasPiercingPattern = HasDirection(structure.piercingPatternDir); bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir); // // Check Bar Pattern Exists ... has = hasPinnedBar || hasEngulfedBar || hasFlagPattern || hasStarPattern || hasSignalKeyBar || hasRisingPattern || hasPiercingPattern; // // Select Pattern Direction and Price and Price Type ... if (has) { // if (hasPinnedBar) { // iDir = structure.pinnedDir; iName = "XPinned_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasEngulfedBar) { // iDir = structure.engulfedDir; iName = "XEngulfed_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasFlagPattern) { // iDir = structure.flagPatternDir; iName = "XFlag_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasStarPattern) { // iDir = structure.starPatternDir; iName = "XStar_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasSignalKeyBar) { // iDir = structure.risingPatternDir; iName = "XRising_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasRisingPattern) { // iDir = structure.piercingPatternDir; iName = "XPiercing_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasPiercingPattern) { // iDir = structure.signalKeyBarPatternDir; iName = "XSignalKey_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } // isBullish = IsSpecifiedBullish(iDir); isBearish = IsSpecifiedBearish(iDir); // // Retrieve Price Type for Validate ... iPriceType = isBullish ? X_PRICE_LOW : X_PRICE_HIGH; iPrice = bar.GetPrice(iPriceType); // has = HasDirection(iDir); } // // Chekc Bullish or Bearish Starter Conditions Exists ... has = isBullish || isBearish; if (has) { // // Do Conditions Validating ... // // Retrieve MA Band for Validation ... double iMABandUpper = fimaHelper.GetMABandUpper(barIndex); double iMABandLower = fimaHelper.GetMABandLower(barIndex); // // Validate ... has = isBullish ? iPrice < iMABandLower : iPrice > iMABandUpper; if (!has) { // isBullish = false; isBearish = false; iDir = X_DIRECTION_NONE; } } // // Collect Support and Resistance Zones and Validate by them ... // // PV Trend Line ... bool hasPVAnalysis = structure.pvAnalysis.IsValid(); if (hasPVAnalysis) { // // Support ... XBoxZone supportBox; has = structure.pvAnalysis.HasSupportBox(supportBox); if (has) { // supportBox.to = bar.time; AddIfNotExists( supportBox, supports // ); // has = poiDrawer.DrawBox( // supportBox, // iSupportObj, // true, // Ignore At ... // supportBox.type // Name ... // ); // if (has) // { // // // XPOIStyle iStyle; // poiDrawer.GetBoxStyle( // iStyle, // supportBox.dir // // ); // poiDrawer.ApplyBoxStyle( // iSupportObj, // iStyle // // ); // iStyle.Clean(); // } } // // Resistance ... XBoxZone resistanceBox; has = structure.pvAnalysis.HasResistanceBox(resistanceBox); if (has) { // resistanceBox.to = bar.time; AddIfNotExists( resistanceBox, supports // ); // has = poiDrawer.DrawBox( // resistanceBox, // iResistanceObj, // true, // Ignore At ... // resistanceBox.type // Name ... // ); // if (has) // { // // // XPOIStyle iStyle; // poiDrawer.GetBoxStyle( // iStyle, // resistanceBox.dir // // ); // poiDrawer.ApplyBoxStyle( // iResistanceObj, // iStyle // // ); // iStyle.Clean(); // } } // // Pivots ... XPivot pivots[]; count = poiDetector.ExtractPVPivots( pivots, barIndex, 50 // ); has = IsValidSize(count); // // Sort ... Sort( pivots, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Remove Newest ... ArrayRemove( pivots, 0, 1 // ); // // Check Trend ... if (has) { // XPivot highs[]; int highsCount = ExtractPivots( highs, pivots, X_PIVOT_TYPE_PEAK // ); Sort( highs, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // XPivot lows[]; int lowsCount = ExtractPivots( lows, pivots, X_PIVOT_TYPE_VALE // ); Sort( lows, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Check Highs and Lows ... has = IsValidSize(lowsCount) && IsValidSize(highsCount) && lowsCount >= 2 && highsCount >= 2; if (has) { // // Try to Get Market Strucutre ... // bool hasLowerHigh = highs[0].value < highs[1].value; bool hasLowerLow = lows[0].value < lows[1].value; // bool hasHigherHigh = highs[0].value > highs[1].value; bool hasHigherLow = lows[0].value > lows[1].value; // pvTrend = (hasHigherHigh && hasHigherLow) ? X_DIRECTION_BULLISH : (hasLowerHigh && hasLowerLow) ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; has = HasDirection(pvTrend); if (has) { // // Select Swings for Trend Line ... XOHCL tmpBar; int llIDX = -1; int hhIDX = -1; datetime toTime = NULL; datetime fromTime = NULL; double toPrice = EMPTY_VALUE; color trendColor = CLR_NONE; double fromPrice = EMPTY_VALUE; if (IsSpecifiedBullish(pvTrend)) { // llIDX = GetLowest(lows); hhIDX = GetHighest(lows); // trendColor = clrAqua; // toTime = lows[hhIDX].time; toPrice = lows[hhIDX].value; // fromTime = lows[llIDX].time; fromPrice = lows[llIDX].value; } else { // llIDX = GetLowest(highs); hhIDX = GetHighest(highs); // trendColor = clrMagenta; // toTime = highs[llIDX].time; toPrice = highs[llIDX].value; // fromTime = highs[hhIDX].time; fromPrice = highs[hhIDX].value; } // // Check Requirements for Trend ... has = NotEmptyZero(toPrice) && NotEmptyZero(fromPrice) && IsSpecifiedValid(toTime) && IsSpecifiedValid(fromTime); if (has) { // has = poiDrawer.DrawTrendLine( fromPrice, fromTime, toPrice, toTime, pvTrendLine, pvTrendName, true // Ray Right ... ); if (has) { pvTrendLine.Color(trendColor); } } // // Cleanup Resources ... tmpBar.Clean(); } // if (!has) { SpecifiedClean(pivots); } } // // Cleanup Resources ... SpecifiedClean(lows); SpecifiedClean(highs); } // // Draw Pivots ... has = HasChild(pivots); if (has) { // Copy( pivots, pvPivots // ); } // // Cleanup Resources ... SpecifiedClean(pivots); } // // ZigZag Trend Line ... bool hasZGAnalysis = structure.zigzagAnalysis.IsValid(); if (hasZGAnalysis) { // // Support ... XBoxZone supportBox; has = structure.zigzagAnalysis.HasSupportBox(supportBox); if (has) { // supportBox.to = bar.time; AddIfNotExists( supportBox, supports // ); } // // Resistance ... XBoxZone resistanceBox; has = structure.zigzagAnalysis.HasResistanceBox(resistanceBox); if (has) { // resistanceBox.to = bar.time; AddIfNotExists( resistanceBox, supports // ); } // // Pivots ... XPivot pivots[]; count = poiDetector.ExtractZigZagPivots( pivots, barIndex, 10 // ); has = IsValidSize(count); // // Sort ... Sort( pivots, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Remove Newest ... ArrayRemove( pivots, 0, 1 // ); // // Check Trend ... if (has) { // XPivot highs[]; int highsCount = ExtractPivots( highs, pivots, X_PIVOT_TYPE_PEAK // ); Sort( highs, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // XPivot lows[]; int lowsCount = ExtractPivots( lows, pivots, X_PIVOT_TYPE_VALE // ); Sort( lows, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Check Highs and Lows ... has = IsValidSize(lowsCount) && IsValidSize(highsCount) && lowsCount >= 2 && highsCount >= 2; if (has) { // // Try to Get Market Strucutre ... // bool hasLowerHigh = highs[0].value < highs[1].value; bool hasLowerLow = lows[0].value < lows[1].value; // bool hasHigherHigh = highs[0].value > highs[1].value; bool hasHigherLow = lows[0].value > lows[1].value; // zgTrend = (hasHigherHigh && hasHigherLow) ? X_DIRECTION_BULLISH : (hasLowerHigh && hasLowerLow) ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; has = HasDirection(zgTrend); if (has) { // // Select Swings for Trend Line ... XOHCL tmpBar; int llIDX = -1; int hhIDX = -1; datetime toTime = NULL; datetime fromTime = NULL; double toPrice = EMPTY_VALUE; color trendColor = CLR_NONE; double fromPrice = EMPTY_VALUE; if (IsSpecifiedBullish(zgTrend)) { // llIDX = GetLowest(lows); hhIDX = GetHighest(lows); // trendColor = clrAqua; // toTime = lows[hhIDX].time; toPrice = lows[hhIDX].value; // fromTime = lows[llIDX].time; fromPrice = lows[llIDX].value; } else { // llIDX = GetLowest(highs); hhIDX = GetHighest(highs); // trendColor = clrMagenta; // toTime = highs[llIDX].time; toPrice = highs[llIDX].value; // fromTime = highs[hhIDX].time; fromPrice = highs[hhIDX].value; } // // Check Requirements for Trend ... has = NotEmptyZero(toPrice) && NotEmptyZero(fromPrice) && IsSpecifiedValid(toTime) && IsSpecifiedValid(fromTime); if (has) { // has = poiDrawer.DrawTrendLine( fromPrice, fromTime, toPrice, toTime, zgTrendLine, zgTrendName, true // Ray Right ... ); if (has) { zgTrendLine.Color(trendColor); } } // // Cleanup Resources ... tmpBar.Clean(); } // if (!has) { SpecifiedClean(pivots); } } // // Cleanup Resources ... SpecifiedClean(lows); SpecifiedClean(highs); } // // Draw Pivots ... has = HasChild(pivots); if (has) { // Copy( pivots, zgPivots // ); } // // Cleanup Resources ... SpecifiedClean(pivots); } // // Support ... bool hasSupport = structure.support.IsValid(); if (hasSupport) { // AddIfNotExists( structure.support, supports // ); // // // XCBoxObject *iObj; // has = fima2Signaller.poiDrawer.DrawBox( // structure.support, // iObj); // if (has) // { // } } // // Resistance ... bool hasResistance = structure.resistance.IsValid(); if (hasResistance) { // AddIfNotExists( structure.resistance, resistances // ); // // // XCBoxObject *iObj; // has = fima2Signaller.poiDrawer.DrawBox( // structure.resistance, // iObj); // if (has) // { // } } // // Validate Positions Support and Resistance Zone ... int insideZoneIDX = -1; has = has && (isBullish ? HasInside( insideZoneIDX, bar, supports // ) : HasInside( insideZoneIDX, bar, resistances // )); // // Validate Selected Inside Zone ... // whith Bars Edge ... has = IsValidIndex(insideZoneIDX); if (has) { // if (isBullish) { iZone = supports[insideZoneIDX]; } else { iZone = resistances[insideZoneIDX]; } // has = isBullish ? bar.high > supports[insideZoneIDX].upper : bar.low < resistances[insideZoneIDX].lower; if (!has) { // isBullish = false; isBearish = false; iDir = X_DIRECTION_NONE; } } else { // isBullish = false; isBearish = false; iDir = X_DIRECTION_NONE; } // // Checking Liquidities ... // // Do all Draws Here ... bool canDraw = false; if (canDraw) { // int iWidth = 2; XPOIStyle iStyle; XCBoxObject *iBoxObj = NULL; color iClr = isBullish ? clrYellow : clrDarkOrange; // // Supports ... has = HasChild(supports); if (has) { // count = ArraySize(supports); for (int i = 0; i < count; i++) { // has = poiDrawer.DrawBox( supports[i], iBoxObj, true, // Ignore At ... supports[i].type // Name ... ); if (has) { // poiDrawer.GetBoxStyle( iStyle, supports[i].dir // ); // poiDrawer.ApplyBoxStyle( iBoxObj, iStyle // ); } // iStyle.Clean(); ZeroMemory(iBoxObj); } } // // Resistances ... has = HasChild(resistances); if (has) { // count = ArraySize(resistances); for (int i = 0; i < count; i++) { // has = poiDrawer.DrawBox( resistances[i], iBoxObj, true, // Ignore At ... resistances[i].type // Name ... ); if (has) { // poiDrawer.GetBoxStyle( iStyle, resistances[i].dir // ); // poiDrawer.ApplyBoxStyle( iBoxObj, iStyle // ); } // iStyle.Clean(); ZeroMemory(iBoxObj); } } // // Selected Zone ... has = iZone.IsValid(); if (has) { // has = poiDrawer.DrawBox( iZone, iBoxObj, true, // Ignore At ... iZone.type // Name ... ); if (has) { // poiDrawer.GetBoxStyle( iStyle, iZone.dir // ); // iStyle.clr = iClr; iStyle.width = iWidth; // poiDrawer.ApplyBoxStyle( iBoxObj, iStyle // ); } } // // TrendLines ... // // Pivots ... // has = HasChild(pvPivots); if (has) { // CArrayObj *drawnPivots = new CArrayObj(); count = poiDrawer.DrawPivots( pvPivots, drawnPivots // ); } // has = HasChild(zgPivots); if (has) { // CArrayObj *drawnPivots = new CArrayObj(); count = poiDrawer.DrawPivots( zgPivots, drawnPivots // ); } // // Patterns Bar ... has = HasDirection(iDir); if (has) { // int iCode = 159; ENUM_ARROW_ANCHOR iAnchor = isBullish ? ANCHOR_TOP : ANCHOR_BOTTOM; // XCBarArrowObject *iPatternObj; has = poiDrawer.DrawBarArrow( bar, iPatternObj, iPriceType, iCode, iClr, iWidth, iAnchor, iName, true, // Ignore Bar Tag ... 10 // Threshold ... ); } } // // Check Signal Founded ... has = HasDirection(iDir); if (has) { // // TODO: Provided SL ... double _point = GetPoints(bar.symbol); double slAddition = 5 * _point; double slPrice = isBullish ? iZone.lower - slAddition : iZone.upper + slAddition; // // Prepare Founded Signal ... XTarget targets[]; has = PrepareSignal( signal, iDir, targets, 0, // Use Default R2R ... slPrice, // Provided Price for SL ... 0 // Specified Risk in Point .... ); if (has) { // // Notify On Signal Event ... NotifySignalEventListeners(signal); } } // // Cleanup Resources ... bar.Clean(); iZone.Clean(); signal.Clean(); structure.Clean(); fimaConditions.Clean(); SpecifiedClean(pvPivots); SpecifiedClean(zgPivots); SpecifiedClean(supports); SpecifiedClean(resistances); } /** * Processing New Bar ... * * @param barIndex: int, Specified Bar Index ... */ void ProcessNewBarNKP1(int barIndex = 0) { // // Normalize ... barIndex = NormalizeInt(barIndex, 0); // // Update Helper ... fimaHelper.Update(barIndex); // XOHCL bar; XSignal signal; XBoxZone iZone; int count = 0; bool has = false; int cIdx = 0; int pIdx = cIdx + 1; string iName = NULL; XBoxZone supports[]; XBoxZone resistances[]; bool isBullish = false; bool isBearish = false; double iPrice = EMPTY_VALUE; double iPriceEdge = EMPTY_VALUE; XFIMAMarketStructure structure; XFIMAConditions fimaConditions; ENUM_X_PRICE iPriceType = X_PRICE_NONE; ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE; // XPivot pvPivots[]; string pvTrendName = "XXIFMA2PVTrend"; CChartObjectTrend *pvTrendLine = NULL; ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE; // XPivot zgPivots[]; string zgTrendName = "XFIMA2ZGTrend"; CChartObjectTrend *zgTrendLine = NULL; ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE; // // Initialize Bar as CBar ... has = bar.Init( symbol, period, barIndex // ); if (!has) { // bar.Clean(); return; } // // Retrieve Conditions ... has = fimaHelper.GetConditions( fimaConditions, barIndex, 10 // Loopback ... ); if (!has) { // bar.Clean(); fimaConditions.Clean(); // return; } // // Analyse Market ... poiDetector.AnalyseMarket( bar, structure, analyserConfig // ); // // Collect Support and Resistance Zones and Validate by them ... // // PV Trend Line ... bool hasPVAnalysis = structure.pvAnalysis.IsValid(); if (hasPVAnalysis) { // // Support ... XBoxZone supportBox; has = structure.pvAnalysis.HasSupportBox(supportBox); if (has) { // supportBox.to = bar.time; AddIfNotExists( supportBox, supports // ); } // // Resistance ... XBoxZone resistanceBox; has = structure.pvAnalysis.HasResistanceBox(resistanceBox); if (has) { // resistanceBox.to = bar.time; AddIfNotExists( resistanceBox, supports // ); } // // Pivots ... XPivot pivots[]; count = poiDetector.ExtractPVPivots( pivots, barIndex, 50 // ); has = IsValidSize(count); // // Sort ... Sort( pivots, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Remove Newest ... ArrayRemove( pivots, 0, 1 // ); // // Check Trend ... if (has) { // XPivot highs[]; int highsCount = ExtractPivots( highs, pivots, X_PIVOT_TYPE_PEAK // ); Sort( highs, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // XPivot lows[]; int lowsCount = ExtractPivots( lows, pivots, X_PIVOT_TYPE_VALE // ); Sort( lows, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Check Highs and Lows ... has = IsValidSize(lowsCount) && IsValidSize(highsCount) && lowsCount >= 2 && highsCount >= 2; if (has) { // // Try to Get Market Strucutre ... // bool hasLowerHigh = highs[0].value < highs[1].value; bool hasLowerLow = lows[0].value < lows[1].value; // bool hasHigherHigh = highs[0].value > highs[1].value; bool hasHigherLow = lows[0].value > lows[1].value; // pvTrend = (hasHigherHigh && hasHigherLow) ? X_DIRECTION_BULLISH : (hasLowerHigh && hasLowerLow) ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; has = HasDirection(pvTrend); if (has) { // // Select Swings for Trend Line ... XOHCL tmpBar; int llIDX = -1; int hhIDX = -1; datetime toTime = NULL; datetime fromTime = NULL; double toPrice = EMPTY_VALUE; color trendColor = CLR_NONE; double fromPrice = EMPTY_VALUE; if (IsSpecifiedBullish(pvTrend)) { // llIDX = GetLowest(lows); hhIDX = GetHighest(lows); // trendColor = clrAqua; // toTime = lows[hhIDX].time; toPrice = lows[hhIDX].value; // fromTime = lows[llIDX].time; fromPrice = lows[llIDX].value; } else { // llIDX = GetLowest(highs); hhIDX = GetHighest(highs); // trendColor = clrMagenta; // toTime = highs[llIDX].time; toPrice = highs[llIDX].value; // fromTime = highs[hhIDX].time; fromPrice = highs[hhIDX].value; } // // Check Requirements for Trend ... has = NotEmptyZero(toPrice) && NotEmptyZero(fromPrice) && IsSpecifiedValid(toTime) && IsSpecifiedValid(fromTime); if (has) { // has = poiDrawer.DrawTrendLine( fromPrice, fromTime, toPrice, toTime, pvTrendLine, pvTrendName, true // Ray Right ... ); if (has) { pvTrendLine.Color(trendColor); } } // // Cleanup Resources ... tmpBar.Clean(); } // if (!has) { SpecifiedClean(pivots); } } // // Cleanup Resources ... SpecifiedClean(lows); SpecifiedClean(highs); } // // Draw Pivots ... has = HasChild(pivots); if (has) { // Copy( pivots, pvPivots // ); } // // Cleanup Resources ... SpecifiedClean(pivots); } // // ZigZag Trend Line ... bool hasZGAnalysis = structure.zigzagAnalysis.IsValid(); if (hasZGAnalysis) { // // Support ... XBoxZone supportBox; has = structure.zigzagAnalysis.HasSupportBox(supportBox); if (has) { // supportBox.to = bar.time; AddIfNotExists( supportBox, supports // ); } // // Resistance ... XBoxZone resistanceBox; has = structure.zigzagAnalysis.HasResistanceBox(resistanceBox); if (has) { // resistanceBox.to = bar.time; AddIfNotExists( resistanceBox, supports // ); } // // Pivots ... XPivot pivots[]; count = poiDetector.ExtractZigZagPivots( pivots, barIndex, 10 // ); has = IsValidSize(count); // // Sort ... Sort( pivots, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Remove Newest ... ArrayRemove( pivots, 0, 1 // ); // // Check Trend ... if (has) { // XPivot highs[]; int highsCount = ExtractPivots( highs, pivots, X_PIVOT_TYPE_PEAK // ); Sort( highs, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // XPivot lows[]; int lowsCount = ExtractPivots( lows, pivots, X_PIVOT_TYPE_VALE // ); Sort( lows, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Check Highs and Lows ... has = IsValidSize(lowsCount) && IsValidSize(highsCount) && lowsCount >= 2 && highsCount >= 2; if (has) { // // Try to Get Market Strucutre ... // bool hasLowerHigh = highs[0].value < highs[1].value; bool hasLowerLow = lows[0].value < lows[1].value; // bool hasHigherHigh = highs[0].value > highs[1].value; bool hasHigherLow = lows[0].value > lows[1].value; // zgTrend = (hasHigherHigh && hasHigherLow) ? X_DIRECTION_BULLISH : (hasLowerHigh && hasLowerLow) ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; has = HasDirection(zgTrend); if (has) { // // Select Swings for Trend Line ... XOHCL tmpBar; int llIDX = -1; int hhIDX = -1; datetime toTime = NULL; datetime fromTime = NULL; double toPrice = EMPTY_VALUE; color trendColor = CLR_NONE; double fromPrice = EMPTY_VALUE; if (IsSpecifiedBullish(zgTrend)) { // llIDX = GetLowest(lows); hhIDX = GetHighest(lows); // trendColor = clrAqua; // toTime = lows[hhIDX].time; toPrice = lows[hhIDX].value; // fromTime = lows[llIDX].time; fromPrice = lows[llIDX].value; } else { // llIDX = GetLowest(highs); hhIDX = GetHighest(highs); // trendColor = clrMagenta; // toTime = highs[llIDX].time; toPrice = highs[llIDX].value; // fromTime = highs[hhIDX].time; fromPrice = highs[hhIDX].value; } // // Check Requirements for Trend ... has = NotEmptyZero(toPrice) && NotEmptyZero(fromPrice) && IsSpecifiedValid(toTime) && IsSpecifiedValid(fromTime); if (has) { // has = poiDrawer.DrawTrendLine( fromPrice, fromTime, toPrice, toTime, zgTrendLine, zgTrendName, true // Ray Right ... ); if (has) { zgTrendLine.Color(trendColor); } } // // Cleanup Resources ... tmpBar.Clean(); } // if (!has) { SpecifiedClean(pivots); } } // // Cleanup Resources ... SpecifiedClean(lows); SpecifiedClean(highs); } // // Draw Pivots ... has = HasChild(pivots); if (has) { // Copy( pivots, zgPivots // ); } // // Cleanup Resources ... SpecifiedClean(pivots); } // // Support ... bool hasSupport = structure.support.IsValid(); if (hasSupport) { // AddIfNotExists( structure.support, supports // ); } // // Resistance ... bool hasResistance = structure.resistance.IsValid(); if (hasResistance) { // AddIfNotExists( structure.resistance, resistances // ); } // // Check Required Pattern Exists ... bool hasPinnedBar = HasDirection(structure.pinnedDir); bool hasEngulfedBar = HasDirection(structure.engulfedDir); bool hasFlagPattern = HasDirection(structure.flagPatternDir); bool hasStarPattern = HasDirection(structure.starPatternDir); bool hasRisingPattern = HasDirection(structure.risingPatternDir); bool hasPiercingPattern = HasDirection(structure.piercingPatternDir); bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir); // // Check Bar Pattern Exists ... // and Select Pattern Direction and Price and Price Type ... has = hasPinnedBar || hasEngulfedBar || hasFlagPattern || hasStarPattern || hasSignalKeyBar || hasRisingPattern || hasPiercingPattern; if (has) { // if (hasPinnedBar) { // iDir = structure.pinnedDir; iName = "XPinned_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasEngulfedBar) { // iDir = structure.engulfedDir; iName = "XEngulfed_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasFlagPattern) { // iDir = structure.flagPatternDir; iName = "XFlag_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasStarPattern) { // iDir = structure.starPatternDir; iName = "XStar_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasSignalKeyBar) { // iDir = structure.risingPatternDir; iName = "XRising_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasRisingPattern) { // iDir = structure.piercingPatternDir; iName = "XPiercing_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasPiercingPattern) { // iDir = structure.signalKeyBarPatternDir; iName = "XSignalKey_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } // isBullish = IsSpecifiedBullish(iDir); isBearish = IsSpecifiedBearish(iDir); // // Retrieve Price Type for Validate ... iPriceType = isBullish ? X_PRICE_DOWN : X_PRICE_UP; iPriceEdgeType = isBullish ? X_PRICE_LOW : X_PRICE_HIGH; // iPrice = bar.GetPrice(iPriceType); iPriceEdge = bar.GetPrice(iPriceEdgeType); // // Validate Calculations ... has = HasDirection(iDir) && (isBullish || isBearish) && NotEmptyZero(iPrice) && NotEmptyZero(iPriceEdge) && iPrice != iPriceEdge; if (!has) { // isBullish = false; isBearish = false; iDir = X_DIRECTION_NONE; } } // // Check Petterns Happens ... // Chekc Bullish or Bearish Starter Conditions Exists ... has = HasDirection(iDir); if (has) { // // Do Conditions Validating ... // // Retrieve MA Band for Validation ... double iMABandUpper = fimaConditions.maBandUpperBuffer[cIdx]; double iMABandLower = fimaConditions.maBandLowerBuffer[cIdx]; // // Validate ... // // Validate by Edge Price ... has = isBullish ? iPriceEdge < iMABandLower : iPriceEdge > iMABandUpper; // // Validate by Body Price ... // has = isBullish // ? iPrice < iMABandLower // : iPrice > iMABandUpper; if (!has) { // isBullish = false; isBearish = false; iDir = X_DIRECTION_NONE; } } // // Validate ... // Detect Support and Resistances ... // and Validate Price based on it's ... has = HasDirection(iDir); if (has) { // // Validate Positions Support and Resistance Zone ... int insideZoneIDX = -1; has = has && (isBullish ? HasInside( insideZoneIDX, bar, supports // ) : HasInside( insideZoneIDX, bar, resistances // )); // // Validate Selected Inside Zone ... // whith Bars Edge ... has = IsValidIndex(insideZoneIDX); if (has) { // if (isBullish) { iZone = supports[insideZoneIDX]; } else { iZone = resistances[insideZoneIDX]; } // has = isBullish ? bar.high > supports[insideZoneIDX].upper : bar.low < resistances[insideZoneIDX].lower; if (!has) { // isBullish = false; isBearish = false; iDir = X_DIRECTION_NONE; } } else { // isBullish = false; isBearish = false; iDir = X_DIRECTION_NONE; } } // // Checking Liquidities ... // // Do all Draws Here ... bool canDraw = true; if (canDraw) { // int iWidth = 2; XPOIStyle iStyle; XCBoxObject *iBoxObj = NULL; color iClr = isBullish ? clrYellow : clrDarkOrange; // // Supports ... has = HasChild(supports); if (has) { // count = ArraySize(supports); for (int i = 0; i < count; i++) { // has = poiDrawer.DrawBox( supports[i], iBoxObj, true, // Ignore At ... supports[i].type // Name ... ); if (has) { // poiDrawer.GetBoxStyle( iStyle, supports[i].dir // ); // poiDrawer.ApplyBoxStyle( iBoxObj, iStyle // ); } // iStyle.Clean(); ZeroMemory(iBoxObj); } } // // Resistances ... has = HasChild(resistances); if (has) { // count = ArraySize(resistances); for (int i = 0; i < count; i++) { // has = poiDrawer.DrawBox( resistances[i], iBoxObj, true, // Ignore At ... resistances[i].type // Name ... ); if (has) { // poiDrawer.GetBoxStyle( iStyle, resistances[i].dir // ); // poiDrawer.ApplyBoxStyle( iBoxObj, iStyle // ); } // iStyle.Clean(); ZeroMemory(iBoxObj); } } // // Selected Zone ... has = iZone.IsValid(); if (has) { // has = poiDrawer.DrawBox( iZone, iBoxObj, true, // Ignore At ... iZone.type // Name ... ); if (has) { // poiDrawer.GetBoxStyle( iStyle, iZone.dir // ); // iStyle.clr = iClr; iStyle.width = iWidth; // poiDrawer.ApplyBoxStyle( iBoxObj, iStyle // ); } } // // TrendLines ... // // Pivots ... // has = HasChild(pvPivots); if (has) { // CArrayObj *drawnPivots = new CArrayObj(); count = poiDrawer.DrawPivots( pvPivots, drawnPivots // ); } // has = HasChild(zgPivots); if (has) { // CArrayObj *drawnPivots = new CArrayObj(); count = poiDrawer.DrawPivots( zgPivots, drawnPivots // ); } // // Patterns Bar ... has = HasDirection(iDir); if (has) { // int iCode = 159; ENUM_ARROW_ANCHOR iAnchor = isBullish ? ANCHOR_TOP : ANCHOR_BOTTOM; // XCBarArrowObject *iPatternObj; has = poiDrawer.DrawBarArrow( bar, iPatternObj, iPriceType, iCode, iClr, iWidth, iAnchor, iName, true, // Ignore Bar Tag ... 10 // Threshold ... ); } } // // Check Signal Founded ... has = HasDirection(iDir); // if (has) { Print("a Valid ", ToXString(iDir), " Pattern Exists ..."); } // if (has) { // // TODO: Provided SL ... double _point = GetPoints(bar.symbol); double slAddition = 5 * _point; double slPrice = isBullish ? iZone.lower - slAddition : iZone.upper + slAddition; // // Prepare Founded Signal ... XTarget targets[]; has = PrepareSignal( signal, iDir, targets, 0, // Use Default R2R ... slPrice, // Provided Price for SL ... 0 // Specified Risk in Point .... ); if (has) { // // Notify On Signal Event ... NotifySignalEventListeners(signal); } } // // Cleanup Resources ... bar.Clean(); iZone.Clean(); signal.Clean(); structure.Clean(); fimaConditions.Clean(); SpecifiedClean(pvPivots); SpecifiedClean(zgPivots); SpecifiedClean(supports); SpecifiedClean(resistances); } /** * Processing New Bar ... * * @param barIndex: int, Specified Bar Index ... */ virtual void ProcessNewBar(int barIndex = 0) { // // Normalize ... barIndex = NormalizeInt(barIndex, 0); // // Update Helper ... fimaHelper.Update(barIndex); // XOHCL bar; XSignal signal; XBoxZone iZone; int count = 0; bool has = false; int cIdx = 0; int pIdx = cIdx + 1; string iName = NULL; XBoxZone supports[]; XBoxZone resistances[]; bool isBullish = false; bool isBearish = false; double iPrice = EMPTY_VALUE; double iPriceEdge = EMPTY_VALUE; XFIMAMarketStructure structure; XFIMAConditions fimaConditions; ENUM_X_PRICE iPriceType = X_PRICE_NONE; ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE; // XPivot pvPivots[]; string pvTrendName = "XXIFMA2PVTrend"; CChartObjectTrend *pvTrendLine = NULL; ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE; // XPivot zgPivots[]; string zgTrendName = "XFIMA2ZGTrend"; CChartObjectTrend *zgTrendLine = NULL; ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE; // // Initialize Bar as CBar ... has = bar.Init( symbol, period, barIndex // ); if (!has) { // bar.Clean(); return; } // // Retrieve Conditions ... has = fimaHelper.GetConditions( fimaConditions, barIndex, 10 // Loopback ... ); if (!has) { // bar.Clean(); fimaConditions.Clean(); // return; } // // Analyse Market ... poiDetector.AnalyseMarket( bar, structure, analyserConfig // ); // // Collect Support and Resistance Zones and Validate by them ... // // PV Trend Line ... bool hasPVAnalysis = structure.pvAnalysis.IsValid(); if (hasPVAnalysis) { // // Support ... XBoxZone supportBox; has = structure.pvAnalysis.HasSupportBox(supportBox); if (has) { // supportBox.to = bar.time; AddIfNotExists( supportBox, supports // ); } // // Resistance ... XBoxZone resistanceBox; has = structure.pvAnalysis.HasResistanceBox(resistanceBox); if (has) { // resistanceBox.to = bar.time; AddIfNotExists( resistanceBox, supports // ); } // // Pivots ... XPivot pivots[]; count = poiDetector.ExtractPVPivots( pivots, barIndex, 50 // ); has = IsValidSize(count); // // Sort ... Sort( pivots, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Remove Newest ... ArrayRemove( pivots, 0, 1 // ); // // Check Trend ... if (has) { // XPivot highs[]; int highsCount = ExtractPivots( highs, pivots, X_PIVOT_TYPE_PEAK // ); Sort( highs, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // XPivot lows[]; int lowsCount = ExtractPivots( lows, pivots, X_PIVOT_TYPE_VALE // ); Sort( lows, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Check Highs and Lows ... has = IsValidSize(lowsCount) && IsValidSize(highsCount) && lowsCount >= 2 && highsCount >= 2; if (has) { // // Try to Get Market Strucutre ... // bool hasLowerHigh = highs[0].value < highs[1].value; bool hasLowerLow = lows[0].value < lows[1].value; // bool hasHigherHigh = highs[0].value > highs[1].value; bool hasHigherLow = lows[0].value > lows[1].value; // pvTrend = (hasHigherHigh && hasHigherLow) ? X_DIRECTION_BULLISH : (hasLowerHigh && hasLowerLow) ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; has = HasDirection(pvTrend); if (has) { // // Select Swings for Trend Line ... XOHCL tmpBar; int llIDX = -1; int hhIDX = -1; datetime toTime = NULL; datetime fromTime = NULL; double toPrice = EMPTY_VALUE; color trendColor = CLR_NONE; double fromPrice = EMPTY_VALUE; if (IsSpecifiedBullish(pvTrend)) { // llIDX = GetLowest(lows); hhIDX = GetHighest(lows); // trendColor = clrAqua; // toTime = lows[hhIDX].time; toPrice = lows[hhIDX].value; // fromTime = lows[llIDX].time; fromPrice = lows[llIDX].value; } else { // llIDX = GetLowest(highs); hhIDX = GetHighest(highs); // trendColor = clrMagenta; // toTime = highs[llIDX].time; toPrice = highs[llIDX].value; // fromTime = highs[hhIDX].time; fromPrice = highs[hhIDX].value; } // // Check Requirements for Trend ... has = NotEmptyZero(toPrice) && NotEmptyZero(fromPrice) && IsSpecifiedValid(toTime) && IsSpecifiedValid(fromTime); if (has) { // has = poiDrawer.DrawTrendLine( fromPrice, fromTime, toPrice, toTime, pvTrendLine, pvTrendName, true // Ray Right ... ); if (has) { pvTrendLine.Color(trendColor); } } // // Cleanup Resources ... tmpBar.Clean(); } // if (!has) { SpecifiedClean(pivots); } } // // Cleanup Resources ... SpecifiedClean(lows); SpecifiedClean(highs); } // // Draw Pivots ... has = HasChild(pivots); if (has) { // Copy( pivots, pvPivots // ); } // // Cleanup Resources ... SpecifiedClean(pivots); } // // ZigZag Trend Line ... bool hasZGAnalysis = structure.zigzagAnalysis.IsValid(); if (hasZGAnalysis) { // // Support ... XBoxZone supportBox; has = structure.zigzagAnalysis.HasSupportBox(supportBox); if (has) { // supportBox.to = bar.time; AddIfNotExists( supportBox, supports // ); } // // Resistance ... XBoxZone resistanceBox; has = structure.zigzagAnalysis.HasResistanceBox(resistanceBox); if (has) { // resistanceBox.to = bar.time; AddIfNotExists( resistanceBox, supports // ); } // // Pivots ... XPivot pivots[]; count = poiDetector.ExtractZigZagPivots( pivots, barIndex, 10 // ); has = IsValidSize(count); // // Sort ... Sort( pivots, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Remove Newest ... ArrayRemove( pivots, 0, 1 // ); // // Check Trend ... if (has) { // XPivot highs[]; int highsCount = ExtractPivots( highs, pivots, X_PIVOT_TYPE_PEAK // ); Sort( highs, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // XPivot lows[]; int lowsCount = ExtractPivots( lows, pivots, X_PIVOT_TYPE_VALE // ); Sort( lows, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Check Highs and Lows ... has = IsValidSize(lowsCount) && IsValidSize(highsCount) && lowsCount >= 2 && highsCount >= 2; if (has) { // // Try to Get Market Strucutre ... // bool hasLowerHigh = highs[0].value < highs[1].value; bool hasLowerLow = lows[0].value < lows[1].value; // bool hasHigherHigh = highs[0].value > highs[1].value; bool hasHigherLow = lows[0].value > lows[1].value; // zgTrend = (hasHigherHigh && hasHigherLow) ? X_DIRECTION_BULLISH : (hasLowerHigh && hasLowerLow) ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; has = HasDirection(zgTrend); if (has) { // // Select Swings for Trend Line ... XOHCL tmpBar; int llIDX = -1; int hhIDX = -1; datetime toTime = NULL; datetime fromTime = NULL; double toPrice = EMPTY_VALUE; color trendColor = CLR_NONE; double fromPrice = EMPTY_VALUE; if (IsSpecifiedBullish(zgTrend)) { // llIDX = GetLowest(lows); hhIDX = GetHighest(lows); // trendColor = clrAqua; // toTime = lows[hhIDX].time; toPrice = lows[hhIDX].value; // fromTime = lows[llIDX].time; fromPrice = lows[llIDX].value; } else { // llIDX = GetLowest(highs); hhIDX = GetHighest(highs); // trendColor = clrMagenta; // toTime = highs[llIDX].time; toPrice = highs[llIDX].value; // fromTime = highs[hhIDX].time; fromPrice = highs[hhIDX].value; } // // Check Requirements for Trend ... has = NotEmptyZero(toPrice) && NotEmptyZero(fromPrice) && IsSpecifiedValid(toTime) && IsSpecifiedValid(fromTime); if (has) { // has = poiDrawer.DrawTrendLine( fromPrice, fromTime, toPrice, toTime, zgTrendLine, zgTrendName, true // Ray Right ... ); if (has) { zgTrendLine.Color(trendColor); } } // // Cleanup Resources ... tmpBar.Clean(); } // if (!has) { SpecifiedClean(pivots); } } // // Cleanup Resources ... SpecifiedClean(lows); SpecifiedClean(highs); } // // Draw Pivots ... has = HasChild(pivots); if (has) { // Copy( pivots, zgPivots // ); } // // Cleanup Resources ... SpecifiedClean(pivots); } // // Support ... bool hasSupport = structure.support.IsValid(); if (hasSupport) { // AddIfNotExists( structure.support, supports // ); } // // Resistance ... bool hasResistance = structure.resistance.IsValid(); if (hasResistance) { // AddIfNotExists( structure.resistance, resistances // ); } // // Check Required Pattern Exists ... bool hasPinnedBar = HasDirection(structure.pinnedDir); bool hasEngulfedBar = HasDirection(structure.engulfedDir); bool hasFlagPattern = HasDirection(structure.flagPatternDir); bool hasStarPattern = HasDirection(structure.starPatternDir); bool hasRisingPattern = HasDirection(structure.risingPatternDir); bool hasPiercingPattern = HasDirection(structure.piercingPatternDir); bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir); // // Check Bar Pattern Exists ... // and Select Pattern Direction and Price and Price Type ... has = hasPinnedBar || hasEngulfedBar || hasFlagPattern || hasStarPattern || hasSignalKeyBar || hasRisingPattern || hasPiercingPattern; if (has) { // if (hasPinnedBar) { // iDir = structure.pinnedDir; iName = "XPinned_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasEngulfedBar) { // iDir = structure.engulfedDir; iName = "XEngulfed_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasFlagPattern) { // iDir = structure.flagPatternDir; iName = "XFlag_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasStarPattern) { // iDir = structure.starPatternDir; iName = "XStar_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasSignalKeyBar) { // iDir = structure.risingPatternDir; iName = "XRising_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasRisingPattern) { // iDir = structure.piercingPatternDir; iName = "XPiercing_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasPiercingPattern) { // iDir = structure.signalKeyBarPatternDir; iName = "XSignalKey_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } // isBullish = IsSpecifiedBullish(iDir); isBearish = IsSpecifiedBearish(iDir); // // Retrieve Price Type for Validate ... iPriceType = isBullish ? X_PRICE_DOWN : X_PRICE_UP; iPriceEdgeType = isBullish ? X_PRICE_LOW : X_PRICE_HIGH; // iPrice = bar.GetPrice(iPriceType); iPriceEdge = bar.GetPrice(iPriceEdgeType); // // Validate Calculations ... has = HasDirection(iDir) && (isBullish || isBearish) && NotEmptyZero(iPrice) && NotEmptyZero(iPriceEdge) && iPrice != iPriceEdge; if (!has) { // isBullish = false; isBearish = false; iDir = X_DIRECTION_NONE; } } // // Strategy 1 ... has = Strategy1HasSignal( bar, iZone, iName, supports, resistances, iDir, fimaConditions, structure // ); // // Do all Draws Here ... bool canDraw = true; if (canDraw && has) { // int iWidth = 2; XPOIStyle iStyle; XCBoxObject *iBoxObj = NULL; color iClr = isBullish ? clrYellow : clrDarkOrange; // // Supports ... has = HasChild(supports); if (has) { // count = ArraySize(supports); for (int i = 0; i < count; i++) { // has = poiDrawer.DrawBox( supports[i], iBoxObj, true, // Ignore At ... supports[i].type // Name ... ); if (has) { // poiDrawer.GetBoxStyle( iStyle, supports[i].dir // ); // poiDrawer.ApplyBoxStyle( iBoxObj, iStyle // ); } // iStyle.Clean(); ZeroMemory(iBoxObj); } } // // Resistances ... has = HasChild(resistances); if (has) { // count = ArraySize(resistances); for (int i = 0; i < count; i++) { // has = poiDrawer.DrawBox( resistances[i], iBoxObj, true, // Ignore At ... resistances[i].type // Name ... ); if (has) { // poiDrawer.GetBoxStyle( iStyle, resistances[i].dir // ); // poiDrawer.ApplyBoxStyle( iBoxObj, iStyle // ); } // iStyle.Clean(); ZeroMemory(iBoxObj); } } // // Selected Zone ... has = iZone.IsValid(); if (has) { // has = poiDrawer.DrawBox( iZone, iBoxObj, true, // Ignore At ... iZone.type // Name ... ); if (has) { // poiDrawer.GetBoxStyle( iStyle, iZone.dir // ); // iStyle.clr = iClr; iStyle.width = iWidth; // poiDrawer.ApplyBoxStyle( iBoxObj, iStyle // ); } } // // TrendLines ... // // Pivots ... // has = HasChild(pvPivots); if (has) { // CArrayObj *drawnPivots = new CArrayObj(); count = poiDrawer.DrawPivots( pvPivots, drawnPivots // ); } // has = HasChild(zgPivots); if (has) { // CArrayObj *drawnPivots = new CArrayObj(); count = poiDrawer.DrawPivots( zgPivots, drawnPivots // ); } // // Patterns Bar ... has = HasDirection(iDir); if (has) { // int iCode = 159; ENUM_ARROW_ANCHOR iAnchor = isBullish ? ANCHOR_TOP : ANCHOR_BOTTOM; // XCBarArrowObject *iPatternObj; has = poiDrawer.DrawBarArrow( bar, iPatternObj, iPriceType, iCode, iClr, iWidth, iAnchor, iName, true, // Ignore Bar Tag ... 10 // Threshold ... ); } } // if (has) { Print("a Valid ", ToXString(iDir), " Pattern Exists ..."); } // if (has) { // // TODO: Provided SL ... double _point = GetPoints(bar.symbol); double slAddition = 5 * _point; double slPrice = isBullish ? iZone.lower - slAddition : iZone.upper + slAddition; // // Prepare Founded Signal ... XTarget targets[]; has = PrepareSignal( signal, iDir, targets, 0, // Use Default R2R ... slPrice, // Provided Price for SL ... 0 // Specified Risk in Point .... ); if (has) { // // Notify On Signal Event ... NotifySignalEventListeners(signal); } } // // Cleanup Resources ... bar.Clean(); iZone.Clean(); signal.Clean(); structure.Clean(); fimaConditions.Clean(); SpecifiedClean(pvPivots); SpecifiedClean(zgPivots); SpecifiedClean(supports); SpecifiedClean(resistances); } /** * Check Guards Based on MarketConditions ... * * @param guards: XGuard[] * @param barIndex: int * * @return ( int ) */ int virtual CheckForGuard( XGuard &guards[], int barIndex = 0 // ) { // int result = 0; // SpecifiedClean(guards); // result = ArraySize(guards); // return result; } // // Private ... private: // // Props ... // // Implementing Strategies ... /** * Validate a Pattern based on MA Band ... * * @param bar: XOHCL, reference to Pattern Bar ... * @param patternName: string, detected pattern's name ... * @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ... * @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... * * @return ( bool ) */ bool ValidatePatternBasedOnMABand( XOHCL &bar, string patternName, ENUM_X_DIRECTION patternDir, XFIMAConditions &fimaConditions // ) { // bool result = false; // // Validate ... result = bar.IsValid() && IsXValid(patternName) && HasDirection(patternDir) && fimaConditions.IsValid(); if (!result) { return result; } // // Define Requirements ... bool isBullish = false; bool isBearish = false; double iPrice = EMPTY_VALUE; double iPriceEdge = EMPTY_VALUE; ENUM_X_PRICE iPriceType = X_PRICE_NONE; ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE; // // Calculating Price and Price Types ... // isBullish = IsXBullish(patternDir); isBearish = IsXBearish(patternDir); // iPriceType = isBullish ? X_PRICE_DOWN : X_PRICE_UP; // iPriceEdgeType = isBullish ? X_PRICE_LOW : X_PRICE_HIGH; // iPrice = bar.GetPrice(iPriceType); iPriceEdge = bar.GetPrice(iPriceEdgeType); // // Validate ... result = NotEmptyZero(iPrice) && IsXValid(iPriceType) && NotEmptyZero(iPriceEdge) && IsXValid(iPriceEdgeType) && ((isBullish && !isBearish) || (isBearish && !isBullish)); if (!result) { return result; } // // Validate Pattern based on MA Band ... // // Retrieve MA Band for Validation ... double iMABandUpper = fimaConditions.maBandUpperBuffer[cIdx]; double iMABandLower = fimaConditions.maBandLowerBuffer[cIdx]; // // Validate by Edge Price ... result = isBullish ? iPriceEdge < iMABandLower : iPriceEdge > iMABandUpper; if (!result) { return result; } // return result; } /** * Check Pattern Has Signal Based on Strategy 1 ... * * @param bar: XOHCL, reference to Pattern Bar ... * @param iZone: XBoxZone, reference to holds affected zone ... * @param patternName: string, detected pattern's name ... * @param supports: XBoxZone, array reference to Provide Exists Supports ... * @param resistances: XBoxZone, array reference to Provide Exists Resistances ... * @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ... * @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... * @param fimaMarketStructure: XFIMAMarketStructure, refrence to Provides Market Structure ... * * @return ( bool ) */ bool Strategy1HasSignal( XOHCL &bar, XBoxZone &iZone, string patternName, XBoxZone &supports[], XBoxZone &resistances[], ENUM_X_DIRECTION patternDir, XFIMAMarketStructure &structure, XFIMAConditions &fimaConditions, XFIMAMarketStructure &fimaMarketStructure // ) { // bool result = false; // // Prepare ... iZone.Clean(); // // Validate ... result = bar.IsValid() && IsXValid(patternName) && HasDirection(patternDir) && fimaConditions.IsValid(); if (!result) { return result; } // // Validate Pattern Based on MA Band ... result = ValidatePatternBasedOnMABand( bar, patternName, patternDir, fimaConditions // ); if (!result) { return result; } // // Check Affected Zone ... // Select a Support or Resistance ... int insideZoneIDX = -1; result = (isBullish ? HasInside( insideZoneIDX, bar, supports // ) : HasInside( insideZoneIDX, bar, resistances // )); if (!result) { return result; } // // Filling Affected Zone ... // and Validate it ... if (IsXBullish(patternDir)) { iZone = supports[insideZoneIDX]; } else if (IsXBearish(patternDir)) { iZone = resistances[insideZoneIDX]; } result = iZOne.IsValid(); if (!result) { return result; } // // Validate affected Zone based on Pattern's Bar ... result = IsXBullish(patternDir) ? bar.high > iZZone.upper : IsXBearish(patternDir) ? bar.low < iZone.lower : false; // // Cleanup Resources ... if (!result) { iZone.Clean(); } // return result; } /** * Check Pattern Has Signal Based on Strategy 1 ... * * @param bar: XOHCL, reference to Pattern Bar ... * @param iZone: XBoxZone, reference to holds affected zone ... * @param patternName: string, detected pattern's name ... * @param supports: XBoxZone, array reference to Provide Exists Supports ... * @param resistances: XBoxZone, array reference to Provide Exists Resistances ... * @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ... * @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... * @param fimaMarketStructure: XFIMAMarketStructure, refrence to Provides Market Structure ... * * @return ( bool ) */ bool Strategy2HasSignal( XOHCL &bar, XBoxZone &iZone, string patternName, XBoxZone &supports[], XBoxZone &resistances[], ENUM_X_DIRECTION patternDir, XFIMAMarketStructure &structure, XFIMAConditions &fimaConditions, XFIMAMarketStructure &fimaMarketStructure // ) { // bool result = false; // // Prepare ... // // Validate ... // // Do Detection ... // // Validate result ... // // Cleanup Resources ... // return result; } // }; //