1657 lines
42 KiB
Plaintext
1657 lines
42 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 ...
|
|
if (!has)
|
|
{
|
|
// //
|
|
// has = Strategy2HasSignal(
|
|
// iBar,
|
|
// iZone,
|
|
// iTargets,
|
|
// iDir,
|
|
// iFIMAConditions,
|
|
// structure //
|
|
// );
|
|
}
|
|
|
|
//
|
|
// Strategy 3 ...
|
|
if (!has)
|
|
{
|
|
//
|
|
// has = Strategy3HasSignal(
|
|
// iBar,
|
|
// iZone,
|
|
// iTargets,
|
|
// iDir,
|
|
// iFIMAConditions,
|
|
// structure //
|
|
// );
|
|
}
|
|
|
|
//
|
|
// Strategy 4 ...
|
|
has = false;
|
|
if (!has)
|
|
{
|
|
//
|
|
has = Strategy4HasSignal(
|
|
iBar,
|
|
iZone,
|
|
iTargets,
|
|
iDir,
|
|
iFIMAConditions,
|
|
structure //
|
|
);
|
|
}
|
|
|
|
//
|
|
has = HasDirection(iDir) &&
|
|
iZone.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
has = false;
|
|
iZone.Clean();
|
|
iDir = X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
if (has)
|
|
{
|
|
//
|
|
isBullish = IsXBullish(iDir);
|
|
isBearish = IsXBearish(iDir);
|
|
|
|
//
|
|
// TODO: Provided SL ...
|
|
double _point = GetPoints(iBar.symbol);
|
|
double slAddition = 5 * _point;
|
|
double atrAddition = GetAverageTrueRange(
|
|
iZone.symbol,
|
|
iZone.period,
|
|
0 //
|
|
);
|
|
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 2 ...
|
|
*
|
|
* @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;
|
|
}
|
|
|
|
/**
|
|
* Check Bar Has Signal Based on Strategy 3 ...
|
|
*
|
|
* @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 Strategy3HasSignal(
|
|
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;
|
|
}
|
|
|
|
//
|
|
// Define Requirements ...
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
XOHCL pBar;
|
|
int barIndex = bar.Index();
|
|
int pBarIndex = barIndex + 1;
|
|
result = bar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do Conditions Checking ...
|
|
|
|
//
|
|
XBoxZone zones[];
|
|
int zonesCount = 0;
|
|
ENUM_X_PRICE bullishPriceType = X_PRICE_LOW;
|
|
ENUM_X_PRICE bearishPriceType = X_PRICE_HIGH;
|
|
|
|
//
|
|
isBullish = fimaHelper.IsSwitchedUnderHKBondLower(bullishPriceType, pBarIndex);
|
|
|
|
//
|
|
isBearish = fimaHelper.IsSwitchedOverHKBondUpper(bearishPriceType, pBarIndex);
|
|
|
|
//
|
|
result =
|
|
isBullish ||
|
|
isBearish;
|
|
|
|
//
|
|
// Do Validations ...
|
|
if (result)
|
|
{
|
|
//
|
|
// Direction Assignment ...
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
int lastIDX;
|
|
XBoxZone tmpZones[];
|
|
int tmpZonesCount = 0;
|
|
int validationCount = 0;
|
|
ENUM_X_PRICE priceType =
|
|
isBullish
|
|
? bullishPriceType
|
|
: bearishPriceType;
|
|
|
|
//
|
|
// Detect Last Direction Change ...
|
|
if (isBullish)
|
|
{
|
|
result = fimaHelper.FindLastUnderHKBondLower(lastIDX, bullishPriceType, pBarIndex);
|
|
}
|
|
else
|
|
{
|
|
result = fimaHelper.FindLastOverHKBondUpper(lastIDX, bearishPriceType, pBarIndex);
|
|
}
|
|
|
|
//
|
|
// Validate Direction Changed ...
|
|
if (result)
|
|
{
|
|
//
|
|
validationCount = lastIDX - pBarIndex;
|
|
result = validationCount >= 10;
|
|
}
|
|
|
|
//
|
|
// Collect Zones ...
|
|
if (result)
|
|
{
|
|
//
|
|
// Support and Resistances ...
|
|
tmpZonesCount = poiDetector.CollectZones(
|
|
pBar,
|
|
tmpZones,
|
|
5,
|
|
14, // Zones Validation Length ...
|
|
0, // Required Count ...
|
|
validationCount // Loopback ...
|
|
);
|
|
if (IsValidSize(tmpZonesCount))
|
|
{
|
|
//
|
|
Copy(
|
|
tmpZones,
|
|
zones,
|
|
false // ignore Clean ...
|
|
);
|
|
}
|
|
|
|
//
|
|
// OB ...
|
|
tmpZonesCount = poiDetector.CollectOBs(
|
|
pBar,
|
|
tmpZones,
|
|
5, // Zones Loopback ...
|
|
0, // Required Count ...
|
|
validationCount // Loopback ...
|
|
);
|
|
if (IsValidSize(tmpZonesCount))
|
|
{
|
|
//
|
|
Copy(
|
|
tmpZones,
|
|
zones,
|
|
false // ignore Clean ...
|
|
);
|
|
}
|
|
|
|
//
|
|
// FVG ...
|
|
tmpZonesCount = poiDetector.CollectFVGs(
|
|
pBar,
|
|
tmpZones,
|
|
5, // Zones Loopback ...
|
|
0, // Required Count ...
|
|
validationCount // Loopback ...
|
|
);
|
|
if (IsValidSize(tmpZonesCount))
|
|
{
|
|
//
|
|
Copy(
|
|
tmpZones,
|
|
zones,
|
|
false // ignore Clean ...
|
|
);
|
|
}
|
|
|
|
//
|
|
// Filter Zones Based on pBar ...
|
|
zonesCount = poiDetector.FilterZones(
|
|
pBar,
|
|
zones,
|
|
dir,
|
|
priceType,
|
|
dir //
|
|
);
|
|
|
|
//
|
|
// Extract Affected Zones ...
|
|
XClean(tmpZones);
|
|
tmpZonesCount = ExtractAffectedZones(
|
|
pBar,
|
|
zones,
|
|
tmpZones,
|
|
dir //
|
|
);
|
|
Copy(tmpZones, zones);
|
|
zonesCount = ArraySize(zones);
|
|
|
|
//
|
|
// Update Zones Time ...
|
|
UpdateToTime(zones);
|
|
}
|
|
|
|
//
|
|
// Draw Zones ...
|
|
result = IsValidSize(zonesCount);
|
|
if (result)
|
|
{
|
|
//
|
|
for (int i = 0; i < zonesCount; i++)
|
|
{
|
|
poiDrawer.DrawZone(zones[i], structureDrawConfig.drawConfig);
|
|
}
|
|
}
|
|
|
|
//
|
|
XClean(tmpZones);
|
|
}
|
|
|
|
//
|
|
// Prepare Zone ...
|
|
if (result)
|
|
{
|
|
//
|
|
// Zone Detection ...
|
|
zone.Clean();
|
|
if (isBullish)
|
|
{
|
|
//
|
|
int idx = GetLowest(zones);
|
|
if (IsValidIndex(idx))
|
|
{
|
|
zone = zones[idx];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
int idx = GetHighest(zones);
|
|
if (IsValidIndex(idx))
|
|
{
|
|
zone = zones[idx];
|
|
}
|
|
}
|
|
|
|
// zone.dir = dir;
|
|
// zone.type = name;
|
|
// zone.to = bar.time;
|
|
// zone.at = pBar.time;
|
|
// zone.from = pBar.time;
|
|
// zone.symbol = bar.symbol;
|
|
// zone.period = bar.period;
|
|
// zone.lower = MathMin(pBar.low, bar.low);
|
|
// zone.upper = MathMax(pBar.high, bar.high);
|
|
|
|
//
|
|
result = zone.IsValid();
|
|
}
|
|
|
|
//
|
|
// Prepare Targets ...
|
|
if (result)
|
|
{
|
|
//
|
|
// Target Handling ...
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
if (!result)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
}
|
|
pBar.Clean();
|
|
XClean(zones);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Bar Has Signal Based on Strategy 4 ...
|
|
*
|
|
* @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 Strategy4HasSignal(
|
|
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;
|
|
}
|
|
|
|
//
|
|
// Define Requirements ...
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
XOHCL pBar;
|
|
int barIndex = bar.Index();
|
|
int pBarIndex = barIndex + 1;
|
|
result = bar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do Conditions Checking ...
|
|
|
|
//
|
|
// Reading HK Bond ...
|
|
double hkBondUpper = fimaHelper.GetHKBondUpper(pBarIndex);
|
|
double hkBondLower = fimaHelper.GetHKBondLower(pBarIndex);
|
|
bool hasHKBoundary =
|
|
NotEmptyZero(hkBondUpper) &&
|
|
NotEmptyZero(hkBondLower);
|
|
|
|
//
|
|
// Pullback Detection ...
|
|
bool isPullback = poiDetector.IsPullbackPattern(
|
|
pBar,
|
|
zone,
|
|
dir,
|
|
2,
|
|
false //
|
|
);
|
|
|
|
//
|
|
isBullish =
|
|
isPullback &&
|
|
hasHKBoundary &&
|
|
IsXBullish(dir) &&
|
|
zone.lower > hkBondLower;
|
|
|
|
//
|
|
isBearish =
|
|
isPullback &&
|
|
hasHKBoundary &&
|
|
IsXBearish(dir) &&
|
|
zone.upper < hkBondUpper;
|
|
|
|
//
|
|
result =
|
|
isBullish ||
|
|
isBearish;
|
|
|
|
//
|
|
// Do Validations ...
|
|
if (result)
|
|
{
|
|
//
|
|
// Direction Assignment ...
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
// TEMP ...
|
|
poiDrawer.DrawZone(
|
|
zone,
|
|
structureDrawConfig.drawConfig //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Prepare Decision Zone ...
|
|
if (result)
|
|
{
|
|
//
|
|
// Zone Detection ...
|
|
zone.Clean();
|
|
|
|
//
|
|
// zone.dir = dir;
|
|
// zone.type = name;
|
|
// zone.to = bar.time;
|
|
// zone.at = pBar.time;
|
|
// zone.from = pBar.time;
|
|
// zone.symbol = bar.symbol;
|
|
// zone.period = bar.period;
|
|
// zone.lower = MathMin(pBar.low, bar.low);
|
|
// zone.upper = MathMax(pBar.high, bar.high);
|
|
|
|
//
|
|
result = zone.IsValid();
|
|
}
|
|
|
|
//
|
|
// Prepare Targets ...
|
|
if (result)
|
|
{
|
|
//
|
|
// Target Handling ...
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
if (!result)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
}
|
|
pBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
// |