diff --git a/Classes/x-saherelm.x-market.pattern.class.mq5 b/Classes/x-saherelm.x-market.pattern.class.mq5 index 4ed7fef9..88bd8d3a 100644 --- a/Classes/x-saherelm.x-market.pattern.class.mq5 +++ b/Classes/x-saherelm.x-market.pattern.class.mq5 @@ -1268,6 +1268,194 @@ class XCMarketPatternDetector : public XCBase return result; } + bool HasSupport( + XOHCL &bar, + XOHCL &support, + int validationLength = 21, + int maxAllowedLoopback = 1500 // + ) + { + // + bool result = false; + + // + // Prepare ... + support.Clean(); + + // + // Normalizing ... + validationLength = NormalizeInt(validationLength, 7); + maxAllowedLoopback = NormalizeInt(maxAllowedLoopback, 21, 1500); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Find Support Swing ... + int idx = -1; + bool has = false; + int lookupIDX = bar.Index(); + while (!IsValidIndex(idx) && + lookupIDX < maxAllowedLoopback) + { + // + // Detect Swing ... + idx = FindXSwing( + X_SWING_LOW, + bar.symbol, + bar.period, + lookupIDX, + validationLength // + ); + has = IsValidIndex(idx); + if (!has) + { + // + lookupIDX++; + continue; + } + + // + // Retrieve Swing Bar ... + has = support.Init( + bar.symbol, + bar.period, + idx // + ); + if (!has) + { + // + idx = -1; + lookupIDX++; + support.Clean(); + continue; + } + + // + // Check Suppor Low Shadow ... + has = support.GetDown() < bar.low; + if (!has) + { + // + idx = -1; + lookupIDX++; + support.Clean(); + continue; + } + + // + if (IsValidIndex(idx)) + { + break; + } + } + + // + result = support.IsValid(); + + // + return result; + } + + bool HasResistance( + XOHCL &bar, + XOHCL &resistence, + int validationLength = 21, + int maxAllowedLoopback = 1500 // + ) + { + // + bool result = false; + + // + // Prepare ... + resistence.Clean(); + + // + // Normalizing ... + validationLength = NormalizeInt(validationLength, 7); + maxAllowedLoopback = NormalizeInt(maxAllowedLoopback, 21, 1500); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Find Support Swing ... + int idx = -1; + bool has = false; + int lookupIDX = bar.Index(); + while (!IsValidIndex(idx) && + lookupIDX < maxAllowedLoopback) + { + // + // Detect Swing ... + idx = FindXSwing( + X_SWING_HIGH, + bar.symbol, + bar.period, + lookupIDX, + validationLength // + ); + has = IsValidIndex(idx); + if (!has) + { + // + lookupIDX++; + continue; + } + + // + // Retrieve Swing Bar ... + has = resistence.Init( + bar.symbol, + bar.period, + idx // + ); + if (!has) + { + // + idx = -1; + lookupIDX++; + resistence.Clean(); + continue; + } + + // + // Check Resistance High Shadow ... + has = resistence.GetUp() > bar.high; + if (!has) + { + // + idx = -1; + lookupIDX++; + resistence.Clean(); + continue; + } + + // + if (IsValidIndex(idx)) + { + break; + } + } + + // + result = resistence.IsValid(); + + // + return result; + } + // // Protected ... protected: diff --git a/Classes/x-saherelm.x-poi.drawer.class.mq5 b/Classes/x-saherelm.x-poi.drawer.class.mq5 index dfa90237..ffb62cac 100644 --- a/Classes/x-saherelm.x-poi.drawer.class.mq5 +++ b/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -889,6 +889,95 @@ class XCPOIDrawer : public XCBase return result; } + /** + * Draw Trend Line based on Swings Points ... + * + * @param swings: XOHCL, Specified Swings ... + * @param dir: ENUM_X_DIRECTION, Specified Trend Direction ... + * @param rayRight: Ray to Right ... + * @param rayLeft: Ray to Left ... + * + * @return ( bool ) + */ + bool DrawSwingTrend( + XOHCL &swings[], + ENUM_X_DIRECTION dir, + CChartObjectTrend *&object, + bool rayRight = false, + bool rayLeft = false // + ) + { + // + bool result = false; + + // + int count = ArraySize(swings); + result = HasChild(swings) && + count >= 2 && + HasDirection(dir); + if (!result) + { + return result; + } + + // + bool isBullish = IsSpecifiedBullish(dir); + + // + double price1 = + isBullish + ? swings[0].low + : swings[0].high; + datetime time1 = swings[0].time; + + // + double price2 = + isBullish + ? swings[count - 1].low + : swings[count - 1].high; + datetime time2 = swings[count - 1].time; + + // + ulong chartId = ChartIdentification(); + int subWindow = SubWindowIdentification(); + string name = ToXString(dir) + "_Trend_" + ToXString(price1) + "_" + ToXString(price2); + + // + object = new CChartObjectTrend(); + result = object.Create( + chartId, + name, + subWindow, + time1, + price1, + time2, + price2 // + ); + if (result) + { + // + ApplyStyle( + object, + dir // + ); + + // + if (rayRight) + { + object.RayRight(true); + } + + // + if (rayLeft) + { + object.RayLeft(true); + } + } + + // + return result; + } + /** * Apply Specified Style to Object ... */ @@ -932,7 +1021,7 @@ class XCPOIDrawer : public XCBase /** * Apply Style to Specified Chart Object ... - * + * * @param dir: Argument 2 */ void ApplyStyle( diff --git a/Experts/x-saherelm.xfima.backtester.ea.mq5 b/Experts/x-saherelm.xfima.backtester.ea.mq5 index 77444eda..46b4355a 100644 --- a/Experts/x-saherelm.xfima.backtester.ea.mq5 +++ b/Experts/x-saherelm.xfima.backtester.ea.mq5 @@ -25,16 +25,9 @@ // Imports ... #include "../Classes/x-saherelm.x-backtester.expert.class.mq5" #include "../Classes/x-saherelm.x-market.pattern.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" #include "../Helpers/x-saherelm.xom1.helper.mq5" -// -#import "user32.dll" -void keybd_event(int bVk, int bScan, int dwFlags, int dwExtraInfo); -#import -#define VK_SPACE 0x20 // Space -#define VK_RETURN 0x0D // Return - Enter Key -#define KEYEVENTF_KEYUP 0x0002 // Key up - // // Definitions ... @@ -133,6 +126,10 @@ string eaLogTag; // EA Log Prefix ... XCBackTesterEA *eaExpert; // EA Expert ... XCMarketPatternDetector *eaPatternDetector; // EA Pattern Detector ... +// +XCPOIDrawer *eaDrawer; // Ea POI Drawer ... +CArrayObj draws; // Drawn Objects ... + // XBarTracker eaBarTracker; // EA Bar Traker ... @@ -140,6 +137,9 @@ XBarTracker eaBarTracker; // EA Bar Traker ... int eaHandler = INVALID_HANDLE; // Indicator Handler ... int eaCTHandler = INVALID_HANDLE; // Candle Timer Handler ... +// +ENUM_X_DIRECTION trendDir = X_DIRECTION_NONE; + // // Define Indicators Here ... @@ -314,6 +314,10 @@ int OnInit() // Instantiate Market Pattern Detector ... eaPatternDetector = new XCMarketPatternDetector(); + // + // Instantiate POI Drawer ... + eaDrawer = new XCPOIDrawer(); + // Print(ShortName, ": Initialized Successfully ..."); return INIT_SUCCEEDED; @@ -346,6 +350,10 @@ void OnDeinit(const int reason) // eaBarTracker.Clean(); + // + delete eaDrawer; + ZeroMemory(eaDrawer); + // delete eaPatternDetector; ZeroMemory(eaPatternDetector); @@ -363,242 +371,7 @@ void OnTick() eaExpert.HandleOnTick(); // - bool isNewBar = eaBarTracker.IsNewBar(); - if (isNewBar) - { - // - // Initialize 1 Indexed Bar ... - XOHCL cBar; - bool has = cBar.Init( - _Symbol, - _Period, - 1 // - ); - if (has) - { - // - // Do Analysis ... - - // - ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; - - // - // Define Detection Flags ... - - // - bool detectPinned = false; - bool detectMomentum = false; - bool detectEngulfed = false; - bool detectTrueGaped = false; - - // - bool detectStarPattern = false; - bool detectFlagPattern = false; - bool detectRisingPattern = false; - bool detectPiercingPattern = false; - bool detectSignalKeyBarPattern = true; - - // - bool detectSwingTrend = false; - - // - // Checking Momentum Bar ... - if (detectMomentum) - { - // - bool isMomentum = eaPatternDetector.IsMomentumBar( - cBar, - iDir // - ); - bool isBullishMomentum = isMomentum && - IsSpecifiedBullish(iDir); - bool isBearishMomentum = isMomentum && - IsSpecifiedBearish(iDir); - if (isMomentum) - { - Print(ToXString(iDir), " Momentum Bar: ", cBar.time); - } - } - - // - // Checking Engulfed Bar ... - if (detectEngulfed) - { - // - bool isEngulfed = eaPatternDetector.IsEngulfedBar( - cBar, - iDir // - ); - bool isBullishEngulfed = isEngulfed && - IsSpecifiedBullish(iDir); - bool isBearishEngulfed = isEngulfed && - IsSpecifiedBearish(iDir); - if (isEngulfed) - { - Print(ToXString(iDir), " Engulfed Bar: ", cBar.time); - } - } - - // - // Checking TruGaped Bar ... - if (detectTrueGaped) - { - // - bool isTrueGaped = eaPatternDetector.IsTrueGapedBar( - cBar, - iDir // - ); - bool isBullishTrueGaped = isTrueGaped && - IsSpecifiedBullish(iDir); - bool isBearishTrueGaped = isTrueGaped && - IsSpecifiedBearish(iDir); - if (isTrueGaped) - { - Print(ToXString(iDir), " TrueGapped Bar: ", cBar.time); - } - } - - // - // Checking Pinned Bar ... - if (detectPinned) - { - bool isPinned = eaPatternDetector.IsPinnedBar( - cBar, - iDir // - ); - bool isBullishPinned = isPinned && - IsSpecifiedBullish(iDir); - bool isBearishPinned = isPinned && - IsSpecifiedBearish(iDir); - if (isPinned) - { - Print(ToXString(iDir), " Pinned Bar: ", cBar.time); - } - } - - // - // Checking Star Pattern ... - if (detectStarPattern) - { - bool isStarPattern = eaPatternDetector.IsStartPattern( - cBar, - iDir // - ); - bool isBullishStarPattern = isStarPattern && - IsSpecifiedBullish(iDir); - bool isBearishStarPattern = isStarPattern && - IsSpecifiedBearish(iDir); - if (isStarPattern) - { - Print(ToXString(iDir), " Star Pattern: ", cBar.time); - } - } - - // - // Checking Piercing Pattern ... - if (detectPiercingPattern) - { - // - bool isPiercingPattern = eaPatternDetector.IsPiercingPattern( - cBar, - iDir // - ); - bool isBullishPiercingPattern = isPiercingPattern && - IsSpecifiedBullish(iDir); - bool isBearishPiercingPattern = isPiercingPattern && - IsSpecifiedBearish(iDir); - if (isPiercingPattern) - { - Print(ToXString(iDir), " Piercing Pattern: ", cBar.time); - } - } - - // - // Checking Rising Pattern ... - if (detectRisingPattern) - { - // - bool isRisingPattern = eaPatternDetector.IsRisingPattern( - cBar, - iDir // - ); - bool isBullishRisingPattern = isRisingPattern && - IsSpecifiedBullish(iDir); - bool isBearishRisingPattern = isRisingPattern && - IsSpecifiedBearish(iDir); - if (isRisingPattern) - { - Print(ToXString(iDir), " Rising Pattern: ", cBar.time); - } - } - - // - // Checking Flag Pattern ... - if (detectFlagPattern) - { - // - XOHCL swingBar; - bool isFlagPattern = eaPatternDetector.IsFlagPattern( - cBar, - iDir, - swingBar // - ); - bool isBullishFlagPattern = isFlagPattern && - IsSpecifiedBullish(iDir); - bool isBearishFlagPattern = isFlagPattern && - IsSpecifiedBearish(iDir); - if (isFlagPattern) - { - Print(ToXString(iDir), " Flag Pattern: ", cBar.time, ", Swing: ", swingBar.time); - } - swingBar.Clean(); - } - - // - // Detect Swing Trend ... - if (detectSwingTrend) - { - // - XOHCL swings[]; - bool hasSwingTrend = eaPatternDetector.HasSwingTrend( - cBar, - iDir, - swings // - ); - bool hasBullishSwingTrend = hasSwingTrend && - IsSpecifiedBullish(iDir); - bool hasBearishSwingTrend = hasSwingTrend && - IsSpecifiedBearish(iDir); - if (hasSwingTrend) - { - Print(ToXString(iDir), " Swing Trend: ", cBar.time); - } - SpecifiedClean(swings); - } - - // - // Detect SignalKey Bar Pattern ... - if (detectSignalKeyBarPattern) - { - // - bool isSignalKeyBar = eaPatternDetector.IsSignalKeyBarPattern( - cBar, - iDir // - ); - bool isBullishSignalKeyBar = isSignalKeyBar && - IsSpecifiedBullish(iDir); - bool isBearishSignalKeyBar = isSignalKeyBar && - IsSpecifiedBearish(iDir); - if (isSignalKeyBar) - { - Print(ToXString(iDir), " SignalKey Bar Pattern: ", cBar.time); - } - } - } - - // - cBar.Clean(); - } + DetectPatterns(); } // @@ -852,3 +625,403 @@ void OnTradeStateChanged(const XOnTradeHandlerState &state) { eaExpert.HandleOnTradeStateChanged(state); } + +/** + * Check Market Conditions for Pattern Detection ... + */ +void DetectPatterns() +{ + // + bool isNewBar = eaBarTracker.IsNewBar(); + if (!isNewBar) + { + return; + } + + // + // Initialize 1 Indexed Bar ... + XOHCL cBar; + bool has = cBar.Init( + _Symbol, + _Period, + 1 // + ); + if (!has) + { + return; + } + + // + // Do Analysis ... + + // + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Define Detection Flags ... + + // + bool detectPinned = false; + bool detectMomentum = false; + bool detectEngulfed = false; + bool detectTrueGaped = false; + + // + bool detectStarPattern = false; + bool detectFlagPattern = false; + bool detectRisingPattern = false; + bool detectPiercingPattern = false; + bool detectSignalKeyBarPattern = false; + + // + bool detectSwingTrend = false; + bool detectSwingTrendBreakes = false; + + // + bool detectSupports = false; + bool detectResistance = false; + + // + // Checking Momentum Bar ... + if (detectMomentum) + { + // + bool isMomentum = eaPatternDetector.IsMomentumBar( + cBar, + iDir // + ); + bool isBullishMomentum = isMomentum && + IsSpecifiedBullish(iDir); + bool isBearishMomentum = isMomentum && + IsSpecifiedBearish(iDir); + if (isMomentum) + { + Print(ToXString(iDir), " Momentum Bar: ", cBar.time); + } + } + + // + // Checking Engulfed Bar ... + if (detectEngulfed) + { + // + bool isEngulfed = eaPatternDetector.IsEngulfedBar( + cBar, + iDir // + ); + bool isBullishEngulfed = isEngulfed && + IsSpecifiedBullish(iDir); + bool isBearishEngulfed = isEngulfed && + IsSpecifiedBearish(iDir); + if (isEngulfed) + { + Print(ToXString(iDir), " Engulfed Bar: ", cBar.time); + } + } + + // + // Checking TruGaped Bar ... + if (detectTrueGaped) + { + // + bool isTrueGaped = eaPatternDetector.IsTrueGapedBar( + cBar, + iDir // + ); + bool isBullishTrueGaped = isTrueGaped && + IsSpecifiedBullish(iDir); + bool isBearishTrueGaped = isTrueGaped && + IsSpecifiedBearish(iDir); + if (isTrueGaped) + { + Print(ToXString(iDir), " TrueGapped Bar: ", cBar.time); + } + } + + // + // Checking Pinned Bar ... + if (detectPinned) + { + bool isPinned = eaPatternDetector.IsPinnedBar( + cBar, + iDir // + ); + bool isBullishPinned = isPinned && + IsSpecifiedBullish(iDir); + bool isBearishPinned = isPinned && + IsSpecifiedBearish(iDir); + if (isPinned) + { + Print(ToXString(iDir), " Pinned Bar: ", cBar.time); + } + } + + // + // Checking Star Pattern ... + if (detectStarPattern) + { + bool isStarPattern = eaPatternDetector.IsStartPattern( + cBar, + iDir // + ); + bool isBullishStarPattern = isStarPattern && + IsSpecifiedBullish(iDir); + bool isBearishStarPattern = isStarPattern && + IsSpecifiedBearish(iDir); + if (isStarPattern) + { + Print(ToXString(iDir), " Star Pattern: ", cBar.time); + } + } + + // + // Checking Piercing Pattern ... + if (detectPiercingPattern) + { + // + bool isPiercingPattern = eaPatternDetector.IsPiercingPattern( + cBar, + iDir // + ); + bool isBullishPiercingPattern = isPiercingPattern && + IsSpecifiedBullish(iDir); + bool isBearishPiercingPattern = isPiercingPattern && + IsSpecifiedBearish(iDir); + if (isPiercingPattern) + { + Print(ToXString(iDir), " Piercing Pattern: ", cBar.time); + } + } + + // + // Checking Rising Pattern ... + if (detectRisingPattern) + { + // + bool isRisingPattern = eaPatternDetector.IsRisingPattern( + cBar, + iDir // + ); + bool isBullishRisingPattern = isRisingPattern && + IsSpecifiedBullish(iDir); + bool isBearishRisingPattern = isRisingPattern && + IsSpecifiedBearish(iDir); + if (isRisingPattern) + { + Print(ToXString(iDir), " Rising Pattern: ", cBar.time); + } + } + + // + // Checking Flag Pattern ... + if (detectFlagPattern) + { + // + XOHCL swingBar; + bool isFlagPattern = eaPatternDetector.IsFlagPattern( + cBar, + iDir, + swingBar // + ); + bool isBullishFlagPattern = isFlagPattern && + IsSpecifiedBullish(iDir); + bool isBearishFlagPattern = isFlagPattern && + IsSpecifiedBearish(iDir); + if (isFlagPattern) + { + Print(ToXString(iDir), " Flag Pattern: ", cBar.time, ", Swing: ", swingBar.time); + } + swingBar.Clean(); + } + + // + // Detect SignalKey Bar Pattern ... + if (detectSignalKeyBarPattern) + { + // + bool isSignalKeyBar = eaPatternDetector.IsSignalKeyBarPattern( + cBar, + iDir // + ); + bool isBullishSignalKeyBar = isSignalKeyBar && + IsSpecifiedBullish(iDir); + bool isBearishSignalKeyBar = isSignalKeyBar && + IsSpecifiedBearish(iDir); + if (isSignalKeyBar) + { + Print(ToXString(iDir), " SignalKey Bar Pattern: ", cBar.time); + } + } + + // + // Detect Swing Trend ... + if (detectSwingTrend) + { + // + XOHCL swings[]; + bool hasSwingTrend = eaPatternDetector.HasSwingTrend( + cBar, + iDir, + swings // + ); + bool hasBullishSwingTrend = hasSwingTrend && + IsSpecifiedBullish(iDir); + bool hasBearishSwingTrend = hasSwingTrend && + IsSpecifiedBearish(iDir); + if (hasSwingTrend) + { + // + Print(ToXString(iDir), " Swing Trend: ", cBar.time); + + // + CChartObjectTrend *iObj; + has = eaDrawer.DrawSwingTrend( + swings, + iDir, + iObj, + true // Ray Right ... + ); + if (has) + { + draws.Add(iObj); + } + } + SpecifiedClean(swings); + } + + // + // Swing Trend Breakes ... + if (detectSwingTrendBreakes) + { + // + XOHCL swings[]; + bool hasSwingTrend = eaPatternDetector.HasSwingTrend( + cBar, + iDir, + swings // + ); + bool hasBullishSwingTrend = hasSwingTrend && + IsSpecifiedBullish(iDir); + bool hasBearishSwingTrend = hasSwingTrend && + IsSpecifiedBearish(iDir); + if (hasSwingTrend) + { + // + if (!HasDirection(trendDir)) + { + trendDir = iDir; + } + } + + // + // Breaked Detection ... + if (trendDir != iDir) + { + // + Print("Trend Dir Breaked to: ", ToXString(iDir)); + trendDir = iDir; + } + + // + SpecifiedClean(swings); + } + + // + // Detect Supports ... + if (detectSupports) + { + // + XOHCL support; + bool hasSupport = eaPatternDetector.HasSupport( + cBar, + support // + ); + if (hasSupport) + { + // + XBoxZone supportBox; + has = ToSupportBox(support, supportBox); + if (has) + { + // + // Draw Box ... + XCBoxObject *iObj; + has = eaDrawer.DrawBox( + supportBox, + iObj // + ); + if (has) + { + // + // Apply Style ... + eaDrawer.ApplyStyle( + iObj, + eaDrawer.boxBullishStyle // + ); + + // + draws.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + supportBox.Clean(); + } + support.Clean(); + } + + // + // Detect Resistance ... + if (detectResistance) + { + // + XOHCL resistance; + bool hasResistance = eaPatternDetector.HasResistance( + cBar, + resistance // + ); + if (hasResistance) + { + // + XBoxZone resistanceBox; + has = ToResistanceBox(resistance, resistanceBox); + if (has) + { + // + // Draw Box ... + XCBoxObject *iObj; + has = eaDrawer.DrawBox( + resistanceBox, + iObj // + ); + if (has) + { + // + // Apply Style ... + eaDrawer.ApplyStyle( + iObj, + eaDrawer.boxBearishStyle // + ); + + // + draws.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + resistanceBox.Clean(); + } + resistance.Clean(); + } + + // + cBar.Clean(); +} + +// \ No newline at end of file diff --git a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 index 785304d3..5318ee47 100644 --- a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 @@ -1260,4 +1260,104 @@ void ValidateBoxes( // } +/** + * Converts a Bar to Support Box ... + * + * @param bar: XOHCL, Specified Bar ... + * @param box: XBoxZone, destination Box ... + * @param toTime: datetime, Specified Box to Time ... + * + * @return ( bool ) + */ +bool ToSupportBox( + XOHCL &bar, + XBoxZone &box, + datetime toTime = NULL // +) +{ + // + bool result = false; + + // + box.Clean(); + toTime = NormalizeTime(toTime); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + box.to = toTime; + box.from = bar.time; + box.lower = bar.low; + box.symbol = bar.symbol; + box.period = bar.period; + box.upper = bar.GetDown(); + box.dir = X_DIRECTION_BULLISH; + box.type = "Support"; + + // + result = box.IsValid(); + if (!result) + { + box.Clean(); + } + + // + return result; +} + +/** + * Converts a Bar to Resistance Box ... + * + * @param bar: XOHCL, Specified Bar ... + * @param box: XBoxZone, destination Box ... + * @param toTime: datetime, Specified Box to Time ... + * + * @return ( bool ) + */ +bool ToResistanceBox( + XOHCL &bar, + XBoxZone &box, + datetime toTime = NULL // +) +{ + // + bool result = false; + + // + box.Clean(); + toTime = NormalizeTime(toTime); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + box.to = toTime; + box.from = bar.time; + box.upper = bar.high; + box.symbol = bar.symbol; + box.period = bar.period; + box.lower = bar.GetUp(); + box.dir = X_DIRECTION_BEARISH; + box.type = "Resistance"; + + // + result = box.IsValid(); + if (!result) + { + box.Clean(); + } + + // + return result; +} + // \ No newline at end of file