/////////////////////////////////////////////////////// // // SaherElm IT Center MQL4 X Signal Global Library // --------------------------------------------------- // saherelm useful tools and definitions ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// #property library #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://www.saherelm.ir" #property version "1.00" #property strict // // Includes library ... #include "../Libraries/x-saherelm.lib.mq4" // // Includes Indicator library ... #include "../Libraries/x-saherelm.indicator.lib.mq4" // // Includes Models library ... #include "../Libraries/x-saherelm.models.lib.mq4" // // START Inputs ... // // input string xStarter = "- X Signal Provider -"; // ---> X Signal Provider <--- // input bool enableXSignalling = true; // X Signalling Enable // input bool enableXLong = true; // X Signalling Enable Long input bool enableXShort = true; // X Signalling Enable Short // input double xShortR2R = 3; // X Short Risk To Reward Ratio input double xShortLotsPerTradePercent = 0.0002; // X Lots Percent per Short Trades input double xShortMaxDrawdownPerTradePercent = 0.4; // X Max Allowed DrawDown Percent per Short Trade // input double xLongR2R = 3; // X Long Risk To Reward Ratio input double xLongLotsPerTradePercent = 0.0002; // X Lots Percent per Short Trades input double xLongMaxDrawdownPerTradePercent = 0.4; // X Max Allowed DrawDown Percent per Long Trade // input double xSharpDetectorFactor = 700; // X Sharp Detection Factor // input int xMaximumCandlesPerTrade = 206; // X Maximum Candles which a Trade can open // input int xOscillatorLength = 7; // X Oscillator Length // input double xPSarStep = 0.02; // X Parabolic Sar Step input double xPSarMaximum = 0.2; // X Parabolic Sar Maximum // input int xRangeMarketLength = 5; // X Range Detector Length // input int xSwingLength = 7; // X Signal Swing Length // // END Inputs ... // // // START Global Requirement Functions ... // // // X Based Signal Conditions ... struct XSignalConditions { datetime startTime; datetime signalTime; datetime entryTime; }; // struct XMarketState { double psar; double fast; double slow; double open; double verifier; double oscillator; double oscillatorVerifier; }; // static XSignalConditions xLongConds; static bool xCloseLongTrades = false; static bool xWaitForLongSignals = true; // static XSignalConditions xShortConds; static bool xCloseShortTrades = false; static bool xWaitForShortSignals = true; // // Count Number of Closed Maximum DrawDown Trades ... static int xFailedSignals = 0; // datetime lastVerifierTouched; // // END Global Requirement Functions ... // // // START Functions ... // // // Check and Fill Long and Short Signal Handlers ... void CheckXSignalHandler( const int bar_index ) { // // Check Market For Enable/Disable Signal Handlers ... // Checking Market for Long Signals ... // if ( !enableXSignalling || !(enableXLong || enableXShort) ) { return; } // datetime barTime = iTime( _Symbol, _Period, bar_index ); // XOHCL candle = GetCandleModel(bar_index); XOHCL pCandle = GetCandleModel(bar_index + 1); XTPOWState tPowState = GetXTPowState( bar_index + 1, xSwingLength ); // XMarketState state = GetXMarketState( bar_index + 1 ); // // Check Verifier Last Touched ... bool isVerifierTouched = pCandle.high > state.verifier && pCandle.low < state.verifier; // // Disable Signals if a signal Failed ... if (xFailedSignals) { // // TODO: Complete this ... } // // Enable Or Disable Signalling ... if (isVerifierTouched) { // lastVerifierTouched = barTime; // if (xWaitForLongSignals) { xWaitForLongSignals = false; } // if (xWaitForShortSignals) { xWaitForShortSignals = false; } } else { // int lastVerifierTouchedBarIndex = iBarShift( _Symbol, _Period, lastVerifierTouched ); // int distance = MathAbs(lastVerifierTouchedBarIndex - bar_index); // if ( !xWaitForLongSignals && distance > (xSwingLength * 2) ) { xWaitForLongSignals = true; } // if ( !xWaitForShortSignals && ( distance > (xSwingLength * 2) || ( tPowState.powerDown > tPowState.powerUp && tPowState.powerDown < 49 ) ) ) { xWaitForShortSignals = true; } } // // Close All Long Open Trades ... if ( tPowState.powerDown > 55 && tPowState.powerDown > tPowState.powerUp ) { // xCloseLongTrades = true; } } // // Check and Fill Long Signal Conditions ... void CheckXLongSignalConditions( const int bar_index ) { // if ( !enableXLong || !enableXSignalling || !xWaitForLongSignals ) { return; } // datetime barTime = iTime( _Symbol, _Period, bar_index ); // bool isCrossOver = false; bool isCrossUnder = false; // XMarketState cState = GetXMarketState(1); XMarketState pState = GetXMarketState(2); // isCrossUnder = cState.fast < cState.slow && !(pState.fast < pState.slow) ; // isCrossOver = cState.fast > cState.slow && !(pState.fast > pState.slow) ; // if ( isCrossUnder && xLongConds.startTime == 0 ) { // xLongConds.startTime = barTime; return; } // if ( isCrossOver && xLongConds.startTime > 0 && xLongConds.signalTime == 0 ) { // xLongConds.signalTime = barTime; xLongConds.entryTime = barTime; return; } } // // Check and Fill Short Signal Conditions ... void CheckXShortSignalConditions( const int bar_index ) { // if ( !enableXShort || !enableXSignalling || !xWaitForShortSignals ) { return; } // datetime barTime = iTime( _Symbol, _Period, bar_index ); // bool isCrossOver = false; bool isCrossUnder = false; // XMarketState cState = GetXMarketState(1); XMarketState pState = GetXMarketState(2); // isCrossUnder = cState.fast < cState.slow && !(pState.fast < pState.slow) ; // isCrossOver = cState.fast > cState.slow && !(pState.fast > pState.slow) ; // if ( isCrossOver && xShortConds.startTime == 0 ) { // xShortConds.startTime = barTime; return; } // if ( isCrossUnder && xShortConds.startTime > 0 && xShortConds.signalTime == 0 ) { // xShortConds.signalTime = barTime; xShortConds.entryTime = barTime; return; } } // // Convert Long Signal Conditions to XSignal ... XSignalRequest GenerateXSignal( const ENUM_X_SIGNAL_TYPE type, // Signal Type ... const string signalTag , // Signal Tag ... const int bar_index ) { // XSignalRequest result = {}; // result.hasSignal = false; result.type = X_SIGNAL_NONE; result.provider = X_UNKNOWN_PROVIDER; // if ( !enableXSignalling || !(enableXLong || enableXShort) ) { return result; } // bool requestLong = type == X_SIGNAL_LONG; // if (requestLong) { // if ( !ValidateXLongConditions() ) { return result; } } else { // if ( !ValidateXShortConditions() ) { return result; } } // // Price Calculations ... // RefreshRates(); // double askPrice = SymbolInfoDouble( _Symbol, SYMBOL_ASK ); // double bidPrice = SymbolInfoDouble( _Symbol, SYMBOL_BID ); // double entryPrice = requestLong ? askPrice : bidPrice; // double exitPrice = requestLong ? bidPrice : askPrice; // double priceGap = MathAbs(entryPrice - exitPrice); // double ll = // GetMarketLowestLow( bar_index, xSwingLength ) ; // double hh = // GetMarketHighestHigh( bar_index, xSwingLength ) ; // double openPrice = iOpen( _Symbol, _Period, bar_index ); // double closePrice = iClose( _Symbol, _Period, bar_index ); // double risk = requestLong ? MathMin(openPrice, closePrice) - ll : hh - MathMax(openPrice, closePrice) ; // double reward = requestLong ? risk * xLongR2R : risk * xShortR2R ; // double sl = requestLong ? 0 : 0; double tp = requestLong ? entryPrice + reward : entryPrice - reward ; // XRState range = GetXRange( bar_index, xRangeMarketLength ); // datetime barTime = iTime( _Symbol, _Period, bar_index ); // result.signal.tp = tp; result.signal.sl = sl; result.signal.type = type; result.signal.time = barTime; result.signal.tag = signalTag; result.signal.symbol = _Symbol; result.signal.entry = entryPrice; result.signal.id = totalSignals + 1; result.signal.provider = X_XXX_PROVIDER; // result.hasSignal = true; result.type = type; result.provider = X_XXX_PROVIDER; // return result; } // // Validate Signal Conditions ... bool ValidateXLongConditions() { // if ( !enableXLong || !enableXSignalling ) { return false; } // bool isConditionsFilled = xLongConds.startTime > 0 && xLongConds.signalTime > 0 && xLongConds.entryTime > 0 ; // bool isBLFilled = false; if (isConditionsFilled) { // int startBarIndex = iBarShift( _Symbol, _Period, xLongConds.startTime ); // int signalBarIndex = iBarShift( _Symbol, _Period, xLongConds.signalTime ); // int entryBarIndex = iBarShift( _Symbol, _Period, xLongConds.entryTime ); // isBLFilled = // xLongConds.signalTime > xLongConds.startTime && xLongConds.entryTime >= xLongConds.signalTime // && MathAbs(signalBarIndex - startBarIndex) >= 1 ; } // bool result = isBLFilled && isConditionsFilled && xWaitForLongSignals ; // // Since maybe Conditions Filled but // Slope is Negative, for Handling Next Signals and // Prevent from infinity loop, here we Clear Signal Conditions ... if ( !result && isConditionsFilled ) { ClearXLongSignalConditions(); } // return result; } // // Validate Signal Conditions ... bool ValidateXShortConditions() { // if ( !enableXShort || !enableXSignalling ) { return false; } // bool isConditionsFilled = xShortConds.startTime > 0 && xShortConds.signalTime > 0 && xShortConds.entryTime > 0 ; // bool isBLFilled = false; if (isConditionsFilled) { // int startBarIndex = iBarShift( _Symbol, _Period, xShortConds.startTime ); // int signalBarIndex = iBarShift( _Symbol, _Period, xShortConds.signalTime ); // int entryBarIndex = iBarShift( _Symbol, _Period, xShortConds.entryTime ); // isBLFilled = // xShortConds.signalTime > xShortConds.startTime && xShortConds.entryTime >= xShortConds.signalTime ; } // bool result = isBLFilled && isConditionsFilled && xWaitForShortSignals ; // // Since maybe Conditions Filled but // Slope is Negative, for Handling Next Signals and // Prevent from infinity loop, here we Clear Signal Conditions ... if ( !result && isConditionsFilled ) { ClearXShortSignalConditions(); } // return result; } // // Clear Long Signal Conditions for New One ... void ClearXLongSignalConditions() { // xLongConds.startTime = 0; xLongConds.entryTime = 0; xLongConds.signalTime = 0; } // // Clear Short Signal Conditions for New One ... void ClearXShortSignalConditions() { // xShortConds.startTime = 0; xShortConds.entryTime = 0; xShortConds.signalTime = 0; } // // Check State for Long Signals ... bool IsReadyForXSignals( const XSignal &signal ) { // bool result = false; // if ( !enableXSignalling || !(enableXLong || enableXShort) ) { return result; } // int signalBarIndex = iBarShift( _Symbol, _Period, signal.time ); // // XOHCL candle = GetCandleModel(0); XOHCL candle = GetCandleModel(signalBarIndex); XOHCL pCandle = GetCandleModel(signalBarIndex + 1); // // Retrieve Range ... XRState range = GetXRange( signalBarIndex, xRangeMarketLength ); // // Retrive XMarket States ... XMarketState xState0 = GetXMarketState(signalBarIndex); XMarketState xState1 = GetXMarketState(signalBarIndex + 1); XMarketState xState2 = GetXMarketState(signalBarIndex + 2); XMarketState xStateLast = GetXMarketState(signalBarIndex + xSwingLength); // // Retrieve Trend Powers ... XTPOWState xTPow0 = GetXTPowState( signalBarIndex, xSwingLength ); XTPOWState xTPow1 = GetXTPowState( signalBarIndex + 1, xSwingLength ); // double hh = GetMarketHighestHigh( signalBarIndex, xSwingLength ); double ll = GetMarketLowestLow( signalBarIndex, xSwingLength ); double diffChange = (hh - ll); bool isBigSharpOccured = diffChange > (xSharpDetectorFactor * _Point) ; // bool isPSarVerified = false; bool isTPowVerified = false; bool isStateVerified = false; bool isPriceVerified = false; // // Verify Long Signals ... if (signal.type == X_SIGNAL_LONG) { // // Get Price Verification for Long ... isPriceVerified = // // Starter ... true // && !isBigSharpOccured // && signal.entry < hh // // && signal.entry < range.hh // && signal.entry > range.mid // // // && candle.high > xState0.verifier // && signal.entry > xState0.verifier // // && pCandle.low != ll && pCandle.high != hh ; // int above20TPowers = 0; double signalSlope = 0; int tPowUnverifyConditions = 0; int tPowUnverifyConditionsIdx = 0; for (int i = signalBarIndex; i < signalBarIndex + xSwingLength; i++) { // XTPOWState iTPowState = GetXTPowState( i, xSwingLength ); // // Calculate Signal Slope ... if (i == signalBarIndex) { // signalSlope = iTPowState.signal; } else if (i == signalBarIndex + 1) { // signalSlope = GetSlope( 1, iTPowState.signal, 2, signalSlope ); } // if ( iTPowState.powerUp > iTPowState.powerDown && MathMax(iTPowState.powerUp, iTPowState.powerDown) > 20 ) { above20TPowers++; } // if (tPowUnverifyConditionsIdx < 3) { // if ( iTPowState.powerUp < iTPowState.powerDown || iTPowState.signal > MathMax(iTPowState.powerUp, iTPowState.powerDown) ) { tPowUnverifyConditions++; } // tPowUnverifyConditionsIdx++; } } // isTPowVerified = above20TPowers > 1 && tPowUnverifyConditions == 0 ; // isPSarVerified = xState0.psar < signal.entry && xState0.psar < candle.low; // isStateVerified = // // Start ... true // // && xState0.open < xState0.slow ; // result = // // Starter ... true // && isPSarVerified // && isTPowVerified // && isStateVerified // && isPriceVerified ; } else // // Verify Short Signals ... if (signal.type == X_SIGNAL_SHORT) { // isPSarVerified = xState0.psar > signal.entry && xState0.psar > candle.high ; // // Get Price Verification for Short ... isPriceVerified = // // Starter ... true // && !isBigSharpOccured // && signal.entry > ll && pCandle.low != ll ; // int above20TPowers = 0; double signalSlope = 0; int tPowUnverifyConditions = 0; int tPowUnverifyConditionsIdx = 0; for (int i = signalBarIndex; i < signalBarIndex + xSwingLength; i++) { // XTPOWState iTPowState = GetXTPowState( i, xSwingLength ); // // Calculate Signal Slope ... if (i == signalBarIndex) { // signalSlope = iTPowState.signal; } else if (i == signalBarIndex + 1) { // signalSlope = GetSlope( 1, iTPowState.signal, 2, signalSlope ); } // if ( iTPowState.powerUp > iTPowState.powerDown && MathMax(iTPowState.powerUp, iTPowState.powerDown) > 20 ) { above20TPowers++; } // if (tPowUnverifyConditionsIdx < 3) { // if ( iTPowState.powerUp > iTPowState.powerDown || iTPowState.signal < MathMax(iTPowState.powerUp, iTPowState.powerDown) ) { tPowUnverifyConditions++; } // tPowUnverifyConditionsIdx++; } } // isTPowVerified = above20TPowers < 1 && tPowUnverifyConditions == 0 && MathAbs(xTPow0.powerUp - xTPow0.powerDown) > 50 * _Point ; // isStateVerified = // // Start ... true // // && (xStateLast.verifier - xState0.verifier) >= 0 // && xState0.verifier > signal.entry // && MathAbs(signal.entry - xState0.verifier) < (xSharpDetectorFactor * _Point) ; // result = // // Starter Condition ... true // && isPSarVerified // && isTPowVerified // && isStateVerified // && isPriceVerified ; } // return result; } // // END Functions ... // // // START Data Provider ... // XMarketState GetXMarketState( const int bar_index ) { // XMarketState result = {}; // double fast = GetMA( bar_index, xSwingLength, 0, MODE_SMA, PRICE_CLOSE ); // double open = GetMA( bar_index, xSwingLength, 0, MODE_SMA, PRICE_OPEN ); // double slow = GetMA( bar_index, xSwingLength * 2, 0, MODE_SMA, PRICE_CLOSE ); // double oscillator = GetMA( bar_index, xSwingLength, 0, MODE_EMA, PRICE_CLOSE ); // double oscillatorVerifier = GetMA( bar_index, xSwingLength, 0, MODE_EMA, PRICE_WEIGHTED ); // int dailyCount = GetDailyCandleCount(); double verifier = GetMA( bar_index, dailyCount, 0, MODE_EMA, PRICE_MEDIAN ); // double psar = iSAR( _Symbol, _Period, xPSarStep, xPSarMaximum, bar_index ); // result.psar = psar; result.fast = fast; result.open = open; result.slow = slow; result.verifier = verifier; result.oscillator = oscillator; result.oscillatorVerifier = oscillatorVerifier; // return result; } // // END Data Provider ... //