/////////////////////////////////////////////////////// // // SaherElm IT Center MQL4 OSC 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 ... // // // SHP Based Signal Conditions ... struct XOSCLongSignalConditions { // datetime crossOverTime; double slowOnCrossOver; // datetime crossUnderTime; double slowOnCrossUnder; }; // static XOSCLongSignalConditions oscLongConds; // // END Global Requirement Functions ... // // // START Functions ... // // // Check and Fill CC Signal Conditions ... void CheckOSCLongSignalConditions( const int bar_index, const int marketLen, // double stp, double mxm, // int scFMult, int scSMult, // int mcFMult, int mcSMult, // int lcFMult, int lcSMult, // const double smoother = 5 ) { // datetime barTime = iTime( _Symbol, _Period, bar_index ); // XState states[]; ArrayResize( states, marketLen ); // int index = 0; for (int i = bar_index; i < marketLen; i++) { // XState state = GetXState( i, marketLen, // stp, mxm, scFMult, scSMult, mcFMult, mcSMult, lcFMult, lcSMult ); // states[index] = state; // index++; } // bool isCrossUnder = states[0].osc.fast < 0 && !(states[1].osc.fast < 0) ; // bool isCrossOver = states[0].osc.fast > 0 && !(states[1].osc.fast > 0) ; // int oneTouches = 0; int halfTouches = 0; int minusOneTouches = 0; for (int i = 0; i < marketLen - 1; i++) { // // One Touches ... if ( states[i].osc.fast > 1 && !(states[i + 1].osc.fast > 1) ) { oneTouches++; } // // Half Touches ... if ( states[i].osc.fast > 0.5 && !(states[i + 1].osc.fast > 0.5) ) { halfTouches++; } // // Minus One Touches ... if ( states[i].osc.fast < -1 && !(states[i + 1].osc.fast < -1) ) { minusOneTouches++; } } // if ( isCrossUnder && oscLongConds.crossUnderTime == 0 ) { // oscLongConds.crossUnderTime = barTime; oscLongConds.slowOnCrossUnder = states[0].osc.slow; return; } // if ( isCrossOver && oscLongConds.crossUnderTime > 0 && oscLongConds.crossOverTime == 0 ) { // oscLongConds.crossOverTime = barTime; oscLongConds.slowOnCrossOver = states[0].osc.slow; return; } } // // Convert Long Signal Conditions to XSignal ... XSignalRequest GenerateOSCLongSignal( const int bar_index, // Bar Index ... const int marketLen, // MarketLength for TP and SL ... const double r2r // Risk to Reward ratio ... ) { // XSignalRequest result = {}; // result.hasSignal = false; result.type = X_SIGNAL_NONE; result.provider = X_UNKNOWN_PROVIDER; // if (!ValidateOSCLongConditions()) { return result; } // // Price Calculations ... // RefreshRates(); // double entryPrice = SymbolInfoDouble( _Symbol, SYMBOL_ASK ); // double exitPrice = SymbolInfoDouble( _Symbol, SYMBOL_BID ); // double priceGap = MathAbs(entryPrice - exitPrice); // double ll = GetMarketLowestLow( bar_index, marketLen ); // double openPrice = iOpen( _Symbol, _Period, bar_index ); // double closePrice = iClose( _Symbol, _Period, bar_index ); // double risk = MathMin(openPrice, closePrice) - ll; double reward = risk * r2r; // 300 * _Point; // double sl = 0; // ll; double tp = entryPrice + reward; // datetime barTime = iTime( _Symbol, _Period, bar_index ); // result.signal.tp = tp; result.signal.sl = sl; result.signal.symbol = _Symbol; result.signal.type = X_SIGNAL_LONG; result.signal.id = totalSignals + 1; result.signal.entry = entryPrice; result.signal.provider = X_OSC_PROVIDER; result.signal.time = barTime; // result.hasSignal = true; result.type = X_SIGNAL_LONG; result.provider = X_OSC_PROVIDER; // return result; } // // Validate Signal Conditions ... bool ValidateOSCLongConditions() { // bool isConditionsFilled = oscLongConds.crossOverTime > 0 && oscLongConds.crossUnderTime > 0 && oscLongConds.slowOnCrossOver > 0 && oscLongConds.slowOnCrossUnder > 0 && oscLongConds.crossOverTime > oscLongConds.crossUnderTime ; // bool isBLFilled = false; if (isConditionsFilled) { // int crossUnderBarIndex = iBarShift( _Symbol, _Period, oscLongConds.crossUnderTime ); // int crossOverBarIndex = iBarShift( _Symbol, _Period, oscLongConds.crossOverTime ); // isBLFilled = crossUnderBarIndex > crossOverBarIndex // && oscLongConds.slowOnCrossOver > oscLongConds.slowOnCrossUnder ; } // bool result = isBLFilled && isConditionsFilled ; // // 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 ) { ClearOSCLongSignalConditions(); } // return result; } // // Clear Long Signal Conditions for New One ... void ClearOSCLongSignalConditions() { // oscLongConds.crossOverTime = 0;; oscLongConds.crossUnderTime = 0;; } // // Check State for Long Signals ... bool IsReadyForOSCLongSignals( const XSignal &signal, const XState &states[] ) { // bool result = false; // result = // true ; // return result; } // // END Functions ... //