/////////////////////////////////////////////////////// // // SaherElm IT Center MQL4 XMA 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 ... // // // XMA Based Signal Conditions ... struct XMAMCLongSignalConditions { // datetime mcFastCrossUnderSlowTime; double crossUnderMCFast; double crossUnderMCSlow; // datetime mcFastCrossOverSlowTime; double crossOverMCFast; double crossOverMCSlow; // datetime mcFastBiggerThanCrossUnderSlowTime; }; // static XMAMCLongSignalConditions xmaMCLongConds; // // END Global Requirement Functions ... // // // START Functions ... // // // Check and Fill CC Signal Conditions ... void CheckXMAMCLongSignalConditions( const int bar_index, const int marketLen, // double stp, double mxm, // int scFMult, int scSMult, // int mcFMult, int mcSMult ) { // XCycleState mcs[]; int positionsMarketLen = bar_index + marketLen; // // Retrieve Bar Time ... datetime barTime = iTime( _Symbol, _Period, bar_index ); // // Resize Arrays ... ArrayResize( mcs, marketLen ); // int index = 0; for (int i = bar_index; i < positionsMarketLen; i++) { // XCycleState mc = GetXMAMC( i, marketLen, mcFMult, mcSMult ); mcs[index] = mc; // index++; } // bool isMCFastCrossUnderSlow = mcs[0].fast < mcs[0].slow && !(mcs[1].fast <= mcs[1].slow) ; bool isMCFastCrossOverSlow = mcs[0].fast > mcs[0].slow && !(mcs[1].fast >= mcs[1].slow) ; // if ( isMCFastCrossUnderSlow && xmaMCLongConds.mcFastCrossUnderSlowTime == 0 ) { // xmaMCLongConds.crossUnderMCFast = mcs[0].fast; xmaMCLongConds.crossUnderMCSlow = mcs[0].slow; xmaMCLongConds.mcFastCrossUnderSlowTime = barTime; return; } // if ( isMCFastCrossUnderSlow && xmaMCLongConds.mcFastCrossUnderSlowTime > 0 ) { // ClearXMAMCLongSignalConditions(); // xmaMCLongConds.crossUnderMCFast = mcs[0].fast; xmaMCLongConds.crossUnderMCSlow = mcs[0].slow; xmaMCLongConds.mcFastCrossUnderSlowTime = barTime; return; } // if ( isMCFastCrossOverSlow && xmaMCLongConds.mcFastCrossUnderSlowTime > 0 && xmaMCLongConds.mcFastCrossOverSlowTime == 0 ) { // xmaMCLongConds.crossOverMCFast = mcs[0].fast; xmaMCLongConds.crossOverMCSlow = mcs[0].slow; xmaMCLongConds.mcFastCrossOverSlowTime = barTime; return; } // if ( xmaMCLongConds.mcFastCrossUnderSlowTime > 0 && xmaMCLongConds.mcFastCrossOverSlowTime > 0 && mcs[0].fast > xmaMCLongConds.crossUnderMCSlow && xmaMCLongConds.mcFastBiggerThanCrossUnderSlowTime == 0 ) { // xmaMCLongConds.mcFastBiggerThanCrossUnderSlowTime = barTime; return; } } // // Convert XMA Long Signal Conditions to XSignal ... XSignalRequest GenerateXMAMCLongSignal( const int bar_index, // Bar Index ... const int marketLen, // MarketLength for TP and SL ... const double r2r, // Risk to Reward ratio ... const double shpDetectMult, const double smoother = 50 ) { // XSignalRequest result = {}; // result.hasSignal = false; result.type = X_SIGNAL_NONE; result.provider = X_UNKNOWN_PROVIDER; // if ( !ValidateXMAMCLongConditions( marketLen, shpDetectMult, smoother ) ) { 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, 3 ); // 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; 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_XMA_PROVIDER; result.signal.time = barTime; // result.hasSignal = true; result.type = X_SIGNAL_LONG; result.provider = X_XMA_PROVIDER; // return result; } // // Validate XMA Signal Conditions ... bool ValidateXMAMCLongConditions( const int marketLen, const double shpDetectMult, const double smoother = 50 ) { // bool isConditionsFilled = xmaMCLongConds.crossOverMCSlow > 0 && xmaMCLongConds.crossOverMCFast > 0 && xmaMCLongConds.crossUnderMCFast > 0 && xmaMCLongConds.crossUnderMCSlow > 0 && xmaMCLongConds.mcFastCrossOverSlowTime != 0 && xmaMCLongConds.mcFastCrossUnderSlowTime != 0 && xmaMCLongConds.mcFastBiggerThanCrossUnderSlowTime != 0 ; // bool isBLFilled = false; if (isConditionsFilled) { // int crossUnderBarIndex = iBarShift( _Symbol, _Period, xmaMCLongConds.mcFastCrossUnderSlowTime ); // int crossOverAndBiggerBarIndex = iBarShift( _Symbol, _Period, xmaMCLongConds.mcFastBiggerThanCrossUnderSlowTime ); // int cycleMarketLen = MathMin( MathAbs(crossUnderBarIndex - crossOverAndBiggerBarIndex), marketLen * 2 ); double hh = GetMarketHighestHigh( crossOverAndBiggerBarIndex, cycleMarketLen ); double ll = GetMarketLowestLow( crossOverAndBiggerBarIndex, cycleMarketLen ); // double high = iHigh( _Symbol, _Period, crossOverAndBiggerBarIndex ); double pcHigh = iHigh( _Symbol, _Period, crossOverAndBiggerBarIndex + 1 ); // double diff = (hh - ll); double shpValue = shpDetectMult * _Point; // bool isPriceRegular = // true // && ( diff < shpValue || diff < shpValue - (smoother * _Point) ) && !( high == hh || pcHigh == hh || MathAbs(hh - high) < (smoother * _Point) || MathAbs(hh - pcHigh) < (smoother * _Point) ) ; // // LogMessage("Price Regular: " + isPriceRegular); // isBLFilled = isPriceRegular && xmaMCLongConds.mcFastCrossUnderSlowTime < xmaMCLongConds.mcFastCrossOverSlowTime && xmaMCLongConds.mcFastBiggerThanCrossUnderSlowTime >= xmaMCLongConds.mcFastCrossUnderSlowTime ; } // 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 ) { ClearXMAMCLongSignalConditions(); } // return result; } // // Clear Long Signal Conditions for New One ... void ClearXMAMCLongSignalConditions() { // xmaMCLongConds.mcFastCrossUnderSlowTime = 0; xmaMCLongConds.crossUnderMCFast = 0; xmaMCLongConds.crossUnderMCSlow = 0; // xmaMCLongConds.mcFastCrossOverSlowTime = 0; xmaMCLongConds.crossOverMCFast = 0; xmaMCLongConds.crossOverMCSlow = 0; // xmaMCLongConds.mcFastBiggerThanCrossUnderSlowTime = 0; } // // Check XMA State for Long Signals ... bool IsReadyForXMAMCLongSignals( const XSignal &signal, const XState &states[], const int marketLen ) { // bool result = false; // int countRangedCandles = 0; bool isMarketRanging = false; for (int i = 1; i < marketLen; i++) { // double high = iHigh( _Symbol, _Period, i ); // double low = iLow( _Symbol, _Period, i ); // bool isRanging = // high > states[i].mc.fast && high > states[i].mc.slow // && low < states[i].mc.fast && low < states[i].mc.slow ; if (isRanging) { countRangedCandles++; } } // XStateInfo info = ParseXMAStates(states); double mmSlope = GetSlope( 1, states[1].marketMiddleage, 2, states[0].marketMiddleage ); double mmSlope1 = GetSlope( 1, states[2].marketMiddleage, 2, states[1].marketMiddleage ); double mmSlopeDiff = mmSlope - mmSlope1; // isMarketRanging = countRangedCandles > 0; // result = // true // && mmSlope > 0 && mmSlope1 > 0 && mmSlopeDiff > 0 && !isMarketRanging && states[0].marketMiddleage < info.mmMax ; // if (result) { // LogMessage("mmSlope: " + mmSlope + ", mmSlope1: " + mmSlope1 + ", Diff: " + mmSlopeDiff); // } // return result; } // // END Functions ... //