From f65fdcd14aa4363283c085c5d4df0cd7cd752fea Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Thu, 6 Jun 2024 23:05:09 +0330 Subject: [PATCH] last ... --- Classes/x-saherelm.x121.xea.class.mq5 | 35 +- Experts/x-be-test.mq5 | 351 ++++++++++ Experts/x-sample.ea.mq5 | 619 ++++++++++++++++++ Experts/x-test.x121ea.mq5 | 97 +-- Libraries/x-saherelm.common.lib.mq5 | 103 ++- Signallers/x-saherelm.x92.signaller.class.mq5 | 367 +++++++++++ 6 files changed, 1522 insertions(+), 50 deletions(-) create mode 100644 Experts/x-be-test.mq5 create mode 100644 Experts/x-sample.ea.mq5 create mode 100644 Signallers/x-saherelm.x92.signaller.class.mq5 diff --git a/Classes/x-saherelm.x121.xea.class.mq5 b/Classes/x-saherelm.x121.xea.class.mq5 index a9ef8e5b..d5705567 100644 --- a/Classes/x-saherelm.x121.xea.class.mq5 +++ b/Classes/x-saherelm.x121.xea.class.mq5 @@ -230,6 +230,12 @@ public: // X121ProviderDescriptor iDescriptor = mDescriptors[i]; + // + if (iDescriptor.provider.CanIgnoreProcess()) + { + continue; + } + // int iSignalsCount = iDescriptor.HasSignal(); if (IsValidSize(iSignalsCount)) @@ -524,6 +530,10 @@ public: // const bool result = false; + // + // Here we Implement Account Protector ... + HandleAccountProtect(); + // // Check Descriptor ... int descriptorsCount = CountDescriptors(); @@ -568,11 +578,13 @@ public: // // Check Profits Enough for Hedge or not ... double profit = SpecifiedCalculatePositionsProfit(positions); - bool isReadyForHedge = SpecifiedIsPositionsReadyForHedge( - positions, - mDescriptors[i].signallers[j].minRequiredProfitPerTrade, - mDescriptors[i].signallers[j].minRequiredProfitPerTradeVolumeFactor // - ); + bool isReadyForHedge = + positionsCount > 1 && + SpecifiedIsPositionsReadyForHedge( + positions, + mDescriptors[i].signallers[j].minRequiredProfitPerTrade, + mDescriptors[i].signallers[j].minRequiredProfitPerTradeVolumeFactor // + ); if (isReadyForHedge) { // @@ -637,6 +649,19 @@ public: return result; } + // + void HandleAccountProtect() { + // + XPosition positions[]; + int positionsCount = mTrader.GetPositions(positions); + if (!IsValidSize(positionsCount)) { + return; + } + + // + + } + // // Tools ... diff --git a/Experts/x-be-test.mq5 b/Experts/x-be-test.mq5 new file mode 100644 index 00000000..29b09a9f --- /dev/null +++ b/Experts/x-be-test.mq5 @@ -0,0 +1,351 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XSAMPLE MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XSAMPLE +// Description: an Exper Advisor which used RSI and MA +// 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 XSAMPLE" +#property strict + +// +#include "../Libraries/x-saherelm.draw.lib.mq5" +#include "../Classes/x-saherelm.xalert.class.mq5" +#include "../Classes/x-saherelm.xtrade.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +#define ShortName "XSAMPLE" + +// +int swingLifeTime = 20; +ENUM_TIMEFRAMES destPEriod = PERIOD_H4; + +// +XOHCL hSwing0; +XOHCL hSwing1; + +// +XOHCL lSwing0; +XOHCL lSwing1; + +// +XSCAlert *mAlert; +XSCTrade *mTrader; + +// +XBarTracker xBarTracker; +XMarketCycle xDestCycle; + +// +// Initialization ... +int OnInit() +{ + // + drawPrefix = ShortName; + + // + if (!InitialEA()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // 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 ... +} + +// +// On Tick Handler ... +void OnTick() +{ + // + if (!xBarTracker.IsNewBar()) + { + return; + } + + // + xDestCycle.Update(0); + + // + Analyze(); +} + +// +// + +// +bool InitialEA() +{ + // + bool result = false; + + // + mAlert = new XSCAlert(); + mAlert.SetLogAlerts(true); + mAlert.SetPrefix(ShortName); + mAlert.SetEnableAlerts(true); + mAlert.SetPushAlerts(false); + mAlert.SetMailAlerts(false); + mAlert.SetTerminalAlerts(false); + + // + mTrader = new XSCTrade( + 10, + 78692110, + 0, + 0, + 0 // + ); + + // + result = xBarTracker.Init( + _Symbol, + _Period // + ); + if (!result) + { + return result; + } + + // + result = xDestCycle.Init( + _Symbol, + _Period, + X_MARKET_CYCLE_MEDIUM, + X_PERIOD_MANUALLY, + destPEriod, + "DEST" // + ); + if (!result) + { + return result; + } + + // + result = true; + + // + return result; +} + +// +void Analyze() +{ + // + XOHCL cBar; + cBar.Init( + _Symbol, + _Period, + 1 // + ); + + // + FindSwings(cBar); +} + +// +void FindSwings(XOHCL &bar) +{ + // + // High Swings ... + + // + if (!hSwing0.IsValid()) + { + // + int index = bar.FindSwing(X_SWING_HIGH, 10); + + // + if (index >= 0) + { + // + bool isInited = hSwing0.Init( + bar.symbol, + bar.period, + index // + ); + } + } + + // + if (hSwing0.IsValid() && !hSwing1.IsValid()) + { + // + int index = bar.FindNextSwing(X_SWING_HIGH, hSwing0.Index(), 10); + + // + if (index >= 0) + { + // + index += hSwing0.Index(); + + // + bool isInited = hSwing1.Init( + bar.symbol, + bar.period, + index // + ); + } + } + + // + // Draw Swings ... + if (hSwing0.IsValid() && hSwing1.IsValid()) + { + // + DrawSwing( + hSwing1, + X_PRICE_HIGH, + hSwing0, + X_PRICE_HIGH, + clrAqua, + "HH" // + ); + } + + // + // Low Swings ... + + // + if (!lSwing0.IsValid()) + { + // + int index = bar.FindSwing(X_SWING_LOW, 10); + + // + if (index >= 0) + { + // + bool isInited = lSwing0.Init( + bar.symbol, + bar.period, + index // + ); + } + } + + // + if (lSwing0.IsValid() && !lSwing1.IsValid()) + { + // + int index = bar.FindNextSwing(X_SWING_LOW, lSwing0.Index(), 10); + + // + if (index >= 0) + { + // + index += lSwing0.Index(); + + // + bool isInited = lSwing1.Init( + bar.symbol, + bar.period, + index // + ); + } + } + + // + // Draw Swings ... + if (lSwing0.IsValid() && lSwing1.IsValid()) + { + // + DrawSwing( + lSwing1, + X_PRICE_LOW, + lSwing0, + X_PRICE_LOW, + clrMagenta, + "LL" // + ); + } +} + +// +// Draw Line ... + +// +void DrawSwing( + XOHCL &bar1, // From (Old) ... + ENUM_X_PRICE price1, // How to Select Bar 1 Price ... + XOHCL &bar0, // To (New) ... + ENUM_X_PRICE price0, // How to Select Bar 0 Price ... + color clr, + string prefix, + bool forceRemove = false // +) +{ + // + long chartID = ChartID(); + + // + double b1Price = bar1.GetPrice(price1); + double b0Price = bar0.GetPrice(price0); + + // + string lName = prefix + "Swing_" + + ToString(b1Price) + "_TO_" + + ToString(b0Price); + + // + if (IsDrawExists(prefix) && forceRemove) + { + RemoveDraws(prefix); + } + + // + // if (IsDrawExists(lName)) + // { + // return; + // } + + // + DrawTrendLine( + chartID, + lName, + 0, + bar1.time, + b1Price, + bar0.time, + b0Price, + clr, + STYLE_SOLID, + 2, + false, + false, + true // + ); +} diff --git a/Experts/x-sample.ea.mq5 b/Experts/x-sample.ea.mq5 new file mode 100644 index 00000000..037efcc0 --- /dev/null +++ b/Experts/x-sample.ea.mq5 @@ -0,0 +1,619 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XSAMPLE MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XSAMPLE +// Description: an Exper Advisor which used RSI and MA +// 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 XSAMPLE" +#property strict + +// +#include "../Libraries/x-saherelm.draw.lib.mq5" +#include "../Classes/x-saherelm.xalert.class.mq5" +#include "../Classes/x-saherelm.xtrade.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +#define ShortName "XSAMPLE" + +// +int pivotLifeTime = 20; +int pivotBreakoutsLifeTime = 10; +ENUM_TIMEFRAMES destPEriod = PERIOD_H4; + +// +int xAge = 0; + +// +double lastHH = 0; +double lastUpper = 0; +double lastDestHH = 0; + +// +double lastLL = 0; +double lastLower = 0; +double lastDestLL = 0; + +// +datetime lastTime = NULL; +datetime lastDestTime = NULL; + +// +XSCAlert *mAlert; +XSCTrade *mTrader; + +// +XBarTracker xBarTracker; +XMarketCycle xDestCycle; + +// +// Initialization ... +int OnInit() +{ + // + drawPrefix = ShortName; + + // + if (!InitialEA()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // 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 ... +} + +// +// On Tick Handler ... +void OnTick() +{ + // + if (!xBarTracker.IsNewBar()) + { + return; + } + + // + xDestCycle.Update(0); + + // + Analyze(); + + // + ManxAge(); +} + +// +// + +// +bool InitialEA() +{ + // + bool result = false; + + // + mAlert = new XSCAlert(); + mAlert.SetLogAlerts(true); + mAlert.SetPrefix(ShortName); + mAlert.SetEnableAlerts(true); + mAlert.SetPushAlerts(false); + mAlert.SetMailAlerts(false); + mAlert.SetTerminalAlerts(false); + + // + mTrader = new XSCTrade( + 10, + 78692110, + 0, + 0, + 0 // + ); + + // + result = xBarTracker.Init( + _Symbol, + _Period // + ); + if (!result) + { + return result; + } + + // + result = xDestCycle.Init( + _Symbol, + _Period, + X_MARKET_CYCLE_MEDIUM, + X_PERIOD_MANUALLY, + destPEriod, + "DEST" // + ); + if (!result) + { + return result; + } + + // + result = true; + + // + return result; +} + +// +void Analyze() +{ + // + XOHCL cBar; + cBar.Init( + _Symbol, + _Period, + 1 // + ); + + // + if (IsLookingForBoundary()) + { + FindBoundary(); + return; + } + + // + double longSLPrice = 0; + double shortSLPrice = 0; + + // // + // xAge = 0; + // if (IsValid(lastTime)) + // { + // // + // xAge = iBarShift( + // _Symbol, + // _Period, + // lastTime // + // ); + // } + + // // + // if (xAge > pivotBreakoutsLifeTime) + // { + // // + // lastHH = cBar.FindHighest( + // xAge - 1, + // MODE_HIGH // + // ); + + // // + // lastLL = cBar.FindLowest( + // xAge - 1, + // MODE_LOW // + // ); + + // // + // DrawPivot(lastLL, clrAqua, "PVB_L_", true); + // DrawPivot(lastHH, clrMagenta, "PVB_H_", true); + // } + + // + // Detect Breakouts for Long ... + // - Upper Must Breaked as Resistance ... + // - Lower Must Rejects as Support ... + + // // + // bool isSupRejected = cBar.IsSupportRejected(lastLower); + // bool isResBreaked = cBar.IsResistanceBreaked(lastUpper); + // bool isLastLLRejectedAsSupport = cBar.IsSupportRejected(lastDestLL); + // bool isLastHHBreakedAsResistance = cBar.IsResistanceBreaked(lastDestHH); + + // // + // bool hasLong = + // // + // cBar.HasStrongBody() && + // ( + // // + // (isLastLLRejectedAsSupport + // // + // || + // // + // isLastHHBreakedAsResistance) + // // + // || + // // + // (cBar.GetMid() > MathMax(lastLower, lastUpper) && + // (isResBreaked + // // + // || + // // + // isSupRejected)) + // // + // ) + // // + // ; + + // // + // if (hasLong) + // { + // // + // longSLPrice = isResBreaked + // ? lastUpper + // : isLastHHBreakedAsResistance + // ? lastDestHH + // : isSupRejected + // ? lastLower + // : lastDestLL; + // } + + // + // Detect Breakouts for Long ... + // - Upper Must Rejects as Resistance ... + // - Lower Must Breaked as Support ... + + // // + // bool isResRejected = cBar.IsResistanceRejected(lastUpper); + // bool isSupBreaked = cBar.IsSupportBreaked(lastLower); + // bool isLastLLBreadedAsSupport = cBar.IsSupportBreaked(lastDestLL); + // bool isLastHHRejectedAsResistance = cBar.IsResistanceRejected(lastDestHH); + + // // + // bool hasShort = + // // + // cBar.HasStrongBody() && + // ( + // // + // (isLastLLBreadedAsSupport + // // + // || + // // + // isLastHHRejectedAsResistance) + // // + // || + // // + // (cBar.GetMid() < MathMin(lastLower, lastUpper) && + // (isSupBreaked + // // + // || + // // + // isResRejected)) + // // + // ) + // // + // ; + + // // + // if (hasShort) + // { + // // + // shortSLPrice = isSupBreaked + // ? lastLower + // : isLastLLBreadedAsSupport + // ? lastDestLL + // : isResRejected + // ? lastUpper + // : lastDestHH; + // } + + // + // + bool hasLong = false; + bool hasShort = false; + + // + bool hasSignal = hasLong || hasShort; + if (hasSignal) + { + // + double slPrice = + hasLong + ? longSLPrice + : shortSLPrice; + // double slPrice = + // hasLong + // ? shortSLPrice + // : longSLPrice; + + // + ENUM_POSITION_TYPE mType = + hasLong + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL + // + ; + // ENUM_POSITION_TYPE mType = + // hasLong + // ? POSITION_TYPE_BUY + // : POSITION_TYPE_SELL + // // + // ; + + // + double mEntry = GetEntry( + _Symbol, + mType // + ); + + // + double priceToRisk = PointToPrice(30, _Symbol); + double priceToReward = PointToPrice(30, _Symbol); + + // + double mSL = 0; + double mTP = 0; + CalculateTPSL( + mSL, + mTP, + mType, + mEntry, + 1, + slPrice, + 0, + priceToRisk, + priceToReward // + ); + + // + // Ignore Zero TP SL ... + if (mTP > 0 && mSL > 0) + { + // + XSignal signal; + bool isPrepared = signal.Prepare( + _Symbol, + "X92", + _Period, + mType, + X_ORDER_MODE_MARKET, + mEntry, + 0.01, + mSL, + mTP // + ); + + // + if (isPrepared) + { + // + ENUM_X_SIGNAL_EXECUTION_RESULT state; + bool isExecuted = mTrader.ExecuteSignal( + signal, + state // + ); + } + } + } + + // + bool resetLast = + xAge > pivotLifeTime || hasSignal; + + // + if (resetLast) + { + // + lastUpper = 0; + lastLower = 0; + + // + RemoveDraws(); + } +} + +// +void ManxAge() +{ + // + return; + double profit = mTrader.Profit(); + if (profit > 50 || profit < -100) + { + // + string comment = "EQM Hedge: " + ToString(profit); + + // + int numberOfClosed = mTrader.Close(comment); + if (numberOfClosed > 0) + { + mAlert.Alert(comment); + } + } +} + +// +bool IsLookingForBoundary() +{ + // + bool result = lastUpper == 0 && lastLower == 0; + return result; +} + +// +void FindBoundary() +{ + // + int zIndex = 0; + int cIndex = 1; + int pIndex = 2; + int ppIndex = 3; + + // + // Detect Inside Bar ... + XOHCL cBar; + cBar.Init( + _Symbol, + _Period, + 1 // + ); + + // + XOHCL cDestBar = xDestCycle.GetBar(1); + + // + if (cDestBar.time != lastDestTime) { + // + lastDestLL = cDestBar.low; + lastDestHH = cDestBar.high; + + // + lastDestTime = cDestBar.time; + + // + DrawPivot(lastUpper, clrOrangeRed, "Pvt_"); + DrawPivot(lastLower, clrLimeGreen, "Pvt_"); + } + + // + // if (cDestBar.IsInsideBar()) + // { + // // + // lastUpper = cDestBar.high; + // lastLower = cDestBar.low; + + // // + // lastTime = TimeCurrent(); + + // // + // DrawPivot(lastUpper, clrOrangeRed, "Pvt_"); + // DrawPivot(lastLower, clrLimeGreen, "Pvt_"); + // } + + // // + // if (lastUpper != cDestBar.high && lastLower != cDestBar.low) + // { + // // + // lastDestHH = cDestBar.high; + // lastDestLL = cDestBar.low; + + // // + // DrawPivot(lastDestLL, clrYellow, "LDST_LL_", true); + // DrawPivot(lastDestHH, clrYellow, "LDST_HH_", true); + + // // + // lastDestTime = TimeCurrent(); + // } + + // + DrawFibo(); +} + +// +void DrawPivot( + double price, + color clr, + string prefix, + bool forceRemove = false // +) +{ + // + long chartID = ChartID(); + datetime time1 = iTime( + _Symbol, + _Period, + 2 // + ); + datetime time = iTime( + _Symbol, + _Period, + 0 // + ); + + // + string pPrefix = prefix + "P_" + + ToString(price); + + // + if (IsDrawExists(prefix) && forceRemove) + { + RemoveDraws(prefix); + } + + // + if (IsDrawExists(pPrefix)) + { + return; + } + + // + DrawTrendLine( + chartID, + pPrefix, + 0, + time1, + price, + time, + price, + clr, + STYLE_SOLID, + 2, + false, + false, + true // + ); +} + +// +void DrawFibo() +{ + // + if (!IsValid(lastDestTime) || lastDestHH == 0 || lastDestLL == 0) + { + return; + } + + // + string name = "LDST_FIb"; + + // + datetime time1 = TimeCurrent(); + datetime time0 = lastDestTime; + + // + RemoveDraw(name); + + // + DrawFibonacci( + ChartID(), + name, + 0, + time0, + lastDestHH, + time1, + lastDestLL, + clrAquamarine, + STYLE_DOT // + ); +} + +// \ No newline at end of file diff --git a/Experts/x-test.x121ea.mq5 b/Experts/x-test.x121ea.mq5 index 6f5f59f6..197b23cb 100644 --- a/Experts/x-test.x121ea.mq5 +++ b/Experts/x-test.x121ea.mq5 @@ -24,6 +24,7 @@ // #include "../Classes/x-saherelm.x121.xea.class.mq5" +#include "../Signallers/x-saherelm.x92.signaller.class.mq5" #include "../Signallers/x-saherelm.x110.signaller.class.mq5" #include "../Signallers/x-saherelm.x121.signaller.class.mq5" #include "../Signallers/x-saherelm.x786.signaller.class.mq5" @@ -204,42 +205,6 @@ bool InitialEA() // mX121EA.SetAlertPrefix(ShortName); - // - // Prepare Signallers ... - - // - // X786 Signaller ... - X786Signaller *x786Signaller = new X786Signaller(); - x786Signaller.Default(); - x786Signaller.allowLong = x121EAAllowLong; - x786Signaller.allowShort = x121EAAllowShort; - x786Signaller.maxAllowedOpenPositionAge = 0; - x786Signaller.minRequiredProfitPerTrade = 0; - x786Signaller.openNextPositionOnProfit = false; - x786Signaller.delayBetweenTwoSameTypeSignals = 6; - - // - // X121 Signaller ... - X121Signaller *x121Signaller = new X121Signaller(); - x121Signaller.Default(); - x121Signaller.allowLong = x121EAAllowLong; - x121Signaller.allowShort = x121EAAllowShort; - x121Signaller.maxAllowedOpenPositionAge = 0; - x121Signaller.minRequiredProfitPerTrade = 0; - x121Signaller.openNextPositionOnProfit = false; - x121Signaller.delayBetweenTwoSameTypeSignals = 6; - - // - // X110 Signaller ... - X110Signaller *x110Signaller = new X110Signaller(); - x110Signaller.Default(); - x110Signaller.allowLong = x121EAAllowLong; - x110Signaller.allowShort = x121EAAllowShort; - x110Signaller.maxAllowedOpenPositionAge = 0; - x110Signaller.minRequiredProfitPerTrade = 0; - x110Signaller.openNextPositionOnProfit = false; - x110Signaller.delayBetweenTwoSameTypeSignals = 6; - // // Prepare Providers and Add them into mX121EA class ... for (int i = 0; i < symbolsCount; i++) @@ -260,16 +225,68 @@ bool InitialEA() // // Attach Signallers ... + // + // X786 Signaller ... + X786Signaller *x786Signaller = new X786Signaller(); + x786Signaller.Default(); + x786Signaller.allowLong = x121EAAllowLong; + x786Signaller.allowShort = x121EAAllowShort; + x786Signaller.maxAllowedOpenPositionAge = 0; + x786Signaller.minRequiredProfitPerTrade = 1; + x786Signaller.openNextPositionOnProfit = true; + x786Signaller.delayBetweenTwoSameTypeSignals = 6; + + // + // X121 Signaller ... + X121Signaller *x121Signaller = new X121Signaller(); + x121Signaller.Default(); + x121Signaller.allowLong = x121EAAllowLong; + x121Signaller.allowShort = x121EAAllowShort; + x121Signaller.maxAllowedOpenPositionAge = 0; + x121Signaller.minRequiredProfitPerTrade = 1; + x121Signaller.openNextPositionOnProfit = true; + x121Signaller.delayBetweenTwoSameTypeSignals = 6; + + // + // X110 Signaller ... + X110Signaller *x110Signaller = new X110Signaller(); + x110Signaller.Default(); + x110Signaller.allowLong = x121EAAllowLong; + x110Signaller.allowShort = x121EAAllowShort; + x110Signaller.maxAllowedOpenPositionAge = 0; + x110Signaller.minRequiredProfitPerTrade = 1; + x110Signaller.openNextPositionOnProfit = true; + x110Signaller.delayBetweenTwoSameTypeSignals = 6; + + // + // X92 Signaller ... + X92Signaller *x92Signaller = new X92Signaller(); + x92Signaller.Default(); + x92Signaller.SetSymbol(iSymbol); + x92Signaller.SetPeriod(iPeriod); + x92Signaller.allowLong = x121EAAllowLong; + x92Signaller.allowShort = x121EAAllowShort; + x92Signaller.maxAllowedOpenPositionAge = 0; + x92Signaller.minRequiredProfitPerTrade = 1; + x92Signaller.openNextPositionOnProfit = true; + x92Signaller.delayBetweenTwoSameTypeSignals = 6; + // Clean(iDescriptor.signallers); // - ArrayResize(iDescriptor.signallers, 3); + int idx = 0; + ArrayResize(iDescriptor.signallers, 4); // - iDescriptor.signallers[0] = x786Signaller; - iDescriptor.signallers[1] = x121Signaller; - iDescriptor.signallers[2] = x110Signaller; + iDescriptor.signallers[idx] = x786Signaller; + idx++; + iDescriptor.signallers[idx] = x121Signaller; + idx++; + iDescriptor.signallers[idx] = x110Signaller; + idx++; + iDescriptor.signallers[idx] = x92Signaller; + idx++; // // Set Inputs to Default ... diff --git a/Libraries/x-saherelm.common.lib.mq5 b/Libraries/x-saherelm.common.lib.mq5 index d73c240d..a18268e1 100644 --- a/Libraries/x-saherelm.common.lib.mq5 +++ b/Libraries/x-saherelm.common.lib.mq5 @@ -2481,6 +2481,85 @@ struct XBarTracker symbol = NormalizeSymbol(NULL); period = NormalizePeriod(NULL); } + + // + bool GetBar( + XOHCL &bar, + int index = 0 // + ) + { + // + bool result = false; + + // + result = bar.Init( + symbol, + period, + index // + ); + + // + return result; + } + + // + bool GetBar( + XOHCL &bar, + datetime time = NULL // + ) + { + // + bool result = false; + + // + NormalizeTime(time); + + // + int barIndex = iBarShift( + symbol, + period, + time, + false // + ); + + // + result = barIndex >= 0; + if (!result) + { + return result; + } + + // + result = bar.Init( + symbol, + period, + barIndex // + ); + + // + return result; + } + + // + int Index(datetime time = NULL) + { + // + int result = 0; + + // + NormalizeTime(time); + + // + result = iBarShift( + symbol, + period, + time, + false // + ); + + // + return result; + } }; // @@ -3523,6 +3602,10 @@ bool IsValid(datetime value) // return result; } +bool IsSpecifiedValid(datetime value) +{ + return IsValid(value); +} // // Validate a Period Param ... @@ -4341,7 +4424,9 @@ void CalculateTPSL( double mEntry, // Entry Price double mR2R = 1, // Provided Risk To Reward Ratio double slPrice = 0, // Provided SL Price - double tpPrice = 0 // Provided TP Price + double tpPrice = 0, // Provided TP Price + double priceToRisk = 0, // If Entry equal to Provided SL Price Risk Point + double priceToReward = 0 // If Entry equal to Provided TP Price Reward Point ) { // @@ -4378,26 +4463,34 @@ void CalculateTPSL( // bool canCalculateBasedOnSL = slPrice > 0 && (isLong - ? slPrice < mEntry - : slPrice > mEntry); + ? slPrice <= mEntry + : slPrice >= mEntry); // bool canCalculateBasedOnTP = tpPrice > 0 && (isLong - ? tpPrice > mEntry - : tpPrice < mEntry); + ? tpPrice >= mEntry + : tpPrice <= mEntry); // if (canCalculateBasedOnSL && !canCalculateBasedOnTP) { // risk = MathAbs(mEntry - slPrice); + if (risk == 0) + { + risk = priceToRisk; + } reward = risk * mR2R; } else if (!canCalculateBasedOnSL && canCalculateBasedOnTP) { // reward = MathAbs(mEntry - tpPrice); + if (reward == 0) + { + reward = priceToReward; + } risk = reward / mR2R; } else if (!canCalculateBasedOnSL && !canCalculateBasedOnTP) diff --git a/Signallers/x-saherelm.x92.signaller.class.mq5 b/Signallers/x-saherelm.x92.signaller.class.mq5 new file mode 100644 index 00000000..3288314b --- /dev/null +++ b/Signallers/x-saherelm.x92.signaller.class.mq5 @@ -0,0 +1,367 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: X92Signaller +// Description: Signalling using X121 rules ... +// +// +// 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.xtrade.lib.mq5" +#include "../Classes/x-saherelm.x121.xmcycle.class.mq5" + +// +// Definitions ... + +// +// Class ... +class X92Signaller : public XSignallerDescriptor +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructor(s) ... + void X92Signaller() + { + // + name = X92; + Default(); + } + + // + // Deconstructor ... + void ~X92Signaller() {} + + // + void SetSymbol(string value) + { + this.symbol = value; + } + + // + void SetPeriod(ENUM_TIMEFRAMES value) + { + this.period = value; + } + + // + // Override(s) ... + + // + bool HasLongConditions( + const X121MCycleConditions &conditions, // Market Conditions + double &sl, // Hold SL ... + double &tp // Hold TP ... + ) override + { + // + bool result = false; + + // + sl = 0; + tp = 0; + + // + result = allowLong; + if (!result) + { + return result; + } + + // + if (IsLookingForBoundary()) + { + // + FindBoundary(conditions); + + // + return result; + } + + // + bool isRejected = + // + (conditions.bars[1].low > lastLower && + conditions.bars[2].low > lastLower && + conditions.bars[3].low > lastLower && + conditions.bars[4].low > lastLower && + conditions.bars[5].low > lastLower) + // + || + // + conditions.bars[1].IsSupportRejected(lastLower) + // + ; + bool isBreaked = + // + (conditions.bars[1].low > lastUpper && + conditions.bars[2].low > lastUpper && + conditions.bars[3].low > lastUpper && + conditions.bars[4].low > lastUpper && + conditions.bars[5].low > lastUpper) + // + || + // + conditions.bars[1].IsResistanceBreaked(lastUpper) + // + ; + + // + result = + // + isBreaked + // + || + // + isRejected + // + ; + + // + if (result) + { + // + sl = isBreaked + ? lastUpper + : lastLower; + } + + // + HandleResetBundary(); + + // + return result; + } + + // + bool HasShortConditions( + const X121MCycleConditions &conditions, // Market Conditions + double &sl, // Hold SL ... + double &tp // Hold TP ... + ) override + { + // + bool result = false; + + // + sl = 0; + tp = 0; + + // + result = allowLong; + if (!result) + { + return result; + } + + // + if (IsLookingForBoundary()) + { + // + FindBoundary(conditions); + + // + return result; + } + + // + bool isRejected = + // + (conditions.bars[1].high < lastUpper && + conditions.bars[2].high < lastUpper && + conditions.bars[3].high < lastUpper && + conditions.bars[4].high < lastUpper && + conditions.bars[5].high < lastUpper) + // + || + // + conditions.bars[1].IsResistanceRejected(lastUpper) + // + ; + bool isBreaked = + // + (conditions.bars[1].high < lastLower && + conditions.bars[2].high < lastLower && + conditions.bars[3].high < lastLower && + conditions.bars[4].high < lastLower && + conditions.bars[5].high < lastLower) + // + || + // + conditions.bars[1].IsSupportBreaked(lastLower) + // + ; + + // + result = + // + isBreaked + // + || + // + isRejected + // + ; + + // + if (result) + { + // + sl = isBreaked + ? lastLower + : lastUpper; + } + + // + HandleResetBundary(); + + // + return result; + } + + // + // Protected ... +protected: + // + // Props ... + double lastUpper; + double lastLower; + datetime lastTime; + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + bool IsLookingForBoundary() + { + // + bool result = lastUpper == 0 && lastLower == 0; + return result; + } + + // + void FindBoundary(const X121MCycleConditions &conditions) + { + // + int zIndex = 0; + int cIndex = 1; + int pIndex = 2; + int ppIndex = 3; + + // + // Detect Inside Bar ... + if (conditions.bars[cIndex].IsInsideBar()) + { + // + lastUpper = conditions.bars[pIndex].high; + lastLower = conditions.bars[pIndex].low; + + // + lastTime = TimeCurrent(); + + // + DrawPivot(lastUpper, clrOrangeRed); + DrawPivot(lastLower, clrLimeGreen); + } + } + + // + void HandleResetBundary() + { + // + if (!IsSpecifiedValid(lastTime)) + { + return; + } + + // + int age = iBarShift( + symbol, + period, + lastTime, + false // + ); + + // + if (age < 7) + { + return; + } + + // + RemoveDraws("X92_"); + + // + lastLower = 0; + lastUpper = 0; + lastTime = NULL; + } + + // + void DrawPivot( + double price, + color clr // + ) + { + // + long chartID = ChartID(); + datetime time1 = iTime( + symbol, + period, + 2 // + ); + datetime time = iTime( + symbol, + period, + 0 // + ); + + // + string pPrefix = "X92_P_" + + ToString(price); + + // + if (IsDrawExists(pPrefix)) + { + return; + } + + // + DrawTrendLine( + chartID, + pPrefix, + 0, + time1, + price, + time, + price, + clr, + STYLE_SOLID, + 2, + false, + false, + true // + ); + } + + // +}; \ No newline at end of file