3485 lines
87 KiB
Plaintext
3485 lines
87 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.parser.class.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 ...
|
|
|
|
//
|
|
CArrayObj drawnObjects; // Drawing Objects Holder ...
|
|
XFIMAInputs fimaInputs; // XFIMA Inputs ...
|
|
XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ...
|
|
XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ...
|
|
XCXFIMAHelperParser *fimaParser; // XFIMA Helper Parser ...
|
|
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);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Instantiate XFIMA Helper Parser ...
|
|
fimaParser = new XCXFIMAHelperParser(fimaHelper);
|
|
|
|
//
|
|
poiDrawer = new XCXFIMAPOIDrawer();
|
|
poiDetector = new XCXFIMAPOIDetector(fimaHelper, fimaParser);
|
|
|
|
//
|
|
// 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;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
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 ...
|
|
|
|
//
|
|
// 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 ...
|
|
drawLeg = true;
|
|
drawZones = true;
|
|
drawIZones = true;
|
|
drawTrends = true;
|
|
drawSCTrend = true;
|
|
drawMCTrend = true;
|
|
drawLCTrend = true;
|
|
drawHCTrend = true;
|
|
drawSupport = true;
|
|
drawISupport = true;
|
|
drawOrderFlow = true;
|
|
drawResistance = true;
|
|
drawIResistance = true;
|
|
|
|
//
|
|
manageLegs = true;
|
|
manageZones = true;
|
|
manageIZones = true;
|
|
manageTrends = false;
|
|
manageOrderFlow = true;
|
|
|
|
//
|
|
structureConfig.Default();
|
|
structureDrawConfig.Default();
|
|
}
|
|
|
|
//
|
|
// Deconstructor ...
|
|
~XCXFIMAStrategy1Signaller()
|
|
{
|
|
//
|
|
Destroy();
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
XBoxZone iZone;
|
|
XSignal iSignal;
|
|
bool has = false;
|
|
XTarget iTargets[];
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Initialize Bar as CBar ...
|
|
has = iBar.Init(
|
|
symbol,
|
|
period,
|
|
barIndex //
|
|
);
|
|
if (!has)
|
|
{
|
|
//
|
|
iBar.Clean();
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Manage ...
|
|
Manage(iBar);
|
|
|
|
//
|
|
// Strategy X ...
|
|
has = HasSignal(
|
|
iBar,
|
|
iZone,
|
|
iTargets,
|
|
iDir //
|
|
);
|
|
|
|
//
|
|
// Handle Resting Signals ...
|
|
has = HasDirection(iDir) &&
|
|
iZone.IsValid();
|
|
|
|
//
|
|
// Prepare Signal ...
|
|
if (has)
|
|
{
|
|
//
|
|
isBullish = IsXBullish(iDir);
|
|
isBearish = IsXBearish(iDir);
|
|
|
|
//
|
|
// Provided SL ...
|
|
double points = GetPoints(symbol);
|
|
double spread = GetSpread(symbol);
|
|
double entry = GetEntry(symbol, iDir);
|
|
|
|
//
|
|
// Calculate SL Addition ...
|
|
double slAddition =
|
|
slAdditionDistance <= 0
|
|
? 0
|
|
: slAdditionDistance * points;
|
|
|
|
//
|
|
// Calculate SL Price ...
|
|
double sl =
|
|
isBullish
|
|
? iZone.lower - slAddition
|
|
: iZone.upper + slAddition;
|
|
|
|
//
|
|
// Prepare Signal ...
|
|
has = PrepareSignal(
|
|
iSignal,
|
|
iDir,
|
|
iTargets,
|
|
0, // Use Default R2R ...
|
|
sl, // Provided Price for SL ...
|
|
0 // Specified Risk in Point ....
|
|
);
|
|
}
|
|
|
|
//
|
|
// Notify On Signal Event ...
|
|
if (has)
|
|
{
|
|
NotifySignalEventListeners(iSignal);
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
iBar.Clean();
|
|
iZone.Clean();
|
|
iSignal.Clean();
|
|
XClean(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;
|
|
|
|
//
|
|
XClean(guards);
|
|
return result;
|
|
|
|
//
|
|
int positionsCount = ArraySize(positions);
|
|
if (!IsValidSize(positionsCount))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Requirements ...
|
|
XGuard iGuard;
|
|
bool has = false;
|
|
int samePeaks = 0;
|
|
int sameVales = 0;
|
|
double iValue = 0;
|
|
double points10 = 0;
|
|
double points50 = 0;
|
|
double points100 = 0;
|
|
int samePVValidation = 5;
|
|
bool isPeakOverLast = false;
|
|
bool isValeUnderLast = false;
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
points10 = 10 * positions[i].GetPointsValue();
|
|
points50 = 50 * positions[i].GetPointsValue();
|
|
points100 = 100 * positions[i].GetPointsValue();
|
|
|
|
//
|
|
// Near to TP Guard ...
|
|
has = positions[i].profit > 0;
|
|
if (has)
|
|
{
|
|
//
|
|
// Has Same Peaks or Vales ...
|
|
samePeaks = fimaParser.CountSamePeaks(barIndex);
|
|
sameVales = fimaParser.CountSameVales(barIndex);
|
|
isPeakOverLast = (fimaParser.IsPeakOverLast(barIndex) ||
|
|
fimaParser.IsPeakOverLast(barIndex + 1));
|
|
isValeUnderLast = (fimaParser.IsValeUnderLast(barIndex) ||
|
|
fimaParser.IsValeUnderLast(barIndex + 1));
|
|
has = (positions[i].IsBullish()
|
|
? (
|
|
isPeakOverLast &&
|
|
sameVales >= samePVValidation &&
|
|
fimaHelper.GetVale(barIndex) > positions[i].sl)
|
|
: positions[i].IsBearish()
|
|
? (
|
|
isValeUnderLast &&
|
|
samePeaks >= samePVValidation &&
|
|
fimaHelper.GetPeak(barIndex) < positions[i].sl)
|
|
: false);
|
|
if (has)
|
|
{
|
|
//
|
|
iGuard.Clean();
|
|
iGuard.time = TimeCurrent();
|
|
iGuard.symbol = positions[i].symbol;
|
|
iGuard.period = positions[i].period;
|
|
iGuard.ticket = positions[i].ticket;
|
|
iGuard.provider = positions[i].provider;
|
|
iGuard.sl = positions[i].IsBullish()
|
|
? fimaHelper.GetVale(barIndex) - points10
|
|
: fimaHelper.GetPeak(barIndex) + points10;
|
|
iGuard.action = X_GUARD_ACTION_TRAIL_STOP;
|
|
|
|
//
|
|
has = iGuard.IsValid();
|
|
if (has)
|
|
{
|
|
AddRef(iGuard, guards);
|
|
|
|
//
|
|
// Remove TP if in Profit SL ...
|
|
iValue = (positions[i].IsBullish() ? positions[i].entry + points10 : positions[i].entry - points10);
|
|
has =
|
|
(positions[i].IsBullish() && HasResistance())
|
|
? (iGuard.sl >= iValue &&
|
|
positions[i].tp < resistance.lower)
|
|
: (positions[i].IsBearish() && HasSupport())
|
|
? (iGuard.sl <= iValue &&
|
|
positions[i].tp > support.upper)
|
|
: false;
|
|
if (has)
|
|
{
|
|
//
|
|
iGuard.Clean();
|
|
iGuard.force = false;
|
|
iGuard.tp = positions[i].IsBullish()
|
|
? resistance.lower
|
|
: support.upper;
|
|
iGuard.time = TimeCurrent();
|
|
iGuard.symbol = positions[i].symbol;
|
|
iGuard.period = positions[i].period;
|
|
iGuard.ticket = positions[i].ticket;
|
|
iGuard.provider = positions[i].provider;
|
|
iGuard.action = X_GUARD_ACTION_TRAIL_TARGET;
|
|
|
|
//
|
|
has = iGuard.IsValid();
|
|
if (has)
|
|
{
|
|
AddRef(iGuard, guards);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(guards);
|
|
|
|
//
|
|
// Cleanup ...
|
|
iGuard.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Protected ...
|
|
protected:
|
|
//
|
|
|
|
//
|
|
void Manage(XOHCL &bar)
|
|
{
|
|
//
|
|
bool has = bar.IsValid();
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XOHCL pBar;
|
|
XOHCL p2Bar;
|
|
XOHCL p3Bar;
|
|
has = bar.GetPreviousBar(pBar);
|
|
has = has &&
|
|
pBar.GetPreviousBar(p2Bar);
|
|
has = has &&
|
|
p2Bar.GetPreviousBar(p3Bar);
|
|
if (!has)
|
|
{
|
|
//
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
}
|
|
|
|
//
|
|
ManageLeg(bar);
|
|
ManageTrends(bar);
|
|
ManageZones(p2Bar);
|
|
ManageIZones(p2Bar);
|
|
ManageOrderFlow(p3Bar);
|
|
|
|
//
|
|
// Cleanup ...
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
}
|
|
|
|
//
|
|
// Private ...
|
|
private:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
// Leg ...
|
|
|
|
XLeg leg; // Exists Leg ...
|
|
bool drawLeg; // Draw Leg ...
|
|
bool manageLegs;
|
|
|
|
//
|
|
bool HasLeg()
|
|
{
|
|
return leg.IsValid();
|
|
}
|
|
|
|
//
|
|
bool ValidateLeg(XOHCL &bar)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = HasLeg() &&
|
|
bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
leg.IsBullish()
|
|
? bar.low > leg.lower
|
|
: leg.IsBearish()
|
|
? bar.high < leg.upper
|
|
: false;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void DrawLeg()
|
|
{
|
|
//
|
|
if (!drawLeg)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
if (!HasLeg())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Update to Times ...
|
|
leg.UpdateTimes();
|
|
|
|
//
|
|
// Draw Leg Box ...
|
|
XBoxZone legZone;
|
|
leg.ToBox(legZone);
|
|
if (legZone.IsValid())
|
|
{
|
|
//
|
|
legZone.to = TimeCurrent();
|
|
poiDrawer.DrawZone(legZone, structureDrawConfig.drawConfig);
|
|
}
|
|
|
|
//
|
|
// Draw Legs Other Stufs ...
|
|
return;
|
|
|
|
//
|
|
// FVGs ...
|
|
poiDrawer.DrawZones(leg.bullishFVGs, structureDrawConfig.drawConfig);
|
|
poiDrawer.DrawZones(leg.bearishFVGs, structureDrawConfig.drawConfig);
|
|
|
|
//
|
|
// Support and Resistances ...
|
|
poiDrawer.DrawZones(leg.supports, structureDrawConfig.drawConfig);
|
|
poiDrawer.DrawZones(leg.resistances, structureDrawConfig.drawConfig);
|
|
|
|
//
|
|
// Patterns ...
|
|
poiDrawer.DrawPatternAnalysises(leg.patterns, structureDrawConfig.barAnalysisDrawConfig);
|
|
}
|
|
|
|
//
|
|
void ManageLeg(XOHCL &bar)
|
|
{
|
|
//
|
|
// Validate Exists ...
|
|
if (HasLeg())
|
|
{
|
|
//
|
|
if (!ValidateLeg(bar))
|
|
{
|
|
//
|
|
// Invalidate XLeg ...
|
|
leg.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Detect New ...
|
|
if (!HasLeg())
|
|
{
|
|
poiDetector.IsLegPattern(bar, leg);
|
|
}
|
|
|
|
//
|
|
// Update Exists ...
|
|
if (HasLeg())
|
|
{
|
|
//
|
|
// Update to Times ...
|
|
leg.UpdateTimes();
|
|
|
|
//
|
|
DrawLeg();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Order Flow ...
|
|
|
|
//
|
|
bool drawOrderFlow;
|
|
XBoxZone orderFlow[];
|
|
bool manageOrderFlow;
|
|
ENUM_X_DIRECTION orderFlowDir;
|
|
|
|
//
|
|
bool HasOrderFlow()
|
|
{
|
|
//
|
|
return HasChild(orderFlow) &&
|
|
HasDirection(orderFlowDir);
|
|
}
|
|
|
|
//
|
|
bool HasBullishOrderFlow()
|
|
{
|
|
return HasOrderFlow() &&
|
|
IsXBullish(orderFlowDir);
|
|
}
|
|
|
|
//
|
|
bool HasBearishOrderFlow()
|
|
{
|
|
return HasOrderFlow() &&
|
|
IsXBearish(orderFlowDir);
|
|
}
|
|
|
|
//
|
|
bool GetOrderFlowBoundary(
|
|
double &upper,
|
|
double &lower //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
upper = EMPTY_VALUE;
|
|
lower = EMPTY_VALUE;
|
|
|
|
//
|
|
// Validate ...
|
|
result = HasOrderFlow();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
|
|
//
|
|
// Upper ...
|
|
idx = GetHighest(orderFlow);
|
|
if (IsValidIndex(idx))
|
|
{
|
|
upper = orderFlow[idx].upper;
|
|
}
|
|
|
|
//
|
|
// Lower ...
|
|
idx = GetLowest(orderFlow);
|
|
if (IsValidIndex(idx))
|
|
{
|
|
lower = orderFlow[idx].lower;
|
|
}
|
|
|
|
//
|
|
result = NotEmptyZero(upper) &&
|
|
NotEmptyZero(lower) &&
|
|
upper > lower;
|
|
|
|
//
|
|
// Cleanup ...
|
|
if (!result)
|
|
{
|
|
//
|
|
upper = EMPTY_VALUE;
|
|
lower = EMPTY_VALUE;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool ValidateOrderFlow(XOHCL &bar)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
HasOrderFlow();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double upper = EMPTY_VALUE;
|
|
double lower = EMPTY_VALUE;
|
|
result = GetOrderFlowBoundary(upper, lower);
|
|
result = result &&
|
|
HasBullishOrderFlow()
|
|
? bar.low > lower
|
|
: bar.high < upper;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void DrawOrderFlow()
|
|
{
|
|
//
|
|
if (!drawOrderFlow || !HasOrderFlow())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
poiDrawer.DrawZones(orderFlow, structureDrawConfig.drawConfig);
|
|
}
|
|
|
|
//
|
|
void ManageOrderFlow(XOHCL &bar)
|
|
{
|
|
//
|
|
// Validate Exists ...
|
|
if (HasOrderFlow())
|
|
{
|
|
//
|
|
if (!ValidateOrderFlow(bar))
|
|
{
|
|
//
|
|
// Invalidate OrderFlow ...
|
|
XClean(orderFlow);
|
|
orderFlowDir = X_DIRECTION_NONE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Detect New ...
|
|
if (!HasOrderFlow())
|
|
{
|
|
//
|
|
XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig;
|
|
// patternConfig.Default();
|
|
// patternConfig.supportAndResistanceLoopbackLength = 21;
|
|
// patternConfig.supportAndResistanceValidationLength = 7;
|
|
|
|
//
|
|
poiDetector.HasOrderFlow(
|
|
bar,
|
|
orderFlowDir,
|
|
orderFlow,
|
|
structureConfig.orderFlowValidation,
|
|
structureConfig.orderFlowUseOB,
|
|
structureConfig.orderFlowUseFVG,
|
|
structureConfig.orderFlowUseSupportAndResistance,
|
|
patternConfig.supportAndResistanceLoopbackLength,
|
|
patternConfig.supportAndResistanceValidationLength,
|
|
structureConfig.loopback //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Update Exists ...
|
|
if (HasOrderFlow())
|
|
{
|
|
//
|
|
// Update to Times ...
|
|
UpdateToTime(orderFlow, TimeCurrent());
|
|
|
|
//
|
|
DrawOrderFlow();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Zone ...
|
|
|
|
//
|
|
XBoxZone support;
|
|
XBoxZone resistance;
|
|
bool drawZones;
|
|
bool drawSupport;
|
|
bool manageZones;
|
|
bool drawResistance;
|
|
|
|
//
|
|
bool HasZones()
|
|
{
|
|
return HasSupport() ||
|
|
HasResistance();
|
|
}
|
|
|
|
//
|
|
bool HasSupport()
|
|
{
|
|
return support.IsValid();
|
|
}
|
|
|
|
//
|
|
bool HasResistance()
|
|
{
|
|
return resistance.IsValid();
|
|
}
|
|
|
|
//
|
|
bool ValidateZones(XOHCL &bar)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
HasZones();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Support ...
|
|
bool hasSupport = HasSupport();
|
|
if (hasSupport)
|
|
{
|
|
//
|
|
result = bar.close > support.lower &&
|
|
!IsBreaked(support, X_PRICE_CLOSE);
|
|
if (!result)
|
|
{
|
|
//
|
|
iResistance = support;
|
|
iResistance.breakAt = NULL;
|
|
iResistance.dir = X_DIRECTION_BEARISH;
|
|
iResistance.to = bar.time + (PeriodSeconds(bar.period));
|
|
iResistance.from = bar.time - (PeriodSeconds(bar.period));
|
|
|
|
//
|
|
support.breakAt = bar.time;
|
|
support.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Resistance ...
|
|
bool hasResistance = HasResistance();
|
|
if (hasResistance)
|
|
{
|
|
//
|
|
result = bar.close < resistance.upper &&
|
|
!IsBreaked(resistance, X_PRICE_CLOSE);
|
|
if (!result)
|
|
{
|
|
//
|
|
iSupport = resistance;
|
|
iSupport.breakAt = NULL;
|
|
iSupport.dir = X_DIRECTION_BULLISH;
|
|
iSupport.to = bar.time + (PeriodSeconds(bar.period));
|
|
iSupport.from = bar.time - (PeriodSeconds(bar.period));
|
|
|
|
//
|
|
resistance.breakAt = bar.time;
|
|
resistance.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
result =
|
|
(hasSupport && !HasSupport()) ||
|
|
(hasResistance && !HasResistance());
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void DrawZones()
|
|
{
|
|
//
|
|
if (!drawZones || !HasZones())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
if (drawSupport && HasSupport())
|
|
{
|
|
poiDrawer.DrawZone(support, structureDrawConfig.drawConfig);
|
|
}
|
|
|
|
//
|
|
if (drawResistance && HasResistance())
|
|
{
|
|
poiDrawer.DrawZone(resistance, structureDrawConfig.drawConfig);
|
|
}
|
|
}
|
|
|
|
//
|
|
void ManageZones(XOHCL &bar)
|
|
{
|
|
//
|
|
// Validate Exists ...
|
|
if (HasZones())
|
|
{
|
|
//
|
|
if (!ValidateZones(bar))
|
|
{
|
|
//
|
|
// Invalidate Zones ...
|
|
|
|
//
|
|
// Support ...
|
|
if (IsXValid(support.breakAt))
|
|
{
|
|
//
|
|
iResistance = support;
|
|
iResistance.breakAt = NULL;
|
|
iResistance.dir = X_DIRECTION_BEARISH;
|
|
iResistance.to = bar.time + (PeriodSeconds(bar.period));
|
|
iResistance.from = bar.time - (PeriodSeconds(bar.period));
|
|
|
|
//
|
|
support.Clean();
|
|
}
|
|
|
|
//
|
|
// Resistance ...
|
|
if (IsXValid(resistance.breakAt))
|
|
{
|
|
//
|
|
iSupport = resistance;
|
|
iSupport.breakAt = NULL;
|
|
iSupport.dir = X_DIRECTION_BULLISH;
|
|
iSupport.to = bar.time + (PeriodSeconds(bar.period));
|
|
iSupport.from = bar.time - (PeriodSeconds(bar.period));
|
|
|
|
//
|
|
resistance.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Detect New ...
|
|
XOHCL tmpBar;
|
|
bool has = false;
|
|
|
|
//
|
|
// Detect Support ...
|
|
if (!HasSupport())
|
|
{
|
|
//
|
|
has = poiDetector.HasSupport(
|
|
bar,
|
|
tmpBar,
|
|
structureConfig.barsAnalysisConfig.supportAndResistanceValidationLength,
|
|
structureConfig.barsAnalysisConfig.supportAndResistanceLoopbackLength //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
has = ToSupportBox(tmpBar, support, bar.time);
|
|
has =
|
|
has &&
|
|
!IsBreaked(support, X_PRICE_CLOSE);
|
|
if (!has)
|
|
{
|
|
//
|
|
if (support.IsValid())
|
|
{
|
|
//
|
|
iResistance = support;
|
|
iResistance.breakAt = NULL;
|
|
iResistance.dir = X_DIRECTION_BEARISH;
|
|
iResistance.to = bar.time + (PeriodSeconds(bar.period));
|
|
iResistance.from = bar.time - (PeriodSeconds(bar.period));
|
|
}
|
|
|
|
//
|
|
support.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Detect Resistance ...
|
|
if (!HasResistance())
|
|
{
|
|
//
|
|
has = poiDetector.HasResistance(
|
|
bar,
|
|
tmpBar,
|
|
structureConfig.barsAnalysisConfig.supportAndResistanceValidationLength,
|
|
structureConfig.barsAnalysisConfig.supportAndResistanceLoopbackLength //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
has = ToResistanceBox(tmpBar, resistance, bar.time);
|
|
has =
|
|
has &&
|
|
!IsBreaked(resistance, X_PRICE_CLOSE);
|
|
if (!has)
|
|
{
|
|
//
|
|
if (resistance.IsValid())
|
|
{
|
|
//
|
|
iSupport = resistance;
|
|
iSupport.breakAt = NULL;
|
|
iSupport.dir = X_DIRECTION_BULLISH;
|
|
iSupport.to = bar.time + (PeriodSeconds(bar.period));
|
|
iSupport.from = bar.time - (PeriodSeconds(bar.period));
|
|
}
|
|
|
|
//
|
|
resistance.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update Exists ...
|
|
if (HasZones())
|
|
{
|
|
//
|
|
if (HasSupport())
|
|
{
|
|
//
|
|
support.to = bar.time;
|
|
support.type = "XFIMASup";
|
|
}
|
|
|
|
//
|
|
if (HasResistance())
|
|
{
|
|
//
|
|
resistance.to = bar.time;
|
|
resistance.type = "XFIMARes";
|
|
}
|
|
|
|
//
|
|
DrawZones();
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
tmpBar.Clean();
|
|
}
|
|
|
|
//
|
|
XBoxZone iSupport;
|
|
XBoxZone iResistance;
|
|
bool drawIZones;
|
|
bool drawISupport;
|
|
bool manageIZones;
|
|
bool drawIResistance;
|
|
|
|
//
|
|
bool HasIZones()
|
|
{
|
|
//
|
|
return HasISupport() ||
|
|
HasIResistance();
|
|
}
|
|
|
|
//
|
|
bool HasISupport()
|
|
{
|
|
return iSupport.IsValid();
|
|
}
|
|
|
|
//
|
|
bool HasIResistance()
|
|
{
|
|
return iResistance.IsValid();
|
|
}
|
|
|
|
//
|
|
void DrawIZones()
|
|
{
|
|
//
|
|
if (!drawIZones || !HasIZones())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
if (drawISupport && HasISupport())
|
|
{
|
|
poiDrawer.DrawZone(iSupport, structureDrawConfig.drawConfig);
|
|
}
|
|
|
|
//
|
|
if (drawIResistance && HasIResistance())
|
|
{
|
|
poiDrawer.DrawZone(iResistance, structureDrawConfig.drawConfig);
|
|
}
|
|
}
|
|
|
|
//
|
|
bool ValidateIZones(XOHCL &bar)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
HasIZones();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
|
|
//
|
|
// Support ...
|
|
bool hasSupport = HasISupport();
|
|
if (hasSupport)
|
|
{
|
|
//
|
|
result = bar.close > iSupport.lower &&
|
|
!IsBreaked(iSupport, X_PRICE_CLOSE);
|
|
if (!result)
|
|
{
|
|
//
|
|
iSupport.breakAt = bar.time;
|
|
iSupport.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Resistance ...
|
|
bool hasResistance = HasIResistance();
|
|
if (hasResistance)
|
|
{
|
|
//
|
|
result = bar.close < iResistance.upper &&
|
|
!IsBreaked(iResistance, X_PRICE_CLOSE);
|
|
if (!result)
|
|
{
|
|
//
|
|
iResistance.breakAt = bar.time;
|
|
iResistance.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
result =
|
|
(hasSupport && !HasISupport()) ||
|
|
(hasResistance && !HasIResistance());
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void ManageIZones(XOHCL &bar)
|
|
{
|
|
//
|
|
// Validate Exists ...
|
|
if (HasIZones())
|
|
{
|
|
//
|
|
if (!ValidateIZones(bar))
|
|
{
|
|
//
|
|
// Invalidate Zones ...
|
|
|
|
//
|
|
// Support ...
|
|
if (IsXValid(iSupport.breakAt))
|
|
{
|
|
iSupport.Clean();
|
|
}
|
|
|
|
//
|
|
// Resistance ...
|
|
if (IsXValid(iResistance.breakAt))
|
|
{
|
|
iResistance.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update Exists ...
|
|
if (HasIZones())
|
|
{
|
|
//
|
|
if (HasISupport())
|
|
{
|
|
//
|
|
iSupport.to = bar.time;
|
|
iSupport.type = "XFIMAISup";
|
|
}
|
|
|
|
//
|
|
if (HasIResistance())
|
|
{
|
|
//
|
|
iResistance.to = bar.time;
|
|
iResistance.type = "XFIMAIRes";
|
|
}
|
|
|
|
//
|
|
DrawIZones();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Trends ...
|
|
|
|
//
|
|
XTrend scTrend;
|
|
XTrend mcTrend;
|
|
XTrend lcTrend;
|
|
XTrend hcTrend;
|
|
|
|
//
|
|
bool drawTrends;
|
|
bool drawSCTrend;
|
|
bool drawMCTrend;
|
|
bool drawLCTrend;
|
|
bool drawHCTrend;
|
|
bool manageTrends;
|
|
|
|
//
|
|
bool HasTrend()
|
|
{
|
|
//
|
|
bool result =
|
|
HasSCTrend() ||
|
|
HasMCTrend() ||
|
|
HasLCTrend() ||
|
|
HasHCTrend();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasSCTrend()
|
|
{
|
|
return scTrend.IsValid() &&
|
|
scTrend.HasTrend();
|
|
}
|
|
|
|
//
|
|
bool HasMCTrend()
|
|
{
|
|
return mcTrend.IsValid() &&
|
|
mcTrend.HasTrend();
|
|
}
|
|
|
|
//
|
|
bool HasLCTrend()
|
|
{
|
|
return lcTrend.IsValid() &&
|
|
lcTrend.HasTrend();
|
|
}
|
|
|
|
//
|
|
bool HasHCTrend()
|
|
{
|
|
return hcTrend.IsValid() &&
|
|
hcTrend.HasTrend();
|
|
}
|
|
|
|
//
|
|
void DrawTrends()
|
|
{
|
|
//
|
|
if (!drawTrends || !HasTrend())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// SC ...
|
|
if (drawSCTrend && HasSCTrend())
|
|
{
|
|
poiDrawer.DrawTrendLine(scTrend, structureDrawConfig.drawConfig);
|
|
}
|
|
|
|
//
|
|
// MC ...
|
|
if (drawMCTrend && HasMCTrend())
|
|
{
|
|
poiDrawer.DrawTrendLine(mcTrend, structureDrawConfig.drawConfig);
|
|
}
|
|
|
|
//
|
|
// LC ...
|
|
if (drawLCTrend && HasLCTrend())
|
|
{
|
|
poiDrawer.DrawTrendLine(lcTrend, structureDrawConfig.drawConfig);
|
|
}
|
|
|
|
//
|
|
// HC ...
|
|
if (drawHCTrend && HasHCTrend())
|
|
{
|
|
poiDrawer.DrawTrendLine(hcTrend, structureDrawConfig.drawConfig);
|
|
}
|
|
}
|
|
|
|
//
|
|
void ManageTrends(XOHCL &bar)
|
|
{
|
|
//
|
|
// Validate ...
|
|
bool has = bar.IsValid();
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XTrend tmpTrend;
|
|
|
|
//
|
|
// SC ...
|
|
tmpTrend.Clean();
|
|
has = fimaParser.HasSCTrend(tmpTrend, bar.Index());
|
|
if (has)
|
|
{
|
|
scTrend = tmpTrend;
|
|
}
|
|
|
|
//
|
|
// MC ...
|
|
tmpTrend.Clean();
|
|
has = fimaParser.HasMCTrend(tmpTrend, bar.Index());
|
|
if (has)
|
|
{
|
|
mcTrend = tmpTrend;
|
|
}
|
|
|
|
//
|
|
// LC ...
|
|
tmpTrend.Clean();
|
|
has = fimaParser.HasLCTrend(tmpTrend, bar.Index());
|
|
if (has)
|
|
{
|
|
lcTrend = tmpTrend;
|
|
}
|
|
|
|
//
|
|
// HC ...
|
|
tmpTrend.Clean();
|
|
has = fimaParser.HasHCTrend(tmpTrend, bar.Index());
|
|
if (has)
|
|
{
|
|
hcTrend = tmpTrend;
|
|
}
|
|
|
|
//
|
|
DrawTrends();
|
|
|
|
//
|
|
// Cleanup ...
|
|
tmpTrend.Clean();
|
|
}
|
|
|
|
//
|
|
// Implementing Strategies ...
|
|
|
|
/**
|
|
* Check Bar Has Signal Based on Strategy X ...
|
|
*
|
|
* @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 ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasSignal(
|
|
XOHCL &bar,
|
|
XBoxZone &zone,
|
|
XTarget &targets[],
|
|
ENUM_X_DIRECTION &dir //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Configuration Flags ...
|
|
|
|
//
|
|
// Signaller Flags ...
|
|
bool useSignaller1 = false;
|
|
bool useSignaller2 = true;
|
|
bool useSignaller3 = true;
|
|
bool useSignaller4 = true;
|
|
|
|
//
|
|
// Validator Flags ...
|
|
string provider = NULL;
|
|
bool validateByOrderFlow = false;
|
|
|
|
//
|
|
// Target Flags ...
|
|
bool hasPartialCloseOnTp1 = false;
|
|
|
|
//
|
|
bool doRFOnEntryOnTP1 = false;
|
|
|
|
//
|
|
// Draw Flags ...
|
|
bool draw = true;
|
|
bool drawZone = true;
|
|
bool drawMarketStructurePivots = false;
|
|
bool drawMarketStructureAnalysis = false;
|
|
bool drawMarketStructureOrderFlow = false;
|
|
XPOIDrawConfig iDrawConfig;
|
|
|
|
//
|
|
drawLeg = false;
|
|
drawZones = false;
|
|
drawIZones = false;
|
|
drawTrends = false;
|
|
drawSCTrend = false;
|
|
drawMCTrend = false;
|
|
drawLCTrend = false;
|
|
drawHCTrend = false;
|
|
drawSupport = false;
|
|
drawISupport = false;
|
|
drawOrderFlow = false;
|
|
drawResistance = false;
|
|
drawIResistance = false;
|
|
|
|
//
|
|
// Signal Checking ...
|
|
|
|
//
|
|
// Analyse Market Strucutre ...
|
|
XFIMAMarketStructure marketStructure;
|
|
|
|
//
|
|
// Signaller 1 ...
|
|
if (!result && useSignaller1)
|
|
{
|
|
//
|
|
result = Strategy1HasSignal(
|
|
bar,
|
|
zone,
|
|
targets,
|
|
dir //
|
|
);
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
provider = "1";
|
|
}
|
|
}
|
|
|
|
//
|
|
// Signaller 2 ...
|
|
if (!result && useSignaller2)
|
|
{
|
|
//
|
|
result = Strategy2HasSignal(
|
|
bar,
|
|
zone,
|
|
targets,
|
|
dir //
|
|
);
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
provider = "2";
|
|
}
|
|
}
|
|
|
|
//
|
|
// Signaller 3 ...
|
|
if (!result && useSignaller3)
|
|
{
|
|
//
|
|
result = Strategy3HasSignal(
|
|
bar,
|
|
zone,
|
|
targets,
|
|
dir //
|
|
);
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
provider = "3";
|
|
}
|
|
}
|
|
|
|
//
|
|
// Signaller 4 ...
|
|
if (!result && useSignaller4)
|
|
{
|
|
//
|
|
result = Strategy4HasSignal(
|
|
bar,
|
|
zone,
|
|
targets,
|
|
dir //
|
|
);
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
provider = "4";
|
|
}
|
|
}
|
|
|
|
//
|
|
// Signal Validating ...
|
|
|
|
//
|
|
// Validate Signals by Order Flow ...
|
|
if (result && validateByOrderFlow)
|
|
{
|
|
//
|
|
// Analyse Market Structure if Required ...
|
|
if (!marketStructure.IsValid())
|
|
{
|
|
//
|
|
poiDetector.AnalyseMarket(
|
|
marketStructure,
|
|
structureConfig,
|
|
bar.Index() //
|
|
);
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsXBullish(dir) &&
|
|
marketStructure.HasBullishOrderFlow();
|
|
|
|
//
|
|
bool isBearish = IsXBearish(dir) &&
|
|
marketStructure.HasBearishOrderFlow();
|
|
|
|
//
|
|
// Summarizing result ...
|
|
result = isBullish ||
|
|
isBearish;
|
|
}
|
|
|
|
//
|
|
// Targets, Restrictions and Risk Management ...
|
|
if (result)
|
|
{
|
|
//
|
|
// Requirements ...
|
|
XTarget iTarget;
|
|
|
|
//
|
|
// Checking Direction of Signal ...
|
|
bool isBullish = IsXBullish(dir);
|
|
bool isBearish = IsXBearish(dir);
|
|
|
|
//
|
|
// Provided SL ...
|
|
double points = GetPoints(symbol);
|
|
double spread = GetSpread(symbol);
|
|
double entry = GetEntry(symbol, dir);
|
|
|
|
//
|
|
// Calculate SL Addition ...
|
|
double slAddition =
|
|
slAdditionDistance <= 0
|
|
? 0
|
|
: slAdditionDistance * points;
|
|
|
|
//
|
|
// Calculate SL Price ...
|
|
double sl =
|
|
isBullish
|
|
? zone.lower - slAddition
|
|
: zone.upper + slAddition;
|
|
|
|
//
|
|
// Calculate Risk ...
|
|
double risk = MathAbs(entry - sl);
|
|
|
|
//
|
|
// Calculate Reward ...
|
|
double reward = defaultSignalR2R * risk;
|
|
|
|
//
|
|
// Calculate TP1 ...
|
|
double tp1 = isBullish
|
|
? entry + risk
|
|
: entry - risk;
|
|
double tp2 = isBullish
|
|
? entry + (2 * risk)
|
|
: entry - (2 * risk);
|
|
|
|
//
|
|
// Calculate TP ...
|
|
double tp = isBullish
|
|
? entry + reward
|
|
: entry - reward;
|
|
|
|
//
|
|
// Check Max Allowed Risk ...
|
|
bool hasTooMuchRisk = maxAllowedRiskDistance <= 0
|
|
? false
|
|
: risk >= (maxAllowedRiskDistance * points);
|
|
if (hasTooMuchRisk)
|
|
{
|
|
//
|
|
// Clean Signal if Too much Risk ...
|
|
zone.Clean();
|
|
dir = X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
// Common Targets ...
|
|
|
|
//
|
|
// Partial Close on TP 1 ...
|
|
if (hasPartialCloseOnTp1)
|
|
{
|
|
//
|
|
iTarget.Clean();
|
|
iTarget.target = tp1;
|
|
iTarget.actingDistance = 5;
|
|
iTarget.volumeMultiplier = 0.8;
|
|
iTarget.doRFOnEntry = doRFOnEntryOnTP1;
|
|
|
|
//
|
|
AddRef(iTarget, targets);
|
|
}
|
|
|
|
//
|
|
// Custom Signaller Targets ...
|
|
|
|
//
|
|
// Restrictions Handling ...
|
|
if (risk > 0 && HasRestrictions())
|
|
{
|
|
//
|
|
// Reset Restricitons if necessary ...
|
|
ResetRestrictions();
|
|
|
|
//
|
|
// Handle Custom Restrictions Senario ...
|
|
}
|
|
|
|
//
|
|
// Ignore Targets ...
|
|
if (ignoreTargets)
|
|
{
|
|
XClean(targets);
|
|
}
|
|
|
|
//
|
|
// Summarize Result ...
|
|
result = zone.IsValid() &&
|
|
HasDirection(dir);
|
|
|
|
//
|
|
// Cleanup ...
|
|
iTarget.Clean();
|
|
}
|
|
|
|
//
|
|
// Draws ...
|
|
if (result && draw)
|
|
{
|
|
//
|
|
// Prepare Draw Config ...
|
|
iDrawConfig = structureDrawConfig.drawConfig;
|
|
iDrawConfig.zonesWidth = 3;
|
|
iDrawConfig.zonesStyle = STYLE_DASH;
|
|
iDrawConfig.bullishColor = clrYellow;
|
|
iDrawConfig.bearishColor = clrDarkOrange;
|
|
|
|
//
|
|
// Draw Zone ...
|
|
if (drawZone)
|
|
{
|
|
poiDrawer.DrawZone(zone, iDrawConfig);
|
|
}
|
|
|
|
//
|
|
// Draw Market Structure ...
|
|
//
|
|
// Analyse Market Structure if Required ...
|
|
if (!marketStructure.IsValid())
|
|
{
|
|
//
|
|
poiDetector.AnalyseMarket(
|
|
marketStructure,
|
|
structureConfig,
|
|
bar.Index() //
|
|
);
|
|
}
|
|
if (marketStructure.IsValid())
|
|
{
|
|
//
|
|
// Order Flow ...
|
|
if (drawMarketStructureOrderFlow && marketStructure.HasOrderFlow())
|
|
{
|
|
poiDrawer.DrawZones(marketStructure.orderFlow, iDrawConfig);
|
|
}
|
|
|
|
//
|
|
// Pivots ...
|
|
if (drawMarketStructurePivots)
|
|
{
|
|
//
|
|
XPivot pivots[];
|
|
int pivotsCount = marketStructure.CollectPivots(
|
|
pivots,
|
|
true // Contains Patterns ...
|
|
);
|
|
if (IsValidSize(pivotsCount))
|
|
{
|
|
poiDrawer.DrawPivots(pivots, iDrawConfig);
|
|
}
|
|
|
|
//
|
|
XClean(pivots);
|
|
}
|
|
|
|
//
|
|
// Analysis ...
|
|
if (drawMarketStructureAnalysis)
|
|
{
|
|
//
|
|
}
|
|
}
|
|
|
|
//
|
|
// Other Drawing Materials ...
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
if (!result)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
iDrawConfig.Clean();
|
|
marketStructure.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Custom Signal Strategies ...
|
|
|
|
/**
|
|
* 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 ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Strategy1HasSignal(
|
|
XOHCL &bar,
|
|
XBoxZone &zone,
|
|
XTarget &targets[],
|
|
ENUM_X_DIRECTION &dir //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Define Requirements ...
|
|
|
|
//
|
|
XOHCL pBar;
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
// Read PBar ...
|
|
result = bar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
//
|
|
pBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Reading Conditions ...
|
|
int pullBackStartBar = -1;
|
|
bool isPullBack = result &&
|
|
poiDetector.IsPullbackPattern(
|
|
pBar,
|
|
zone,
|
|
dir,
|
|
2,
|
|
false // Force Break ...
|
|
);
|
|
bool isPullbackBullish = isPullBack &&
|
|
IsXBullish(dir);
|
|
bool isPullbackBearish = isPullBack &&
|
|
IsXBearish(dir);
|
|
if (isPullBack)
|
|
{
|
|
pullBackStartBar = zone.FromIndex();
|
|
}
|
|
|
|
//
|
|
// Reading HK Band ...
|
|
|
|
//
|
|
double pHKBandUpper = fimaHelper.GetHKBandUpper(pBar.Index());
|
|
double pHKBandLower = fimaHelper.GetHKBandLower(pBar.Index());
|
|
int overHKBandUpperCount = fimaParser.CountOverHKBandUpper(pullBackStartBar, X_PRICE_LOW);
|
|
int underHKBandLowerCount = fimaParser.CountUnderHKBandLower(pullBackStartBar, X_PRICE_HIGH);
|
|
|
|
//
|
|
// Reading PV Requirements ...
|
|
|
|
//
|
|
int lastPeakOverLastIDX = -1;
|
|
int lastValeUnderLastIDX = -1;
|
|
double pPeak = fimaHelper.GetPeak(pBar.Index());
|
|
double pVale = fimaHelper.GetVale(pBar.Index());
|
|
int samePeaks = fimaParser.CountSamePeaks(pBar.Index());
|
|
int sameVales = fimaParser.CountSameVales(pBar.Index());
|
|
fimaParser.FindLastPeakOverLast(lastPeakOverLastIDX, pBar.Index());
|
|
fimaParser.FindLastValeUnderLast(lastValeUnderLastIDX, pBar.Index());
|
|
|
|
//
|
|
// Reading pBar Patterns ...
|
|
XPatternAnalysis pBarAnalysis;
|
|
poiDetector.AnalyseBarPatterns(
|
|
pBar,
|
|
pBarAnalysis,
|
|
structureConfig.barsAnalysisConfig //
|
|
);
|
|
|
|
//
|
|
// Check Bar Patterns ...
|
|
bool isPBarHasBullishPatterns =
|
|
(bar.close > pBar.low ||
|
|
bar.open > pBar.low) &&
|
|
(
|
|
//
|
|
pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) ||
|
|
pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) ||
|
|
pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) ||
|
|
pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) ||
|
|
pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH)
|
|
//
|
|
);
|
|
bool isPBarHasBearishPatterns =
|
|
(bar.close < pBar.high ||
|
|
bar.open < pBar.high) &&
|
|
(
|
|
//
|
|
pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) ||
|
|
pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) ||
|
|
pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) ||
|
|
pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) ||
|
|
pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH)
|
|
//
|
|
);
|
|
|
|
//
|
|
// Check PBar Close Over Under Fast Ma ...
|
|
bool isPBarCloseOverFast = pBar.close > fimaHelper.GetMAFast(pBar.Index());
|
|
bool isPBarCloseUnderFast = pBar.close < fimaHelper.GetMAFast(pBar.Index());
|
|
|
|
//
|
|
// Try To Find Affected Zone ...
|
|
|
|
//
|
|
// Collecting Zones ...
|
|
XBoxZone zones[];
|
|
XBoxZone affectedZones[];
|
|
XBoxZone affectedZonesBullish[];
|
|
XBoxZone affectedZonesBearish[];
|
|
int zonesCount = poiDetector.CollectZones(
|
|
pBar,
|
|
zones, //
|
|
5, // Zones Loopback ...
|
|
3 // Zones Validation Length ...
|
|
// Required Zones ...
|
|
// Loopback ...
|
|
);
|
|
int affectedZonesCount = ExtractAffectedZones(
|
|
pBar,
|
|
zones,
|
|
affectedZones //
|
|
);
|
|
int affectedZonesBullishCount = ExtractByDirection(
|
|
affectedZonesBullish,
|
|
affectedZones,
|
|
X_DIRECTION_BULLISH //
|
|
);
|
|
int affectedZonesBearishCount = ExtractByDirection(
|
|
affectedZonesBearish,
|
|
affectedZones,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
int insideBullishIDX = -1;
|
|
int insideBearishIDX = -1;
|
|
bool hasBullishInside =
|
|
pBar.IsBullish() &&
|
|
HasInside(
|
|
insideBullishIDX,
|
|
pBar,
|
|
affectedZonesBullish //
|
|
);
|
|
bool hasBearishInside =
|
|
pBar.IsBearish() &&
|
|
HasInside(
|
|
insideBearishIDX,
|
|
pBar,
|
|
affectedZonesBearish //
|
|
);
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
isBullish =
|
|
//
|
|
hasBullishInside &&
|
|
isPullbackBullish &&
|
|
isPBarHasBullishPatterns &&
|
|
fimaParser.IsSARBullish(pBar.Index()) &&
|
|
(pVale >= affectedZonesBullish[insideBullishIDX].lower &&
|
|
pVale <= affectedZonesBullish[insideBullishIDX].upper)
|
|
//
|
|
;
|
|
|
|
//
|
|
isBearish =
|
|
//
|
|
hasBearishInside &&
|
|
isPullbackBearish &&
|
|
isPBarHasBearishPatterns &&
|
|
fimaParser.IsSARBearish(pBar.Index()) &&
|
|
(pPeak >= affectedZonesBearish[insideBearishIDX].lower &&
|
|
pPeak <= affectedZonesBearish[insideBearishIDX].upper)
|
|
//
|
|
;
|
|
|
|
//
|
|
// Validate ...
|
|
result = isBullish ||
|
|
isBearish;
|
|
if (result)
|
|
{
|
|
//
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = HasDirection(dir);
|
|
}
|
|
|
|
//
|
|
// Prepare Zone ...
|
|
if (result)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
if (isBullish)
|
|
{
|
|
zone = affectedZonesBullish[insideBullishIDX];
|
|
}
|
|
else
|
|
{
|
|
zone = affectedZonesBearish[insideBearishIDX];
|
|
}
|
|
|
|
//
|
|
result = zone.IsValid();
|
|
}
|
|
|
|
//
|
|
// Prepare Targets ...
|
|
if (result)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
if (!result)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
}
|
|
pBar.Clean();
|
|
XClean(zones);
|
|
pBarAnalysis.Clean();
|
|
XClean(affectedZones);
|
|
XClean(affectedZonesBullish);
|
|
XClean(affectedZonesBearish);
|
|
|
|
//
|
|
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 ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Strategy2HasSignal(
|
|
XOHCL &bar,
|
|
XBoxZone &zone,
|
|
XTarget &targets[],
|
|
ENUM_X_DIRECTION &dir //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Define Requirements ...
|
|
|
|
//
|
|
XOHCL pBar;
|
|
XOHCL p2Bar;
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
// Read PBar ...
|
|
result = bar.GetPreviousBar(pBar);
|
|
result = result &&
|
|
pBar.GetPreviousBar(p2Bar);
|
|
if (!result)
|
|
{
|
|
//
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Reading pBar Patterns ...
|
|
XPatternAnalysis pBarAnalysis;
|
|
poiDetector.AnalyseBarPatterns(
|
|
pBar,
|
|
pBarAnalysis,
|
|
structureConfig.barsAnalysisConfig //
|
|
);
|
|
|
|
//
|
|
// Check Bar Patterns ...
|
|
bool isPBarHasBullishPatterns =
|
|
(bar.close > pBar.low ||
|
|
bar.open > pBar.low) &&
|
|
(
|
|
//
|
|
pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) ||
|
|
pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) ||
|
|
pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) ||
|
|
pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) ||
|
|
pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH)
|
|
//
|
|
);
|
|
bool isPBarHasBearishPatterns =
|
|
(bar.close < pBar.high ||
|
|
bar.open < pBar.high) &&
|
|
(
|
|
//
|
|
pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) ||
|
|
pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) ||
|
|
pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) ||
|
|
pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) ||
|
|
pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH)
|
|
//
|
|
);
|
|
|
|
//
|
|
double peak = fimaHelper.GetPeak(bar.Index());
|
|
double vale = fimaHelper.GetVale(bar.Index());
|
|
double pPeak = fimaHelper.GetPeak(pBar.Index());
|
|
double pVale = fimaHelper.GetVale(pBar.Index());
|
|
double p2Peak = fimaHelper.GetPeak(p2Bar.Index());
|
|
double p2Vale = fimaHelper.GetVale(p2Bar.Index());
|
|
bool isPPeakOverLast = fimaParser.IsPeakOverLast(pBar.Index());
|
|
bool isPValeUnderLast = fimaParser.IsValeUnderLast(pBar.Index());
|
|
bool isP2PeakOverLast = fimaParser.IsPeakOverLast(p2Bar.Index());
|
|
bool isP2ValeUnderLast = fimaParser.IsValeUnderLast(p2Bar.Index());
|
|
bool isPeakOverLast = isPPeakOverLast ||
|
|
isP2PeakOverLast;
|
|
bool isValeUnderLast = isPValeUnderLast ||
|
|
isP2ValeUnderLast;
|
|
bool isP2ValeOverLast = pVale > p2Vale;
|
|
bool isP2PeakUnderLast = pPeak < p2Peak;
|
|
|
|
//
|
|
// Check PBar Close Over Under Fast Ma ...
|
|
bool isPBarCloseOverFast = pBar.close > fimaHelper.GetMAFast(pBar.Index());
|
|
bool isPBarCloseUnderFast = pBar.close < fimaHelper.GetMAFast(pBar.Index());
|
|
bool isFastOverLast = fimaHelper.GetMAFast(pBar.Index()) > fimaHelper.GetMAFast(p2Bar.Index());
|
|
bool isFastUnderLast = fimaHelper.GetMAFast(pBar.Index()) < fimaHelper.GetMAFast(p2Bar.Index());
|
|
|
|
//
|
|
// Force P2Bar is Pin Bar ...
|
|
ENUM_X_DIRECTION p2Dir;
|
|
bool isP2BarPinned = poiDetector.IsPinnedBar(
|
|
p2Bar,
|
|
p2Dir //
|
|
);
|
|
bool isP2BarBullishPinned =
|
|
isP2BarPinned &&
|
|
IsXBullish(p2Dir);
|
|
bool isP2BarBearishPinned =
|
|
isP2BarPinned &&
|
|
IsXBearish(p2Dir);
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
isBullish =
|
|
//
|
|
isFastOverLast &&
|
|
isValeUnderLast &&
|
|
!isP2PeakUnderLast &&
|
|
isPBarCloseOverFast &&
|
|
isP2BarBullishPinned &&
|
|
isPBarHasBullishPatterns
|
|
//
|
|
;
|
|
|
|
//
|
|
isBearish =
|
|
//
|
|
isPeakOverLast &&
|
|
isFastUnderLast &&
|
|
!isP2ValeOverLast &&
|
|
isPBarCloseUnderFast &&
|
|
isP2BarBearishPinned &&
|
|
isPBarHasBearishPatterns
|
|
//
|
|
;
|
|
|
|
//
|
|
// Validate ...
|
|
result = isBullish ||
|
|
isBearish;
|
|
if (result)
|
|
{
|
|
//
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = HasDirection(dir);
|
|
}
|
|
|
|
//
|
|
// Prepare Zone ...
|
|
if (result)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
result = ToBox(
|
|
p2Bar,
|
|
zone,
|
|
dir,
|
|
X_BAR_PATTERN_PINNED //
|
|
);
|
|
|
|
//
|
|
// Manage Stops ...
|
|
if (result)
|
|
{
|
|
//
|
|
double entry = GetEntry(zone.symbol, zone.dir);
|
|
double riskSide = zone.IsBullish() ? zone.lower : zone.upper;
|
|
double risk = MathAbs(entry - riskSide);
|
|
|
|
//
|
|
// Collecting Affected Zones ...
|
|
XBoxZone tmps[];
|
|
XBoxZone zones[];
|
|
XBoxZone actedZones[];
|
|
XBoxZone insideZones[];
|
|
XBoxZone breakedZones[];
|
|
XBoxZone affectedZones[];
|
|
|
|
//
|
|
// Support and Resistances ...
|
|
poiDetector.CollectZones(bar, tmps);
|
|
Copy(tmps, zones, false);
|
|
|
|
//
|
|
// OBS ...
|
|
poiDetector.CollectOBs(bar, tmps);
|
|
Copy(tmps, zones, false);
|
|
|
|
//
|
|
// FVGs ...
|
|
poiDetector.CollectFVGs(bar, tmps);
|
|
Copy(tmps, zones, false);
|
|
|
|
//
|
|
ExtractAffectedZones(bar, zones, affectedZones);
|
|
|
|
//
|
|
// Acteds Zones ...
|
|
ExtractActeds(bar, actedZones, affectedZones);
|
|
|
|
//
|
|
// Inside Zones ...
|
|
ExtractInsides(bar, insideZones, affectedZones);
|
|
|
|
//
|
|
// Breaked Zones ...
|
|
ExtractBreakeds(bar, breakedZones, affectedZones);
|
|
|
|
//
|
|
// Cleanup ...
|
|
XClean(tmps);
|
|
XClean(zones);
|
|
XClean(actedZones);
|
|
XClean(insideZones);
|
|
XClean(breakedZones);
|
|
XClean(affectedZones);
|
|
}
|
|
|
|
//
|
|
result = zone.IsValid();
|
|
}
|
|
|
|
//
|
|
// Prepare Targets ...
|
|
if (result)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
if (!result)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
}
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Bar Has Signal Based on Strategy 3 ...
|
|
*
|
|
* Strategy 3:
|
|
* ===========
|
|
* - Works Based On Breaked Support or Resistances ...
|
|
* - Looking for a Support or Resistance to Breaked ...
|
|
* - Validate Breaker Bar to Change Peak or Vale ...
|
|
* - Validate Bar Opposit Side of Breaker Bar's Shadow ...
|
|
* - Validate by Checking Market Strucutre to Has Directional Zone
|
|
* (Support for Resistance Break / Resistance for Support Break) ...
|
|
* - Validate Breaker Bar to Has Directional FVG ...
|
|
*
|
|
* Manipulations:
|
|
* ================
|
|
* there are Some Flags properties to Change Validations in Strategy ...
|
|
* we can use them for Testing Purposes ...
|
|
*
|
|
* @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 ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Strategy3HasSignal(
|
|
XOHCL &bar,
|
|
XBoxZone &zone,
|
|
XTarget &targets[],
|
|
ENUM_X_DIRECTION &dir //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Validation Flags ...
|
|
|
|
//
|
|
bool validateByPVChanges = true;
|
|
bool validateByGapExists = true;
|
|
bool validateByBarShadows = true;
|
|
bool validateHasDirectionalZone = true;
|
|
|
|
//
|
|
// Define Requirements ...
|
|
|
|
//
|
|
XOHCL pBar;
|
|
XOHCL p2Bar;
|
|
XOHCL p3Bar;
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
// Read PBar ...
|
|
result = bar.GetPreviousBar(pBar);
|
|
result = result &&
|
|
pBar.GetPreviousBar(p2Bar);
|
|
result = result &&
|
|
p2Bar.GetPreviousBar(p3Bar);
|
|
if (!result)
|
|
{
|
|
//
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
// Retrieve pBar Patterns ...
|
|
XBoxZone _fvg;
|
|
XBoxZone _support;
|
|
XBoxZone _resistance;
|
|
XPatternAnalysis pBarPatterns;
|
|
XPatternAnalysis p2BarPatterns;
|
|
XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig;
|
|
|
|
//
|
|
poiDetector.AnalyseBarPatterns(
|
|
pBar,
|
|
pBarPatterns,
|
|
patternConfig //
|
|
);
|
|
poiDetector.AnalyseBarPatterns(
|
|
p2Bar,
|
|
p2BarPatterns,
|
|
patternConfig //
|
|
);
|
|
|
|
//
|
|
// Price Must Break Support or Resistance ...
|
|
|
|
//
|
|
// Extract Support and Resistance ...
|
|
bool hasSupport = p2BarPatterns.IsSupport();
|
|
bool hasResistance = p2BarPatterns.IsResistance();
|
|
if (hasSupport)
|
|
{
|
|
//
|
|
XOHCL tmpBar;
|
|
XPivot tmpPivot;
|
|
hasSupport = p2BarPatterns.GetSupport(tmpBar, tmpPivot, _support);
|
|
tmpBar.Clean();
|
|
tmpPivot.Clean();
|
|
}
|
|
if (hasResistance)
|
|
{
|
|
//
|
|
XOHCL tmpBar;
|
|
XPivot tmpPivot;
|
|
hasResistance = p2BarPatterns.GetResistance(tmpBar, tmpPivot, _resistance);
|
|
tmpBar.Clean();
|
|
tmpPivot.Clean();
|
|
}
|
|
|
|
//
|
|
bool hasBreakedSupport = hasSupport &&
|
|
pBar.close < _support.lower &&
|
|
p2Bar.close > _support.lower;
|
|
bool hasBreakedResistance = hasResistance &&
|
|
pBar.close > _resistance.upper &&
|
|
p2Bar.close < _resistance.upper;
|
|
|
|
//
|
|
isBullish = hasBreakedResistance;
|
|
isBearish = hasBreakedSupport;
|
|
|
|
//
|
|
result = isBullish || isBearish;
|
|
|
|
//
|
|
// Validate By PV Changed ...
|
|
// Breaker Bar must Change Peak or Value ...
|
|
if (result && validateByPVChanges)
|
|
{
|
|
//
|
|
bool isPeakOverLast = fimaParser.IsPeakOverLast(pBar.Index());
|
|
bool isValeUnderLast = fimaParser.IsValeUnderLast(pBar.Index());
|
|
|
|
//
|
|
isBullish =
|
|
isBullish &&
|
|
isPeakOverLast;
|
|
|
|
//
|
|
isBearish =
|
|
isBearish &&
|
|
isValeUnderLast;
|
|
|
|
//
|
|
// Summarize Result ...
|
|
result = isBullish || isBearish;
|
|
}
|
|
|
|
//
|
|
// Validate by Bar Shadows ...
|
|
// Breakre Bar Side Shadow must not Reached ...
|
|
if (result && validateByBarShadows)
|
|
{
|
|
//
|
|
isBullish =
|
|
isBullish &&
|
|
pBar.low > p2Bar.low;
|
|
|
|
//
|
|
isBearish =
|
|
isBearish &&
|
|
pBar.high < p2Bar.high;
|
|
|
|
//
|
|
// Summarize Result ...
|
|
result = isBullish || isBearish;
|
|
}
|
|
|
|
//
|
|
// Validate Has Directional Zone ...
|
|
if (result && validateHasDirectionalZone)
|
|
{
|
|
//
|
|
isBullish =
|
|
isBullish &&
|
|
hasSupport;
|
|
|
|
//
|
|
isBearish =
|
|
isBearish &&
|
|
hasResistance;
|
|
|
|
//
|
|
// Summarize Result ...
|
|
result = isBullish || isBearish;
|
|
}
|
|
|
|
//
|
|
// Validate By Gap Exists ...
|
|
if (result && validateByGapExists)
|
|
{
|
|
//
|
|
ENUM_X_DIRECTION tmpDir;
|
|
bool hasFVG = poiDetector.HasFVG(
|
|
pBar,
|
|
tmpDir,
|
|
_fvg //
|
|
);
|
|
|
|
//
|
|
isBullish =
|
|
isBullish &&
|
|
hasFVG &&
|
|
IsXBullish(tmpDir);
|
|
|
|
//
|
|
isBearish =
|
|
isBearish &&
|
|
hasFVG &&
|
|
IsXBearish(tmpDir);
|
|
|
|
//
|
|
// Summarize Result ...
|
|
result = isBullish || isBearish;
|
|
}
|
|
|
|
//
|
|
// Prepare Direction and Zone ...
|
|
if (result)
|
|
{
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
zone = _resistance;
|
|
zone.dir = Opposit(_resistance.dir);
|
|
dir = zone.dir;
|
|
zone.upper = MathMax(zone.upper, _fvg.upper);
|
|
zone.lower = MathMin(zone.lower, _fvg.lower);
|
|
}
|
|
|
|
//
|
|
if (isBearish)
|
|
{
|
|
//
|
|
zone = _support;
|
|
zone.dir = Opposit(_support.dir);
|
|
dir = zone.dir;
|
|
zone.upper = MathMax(zone.upper, _fvg.upper);
|
|
zone.lower = MathMin(zone.lower, _fvg.lower);
|
|
}
|
|
|
|
//
|
|
// Zone Validation Base ...
|
|
result = zone.IsValid();
|
|
if (result)
|
|
{
|
|
//
|
|
// Validate By Trend of Zone ...
|
|
XTrend zoneTrend;
|
|
XTrend zoneToTrend;
|
|
|
|
//
|
|
// Detecting Trends ...
|
|
result = poiDetector.HasBoundaryTrend(zone, zoneTrend, false);
|
|
result = result &&
|
|
poiDetector.HasBoundaryTrend(zone, zoneToTrend, true);
|
|
|
|
//
|
|
// Validate Trend ...
|
|
result =
|
|
result &&
|
|
zone.dir == zoneTrend.dir &&
|
|
zone.dir == zoneToTrend.dir;
|
|
|
|
//
|
|
// Draw ...
|
|
if (result)
|
|
{
|
|
//
|
|
XPOIDrawConfig iConfig = structureDrawConfig.drawConfig;
|
|
iConfig.trendRayLeft = false;
|
|
iConfig.trendRayRight = false;
|
|
|
|
//
|
|
poiDrawer.DrawTrendLine(zoneTrend, iConfig);
|
|
poiDrawer.DrawTrendLine(zoneToTrend, iConfig);
|
|
|
|
//
|
|
iConfig.Clean();
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
zoneTrend.Clean();
|
|
zoneToTrend.Clean();
|
|
|
|
//
|
|
// Reset Flags ...
|
|
if (!result)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
isBullish = false;
|
|
isBearish = false;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = zone.IsValid();
|
|
}
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
if (_support.IsValid())
|
|
{
|
|
poiDrawer.DrawZone(_support, structureDrawConfig.drawConfig);
|
|
}
|
|
|
|
//
|
|
if (_resistance.IsValid())
|
|
{
|
|
poiDrawer.DrawZone(_resistance, structureDrawConfig.drawConfig);
|
|
}
|
|
|
|
//
|
|
if (pBarPatterns.IsValid())
|
|
{
|
|
poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
if (!result)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
}
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
pBarPatterns.Clean();
|
|
p2BarPatterns.Clean();
|
|
patternConfig.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Bar Has Signal Based on Strategy 4 ...
|
|
*
|
|
* Strategy 4:
|
|
* ===========
|
|
* - Works Based on Order Flow ...
|
|
* - Looking for new and Fresh Order Flow ...
|
|
* - Validate Bar is Inside Order Flow ...
|
|
* - Validate Bar has Proper Pattern ...
|
|
* - Validate Bar Based on ATR Band in two Step:
|
|
* - Step 1: Bars is Inside ATR Band (Middle) ...
|
|
* - Step 2: Trigger Bars Close Price based on ATR Band ...
|
|
* - Validate Order Flow based on Market Structure Zone ...
|
|
* - Validate Trigger Bar based on InDirectional Market Structure Zones ...
|
|
*
|
|
* Manipulations:
|
|
* ================
|
|
* there are Some Flags properties to Change Validations in Strategy ...
|
|
* we can use them for Testing Purposes ...
|
|
*
|
|
* @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 ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Strategy4HasSignal(
|
|
XOHCL &bar,
|
|
XBoxZone &zone,
|
|
XTarget &targets[],
|
|
ENUM_X_DIRECTION &dir //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Validation Flags ...
|
|
bool validateBarInsideZone = true;
|
|
bool validateByBarPatterns = true;
|
|
bool validateByXFIMABoundary = true;
|
|
bool validateByBarInsideATRBand = true;
|
|
bool validateByBarBasedOnATRBand = true;
|
|
bool validateByXFIMABoundaryTrend = true;
|
|
bool validateMarketStructureHasDirectionalZone = true;
|
|
bool validateMarketStructureDirectionalZoneInsideOrderFlow = true;
|
|
bool validateMarketStructureHasNotInDirectionalZoneOrUnReachedTP = true;
|
|
|
|
//
|
|
// Define Requirements ...
|
|
|
|
//
|
|
XOHCL pBar;
|
|
XOHCL p2Bar;
|
|
XOHCL p3Bar;
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
// Read PBar ...
|
|
result = bar.GetPreviousBar(pBar);
|
|
result = result &&
|
|
pBar.GetPreviousBar(p2Bar);
|
|
result = result &&
|
|
p2Bar.GetPreviousBar(p3Bar);
|
|
if (!result)
|
|
{
|
|
//
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
// Retrieve pBar Patterns ...
|
|
XPatternAnalysis pBarPatterns;
|
|
XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig;
|
|
|
|
//
|
|
poiDetector.AnalyseBarPatterns(
|
|
pBar,
|
|
pBarPatterns,
|
|
patternConfig //
|
|
);
|
|
|
|
//
|
|
// Detecting OrderFlow ...
|
|
XBoxZone oFlow[];
|
|
bool hasOrderFlow = poiDetector.HasOrderFlow(
|
|
p3Bar,
|
|
dir,
|
|
oFlow,
|
|
structureConfig.orderFlowValidation,
|
|
structureConfig.orderFlowUseOB,
|
|
structureConfig.orderFlowUseFVG,
|
|
structureConfig.orderFlowUseSupportAndResistance,
|
|
patternConfig.supportAndResistanceLoopbackLength,
|
|
patternConfig.supportAndResistanceValidationLength,
|
|
structureConfig.loopback //
|
|
);
|
|
|
|
//
|
|
XTrend boundaryTrend;
|
|
XTrend boundaryZoneTrend;
|
|
|
|
//
|
|
double atrBandUpper = EMPTY_VALUE;
|
|
double atrBandLower = EMPTY_VALUE;
|
|
double atrBandMiddle = EMPTY_VALUE;
|
|
|
|
//
|
|
isBullish = hasOrderFlow &&
|
|
IsXBullish(dir);
|
|
|
|
//
|
|
isBearish = hasOrderFlow &&
|
|
IsXBearish(dir);
|
|
|
|
//
|
|
// Summarize Result ...
|
|
result = isBullish || isBearish;
|
|
|
|
//
|
|
// Force Price of p2Bar is Inside Order Flow ...
|
|
if (result && validateBarInsideZone)
|
|
{
|
|
//
|
|
double orderFlowUpper = 0;
|
|
double orderFlowLower = 0;
|
|
|
|
//
|
|
int idx = -1;
|
|
idx = GetHighest(oFlow);
|
|
if (IsValidIndex(idx))
|
|
{
|
|
orderFlowUpper = oFlow[idx].upper;
|
|
}
|
|
idx = GetLowest(oFlow);
|
|
if (IsValidIndex(idx))
|
|
{
|
|
orderFlowLower = oFlow[idx].lower;
|
|
}
|
|
|
|
//
|
|
result = NotEmptyZero(orderFlowUpper) &&
|
|
NotEmptyZero(orderFlowLower) &&
|
|
orderFlowUpper > orderFlowLower &&
|
|
(isBullish
|
|
? p2Bar.low < orderFlowUpper
|
|
: p2Bar.high > orderFlowLower);
|
|
|
|
//
|
|
// Reset Flags ...
|
|
if (!result)
|
|
{
|
|
//
|
|
isBullish = false;
|
|
isBearish = false;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Force PBar Has Pattern ...
|
|
if (result && validateByBarPatterns)
|
|
{
|
|
//
|
|
// Analyse Bar Patterns ...
|
|
result = pBarPatterns.IsValid();
|
|
|
|
//
|
|
// Bullish ...
|
|
bool isPBarHasBullishPatterns =
|
|
result &&
|
|
// (bar.close > pBar.low ||
|
|
// bar.open > pBar.low) &&
|
|
(
|
|
//
|
|
pBarPatterns.IsPinned(X_DIRECTION_BULLISH) ||
|
|
pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) ||
|
|
pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) ||
|
|
pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) ||
|
|
pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH)
|
|
//
|
|
);
|
|
|
|
//
|
|
// Bearish ...
|
|
bool isPBarHasBearishPatterns =
|
|
result &&
|
|
// (bar.close < pBar.high ||
|
|
// bar.open < pBar.high) &&
|
|
(
|
|
//
|
|
pBarPatterns.IsPinned(X_DIRECTION_BEARISH) ||
|
|
pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) ||
|
|
pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) ||
|
|
pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) ||
|
|
pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH)
|
|
//
|
|
);
|
|
|
|
//
|
|
isBullish =
|
|
isBullish &&
|
|
isPBarHasBullishPatterns &&
|
|
!isPBarHasBearishPatterns;
|
|
|
|
//
|
|
isBearish =
|
|
isBearish &&
|
|
isPBarHasBearishPatterns &&
|
|
!isPBarHasBullishPatterns;
|
|
|
|
//
|
|
// Summarize Result ...
|
|
result = isBullish || isBearish;
|
|
|
|
//
|
|
// Reset Flags ...
|
|
if (!result)
|
|
{
|
|
//
|
|
isBullish = false;
|
|
isBearish = false;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Force P2Bar Place Checking based on ATR Band ...
|
|
if (result && validateByBarInsideATRBand)
|
|
{
|
|
//
|
|
atrBandUpper = fimaHelper.GetATRBandUpper(p2Bar.Index());
|
|
atrBandLower = fimaHelper.GetATRBandLower(p2Bar.Index());
|
|
|
|
//
|
|
atrBandMiddle = atrBandLower + ((atrBandUpper - atrBandLower) / 2);
|
|
|
|
//
|
|
isBullish =
|
|
isBullish &&
|
|
NotEmptyZero(atrBandMiddle) &&
|
|
p2Bar.low < atrBandMiddle;
|
|
|
|
//
|
|
isBearish =
|
|
isBearish &&
|
|
NotEmptyZero(atrBandMiddle) &&
|
|
p2Bar.high > atrBandMiddle;
|
|
|
|
//
|
|
// Summarize Result ...
|
|
result = isBullish || isBearish;
|
|
|
|
//
|
|
// Reset Flags ...
|
|
if (!result)
|
|
{
|
|
//
|
|
isBullish = false;
|
|
isBearish = false;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Force PBar Place Checking based on ATR Band ...
|
|
if (result && validateByBarBasedOnATRBand)
|
|
{
|
|
//
|
|
atrBandUpper = fimaHelper.GetATRBandUpper(pBar.Index());
|
|
atrBandLower = fimaHelper.GetATRBandLower(pBar.Index());
|
|
|
|
//
|
|
result =
|
|
NotEmptyZero(atrBandUpper) &&
|
|
NotEmptyZero(atrBandLower) &&
|
|
(isBullish
|
|
? pBar.close > atrBandLower
|
|
: pBar.close < atrBandUpper);
|
|
|
|
//
|
|
// Reset Flags ...
|
|
if (!result)
|
|
{
|
|
//
|
|
isBullish = false;
|
|
isBearish = false;
|
|
}
|
|
}
|
|
|
|
//
|
|
// for Bullish has Support ...
|
|
// for Bearish has Resistance ...
|
|
if (result && validateMarketStructureHasDirectionalZone)
|
|
{
|
|
//
|
|
XOHCL tmpBar;
|
|
XPivot tmpPivot;
|
|
XBoxZone _support;
|
|
XBoxZone _resistance;
|
|
|
|
//
|
|
// Check Market Strucutre Has Support / Resistance ...
|
|
bool hasSupport = pBarPatterns.IsSupport();
|
|
bool hasResistance = pBarPatterns.IsResistance();
|
|
|
|
//
|
|
// Retrieve Support / Resistance Zone ...
|
|
if (hasSupport)
|
|
{
|
|
pBarPatterns.GetSupport(tmpBar, tmpPivot, _support);
|
|
}
|
|
if (hasResistance)
|
|
{
|
|
pBarPatterns.GetResistance(tmpBar, tmpPivot, _resistance);
|
|
}
|
|
|
|
//
|
|
// Validate Support and Resistance by Order Flow ...
|
|
|
|
//
|
|
// Converts Order Flow to Zone ...
|
|
XBoxZone ofZone;
|
|
bool hasOFBox = ToBox(ofZone, oFlow);
|
|
|
|
//
|
|
// Check Market Strucutre Support and Resistance Validation ...
|
|
if (validateMarketStructureDirectionalZoneInsideOrderFlow)
|
|
{
|
|
//
|
|
hasSupport =
|
|
hasOFBox &&
|
|
hasSupport &&
|
|
ofZone.lower < _support.lower &&
|
|
ofZone.upper > _support.upper;
|
|
|
|
//
|
|
hasResistance =
|
|
hasOFBox &&
|
|
hasResistance &&
|
|
ofZone.lower < _resistance.lower &&
|
|
ofZone.upper > _resistance.upper;
|
|
}
|
|
|
|
//
|
|
// Validate Directional Support or Resistance Exists ...
|
|
|
|
//
|
|
isBullish =
|
|
isBullish &&
|
|
hasSupport;
|
|
|
|
//
|
|
isBearish =
|
|
isBearish &&
|
|
hasResistance;
|
|
|
|
//
|
|
// Cleanup ...
|
|
ofZone.Clean();
|
|
tmpBar.Clean();
|
|
_support.Clean();
|
|
tmpPivot.Clean();
|
|
_resistance.Clean();
|
|
|
|
//
|
|
// Summarize Result ...
|
|
result = isBullish || isBearish;
|
|
}
|
|
|
|
//
|
|
// Validate Makret Structure Has Not Indirectional Zone ...
|
|
if (result && validateMarketStructureHasNotInDirectionalZoneOrUnReachedTP)
|
|
{
|
|
//
|
|
XOHCL tmpBar;
|
|
XPivot tmpPivot;
|
|
XBoxZone _support;
|
|
XBoxZone _resistance;
|
|
|
|
//
|
|
// Check Market Strucutre Has Support / Resistance ...
|
|
bool hasSupport = pBarPatterns.IsSupport();
|
|
bool hasResistance = pBarPatterns.IsResistance();
|
|
|
|
//
|
|
// Retrieve Support / Resistance Zone ...
|
|
if (hasSupport)
|
|
{
|
|
pBarPatterns.GetSupport(tmpBar, tmpPivot, _support);
|
|
}
|
|
if (hasResistance)
|
|
{
|
|
pBarPatterns.GetResistance(tmpBar, tmpPivot, _resistance);
|
|
}
|
|
|
|
//
|
|
// Converts Order Flow to Zone ...
|
|
XBoxZone ofZone;
|
|
bool hasOFBox = ToBox(ofZone, oFlow);
|
|
|
|
//
|
|
bool hasIndirectionalZone =
|
|
(isBullish && hasResistance) ||
|
|
(isBearish && hasSupport);
|
|
if (hasIndirectionalZone)
|
|
{
|
|
//
|
|
// Here we Have to Validate Zone Place ...
|
|
|
|
//
|
|
double point = GetPoints(bar.symbol);
|
|
double entry = GetEntry(bar.symbol, dir);
|
|
double slAddition = slAdditionDistance > 0 ? slAdditionDistance : 0;
|
|
double risk = MathAbs(entry - (isBullish ? oFlow[0].lower : oFlow[0].upper)) + (slAddition * point);
|
|
double reward = (defaultSignalR2R * risk);
|
|
double tp = isBullish
|
|
? entry + reward
|
|
: entry - reward;
|
|
|
|
//
|
|
// Bullish ...
|
|
if (isBullish && hasResistance)
|
|
{
|
|
hasResistance = _resistance.lower <= tp;
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
if (isBearish && hasSupport)
|
|
{
|
|
hasSupport = _support.upper >= tp;
|
|
}
|
|
}
|
|
|
|
//
|
|
isBullish =
|
|
isBullish &&
|
|
!hasResistance;
|
|
|
|
//
|
|
isBearish =
|
|
isBearish &&
|
|
!hasSupport;
|
|
|
|
//
|
|
// Cleanup ...
|
|
ofZone.Clean();
|
|
tmpBar.Clean();
|
|
_support.Clean();
|
|
tmpPivot.Clean();
|
|
_resistance.Clean();
|
|
|
|
//
|
|
// Summarize Result ...
|
|
result = isBullish || isBearish;
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
result = isBullish || isBearish;
|
|
if (result)
|
|
{
|
|
//
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = HasDirection(dir);
|
|
}
|
|
|
|
//
|
|
// Prepare Zone and do Zone Based Validations ...
|
|
if (result)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
result = ToBox(
|
|
p2Bar,
|
|
zone,
|
|
dir,
|
|
X_BAR_PATTERN_PINNED //
|
|
);
|
|
|
|
//
|
|
// Refine Zone ...
|
|
zone.to = bar.time;
|
|
zone.upper = MathMax(zone.upper, atrBandMiddle);
|
|
zone.lower = MathMin(zone.lower, atrBandMiddle);
|
|
|
|
//
|
|
// Validate by XFIMA Boundary ...
|
|
if (result && validateByXFIMABoundary)
|
|
{
|
|
//
|
|
// Try to Retrieve Boundary To Trend ...
|
|
result = poiDetector.HasBoundaryTrend(
|
|
zone,
|
|
boundaryTrend,
|
|
true //
|
|
);
|
|
|
|
//
|
|
// Try to Retrieve Boundary Zone Trend ...
|
|
result =
|
|
result &&
|
|
poiDetector.HasBoundaryTrend(
|
|
zone,
|
|
boundaryZoneTrend,
|
|
false //
|
|
);
|
|
|
|
//
|
|
// Check and Validate Trend Direction ...
|
|
result =
|
|
result &&
|
|
zone.dir == boundaryTrend.dir &&
|
|
zone.dir == boundaryZoneTrend.dir;
|
|
|
|
//
|
|
// Reset Flags ...
|
|
if (!result)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
result = false;
|
|
isBullish = false;
|
|
isBearish = false;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Manage Stops ...
|
|
if (result)
|
|
{
|
|
//
|
|
// Since Stop Management Changes Zones Edge(s) ...
|
|
// we do it here for Refining Zone ...
|
|
}
|
|
|
|
//
|
|
result = zone.IsValid();
|
|
}
|
|
|
|
//
|
|
// Prepare Targets ...
|
|
if (result)
|
|
{
|
|
//
|
|
XTarget iTarget;
|
|
|
|
//
|
|
// Calculate Requirements ...
|
|
double point = GetPoints(bar.symbol);
|
|
double entry = GetEntry(bar.symbol, dir);
|
|
double slAddition = slAdditionDistance > 0 ? slAdditionDistance : 0;
|
|
double risk = MathAbs(entry - (isBullish ? zone.lower : zone.upper)) + (slAddition * point);
|
|
double reward = (defaultSignalR2R * risk);
|
|
double tp = isBullish
|
|
? entry + reward
|
|
: entry - reward;
|
|
|
|
//
|
|
// High Risk Target is Used to Protect In Profit Positiions
|
|
// from Reversal Patterns ...
|
|
double highRiskR2r = (defaultSignalR2R / 5) * 4;
|
|
double highRiskReward = highRiskR2r * risk;
|
|
double highRiskTP = isBullish
|
|
? entry + highRiskReward
|
|
: entry - highRiskReward;
|
|
iTarget.Clean();
|
|
iTarget.actingDistance = 5;
|
|
iTarget.doRFOnEntry = true;
|
|
iTarget.target = highRiskTP;
|
|
iTarget.volumeMultiplier = 0.8;
|
|
// AddRef(iTarget, targets);
|
|
|
|
//
|
|
// Cleanup ...
|
|
iTarget.Clean();
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
if (!result)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
}
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
p3Bar.Clean();
|
|
XClean(oFlow);
|
|
pBarPatterns.Clean();
|
|
boundaryTrend.Clean();
|
|
patternConfig.Clean();
|
|
boundaryZoneTrend.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
// |