/////////////////////////////////////////////////////// // // 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, bool allowSignallingConditions1 = false, bool allowSignallingConditions2 = false, bool allowSignallingConditions3 = false, bool allowSignallingConditions4 = false, bool allowSignallingConditions5 = false, bool allowSignallingConditions6 = false, 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; 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; // // 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 iBDir; // // Rejected ... bool isRejected = barAnalyser .IsRejected( conditions.bars[cIDX], iBDir // ); bool isBullishRejected = isRejected && IsBullish(iBDir); bool isBearishRejected = isRejected && IsBearish(iBDir); // // Engulfed ... bool isEngulfed = barAnalyser .IsEngulfed( conditions.bars[cIDX], iBDir // ); bool isBullishEngulfed = isEngulfed && IsBullish(iBDir); bool isBearishEngulfed = isEngulfed && IsBearish(iBDir); // // Momentum ... bool isMomentum = barAnalyser .IsMomentum( conditions.bars[cIDX], iBDir // ); bool isBullishMomentum = isMomentum && IsBullish(iBDir); bool isBearishMomentum = isMomentum && IsBearish(iBDir); // bool isBarBullishPressured = isBullishRejected || isBullishEngulfed || isBullishMomentum; // bool isBarBearishPressured = isBearishRejected || isBearishEngulfed || isBearishMomentum; // // Implement Signalling Conditions ... // // -------------- // Conditions 1: // -------------- // Descriptions: // - [] Detect Parabolic Sar Direction Change ... // - [] Check Some others Conditions based on Changed Direction ... // - [] Generate Direction Change Zone ... // - [] Use it to Fill Signal Zone ... // ------------------------------------ // bool isCond1Bullish = false; bool isCond1Bearish = false; if (allowSignallingConditions1) { // isCond1Bullish = // // Start ... (isSarBullishStart && !isSarBearishStart) && // // SCORE ... isScoreBullish && // // BAR ... isBarBullishPressured && // // KI ... // conditions.isKIUp && conditions.isKIBullish && // // ATR ... conditions.isATRUp && // // TREND ... conditions.isTrendUp // && // conditions.isTrendBullish // ; // 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) { // // Generate Direction Shift Zone ... has = GenerateSarDirectionShiftBox( signalZone, helper, conditions // ); if (has) { // iTo = signalZone.to; iDir = signalZone.dir; iType = signalZone.type; iFrom = signalZone.from; iUpper = signalZone.upper; iLower = signalZone.lower; } } // ---------------------------------- // // -------------- // Conditions 2: // -------------- // Descriptions: // - [] Detect Trend Direction Change ... // - [] Check Some others Conditions based on Changed Direction ... // - [] Generate Direction Change Zone ... // - [] Use it to Fill Signal Zone ... // ------------------------------------ // bool isCond2Bullish = false; bool isCond2Bearish = false; if (allowSignallingConditions2) { // isCond2Bullish = // // Start ... (isTrendBullishStart && !isTrendBearishStart) // ; // isCond2Bearish = // // Start ... (isTrendBearishStart && !isTrendBullishStart) // ; } // bool isCond2 = isCond2Bullish || isCond2Bearish; if (isCond2) { // // Generate Direction Shift Zone ... has = GenerateTrendDirectionShiftBox( signalZone, helper, conditions // ); if (has) { // iTo = signalZone.to; iDir = signalZone.dir; iType = signalZone.type; iFrom = signalZone.from; iUpper = signalZone.upper; iLower = signalZone.lower; } } // ------------------------------------ // // -------------- // Conditions 3: // -------------- // Descriptions: // - [] Detect Delta Direction Change ... // - [] Check Some others Conditions based on Changed Direction ... // - [] Generate Direction Change Zone ... // - [] Use it to Fill Signal Zone ... // ------------------------------------ // bool isCond3Bullish = false; bool isCond3Bearish = false; if (allowSignallingConditions3) { // isCond3Bullish = // // Start ... (isDeltaBullishStart && !isDeltaBearishStart) // ; // isCond3Bearish = // // Start ... (isDeltaBearishStart && !isDeltaBullishStart) // ; } // bool isCond3 = isCond3Bullish || isCond3Bearish; if (isCond3) { // // Generate Direction Shift Zone ... has = GenerateDeltaDirectionShiftBox( signalZone, helper, conditions // ); if (has) { // iTo = signalZone.to; iDir = signalZone.dir; iType = signalZone.type; iFrom = signalZone.from; iUpper = signalZone.upper; iLower = signalZone.lower; } } // ------------------------------------ // // -------------- // Conditions 4: // -------------- // Descriptions: // - [] Detect Volume Direction Change ... // - [] Check Some others Conditions based on Changed Direction ... // - [] Generate Direction Change Zone ... // - [] Use it to Fill Signal Zone ... // ------------------------------------ // bool isCond4Bullish = false; bool isCond4Bearish = false; if (allowSignallingConditions4) { // isCond4Bullish = // // Start ... (isVolumeBullishStart && !isVolumeBearishStart) // ; // isCond4Bearish = // // Start ... (isVolumeBearishStart && !isVolumeBullishStart) // ; } // bool isCond4 = isCond4Bullish || isCond4Bearish; if (isCond4) { // // Generate Direction Shift Zone ... has = GenerateVolumeDirectionShiftBox( signalZone, helper, conditions // ); if (has) { // iTo = signalZone.to; iDir = signalZone.dir; iType = signalZone.type; iFrom = signalZone.from; iUpper = signalZone.upper; iLower = signalZone.lower; } } // ------------------------------------ // // -------------- // Conditions 5: // -------------- // Descriptions: // - [] Detect Signal Bar Direction Change ... // - [] Check Some others Conditions based on Changed Direction ... // - [] Generate Direction Change Zone ... // - [] Use it to Fill Signal Zone ... // ------------------------------------ // bool isCond5Bullish = false; bool isCond5Bearish = false; if (allowSignallingConditions5) { // isCond5Bullish = // // Start ... (isSBarBullishStart && !isSBarBearishStart) // ; // isCond5Bearish = // // Start ... (isSBarBearishStart && !isSBarBullishStart) // ; } // bool isCond5 = isCond5Bullish || isCond5Bearish; if (isCond5) { // // Generate Direction Shift Zone ... has = GenerateSignalBarDirectionShiftBox( signalZone, helper, conditions // ); if (has) { // iTo = signalZone.to; iDir = signalZone.dir; iType = signalZone.type; iFrom = signalZone.from; iUpper = signalZone.upper; iLower = signalZone.lower; } } // ------------------------------------ // // -------------- // Conditions 6: // -------------- // Descriptions: // - [] Detect HK Signal Bar Direction Change ... // - [] Check Some others Conditions based on Changed Direction ... // - [] Generate Direction Change Zone ... // - [] Use it to Fill Signal Zone ... // ------------------------------------ // bool isCond6Bullish = false; bool isCond6Bearish = false; if (allowSignallingConditions6) { // isCond6Bullish = // // Start ... (isHKSBarBullishStart && !isHKSBarBearishStart) // ; // isCond6Bearish = // // Start ... (isHKSBarBearishStart && !isHKSBarBullishStart) // ; } // bool isCond6 = isCond6Bullish || isCond6Bearish; if (isCond6) { // // Generate Direction Shift Zone ... has = GenerateHKSignalBarDirectionShiftBox( signalZone, helper, conditions // ); if (has) { // iTo = signalZone.to; iDir = signalZone.dir; iType = signalZone.type; iFrom = signalZone.from; iUpper = signalZone.upper; iLower = signalZone.lower; } } // ------------------------------------ // // Summarizing Signalling Results ... // isBullish = // isCond1Bullish || isCond2Bullish || isCond3Bullish || isCond4Bullish || isCond5Bullish || isCond6Bullish // ; // isBearish = // isCond1Bearish || isCond2Bearish || isCond3Bearish || isCond4Bearish || isCond5Bearish || isCond6Bearish // ; } // // Summarize Result ... 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 = signalZone.type + "_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) { // XCATBPivotStyle iStyle; iStyle.width = 2; iStyle.clr = isBullish ? clrYellow : clrOrange; iStyle.style = STYLE_SOLID; // XCBoxObject *iObj; has = drawer .drawer .DrawBox( signalZone, iObj // ); if (has) { drawer.ApplyPivotStyle(iObj, iStyle); } } // Print("Conditions ..."); // signalZone.Clean(); } // // Validate Result ... result = signalZone.IsValid(); // // Cleanup Resources ... // if (!result) { // signalZone.Clean(); conditions.Clean(); } // return result; } //