From b5cec1f52a99ec2e397be0533e48d235931c9f03 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Tue, 10 Dec 2024 01:38:29 +0330 Subject: [PATCH] Add Support for Sar Changes Detection ... --- Libraries/x-saherelm.common.lib.mq5 | 40 ++- .../x-121.smc.market.cycle.helper.class.mq5 | 237 ++++++++++++------ X121SMCEA/Libraries/x-121.smc.lib.mq5 | 182 ++++++++++++++ .../x-121.smc.test.strategy.class.mq5 | 113 ++++++--- 4 files changed, 453 insertions(+), 119 deletions(-) diff --git a/Libraries/x-saherelm.common.lib.mq5 b/Libraries/x-saherelm.common.lib.mq5 index 93a01551..eed1c59a 100644 --- a/Libraries/x-saherelm.common.lib.mq5 +++ b/Libraries/x-saherelm.common.lib.mq5 @@ -215,7 +215,7 @@ struct XTick double bid; // Bid ... double ask; // Ask ... double spread; // Spread ... - long volume; // Volume ... + long volume; // Volume ... // // Constructor ... @@ -10398,6 +10398,41 @@ bool RemoveLastItem( return result; } +template +void CleanupArray( + T &buffer[], // Buffer to Cleanup ... + int maxAllowed = 0 // Max Allowed Number of items ... +) +{ + // + if (maxAllowed <= 0) + { + return; + } + + // + int count = ArraySize(buffer); + if (!IsValidSize(count) || + count <= maxAllowed) + { + return; + } + + // + int mustRemove = count - maxAllowed; + if (!IsValidSize(mustRemove)) + { + return; + } + + // + ArrayRemove( + buffer, + 0, + mustRemove // + ); +} + // // Search Array For Specific Item ... template @@ -10851,7 +10886,8 @@ void FindSames( void AddIfNotExists( double value, double &values[], - double smoothingPoint = 3) + double smoothingPoint = 3 // +) { // double smoothingValue = smoothingPoint * GetPoints(_Symbol); diff --git a/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 b/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 index 2a95cb75..a436787a 100644 --- a/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 +++ b/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 @@ -25,6 +25,9 @@ #include "../../Classes/x-saherelm.x-poi.class.mq5" #include "../Libraries/x-121.smc.lib.mq5" +// +// Definitions ... + // // Implementations ... @@ -47,6 +50,7 @@ class XC121SMCCycleHelper : public XCBase // Constructor(s) ... XC121SMCCycleHelper() { + Default(); } // @@ -59,6 +63,33 @@ class XC121SMCCycleHelper : public XCBase // // Getter/Setter(s) ... + /** + * Get Max llowed Changes to Save ... + * + * @return ( int ) + */ + int MaxAllowedSavedChanges() + { + return mMaxAllowedSavedChanges; + } + + /** + * Set Max llowed Changes to Save ... + * + * @param value: Integer ... + */ + void MaxAllowedSavedChanges(int value) + { + // + if (value < 10) + { + value = 10; + } + + // + mMaxAllowedSavedChanges = value; + } + // // Actions ... @@ -627,6 +658,15 @@ class XC121SMCCycleHelper : public XCBase // // Virtuals ... + /** + * Set Default Properties Values ... + */ + virtual void Default() + { + // + MaxAllowedSavedChanges(50); + } + // protected: // @@ -643,102 +683,69 @@ class XC121SMCCycleHelper : public XCBase ) { // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL changeBar; int index = barIndex <= 0 ? 1 : barIndex; - bool isInited = false; - string symbol = GetSymbol(); - - // - // Retrieve Bar ... - XOHCL bar; - isInited = GetBar(bar, index); + bool isInited = GetBar( + changeBar, + index // + ); if (!isInited) { return; } // - // Retrieve Previous Bar ... - XOHCL pBar; - int pIndex = index + 1; - isInited = GetBar(pBar, pIndex); - if (!isInited) - { - return; - } + // Detect Sar Change ... + bool isSarSwitchedToBullish = conditions.x121Conditions.isSarSwitchedToBullish; + bool isSarSwitchedToBearish = conditions.x121Conditions.isSarSwitchedToBearish; + bool isSarChanged = isSarSwitchedToBullish || + isSarSwitchedToBearish; // - XTick xTick; - isInited = xTick.Init(symbol); - if (!isInited) + if (period == PERIOD_M1) { - return; + // + if (isSarChanged) + { + // + XValueChange sarChanged; + + // + datetime time = changeBar.time; + double after = conditions.x121Conditions.sarBuffer[1]; + double before = conditions.x121Conditions.sarBuffer[2]; + ENUM_X_DIRECTION dir = + isSarSwitchedToBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Initialize Model ... + isInited = sarChanged.Init( + before, + after, + dir, + time // + ); + if (isInited) + { + // + isInited = AddSarChange(sarChanged); + if (isInited) + { + Print("Sar Switched ..."); + } + } + } } - // - bool isSarAttached = - bar.close > conditions.x121Conditions.sarBuffer[0]; - if (isSarAttached) - { - Print("Sar Attached ..."); - } - - // // - // bool isSarBullish = - // conditions.x121Conditions.sarBuffer[index] < bar.low; - // bool isSarBullishPrev = - // conditions.x121Conditions.sarBuffer[pIndex] < pBar.low; - - // // - // bool isSarBearish = - // conditions.x121Conditions.sarBuffer[index] > bar.high; - // bool isSarBearishPrev = - // conditions.x121Conditions.sarBuffer[pIndex] > pBar.high; - - // // - // bool isSarSwitchedToBullish = - // isSarBullish && - // !isSarBullishPrev && - // isSarBearishPrev; - - // // - // bool isSarSwitchedToBearish = - // isSarBearish && - // !isSarBearishPrev && - // isSarBullishPrev; - - // // - // if (isSarSwitchedToBullish || - // isSarSwitchedToBearish) - // { - // Print("Sar Switched ..."); - // } - - // // - // bool isSarBullish = - // conditions.x121Conditions.sarBuffer[1] < xTick.ask && - // conditions.x121Conditions.sarBuffer[1] < xTick.bid && - // conditions.x121Conditions.isSarBullish; - - // // - // bool isSarBearish = - // conditions.x121Conditions.sarBuffer[1] > xTick.ask && - // conditions.x121Conditions.sarBuffer[1] > xTick.bid && - // conditions.x121Conditions.isSarBearish; - - // - // Detect Sar Changes ... - // bool isSarChanged = (isSarBullish && - // !isSarBearish) || - // (isSarBearish && - // !isSarBullish); - // if (isSarChanged) - // { - // Print("SarChaned"); - // } - // // Detect Peak Changes ... @@ -752,6 +759,11 @@ class XC121SMCCycleHelper : public XCBase // Props ... XCBarAnalyser *mBarAnalyser; + // + // Change Holders ... + int mMaxAllowedSavedChanges; // Max llowed Changes to Save ... + XValueChange mSarChanges[]; // Holds Parabolic Sar Direction Changes ... + // // Actions ... @@ -854,4 +866,67 @@ class XC121SMCCycleHelper : public XCBase // return result; } + + // + // Change Values Actions ... + + /** + * Count Saved Parabolic Sar Changes ... + * + * @return ( int ) + */ + int CountSarChanges() + { + return ArraySize(mSarChanges); + } + + /** + * Add Specified Parabolic Sar Changed Item ... + * + * @param value: XValueChange instance Reference ... + * + * @return ( bool ) + */ + bool AddSarChange(XValueChange &value) + { + // + bool result = false; + + // + result = value.IsValid(); + if (!result) + { + return result; + } + + // + int beforeCount = CountSarChanges(); + + // + AddIfNotExists( + value, + mSarChanges // + ); + + // + int afterCount = CountSarChanges(); + + // + result = afterCount == beforeCount + 1; + if (result) + { + // + // Cleaning Up Unused Items ... + int maxAllowed = MaxAllowedSavedChanges(); + CleanupArray( + mSarChanges, + maxAllowed // + ); + } + + // + return result; + } + + // }; diff --git a/X121SMCEA/Libraries/x-121.smc.lib.mq5 b/X121SMCEA/Libraries/x-121.smc.lib.mq5 index bd2f9ee7..4ff53480 100644 --- a/X121SMCEA/Libraries/x-121.smc.lib.mq5 +++ b/X121SMCEA/Libraries/x-121.smc.lib.mq5 @@ -1839,4 +1839,186 @@ ENUM_X_121_SMC_PROVIDERS ParseProvider(string value) return result; } +// +// Model Value Changed ... +struct XValueChange +{ + // + // Props ... + double before; // Before Change Value ... + double after; // After Change Value ... + datetime time; // Change Time ... + ENUM_X_DIRECTION dir; // Change Direction ... + + // + // Constructor ... + XValueChange() + { + Clean(); + } + + // + // Tools ... + + /** + * Initialize ... + * + * @param _before: Double, Value Before Change ... + * @param _after: Double, Value After Change ... + * @param _time: Datetime, Change Time ... + * @param _dir: ENUM_X_DIRECTION member, Specified Changed Direction ... + * + * @return ( bool ) + */ + bool Init( + double _before, // Before Change Value ... + double _after, // After Change Value ... + ENUM_X_DIRECTION _dir, // Change Direction ... + datetime _time = NULL // Change Time ... + ) + { + // + bool result = false; + + // + _time = NormalizeTime(_time); + + // + // Validate Inputs ... + result = + // + _after > 0 && + _before > 0 && + IsValid(_time) && + _after != _before && + HasDirection(_dir) + // + ; + if (!result) + { + return result; + } + + // + // Set Validated Values ... + dir = _dir; + time = _time; + after = _after; + before = _before; + + // + result = IsValid(); + + // + return result; + } + + /** + * Cleaning Up ... + */ + void Clean() + { + // + after = 0; + before = 0; + time = NULL; + dir = X_DIRECTION_NONE; + } + + /** + * Validate Model ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + after > 0 && + before > 0 && + IsValid(time) && + after != before && + HasDirection(dir) + // + ; + + // + return result; + } + + // +}; + +/** + * Add Value Change instance to Exists Collection if it's not Exists ... + * + * @param item: XValueChange instance Reference ... + * @param items: XValueChange instance Array Reference ... + * + * @return ( int ) + */ +int AddIfNotExists( + XValueChange &item, + XValueChange &items[] // +) +{ + // + int result = 0; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + bool canAdd = false; + int count = ArraySize(items); + if (!IsValidSize(count)) + { + canAdd = true; + } + else + { + // + XValueChange last; + bool hasItem = GetLastItem( + last, + items // + ); + if (!hasItem) + { + canAdd = true; + } + else + { + // + // Compare Last Item with Current ... + canAdd = item.time > last.time; + } + } + + // + // Add Item if Allowed ... + if (canAdd) + { + // + AddRef( + item, + items // + ); + } + + // + result = ArraySize(items); + + // + return result; +} + // \ No newline at end of file diff --git a/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 b/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 index d42e8ff3..4de82a5b 100644 --- a/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 +++ b/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 @@ -124,24 +124,32 @@ class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy double pip2 = 2 * pip; // - // Check Spread ... + // Retrieve and Fill Cycle Conditions ... + result = GetCyclesConditions(conditions); + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + // Check Spread for Signalling Conditions ... bool isSpreadPassed = IsSpreadPass(); result = isSpreadPassed; if (!result) { // - // string message = "Spread is not Passed for Analysing ..."; - // LogAlert(message); - - // + conditions.Clean(); return result; } // - // Detect Conditions ... + // Detect Signal Conditions ... result = DetectConditions(conditions); if (!result) { + // conditions.Clean(); return result; } @@ -272,11 +280,13 @@ class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy // Actions ... /** - * Detect and Parse Market Conditions ... + * Retrieve Cycles Conditions ... + * + * @param conditions: X121SMCStrategyConditions instance Reference ... * * @return ( bool ) */ - bool DetectConditions( + bool GetCyclesConditions( X121SMCStrategyConditions &conditions // ) { @@ -294,34 +304,6 @@ class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy int ppIndex = pIndex + 1; // - XOHCL zBar; - result = zBar.Init( - symbol, - period, - zIndex // - ); - if (!result) - { - return result; - } - - // - XOHCL cBar; - result = cBar.Init( - symbol, - period, - cIndex // - ); - if (!result) - { - return result; - } - - // - string msg = NULL; - - // - double bid = GetBid(symbol); datetime cTime = TimeCurrent(); // @@ -425,6 +407,65 @@ class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy } conditions.visionConditions.state = mVisionState; + // + return result; + } + + /** + * Detect and Parse Market Conditions ... + * + * @param conditions: X121SMCStrategyConditions instance Reference ... + * + * @return ( bool ) + */ + bool DetectConditions( + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + string msg = NULL; + + // + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + // // // // Detect Valid Supply and Demand Zones ... // XCSupplyZone *supplyZone;