From 8312af12b8cf7014845d474236e78953bf48ec73 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Fri, 12 Jul 2024 04:20:56 +0330 Subject: [PATCH] complete srbr strategy ... --- Classes/x-saherelm.xstrategy.class.mq5 | 506 ++++++++++++++ Experts/x-test-strategies.ea.mq5 | 192 ++++++ Libraries/x-saherelm.common.lib.mq5 | 80 +++ Libraries/x-saherelm.tools.mq5 | 20 +- Strategies/x-saherelm.xsrbr.strategy.mq5 | 799 +++++++++++++++++++++++ 5 files changed, 1587 insertions(+), 10 deletions(-) create mode 100644 Classes/x-saherelm.xstrategy.class.mq5 create mode 100644 Experts/x-test-strategies.ea.mq5 create mode 100644 Strategies/x-saherelm.xsrbr.strategy.mq5 diff --git a/Classes/x-saherelm.xstrategy.class.mq5 b/Classes/x-saherelm.xstrategy.class.mq5 new file mode 100644 index 00000000..b6a7d12e --- /dev/null +++ b/Classes/x-saherelm.xstrategy.class.mq5 @@ -0,0 +1,506 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XSCBaseStrategy +// Description: provides all based classes for use ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +/// Imports ... +#include "../Libraries/x-saherelm.tools.mq5" +#include "../Classes/x-saherelm.xtrade.class.mq5" +#include "../Classes/x-saherelm.xalert.class.mq5" + +// +class XSCBaseStrategy : public XSCBaseAlert +{ + // + // Public ... +public: + // + // Constructors ... + void XSCBaseStrategy( + string _symbol, // Trading Symbol + ENUM_TIMEFRAMES _period, // Trading TimeFrame + double _volume, // Voluem + double _r2r, // Risk/Reward Ratio + int _slippage, // Trader Slippage + long _magicNumber, // Trader Magic Number + bool _allowLong = true, + bool _allowShort = true, + int _maxAllowedLongs = 0, + int _maxAllowedShorts = 0 // + ) + { + // + // Fill Properties ... + mR2R = _r2r; + mVolume = _volume; + mSymbol = _symbol; + mPeriod = _period; + mSlippage = _slippage; + mAllowLong = _allowLong; + mAllowShort = _allowShort; + mMagicNumber = _magicNumber; + mMaxAllowedLongs = _maxAllowedLongs; + mMaxAllowedShorts = _maxAllowedShorts; + + // + mForceDisabled = false; + + // + // Initial Trader Class Instance ... + trader = new XSCTrade( + mSlippage, + mMagicNumber // + ); + + // + // Initial Time Tracker ... + barTracker.Init( + mSymbol, + mPeriod // + ); + + // + SetAlertPrefix(GetTag()); + } + + // + // Deconstructor ... + void ~XSCBaseStrategy() + { + // + delete trader; + + // + Reset(); + } + + // + // Getter and Setter (s) ... + + // + int Slippage() + { + return mSlippage; + } + + // + long MagicNumber() + { + return mMagicNumber; + } + + // + string Symbol() + { + return mSymbol; + } + + // + ENUM_TIMEFRAMES Period() + { + return mPeriod; + } + + // + bool IsDisabled() + { + return mForceDisabled; + } + + // + void Disable() + { + mForceDisabled = true; + } + + // + void Enable() + { + mForceDisabled = false; + } + + // + double Volume() + { + return mVolume; + } + + // + void Volume(double value) + { + // + if (value < 0.01) + { + value = 0.01; + } + + // + mVolume = value; + } + + // + double R2R() + { + return mR2R; + } + + // + bool AllowLong() + { + return mAllowLong; + } + + // + void AllowLong(bool value) + { + mAllowLong = value; + } + + // + bool AllowShort() + { + return mAllowShort; + } + + // + void AllowShort(bool value) + { + mAllowShort = value; + } + + // + int MaxAllowedLongs() + { + return mMaxAllowedLongs; + } + + // + void MaxAllowedLongs(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedLongs = value; + } + + // + int MaxAllowedShorts() + { + return mMaxAllowedShorts; + } + + // + void MaxAllowedShorts(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedShorts = value; + } + + // + int RequiredPivots() + { + return mRequiredPivots; + } + + // + void RequiredPivots(int value) + { + // + if (value < 3) + { + value = 3; + } + + // + mRequiredPivots = value; + } + + // + int RequiredShoulders() + { + return mRequiredShoulders; + } + + // + void RequiredShoulders(int value) + { + // + if (value < 5) + { + value = 5; + } + + // + mRequiredShoulders = value; + } + + // + // Virtual Methods ... + + // + // Tag ... + virtual string GetTag() + { + return "XBaseStrategy"; + } + + // + // Check Conditions for Signal ... + // this must be Override based on each Strategy ... + virtual bool HasSignal( + XSignal &signal // + ) + { + return false; + } + + // + // Check Conditions For Signal and Execute Signal ... + virtual void HandleTick() + { + // + if (IsDisabled()) + { + return; + } + + // + if (!AllowLong() && !AllowShort()) + { + return; + } + + // + if (!barTracker.CanProcessBar()) + { + return; + } + + // + MqlTick cTick; + bool hasTick = GetTick( + mSymbol, + cTick // + ); + bool isSameAsLast = cTick.time == lastTick.time; + if (isSameAsLast) + { + return; + } + + // + lastTick = cTick; + + // + XSignal signal; + bool hasSignal = HasSignal(signal); + if (!hasSignal) + { + return; + } + + // + barTracker.Waits(); + + // + Execute(signal); + } + + // + // Handle Signal Execution ... + virtual bool Execute(XSignal &signal) + { + // + bool result = false; + + // + result = !IsDisabled(); + if (!result) + { + return result; + } + + // + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + bool isLong = IsLong(signal.type); + + // + result = + // + isLong + ? AllowLong() + : AllowShort() + // + ; + if (!result) + { + return result; + } + + // + // Check Max Allowed Trades Limitation ... + if ( + (isLong && MaxAllowedLongs() > 0) || + (!isLong && MaxAllowedShorts() > 0)) + { + // + // Here We Have to Count Positions ... + + // + // Get and Count Positions ... + XPosition positions[]; + int positionsCount = trader.GetPositions( + positions // + ); + + // + // Get and Count Lng and Short Positions ... + XPosition longs[]; + XPosition shorts[]; + ExtractPositions( + positions, + longs, + shorts // + ); + int longsCount = ArraySize(longs); + int shortsCount = ArraySize(shorts); + + // + result = + // + isLong + ? longsCount < MaxAllowedLongs() + : shortsCount < MaxAllowedShorts() + // + ; + if (!result) + { + return result; + } + } + + // + ENUM_X_SIGNAL_EXECUTION_RESULT state; + result = trader.ExecuteSignal( + signal, + state // + ); + if (result) + { + // + string message = "Execute " + (isLong ? "Long" : "Short") + " " + signal.symbol + "/" + ToString(signal.period) + " ..."; + Alert(message); + + // + OnSignalExecuted(signal); + } + else + { + OnSignalExecutionFailed(signal, state); + } + + // + return result; + } + + // + // Calls When a Signal Executed Successfully ... + virtual void OnSignalExecuted(XSignal &signal) + { + } + + // + // Calls When a Signal Execution Failed ... + virtual void OnSignalExecutionFailed( + XSignal &signal, + ENUM_X_SIGNAL_EXECUTION_RESULT result // + ) + { + } + + // + // Protected ... +protected: + // + int mSlippage; // Trader Slippage + long mMagicNumber; // Trader Magic Number + bool mForceDisabled; // Force Disabled + bool mAllowLong; // Allow Long Signals + bool mAllowShort; // Allow Short Signals + int mMaxAllowedLongs; // Max Allowed Longs + int mMaxAllowedShorts; // Max Allowed Shorts + + // + string mSymbol; // Trading Symbol ... + ENUM_TIMEFRAMES mPeriod; // Trading TimeFrame ... + + // + double mR2R; // Risk/Rewar Ratio ... + double mVolume; // Static Volume Per Trades ... + + // + XBarTracker barTracker; // Strategy Time Tracker ... + + // + // Trend Detecting ... + int mRequiredPivots; // Required Pivots For Trend Detecting ... + int mRequiredShoulders; // Required Pivots Shoulders ... + + // + XTrendDetector trendDetector; // Trend Detector ... + + // + XSCTrade *trader; + + // + MqlTick lastTick; + + // + void Reset() + { + // + barTracker.Clean(); + trendDetector.Clean(); + } + + // + // Private ... +private: + // + // Props ... +}; + +// \ No newline at end of file diff --git a/Experts/x-test-strategies.ea.mq5 b/Experts/x-test-strategies.ea.mq5 new file mode 100644 index 00000000..48394013 --- /dev/null +++ b/Experts/x-test-strategies.ea.mq5 @@ -0,0 +1,192 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XTest MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XTestPivotsEA +// Description: an Exper Advisor which used XTestSetup +// to Analyse Market ... +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +//////////////////////////////////////////////////////x +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XTestPivotsEA" +#property strict + +// +#define ShortName "XTestPivotsEA" + +// +// Imports ... +#include "../Helpers/x-saherelm.xct.helper.mq5" +#include "../Helpers/x-saherelm.xcc.helper.mq5" +#include "../Strategies/x-saherelm.xsrbr.strategy.mq5" + +// +// Inputs ... +long mMagicNumber = 78692110; // Magic Number +int mSlippage = 10; // Slippgae + +// +double eaVolume = 0.01; +double eaAllowLong = true; +double eaAllowShort = true; + +// +// Variables ... +XSCXCTHelper *mCTHelper; +XSCXCCHelper *mCCHelper; + +// +XSCXSRBRStrategy *strategy; + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + if (!InitialEA()) + { + return INIT_FAILED; + } + + // + EventSetTimer(1); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // De Initialize XSampleEA Providers ... + delete mCTHelper; + delete mCCHelper; + + // + EventKillTimer(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + strategy.HandleTick(); +} + +// +// On Timer ... +void OnTimer() +{ + // +} + +// +// Custom Functions ... + +// +bool ValidateInputs() +{ + // + bool result = false; + + // + result = true; + + // + return result; +} + +// +bool InitialEA() +{ + // + bool result = false; + + // + // Bar Timer ... + XCTInputs ctInputs; + ctInputs.Default(); + mCTHelper = new XSCXCTHelper(); + result = mCTHelper.Init( + _Symbol, + _Period, + ctInputs // + ); + if (!result) + { + return result; + } + + // + // Bar Styles ... + XCCInputs ccInputs; + ccInputs.Default(); + mCCHelper = new XSCXCCHelper(); + result = mCCHelper.Init( + _Symbol, + _Period, + ccInputs // + ); + if (!result) + { + return result; + } + + // + strategy = new XSCXSRBRStrategy( + _Symbol, + _Period, + eaVolume, + 1.5, // R2R ... + mSlippage, + mMagicNumber + 1, + eaAllowLong, + eaAllowShort, + 0, // Max Longs + 0 // Max Shorts + ); + strategy.SetAlertLogAlerts(true); + strategy.SetAlertEnableAlerts(true); + strategy.DarwSupportAndResistances(true); + + // + return result; +} + +// +// Custom Testing Functions ... + +// \ No newline at end of file diff --git a/Libraries/x-saherelm.common.lib.mq5 b/Libraries/x-saherelm.common.lib.mq5 index f3c6c7ed..a49adaa3 100644 --- a/Libraries/x-saherelm.common.lib.mq5 +++ b/Libraries/x-saherelm.common.lib.mq5 @@ -4641,6 +4641,86 @@ bool CalculateTPSLByPoint( return result; } +// +bool CalculateTPSLBtPrice( + double &mSL, // Hold SL + double &mTP, // Hold TP + ENUM_POSITION_TYPE mType, // Position Type Long (Buy) / Short (Sell) + double mEntry, // Entry Price + double mR2R = 1 // Provided Risk To Reward Ratio +) +{ + // + bool result = false; + + // + bool isLong = IsLong(mType); + + // + // Set Default R2R ... + if (mR2R < 1) + { + mR2R = 1; + } + + // + if (mEntry <= 0 || + (mSL <= 0 && mTP <= 0)) + { + return result; + } + + // + double risk = 0; + double reward = 0; + + // + bool canCalculateBasedOnSL = mSL > 0; + bool canCalculateBasedOnTP = mTP > 0; + + // + if ( + !canCalculateBasedOnSL && + !canCalculateBasedOnTP) + { + return result; + } + + // + if (!canCalculateBasedOnSL && canCalculateBasedOnTP) + { + // + reward = MathAbs(mTP - mEntry); + risk = reward / mR2R; + } + else if (canCalculateBasedOnSL && !canCalculateBasedOnTP) + { + // + risk = MathAbs(mEntry - mSL); + reward = risk * mR2R; + } + + // + result = risk > 0 && reward > 0; + if (!result) + { + return result; + } + + // + mTP = isLong + ? mEntry + reward + : mEntry - reward; + + // + mSL = isLong + ? mEntry - risk + : mEntry + risk; + + // + return result; +} + // bool GetTick( string mSymbol, diff --git a/Libraries/x-saherelm.tools.mq5 b/Libraries/x-saherelm.tools.mq5 index 7a3c7123..0d54e90f 100644 --- a/Libraries/x-saherelm.tools.mq5 +++ b/Libraries/x-saherelm.tools.mq5 @@ -1082,16 +1082,16 @@ struct XPivot ; if (result) { - DrawArrow( - 0, - "PBar", - 0, - pBar.time, - pBar.low, - 233, - ANCHOR_TOP, - clrYellow // - ); + // DrawArrow( + // 0, + // "PBar", + // 0, + // pBar.time, + // pBar.low, + // 233, + // ANCHOR_TOP, + // clrYellow // + // ); } // diff --git a/Strategies/x-saherelm.xsrbr.strategy.mq5 b/Strategies/x-saherelm.xsrbr.strategy.mq5 new file mode 100644 index 00000000..09dc2a8e --- /dev/null +++ b/Strategies/x-saherelm.xsrbr.strategy.mq5 @@ -0,0 +1,799 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XSCXSRBRStrategy +// Description: provides all based classes for use ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +/// Imports ... +#include "../Classes/x-saherelm.xstrategy.class.mq5" + +// +string XSRBRStartegyToken = "XSRBR"; + +// +class XSCXSRBRStrategy : public XSCBaseStrategy +{ + // + // Public ... +public: + // + // Constructor(s) ... + void XSCXSRBRStrategy( + // + // Base ... + string _symbol, // Trading Symbol + ENUM_TIMEFRAMES _period, // Trading TimeFrame + double _volume, // Voluem + double _r2r, // Risk/Reward Ratio + int _slippage, // Trader Slippage + long _magicNumber, // Trader Magic Number + bool _allowLong = true, + bool _allowShort = true, + int _maxAllowedLongs = 0, + int _maxAllowedShorts = 0 // + ) : XSCBaseStrategy(_symbol, + _period, + _volume, + _r2r, + _slippage, + _magicNumber, + _allowLong, + _allowShort, + _maxAllowedLongs, + _maxAllowedShorts // + ) + { + // + mThreshold = 5; + mVerificationsStep = 21; + mConditionsValidationAge = 20; + + // + SetAlertPrefix(XSRBRStartegyToken); + } + + // + // Getter / Setter (s) ... + + // + double Treshold() + { + return mThreshold; + } + + // + void Treshold(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mThreshold = value; + } + + // + int VerificationsStep() + { + return mVerificationsStep; + } + + // + void VerificationsStep(int value) + { + // + if (value < 5) + { + value = 5; + } + + // + mVerificationsStep = value; + } + + // + int ConditionsValidationAge() + { + return mConditionsValidationAge; + } + + // + void ConditionsValidationAge(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mConditionsValidationAge = value; + } + + // + bool DarwSupportAndResistances() + { + return mDarwSupportAndResistances; + } + + // + void DarwSupportAndResistances(bool value) + { + // + mDarwSupportAndResistances = value; + + // + if (!value) + { + // + supportPivot.Remove(); + resistancePivot.Remove(); + } + } + + // + // Overrides ... + + // + // Customize Strategy Identifier ... + string GetTag() override + { + return XSRBRStartegyToken; + } + + // + // Check Conditions For Signal ... + bool HasSignal( + XSignal &signal // + ) override + { + // + bool result = false; + + // + // Try to Detect Trend ... + result = trendDetector.HasTrend(); + if (!result) + { + // + result = trendDetector.FindTrend( + mSymbol, + mPeriod // + ); + + // + if (!result) + { + // + trendDetector.Clean(); + return result; + } + } + + // + // Check Resistance Exists or not ... + // if Not, Try to Find One ... + if (!resistancePivot.isResistance) + { + // + result = resistancePivot.FindLastResistance( + mSymbol, + mPeriod // + ); + + // + if (!result) + { + // + resistancePivot.Clean(); + return result; + } + else + { + // + if (DarwSupportAndResistances()) + { + resistancePivot.Draw(ChartID()); + } + } + } + + // + // Check Support Exists or not ... + // if Not, try to Find One ... + if (!supportPivot.isSupport) + { + // + result = supportPivot.FindLastSupport( + mSymbol, + mPeriod // + ); + + // + if (!result) + { + // + supportPivot.Clean(); + return result; + } + else + { + // + if (DarwSupportAndResistances()) + { + supportPivot.Draw(ChartID()); + } + } + } + + // + // Retrieve Bar 1 ... + XOHCL cBar; + result = cBar.Init( + mSymbol, + mPeriod, + 1 // + ); + if (!result) + { + // + CheckConditionLife(); + return result; + } + + // + signal.Clean(); + + // + double sl = 0; + double tp = 0; + double risk = 0; + double entry = 0; + double reward = 0; + double r2r = R2R(); + ENUM_POSITION_TYPE type; + ENUM_X_ORDER_MODES mode = X_ORDER_MODE_MARKET; + + // + bool isSupportBreaked = supportPivot.IsBreaked(); + bool isSupportRejected = supportPivot.IsRejected(); + + // + bool isResistancetBreaked = resistancePivot.IsBreaked(); + bool isResistancetRejected = resistancePivot.IsRejected(); + + // + bool isBarBullishPattern = + // + cBar.IsBullish() && + cBar.HasStrongBody() && + (cBar.IsHammer() || + cBar.IsBullishEngulf()) + // + ; + + // + bool isBarBearishPattern = + // + cBar.IsBearish() && + cBar.HasStrongBody() && + (cBar.IsShootingStar() || + cBar.IsBearishEngulf()) + // + ; + + // + // Up Trend ... + if (trendDetector.isUpTrend) + { + // + // During Up Trend ... + // Supports Must Rejected ... + // Resistance Must Breaked ... + + // + // Check Trend Trading ... + // Check Based Support ... + bool hasSupportLong = + // + isSupportRejected && + isBarBullishPattern + // + ; + + // + // Check Trend Trading ... + // Check Based On Resistance ... + bool hasResistanceLong = + // + isResistancetBreaked && + isBarBullishPattern + // + ; + + // + // Check Trend Reversal Trading ... + // Check Based Support ... + bool hasSupportShort = + // + isSupportBreaked && + isBarBearishPattern + // + ; + + // + // Check Trend Reversal Trading ... + // Check Based On Resistance ... + bool hasResistanceShort = + // + isResistancetRejected && + isBarBearishPattern + // + ; + + // + // Check Trend Trading ... + bool hasLong = + // + hasSupportLong || + hasResistanceLong + // + ; + + // + // Check Trend Reversal Trading ... + bool hasShort = + // + hasSupportShort || + hasResistanceShort + // + ; + + // + // Filling Signal ... + if (hasLong) + { + // + type = POSITION_TYPE_BUY; + entry = GetEntry( + _Symbol, + type // + ); + + // + if (hasSupportLong) + { + // + sl = supportPivot.price; + if (supportPivot._threshold > 0) + { + // + double threshold = GetPoints(_Symbol) * supportPivot._threshold; + sl -= threshold; + } + + // + CalculateTPSLBtPrice( + sl, + tp, + type, + entry, + r2r // + ); + } + else if (hasResistanceLong) + { + // + sl = resistancePivot.price; + if (resistancePivot._threshold > 0) + { + // + double threshold = GetPoints(_Symbol) * resistancePivot._threshold; + sl -= threshold; + } + + // + CalculateTPSLBtPrice( + sl, + tp, + type, + entry, + r2r // + ); + } + + // + result = signal.Prepare( + _Symbol, + "XSUPRES", + _Period, + type, + mode, + entry, + mVolume, + sl, + tp // + ); + } + else if (hasShort) + { + // + type = POSITION_TYPE_SELL; + entry = GetEntry( + _Symbol, + type // + ); + + // + if (hasSupportShort) + { + // + sl = supportPivot.price; + if (supportPivot._threshold > 0) + { + // + double threshold = GetPoints(_Symbol) * supportPivot._threshold; + sl += threshold; + } + + // + CalculateTPSLBtPrice( + sl, + tp, + type, + entry, + r2r // + ); + } + else if (hasResistanceShort) + { + // + sl = resistancePivot.price; + if (resistancePivot._threshold > 0) + { + // + double threshold = GetPoints(_Symbol) * resistancePivot._threshold; + sl += threshold; + } + + // + CalculateTPSLBtPrice( + sl, + tp, + type, + entry, + r2r // + ); + } + + // + result = signal.Prepare( + _Symbol, + "XSUPRES", + _Period, + type, + mode, + entry, + mVolume, + sl, + tp // + ); + } + else + { + result = false; + } + } + // + // Down Trend ... + else if (trendDetector.isDownTrend) + { + // + // During Down Trend ... + // Supports Must Breaked ... + // Resistance Must Rejected ... + + // + // Check Trend Reversal Trading ... + // Check Based Support ... + bool hasSupportLong = + // + isSupportRejected && + isBarBullishPattern + // + ; + + // + // Check Trend Reversal Trading ... + // Check Based On Resistance ... + bool hasResistanceLong = + // + isResistancetBreaked && + isBarBullishPattern + // + ; + + // + // Check Trend Trading ... + // Check Based Support ... + bool hasSupportShort = + // + isSupportBreaked && + isBarBearishPattern + // + ; + + // + // Check Trend Trading ... + // Check Based On Resistance ... + bool hasResistanceShort = + // + isResistancetRejected && + isBarBearishPattern + // + ; + + // + // Check Trend Reversal Trading ... + bool hasLong = + // + hasSupportLong || + hasResistanceLong + // + ; + + // + // Check Trend Trading ... + bool hasShort = + // + hasSupportShort || + hasResistanceShort + // + ; + + // + // Filling Signal ... + if (hasLong) + { + // + type = POSITION_TYPE_BUY; + entry = GetEntry( + _Symbol, + type // + ); + + // + if (hasSupportLong) + { + // + sl = supportPivot.price; + if (supportPivot._threshold > 0) + { + // + double threshold = GetPoints(_Symbol) * supportPivot._threshold; + sl -= threshold; + } + + // + CalculateTPSLBtPrice( + sl, + tp, + type, + entry, + r2r // + ); + } + else if (hasResistanceLong) + { + // + sl = resistancePivot.price; + if (resistancePivot._threshold > 0) + { + // + double threshold = GetPoints(_Symbol) * resistancePivot._threshold; + sl -= threshold; + } + + // + CalculateTPSLBtPrice( + sl, + tp, + type, + entry, + r2r // + ); + } + + // + result = signal.Prepare( + _Symbol, + "XSUPRES", + _Period, + type, + mode, + entry, + mVolume, + sl, + tp // + ); + } + else if (hasShort) + { + // + type = POSITION_TYPE_SELL; + entry = GetEntry( + _Symbol, + type // + ); + + // + if (hasSupportShort) + { + // + sl = supportPivot.price; + if (supportPivot._threshold > 0) + { + // + double threshold = GetPoints(_Symbol) * supportPivot._threshold; + sl += threshold; + } + + // + CalculateTPSLBtPrice( + sl, + tp, + type, + entry, + r2r // + ); + } + else if (hasResistanceShort) + { + // + sl = resistancePivot.price; + if (resistancePivot._threshold > 0) + { + // + double threshold = GetPoints(_Symbol) * resistancePivot._threshold; + sl += threshold; + } + + // + CalculateTPSLBtPrice( + sl, + tp, + type, + entry, + r2r // + ); + } + + // + result = signal.Prepare( + _Symbol, + "XSUPRES", + _Period, + type, + mode, + entry, + mVolume, + sl, + tp // + ); + } + else + { + result = false; + } + } + + // + if (!result) + { + CheckConditionLife(); + } + + // + return result; + } + + // + // Notify Signal Execution ... + void OnSignalExecuted(XSignal &signal) override + { + ResetConditions(); + } + + // + // Protected ... +protected: + // + // Pivots Detecting ... + double mThreshold; // Pivots Edge's Threshold ... + int mVerificationsStep; // Pivots Verification Steps ... + int mConditionsValidationAge; // How Many Bars a Support or Resistance is Valid ... + + // + XPivot supportPivot; + XPivot resistancePivot; + + // + bool mDarwSupportAndResistances; // Draw Last Found Support and Resistance + + // + // Private ... +private: + // + // Check Conditions Time Life ... + void CheckConditionLife() + { + // + datetime cTime = TimeCurrent(); + datetime lTime = + // + supportPivot.time < resistancePivot.time + ? supportPivot.time + : resistancePivot.time + // + ; + + // + bool canReset = + // + ( + // // + // supportPivot.IsBreaked() + // // + // || + // // + // resistancePivot.IsBreaked() + // // + // || + // + (((int)cTime - (int)lTime) / PeriodSeconds(mPeriod)) > mConditionsValidationAge + // + ) + // + ; + if (canReset) + { + ResetConditions(); + } + } + + // + // Reset Conditions ... + void ResetConditions() + { + // + trendDetector.Clean(); + + // + supportPivot.Remove(); + supportPivot.Clean(); + + // + resistancePivot.Remove(); + resistancePivot.Clean(); + } +}; + +// \ No newline at end of file