2147 lines
63 KiB
Plaintext
2147 lines
63 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Class
|
|
// -------------------------------------------------
|
|
// Name: XCXCATBEASignaller ...
|
|
// Description: Class for XCATBEA Signaller ...
|
|
//
|
|
//
|
|
// 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 XCXCATBEASignaller Class"
|
|
#property strict
|
|
|
|
//
|
|
// Imports ...
|
|
#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5"
|
|
#include "../../Classes/x-saherelm.x-guard.class.mq5"
|
|
#include "../../Helpers/x-saherelm.x121.xcatb.helper.mq5"
|
|
#include "../Classes/xcatbea.x-poi.detector.class.mq5"
|
|
#include "../Classes/xcatbea.x-poi.drawer.class.mq5"
|
|
#include "../Libraries/xcatbea.lib.mq5"
|
|
#include "../Libraries/xcatbea.signaller.lib.mq5"
|
|
#include "../Libraries/xcatbea.x-poi.extensions.lib.mq5"
|
|
|
|
//
|
|
// Definitions ...
|
|
|
|
//
|
|
// Configure Signalelrs ...
|
|
struct XCATBEASignallingConfigs
|
|
{
|
|
//
|
|
// Signalling Method ...
|
|
bool allowSignallingBasedOnConditions; // Signalling Based on Market Conditions
|
|
bool allowSignallingBasedOnTriggerBlocks; // Signalling Based on Trigger Blocks
|
|
bool allowSignallingBasedOnTriggerBlocksInsideOther; // Signalling Based on Trigger Blocks Seccond inputs
|
|
|
|
//
|
|
// Others ...
|
|
bool applyValidateAndFilterOnSelectInsideOthers; // Select Trigger Blocks by Applying Validations and Filterss
|
|
bool secondsTriggersSLUsingFirstTriggerBlock; // Use First Trigger Block for SL of Seconds Trigger Block Signalss
|
|
|
|
//
|
|
// Market Conditions Signall Providers ...
|
|
bool allowSignallingConditions1; // Allow Market Conditions Signaller to Using Sar Starter Signals
|
|
bool allowSignallingConditions2; // Allow Market Conditions Signaller to Using Trend Starter Signals
|
|
bool allowSignallingConditions3; // Allow Market Conditions Signaller to Using Delta Starter Signals
|
|
bool allowSignallingConditions4; // Allow Market Conditions Signaller to Using Volume Starter Signals
|
|
bool allowSignallingConditions5; // Allow Market Conditions Signaller to Using Signal Bar Starter Signals
|
|
bool allowSignallingConditions6; // Allow Market Conditions Signaller to Using HK Signal Bar Starter Signals
|
|
|
|
//
|
|
// Constructor ...
|
|
XCATBEASignallingConfigs()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
// Cleaning Up ...
|
|
void Clean()
|
|
{
|
|
//
|
|
allowSignallingBasedOnConditions = false;
|
|
allowSignallingBasedOnTriggerBlocks = false;
|
|
allowSignallingBasedOnTriggerBlocksInsideOther = false;
|
|
|
|
//
|
|
secondsTriggersSLUsingFirstTriggerBlock = false;
|
|
applyValidateAndFilterOnSelectInsideOthers = false;
|
|
|
|
//
|
|
allowSignallingConditions1 = false;
|
|
allowSignallingConditions2 = false;
|
|
allowSignallingConditions3 = false;
|
|
allowSignallingConditions4 = false;
|
|
allowSignallingConditions5 = false;
|
|
allowSignallingConditions6 = false;
|
|
}
|
|
};
|
|
|
|
//
|
|
struct XCATBEASignallerInputs
|
|
{
|
|
//
|
|
// Pros ...
|
|
string symbol;
|
|
string provider;
|
|
bool allowDraws;
|
|
bool allowGuards;
|
|
int riskToRewardRatio;
|
|
ENUM_TIMEFRAMES period;
|
|
double slATRMultiplier;
|
|
X121XCatbInputs catbInputs;
|
|
XTriggerBlockFilters filters;
|
|
XTriggerBlockValidationRules validations;
|
|
XCATBEASignallingConfigs signallerConfigs;
|
|
|
|
//
|
|
// Constructor(s) ...
|
|
XCATBEASignallerInputs()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
// Cleanup ...
|
|
void Clean()
|
|
{
|
|
//
|
|
symbol = NULL;
|
|
period = NULL;
|
|
provider = NULL;
|
|
filters.Clean();
|
|
catbInputs.Clean();
|
|
allowDraws = false;
|
|
validations.Clean();
|
|
allowGuards = false;
|
|
slATRMultiplier = 0;
|
|
riskToRewardRatio = 0;
|
|
signallerConfigs.Clean();
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
IsValid(symbol) &&
|
|
IsValid(period) &&
|
|
IsValid(provider) &&
|
|
catbInputs.IsValid() &&
|
|
riskToRewardRatio > 0;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
//
|
|
// Implementations ...
|
|
class XCXCATBEASignaller : XCBase
|
|
{
|
|
//
|
|
// Public ...
|
|
public:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
bool allowSignallingBasedOnConditions; // Signalling Based on Market Conditions
|
|
bool allowSignallingBasedOnTriggerBlocks; // Signalling Based on Trigger Blocks
|
|
bool allowSignallingBasedOnTriggerBlocksInsideOther; // Signalling Based on Trigger Blocks Seccond inputs
|
|
|
|
//
|
|
bool secondsTriggersSLUsingFirstTriggerBlock; // Use First Trigger Block for SL of Seconds Trigger Block Signalss
|
|
bool applyValidateAndFilterOnSelectInsideOthers; // Select Trigger Blocks by Applying Validations and Filterss
|
|
|
|
//
|
|
// Market Conditions Signall Providers ...
|
|
bool allowSignallingConditions1; // Allow Market Conditions Signaller to Using Sar Starter Signals
|
|
bool allowSignallingConditions2; // Allow Market Conditions Signaller to Using Trend Starter Signals
|
|
bool allowSignallingConditions3; // Allow Market Conditions Signaller to Using Delta Starter Signals
|
|
bool allowSignallingConditions4; // Allow Market Conditions Signaller to Using Volume Starter Signals
|
|
bool allowSignallingConditions5; // Allow Market Conditions Signaller to Using Signal Bar Starter Signals
|
|
bool allowSignallingConditions6; // Allow Market Conditions Signaller to Using HK Signal Bar Starter Signals
|
|
|
|
//
|
|
bool allowDraws; // Allow Draws or not ...
|
|
bool allowGuards; // Allow Guards or not ...
|
|
int riskToRewardRatio; // Signals R2R ...
|
|
double slATRMultiplier; // SL ATR Multiplier ...
|
|
|
|
//
|
|
XBarTracker barTraker; // Bar Tracker ...
|
|
XCX121XCatbHelper *helper; // XCATB Helper Class instance ...
|
|
XCBarAnalyser *barAnalyser; // Bar Analyser ...
|
|
XCXCATBEAPOIDrawer *drawer; // POI Drawer ...
|
|
XTriggerBlockFilters filters; // Trigger Block Filters ...
|
|
XCXCATBEAPOIDetector *detector; // POI Detector ...
|
|
XTriggerBlockValidationRules validations; // Trigger Block Validations ...
|
|
|
|
//
|
|
XBoxZone cPeak; // Current Peak ...
|
|
XBoxZone cVale; // Current Vale ...
|
|
XBoxZone unavailableZones[]; // Un Available Zones ...
|
|
XTriggerBlock cTriggerBlock; // Currently Selected Trigger Block ...
|
|
XTriggerBlock triggerBlocks[]; // Founded Trigger Blocks ...
|
|
bool waitsUntilPeakInvalidate; // Waits Until Peak Invalidate ...
|
|
bool waitsUntilValeInvalidate; // Waits Until Vale Invalidate ...
|
|
XTriggerBlock cInsideTriggerBlock; // a TriggerBlock which Currently Selected Trigger Block is Inside it ...
|
|
|
|
//
|
|
XCATBEAStrategyConditions mConditions;
|
|
XCATBEAStrategyConditions mConditionsCollection[];
|
|
|
|
//
|
|
// Constructor ...
|
|
XCXCATBEASignaller(XCATBEASignallerInputs &inputs)
|
|
{
|
|
Init(inputs);
|
|
}
|
|
|
|
//
|
|
// Deconstructor ...
|
|
~XCXCATBEASignaller()
|
|
{
|
|
DeInit();
|
|
}
|
|
|
|
//
|
|
// Properties ...
|
|
|
|
//
|
|
string GetSymbol()
|
|
{
|
|
return symbol;
|
|
}
|
|
|
|
//
|
|
string GetProvider()
|
|
{
|
|
return provider;
|
|
}
|
|
|
|
//
|
|
ENUM_TIMEFRAMES GetPeriod()
|
|
{
|
|
return period;
|
|
}
|
|
|
|
//
|
|
double GetR2R()
|
|
{
|
|
return riskToRewardRatio;
|
|
}
|
|
|
|
//
|
|
// Tick Analyser ...
|
|
|
|
/**
|
|
* Process Tick ...
|
|
*/
|
|
void ProcessTick(
|
|
XPosition &positions[],
|
|
XGuard &guards[],
|
|
XCATBEAStrategyConditions &conditions,
|
|
bool isActiveSession = true //
|
|
)
|
|
{
|
|
//
|
|
Clean(guards);
|
|
conditions.Clean();
|
|
|
|
//
|
|
XOHCL bar;
|
|
int count = 0;
|
|
bool has = false;
|
|
int barIndex = 0;
|
|
cTriggerBlock.Clean();
|
|
cInsideTriggerBlock.Clean();
|
|
|
|
//
|
|
// Check Guards ...
|
|
has = DetectGuards(
|
|
guards,
|
|
positions,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
// Check Triggered Conditions ...
|
|
has = HasChild(mConditionsCollection);
|
|
if (has)
|
|
{
|
|
//
|
|
int selectedIDX = -1;
|
|
count = ArraySize(mConditionsCollection);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
// Select indexed Conditions ...
|
|
XCATBEAStrategyConditions iConditions = mConditionsCollection[i];
|
|
|
|
//
|
|
// Check Conditions Triggered ...
|
|
has = DetectSignalTrigger(
|
|
iConditions,
|
|
barIndex //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
selectedIDX = i;
|
|
conditions = iConditions;
|
|
iConditions.Clean();
|
|
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
// When Setup Invalidated
|
|
// Signaller Clean Conditions ...
|
|
if (!has &&
|
|
!iConditions.IsValid())
|
|
{
|
|
//
|
|
selectedIDX = i;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
iConditions.Clean();
|
|
}
|
|
|
|
//
|
|
// Check Can Trigger ...
|
|
has = IsValidIndex(selectedIDX) &&
|
|
conditions.IsValid() &&
|
|
conditions.IsSetuped() &&
|
|
conditions.CanTrigger();
|
|
if (has)
|
|
{
|
|
//
|
|
ArrayRemove(
|
|
mConditionsCollection,
|
|
selectedIDX,
|
|
1 //
|
|
);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Check Selected Index for Invalid Conditions ...
|
|
if (IsValidIndex(selectedIDX))
|
|
{
|
|
//
|
|
// Remove Invalidated Conditions ...
|
|
ArrayRemove(
|
|
mConditionsCollection,
|
|
selectedIDX,
|
|
1 //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Cleanup Resource ...
|
|
conditions.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Bar Processing ...
|
|
if (!barTraker.CanProcessBar())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Initialize Bar ...
|
|
bar.Init(
|
|
symbol,
|
|
period,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
// Detect POI(s) ...
|
|
detector.Detect(barIndex);
|
|
|
|
//
|
|
// Validate POI(s) ...
|
|
detector.Validate(
|
|
unavailableZones,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
// Check Helper Last Changes ...
|
|
helper.Check(barIndex);
|
|
|
|
//
|
|
// Draw POI(s) ...
|
|
if (allowDraws)
|
|
{
|
|
// drawer.Draw(bar.time);
|
|
}
|
|
|
|
//
|
|
// Detect Trigger Blocks and Collect them ...
|
|
XTriggerBlock iTriggerBlock;
|
|
X121XCatbConditions iConditions;
|
|
XTriggerBlockFilters iFilters;
|
|
XTriggerBlockValidationRules iValidations;
|
|
if (applyValidateAndFilterOnSelectInsideOthers)
|
|
{
|
|
//
|
|
// Validations ...
|
|
iValidations.forceHasSwing = validations.forceHasSwing;
|
|
iValidations.forceOBBarType = validations.forceOBBarType;
|
|
iValidations.forceFVGBarType = validations.forceFVGBarType;
|
|
iValidations.maxAllowedRange = validations.maxAllowedRange;
|
|
iValidations.minAllowedRange = validations.minAllowedRange;
|
|
iValidations.minRequiredOBBar = validations.minRequiredOBBar;
|
|
iValidations.liquidityLoopback = validations.liquidityLoopback;
|
|
iValidations.forceHasFLiquidity = validations.forceHasFLiquidity;
|
|
iValidations.forceHasRLiquidity = validations.forceHasRLiquidity;
|
|
iValidations.validateGapSequence = validations.validateGapSequence;
|
|
iValidations.minAllowedBlockLength = validations.minAllowedBlockLength;
|
|
iValidations.validateBlockEdgeBreakout = validations.validateBlockEdgeBreakout;
|
|
|
|
//
|
|
// Clone Filters and Validations ...
|
|
iFilters.bosLoopback = filters.bosLoopback;
|
|
iFilters.filterBasedOnKI = filters.filterBasedOnKI;
|
|
iFilters.filterBasedOnPV = filters.filterBasedOnPV;
|
|
iFilters.filterBasedOnSar = filters.filterBasedOnSar;
|
|
iFilters.filterBasedOnRSI = filters.filterBasedOnRSI;
|
|
iFilters.filterBasedOnADX = filters.filterBasedOnADX;
|
|
iFilters.filterBasedOnATR = filters.filterBasedOnATR;
|
|
iFilters.forceSarSwitched = filters.forceSarSwitched;
|
|
iFilters.forceHasTrendDir = filters.forceHasTrendDir;
|
|
iFilters.filterBasedOnTrend = filters.filterBasedOnTrend;
|
|
iFilters.filterBasedOnDelta = filters.filterBasedOnDelta;
|
|
iFilters.forceSarOnBothSide = filters.forceSarOnBothSide;
|
|
iFilters.forceHasTrendPlace = filters.forceHasTrendPlace;
|
|
iFilters.forceSarHasBreakout = filters.forceSarHasBreakout;
|
|
iFilters.filterBasedOnVolume = filters.filterBasedOnVolume;
|
|
iFilters.forceHasRSITrending = filters.forceHasRSITrending;
|
|
iFilters.forceHasRSIVPattern = filters.forceHasRSIVPattern;
|
|
iFilters.forceHasRSICrossing = filters.forceHasRSICrossing;
|
|
iFilters.forceHasADXTrending = filters.forceHasADXTrending;
|
|
iFilters.forceHasADXCrossing = filters.forceHasADXCrossing;
|
|
iFilters.forceHasATRTrending = filters.forceHasATRTrending;
|
|
iFilters.forceHasATRBreakout = filters.forceHasATRBreakout;
|
|
iFilters.forceHasTrendChange = filters.forceHasTrendChange;
|
|
iFilters.forceHasTrendTrending = filters.forceHasTrendTrending;
|
|
iFilters.forceHasTrendRejection = filters.forceHasTrendRejection;
|
|
iFilters.filterBasedOnSignalBar = filters.filterBasedOnSignalBar;
|
|
iFilters.forceHasTrendLineInside = filters.forceHasTrendLineInside;
|
|
iFilters.forceSarHasReversalSide = filters.forceSarHasReversalSide;
|
|
iFilters.filterBasedOnHKSignalBar = filters.filterBasedOnHKSignalBar;
|
|
iFilters.forceHasTrendDirOnBothSide = filters.forceHasTrendDirOnBothSide;
|
|
}
|
|
has = DetectTriggerBlock(
|
|
helper,
|
|
barAnalyser,
|
|
iTriggerBlock,
|
|
iConditions,
|
|
iValidations,
|
|
iFilters,
|
|
barIndex,
|
|
10 // Loopback ...
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
// Add Trigger Block to Collection if not Exists ...
|
|
AddIfNotExists(
|
|
iTriggerBlock,
|
|
triggerBlocks //
|
|
);
|
|
}
|
|
iFilters.Clean();
|
|
iConditions.Clean();
|
|
iValidations.Clean();
|
|
iTriggerBlock.Clean();
|
|
|
|
//
|
|
// Draw Trigger Blocks ...
|
|
if (allowDraws)
|
|
{
|
|
//
|
|
// Handle To Updating ...
|
|
// datetime cTime = TimeCurrent();
|
|
// DrawTriggerBlocks(cTime);
|
|
}
|
|
|
|
//
|
|
// Here we Check Active Session ...
|
|
// and Prevent Moving forward if there is not
|
|
// Session actives ...
|
|
// for improvement Calculation Speeds ...
|
|
if (isActiveSession)
|
|
{
|
|
//
|
|
// Check Signal Setups ...
|
|
has = DetectSignalSetup(barIndex);
|
|
if (has)
|
|
{
|
|
//
|
|
barTraker.Waits();
|
|
|
|
//
|
|
AddConditionsIfNotExists();
|
|
|
|
//
|
|
mConditions.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
bar.Clean();
|
|
}
|
|
|
|
//
|
|
// Signalling Tools ...
|
|
|
|
/**
|
|
* Detect Setup Conditions based on Signalling ...
|
|
*
|
|
* @param maxAllowedSLDistanceInPoint: int, Max Allowed SL Distance in Points (if Bigger thn Zero Provided) ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectSignalSetup(int barIndex = 0)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize Args ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
|
|
//
|
|
// Update All Required Buffers ...
|
|
helper.Update(barIndex);
|
|
|
|
//
|
|
bool has = false;
|
|
datetime cTime = TimeCurrent();
|
|
|
|
//
|
|
// cPeak and cVale ...
|
|
// these Helpes Us to Detect Price Levels ...
|
|
//
|
|
// Draw Peak and Vale if Exists ...
|
|
|
|
//
|
|
// Peak ...
|
|
if (cPeak.IsValid())
|
|
{
|
|
//
|
|
cPeak.to = cTime;
|
|
// drawer.DrawBox(cPeak);
|
|
}
|
|
|
|
//
|
|
// Vale ...
|
|
if (cVale.IsValid())
|
|
{
|
|
//
|
|
cVale.to = cTime;
|
|
// drawer.DrawBox(cVale);
|
|
}
|
|
|
|
//
|
|
// Try to Validate cPeak an cVale if Exists ...
|
|
XOHCL zBar;
|
|
XOHCL cBar;
|
|
bool isInited = zBar.Init(
|
|
symbol,
|
|
period,
|
|
barIndex //
|
|
);
|
|
isInited = zBar.GetPreviousBar(cBar);
|
|
isInited = helper.GetConditions(
|
|
mConditions.conditions,
|
|
barIndex,
|
|
10 //
|
|
);
|
|
if (isInited)
|
|
{
|
|
//
|
|
// Validate cPeak and cVale if Exists ...
|
|
|
|
//
|
|
// cPeak ...
|
|
if (cPeak.IsValid())
|
|
{
|
|
//
|
|
isInited = cBar.high < cPeak.lower;
|
|
if (!isInited)
|
|
{
|
|
//
|
|
cPeak.Clean();
|
|
cVale.Clean();
|
|
|
|
//
|
|
waitsUntilPeakInvalidate = false;
|
|
waitsUntilValeInvalidate = false;
|
|
}
|
|
}
|
|
|
|
//
|
|
// cVale ...
|
|
if (cVale.IsValid())
|
|
{
|
|
//
|
|
isInited = cBar.low > cVale.upper;
|
|
if (!isInited)
|
|
{
|
|
//
|
|
cPeak.Clean();
|
|
cVale.Clean();
|
|
|
|
//
|
|
waitsUntilPeakInvalidate = false;
|
|
waitsUntilValeInvalidate = false;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Try To Detect Peak and Vale based on cBar ...
|
|
|
|
//
|
|
// Selecting Peak ...
|
|
if (!cPeak.IsValid())
|
|
{
|
|
//
|
|
XBoxZone tmpPeaks[];
|
|
detector.FillPeakPivots(tmpPeaks);
|
|
while (HasChild(tmpPeaks))
|
|
{
|
|
//
|
|
// Find Index ...
|
|
int idx = GetLowest(tmpPeaks);
|
|
if (!IsValidIndex(idx))
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Select ...
|
|
cPeak = tmpPeaks[idx];
|
|
ArrayRemove(
|
|
tmpPeaks,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
// Validate Peak ...
|
|
bool isValid = cPeak.lower > cBar.high;
|
|
if (isValid)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
cPeak.Clean();
|
|
}
|
|
Clean(tmpPeaks);
|
|
}
|
|
|
|
//
|
|
// Selecting Vale ...
|
|
if (!cVale.IsValid())
|
|
{
|
|
//
|
|
XBoxZone tmpVales[];
|
|
detector.FillValePivots(tmpVales);
|
|
while (HasChild(tmpVales))
|
|
{
|
|
//
|
|
// Find Index ...
|
|
int idx = GetHighest(tmpVales);
|
|
if (!IsValidIndex(idx))
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Select ...
|
|
cVale = tmpVales[idx];
|
|
ArrayRemove(
|
|
tmpVales,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
// Validate Vale ...
|
|
bool isValid = cVale.upper < cBar.low;
|
|
if (isValid)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
cVale.Clean();
|
|
}
|
|
Clean(tmpVales);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Detect Signal Setup Based on Market Conditions ...
|
|
if (!result &&
|
|
allowSignallingBasedOnConditions)
|
|
{
|
|
//
|
|
// Detect Signalling Zone ...
|
|
result = DetectSignalZone(
|
|
helper,
|
|
drawer,
|
|
detector,
|
|
barAnalyser,
|
|
mConditions.conditions,
|
|
mConditions.pivotZone,
|
|
allowSignallingConditions1,
|
|
allowSignallingConditions2,
|
|
allowSignallingConditions3,
|
|
allowSignallingConditions4,
|
|
allowSignallingConditions5,
|
|
allowSignallingConditions6,
|
|
barIndex,
|
|
10 // Loopback ...
|
|
);
|
|
if (result)
|
|
{
|
|
//
|
|
// Use Signal Zone ...
|
|
UseBox(mConditions.pivotZone);
|
|
|
|
//
|
|
// Prepare Condition ...
|
|
|
|
//
|
|
// Prepare Signal ...
|
|
mConditions.dir =
|
|
mConditions
|
|
.pivotZone
|
|
.dir;
|
|
mConditions.symbol = symbol;
|
|
mConditions.period = period;
|
|
mConditions.provider = provider;
|
|
mConditions.reward = riskToRewardRatio;
|
|
mConditions.time = mConditions.conditions.bars[0].time;
|
|
mConditions.setupTime = mConditions.conditions.bars[0].time;
|
|
|
|
//
|
|
// Prepare Target ...
|
|
double targets[];
|
|
for (int i = 1; i <= riskToRewardRatio; i++)
|
|
{
|
|
//
|
|
Add(
|
|
(double)i,
|
|
targets //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Calculate SL Additions ...
|
|
double iATR = 0;
|
|
if (barIndex > 0 &&
|
|
barIndex < ArraySize(helper.atrBuffer))
|
|
{
|
|
iATR = helper.atrBuffer[barIndex];
|
|
}
|
|
double slAdditional = slATRMultiplier * iATR;
|
|
|
|
//
|
|
// Preparing Signal ...
|
|
XSignal iSignal;
|
|
result = ToSignal(
|
|
mConditions.pivotZone,
|
|
iSignal,
|
|
targets,
|
|
slAdditional //
|
|
);
|
|
if (result)
|
|
{
|
|
//
|
|
mConditions.sl = iSignal.sl;
|
|
mConditions.tp = iSignal.tp;
|
|
mConditions.pivot = iSignal.sl;
|
|
mConditions.entry = iSignal.entry;
|
|
mConditions.point = iSignal.entry;
|
|
mConditions.type = ToPositionType(iSignal.type);
|
|
|
|
//
|
|
// Draw Trigger Block ...
|
|
if (allowDraws)
|
|
{
|
|
//
|
|
XCBoxObject *iObj;
|
|
has = drawer
|
|
.drawer
|
|
.DrawBox(
|
|
mConditions.pivotZone,
|
|
iObj //
|
|
);
|
|
if (has)
|
|
{
|
|
mObjects.Add(iObj);
|
|
}
|
|
ZeroMemory(iObj);
|
|
}
|
|
}
|
|
iSignal.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Detect Signal Setup Based on Trigger Block Detection ...
|
|
if (!result &&
|
|
allowSignallingBasedOnTriggerBlocks)
|
|
{
|
|
//
|
|
// Detect Trigger Block ...
|
|
result = DetectTriggerBlock(
|
|
helper,
|
|
barAnalyser,
|
|
mConditions.triggerBlock,
|
|
mConditions.conditions,
|
|
validations,
|
|
filters,
|
|
barIndex,
|
|
10 // Loopback ...
|
|
);
|
|
if (result)
|
|
{
|
|
//
|
|
// Use Trigger Block ...
|
|
UseTriggerBlock(mConditions.triggerBlock);
|
|
|
|
//
|
|
// Prepare Condition ...
|
|
|
|
//
|
|
// Prepare Signal ...
|
|
mConditions.dir =
|
|
mConditions
|
|
.triggerBlock
|
|
.GetDirection();
|
|
mConditions.symbol = symbol;
|
|
mConditions.period = period;
|
|
mConditions.provider = provider;
|
|
mConditions.reward = riskToRewardRatio;
|
|
mConditions.time = mConditions.conditions.bars[0].time;
|
|
mConditions.setupTime = mConditions.conditions.bars[0].time;
|
|
|
|
//
|
|
// Prepare Target ...
|
|
double targets[];
|
|
for (int i = 1; i <= riskToRewardRatio; i++)
|
|
{
|
|
//
|
|
Add(
|
|
(double)i,
|
|
targets //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Calculate SL Additions ...
|
|
double iATR = 0;
|
|
if (barIndex > 0 &&
|
|
barIndex < ArraySize(helper.atrBuffer))
|
|
{
|
|
iATR = helper.atrBuffer[barIndex];
|
|
}
|
|
double slAdditional = slATRMultiplier * iATR;
|
|
|
|
//
|
|
// Preparing Signal ...
|
|
result = ToSignal(
|
|
mConditions.triggerBlock.trigger,
|
|
mConditions.triggerBlock.signal,
|
|
targets,
|
|
slAdditional //
|
|
);
|
|
if (result)
|
|
{
|
|
//
|
|
mConditions.triggerBlock.signal.provider = provider;
|
|
mConditions.sl = mConditions.triggerBlock.signal.sl;
|
|
mConditions.tp = mConditions.triggerBlock.signal.tp;
|
|
mConditions.pivot = mConditions.triggerBlock.signal.sl;
|
|
mConditions.entry = mConditions.triggerBlock.signal.entry;
|
|
mConditions.point = mConditions.triggerBlock.signal.entry;
|
|
mConditions.type = ToPositionType(mConditions.triggerBlock.signal.type);
|
|
|
|
//
|
|
// Draw Trigger Block ...
|
|
if (allowDraws)
|
|
{
|
|
//
|
|
DrawTriggerBlock(
|
|
mConditions.triggerBlock,
|
|
drawer.drawer,
|
|
mObjects,
|
|
NULL, // To ...
|
|
false // Draw Signal ...
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Detect Signal Setup Based On Trigger Blocks Second Entry ...
|
|
if (!result &&
|
|
allowSignallingBasedOnTriggerBlocksInsideOther)
|
|
{
|
|
//
|
|
// Trigger Block Detection ...
|
|
result = HasChild(triggerBlocks) &&
|
|
ArraySize(triggerBlocks) > 1 &&
|
|
!waitsUntilPeakInvalidate &&
|
|
!waitsUntilValeInvalidate;
|
|
if (result)
|
|
{
|
|
//
|
|
// Check Newest Trigger Block ...
|
|
bool isTriggerBlockSelected = false;
|
|
XTriggerBlock tmpTBs[];
|
|
Copy(
|
|
triggerBlocks,
|
|
tmpTBs //
|
|
);
|
|
while (HasChild(tmpTBs))
|
|
{
|
|
//
|
|
int idx = GetYoungest(tmpTBs);
|
|
if (!IsValidIndex(idx))
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Select ...
|
|
// and Remove From Collection ...
|
|
cTriggerBlock = tmpTBs[idx];
|
|
ArrayRemove(
|
|
tmpTBs,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
// Validate ...
|
|
isTriggerBlockSelected =
|
|
//
|
|
// Check Bar is Valid ...
|
|
cBar.IsValid() &&
|
|
//
|
|
// Currently Happens ...
|
|
(cTriggerBlock.trigger.to == zBar.time ||
|
|
cTriggerBlock.trigger.to == cBar.time) &&
|
|
//
|
|
// Price Validations ...
|
|
(cTriggerBlock.IsBullish()
|
|
? cBar.low > cTriggerBlock.trigger.lower
|
|
: cBar.high < cTriggerBlock.trigger.upper)
|
|
//
|
|
;
|
|
if (isTriggerBlockSelected)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Clean Trigger Block ...
|
|
cTriggerBlock.Clean();
|
|
}
|
|
Clean(tmpTBs);
|
|
|
|
//
|
|
// Check Trigger Block Selection ...
|
|
result = isTriggerBlockSelected;
|
|
if (result)
|
|
{
|
|
//
|
|
bool isBullish = cTriggerBlock.IsBullish();
|
|
bool isBearish = cTriggerBlock.IsBearish();
|
|
|
|
//
|
|
// Now we have to Check Newest Trigger Block Place ...
|
|
int insideTBIDX = DetectInsideTriggerBlock(
|
|
cTriggerBlock,
|
|
cInsideTriggerBlock,
|
|
triggerBlocks //
|
|
);
|
|
|
|
//
|
|
// Check InsideTB is Exists and Valid ...
|
|
result =
|
|
cInsideTriggerBlock.IsValid() &&
|
|
IsValidIndex(insideTBIDX);
|
|
if (result)
|
|
{
|
|
//
|
|
// Now we Have to Detect Peak and Vales ...
|
|
result =
|
|
cPeak.IsValid() &&
|
|
cVale.IsValid();
|
|
|
|
//
|
|
// If Exists Before Validate them based Trigger Blocks ...
|
|
if (result)
|
|
{
|
|
//
|
|
// Validate cPeak and cVale based on
|
|
// cTriggerBlock and cInsideTriggerBlock ...
|
|
result =
|
|
//
|
|
// Peak ...
|
|
cPeak.lower > cTriggerBlock.trigger.upper &&
|
|
cPeak.lower > cInsideTriggerBlock.trigger.upper &&
|
|
//
|
|
// Vale ...
|
|
cVale.upper < cTriggerBlock.trigger.lower &&
|
|
cVale.upper < cInsideTriggerBlock.trigger.lower &&
|
|
//
|
|
// Bar Validation ...
|
|
cBar.IsValid() &&
|
|
cBar.low > cVale.upper &&
|
|
cBar.high < cPeak.lower
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
//
|
|
cPeak.Clean();
|
|
cVale.Clean();
|
|
|
|
//
|
|
waitsUntilPeakInvalidate = false;
|
|
waitsUntilValeInvalidate = false;
|
|
}
|
|
}
|
|
|
|
//
|
|
// if not Exists, or Clean them on Invalidating Process, try to Find Corrects ...
|
|
if (!result)
|
|
{
|
|
//
|
|
// Selecting Peak ...
|
|
XBoxZone tmpPeaks[];
|
|
detector.FillPeakPivots(tmpPeaks);
|
|
while (HasChild(tmpPeaks))
|
|
{
|
|
//
|
|
// Find Index ...
|
|
int idx = GetLowest(tmpPeaks);
|
|
if (!IsValidIndex(idx))
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Select ...
|
|
cPeak = tmpPeaks[idx];
|
|
ArrayRemove(
|
|
tmpPeaks,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
// Validate Peak ...
|
|
bool isValid =
|
|
//
|
|
// Bar Validation ...
|
|
cBar.IsValid() &&
|
|
cBar.high < cPeak.lower &&
|
|
//
|
|
// Peak Validation ...
|
|
cPeak.lower > cTriggerBlock.trigger.upper &&
|
|
cPeak.lower > cInsideTriggerBlock.trigger.upper;
|
|
if (isValid)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
cPeak.Clean();
|
|
}
|
|
Clean(tmpPeaks);
|
|
|
|
//
|
|
// Selecting Vale ...
|
|
XBoxZone tmpVales[];
|
|
detector.FillValePivots(tmpVales);
|
|
while (HasChild(tmpVales))
|
|
{
|
|
//
|
|
// Find Index ...
|
|
int idx = GetHighest(tmpVales);
|
|
if (!IsValidIndex(idx))
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Select ...
|
|
cVale = tmpVales[idx];
|
|
ArrayRemove(
|
|
tmpVales,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
// Validate Vale ...
|
|
bool isValid =
|
|
//
|
|
// Bar Validation ...
|
|
cBar.IsValid() &&
|
|
cBar.low > cVale.upper &&
|
|
//
|
|
// Vale Validation ...
|
|
cVale.upper < cTriggerBlock.trigger.lower &&
|
|
cVale.upper < cInsideTriggerBlock.trigger.lower;
|
|
if (isValid)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
cVale.Clean();
|
|
}
|
|
Clean(tmpVales);
|
|
|
|
//
|
|
// Summarizing Result ...
|
|
result =
|
|
cPeak.IsValid() &&
|
|
cVale.IsValid();
|
|
}
|
|
|
|
//
|
|
// Check Peak and Vale Exists ...
|
|
if (result)
|
|
{
|
|
//
|
|
// Remove Peak from Detector Collections ...
|
|
// and Make it unavailable ...
|
|
UseBox(cPeak);
|
|
|
|
//
|
|
// Remove Vale from Detector Collections ...
|
|
// and Make it unavailable ...
|
|
UseBox(cVale);
|
|
|
|
//
|
|
// Remove Selected Trigger Block ...
|
|
// and Make it unavailable ...
|
|
RemoveTriggerBlock(
|
|
cTriggerBlock,
|
|
triggerBlocks //
|
|
);
|
|
UseTriggerBlock(cTriggerBlock);
|
|
|
|
//
|
|
// Remove Selected Inside Trigger Block ...
|
|
// and Make it unavailable ...
|
|
RemoveTriggerBlock(
|
|
cInsideTriggerBlock,
|
|
triggerBlocks //
|
|
);
|
|
UseTriggerBlock(cInsideTriggerBlock);
|
|
|
|
//
|
|
// Update Peak and Vales To ...
|
|
cPeak.to = cTime;
|
|
cVale.to = cTime;
|
|
|
|
//
|
|
// Draw Peak and Vales ...
|
|
if (allowDraws)
|
|
{
|
|
//
|
|
drawer.DrawBox(cPeak);
|
|
drawer.DrawBox(cVale);
|
|
}
|
|
|
|
//
|
|
// Validate Peaks and Vales ...
|
|
bool isPeakPassed = false;
|
|
bool isValePassed = false;
|
|
cInsideTriggerBlock.trigger.to = cTime;
|
|
int toIDX = cInsideTriggerBlock.ToIndex();
|
|
int fromIDX = cInsideTriggerBlock.FromIndex();
|
|
for (int i = toIDX; i < fromIDX; i++)
|
|
{
|
|
//
|
|
// Reading Values ...
|
|
|
|
//
|
|
double iPeak = helper.GetPeak(i);
|
|
double iPPeak = helper.GetPeak(i + 1);
|
|
|
|
//
|
|
double iVale = helper.GetVale(i);
|
|
double iPVale = helper.GetVale(i + 1);
|
|
|
|
//
|
|
bool isPeakOverLast = iPeak > iPPeak;
|
|
bool isPeakUnderLast = iPeak < iPPeak;
|
|
|
|
//
|
|
bool isValeOverLast = iVale > iPVale;
|
|
bool isValeUnderLast = iVale < iPVale;
|
|
|
|
//
|
|
if (!isPeakPassed)
|
|
{
|
|
//
|
|
isPeakPassed =
|
|
isBullish ? isPeakOverLast
|
|
: isPeakUnderLast;
|
|
}
|
|
|
|
//
|
|
if (!isValePassed)
|
|
{
|
|
//
|
|
isValePassed =
|
|
isBullish
|
|
? isValeUnderLast
|
|
: isPeakOverLast;
|
|
}
|
|
|
|
//
|
|
result =
|
|
isPeakPassed &&
|
|
isValePassed;
|
|
if (result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (result)
|
|
{
|
|
//
|
|
// Draw Trigger Blocks if Allowed ...
|
|
if (allowDraws)
|
|
{
|
|
//
|
|
// Draw Blocks ...
|
|
|
|
//
|
|
// mObjects.Clear();
|
|
|
|
//
|
|
// Detected Block ...
|
|
DrawTriggerBlock(
|
|
cTriggerBlock,
|
|
drawer.drawer,
|
|
mObjects,
|
|
cTime,
|
|
false // Draw Signal ...
|
|
);
|
|
|
|
//
|
|
// Inside Block ...
|
|
DrawTriggerBlock(
|
|
cInsideTriggerBlock,
|
|
drawer.drawer,
|
|
mObjects,
|
|
cTime,
|
|
false // Draw Signal ...
|
|
);
|
|
}
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
waitsUntilPeakInvalidate = true;
|
|
}
|
|
else if (isBearish)
|
|
{
|
|
waitsUntilValeInvalidate = true;
|
|
}
|
|
|
|
//
|
|
mConditions.triggerBlock = cTriggerBlock;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Preparing Conditions based on result ...
|
|
if (result)
|
|
{
|
|
//
|
|
bool isBullish = mConditions.triggerBlock.IsBullish();
|
|
|
|
//
|
|
// Preparing mConditions ...
|
|
mConditions.dir =
|
|
mConditions
|
|
.triggerBlock
|
|
.GetDirection();
|
|
mConditions.symbol = symbol;
|
|
mConditions.period = period;
|
|
mConditions.provider = provider;
|
|
mConditions.reward = riskToRewardRatio;
|
|
mConditions.time = mConditions.conditions.bars[0].time;
|
|
mConditions.setupTime = mConditions.conditions.bars[0].time;
|
|
|
|
//
|
|
// Prepare Target ...
|
|
double targets[];
|
|
for (int i = 1; i <= riskToRewardRatio; i++)
|
|
{
|
|
//
|
|
Add(
|
|
(double)i,
|
|
targets //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Calculate SL Additions ...
|
|
double iATR = 0;
|
|
if (barIndex > 0 &&
|
|
barIndex < ArraySize(helper.atrBuffer))
|
|
{
|
|
iATR = helper.atrBuffer[barIndex];
|
|
}
|
|
double slAdditional = slATRMultiplier * iATR;
|
|
|
|
//
|
|
// Preparing Signal ...
|
|
result = ToSignal(
|
|
mConditions.triggerBlock.trigger,
|
|
mConditions.triggerBlock.signal,
|
|
targets,
|
|
slAdditional //
|
|
);
|
|
XSignal insideTBSignal;
|
|
result =
|
|
result &&
|
|
ToSignal(
|
|
cInsideTriggerBlock.trigger,
|
|
insideTBSignal,
|
|
targets,
|
|
slAdditional //
|
|
);
|
|
if (result)
|
|
{
|
|
//
|
|
// Try to Use SL Based on Inside Trigger Block ...
|
|
double sl = 0;
|
|
double tp = 0;
|
|
if (secondsTriggersSLUsingFirstTriggerBlock)
|
|
{
|
|
//
|
|
sl = insideTBSignal.sl;
|
|
tp = insideTBSignal.tp;
|
|
|
|
//
|
|
// Add Target for usuall Signal TP ...
|
|
XTarget iTarget;
|
|
iTarget.doRF = true;
|
|
iTarget.target = mConditions.triggerBlock.signal.tp;
|
|
|
|
//
|
|
AddRef(
|
|
iTarget,
|
|
mConditions.targets);
|
|
|
|
//
|
|
iTarget.Clean();
|
|
}
|
|
else
|
|
{
|
|
//
|
|
sl = mConditions.triggerBlock.signal.sl;
|
|
tp = mConditions.triggerBlock.signal.tp;
|
|
}
|
|
|
|
//
|
|
mConditions.sl = sl;
|
|
mConditions.tp = tp;
|
|
mConditions.pivot = sl;
|
|
mConditions.triggerBlock.signal.provider = provider;
|
|
mConditions.entry = mConditions.triggerBlock.signal.entry;
|
|
mConditions.point = mConditions.triggerBlock.signal.entry;
|
|
mConditions.type = ToPositionType(mConditions.triggerBlock.signal.type);
|
|
|
|
//
|
|
// Draw Trigger Block ...
|
|
if (allowDraws)
|
|
{
|
|
//
|
|
DrawTriggerBlock(
|
|
mConditions.triggerBlock,
|
|
drawer.drawer,
|
|
mObjects,
|
|
NULL, // To ...
|
|
false // Draw Signal ...
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check a Signal Setup Exists or not ...
|
|
result = mConditions.IsValid() &&
|
|
mConditions.IsSetuped();
|
|
|
|
//
|
|
// Cleanup Resource ...
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
cTriggerBlock.Clean();
|
|
cInsideTriggerBlock.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Trigger Conditions for Specified Signal ...
|
|
*
|
|
* @param conditions: XCATBEAStrategyConditions instance Reference, Specified Signal Conditions ...
|
|
* @param maxAllowedSetupAge: specified Setup Age for Expiration (if bigger than Zero) ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectSignalTrigger(
|
|
XCATBEAStrategyConditions &conditions,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize Args ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
|
|
//
|
|
// Validate Setup ...
|
|
result = conditions.IsSetuped();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool has = false;
|
|
datetime cTime = TimeCurrent();
|
|
bool isBullish = IsBullish(conditions.dir);
|
|
bool isBearish = IsBearish(conditions.dir);
|
|
|
|
//
|
|
bool isBasedOnPivotZone = conditions.pivotZone.IsValid();
|
|
bool isBasedOnTriggerBlock = conditions.triggerBlock.IsValid();
|
|
|
|
//
|
|
// Reading Current Market Conditions ...
|
|
X121XCatbConditions cConditions;
|
|
result =
|
|
result &&
|
|
helper.GetConditions(
|
|
cConditions,
|
|
barIndex,
|
|
10 //
|
|
);
|
|
|
|
//
|
|
// Validate Direction of Setuped Conditions ...
|
|
result =
|
|
result &&
|
|
(isBullish ||
|
|
isBearish);
|
|
|
|
//
|
|
// Detecting Trigger Bar ...
|
|
|
|
//
|
|
ENUM_X_DIRECTION triggerDir;
|
|
bool isTriggerBar = barAnalyser
|
|
.IsValidForTrigger(
|
|
cConditions.bars[0],
|
|
triggerDir,
|
|
false, // Allow Cond 1 ...
|
|
false, // Allow Cond 2 ...
|
|
false, // Allow Cond 3 ...
|
|
false, // Allow Cond 4 ...
|
|
false, // Allow Cond 5 ...
|
|
false, // Allow Cond 6 ...
|
|
true // Allow Cond 7 ...
|
|
//
|
|
);
|
|
bool isBullishTriggerBar =
|
|
isTriggerBar &&
|
|
IsBullish(triggerDir);
|
|
bool isBearishTriggerBar =
|
|
isTriggerBar &&
|
|
IsBearish(triggerDir);
|
|
|
|
//
|
|
// Do Triggering Senario based on Trigger Block ...
|
|
if (result &&
|
|
isBasedOnTriggerBlock)
|
|
{
|
|
//
|
|
// Checking Score ...
|
|
double bullishScore = 0;
|
|
double bearishScore = 0;
|
|
conditions
|
|
.conditions
|
|
.GenerateScore(
|
|
bullishScore,
|
|
bearishScore //
|
|
);
|
|
bool isScorePassed =
|
|
isBullish
|
|
? bullishScore > bearishScore
|
|
: bearishScore > bullishScore;
|
|
|
|
//
|
|
// Complete Conditions Here ...
|
|
if (isScorePassed)
|
|
{
|
|
conditions.triggerTime = TimeCurrent();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Do Triggering based on Market Conditions PivotZones ...
|
|
if (result &&
|
|
isBasedOnPivotZone)
|
|
{
|
|
//
|
|
// Update Box To ...
|
|
conditions.pivotZone.to = cTime;
|
|
|
|
//
|
|
// Draw Box ...
|
|
XCBoxObject *iObj;
|
|
has = drawer
|
|
.drawer
|
|
.DrawBox(
|
|
conditions.pivotZone,
|
|
iObj //
|
|
);
|
|
if (has)
|
|
{
|
|
mObjects.Add(iObj);
|
|
}
|
|
|
|
//
|
|
// Check atleast 3 Bars Close Outside of applied Edge ...
|
|
// Check Current Bar is a Trigger Bar ...
|
|
// TODO: Complete this ...
|
|
//
|
|
}
|
|
|
|
//
|
|
// Do Other Validation Senarios ...
|
|
|
|
//
|
|
result = conditions.IsValid() &&
|
|
conditions.IsSetuped() &&
|
|
conditions.CanTrigger();
|
|
|
|
//
|
|
// Check Setup Age or Setup Validations here ...
|
|
if (!result)
|
|
{
|
|
//
|
|
// Validate Trigger Block Based Setups ...
|
|
|
|
//
|
|
// Validate Pivot Zone Based Setups ...
|
|
|
|
//
|
|
// Validate Setup Age ...
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Guards bsed on Signalling Class ...
|
|
*
|
|
* @param guards: XCAEAGuard instance Collection, Holds Provided Guards ...
|
|
* @param positions: XPosition instance Collection, Provides Signalling Based Positions for Apply Guards on them ...
|
|
* @param provider: X121SMCStrategySignalProviderData instance Reference, Specified Data for Cycles ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectGuards(
|
|
XGuard &guards[],
|
|
const XPosition &positions[],
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize Args ...
|
|
Clean(guards);
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
|
|
//
|
|
result = allowGuards &&
|
|
HasChild(positions);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// TODO: Implement this ...
|
|
|
|
//
|
|
result = HasChild(guards);
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
Clean(guards);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Protected ...
|
|
protected:
|
|
//
|
|
|
|
/**
|
|
* Initialize ...
|
|
*/
|
|
void Init(XCATBEASignallerInputs &inputs)
|
|
{
|
|
//
|
|
maxAllowedCollection = 100;
|
|
|
|
//
|
|
allowSignallingBasedOnConditions = inputs.signallerConfigs.allowSignallingBasedOnConditions;
|
|
allowSignallingBasedOnTriggerBlocks = inputs.signallerConfigs.allowSignallingBasedOnTriggerBlocks;
|
|
allowSignallingBasedOnTriggerBlocksInsideOther = inputs.signallerConfigs.allowSignallingBasedOnTriggerBlocksInsideOther;
|
|
|
|
//
|
|
secondsTriggersSLUsingFirstTriggerBlock = inputs.signallerConfigs.secondsTriggersSLUsingFirstTriggerBlock;
|
|
applyValidateAndFilterOnSelectInsideOthers = inputs.signallerConfigs.applyValidateAndFilterOnSelectInsideOthers;
|
|
|
|
//
|
|
allowSignallingConditions1 = inputs.signallerConfigs.allowSignallingConditions1;
|
|
allowSignallingConditions2 = inputs.signallerConfigs.allowSignallingConditions2;
|
|
allowSignallingConditions3 = inputs.signallerConfigs.allowSignallingConditions3;
|
|
allowSignallingConditions4 = inputs.signallerConfigs.allowSignallingConditions4;
|
|
allowSignallingConditions5 = inputs.signallerConfigs.allowSignallingConditions5;
|
|
allowSignallingConditions6 = inputs.signallerConfigs.allowSignallingConditions6;
|
|
|
|
//
|
|
bool has = inputs.IsValid();
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
symbol = inputs.symbol;
|
|
period = inputs.period;
|
|
filters = inputs.filters;
|
|
provider = inputs.provider;
|
|
allowDraws = inputs.allowDraws;
|
|
allowGuards = inputs.allowGuards;
|
|
validations = inputs.validations;
|
|
slATRMultiplier = inputs.slATRMultiplier;
|
|
riskToRewardRatio = inputs.riskToRewardRatio;
|
|
|
|
//
|
|
mObjects = new CArrayObj();
|
|
|
|
//
|
|
// Initialize Bar Tracker ...
|
|
has = barTraker.Init(
|
|
symbol,
|
|
period //
|
|
);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Initialize Bar Analyser ...
|
|
barAnalyser = new XCBarAnalyser();
|
|
|
|
//
|
|
// initialize Helper ...
|
|
helper = new XCX121XCatbHelper();
|
|
has = helper.Init(
|
|
symbol,
|
|
period,
|
|
inputs.catbInputs //
|
|
);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
mConditions.Clean();
|
|
Clean(mConditionsCollection);
|
|
|
|
//
|
|
InitPOI();
|
|
}
|
|
|
|
/**
|
|
* DeInitialize ...
|
|
*/
|
|
void DeInit()
|
|
{
|
|
//
|
|
mObjects.Clear();
|
|
delete mObjects;
|
|
ZeroMemory(mObjects);
|
|
|
|
//
|
|
drawer.Clear();
|
|
delete drawer;
|
|
ZeroMemory(drawer);
|
|
|
|
//
|
|
detector.CleanPivots();
|
|
delete detector;
|
|
ZeroMemory(detector);
|
|
|
|
//
|
|
delete helper;
|
|
ZeroMemory(helper);
|
|
|
|
//
|
|
delete barAnalyser;
|
|
ZeroMemory(barAnalyser);
|
|
|
|
//
|
|
barTraker.Clean();
|
|
}
|
|
|
|
/**
|
|
* Add Conditions to Conditions Collection if not Exists ...
|
|
*
|
|
* @param maxAllowed: int, Specified Max Allowed Holding Conditions ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int AddConditionsIfNotExists(
|
|
int maxAllowed = 50 //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Normalize Args ...
|
|
maxAllowed = maxAllowedCollection;
|
|
|
|
//
|
|
bool isSetuped = IsValid(mConditions.setupTime) &&
|
|
HasDirection(mConditions.dir);
|
|
if (!isSetuped)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(mConditionsCollection);
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
// Copy Original Items ...
|
|
XCATBEAStrategyConditions tmpItems[];
|
|
Copy(
|
|
mConditionsCollection,
|
|
tmpItems //
|
|
);
|
|
|
|
//
|
|
// Prese Item Data ...
|
|
bool isBullish = IsBullish(mConditions.dir);
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCATBEAStrategyConditions iItem = tmpItems[i];
|
|
|
|
//
|
|
bool canRemove = mConditions.dir == iItem.dir &&
|
|
mConditions.pivot == iItem.pivot;
|
|
if (canRemove)
|
|
{
|
|
//
|
|
ArrayRemove(
|
|
mConditionsCollection,
|
|
i,
|
|
1 //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(tmpItems);
|
|
}
|
|
|
|
//
|
|
AddRef(
|
|
mConditions,
|
|
mConditionsCollection //
|
|
);
|
|
|
|
//
|
|
// Remove Olds ...
|
|
CleanupArray(
|
|
mConditionsCollection,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
result = ArraySize(mConditionsCollection);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Add TriggerBlock if not Exists
|
|
* inside a Collection ...
|
|
*/
|
|
int AddIfNotExists(
|
|
XTriggerBlock &tb,
|
|
XTriggerBlock &tbs[],
|
|
int maxAllowed = 50 //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Normalize Args ...
|
|
maxAllowed = maxAllowedCollection;
|
|
|
|
//
|
|
// First Validate ...
|
|
if (!tb.IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Exists ...
|
|
// and prevent moving forward if exists ...
|
|
int idx = -1;
|
|
bool isExists = FindTriggerBlockIndex(
|
|
idx,
|
|
tb,
|
|
tbs //
|
|
);
|
|
result = !isExists;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Add if not Exists ...
|
|
AddRef(
|
|
tb,
|
|
tbs //
|
|
);
|
|
|
|
//
|
|
// Cleanup ...
|
|
CleanupArray(
|
|
tbs,
|
|
maxAllowed //
|
|
);
|
|
|
|
//
|
|
result = ArraySize(tbs);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Use Specified Box and make it Unavailable ...
|
|
*
|
|
* @param box: XBoxZone instance reference ...
|
|
*/
|
|
void UseBox(XBoxZone &box)
|
|
{
|
|
//
|
|
// Validate Box ...
|
|
bool has = box.IsValid();
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Check Box Added Before or not ...
|
|
int idx = -1;
|
|
has = FindBoxIndex(
|
|
idx,
|
|
box,
|
|
unavailableZones //
|
|
);
|
|
if (has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Adding Box Reference to
|
|
// Unavailable Zones ...
|
|
AddRef(
|
|
box,
|
|
unavailableZones //
|
|
);
|
|
|
|
//
|
|
// Cleanup Array ...
|
|
CleanupArray(
|
|
unavailableZones,
|
|
maxAllowedCollection //
|
|
);
|
|
|
|
//
|
|
}
|
|
|
|
/**
|
|
* Use Specified Trigger Block and Make it Un Available ...
|
|
*
|
|
* @param tb: XTriggerBlock instance reference, Specified Used Trigger Block ...
|
|
*/
|
|
void UseTriggerBlock(XTriggerBlock &tb)
|
|
{
|
|
//
|
|
bool has = tb.IsValid();
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Trigger Box ...
|
|
has = tb.trigger.IsValid();
|
|
if (has)
|
|
{
|
|
UseBox(tb.trigger);
|
|
}
|
|
|
|
//
|
|
// Order Block Box ...
|
|
has = tb.ob.IsValid();
|
|
if (has)
|
|
{
|
|
UseBox(tb.ob);
|
|
}
|
|
|
|
//
|
|
// Fair Value Gap ...
|
|
has = tb.fvg.IsValid();
|
|
if (has)
|
|
{
|
|
UseBox(tb.fvg);
|
|
}
|
|
|
|
//
|
|
// Following Liquidity ...
|
|
has = tb.fLiquidity.IsValid();
|
|
if (has)
|
|
{
|
|
UseBox(tb.fLiquidity);
|
|
}
|
|
|
|
//
|
|
// Reversal Liquidity ...
|
|
has = tb.rLiquidity.IsValid();
|
|
if (has)
|
|
{
|
|
UseBox(tb.rLiquidity);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Draw Exists Trigger Blocks ...
|
|
*/
|
|
void DrawTriggerBlocks(datetime to = NULL)
|
|
{
|
|
//
|
|
// Check Has Child of trigger Blocks ...
|
|
bool has = HasChild(triggerBlocks);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Loop through Blocks ...
|
|
int count = ArraySize(triggerBlocks);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
// Draw Indexed Trigger Block ...
|
|
DrawTriggerBlock(
|
|
triggerBlocks[i],
|
|
drawer.drawer,
|
|
mObjects,
|
|
to,
|
|
false //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Private ...
|
|
private:
|
|
//
|
|
// Props ...
|
|
string symbol;
|
|
string provider;
|
|
CArrayObj *mObjects;
|
|
ENUM_TIMEFRAMES period;
|
|
int maxAllowedCollection; // Max Allowed Collection Items ...
|
|
|
|
//
|
|
// Initialize and Configure POI Detector and Drawer ...
|
|
void InitPOI()
|
|
{
|
|
//
|
|
// Initialize POI Detector ...
|
|
bool has = helper != NULL;
|
|
if (has)
|
|
{
|
|
//
|
|
detector = new XCXCATBEAPOIDetector(helper);
|
|
|
|
//
|
|
// Configure ...
|
|
|
|
//
|
|
detector.detectPeakPivots = true;
|
|
detector.detectValePivots = true;
|
|
|
|
//
|
|
detector.detectMTBullishPivots = true;
|
|
detector.detectMTBearishPivots = true;
|
|
|
|
//
|
|
detector.detectOBBullishPivots = true;
|
|
detector.detectOBBearishPivots = true;
|
|
}
|
|
|
|
//
|
|
// Initialize POI Drawer ...
|
|
has = detector != NULL;
|
|
if (has)
|
|
{
|
|
//
|
|
drawer = new XCXCATBEAPOIDrawer(detector);
|
|
|
|
//
|
|
// Configure ...
|
|
drawer.drawPeakPivots = true;
|
|
drawer.drawValePivots = true;
|
|
|
|
//
|
|
XCATBPivotStyle iStyle;
|
|
|
|
//
|
|
// Styling Peak Pivot ...
|
|
iStyle.width = 1;
|
|
iStyle.clr = clrMagenta;
|
|
iStyle.style = STYLE_SOLID;
|
|
|
|
//
|
|
drawer.peakPivotStyle = iStyle;
|
|
|
|
//
|
|
// Styling Vale Pivot ...
|
|
iStyle.width = 1;
|
|
iStyle.clr = clrAqua;
|
|
iStyle.style = STYLE_SOLID;
|
|
|
|
//
|
|
drawer.valePivotStyle = iStyle;
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
|
|
//
|
|
iStyle.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
// |