/////////////////////////////////////////////////////// // // 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 xRStarter = "- XR Signal Provider -"; // --> XR Signal Provider <-- // input bool enableXRSignalling = false; // XR Signalling Enable // input bool enableXRLong = true; // XR Signalling Enable Long input bool enableXRShort = true; // XR Signalling Enable Short // input double xRShortR2R = 1.5; // XR Short Risk To Reward Ratio input double xRShortLotsPerTradePercent = 0.0002; // XR Lots Percent per Short Trades input double xRShortMaxDrawdownPerTradePercent = 0.15; // XR Max Allowed DrawDown Percent per Short Trade // input double xRLongR2R = 1.5; // XR Long Risk To Reward Ratio input double xRLongLotsPerTradePercent = 0.0002; // XR Lots Percent per Short Trades input double xRLongMaxDrawdownPerTradePercent = 0.15; // XR Max Allowed DrawDown Percent per Long Trade // input int xRMaximumCandlesPerTrade = 96; // XR Maximum Candles which a Trade can open // input int xRSwingLength = 48; // XR Swing Length // // END Inputs ... // // input double xRSharpDetectionFactor = 1350; // XR Sharp Detection Factor // // START Global Requirement Functions ... // // // XR Market State ... struct XRMarketState { // double fast; double slow; double open; // double range; double rangeFast; double rangeSlow; double rangeOpen; // double verifier; }; // // XR Based Signal Conditions ... struct XRSignalConditions { datetime startTime; datetime signalTime; datetime entryTime; }; // static XRSignalConditions xRLongConds; static bool xRCloseLongTrades = false; static bool xRWaitForLongSignals = true; // static XRSignalConditions xRShortConds; static bool xRCloseShortTrades = false; static bool xRWaitForShortSignals = true; // // Count Number of Closed Maximum DrawDown Trades ... static int xRFailedSignals = 0; // double xRMaximumDrawDown = 0; // int fastLength = 0; int slowLength = 0; // int verifierLength = 0; // int rangeFastLength = 0; int rangeSlowLength = 0; // // END Global Requirement Functions ... // // // START Functions ... // // // Check and Fill Long and Short Signal Handlers ... void CheckXRSignalHandler( const int bar_index ) { // // Check Market For Enable/Disable Signal Handlers ... // Checking Market for Long Signals ... // if ( !enableXRSignalling || !(enableXRLong || enableXRShort) ) { return; } } // // Check and Fill Long Signal Conditions ... void CheckXRLongSignalConditions( const int bar_index ) { // if ( !enableXRLong || !enableXRSignalling ) { return; } // datetime barTime = iTime( _Symbol, _Period, bar_index ); // // Read Prices ... XPrice prices = GetPrice(); // // Read XPVTState ... XPvtState pvt0 = GetPVTState( bar_index, xRSwingLength ); // // Double Length Pivots ... XPvtState dblPvt0 = GetPVTState( bar_index, (xRSwingLength * 2) ); // // Reading Required Candles ... XOHCL candle0 = GetCandleModel(bar_index); XOHCL candle1 = GetCandleModel(bar_index + 1); XOHCL candle2 = GetCandleModel(bar_index + 2); XOHCL candle3 = GetCandleModel(bar_index + 3); // // Reding Required XRMarketStates ... XRMarketState state0 = GetXRMarketState(bar_index); XRMarketState state1 = GetXRMarketState(bar_index + 1); XRMarketState state2 = GetXRMarketState(bar_index + 2); XRMarketState state3 = GetXRMarketState(bar_index + 3); // // Reading required XRangeStates ... XRState range0 = ReadXRange( bar_index + xRSwingLength, xRSwingLength ); XRState range1 = ReadXRange( bar_index + xRSwingLength + 1, xRSwingLength ); XRState range2 = ReadXRange( bar_index + xRSwingLength + 2, xRSwingLength ); // XRState cRange0 = ReadXRange( bar_index, xRSwingLength ); // // Validate Farest Range Values ... if ( range2.hh == 0 || range2.ll == 0 || range2.mid == 0 ) { return; } // // Reading Required XTPowStates ... XTPOWState tPow0 = GetXTPowState( bar_index, xRSwingLength ); XTPOWState tPow1 = GetXTPowState( bar_index + 1, xRSwingLength ); XTPOWState tPow2 = GetXTPowState( bar_index + 2, xRSwingLength ); // // if state verifier below range middle // this means market is bullish ... // // if state verifier above range middle // this means market is bearish ... // // bool isMarketBullish = state0.verifier < range0.mid && state1.verifier < range1.mid; bool isMarketBearish = state0.verifier > range0.mid && state1.verifier > range1.mid; bool isMarketGoingBullish = state0.verifier > range0.mid && !(state1.verifier > range1.mid); bool isMarketGoingBearish = state0.verifier < range0.mid && !(state1.verifier < range1.mid); // // Check Highest High Conditions ... bool isHHVerified = !( pvt0.hh == dblPvt0.hh ) ; // int sharpDetectionLength = 7; double sharpDetectionValue = xRSharpDetectionFactor * _Point; // int sharpHHIdx = iHighest( _Symbol, _Period, MODE_HIGH, sharpDetectionLength, bar_index ); double sharpHH = iHigh( _Symbol, _Period, sharpHHIdx ); // int sharpLLIdx = iLowest( _Symbol, _Period, MODE_LOW, sharpDetectionLength, bar_index ); double sharpLL = iLow( _Symbol, _Period, sharpLLIdx ); // double sharpDiff = sharpHH - sharpLL; bool isSharpOccered = sharpDiff > sharpDetectionValue; // XRMarketState lastState = GetXRMarketState( bar_index + sharpDetectionLength ); // double stateFSDiff = (state0.fast - state0.slow) - (lastState.fast - lastState.slow); // // Start Calculating Long Conditions ... bool longCondition1 = // // Starter ... true // && isMarketBullish // && ( candle2.high < range2.mid || ( candle2.high > range2.mid && candle2.low < range2.mid ) ) && candle1.low > range1.mid ; // if ( // ( longCondition1 ) // && xRLongConds.startTime == 0 && xRLongConds.entryTime == 0 && xRLongConds.signalTime == 0 ) { // xRLongConds.startTime = barTime; xRLongConds.entryTime = barTime; xRLongConds.signalTime = barTime; // return; } } // // Check and Fill Short Signal Conditions ... void CheckXRShortSignalConditions( const int bar_index ) { // if ( !enableXRShort || !enableXRSignalling ) { return; } // datetime barTime = iTime( _Symbol, _Period, bar_index ); // // Read Prices ... XPrice prices = GetPrice(); // // Read XPVTState ... XPvtState pvt0 = GetPVTState( bar_index, xRSwingLength ); // // Double Length Pivots ... XPvtState dblPvt0 = GetPVTState( bar_index, (xRSwingLength * 2) ); // // Reading Required Candles ... XOHCL candle0 = GetCandleModel(bar_index); XOHCL candle1 = GetCandleModel(bar_index + 1); XOHCL candle2 = GetCandleModel(bar_index + 2); XOHCL candle3 = GetCandleModel(bar_index + 3); // // Reding Required XRMarketStates ... XRMarketState state0 = GetXRMarketState(bar_index); XRMarketState state1 = GetXRMarketState(bar_index + 1); XRMarketState state2 = GetXRMarketState(bar_index + 2); XRMarketState state3 = GetXRMarketState(bar_index + 3); // // Reading required XRangeStates ... XRState range0 = ReadXRange( bar_index + xRSwingLength, xRSwingLength ); XRState range1 = ReadXRange( bar_index + xRSwingLength + 1, xRSwingLength ); XRState range2 = ReadXRange( bar_index + xRSwingLength + 2, xRSwingLength ); // XRState cRange0 = ReadXRange( bar_index, xRSwingLength ); // // Validate Farest Range Values ... if ( range2.hh == 0 || range2.ll == 0 || range2.mid == 0 ) { return; } // // Reading Required XTPowStates ... XTPOWState tPow0 = GetXTPowState( bar_index, xRSwingLength ); XTPOWState tPow1 = GetXTPowState( bar_index + 1, xRSwingLength ); XTPOWState tPow2 = GetXTPowState( bar_index + 2, xRSwingLength ); // // if state verifier below range middle // this means market is bullish ... // // if state verifier above range middle // this means market is bearish ... // // bool isMarketBullish = state0.verifier < range0.mid && state1.verifier < range1.mid; bool isMarketBearish = state0.verifier > range0.mid && state1.verifier > range1.mid; bool isMarketGoingBullish = state0.verifier > range0.mid && !(state1.verifier > range1.mid); bool isMarketGoingBearish = state0.verifier < range0.mid && !(state1.verifier < range1.mid); // // Check Highest High Conditions ... bool isHHVerified = !( pvt0.hh == dblPvt0.hh ) ; // int sharpDetectionLength = 7; double sharpDetectionValue = xRSharpDetectionFactor * _Point; // int sharpHHIdx = iHighest( _Symbol, _Period, MODE_HIGH, sharpDetectionLength, bar_index ); double sharpHH = iHigh( _Symbol, _Period, sharpHHIdx ); // int sharpLLIdx = iLowest( _Symbol, _Period, MODE_LOW, sharpDetectionLength, bar_index ); double sharpLL = iLow( _Symbol, _Period, sharpLLIdx ); // double sharpDiff = sharpHH - sharpLL; bool isSharpOccered = sharpDiff > sharpDetectionValue; // XRMarketState lastState = GetXRMarketState( bar_index + sharpDetectionLength ); // double stateFSDiff = (state0.fast - state0.slow) - (lastState.fast - lastState.slow); // // Start Calculating Long Conditions ... bool shortCondition1 = // // Starter ... true // && isMarketBearish // && ( candle2.low > range2.mid || ( candle2.high > range2.mid && candle2.low < range2.mid ) ) && candle1.high < range1.mid ; // if ( // ( shortCondition1 ) // && xRShortConds.startTime == 0 && xRShortConds.entryTime == 0 && xRShortConds.signalTime == 0 ) { // xRShortConds.startTime = barTime; xRShortConds.entryTime = barTime; xRShortConds.signalTime = barTime; // return; } } // // Convert Long Signal Conditions to XSignal ... XSignalRequest GenerateXRSignal( 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 ( !enableXRSignalling || !(enableXRLong || enableXRShort) ) { return result; } // bool requestLong = type == X_SIGNAL_LONG; // if (requestLong) { // if ( !ValidateXRLongConditions() ) { return result; } } else { // if ( !ValidateXRShortConditions() ) { return result; } } // // Price Calculations ... XPvtState pvts = GetPVTState( bar_index, xRSwingLength ); XPrice prices = GetPrice(); // double entryPrice = requestLong ? prices.longEntry : prices.shortEntry ; // double openPrice = iOpen( _Symbol, _Period, bar_index ); // double closePrice = iClose( _Symbol, _Period, bar_index ); // double risk = requestLong ? MathMin(openPrice, closePrice) - pvts.ll : pvts.hh - MathMax(openPrice, closePrice); if (risk <= 0) { // risk = requestLong ? MathAbs(pvts.hh - entryPrice) : MathAbs(pvts.ll - entryPrice) ; } // double reward = requestLong ? risk * xRLongR2R : risk * xRShortR2R ; // double sl = requestLong ? 0 : 0; // double tp = requestLong ? entryPrice + reward : entryPrice - reward ; // 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_XR_PROVIDER; // result.hasSignal = true; result.type = type; result.provider = X_XR_PROVIDER; // return result; } // // Validate Long Signal Conditions ... bool ValidateXRLongConditions() { // if ( !enableXRLong || !enableXRSignalling ) { return false; } // bool isConditionsFilled = xRLongConds.startTime > 0 && xRLongConds.signalTime > 0 && xRLongConds.entryTime > 0 ; // bool isBLFilled = false; if (isConditionsFilled) { // isBLFilled = // xRLongConds.signalTime >= xRLongConds.startTime && xRLongConds.entryTime >= xRLongConds.signalTime ; } // bool result = isBLFilled && isConditionsFilled && xRWaitForLongSignals ; // // 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 ) { ClearXRLongSignalConditions(); } // return result; } // // Validate Short Signal Conditions ... bool ValidateXRShortConditions() { // if ( !enableXRShort || !enableXRSignalling ) { return false; } // bool isConditionsFilled = xRShortConds.startTime > 0 && xRShortConds.signalTime > 0 && xRShortConds.entryTime > 0 ; // bool isBLFilled = false; if (isConditionsFilled) { // isBLFilled = // xRShortConds.signalTime >= xRShortConds.startTime && xRShortConds.entryTime >= xRShortConds.signalTime ; } // bool result = isBLFilled && isConditionsFilled && xRWaitForShortSignals ; // // 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 ) { ClearXRShortSignalConditions(); } // return result; } // // Clear Long Signal Conditions for New One ... void ClearXRLongSignalConditions() { // xRLongConds.startTime = 0; xRLongConds.signalTime = 0; xRLongConds.entryTime = 0; } // // Clear Short Signal Conditions for New One ... void ClearXRShortSignalConditions() { // xRShortConds.startTime = 0; xRShortConds.signalTime = 0; xRShortConds.entryTime = 0; } // // Check State for Long Signals ... bool IsReadyForXRSignals( const XSignal &signal ) { // bool result = false; // if ( !enableXRSignalling || !(enableXRLong || enableXRShort) ) { return result; } // // Find Signal Bar Index ... int signalBarIndex = iBarShift( _Symbol, _Period, signal.time ); // // Read Prices ... XPrice prices = GetPrice(); // // Read XPVTState ... XPvtState pvt0 = GetPVTState( signalBarIndex, xRSwingLength ); // // Reading Required Candles ... XOHCL candle0 = GetCandleModel(signalBarIndex); XOHCL candle1 = GetCandleModel(signalBarIndex + 1); XOHCL candle2 = GetCandleModel(signalBarIndex + 2); XOHCL candle3 = GetCandleModel(signalBarIndex + 3); // // Reding Required XRMarketStates ... XRMarketState state0 = GetXRMarketState(signalBarIndex); XRMarketState state1 = GetXRMarketState(signalBarIndex + 1); XRMarketState state2 = GetXRMarketState(signalBarIndex + 2); XRMarketState state3 = GetXRMarketState(signalBarIndex + 3); // // Reading required XRangeStates ... XRState range0 = ReadXRange( signalBarIndex + xRSwingLength, xRSwingLength ); XRState range1 = ReadXRange( signalBarIndex + xRSwingLength + 1, xRSwingLength ); XRState range2 = ReadXRange( signalBarIndex + xRSwingLength + 2, xRSwingLength ); // // Reading Required XTPowStates ... XTPOWState tPow0 = GetXTPowState( signalBarIndex, xRSwingLength ); XTPOWState tPow1 = GetXTPowState( signalBarIndex + 1, xRSwingLength ); XTPOWState tPow2 = GetXTPowState( signalBarIndex + 2, xRSwingLength ); // double hhllDiff = MathAbs(pvt0.hh - pvt0.ll); double sharpDetectionValue = xRSharpDetectionFactor * _Point; bool isSharpOccured = hhllDiff > sharpDetectionValue; // // Calculate State Min Max Diff ... // double state0Min = MathMin(state0.fast, state0.slow); state0Min = MathMin(state0Min, state0.open); state0Min = MathMin(state0Min, state0.rangeFast); state0Min = MathMin(state0Min, state0.rangeSlow); state0Min = MathMin(state0Min, state0.rangeOpen); state0Min = MathMin(state0Min, state0.verifier); // double state0Max = MathMax(state0.fast, state0.slow); state0Max = MathMax(state0Max, state0.open); state0Max = MathMax(state0Max, state0.rangeFast); state0Max = MathMax(state0Max, state0.rangeSlow); state0Max = MathMax(state0Max, state0.rangeOpen); state0Max = MathMax(state0Max, state0.verifier); // double state0MinMaxDiff = (state0Max - state0Min); // bool isTPowValid = false; bool isStateValid = false; bool isRangeValid = false; // // Verify Long Signals ... if (signal.type == X_SIGNAL_LONG) { // // Retrieve TPow Verifications ... isTPowValid = // // Starter ... true ; // // Retrieve XMarket Verifications ... isStateValid = // // Starter ... true // // && !(state0MinMaxDiff > sharpDetectionValue) ; // // Retrieve XRange Verifications ... isRangeValid = // // Starter ... true ; // result = // // Starter ... true // && isTPowValid && isStateValid && isRangeValid ; } else // // Verify Short Signals ... if (signal.type == X_SIGNAL_SHORT) { // // Retrieve TPow Verifications ... isTPowValid = // // Starter ... true ; // // Retrieve XMarket Verifications ... isStateValid = // // Starter ... true ; // // Retrieve XRange Verifications ... isRangeValid = // // Starter ... true ; // result = // // Starter ... true // && isTPowValid && isStateValid && isRangeValid ; } // return result; } // // END Functions ... // // // START Data Providers ... // // XRMarketState GetXRMarketState( const int bar_index ) { // XRMarketState result = {}; // // Calculate Market Lengths ... // if (fastLength == 0) { fastLength = xRSwingLength; } // if (slowLength == 0) { slowLength = xRSwingLength * 2; } // if (verifierLength == 0) { verifierLength = (GetDailyCandleCount() * 2); } // if (rangeFastLength == 0) { rangeFastLength = (int)(verifierLength / 2); } // if (rangeSlowLength == 0) { rangeSlowLength = verifierLength; } // // Reading Values ... // double fast = GetMA( bar_index, fastLength, 0, MODE_SMA, PRICE_CLOSE ); // double slow = GetMA( bar_index, slowLength, 0, MODE_SMA, PRICE_CLOSE ); // double open = GetMA( bar_index, fastLength, 0, MODE_SMA, PRICE_OPEN ); // double rangeFast = GetMA( bar_index, rangeFastLength, 0, MODE_SMA, PRICE_CLOSE ); // double rangeSlow = GetMA( bar_index, rangeSlowLength, 0, MODE_SMA, PRICE_CLOSE ); // double rangeOpen = GetMA( bar_index, rangeFastLength, 0, MODE_SMA, PRICE_OPEN ); // double verifier = GetMA( bar_index, verifierLength, 0, MODE_EMA, PRICE_MEDIAN ); // // Filling Result ... result.fast = fast; result.slow = slow; result.open = open; result.verifier = verifier; result.rangeFast = rangeFast; result.rangeSlow = rangeSlow; result.rangeOpen = rangeOpen; // return result; } // // END Data Providers ... //