/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Library // --------------------------------------- // Name: XCATBEASignallerLib // Description: required Parsers for XCATBEA Signaller ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property library #property copyright "Copyright `023, SaherElm IT Center" #property link "https://www.saherelm.ir" #property version "1.00" #property strict // // Imports ... #include "../../Helpers/x-saherelm.x121.xcatb.helper.mq5" #include "../../Libraries/x-saherelm.common.lib.mq5" #include "../../Libraries/x-saherelm.x-poi.lib.mq5" #include "../../Libraries/x-saherelm.x-trade.lib.mq5" #include "../Classes/xcatbea.x-poi.detector.class.mq5" #include "../Classes/xcatbea.x-poi.drawer.class.mq5" #include "../Libraries/xcatbea.lib.mq5" // // Definitions ... // struct XCATBEAStrategyConditions { // // Props ... // string symbol; ENUM_TIMEFRAMES period; // // Setup Props ... // double sl; double tp; double pivot; double point; double entry; double reward; string provider; // XTarget targets[]; // datetime time; datetime setupTime; datetime triggerTime; // XBoxZone pivotZone; ENUM_X_DIRECTION dir; XTriggerBlock triggerBlock; ENUM_X_POSITION_TYPES type; X121XCatbConditions conditions; // // Constructor ... XCATBEAStrategyConditions() { Clean(); } // // Tools ... /** * Cleaning Up ... */ void Clean() { // sl = 0; tp = 0; pivot = 0; point = 0; entry = 0; reward = 0; // symbol = NULL; period = NULL; provider = NULL; // time = NULL; setupTime = NULL; triggerTime = NULL; // Clean(targets); // pivotZone.Clean(); conditions.Clean(); triggerBlock.Clean(); // dir = X_DIRECTION_NONE; type = X_POSITION_TYPE_NONE; // ZeroMemory(this); } // // Signalling ... /** * Validate ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = IsSpecifiedValid(symbol) && IsSpecifiedValid(period) && IsSpecifiedValid(time); // return result; } /** * Check Conditions Has Valid Bullish Signal ... * * @return ( bool ) */ bool HasBullishSignal() { // bool result = false; // result = (sl > 0 || tp > 0) && IsValid() && HasDirection(dir); if (!result) { return result; } // result = IsBullish(dir); // return result; } /** * Check Conditions Has Valid Bearish Signal ... * * @return ( bool ) */ bool HasBearishSignal() { // bool result = false; // result = (sl > 0 || tp > 0) && IsValid() && HasDirection(dir); if (!result) { return result; } // result = IsBearish(dir); // return result; } // // Setting Up and Triggering Up ... /** * Check Condition is Setting Up ... * * @param dir: ENUM_X_DIRECTION member, Setting Up Direction ... * * @return ( bool ) */ bool IsSetuped() { // bool result = false; // result = IsValid(setupTime) && HasDirection(dir); if (!result) { return result; } // return result; } /** * Calculate Setup Age ... * * @return ( int ) */ int GetSetupAge() { // int result = 0; // if (!IsSetuped()) { return result; } // result = (int)(TimeCurrent() - setupTime) / PeriodSeconds(period); // return result; } /** * Detect How we Can Trigger Signal ... * * @return ( bool ) */ bool CanTrigger() { // bool result = false; // result = // sl > 0 && IsValid(symbol) && IsValid(period) && IsValid(triggerTime) && type != X_POSITION_TYPE_ALL && type != X_POSITION_TYPE_NONE // ; // return result; } // }; /** * Converts Strategy Conditions to Signal ... */ bool ToSignal( XSignal &signal, XCATBEAStrategyConditions &conditions // ) { // bool result = false; // // Normalize Args ... signal.Clean(); // // Validate Args ... result = conditions.IsValid() && conditions.IsSetuped() && conditions.CanTrigger(); if (!result) { return result; } // // Do Converting ... signal.volume = 0.01; signal.tp = conditions.tp; signal.sl = conditions.sl; signal.entry = conditions.entry; signal.symbol = conditions.symbol; signal.period = conditions.period; signal.mode = X_ORDER_MODE_MARKET; signal.time = conditions.triggerTime; signal.provider = conditions.provider; signal.type = conditions.type == X_POSITION_TYPE_LONG ? POSITION_TYPE_BUY : POSITION_TYPE_SELL; signal.conditions = conditions .conditions .GenerateSummary( false, true, true, false // Ignore False Conditions ... ); Copy( conditions.targets, signal.targets // ); // // Validate Result ... result = signal.IsValid(); // return result; } /** * Detect Signal Zone based on Market Conditions ... * * @param helper: XCX121XCatbHelper instance pointer ... * @param barAnalyser: XCBarAnalyser instance pointer ... * @param conditions: X121XCatbConditions instance reference, hold signalling Conditions ... * @param signalZone: XBoxZone instance reference, hold Signal Zone ... * @param barIndex: int, Bar Index ... * @param loopback: int, Loopback for Market Conditions ... * * @return ( bool ) */ bool DetectSignalZone( XCX121XCatbHelper *helper, XCXCATBEAPOIDrawer *drawer, XCXCATBEAPOIDetector *detector, XCBarAnalyser *barAnalyser, X121XCatbConditions &conditions, XBoxZone &signalZone, int barIndex = 0, int loopback = 10 // ) { // bool result = false; // // Normalize Args ... signalZone.Clean(); conditions.Clean(); loopback = NormalizeInt(loopback, 0); barIndex = NormalizeInt(barIndex, 0); // // Validate Args ... result = helper != NULL && detector != NULL && barAnalyser != NULL; if (!result) { return result; } // // Try to Recieve Conditions of Market ... // result = helper.GetConditions( conditions, barIndex, loopback // ); // int zIDX = 0; int cIDX = zIDX + 1; int pIDX = cIDX + 1; int p2IDX = pIDX + 1; int p3IDX = p2IDX + 1; int p4IDX = p3IDX + 1; // int idx = -1; XBoxZone iPeak; XBoxZone iVale; XBoxZone iOBBull; XBoxZone iOBBear; XBoxZone iMTBull; XBoxZone iMTBear; bool has = false; bool isBullish = false; bool isBearish = false; double bullishScore = 0; double bearishScore = 0; // double iUpper = 0; double iLower = 0; string iType = NULL; datetime iTo = NULL; string iSymbol = NULL; datetime iFrom = NULL; ENUM_TIMEFRAMES iPeriod = NULL; ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; // // Select MT Block ... if (result) { // // New MT Pivot Detected ... if (detector.newMTBullishPivotDetected) { // idx = GetYoungest(detector.mtBullishPivots); if (IsValidIndex(idx)) { iMTBull = detector.mtBullishPivots[idx]; } } else if (detector.newMTBearishPivotDetected) { // idx = GetYoungest(detector.mtBearishPivots); if (IsValidIndex(idx)) { iMTBear = detector.mtBearishPivots[idx]; } } // // Draw MT ... // // Bullish ... has = iMTBull.IsValid(); if (has) { // iMTBull.to = conditions.bars[zIDX].time; // XCBoxObject *iObj; has = drawer .drawer .DrawBox( iMTBull, iObj // ); if (has) { drawer.ApplyMTBullishPivotStyle(iObj); } } // // Bearish ... has = iMTBear.IsValid(); if (has) { // iMTBear.to = conditions.bars[zIDX].time; // XCBoxObject *iObj; has = drawer .drawer .DrawBox( iMTBear, iObj // ); if (has) { drawer.ApplyMTBearishPivotStyle(iObj); } } } // // Select Peak and Vale ... // this used to Signalling Better ... if (result) { // // Select Peak ... idx = GetLowest( conditions.bars[cIDX], detector.peakPivots // ); if (IsValidIndex(idx)) { // iPeak = detector.peakPivots[idx]; iPeak.to = conditions.bars[zIDX].time; } // // Select Vale ... idx = GetHighest( conditions.bars[cIDX], detector.valePivots // ); if (IsValidIndex(idx)) { // iVale = detector.valePivots[idx]; iVale.to = conditions.bars[zIDX].time; } // // Checkig Result ... result = iPeak.IsValid() && iVale.IsValid(); // // Draw Peak and Vales ... if (result) { // // Object Definitions ... XCBoxObject *iObj; // // Draw Peak ... has = drawer .drawer .DrawBox( iPeak, iObj // ); if (has) { drawer.ApplyPeakPivotStyle(iObj); } ZeroMemory(iObj); // // Draw Vale ... has = drawer .drawer .DrawBox( iVale, iObj // ); if (has) { drawer.ApplyValePivotStyle(iObj); } ZeroMemory(iObj); } } // // Signalling ... if (result) { // iSymbol = conditions.symbol; iPeriod = conditions.period; // // Looking For Conditions ... // // Reading Values ... // // Readng Scores ... conditions.GenerateScore( bullishScore, bearishScore // ); // // Prepared Conditions ... // // SCORES ... bool isScoreBullish = bullishScore > bearishScore; bool isScoreBearish = bearishScore > bullishScore; // // SAR ... // bool isSarBullishStart = // ( // // Current SAR is Directional ... conditions.isSarBullish && // // Previous InDirectional Sar Exists ... helper.lastSarBearish.IsValid() && // // Current Close is Over previous Sar ... conditions.bars[cIDX].close > helper.lastSarBearish.after && // // Before Close is not Over previous Sar ... conditions.bars[pIDX].close <= helper.lastSarBearish.after // ) // ; // bool isSarBearishStart = // ( // // Current SAR is Directional ... conditions.isSarBearish && // // Previous InDirectional Sar Exists ... helper.lastSarBullish.IsValid() && // // Current Close is Under previous ... conditions.bars[cIDX].close < helper.lastSarBullish.after && // // Before Close is not Under previous ... conditions.bars[pIDX].close >= helper.lastSarBullish.after // ) // ; // // TREND ... // bool isTrendBullishStart = // ( // // Current Trend is Directional ... conditions.isTrendBullish && // // Previous InDirectiona; Trend Exists ... helper.lastTrendBearish.IsValid() && // // Current Close is Over previous ... conditions.bars[cIDX].close > helper.lastTrendBearish.after && // // Before close is not Over previous ... conditions.bars[pIDX].close <= helper.lastTrendBearish.after // ) // ; // bool isTrendBearishStart = // ( // // Current Trend is Directional ... conditions.isTrendBearish && // // Previous InDirectiona; Trend Exists ... helper.lastTrendBullish.IsValid() && // // Current Close is Under previous ... conditions.bars[cIDX].close < helper.lastTrendBullish.after && // // Before close is not Under previous ... conditions.bars[pIDX].close >= helper.lastTrendBullish.after // ) // ; // // ADX ... // bool isADXBullishStart = // ( // // ADX Value is Switched to Strong ... conditions.adxBuffer[cIDX] > conditions.adxThreshold && conditions.adxBuffer[pIDX] <= conditions.adxThreshold && // // ADX must Up ... conditions.adxBuffer[cIDX] > conditions.adxBuffer[pIDX] && // // ADX +DI is Bigger than -DI ... conditions.adxpBuffer[cIDX] > conditions.adxnBuffer[cIDX] && // // ADX +DI is Up ... conditions.adxpBuffer[cIDX] > conditions.adxpBuffer[pIDX] // ) // ; // bool isADXBearishStart = // ( // // ADX Value is Switched to Strong ... conditions.adxBuffer[cIDX] > conditions.adxThreshold && conditions.adxBuffer[pIDX] <= conditions.adxThreshold && // // ADX must Up ... conditions.adxBuffer[cIDX] > conditions.adxBuffer[pIDX] && // // ADX -DI is Bigger than +DI ... conditions.adxnBuffer[cIDX] > conditions.adxpBuffer[cIDX] && // // ADX -DI is Up ... conditions.adxnBuffer[cIDX] > conditions.adxnBuffer[pIDX] // ) // ; // // DELTA ... // bool isDeltaBullishStart = // // Check State ... ( // // Delta is Up ... conditions.deltaBuffer[cIDX] > conditions.deltaBuffer[pIDX] && // // Delta Signal is Up ... conditions.deltaSignalBuffer[cIDX] > conditions.deltaSignalBuffer[pIDX] && // // Delta Crossed Over Delta Signal ... conditions.deltaBuffer[cIDX] > conditions.deltaSignalBuffer[cIDX] // ) // && // // Check Last InDirectional Exists ... helper.lastDeltaBearish.IsValid() && // // Current Close is Over last ... conditions.bars[cIDX].close > helper.lastDeltaBearish.after && // // Before Close is not Over last ... conditions.bars[pIDX].close <= helper.lastDeltaBearish.after // ; // bool isDeltaBearishStart = // // Check State ... ( // // Delta is Down ... conditions.deltaBuffer[cIDX] < conditions.deltaBuffer[pIDX] && // // Delta Signal is Down ... conditions.deltaSignalBuffer[cIDX] < conditions.deltaSignalBuffer[pIDX] && // // Delta Crossed Under Delta Signal ... conditions.deltaBuffer[cIDX] < conditions.deltaSignalBuffer[cIDX] // ) // && // // Check Last InDirectional Exists ... helper.lastDeltaBullish.IsValid() && // // Current Close is Under last ... conditions.bars[cIDX].close < helper.lastDeltaBullish.after && // // Before Close is not Under last ... conditions.bars[pIDX].close >= helper.lastDeltaBullish.after // ; // // VOLUME ... // bool isVolumeBullishStart = // ( // // // Volume is Up ... conditions.bullishVolumeBuffer[1] > conditions.bullishVolumeBuffer[2] && // // Volume Signal is Up ... conditions.bullishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[2] && // // Volume Signals Crossed Over ... conditions.bullishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[1] // ) // && // // Check Last InDirectional Exists ... helper.lastVolumeBearish.IsValid() && // // Current Close is Over last ... conditions.bars[cIDX].close > helper.lastVolumeBearish.after && // // Before Close is not Over last ... conditions.bars[pIDX].close <= helper.lastVolumeBearish.after // ; // bool isVolumeBearishStart = // ( // // // Volume is Up ... conditions.bearishVolumeBuffer[1] > conditions.bearishVolumeBuffer[2] && // // Volume Signal is Up ... conditions.bearishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[2] && // // Volume Signals Crossed Over ... conditions.bearishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[1] // ) // && // // Check Last InDirectional Exists ... helper.lastVolumeBullish.IsValid() && // // Current Close is Over last ... conditions.bars[cIDX].close < helper.lastVolumeBullish.after && // // Before Close is not Over last ... conditions.bars[pIDX].close >= helper.lastVolumeBullish.after // ; // // SIGNAL Bar ... // bool isSBarBullishStart = // ( // // Check Direction ... conditions.isSBarBullish && // // Previous InDirectional Exists ... helper.lastSignalBarBearish.IsValid() && // // Current Signal Bar close over prev ... conditions.sBarCloseBuffer[cIDX] > helper.lastSignalBarBearish.after && // // Prev Signal Bar not close over prev ... conditions.sBarCloseBuffer[pIDX] <= helper.lastSignalBarBearish.after // ) // ; // bool isSBarBearishStart = // ( // // Check Direction ... conditions.isSBarBearish && // // Previous InDirectional Exists ... helper.lastSignalBarBullish.IsValid() && // // Current Signal Bar close over prev ... conditions.sBarCloseBuffer[cIDX] < helper.lastSignalBarBullish.after && // // Prev Signal Bar not close over prev ... conditions.sBarCloseBuffer[pIDX] >= helper.lastSignalBarBullish.after // ) // ; // // HKSIGNAL Bar ... // bool isHKSBarBullishStart = // ( // // Check Direction ... conditions.isHKSBarBullish && // // Previous InDirectional Exists ... helper.lastHKSignalBarBearish.IsValid() && // // Current Signal Bar close over prev ... conditions.hkSBarCloseBuffer[cIDX] > helper.lastHKSignalBarBearish.after && // // Prev Signal Bar not close over prev ... conditions.hkSBarCloseBuffer[pIDX] <= helper.lastHKSignalBarBearish.after // ) // ; // bool isHKSBarBearishStart = // ( // // Check Direction ... conditions.isHKSBarBearish && // // Previous InDirectional Exists ... helper.lastHKSignalBarBullish.IsValid() && // // Current Signal Bar close over prev ... conditions.hkSBarCloseBuffer[cIDX] < helper.lastHKSignalBarBullish.after && // // Prev Signal Bar not close over prev ... conditions.hkSBarCloseBuffer[pIDX] >= helper.lastHKSignalBarBullish.after // ) // ; // // Detect Bar Verifications ... // ENUM_X_DIRECTION iDir; // // Rejected ... bool isRejected = barAnalyser .IsRejected( conditions.bars[cIDX], iDir // ); bool isBullishRejected = isRejected && IsBullish(iDir); bool isBearishRejected = isRejected && IsBearish(iDir); // // Engulfed ... bool isEngulfed = barAnalyser .IsEngulfed( conditions.bars[cIDX], iDir // ); bool isBullishEngulfed = isEngulfed && IsBullish(iDir); bool isBearishEngulfed = isEngulfed && IsBearish(iDir); // // Momentum ... bool isMomentum = barAnalyser .IsMomentum( conditions.bars[cIDX], iDir // ); bool isBullishMomentum = isMomentum && IsBullish(iDir); bool isBearishMomentum = isMomentum && IsBearish(iDir); // bool isBarBullishPressured = isBullishRejected || isBullishEngulfed || isBullishMomentum; // bool isBarBearishPressured = isBearishRejected || isBearishEngulfed || isBearishMomentum; // // Implement Signalling Conditions ... // // -------------- // Conditions 1: // -------------- // Descriptions: // - [] Detect Parabolic Sar Start ... // - [] Convert is to Box ... // ------------------------------------ // bool isCond1Bullish = // // Start ... (isSarBullishStart && !isSarBearishStart) && // // SCORE ... isScoreBullish && // // BAR ... isBarBullishPressured && // // KI ... // conditions.isKIUp && conditions.isKIBullish && // // ATR ... conditions.isATRUp && // // TREND ... conditions.isTrendUp // && // conditions.isTrendBullish // ; // bool isCond1Bearish = // // Start ... (isSarBearishStart && !isSarBullishStart) && // // SCORE ... isScoreBearish && // // BAR ... isBarBearishPressured && // // KI ... // conditions.isKIDown && conditions.isKIBearish && // // ATR ... conditions.isATRDown && // // TREND ... conditions.isTrendDown // && // conditions.isTrendBearish // ; // bool isCond1 = isCond1Bullish || isCond1Bearish; if (isCond1) { // // Validate Some Other Requirements ... // // // // We Have to Detect Youngest Order Block ... // // or Mitigation Block ... // if (isCond1Bullish) // { // // // // // // OB ... // // idx = GetYoungest(detector.obBullishPivots); // // has = IsValidIndex(idx); // // if (has) // // { // // iOB = detector.obBullishPivots[idx]; // // } // // // // MT ... // idx = GetYoungest(detector.mtBullishPivots); // has = IsValidIndex(idx); // if (has) // { // iOB = detector.mtBullishPivots[idx]; // } // } // else if (isCond1Bearish) // { // // // // OB // // idx = GetYoungest(detector.obBearishPivots); // // has = IsValidIndex(idx); // // if (has) // // { // // iOB = detector.obBearishPivots[idx]; // // } // // // // MT // idx = GetYoungest(detector.mtBearishPivots); // has = IsValidIndex(idx); // if (has) // { // iMT = detector.mtBearishPivots[idx]; // } // } // // // // Now we can Do some Verifications Using these ... // result = // isCond1Bullish // ? iMT.IsBullish() // : iMT.IsBearish(); // if (!result) // { // // // isCond1Bullish = false; // isCond1Bearish = false; // } // // All Requirements based on Cond 1 ... } // ---------------------------------- // // Summarizing Result ... // isBullish = // isCond1Bullish // ; // isBearish = // isCond1Bearish // ; } // result = isBullish || isBearish; // // Preparing Signal Zone ... if (result) { // iDir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // // Preparing Signal Zone ... signalZone.to = iTo; signalZone.dir = iDir; signalZone.from = iFrom; signalZone.type = iType; signalZone.upper = iUpper; signalZone.lower = iLower; signalZone.symbol = iSymbol; signalZone.period = iPeriod; // // Temparory Object ... color iColor = isBullish ? clrAqua : clrMagenta; string iName = "Conditions_" + ToString(iDir) + "_" + ToString(((int)conditions.time)); // CChartObjectVLine *iObj = new CChartObjectVLine(); has = iObj.Create( 0, iName, 0, conditions.bars[zIDX].time // ); if (has) { // iObj.Color(iColor); } // // Validate Signal Zone and Draw it ... has = signalZone.IsValid(); if (has) { drawer.DrawBox(signalZone); } // Print("Conditions ..."); } // // Validate Result ... result = signalZone.IsValid(); // // Cleanup Resources ... // iPeak.Clean(); iVale.Clean(); iOBBull.Clean(); iOBBear.Clean(); iMTBull.Clean(); iMTBear.Clean(); // if (!result) { // signalZone.Clean(); conditions.Clean(); } // return result; } //