/////////////////////////////////////////////////////// // // SaherElm IT Center MQL4 CCI 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 ... // // // Based Signal Conditions ... struct XCCILongSignalConditions { // datetime start; // datetime crossOverMinusHundredTime; datetime crossUnderMinusHundredTime; // double crossOverSlope; }; // static XCCILongSignalConditions cciLongConds; // // END Global Requirement Functions ... // // // START Functions ... // // // Check and Fill Signal Conditions ... void CheckCCILongSignalConditions( const int bar_index, const int marketLen, // const double smoother = 10 ) { // // Retrieve Bar Time ... datetime barTime = iTime( _Symbol, _Period, bar_index ); // // LONG: // wait for cci cross under -100 // then wait for cross over -100 // slope of crossing over ??? ... if (cciLongConds.start == 0) { // LogMessage("Start"); cciLongConds.start = barTime; return; } // // Check Start Time ... if (cciLongConds.start == 0) { return; } // // Read current, prev, and prevPrev CCI ... double cci = GetMarketCCI( bar_index, marketLen ); double cci1 = GetMarketCCI( bar_index + 1, marketLen ); double cci2 = GetMarketCCI( bar_index + 2, marketLen ); // // Find Cross Under -100 ... bool isCrossUnderMinusHundred = cci < -105 && !(cci1 < -105) && MathAbs(MathAbs(cci) - MathAbs(cci1)) > smoother ; // // Find Cross Over -100 ... bool isCrossOverMinusHundred = cci > -105 && !(cci1 > -105) && MathAbs(cci - cci1) > smoother ; // // Fill Conditions ... if ( isCrossUnderMinusHundred && cciLongConds.crossUnderMinusHundredTime == 0 && cciLongConds.crossOverMinusHundredTime == 0 ) { // LogMessage("Cross Under ..."); cciLongConds.crossUnderMinusHundredTime = barTime; return; } // // Fill Conditions ... if ( isCrossOverMinusHundred && cciLongConds.crossOverMinusHundredTime == 0 && cciLongConds.crossUnderMinusHundredTime != 0 ) { // // LogMessage("Cross Over ..."); cciLongConds.crossOverMinusHundredTime = barTime; } // // Prevent Going forward untill Cross Under Happens ... if (cciLongConds.crossUnderMinusHundredTime == 0) { return; } // // Prevent from Going forward untill Cross Over Happens ... if (cciLongConds.crossOverMinusHundredTime == 0) { return; } // // Calculate Slope ... double x1 = 0; double y1 = cci1; double x2 = 1; double y2 = cci; // // Calculat Line Slope ... double tSlope = GetSlope( x1, y1, x2, y2 ); // cciLongConds.crossOverSlope = tSlope; // LogMessage("Slope: " + tSlope); } // // Convert Long Signal Conditions to XSignal ... XSignalRequest GenerateCCILongSignal( 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 (!ValidateCCILongConditions()) { return result; } // // Price Calculations ... // RefreshRates(); // double entryPrice = SymbolInfoDouble( _Symbol, SYMBOL_ASK ); // double exitPrice = SymbolInfoDouble( _Symbol, SYMBOL_BID ); // double priceGap = MathAbs(entryPrice - exitPrice); // int llIdx = GetLowestLowOFCCILongPeriodIndex(); double ll = GetMarketLowestLow( bar_index, marketLen ); // GetLowestLowOFCCILongPeriod(); // int hhIdx = GetHighestHighOfCCILongPeriodIndex(); double hh = GetHighestHighOfCCILongPeriod(); // GetMarketHighestHigh( // 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; // 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_CCI_PROVIDER; result.signal.time = barTime; // result.hasSignal = true; result.type = X_SIGNAL_LONG; result.provider = X_CCI_PROVIDER; // return result; } // // Validate Signal Conditions ... bool ValidateCCILongConditions() { // int crossUnderBarIndex = cciLongConds.crossUnderMinusHundredTime != 0 ? iBarShift( _Symbol, _Period, cciLongConds.crossUnderMinusHundredTime ) : -1 ; // int crossOverBarIndex = cciLongConds.crossOverMinusHundredTime != 0 ? iBarShift( _Symbol, _Period, cciLongConds.crossOverMinusHundredTime ) : -1 ; // bool isConditionsFilled = // cciLongConds.start != 0 && cciLongConds.crossUnderMinusHundredTime != 0 && cciLongConds.crossOverMinusHundredTime != 0 && cciLongConds.crossUnderMinusHundredTime >= cciLongConds.start && cciLongConds.crossOverMinusHundredTime > cciLongConds.crossUnderMinusHundredTime ; // bool isLogicPassed = // crossOverBarIndex > 0 && crossUnderBarIndex > 0 && crossUnderBarIndex > crossOverBarIndex && (crossUnderBarIndex - crossOverBarIndex) >= 5 ; // bool result = // isConditionsFilled && isLogicPassed && cciLongConds.crossOverSlope > 0 ; // // 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 ) { ClearCCILongSignalConditions(); } // return result; } // // Clear Long Signal Conditions for New One ... void ClearCCILongSignalConditions() { // cciLongConds.start = 0; cciLongConds.crossOverSlope = 0; cciLongConds.crossOverMinusHundredTime = 0; cciLongConds.crossUnderMinusHundredTime = 0; } // int GetHighestHighOfCCILongPeriodIndex() { // int crossUnderBarIndex = iBarShift( _Symbol, _Period, cciLongConds.crossUnderMinusHundredTime ); // int crossOverBarIndex = iBarShift( _Symbol, _Period, cciLongConds.crossOverMinusHundredTime ); // int result = iHighest( _Symbol, _Period, MODE_HIGH, crossUnderBarIndex - crossOverBarIndex, crossOverBarIndex ); // return result; } // double GetHighestHighOfCCILongPeriod() { // int index = GetHighestHighOfCCILongPeriodIndex(); // double result = iHigh( _Symbol, _Period, index ); // return result; } // int GetLowestLowOFCCILongPeriodIndex() { // int crossUnderBarIndex = iBarShift( _Symbol, _Period, cciLongConds.crossUnderMinusHundredTime ); // int crossOverBarIndex = iBarShift( _Symbol, _Period, cciLongConds.crossOverMinusHundredTime ); // int result = iLowest( _Symbol, _Period, MODE_LOW, crossUnderBarIndex - crossOverBarIndex, crossOverBarIndex ); // return result; } // double GetLowestLowOFCCILongPeriod() { // int index = GetLowestLowOFCCILongPeriodIndex(); // double result = iLow( _Symbol, _Period, index ); // return result; } // // Check XMA State for Long Signals ... bool IsReadyForCCILongSignals( const XState &states[] ) { // bool result = false; // XStateInfo info = ParseXMAStates(states); // result = // true // // && states[1].mc.fast > states[1].mc.slow // && MathAbs(states[1].mc.fast - states[1].mc.slow) > 100 * _Point // && states[1].marketMiddleage > states[1].sc.fast // && states[1].marketMiddleage > states[1].mc.fast ; // return result; } // // END Functions ... //