ass support for PV and KISuperSlow and MASuper Slow in KI Indicator and also Helper and implement them in BackTester ...
1720 lines
38 KiB
Plaintext
1720 lines
38 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Class
|
|
// -------------------------------------------------
|
|
// Name: XCX121XKISignaller ...
|
|
// Description: X121XKI 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 X121XKI Signaller Class"
|
|
#property strict
|
|
|
|
//
|
|
// Imports ...
|
|
#include "../../Classes/x-saherelm.x-signaller.class.mq5"
|
|
#include "../../Helpers/x-saherelm.x121.xki.helper.mq5"
|
|
#include "../Classes/x-saherelm.x121.xki.parser.class.mq5"
|
|
#include "../Classes/x-saherelm.x121.xki.x-poi.detector.class.mq5"
|
|
#include "../Classes/x-saherelm.x121.xki.x-poi.drawer.class.mq5"
|
|
#include "../Libraries/x-saherelm.x121.xki.lib.mq5"
|
|
|
|
//
|
|
// Implementation ...
|
|
|
|
//
|
|
// Base X121XKI base Signaller ...
|
|
class XCX121XKIBaseSignaller : public XCBaseSignaller
|
|
{
|
|
//
|
|
// Public ...
|
|
public:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
CArrayObj drawnObjects; // Drawing Objects Holder ...
|
|
X121XKIInputs kiInputs; // X121XKI Inputs ...
|
|
XCX121XKIHelper *kiHelper; // X121XKI Indicator Helper ...
|
|
XCX121XKIPOIDrawer *poiDrawer; // X121XKI POI Drawer ...
|
|
XCX121XKIPOIDetector *poiDetector; // X121XKI POI Detector ...
|
|
XCX121XKIHelperParser *kiParser; // X121XKI Helper Parser ...
|
|
|
|
//
|
|
// Constructor ...
|
|
XCX121XKIBaseSignaller(
|
|
string _name, // Name ...
|
|
string _symbol, // Symbol ...
|
|
ENUM_TIMEFRAMES _period, // Period ...
|
|
X121XKIInputs &_kiInputs, // X121XKIInputs ...
|
|
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 X121XKI Indicator Helper Class ...
|
|
if (_kiInputs.IsValid())
|
|
{
|
|
//
|
|
kiHelper = new XCX121XKIHelper();
|
|
bool isInited = kiHelper.Init(
|
|
_symbol,
|
|
_period,
|
|
_kiInputs //
|
|
);
|
|
if (isInited)
|
|
{
|
|
kiInputs = _kiInputs;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
delete kiHelper;
|
|
ZeroMemory(kiHelper);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Instantiate X121XKI Helper Parser ...
|
|
kiParser = new XCX121XKIHelperParser(kiHelper);
|
|
|
|
//
|
|
poiDrawer = new XCX121XKIPOIDrawer();
|
|
poiDetector = new XCX121XKIPOIDetector(kiHelper, kiParser);
|
|
}
|
|
|
|
//
|
|
// Deconstructor ...
|
|
~XCX121XKIBaseSignaller()
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
//
|
|
// Overrides ...
|
|
|
|
//
|
|
// Actions ...
|
|
|
|
/**
|
|
* Destroy ...
|
|
*/
|
|
void Destroy()
|
|
{
|
|
//
|
|
BeforeDestroy();
|
|
|
|
//
|
|
kiInputs.Clean();
|
|
|
|
//
|
|
delete poiDrawer;
|
|
ZeroMemory(poiDrawer);
|
|
|
|
//
|
|
delete poiDetector;
|
|
ZeroMemory(poiDetector);
|
|
|
|
//
|
|
delete kiHelper;
|
|
ZeroMemory(kiHelper);
|
|
}
|
|
|
|
//
|
|
// 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 = kiInputs.IsValid() &&
|
|
kiHelper != 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:
|
|
//
|
|
};
|
|
|
|
//
|
|
// X121XKI Strategy 1 Signaller Class ...
|
|
class XCX121XKIStrategy1Signaller : public XCX121XKIBaseSignaller
|
|
{
|
|
//
|
|
// Public ...
|
|
public:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
// Constructor ...
|
|
XCX121XKIStrategy1Signaller(
|
|
string _symbol, // Symbol ...
|
|
ENUM_TIMEFRAMES _period, // Period ...
|
|
X121XKIInputs &_kiInputs, // X121XKIInputs ...
|
|
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 ...
|
|
) : XCX121XKIBaseSignaller("X121XKI1",
|
|
_symbol,
|
|
_period,
|
|
_kiInputs,
|
|
_processAllTicks,
|
|
_defaultSignalR2R,
|
|
_defaultSignalRiskInPoint,
|
|
_defaultSignalVolume //
|
|
)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Deconstructor ...
|
|
~XCX121XKIStrategy1Signaller()
|
|
{
|
|
//
|
|
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 ....
|
|
);
|
|
if (has)
|
|
{
|
|
iSignal.provider += "_" + iZone.type;
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
string provider = NULL;
|
|
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();
|
|
|
|
//
|
|
// Check Provided By Strategy 1 ...
|
|
provider = positions[i].provider;
|
|
StringReplace(
|
|
provider,
|
|
name,
|
|
"" //
|
|
);
|
|
has = Contains(ToXString(X121_XKI_STRATEGY_1), positions[i].provider);
|
|
if (has)
|
|
{
|
|
//
|
|
// Now we Check Exit ...
|
|
// if (positions[i].IsLong())
|
|
// {
|
|
// has = ExitBullishPOILong();
|
|
// }
|
|
// else if (positions[i].IsShort())
|
|
// {
|
|
// has = ExitBearishPOIShort();
|
|
// }
|
|
|
|
// //
|
|
// if (has)
|
|
// {
|
|
// }
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(guards);
|
|
|
|
//
|
|
// Cleanup ...
|
|
iGuard.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Protected ...
|
|
protected:
|
|
//
|
|
|
|
//
|
|
// 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 = true;
|
|
bool useSignaller2 = false;
|
|
bool useSignaller3 = false;
|
|
bool useSignaller4 = false;
|
|
bool useSignaller5 = false;
|
|
bool useSignaller6 = false;
|
|
|
|
//
|
|
XBoxZone tmpZone;
|
|
string provider = NULL;
|
|
ENUM_X_DIRECTION tmpDir;
|
|
|
|
//
|
|
bool signaller1HasSignal = false;
|
|
bool signaller2HasSignal = false;
|
|
bool signaller3HasSignal = false;
|
|
bool signaller4HasSignal = false;
|
|
bool signaller5HasSignal = false;
|
|
bool signaller6HasSignal = false;
|
|
|
|
//
|
|
// Validator Flags ...
|
|
bool validateByOrderFlow = false;
|
|
|
|
//
|
|
// Target Flags ...
|
|
bool hasPartialCloseOnTp1 = false;
|
|
|
|
//
|
|
bool doRFOnEntryOnTP1 = false;
|
|
|
|
//
|
|
// Draw Flags ...
|
|
bool draw = true;
|
|
|
|
//
|
|
// Signal Checking ...
|
|
|
|
//
|
|
// Signal Detection Flags ...
|
|
|
|
//
|
|
// Signaller 1 ...
|
|
// POI ...
|
|
if (useSignaller1)
|
|
{
|
|
//
|
|
signaller1HasSignal = Strategy1HasSignal(
|
|
bar,
|
|
tmpZone,
|
|
targets,
|
|
tmpDir //
|
|
);
|
|
|
|
//
|
|
if (signaller1HasSignal)
|
|
{
|
|
//
|
|
provider += ToXString(X121_XKI_STRATEGY_1);
|
|
|
|
//
|
|
if (!zone.IsValid())
|
|
{
|
|
//
|
|
dir = tmpDir;
|
|
zone = tmpZone;
|
|
}
|
|
}
|
|
|
|
//
|
|
tmpZone.Clean();
|
|
tmpDir = X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
// Signaller 2 ...
|
|
// Breakout POI ...
|
|
if (useSignaller2)
|
|
{
|
|
//
|
|
signaller2HasSignal = Strategy2HasSignal(
|
|
bar,
|
|
tmpZone,
|
|
targets,
|
|
tmpDir //
|
|
);
|
|
|
|
//
|
|
if (signaller2HasSignal)
|
|
{
|
|
//
|
|
provider += ToXString(X121_XKI_STRATEGY_2);
|
|
|
|
//
|
|
if (!zone.IsValid())
|
|
{
|
|
//
|
|
dir = tmpDir;
|
|
zone = tmpZone;
|
|
}
|
|
}
|
|
|
|
//
|
|
tmpZone.Clean();
|
|
tmpDir = X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
// Signaller 3 ...
|
|
// Reversal ...
|
|
if (useSignaller3)
|
|
{
|
|
//
|
|
signaller3HasSignal = Strategy3HasSignal(
|
|
bar,
|
|
tmpZone,
|
|
targets,
|
|
tmpDir //
|
|
);
|
|
|
|
//
|
|
if (signaller3HasSignal)
|
|
{
|
|
//
|
|
provider += ToXString(X121_XKI_STRATEGY_3);
|
|
|
|
//
|
|
if (!zone.IsValid())
|
|
{
|
|
//
|
|
dir = tmpDir;
|
|
zone = tmpZone;
|
|
}
|
|
}
|
|
|
|
//
|
|
tmpZone.Clean();
|
|
tmpDir = X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
// Signaller 4 ...
|
|
// Continuation ...
|
|
if (useSignaller4)
|
|
{
|
|
//
|
|
signaller4HasSignal = Strategy4HasSignal(
|
|
bar,
|
|
tmpZone,
|
|
targets,
|
|
tmpDir //
|
|
);
|
|
|
|
//
|
|
if (signaller4HasSignal)
|
|
{
|
|
//
|
|
provider += ToXString(X121_XKI_STRATEGY_4);
|
|
|
|
//
|
|
if (!zone.IsValid())
|
|
{
|
|
//
|
|
dir = tmpDir;
|
|
zone = tmpZone;
|
|
}
|
|
}
|
|
|
|
//
|
|
tmpZone.Clean();
|
|
tmpDir = X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
// Signaller 5 ...
|
|
// Exhaustion ...
|
|
if (useSignaller5)
|
|
{
|
|
//
|
|
signaller5HasSignal = Strategy5HasSignal(
|
|
bar,
|
|
tmpZone,
|
|
targets,
|
|
tmpDir //
|
|
);
|
|
|
|
//
|
|
if (signaller5HasSignal)
|
|
{
|
|
//
|
|
provider += ToXString(X121_XKI_STRATEGY_5);
|
|
|
|
//
|
|
if (!zone.IsValid())
|
|
{
|
|
//
|
|
dir = tmpDir;
|
|
zone = tmpZone;
|
|
}
|
|
}
|
|
|
|
//
|
|
tmpZone.Clean();
|
|
tmpDir = X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
// Signaller 6 ...
|
|
// Trend Exhaustion ...
|
|
if (useSignaller6)
|
|
{
|
|
//
|
|
signaller6HasSignal = Strategy6HasSignal(
|
|
bar,
|
|
tmpZone,
|
|
targets,
|
|
tmpDir //
|
|
);
|
|
|
|
//
|
|
if (signaller6HasSignal)
|
|
{
|
|
//
|
|
provider += ToXString(X121_XKI_STRATEGY_6);
|
|
|
|
//
|
|
if (!zone.IsValid())
|
|
{
|
|
//
|
|
dir = tmpDir;
|
|
zone = tmpZone;
|
|
}
|
|
}
|
|
|
|
//
|
|
tmpZone.Clean();
|
|
tmpDir = X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
// Summarize Signallers Result ...
|
|
result = signaller1HasSignal ||
|
|
signaller2HasSignal ||
|
|
signaller3HasSignal ||
|
|
signaller4HasSignal ||
|
|
signaller5HasSignal ||
|
|
signaller6HasSignal;
|
|
|
|
//
|
|
// Signal Validating ...
|
|
|
|
//
|
|
// 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);
|
|
if (result)
|
|
{
|
|
zone.type = "" + provider;
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
iTarget.Clean();
|
|
}
|
|
|
|
//
|
|
// Draws ...
|
|
if (result && draw)
|
|
{
|
|
//
|
|
// Other Drawing Materials ...
|
|
XPOIDrawConfig drawConfig;
|
|
drawConfig.Default();
|
|
|
|
//
|
|
poiDrawer.DrawZone(zone, drawConfig);
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
if (!result)
|
|
{
|
|
//
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
tmpZone.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
// #region Custom Signal Strategies ...
|
|
/**
|
|
* Check Bar Has Signal Based on Strategy 1 ...
|
|
* POI ...
|
|
*
|
|
* @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;
|
|
|
|
//
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int scoreBullish = 0;
|
|
int scoreBearish = 0;
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
int barIndex = bar.Index() + 1;
|
|
|
|
//
|
|
// Initialize Indexed Bar ...
|
|
XOHCL iBar;
|
|
result = iBar.Init(bar.symbol, bar.period, barIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone swingLow;
|
|
XBoxZone swingHigh;
|
|
ENUM_X_DIRECTION patternsDir[];
|
|
ENUM_X_BAR_PATTERN patterns[];
|
|
poiDetector.FillStrategy1Patterns(
|
|
patterns,
|
|
patternsDir //
|
|
);
|
|
|
|
//
|
|
// Reading Swings ...
|
|
poiDetector.DetectRecentSwings(
|
|
swingHigh,
|
|
swingLow,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
// Reading Order Flow ...
|
|
|
|
//
|
|
// Bullish Order Flow ...
|
|
XBoxZone bullishOrderFlow[];
|
|
int bullishOrderFlowRejectdIDX = -1;
|
|
poiDetector.HasOrderFlow(bullishOrderFlow, barIndex, 4, X_DIRECTION_BULLISH, 15);
|
|
|
|
//
|
|
// Bearish Order Flow ...
|
|
XBoxZone bearishOrderFlow[];
|
|
int bearishOrderFlowRejectdIDX = -1;
|
|
poiDetector.HasOrderFlow(bearishOrderFlow, barIndex, 4, X_DIRECTION_BEARISH, 15);
|
|
|
|
//
|
|
// Base Conditions ...
|
|
|
|
//
|
|
isBullish =
|
|
IsTFBullishPattern(barIndex, PERIOD_M1) &&
|
|
IsTFBullishPattern(barIndex, PERIOD_M5) &&
|
|
IsTFBullishPattern(barIndex, iBar.period) &&
|
|
HasRejected(
|
|
bullishOrderFlowRejectdIDX,
|
|
iBar,
|
|
bullishOrderFlow //
|
|
) &&
|
|
poiDetector.HasRecentPatternRejected(
|
|
zone,
|
|
patterns,
|
|
patternsDir,
|
|
barIndex,
|
|
3, // Loopback ..
|
|
iBar.period,
|
|
X_DIRECTION_BULLISH //
|
|
);
|
|
if (!isBullish)
|
|
{
|
|
//
|
|
isBearish =
|
|
IsTFBearishPattern(barIndex, PERIOD_M1) &&
|
|
IsTFBearishPattern(barIndex, PERIOD_M5) &&
|
|
IsTFBearishPattern(barIndex, iBar.period) &&
|
|
HasRejected(
|
|
bearishOrderFlowRejectdIDX,
|
|
iBar,
|
|
bearishOrderFlow //
|
|
) &&
|
|
poiDetector.HasRecentPatternRejected(
|
|
zone,
|
|
patterns,
|
|
patternsDir,
|
|
barIndex,
|
|
3, // Loopback ..
|
|
iBar.period,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Summarize Result ...
|
|
result = isBullish || isBearish;
|
|
|
|
//
|
|
// Count Touches ...
|
|
int bullishTouches = 0;
|
|
int bearishTouches = 0;
|
|
if (result)
|
|
{
|
|
//
|
|
kiParser.CountTouches(
|
|
bullishTouches,
|
|
bearishTouches,
|
|
barIndex,
|
|
4 // Loopback ...
|
|
);
|
|
|
|
//
|
|
isBullish =
|
|
isBullish &&
|
|
bullishTouches >= bearishTouches;
|
|
|
|
//
|
|
isBearish =
|
|
isBearish &&
|
|
bearishTouches >= bullishTouches;
|
|
|
|
//
|
|
// Summarize Result ...
|
|
result = isBullish || isBearish;
|
|
if (!result)
|
|
{
|
|
//
|
|
isBullish = false;
|
|
isBearish = false;
|
|
}
|
|
|
|
//
|
|
if (bullishTouches > 0 || bearishTouches > 0)
|
|
{
|
|
// DebugBreak();
|
|
}
|
|
}
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
//
|
|
iBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do Directional Validation ...
|
|
if (result)
|
|
{
|
|
//
|
|
poiDetector.RefactorStrategy1OperationalZone(zone);
|
|
|
|
//
|
|
// Bullish ...
|
|
if (isBullish)
|
|
{
|
|
// //
|
|
// isBullish =
|
|
// isBullish &&
|
|
// isLowerTFBullish &&
|
|
// isCandlestickBullish;
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
if (isBearish)
|
|
{
|
|
// //
|
|
// isBearish =
|
|
// isBearish &&
|
|
// isLowerTFBearish &&
|
|
// isCandlestickBearish;
|
|
}
|
|
|
|
//
|
|
result = isBullish || isBearish;
|
|
if (!result)
|
|
{
|
|
//
|
|
isBullish = false;
|
|
isBearish = false;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Draws ...
|
|
bool draw = true;
|
|
if (draw && result)
|
|
{
|
|
//
|
|
int drawn = 0;
|
|
|
|
//
|
|
poiDrawer.drawnObjects.Clear();
|
|
|
|
//
|
|
XPOIDrawConfig config;
|
|
config.Default();
|
|
|
|
//
|
|
if (zone.IsValid())
|
|
{
|
|
//
|
|
drawn++;
|
|
|
|
//
|
|
config.zonesWidth = 3;
|
|
config.bullishColor = clrYellow;
|
|
config.bearishColor = clrOrange;
|
|
|
|
//
|
|
poiDrawer.DrawZone(zone, config);
|
|
|
|
//
|
|
config.Default();
|
|
}
|
|
|
|
//
|
|
if (swingLow.IsValid())
|
|
{
|
|
//
|
|
drawn++;
|
|
poiDrawer.DrawZone(swingLow, config);
|
|
}
|
|
|
|
//
|
|
if (swingHigh.IsValid())
|
|
{
|
|
//
|
|
drawn++;
|
|
poiDrawer.DrawZone(swingHigh, config);
|
|
}
|
|
|
|
//
|
|
if (HasChild(bullishOrderFlow))
|
|
{
|
|
//
|
|
drawn += ArraySize(bullishOrderFlow);
|
|
poiDrawer.DrawZones(bullishOrderFlow, config);
|
|
}
|
|
|
|
//
|
|
if (HasChild(bearishOrderFlow))
|
|
{
|
|
//
|
|
drawn += ArraySize(bearishOrderFlow);
|
|
poiDrawer.DrawZones(bearishOrderFlow, config);
|
|
}
|
|
|
|
//
|
|
if (drawn > 0)
|
|
{
|
|
DebugBreak();
|
|
return false;
|
|
}
|
|
|
|
//
|
|
config.Clean();
|
|
}
|
|
|
|
//
|
|
// Check and Prepare Direction ...
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish ? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
result = result &&
|
|
HasDirection(dir);
|
|
if (result)
|
|
{
|
|
//
|
|
// Prepare Zone ...
|
|
double entry = GetEntry(iBar.symbol, dir);
|
|
|
|
//
|
|
double upper = isBullish
|
|
? entry
|
|
: zone.upper;
|
|
double lower = isBullish
|
|
? zone.lower
|
|
: entry;
|
|
datetime to = bar.time;
|
|
datetime from = isBullish
|
|
? zone.from
|
|
: zone.from;
|
|
result = zone.Init(
|
|
iBar.symbol,
|
|
iBar.period,
|
|
upper,
|
|
lower,
|
|
from,
|
|
to,
|
|
dir,
|
|
"XS1" //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
iBar.Clean();
|
|
swingLow.Clean();
|
|
XClean(patterns);
|
|
swingHigh.Clean();
|
|
XClean(patternsDir);
|
|
XClean(bullishOrderFlow);
|
|
XClean(bearishOrderFlow);
|
|
|
|
//
|
|
result =
|
|
result &&
|
|
zone.IsValid() &&
|
|
HasDirection(dir);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Bar Has Signal Based on Strategy 2 ...
|
|
* Breakout POI ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Strategy2HasSignal(
|
|
XOHCL &bar,
|
|
XBoxZone &zone,
|
|
XTarget &targets[],
|
|
ENUM_X_DIRECTION &dir //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int barIndex = bar.Index() + 1;
|
|
|
|
//
|
|
// Retrieve Base Conditions ...
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
// Validate Conditions ...
|
|
result = isBullish || isBearish;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do Validation and Filtering Market Structure if required ...
|
|
|
|
//
|
|
// Check and Prepare Direction ...
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish ? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
result = HasDirection(dir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prepare Zone ...
|
|
|
|
//
|
|
result =
|
|
result &&
|
|
zone.IsValid() &&
|
|
HasDirection(dir);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Bar Has Signal Based on Strategy 3 ...
|
|
* Reversal ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Strategy3HasSignal(
|
|
XOHCL &bar,
|
|
XBoxZone &zone,
|
|
XTarget &targets[],
|
|
ENUM_X_DIRECTION &dir //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int barIndex = bar.Index() + 1;
|
|
|
|
//
|
|
// Retrieve Base Conditions ...
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
// Validate Conditions ...
|
|
result = isBullish || isBearish;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do Validation and Filtering Market Structure if required ...
|
|
|
|
//
|
|
// Check and Prepare Direction ...
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish ? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
result = HasDirection(dir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prepare Zone ...
|
|
|
|
//
|
|
result =
|
|
result &&
|
|
zone.IsValid() &&
|
|
HasDirection(dir);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Bar Has Signal Based on Strategy 4 ...
|
|
* Continuation ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Strategy4HasSignal(
|
|
XOHCL &bar,
|
|
XBoxZone &zone,
|
|
XTarget &targets[],
|
|
ENUM_X_DIRECTION &dir //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int barIndex = bar.Index() + 1;
|
|
|
|
//
|
|
// Retrieve Base Conditions ...
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
// Validate Conditions ...
|
|
result = isBullish || isBearish;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do Validation and Filtering Market Structure if required ...
|
|
|
|
//
|
|
// Check and Prepare Direction ...
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish ? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
result = HasDirection(dir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prepare Zone ...
|
|
|
|
//
|
|
result =
|
|
result &&
|
|
zone.IsValid() &&
|
|
HasDirection(dir);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Bar Has Signal Based on Strategy 5 ...
|
|
* Exhaustion ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Strategy5HasSignal(
|
|
XOHCL &bar,
|
|
XBoxZone &zone,
|
|
XTarget &targets[],
|
|
ENUM_X_DIRECTION &dir //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int barIndex = bar.Index() + 1;
|
|
|
|
//
|
|
// Retrieve Base Conditions ...
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
// Validate Conditions ...
|
|
result = isBullish || isBearish;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do Validation and Filtering Market Structure if required ...
|
|
|
|
//
|
|
// Check and Prepare Direction ...
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish ? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
result = HasDirection(dir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prepare Zone ...
|
|
|
|
//
|
|
result =
|
|
result &&
|
|
zone.IsValid() &&
|
|
HasDirection(dir);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Bar Has Signal Based on Strategy 6 ...
|
|
* Trend Exhaustion ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Strategy6HasSignal(
|
|
XOHCL &bar,
|
|
XBoxZone &zone,
|
|
XTarget &targets[],
|
|
ENUM_X_DIRECTION &dir //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
zone.Clean();
|
|
XClean(targets);
|
|
dir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = bar.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int barIndex = bar.Index() + 1;
|
|
|
|
//
|
|
// Retrieve Base Conditions ...
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
// Validate Conditions ...
|
|
result = isBullish || isBearish;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Do Validation and Filtering Market Structure if required ...
|
|
|
|
//
|
|
// Check and Prepare Direction ...
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish ? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
result = HasDirection(dir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prepare Zone ...
|
|
|
|
//
|
|
result =
|
|
result &&
|
|
zone.IsValid() &&
|
|
HasDirection(dir);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
// #endregion
|
|
|
|
// #region TF Patterns ...
|
|
bool IsTFBullishPattern(
|
|
int barIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
if (!IsXValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
XOHCL bar;
|
|
result = bar.Init(symbol, forPeriod, barIndex) &&
|
|
poiDetector.HasCandlestickDirection(bar, X_DIRECTION_BULLISH);
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsTFBearishPattern(
|
|
int barIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
if (!IsXValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
XOHCL bar;
|
|
result = bar.Init(symbol, forPeriod, barIndex) &&
|
|
poiDetector.HasCandlestickDirection(bar, X_DIRECTION_BEARISH);
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
// #endregion
|
|
|
|
//
|
|
};
|
|
|
|
// |