Files
MQL5Data/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5
T
2025-10-14 03:23:28 +03:30

1171 lines
30 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 ...
//
bool ignoreTargets; // Ignore Signal Targets ...
CArrayObj drawnObjects; // Drawing Objects Holder ...
XFIMAInputs fimaInputs; // XFIMA Inputs ...
XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ...
XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ...
XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ...
XFIMAMarketStructureConfig structureConfig; // XFIMA Market Structure Detector Config ...
XFIMAMarketStructureDrawerConfig structureDrawConfig; // XFIMA Market Structure Draw Config ...
//
// 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);
//
// Configure ...
structureConfig.Default();
structureDrawConfig.Default();
}
//
// Deconstructor ...
~XCXFIMABaseSignaller()
{
Destroy();
}
//
// Overrides ...
//
// Actions ...
/**
* Destroy ...
*/
void Destroy()
{
//
BeforeDestroy();
//
fimaInputs.Clean();
//
delete fimaHelper;
ZeroMemory(fimaHelper);
//
delete poiDrawer;
ZeroMemory(poiDrawer);
//
delete poiDetector;
ZeroMemory(poiDetector);
//
structureConfig.Clean();
structureDrawConfig.Clean();
}
//
// 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, reference collection to holds result ...
* @param positions: XPosition, reference collection to provides positions ...
* @param barIndex: int
*
* @return ( int )
*/
int virtual CheckForGuard(
XGuard &guards[],
XPosition &positions[],
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 ...
//
// Private ...
private:
//
};
//
// XFIMA Strategy 2 Signaller Class ...
class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller
{
//
// Public ...
public:
//
// Props ...
XFIMAMarketStructure structure; // XFIMA Market Structure ...
//
// 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 //
)
{
//
// Configure ...
structureConfig.Default();
structureDrawConfig.Default();
//
structure.Clean();
//
// Ignore Signal Targets ...
ignoreTargets = false;
}
//
// Deconstructor ...
~XCXFIMAStrategy1Signaller()
{
//
Destroy();
//
structure.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 iTargets[];
string iName = NULL;
bool isBullish = false;
bool isBearish = false;
XFIMAConditions iFIMAConditions;
ENUM_X_DIRECTION iDir = 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;
}
//
structure.Clean();
poiDetector.AnalyseMarket(
structure,
structureConfig,
barIndex //
);
// poiDrawer.drawnObjects.Clear();
// poiDrawer.DrawMarketStructure(
// structure,
// structureDrawConfig //
// );
//
// Strategy 1 ...
// has = Strategy1HasSignal(
// iBar,
// iZone,
// iTargets,
// iDir,
// iFIMAConditions,
// structure //
// );
//
// Strategy 2 ...
has = false;
if (!has)
{
//
has = Strategy2HasSignal(
iBar,
iZone,
iTargets,
iDir,
iFIMAConditions,
structure //
);
}
//
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 ...
//
// Handle Signal Targets ...
if (ignoreTargets)
{
XClean(iTargets);
}
//
has = PrepareSignal(
iSignal,
iDir,
iTargets,
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();
iFIMAConditions.Clean();
SpecifiedClean(iTargets);
}
/**
* Check Guards Based on MarketConditions ...
*
* @param guards: XGuard, reference collection to holds result ...
* @param positions: XPosition, reference collection to provides positions ...
* @param barIndex: int
*
* @return ( int )
*/
int virtual CheckForGuard(
XGuard &guards[],
XPosition &positions[],
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 zone: XBoxZone, reference to holds affected zone ...
* @param targets: XTarget, reference to detected Signal's Targets collections ...
* @param dir: ENUM_X_DIRECTION, detected Signal's direction ...
* @param conditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ...
* @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ...
*
* @return ( bool )
*/
bool Strategy1HasSignal(
XOHCL &bar,
XBoxZone &zone,
XTarget &targets[],
ENUM_X_DIRECTION &dir,
XFIMAConditions &conditions,
XFIMAMarketStructure &_structure //
)
{
//
bool result = false;
//
// Prepare ...
zone.Clean();
XClean(targets);
dir = X_DIRECTION_NONE;
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Testing Porposes ...
result =
result &&
fimaHelper.IsBoundaryFakeBreaked(
dir,
bar.Index(),
X_PRICE_CLOSE,
X_PRICE_CLOSE //
);
//
// Nearest Noisy ZG Pivot Must has Same Direction
// by Boundary Faked Break ...
result =
result &&
HasDirection(dir) &&
_structure.zgAnalysis.IsValid() &&
_structure.zgAnalysis.HasPivots() &&
_structure.zgAnalysis.pivots[0].dir == dir;
//
// We Have to Detect a Zone which Nearest ZG Pivot Reject or goes inside it ...
//
int idx = -1;
XOHCL tmpBar;
XPivot pivot;
XPivot pivots[];
XBoxZone zones[];
bool has = false;
int zonesCount = 0;
int pivotIndex = -1;
XBoxZone affectedZone;
double bullishScore = 0;
double bearishScore = 0;
int prevPivotIndex = -1;
XBoxZone affectedZones[];
int affectedZonesCount = 0;
//
Copy(
_structure.zgAnalysis.pivots,
pivots //
);
pivot = pivots[0];
ArrayRemove(pivots, 0, 1);
//
bool isBullish = IsXBullish(dir);
bool isBearish = IsXBearish(dir);
//
zonesCount = _structure.CollectZones(
zones,
dir //
);
result = result &&
IsValidSize(zonesCount);
//
// Noisey ZG Pivot must inside atleast one of Zones ...
//
// Initial Pivots Bar ...
result =
result &&
bar.BarAt(pivot.time, tmpBar);
//
// Extract Affected Zones ...
if (result)
{
//
affectedZonesCount = ExtractAffectedZones(
tmpBar,
zones,
affectedZones,
dir //
);
}
//
// Validate Affected Zones ...
result =
result &&
HasChild(affectedZones) &&
affectedZonesCount >= 1;
if (result)
{
affectedZone = affectedZones[0];
}
result =
result &&
affectedZone.IsValid() &&
(isBullish
? bar.close > affectedZone.upper
: bar.close < affectedZone.lower);
//
// There Must another Same Directional ZG Pivot Exists
// which is Affect another Zone ...
idx = GetYoungest(pivots, pivot.type);
result =
result &&
IsValidIndex(idx) &&
affectedZone.IsValid() &&
(isBullish
? pivots[idx].value < pivot.value
: pivots[idx].value > pivot.value);
if (result)
{
//
pivot.Clean();
tmpBar.Clean();
pivot = pivots[idx];
XClean(affectedZones);
ArrayRemove(pivots, idx, 1);
//
result = bar.BarAt(pivot.time, tmpBar);
}
//
// Extract Affected Zones ...
XClean(affectedZones);
affectedZonesCount = 0;
if (result)
{
//
affectedZonesCount = ExtractAffectedZones(
tmpBar,
zones,
affectedZones,
dir //
);
}
result =
result &&
HasChild(affectedZones) &&
affectedZonesCount >= 1;
//
// Handling Scores ...
if (result)
{
//
for (int i = 0; i < ArraySize(_structure.barsAnalysis); i++)
{
//
bullishScore += _structure.barsAnalysis[i].Count(X_DIRECTION_BULLISH);
bearishScore += _structure.barsAnalysis[i].Count(X_DIRECTION_BEARISH);
}
}
result =
isBullish
? bullishScore > bearishScore
: bearishScore > bullishScore;
//
// Last Validation is Candlestick Patterns of Bar ...
// XPatternAnalysis barAnalysis;
// result =
// result &&
// poiDetector.AnalyseBarPatterns(
// bar,
// barAnalysis,
// structureConfig.barsAnalysisConfig //
// );
//
if (!result)
{
//
dir = X_DIRECTION_NONE;
//
return result;
}
//
// Drawa ...
if (result)
{
//
// Affected Zone ...
XCBoxObject *iObj;
has = poiDrawer.DrawBox(
affectedZone,
iObj,
true,
affectedZone.type + "_" + ToXString(TimeToSeconds(affectedZone.from)) //
);
if (has)
{
//
XPOIStyle iStyle;
poiDrawer.GetBoxStyle(
iStyle,
affectedZone.dir //
);
iStyle.clr = clrYellow;
poiDrawer.ApplyBoxStyle(
iObj,
iStyle //
);
iStyle.Clean();
//
Print("Affected Zone ...");
}
//
// Draw Bar Pattern ...
// poiDrawer.DrawPatternAnalysis(barAnalysis, structureDrawConfig.barAnalysisDrawConfig);
}
//
// Prepare zone ...
if (result)
{
//
zone = affectedZone;
//
zone.type = name + "_" + ToXString(dir);
//
double entry = GetEntry(bar.symbol, dir);
double points = GetPoints(bar.symbol);
double risk = MathAbs(entry - (isBullish ? zone.lower : zone.upper));
double reward = risk * defaultSignalR2R;
//
// Partially Close on TP 1 ...
double tp1 = isBullish
? entry + (risk * 1)
: entry - (risk * 1);
XTarget target1;
target1.target = tp1;
target1.doRF = false;
target1.actingDistance = 2;
target1.volumeMultiplier = 0.5;
//
// TP 3 ...
double tp3 = isBullish
? entry + (risk * 3)
: entry - (risk * 3);
XTarget target3;
target3.target = tp3;
target3.doRF = true;
target3.actingDistance = 10;
//
// TP 5 ...
double tp5 = isBullish
? entry + (risk * 5)
: entry - (risk * 5);
XTarget target5;
target5.target = tp5;
target5.doRF = true;
target5.actingDistance = 10;
//
AddRef(
target1,
targets //
);
AddRef(
target3,
targets //
);
AddRef(
target5,
targets //
);
//
result = zone.IsValid();
}
//
// Check Result ...
if (result)
{
//
// dir = structure.maCrossDir;
//
// Handle Targets Detection ...
}
//
// Cleanup ...
if (!result)
{
//
zone.Clean();
XClean(targets);
}
//
pivot.Clean();
XClean(zones);
tmpBar.Clean();
XClean(pivots);
affectedZone.Clean();
XClean(affectedZones);
//
return result;
}
/**
* Check Bar Has Signal Based on Strategy 1 ...
*
* @param bar: XOHCL, reference to Bar ...
* @param zone: XBoxZone, reference to holds affected zone ...
* @param targets: XTarget, reference to detected Signal's Targets collections ...
* @param dir: ENUM_X_DIRECTION, detected Signal's direction ...
* @param conditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ...
* @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ...
*
* @return ( bool )
*/
bool Strategy2HasSignal(
XOHCL &bar,
XBoxZone &zone,
XTarget &targets[],
ENUM_X_DIRECTION &dir,
XFIMAConditions &conditions,
XFIMAMarketStructure &_structure //
)
{
//
bool result = false;
//
// Prepare ...
XOHCL pBar;
XOHCL p2Bar;
zone.Clean();
pBar.Clean();
p2Bar.Clean();
XClean(targets);
dir = X_DIRECTION_NONE;
//
// Validate ...
result = bar.IsValid() &&
bar.GetPreviousBar(pBar) &&
pBar.GetPreviousBar(p2Bar);
if (!result)
{
return result;
}
//
result = false;
bool isBullish = false;
bool isBearish = false;
ENUM_X_DIRECTION tmpDir;
//
// Do Signal Detection ...
//
// Preparing Requirement Conditions ...
// Here we Have to Prepare Some Directional Confirmations Using Indicators ...
// for Validate Signals ...
//
int verifierBarIndex = pBar.Index();
//
bool hasSarSwitch = fimaHelper.HasSARSwitch(tmpDir, verifierBarIndex);
bool isSarSwitchedToBullish = hasSarSwitch &&
IsXBullish(tmpDir);
bool isSarSwitchedToBearish = hasSarSwitch &&
IsXBearish(tmpDir);
//
bool hasMACross = fimaHelper.HasMACross(
tmpDir,
verifierBarIndex,
structureConfig.maCrossValidationDiffMultiplier //
);
bool isCrossedOver = hasMACross &&
IsXBullish(tmpDir);
bool isCrossedUnder = hasMACross &&
IsXBearish(tmpDir);
//
bool hasHKSwitch = fimaHelper.HasHKSwitch(tmpDir, verifierBarIndex);
bool isHKSwitchedToBullish = hasHKSwitch &&
IsXBullish(tmpDir);
bool isHKSwitchedToBearish = hasHKSwitch &&
IsXBearish(tmpDir);
//
bool isBoundaryFakeBreaked = fimaHelper.IsBoundaryFakeBreaked(tmpDir, verifierBarIndex);
bool isBoundaryFakeBreakedBullish = isBoundaryFakeBreaked &&
IsXBullish(tmpDir);
bool isBoundaryFakeBreakedBearish = isBoundaryFakeBreaked &&
IsBearish(tmpDir);
//
bool hasZigZagHigherLow = fimaHelper.HasZigZagHigherLow(bar.Index(), true);
bool hasZigZagLowerHigh = fimaHelper.HasZigZagLowerHigh(bar.Index(), true);
//
// Summarize Confirmations ...
//
bool isBullishConfirmed =
(hasZigZagHigherLow &&
(
//
isCrossedOver ||
isHKSwitchedToBullish ||
isSarSwitchedToBullish ||
isBoundaryFakeBreakedBullish
//
));
//
bool isBearishConfirmed =
(hasZigZagLowerHigh &&
(
//
isCrossedUnder ||
isHKSwitchedToBearish ||
isSarSwitchedToBearish ||
isBoundaryFakeBreakedBullish
//
));
//
// Validation Patterns ...
int directionalPatternsValidations = 3;
//
// Check Bullish Conditions ...
isBullish =
//
// Confirmations Passed ...
isBullishConfirmed &&
//
// Quarters Has Minor Support Zone ...
_structure.barAnalysis.HasMinorSupport() &&
//
// Current Bar's Price Placed Propper ...
bar.open > _structure.barAnalysis.minorSupport.upper &&
bar.close > _structure.barAnalysis.minorSupport.upper &&
//
// Required Number of Pivots Validation Exists ...
(_structure.barsAnalysis[1].Count(X_DIRECTION_BULLISH) >= directionalPatternsValidations) &&
//
// Bar or PBar ReTested Quarter Zone ...
(IsTested(
pBar,
_structure.barAnalysis.minorSupport //
) ||
IsTested(
p2Bar,
_structure.barAnalysis.minorSupport //
))
//
;
//
// Check Bearish Conditions ...
isBearish =
//
// Confirmations Passed ...
isBearishConfirmed &&
//
// Quarters Has Minor Resistance Zone ...
_structure.barAnalysis.HasMinorResistance() &&
//
// Current Bar's Price Placed Propper ...
bar.open < _structure.barAnalysis.minorResistance.lower &&
bar.close < _structure.barAnalysis.minorResistance.lower &&
//
// Required Number of Pivots Validation Exists ...
(_structure.barsAnalysis[1].Count(X_DIRECTION_BEARISH) >= directionalPatternsValidations) &&
//
// Bar or pBar ReTested Quarter Zone ...
(IsTested(
pBar,
_structure.barAnalysis.minorResistance //
) ||
IsTested(
p2Bar,
_structure.barAnalysis.minorResistance //
))
//
;
//
// Summarize Conditions ...
result =
isBullish ||
isBearish;
//
// Assign Direction ...
if (result)
{
//
dir = isBullish
? X_DIRECTION_BULLISH
: isBearish
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
//
if (isBullish)
{
zone = _structure.barAnalysis.minorSupport;
}
//
if (isBearish)
{
zone = _structure.barAnalysis.minorResistance;
}
}
//
// Validate Result ...
result =
result &&
zone.IsValid() &&
HasDirection(dir);
// if (result)
// {
// //
// XPOIDrawConfig iConfig = structureDrawConfig
// .barAnalysisDrawConfig
// .quarterMinorsDrawConfig;
// iConfig.zonesWidth = 3;
// iConfig.zonesFill = true;
// iConfig.bullishColor = clrYellow;
// iConfig.bearishColor = clrYellow;
// //
// if (isBullish)
// {
// //
// poiDrawer.DrawZone(
// _structure.barAnalysis.minorSupport,
// iConfig //
// );
// //
// Print("Bullish Condition ...");
// }
// //
// if (isBearish)
// {
// //
// poiDrawer.DrawZone(
// _structure.barAnalysis.minorResistance,
// iConfig //
// );
// //
// Print("Bearish Condition ...");
// }
// //
// Print(ToXString(dir), " Detected ...");
// }
//
// Provide Direction and Targets if Required ...
if (result)
{
//
// Handle Targets Detection ...
//
double spread = GetSpread(zone.symbol);
double entry = GetEntry(zone.symbol, dir);
//
double risk = isBullish
? entry - zone.lower
: zone.upper - entry;
double reward1 = entry + (isBullish
? risk
: (-1 * risk) //
);
double reward4 = entry + (isBullish
? 4 * risk
: (-4 * risk) //
);
double requiredDistance = PriceToPoint(spread * 2, zone.symbol);
//
XTarget iRFOnEntryOnTP1;
iRFOnEntryOnTP1.target = reward1;
iRFOnEntryOnTP1.tpValue = reward4;
iRFOnEntryOnTP1.doRFOnEntry = true;
iRFOnEntryOnTP1.volumeMultiplier = 0.5;
iRFOnEntryOnTP1.actingDistance = requiredDistance;
//
AddRef(
iRFOnEntryOnTP1,
targets //
);
}
//
// Cleanup Resources ...
if (!result)
{
//
zone.Clean();
XClean(targets);
}
pBar.Clean();
p2Bar.Clean();
//
return result;
}
//
};
//