This commit is contained in:
2025-09-25 18:36:56 +03:30
parent 696d3a55da
commit 4277b25b87
5 changed files with 942 additions and 17 deletions
@@ -23,6 +23,7 @@
// Imports ... // Imports ...
#include "../Classes/x-saherelm.base.class.mq5" #include "../Classes/x-saherelm.base.class.mq5"
#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" #include "../Classes/x-saherelm.x-bar.analyser.class.mq5"
#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5"
#include "../Libraries/x-saherelm.x-poi.lib.mq5" #include "../Libraries/x-saherelm.x-poi.lib.mq5"
// //
@@ -57,6 +58,180 @@ class XCMarketPatternDetector : public XCBase
// //
// Actions / Helpers ... // Actions / Helpers ...
//
// Analysers ...
/**
* Check for Price Touch Support Level ...
*
* @param bar: XOHCL, Specified Bar ...
* @param supportBar: XOHCL, reference to holds Zone Bar ...
* @param supportBox: XBoxZone, reference to holds Zone Box ...
* @param validationLength: int, Validation Length ...
* @param maxAllowedLoopback: int, Max Allowed Loopback to Detection ...
*
* @return ( bool )
*/
bool IsSupportTouched(
XOHCL &bar,
XOHCL &supportBar,
XBoxZone &supportBox,
int validationLength = 21,
int maxAllowedLoopback = 1500 //
)
{
//
bool result = false;
//
// Prepare ...
supportBar.Clean();
supportBox.Clean();
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Check Support Exists ...
result = HasSupport(
bar,
supportBar,
validationLength,
maxAllowedLoopback //
);
if (!result)
{
//
supportBar.Clean();
return result;
}
//
// Extract Support Box ...
result = ToSupportBox(
supportBar,
supportBox //
);
//
// Retrieve Previous Bar ...
XOHCL pBar;
result =
result &&
bar.GetPreviousBar(pBar);
//
// Chekc Price of Bar ...
result =
result &&
pBar.low < supportBox.upper;
//
// Cleanup Resources ...
if (!result)
{
//
supportBar.Clean();
supportBox.Clean();
}
pBar.Clean();
//
return result;
}
/**
* Check for Price Touch Resistance Level ...
*
* @param bar: XOHCL, Specified Bar ...
* @param supportBar: XOHCL, reference to holds Zone Bar ...
* @param supportBox: XBoxZone, reference to holds Zone Box ...
* @param validationLength: int, Validation Length ...
* @param maxAllowedLoopback: int, Max Allowed Loopback to Detection ...
*
* @return ( bool )
*/
bool IsResistanceTouched(
XOHCL &bar,
XOHCL &resistanceBar,
XBoxZone &resistanceBox,
int validationLength = 21,
int maxAllowedLoopback = 1500 //
)
{
//
bool result = false;
//
// Prepare ...
resistanceBar.Clean();
resistanceBox.Clean();
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Check Resistance Exists ...
result = HasResistance(
bar,
resistanceBar,
validationLength,
maxAllowedLoopback //
);
if (!result)
{
//
resistanceBar.Clean();
return result;
}
//
// Extract Resistance Box ...
result = ToResistanceBox(
resistanceBar,
resistanceBox //
);
//
// Retrieve Previous Bar ...
XOHCL pBar;
result =
result &&
bar.GetPreviousBar(pBar);
//
// Chekc Price of Bar ...
result =
result &&
pBar.high > resistanceBox.lower;
//
// Cleanup Resources ...
if (!result)
{
//
resistanceBar.Clean();
resistanceBox.Clean();
}
pBar.Clean();
//
return result;
}
//
// Detectors ...
/** /**
* Check Specified Bar is Momentum Bar or not ... * Check Specified Bar is Momentum Bar or not ...
* *
+154 -12
View File
@@ -462,7 +462,7 @@ void OnTick()
bool isInited = cBar.Init( bool isInited = cBar.Init(
_Symbol, _Symbol,
_Period, _Period,
1 // 0 //
); );
// //
// Here We Apply Custom Detecting ... // Here We Apply Custom Detecting ...
@@ -506,22 +506,164 @@ void OnTick()
if (marketStructure.support.IsValid() || marketStructure.resistance.IsValid()) if (marketStructure.support.IsValid() || marketStructure.resistance.IsValid())
{ {
// //
// Check Conditions ... XOHCL pBar;
datetime beforeTime = cBar.BeforeOn(); XOHCL p2Bar;
bool hasSupport = bool has = cBar.GetPreviousBar(pBar);
(marketStructure.support.IsValid() && has = has &&
marketStructure.support.from == beforeTime); pBar.GetPreviousBar(p2Bar);
bool hasResistance = if (!has)
(marketStructure.resistance.IsValid() && {
marketStructure.resistance.from == beforeTime); //
bool has = pBar.Clean();
hasSupport || p2Bar.Clean();
hasResistance; return;
}
// //
// bool isSupportTouched = marketStructure.isSupportTouched;
// bool isResistanceTouched = marketStructure.isResistanceTouched;
// has =
// isSupportTouched ||
// isResistanceTouched;
// if (!has)
// {
// //
// pBar.Clean();
// return;
// }
// //
// // Here we Have to Detect Previous Support or Resistance ...
// XOHCL prevZoneBar;
// XBoxZone prevZoneBox;
// //
// // Previous Support ...
// bool hasPrevSupport = isSupportTouched &&
// fima2Signaller
// .poiDetector
// .HasSupport(
// pBar,
// prevZoneBar,
// detectorConfig.supportAndResistanceValidationLength,
// detectorConfig.supportAndResistanceMaxAllowedLoopback //
// );
// if (hasPrevSupport)
// {
// hasPrevSupport = ToSupportBox(prevZoneBar, prevZoneBox, pBar.time);
// }
// //
// // Previous Resistance ...
// bool hasPrevResistance = isResistanceTouched &&
// fima2Signaller
// .poiDetector
// .HasSupport(
// pBar,
// prevZoneBar,
// detectorConfig.supportAndResistanceValidationLength,
// detectorConfig.supportAndResistanceMaxAllowedLoopback //
// );
// if (hasPrevResistance)
// {
// hasPrevResistance = ToResistanceBox(prevZoneBar, prevZoneBox, pBar.time);
// }
// //
// has = hasPrevSupport ||
// hasPrevResistance;
// if (!has)
// {
// //
// pBar.Clean();
// prevZoneBox.Clean();
// prevZoneBar.Clean();
// return;
// }
// //
// // Select Youngest ...
// int idx = -1;
// //
// if (hasPrevSupport)
// {
// //
// idx = GetYoungestBefore(
// marketStructure.support.from,
// fima2Signaller.poiDetector.supports //
// );
// has = IsValidIndex(idx);
// if (has)
// {
// //
// prevZoneBox.to = pBar.time;
// prevZoneBox = fima2Signaller.poiDetector.supports[idx];
// }
// }
// //
// if (hasPrevResistance)
// {
// //
// idx = GetYoungestBefore(
// marketStructure.resistance.from,
// fima2Signaller.poiDetector.resistances //
// );
// has = IsValidIndex(idx);
// if (has)
// {
// //
// prevZoneBox.to = pBar.time;
// prevZoneBox = fima2Signaller.poiDetector.resistances[idx];
// }
// }
//
// Draw Prev Zone ...
// XCBoxObject *iPrevZoneObj;
// prevZoneBox.to = pBar.time;
// has = fima2Signaller.poiDrawer.DrawBox(
// prevZoneBox,
// iPrevZoneObj //
// );
// if (has)
// {
// //
// XPOIStyle style;
// fima2Signaller.poiDrawer.GetBoxStyle(
// style,
// prevZoneBox.dir //
// );
// style.clr = clrYellow;
// fima2Signaller.poiDrawer.ApplyBoxStyle(
// iPrevZoneObj,
// style //
// );
// //
// style.Clean();
// eaDraws.Add(iPrevZoneObj);
// }
//
// Check Prev Zone is Breaked or not ...
//
if (has) if (has)
{ {
Print("Detected ..."); Print("Detected ...");
} }
//
// Cleanup Resources ...
pBar.Clean();
p2Bar.Clean();
// prevZoneBox.Clean();
// prevZoneBar.Clean();
} }
//
cBar.Clean();
} }
// //
+492 -1
View File
@@ -26,7 +26,6 @@
// //
// Extensions ... // Extensions ...
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
//| Oldest Detection | //| Oldest Detection |
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
@@ -976,6 +975,498 @@ int GetLowest(
} }
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Box |
//+------------------------------------------------------------------+
int GetOldestBefore(
datetime _time,
XBoxZone &source[] //
)
{
//
int result = -1;
//
// Validate ...
bool has =
HasChild(source) &&
IsSpecifiedValid(_time);
if (!has)
{
return result;
}
//
int idx = -1;
XBoxZone tmps[];
int count = ArraySize(source);
for (int i = 0; i < count; i++)
{
//
has = source[i].from < _time;
if (has)
{
//
AddIfNotExists(
source[i],
tmps //
);
}
}
has = HasChild(tmps);
if (!has)
{
//
result = -1;
return result;
}
//
idx = GetOldest(tmps);
has =
IsValidIndex(idx) &&
FindIndex(
result,
tmps[idx],
source //
);
//
// Cleanup Resources ...
SpecifiedClean(tmps);
//
return result;
}
int GetOldestAfter(
datetime _time,
XBoxZone &source[] //
)
{
//
int result = -1;
//
// Validate ...
bool has =
HasChild(source) &&
IsSpecifiedValid(_time);
if (!has)
{
return result;
}
//
int idx = -1;
XBoxZone tmps[];
int count = ArraySize(source);
for (int i = 0; i < count; i++)
{
//
has = source[i].from > _time;
if (has)
{
//
AddIfNotExists(
source[i],
tmps //
);
}
}
has = HasChild(tmps);
if (!has)
{
//
result = -1;
return result;
}
//
idx = GetOldest(tmps);
has =
IsValidIndex(idx) &&
FindIndex(
result,
tmps[idx],
source //
);
//
// Cleanup Resources ...
SpecifiedClean(tmps);
//
return result;
}
int GetYoungestBefore(
datetime _time,
XBoxZone &source[] //
)
{
//
int result = -1;
//
// Validate ...
bool has =
HasChild(source) &&
IsSpecifiedValid(_time);
if (!has)
{
return result;
}
//
int idx = -1;
XBoxZone tmps[];
int count = ArraySize(source);
for (int i = 0; i < count; i++)
{
//
has = source[i].from < _time;
if (has)
{
//
AddIfNotExists(
source[i],
tmps //
);
}
}
has = HasChild(tmps);
if (!has)
{
//
result = -1;
return result;
}
//
idx = GetYoungest(tmps);
has =
IsValidIndex(idx) &&
FindIndex(
result,
tmps[idx],
source //
);
//
// Cleanup Resources ...
SpecifiedClean(tmps);
//
return result;
}
int GetYoungestAfter(
datetime _time,
XBoxZone &source[] //
)
{
//
int result = -1;
//
// Validate ...
bool has =
HasChild(source) &&
IsSpecifiedValid(_time);
if (!has)
{
return result;
}
//
int idx = -1;
XBoxZone tmps[];
int count = ArraySize(source);
for (int i = 0; i < count; i++)
{
//
has = source[i].from > _time;
if (has)
{
//
AddIfNotExists(
source[i],
tmps //
);
}
}
has = HasChild(tmps);
if (!has)
{
//
result = -1;
return result;
}
//
idx = GetYoungest(tmps);
has =
IsValidIndex(idx) &&
FindIndex(
result,
tmps[idx],
source //
);
//
// Cleanup Resources ...
SpecifiedClean(tmps);
//
return result;
}
int GetHighestAbove(
double _value,
XBoxZone &source[] //
)
{
//
int result = -1;
//
// Validate ...
bool has =
HasChild(source) &&
NotEmptyZero(_value);
if (!has)
{
return result;
}
//
int idx = -1;
XBoxZone tmps[];
int count = ArraySize(source);
for (int i = 0; i < count; i++)
{
//
has = source[i].upper > _value;
if (has)
{
//
AddIfNotExists(
source[i],
tmps //
);
}
}
has = HasChild(tmps);
if (!has)
{
//
result = -1;
return result;
}
//
idx = GetHighest(tmps);
has =
IsValidIndex(idx) &&
FindIndex(
result,
tmps[idx],
source //
);
//
// Cleanup Resources ...
SpecifiedClean(tmps);
//
return result;
}
int GetHighestBelow(
double _value,
XBoxZone &source[] //
)
{
//
int result = -1;
//
// Validate ...
bool has =
HasChild(source) &&
NotEmptyZero(_value);
if (!has)
{
return result;
}
//
int idx = -1;
XBoxZone tmps[];
int count = ArraySize(source);
for (int i = 0; i < count; i++)
{
//
has = source[i].upper < _value;
if (has)
{
//
AddIfNotExists(
source[i],
tmps //
);
}
}
has = HasChild(tmps);
if (!has)
{
//
result = -1;
return result;
}
//
idx = GetHighest(tmps);
has =
IsValidIndex(idx) &&
FindIndex(
result,
tmps[idx],
source //
);
//
// Cleanup Resources ...
SpecifiedClean(tmps);
//
return result;
}
int GetLowestAbove(
double _value,
XBoxZone &source[] //
)
{
//
int result = -1;
//
// Validate ...
bool has =
HasChild(source) &&
NotEmptyZero(_value);
if (!has)
{
return result;
}
//
int idx = -1;
XBoxZone tmps[];
int count = ArraySize(source);
for (int i = 0; i < count; i++)
{
//
has = source[i].lower > _value;
if (has)
{
//
AddIfNotExists(
source[i],
tmps //
);
}
}
has = HasChild(tmps);
if (!has)
{
//
result = -1;
return result;
}
//
idx = GetLowest(tmps);
has =
IsValidIndex(idx) &&
FindIndex(
result,
tmps[idx],
source //
);
//
// Cleanup Resources ...
SpecifiedClean(tmps);
//
return result;
}
int GetLowestBelow(
double _value,
XBoxZone &source[] //
)
{
//
int result = -1;
//
// Validate ...
bool has =
HasChild(source) &&
NotEmptyZero(_value);
if (!has)
{
return result;
}
//
int idx = -1;
XBoxZone tmps[];
int count = ArraySize(source);
for (int i = 0; i < count; i++)
{
//
has = source[i].lower < _value;
if (has)
{
//
AddIfNotExists(
source[i],
tmps //
);
}
}
has = HasChild(tmps);
if (!has)
{
//
result = -1;
return result;
}
//
idx = GetLowest(tmps);
has =
IsValidIndex(idx) &&
FindIndex(
result,
tmps[idx],
source //
);
//
// Cleanup Resources ...
SpecifiedClean(tmps);
//
return result;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
//| Sort | //| Sort |
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
@@ -39,6 +39,12 @@ class XCXFIMAPOIDetector : public XCMarketPatternDetector
XCBarAnalyser *barAnalyser; // Bar Analyser ... XCBarAnalyser *barAnalyser; // Bar Analyser ...
XCXFIMAHelper *fimaHelper; // XFIMA Helper ... XCXFIMAHelper *fimaHelper; // XFIMA Helper ...
//
XBoxZone obs[];
XBoxZone fvgs[];
XBoxZone supports[];
XBoxZone resistances[];
// //
// Constructor ... // Constructor ...
XCXFIMAPOIDetector( XCXFIMAPOIDetector(
@@ -475,6 +481,12 @@ class XCXFIMAPOIDetector : public XCMarketPatternDetector
*/ */
void Destroy() void Destroy()
{ {
//
SpecifiedClean(obs);
SpecifiedClean(fvgs);
SpecifiedClean(supports);
SpecifiedClean(resistances);
// //
delete barAnalyser; delete barAnalyser;
ZeroMemory(barAnalyser); ZeroMemory(barAnalyser);
@@ -515,6 +527,7 @@ class XCXFIMAPOIDetector : public XCMarketPatternDetector
// //
bool has = false; bool has = false;
int maxAllowedCollecting = 50;
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
// //
@@ -539,6 +552,33 @@ class XCXFIMAPOIDetector : public XCMarketPatternDetector
{ {
structure.ob.Clean(); structure.ob.Clean();
} }
//
// Detect Touches ...
if (isOB)
{
//
AddIfNotExists(
structure.ob,
obs,
maxAllowedCollecting //
);
//
XOHCL pBar;
bool has = forBar.GetPreviousBar(pBar);
if (has)
{
//
structure.isOBTouched =
isBullishOB
? pBar.low < structure.ob.upper
: pBar.high > structure.ob.lower;
}
//
pBar.Clean();
}
} }
// //
@@ -552,14 +592,41 @@ class XCXFIMAPOIDetector : public XCMarketPatternDetector
structure.fvg, structure.fvg,
config.fvgLoopback // config.fvgLoopback //
); );
bool isBullishOB = isFVG && bool isBullishFVG = isFVG &&
IsSpecifiedBullish(iDir); IsSpecifiedBullish(iDir);
bool isBearishOB = isFVG && bool isBearishFVG = isFVG &&
IsSpecifiedBearish(iDir); IsSpecifiedBearish(iDir);
if (!isFVG) if (!isFVG)
{ {
structure.fvg.Clean(); structure.fvg.Clean();
} }
//
// Detect Touches ...
if (isFVG)
{
//
AddIfNotExists(
structure.fvg,
fvgs,
maxAllowedCollecting //
);
//
XOHCL pBar;
bool has = forBar.GetPreviousBar(pBar);
if (has)
{
//
structure.isFVGTouched =
isBullishFVG
? pBar.low < structure.fvg.upper
: pBar.high > structure.fvg.lower;
}
//
pBar.Clean();
}
} }
// //
@@ -796,10 +863,29 @@ class XCXFIMAPOIDetector : public XCMarketPatternDetector
has = ToSupportBox(support, supportBox); has = ToSupportBox(support, supportBox);
if (has) if (has)
{ {
//
AddIfNotExists(
supportBox,
supports,
maxAllowedCollecting //
);
//
structure.support = supportBox; structure.support = supportBox;
} }
// //
// Check for Support Touches ...
XOHCL pBar;
has = has &&
forBar.GetPreviousBar(pBar);
if (has)
{
structure.isSupportTouched = pBar.low < supportBox.upper;
}
//
pBar.Clean();
supportBox.Clean(); supportBox.Clean();
} }
support.Clean(); support.Clean();
@@ -824,10 +910,29 @@ class XCXFIMAPOIDetector : public XCMarketPatternDetector
has = ToResistanceBox(resistance, resistanceBox); has = ToResistanceBox(resistance, resistanceBox);
if (has) if (has)
{ {
//
AddIfNotExists(
resistanceBox,
resistances,
maxAllowedCollecting //
);
//
structure.resistance = resistanceBox; structure.resistance = resistanceBox;
} }
// //
// Check for Resistance Touches ...
XOHCL pBar;
has = has &&
forBar.GetPreviousBar(pBar);
if (has)
{
structure.isResistanceTouched = pBar.high > resistanceBox.upper;
}
//
pBar.Clean();
resistanceBox.Clean(); resistanceBox.Clean();
} }
resistance.Clean(); resistance.Clean();
@@ -360,6 +360,12 @@ struct XFIMAMarketStructure
XBoxZone support; XBoxZone support;
XBoxZone resistance; XBoxZone resistance;
//
bool isOBTouched;
bool isFVGTouched;
bool isSupportTouched;
bool isResistanceTouched;
// //
// Analysis ... // Analysis ...
XPivotAnalysis pvAnalysis; XPivotAnalysis pvAnalysis;
@@ -408,6 +414,12 @@ struct XFIMAMarketStructure
support.Clean(); support.Clean();
resistance.Clean(); resistance.Clean();
//
isOBTouched = false;
isFVGTouched = false;
isSupportTouched = false;
isResistanceTouched = false;
// //
bar.Clean(); bar.Clean();
flagSwing.Clean(); flagSwing.Clean();