1834 lines
46 KiB
Plaintext
1834 lines
46 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 ...
|
|
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;
|
|
}
|
|
|
|
//
|
|
// 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);
|
|
|
|
//
|
|
int positionsCount = ArraySize(positions);
|
|
if (!IsValidSize(positionsCount))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Requirements ...
|
|
XGuard iGuard;
|
|
bool has = false;
|
|
|
|
//
|
|
// Force Hedging ...
|
|
// bool forceHedging = (positionsCount >= 2);
|
|
// if (forceHedging)
|
|
// {
|
|
// //
|
|
// // Minimum Required Reward ...
|
|
// double minRequiredReward = 1.5;
|
|
|
|
// //
|
|
// // Summarizing Risk and Reward of Collections ...
|
|
// // double risk = 0;
|
|
// // double volume = 0;
|
|
// // double reward = 0;
|
|
// // for (int i = 0; i < positionsCount; i++)
|
|
// // {
|
|
// // //
|
|
// // risk += positions[i].GetRisk() + positions[i].commission + (-1 * positions[i].swap);
|
|
// // reward += positions[i].profit;
|
|
// // volume += positions[i].volume;
|
|
// // }
|
|
|
|
// // //
|
|
// // risk *= volume;
|
|
// // reward *= volume;
|
|
|
|
// // //
|
|
// // // Calculating Can Hedge rops ...
|
|
// // has = reward >= (risk * minRequiredReward);
|
|
// // if (has)
|
|
// // {
|
|
// // //
|
|
// // iGuard.Clean();
|
|
// // iGuard.force = true;
|
|
// // iGuard.symbol = symbol;
|
|
// // iGuard.period = period;
|
|
// // iGuard.provider = name;
|
|
// // iGuard.time = TimeCurrent();
|
|
// // iGuard.action = X_GUARD_ACTION_HEDGE;
|
|
|
|
// // //
|
|
// // // Validate Guard ...
|
|
// // has = iGuard.IsValid();
|
|
// // if (has)
|
|
// // {
|
|
// // //
|
|
// // AddRef(
|
|
// // iGuard,
|
|
// // guards //
|
|
// // );
|
|
// // }
|
|
// // }
|
|
// }
|
|
|
|
//
|
|
result = ArraySize(guards);
|
|
|
|
//
|
|
// Cleanup ...
|
|
iGuard.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Private ...
|
|
private:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
// 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 = false;
|
|
bool useSignaller3 = false;
|
|
bool useSignaller4 = true;
|
|
|
|
//
|
|
// Validator Flags ...
|
|
string provider = NULL;
|
|
bool validateByOrderFlow = false;
|
|
|
|
//
|
|
// Target Flags ...
|
|
bool hasPartialCloseOnTp1 = true;
|
|
|
|
//
|
|
// Draw Flags ...
|
|
bool draw = true;
|
|
bool drawZone = true;
|
|
bool drawMarketStructurePivots = true;
|
|
bool drawMarketStructureAnalysis = true;
|
|
bool drawMarketStructureOrderFlow = true;
|
|
XPOIDrawConfig iDrawConfig;
|
|
|
|
//
|
|
// 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.doRFOnEntry = true;
|
|
iTarget.actingDistance = 5;
|
|
iTarget.volumeMultiplier = 0.8;
|
|
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
// Debug Breake ...
|
|
if (result)
|
|
{
|
|
DebugBreak();
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
iDrawConfig.Clean();
|
|
marketStructure.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 ...
|
|
*
|
|
* @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 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 ...
|
|
*
|
|
* @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;
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
// XFIMA Consolidation ...
|
|
|
|
//
|
|
bool isConsolidation = poiDetector.DetectPVConsolidationZone(
|
|
zone,
|
|
pBar.Index(),
|
|
true, // Force PV Break ...
|
|
true // Force Has Sar Switch ...
|
|
);
|
|
|
|
//
|
|
isBullish =
|
|
isConsolidation &&
|
|
zone.IsBullish();
|
|
|
|
//
|
|
isBearish =
|
|
isConsolidation &&
|
|
zone.IsBearish();
|
|
|
|
//
|
|
// Validate based on Bars Patterns ...
|
|
bool validateByBarPatterns = true;
|
|
if (validateByBarPatterns)
|
|
{
|
|
//
|
|
// Reading pBar Patterns ...
|
|
XPatternAnalysis pBarAnalysis;
|
|
poiDetector.AnalyseBarPatterns(
|
|
pBar,
|
|
pBarAnalysis,
|
|
structureConfig.barsAnalysisConfig //
|
|
);
|
|
|
|
//
|
|
// Bullish ...
|
|
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)
|
|
//
|
|
);
|
|
|
|
//
|
|
// Bearish ...
|
|
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)
|
|
//
|
|
);
|
|
|
|
//
|
|
isBullish =
|
|
isBullish &&
|
|
isPBarHasBullishPatterns &&
|
|
!isPBarHasBearishPatterns;
|
|
|
|
//
|
|
isBearish =
|
|
isBearish &&
|
|
isPBarHasBearishPatterns &&
|
|
!isPBarHasBullishPatterns;
|
|
|
|
//
|
|
// Summarize Result ...
|
|
result = isBullish ||
|
|
isBearish;
|
|
}
|
|
|
|
//
|
|
// Checking PullBack ...
|
|
bool validateByPullback = false;
|
|
if (validateByPullback)
|
|
{
|
|
//
|
|
XBoxZone pullback;
|
|
ENUM_X_DIRECTION pullbackDir;
|
|
bool isPullBack = result &&
|
|
poiDetector.IsPullbackPattern(
|
|
pBar,
|
|
pullback,
|
|
pullbackDir,
|
|
2,
|
|
false // Force Break ...
|
|
);
|
|
bool isPullbackBullish = isPullBack &&
|
|
IsXBullish(pullbackDir);
|
|
bool isPullbackBearish = isPullBack &&
|
|
IsXBearish(pullbackDir);
|
|
|
|
//
|
|
isBullish =
|
|
isBullish &&
|
|
isPullbackBullish;
|
|
|
|
//
|
|
isBearish =
|
|
isBearish &&
|
|
isPullbackBearish;
|
|
|
|
//
|
|
// Summarize Result ...
|
|
result = isBullish ||
|
|
isBearish;
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
result = isBullish ||
|
|
isBearish;
|
|
|
|
//
|
|
// Prepare Zone ...
|
|
if (result)
|
|
{
|
|
}
|
|
|
|
//
|
|
// 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 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 ...
|
|
*
|
|
* @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;
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
// Do ...
|
|
|
|
//
|
|
// Detecting OrderFlow ...
|
|
XBoxZone orderFlow[];
|
|
bool hasOrderFlow = poiDetector.HasOrderFlow(
|
|
pBar,
|
|
dir,
|
|
orderFlow,
|
|
structureConfig.orderFlowValidation,
|
|
structureConfig.orderFlowUseOB,
|
|
structureConfig.orderFlowUseFVG,
|
|
structureConfig.orderFlowUseSupportAndResistance,
|
|
structureConfig.barsAnalysisConfig.supportAndResistanceLoopbackLength,
|
|
structureConfig.barsAnalysisConfig.supportAndResistanceValidationLength,
|
|
structureConfig.loopback //
|
|
);
|
|
|
|
//
|
|
isBullish = hasOrderFlow &&
|
|
IsXBullish(dir);
|
|
|
|
//
|
|
isBearish = hasOrderFlow &&
|
|
IsXBearish(dir);
|
|
|
|
//
|
|
result = isBullish ||
|
|
isBearish;
|
|
if (result) {
|
|
//
|
|
poiDrawer.DrawZones(orderFlow, structureDrawConfig.drawConfig);
|
|
Print("OrderFlow ...");
|
|
}
|
|
|
|
//
|
|
isBullish =
|
|
//
|
|
false
|
|
//
|
|
;
|
|
|
|
//
|
|
isBearish =
|
|
//
|
|
false
|
|
//
|
|
;
|
|
|
|
//
|
|
// 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)
|
|
{
|
|
}
|
|
|
|
//
|
|
result = zone.IsValid();
|
|
}
|
|
|
|
//
|
|
// Prepare Targets ...
|
|
if (result)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
if (!result)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
}
|
|
pBar.Clean();
|
|
p2Bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
// |