last works on pattern detector ...

This commit is contained in:
2025-09-17 08:58:58 +03:30
parent 21fe832447
commit c1da10ba3a
4 changed files with 795 additions and 245 deletions
@@ -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:
+90 -1
View File
@@ -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(
+417 -244
View File
@@ -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();
}
//
@@ -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;
}
//