/////////////////////////////////////////////////////// // // 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 Global Requirement Functions ... // // // X Based Signal Conditions ... struct XSignalConditions { datetime startTime; datetime signalTime; datetime entryTime; }; // static XSignalConditions xLongConds; static bool xCloseLongTrades = false; static bool xWaitForLongSignals = true; static datetime lastLCFCrossOverSCLLTime; static datetime xWaitForLongSignalChangeTime; // static XSignalConditions xShortConds; static bool xWaitForShortSignals = true; static bool xCloseShortTrades = false; // // END Global Requirement Functions ... // // // START Functions ... // // // Check and Fill Long and Short Signal Handlers ... void CheckSignalHandler( const int bar_index, const int marketLen, const XState &states[], // const double smoother = 10 ) { // // Check Market For Enable/Disable Signal Handlers ... // Checking Market for Long Signals ... if (xWaitForLongSignals) { // // // bool isLCFastOnTrendingUpTouchLowestLow = // // // // LC Trending Up ... // states[1].lc.fast > states[1].lc.slow // && states[2].lc.fast > states[2].lc.slow // // // // LC Fast Touch Market Lowest Low ... // && states[1].lc.fast > states[1].mkt.lowestLow // && !(states[2].lc.fast > states[2].mkt.lowestLow) // ; // // // bool isMCSlowCrossOverBNDHigh = // states[1].mc.fast > states[1].mc.slow // && states[1].mc.slow > states[1].bnd.high // && !(states[2].mc.slow > states[2].bnd.high) // ; // // Disable Long Trade Handlers ... // if ( // isMCSlowCrossOverBNDHigh // || isLCFastOnTrendingUpTouchLowestLow // ) { // // // xWaitForLongSignals = false; // xWaitForLongSignalChangeTime = TimeCurrent(); // LogMessage("Disable Long ..."); // } } else { // bool isAllTrendingUp = // // SC ... states[1].sc.fast > states[1].sc.slow // // MC ... && states[1].mc.fast > states[1].mc.slow && !(states[2].mc.fast > states[2].mc.slow) // // LC ... && states[1].lc.fast > states[1].lc.slow ; // int lastWaitChangeBarIndex = iBarShift( _Symbol, _Period, xWaitForLongSignalChangeTime ); // // Enable Long Trade Handlers ... if ( isAllTrendingUp && lastWaitChangeBarIndex - bar_index >= marketLen ) { xWaitForLongSignals = true; LogMessage("Enable Long ..."); } } } // // Check and Fill Long Signal Conditions ... void CheckXLongSignalConditions( const int bar_index, const int marketLen, const XState &states[], // const double smoother = 10 ) { // datetime barTime = iTime( _Symbol, _Period, bar_index ); // // for Long Signals it happens when sc fast cross over slow ... bool isCrossUnder = states[0].sc.fast > states[0].sc.slow && states[1].sc.fast > states[1].sc.slow && !(states[2].sc.fast > states[2].sc.slow) ; // // for Long Signals it happens when sc fast cross under slow ... bool isCrossOver = states[0].sc.fast < states[0].sc.slow && states[1].sc.fast < states[1].sc.slow && !(states[2].sc.fast < states[2].sc.slow) ; // // Check Special Conditions ... // XOHCL pCandle = GetCandleModel(bar_index + 1); // XOHCL ppCandle = GetCandleModel(bar_index + 2); // XOHCL mCandle = GetCandleModel(bar_index + marketLen); // bool isLCGoingDownPrice = // // // pCandle.low > states[1].lc.slow // && ppCandle.low > states[2].lc.slow // && mCandle.low < states[marketLen - 1].lc.slow // ; // if () // if ( isCrossUnder && xLongConds.startTime == 0 ) { // xLongConds.startTime = barTime; return; } // if ( isCrossOver && xLongConds.startTime > 0 && xLongConds.signalTime == 0 ) { // xLongConds.signalTime = barTime; xLongConds.entryTime = barTime; // // if (states[0].parabolicSAR < states[0].sc.slow) { // } return; } // // // if ( // xLongConds.startTime > 0 // && xLongConds.signalTime > 0 // && xLongConds.entryTime == 0 // && states[0].parabolicSAR < states[0].sc.slow // ) { // // // xLongConds.entryTime = barTime; // return; // } } // // Check and Fill Short Signal Conditions ... void CheckXShortSignalConditions( const int bar_index, const int marketLen, const XState &states[], // const double smoother = 10 ) { // datetime barTime = iTime( _Symbol, _Period, bar_index ); // bool isCrossUnder = false; // bool isCrossOver = false; // if ( isCrossOver && xShortConds.startTime == 0 ) { // xShortConds.startTime = barTime; return; } // if ( isCrossUnder && xShortConds.startTime > 0 && xShortConds.signalTime == 0 ) { // xShortConds.signalTime = 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, // Bar Index ... const int marketLen, // MarketLength for TP and SL ... const int longCycleMult, // Long Cycle Multiplier for XRange Calculations ... const double r2r, // Risk to Reward ratio ... const XState &states[], // const double smoother = 10 ) { // XSignalRequest result = {}; // result.hasSignal = false; result.type = X_SIGNAL_NONE; result.provider = X_UNKNOWN_PROVIDER; // bool requestLong = type == X_SIGNAL_LONG; // if (requestLong) { // if ( !ValidateXLongConditions( marketLen, states, smoother ) ) { return result; } } else { // if ( !ValidateXShortConditions( marketLen, states, smoother ) ) { 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, marketLen ) ; // double hh = // GetMarketHighestHigh( bar_index, marketLen ) ; // 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 * r2r; // risk * r2r; // 300 * _Point; // if (risk > (500 * _Point)) { // reward = 300 * _Point; // } // double sl = requestLong ? 0 : // ll : 0; // ll; double tp = requestLong ? entryPrice + reward : entryPrice - reward; // // // double fibLevel = 1.618; // double fibLevelPrice = GetFibonacciLevel( // tp, // entryPrice, // fibLevel, // 1 // ); // // // if (requestLong) { // sl = fibLevelPrice; // } // if ( // // Condition 1 ... ( tp > states[0].lc.hh && ll == states[0].sc.ll && states[0].sc.ll == states[0].mc.ll ) || // // Condition 2 ... ( states[0].sc.hh == states[0].mc.hh && states[0].lc.hh == states[0].mc.hh && states[0].sc.ll == states[0].mc.ll ) ) { // reward = risk * 1; tp = requestLong ? entryPrice + reward : entryPrice - reward; } // // // int rangeMarketLength = marketLen * longCycleMult; // // // XRange range = GetMarketRange( // bar_index, // rangeMarketLength, // marketLen // ); // // // bool isRangeVerified = IsRangeVerified( // bar_index, // rangeMarketLength, // marketLen, // type, // entryPrice, // tp, // range // ); // // // if (!isRangeVerified) { // // // // sl = requestLong ? // // states[0].mc.ll : // // states[0].mc.hh // // ; // } // 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( const int marketLen, const XState &states[], // const double smoother = 10 ) { // 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 ); // isBLFilled = // xLongConds.signalTime > xLongConds.startTime && xLongConds.entryTime >= xLongConds.signalTime && MathAbs(signalBarIndex - startBarIndex) > 2 ; } // 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; } bool ValidateXShortConditions( const int marketLen, const XState &states[], // const double smoother = 10 ) { // 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 ); // isBLFilled = // xShortConds.signalTime > xShortConds.startTime && xShortConds.entryTime >= xShortConds.signalTime && MathAbs(signalBarIndex - startBarIndex) > marketLen ; } // 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 ) { ClearXShortSignalConditions(); } // return result; } // // Clear Long Signal Conditions for New One ... void ClearXLongSignalConditions() { // xLongConds.startTime = 0; xLongConds.signalTime = 0; } // // Clear Short Signal Conditions for New One ... void ClearXShortSignalConditions() { // xShortConds.startTime = 0; xShortConds.signalTime = 0; } // // Check State for Long Signals ... bool IsReadyForXSignals( const XSignal &signal, const XState &states[], const int marketLen, // const int shortCycleMult, const int mediumCycleMult, const int longCycleMult, // double smoother = 10 ) { // bool result = false; // bool isSCTrendUp = false; bool isSCTrendDown = false; // bool isMCTrendUp = false; bool isMCTrendDown = false; // bool isLCTrendUp = false; bool isLCTrendDown = false; // XOHCL candle = GetCandleModel(0); XOHCL pCandle = GetCandleModel(1); // // // bool isRange = false; // int rangeMarketLength = 5 * marketLen; // for (int i = 1; i < rangeMarketLength; i++) { // // // XState iState = GetXState( // i, // marketLen, // 0.01, // 0.1, // shortCycleMult, // mediumCycleMult, // longCycleMult // ); // // // isRange = // iState.mc.hh == iState.lc.hh // && iState.mc.hh == states[0].mc.hh // ; // } // // // int statesLast = ArraySize(states) - 1; // double scSlope = // GetSlope( // statesLast, // states[statesLast].sc.slow, // 0, // states[0].sc.slow // ); // double mcSlope = // GetSlope( // statesLast, // states[statesLast].mc.slow, // 0, // states[0].mc.slow // ); // double lcSlope = // GetSlope( // statesLast, // states[statesLast].lc.slow, // 0, // states[0].lc.slow // ); // // Verify Long Signals ... if (signal.type == X_SIGNAL_LONG) { // isSCTrendUp = states[0].sc.fast < states[0].sc.slow && states[1].sc.fast < states[1].sc.slow // && states[2].sc.fast < states[2].sc.slow ; // isMCTrendUp = states[0].mc.fast < states[0].mc.slow && states[1].mc.fast < states[1].mc.slow // && states[2].mc.fast < states[2].mc.slow ; // isLCTrendUp = states[0].lc.fast < states[0].lc.slow && states[1].lc.fast < states[1].lc.slow // && states[2].lc.fast < states[2].lc.slow ; // result = // // Starter ... true // // Trending State ... && isSCTrendUp && isMCTrendUp && isLCTrendUp // // && !isRange // // Condition 1 ... && states[0].mc.fast > states[0].sc.slow // && states[0].lc.slow < states[0].sc.ll ; } else // // Verify Short Signals ... if (signal.type == X_SIGNAL_SHORT) { // result = false ; } // // // if (result) { // // // LogMessage( // StringConcatenate( // "scSlope: ", scSlope, // ", mcSlope: ", mcSlope, // ", lcSlope: ", lcSlope // ) // ); // } // return result; } // // END Functions ... //