3804 lines
105 KiB
Plaintext
3804 lines
105 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Class
|
|
// -------------------------------------------------
|
|
// Name: XCXFIMASignaller ...
|
|
// Description: XFIMA Signaller Class ...
|
|
//
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property library
|
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
|
#property link "https://saherelm.ir"
|
|
#property version "1.00"
|
|
#property description "SaherElm XFIMA Signaller Class"
|
|
#property strict
|
|
|
|
//
|
|
// Imports ...
|
|
#include "../../Classes/x-saherelm.x-signaller.class.mq5"
|
|
#include "../../Helpers/x-saherelm.xfima.helper.mq5"
|
|
#include "../Classes/x-saherelm.xfima.x-poi.detector.class.mq5"
|
|
#include "../Classes/x-saherelm.xfima.x-poi.drawer.class.mq5"
|
|
|
|
//
|
|
// Implementation ...
|
|
|
|
//
|
|
// Base XFIMA base Signaller ...
|
|
class XCXFIMABaseSignaller : public XCBaseSignaller
|
|
{
|
|
//
|
|
// Public ...
|
|
public:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
XFIMAInputs fimaInputs; // XFIMA Inputs ...
|
|
XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ...
|
|
XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ...
|
|
XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ...
|
|
|
|
//
|
|
// Constructor ...
|
|
XCXFIMABaseSignaller(
|
|
string _name, // Name ...
|
|
string _symbol, // Symbol ...
|
|
ENUM_TIMEFRAMES _period, // Period ...
|
|
XFIMAInputs &_fimaInputs, // XFIMAInputs ...
|
|
bool _processAllTicks = false, // Process All Ticks ...
|
|
double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ...
|
|
double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ...
|
|
double _defaultSignalVolume = 0.01 // Default Signal Volume ...
|
|
) : XCBaseSignaller(_name,
|
|
_symbol,
|
|
_period,
|
|
_processAllTicks,
|
|
_defaultSignalR2R,
|
|
_defaultSignalRiskInPoint,
|
|
_defaultSignalVolume //
|
|
)
|
|
{
|
|
//
|
|
// Instantiating XFIMA Indicator Helper Class ...
|
|
if (_fimaInputs.IsValid())
|
|
{
|
|
//
|
|
fimaHelper = new XCXFIMAHelper();
|
|
bool isInited = fimaHelper.Init(
|
|
_symbol,
|
|
_period,
|
|
_fimaInputs //
|
|
);
|
|
if (isInited)
|
|
{
|
|
fimaInputs = _fimaInputs;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
delete fimaHelper;
|
|
ZeroMemory(fimaHelper);
|
|
}
|
|
}
|
|
|
|
//
|
|
poiDrawer = new XCXFIMAPOIDrawer();
|
|
poiDetector = new XCXFIMAPOIDetector(fimaHelper);
|
|
}
|
|
|
|
//
|
|
// Deconstructor ...
|
|
~XCXFIMABaseSignaller()
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
//
|
|
// Overrides ...
|
|
|
|
//
|
|
// Actions ...
|
|
|
|
/**
|
|
* Destroy ...
|
|
*/
|
|
void Destroy()
|
|
{
|
|
//
|
|
BeforeDestroy();
|
|
|
|
//
|
|
fimaInputs.Clean();
|
|
|
|
//
|
|
delete fimaHelper;
|
|
ZeroMemory(fimaHelper);
|
|
|
|
//
|
|
delete poiDrawer;
|
|
ZeroMemory(poiDrawer);
|
|
|
|
//
|
|
delete poiDetector;
|
|
ZeroMemory(poiDetector);
|
|
}
|
|
|
|
//
|
|
// 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[]
|
|
* @param barIndex: int
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int virtual CheckForGuard(
|
|
XGuard &guards[],
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
SpecifiedClean(guards);
|
|
|
|
//
|
|
result = ArraySize(guards);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Additional Validations on Childs Instances ...
|
|
*
|
|
* @return ( bool virtual )
|
|
*/
|
|
bool virtual CheckAdditionslSignallerValidations()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Fima Helper Requirements ...
|
|
result = fimaInputs.IsValid() &&
|
|
fimaHelper != NULL &&
|
|
poiDetector != NULL;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Normalizing Signal by Signaller Custom Props ...
|
|
*
|
|
* @param signal: XSignal ...
|
|
*/
|
|
void virtual NormalizeSignal(XSignal &signal)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Protected ...
|
|
protected:
|
|
//
|
|
|
|
//
|
|
// Private ...
|
|
private:
|
|
//
|
|
};
|
|
|
|
//
|
|
// XFIMA Strategy 1 Signaller Class ...
|
|
class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller
|
|
{
|
|
//
|
|
// Public ...
|
|
public:
|
|
//
|
|
// Props ...
|
|
int fvgLookupLenght; // Maximum Lenght for Looking up FVG before Crosses
|
|
|
|
//
|
|
// 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 //
|
|
)
|
|
{
|
|
//
|
|
fvgLookupLenght = 5;
|
|
}
|
|
|
|
//
|
|
// 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);
|
|
|
|
//
|
|
// Update Helper ...
|
|
fimaHelper.Update(barIndex);
|
|
|
|
//
|
|
XOHCL bar;
|
|
XSignal signal;
|
|
bool has = false;
|
|
int cIdx = barIndex + 1;
|
|
int pIdx = cIdx + 1;
|
|
ENUM_X_DIRECTION signalDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Initialize Bar as CBar ...
|
|
has = bar.Init(
|
|
symbol,
|
|
period,
|
|
cIdx //
|
|
);
|
|
if (!has)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Retrieve Conditions ...
|
|
XFIMAConditions fimaConditions;
|
|
has = fimaHelper.GetConditions(
|
|
fimaConditions,
|
|
barIndex,
|
|
10 // Loopback ...
|
|
);
|
|
if (!has)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
fimaConditions.Clean();
|
|
|
|
//
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Analyse Conditions for Finding Signal ...
|
|
|
|
//
|
|
// TODO: Remove this ...
|
|
|
|
//
|
|
bool isFastCrossedOverSlow =
|
|
fimaConditions.maFastBuffer[cIdx] > fimaConditions.maSlowBuffer[cIdx] &&
|
|
fimaConditions.maFastBuffer[pIdx] < fimaConditions.maSlowBuffer[pIdx];
|
|
|
|
//
|
|
bool isFastCrossedUnderSlow =
|
|
fimaConditions.maFastBuffer[cIdx] < fimaConditions.maSlowBuffer[cIdx] &&
|
|
fimaConditions.maFastBuffer[pIdx] > fimaConditions.maSlowBuffer[pIdx];
|
|
|
|
//
|
|
has =
|
|
isFastCrossedOverSlow ||
|
|
isFastCrossedUnderSlow;
|
|
if (has)
|
|
{
|
|
//
|
|
// Do Conditions Validating ...
|
|
// TODO: Igmore All Validations for Testing Purposes ...
|
|
|
|
//
|
|
// Validate MA Positions ...
|
|
double iFastMa = fimaConditions.maFastBuffer[cIdx];
|
|
double iSlowMa = fimaConditions.maSlowBuffer[cIdx];
|
|
double iFiboUpper = fimaConditions.fiboUpperBuffer[cIdx];
|
|
double iFiboLower = fimaConditions.fiboLowerBuffer[cIdx];
|
|
|
|
//
|
|
// Checking Has FVG ...
|
|
XBoxZone fvg;
|
|
ENUM_X_DIRECTION fvgDir;
|
|
bool hasFVG = patternDetector.HasFVG(
|
|
bar,
|
|
fvgDir,
|
|
fvg,
|
|
fvgLookupLenght //
|
|
);
|
|
|
|
//
|
|
// Checking Crossed On Shadow ...
|
|
|
|
//
|
|
bool isCrossedOverHappensOnShadow =
|
|
isFastCrossedOverSlow &&
|
|
iFastMa <= bar.GetDown() &&
|
|
iFastMa >= bar.low;
|
|
|
|
//
|
|
bool isCrossedUnderHappensOnShadow =
|
|
isFastCrossedUnderSlow &&
|
|
iFastMa <= bar.high &&
|
|
iFastMa >= bar.GetUp();
|
|
|
|
//
|
|
// Bullish Validation ...
|
|
bool isBullish =
|
|
//
|
|
// Has Cross ...
|
|
isFastCrossedOverSlow
|
|
//
|
|
// &&
|
|
// //
|
|
// // Cross Places Based on Fibo ...
|
|
// MathMax(iFastMa, iSlowMa) < iFiboLower
|
|
// //
|
|
// &&
|
|
// //
|
|
// (
|
|
// //
|
|
// // Checking FVG ...
|
|
// (hasFVG &&
|
|
// fvg.IsBullish())
|
|
// //
|
|
// ||
|
|
// //
|
|
// // Checking Crossed Place ...
|
|
// isCrossedOverHappensOnShadow
|
|
// //
|
|
// )
|
|
// //
|
|
;
|
|
|
|
//
|
|
// Bearish Validation ...
|
|
bool isBearish =
|
|
//
|
|
// Has Cross ...
|
|
isFastCrossedUnderSlow
|
|
//
|
|
// &&
|
|
// //
|
|
// // Cross Places Based on Fibo ...
|
|
// MathMin(iFastMa, iSlowMa) > iFiboUpper
|
|
// //
|
|
// &&
|
|
// //
|
|
// (
|
|
// //
|
|
// // Checking FVG ...
|
|
// (hasFVG &&
|
|
// fvg.IsBearish())
|
|
// //
|
|
// ||
|
|
// //
|
|
// // Checking Crossed Place ...
|
|
// isCrossedUnderHappensOnShadow
|
|
// //
|
|
// )
|
|
// //
|
|
;
|
|
|
|
//
|
|
has =
|
|
(isBullish && !isBearish) ||
|
|
(isBearish && !isBullish);
|
|
if (has)
|
|
{
|
|
//
|
|
signalDir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Signal Founded ...
|
|
has = HasDirection(signalDir);
|
|
if (has)
|
|
{
|
|
//
|
|
// Prepare Founded Signal ...
|
|
XTarget targets[];
|
|
has = PrepareSignal(
|
|
signal,
|
|
signalDir,
|
|
targets //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
// Notify On Signal Event ...
|
|
NotifySignalEventListeners(signal);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
bar.Clean();
|
|
signal.Clean();
|
|
fimaConditions.Clean();
|
|
}
|
|
|
|
/**
|
|
* Check Guards Based on MarketConditions ...
|
|
*
|
|
* @param guards: XGuard[]
|
|
* @param barIndex: int
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int virtual CheckForGuard(
|
|
XGuard &guards[],
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
SpecifiedClean(guards);
|
|
|
|
//
|
|
result = ArraySize(guards);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Private ...
|
|
private:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
// Lookup FVG ...
|
|
bool LookupFVG(
|
|
XOHCL &bar,
|
|
ENUM_X_DIRECTION &dir,
|
|
XBoxZone &fvgBox //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
//
|
|
// XFIMA Strategy 2 Signaller Class ...
|
|
class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller
|
|
{
|
|
//
|
|
// Public ...
|
|
public:
|
|
//
|
|
// Props ...
|
|
XFIMAPatternDetectorConfig analyserConfig;
|
|
|
|
//
|
|
// Constructor ...
|
|
XCXFIMAStrategy2Signaller(
|
|
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("XFIMA2",
|
|
_symbol,
|
|
_period,
|
|
_fimaInputs,
|
|
_processAllTicks,
|
|
_defaultSignalR2R,
|
|
_defaultSignalRiskInPoint,
|
|
_defaultSignalVolume //
|
|
)
|
|
{
|
|
//
|
|
// Configure Detector ...
|
|
analyserConfig.Default();
|
|
analyserConfig.FullDetect();
|
|
}
|
|
|
|
//
|
|
// Deconstructor ...
|
|
~XCXFIMAStrategy2Signaller()
|
|
{
|
|
//
|
|
Destroy();
|
|
|
|
//
|
|
analyserConfig.Clean();
|
|
}
|
|
|
|
//
|
|
// Overrides ...
|
|
|
|
/**
|
|
* Processing Tick ...
|
|
*
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
*/
|
|
virtual void ProcessTick(int barIndex = 0)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Processing New Bar ...
|
|
*
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
*/
|
|
void ProcessNewBarNKP(int barIndex = 0)
|
|
{
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
|
|
//
|
|
// Update Helper ...
|
|
fimaHelper.Update(barIndex);
|
|
|
|
//
|
|
XOHCL bar;
|
|
XSignal signal;
|
|
XBoxZone iZone;
|
|
int count = 0;
|
|
bool has = false;
|
|
int cIdx = barIndex + 1;
|
|
int pIdx = cIdx + 1;
|
|
string iName = NULL;
|
|
XBoxZone supports[];
|
|
XBoxZone resistances[];
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
double iPrice = EMPTY_VALUE;
|
|
XFIMAMarketStructure structure;
|
|
XFIMAConditions fimaConditions;
|
|
ENUM_X_PRICE iPriceType = X_PRICE_NONE;
|
|
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
XPivot pvPivots[];
|
|
string pvTrendName = "XXIFMA2PVTrend";
|
|
CChartObjectTrend *pvTrendLine = NULL;
|
|
ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE;
|
|
|
|
//
|
|
XPivot zgPivots[];
|
|
string zgTrendName = "XFIMA2ZGTrend";
|
|
CChartObjectTrend *zgTrendLine = NULL;
|
|
ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Initialize Bar as CBar ...
|
|
has = bar.Init(
|
|
symbol,
|
|
period,
|
|
cIdx //
|
|
);
|
|
if (!has)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Retrieve Conditions ...
|
|
has = fimaHelper.GetConditions(
|
|
fimaConditions,
|
|
barIndex,
|
|
10 // Loopback ...
|
|
);
|
|
if (!has)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
fimaConditions.Clean();
|
|
|
|
//
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Analyse Market ...
|
|
poiDetector.AnalyseMarket(
|
|
bar,
|
|
structure,
|
|
analyserConfig //
|
|
);
|
|
|
|
//
|
|
// Check Required Pattern Exists ...
|
|
bool hasPinnedBar = HasDirection(structure.pinnedDir);
|
|
bool hasEngulfedBar = HasDirection(structure.engulfedDir);
|
|
bool hasFlagPattern = HasDirection(structure.flagPatternDir);
|
|
bool hasStarPattern = HasDirection(structure.starPatternDir);
|
|
bool hasRisingPattern = HasDirection(structure.risingPatternDir);
|
|
bool hasPiercingPattern = HasDirection(structure.piercingPatternDir);
|
|
bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir);
|
|
|
|
//
|
|
// Check Bar Pattern Exists ...
|
|
has = hasPinnedBar ||
|
|
hasEngulfedBar ||
|
|
hasFlagPattern ||
|
|
hasStarPattern ||
|
|
hasSignalKeyBar ||
|
|
hasRisingPattern ||
|
|
hasPiercingPattern;
|
|
|
|
//
|
|
// Select Pattern Direction and Price and Price Type ...
|
|
if (has)
|
|
{
|
|
//
|
|
if (hasPinnedBar)
|
|
{
|
|
//
|
|
iDir = structure.pinnedDir;
|
|
iName = "XPinned_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
else if (hasEngulfedBar)
|
|
{
|
|
//
|
|
iDir = structure.engulfedDir;
|
|
iName = "XEngulfed_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
else if (hasFlagPattern)
|
|
{
|
|
//
|
|
iDir = structure.flagPatternDir;
|
|
iName = "XFlag_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
else if (hasStarPattern)
|
|
{
|
|
//
|
|
iDir = structure.starPatternDir;
|
|
iName = "XStar_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
else if (hasSignalKeyBar)
|
|
{
|
|
//
|
|
iDir = structure.risingPatternDir;
|
|
iName = "XRising_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
else if (hasRisingPattern)
|
|
{
|
|
//
|
|
iDir = structure.piercingPatternDir;
|
|
iName = "XPiercing_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
else if (hasPiercingPattern)
|
|
{
|
|
//
|
|
iDir = structure.signalKeyBarPatternDir;
|
|
iName = "XSignalKey_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
|
|
//
|
|
isBullish = IsSpecifiedBullish(iDir);
|
|
isBearish = IsSpecifiedBearish(iDir);
|
|
|
|
//
|
|
// Retrieve Price Type for Validate ...
|
|
iPriceType = isBullish
|
|
? X_PRICE_LOW
|
|
: X_PRICE_HIGH;
|
|
iPrice = bar.GetPrice(iPriceType);
|
|
|
|
//
|
|
has = HasDirection(iDir);
|
|
}
|
|
|
|
//
|
|
// Chekc Bullish or Bearish Starter Conditions Exists ...
|
|
has =
|
|
isBullish ||
|
|
isBearish;
|
|
if (has)
|
|
{
|
|
//
|
|
// Do Conditions Validating ...
|
|
|
|
//
|
|
// Retrieve MA Band for Validation ...
|
|
double iMABandUpper = fimaHelper.GetMABandUpper(barIndex);
|
|
double iMABandLower = fimaHelper.GetMABandLower(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
has = isBullish
|
|
? iPrice < iMABandLower
|
|
: iPrice > iMABandUpper;
|
|
if (!has)
|
|
{
|
|
//
|
|
isBullish = false;
|
|
isBearish = false;
|
|
iDir = X_DIRECTION_NONE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Collect Support and Resistance Zones and Validate by them ...
|
|
|
|
//
|
|
// PV Trend Line ...
|
|
bool hasPVAnalysis = structure.pvAnalysis.IsValid();
|
|
if (hasPVAnalysis)
|
|
{
|
|
//
|
|
// Support ...
|
|
XBoxZone supportBox;
|
|
has = structure.pvAnalysis.HasSupportBox(supportBox);
|
|
if (has)
|
|
{
|
|
//
|
|
supportBox.to = bar.time;
|
|
AddIfNotExists(
|
|
supportBox,
|
|
supports //
|
|
);
|
|
// has = poiDrawer.DrawBox(
|
|
// supportBox,
|
|
// iSupportObj,
|
|
// true, // Ignore At ...
|
|
// supportBox.type // Name ...
|
|
// );
|
|
// if (has)
|
|
// {
|
|
// //
|
|
// XPOIStyle iStyle;
|
|
// poiDrawer.GetBoxStyle(
|
|
// iStyle,
|
|
// supportBox.dir //
|
|
// );
|
|
// poiDrawer.ApplyBoxStyle(
|
|
// iSupportObj,
|
|
// iStyle //
|
|
// );
|
|
// iStyle.Clean();
|
|
// }
|
|
}
|
|
|
|
//
|
|
// Resistance ...
|
|
XBoxZone resistanceBox;
|
|
has = structure.pvAnalysis.HasResistanceBox(resistanceBox);
|
|
if (has)
|
|
{
|
|
//
|
|
resistanceBox.to = bar.time;
|
|
AddIfNotExists(
|
|
resistanceBox,
|
|
supports //
|
|
);
|
|
// has = poiDrawer.DrawBox(
|
|
// resistanceBox,
|
|
// iResistanceObj,
|
|
// true, // Ignore At ...
|
|
// resistanceBox.type // Name ...
|
|
// );
|
|
// if (has)
|
|
// {
|
|
// //
|
|
// XPOIStyle iStyle;
|
|
// poiDrawer.GetBoxStyle(
|
|
// iStyle,
|
|
// resistanceBox.dir //
|
|
// );
|
|
// poiDrawer.ApplyBoxStyle(
|
|
// iResistanceObj,
|
|
// iStyle //
|
|
// );
|
|
// iStyle.Clean();
|
|
// }
|
|
}
|
|
|
|
//
|
|
// Pivots ...
|
|
XPivot pivots[];
|
|
count = poiDetector.ExtractPVPivots(
|
|
pivots,
|
|
barIndex,
|
|
50 //
|
|
);
|
|
has = IsValidSize(count);
|
|
|
|
//
|
|
// Sort ...
|
|
Sort(
|
|
pivots,
|
|
X_SORT_BY_DATE,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
// Remove Newest ...
|
|
ArrayRemove(
|
|
pivots,
|
|
0,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
// Check Trend ...
|
|
if (has)
|
|
{
|
|
//
|
|
XPivot highs[];
|
|
int highsCount = ExtractPivots(
|
|
highs,
|
|
pivots,
|
|
X_PIVOT_TYPE_PEAK //
|
|
);
|
|
Sort(
|
|
highs,
|
|
X_SORT_BY_DATE,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
XPivot lows[];
|
|
int lowsCount = ExtractPivots(
|
|
lows,
|
|
pivots,
|
|
X_PIVOT_TYPE_VALE //
|
|
);
|
|
Sort(
|
|
lows,
|
|
X_SORT_BY_DATE,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
// Check Highs and Lows ...
|
|
has = IsValidSize(lowsCount) &&
|
|
IsValidSize(highsCount) &&
|
|
lowsCount >= 2 &&
|
|
highsCount >= 2;
|
|
if (has)
|
|
{
|
|
//
|
|
// Try to Get Market Strucutre ...
|
|
|
|
//
|
|
bool hasLowerHigh = highs[0].value < highs[1].value;
|
|
bool hasLowerLow = lows[0].value < lows[1].value;
|
|
|
|
//
|
|
bool hasHigherHigh = highs[0].value > highs[1].value;
|
|
bool hasHigherLow = lows[0].value > lows[1].value;
|
|
|
|
//
|
|
pvTrend =
|
|
(hasHigherHigh &&
|
|
hasHigherLow)
|
|
? X_DIRECTION_BULLISH
|
|
: (hasLowerHigh &&
|
|
hasLowerLow)
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
has = HasDirection(pvTrend);
|
|
if (has)
|
|
{
|
|
//
|
|
// Select Swings for Trend Line ...
|
|
XOHCL tmpBar;
|
|
int llIDX = -1;
|
|
int hhIDX = -1;
|
|
datetime toTime = NULL;
|
|
datetime fromTime = NULL;
|
|
double toPrice = EMPTY_VALUE;
|
|
color trendColor = CLR_NONE;
|
|
double fromPrice = EMPTY_VALUE;
|
|
if (IsSpecifiedBullish(pvTrend))
|
|
{
|
|
//
|
|
llIDX = GetLowest(lows);
|
|
hhIDX = GetHighest(lows);
|
|
|
|
//
|
|
trendColor = clrAqua;
|
|
|
|
//
|
|
toTime = lows[hhIDX].time;
|
|
toPrice = lows[hhIDX].value;
|
|
|
|
//
|
|
fromTime = lows[llIDX].time;
|
|
fromPrice = lows[llIDX].value;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
llIDX = GetLowest(highs);
|
|
hhIDX = GetHighest(highs);
|
|
|
|
//
|
|
trendColor = clrMagenta;
|
|
|
|
//
|
|
toTime = highs[llIDX].time;
|
|
toPrice = highs[llIDX].value;
|
|
|
|
//
|
|
fromTime = highs[hhIDX].time;
|
|
fromPrice = highs[hhIDX].value;
|
|
}
|
|
|
|
//
|
|
// Check Requirements for Trend ...
|
|
has =
|
|
NotEmptyZero(toPrice) &&
|
|
NotEmptyZero(fromPrice) &&
|
|
IsSpecifiedValid(toTime) &&
|
|
IsSpecifiedValid(fromTime);
|
|
if (has)
|
|
{
|
|
//
|
|
has = poiDrawer.DrawTrendLine(
|
|
fromPrice,
|
|
fromTime,
|
|
toPrice,
|
|
toTime,
|
|
pvTrendLine,
|
|
pvTrendName,
|
|
true // Ray Right ...
|
|
);
|
|
if (has)
|
|
{
|
|
pvTrendLine.Color(trendColor);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
tmpBar.Clean();
|
|
}
|
|
|
|
//
|
|
if (!has)
|
|
{
|
|
SpecifiedClean(pivots);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
SpecifiedClean(lows);
|
|
SpecifiedClean(highs);
|
|
}
|
|
|
|
//
|
|
// Draw Pivots ...
|
|
has = HasChild(pivots);
|
|
if (has)
|
|
{
|
|
//
|
|
Copy(
|
|
pivots,
|
|
pvPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
SpecifiedClean(pivots);
|
|
}
|
|
|
|
//
|
|
// ZigZag Trend Line ...
|
|
bool hasZGAnalysis = structure.zigzagAnalysis.IsValid();
|
|
if (hasZGAnalysis)
|
|
{
|
|
//
|
|
// Support ...
|
|
XBoxZone supportBox;
|
|
has = structure.zigzagAnalysis.HasSupportBox(supportBox);
|
|
if (has)
|
|
{
|
|
//
|
|
supportBox.to = bar.time;
|
|
AddIfNotExists(
|
|
supportBox,
|
|
supports //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Resistance ...
|
|
XBoxZone resistanceBox;
|
|
has = structure.zigzagAnalysis.HasResistanceBox(resistanceBox);
|
|
if (has)
|
|
{
|
|
//
|
|
resistanceBox.to = bar.time;
|
|
AddIfNotExists(
|
|
resistanceBox,
|
|
supports //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Pivots ...
|
|
XPivot pivots[];
|
|
count = poiDetector.ExtractZigZagPivots(
|
|
pivots,
|
|
barIndex,
|
|
10 //
|
|
);
|
|
has = IsValidSize(count);
|
|
|
|
//
|
|
// Sort ...
|
|
Sort(
|
|
pivots,
|
|
X_SORT_BY_DATE,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
// Remove Newest ...
|
|
ArrayRemove(
|
|
pivots,
|
|
0,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
// Check Trend ...
|
|
if (has)
|
|
{
|
|
//
|
|
XPivot highs[];
|
|
int highsCount = ExtractPivots(
|
|
highs,
|
|
pivots,
|
|
X_PIVOT_TYPE_PEAK //
|
|
);
|
|
Sort(
|
|
highs,
|
|
X_SORT_BY_DATE,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
XPivot lows[];
|
|
int lowsCount = ExtractPivots(
|
|
lows,
|
|
pivots,
|
|
X_PIVOT_TYPE_VALE //
|
|
);
|
|
Sort(
|
|
lows,
|
|
X_SORT_BY_DATE,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
// Check Highs and Lows ...
|
|
has = IsValidSize(lowsCount) &&
|
|
IsValidSize(highsCount) &&
|
|
lowsCount >= 2 &&
|
|
highsCount >= 2;
|
|
if (has)
|
|
{
|
|
//
|
|
// Try to Get Market Strucutre ...
|
|
|
|
//
|
|
bool hasLowerHigh = highs[0].value < highs[1].value;
|
|
bool hasLowerLow = lows[0].value < lows[1].value;
|
|
|
|
//
|
|
bool hasHigherHigh = highs[0].value > highs[1].value;
|
|
bool hasHigherLow = lows[0].value > lows[1].value;
|
|
|
|
//
|
|
zgTrend =
|
|
(hasHigherHigh &&
|
|
hasHigherLow)
|
|
? X_DIRECTION_BULLISH
|
|
: (hasLowerHigh &&
|
|
hasLowerLow)
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
has = HasDirection(zgTrend);
|
|
if (has)
|
|
{
|
|
//
|
|
// Select Swings for Trend Line ...
|
|
XOHCL tmpBar;
|
|
int llIDX = -1;
|
|
int hhIDX = -1;
|
|
datetime toTime = NULL;
|
|
datetime fromTime = NULL;
|
|
double toPrice = EMPTY_VALUE;
|
|
color trendColor = CLR_NONE;
|
|
double fromPrice = EMPTY_VALUE;
|
|
if (IsSpecifiedBullish(zgTrend))
|
|
{
|
|
//
|
|
llIDX = GetLowest(lows);
|
|
hhIDX = GetHighest(lows);
|
|
|
|
//
|
|
trendColor = clrAqua;
|
|
|
|
//
|
|
toTime = lows[hhIDX].time;
|
|
toPrice = lows[hhIDX].value;
|
|
|
|
//
|
|
fromTime = lows[llIDX].time;
|
|
fromPrice = lows[llIDX].value;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
llIDX = GetLowest(highs);
|
|
hhIDX = GetHighest(highs);
|
|
|
|
//
|
|
trendColor = clrMagenta;
|
|
|
|
//
|
|
toTime = highs[llIDX].time;
|
|
toPrice = highs[llIDX].value;
|
|
|
|
//
|
|
fromTime = highs[hhIDX].time;
|
|
fromPrice = highs[hhIDX].value;
|
|
}
|
|
|
|
//
|
|
// Check Requirements for Trend ...
|
|
has =
|
|
NotEmptyZero(toPrice) &&
|
|
NotEmptyZero(fromPrice) &&
|
|
IsSpecifiedValid(toTime) &&
|
|
IsSpecifiedValid(fromTime);
|
|
if (has)
|
|
{
|
|
//
|
|
has = poiDrawer.DrawTrendLine(
|
|
fromPrice,
|
|
fromTime,
|
|
toPrice,
|
|
toTime,
|
|
zgTrendLine,
|
|
zgTrendName,
|
|
true // Ray Right ...
|
|
);
|
|
if (has)
|
|
{
|
|
zgTrendLine.Color(trendColor);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
tmpBar.Clean();
|
|
}
|
|
|
|
//
|
|
if (!has)
|
|
{
|
|
SpecifiedClean(pivots);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
SpecifiedClean(lows);
|
|
SpecifiedClean(highs);
|
|
}
|
|
|
|
//
|
|
// Draw Pivots ...
|
|
has = HasChild(pivots);
|
|
if (has)
|
|
{
|
|
//
|
|
Copy(
|
|
pivots,
|
|
zgPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
SpecifiedClean(pivots);
|
|
}
|
|
|
|
//
|
|
// Support ...
|
|
bool hasSupport = structure.support.IsValid();
|
|
if (hasSupport)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
structure.support,
|
|
supports //
|
|
);
|
|
|
|
// //
|
|
// XCBoxObject *iObj;
|
|
// has = fima2Signaller.poiDrawer.DrawBox(
|
|
// structure.support,
|
|
// iObj);
|
|
// if (has)
|
|
// {
|
|
// }
|
|
}
|
|
|
|
//
|
|
// Resistance ...
|
|
bool hasResistance = structure.resistance.IsValid();
|
|
if (hasResistance)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
structure.resistance,
|
|
resistances //
|
|
);
|
|
|
|
// //
|
|
// XCBoxObject *iObj;
|
|
// has = fima2Signaller.poiDrawer.DrawBox(
|
|
// structure.resistance,
|
|
// iObj);
|
|
// if (has)
|
|
// {
|
|
// }
|
|
}
|
|
|
|
//
|
|
// Validate Positions Support and Resistance Zone ...
|
|
int insideZoneIDX = -1;
|
|
has = has &&
|
|
(isBullish
|
|
? HasInside(
|
|
insideZoneIDX,
|
|
bar,
|
|
supports //
|
|
)
|
|
: HasInside(
|
|
insideZoneIDX,
|
|
bar,
|
|
resistances //
|
|
));
|
|
|
|
//
|
|
// Validate Selected Inside Zone ...
|
|
// whith Bars Edge ...
|
|
has = IsValidIndex(insideZoneIDX);
|
|
if (has)
|
|
{
|
|
//
|
|
if (isBullish)
|
|
{
|
|
iZone = supports[insideZoneIDX];
|
|
}
|
|
else
|
|
{
|
|
iZone = resistances[insideZoneIDX];
|
|
}
|
|
|
|
//
|
|
has = isBullish
|
|
? bar.high > supports[insideZoneIDX].upper
|
|
: bar.low < resistances[insideZoneIDX].lower;
|
|
if (!has)
|
|
{
|
|
//
|
|
isBullish = false;
|
|
isBearish = false;
|
|
iDir = X_DIRECTION_NONE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
isBullish = false;
|
|
isBearish = false;
|
|
iDir = X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
// Checking Liquidities ...
|
|
|
|
//
|
|
// Do all Draws Here ...
|
|
bool canDraw = false;
|
|
if (canDraw)
|
|
{
|
|
//
|
|
int iWidth = 2;
|
|
XPOIStyle iStyle;
|
|
XCBoxObject *iBoxObj = NULL;
|
|
color iClr = isBullish
|
|
? clrYellow
|
|
: clrDarkOrange;
|
|
|
|
//
|
|
// Supports ...
|
|
has = HasChild(supports);
|
|
if (has)
|
|
{
|
|
//
|
|
count = ArraySize(supports);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = poiDrawer.DrawBox(
|
|
supports[i],
|
|
iBoxObj,
|
|
true, // Ignore At ...
|
|
supports[i].type // Name ...
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
poiDrawer.GetBoxStyle(
|
|
iStyle,
|
|
supports[i].dir //
|
|
);
|
|
|
|
//
|
|
poiDrawer.ApplyBoxStyle(
|
|
iBoxObj,
|
|
iStyle //
|
|
);
|
|
}
|
|
|
|
//
|
|
iStyle.Clean();
|
|
ZeroMemory(iBoxObj);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Resistances ...
|
|
has = HasChild(resistances);
|
|
if (has)
|
|
{
|
|
//
|
|
count = ArraySize(resistances);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = poiDrawer.DrawBox(
|
|
resistances[i],
|
|
iBoxObj,
|
|
true, // Ignore At ...
|
|
resistances[i].type // Name ...
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
poiDrawer.GetBoxStyle(
|
|
iStyle,
|
|
resistances[i].dir //
|
|
);
|
|
|
|
//
|
|
poiDrawer.ApplyBoxStyle(
|
|
iBoxObj,
|
|
iStyle //
|
|
);
|
|
}
|
|
|
|
//
|
|
iStyle.Clean();
|
|
ZeroMemory(iBoxObj);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Selected Zone ...
|
|
has = iZone.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
has = poiDrawer.DrawBox(
|
|
iZone,
|
|
iBoxObj,
|
|
true, // Ignore At ...
|
|
iZone.type // Name ...
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
poiDrawer.GetBoxStyle(
|
|
iStyle,
|
|
iZone.dir //
|
|
);
|
|
|
|
//
|
|
iStyle.clr = iClr;
|
|
iStyle.width = iWidth;
|
|
|
|
//
|
|
poiDrawer.ApplyBoxStyle(
|
|
iBoxObj,
|
|
iStyle //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// TrendLines ...
|
|
|
|
//
|
|
// Pivots ...
|
|
|
|
//
|
|
has = HasChild(pvPivots);
|
|
if (has)
|
|
{
|
|
//
|
|
CArrayObj *drawnPivots = new CArrayObj();
|
|
count = poiDrawer.DrawPivots(
|
|
pvPivots,
|
|
drawnPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
has = HasChild(zgPivots);
|
|
if (has)
|
|
{
|
|
//
|
|
CArrayObj *drawnPivots = new CArrayObj();
|
|
count = poiDrawer.DrawPivots(
|
|
zgPivots,
|
|
drawnPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Patterns Bar ...
|
|
has = HasDirection(iDir);
|
|
if (has)
|
|
{
|
|
//
|
|
int iCode = 159;
|
|
ENUM_ARROW_ANCHOR iAnchor = isBullish
|
|
? ANCHOR_TOP
|
|
: ANCHOR_BOTTOM;
|
|
|
|
//
|
|
XCBarArrowObject *iPatternObj;
|
|
has = poiDrawer.DrawBarArrow(
|
|
bar,
|
|
iPatternObj,
|
|
iPriceType,
|
|
iCode,
|
|
iClr,
|
|
iWidth,
|
|
iAnchor,
|
|
iName,
|
|
true, // Ignore Bar Tag ...
|
|
10 // Threshold ...
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Signal Founded ...
|
|
has = HasDirection(iDir);
|
|
if (has)
|
|
{
|
|
//
|
|
// TODO: Provided SL ...
|
|
double _point = GetPoints(bar.symbol);
|
|
double slAddition = 5 * _point;
|
|
double slPrice =
|
|
isBullish
|
|
? iZone.lower - slAddition
|
|
: iZone.upper + slAddition;
|
|
|
|
//
|
|
// Prepare Founded Signal ...
|
|
XTarget targets[];
|
|
has = PrepareSignal(
|
|
signal,
|
|
iDir,
|
|
targets,
|
|
0, // Use Default R2R ...
|
|
slPrice, // Provided Price for SL ...
|
|
0 // Specified Risk in Point ....
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
// Notify On Signal Event ...
|
|
NotifySignalEventListeners(signal);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
bar.Clean();
|
|
iZone.Clean();
|
|
signal.Clean();
|
|
structure.Clean();
|
|
fimaConditions.Clean();
|
|
SpecifiedClean(pvPivots);
|
|
SpecifiedClean(zgPivots);
|
|
SpecifiedClean(supports);
|
|
SpecifiedClean(resistances);
|
|
}
|
|
|
|
/**
|
|
* Processing New Bar ...
|
|
*
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
*/
|
|
void ProcessNewBarNKP1(int barIndex = 0)
|
|
{
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
|
|
//
|
|
// Update Helper ...
|
|
fimaHelper.Update(barIndex);
|
|
|
|
//
|
|
XOHCL bar;
|
|
XSignal signal;
|
|
XBoxZone iZone;
|
|
int count = 0;
|
|
bool has = false;
|
|
int cIdx = 0;
|
|
int pIdx = cIdx + 1;
|
|
string iName = NULL;
|
|
XBoxZone supports[];
|
|
XBoxZone resistances[];
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
double iPrice = EMPTY_VALUE;
|
|
double iPriceEdge = EMPTY_VALUE;
|
|
XFIMAMarketStructure structure;
|
|
XFIMAConditions fimaConditions;
|
|
ENUM_X_PRICE iPriceType = X_PRICE_NONE;
|
|
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
|
|
ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE;
|
|
|
|
//
|
|
XPivot pvPivots[];
|
|
string pvTrendName = "XXIFMA2PVTrend";
|
|
CChartObjectTrend *pvTrendLine = NULL;
|
|
ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE;
|
|
|
|
//
|
|
XPivot zgPivots[];
|
|
string zgTrendName = "XFIMA2ZGTrend";
|
|
CChartObjectTrend *zgTrendLine = NULL;
|
|
ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Initialize Bar as CBar ...
|
|
has = bar.Init(
|
|
symbol,
|
|
period,
|
|
barIndex //
|
|
);
|
|
if (!has)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Retrieve Conditions ...
|
|
has = fimaHelper.GetConditions(
|
|
fimaConditions,
|
|
barIndex,
|
|
10 // Loopback ...
|
|
);
|
|
if (!has)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
fimaConditions.Clean();
|
|
|
|
//
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Analyse Market ...
|
|
poiDetector.AnalyseMarket(
|
|
bar,
|
|
structure,
|
|
analyserConfig //
|
|
);
|
|
|
|
//
|
|
// Collect Support and Resistance Zones and Validate by them ...
|
|
|
|
//
|
|
// PV Trend Line ...
|
|
bool hasPVAnalysis = structure.pvAnalysis.IsValid();
|
|
if (hasPVAnalysis)
|
|
{
|
|
//
|
|
// Support ...
|
|
XBoxZone supportBox;
|
|
has = structure.pvAnalysis.HasSupportBox(supportBox);
|
|
if (has)
|
|
{
|
|
//
|
|
supportBox.to = bar.time;
|
|
AddIfNotExists(
|
|
supportBox,
|
|
supports //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Resistance ...
|
|
XBoxZone resistanceBox;
|
|
has = structure.pvAnalysis.HasResistanceBox(resistanceBox);
|
|
if (has)
|
|
{
|
|
//
|
|
resistanceBox.to = bar.time;
|
|
AddIfNotExists(
|
|
resistanceBox,
|
|
supports //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Pivots ...
|
|
XPivot pivots[];
|
|
count = poiDetector.ExtractPVPivots(
|
|
pivots,
|
|
barIndex,
|
|
50 //
|
|
);
|
|
has = IsValidSize(count);
|
|
|
|
//
|
|
// Sort ...
|
|
Sort(
|
|
pivots,
|
|
X_SORT_BY_DATE,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
// Remove Newest ...
|
|
ArrayRemove(
|
|
pivots,
|
|
0,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
// Check Trend ...
|
|
if (has)
|
|
{
|
|
//
|
|
XPivot highs[];
|
|
int highsCount = ExtractPivots(
|
|
highs,
|
|
pivots,
|
|
X_PIVOT_TYPE_PEAK //
|
|
);
|
|
Sort(
|
|
highs,
|
|
X_SORT_BY_DATE,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
XPivot lows[];
|
|
int lowsCount = ExtractPivots(
|
|
lows,
|
|
pivots,
|
|
X_PIVOT_TYPE_VALE //
|
|
);
|
|
Sort(
|
|
lows,
|
|
X_SORT_BY_DATE,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
// Check Highs and Lows ...
|
|
has = IsValidSize(lowsCount) &&
|
|
IsValidSize(highsCount) &&
|
|
lowsCount >= 2 &&
|
|
highsCount >= 2;
|
|
if (has)
|
|
{
|
|
//
|
|
// Try to Get Market Strucutre ...
|
|
|
|
//
|
|
bool hasLowerHigh = highs[0].value < highs[1].value;
|
|
bool hasLowerLow = lows[0].value < lows[1].value;
|
|
|
|
//
|
|
bool hasHigherHigh = highs[0].value > highs[1].value;
|
|
bool hasHigherLow = lows[0].value > lows[1].value;
|
|
|
|
//
|
|
pvTrend =
|
|
(hasHigherHigh &&
|
|
hasHigherLow)
|
|
? X_DIRECTION_BULLISH
|
|
: (hasLowerHigh &&
|
|
hasLowerLow)
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
has = HasDirection(pvTrend);
|
|
if (has)
|
|
{
|
|
//
|
|
// Select Swings for Trend Line ...
|
|
XOHCL tmpBar;
|
|
int llIDX = -1;
|
|
int hhIDX = -1;
|
|
datetime toTime = NULL;
|
|
datetime fromTime = NULL;
|
|
double toPrice = EMPTY_VALUE;
|
|
color trendColor = CLR_NONE;
|
|
double fromPrice = EMPTY_VALUE;
|
|
if (IsSpecifiedBullish(pvTrend))
|
|
{
|
|
//
|
|
llIDX = GetLowest(lows);
|
|
hhIDX = GetHighest(lows);
|
|
|
|
//
|
|
trendColor = clrAqua;
|
|
|
|
//
|
|
toTime = lows[hhIDX].time;
|
|
toPrice = lows[hhIDX].value;
|
|
|
|
//
|
|
fromTime = lows[llIDX].time;
|
|
fromPrice = lows[llIDX].value;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
llIDX = GetLowest(highs);
|
|
hhIDX = GetHighest(highs);
|
|
|
|
//
|
|
trendColor = clrMagenta;
|
|
|
|
//
|
|
toTime = highs[llIDX].time;
|
|
toPrice = highs[llIDX].value;
|
|
|
|
//
|
|
fromTime = highs[hhIDX].time;
|
|
fromPrice = highs[hhIDX].value;
|
|
}
|
|
|
|
//
|
|
// Check Requirements for Trend ...
|
|
has =
|
|
NotEmptyZero(toPrice) &&
|
|
NotEmptyZero(fromPrice) &&
|
|
IsSpecifiedValid(toTime) &&
|
|
IsSpecifiedValid(fromTime);
|
|
if (has)
|
|
{
|
|
//
|
|
has = poiDrawer.DrawTrendLine(
|
|
fromPrice,
|
|
fromTime,
|
|
toPrice,
|
|
toTime,
|
|
pvTrendLine,
|
|
pvTrendName,
|
|
true // Ray Right ...
|
|
);
|
|
if (has)
|
|
{
|
|
pvTrendLine.Color(trendColor);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
tmpBar.Clean();
|
|
}
|
|
|
|
//
|
|
if (!has)
|
|
{
|
|
SpecifiedClean(pivots);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
SpecifiedClean(lows);
|
|
SpecifiedClean(highs);
|
|
}
|
|
|
|
//
|
|
// Draw Pivots ...
|
|
has = HasChild(pivots);
|
|
if (has)
|
|
{
|
|
//
|
|
Copy(
|
|
pivots,
|
|
pvPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
SpecifiedClean(pivots);
|
|
}
|
|
|
|
//
|
|
// ZigZag Trend Line ...
|
|
bool hasZGAnalysis = structure.zigzagAnalysis.IsValid();
|
|
if (hasZGAnalysis)
|
|
{
|
|
//
|
|
// Support ...
|
|
XBoxZone supportBox;
|
|
has = structure.zigzagAnalysis.HasSupportBox(supportBox);
|
|
if (has)
|
|
{
|
|
//
|
|
supportBox.to = bar.time;
|
|
AddIfNotExists(
|
|
supportBox,
|
|
supports //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Resistance ...
|
|
XBoxZone resistanceBox;
|
|
has = structure.zigzagAnalysis.HasResistanceBox(resistanceBox);
|
|
if (has)
|
|
{
|
|
//
|
|
resistanceBox.to = bar.time;
|
|
AddIfNotExists(
|
|
resistanceBox,
|
|
supports //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Pivots ...
|
|
XPivot pivots[];
|
|
count = poiDetector.ExtractZigZagPivots(
|
|
pivots,
|
|
barIndex,
|
|
10 //
|
|
);
|
|
has = IsValidSize(count);
|
|
|
|
//
|
|
// Sort ...
|
|
Sort(
|
|
pivots,
|
|
X_SORT_BY_DATE,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
// Remove Newest ...
|
|
ArrayRemove(
|
|
pivots,
|
|
0,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
// Check Trend ...
|
|
if (has)
|
|
{
|
|
//
|
|
XPivot highs[];
|
|
int highsCount = ExtractPivots(
|
|
highs,
|
|
pivots,
|
|
X_PIVOT_TYPE_PEAK //
|
|
);
|
|
Sort(
|
|
highs,
|
|
X_SORT_BY_DATE,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
XPivot lows[];
|
|
int lowsCount = ExtractPivots(
|
|
lows,
|
|
pivots,
|
|
X_PIVOT_TYPE_VALE //
|
|
);
|
|
Sort(
|
|
lows,
|
|
X_SORT_BY_DATE,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
// Check Highs and Lows ...
|
|
has = IsValidSize(lowsCount) &&
|
|
IsValidSize(highsCount) &&
|
|
lowsCount >= 2 &&
|
|
highsCount >= 2;
|
|
if (has)
|
|
{
|
|
//
|
|
// Try to Get Market Strucutre ...
|
|
|
|
//
|
|
bool hasLowerHigh = highs[0].value < highs[1].value;
|
|
bool hasLowerLow = lows[0].value < lows[1].value;
|
|
|
|
//
|
|
bool hasHigherHigh = highs[0].value > highs[1].value;
|
|
bool hasHigherLow = lows[0].value > lows[1].value;
|
|
|
|
//
|
|
zgTrend =
|
|
(hasHigherHigh &&
|
|
hasHigherLow)
|
|
? X_DIRECTION_BULLISH
|
|
: (hasLowerHigh &&
|
|
hasLowerLow)
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
has = HasDirection(zgTrend);
|
|
if (has)
|
|
{
|
|
//
|
|
// Select Swings for Trend Line ...
|
|
XOHCL tmpBar;
|
|
int llIDX = -1;
|
|
int hhIDX = -1;
|
|
datetime toTime = NULL;
|
|
datetime fromTime = NULL;
|
|
double toPrice = EMPTY_VALUE;
|
|
color trendColor = CLR_NONE;
|
|
double fromPrice = EMPTY_VALUE;
|
|
if (IsSpecifiedBullish(zgTrend))
|
|
{
|
|
//
|
|
llIDX = GetLowest(lows);
|
|
hhIDX = GetHighest(lows);
|
|
|
|
//
|
|
trendColor = clrAqua;
|
|
|
|
//
|
|
toTime = lows[hhIDX].time;
|
|
toPrice = lows[hhIDX].value;
|
|
|
|
//
|
|
fromTime = lows[llIDX].time;
|
|
fromPrice = lows[llIDX].value;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
llIDX = GetLowest(highs);
|
|
hhIDX = GetHighest(highs);
|
|
|
|
//
|
|
trendColor = clrMagenta;
|
|
|
|
//
|
|
toTime = highs[llIDX].time;
|
|
toPrice = highs[llIDX].value;
|
|
|
|
//
|
|
fromTime = highs[hhIDX].time;
|
|
fromPrice = highs[hhIDX].value;
|
|
}
|
|
|
|
//
|
|
// Check Requirements for Trend ...
|
|
has =
|
|
NotEmptyZero(toPrice) &&
|
|
NotEmptyZero(fromPrice) &&
|
|
IsSpecifiedValid(toTime) &&
|
|
IsSpecifiedValid(fromTime);
|
|
if (has)
|
|
{
|
|
//
|
|
has = poiDrawer.DrawTrendLine(
|
|
fromPrice,
|
|
fromTime,
|
|
toPrice,
|
|
toTime,
|
|
zgTrendLine,
|
|
zgTrendName,
|
|
true // Ray Right ...
|
|
);
|
|
if (has)
|
|
{
|
|
zgTrendLine.Color(trendColor);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
tmpBar.Clean();
|
|
}
|
|
|
|
//
|
|
if (!has)
|
|
{
|
|
SpecifiedClean(pivots);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
SpecifiedClean(lows);
|
|
SpecifiedClean(highs);
|
|
}
|
|
|
|
//
|
|
// Draw Pivots ...
|
|
has = HasChild(pivots);
|
|
if (has)
|
|
{
|
|
//
|
|
Copy(
|
|
pivots,
|
|
zgPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
SpecifiedClean(pivots);
|
|
}
|
|
|
|
//
|
|
// Support ...
|
|
bool hasSupport = structure.support.IsValid();
|
|
if (hasSupport)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
structure.support,
|
|
supports //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Resistance ...
|
|
bool hasResistance = structure.resistance.IsValid();
|
|
if (hasResistance)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
structure.resistance,
|
|
resistances //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Check Required Pattern Exists ...
|
|
bool hasPinnedBar = HasDirection(structure.pinnedDir);
|
|
bool hasEngulfedBar = HasDirection(structure.engulfedDir);
|
|
bool hasFlagPattern = HasDirection(structure.flagPatternDir);
|
|
bool hasStarPattern = HasDirection(structure.starPatternDir);
|
|
bool hasRisingPattern = HasDirection(structure.risingPatternDir);
|
|
bool hasPiercingPattern = HasDirection(structure.piercingPatternDir);
|
|
bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir);
|
|
|
|
//
|
|
// Check Bar Pattern Exists ...
|
|
// and Select Pattern Direction and Price and Price Type ...
|
|
has = hasPinnedBar ||
|
|
hasEngulfedBar ||
|
|
hasFlagPattern ||
|
|
hasStarPattern ||
|
|
hasSignalKeyBar ||
|
|
hasRisingPattern ||
|
|
hasPiercingPattern;
|
|
if (has)
|
|
{
|
|
//
|
|
if (hasPinnedBar)
|
|
{
|
|
//
|
|
iDir = structure.pinnedDir;
|
|
iName = "XPinned_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
else if (hasEngulfedBar)
|
|
{
|
|
//
|
|
iDir = structure.engulfedDir;
|
|
iName = "XEngulfed_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
else if (hasFlagPattern)
|
|
{
|
|
//
|
|
iDir = structure.flagPatternDir;
|
|
iName = "XFlag_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
else if (hasStarPattern)
|
|
{
|
|
//
|
|
iDir = structure.starPatternDir;
|
|
iName = "XStar_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
else if (hasSignalKeyBar)
|
|
{
|
|
//
|
|
iDir = structure.risingPatternDir;
|
|
iName = "XRising_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
else if (hasRisingPattern)
|
|
{
|
|
//
|
|
iDir = structure.piercingPatternDir;
|
|
iName = "XPiercing_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
else if (hasPiercingPattern)
|
|
{
|
|
//
|
|
iDir = structure.signalKeyBarPatternDir;
|
|
iName = "XSignalKey_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
|
|
//
|
|
isBullish = IsSpecifiedBullish(iDir);
|
|
isBearish = IsSpecifiedBearish(iDir);
|
|
|
|
//
|
|
// Retrieve Price Type for Validate ...
|
|
iPriceType = isBullish
|
|
? X_PRICE_DOWN
|
|
: X_PRICE_UP;
|
|
iPriceEdgeType = isBullish
|
|
? X_PRICE_LOW
|
|
: X_PRICE_HIGH;
|
|
|
|
//
|
|
iPrice = bar.GetPrice(iPriceType);
|
|
iPriceEdge = bar.GetPrice(iPriceEdgeType);
|
|
|
|
//
|
|
// Validate Calculations ...
|
|
has = HasDirection(iDir) &&
|
|
(isBullish ||
|
|
isBearish) &&
|
|
NotEmptyZero(iPrice) &&
|
|
NotEmptyZero(iPriceEdge) &&
|
|
iPrice != iPriceEdge;
|
|
if (!has)
|
|
{
|
|
//
|
|
isBullish = false;
|
|
isBearish = false;
|
|
iDir = X_DIRECTION_NONE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Petterns Happens ...
|
|
// Chekc Bullish or Bearish Starter Conditions Exists ...
|
|
has = HasDirection(iDir);
|
|
if (has)
|
|
{
|
|
//
|
|
// Do Conditions Validating ...
|
|
|
|
//
|
|
// Retrieve MA Band for Validation ...
|
|
double iMABandUpper = fimaConditions.maBandUpperBuffer[cIdx];
|
|
double iMABandLower = fimaConditions.maBandLowerBuffer[cIdx];
|
|
|
|
//
|
|
// Validate ...
|
|
|
|
//
|
|
// Validate by Edge Price ...
|
|
has = isBullish
|
|
? iPriceEdge < iMABandLower
|
|
: iPriceEdge > iMABandUpper;
|
|
|
|
//
|
|
// Validate by Body Price ...
|
|
// has = isBullish
|
|
// ? iPrice < iMABandLower
|
|
// : iPrice > iMABandUpper;
|
|
if (!has)
|
|
{
|
|
//
|
|
isBullish = false;
|
|
isBearish = false;
|
|
iDir = X_DIRECTION_NONE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
// Detect Support and Resistances ...
|
|
// and Validate Price based on it's ...
|
|
has = HasDirection(iDir);
|
|
if (has)
|
|
{
|
|
//
|
|
// Validate Positions Support and Resistance Zone ...
|
|
int insideZoneIDX = -1;
|
|
has = has &&
|
|
(isBullish
|
|
? HasInside(
|
|
insideZoneIDX,
|
|
bar,
|
|
supports //
|
|
)
|
|
: HasInside(
|
|
insideZoneIDX,
|
|
bar,
|
|
resistances //
|
|
));
|
|
|
|
//
|
|
// Validate Selected Inside Zone ...
|
|
// whith Bars Edge ...
|
|
has = IsValidIndex(insideZoneIDX);
|
|
if (has)
|
|
{
|
|
//
|
|
if (isBullish)
|
|
{
|
|
iZone = supports[insideZoneIDX];
|
|
}
|
|
else
|
|
{
|
|
iZone = resistances[insideZoneIDX];
|
|
}
|
|
|
|
//
|
|
has = isBullish
|
|
? bar.high > supports[insideZoneIDX].upper
|
|
: bar.low < resistances[insideZoneIDX].lower;
|
|
if (!has)
|
|
{
|
|
//
|
|
isBullish = false;
|
|
isBearish = false;
|
|
iDir = X_DIRECTION_NONE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
isBullish = false;
|
|
isBearish = false;
|
|
iDir = X_DIRECTION_NONE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Checking Liquidities ...
|
|
|
|
//
|
|
// Do all Draws Here ...
|
|
bool canDraw = true;
|
|
if (canDraw)
|
|
{
|
|
//
|
|
int iWidth = 2;
|
|
XPOIStyle iStyle;
|
|
XCBoxObject *iBoxObj = NULL;
|
|
color iClr = isBullish
|
|
? clrYellow
|
|
: clrDarkOrange;
|
|
|
|
//
|
|
// Supports ...
|
|
has = HasChild(supports);
|
|
if (has)
|
|
{
|
|
//
|
|
count = ArraySize(supports);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = poiDrawer.DrawBox(
|
|
supports[i],
|
|
iBoxObj,
|
|
true, // Ignore At ...
|
|
supports[i].type // Name ...
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
poiDrawer.GetBoxStyle(
|
|
iStyle,
|
|
supports[i].dir //
|
|
);
|
|
|
|
//
|
|
poiDrawer.ApplyBoxStyle(
|
|
iBoxObj,
|
|
iStyle //
|
|
);
|
|
}
|
|
|
|
//
|
|
iStyle.Clean();
|
|
ZeroMemory(iBoxObj);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Resistances ...
|
|
has = HasChild(resistances);
|
|
if (has)
|
|
{
|
|
//
|
|
count = ArraySize(resistances);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = poiDrawer.DrawBox(
|
|
resistances[i],
|
|
iBoxObj,
|
|
true, // Ignore At ...
|
|
resistances[i].type // Name ...
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
poiDrawer.GetBoxStyle(
|
|
iStyle,
|
|
resistances[i].dir //
|
|
);
|
|
|
|
//
|
|
poiDrawer.ApplyBoxStyle(
|
|
iBoxObj,
|
|
iStyle //
|
|
);
|
|
}
|
|
|
|
//
|
|
iStyle.Clean();
|
|
ZeroMemory(iBoxObj);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Selected Zone ...
|
|
has = iZone.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
has = poiDrawer.DrawBox(
|
|
iZone,
|
|
iBoxObj,
|
|
true, // Ignore At ...
|
|
iZone.type // Name ...
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
poiDrawer.GetBoxStyle(
|
|
iStyle,
|
|
iZone.dir //
|
|
);
|
|
|
|
//
|
|
iStyle.clr = iClr;
|
|
iStyle.width = iWidth;
|
|
|
|
//
|
|
poiDrawer.ApplyBoxStyle(
|
|
iBoxObj,
|
|
iStyle //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// TrendLines ...
|
|
|
|
//
|
|
// Pivots ...
|
|
|
|
//
|
|
has = HasChild(pvPivots);
|
|
if (has)
|
|
{
|
|
//
|
|
CArrayObj *drawnPivots = new CArrayObj();
|
|
count = poiDrawer.DrawPivots(
|
|
pvPivots,
|
|
drawnPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
has = HasChild(zgPivots);
|
|
if (has)
|
|
{
|
|
//
|
|
CArrayObj *drawnPivots = new CArrayObj();
|
|
count = poiDrawer.DrawPivots(
|
|
zgPivots,
|
|
drawnPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Patterns Bar ...
|
|
has = HasDirection(iDir);
|
|
if (has)
|
|
{
|
|
//
|
|
int iCode = 159;
|
|
ENUM_ARROW_ANCHOR iAnchor = isBullish
|
|
? ANCHOR_TOP
|
|
: ANCHOR_BOTTOM;
|
|
|
|
//
|
|
XCBarArrowObject *iPatternObj;
|
|
has = poiDrawer.DrawBarArrow(
|
|
bar,
|
|
iPatternObj,
|
|
iPriceType,
|
|
iCode,
|
|
iClr,
|
|
iWidth,
|
|
iAnchor,
|
|
iName,
|
|
true, // Ignore Bar Tag ...
|
|
10 // Threshold ...
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Signal Founded ...
|
|
has = HasDirection(iDir);
|
|
|
|
//
|
|
if (has)
|
|
{
|
|
Print("a Valid ", ToXString(iDir), " Pattern Exists ...");
|
|
}
|
|
|
|
//
|
|
if (has)
|
|
{
|
|
//
|
|
// TODO: Provided SL ...
|
|
double _point = GetPoints(bar.symbol);
|
|
double slAddition = 5 * _point;
|
|
double slPrice =
|
|
isBullish
|
|
? iZone.lower - slAddition
|
|
: iZone.upper + slAddition;
|
|
|
|
//
|
|
// Prepare Founded Signal ...
|
|
XTarget targets[];
|
|
has = PrepareSignal(
|
|
signal,
|
|
iDir,
|
|
targets,
|
|
0, // Use Default R2R ...
|
|
slPrice, // Provided Price for SL ...
|
|
0 // Specified Risk in Point ....
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
// Notify On Signal Event ...
|
|
NotifySignalEventListeners(signal);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
bar.Clean();
|
|
iZone.Clean();
|
|
signal.Clean();
|
|
structure.Clean();
|
|
fimaConditions.Clean();
|
|
SpecifiedClean(pvPivots);
|
|
SpecifiedClean(zgPivots);
|
|
SpecifiedClean(supports);
|
|
SpecifiedClean(resistances);
|
|
}
|
|
|
|
/**
|
|
* Processing New Bar ...
|
|
*
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
*/
|
|
virtual void ProcessNewBar(int barIndex = 0)
|
|
{
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
|
|
//
|
|
// Update Helper ...
|
|
fimaHelper.Update(barIndex);
|
|
|
|
//
|
|
XOHCL bar;
|
|
XSignal signal;
|
|
XBoxZone iZone;
|
|
int count = 0;
|
|
bool has = false;
|
|
int cIdx = 0;
|
|
int pIdx = cIdx + 1;
|
|
string iName = NULL;
|
|
XBoxZone supports[];
|
|
XBoxZone resistances[];
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
double iPrice = EMPTY_VALUE;
|
|
double iPriceEdge = EMPTY_VALUE;
|
|
XFIMAMarketStructure structure;
|
|
XFIMAConditions fimaConditions;
|
|
ENUM_X_PRICE iPriceType = X_PRICE_NONE;
|
|
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
|
|
ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE;
|
|
|
|
//
|
|
XPivot pvPivots[];
|
|
string pvTrendName = "XXIFMA2PVTrend";
|
|
CChartObjectTrend *pvTrendLine = NULL;
|
|
ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE;
|
|
|
|
//
|
|
XPivot zgPivots[];
|
|
string zgTrendName = "XFIMA2ZGTrend";
|
|
CChartObjectTrend *zgTrendLine = NULL;
|
|
ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Initialize Bar as CBar ...
|
|
has = bar.Init(
|
|
symbol,
|
|
period,
|
|
barIndex //
|
|
);
|
|
if (!has)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Retrieve Conditions ...
|
|
has = fimaHelper.GetConditions(
|
|
fimaConditions,
|
|
barIndex,
|
|
10 // Loopback ...
|
|
);
|
|
if (!has)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
fimaConditions.Clean();
|
|
|
|
//
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Analyse Market ...
|
|
poiDetector.AnalyseMarket(
|
|
bar,
|
|
structure,
|
|
analyserConfig //
|
|
);
|
|
|
|
//
|
|
// Collect Support and Resistance Zones and Validate by them ...
|
|
|
|
//
|
|
// PV Trend Line ...
|
|
bool hasPVAnalysis = structure.pvAnalysis.IsValid();
|
|
if (hasPVAnalysis)
|
|
{
|
|
//
|
|
// Support ...
|
|
XBoxZone supportBox;
|
|
has = structure.pvAnalysis.HasSupportBox(supportBox);
|
|
if (has)
|
|
{
|
|
//
|
|
supportBox.to = bar.time;
|
|
AddIfNotExists(
|
|
supportBox,
|
|
supports //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Resistance ...
|
|
XBoxZone resistanceBox;
|
|
has = structure.pvAnalysis.HasResistanceBox(resistanceBox);
|
|
if (has)
|
|
{
|
|
//
|
|
resistanceBox.to = bar.time;
|
|
AddIfNotExists(
|
|
resistanceBox,
|
|
supports //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Pivots ...
|
|
XPivot pivots[];
|
|
count = poiDetector.ExtractPVPivots(
|
|
pivots,
|
|
barIndex,
|
|
50 //
|
|
);
|
|
has = IsValidSize(count);
|
|
|
|
//
|
|
// Sort ...
|
|
Sort(
|
|
pivots,
|
|
X_SORT_BY_DATE,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
// Remove Newest ...
|
|
ArrayRemove(
|
|
pivots,
|
|
0,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
// Check Trend ...
|
|
if (has)
|
|
{
|
|
//
|
|
XPivot highs[];
|
|
int highsCount = ExtractPivots(
|
|
highs,
|
|
pivots,
|
|
X_PIVOT_TYPE_PEAK //
|
|
);
|
|
Sort(
|
|
highs,
|
|
X_SORT_BY_DATE,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
XPivot lows[];
|
|
int lowsCount = ExtractPivots(
|
|
lows,
|
|
pivots,
|
|
X_PIVOT_TYPE_VALE //
|
|
);
|
|
Sort(
|
|
lows,
|
|
X_SORT_BY_DATE,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
// Check Highs and Lows ...
|
|
has = IsValidSize(lowsCount) &&
|
|
IsValidSize(highsCount) &&
|
|
lowsCount >= 2 &&
|
|
highsCount >= 2;
|
|
if (has)
|
|
{
|
|
//
|
|
// Try to Get Market Strucutre ...
|
|
|
|
//
|
|
bool hasLowerHigh = highs[0].value < highs[1].value;
|
|
bool hasLowerLow = lows[0].value < lows[1].value;
|
|
|
|
//
|
|
bool hasHigherHigh = highs[0].value > highs[1].value;
|
|
bool hasHigherLow = lows[0].value > lows[1].value;
|
|
|
|
//
|
|
pvTrend =
|
|
(hasHigherHigh &&
|
|
hasHigherLow)
|
|
? X_DIRECTION_BULLISH
|
|
: (hasLowerHigh &&
|
|
hasLowerLow)
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
has = HasDirection(pvTrend);
|
|
if (has)
|
|
{
|
|
//
|
|
// Select Swings for Trend Line ...
|
|
XOHCL tmpBar;
|
|
int llIDX = -1;
|
|
int hhIDX = -1;
|
|
datetime toTime = NULL;
|
|
datetime fromTime = NULL;
|
|
double toPrice = EMPTY_VALUE;
|
|
color trendColor = CLR_NONE;
|
|
double fromPrice = EMPTY_VALUE;
|
|
if (IsSpecifiedBullish(pvTrend))
|
|
{
|
|
//
|
|
llIDX = GetLowest(lows);
|
|
hhIDX = GetHighest(lows);
|
|
|
|
//
|
|
trendColor = clrAqua;
|
|
|
|
//
|
|
toTime = lows[hhIDX].time;
|
|
toPrice = lows[hhIDX].value;
|
|
|
|
//
|
|
fromTime = lows[llIDX].time;
|
|
fromPrice = lows[llIDX].value;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
llIDX = GetLowest(highs);
|
|
hhIDX = GetHighest(highs);
|
|
|
|
//
|
|
trendColor = clrMagenta;
|
|
|
|
//
|
|
toTime = highs[llIDX].time;
|
|
toPrice = highs[llIDX].value;
|
|
|
|
//
|
|
fromTime = highs[hhIDX].time;
|
|
fromPrice = highs[hhIDX].value;
|
|
}
|
|
|
|
//
|
|
// Check Requirements for Trend ...
|
|
has =
|
|
NotEmptyZero(toPrice) &&
|
|
NotEmptyZero(fromPrice) &&
|
|
IsSpecifiedValid(toTime) &&
|
|
IsSpecifiedValid(fromTime);
|
|
if (has)
|
|
{
|
|
//
|
|
has = poiDrawer.DrawTrendLine(
|
|
fromPrice,
|
|
fromTime,
|
|
toPrice,
|
|
toTime,
|
|
pvTrendLine,
|
|
pvTrendName,
|
|
true // Ray Right ...
|
|
);
|
|
if (has)
|
|
{
|
|
pvTrendLine.Color(trendColor);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
tmpBar.Clean();
|
|
}
|
|
|
|
//
|
|
if (!has)
|
|
{
|
|
SpecifiedClean(pivots);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
SpecifiedClean(lows);
|
|
SpecifiedClean(highs);
|
|
}
|
|
|
|
//
|
|
// Draw Pivots ...
|
|
has = HasChild(pivots);
|
|
if (has)
|
|
{
|
|
//
|
|
Copy(
|
|
pivots,
|
|
pvPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
SpecifiedClean(pivots);
|
|
}
|
|
|
|
//
|
|
// ZigZag Trend Line ...
|
|
bool hasZGAnalysis = structure.zigzagAnalysis.IsValid();
|
|
if (hasZGAnalysis)
|
|
{
|
|
//
|
|
// Support ...
|
|
XBoxZone supportBox;
|
|
has = structure.zigzagAnalysis.HasSupportBox(supportBox);
|
|
if (has)
|
|
{
|
|
//
|
|
supportBox.to = bar.time;
|
|
AddIfNotExists(
|
|
supportBox,
|
|
supports //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Resistance ...
|
|
XBoxZone resistanceBox;
|
|
has = structure.zigzagAnalysis.HasResistanceBox(resistanceBox);
|
|
if (has)
|
|
{
|
|
//
|
|
resistanceBox.to = bar.time;
|
|
AddIfNotExists(
|
|
resistanceBox,
|
|
supports //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Pivots ...
|
|
XPivot pivots[];
|
|
count = poiDetector.ExtractZigZagPivots(
|
|
pivots,
|
|
barIndex,
|
|
10 //
|
|
);
|
|
has = IsValidSize(count);
|
|
|
|
//
|
|
// Sort ...
|
|
Sort(
|
|
pivots,
|
|
X_SORT_BY_DATE,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
// Remove Newest ...
|
|
ArrayRemove(
|
|
pivots,
|
|
0,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
// Check Trend ...
|
|
if (has)
|
|
{
|
|
//
|
|
XPivot highs[];
|
|
int highsCount = ExtractPivots(
|
|
highs,
|
|
pivots,
|
|
X_PIVOT_TYPE_PEAK //
|
|
);
|
|
Sort(
|
|
highs,
|
|
X_SORT_BY_DATE,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
XPivot lows[];
|
|
int lowsCount = ExtractPivots(
|
|
lows,
|
|
pivots,
|
|
X_PIVOT_TYPE_VALE //
|
|
);
|
|
Sort(
|
|
lows,
|
|
X_SORT_BY_DATE,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
|
|
//
|
|
// Check Highs and Lows ...
|
|
has = IsValidSize(lowsCount) &&
|
|
IsValidSize(highsCount) &&
|
|
lowsCount >= 2 &&
|
|
highsCount >= 2;
|
|
if (has)
|
|
{
|
|
//
|
|
// Try to Get Market Strucutre ...
|
|
|
|
//
|
|
bool hasLowerHigh = highs[0].value < highs[1].value;
|
|
bool hasLowerLow = lows[0].value < lows[1].value;
|
|
|
|
//
|
|
bool hasHigherHigh = highs[0].value > highs[1].value;
|
|
bool hasHigherLow = lows[0].value > lows[1].value;
|
|
|
|
//
|
|
zgTrend =
|
|
(hasHigherHigh &&
|
|
hasHigherLow)
|
|
? X_DIRECTION_BULLISH
|
|
: (hasLowerHigh &&
|
|
hasLowerLow)
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
has = HasDirection(zgTrend);
|
|
if (has)
|
|
{
|
|
//
|
|
// Select Swings for Trend Line ...
|
|
XOHCL tmpBar;
|
|
int llIDX = -1;
|
|
int hhIDX = -1;
|
|
datetime toTime = NULL;
|
|
datetime fromTime = NULL;
|
|
double toPrice = EMPTY_VALUE;
|
|
color trendColor = CLR_NONE;
|
|
double fromPrice = EMPTY_VALUE;
|
|
if (IsSpecifiedBullish(zgTrend))
|
|
{
|
|
//
|
|
llIDX = GetLowest(lows);
|
|
hhIDX = GetHighest(lows);
|
|
|
|
//
|
|
trendColor = clrAqua;
|
|
|
|
//
|
|
toTime = lows[hhIDX].time;
|
|
toPrice = lows[hhIDX].value;
|
|
|
|
//
|
|
fromTime = lows[llIDX].time;
|
|
fromPrice = lows[llIDX].value;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
llIDX = GetLowest(highs);
|
|
hhIDX = GetHighest(highs);
|
|
|
|
//
|
|
trendColor = clrMagenta;
|
|
|
|
//
|
|
toTime = highs[llIDX].time;
|
|
toPrice = highs[llIDX].value;
|
|
|
|
//
|
|
fromTime = highs[hhIDX].time;
|
|
fromPrice = highs[hhIDX].value;
|
|
}
|
|
|
|
//
|
|
// Check Requirements for Trend ...
|
|
has =
|
|
NotEmptyZero(toPrice) &&
|
|
NotEmptyZero(fromPrice) &&
|
|
IsSpecifiedValid(toTime) &&
|
|
IsSpecifiedValid(fromTime);
|
|
if (has)
|
|
{
|
|
//
|
|
has = poiDrawer.DrawTrendLine(
|
|
fromPrice,
|
|
fromTime,
|
|
toPrice,
|
|
toTime,
|
|
zgTrendLine,
|
|
zgTrendName,
|
|
true // Ray Right ...
|
|
);
|
|
if (has)
|
|
{
|
|
zgTrendLine.Color(trendColor);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
tmpBar.Clean();
|
|
}
|
|
|
|
//
|
|
if (!has)
|
|
{
|
|
SpecifiedClean(pivots);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
SpecifiedClean(lows);
|
|
SpecifiedClean(highs);
|
|
}
|
|
|
|
//
|
|
// Draw Pivots ...
|
|
has = HasChild(pivots);
|
|
if (has)
|
|
{
|
|
//
|
|
Copy(
|
|
pivots,
|
|
zgPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
SpecifiedClean(pivots);
|
|
}
|
|
|
|
//
|
|
// Support ...
|
|
bool hasSupport = structure.support.IsValid();
|
|
if (hasSupport)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
structure.support,
|
|
supports //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Resistance ...
|
|
bool hasResistance = structure.resistance.IsValid();
|
|
if (hasResistance)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
structure.resistance,
|
|
resistances //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Check Required Pattern Exists ...
|
|
bool hasPinnedBar = HasDirection(structure.pinnedDir);
|
|
bool hasEngulfedBar = HasDirection(structure.engulfedDir);
|
|
bool hasFlagPattern = HasDirection(structure.flagPatternDir);
|
|
bool hasStarPattern = HasDirection(structure.starPatternDir);
|
|
bool hasRisingPattern = HasDirection(structure.risingPatternDir);
|
|
bool hasPiercingPattern = HasDirection(structure.piercingPatternDir);
|
|
bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir);
|
|
|
|
//
|
|
// Check Bar Pattern Exists ...
|
|
// and Select Pattern Direction and Price and Price Type ...
|
|
has = hasPinnedBar ||
|
|
hasEngulfedBar ||
|
|
hasFlagPattern ||
|
|
hasStarPattern ||
|
|
hasSignalKeyBar ||
|
|
hasRisingPattern ||
|
|
hasPiercingPattern;
|
|
if (has)
|
|
{
|
|
//
|
|
if (hasPinnedBar)
|
|
{
|
|
//
|
|
iDir = structure.pinnedDir;
|
|
iName = "XPinned_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
else if (hasEngulfedBar)
|
|
{
|
|
//
|
|
iDir = structure.engulfedDir;
|
|
iName = "XEngulfed_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
else if (hasFlagPattern)
|
|
{
|
|
//
|
|
iDir = structure.flagPatternDir;
|
|
iName = "XFlag_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
else if (hasStarPattern)
|
|
{
|
|
//
|
|
iDir = structure.starPatternDir;
|
|
iName = "XStar_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
else if (hasSignalKeyBar)
|
|
{
|
|
//
|
|
iDir = structure.risingPatternDir;
|
|
iName = "XRising_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
else if (hasRisingPattern)
|
|
{
|
|
//
|
|
iDir = structure.piercingPatternDir;
|
|
iName = "XPiercing_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
else if (hasPiercingPattern)
|
|
{
|
|
//
|
|
iDir = structure.signalKeyBarPatternDir;
|
|
iName = "XSignalKey_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time));
|
|
}
|
|
|
|
//
|
|
isBullish = IsSpecifiedBullish(iDir);
|
|
isBearish = IsSpecifiedBearish(iDir);
|
|
|
|
//
|
|
// Retrieve Price Type for Validate ...
|
|
iPriceType = isBullish
|
|
? X_PRICE_DOWN
|
|
: X_PRICE_UP;
|
|
iPriceEdgeType = isBullish
|
|
? X_PRICE_LOW
|
|
: X_PRICE_HIGH;
|
|
|
|
//
|
|
iPrice = bar.GetPrice(iPriceType);
|
|
iPriceEdge = bar.GetPrice(iPriceEdgeType);
|
|
|
|
//
|
|
// Validate Calculations ...
|
|
has = HasDirection(iDir) &&
|
|
(isBullish ||
|
|
isBearish) &&
|
|
NotEmptyZero(iPrice) &&
|
|
NotEmptyZero(iPriceEdge) &&
|
|
iPrice != iPriceEdge;
|
|
if (!has)
|
|
{
|
|
//
|
|
isBullish = false;
|
|
isBearish = false;
|
|
iDir = X_DIRECTION_NONE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Strategy 1 ...
|
|
has = Strategy1HasSignal(
|
|
bar,
|
|
iZone,
|
|
iName,
|
|
supports,
|
|
resistances,
|
|
iDir,
|
|
fimaConditions,
|
|
structure //
|
|
);
|
|
|
|
//
|
|
// Do all Draws Here ...
|
|
bool canDraw = true;
|
|
if (canDraw && has)
|
|
{
|
|
//
|
|
int iWidth = 2;
|
|
XPOIStyle iStyle;
|
|
XCBoxObject *iBoxObj = NULL;
|
|
color iClr = isBullish
|
|
? clrYellow
|
|
: clrDarkOrange;
|
|
|
|
//
|
|
// Supports ...
|
|
has = HasChild(supports);
|
|
if (has)
|
|
{
|
|
//
|
|
count = ArraySize(supports);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = poiDrawer.DrawBox(
|
|
supports[i],
|
|
iBoxObj,
|
|
true, // Ignore At ...
|
|
supports[i].type // Name ...
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
poiDrawer.GetBoxStyle(
|
|
iStyle,
|
|
supports[i].dir //
|
|
);
|
|
|
|
//
|
|
poiDrawer.ApplyBoxStyle(
|
|
iBoxObj,
|
|
iStyle //
|
|
);
|
|
}
|
|
|
|
//
|
|
iStyle.Clean();
|
|
ZeroMemory(iBoxObj);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Resistances ...
|
|
has = HasChild(resistances);
|
|
if (has)
|
|
{
|
|
//
|
|
count = ArraySize(resistances);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = poiDrawer.DrawBox(
|
|
resistances[i],
|
|
iBoxObj,
|
|
true, // Ignore At ...
|
|
resistances[i].type // Name ...
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
poiDrawer.GetBoxStyle(
|
|
iStyle,
|
|
resistances[i].dir //
|
|
);
|
|
|
|
//
|
|
poiDrawer.ApplyBoxStyle(
|
|
iBoxObj,
|
|
iStyle //
|
|
);
|
|
}
|
|
|
|
//
|
|
iStyle.Clean();
|
|
ZeroMemory(iBoxObj);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Selected Zone ...
|
|
has = iZone.IsValid();
|
|
if (has)
|
|
{
|
|
//
|
|
has = poiDrawer.DrawBox(
|
|
iZone,
|
|
iBoxObj,
|
|
true, // Ignore At ...
|
|
iZone.type // Name ...
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
poiDrawer.GetBoxStyle(
|
|
iStyle,
|
|
iZone.dir //
|
|
);
|
|
|
|
//
|
|
iStyle.clr = iClr;
|
|
iStyle.width = iWidth;
|
|
|
|
//
|
|
poiDrawer.ApplyBoxStyle(
|
|
iBoxObj,
|
|
iStyle //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// TrendLines ...
|
|
|
|
//
|
|
// Pivots ...
|
|
|
|
//
|
|
has = HasChild(pvPivots);
|
|
if (has)
|
|
{
|
|
//
|
|
CArrayObj *drawnPivots = new CArrayObj();
|
|
count = poiDrawer.DrawPivots(
|
|
pvPivots,
|
|
drawnPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
has = HasChild(zgPivots);
|
|
if (has)
|
|
{
|
|
//
|
|
CArrayObj *drawnPivots = new CArrayObj();
|
|
count = poiDrawer.DrawPivots(
|
|
zgPivots,
|
|
drawnPivots //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Patterns Bar ...
|
|
has = HasDirection(iDir);
|
|
if (has)
|
|
{
|
|
//
|
|
int iCode = 159;
|
|
ENUM_ARROW_ANCHOR iAnchor = isBullish
|
|
? ANCHOR_TOP
|
|
: ANCHOR_BOTTOM;
|
|
|
|
//
|
|
XCBarArrowObject *iPatternObj;
|
|
has = poiDrawer.DrawBarArrow(
|
|
bar,
|
|
iPatternObj,
|
|
iPriceType,
|
|
iCode,
|
|
iClr,
|
|
iWidth,
|
|
iAnchor,
|
|
iName,
|
|
true, // Ignore Bar Tag ...
|
|
10 // Threshold ...
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
if (has)
|
|
{
|
|
Print("a Valid ", ToXString(iDir), " Pattern Exists ...");
|
|
}
|
|
|
|
//
|
|
if (has)
|
|
{
|
|
//
|
|
// TODO: Provided SL ...
|
|
double _point = GetPoints(bar.symbol);
|
|
double slAddition = 5 * _point;
|
|
double slPrice =
|
|
isBullish
|
|
? iZone.lower - slAddition
|
|
: iZone.upper + slAddition;
|
|
|
|
//
|
|
// Prepare Founded Signal ...
|
|
XTarget targets[];
|
|
has = PrepareSignal(
|
|
signal,
|
|
iDir,
|
|
targets,
|
|
0, // Use Default R2R ...
|
|
slPrice, // Provided Price for SL ...
|
|
0 // Specified Risk in Point ....
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
// Notify On Signal Event ...
|
|
NotifySignalEventListeners(signal);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
bar.Clean();
|
|
iZone.Clean();
|
|
signal.Clean();
|
|
structure.Clean();
|
|
fimaConditions.Clean();
|
|
SpecifiedClean(pvPivots);
|
|
SpecifiedClean(zgPivots);
|
|
SpecifiedClean(supports);
|
|
SpecifiedClean(resistances);
|
|
}
|
|
|
|
/**
|
|
* Check Guards Based on MarketConditions ...
|
|
*
|
|
* @param guards: XGuard[]
|
|
* @param barIndex: int
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int virtual CheckForGuard(
|
|
XGuard &guards[],
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
SpecifiedClean(guards);
|
|
|
|
//
|
|
result = ArraySize(guards);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Private ...
|
|
private:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
// Implementing Strategies ...
|
|
|
|
/**
|
|
* Validate a Pattern based on MA Band ...
|
|
*
|
|
* @param bar: XOHCL, reference to Pattern Bar ...
|
|
* @param patternName: string, detected pattern's name ...
|
|
* @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ...
|
|
* @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ValidatePatternBasedOnMABand(
|
|
XOHCL &bar,
|
|
string patternName,
|
|
ENUM_X_DIRECTION patternDir,
|
|
XFIMAConditions &fimaConditions //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
IsXValid(patternName) &&
|
|
HasDirection(patternDir) &&
|
|
fimaConditions.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Define Requirements ...
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
double iPrice = EMPTY_VALUE;
|
|
double iPriceEdge = EMPTY_VALUE;
|
|
ENUM_X_PRICE iPriceType = X_PRICE_NONE;
|
|
ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE;
|
|
|
|
//
|
|
// Calculating Price and Price Types ...
|
|
|
|
//
|
|
isBullish = IsXBullish(patternDir);
|
|
isBearish = IsXBearish(patternDir);
|
|
|
|
//
|
|
iPriceType = isBullish
|
|
? X_PRICE_DOWN
|
|
: X_PRICE_UP;
|
|
|
|
//
|
|
iPriceEdgeType = isBullish
|
|
? X_PRICE_LOW
|
|
: X_PRICE_HIGH;
|
|
|
|
//
|
|
iPrice = bar.GetPrice(iPriceType);
|
|
iPriceEdge = bar.GetPrice(iPriceEdgeType);
|
|
|
|
//
|
|
// Validate ...
|
|
result =
|
|
NotEmptyZero(iPrice) &&
|
|
IsXValid(iPriceType) &&
|
|
NotEmptyZero(iPriceEdge) &&
|
|
IsXValid(iPriceEdgeType) &&
|
|
((isBullish && !isBearish) ||
|
|
(isBearish && !isBullish));
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Validate Pattern based on MA Band ...
|
|
|
|
//
|
|
// Retrieve MA Band for Validation ...
|
|
double iMABandUpper = fimaConditions.maBandUpperBuffer[cIdx];
|
|
double iMABandLower = fimaConditions.maBandLowerBuffer[cIdx];
|
|
|
|
//
|
|
// Validate by Edge Price ...
|
|
result = isBullish
|
|
? iPriceEdge < iMABandLower
|
|
: iPriceEdge > iMABandUpper;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Pattern Has Signal Based on Strategy 1 ...
|
|
*
|
|
* @param bar: XOHCL, reference to Pattern Bar ...
|
|
* @param iZone: XBoxZone, reference to holds affected zone ...
|
|
* @param patternName: string, detected pattern's name ...
|
|
* @param supports: XBoxZone, array reference to Provide Exists Supports ...
|
|
* @param resistances: XBoxZone, array reference to Provide Exists Resistances ...
|
|
* @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ...
|
|
* @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ...
|
|
* @param fimaMarketStructure: XFIMAMarketStructure, refrence to Provides Market Structure ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Strategy1HasSignal(
|
|
XOHCL &bar,
|
|
XBoxZone &iZone,
|
|
string patternName,
|
|
XBoxZone &supports[],
|
|
XBoxZone &resistances[],
|
|
ENUM_X_DIRECTION patternDir,
|
|
XFIMAMarketStructure &structure,
|
|
XFIMAConditions &fimaConditions,
|
|
XFIMAMarketStructure &fimaMarketStructure //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
iZone.Clean();
|
|
|
|
//
|
|
// Validate ...
|
|
result = bar.IsValid() &&
|
|
IsXValid(patternName) &&
|
|
HasDirection(patternDir) &&
|
|
fimaConditions.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Validate Pattern Based on MA Band ...
|
|
result = ValidatePatternBasedOnMABand(
|
|
bar,
|
|
patternName,
|
|
patternDir,
|
|
fimaConditions //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Affected Zone ...
|
|
// Select a Support or Resistance ...
|
|
int insideZoneIDX = -1;
|
|
result =
|
|
(isBullish
|
|
? HasInside(
|
|
insideZoneIDX,
|
|
bar,
|
|
supports //
|
|
)
|
|
: HasInside(
|
|
insideZoneIDX,
|
|
bar,
|
|
resistances //
|
|
));
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Filling Affected Zone ...
|
|
// and Validate it ...
|
|
if (IsXBullish(patternDir))
|
|
{
|
|
iZone = supports[insideZoneIDX];
|
|
}
|
|
else if (IsXBearish(patternDir))
|
|
{
|
|
iZone = resistances[insideZoneIDX];
|
|
}
|
|
result = iZOne.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Validate affected Zone based on Pattern's Bar ...
|
|
result = IsXBullish(patternDir)
|
|
? bar.high > iZZone.upper
|
|
: IsXBearish(patternDir)
|
|
? bar.low < iZone.lower
|
|
: false;
|
|
//
|
|
// Cleanup Resources ...
|
|
if (!result)
|
|
{
|
|
iZone.Clean();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Pattern Has Signal Based on Strategy 1 ...
|
|
*
|
|
* @param bar: XOHCL, reference to Pattern Bar ...
|
|
* @param iZone: XBoxZone, reference to holds affected zone ...
|
|
* @param patternName: string, detected pattern's name ...
|
|
* @param supports: XBoxZone, array reference to Provide Exists Supports ...
|
|
* @param resistances: XBoxZone, array reference to Provide Exists Resistances ...
|
|
* @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ...
|
|
* @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ...
|
|
* @param fimaMarketStructure: XFIMAMarketStructure, refrence to Provides Market Structure ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Strategy2HasSignal(
|
|
XOHCL &bar,
|
|
XBoxZone &iZone,
|
|
string patternName,
|
|
XBoxZone &supports[],
|
|
XBoxZone &resistances[],
|
|
ENUM_X_DIRECTION patternDir,
|
|
XFIMAMarketStructure &structure,
|
|
XFIMAConditions &fimaConditions,
|
|
XFIMAMarketStructure &fimaMarketStructure //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
|
|
//
|
|
// Validate ...
|
|
|
|
//
|
|
// Do Detection ...
|
|
|
|
//
|
|
// Validate result ...
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
// |