Files
MQL5Data/Documents/BKP/x-saherelm.xfima.signaller.class copy.mq5
T
2025-10-01 05:10:42 +03:30

1697 lines
44 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Class
// -------------------------------------------------
// Name: XCXFIMASignaller ...
// Description: XFIMA Signaller Class ...
//
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
//
// Global Properties ...
#property library
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://saherelm.ir"
#property version "1.00"
#property description "SaherElm XFIMA Signaller Class"
#property strict
//
// Imports ...
#include "../../Classes/x-saherelm.x-signaller.class.mq5"
#include "../../Helpers/x-saherelm.xfima.helper.mq5"
#include "../Classes/x-saherelm.xfima.x-poi.detector.class.mq5"
#include "../Classes/x-saherelm.xfima.x-poi.drawer.class.mq5"
//
// Implementation ...
//
// Base XFIMA base Signaller ...
class XCXFIMABaseSignaller : public XCBaseSignaller
{
//
// Public ...
public:
//
// Props ...
//
XFIMAInputs fimaInputs; // XFIMA Inputs ...
XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ...
XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ...
XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ...
//
// Constructor ...
XCXFIMABaseSignaller(
string _name, // Name ...
string _symbol, // Symbol ...
ENUM_TIMEFRAMES _period, // Period ...
XFIMAInputs &_fimaInputs, // XFIMAInputs ...
bool _processAllTicks = false, // Process All Ticks ...
double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ...
double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ...
double _defaultSignalVolume = 0.01 // Default Signal Volume ...
) : XCBaseSignaller(_name,
_symbol,
_period,
_processAllTicks,
_defaultSignalR2R,
_defaultSignalRiskInPoint,
_defaultSignalVolume //
)
{
//
// Instantiating XFIMA Indicator Helper Class ...
if (_fimaInputs.IsValid())
{
//
fimaHelper = new XCXFIMAHelper();
bool isInited = fimaHelper.Init(
_symbol,
_period,
_fimaInputs //
);
if (isInited)
{
fimaInputs = _fimaInputs;
}
else
{
//
delete fimaHelper;
ZeroMemory(fimaHelper);
}
}
//
poiDrawer = new XCXFIMAPOIDrawer();
poiDetector = new XCXFIMAPOIDetector(fimaHelper);
}
//
// Deconstructor ...
~XCXFIMABaseSignaller()
{
Destroy();
}
//
// Overrides ...
//
// Actions ...
/**
* Destroy ...
*/
void Destroy()
{
//
BeforeDestroy();
//
fimaInputs.Clean();
//
delete fimaHelper;
ZeroMemory(fimaHelper);
//
delete poiDrawer;
ZeroMemory(poiDrawer);
//
delete poiDetector;
ZeroMemory(poiDetector);
}
//
// Virtuals ...
/**
* Before Destroy ...
*/
void virtual BeforeDestroy()
{
}
/**
* Processing Tick ...
*
* @param barIndex: int, Specified Bar Index ...
*/
virtual void ProcessTick(int barIndex = 0)
{
}
/**
* Processing New Bar ...
*
* @param barIndex: int, Specified Bar Index ...
*/
virtual void ProcessNewBar(int barIndex = 0)
{
}
/**
* Check Guards Based on MarketConditions ...
*
* @param guards: XGuard[]
* @param barIndex: int
*
* @return ( int )
*/
int virtual CheckForGuard(
XGuard &guards[],
int barIndex = 0 //
)
{
//
int result = 0;
//
SpecifiedClean(guards);
//
result = ArraySize(guards);
//
return result;
}
/**
* Check Additional Validations on Childs Instances ...
*
* @return ( bool virtual )
*/
bool virtual CheckAdditionslSignallerValidations()
{
//
bool result = false;
//
// Validate Fima Helper Requirements ...
result = fimaInputs.IsValid() &&
fimaHelper != NULL &&
poiDetector != NULL;
//
return result;
}
/**
* Normalizing Signal by Signaller Custom Props ...
*
* @param signal: XSignal ...
*/
void virtual NormalizeSignal(XSignal &signal)
{
}
//
// Protected ...
protected:
//
//
// Protected Actions ...
/**
* Check Specified Bar has Pattern or not ...
*
* @param bar: XOHCL, reference to Specified Bar ...
* @param name: string, reference to holds Detected Patterns Name ...
* @param dir: ENUM_X_DIRECTION, reference to holds Detected Patterns Direction ...
* @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ...
*
* @return ( bool )
*/
bool HasPattern(
XOHCL &bar,
string &patternName,
ENUM_X_DIRECTION &patternDir,
XFIMAMarketStructure &structure //
)
{
//
bool result = false;
//
// Prepare ...
patternName = NULL;
patternDir = X_DIRECTION_NONE;
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Check Required Pattern Exists ...
bool hasPinnedBar = HasDirection(structure.pinnedDir);
bool hasEngulfedBar = HasDirection(structure.engulfedDir);
bool hasFlagPattern = HasDirection(structure.flagPatternDir);
bool hasStarPattern = HasDirection(structure.starPatternDir);
bool hasRisingPattern = HasDirection(structure.risingPatternDir);
bool hasPiercingPattern = HasDirection(structure.piercingPatternDir);
bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir);
//
// Check Bar Pattern Exists ...
// and Select Pattern Direction and Price and Price Type ...
result = hasPinnedBar ||
hasEngulfedBar ||
hasFlagPattern ||
hasStarPattern ||
hasSignalKeyBar ||
hasRisingPattern ||
hasPiercingPattern;
//
if (result)
{
//
if (hasPinnedBar)
{
//
patternDir = structure.pinnedDir;
patternName = "XPinned_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time));
}
else if (hasEngulfedBar)
{
//
patternDir = structure.engulfedDir;
patternName = "XEngulfed_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time));
}
else if (hasFlagPattern)
{
//
patternDir = structure.flagPatternDir;
patternName = "XFlag_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time));
}
else if (hasStarPattern)
{
//
patternDir = structure.starPatternDir;
patternName = "XStar_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time));
}
else if (hasSignalKeyBar)
{
//
patternDir = structure.risingPatternDir;
patternName = "XRising_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time));
}
else if (hasRisingPattern)
{
//
patternDir = structure.piercingPatternDir;
patternName = "XPiercing_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time));
}
else if (hasPiercingPattern)
{
//
patternDir = structure.signalKeyBarPatternDir;
patternName = "XSignalKey_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time));
}
}
//
result =
result &&
IsXValid(patternName) &&
HasDirection(patternDir);
//
return result;
}
/**
* Validate a Pattern based on MA Band ...
*
* @param bar: XOHCL, reference to Pattern Bar ...
* @param patternName: string, detected pattern's name ...
* @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ...
* @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ...
*
* @return ( bool )
*/
bool ValidatePatternBasedOnMABand(
XOHCL &bar,
string patternName,
ENUM_X_DIRECTION patternDir,
XFIMAConditions &fimaConditions //
)
{
//
bool result = false;
//
// Validate ...
result = bar.IsValid() &&
IsXValid(patternName) &&
HasDirection(patternDir);
if (!result)
{
return result;
}
//
// Define Requirements ...
bool isBullish = false;
bool isBearish = false;
double iPrice = EMPTY_VALUE;
double iPriceEdge = EMPTY_VALUE;
ENUM_X_PRICE iPriceType = X_PRICE_NONE;
ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE;
//
// Calculating Price and Price Types ...
//
isBullish = IsXBullish(patternDir);
isBearish = IsXBearish(patternDir);
//
iPriceType = isBullish
? X_PRICE_DOWN
: X_PRICE_UP;
//
iPriceEdgeType = isBullish
? X_PRICE_LOW
: X_PRICE_HIGH;
//
iPrice = bar.GetPrice(iPriceType);
iPriceEdge = bar.GetPrice(iPriceEdgeType);
//
// Validate ...
result =
NotEmptyZero(iPrice) &&
IsXValid(iPriceType) &&
NotEmptyZero(iPriceEdge) &&
IsXValid(iPriceEdgeType) &&
((isBullish && !isBearish) ||
(isBearish && !isBullish));
if (!result)
{
return result;
}
//
// Validate Pattern based on MA Band ...
//
// Retrieve MA Band for Validation ...
double iMABandUpper = fimaConditions.maBandUpperBuffer[0];
double iMABandLower = fimaConditions.maBandLowerBuffer[0];
//
// Validate by Edge Price ...
result =
NotEmptyZero(iMABandUpper) &&
NotEmptyZero(iMABandLower) &&
(isBullish
? iPriceEdge < iMABandLower
: iPriceEdge > iMABandUpper);
if (!result)
{
return result;
}
//
return result;
}
//
// Private ...
private:
//
};
//
// XFIMA Strategy 1 Signaller Class ...
class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller
{
//
// Public ...
public:
//
// Props ...
int fvgLookupLenght; // Maximum Lenght for Looking up FVG before Crosses
//
// Constructor ...
XCXFIMAStrategy1Signaller(
string _symbol, // Symbol ...
ENUM_TIMEFRAMES _period, // Period ...
XFIMAInputs &_fimaInputs, // XFIMAInputs ...
bool _processAllTicks = false, // Process All Ticks ...
double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ...
double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ...
double _defaultSignalVolume = 0.01 // Default Signal Volume ...
) : XCXFIMABaseSignaller("XFIMA1",
_symbol,
_period,
_fimaInputs,
_processAllTicks,
_defaultSignalR2R,
_defaultSignalRiskInPoint,
_defaultSignalVolume //
)
{
//
fvgLookupLenght = 5;
}
//
// Overrides ...
/**
* Processing Tick ...
*
* @param barIndex: int, Specified Bar Index ...
*/
virtual void ProcessTick(int barIndex = 0)
{
}
/**
* Processing New Bar ...
*
* @param barIndex: int, Specified Bar Index ...
*/
virtual void ProcessNewBar(int barIndex = 0)
{
//
// Normalize ...
barIndex = NormalizeInt(barIndex, 0);
//
XOHCL bar;
XSignal signal;
bool has = false;
int cIdx = barIndex + 1;
int pIdx = cIdx + 1;
ENUM_X_DIRECTION signalDir = X_DIRECTION_NONE;
//
// Initialize Bar as CBar ...
has = bar.Init(
symbol,
period,
cIdx //
);
if (!has)
{
//
bar.Clean();
return;
}
//
// Retrieve Conditions ...
XFIMAConditions fimaConditions;
has = fimaHelper.GetConditions(
fimaConditions,
barIndex,
10 // Loopback ...
);
if (!has)
{
//
bar.Clean();
fimaConditions.Clean();
//
return;
}
//
// Analyse Conditions for Finding Signal ...
//
// TODO: Remove this ...
//
bool isFastCrossedOverSlow =
fimaConditions.maFastBuffer[cIdx] > fimaConditions.maSlowBuffer[cIdx] &&
fimaConditions.maFastBuffer[pIdx] < fimaConditions.maSlowBuffer[pIdx];
//
bool isFastCrossedUnderSlow =
fimaConditions.maFastBuffer[cIdx] < fimaConditions.maSlowBuffer[cIdx] &&
fimaConditions.maFastBuffer[pIdx] > fimaConditions.maSlowBuffer[pIdx];
//
has =
isFastCrossedOverSlow ||
isFastCrossedUnderSlow;
if (has)
{
//
// Do Conditions Validating ...
// TODO: Igmore All Validations for Testing Purposes ...
//
// Validate MA Positions ...
double iFastMa = fimaConditions.maFastBuffer[cIdx];
double iSlowMa = fimaConditions.maSlowBuffer[cIdx];
double iFiboUpper = fimaConditions.fiboUpperBuffer[cIdx];
double iFiboLower = fimaConditions.fiboLowerBuffer[cIdx];
//
// Checking Has FVG ...
XBoxZone fvg;
ENUM_X_DIRECTION fvgDir;
bool hasFVG = patternDetector.HasFVG(
bar,
fvgDir,
fvg,
fvgLookupLenght //
);
//
// Checking Crossed On Shadow ...
//
bool isCrossedOverHappensOnShadow =
isFastCrossedOverSlow &&
iFastMa <= bar.GetDown() &&
iFastMa >= bar.low;
//
bool isCrossedUnderHappensOnShadow =
isFastCrossedUnderSlow &&
iFastMa <= bar.high &&
iFastMa >= bar.GetUp();
//
// Bullish Validation ...
bool isBullish =
//
// Has Cross ...
isFastCrossedOverSlow
//
// &&
// //
// // Cross Places Based on Fibo ...
// MathMax(iFastMa, iSlowMa) < iFiboLower
// //
// &&
// //
// (
// //
// // Checking FVG ...
// (hasFVG &&
// fvg.IsBullish())
// //
// ||
// //
// // Checking Crossed Place ...
// isCrossedOverHappensOnShadow
// //
// )
// //
;
//
// Bearish Validation ...
bool isBearish =
//
// Has Cross ...
isFastCrossedUnderSlow
//
// &&
// //
// // Cross Places Based on Fibo ...
// MathMin(iFastMa, iSlowMa) > iFiboUpper
// //
// &&
// //
// (
// //
// // Checking FVG ...
// (hasFVG &&
// fvg.IsBearish())
// //
// ||
// //
// // Checking Crossed Place ...
// isCrossedUnderHappensOnShadow
// //
// )
// //
;
//
has =
(isBullish && !isBearish) ||
(isBearish && !isBullish);
if (has)
{
//
signalDir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
}
}
//
// Check Signal Founded ...
has = HasDirection(signalDir);
if (has)
{
//
// Prepare Founded Signal ...
XTarget targets[];
has = PrepareSignal(
signal,
signalDir,
targets //
);
if (has)
{
//
// Notify On Signal Event ...
NotifySignalEventListeners(signal);
}
}
//
// Cleanup Resources ...
bar.Clean();
signal.Clean();
fimaConditions.Clean();
}
/**
* Check Guards Based on MarketConditions ...
*
* @param guards: XGuard[]
* @param barIndex: int
*
* @return ( int )
*/
int virtual CheckForGuard(
XGuard &guards[],
int barIndex = 0 //
)
{
//
int result = 0;
//
SpecifiedClean(guards);
//
result = ArraySize(guards);
//
return result;
}
//
// Private ...
private:
//
// Props ...
//
// Lookup FVG ...
bool LookupFVG(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
XBoxZone &fvgBox //
)
{
//
bool result = false;
//
return result;
}
//
};
//
// XFIMA Strategy 2 Signaller Class ...
class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller
{
//
// Public ...
public:
//
// Props ...
XFIMAPatternDetectorConfig analyserConfig;
//
// Constructor ...
XCXFIMAStrategy2Signaller(
string _symbol, // Symbol ...
ENUM_TIMEFRAMES _period, // Period ...
XFIMAInputs &_fimaInputs, // XFIMAInputs ...
bool _processAllTicks = false, // Process All Ticks ...
double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ...
double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ...
double _defaultSignalVolume = 0.01 // Default Signal Volume ...
) : XCXFIMABaseSignaller("XFIMA2",
_symbol,
_period,
_fimaInputs,
_processAllTicks,
_defaultSignalR2R,
_defaultSignalRiskInPoint,
_defaultSignalVolume //
)
{
//
// Configure Detector ...
//
analyserConfig.Default();
analyserConfig.validMACrossDiffMultiplier = 4;
//
analyserConfig.FullDetect();
}
//
// Deconstructor ...
~XCXFIMAStrategy2Signaller()
{
//
Destroy();
//
analyserConfig.Clean();
}
//
// Overrides ...
/**
* Processing Tick ...
*
* @param barIndex: int, Specified Bar Index ...
*/
virtual void ProcessTick(int barIndex = 0)
{
}
/**
* Processing New Bar ...
*
* @param barIndex: int, Specified Bar Index ...
*/
virtual void ProcessNewBar(int barIndex = 0)
{
//
// Normalize ...
barIndex = NormalizeInt(barIndex, 0);
//
XOHCL iBar;
int count = 0;
XBoxZone iZone;
XSignal iSignal;
bool has = false;
XTarget targets[];
string iName = NULL;
XBoxZone supports[];
XBoxZone resistances[];
bool isBullish = false;
bool isBearish = false;
int numberOfPivots = 25;
XFIMAConditions iFIMAConditions;
XFIMAMarketStructure iStructure;
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
//
XPivot pvPivots[];
string pvTrendName = "XXIFMA2PVTrend";
CChartObjectTrend *pvTrendLine = NULL;
ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE;
//
XPivot zgPivots[];
string zgTrendName = "XFIMA2ZGTrend";
CChartObjectTrend *zgTrendLine = NULL;
ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE;
//
// Initialize Bar as CBar ...
has = iBar.Init(
symbol,
period,
barIndex //
);
if (!has)
{
//
iBar.Clean();
return;
}
//
// Retrieve Conditions ...
has = fimaHelper.GetConditions(
iFIMAConditions,
barIndex,
10 // Loopback ...
);
if (!has)
{
//
iBar.Clean();
iFIMAConditions.Clean();
//
return;
}
//
// Analyse Market ...
poiDetector.AnalyseMarket(
iBar,
iStructure,
analyserConfig //
);
//
// Collect Support and Resistance Zones and Validate by them ...
//
// PV Trend Line ...
bool hasPVAnalysis = iStructure.pvAnalysis.IsValid();
if (hasPVAnalysis)
{
//
// Support ...
XBoxZone supportBox;
has = iStructure.pvAnalysis.HasSupportBox(supportBox);
if (has)
{
//
supportBox.to = iBar.time;
AddIfNotExists(
supportBox,
supports //
);
}
//
// Resistance ...
XBoxZone resistanceBox;
has = iStructure.pvAnalysis.HasResistanceBox(resistanceBox);
if (has)
{
//
resistanceBox.to = iBar.time;
AddIfNotExists(
resistanceBox,
supports //
);
}
//
// Pivots ...
XPivot pivots[];
count = poiDetector.ExtractPVPivots(
pivots,
barIndex,
numberOfPivots //
);
has = IsValidSize(count);
//
// Sort ...
Sort(
pivots,
X_SORT_BY_DATE,
X_DIRECTION_BEARISH //
);
//
// Remove Newest ...
ArrayRemove(
pivots,
0,
1 //
);
//
// Check Trend ...
if (has)
{
//
XPivot highs[];
int highsCount = ExtractPivots(
highs,
pivots,
X_PIVOT_TYPE_PEAK //
);
Sort(
highs,
X_SORT_BY_DATE,
X_DIRECTION_BEARISH //
);
//
XPivot lows[];
int lowsCount = ExtractPivots(
lows,
pivots,
X_PIVOT_TYPE_VALE //
);
Sort(
lows,
X_SORT_BY_DATE,
X_DIRECTION_BEARISH //
);
//
// Check Highs and Lows ...
has = IsValidSize(lowsCount) &&
IsValidSize(highsCount) &&
lowsCount >= 2 &&
highsCount >= 2;
if (has)
{
//
// Try to Get Market Strucutre ...
//
bool hasLowerHigh = highs[0].value < highs[1].value;
bool hasLowerLow = lows[0].value < lows[1].value;
//
bool hasHigherHigh = highs[0].value > highs[1].value;
bool hasHigherLow = lows[0].value > lows[1].value;
//
pvTrend =
(hasHigherHigh &&
hasHigherLow)
? X_DIRECTION_BULLISH
: (hasLowerHigh &&
hasLowerLow)
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
has = HasDirection(pvTrend);
if (has)
{
//
// Select Swings for Trend Line ...
XOHCL tmpBar;
int llIDX = -1;
int hhIDX = -1;
datetime toTime = NULL;
datetime fromTime = NULL;
double toPrice = EMPTY_VALUE;
color trendColor = CLR_NONE;
double fromPrice = EMPTY_VALUE;
if (IsSpecifiedBullish(pvTrend))
{
//
llIDX = GetLowest(lows);
hhIDX = GetHighest(lows);
//
trendColor = clrAqua;
//
toTime = lows[hhIDX].time;
toPrice = lows[hhIDX].value;
//
fromTime = lows[llIDX].time;
fromPrice = lows[llIDX].value;
}
else
{
//
llIDX = GetLowest(highs);
hhIDX = GetHighest(highs);
//
trendColor = clrMagenta;
//
toTime = highs[llIDX].time;
toPrice = highs[llIDX].value;
//
fromTime = highs[hhIDX].time;
fromPrice = highs[hhIDX].value;
}
//
// Check Requirements for Trend ...
has =
NotEmptyZero(toPrice) &&
NotEmptyZero(fromPrice) &&
IsSpecifiedValid(toTime) &&
IsSpecifiedValid(fromTime);
if (has)
{
//
has = poiDrawer.DrawTrendLine(
fromPrice,
fromTime,
toPrice,
toTime,
pvTrendLine,
pvTrendName,
true // Ray Right ...
);
if (has)
{
pvTrendLine.Color(trendColor);
}
}
//
// Cleanup Resources ...
tmpBar.Clean();
}
//
if (!has)
{
SpecifiedClean(pivots);
}
}
//
// Cleanup Resources ...
SpecifiedClean(lows);
SpecifiedClean(highs);
}
//
has = HasChild(pivots);
if (has)
{
//
Copy(
pivots,
pvPivots //
);
}
//
// Cleanup Resources ...
SpecifiedClean(pivots);
}
//
// ZigZag Trend Line ...
bool hasZGAnalysis = iStructure.zigzagAnalysis.IsValid();
if (hasZGAnalysis)
{
//
// Support ...
XBoxZone supportBox;
has = iStructure.zigzagAnalysis.HasSupportBox(supportBox);
if (has)
{
//
supportBox.to = iBar.time;
AddIfNotExists(
supportBox,
supports //
);
}
//
// Resistance ...
XBoxZone resistanceBox;
has = iStructure.zigzagAnalysis.HasResistanceBox(resistanceBox);
if (has)
{
//
resistanceBox.to = iBar.time;
AddIfNotExists(
resistanceBox,
supports //
);
}
//
// Pivots ...
XPivot pivots[];
count = poiDetector.ExtractZigZagPivots(
pivots,
barIndex,
numberOfPivots //
);
has = IsValidSize(count);
//
// Sort ...
Sort(
pivots,
X_SORT_BY_DATE,
X_DIRECTION_BEARISH //
);
//
// Remove Newest ...
ArrayRemove(
pivots,
0,
1 //
);
//
// Check Trend ...
if (has)
{
//
XPivot highs[];
int highsCount = ExtractPivots(
highs,
pivots,
X_PIVOT_TYPE_PEAK //
);
Sort(
highs,
X_SORT_BY_DATE,
X_DIRECTION_BEARISH //
);
//
XPivot lows[];
int lowsCount = ExtractPivots(
lows,
pivots,
X_PIVOT_TYPE_VALE //
);
Sort(
lows,
X_SORT_BY_DATE,
X_DIRECTION_BEARISH //
);
//
// Check Highs and Lows ...
has = IsValidSize(lowsCount) &&
IsValidSize(highsCount) &&
lowsCount >= 2 &&
highsCount >= 2;
if (has)
{
//
// Try to Get Market Strucutre ...
//
bool hasLowerHigh = highs[0].value < highs[1].value;
bool hasLowerLow = lows[0].value < lows[1].value;
//
bool hasHigherHigh = highs[0].value > highs[1].value;
bool hasHigherLow = lows[0].value > lows[1].value;
//
zgTrend =
(hasHigherHigh &&
hasHigherLow)
? X_DIRECTION_BULLISH
: (hasLowerHigh &&
hasLowerLow)
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
has = HasDirection(zgTrend);
if (has)
{
//
// Select Swings for Trend Line ...
XOHCL tmpBar;
int llIDX = -1;
int hhIDX = -1;
datetime toTime = NULL;
datetime fromTime = NULL;
double toPrice = EMPTY_VALUE;
color trendColor = CLR_NONE;
double fromPrice = EMPTY_VALUE;
if (IsSpecifiedBullish(zgTrend))
{
//
llIDX = GetLowest(lows);
hhIDX = GetHighest(lows);
//
trendColor = clrAqua;
//
toTime = lows[hhIDX].time;
toPrice = lows[hhIDX].value;
//
fromTime = lows[llIDX].time;
fromPrice = lows[llIDX].value;
}
else
{
//
llIDX = GetLowest(highs);
hhIDX = GetHighest(highs);
//
trendColor = clrMagenta;
//
toTime = highs[llIDX].time;
toPrice = highs[llIDX].value;
//
fromTime = highs[hhIDX].time;
fromPrice = highs[hhIDX].value;
}
//
// Check Requirements for Trend ...
has =
NotEmptyZero(toPrice) &&
NotEmptyZero(fromPrice) &&
IsSpecifiedValid(toTime) &&
IsSpecifiedValid(fromTime);
if (has)
{
//
has = poiDrawer.DrawTrendLine(
fromPrice,
fromTime,
toPrice,
toTime,
zgTrendLine,
zgTrendName,
true // Ray Right ...
);
if (has)
{
zgTrendLine.Color(trendColor);
}
}
//
// Cleanup Resources ...
tmpBar.Clean();
}
//
if (!has)
{
SpecifiedClean(pivots);
}
}
//
// Cleanup Resources ...
SpecifiedClean(lows);
SpecifiedClean(highs);
}
//
has = HasChild(pivots);
if (has)
{
//
Copy(
pivots,
zgPivots //
);
}
//
// Cleanup Resources ...
SpecifiedClean(pivots);
}
//
// Support ...
bool hasSupport = iStructure.support.IsValid();
if (hasSupport)
{
//
iStructure.support.to = iBar.time;
AddIfNotExists(
iStructure.support,
supports //
);
}
//
// Resistance ...
bool hasResistance = iStructure.resistance.IsValid();
if (hasResistance)
{
//
iStructure.resistance.to = iBar.time;
AddIfNotExists(
iStructure.resistance,
resistances //
);
}
//
// Disable Signallers ...
has = false;
//
// Strategy 1 ...
// Works on Support or Resistances Areas ...
// has = Strategy1HasSignal(
// iBar,
// iZone,
// supports,
// resistances,
// iDir,
// iStructure,
// iFIMAConditions //
// );
//
// Strategy 2 ...
// Works on MA Crosses ...
has = Strategy2HasSignal(
iBar,
iZone,
supports,
resistances,
iDir,
iStructure,
iFIMAConditions //
);
//
has = HasDirection(iDir);
if (has)
{
//
isBullish = IsXBullish(iDir);
isBearish = IsXBearish(iDir);
//
// TODO: Provided SL ...
double _point = GetPoints(iBar.symbol);
double slAddition = 5 * _point;
double slPrice =
isBullish
? iZone.lower - slAddition
: iZone.upper + slAddition;
//
// Prepare Founded Signal ...
has = PrepareSignal(
iSignal,
iDir,
targets,
0, // Use Default R2R ...
slPrice, // Provided Price for SL ...
0 // Specified Risk in Point ....
);
if (has)
{
//
// Notify On Signal Event ...
NotifySignalEventListeners(iSignal);
}
}
//
// Cleanup Resources ...
iBar.Clean();
iZone.Clean();
iSignal.Clean();
iStructure.Clean();
iFIMAConditions.Clean();
SpecifiedClean(targets);
SpecifiedClean(pvPivots);
SpecifiedClean(zgPivots);
SpecifiedClean(supports);
SpecifiedClean(resistances);
}
/**
* Check Guards Based on MarketConditions ...
*
* @param guards: XGuard[]
* @param barIndex: int
*
* @return ( int )
*/
int virtual CheckForGuard(
XGuard &guards[],
int barIndex = 0 //
)
{
//
int result = 0;
//
SpecifiedClean(guards);
//
result = ArraySize(guards);
//
return result;
}
//
// Private ...
private:
//
// Props ...
//
// Implementing Strategies ...
/**
* Check Bar Has Signal Based on Strategy 1 ...
*
* @param bar: XOHCL, reference to Bar ...
* @param iZone: XBoxZone, reference to holds affected zone ...
* @param supports: XBoxZone, array reference to Provide Exists Supports ...
* @param resistances: XBoxZone, array reference to Provide Exists Resistances ...
* @param iDir: ENUM_X_DIRECTION, detected Signal's direction ...
* @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ...
* @param conditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ...
*
* @return ( bool )
*/
bool Strategy1HasSignal(
XOHCL &bar,
XBoxZone &iZone,
XBoxZone &supports[],
XBoxZone &resistances[],
ENUM_X_DIRECTION &iDir,
XFIMAMarketStructure &structure,
XFIMAConditions &conditions //
)
{
//
bool result = false;
//
// Prepare ...
iZone.Clean();
iDir = X_DIRECTION_NONE;
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Check Pattern Exists ...
string patternName = NULL;
ENUM_X_DIRECTION patternDir = X_DIRECTION_NONE;
result = HasPattern(
bar,
patternName,
patternDir,
structure //
);
if (!result)
{
return result;
}
//
// Validate Pattern Based on MA Band ...
result = ValidatePatternBasedOnMABand(
bar,
patternName,
patternDir,
conditions //
);
if (!result)
{
return result;
}
//
// Check Affected Zone ...
// Select a Support or Resistance ...
int insideZoneIDX = -1;
result =
(IsXBullish(patternDir)
? HasInside(
insideZoneIDX,
bar,
supports //
)
: IsXBearish(patternDir)
? HasInside(
insideZoneIDX,
bar,
resistances //
)
: false //
);
if (!result)
{
return result;
}
//
// Filling Affected Zone ...
// and Validate it ...
if (IsXBullish(patternDir))
{
iZone = supports[insideZoneIDX];
}
else if (IsXBearish(patternDir))
{
iZone = resistances[insideZoneIDX];
}
result = iZone.IsValid();
if (!result)
{
return result;
}
//
// Validate affected Zone based on Pattern's Bar ...
result = IsXBullish(patternDir)
? bar.high > iZone.upper
: IsXBearish(patternDir)
? bar.low < iZone.lower
: false;
if (result)
{
iDir = patternDir;
}
//
// Cleanup Resources ...
if (!result)
{
iZone.Clean();
}
//
return result;
}
/**
* Check Bar Has Signal Based on Strategy 1 ...
*
* @param bar: XOHCL, reference to Bar ...
* @param iZone: XBoxZone, reference to holds affected zone ...
* @param supports: XBoxZone, array reference to Provide Exists Supports ...
* @param resistances: XBoxZone, array reference to Provide Exists Resistances ...
* @param iDir: ENUM_X_DIRECTION, detected Signal's direction ...
* @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ...
* @param conditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ...
*
* @return ( bool )
*/
bool Strategy2HasSignal(
XOHCL &bar,
XBoxZone &iZone,
XBoxZone &supports[],
XBoxZone &resistances[],
ENUM_X_DIRECTION &iDir,
XFIMAMarketStructure &structure,
XFIMAConditions &conditions //
)
{
//
bool result = false;
//
// Prepare ...
iZone.Clean();
iDir = X_DIRECTION_NONE;
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Detect Specified MA Cross ...
result = HasDirection(structure.maCrossDir);
//
// Validate Conditions ...
//
// Prepare iZone ...
iZone.to = bar.time;
iZone.from = GetBarTime(
bar.symbol,
bar.period,
bar.Index() + 2 //
);
iZone.symbol = bar.symbol;
iZone.period = bar.period;
iZone.dir = structure.maCrossDir;
iZone.lower = bar.FindLowest(2, MODE_LOW);
iZone.upper = bar.FindHighest(2, MODE_HIGH);
iZone.type = name + "_" + ToXString(structure.maCrossDir);
//
// Check Result ...
result = iZone.IsValid();
if (result)
{
iDir = structure.maCrossDir;
}
//
// Cleanup Resources ...
if (!result)
{
iZone.Clean();
}
//
return result;
}
//
};
//