Files
MQL5Data/XCATBEA/Libraries/xcatbea.lib.mq5
T
2025-06-01 13:16:07 +03:30

3268 lines
78 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Indicator
// -------------------------------------------------
// Name: XCATBEA Lib
// Description: Library for XCATBEA ...
//
//
// 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 Library for XCATBEA Signaller"
#property strict
//
// Imports ...
#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5"
#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5"
#include "../../Helpers/x-saherelm.x121.xcatb.helper.mq5"
//
// Definiions ...
//
#define XLiquidityToken "XLQ";
#define XTriggerBlockToken "XTRG";
//
struct XTriggerBlock
{
//
// Props ...
XBoxZone ob; // Order Block
XBoxZone fvg; // Fair Value Gap
XOHCL swingBar; // Swing of Trigger
XBoxZone trigger; // Trigger Block
XBoxZone rLiquidity; // Reversal Liquidity
XBoxZone fLiquidity; // Following Liquidity
//
XSignal signal; // Pepared Signal
//
// Constructor ...
XTriggerBlock()
{
Clean();
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
ob.Clean();
fvg.Clean();
signal.Clean();
trigger.Clean();
swingBar.Clean();
rLiquidity.Clean();
fLiquidity.Clean();
//
ZeroMemory(this);
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result = ob.IsValid() &&
fvg.IsValid() &&
trigger.IsValid();
//
return result;
}
//
bool IsBullish()
{
return IsValid() &&
ob.IsBullish();
}
//
bool IsBearish()
{
return IsValid() &&
ob.IsBearish();
}
//
int ToIndex()
{
return trigger.ToIndex();
}
//
int FromIndex()
{
return trigger.FromIndex();
}
//
ENUM_X_DIRECTION GetDirection()
{
//
ENUM_X_DIRECTION result = X_DIRECTION_NONE;
//
if (IsValid())
{
result = ob.dir;
}
//
return result;
}
//
};
//
// Trigger Block Validation Rules ...
struct XTriggerBlockValidationRules
{
//
// Props ...
bool forceHasSwing; // Force Block to Has Propper Swing ...
bool forceOBBarType; // Force Order Block to Has InDirectional Bars ...
int minRequiredOBBar; // Min Required OB Bar ...
bool forceFVGBarType; // Force Fair Value Gaps Bars Type ...
int liquidityLoopback; // Liquidity Detection Loopback ...
double maxAllowedRange; // Max Allowed Order Block Range ...
double minAllowedRange; // Min Allowed Order Block Range ...
bool forceHasFLiquidity; // Force Order Block To Has Reversal Liquidity ...
bool forceHasRLiquidity; // Force Order Block to Has Following Liquidity ...
bool validateGapSequence; // Validate Fair Value Gaps Bar Sequences ...
int minAllowedBlockLength; // Min Allowed Block Length ...
bool validateBlockEdgeBreakout; // Validate Order Block Edge Breakeout ...
//
// Constructor(s) ...
XTriggerBlockValidationRules()
{
Clean();
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
maxAllowedRange = 0;
minAllowedRange = 0;
minRequiredOBBar = 0;
liquidityLoopback = 0;
forceHasSwing = false;
forceOBBarType = false;
forceFVGBarType = false;
minAllowedBlockLength = 0;
forceHasFLiquidity = false;
forceHasRLiquidity = false;
validateGapSequence = false;
validateBlockEdgeBreakout = false;
//
ZeroMemory(this);
}
};
//
// Trigger Block Filters ...
struct XTriggerBlockFilters
{
//
// Props ...
bool filterBasedOnKI; // Filter Based On KI Flats ...
bool filterBasedOnPV; // Filter Based On PV ...
bool filterBasedOnSar; // Filter Based On SAR ...
bool filterBasedOnRSI; // Filter Based On RSI ...
bool filterBasedOnADX; // Filter Based On ADX ...
bool filterBasedOnATR; // Filter Based On ATR ...
bool filterBasedOnTrend; // Filter Based On Trend ...
bool filterBasedOnDelta; // Filter Based On Delta ...
bool filterBasedOnVolume; // Filter Based On Volume ...
bool filterBasedOnSignalBar; // Filter Based on Signal Bar ...
bool filterBasedOnHKSignalBar; // Filter Based On HK Signal Bar ...
//
int bosLoopback; // PV Based Filtering BOS Lookup ...
//
bool forceSarSwitched; // SAR Switched on Sides for Filtering ...
bool forceSarOnBothSide; // SAR Check on Both Sides for Filtering ...
bool forceSarHasBreakout; // SAR Must SAR Must Breakout ...
bool forceSarHasReversalSide; // SAR Must SAR Must Has Reversal Direction ...
//
bool forceHasRSITrending; // RSI Must Has Trending ...
bool forceHasRSIVPattern; // RSI Must Has Pattern ...
bool forceHasRSICrossing; // RSI Must Has Crossing Levels ...
//
bool forceHasADXTrending; // ADX Must Has Trending ...
bool forceHasADXCrossing; // ADX Must Has Crossing +DI/-DI ...
//
bool forceHasATRTrending; // ATR Must Has Trending ...
bool forceHasATRBreakout; // ATR Must Has Breakout ...
//
bool forceHasTrendDir; // TREND Must Has Following Direction ...
bool forceHasTrendPlace; // TREND Place Based Filtering ...
bool forceHasTrendChange; // TREND Change Filtering ...
bool forceHasTrendTrending; // TREND Must Has Trending ...
bool forceHasTrendRejection; // TREND Line Must Rejected ...
bool forceHasTrendLineInside; // TREND Line has Inside ...
bool forceHasTrendDirOnBothSide; // TREND Must Has Following Direction in Both Side ...
//
// Constructor(s) ...
XTriggerBlockFilters()
{
Clean();
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
filterBasedOnKI = false;
filterBasedOnPV = false;
filterBasedOnSar = false;
filterBasedOnRSI = false;
filterBasedOnADX = false;
filterBasedOnATR = false;
filterBasedOnTrend = false;
filterBasedOnDelta = false;
filterBasedOnVolume = false;
filterBasedOnSignalBar = false;
filterBasedOnHKSignalBar = false;
//
bosLoopback = 0;
//
forceSarSwitched = false;
forceSarOnBothSide = false;
forceSarHasBreakout = false;
forceSarHasReversalSide = false;
//
forceHasRSITrending = false;
forceHasRSIVPattern = false;
forceHasRSICrossing = false;
//
forceHasADXTrending = false;
forceHasADXCrossing = false;
//
forceHasATRTrending = false;
forceHasATRBreakout = false;
//
forceHasTrendDir = false;
forceHasTrendPlace = false;
forceHasTrendChange = false;
forceHasTrendTrending = false;
forceHasTrendRejection = false;
forceHasTrendLineInside = false;
forceHasTrendDirOnBothSide = false;
//
ZeroMemory(this);
}
};
//
// Extensions ...
/**
* Detect Trigger Block ...
*
* @param helper: XCX121XCatbHelper instance pointer ...
* @param barAnalyser: XCBarAnalyser instance pointer ...
* @param triggerBlock: XTriggerBlock Refrence, holds Detected Trigger Block ...
* @param conditions: X121XCatbConditions Refrence, holds Trigger Block Conditions ...
* @param validations: XTriggerBlockValidationRules Refrence, Provides Trigger Block Validation Rules ...
* @param filters: XTriggerBlockFilters Refrence, Provides Trigger Block Filters ...
* @param barIndex: int, Bar Index ...
* @param loopback: int, Loopback for Conditions reading ...
*
* @return ( bool )
*/
bool DetectTriggerBlock1(
XCX121XCatbHelper *helper,
XCBarAnalyser *barAnalyser,
XTriggerBlock &triggerBlock,
X121XCatbConditions &conditions,
XTriggerBlockValidationRules &validations,
XTriggerBlockFilters &filters,
int barIndex = 0,
int loopback = 10 //
)
{
//
bool result = false;
//
// Normalize Args ...
conditions.Clean();
triggerBlock.Clean();
barIndex = NormalizeInt(barIndex, 0);
loopback = NormalizeInt(loopback, 0);
//
// Validate Args ...
result =
helper != NULL &&
barAnalyser != NULL;
if (!result)
{
return result;
}
//
int zIDX = 0;
int cIDX = zIDX + 1;
int pIDX = cIDX + 1;
int p2IDX = pIDX + 1;
int p3IDX = p2IDX + 1;
int p4IDX = p3IDX + 1;
//
bool has = false;
string symbol = helper.GetSymbol();
ENUM_TIMEFRAMES period = helper.GetPeriod();
//
// Initial Requirements ...
//
// Required Bars ...
XOHCL zBar;
XOHCL cBar;
result =
result &&
zBar.Init(
symbol,
period,
barIndex //
);
result =
result &&
zBar.GetPreviousBar(cBar);
//
// Here we Must Detect Order Block ...
// then Detect FVG ...
// then Prepare Trigger Box ...
//
// Select Application Bar ...
XOHCL iBar;
if (barIndex == 0)
{
iBar = cBar;
}
else if (barIndex > 0)
{
iBar = zBar;
}
iBar = cBar;
result =
result &&
iBar.IsValid();
//
// Detect Order Block ...
result =
result &&
barAnalyser
.IsOB(
iBar,
triggerBlock.ob,
false,
false //
);
//
// Detect Fair Value Gap ...
result =
result &&
barAnalyser
.IsFVG(
iBar,
triggerBlock.fvg,
false //
);
//
// Check Result and Create Trigger Box based on it ...
if (result)
{
//
triggerBlock.trigger = triggerBlock.ob;
triggerBlock.trigger.type = XTriggerBlockToken;
//
// Update Upper and Lower ...
int toIDX = triggerBlock.ob.ToIndex();
int fromIDX = triggerBlock.ob.FromIndex();
//
iBar.Clean();
result = iBar.Init(
symbol,
period,
toIDX //
);
if (result)
{
//
double iLL = iBar.FindLowest(fromIDX - toIDX, MODE_LOW);
double iHH = iBar.FindHighest(fromIDX - toIDX, MODE_HIGH);
//
triggerBlock.trigger.upper = MathMax(iHH, triggerBlock.trigger.upper);
triggerBlock.trigger.lower = MathMin(iLL, triggerBlock.trigger.lower);
}
//
iBar.Clean();
}
//
// Apply Validations ...
if (result)
{
//
result = ValidateTriggerBlock(
helper,
barAnalyser,
triggerBlock,
conditions,
validations,
barIndex,
loopback //
);
//
if (!result)
{
triggerBlock.Clean();
}
}
//
// Apply Filtering ...
if (result)
{
//
result = FilterTriggerBlock(
helper,
barAnalyser,
triggerBlock,
conditions,
filters,
barIndex,
loopback //
);
//
if (!result)
{
triggerBlock.Clean();
}
}
//
// Summarizing Result ...
result =
result &&
triggerBlock.IsValid();
//
// Preparing Signal ...
if (result)
{
//
}
//
// Cleanup Resources ...
//
iBar.Clean();
zBar.Clean();
cBar.Clean();
//
if (!result)
{
triggerBlock.Clean();
}
//
return result;
}
/**
* Validate a Trigger Block ...
*
* @param helper: XCX121XCatbHelper instance pointer ...
* @param barAnalyser: XCBarAnalyser instance pointer ...
* @param triggerBlock: XTriggerBlock Refrence, Trigger Block ...
* @param conditions: X121XCatbConditions Refrence, Trigger Block Conditions ...
* @param validations: XTriggerBlockValidationRules Refrence, Provides Trigger Block Validation Rules ...
* @param barIndex: int, Bar Index ...
* @param loopback: int, Loopback for Conditions reading ...
*
* @return ( bool )
*/
bool ValidateTriggerBlock(
XCX121XCatbHelper *helper,
XCBarAnalyser *barAnalyser,
XTriggerBlock &triggerBlock,
X121XCatbConditions &conditions,
XTriggerBlockValidationRules &validations,
int barIndex = 0,
int loopback = 10 //
)
{
//
bool result = false;
//
// Checking Conditions ...
//
// Normalize Args ...
conditions.Clean();
barIndex = NormalizeInt(barIndex, 0);
loopback = NormalizeInt(loopback, 0);
//
// Validate Args ...
result =
helper != NULL &&
barAnalyser != NULL &&
triggerBlock.IsValid();
if (!result)
{
return result;
}
//
// Reading Market Conditions ...
result = helper.GetConditions(
conditions,
barIndex,
loopback //
);
if (!result)
{
//
conditions.Clean();
//
return result;
}
//
int zIDX = 0;
int cIDX = zIDX + 1;
int pIDX = cIDX + 1;
int p2IDX = pIDX + 1;
int p3IDX = p2IDX + 1;
int p4IDX = p3IDX + 1;
//
XOHCL iBar;
int count = 0;
int toIDX = -1;
int fromIDX = -1;
bool has = false;
bool isBullish = triggerBlock.IsBullish();
bool isBearish = triggerBlock.IsBearish();
double points = GetPoints(triggerBlock.ob.symbol);
ENUM_X_DIRECTION iDir = triggerBlock.GetDirection();
//
// Checking Conditions ...
//
// Range Validation ...
//
// Max Allowed OB Range ...
if (result &&
validations.maxAllowedRange > 0)
{
//
double iRange = triggerBlock.ob.GetRange();
result = iRange <= (validations.maxAllowedRange * points);
}
//
// Min Allowed OB Range ...
if (result &&
validations.minAllowedRange > 0)
{
//
double iRange = triggerBlock.ob.GetRange();
result = iRange >= (validations.maxAllowedRange * points);
}
//
// Has Swing ...
if (result &&
validations.forceHasSwing)
{
//
bool isSwing = false;
toIDX = triggerBlock.ToIndex();
fromIDX = triggerBlock.FromIndex();
ENUM_X_DIRECTION swingDir = X_DIRECTION_NONE;
for (int i = toIDX; i <= fromIDX; i++)
{
//
// Initialize iBar ...
has = iBar.Init(
conditions.symbol,
conditions.period,
i //
);
isSwing =
has &&
barAnalyser
.IsSimpleSwing(
iBar,
swingDir //
);
if (isSwing &&
swingDir == iDir)
{
break;
}
//
iBar.Clean();
}
//
result =
isSwing &&
iBar.IsValid() &&
swingDir == iDir;
if (result)
{
//
// Initialize Swing Bar ...
result = triggerBlock
.swingBar
.Init(
iBar.symbol,
iBar.period,
iBar.Index() + 2 //
);
}
//
iBar.Clean();
}
//
// Force FVG Bar Types ...
if (result &&
validations.forceFVGBarType)
{
//
toIDX = triggerBlock.fvg.ToIndex();
fromIDX = triggerBlock.fvg.FromIndex();
for (int i = toIDX; i < fromIDX; i++)
{
//
// Initialize iBar ...
result = iBar.Init(
conditions.symbol,
conditions.period,
i //
);
result =
result &&
iDir == iBar.GetDirection();
//
iBar.Clean();
//
if (!result)
{
break;
}
}
//
iBar.Clean();
}
//
// Force OB Start By InDirectional Bars ...
if (result &&
validations.forceOBBarType)
{
//
count = 0;
fromIDX = triggerBlock.fvg.FromIndex() + 1;
int sIDX = fromIDX;
has = true;
while (has)
{
//
// Initialize iBar ..
has = iBar.Init(
conditions.symbol,
conditions.period,
fromIDX //
);
has = has &&
iDir == Opposit(iBar.GetDirection());
if (has)
{
count++;
}
//
fromIDX++;
}
//
int required =
validations.minRequiredOBBar > 0
? validations.minRequiredOBBar
: 1;
//
result = count >= required;
//
// Update Trigger Block Box based on OB Bar Types ...
if (result)
{
//
result = iBar.Init(
conditions.symbol,
conditions.period,
sIDX //
);
if (result)
{
//
datetime iFrom = GetBarTime(
conditions.symbol,
conditions.period,
sIDX + count //
);
double iLL = iBar.FindLowest(count, MODE_LOW);
double iHH = iBar.FindHighest(count, MODE_HIGH);
//
triggerBlock.trigger.from = iFrom;
triggerBlock.trigger.upper = MathMax(iHH, triggerBlock.trigger.upper);
triggerBlock.trigger.lower = MathMin(iLL, triggerBlock.trigger.lower);
}
}
//
iBar.Clean();
}
//
// Force Fair Value Gap to Following Sequence ...
if (result &&
validations.validateGapSequence)
{
//
XOHCL iPBar;
toIDX = triggerBlock.fvg.ToIndex();
fromIDX = triggerBlock.fvg.FromIndex() - 1;
for (int i = toIDX; i < fromIDX; i++)
{
//
result = iBar.Init(
conditions.symbol,
conditions.period,
i //
);
result =
result &&
iBar.GetPreviousBar(iPBar);
result =
result &&
(isBullish
? iBar.low > iPBar.low
: iBar.high < iPBar.high);
if (!result)
{
break;
}
//
iBar.Clean();
iPBar.Clean();
}
//
iBar.Clean();
iPBar.Clean();
}
//
// Validate OB Edge Breakeout Using Gaps End Bar ...
if (result &&
validations.validateBlockEdgeBreakout)
{
//
// Initialize Gap End Bar ...
toIDX = triggerBlock.fvg.ToIndex();
result = iBar.Init(
conditions.symbol,
conditions.period,
toIDX //
);
//
result =
result &&
(isBullish
? iBar.open < triggerBlock.ob.upper &&
iBar.close > triggerBlock.ob.upper
: iBar.open > triggerBlock.ob.lower &&
iBar.close < triggerBlock.ob.lower);
//
// Here we Can Apply Edge Breakout Using Fibo ...
//
iBar.Clean();
}
//
// Force Block to Has Liquidity ...
if (result &&
validations.liquidityLoopback > 0 &&
(validations.forceHasFLiquidity ||
validations.forceHasRLiquidity))
{
//
toIDX = triggerBlock.ToIndex();
fromIDX = triggerBlock.FromIndex();
ENUM_X_DIRECTION iLiqDir = X_DIRECTION_NONE;
for (int i = toIDX; i < fromIDX + validations.liquidityLoopback; i++)
{
//
// Initialize iBar ...
has = iBar.Init(
conditions.symbol,
conditions.period,
i //
);
has =
has &&
barAnalyser
.IsRejected(
iBar,
iLiqDir,
false, // Force Bar Type ...
true // Force Fibo Pressure ...
);
//
bool isFLiq =
has &&
iLiqDir == iDir;
if (isFLiq &&
validations.forceHasFLiquidity &&
!triggerBlock.fLiquidity.IsValid())
{
//
FillLiquidity(
iBar,
iLiqDir,
triggerBlock.fLiquidity,
triggerBlock.trigger.to //
);
}
//
bool isRLiq =
has &&
iLiqDir == Opposit(iDir);
if (isRLiq &&
validations.forceHasRLiquidity &&
!triggerBlock.rLiquidity.IsValid())
{
//
FillLiquidity(
iBar,
iLiqDir,
triggerBlock.rLiquidity,
triggerBlock.trigger.to //
);
}
//
// Here We Can Apply Liquidity Validations ...
ValidateTriggerBlockLiquidities(
helper,
barAnalyser,
triggerBlock,
conditions,
validations //
);
//
// Check Liquidities ...
has = (!validations.forceHasFLiquidity
? true
: triggerBlock.fLiquidity.IsValid()) &&
(!validations.forceHasRLiquidity
? true
: triggerBlock.rLiquidity.IsValid());
//
iBar.Clean();
//
if (has)
{
break;
}
}
//
// Check Result ...
result = (!validations.forceHasFLiquidity
? true
: triggerBlock.fLiquidity.IsValid()) &&
(!validations.forceHasRLiquidity
? true
: triggerBlock.rLiquidity.IsValid());
//
iBar.Clean();
}
//
// Validating Block Length Based on Direction ...
if (result &&
validations.minAllowedBlockLength)
{
//
count = 0;
fromIDX = triggerBlock.FromIndex();
int sIDX = fromIDX;
has = true;
while (has)
{
//
// Initialize iBar ...
has = iBar.Init(
conditions.symbol,
conditions.period,
sIDX //
);
//
has =
has &&
(isBullish
? iBar.low > triggerBlock.trigger.lower
: iBar.high < triggerBlock.trigger.upper);
//
if (!has)
{
break;
}
//
sIDX++;
count++;
iBar.Clean();
}
//
result =
iBar.IsValid() &&
count >= validations.minAllowedBlockLength;
if (result)
{
//
// Update Trigger Block ...
bool usaMinAllowedForBlockLength = false;
if (usaMinAllowedForBlockLength)
{
fromIDX = fromIDX + validations.minAllowedBlockLength;
}
else
{
fromIDX = sIDX - 1;
}
//
triggerBlock.trigger.from = GetBarTime(
conditions.symbol,
conditions.period,
fromIDX //
);
}
//
iBar.Clean();
}
//
if (!result)
{
triggerBlock.Clean();
}
//
// Summarize result ...
result = triggerBlock.IsValid();
//
// Cleanup Resources ...
//
iBar.Clean();
//
if (!result)
{
//
conditions.Clean();
triggerBlock.Clean();
}
//
return result;
}
/**
* Filter a Trigger Block ...
*
* @param helper: XCX121XCatbHelper instance pointer ...
* @param barAnalyser: XCBarAnalyser instance pointer ...
* @param triggerBlock: XTriggerBlock Refrence, Trigger Block ...
* @param conditions: X121XCatbConditions Refrence, Trigger Block Conditions ...
* @param filters: XTriggerBlockFilters Refrence, Provides Trigger Block Filters ...
* @param barIndex: int, Bar Index ...
* @param loopback: int, Loopback for Conditions reading ...
*
* @return ( bool )
*/
bool FilterTriggerBlock(
XCX121XCatbHelper *helper,
XCBarAnalyser *barAnalyser,
XTriggerBlock &triggerBlock,
X121XCatbConditions &conditions,
XTriggerBlockFilters &filters,
int barIndex = 0,
int loopback = 10 //
)
{
//
bool result = false;
//
// Checking Conditions ...
//
// Normalize Args ...
conditions.Clean();
barIndex = NormalizeInt(barIndex, 0);
loopback = NormalizeInt(loopback, 0);
//
// Validate Args ...
result =
helper != NULL &&
barAnalyser != NULL &&
triggerBlock.IsValid();
if (!result)
{
return result;
}
//
// Reading Market Conditions ...
result = helper.GetConditions(
conditions,
barIndex,
loopback //
);
if (!result)
{
//
conditions.Clean();
//
return result;
}
//
int zIDX = 0;
int cIDX = zIDX + 1;
int pIDX = cIDX + 1;
int p2IDX = pIDX + 1;
int p3IDX = p2IDX + 1;
int p4IDX = p3IDX + 1;
//
XOHCL iBar;
int toIDX = -1;
int fromIDX = -1;
bool has = false;
bool isBullish = triggerBlock.IsBullish();
bool isBearish = triggerBlock.IsBearish();
double points = GetPoints(triggerBlock.ob.symbol);
ENUM_X_DIRECTION iDir = triggerBlock.GetDirection();
//
// Checking Conditions ...
//
// Filter Based KI ...
if (result &&
filters.filterBasedOnKI)
{
//
int count = 0;
toIDX = triggerBlock.ob.ToIndex();
fromIDX = triggerBlock.ob.FromIndex();
double lKI = conditions.kiBuffer[zIDX];
for (int i = toIDX; i < fromIDX; i++)
{
//
double iKI = helper.GetKI(i);
if (iKI == lKI)
{
count++;
}
else
{
break;
}
}
//
result = count >= 3;
}
//
// Filter Based On PV ...
if (result &&
filters.filterBasedOnPV)
{
//
// For PV Filtering ...
//
// Detect BOS ...
//
// When Loopback for BOS has Specified Value ...
// we Lookup for BOS on Specific Period ...
if (filters.bosLoopback > 0)
{
//
has = true;
int fBOSIDX = -1;
int rBOSIDX = -1;
bool isBOS = false;
bool isFBOS = false;
bool isRBOS = false;
bool isPeakOverLast = false;
bool isValeUnderLast = false;
toIDX = triggerBlock.ob.ToIndex();
fromIDX = triggerBlock.ob.FromIndex();
int sIDX = fromIDX;
while (has)
{
//
double iPeak = helper.GetPeak(sIDX);
double iPPeak = helper.GetPeak(sIDX + 1);
//
double iVale = helper.GetVale(sIDX);
double iPVale = helper.GetVale(sIDX + 1);
//
isPeakOverLast =
iPeak > 0 &&
iPeak > iPPeak;
//
isValeUnderLast =
iVale > 0 &&
iVale < iPVale;
//
isFBOS =
isBullish
? isPeakOverLast
: isValeUnderLast;
if (isFBOS)
{
fBOSIDX = sIDX;
}
//
isRBOS =
isBullish
? isValeUnderLast
: isPeakOverLast;
if (isRBOS)
{
rBOSIDX = sIDX;
}
//
isBOS =
(isBullish &&
isPeakOverLast) ||
(isBearish &&
isValeUnderLast);
if (isBOS)
{
break;
}
//
sIDX++;
has = !isBOS &&
sIDX < fromIDX + filters.bosLoopback;
}
//
isFBOS = IsValidIndex(fBOSIDX);
isRBOS = IsValidIndex(rBOSIDX);
//
result = isBOS &&
isFBOS &&
!isRBOS;
}
//
// When Loopback for BOS has not Specified Value ...
// we Lookup for BOS on GAP End Bar ...
if (filters.bosLoopback <= 0)
{
//
toIDX = triggerBlock.ToIndex();
//
// Initialize iBar ...
result = iBar.Init(
conditions.symbol,
conditions.period,
toIDX //
);
result =
result &&
(isBullish ? iBar.high > helper.GetPeak(toIDX + 1)
: iBar.low < helper.GetVale(toIDX + 1));
}
}
//
// Filter Based on SAR ...
if (result &&
filters.filterBasedOnSar)
{
//
toIDX = triggerBlock.ToIndex();
fromIDX = triggerBlock.FromIndex();
//
double iSarState = helper.GetSarState(toIDX);
double iPSarState = helper.GetSarState(toIDX + 1);
//
double iFSarState = helper.GetSarState(fromIDX);
double iPFSarState = helper.GetSarState(fromIDX + 1);
//
bool isSarBullish =
iSarState > 0;
//
bool isSarBearish =
iSarState < 0;
//
bool isFSarBullish =
iFSarState > 0;
//
bool isFSarBearish =
iFSarState < 0;
//
bool isSarSwitchedToBullish =
iSarState > 0 &&
iPSarState <= 0;
//
bool isSarSwitchedToBearish =
iSarState < 0 &&
iPSarState >= 0;
//
bool isFSarSwitchedToBullish =
iFSarState > 0 &&
iPFSarState <= 0;
//
bool isFSarSwitchedToBearish =
iFSarState < 0 &&
iPFSarState >= 0;
//
// Check SAR Direction ...
//
if (result &&
!filters.forceSarSwitched)
{
//
result = isBullish
? isSarBullish
: isSarBearish;
}
//
if (result &&
filters.forceSarSwitched)
{
//
result = isBullish
? isSarSwitchedToBullish
: isSarSwitchedToBearish;
}
//
if (result &&
filters.forceSarOnBothSide)
{
//
if (result &&
!filters.forceSarSwitched)
{
//
result = isBullish
? isFSarBullish
: isFSarBearish;
}
//
if (result &&
filters.forceSarSwitched)
{
//
result = isBullish
? isFSarSwitchedToBullish
: isFSarSwitchedToBearish;
}
}
//
// Check Sar Has Reversal Direction inside Trigger Block ...
if (result &&
filters.forceSarHasReversalSide)
{
//
toIDX = triggerBlock.ToIndex();
fromIDX = triggerBlock.FromIndex();
for (int i = toIDX; i < fromIDX; i++)
{
//
double iSarState = helper.GetSarState(i);
//
has =
isBullish
? iSarState > 0
: iSarState < 0;
if (has)
{
break;
}
}
//
result = has;
}
//
// Force Sar Breakouts ...
// in this Senario Sar must in following Direction and
// there is not any Switches ...
// but must breakout Bar the last in Reversal Direction
// of Sar ...
if (result &&
filters.forceSarHasBreakout)
{
//
bool isSarBullishStart =
//
(
//
// Current SAR is Directional ...
conditions.isSarBullish &&
//
// Previous InDirectional Sar Exists ...
helper.lastSarBearish.IsValid() &&
//
// Current Close is Over previous Sar ...
conditions.bars[cIDX].close > helper.lastSarBearish.after &&
//
// Before Close is not Over previous Sar ...
conditions.bars[pIDX].close <= helper.lastSarBearish.after
//
)
//
;
//
bool isSarBearishStart =
//
(
//
// Current SAR is Directional ...
conditions.isSarBearish &&
//
// Previous InDirectional Sar Exists ...
helper.lastSarBullish.IsValid() &&
//
// Current Close is Under previous ...
conditions.bars[cIDX].close < helper.lastSarBullish.after &&
//
// Before Close is not Under previous ...
conditions.bars[pIDX].close >= helper.lastSarBullish.after
//
)
//
;
//
result =
isBullish
? isSarBullishStart
: isSarBearishStart;
}
}
//
// Filter Based On RSI ...
if (result &&
filters.filterBasedOnRSI)
{
//
// Here We Can Apply RSI Filters ...
// Since RSI Filters must be Check on FVG Bars ...
// we Have to Loop back Based on FVG Bars to Detect Conditions ...
double rsiTrend = (conditions.rsiOBLevel + conditions.rsiOSLevel) / 2;
//
toIDX = triggerBlock.fvg.ToIndex();
fromIDX = triggerBlock.fvg.FromIndex();
//
// Filter Using RSI Trending ...
if (result &&
filters.forceHasRSITrending)
{
//
for (int i = toIDX; i < fromIDX; i++)
{
//
double iRSI = helper.GetRSI(i);
double iPRSI = helper.GetRSI(i + 1);
//
has =
(isBullish
? (iRSI > rsiTrend &&
iRSI > iPRSI)
: (iRSI < rsiTrend &&
iRSI < iPRSI));
if (has)
{
break;
}
}
//
result = has;
}
//
// Filter Using RSI V Pattern ...
if (result &&
filters.forceHasRSIVPattern)
{
//
for (int i = toIDX; i < fromIDX; i++)
{
//
double iRSI = helper.GetRSI(i);
double iPRSI = helper.GetRSI(i + 1);
double iP2RSI = helper.GetRSI(i + 2);
//
bool isRSIVBullish =
iRSI > iPRSI &&
iP2RSI > iPRSI;
//
bool isRSIVBearish =
iRSI < iPRSI &&
iP2RSI < iPRSI;
//
has =
(isBullish
? isRSIVBullish
: isRSIVBearish);
if (has)
{
break;
}
}
//
result = has;
}
//
// Filter Using RSI Crossing on OB/OS Levels ...
if (result &&
filters.forceHasRSICrossing)
{
//
for (int i = toIDX; i < fromIDX; i++)
{
//
double iRSI = helper.GetRSI(i);
double iPRSI = helper.GetRSI(i + 1);
//
bool isRSICrossedOverOS =
iRSI > conditions.rsiOSLevel &&
iPRSI <= conditions.rsiOSLevel;
//
bool isRSICrossedUnderOB =
iRSI < conditions.rsiOBLevel &&
iPRSI >= conditions.rsiOBLevel;
//
has =
(isBullish
? isRSICrossedOverOS
: isRSICrossedUnderOB);
if (has)
{
break;
}
}
//
result = has;
}
}
//
// Filter Based On ADX ...
if (result &&
filters.filterBasedOnADX)
{
//
// Here We Can Apply ADX Filters ...
// Since ADX Filters must be Check on FVG Bars ...
// we Have to Loop back Based on FVG Bars to Detect Conditions ...
//
toIDX = triggerBlock.fvg.ToIndex();
fromIDX = triggerBlock.fvg.FromIndex();
//
// Filter Using ADX Trending ...
if (result &&
filters.forceHasADXTrending)
{
//
for (int i = toIDX; i < fromIDX; i++)
{
//
double iADX = helper.GetADX(i);
double iPADX = helper.GetADX(i + 1);
//
has = iADX > conditions.adxThreshold &&
iADX > iPADX;
if (has)
{
break;
}
}
//
result = has;
}
//
// Filter Using ADX Crossing on +DI/-DI ...
if (result &&
filters.forceHasADXCrossing)
{
//
for (int i = toIDX; i < fromIDX; i++)
{
//
double iDIPlus = helper.GetADXP(i);
double iPDIPlus = helper.GetADXP(i + 1);
//
double iDIMinus = helper.GetADXN(i);
double iPDIMinus = helper.GetADXN(i + 1);
//
bool isADXPlusCrossedOverMinus =
iDIPlus > iDIMinus &&
iPDIPlus <= iDIMinus;
//
bool isADXMinusCrossedOverPlus =
iDIMinus > iDIPlus &&
iPDIMinus <= iDIPlus;
//
has =
isBullish
? isADXPlusCrossedOverMinus
: isADXMinusCrossedOverPlus;
if (has)
{
break;
}
}
//
result = has;
}
}
//
// Filter Based On ATR Band ...
if (result &&
filters.filterBasedOnATR)
{
//
// Here We Can Apply ATR Filters ...
// Since ATR Filters must be Check on OB Bars ...
// we Have to Loop back Based on OB Bars to Detect Conditions ...
//
toIDX = triggerBlock.ob.ToIndex();
fromIDX = triggerBlock.ob.FromIndex();
//
// Filter Using ATR Trending ...
if (result &&
filters.forceHasATRTrending)
{
//
for (int i = toIDX; i < fromIDX; i++)
{
//
double iATRUpper = helper.GetATRUpper(i);
double iPATRUpper = helper.GetATRUpper(i + 1);
//
double iATRLower = helper.GetATRLower(i);
double iPATRLower = helper.GetATRLower(i + 1);
//
bool isATRUp =
iATRLower > iPATRLower;
//
bool isATRDown =
iATRUpper < iPATRUpper;
//
has = isBullish
? isATRUp
: isATRDown;
if (has)
{
break;
}
}
//
result = has;
}
//
// Filter Using ATR Breakout ...
if (result &&
filters.forceHasATRBreakout)
{
//
for (int i = toIDX; i < fromIDX; i++)
{
//
double iATRUpper = helper.GetATRUpper(i);
double iATRLower = helper.GetATRLower(i);
//
has = isBullish
? triggerBlock.ob.lower < iATRLower
: triggerBlock.ob.upper > iATRUpper;
if (has)
{
break;
}
}
//
result = has;
}
}
//
// Filter Based On Trend ...
if (result &&
filters.filterBasedOnTrend)
{
//
toIDX = triggerBlock.fvg.ToIndex();
fromIDX = triggerBlock.fvg.FromIndex();
//
// Filter Using Trend Direction ...
if (result &&
filters.forceHasTrendDir)
{
//
result =
result &&
isBullish
? conditions.isTrendBullish
: conditions.isTrendBearish;
}
//
// Filter Using Trend Direction On Both Side ...
if (result &&
filters.forceHasTrendDirOnBothSide)
{
//
// Side To ...
result =
result &&
isBullish
? conditions.isTrendBullish
: conditions.isTrendBearish;
//
// Side From ...
int sFIDX = triggerBlock.ob.FromIndex();
double sFTrendState = helper.GetTrendState(sFIDX);
result =
result &&
isBullish
? sFTrendState > 0
: sFTrendState < 0;
}
//
// Filter Using Trend Change ...
if (result &&
filters.forceHasTrendChange)
{
//
for (int i = toIDX; i < fromIDX; i++)
{
//
double iTrendState = helper.GetTrendState(i);
double iPTrendState = helper.GetTrendState(i + 1);
//
bool isTrendSwitchedToBullish =
iTrendState > 0 &&
iPTrendState <= 0;
//
bool isTrendSwitchedToBearish =
iTrendState < 0 &&
iPTrendState >= 0;
//
has =
isBullish
? isTrendSwitchedToBullish
: isTrendSwitchedToBearish;
if (has)
{
break;
}
}
//
result = has;
}
//
// Filter Using Trend Trending ...
if (result &&
filters.forceHasTrendTrending)
{
//
result =
result &&
(isBullish
? conditions.trendBuffer[cIDX] > conditions.trendBuffer[pIDX]
: conditions.trendBuffer[cIDX] < conditions.trendBuffer[pIDX]);
}
//
// Filter Using Trend Rejection ...
if (result &&
filters.forceHasTrendRejection)
{
//
toIDX = triggerBlock.ob.ToIndex();
fromIDX = triggerBlock.ob.FromIndex();
for (int i = toIDX; i < fromIDX; i++)
{
//
// Initialize iBar ...
has = iBar.Init(
conditions.symbol,
conditions.period,
i //
);
//
// Read Trend Value ...
double iTrend = helper.GetTrend(i);
//
bool isTrendBullishRejected =
has &&
iBar.low < iTrend &&
iBar.GetDown() > iTrend;
//
bool isTrendBearishRejected =
has &&
iBar.high > iTrend &&
iBar.GetUp() < iTrend;
//
has =
has &&
(isBullish
? isTrendBullishRejected
: isTrendBearishRejected);
if (has)
{
break;
}
}
//
result = has;
}
//
// Filter Using Trend Inside ...
if (result &&
filters.forceHasTrendLineInside)
{
//
result =
result &&
conditions.trendBuffer[cIDX] > triggerBlock.ob.lower &&
conditions.trendBuffer[cIDX] < triggerBlock.ob.upper;
}
//
// Filter Using Trend Place ...
if (result &&
filters.forceHasTrendPlace)
{
//
toIDX = triggerBlock.ob.ToIndex();
fromIDX = triggerBlock.ob.FromIndex();
double mult =
isBullish
? 1
: -1;
double edge = isBullish
? triggerBlock.ob.lower
: triggerBlock.ob.upper;
double factor = edge + (mult * (triggerBlock.ob.GetRange() / 4));
for (int i = toIDX; i < fromIDX; i++)
{
//
double iTrend = helper.GetTrend(i);
//
has =
isBullish
? factor >= iTrend
: factor <= iTrend;
if (has)
{
break;
}
}
//
result = has;
}
}
//
// Filter Using Delta ...
if (result &&
filters.filterBasedOnDelta)
{
//
toIDX = triggerBlock.ob.ToIndex();
fromIDX = triggerBlock.ob.FromIndex();
//
for (int i = toIDX; i < fromIDX; i++)
{
//
double iDelta = helper.GetDelta(i);
double iPDelta = helper.GetDelta(i + 1);
//
double iDeltaSignal = helper.GetDeltaSignal(i);
double iPDeltaSignal = helper.GetDeltaSignal(i + 1);
//
bool isDeltaUp =
iDelta > iPDelta;
//
bool isDeltaDown =
iDelta < iPDelta;
//
bool isDeltaSignalUp =
iDeltaSignal > iPDeltaSignal;
//
bool isDeltaSignalDown =
iDeltaSignal < iPDeltaSignal;
//
bool isDeltaCrossedOverSignal =
iDelta > iDeltaSignal &&
iPDelta <= iPDeltaSignal;
//
bool isDeltaCrossedUnderSignal =
iDelta < iDeltaSignal &&
iPDelta >= iPDeltaSignal;
//
has =
isBullish
? (isDeltaUp &&
isDeltaSignalUp &&
isDeltaCrossedOverSignal)
: (isDeltaDown &&
isDeltaSignalDown &&
isDeltaCrossedUnderSignal);
if (has)
{
break;
}
}
//
result = has;
}
//
// Filter Using Volume ...
if (result &&
filters.filterBasedOnVolume)
{
//
toIDX = triggerBlock.ob.ToIndex();
fromIDX = triggerBlock.ob.FromIndex();
//
for (int i = toIDX; i < fromIDX; i++)
{
//
double iBullVolume = helper.GetBullishVolume(i);
double iPBullVolume = helper.GetBullishVolume(i + 1);
//
double iBullVolumeSignal = helper.GetBullishVolumeSignal(i);
double iPBullVolumeSignal = helper.GetBullishVolumeSignal(i + 1);
//
double iBearVolume = helper.GetBearishVolume(i);
double iPBearVolume = helper.GetBearishVolume(i + 1);
//
double iBearVolumeSignal = helper.GetBearishVolumeSignal(i);
double iPBearVolumeSignal = helper.GetBearishVolumeSignal(i + 1);
//
bool isBullVolumeUp =
iBullVolume > iPBullVolume;
//
bool isBullVolumeSignalUp =
iBullVolumeSignal > iPBullVolumeSignal;
//
bool isBearVolumeUp =
iBearVolume > iPBearVolume;
//
bool isBearVolumeSignalUp =
iBearVolumeSignal > iPBearVolumeSignal;
//
bool isVolumeSwitchedToBullish =
iBullVolumeSignal > iBearVolumeSignal &&
iPBullVolumeSignal <= iPBearVolumeSignal;
//
bool isVolumeSwitchedToBearish =
iBearVolumeSignal > iBullVolumeSignal &&
iPBearVolumeSignal <= iPBullVolumeSignal;
//
has =
isBullish
? (isBullVolumeUp &&
isBullVolumeSignalUp &&
isVolumeSwitchedToBullish)
: (isBearVolumeUp &&
isBearVolumeSignalUp &&
isVolumeSwitchedToBearish);
if (has)
{
break;
}
}
//
result = has;
}
//
// Filter Using Signal Bar ...
if (result &&
filters.filterBasedOnSignalBar)
{
//
toIDX = triggerBlock.ob.ToIndex();
fromIDX = triggerBlock.ob.FromIndex();
//
double iSOpen = helper.GetSBarOpen(toIDX);
double iPSOpen = helper.GetSBarOpen(toIDX + 1);
//
double iSClose = helper.GetSBarClose(toIDX);
double iPSClose = helper.GetSBarClose(toIDX + 1);
//
double iSPow = MathAbs(iSOpen - iSClose);
double iPSPow = MathAbs(iPSOpen - iPSClose);
//
result =
result &&
iSPow > iPSPow &&
(isBullish
? iSClose > iSOpen
: iSClose < iSOpen);
//
// Now Looking for Dir Change ...
if (result)
{
//
for (int i = toIDX; i < fromIDX; i++)
{
//
iSOpen = helper.GetSBarOpen(toIDX);
iPSOpen = helper.GetSBarOpen(toIDX + 1);
//
iSClose = helper.GetSBarClose(toIDX);
iPSClose = helper.GetSBarClose(toIDX + 1);
//
bool isSBullish =
iSClose > iSOpen;
//
bool isPSBullish =
iPSClose > iPSOpen;
//
bool isSBearish =
iSClose < iSOpen;
//
bool isPSBearish =
iPSClose < iPSOpen;
//
bool isSSwitchedToBullish =
isSBullish &&
!isPSBullish;
//
bool isSSwitchedToBearish =
isSBearish &&
!isPSBearish;
//
has =
isBullish
? isSSwitchedToBullish
: isSSwitchedToBearish;
if (has)
{
break;
}
}
//
result = has;
}
}
//
// Filter Using Signal Bar ...
if (result &&
filters.filterBasedOnHKSignalBar)
{
//
toIDX = triggerBlock.ob.ToIndex();
fromIDX = triggerBlock.ob.FromIndex();
//
double iSOpen = helper.GetHKSBarOpen(toIDX);
double iPSOpen = helper.GetHKSBarOpen(toIDX + 1);
//
double iSClose = helper.GetHKSBarClose(toIDX);
double iPSClose = helper.GetHKSBarClose(toIDX + 1);
//
double iSPow = MathAbs(iSOpen - iSClose);
double iPSPow = MathAbs(iPSOpen - iPSClose);
//
result =
result &&
iSPow > iPSPow &&
(isBullish
? iSClose > iSOpen
: iSClose < iSOpen);
//
// Now Looking for Dir Change ...
if (result)
{
//
for (int i = toIDX; i < fromIDX; i++)
{
//
iSOpen = helper.GetHKSBarOpen(toIDX);
iPSOpen = helper.GetHKSBarOpen(toIDX + 1);
//
iSClose = helper.GetHKSBarClose(toIDX);
iPSClose = helper.GetHKSBarClose(toIDX + 1);
//
bool isSBullish =
iSClose > iSOpen;
//
bool isPSBullish =
iPSClose > iPSOpen;
//
bool isSBearish =
iSClose < iSOpen;
//
bool isPSBearish =
iPSClose < iPSOpen;
//
bool isSSwitchedToBullish =
isSBullish &&
!isPSBullish;
//
bool isSSwitchedToBearish =
isSBearish &&
!isPSBearish;
//
has =
isBullish
? isSSwitchedToBullish
: isSSwitchedToBearish;
if (has)
{
break;
}
}
//
result = has;
}
}
//
if (!result)
{
triggerBlock.Clean();
}
//
// Summarize result ...
result = triggerBlock.IsValid();
//
// Cleanup Resources ...
//
iBar.Clean();
//
if (!result)
{
//
conditions.Clean();
triggerBlock.Clean();
}
//
return result;
}
//
void ValidateTriggerBlockLiquidities(
XCX121XCatbHelper *helper,
XCBarAnalyser *barAnalyser,
XTriggerBlock &triggerBlock,
X121XCatbConditions &conditions,
XTriggerBlockValidationRules &validations //
)
{
//
bool has = false;
//
has =
helper != NULL &&
barAnalyser != NULL &&
triggerBlock.IsValid() &&
(triggerBlock.fLiquidity.IsValid() ||
triggerBlock.rLiquidity.IsValid());
if (!has)
{
return;
}
//
bool hasFLiq = triggerBlock.fLiquidity.IsValid();
bool hasRLiq = triggerBlock.rLiquidity.IsValid();
//
// TODO: Implement Liquidity Validation ...
}
//
bool DetectSignalZone(
XCPOIDrawer *&drawer,
XCX121XCatbHelper *helper,
XCBarAnalyser *barAnalyser,
XBoxZone &signalZone,
X121XCatbConditions &conditions,
int barIndex = 0,
int loopback = 10 //
)
{
//
bool result = false;
//
// Checking Conditions ...
//
// Normalize Args ...
signalZone.Clean();
conditions.Clean();
barIndex = NormalizeInt(barIndex, 0);
loopback = NormalizeInt(loopback, 0);
//
// Validate Args ...
result = helper != NULL &&
barAnalyser != NULL;
if (!result)
{
return result;
}
//
// Reading Market Conditions ...
result = helper.GetConditions(
conditions,
barIndex,
loopback //
);
if (!result)
{
//
signalZone.Clean();
conditions.Clean();
//
return result;
}
//
int zIDX = 0;
int cIDX = zIDX + 1;
int pIDX = cIDX + 1;
int p2IDX = pIDX + 1;
int p3IDX = p2IDX + 1;
int p4IDX = p3IDX + 1;
//
double sl = 0;
double tp = 0;
double upper = 0;
double lower = 0;
datetime to = NULL;
datetime from = NULL;
string signalProvider = NULL;
//
// Checking Conditions ...
//
// Detect Bar Verifications ...
//
ENUM_X_DIRECTION iDir;
//
// Rejected ...
bool isRejected =
barAnalyser
.IsRejected(
conditions.bars[cIDX],
iDir //
);
bool isBullishRejected =
isRejected &&
IsBullish(iDir);
bool isBearishRejected =
isRejected &&
IsBearish(iDir);
//
// Engulfed ...
bool isEngulfed =
barAnalyser
.IsEngulfed(
conditions.bars[cIDX],
iDir //
);
bool isBullishEngulfed =
isEngulfed &&
IsBullish(iDir);
bool isBearishEngulfed =
isEngulfed &&
IsBearish(iDir);
//
// Momentum ...
bool isMomentum =
barAnalyser
.IsMomentum(
conditions.bars[cIDX],
iDir //
);
bool isBullishMomentum =
isMomentum &&
IsBullish(iDir);
bool isBearishMomentum =
isMomentum &&
IsBearish(iDir);
//
bool isBarBullishPressured =
isBullishRejected ||
isBullishEngulfed ||
isBullishMomentum;
//
bool isBarBearishPressured =
isBearishRejected ||
isBearishEngulfed ||
isBearishMomentum;
//
// Detect Indicator Base Start Directional Movement ...
//
// SAR ...
//
bool isSarBullishStart =
//
(
//
// Current SAR is Directional ...
conditions.isSarBullish &&
//
// Previous InDirectional Sar Exists ...
helper.lastSarBearish.IsValid() &&
//
// Current Close is Over previous Sar ...
conditions.bars[cIDX].close > helper.lastSarBearish.after &&
//
// Before Close is not Over previous Sar ...
conditions.bars[pIDX].close <= helper.lastSarBearish.after
//
)
//
;
//
bool isSarBearishStart =
//
(
//
// Current SAR is Directional ...
conditions.isSarBearish &&
//
// Previous InDirectional Sar Exists ...
helper.lastSarBullish.IsValid() &&
//
// Current Close is Under previous ...
conditions.bars[cIDX].close < helper.lastSarBullish.after &&
//
// Before Close is not Under previous ...
conditions.bars[pIDX].close >= helper.lastSarBullish.after
//
)
//
;
//
// TREND ...
//
bool isTrendBullishStart =
//
(
//
// Current Trend is Directional ...
conditions.isTrendBullish &&
//
// Previous InDirectiona; Trend Exists ...
helper.lastTrendBearish.IsValid() &&
//
// Current Close is Over previous ...
conditions.bars[cIDX].close > helper.lastTrendBearish.after &&
//
// Before close is not Over previous ...
conditions.bars[pIDX].close <= helper.lastTrendBearish.after
//
)
//
;
//
bool isTrendBearishStart =
//
(
//
// Current Trend is Directional ...
conditions.isTrendBearish &&
//
// Previous InDirectiona; Trend Exists ...
helper.lastTrendBullish.IsValid() &&
//
// Current Close is Under previous ...
conditions.bars[cIDX].close < helper.lastTrendBullish.after &&
//
// Before close is not Under previous ...
conditions.bars[pIDX].close >= helper.lastTrendBullish.after
//
)
//
;
//
// ADX ...
//
bool isADXBullishStart =
//
(
//
// ADX Value is Switched to Strong ...
conditions.adxBuffer[cIDX] > conditions.adxThreshold &&
conditions.adxBuffer[pIDX] <= conditions.adxThreshold &&
//
// ADX must Up ...
conditions.adxBuffer[cIDX] > conditions.adxBuffer[pIDX] &&
//
// ADX +DI is Bigger than -DI ...
conditions.adxpBuffer[cIDX] > conditions.adxnBuffer[cIDX] &&
//
// ADX +DI is Up ...
conditions.adxpBuffer[cIDX] > conditions.adxpBuffer[pIDX]
//
)
//
;
//
bool isADXBearishStart =
//
(
//
// ADX Value is Switched to Strong ...
conditions.adxBuffer[cIDX] > conditions.adxThreshold &&
conditions.adxBuffer[pIDX] <= conditions.adxThreshold &&
//
// ADX must Up ...
conditions.adxBuffer[cIDX] > conditions.adxBuffer[pIDX] &&
//
// ADX -DI is Bigger than +DI ...
conditions.adxnBuffer[cIDX] > conditions.adxpBuffer[cIDX] &&
//
// ADX -DI is Up ...
conditions.adxnBuffer[cIDX] > conditions.adxnBuffer[pIDX]
//
)
//
;
//
// DELTA ...
//
bool isDeltaBullishStart =
//
// Check State ...
(
//
// Delta is Up ...
conditions.deltaBuffer[cIDX] > conditions.deltaBuffer[pIDX] &&
//
// Delta Signal is Up ...
conditions.deltaSignalBuffer[cIDX] > conditions.deltaSignalBuffer[pIDX] &&
//
// Delta Crossed Over Delta Signal ...
conditions.deltaBuffer[cIDX] > conditions.deltaSignalBuffer[cIDX]
//
)
//
&&
//
// Check Last InDirectional Exists ...
helper.lastDeltaBearish.IsValid() &&
//
// Current Close is Over last ...
conditions.bars[cIDX].close > helper.lastDeltaBearish.after &&
//
// Before Close is not Over last ...
conditions.bars[pIDX].close <= helper.lastDeltaBearish.after
//
;
//
bool isDeltaBearishStart =
//
// Check State ...
(
//
// Delta is Down ...
conditions.deltaBuffer[cIDX] < conditions.deltaBuffer[pIDX] &&
//
// Delta Signal is Down ...
conditions.deltaSignalBuffer[cIDX] < conditions.deltaSignalBuffer[pIDX] &&
//
// Delta Crossed Under Delta Signal ...
conditions.deltaBuffer[cIDX] < conditions.deltaSignalBuffer[cIDX]
//
)
//
&&
//
// Check Last InDirectional Exists ...
helper.lastDeltaBullish.IsValid() &&
//
// Current Close is Under last ...
conditions.bars[cIDX].close < helper.lastDeltaBullish.after &&
//
// Before Close is not Under last ...
conditions.bars[pIDX].close >= helper.lastDeltaBullish.after
//
;
//
// VOLUME ...
//
bool isVolumeBullishStart =
//
(
//
//
// Volume is Up ...
conditions.bullishVolumeBuffer[1] > conditions.bullishVolumeBuffer[2] &&
//
// Volume Signal is Up ...
conditions.bullishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[2] &&
//
// Volume Signals Crossed Over ...
conditions.bullishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[1]
//
)
//
&&
//
// Check Last InDirectional Exists ...
helper.lastVolumeBearish.IsValid() &&
//
// Current Close is Over last ...
conditions.bars[cIDX].close > helper.lastVolumeBearish.after &&
//
// Before Close is not Over last ...
conditions.bars[pIDX].close <= helper.lastVolumeBearish.after
//
;
//
bool isVolumeBearishStart =
//
(
//
//
// Volume is Up ...
conditions.bearishVolumeBuffer[1] > conditions.bearishVolumeBuffer[2] &&
//
// Volume Signal is Up ...
conditions.bearishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[2] &&
//
// Volume Signals Crossed Over ...
conditions.bearishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[1]
//
)
//
&&
//
// Check Last InDirectional Exists ...
helper.lastVolumeBullish.IsValid() &&
//
// Current Close is Over last ...
conditions.bars[cIDX].close < helper.lastVolumeBullish.after &&
//
// Before Close is not Over last ...
conditions.bars[pIDX].close >= helper.lastVolumeBullish.after
//
;
//
// SIGNAL Bar ...
//
bool isSBarBullishStart =
//
(
//
// Check Direction ...
conditions.isSBarBullish &&
//
// Previous InDirectional Exists ...
helper.lastSignalBarBearish.IsValid() &&
//
// Current Signal Bar close over prev ...
conditions.sBarCloseBuffer[cIDX] > helper.lastSignalBarBearish.after &&
//
// Prev Signal Bar not close over prev ...
conditions.sBarCloseBuffer[pIDX] <= helper.lastSignalBarBearish.after
//
)
//
;
//
bool isSBarBearishStart =
//
(
//
// Check Direction ...
conditions.isSBarBearish &&
//
// Previous InDirectional Exists ...
helper.lastSignalBarBullish.IsValid() &&
//
// Current Signal Bar close over prev ...
conditions.sBarCloseBuffer[cIDX] < helper.lastSignalBarBullish.after &&
//
// Prev Signal Bar not close over prev ...
conditions.sBarCloseBuffer[pIDX] >= helper.lastSignalBarBullish.after
//
)
//
;
//
// HKSIGNAL Bar ...
//
bool isHKSBarBullishStart =
//
(
//
// Check Direction ...
conditions.isHKSBarBullish &&
//
// Previous InDirectional Exists ...
helper.lastHKSignalBarBearish.IsValid() &&
//
// Current Signal Bar close over prev ...
conditions.hkSBarCloseBuffer[cIDX] > helper.lastHKSignalBarBearish.after &&
//
// Prev Signal Bar not close over prev ...
conditions.hkSBarCloseBuffer[pIDX] <= helper.lastHKSignalBarBearish.after
//
)
//
;
//
bool isHKSBarBearishStart =
//
(
//
// Check Direction ...
conditions.isHKSBarBearish &&
//
// Previous InDirectional Exists ...
helper.lastHKSignalBarBullish.IsValid() &&
//
// Current Signal Bar close over prev ...
conditions.hkSBarCloseBuffer[cIDX] < helper.lastHKSignalBarBullish.after &&
//
// Prev Signal Bar not close over prev ...
conditions.hkSBarCloseBuffer[pIDX] >= helper.lastHKSignalBarBullish.after
//
)
//
;
//
// Check for Vale and Peak ...
//
bool isPeakOverLast =
//
(conditions.peakBuffer[cIDX] > conditions.peakBuffer[pIDX] &&
conditions.peakBuffer[pIDX] <= conditions.peakBuffer[p2IDX] &&
conditions.bars[cIDX].close > conditions.peakBuffer[pIDX])
//
;
//
bool isValeUnderLast =
//
(conditions.valeBuffer[cIDX] < conditions.valeBuffer[pIDX] &&
conditions.valeBuffer[pIDX] >= conditions.valeBuffer[p2IDX] &&
conditions.bars[cIDX].close < conditions.valeBuffer[pIDX])
//
;
//
// Start Different Conditions Implemntation ...
//
// Condition 1:
// ---------------------------
// Descriptions:
//
//
// ---------------------------
//
// Bullish ...
bool isCond1Bullish = false;
//
// Bearish ...
bool isCond1Bearish = false;
//
bool isCond1 =
isCond1Bullish ||
isCond1Bearish;
if (isCond1)
{
//
// Prepare Cond1 Based Requirements ...
//
to = NULL;
upper = 0;
lower = 0;
from = NULL;
//
// Provider Definition ...
signalProvider = "Cond1";
}
//
// Try to Summarize Conditions ...
//
bool isBullish =
//
isCond1Bullish
//
;
//
bool isBearish =
//
isCond1Bearish
//
;
//
// Summarize Result ...
result =
isBullish ||
isBearish;
if (result)
{
//
// Prepare Signal Zone ...
//
signalZone.to = to;
signalZone.from = from;
signalZone.upper = upper;
signalZone.lower = lower;
signalZone.type = signalProvider;
signalZone.symbol = conditions.symbol;
signalZone.period = conditions.period;
//
signalZone.dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
// Validate Signal Zone ...
result = signalZone.IsValid();
}
//
// Cleanup Resources ...
//
if (!result)
{
//
signalZone.Clean();
conditions.Clean();
}
//
return result;
}
//
// Draw Specific Trigger Block ...
bool DrawTriggerBlock(
XTriggerBlock &trigger,
XCPOIDrawer *drawer,
CArrayObj &objects,
datetime to = NULL,
//
bool _drawSignals = false,
int rrZoneLength = 10,
// Styles ...
//
// Trigger Block ...
int tbWidth = 1, // Trigger Block Width
color tbBullishColor = clrAqua, // Trigger Block Bullish Color
color tbBearishColor = clrMagenta, // Trigger Block Bearish Color
ENUM_LINE_STYLE tbStyle = STYLE_DASHDOTDOT, // Trigger Block Style
//
// OB ...
int obWidth = 1, // OB Width
color obBullishColor = clrLime, // OB Bullish Color
color obBearishColor = clrRed, // OB Bearish Color
ENUM_LINE_STYLE obStyle = STYLE_DOT, // OB Style
//
// FVG ...
int fvgWidth = 2, // FVG Width
color fvgBullishColor = clrLime, // FVG Bullish Color
color fvgBearishColor = clrRed, // FVG Bearish Color
ENUM_LINE_STYLE fvgStyle = STYLE_SOLID // FVG Style
)
{
//
bool result = false;
//
// Validate Args ...
result = trigger.IsValid() &&
drawer != NULL;
if (!result)
{
return result;
}
//
XTriggerBlock _trigger = trigger;
//
// Update To ...
bool canUpdateTo = IsValid(to);
if (canUpdateTo)
{
//
_trigger.trigger.to = to;
_trigger.rLiquidity.to = to;
_trigger.fLiquidity.to = to;
}
//
bool isBullish = _trigger.IsBullish();
//
// Draw OB ...
if (_trigger.ob.IsValid())
{
//
XCBoxObject *iOBObj;
result = drawer.DrawBox(
_trigger.ob,
iOBObj //
);
if (result)
{
//
// Style Object ...
//
color iClr =
isBullish
? obBullishColor
: obBearishColor;
//
iOBObj.BoxColor(iClr);
iOBObj.BoxWidth(obWidth);
iOBObj.BoxStyle(obStyle);
//
// Store Object ...
objects.Add(iOBObj);
}
ZeroMemory(iOBObj);
//
if (!result)
{
return result;
}
}
//
// Draw FVG ...
if (_trigger.fvg.IsValid())
{
//
XCBoxObject *iFVGObj;
result = drawer.DrawBox(
_trigger.fvg,
iFVGObj //
);
if (result)
{
//
// Style Object ...
//
color iClr =
isBullish
? fvgBullishColor
: fvgBearishColor;
//
iFVGObj.BoxColor(iClr);
iFVGObj.BoxWidth(fvgWidth);
iFVGObj.BoxStyle(fvgStyle);
//
// Store Object ...
objects.Add(iFVGObj);
}
ZeroMemory(iFVGObj);
//
if (!result)
{
return result;
}
}
//
// Draw Trigger ...
if (_trigger.trigger.IsValid())
{
//
XCBoxObject *iTriggerObj;
result = drawer.DrawBox(
_trigger.trigger,
iTriggerObj //
);
if (result)
{
//
// Style Object ...
//
color iClr =
isBullish
? tbBullishColor
: tbBearishColor;
//
iTriggerObj.BoxColor(iClr);
iTriggerObj.BoxWidth(tbWidth);
iTriggerObj.BoxStyle(tbStyle);
//
// Store Object ...
objects.Add(iTriggerObj);
}
ZeroMemory(iTriggerObj);
//
if (!result)
{
return result;
}
}
//
// Draw Liquidities ...
//
// Reversla Liquidity ...
if (_trigger.rLiquidity.IsValid())
{
//
XCBoxObject *iLiqObj;
result = drawer.DrawBox(
_trigger.rLiquidity,
iLiqObj //
);
if (result)
{
objects.Add(iLiqObj);
}
ZeroMemory(iLiqObj);
//
if (!result)
{
return result;
}
}
//
// Following Liquidity ...
if (_trigger.fLiquidity.IsValid())
{
//
XCBoxObject *iLiqObj;
result = drawer.DrawBox(
_trigger.fLiquidity,
iLiqObj //
);
if (result)
{
objects.Add(iLiqObj);
}
ZeroMemory(iLiqObj);
//
if (!result)
{
return result;
}
}
//
// Draw Swing Bar ...
if (_trigger.swingBar.IsValid())
{
//
color swingColor =
_trigger.fvg.IsBullish()
? clrAqua
: clrMagenta;
ENUM_X_PRICE swingPType =
_trigger.fvg.IsBullish()
? X_PRICE_LOW
: X_PRICE_HIGH;
//
XCBarArrowObject *swingObj;
result = drawer.CreateBarArrow(
_trigger.swingBar,
swingObj,
swingPType,
159,
swingColor //
);
if (result)
{
objects.Add(swingObj);
}
ZeroMemory(swingObj);
//
if (!result)
{
return result;
}
}
//
// Draw RR of Signal ...
if (_drawSignals &&
_trigger.signal.IsValid() &&
rrZoneLength > 0)
{
//
XCRRObject *iRRObj;
iRRObj = new XCRRObject();
result = iRRObj.Create(
drawer.ChartIdentification(),
drawer.SubWindowIdentification(),
_trigger.signal,
rrZoneLength //
);
if (result)
{
//
int iWidth = 2;
ENUM_LINE_STYLE iStyle = STYLE_SOLID;
//
iRRObj.TPWidth(iWidth);
iRRObj.SLWidth(iWidth);
iRRObj.EntryWidth(iWidth);
iRRObj.TargetWidth(iWidth);
//
iRRObj.TPStyle(iStyle);
iRRObj.SLStyle(iStyle);
iRRObj.EntryStyle(iStyle);
iRRObj.TargetStyle(iStyle);
//
iRRObj.TPColor(clrLime);
iRRObj.SLColor(clrRed);
iRRObj.EntryColor(clrYellow);
iRRObj.TargetColor(clrLightBlue);
//
objects.Add(iRRObj);
}
ZeroMemory(iRRObj);
//
if (result)
{
return result;
}
}
//
return result;
}