2802 lines
64 KiB
Plaintext
2802 lines
64 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Indicator
|
|
// -------------------------------------------------
|
|
// Name: X121 X3MA
|
|
// Description: X3MA ...
|
|
//
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
|
#property link "https://saherelm.ir"
|
|
#property version "1.00"
|
|
#property description "SaherElm X121 XCZone Indicator"
|
|
#property strict
|
|
|
|
//
|
|
// Definitions ...
|
|
|
|
//
|
|
#define ShortName "X121 XCZone"
|
|
|
|
//
|
|
// Includes Common Library ...
|
|
#include "../Classes/x-saherelm.x-alert.class.mq5"
|
|
#include "../Classes/x-saherelm.x-bar.analyser.class.mq5"
|
|
#include "../Classes/x-saherelm.x-poi.drawer.class.mq5"
|
|
#include "../Libraries/x-saherelm.common.lib.mq5"
|
|
#include "../Libraries/x-saherelm.x-poi.lib.mq5"
|
|
|
|
//
|
|
enum ENUM_XCAEA_TIGGER_TYPE
|
|
{
|
|
XCA_TRIGGER_NONE, // None
|
|
XCA_TRIGGER_BULL, // TriggerBull
|
|
XCA_TRIGGER_BEAR, // TriggerBear
|
|
};
|
|
|
|
//
|
|
bool IsValid(ENUM_XCAEA_TIGGER_TYPE value)
|
|
{
|
|
return value != XCA_TRIGGER_NONE;
|
|
}
|
|
|
|
//
|
|
string ToString(ENUM_XCAEA_TIGGER_TYPE value)
|
|
{
|
|
return EnumToString(value);
|
|
}
|
|
|
|
//
|
|
ENUM_XCAEA_TIGGER_TYPE GetType(string type)
|
|
{
|
|
//
|
|
ENUM_XCAEA_TIGGER_TYPE result = XCA_TRIGGER_NONE;
|
|
|
|
//
|
|
bool isTriggerBull = type == ToString(XCA_TRIGGER_BULL);
|
|
bool isTriggerBear = type == ToString(XCA_TRIGGER_BEAR);
|
|
|
|
//
|
|
if (isTriggerBull)
|
|
{
|
|
result = XCA_TRIGGER_BULL;
|
|
}
|
|
else if (isTriggerBear)
|
|
{
|
|
result = XCA_TRIGGER_BEAR;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION GetDirection(ENUM_XCAEA_TIGGER_TYPE value)
|
|
{
|
|
return value == XCA_TRIGGER_BULL
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
}
|
|
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
//
|
|
// Inputs ...
|
|
input group "Market";
|
|
input ENUM_X_PERIOD_METHOD trendPeriodMethod = X_PERIOD_AUTO; // How to Find Trend Period
|
|
input ENUM_TIMEFRAMES trendPeriod = NULL; // Trend Time Period
|
|
input ENUM_MA_METHOD trendMode = MODE_SMA; // Trend Mode
|
|
input ENUM_APPLIED_PRICE trendAppliedTo = PRICE_CLOSE; // Trend Applied To
|
|
input double sarStep = 0.02; // Sar Step
|
|
input double sarMax = 0.2; // Sar Maximum
|
|
input int adxLength = 14; // ADX Length
|
|
input double adxThreshold = 25.0; // ADX Threshold
|
|
input int rsiLength = 14; // RSI Length
|
|
input double rsiOBLevel = 70.0; // RSI OB Level
|
|
input double rsiOSLevel = 30.0; // RSI OS Level
|
|
input ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // RSI Applied To
|
|
input int atrLength = 14; // ATR Length
|
|
input int barsSignalLength = 14; // Bars Signal Length
|
|
input ENUM_X_MA_METHOD barsSignalMethod = X_MA_MODE_EMA; // Bars Signalling Method
|
|
input int deltaSignalLength = 14; // Delta Signal Length
|
|
input ENUM_X_MA_METHOD deltaSignalMethod = X_MA_MODE_EMA; // Delta Signalling Method
|
|
input int volumeSignalLength = 14; // Volume Signal Length
|
|
input ENUM_X_MA_METHOD volumeSignalMethod = X_MA_MODE_EMA; // Volume Signalling Method
|
|
input int hkSignalBarLength = 14; // Hiken Ashi Signal Length
|
|
input ENUM_X_MA_METHOD hkSignalBarMethod = X_MA_MODE_EMA; // Hiken Ashi Signal Method
|
|
|
|
//
|
|
// Validating ...
|
|
input group "Validating";
|
|
input bool forceHasSwing = true; // Force Blocks to Have Swing
|
|
input bool forceHasFLiquidity = false; // Force Blocks to Have Following Liquidity
|
|
input bool forceHasRLiquidity = false; // Force Blocks to Have Reversal Liquidity
|
|
input bool validateGapSequence = false; // Validate Block's Gap Sequence
|
|
input bool validateBlockEdgeBreakout = false; // Validate Block's Edge Breakout
|
|
|
|
//
|
|
// Filtering ...
|
|
input group "Filtering";
|
|
input bool filterBasedOnSar = false; // Filter Based on Sar
|
|
input bool filterBasedOnRSI = false; // Filter Based on RSI
|
|
input bool filterBasedOnADX = false; // Filter Based on ADX
|
|
input bool filterBasedOnTrend = false; // Filter Based on Trend
|
|
input bool filterBasedOnDelta = false; // Filter Based on Delta
|
|
input bool filterBasedOnVolume = false; // Filter Based on Volume
|
|
input bool filterBasedOnSignalBar = false; // Filter Based on Signal Bar
|
|
input bool filterBasedOnTrendBars = false; // Filter Based on Trend Bars
|
|
input bool filterBasedOnHKSignalBar = false; // Filter Based on Hiken Ashi Signal Bar
|
|
|
|
//
|
|
// Alert ...
|
|
input group "Alerts";
|
|
input string alertPrefix = ""; // Alert Prefix
|
|
input bool _logAlerts = true; // Log Alerts
|
|
input bool _pushAlerts = false; // Push Alerts
|
|
input bool _mailAlerts = false; // Mail Alerts
|
|
input bool _terminalAlerts = true; // Terminal Alerts
|
|
|
|
//
|
|
// Presentation ...
|
|
input group "Presentation";
|
|
input bool showBars = true; // Show Bars
|
|
input bool showSar = false; // Show Sar
|
|
input bool showTrend = false; // Show Trend
|
|
input bool showHKBars = false; // Show Hiken Ashi Bars
|
|
input bool showTrendBars = false; // Show Trend Bars
|
|
input bool showSignalBars = false; // Show Signal Bars
|
|
input bool showHKSignalBars = false; // Show Hiken Ashi Signal Bars
|
|
|
|
//
|
|
// Draws ...
|
|
input bool drawZones = true; // Draw Detected Zones
|
|
input bool drawSignals = true; // Draw Zone's Signal
|
|
|
|
//
|
|
input int startCalculationForLastBars = 1000; // Calculate Last n Bars
|
|
input int sarArrowCode = 159; // Sar Arrow Code
|
|
input int rrZoneLength = 7; // Draw Risk Reward Ratio till n Bars
|
|
input int maxSignalR2R = 4; // Max Allowed Signal R2R
|
|
input double slAtrMultiplier = 0; // Additional SL ATR Multiplier
|
|
|
|
//
|
|
// Styling ...
|
|
|
|
//
|
|
// Trigger Block ...
|
|
input int tbWidth = 1; // Trigger Block Width
|
|
input color tbBullishColor = clrAqua; // Trigger Block Bullish Color
|
|
input color tbBearishColor = clrMagenta; // Trigger Block Bearish Color
|
|
input ENUM_LINE_STYLE tbStyle = STYLE_DASHDOTDOT; // Trigger Block Style
|
|
|
|
//
|
|
// OB ...
|
|
input int obWidth = 1; // OB Width
|
|
input color obBullishColor = clrLime; // OB Bullish Color
|
|
input color obBearishColor = clrRed; // OB Bearish Color
|
|
input ENUM_LINE_STYLE obStyle = STYLE_DOT; // OB Style
|
|
|
|
//
|
|
// FVG ...
|
|
input int fvgWidth = 2; // FVG Width
|
|
input color fvgBullishColor = clrLime; // FVG Bullish Color
|
|
input color fvgBearishColor = clrRed; // FVG Bearish Color
|
|
input ENUM_LINE_STYLE fvgStyle = STYLE_SOLID; // FVG Style
|
|
|
|
//
|
|
// Buffers ...
|
|
|
|
//
|
|
#define hideColorIDX 0
|
|
#define bullishColorIDX 1
|
|
#define bearishColorIDX 2
|
|
#define neuturalColorIDX 3
|
|
|
|
//
|
|
#define bullishState 1
|
|
#define neuturalState 0
|
|
#define bearishState -1
|
|
|
|
//
|
|
#define emptyValue 0.0
|
|
|
|
//
|
|
#property indicator_chart_window
|
|
|
|
//
|
|
#property indicator_buffers 32
|
|
#property indicator_plots 5
|
|
|
|
//
|
|
// Plot Buffers ...
|
|
|
|
//
|
|
// TREND ...
|
|
|
|
//
|
|
#define trendBufferIndex 0
|
|
#define trendBufferPlotIndex 0
|
|
double trendBuffer[];
|
|
|
|
//
|
|
#define trendColorBufferIndex 1
|
|
double trendColorBuffer[];
|
|
|
|
//
|
|
#property indicator_label1 "X121 Trend"
|
|
#property indicator_type1 DRAW_COLOR_LINE
|
|
#property indicator_color1 CLR_NONE, clrAqua, clrMagenta, clrGray
|
|
#property indicator_style1 STYLE_DASH
|
|
#property indicator_width1 2
|
|
|
|
//
|
|
// SAR ...
|
|
|
|
//
|
|
#define sarBufferIndex 2
|
|
#define sarBufferPlotIndex 2
|
|
double sarBuffer[];
|
|
|
|
//
|
|
#define sarColorBufferIndex 3
|
|
double sarColorBuffer[];
|
|
|
|
//
|
|
#property indicator_label2 "X121 SAR"
|
|
#property indicator_type2 DRAW_COLOR_ARROW
|
|
#property indicator_color2 CLR_NONE, clrAqua, clrMagenta, clrGray
|
|
#property indicator_width2 2
|
|
|
|
//
|
|
// Signal Bar ...
|
|
|
|
//
|
|
#define openSignalBufferIndex 4
|
|
double openSignalBuffer[];
|
|
|
|
//
|
|
#define highSignalBufferIndex 5
|
|
double highSignalBuffer[];
|
|
|
|
//
|
|
#define lowSignalBufferIndex 6
|
|
double lowSignalBuffer[];
|
|
|
|
//
|
|
#define closeSignalBufferIndex 7
|
|
double closeSignalBuffer[];
|
|
|
|
//
|
|
#define signalBarColorBufferIndex 8
|
|
double signalBarColorBuffer[];
|
|
|
|
//
|
|
#define signalBarBufferIndex 2
|
|
#property indicator_label3 "X121 XSGB Open;X121 XSGB High;X121 XSGB Low;X121 XSGB Close"
|
|
#property indicator_type3 DRAW_COLOR_CANDLES
|
|
#property indicator_color3 CLR_NONE, clrLime, clrRed
|
|
|
|
//
|
|
// XHK ...
|
|
|
|
//
|
|
#define openHKBufferIndex 9
|
|
double openHKBuffer[];
|
|
|
|
//
|
|
#define highHKBufferIndex 10
|
|
double highHKBuffer[];
|
|
|
|
//
|
|
#define lowHKBufferIndex 11
|
|
double lowHKBuffer[];
|
|
|
|
//
|
|
#define closeHKBufferIndex 12
|
|
double closeHKBuffer[];
|
|
|
|
//
|
|
#define barHKColorBufferIndex 13
|
|
double barHKColorBuffer[];
|
|
|
|
//
|
|
#define barHKBufferIndex 3
|
|
#property indicator_label4 "X121 XHK Open;X121 XHK High;X121 XHK Low;X121 XHK Close"
|
|
#property indicator_type4 DRAW_COLOR_CANDLES
|
|
#property indicator_color4 CLR_NONE, clrDodgerBlue, clrDarkGoldenrod
|
|
|
|
//
|
|
// XHK SIGNAL ...
|
|
|
|
//
|
|
// Open ...
|
|
#define openHKSignalBufferIndex 14
|
|
double openHKSignalBuffer[];
|
|
|
|
//
|
|
// High ...
|
|
#define highHKSignalBufferIndex 15
|
|
double highHKSignalBuffer[];
|
|
|
|
//
|
|
// Low ...
|
|
#define lowHKSignalBufferIndex 16
|
|
double lowHKSignalBuffer[];
|
|
|
|
//
|
|
// Close ...
|
|
#define closeHKSignalBufferIndex 17
|
|
double closeHKSignalBuffer[];
|
|
|
|
//
|
|
// Candle Color ...
|
|
#define barHKSignalColorBufferIndex 18
|
|
double barHKSignalColorBuffer[];
|
|
|
|
//
|
|
#define barHKSignalBufferIndex 4
|
|
#property indicator_label5 "X121 XHKSM Open;X121 XHKSM High;X121 XHKSM Low;X121 XHKSM Close"
|
|
#property indicator_type5 DRAW_COLOR_CANDLES
|
|
#property indicator_color5 CLR_NONE, clrAqua, clrMagenta
|
|
|
|
//
|
|
// Data Buffers ...
|
|
|
|
#define mLastBufferIndex 18
|
|
|
|
//
|
|
// TREND State ...
|
|
|
|
//
|
|
#define trendStateBufferIndex mLastBufferIndex + 1
|
|
double trendStateBuffer[];
|
|
|
|
//
|
|
// SAR ...
|
|
|
|
//
|
|
#define sarStateBufferIndex mLastBufferIndex + 2
|
|
double sarStateBuffer[];
|
|
|
|
//
|
|
// RSI ...
|
|
|
|
//
|
|
#define rsiBufferIndex mLastBufferIndex + 3
|
|
double rsiBuffer[];
|
|
|
|
//
|
|
// ADX ...
|
|
|
|
//
|
|
#define adxBufferIndex mLastBufferIndex + 4
|
|
double adxBuffer[];
|
|
|
|
//
|
|
#define adxpBufferIndex mLastBufferIndex + 5
|
|
double adxpBuffer[];
|
|
|
|
//
|
|
#define adxnBufferIndex mLastBufferIndex + 6
|
|
double adxnBuffer[];
|
|
|
|
//
|
|
// DELTA ...
|
|
|
|
//
|
|
#define deltaBufferIndex mLastBufferIndex + 7
|
|
double deltaBuffer[];
|
|
|
|
//
|
|
#define deltaSignalBufferIndex mLastBufferIndex + 8
|
|
double deltaSignalBuffer[];
|
|
|
|
//
|
|
// VOLUMES ...
|
|
|
|
//
|
|
#define bullishVolumeBufferIndex mLastBufferIndex + 9
|
|
double bullishVolumeBuffer[];
|
|
|
|
//
|
|
#define bearishVolumeBufferIndex mLastBufferIndex + 10
|
|
double bearishVolumeBuffer[];
|
|
|
|
//
|
|
#define bullishVolumeSignalBufferIndex mLastBufferIndex + 11
|
|
double bullishVolumeSignalBuffer[];
|
|
|
|
//
|
|
#define bearishVolumeSignalBufferIndex mLastBufferIndex + 12
|
|
double bearishVolumeSignalBuffer[];
|
|
|
|
//
|
|
// ATR ...
|
|
#define atrBufferIndex mLastBufferIndex + 13
|
|
double atrBuffer[];
|
|
|
|
//
|
|
// Variables, Properties and etc ...
|
|
|
|
//
|
|
int limit;
|
|
|
|
//
|
|
int maxLength;
|
|
|
|
//
|
|
int firstBarIndex;
|
|
|
|
//
|
|
// Bars Color Variables ...
|
|
color _upColor = clrLime;
|
|
color _downColor = clrRed;
|
|
color _lineColor = clrLime;
|
|
color _bullishColor = clrLime;
|
|
color _bearishColor = clrRed;
|
|
|
|
//
|
|
XCAlert *alert;
|
|
double mPoints = 0;
|
|
CArrayObj mObjects;
|
|
XCPOIDrawer *drawer;
|
|
bool mEnableAlerts = false;
|
|
XCBarAnalyser *barAnalyser;
|
|
int mTrendPeriodLength = 0;
|
|
int atrHandler = INVALID_HANDLE;
|
|
int sarHandler = INVALID_HANDLE;
|
|
int rsiHandler = INVALID_HANDLE;
|
|
int adxHandler = INVALID_HANDLE;
|
|
int trendHandler = INVALID_HANDLE;
|
|
ENUM_TIMEFRAMES mTrendPeriod = NULL;
|
|
|
|
//
|
|
// Event Handlers ...
|
|
|
|
/**
|
|
* Initialize Indicator ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int OnInit()
|
|
{
|
|
//
|
|
// Validate Inputs ...
|
|
if (!ValidateInputs())
|
|
{
|
|
return INIT_PARAMETERS_INCORRECT;
|
|
}
|
|
|
|
//
|
|
// Initialize Indicator Handlers ...
|
|
|
|
//
|
|
// Configure Alert ...
|
|
alert = new XCAlert();
|
|
mEnableAlerts =
|
|
_logAlerts ||
|
|
_pushAlerts ||
|
|
_mailAlerts ||
|
|
_terminalAlerts;
|
|
string mPrefix = ShortName +
|
|
(!IsValid(alertPrefix)
|
|
? ""
|
|
: "[" + alertPrefix + "]");
|
|
alert.SetPrefix(mPrefix);
|
|
alert.SetLogAlerts(_logAlerts);
|
|
alert.SetMailAlerts(_mailAlerts);
|
|
alert.SetPushAlerts(_pushAlerts);
|
|
alert.SetEnableAlerts(mEnableAlerts);
|
|
alert.SetTerminalAlerts(_terminalAlerts);
|
|
|
|
//
|
|
drawer = new XCPOIDrawer();
|
|
barAnalyser = new XCBarAnalyser();
|
|
|
|
//
|
|
// Initializing TrendPeriod ...
|
|
int cPeriodSeconds = PeriodSeconds(_Period);
|
|
if (trendPeriodMethod == X_PERIOD_AUTO)
|
|
{
|
|
//
|
|
// Select Period ...
|
|
mTrendPeriod = GetCyclePeriod(
|
|
X_MARKET_CYCLE_HIND,
|
|
_Period //
|
|
);
|
|
}
|
|
else
|
|
{
|
|
mTrendPeriod = trendPeriod;
|
|
}
|
|
if (IsValid(mTrendPeriod))
|
|
{
|
|
mTrendPeriodLength = PeriodSeconds(mTrendPeriod) / cPeriodSeconds;
|
|
}
|
|
|
|
//
|
|
// ATR ...
|
|
atrHandler = iATR(
|
|
_Symbol,
|
|
_Period,
|
|
atrLength //
|
|
);
|
|
bool isInited = atrHandler != INVALID_HANDLE;
|
|
if (!isInited)
|
|
{
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
//
|
|
// SAR ...
|
|
sarHandler = iSAR(
|
|
_Symbol,
|
|
_Period,
|
|
sarStep,
|
|
sarMax //
|
|
);
|
|
isInited = sarHandler != INVALID_HANDLE;
|
|
if (!isInited)
|
|
{
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
//
|
|
// RSI ...
|
|
rsiHandler = iRSI(
|
|
_Symbol,
|
|
_Period,
|
|
rsiLength,
|
|
rsiAppliedTo //
|
|
);
|
|
isInited = rsiHandler != INVALID_HANDLE;
|
|
if (!isInited)
|
|
{
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
//
|
|
// ADX ...
|
|
adxHandler = iADX(
|
|
_Symbol,
|
|
_Period,
|
|
adxLength //
|
|
);
|
|
isInited = adxHandler != INVALID_HANDLE;
|
|
if (!isInited)
|
|
{
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
//
|
|
// TREND ...
|
|
trendHandler = iMA(
|
|
_Symbol,
|
|
_Period,
|
|
mTrendPeriodLength,
|
|
0,
|
|
trendMode,
|
|
trendAppliedTo //
|
|
);
|
|
isInited = trendHandler != INVALID_HANDLE;
|
|
if (!isInited)
|
|
{
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
//
|
|
mPoints = GetPoints(_Symbol);
|
|
|
|
//
|
|
// because in some cases we may have more than one input for
|
|
// calculation and we must prevent any calculation
|
|
// untill we pass the biggest input length, here we get max Input length
|
|
// and then wait until pass it ...
|
|
maxLength = ExtractMaxLengthOfInputs();
|
|
|
|
//
|
|
ReadBarStyle();
|
|
|
|
//
|
|
if (showBars)
|
|
{
|
|
ShowBars();
|
|
}
|
|
else
|
|
{
|
|
HideBars();
|
|
}
|
|
|
|
//
|
|
// Define Index Buffers ...
|
|
DefineBuffers();
|
|
|
|
//
|
|
// Set Indicator ShortName ...
|
|
SetIndicatorName();
|
|
|
|
//
|
|
// Init Succeed ...
|
|
return INIT_SUCCEEDED;
|
|
}
|
|
|
|
/**
|
|
* De Initialize Indicator ...
|
|
*
|
|
* @param reason: Integer, De Initialization Reason ...
|
|
*/
|
|
void OnDeinit(const int reason)
|
|
{
|
|
//
|
|
// REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function
|
|
// REASON_REMOVE 1 Program removed from a chart
|
|
// REASON_RECOMPILE 2 Program recompiled
|
|
// REASON_CHARTCHANGE 3 A symbol or a chart period is changed
|
|
// REASON_CHARTCLOSE 4 Chart closed
|
|
// REASON_PARAMETERS 5 Inputs changed by a user
|
|
// REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings
|
|
// REASON_TEMPLATE 7 Another chart template applied
|
|
// REASON_INITFAILED 8 The OnInit() handler returned a non-zero value
|
|
// REASON_CLOSE 9 Terminal closed
|
|
|
|
//
|
|
mObjects.Clear();
|
|
|
|
//
|
|
delete alert;
|
|
delete drawer;
|
|
|
|
//
|
|
ZeroMemory(alert);
|
|
ZeroMemory(drawer);
|
|
ZeroMemory(barAnalyser);
|
|
|
|
//
|
|
ShowBars();
|
|
|
|
//
|
|
IndicatorRelease(atrHandler);
|
|
IndicatorRelease(sarHandler);
|
|
IndicatorRelease(rsiHandler);
|
|
IndicatorRelease(adxHandler);
|
|
IndicatorRelease(trendHandler);
|
|
}
|
|
|
|
/**
|
|
* Calculate Bars ...
|
|
*
|
|
* @param rates_total: Integer, Total Bars on Chart ...
|
|
* @param prev_calculated: Integer, Total Calculated Bars on Charts ...
|
|
* @param time: DateTime Array, History of Open Time ...
|
|
* @param open: Double Array, History of Open Prices ...
|
|
* @param high: Double Array, History of High Prices ...
|
|
* @param low: Double Array, History of Low Prices ...
|
|
* @param close: Double Array, History of Close Prices ...
|
|
* @param tick_volume: Long, History of Tick Volumes on Bar ...
|
|
* @param volume: Long, History of Trade Volumes ...
|
|
* @param spread: Double, History of Spread Price ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int OnCalculate(
|
|
const int rates_total,
|
|
const int prev_calculated,
|
|
const datetime &time[],
|
|
const double &open[],
|
|
const double &high[],
|
|
const double &low[],
|
|
const double &close[],
|
|
const long &tick_volume[],
|
|
const long &volume[],
|
|
const int &spread[] //
|
|
)
|
|
{
|
|
//
|
|
// Prepare Buffers ...
|
|
ArraySetAsSeries(time, true);
|
|
ArraySetAsSeries(open, true);
|
|
ArraySetAsSeries(high, true);
|
|
ArraySetAsSeries(low, true);
|
|
ArraySetAsSeries(close, true);
|
|
ArraySetAsSeries(tick_volume, true);
|
|
ArraySetAsSeries(volume, true);
|
|
ArraySetAsSeries(spread, true);
|
|
|
|
//
|
|
// Validate Calculated Bars ...
|
|
|
|
//
|
|
// ATR ...
|
|
int atrCalculatedBars = BarsCalculated(atrHandler);
|
|
|
|
//
|
|
// SAR ...
|
|
int sarCalculatedBars = BarsCalculated(sarHandler);
|
|
|
|
//
|
|
// RSI ...
|
|
int rsiCalculatedBars = BarsCalculated(rsiHandler);
|
|
|
|
//
|
|
// ADX ...
|
|
int adxCalculatedBars = BarsCalculated(adxHandler);
|
|
|
|
//
|
|
// TREND ...
|
|
int trendCalculatedBars = BarsCalculated(trendHandler);
|
|
|
|
//
|
|
bool isPassedRequiredCalculatedBars =
|
|
//
|
|
// ATR ...
|
|
atrCalculatedBars >= maxLength &&
|
|
//
|
|
// SAR ...
|
|
sarCalculatedBars >= maxLength &&
|
|
//
|
|
// RSI ...
|
|
rsiCalculatedBars >= maxLength &&
|
|
//
|
|
// ADX ...
|
|
adxCalculatedBars >= maxLength &&
|
|
//
|
|
// TREND ...
|
|
trendCalculatedBars >= maxLength
|
|
//
|
|
;
|
|
if (!isPassedRequiredCalculatedBars)
|
|
{
|
|
return prev_calculated;
|
|
}
|
|
|
|
//
|
|
limit = (prev_calculated > rates_total || prev_calculated <= 0)
|
|
? rates_total
|
|
: (rates_total - prev_calculated) + 1;
|
|
|
|
//
|
|
// Buffers Copy ...
|
|
|
|
//
|
|
// ATR ...
|
|
int copiedAtrs = CopyBuffer(atrHandler, MAIN_LINE, 0, limit, atrBuffer);
|
|
|
|
//
|
|
// SAR ...
|
|
int copiedSars = CopyBuffer(sarHandler, MAIN_LINE, 0, limit, sarBuffer);
|
|
|
|
//
|
|
// RSI ...
|
|
int copiedRSIs = CopyBuffer(rsiHandler, MAIN_LINE, 0, limit, rsiBuffer);
|
|
|
|
//
|
|
// ADX ...
|
|
int copiedADXs = CopyBuffer(adxHandler, MAIN_LINE, 0, limit, adxBuffer);
|
|
|
|
//
|
|
// ADX Plus ...
|
|
int copiedADXPs = CopyBuffer(adxHandler, PLUSDI_LINE, 0, limit, adxpBuffer);
|
|
|
|
//
|
|
// ADX Negative ...
|
|
int copiedADXNs = CopyBuffer(adxHandler, MINUSDI_LINE, 0, limit, adxnBuffer);
|
|
|
|
//
|
|
// TREND ...
|
|
int copiedTrends = CopyBuffer(trendHandler, MAIN_LINE, 0, limit, trendBuffer);
|
|
|
|
//
|
|
// Validate Copied Items ...
|
|
bool isPassedRequiredCopiedItems =
|
|
//
|
|
// ATR ...
|
|
copiedAtrs >= limit &&
|
|
//
|
|
// SAR ...
|
|
copiedSars >= limit &&
|
|
//
|
|
// RSI ...
|
|
copiedRSIs >= limit &&
|
|
//
|
|
// TREND ...
|
|
copiedTrends >= limit
|
|
//
|
|
;
|
|
if (!isPassedRequiredCopiedItems)
|
|
{
|
|
return prev_calculated;
|
|
}
|
|
|
|
//
|
|
// Main Loop ...
|
|
for (int i = limit - 1; i >= 0 && !IsStopped(); i--)
|
|
{
|
|
//
|
|
CalculateBuffers(
|
|
i,
|
|
prev_calculated,
|
|
rates_total,
|
|
//
|
|
open,
|
|
high,
|
|
close,
|
|
low,
|
|
tick_volume //
|
|
);
|
|
}
|
|
|
|
//
|
|
return rates_total;
|
|
}
|
|
|
|
//
|
|
// Functions ...
|
|
|
|
/**
|
|
* Validate Input Args for Initialization ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ValidateInputs()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
sarMax > 0 &&
|
|
sarStep > 0 &&
|
|
adxLength > 0 &&
|
|
atrLength > 0 &&
|
|
rsiLength > 0 &&
|
|
rsiOBLevel > 0 &&
|
|
rsiOSLevel > 0 &&
|
|
sarMax > sarStep &&
|
|
barsSignalLength > 2 &&
|
|
deltaSignalLength > 2 &&
|
|
hkSignalBarLength > 2 &&
|
|
volumeSignalLength > 2 &&
|
|
barsSignalMethod != X_MA_MODE_NONE &&
|
|
deltaSignalMethod != X_MA_MODE_NONE &&
|
|
hkSignalBarMethod != X_MA_MODE_NONE &&
|
|
volumeSignalMethod != X_MA_MODE_NONE &&
|
|
IsValid(trendPeriodMethod, trendPeriod)
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extract Max Length of Inputs ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int ExtractMaxLengthOfInputs()
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
result = MathMax(adxLength, rsiLength);
|
|
result = MathMax(result, barsSignalLength);
|
|
result = MathMax(result, deltaSignalLength);
|
|
result = MathMax(result, volumeSignalLength);
|
|
result = MathMax(result, hkSignalBarLength);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Define Required Buffers ...
|
|
*/
|
|
void DefineBuffers()
|
|
{
|
|
//
|
|
// Plot Buffers ...
|
|
|
|
//
|
|
// TREND ...
|
|
|
|
//
|
|
ArraySetAsSeries(trendBuffer, true);
|
|
SetIndexBuffer(trendBufferIndex, trendBuffer, INDICATOR_DATA);
|
|
|
|
//
|
|
PlotIndexSetInteger(trendBufferPlotIndex, PLOT_SHOW_DATA, showTrend);
|
|
|
|
//
|
|
PlotIndexSetDouble(trendBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue);
|
|
|
|
//
|
|
ArraySetAsSeries(trendColorBuffer, true);
|
|
SetIndexBuffer(trendColorBufferIndex, trendColorBuffer, INDICATOR_COLOR_INDEX);
|
|
|
|
//
|
|
// SAR ...
|
|
|
|
//
|
|
ArraySetAsSeries(sarBuffer, true);
|
|
SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_DATA);
|
|
|
|
//
|
|
PlotIndexSetInteger(sarBufferPlotIndex, PLOT_SHOW_DATA, showSar);
|
|
|
|
//
|
|
PlotIndexSetDouble(sarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue);
|
|
PlotIndexSetInteger(sarBufferPlotIndex, PLOT_ARROW, sarArrowCode);
|
|
|
|
//
|
|
ArraySetAsSeries(sarColorBuffer, true);
|
|
SetIndexBuffer(sarColorBufferIndex, sarColorBuffer, INDICATOR_COLOR_INDEX);
|
|
|
|
//
|
|
// SIGNAL Bar ...
|
|
|
|
//
|
|
// Signal Bars Color ...
|
|
ArraySetAsSeries(signalBarColorBuffer, true);
|
|
SetIndexBuffer(signalBarColorBufferIndex, signalBarColorBuffer, INDICATOR_COLOR_INDEX);
|
|
|
|
//
|
|
// Set EMPTY_VALUE on XHK Bar Buffer ...
|
|
PlotIndexSetDouble(signalBarBufferIndex, PLOT_EMPTY_VALUE, 0.0);
|
|
PlotIndexSetInteger(signalBarBufferIndex, PLOT_SHOW_DATA, false);
|
|
|
|
//
|
|
// Open ...
|
|
ArraySetAsSeries(openSignalBuffer, true);
|
|
SetIndexBuffer(openSignalBufferIndex, openSignalBuffer, INDICATOR_DATA);
|
|
|
|
//
|
|
// High ...
|
|
ArraySetAsSeries(highSignalBuffer, true);
|
|
SetIndexBuffer(highSignalBufferIndex, highSignalBuffer, INDICATOR_DATA);
|
|
|
|
//
|
|
// Close ...
|
|
ArraySetAsSeries(closeSignalBuffer, true);
|
|
SetIndexBuffer(closeSignalBufferIndex, closeSignalBuffer, INDICATOR_DATA);
|
|
|
|
//
|
|
// Low ...
|
|
ArraySetAsSeries(lowSignalBuffer, true);
|
|
SetIndexBuffer(lowSignalBufferIndex, lowSignalBuffer, INDICATOR_DATA);
|
|
|
|
//
|
|
// XHK ...
|
|
|
|
//
|
|
// HK Bars Color ...
|
|
ArraySetAsSeries(barHKColorBuffer, true);
|
|
SetIndexBuffer(barHKColorBufferIndex, barHKColorBuffer, INDICATOR_COLOR_INDEX);
|
|
|
|
//
|
|
// Set EMPTY_VALUE on XHK Bar Buffer ...
|
|
PlotIndexSetDouble(barHKBufferIndex, PLOT_EMPTY_VALUE, 0.0);
|
|
PlotIndexSetInteger(barHKBufferIndex, PLOT_SHOW_DATA, false);
|
|
|
|
//
|
|
// Open ...
|
|
ArraySetAsSeries(openHKBuffer, true);
|
|
SetIndexBuffer(openHKBufferIndex, openHKBuffer, INDICATOR_DATA);
|
|
|
|
//
|
|
// High ...
|
|
ArraySetAsSeries(highHKBuffer, true);
|
|
SetIndexBuffer(highHKBufferIndex, highHKBuffer, INDICATOR_DATA);
|
|
|
|
//
|
|
// Close ...
|
|
ArraySetAsSeries(closeHKBuffer, true);
|
|
SetIndexBuffer(closeHKBufferIndex, closeHKBuffer, INDICATOR_DATA);
|
|
|
|
//
|
|
// Low ...
|
|
ArraySetAsSeries(lowHKBuffer, true);
|
|
SetIndexBuffer(lowHKBufferIndex, lowHKBuffer, INDICATOR_DATA);
|
|
|
|
//
|
|
// XHK SIGNAL ...
|
|
|
|
//
|
|
// HK Bars Color ...
|
|
ArraySetAsSeries(barHKSignalColorBuffer, true);
|
|
SetIndexBuffer(barHKSignalColorBufferIndex, barHKSignalColorBuffer, INDICATOR_COLOR_INDEX);
|
|
|
|
//
|
|
// Set EMPTY_VALUE on XHK Bar Buffer ...
|
|
PlotIndexSetDouble(barHKSignalBufferIndex, PLOT_EMPTY_VALUE, 0.0);
|
|
PlotIndexSetInteger(barHKSignalBufferIndex, PLOT_SHOW_DATA, false);
|
|
|
|
//
|
|
// Open ...
|
|
ArraySetAsSeries(openHKSignalBuffer, true);
|
|
SetIndexBuffer(openHKSignalBufferIndex, openHKSignalBuffer, INDICATOR_DATA);
|
|
|
|
//
|
|
// High ...
|
|
ArraySetAsSeries(highHKSignalBuffer, true);
|
|
SetIndexBuffer(highHKSignalBufferIndex, highHKSignalBuffer, INDICATOR_DATA);
|
|
|
|
//
|
|
// Close ...
|
|
ArraySetAsSeries(closeHKSignalBuffer, true);
|
|
SetIndexBuffer(closeHKSignalBufferIndex, closeHKSignalBuffer, INDICATOR_DATA);
|
|
|
|
//
|
|
// Low ...
|
|
ArraySetAsSeries(lowHKSignalBuffer, true);
|
|
SetIndexBuffer(lowHKSignalBufferIndex, lowHKSignalBuffer, INDICATOR_DATA);
|
|
|
|
//
|
|
// Data Buffers ...
|
|
|
|
//
|
|
ArraySetAsSeries(trendStateBuffer, true);
|
|
SetIndexBuffer(trendStateBufferIndex, trendStateBuffer, INDICATOR_CALCULATIONS);
|
|
|
|
//
|
|
ArraySetAsSeries(sarStateBuffer, true);
|
|
SetIndexBuffer(sarStateBufferIndex, sarStateBuffer, INDICATOR_CALCULATIONS);
|
|
|
|
//
|
|
ArraySetAsSeries(rsiBuffer, true);
|
|
SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_CALCULATIONS);
|
|
|
|
//
|
|
ArraySetAsSeries(adxBuffer, true);
|
|
SetIndexBuffer(adxBufferIndex, adxBuffer, INDICATOR_CALCULATIONS);
|
|
|
|
//
|
|
ArraySetAsSeries(adxpBuffer, true);
|
|
SetIndexBuffer(adxpBufferIndex, adxpBuffer, INDICATOR_CALCULATIONS);
|
|
|
|
//
|
|
ArraySetAsSeries(adxnBuffer, true);
|
|
SetIndexBuffer(adxnBufferIndex, adxnBuffer, INDICATOR_CALCULATIONS);
|
|
|
|
//
|
|
// DELTA ...
|
|
|
|
//
|
|
ArraySetAsSeries(deltaBuffer, true);
|
|
SetIndexBuffer(deltaBufferIndex, deltaBuffer, INDICATOR_CALCULATIONS);
|
|
|
|
//
|
|
ArraySetAsSeries(deltaSignalBuffer, true);
|
|
SetIndexBuffer(deltaSignalBufferIndex, deltaSignalBuffer, INDICATOR_CALCULATIONS);
|
|
|
|
//
|
|
// VOLUME ...
|
|
|
|
//
|
|
ArraySetAsSeries(bullishVolumeBuffer, true);
|
|
SetIndexBuffer(bullishVolumeBufferIndex, bullishVolumeBuffer, INDICATOR_CALCULATIONS);
|
|
|
|
//
|
|
ArraySetAsSeries(bearishVolumeBuffer, true);
|
|
SetIndexBuffer(bearishVolumeBufferIndex, bearishVolumeBuffer, INDICATOR_CALCULATIONS);
|
|
|
|
//
|
|
ArraySetAsSeries(bullishVolumeSignalBuffer, true);
|
|
SetIndexBuffer(bullishVolumeSignalBufferIndex, bullishVolumeSignalBuffer, INDICATOR_CALCULATIONS);
|
|
|
|
//
|
|
ArraySetAsSeries(bearishVolumeSignalBuffer, true);
|
|
SetIndexBuffer(bearishVolumeSignalBufferIndex, bearishVolumeSignalBuffer, INDICATOR_CALCULATIONS);
|
|
|
|
//
|
|
// ATR ...
|
|
ArraySetAsSeries(atrBuffer, true);
|
|
SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS);
|
|
}
|
|
|
|
/**
|
|
* Set Indicator Short Name and also we can define Buffers Labels ...
|
|
*/
|
|
void SetIndicatorName()
|
|
{
|
|
//
|
|
IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
|
|
IndicatorSetString(INDICATOR_SHORTNAME, ShortName);
|
|
}
|
|
|
|
/**
|
|
* Calculate Custom Buffers ...
|
|
*
|
|
* @param bar_index: Integer, Represent Current Bar ...
|
|
* @param prevCalculated: Integer, Represent Previous Calculated Bars ...
|
|
* @param ratesTotal: Integer, Represents All Available Bars ...
|
|
* @param open: Double Array, History of Open Prices ...
|
|
* @param high: Double Array, History of High Prices ...
|
|
* @param close: Double Array, History of Close Prices ...
|
|
* @param low: Double Array, History of Low Prices ...
|
|
* @param tickVolume: Long, History of Tick Volumes on Bar ...
|
|
*/
|
|
void CalculateBuffers(
|
|
int bar_index, // Selected Bar Index
|
|
const int prevCalculated,
|
|
const int ratesTotal,
|
|
const double &open[],
|
|
const double &high[],
|
|
const double &close[],
|
|
const double &low[],
|
|
const long &tickVolume[] //
|
|
)
|
|
{
|
|
//
|
|
int barsLimit = startCalculationForLastBars > 0
|
|
? startCalculationForLastBars
|
|
: 0;
|
|
if (barsLimit == 0)
|
|
{
|
|
//
|
|
barsLimit = ratesTotal;
|
|
firstBarIndex = barsLimit - 1;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
firstBarIndex = startCalculationForLastBars;
|
|
}
|
|
|
|
//
|
|
// bool canCalculate = true;
|
|
bool canCalculate =
|
|
bar_index <= barsLimit;
|
|
if (canCalculate)
|
|
{
|
|
//
|
|
// Calculate Values ...
|
|
CalculateValues(
|
|
bar_index,
|
|
prevCalculated,
|
|
ratesTotal,
|
|
open,
|
|
high,
|
|
close,
|
|
low,
|
|
tickVolume //
|
|
);
|
|
}
|
|
else
|
|
{
|
|
FillBuffersZero(bar_index);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fill All Bufers to Zero Vlue for Specified Bar Index ...
|
|
*
|
|
* @param barIndex: Integer ...
|
|
*/
|
|
void FillBuffersZero(int bar_index)
|
|
{
|
|
//
|
|
sarColorBuffer[bar_index] = hideColorIDX;
|
|
trendColorBuffer[bar_index] = hideColorIDX;
|
|
}
|
|
|
|
/**
|
|
* Calculate Values ...
|
|
*
|
|
* @param bar_index: int, Specified Bar Index ...
|
|
* @param prevCalculated: int, Provides Previous Calculated Bars ...
|
|
* @param ratesTotal: int, Provides All Availabled Bars ...
|
|
* @param open: double Collection, Provides Open Prices Time Series ...
|
|
* @param high: double Collection, Provides High Prices Time Series ...
|
|
* @param close: double Collection, Provides Close Prices Time Series ...
|
|
* @param low: double Collection, Provides Low Prices Time Series ...
|
|
* @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ...
|
|
*/
|
|
void CalculateValues(
|
|
int bar_index, // Selected Bar Index
|
|
const int prevCalculated,
|
|
const int ratesTotal,
|
|
const double &open[],
|
|
const double &high[],
|
|
const double &close[],
|
|
const double &low[],
|
|
const long &tickVolume[] //
|
|
)
|
|
{
|
|
//
|
|
int lastBarIndex = bar_index + 1;
|
|
bool isFirstBar =
|
|
startCalculationForLastBars > 0
|
|
? bar_index == startCalculationForLastBars
|
|
: bar_index == firstBarIndex;
|
|
|
|
//
|
|
// Bar Info ...
|
|
double iLow = high[bar_index];
|
|
double iHigh = high[bar_index];
|
|
double iClose = close[bar_index];
|
|
double iOpen = open[bar_index];
|
|
double iVolume = (double)iVolume(_Symbol, _Period, bar_index);
|
|
|
|
//
|
|
bool isBullish = iClose > iOpen;
|
|
bool isBearish = iClose < iOpen;
|
|
|
|
//
|
|
double points = GetPoints(_Symbol);
|
|
|
|
//
|
|
// Calculate Sar Color Buffer ...
|
|
double iSar = sarBuffer[bar_index];
|
|
|
|
//
|
|
double iSarState = neuturalState;
|
|
double iSarColor = neuturalColorIDX;
|
|
if (iLow > iSar)
|
|
{
|
|
//
|
|
iSarState = bullishState;
|
|
iSarColor = !showSar
|
|
? hideColorIDX
|
|
: bullishColorIDX;
|
|
}
|
|
else if (iHigh < iSar)
|
|
{
|
|
//
|
|
iSarState = bearishState;
|
|
iSarColor = !showSar
|
|
? hideColorIDX
|
|
: bearishColorIDX;
|
|
}
|
|
sarStateBuffer[bar_index] = iSarState;
|
|
sarColorBuffer[bar_index] = iSarColor;
|
|
|
|
//
|
|
// Calculate Trend Color Buffer ...
|
|
double iTrend = trendBuffer[bar_index];
|
|
|
|
//
|
|
double iTrendState = neuturalState;
|
|
double iTrendColor = neuturalColorIDX;
|
|
if (iClose > iTrend)
|
|
{
|
|
//
|
|
iTrendState = bullishState;
|
|
iTrendColor = !showTrend
|
|
? hideColorIDX
|
|
: bullishColorIDX;
|
|
}
|
|
else if (iClose < iTrend)
|
|
{
|
|
//
|
|
iTrendState = bearishState;
|
|
iTrendColor = !showTrend
|
|
? hideColorIDX
|
|
: bearishColorIDX;
|
|
}
|
|
trendStateBuffer[bar_index] = iTrendState;
|
|
trendColorBuffer[bar_index] = iTrendColor;
|
|
|
|
//
|
|
// DELTA ...
|
|
double lastDelta =
|
|
isFirstBar
|
|
? emptyValue
|
|
: deltaBuffer[lastBarIndex];
|
|
double iAppliedVolume =
|
|
isBullish
|
|
? iVolume
|
|
: -1 * iVolume;
|
|
double iDelta =
|
|
lastDelta + iAppliedVolume;
|
|
deltaBuffer[bar_index] = iDelta;
|
|
|
|
//
|
|
// Calculate Delta Signal ...
|
|
int deltaSignalsCount = iMAOnBuffer(
|
|
ratesTotal,
|
|
prevCalculated,
|
|
bar_index,
|
|
deltaSignalLength,
|
|
deltaBuffer,
|
|
deltaSignalBuffer,
|
|
deltaSignalMethod //
|
|
);
|
|
|
|
//
|
|
// VOLUME ...
|
|
|
|
//
|
|
double iBullishVolume = emptyValue;
|
|
double iBearishVolume = emptyValue;
|
|
if (isBullish)
|
|
{
|
|
iBullishVolume = iVolume;
|
|
}
|
|
else if (isBearish)
|
|
{
|
|
iBearishVolume = iVolume;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
double iHalfVolume = iVolume / 2;
|
|
|
|
//
|
|
iBullishVolume = iHalfVolume;
|
|
iBearishVolume = iHalfVolume;
|
|
}
|
|
bullishVolumeBuffer[bar_index] = iBullishVolume;
|
|
bearishVolumeBuffer[bar_index] = iBearishVolume;
|
|
|
|
//
|
|
// Calculate Volume Signals ...
|
|
|
|
//
|
|
int bullishVolumeSignalsCount = iMAOnBuffer(
|
|
ratesTotal,
|
|
prevCalculated,
|
|
bar_index,
|
|
volumeSignalLength,
|
|
bullishVolumeBuffer,
|
|
bullishVolumeSignalBuffer,
|
|
volumeSignalMethod //
|
|
);
|
|
|
|
//
|
|
int bearishVolumeSignalsCount = iMAOnBuffer(
|
|
ratesTotal,
|
|
prevCalculated,
|
|
bar_index,
|
|
volumeSignalLength,
|
|
bearishVolumeBuffer,
|
|
bearishVolumeSignalBuffer,
|
|
volumeSignalMethod //
|
|
);
|
|
|
|
//
|
|
// SIGNAL Bar ...
|
|
|
|
//
|
|
// Open ...
|
|
iMAOnBuffer(
|
|
ratesTotal,
|
|
prevCalculated,
|
|
bar_index,
|
|
barsSignalLength,
|
|
open,
|
|
openSignalBuffer,
|
|
barsSignalMethod //
|
|
);
|
|
|
|
//
|
|
// Close ...
|
|
iMAOnBuffer(
|
|
ratesTotal,
|
|
prevCalculated,
|
|
bar_index,
|
|
barsSignalLength,
|
|
close,
|
|
closeSignalBuffer,
|
|
barsSignalMethod //
|
|
);
|
|
|
|
//
|
|
double min = MathMin(closeSignalBuffer[bar_index], openSignalBuffer[bar_index]);
|
|
double max = MathMin(closeSignalBuffer[bar_index], openSignalBuffer[bar_index]);
|
|
|
|
//
|
|
lowSignalBuffer[bar_index] = min;
|
|
highSignalBuffer[bar_index] = max;
|
|
|
|
//
|
|
// Calculate HK Signal Color ...
|
|
double iSignalColorValue =
|
|
openSignalBuffer[bar_index] < closeSignalBuffer[bar_index]
|
|
? bullishColorIDX
|
|
: bearishColorIDX;
|
|
signalBarColorBuffer[bar_index] =
|
|
showSignalBars
|
|
? iSignalColorValue
|
|
: hideColorIDX;
|
|
|
|
//
|
|
// XHK ...
|
|
|
|
//
|
|
double lastHKOpen =
|
|
isFirstBar
|
|
? emptyValue
|
|
: openHKBuffer[lastBarIndex];
|
|
double lastHKClose =
|
|
isFirstBar
|
|
? emptyValue
|
|
: closeHKBuffer[lastBarIndex];
|
|
|
|
//
|
|
double iHKOpenValue = (lastHKOpen + lastHKClose) / 2;
|
|
double iHKCloseValue = (open[bar_index] + high[bar_index] + close[bar_index] + low[bar_index]) / 4;
|
|
double iHKHighValue = MathMax(high[bar_index], MathMax(iHKOpenValue, iHKCloseValue));
|
|
double iHKLowValue = MathMin(low[bar_index], MathMin(iHKOpenValue, iHKCloseValue));
|
|
|
|
//
|
|
double iHKColorValue =
|
|
iHKOpenValue < iHKCloseValue
|
|
? bullishColorIDX
|
|
: bearishColorIDX;
|
|
|
|
//
|
|
// Raw HK Buffers ...
|
|
openHKBuffer[bar_index] = iHKOpenValue;
|
|
highHKBuffer[bar_index] = iHKHighValue;
|
|
lowHKBuffer[bar_index] = iHKLowValue;
|
|
closeHKBuffer[bar_index] = iHKCloseValue;
|
|
barHKColorBuffer[bar_index] = showHKBars ? iHKColorValue
|
|
: hideColorIDX;
|
|
|
|
//
|
|
// XHK Signal ...
|
|
|
|
//
|
|
// Open ...
|
|
iMAOnBuffer(
|
|
ratesTotal,
|
|
prevCalculated,
|
|
bar_index,
|
|
hkSignalBarLength,
|
|
openHKBuffer,
|
|
openHKSignalBuffer,
|
|
hkSignalBarMethod //
|
|
);
|
|
|
|
//
|
|
// Close ...
|
|
iMAOnBuffer(
|
|
ratesTotal,
|
|
prevCalculated,
|
|
bar_index,
|
|
hkSignalBarLength,
|
|
closeHKBuffer,
|
|
closeHKSignalBuffer,
|
|
hkSignalBarMethod //
|
|
);
|
|
|
|
//
|
|
min = MathMin(closeHKSignalBuffer[bar_index], openHKSignalBuffer[bar_index]);
|
|
max = MathMin(closeHKSignalBuffer[bar_index], openHKSignalBuffer[bar_index]);
|
|
|
|
//
|
|
lowHKSignalBuffer[bar_index] = min;
|
|
highHKSignalBuffer[bar_index] = max;
|
|
|
|
//
|
|
// Calculate HK Signal Color ...
|
|
double iHKSignalColorValue =
|
|
openHKSignalBuffer[bar_index] < closeHKSignalBuffer[bar_index]
|
|
? bullishColorIDX
|
|
: bearishColorIDX;
|
|
barHKSignalColorBuffer[bar_index] =
|
|
showHKSignalBars
|
|
? iHKSignalColorValue
|
|
: hideColorIDX;
|
|
|
|
//
|
|
DetectTriggerBlock(
|
|
bar_index,
|
|
prevCalculated,
|
|
ratesTotal,
|
|
open,
|
|
high,
|
|
close,
|
|
low,
|
|
tickVolume //
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Detect Trigger Block ...
|
|
*
|
|
* @param bar_index: int, Specified Bar Index ...
|
|
* @param prevCalculated: int, Provides Previous Calculated Bars ...
|
|
* @param ratesTotal: int, Provides All Availabled Bars ...
|
|
* @param open: double Collection, Provides Open Prices Time Series ...
|
|
* @param high: double Collection, Provides High Prices Time Series ...
|
|
* @param close: double Collection, Provides Close Prices Time Series ...
|
|
* @param low: double Collection, Provides Low Prices Time Series ...
|
|
* @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ...
|
|
*/
|
|
void DetectTriggerBlock(
|
|
int bar_index, // Selected Bar Index
|
|
const int prevCalculated,
|
|
const int ratesTotal,
|
|
const double &open[],
|
|
const double &high[],
|
|
const double &close[],
|
|
const double &low[],
|
|
const long &tickVolume[] //
|
|
)
|
|
{
|
|
//
|
|
int lastBarIndex = bar_index + 1;
|
|
int maxBarIndex = startCalculationForLastBars > 0
|
|
? startCalculationForLastBars
|
|
: ratesTotal;
|
|
bool isFirstBar =
|
|
bar_index == maxBarIndex;
|
|
|
|
//
|
|
// Prevent Calculation ...
|
|
if (maxBarIndex - bar_index < maxLength)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
int zIDX = 0;
|
|
bool has = false;
|
|
bool isDone = false;
|
|
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
// Retrieve Required Bars ...
|
|
|
|
//
|
|
XOHCL iBar;
|
|
XOHCL zBar; // Current Start Checking Bar (Usually Used for Triggering) ...
|
|
has = zBar.Init(
|
|
_Symbol,
|
|
_Period,
|
|
bar_index //
|
|
);
|
|
|
|
//
|
|
// Detect Trend Bar ...
|
|
XOHCL zTrendBar;
|
|
int zTrendIDX = iBarShift(
|
|
_Symbol,
|
|
mTrendPeriod,
|
|
zBar.time //
|
|
);
|
|
has =
|
|
has &&
|
|
zTrendBar.Init(
|
|
_Symbol,
|
|
mTrendPeriod,
|
|
zTrendIDX + 1 //
|
|
);
|
|
|
|
//
|
|
// Define Zone Structure ...
|
|
XTriggerBlock tb;
|
|
|
|
//
|
|
bool validateObBarType = true;
|
|
bool validateFVGBarType = true;
|
|
|
|
//
|
|
// Detect Based Order Block ...
|
|
has =
|
|
has &&
|
|
barAnalyser.IsOB(
|
|
zBar,
|
|
tb.ob,
|
|
validateFVGBarType, // Force FVG Bar Type ...
|
|
validateObBarType // Force Block Two Bar Checking ...
|
|
);
|
|
|
|
//
|
|
// Detect Based Fair Value Gap ...
|
|
has =
|
|
has &&
|
|
barAnalyser.IsFVG(
|
|
zBar,
|
|
tb.fvg,
|
|
validateFVGBarType // Force FVG Bar Type ...
|
|
);
|
|
|
|
//
|
|
// Clone Trigger Block ...
|
|
if (has)
|
|
{
|
|
tb.trigger = tb.ob;
|
|
}
|
|
|
|
//
|
|
bool isBullish =
|
|
has &&
|
|
tb.IsBullish();
|
|
|
|
//
|
|
bool isBearish =
|
|
has &&
|
|
tb.IsBearish();
|
|
|
|
//
|
|
int toIDX = tb.ToIndex();
|
|
int fromIDX = tb.FromIndex();
|
|
|
|
//
|
|
// Verifications and Filters ...
|
|
|
|
//
|
|
int loopback = 144;
|
|
|
|
//
|
|
// Forces ...
|
|
|
|
//
|
|
// Force Has Proper Swing ...
|
|
if (has &&
|
|
forceHasSwing)
|
|
{
|
|
//
|
|
toIDX = tb.ToIndex();
|
|
fromIDX = tb.FromIndex();
|
|
for (int i = toIDX; i < fromIDX; i++)
|
|
{
|
|
//
|
|
// Initialize iBar ...
|
|
isDone = iBar.Init(
|
|
zBar.symbol,
|
|
zBar.period,
|
|
i //
|
|
);
|
|
isDone =
|
|
isDone &&
|
|
barAnalyser.IsSimpleSwing(
|
|
iBar,
|
|
iDir //
|
|
) &&
|
|
iDir == tb.GetDirection();
|
|
if (isDone)
|
|
{
|
|
//
|
|
bool canSet =
|
|
!tb.swingBar.IsValid()
|
|
? true
|
|
: (isBullish
|
|
? tb.swingBar.low > iBar.low
|
|
: tb.swingBar.high < iBar.high);
|
|
if (canSet)
|
|
{
|
|
tb.swingBar = iBar;
|
|
}
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
has = tb.swingBar.IsValid();
|
|
}
|
|
|
|
//
|
|
// Force Has Liquidity ...
|
|
if (has &&
|
|
(forceHasFLiquidity ||
|
|
forceHasRLiquidity))
|
|
{
|
|
//
|
|
toIDX = tb.ToIndex();
|
|
fromIDX = tb.FromIndex();
|
|
for (int i = toIDX; i < fromIDX + loopback; i++)
|
|
{
|
|
//
|
|
// Initialize iBar ...
|
|
isDone = iBar.Init(
|
|
zBar.symbol,
|
|
zBar.period,
|
|
i //
|
|
);
|
|
|
|
//
|
|
bool isRejected =
|
|
isDone &&
|
|
barAnalyser.IsRejected(
|
|
iBar,
|
|
iDir,
|
|
false, // Force Bar Type ...
|
|
true // Force Fibo Pressure ...
|
|
);
|
|
|
|
//
|
|
// Following Liquidity ...
|
|
bool isFLiq =
|
|
isDone &&
|
|
isRejected &&
|
|
iDir == tb.GetDirection() &&
|
|
(isBullish
|
|
? iBar.low < tb.trigger.lower
|
|
: iBar.high > tb.trigger.upper);
|
|
if (isFLiq &&
|
|
forceHasFLiquidity &&
|
|
!tb.fLiquidity.IsValid())
|
|
{
|
|
//
|
|
FillLiquidity(
|
|
iBar,
|
|
iDir,
|
|
tb.fLiquidity,
|
|
tb.trigger.to //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Reversal Liquidity ...
|
|
bool isRLiq =
|
|
isDone &&
|
|
isRejected &&
|
|
Opposit(iDir) == tb.GetDirection() &&
|
|
(isBullish
|
|
? iBar.low > tb.trigger.upper
|
|
: iBar.high < tb.trigger.lower);
|
|
if (isRLiq &&
|
|
forceHasRLiquidity &&
|
|
!tb.rLiquidity.IsValid())
|
|
{
|
|
//
|
|
FillLiquidity(
|
|
iBar,
|
|
iDir,
|
|
tb.rLiquidity,
|
|
tb.trigger.to //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Checking Conditions ...
|
|
isDone =
|
|
(!forceHasFLiquidity
|
|
? true
|
|
: tb.fLiquidity.IsValid()) &&
|
|
(!forceHasRLiquidity
|
|
? true
|
|
: tb.rLiquidity.IsValid());
|
|
if (isDone)
|
|
{
|
|
//
|
|
iBar.Clean();
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
// Checking Conditions ...
|
|
has =
|
|
(!forceHasFLiquidity
|
|
? true
|
|
: tb.fLiquidity.IsValid()) &&
|
|
(!forceHasRLiquidity
|
|
? true
|
|
: tb.rLiquidity.IsValid());
|
|
}
|
|
|
|
//
|
|
// Validations ...
|
|
|
|
//
|
|
// Validating Gap Sequence means
|
|
// Gap Bars must Follow each Other ...
|
|
if (has &&
|
|
validateGapSequence)
|
|
{
|
|
//
|
|
XOHCL iPBar;
|
|
toIDX = tb.fvg.ToIndex();
|
|
fromIDX = tb.fvg.FromIndex();
|
|
|
|
//
|
|
for (int i = toIDX; i < fromIDX - 1; i++)
|
|
{
|
|
//
|
|
// Initialize iBar ...
|
|
has = iBar.Init(
|
|
zBar.symbol,
|
|
zBar.period,
|
|
i //
|
|
);
|
|
has =
|
|
has &&
|
|
iBar.GetPreviousBar(iPBar);
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? iBar.low > iPBar.low
|
|
: iBar.high < iPBar.high);
|
|
if (!has)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
iPBar.Clean();
|
|
}
|
|
|
|
//
|
|
// Validate Block Edge Breakout ...
|
|
if (has &&
|
|
validateBlockEdgeBreakout)
|
|
{
|
|
//
|
|
has = tb.fvg.ToBar(iBar);
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? (iBar.GetDown() < tb.ob.upper &&
|
|
iBar.GetUp() > tb.ob.upper)
|
|
: (iBar.GetDown() < tb.ob.lower &&
|
|
iBar.GetUp() > tb.ob.lower));
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
// Filters ...
|
|
|
|
//
|
|
// DELTA ...
|
|
if (has &&
|
|
filterBasedOnDelta)
|
|
{
|
|
//
|
|
double iDelta = deltaBuffer[bar_index];
|
|
double iPDelta = deltaBuffer[lastBarIndex];
|
|
|
|
//
|
|
bool isDeltaUp = iDelta > iPDelta;
|
|
bool isDeltaDown = iDelta < iPDelta;
|
|
|
|
//
|
|
double iDeltaSignal = deltaSignalBuffer[bar_index];
|
|
double iPDeltaSignal = deltaSignalBuffer[lastBarIndex];
|
|
|
|
//
|
|
bool isDeltaSignalUp = iDeltaSignal > iPDeltaSignal;
|
|
bool isDeltaSignalDown = iDeltaSignal < iPDeltaSignal;
|
|
|
|
//
|
|
bool isDeltaSwitchedToBullish =
|
|
isDeltaUp &&
|
|
isDeltaSignalUp &&
|
|
iDelta > iDeltaSignal &&
|
|
iPDelta < iPDeltaSignal;
|
|
|
|
//
|
|
bool isDeltaSwitchedToBearish =
|
|
isDeltaDown &&
|
|
isDeltaSignalDown &&
|
|
iDelta < iDeltaSignal &&
|
|
iPDelta > iPDeltaSignal;
|
|
|
|
//
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? isDeltaSwitchedToBullish
|
|
: isDeltaSwitchedToBearish);
|
|
}
|
|
|
|
//
|
|
// VOLUME ...
|
|
if (has &&
|
|
filterBasedOnVolume)
|
|
{
|
|
//
|
|
double iBullishVolumeSignal = bullishVolumeSignalBuffer[bar_index];
|
|
double iPBullishVolumeSignal = bullishVolumeSignalBuffer[lastBarIndex];
|
|
|
|
//
|
|
bool isBullishVolumeSignalUp = iBullishVolumeSignal > iPBullishVolumeSignal;
|
|
bool isBullishVolumeSignalDown = iBullishVolumeSignal < iPBullishVolumeSignal;
|
|
|
|
//
|
|
double iBearishVolumeSignal = bearishVolumeSignalBuffer[bar_index];
|
|
double iPBearishVolumeSignal = bearishVolumeSignalBuffer[lastBarIndex];
|
|
|
|
//
|
|
bool isBearishVolumeSignalUp = iBearishVolumeSignal > iPBearishVolumeSignal;
|
|
bool isBearishVolumeSignalDown = iBearishVolumeSignal < iPBearishVolumeSignal;
|
|
|
|
//
|
|
bool isVolumeSwitchdToBullish =
|
|
isBullishVolumeSignalUp &&
|
|
!isBearishVolumeSignalUp &&
|
|
iBullishVolumeSignal > iBearishVolumeSignal &&
|
|
iPBullishVolumeSignal < iPBearishVolumeSignal;
|
|
|
|
//
|
|
bool isVolumeSwitchdToBearish =
|
|
isBearishVolumeSignalUp &&
|
|
!isBullishVolumeSignalUp &&
|
|
iBearishVolumeSignal > iBullishVolumeSignal &&
|
|
iPBearishVolumeSignal < iPBullishVolumeSignal;
|
|
|
|
//
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? isVolumeSwitchdToBullish
|
|
: isVolumeSwitchdToBearish);
|
|
}
|
|
|
|
//
|
|
// SIGNAL Bar ...
|
|
if (has &&
|
|
filterBasedOnSignalBar)
|
|
{
|
|
//
|
|
double iSignalOpen = openSignalBuffer[bar_index];
|
|
double iPSignalOpen = openSignalBuffer[lastBarIndex];
|
|
|
|
//
|
|
double iSignalClose = closeSignalBuffer[bar_index];
|
|
double iPSignalClose = closeSignalBuffer[lastBarIndex];
|
|
|
|
//
|
|
bool isSignalBarBullish = iSignalOpen < iSignalClose;
|
|
bool isPSignalBarBullish = iPSignalOpen < iPSignalClose;
|
|
|
|
//
|
|
bool isSignalBarBearish = iSignalOpen > iSignalClose;
|
|
bool isPSignalBarBearish = iPSignalOpen > iPSignalClose;
|
|
|
|
//
|
|
bool isSignalBarSwitchedToBullish =
|
|
isSignalBarBullish &&
|
|
!isPSignalBarBullish;
|
|
|
|
//
|
|
bool isSignalBarSwitchedToBearish =
|
|
isSignalBarBearish &&
|
|
!isPSignalBarBearish;
|
|
|
|
//
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? isSignalBarSwitchedToBullish
|
|
: isSignalBarSwitchedToBearish);
|
|
}
|
|
|
|
//
|
|
// HK SIGNAL Bar ...
|
|
if (has &&
|
|
filterBasedOnHKSignalBar)
|
|
{
|
|
//
|
|
double iHKSignalOpen = openHKSignalBuffer[bar_index];
|
|
double iPHKSignalOpen = openHKSignalBuffer[lastBarIndex];
|
|
|
|
//
|
|
double iHKSignalClose = closeHKSignalBuffer[bar_index];
|
|
double iPHKSignalClose = closeHKSignalBuffer[lastBarIndex];
|
|
|
|
//
|
|
bool isHKSignalBarBullish = iHKSignalOpen < iHKSignalClose;
|
|
bool isPHKSignalBarBullish = iPHKSignalOpen < iPHKSignalClose;
|
|
|
|
//
|
|
bool isHKSignalBarBearish = iHKSignalOpen > iHKSignalClose;
|
|
bool isPHKSignalBarBearish = iPHKSignalOpen > iPHKSignalClose;
|
|
|
|
//
|
|
bool isHKSignalBarSwitchedToBullish =
|
|
isHKSignalBarBullish &&
|
|
!isPHKSignalBarBullish;
|
|
|
|
//
|
|
bool isHKSignalBarSwitchedToBearish =
|
|
isHKSignalBarBearish &&
|
|
!isPHKSignalBarBearish;
|
|
|
|
//
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? isHKSignalBarSwitchedToBullish
|
|
: isHKSignalBarSwitchedToBearish);
|
|
}
|
|
|
|
//
|
|
// SAR ...
|
|
if (has &&
|
|
filterBasedOnSar)
|
|
{
|
|
//
|
|
double iSarState = sarStateBuffer[bar_index];
|
|
double iPSarState = sarStateBuffer[lastBarIndex];
|
|
double iP2SarState = sarStateBuffer[lastBarIndex + 1];
|
|
|
|
//
|
|
bool isSarBullish = iSarState > 0;
|
|
bool isPSarBullish = iPSarState > 0;
|
|
bool isP2SarBullish = iP2SarState > 0;
|
|
|
|
//
|
|
bool isSarBearish = iSarState < 0;
|
|
bool isPSarBearish = iPSarState < 0;
|
|
bool isP2SarBearish = iP2SarState < 0;
|
|
|
|
//
|
|
bool isSarSwitchedToBullish =
|
|
isSarBullish &&
|
|
!isPSarBullish;
|
|
|
|
//
|
|
bool isSarSwitchedToBearish =
|
|
isSarBearish &&
|
|
!isPSarBearish;
|
|
|
|
//
|
|
bool isSarPSwitchedToBullish =
|
|
isPSarBullish &&
|
|
!isP2SarBullish;
|
|
|
|
//
|
|
bool isSarPSwitchedToBearish =
|
|
isPSarBearish &&
|
|
!isP2SarBearish;
|
|
|
|
//
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? (isSarSwitchedToBullish ||
|
|
isSarPSwitchedToBullish)
|
|
: (isSarSwitchedToBearish ||
|
|
isSarPSwitchedToBearish));
|
|
}
|
|
|
|
//
|
|
// TREND ...
|
|
if (has &&
|
|
filterBasedOnTrend)
|
|
{
|
|
//
|
|
double iTrendState = trendStateBuffer[bar_index];
|
|
double iPTrendState = trendStateBuffer[lastBarIndex];
|
|
|
|
//
|
|
bool isTrendBullish = iTrendState > 0;
|
|
bool isPTrendBullish = iPTrendState > 0;
|
|
|
|
//
|
|
bool isTrendBearish = iTrendState < 0;
|
|
bool isPTrendBearish = iPTrendState < 0;
|
|
|
|
//
|
|
double trends[];
|
|
int toIDX = tb.ToIndex();
|
|
int fromIDX = tb.FromIndex();
|
|
double iTrend = trendBuffer[toIDX];
|
|
for (int i = toIDX; i <= fromIDX; i++)
|
|
{
|
|
//
|
|
Add(
|
|
trendBuffer[i],
|
|
trends //
|
|
);
|
|
}
|
|
double trendsMin = GetMin(trends);
|
|
double trendsMax = GetMax(trends);
|
|
double trendsAVG = GetAverage(trends);
|
|
|
|
//
|
|
bool isTrendUp =
|
|
iTrend > trendsMin &&
|
|
iTrend >= trendsAVG;
|
|
|
|
//
|
|
bool isTrendDown =
|
|
iTrend < trendsMax &&
|
|
iTrend <= trendsAVG;
|
|
|
|
//
|
|
bool isTrendSwitchedToBullish =
|
|
isTrendUp &&
|
|
isTrendBullish &&
|
|
!isPTrendBullish;
|
|
|
|
//
|
|
bool isTrendSwitchedToBearish =
|
|
isTrendDown &&
|
|
isTrendBearish &&
|
|
!isPTrendBearish;
|
|
|
|
//
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? isTrendSwitchedToBullish
|
|
: isTrendSwitchedToBearish);
|
|
}
|
|
|
|
//
|
|
// TREND Bars ...
|
|
if (has &&
|
|
zTrendBar.IsValid() &&
|
|
filterBasedOnTrendBars)
|
|
{
|
|
//
|
|
// Calculate Trend Bar's Midd Range ...
|
|
double mid = zTrendBar.low + ((zTrendBar.high - zTrendBar.low) / 2);
|
|
|
|
//
|
|
// Check zBar Close based on MID ...
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? zBar.close < mid
|
|
: zBar.close > mid);
|
|
|
|
//
|
|
// Check Trigger Block ...
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? tb.trigger.lower < zTrendBar.GetDown()
|
|
: tb.trigger.upper > zTrendBar.GetUp());
|
|
}
|
|
|
|
//
|
|
// RSI ...
|
|
if (has &&
|
|
filterBasedOnRSI)
|
|
{
|
|
//
|
|
double rsiTrend = (rsiOBLevel + rsiOSLevel) / 2;
|
|
|
|
//
|
|
double iRSI = rsiBuffer[bar_index];
|
|
double iPRSI = rsiBuffer[lastBarIndex];
|
|
double iP2RSI = rsiBuffer[lastBarIndex + 1];
|
|
|
|
//
|
|
bool isRSICrossedOverOS =
|
|
iRSI > rsiOSLevel &&
|
|
iPRSI <= rsiOSLevel;
|
|
|
|
//
|
|
bool isRSICrossedUnderOB =
|
|
iRSI < rsiOBLevel &&
|
|
iPRSI >= rsiOBLevel;
|
|
|
|
//
|
|
bool isPRSICrossedOverOS =
|
|
iPRSI > rsiOSLevel &&
|
|
iP2RSI <= rsiOSLevel;
|
|
|
|
//
|
|
bool isPRSICrossedUnderOB =
|
|
iPRSI < rsiOBLevel &&
|
|
iP2RSI >= rsiOBLevel;
|
|
|
|
//
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? (isRSICrossedOverOS ||
|
|
isPRSICrossedOverOS)
|
|
: (isRSICrossedUnderOB ||
|
|
isPRSICrossedUnderOB));
|
|
}
|
|
|
|
//
|
|
// ADX ...
|
|
if (has &&
|
|
filterBasedOnADX)
|
|
{
|
|
//
|
|
// ADX ...
|
|
double iADX = adxBuffer[bar_index];
|
|
double iPADX = adxBuffer[lastBarIndex];
|
|
double iP2ADX = adxBuffer[lastBarIndex + 1];
|
|
|
|
//
|
|
// ADX +DI ...
|
|
double iADXP = adxpBuffer[bar_index];
|
|
double iPADXP = adxpBuffer[lastBarIndex];
|
|
double iP2ADXP = adxpBuffer[lastBarIndex + 1];
|
|
|
|
//
|
|
// ADX -DI ...
|
|
double iADXN = adxnBuffer[bar_index];
|
|
double iPADXN = adxnBuffer[lastBarIndex];
|
|
double iP2ADXN = adxnBuffer[lastBarIndex + 1];
|
|
|
|
//
|
|
// Preparing Conditions ...
|
|
|
|
//
|
|
bool isADXBullish = iADX > adxThreshold;
|
|
bool isADXBearish = iADX < adxThreshold;
|
|
|
|
//
|
|
bool isPADXBullish = iPADX > adxThreshold;
|
|
bool isPADXBearish = iPADX < adxThreshold;
|
|
|
|
//
|
|
bool isP2ADXBullish = iP2ADX > adxThreshold;
|
|
bool isP2ADXBearish = iP2ADX < adxThreshold;
|
|
|
|
//
|
|
bool isADXSwitchedToBullish =
|
|
isADXBullish &&
|
|
!isPADXBullish;
|
|
|
|
//
|
|
bool isADXSwitchedToBearish =
|
|
isADXBearish &&
|
|
!isPADXBearish;
|
|
|
|
//
|
|
bool isPADXSwitchedToBullish =
|
|
isPADXBullish &&
|
|
!isP2ADXBullish;
|
|
|
|
//
|
|
bool isPADXSwitchedToBearish =
|
|
isPADXBearish &&
|
|
!isP2ADXBearish;
|
|
|
|
//
|
|
has =
|
|
has &&
|
|
(isBullish
|
|
? (isADXSwitchedToBullish ||
|
|
isPADXSwitchedToBullish)
|
|
: (isADXSwitchedToBearish ||
|
|
isPADXSwitchedToBearish));
|
|
}
|
|
|
|
//
|
|
// SIGNAL ...
|
|
if (has &&
|
|
(drawSignals &&
|
|
maxSignalR2R > 0))
|
|
{
|
|
//
|
|
double targets[];
|
|
for (int i = 1; i <= maxSignalR2R; i++)
|
|
{
|
|
//
|
|
Add(
|
|
(double)i,
|
|
targets //
|
|
);
|
|
}
|
|
|
|
//
|
|
double iATR = atrBuffer[bar_index];
|
|
double slAdditional = slAtrMultiplier * iATR;
|
|
|
|
//
|
|
has = ToSignal(
|
|
tb.trigger,
|
|
tb.signal,
|
|
targets,
|
|
slAdditional //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Handle Draw ...
|
|
|
|
//
|
|
// Draw Trend Bar ...
|
|
if (has &&
|
|
showTrendBars)
|
|
{
|
|
//
|
|
XCOHCLObject *iObj;
|
|
isDone = drawer.CreateBar(
|
|
zTrendBar,
|
|
iObj,
|
|
zBar.time //
|
|
);
|
|
if (isDone)
|
|
{
|
|
//
|
|
// Style Object ...
|
|
|
|
//
|
|
// Store Object ...
|
|
mObjects.Add(iObj);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Draw Trigger Block ...
|
|
if (has &&
|
|
drawZones)
|
|
{
|
|
DrawTB(tb);
|
|
}
|
|
|
|
//
|
|
// Handle Alerst ...
|
|
bool canAlert =
|
|
mEnableAlerts &&
|
|
prevCalculated > 0;
|
|
bool canLogOnly =
|
|
mEnableAlerts &&
|
|
prevCalculated == 0;
|
|
if (has &&
|
|
(canAlert ||
|
|
canLogOnly))
|
|
{
|
|
//
|
|
string message =
|
|
tb.trigger.symbol + "," +
|
|
ToString(tb.trigger.period) + "> " +
|
|
ToString(tb.trigger.dir) +
|
|
" Zone Detected at: " + ToString(tb.trigger.to);
|
|
|
|
//
|
|
if (canLogOnly)
|
|
{
|
|
alert.LogAlert(message);
|
|
}
|
|
else if (canAlert)
|
|
{
|
|
alert.Alert(message);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
|
|
//
|
|
tb.Clean();
|
|
zBar.Clean();
|
|
iBar.Clean();
|
|
zTrendBar.Clean();
|
|
}
|
|
|
|
//
|
|
void ReadBarStyle()
|
|
{
|
|
//
|
|
long chartId = ChartID();
|
|
|
|
//
|
|
_upColor = GetChartUpColor(chartId);
|
|
_downColor = GetChartDownColor(chartId);
|
|
_lineColor = GetChartLineColor(chartId);
|
|
_bullishColor = GetChartBullishColor(chartId);
|
|
_bearishColor = GetChartBearishColor(chartId);
|
|
}
|
|
|
|
//
|
|
void ShowBars()
|
|
{
|
|
//
|
|
long chartId = ChartID();
|
|
|
|
//
|
|
SetChartUpColor(_upColor, chartId);
|
|
SetChartDownColor(_downColor, chartId);
|
|
SetChartLineColor(_lineColor, chartId);
|
|
SetChartBullishColor(_bullishColor, chartId);
|
|
SetChartBearishColor(_bearishColor, chartId);
|
|
}
|
|
|
|
//
|
|
void HideBars()
|
|
{
|
|
//
|
|
long chartId = ChartID();
|
|
|
|
//
|
|
SetChartUpColor(CLR_NONE, chartId);
|
|
SetChartDownColor(CLR_NONE, chartId);
|
|
SetChartLineColor(CLR_NONE, chartId);
|
|
SetChartBullishColor(CLR_NONE, chartId);
|
|
SetChartBearishColor(CLR_NONE, chartId);
|
|
}
|
|
|
|
//
|
|
// Draw Specific Trigger Block ...
|
|
bool DrawTB(
|
|
XTriggerBlock &trigger,
|
|
datetime to = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
result = trigger.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// 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 ...
|
|
mObjects.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 ...
|
|
mObjects.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 ...
|
|
mObjects.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)
|
|
{
|
|
mObjects.Add(iLiqObj);
|
|
}
|
|
ZeroMemory(iLiqObj);
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Following Liquidity ...
|
|
if (trigger.fLiquidity.IsValid())
|
|
{
|
|
//
|
|
XCBoxObject *iLiqObj;
|
|
result = drawer.DrawBox(
|
|
trigger.fLiquidity,
|
|
iLiqObj //
|
|
);
|
|
if (result)
|
|
{
|
|
mObjects.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)
|
|
{
|
|
mObjects.Add(swingObj);
|
|
}
|
|
ZeroMemory(swingObj);
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Draw RR of Signal ...
|
|
if (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);
|
|
|
|
//
|
|
mObjects.Add(iRRObj);
|
|
}
|
|
ZeroMemory(iRRObj);
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
// |