/////////////////////////////////////////////////////// // // SaherElm IT Center MQL4 XTPW Signal Global Library // --------------------------------------------------- // XSaherElm EA Signal Provider based on // XTPow Indicator... // // // 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 xTPWStarter = "- XTPW Signal Provider -"; // ---> XTPW Signal Provider <--- // input bool enableXTPWSignalling = true; // XTPW Signalling Enable // input bool enableXTPWLong = true; // XTPW Signalling Enable Long input bool enableXTPWShort = true; // XTPW Signalling Enable Short // input double xTPWShortR2R = 2; // XTPW Short Risk To Reward Ratio input double xTPWShortLotsPerTradePercent = 0.0002; // XTPW Lots Percent per Short Trades input double xTPWShortMaxDrawdownPerTradePercent = 0.3; // XTPW Max Allowed DrawDown Percent per Short Trade // input double xTPWLongR2R = 2; // XTPW Long Risk To Reward Ratio input double xTPWLongLotsPerTradePercent = 0.0002; // XTPW Lots Percent per Short Trades input double xTPWLongMaxDrawdownPerTradePercent = 0.3; // XTPW Max Allowed DrawDown Percent per Long Trade // input int xTPWMaximumCandlesPerTrade = 206; // XTPW Maximum Candles which a Trade can open // input double xTPWPSarStep = 0.02; // XTPW Parabolic Sar Step input double xTPWPSarMaximum = 0.2; // XTPW Parabolic Sar Maximum // input int xTPWSwingLength = 7; // XTPW Signal Swing Length // // END Inputs ... // // input double xTPWSharpDetectionFactor = 650; // XTPW Sharp Detection Factor // // START Global Requirement Functions ... // // // XTPW Based Signal Conditions ... struct XTPWSignalConditions { datetime startTime; datetime signalTime; datetime entryTime; }; // struct XTPWMarketState { // double psar; // double scFast; double scSlow; double scWeight; // double mcFast; double mcSlow; double mcWeight; // double lcFast; double lcSlow; double lcWeight; }; // struct XLHS { // double scHH; double scLL; // double mcHH; double mcLL; // double lcHH; double lcLL; }; // static XTPWSignalConditions xTPWLongConds; static bool xTPWCloseLongTrades = false; static bool xTPWWaitForLongSignals = true; // static XTPWSignalConditions xTPWShortConds; static bool xTPWCloseShortTrades = false; static bool xTPWWaitForShortSignals = true; // // Count Number of Closed Maximum DrawDown Trades ... static int xTPWFailedSignals = 0; // double tPowerVerifier = 20; double tPowerMaxVerifier = 55; // int scFastLength = 0; int scSlowLength = 0; // int mcFastLength = 0; int mcSlowLength = 0; // int lcFastLength = 0; int lcSlowLength = 0; // datetime lastTurnOffLongTradesTime; datetime lastTurnOffShortTradesTime; // // END Global Requirement Functions ... // // // START Functions ... // // // Check and Fill Long and Short Signal Handlers ... void CheckXTPWSignalHandler( const int bar_index ) { // // Check Market For Enable/Disable Signal Handlers ... // Checking Market for Long Signals ... // if ( !enableXTPWSignalling || !(enableXTPWLong || enableXTPWShort) ) { return; } // datetime barTime = iTime( _Symbol, _Period, bar_index ); // XOHCL candle0 = GetCandleModel(bar_index); XOHCL candle1 = GetCandleModel(bar_index + 1); XOHCL candle2 = GetCandleModel(bar_index + 1); // XTPOWState tPow0 = GetXTPowState( bar_index, xTPWSwingLength ); XTPOWState tPow1 = GetXTPowState( bar_index + 1, xTPWSwingLength ); XTPOWState tPow2 = GetXTPowState( bar_index + 2, xTPWSwingLength ); // XTPWMarketState state0 = GetXTPWMarketState( bar_index ); XTPWMarketState state1 = GetXTPWMarketState( bar_index + 1 ); XTPWMarketState state2 = GetXTPWMarketState( bar_index + 2 ); // // // // Disable Long Conditions ... // if ( // xTPWWaitForLongSignals // && // ( // isRangeCrossOverRangeWeight // || // isRangeCrossUnderRangeWeight // || // isTPowUpperAboveMaxVerifier // ) // ) { // // // xTPWWaitForLongSignals = false; // lastTurnOffLongTradesTime = barTime; // } // // // // Enable Long Conditions ... // if ( // !xTPWWaitForLongSignals // && lastTurnOffLongTradesTime > 0 // && ( // // isFastCrossOverSlow // // || // // isFastCrossUnderSlow // isRangeCrossOverRangeWeight // || // isRangeCrossUnderRangeWeight // || // isTPowUpperBelowMaxVerifier // ) // ) { // // // // Find Last Turn Off Bar Index ... // int lastTurnOffLongTradesBarIndex = iBarShift( // _Symbol, // _Period, // lastTurnOffLongTradesTime // ); // // // // the Distance must be bigger than market length ... // if (MathAbs(lastTurnOffLongTradesBarIndex - bar_index) > xTPWSwingLength) { // // // xTPWWaitForLongSignals = true; // lastTurnOffLongTradesTime = 0; // } // } } // // Check and Fill Long Signal Conditions ... void CheckXTPWLongSignalConditions( const int bar_index ) { // if ( !enableXTPWLong || !enableXTPWSignalling || !xTPWWaitForLongSignals ) { return; } // datetime barTime = iTime( _Symbol, _Period, bar_index ); // // Retrieve TPow States ... XTPOWState tPow0 = GetXTPowState( bar_index, xTPWSwingLength ); XTPOWState tPow1 = GetXTPowState( bar_index + 1, xTPWSwingLength ); XTPOWState tPow2 = GetXTPowState( bar_index + 2, xTPWSwingLength ); // // Retrieve TPowMarket State ... XTPWMarketState state0 = GetXTPWMarketState( bar_index ); XTPWMarketState state1 = GetXTPWMarketState( bar_index + 1 ); XTPWMarketState state2 = GetXTPWMarketState( bar_index + 2 ); // // Retrieve XPrice Model ... XPrice prices = GetPrice(); // // Retrieve Candles ... XOHCL candle0 = GetCandleModel(bar_index); XOHCL candle1 = GetCandleModel(bar_index + 1); XOHCL candle2 = GetCandleModel(bar_index + 2); // XLHS lhs = GetXTPWLHS(bar_index); // bool isHHSame = lhs.scHH == lhs.mcHH && lhs.mcHH == lhs.lcHH ; // bool isLLSame = lhs.scLL == lhs.mcLL && lhs.mcLL == lhs.lcLL ; // bool startCondition = false; bool signalCondition = false; bool entryCondition = false; // bool longCondition1 = // true // && !isHHSame // && !( lhs.scLL == lhs.mcLL ) // && !( lhs.scHH == lhs.mcHH ) // && !( prices.longEntry && candle0.high < state0.scFast && candle0.high < state0.scSlow && candle0.high < state0.mcFast && candle0.high < state0.mcSlow && candle0.high < state0.lcFast && candle0.high < state0.lcSlow ) // && tPow0.powerDown > tPowerMaxVerifier && tPow1.powerDown > tPowerMaxVerifier && tPow0.powerDown < MathMax(tPow1.powerUp, tPow1.powerDown) && MathMax(tPow1.powerUp, tPow1.powerDown) > tPowerMaxVerifier ; // // Start Conditions ... startCondition = ( longCondition1 ) ; // if ( startCondition && xTPWLongConds.startTime == 0 && xTPWLongConds.signalTime == 0 && xTPWLongConds.entryTime == 0 ) { // xTPWLongConds.startTime = barTime; xTPWLongConds.signalTime = barTime; xTPWLongConds.entryTime = barTime; // return; } } // // Check and Fill Short Signal Conditions ... void CheckXTPWShortSignalConditions( const int bar_index ) { // if ( !enableXTPWShort || !enableXTPWSignalling || !xTPWWaitForShortSignals ) { return; } // datetime barTime = iTime( _Symbol, _Period, bar_index ); // // Retrieve TPower State ... XTPOWState tPow0 = GetXTPowState( bar_index, xTPWSwingLength ); XTPOWState tPow1 = GetXTPowState( bar_index + 1, xTPWSwingLength ); XTPOWState tPow2 = GetXTPowState( bar_index + 2, xTPWSwingLength ); // // Retrieve TPWMarket State ... XTPWMarketState state0 = GetXTPWMarketState( bar_index ); XTPWMarketState state1 = GetXTPWMarketState( bar_index + 1 ); XTPWMarketState state2 = GetXTPWMarketState( bar_index + 2 ); // // Retrieve Candles ... XOHCL candle0 = GetCandleModel(bar_index); XOHCL candle1 = GetCandleModel(bar_index + 1); XOHCL candle2 = GetCandleModel(bar_index + 2); // XPrice prices = GetPrice(); XLHS lhs = GetXTPWLHS(bar_index); // double sharpDetectionValue = xTPWSharpDetectionFactor * _Point; // bool isHHSame = lhs.scHH == lhs.mcHH && lhs.mcHH == lhs.lcHH ; // bool isLLSame = lhs.scLL == lhs.mcLL && lhs.mcLL == lhs.lcLL ; // bool startCondition = false; bool signalCondition = false; bool entryCondition = false; // bool shortCondition1 = // true // && tPow1.powerDown > tPowerMaxVerifier && tPow2.powerDown < tPowerMaxVerifier ; // startCondition = ( shortCondition1 ) ; // if ( startCondition && xTPWShortConds.startTime == 0 && xTPWShortConds.signalTime == 0 && xTPWShortConds.entryTime == 0 ) { // xTPWShortConds.startTime = barTime; xTPWShortConds.signalTime = barTime; xTPWShortConds.entryTime = barTime; // return; } } // // Convert Long Signal Conditions to XSignal ... XSignalRequest GenerateXTPWSignal( 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 ( !enableXTPWSignalling || !(enableXTPWLong || enableXTPWShort) ) { return result; } // bool requestLong = type == X_SIGNAL_LONG; // // Check Condition Validations ... if (requestLong) { // // Check Long Condtion is Valid, if Long Requested ... if ( !ValidateXTPWLongConditions() ) { return result; } } else { // // Check Short Condtion is Valid, if Short Requested ... if ( !ValidateXTPWShortConditions() ) { return result; } } // double ll = // GetMarketLowestLow( bar_index, xTPWSwingLength ) ; // double hh = // GetMarketHighestHigh( bar_index, xTPWSwingLength ) ; // double openPrice = iOpen( _Symbol, _Period, bar_index ); // double closePrice = iClose( _Symbol, _Period, bar_index ); // // Price Calculations ... XPrice prices = GetPrice(); // // Read State ... XTPWMarketState state0 = GetXTPWMarketState(bar_index); // XOHCL candle0 = GetCandleModel(bar_index); XOHCL candle1 = GetCandleModel(bar_index + 1); XOHCL candle2 = GetCandleModel(bar_index + 2); XOHCL candle3 = GetCandleModel(bar_index + 2); // double risk = requestLong ? // MathMin(openPrice, closePrice) - ll : hh - MathMax(openPrice, closePrice) ; // double longR2R = xTPWLongR2R; double shortR2R = xTPWShortR2R; // double sharpDetectorValue = xTPWSharpDetectionFactor * _Point; // if ( risk > 0 && requestLong ) { return result; } // // Define Entry Price ... double entryPrice = requestLong ? prices.longEntry : prices.shortEntry ; // // Fix TP Detects for Short Signals ... if (!requestLong) { risk = 0; } // double reward = requestLong ? risk * longR2R : risk * shortR2R ; // if (risk == 0) { // // Calculate Reward ... reward = requestLong ? MathAbs(hh - entryPrice) : MathAbs(hh - entryPrice) ; // // Detect Sharp Change Occured or not ... bool isSharpOccured = reward > sharpDetectorValue || MathAbs(reward - sharpDetectorValue) < (50 * _Point); // // Change Rewards on Special Conditions ... if ( ( requestLong && isSharpOccured && ( state0.lcFast < state0.lcSlow || ( state0.mcFast > state0.mcSlow && state0.mcWeight < state0.mcSlow ) ) ) ) { reward = reward / 2; } // if (reward < 50 * _Point) { reward = (50 * _Point) + prices.priceGap; } // // // if (!requestLong) { // reward = reward * shortR2R; // } } // double sl = requestLong ? 0 : 0; double tp = requestLong ? entryPrice + reward : entryPrice - reward ; // 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_XTPW_PROVIDER; // result.hasSignal = true; result.type = type; result.provider = X_XTPW_PROVIDER; // return result; } // // Validate Signal Conditions ... bool ValidateXTPWLongConditions() { // if ( !enableXTPWLong || !enableXTPWSignalling ) { return false; } // bool isConditionsFilled = xTPWLongConds.startTime > 0 && xTPWLongConds.signalTime > 0 && xTPWLongConds.entryTime > 0 ; // bool isBLFilled = false; if (isConditionsFilled) { // // // int startBarIndex = iBarShift( // _Symbol, // _Period, // xTPWLongConds.startTime // ); // // // int signalBarIndex = iBarShift( // _Symbol, // _Period, // xTPWLongConds.signalTime // ); // // // int entryBarIndex = iBarShift( // _Symbol, // _Period, // xTPWLongConds.entryTime // ); // // // int startSignalDiff = (signalBarIndex - startBarIndex); // int entrySignalDiff = (entryBarIndex - signalBarIndex); // int maxDiff = MathMax(startSignalDiff, entrySignalDiff); // isBLFilled = // // Starter ... true // && xTPWLongConds.signalTime >= xTPWLongConds.startTime && xTPWLongConds.entryTime >= xTPWLongConds.signalTime // // && maxDiff < (xTPWSwingLength * 2) ; } // bool result = isBLFilled && isConditionsFilled && xTPWWaitForLongSignals ; // // 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 ) { ClearXTPWLongSignalConditions(); } // return result; } // // Validate Signal Conditions ... bool ValidateXTPWShortConditions() { // if ( !enableXTPWShort || !enableXTPWSignalling ) { return false; } // bool isConditionsFilled = xTPWShortConds.startTime > 0 && xTPWShortConds.signalTime > 0 && xTPWShortConds.entryTime > 0 ; // bool isBLFilled = false; if (isConditionsFilled) { // // // int startBarIndex = iBarShift( // _Symbol, // _Period, // xTPWShortConds.startTime // ); // // // int signalBarIndex = iBarShift( // _Symbol, // _Period, // xTPWShortConds.signalTime // ); // // // int entryBarIndex = iBarShift( // _Symbol, // _Period, // xTPWShortConds.entryTime // ); // isBLFilled = // // Starter ... true // && xTPWShortConds.signalTime >= xTPWShortConds.startTime && xTPWShortConds.entryTime >= xTPWShortConds.signalTime ; } // bool result = isBLFilled && isConditionsFilled && xTPWWaitForShortSignals ; // // 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 ) { ClearXTPWShortSignalConditions(); } // return result; } // // Clear Long Signal Conditions for New One ... void ClearXTPWLongSignalConditions() { // xTPWLongConds.startTime = 0; xTPWLongConds.entryTime = 0; xTPWLongConds.signalTime = 0; } // // Clear Short Signal Conditions for New One ... void ClearXTPWShortSignalConditions() { // xTPWShortConds.startTime = 0; xTPWShortConds.entryTime = 0; xTPWShortConds.signalTime = 0; } // // Check State for Long Signals ... bool IsReadyForXTPWSignals( const XSignal &signal ) { // bool result = false; // if ( !enableXTPWSignalling || !(enableXTPWLong || enableXTPWShort) ) { return result; } // int signalBarIndex = iBarShift( _Symbol, _Period, signal.time ); // // XOHCL candle = GetCandleModel(0); XOHCL candle0 = GetCandleModel(signalBarIndex); XOHCL candle1 = GetCandleModel(signalBarIndex + 1); // // Retrieve TPow State ... XTPOWState tPow0 = GetXTPowState( signalBarIndex, xTPWSwingLength ); XTPOWState tPow1 = GetXTPowState( signalBarIndex + 1, xTPWSwingLength ); // // Retrive XMarket States ... XTPWMarketState state0 = GetXTPWMarketState(signalBarIndex); XTPWMarketState state1 = GetXTPWMarketState(signalBarIndex + 1); XTPWMarketState state2 = GetXTPWMarketState(signalBarIndex + 2); // bool isPSarVerified = false; bool isTPowVerified = false; bool isStateVerified = false; bool isPriceVerified = false; // // Calculate Sharp Detection Value ... double sharpDetectionValue = xTPWSharpDetectionFactor * _Point; // // Find State0 Min ... double state0Min = MathMin(state0.scFast, state0.scSlow); state0Min = MathMin(state0Min, state0.mcFast); state0Min = MathMin(state0Min, state0.mcSlow); state0Min = MathMin(state0Min, state0.lcFast); state0Min = MathMin(state0Min, state0.lcSlow); // // Find State0 Min ... double state0Max = MathMax(state0.scFast, state0.scSlow); state0Max = MathMax(state0Max, state0.mcFast); state0Max = MathMax(state0Max, state0.mcSlow); state0Max = MathMax(state0Max, state0.lcFast); state0Max = MathMax(state0Max, state0.lcSlow); // // Find Distance Between State0 Min and Max ... double state0MinMaxDistance = MathAbs(state0Max - state0Min); // // Verify Long Signals ... if (signal.type == X_SIGNAL_LONG) { // // Get Price Verification for Long ... isPriceVerified = // // Starter ... true // ; // isTPowVerified = // // Starter ... true // && tPow0.powerDown > tPowerMaxVerifier && tPow1.powerDown > tPowerMaxVerifier && tPow0.powerDown < MathMax(tPow1.powerUp, tPow1.powerDown) && MathMax(tPow1.powerUp, tPow1.powerDown) > tPowerMaxVerifier ; // isPSarVerified = // // Starter ... true // ; // isStateVerified = // // Start ... true // && state0.mcFast > state0.mcSlow && state1.mcFast > state1.mcSlow // && !( state0.lcFast > state0.mcSlow && state0.lcFast < state0.mcFast ) // && MathAbs(state1.mcFast - state1.mcSlow) > (50 * _Point) ; // result = // // Starter ... true // && isPSarVerified // && isTPowVerified // && isStateVerified // && isPriceVerified ; } else // // Verify Short Signals ... if (signal.type == X_SIGNAL_SHORT) { // isPSarVerified = // // Starter ... true ; // // Get Price Verification for Short ... isPriceVerified = // // Starter ... true ; // isTPowVerified = // // Starter ... true // && tPow0.signal > MathMax(tPow0.powerUp, tPow0.powerDown) ; // isStateVerified = // // Start ... true // && ( // state0.scFast < state0.scSlow && state0.mcFast < state0.mcSlow && state0.lcFast < state0.lcSlow ? signal.entry > state0.scFast : // // Find Minimum and Maximum Distance of State ... state0MinMaxDistance > sharpDetectionValue ? signal.entry > state0Min : true ) // && MathAbs(state0.mcFast - state0.mcSlow) > 50 * _Point ; // result = // // Starter Condition ... true // && isPSarVerified // && isTPowVerified // && isStateVerified // && isPriceVerified ; } // return result; } // // END Functions ... // // // START Data Provider ... // // // Retrieve Market State ... XTPWMarketState GetXTPWMarketState( const int bar_index ) { // XTPWMarketState result = {}; // int dayCount = GetDailyCandleCount(); int halfDayCount = (int)(dayCount / 2); // if (scFastLength == 0) { scFastLength = xTPWSwingLength; } // if (scSlowLength == 0) { scSlowLength = xTPWSwingLength * 2; } // if (mcFastLength == 0) { mcFastLength = halfDayCount; } // if (mcSlowLength == 0) { mcSlowLength = dayCount; } // if (lcFastLength == 0) { lcFastLength = halfDayCount * 3; } // if (lcSlowLength == 0) { lcSlowLength = dayCount * 3; } // double scFast = GetMA( bar_index, scFastLength, 0, MODE_SMA, PRICE_CLOSE ); // double scSlow = GetMA( bar_index, scSlowLength, 0, MODE_SMA, PRICE_CLOSE ); // double scWeight = GetMA( bar_index, scSlowLength, 0, MODE_EMA, PRICE_MEDIAN ); // double mcFast = GetMA( bar_index, mcFastLength, 0, MODE_SMA, PRICE_CLOSE ); // double mcSlow = GetMA( bar_index, mcSlowLength, 0, MODE_SMA, PRICE_CLOSE ); // double mcWeight = GetMA( bar_index, mcSlowLength, 0, MODE_EMA, PRICE_MEDIAN ); // double lcFast = GetMA( bar_index, lcFastLength, 0, MODE_SMA, PRICE_CLOSE ); // double lcSlow = GetMA( bar_index, lcSlowLength, 0, MODE_SMA, PRICE_CLOSE ); // double lcWeight = GetMA( bar_index, lcSlowLength, 0, MODE_EMA, PRICE_MEDIAN ); // double psar = iSAR( _Symbol, _Period, xTPWPSarStep, xTPWPSarMaximum, bar_index ); // result.psar = psar; result.scFast = scFast; result.scSlow = scSlow; result.mcFast = mcFast; result.mcSlow = mcSlow; result.lcFast = lcFast; result.lcSlow = lcSlow; result.scWeight = scWeight; result.mcWeight = mcWeight; result.lcWeight = lcWeight; // return result; } // // Retrieve Highest Highs and Lowest Lows in Cycles ... XLHS GetXTPWLHS( const int bar_index ) { // XLHS result = {}; // // Retrieve LL and HH (s) ... // // SC HH ... double scHH = GetMarketHighestHigh( bar_index, scFastLength ); // // SC LL ... double scLL = GetMarketHighestHigh( bar_index, scFastLength ); // // MC HH ... double mcHH = GetMarketHighestHigh( bar_index, mcFastLength ); // // MC LL ... double mcLL = GetMarketHighestHigh( bar_index, mcFastLength ); // // LC HH ... double lcHH = GetMarketHighestHigh( bar_index, lcFastLength ); // // LC LL ... double lcLL = GetMarketHighestHigh( bar_index, lcFastLength ); // result.scHH = scHH; result.scLL = scLL; result.mcHH = mcHH; result.mcLL = mcLL; result.lcHH = lcHH; result.lcLL = lcLL; // return result; } // // END Data Provider ... //