From 69393d6d83b0dbd6691d0304771e5112c6eb00b2 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Sat, 15 Jun 2024 23:37:33 +0330 Subject: [PATCH] add supports for zone recovery ... --- Classes/x-saherelm.x121.setup.xea.mq5 | 567 +++++++++++++++++++++++++- Classes/x-saherelm.xea.class.mq5 | 2 +- Experts/x-nn-test.mq5 | 273 ++++++++++++- Experts/x-saherelm.x121.ea.mq5 | 17 +- Libraries/x-saherelm.xtrade.lib.mq5 | 45 ++ 5 files changed, 872 insertions(+), 32 deletions(-) diff --git a/Classes/x-saherelm.x121.setup.xea.mq5 b/Classes/x-saherelm.x121.setup.xea.mq5 index 7eaea5cd..aeb199c1 100644 --- a/Classes/x-saherelm.x121.setup.xea.mq5 +++ b/Classes/x-saherelm.x121.setup.xea.mq5 @@ -116,6 +116,7 @@ struct XTradeInfo // ResetGrid(); + ResetRecovery(); } // @@ -580,6 +581,249 @@ struct XTradeInfo // return result; } + + // + // Recovery Zone System ... + + // + ENUM_POSITION_TYPE rLastRecoveryType; // Last Executed Recovery Signal's Type + double rLongEntry; // Represent Next Recovery Long Signal's Entry + double rShortEntry; // Represent Next Recovery Short Signal's Entry + double rVolume; // Represent Next Recovery Signal's Volume + double rZoneUpper; // Zone Recovery Upper Bound + double rZoneLower; // Zone Recovery Lower Bound + + // + void ResetRecovery() + { + // + rVolume = 0; + rLongEntry = 0; + rZoneUpper = 0; + rZoneLower = 0; + rShortEntry = 0; + } + + // + void SetRecovery( + double nextLongEntry, + double nextShortEntry, + double zoneUpper, + double zoneLower, + double nextVolume // + ) + { + // + rVolume = nextVolume; + rZoneUpper = zoneUpper; + rZoneLower = zoneLower; + rLongEntry = nextLongEntry; + rShortEntry = nextShortEntry; + } + + // + void PrepareNextRecovery( + double distance, // Define Target Based On Zones + double volumeMultiplier, // Volume Multiplier + ENUM_POSITION_TYPE lastType // Last Type + ) + { + // + bool isValid = + // + IsValid() && + entry > 0 && + volume > 0 && + distance > 0 && + volumeMultiplier > 0 + // + ; + + // + bool isLong = IsLong(lastType); + + // + double distancePrice = PointToPrice( + distance, + symbol // + ); + + // + double selectedEntry = + isLong + ? rLongEntry <= 0 + ? entry + : rLongEntry + : rShortEntry <= 0 + ? entry + : rShortEntry; + double selectedVolume = + rVolume <= 0 + ? volume + : rVolume; + + // + double nextLongEntry = + isLong + ? selectedEntry + : selectedEntry + distancePrice; + double nextShortEntry = + isLong + ? selectedEntry - distancePrice + : selectedEntry; + + // + double nextVolume = selectedVolume * volumeMultiplier; + + // + double zoneUpper = + rZoneUpper > 0 + ? rZoneUpper + : isLong + ? entry + distancePrice + : entry + (distancePrice * 2); + double zoneLower = + rZoneLower > 0 + ? rZoneLower + : isLong + ? entry + (distancePrice * 2) + : entry - distancePrice; + + // + SetRecovery( + nextLongEntry, + nextShortEntry, + zoneUpper, + zoneLower, + nextVolume // + ); + + // + rLastRecoveryType = lastType; + } + + // + // Check if a Recovery Signal Exists Prepared and + // Provide it ... + bool HasRecovery( + XSignal &signal, // Result Signal ... + double distance, + double volumeMultiplier // + ) + { + // + bool result = false; + + // + signal.Clean(); + + // + result = + // + IsValid() && + entry > 0 && + volume > 0 && + distance > 0 && + volumeMultiplier > 0 + // + ; + if (!result) + { + return result; + } + + // + double distancePrice = PointToPrice( + distance, + symbol // + ); + + // + bool isLong = IsLong(type); + bool isLastLong = IsLong(rLastRecoveryType); + + // + // Check For Long Recovery ... + double cLongEntry = GetEntry( + symbol, + POSITION_TYPE_BUY // + ); + bool hasLongRecovery = + !isLastLong && + rLongEntry > 0 && cLongEntry >= rLongEntry; + + // + // Check For Short Recovery ... + double cShortEntry = GetEntry( + symbol, + POSITION_TYPE_SELL // + ); + bool hasShortRecovery = + isLastLong && + rShortEntry > 0 && + cShortEntry <= rShortEntry; + + // + result = hasLongRecovery || hasShortRecovery; + if (!result) + { + return result; + } + + // + ENUM_POSITION_TYPE rType = + hasLongRecovery + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + + // + double rEntry = + hasLongRecovery + ? cLongEntry + : cShortEntry; + + // + double rTP = + hasLongRecovery + ? rZoneUpper + : rZoneLower; + + // + double rSL = + hasLongRecovery + ? rZoneLower + : rZoneUpper; + + // + result = signal.Prepare( + symbol, + provider, + period, + rType, + X_ORDER_MODE_MARKET, + rEntry, + rVolume, + rSL, // SL ... + rTP // TP ... + ); + if (result) + { + // + // set Support Token ... + string comment = GenerateSupportTag(ticket); + signal.comment = comment; + + // + PrepareNextRecovery( + distance, + volumeMultiplier, + rType // + ); + } + + // + return result; + } }; // @@ -871,6 +1115,79 @@ public: return result; } + // + // Recovery System ... + + // + bool AllowRecovery() + { + return mAllowRecovery; + } + + // + void AllowRecovery(bool value) + { + mAllowRecovery = value; + } + + // + double RecoveryDistance() + { + return mRecoveryDistance; + } + + // + void RecoveryDistance(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mRecoveryDistance = value; + } + + // + double RecoveryVolumeMultiplier() + { + return mRecoveryVolumeMultiplier; + } + + // + void RecoveryVolumeMultiplier(double value) + { + // + if (value <= 1) + { + value = 0; + } + + // + mRecoveryVolumeMultiplier = value; + } + + // + // Check Recovery Properties to Validate it's Enable or not ... + bool EnableRecovery() + { + // + bool result = false; + + // + result = + // + AllowRecovery() && + RecoveryDistance() > 0 && + RecoveryVolumeMultiplier() > 0 + // + ; + + // + return result; + } + // // Tools ... @@ -1081,6 +1398,18 @@ public: GridVolumeMultiplier() // ); } + + // + // Check if Recovery System Enable or Not ... + if (EnableRecovery()) + { + // + data[infoIDX].PrepareNextRecovery( + GridDistance(), + GridVolumeMultiplier(), + signal.type // + ); + } } // @@ -1141,7 +1470,6 @@ public: } // - // Grid System Tools ... int RequestForGrid(XSignal &signals[]) { // @@ -1192,6 +1520,150 @@ public: return result; } + // + int RequestForRecovery(XSignal &signals[]) + { + // + int result = 0; + + // + Clean(signals); + + // + if (!EnableRecovery()) + { + return result; + } + + // + int count = Count(); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XSignal iSignal; + bool hasRecovery = data[i].HasRecovery( + iSignal, + RecoveryDistance(), + RecoveryVolumeMultiplier() // + ); + + // + if (hasRecovery) + { + // + AddRef( + iSignal, + signals // + ); + } + } + + // + result = ArraySize(signals); + + // + return result; + } + + // + int RequestForProtect(XSignal &signals[]) + { + // + // Grid ... + XSignal grids[]; + int gridsCount = RequestForGrid(grids); + + // + // Recovery ... + XSignal recoveries[]; + int recoveriesCount = RequestForRecovery(recoveries); + + // + Clean(signals); + + // + if (IsValidSize(gridsCount)) + { + // + Copy( + grids, + signals, + false // + ); + } + + // + if (IsValidSize(recoveriesCount)) + { + // + Copy( + recoveries, + signals, + false // + ); + } + + // + int result = ArraySize(signals); + + // + return result; + } + + // + // Sync ... + void Sync() + { + // + int count = Count(); + if (!IsValidSize(count)) + { + return; + } + + // + int mustRemoved[]; + for (int i = 0; i < count; i++) + { + // + XTradeInfo iInfo = data[i]; + + // + if (iInfo.ticket > 0 && !mTrader.IsOpen(iInfo.ticket)) + { + // + AddSpecific( + i, + mustRemoved // + ); + } + } + + // + int mustRemovedCount = ArraySize(mustRemoved); + if (!IsValidSize(mustRemovedCount)) + { + return; + } + + // + for (int i = 0; i < mustRemovedCount; i++) + { + // + ArrayRemove( + data, + i, + 1 // + ); + } + } + // // Protected ... protected: @@ -1236,6 +1708,12 @@ protected: bool mAllowGrid; // Use Grid System to Recovery Positions double mGridDistance; // Grid System Distance double mGridVolumeMultiplier; // Grid System Volume Multiplier + + // + // Recovery ... + bool mAllowRecovery; // Use Recovery System to Recovery Positions + double mRecoveryDistance; // Recovery System Distance + double mRecoveryVolumeMultiplier; // Recovery System Volume Multiplier }; // @@ -1528,6 +2006,9 @@ public: mUseSupport = value; } + // + // Grid System ... + // bool AllowGrid() { @@ -1564,6 +2045,45 @@ public: mTradeInfoHandler.GridVolumeMultiplier(value); } + // + // Recovery System ... + + // + bool AllowRecovery() + { + return mTradeInfoHandler.AllowRecovery(); + } + + // + void AllowRecovery(bool value) + { + mTradeInfoHandler.AllowRecovery(value); + } + + // + double RecoveryDistance() + { + return mTradeInfoHandler.RecoveryDistance(); + } + + // + void RecoveryDistance(double value) + { + mTradeInfoHandler.RecoveryDistance(value); + } + + // + double RecoveryVolumeMultiplier() + { + return mTradeInfoHandler.RecoveryVolumeMultiplier(); + } + + // + void RecoveryVolumeMultiplier(double value) + { + mTradeInfoHandler.RecoveryVolumeMultiplier(value); + } + // bool SaveResults() { @@ -2356,8 +2876,8 @@ public: DoEQMCloseOnSpecificTime(); // - // Do EQM Grid if Provided ... - DoEQMGrid(); + // Do EQM Protection if Provided ... + DoEQMProtect(); // // if Returns true, Signal Execution failed ... @@ -2373,7 +2893,15 @@ public: // // Signal Info Manager ... XSignal tSignal = signal; - mTradeInfoHandler.Update(tSignal); + bool isSupport = ExtractSupportedTicket(signal.comment) > 0; + bool isEQMSupport = ExtractEQMSupportedTicket(signal.comment) > 0; + if (!isSupport && !isEQMSupport) + { + mTradeInfoHandler.Update(tSignal); + } + + // + mTradeInfoHandler.Sync(); } // @@ -2386,6 +2914,7 @@ public: // Signal Info Manager ... XSignal tSignal = signal; mTradeInfoHandler.Remove(tSignal); + mTradeInfoHandler.Sync(); } // @@ -2398,8 +2927,16 @@ public: // When a Position Closed Manually ... // Signal Info Manager ... XPosition tPosition = position; + bool isSupport = ExtractSupportedTicket(position.comment) > 0; + bool isEQMSupport = ExtractEQMSupportedTicket(position.comment) > 0; tPosition.comment = comment; - mTradeInfoHandler.Update(tPosition); + if (!isSupport && !isEQMSupport) + { + mTradeInfoHandler.Update(tPosition); + } + + // + mTradeInfoHandler.Sync(); } // @@ -2410,6 +2947,7 @@ public: // Signal Info Manager ... XDeal tDeal = deal; mTradeInfoHandler.Update(tDeal); + mTradeInfoHandler.Sync(); } // @@ -2420,6 +2958,7 @@ public: // Signal Info Manager ... XDeal tDeal = deal; mTradeInfoHandler.Update(tDeal); + mTradeInfoHandler.Sync(); } // @@ -2557,6 +3096,18 @@ private: return mTradeInfoHandler.EnableGrid(); } + // + bool EnableRecovery() + { + return mTradeInfoHandler.EnableRecovery(); + } + + // + bool EnableProtection() + { + return EnableGrid() || EnableRecovery(); + } + // // Remove Untriggered EQM Orders ... void RemoveEQMOrders() @@ -2788,10 +3339,10 @@ private: // // Do Gridding Mechanism ... - void DoEQMGrid() + void DoEQMProtect() { // - if (!EnableGrid()) + if (!EnableProtection()) { return; } @@ -2799,7 +3350,7 @@ private: // XSignal signals[]; int signalsCount = mTradeInfoHandler - .RequestForGrid(signals); + .RequestForProtect(signals); if (!IsValidSize(signalsCount)) { return; diff --git a/Classes/x-saherelm.xea.class.mq5 b/Classes/x-saherelm.xea.class.mq5 index e2d132eb..92bc85ab 100644 --- a/Classes/x-saherelm.xea.class.mq5 +++ b/Classes/x-saherelm.xea.class.mq5 @@ -1122,7 +1122,7 @@ protected: string comment = XEQMSupportToken + " Hedge ..."; // - int closed = mTrader.Close( + int closed = Close( positions, comment // ); diff --git a/Experts/x-nn-test.mq5 b/Experts/x-nn-test.mq5 index 723814e7..4d68dfd6 100644 --- a/Experts/x-nn-test.mq5 +++ b/Experts/x-nn-test.mq5 @@ -20,7 +20,8 @@ #property strict // -#include "../Classes/x-saherelm.xczone.class.mq5" +// Imports ... +#include "../Classes/x-saherelm.xtrade.class.mq5" // #define ShortName "XNNTest" @@ -39,14 +40,16 @@ input double w7 = 0.5; input double w8 = 0.5; input double w9 = 0.5; +// +input double eaVolume = 0.01; + // // Variables ... int barsTotal; // -string mSymbol; -double mVolume; -ENUM_TIMEFRAMES mPeriod; +string eaSymbol; +ENUM_TIMEFRAMES eaPeriod; // // This is our Data Provider ... @@ -54,11 +57,14 @@ int rsiHandler = INVALID_HANDLE; double rsi[]; // -double inputs[]; // Storing Inputs -double weights[]; // Storing Weights; +double nnInputs[]; // Storing Inputs +double nnWeights[]; // Storing Weights; // -double output; // Output Neuron Value +double nnOutput; // Output Neuron Value + +// +XSCTrade *mTrader; // // Initialization ... @@ -93,6 +99,10 @@ void OnDeinit(const int reason) // // De Initialize XSampleEA Providers ... + IndicatorRelease(rsiHandler); + ArrayFree(rsi); + ArrayFree(nnInputs); + ArrayFree(nnWeights); } // @@ -100,17 +110,173 @@ void OnDeinit(const int reason) void OnTick() { // - int bars = iBars( - _Symbol, - _Period // + XPosition positions[]; + + // + XPosition longs[]; + int longsCount = 0; + + // + XPosition shorts[]; + int shortsCount = 0; + + // + int positionsCount = mTrader.GetPositions( + positions // ); - if (barsTotal == bars) + if (IsValidSize(positionsCount)) { - return; + // + ExtractPositions( + positions, + longs, + shorts // + ); + + // + longsCount = ArraySize(longs); + shortsCount = ArraySize(shorts); } // - barsTotal = bars; + if (longsCount == 0 && shortsCount == 0) + { + // + double longEntry = GetEntry(eaSymbol, POSITION_TYPE_BUY); + mTrader.Buy( + eaSymbol, + eaPeriod, + eaVolume, + longEntry // + ); + + // + double shortEntry = GetEntry(eaSymbol, POSITION_TYPE_SELL); + mTrader.Sell( + eaSymbol, + eaPeriod, + eaVolume, + shortEntry // + ); + } + + // + return; + // int rsiCopiedData = CopyBuffer( + // rsiHandler, + // 0, // Line Index + // 1, // BarIndex + // 10, // Count + // rsi // Buffer + // ); + // if (rsiCopiedData < 0) + // { + // // + // // Ignore Moving Forward when there isn't any Copied Data ... + // return; + // } + + // // + // // Normalize Input Data ... + // double lower = 0; + // double upper = 1; + + // // + // double max = rsi[ArrayMaximum(rsi)]; + // double min = rsi[ArrayMinimum(rsi)]; + + // // + // ArrayFree(nnInputs); + // ArrayResize(nnInputs, 10); + + // // + // for (int i = 0; i < ArraySize(rsi); i++) + // { + // nnInputs[i] = ((rsi[i] - min) * (upper - lower) / (max - min)) + lower; + // } + + // // + // // Calculating Output ... + // nnOutput = CalculateNeuron( + // nnInputs, + // nnWeights // + // ); + + // // + // // Now we Can Use NN Output for Placing Trades ... + + // // + // bool canBuy = nnOutput < 0.5; + // bool canSell = nnOutput >= 0.5; + + // // + // XPosition positions[]; + // XPosition longs[]; + // XPosition shorts[]; + // int positionsCount = mTrader.GetPositions( + // positions // + // ); + // if (IsValidSize(positionsCount)) + // { + // // + // ExtractPositions( + // positions, + // longs, + // shorts // + // ); + + // // + // if (canBuy) + // { + // // + // mTrader.Close(shorts, "Opposit"); + + // // + // if (ArraySize(longs) > 0) + // { + // return; + // } + // } + // else if (canSell) + // { + // // + // mTrader.Close(longs, "Opposit"); + + // // + // if (ArraySize(shorts) > 0) + // { + // return; + // } + // } + // } + + // // + // double mEntry = + // canBuy + // ? GetEntry(eaSymbol, POSITION_TYPE_BUY) + // : GetEntry(eaSymbol, POSITION_TYPE_SELL); + + // // + // if (canBuy) + // { + // // + // mTrader.Buy( + // eaSymbol, + // eaPeriod, + // eaVolume, + // mEntry // + // ); + // } + // else if (canSell) + // { + // // + // mTrader.Sell( + // eaSymbol, + // eaPeriod, + // eaVolume, + // mEntry // + // ); + // } } // @@ -123,22 +289,48 @@ bool InitialEA() bool result = false; // - mSymbol = _Symbol; - mPeriod = _Period; + eaSymbol = _Symbol; + eaPeriod = _Period; // // Initialize RSI Handler ... rsiHandler = iRSI( - mSymbol, - mPeriod, + eaSymbol, + eaPeriod, 14, PRICE_CLOSE // ); result = rsiHandler != INVALID_HANDLE; - if (!result) { + if (!result) + { return result; } + // + mTrader = new XSCTrade( + 1, + 78692110 // + ); + + // + ArraySetAsSeries(rsi, true); + + // + ArrayResize(nnWeights, 10); + + // + // Filling Weights Buffer ... + nnWeights[0] = w0; + nnWeights[1] = w1; + nnWeights[2] = w2; + nnWeights[3] = w3; + nnWeights[4] = w4; + nnWeights[5] = w5; + nnWeights[6] = w6; + nnWeights[7] = w7; + nnWeights[8] = w8; + nnWeights[9] = w9; + // result = true; @@ -146,4 +338,47 @@ bool InitialEA() return result; } -// \ No newline at end of file +// +// Activation Function ... +double Activate(double neuron) +{ + // + double result = 0; + + // + result = 1 / (1 + exp(-neuron)); + + // + return result; +} + +// +// Calculating Neuron ... +// NET Inputs ... +double CalculateNeuron( + double &x[], // Inputs + double &w[] // Weights +) +{ + // + double result = 0; + + // + double netInput = 0; + for (int i = 0; i < ArraySize(x); i++) + { + // + netInput += x[i] * w[i]; + } + + // + // Change The Shape of Sigmoid Graph for Smoothing ... + netInput *= 0.4; + + // + // Calculate Activated Result ... + result = Activate(netInput); + + // + return result; +} \ No newline at end of file diff --git a/Experts/x-saherelm.x121.ea.mq5 b/Experts/x-saherelm.x121.ea.mq5 index 811f83c2..1fef4ccb 100644 --- a/Experts/x-saherelm.x121.ea.mq5 +++ b/Experts/x-saherelm.x121.ea.mq5 @@ -49,15 +49,18 @@ input bool x121EAGetVerificationFromOtherTimeFrames = true; // Get Verifications // Risk Management ... input group "Risk Management"; input double x121EAVolume = 0.01; // Static Volume -input double x121EATPPoint = 60; // TP Point -input double x121EASLPoint = 300; // SL Point +input double x121EATPPoint = 100; // TP Point +input double x121EASLPoint = 100; // SL Point input int x121EAMaxAllowedTrades = 1; // Max Allowed Positions -input bool x121EAIgnoreSL = true; // Ignore Calculated SL +input bool x121EAIgnoreSL = false; // Ignore Calculated SL input bool x121EAIgnoreTP = false; // Ignore Calculated TP input bool x121EAUseSupport = false; // Use Support Signals -input bool x121EAAllowGrid = true; // Allow Grid Signals +input bool x121EAAllowGrid = false; // Allow Grid Signals input double x121EAGridDistance = 100; // Grid Distance input double x121EAGridVolumeMultiplier = 2; // Grid Volume Multiplier +input bool x121EAAllowRecovery = true; // Allow Recovery Signals +input double x121EARecoveryDistance = 100; // Recovery Distance +input double x121EARecoveryVolumeMultiplier = 2; // Recovery Volume Multiplier input double x121EAMinRequiredProfitPerTrade = 0.5; // Minimum Required Profit for Hedging input double x121EAMinRequiredProfitPerVolumeFactor = 0.01; // Minimum Required Profit for Hedging Per Volume input int x121EARestingAfterHedge = 300; // Resting Seconds After Hedge @@ -195,6 +198,12 @@ bool InitialEA() x121EA.GridDistance(x121EAGridDistance); x121EA.GridVolumeMultiplier(x121EAGridVolumeMultiplier); + // + // Recovery System ... + x121EA.AllowRecovery(x121EAAllowRecovery); + x121EA.RecoveryDistance(x121EARecoveryDistance); + x121EA.RecoveryVolumeMultiplier(x121EARecoveryVolumeMultiplier); + // // Configure Alert ... x121EA.SetAlertPrefix(ShortName); diff --git a/Libraries/x-saherelm.xtrade.lib.mq5 b/Libraries/x-saherelm.xtrade.lib.mq5 index 330fa7e7..fc0a3e15 100644 --- a/Libraries/x-saherelm.xtrade.lib.mq5 +++ b/Libraries/x-saherelm.xtrade.lib.mq5 @@ -53,6 +53,7 @@ string XSymbolToken = "SMBL"; // string XSupportToken = "SP"; string XEQMSupportToken = "EQM"; +string XEQPToken = "EQP"; // string XSLTrailToken = "SLT"; @@ -4465,6 +4466,50 @@ void CountPositions( } } +// +// Extract Positions based On Type ... +void ExtractPositions( + XPosition &positions[], + XPosition &longs[], + XPosition &shorts[] // +) +{ + // + int count = ArraySize(positions); + if (!IsValidSize(count)) + { + return; + } + + // + Clean(longs); + Clean(shorts); + + // + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = positions[i]; + + // + bool isLong = IsLong(iPosition.type); + if (isLong) + { + AddRef( + iPosition, + longs // + ); + } + else + { + AddRef( + iPosition, + shorts // + ); + } + } +} + // // Custom Drawings ... bool DrawTrendState(