/////////////////////////////////////////////////////// // // 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 double xrR2R = 2; // XR Risk To Reward Ratio input int xRMaximumCandlesPerTrade = 252; // XR Maximum Candles which a Trade can open // input int xrOscillatorLength = 7; // XR Oscillator Length input int xrFastLength = 20; // XR Fast Length input int xrSlowLength = 50; // XR Slow Length input int xrRangeMarketLength = 50; // XR Range Detector Length // input int xrSwingLength = 7; // XR Swing Length // // END Inputs ... // // // START Global Requirement Functions ... // // // XR Market State ... struct XRMarketState { // double fast; double slow; // double prevFast; double prevSlow; // double oscillator; double prevOscillator; // double verifier; }; // // XR Based Signal Conditions ... struct XRSignalConditions { // datetime startTime; datetime signalTime; datetime entryTime; // double value; XRState state; }; // static XRSignalConditions xrLongConds; static bool xrCloseLongTrades = false; static bool xrWaitForLongSignals = true; // static double xrMaximumDrawDown = 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) { return; } // XOHCL candle = GetCandleModel(bar_index); // XRMarketState state = GetXRMarketState( bar_index ); // if (xrWaitForLongSignals) { // if ( state.oscillator < state.fast && state.oscillator < state.slow && state.prevOscillator < state.prevFast && state.prevOscillator < state.prevSlow && candle.low < xrMaximumDrawDown ) { // xrMaximumDrawDown = 0; xrCloseLongTrades = true; } } else { } } // // Check and Fill Long Signal Conditions ... void CheckXRLongSignalConditions( const int bar_index ) { // if (!enableXRSignalling) { return; } // datetime barTime = iTime( _Symbol, _Period, bar_index ); // XOHCL candle = GetCandleModel(bar_index + 1); // XRState xrState = GetXRange( bar_index, xrRangeMarketLength ); // double affectedValue = xrState.mid; // XRMarketState state = GetXRMarketState( bar_index ); // bool isCrossOver = state.fast > state.slow && !(state.prevFast > state.prevSlow) ; // bool isCrossUnder = state.fast < state.slow && !(state.prevFast < state.prevSlow) ; // if ( isCrossUnder && xrLongConds.startTime == 0 ) { // xrLongConds.startTime = barTime; return; } // if ( isCrossOver && xrLongConds.startTime > 0 && xrLongConds.signalTime == 0 ) { // xrLongConds.value = affectedValue; xrLongConds.state = xrState; // xrLongConds.signalTime = barTime; xrLongConds.entryTime = 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) { return result; } // bool requestLong = type == X_SIGNAL_LONG; // if (requestLong) { // if ( !ValidateXRLongConditions() ) { return result; } } else { } // // 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, xrSwingLength ) ; // double hh = // GetMarketHighestHigh( bar_index, xrSwingLength ) ; // 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 = risk * xrR2R; // double sl = requestLong ? 0 : ll; double tp = requestLong ? entryPrice + reward : entryPrice - reward ; // xrMaximumDrawDown = xrMaximumDrawDown == 0 ? xrLongConds.state.mid : xrMaximumDrawDown > xrLongConds.state.mid ? xrMaximumDrawDown : xrLongConds.state.mid; // 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 Signal Conditions ... bool ValidateXRLongConditions() { // if (!enableXRSignalling) { return false; } // bool isConditionsFilled = xrLongConds.startTime > 0 && xrLongConds.signalTime > 0 && xrLongConds.entryTime > 0 // && xrLongConds.value > 0 ; // bool isBLFilled = false; if (isConditionsFilled) { // int startBarIndex = iBarShift( _Symbol, _Period, xrLongConds.startTime ); // int signalBarIndex = iBarShift( _Symbol, _Period, xrLongConds.signalTime ); // // Count Affected Value Touches ... int cStartBarIndex = iBarShift( _Symbol, _Period, xrLongConds.state.start ); // int cEndBarIndex = cStartBarIndex + xrLongConds.state.length; // int highTouched = 0; int valueTouched = 0; for (int i = cStartBarIndex; i <= cStartBarIndex + cEndBarIndex; i++) { // XOHCL iCandle = GetCandleModel(i); // if ( iCandle.low < xrLongConds.value && iCandle.high > xrLongConds.value ) { valueTouched++; } // if ( iCandle.low < xrLongConds.state.hh && iCandle.high > xrLongConds.state.hh ) { highTouched++; } } // isBLFilled = // xrLongConds.signalTime > xrLongConds.startTime && xrLongConds.entryTime >= xrLongConds.signalTime // && highTouched < 2 && valueTouched > (cEndBarIndex - cStartBarIndex) / 6 ; } // 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; } // // Clear Long Signal Conditions for New One ... void ClearXRLongSignalConditions() { // xrLongConds.startTime = 0; xrLongConds.signalTime = 0; xrLongConds.entryTime = 0; // xrLongConds.value = 0; // XRState e = {}; xrLongConds.state = e; } // // Check State for Long Signals ... bool IsReadyForXRSignals( const XSignal &signal ) { // bool result = false; // if (!enableXRSignalling) { return result; } // XRMarketState state = GetXRMarketState(0); // double fSDif = MathAbs(state.fast - state.slow); double fSDifP = MathAbs(state.prevFast - state.prevSlow); // double emaSlope = GetSlope( 1, state.prevOscillator, 2, state.oscillator ); // XOHCL pCandle = GetCandleModel(1); // // Verify Long Signals ... if (signal.type == X_SIGNAL_LONG) { // result = // // Starter ... true // && state.oscillator > state.fast && emaSlope > 0 && signal.entry > state.verifier // && fSDif > fSDifP // && signal.entry < xrLongConds.state.hh && signal.entry > xrLongConds.state.mid ; } else // // Verify Short Signals ... if (signal.type == X_SIGNAL_SHORT) { // result = false ; } // return result; } // // END Functions ... // // // START Data Providers ... // // XRMarketState GetXRMarketState( const int bar_index ) { // XRMarketState result = {}; // // Prepare Market Length ... int xrVerifierMarketLength = GetDailyCandleCount(); // // Calculate Fast and Prev Fast ... // // Fast ... double fast = GetMA( bar_index + 1, xrFastLength, 0, MODE_SMA, PRICE_CLOSE ); // // Prev Fast ... double prevFast = GetMA( bar_index + 2, xrFastLength, 0, MODE_SMA, PRICE_CLOSE ); // // Calculate Slow and Prev Slow ... // // Slow ... double slow = GetMA( bar_index + 1, xrSlowLength, 0, MODE_SMA, PRICE_CLOSE ); // // Prev Slow ... double prevSlow = GetMA( bar_index + 2, xrSlowLength, 0, MODE_SMA, PRICE_CLOSE ); // // Calculate Oscillator and Prev Oscillator ... // // Oscillator ... double oscillator = GetMA( bar_index, xrOscillatorLength, 0, MODE_EMA, PRICE_CLOSE ); // // Prev Oscillator ... double prevOscillator = GetMA( bar_index + 1, xrOscillatorLength, 0, MODE_EMA, PRICE_CLOSE ); // // Calculate Verifier ... double verifier = GetMA( bar_index, xrVerifierMarketLength, 0, MODE_EMA, PRICE_CLOSE ); // result.fast = fast; result.slow = slow; result.verifier = verifier; result.prevFast = prevFast; result.prevSlow = prevSlow; result.oscillator = oscillator; result.prevOscillator = prevOscillator; // return result; } // // END Data Providers ... //