diff --git a/BKPS/14030923/Documents/BKP/Indicators/x-saherelm.x3ma.mq5 b/BKPS/14030923/Documents/BKP/Indicators/x-saherelm.x3ma.mq5 new file mode 100644 index 0000000..399a9c3 --- /dev/null +++ b/BKPS/14030923/Documents/BKP/Indicators/x-saherelm.x3ma.mq5 @@ -0,0 +1,394 @@ +/////////////////////////////////////////////////////// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------- +// Name: X3MA +// Description: X3MA Trend Detector ... +// +// 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 X3MA Indicator" +#property strict + +// +#define ShortName "X3MA" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int fastLength = 50; // Fast Length +input int midLength = 100; // Mid Length +input int slowLength = 200; // Slow Length +input int shiftLength = 0; // Shift +input ENUM_MA_METHOD method = MODE_SMA; // Mode +input ENUM_APPLIED_PRICE appliedTo = PRICE_CLOSE; // Applied To + +// +// Presentation ... +input group "Presentation"; + +// +// Parts ... +input bool showFast = true; // Show Fast +input bool showMid = true; // Show Mid +input bool showSlow = true; // Show Slow + +// +// Buffers ... + +// +#property indicator_chart_window + +// +#property indicator_buffers 3 +#property indicator_plots 3 + +// +// Current ... + +// +// Fast ... +#define fastBufferIndex 0 +double fastBuffer[]; + +// +#property indicator_label1 "X3MA F" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrAqua +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +// Mid ... +#define midBufferIndex 1 +double midBuffer[]; + +// +#property indicator_label2 "X3MA M" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrOrange +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +// Slow ... +#define slowBufferIndex 2 +double slowBuffer[]; + +// +#property indicator_label3 "X3MA S" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrMagenta +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +// Variables ... + +// +int maxLength; + +// +// Handlers ... +int fastHandler = INVALID_HANDLE; +int midHandler = INVALID_HANDLE; +int slowHandler = INVALID_HANDLE; + +// +// EVENT Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + if (!InitHandlers()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // 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(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +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 + + // + // Release Handlers ... + IndicatorRelease(fastHandler); + IndicatorRelease(midHandler); + IndicatorRelease(slowHandler); +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... +) +{ + // + ArraySetAsSeries(low, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(close, true); + + // + // this counts Available Bars ... + int limit; + + // + // Validate Calculated Bars ... + bool isPassedRequiredCalculatedBars = + // + BarsCalculated(fastHandler) >= maxLength && + BarsCalculated(midHandler) >= maxLength && + BarsCalculated(slowHandler) >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = + (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + int copiedFasts = CopyBuffer(fastHandler, 0, 0, limit, fastBuffer); + int copiedMids = CopyBuffer(midHandler, 0, 0, limit, midBuffer); + int copiedSlows = CopyBuffer(slowHandler, 0, 0, limit, slowBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + copiedFasts > 0 && + copiedMids > 0 && + copiedSlows > 0 + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + } + + // + return rates_total; +} + +// +// CUSTOM Functions ... + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + fastLength > 2 && + midLength > fastLength && + slowLength > midLength && + // + shiftLength >= 0 + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Current ... + result = MathMax(fastLength, midLength); + result = MathMax(result, slowLength); + + // + return result; +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // Fast ... + bool canShowFast = showFast; + ENUM_DRAW_TYPE fastDrawType = canShowFast ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(fastBuffer, true); + SetIndexBuffer(fastBufferIndex, fastBuffer, INDICATOR_DATA); + PlotIndexSetDouble(fastBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(fastBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fastBufferIndex, PLOT_SHOW_DATA, canShowFast); + PlotIndexSetInteger(fastBufferIndex, PLOT_DRAW_TYPE, fastDrawType); + + // + // Mid ... + bool canShowMid = showMid; + ENUM_DRAW_TYPE midDrawType = canShowMid ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(midBuffer, true); + SetIndexBuffer(midBufferIndex, midBuffer, INDICATOR_DATA); + PlotIndexSetDouble(midBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(midBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(midBufferIndex, PLOT_SHOW_DATA, canShowMid); + PlotIndexSetInteger(midBufferIndex, PLOT_DRAW_TYPE, midDrawType); + + // + // Slow ... + bool canShowSlow = showSlow; + ENUM_DRAW_TYPE slowDrawType = canShowSlow ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(slowBuffer, true); + SetIndexBuffer(slowBufferIndex, slowBuffer, INDICATOR_DATA); + PlotIndexSetDouble(slowBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(slowBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slowBufferIndex, PLOT_SHOW_DATA, canShowSlow); + PlotIndexSetInteger(slowBufferIndex, PLOT_DRAW_TYPE, slowDrawType); +} + +// +// Initial Indicator Handlers ... +bool InitHandlers() +{ + // + bool result = false; + + // + // Initialize Handlers ... + + // + // Fast ... + fastHandler = iMA( + _Symbol, + _Period, + fastLength, + shiftLength, + method, + appliedTo // + ); + + // + // Mid ... + midHandler = iMA( + _Symbol, + _Period, + midLength, + shiftLength, + method, + appliedTo // + ); + + // + // Slow ... + slowHandler = iMA( + _Symbol, + _Period, + slowLength, + shiftLength, + method, + appliedTo // + ); + + // + result = + // + fastHandler != INVALID_HANDLE && + midHandler != INVALID_HANDLE && + slowHandler != INVALID_HANDLE + // + ; + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/Indicators/x-saherelm.x3vwap.mq5 b/BKPS/14030923/Documents/BKP/Indicators/x-saherelm.x3vwap.mq5 new file mode 100644 index 0000000..50b6b89 --- /dev/null +++ b/BKPS/14030923/Documents/BKP/Indicators/x-saherelm.x3vwap.mq5 @@ -0,0 +1,564 @@ +/////////////////////////////////////////////////////// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------- +// Name: X3VWAP +// Description: X3VWAP Trend Detector ... +// +// 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 X3VWAP Indicator" +#property strict + +// +#define ShortName "X3VWAP" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int fastLength = 50; // Fast Length +input int midLength = 100; // Mid Length +input int slowLength = 200; // Slow Length +input ENUM_APPLIED_PRICE appliedTo = PRICE_CLOSE; // Applied To + +// +// Presentation ... +input group "Presentation"; +input bool showFast = true; // Show Fast +input bool showMid = true; // Show Mid +input bool showSlow = true; // Show Slow + +// +// Buffers ... + +// +#property indicator_chart_window + +// +#property indicator_buffers 11 +#property indicator_plots 3 + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +// Current ... + +// +// Fast ... +#define fastBufferIndex 0 +double fastBuffer[]; + +#define fastColorBufferIndex 1 +double fastColorBuffer[]; + +// +#define fastPlotBufferIndex 0 +#property indicator_label1 "X3VWAP F" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 + +// +// Mid ... +#define midBufferIndex 2 +double midBuffer[]; + +#define midColorBufferIndex 3 +double midColorBuffer[]; + +// +#define midPlotBufferIndex 1 +#property indicator_label2 "X3VWAP M" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style2 STYLE_SOLID +#property indicator_width2 2 + +// +// Slow ... +#define slowBufferIndex 4 +double slowBuffer[]; + +#define slowColorBufferIndex 5 +double slowColorBuffer[]; + +// +#define slowPlotBufferIndex 2 +#property indicator_label3 "X3VWAP S" +#property indicator_type3 DRAW_COLOR_LINE +#property indicator_color3 CLR_NONE, clrSteelBlue, clrDarkRed, clrGray +#property indicator_style3 STYLE_SOLID +#property indicator_width3 2 + +// +// Data Buffers ... + +// +// Volumes ... +#define volumeBufferIndex 6 +double volumeBuffer[]; + +// +// Price ... +#define priceBufferIndex 7 +double priceBuffer[]; + +// +// Fast State ... +#define fastStateBufferIndex 8 +double fastStateBuffer[]; + +// +// Mid State ... +#define midStateBufferIndex 9 +double midStateBuffer[]; + +// +// Slow State ... +#define slowStateBufferIndex 10 +double slowStateBuffer[]; + +// +// Variables ... + +// +int maxLength; + +// +// EVENT Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // 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(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +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 +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... +) +{ + // + ArraySetAsSeries(low, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = + (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // 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; +} + +// +// CUSTOM Functions ... + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + fastLength > 2 && + midLength > fastLength && + slowLength > midLength + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Current ... + result = MathMax(fastLength, midLength); + result = MathMax(result, slowLength); + + // + return result; +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // Fast ... + ArraySetAsSeries(fastBuffer, true); + ArraySetAsSeries(fastColorBuffer, true); + SetIndexBuffer(fastBufferIndex, fastBuffer, INDICATOR_DATA); + SetIndexBuffer(fastColorBufferIndex, fastColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Mid ... + ArraySetAsSeries(midBuffer, true); + ArraySetAsSeries(midColorBuffer, true); + SetIndexBuffer(midBufferIndex, midBuffer, INDICATOR_DATA); + SetIndexBuffer(midColorBufferIndex, midColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Slow ... + ArraySetAsSeries(slowBuffer, true); + ArraySetAsSeries(slowColorBuffer, true); + SetIndexBuffer(slowBufferIndex, slowBuffer, INDICATOR_DATA); + SetIndexBuffer(slowColorBufferIndex, slowColorBuffer, INDICATOR_COLOR_INDEX); + // + // Data Buffers ... + + // + // Volumes ... + ArraySetAsSeries(volumeBuffer, true); + SetIndexBuffer(volumeBufferIndex, volumeBuffer, INDICATOR_CALCULATIONS); + + // + // Price ... + ArraySetAsSeries(priceBuffer, true); + SetIndexBuffer(priceBufferIndex, priceBuffer, INDICATOR_CALCULATIONS); + + // + // Fast State ... + ArraySetAsSeries(fastStateBuffer, true); + SetIndexBuffer(fastStateBufferIndex, fastStateBuffer, INDICATOR_CALCULATIONS); + + // + // Mid State ... + ArraySetAsSeries(midStateBuffer, true); + SetIndexBuffer(midStateBufferIndex, midStateBuffer, INDICATOR_CALCULATIONS); + + // + // Slow State ... + ArraySetAsSeries(slowStateBuffer, true); + SetIndexBuffer(slowStateBufferIndex, slowStateBuffer, INDICATOR_CALCULATIONS); +} + +// +// Calculate Buffers ... +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[] // +) +{ + // + // Calculate Volumes and Price ... + + // + if (ratesTotal - bar_index <= maxLength) + { + // + CalculateDataBuffers( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + return; + } + + // + CalculateDataBuffers( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + CalculateVWAPS( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); +} + +// +// Calculate Required Data Buffers ... +void CalculateDataBuffers( + 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[] // +) +{ + // + double price = GetAppliedPrice( + appliedTo, + open, + high, + low, + close, + bar_index // + ); + priceBuffer[bar_index] = price; + volumeBuffer[bar_index] = (double)tickVolume[bar_index]; +} + +// +// Calculate Different VWaps ... +void CalculateVWAPS( + 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[] // +) +{ + // + // Fast ... + CalculateVWAP( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + // + fastLength, + showFast, + fastBuffer, + fastColorBuffer, + fastStateBuffer // + ); + + // + // Mid ... + CalculateVWAP( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + // + midLength, + showMid, + midBuffer, + midColorBuffer, + midStateBuffer // + ); + + // + // Fast ... + CalculateVWAP( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + // + slowLength, + showSlow, + slowBuffer, + slowColorBuffer, + slowStateBuffer // + ); +} + +// +// Calculate VWAP ... +void CalculateVWAP( + 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 _length, // Calculation Length + bool _show, + double &_buffer[], + double &_colorBuffer[], + double &_stateBuffer[] // +) +{ + // + double vSum = 0; + double pSum = 0; + double mSum = 0; + for (int x = 0; x < _length; x++) + { + // + pSum += priceBuffer[x + bar_index]; + vSum += volumeBuffer[x + bar_index]; + mSum += priceBuffer[x + bar_index] * volumeBuffer[x + bar_index]; + } + + // + double iValue = mSum / vSum; + iValue = NormalizeDouble(iValue, _Digits); + + // + _buffer[bar_index] = iValue; + + // + bool isBullish = low[bar_index] > iValue; + bool isBearish = high[bar_index] < iValue; + + // + double iColor = + isBullish + ? bullishColorIDX + : isBearish + ? bearishColorIDX + : neuturalColorIDX; + + // + _colorBuffer[bar_index] = hideColorIDX; + _stateBuffer[bar_index] = iColor; + if (_show) + { + _colorBuffer[bar_index] = iColor; + } +} + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/Indicators/x-saherelm.xchsar.mq5 b/BKPS/14030923/Documents/BKP/Indicators/x-saherelm.xchsar.mq5 new file mode 100644 index 0000000..736407a --- /dev/null +++ b/BKPS/14030923/Documents/BKP/Indicators/x-saherelm.xchsar.mq5 @@ -0,0 +1,691 @@ +/////////////////////////////////////////////////////// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------- +// Name: XCHM +// Description: XCHMrend Detector ... +// +// 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 XCHM Indicator" +#property strict + +// +#define ShortName "XCHSAR" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input double sarStep = 0.02; // Step +input double sarMax = 0.2; // Maximum + +// +input group "Cycles"; + +// +input group "Short"; +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES scPeriod = NULL; // Time Period + +// +input group "Medium"; +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES mcPeriod = NULL; // Time Period + +// +input group "Long"; +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES lcPeriod = NULL; // Time Period + +// +input group "Hind"; +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES hcPeriod = NULL; // Time Period + +// +// Presentation ... +input group "Presentation"; + +// +input int cArrowCode = 225; // Current Cycle Arrow Code +input int sArrowCode = 225; // Short Cycle Arrow Code +input int mArrowCode = 225; // Medium Cycle Arrow Code +input int lArrowCode = 225; // Long Cycle Arrow Code +input int hArrowCode = 225; // Hind Cycle Arrow Code + +// +input bool showCurrent = true; // Show Current Cycle +input bool showShort = false; // Show Short Cycle +input bool showMedium = false; // Show Medium Cycle +input bool showLong = false; // Show Long Cycle +input bool showHind = false; // Show Hind Cycle + +// +// Buffers ... + +// +#property indicator_chart_window + +// +#property indicator_buffers 5 +#property indicator_plots 5 + +// +// Current ... +#define cBufferIndex 0 +double cBuffer[]; + +// +#property indicator_label1 "XCHSAR C" +#property indicator_type1 DRAW_ARROW +#property indicator_color1 clrYellow +#property indicator_width1 2 + +// +// Short ... +#define sBufferIndex 1 +double sBuffer[]; + +// +#property indicator_label2 "XCHSAR S" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrMagenta +#property indicator_width2 2 + +// +// Medium ... +#define mBufferIndex 2 +double mBuffer[]; + +// +#property indicator_label3 "XCHSAR M" +#property indicator_type3 DRAW_ARROW +#property indicator_color3 clrDodgerBlue +#property indicator_width3 2 + +// +// Long ... +#define lBufferIndex 3 +double lBuffer[]; + +// +#property indicator_label4 "XCHSAR L" +#property indicator_type4 DRAW_ARROW +#property indicator_color4 clrLime +#property indicator_width4 2 + +// +// Hind ... +#define hBufferIndex 4 +double hBuffer[]; + +// +#property indicator_label5 "XCHSAR H" +#property indicator_type5 DRAW_ARROW +#property indicator_color5 clrRed +#property indicator_width5 2 + +// +// Variables ... + +// +int maxLength; + +// +// Current ... +int cHandler = INVALID_HANDLE; + +// +// Short ... +ENUM_TIMEFRAMES mSCPeriod = NULL; +int sHandler = INVALID_HANDLE; + +// +// Medium ... +ENUM_TIMEFRAMES mMCPeriod = NULL; +int mHandler = INVALID_HANDLE; + +// +// Long ... +ENUM_TIMEFRAMES mLCPeriod = NULL; +int lHandler = INVALID_HANDLE; + +// +// Hind ... +ENUM_TIMEFRAMES mHCPeriod = NULL; +int hHandler = INVALID_HANDLE; + +// +// EVENT Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + if (!InitMarketCycles()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // 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(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +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 + + // + // Current ... + IndicatorRelease(cHandler); + + // + // Short ... + IndicatorRelease(sHandler); + + // + // Medium ... + IndicatorRelease(mHandler); + + // + // Long ... + IndicatorRelease(lHandler); + + // + // Hind ... + IndicatorRelease(hHandler); +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... +) +{ + // + ArraySetAsSeries(low, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(close, true); + + // + // this counts Available Bars ... + int limit; + + // + // Validate Calculated Bars ... + bool isPassedRequiredCalculatedBars = + // + // Current ... + BarsCalculated(cHandler) >= maxLength && + // + // Short ... + BarsCalculated(sHandler) >= maxLength && + // + // Medium ... + BarsCalculated(mHandler) >= maxLength && + // + // Long ... + BarsCalculated(lHandler) >= maxLength && + // + // Hind ... + BarsCalculated(hHandler) >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = + (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // Current ... + int copiedCs = CopyBuffer(cHandler, 0, 0, limit, cBuffer); + + // + // Short ... + int copiedSs = CopyBuffer(sHandler, 0, 0, limit, sBuffer); + + // + // Medium ... + int copiedMs = CopyBuffer(mHandler, 0, 0, limit, mBuffer); + + // + // Long ... + int copiedLs = CopyBuffer(lHandler, 0, 0, limit, lBuffer); + + // + // Hind ... + int copiedHs = CopyBuffer(hHandler, 0, 0, limit, hBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // + // Current ... + copiedCs > 0 && + // + // Short ... + copiedSs > 0 && + // + // Medium ... + copiedMs > 0 && + // + // Long ... + copiedLs > 0 && + // + // Hind ... + copiedHs > 0 + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + // for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + // { + // CalculateBuffers(i); + // } + + // + return rates_total; +} + +// +// CUSTOM Functions ... + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + sarStep > 0 && + sarMax > sarStep && + // + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + return result; +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // CURRENT ... + + // + ENUM_DRAW_TYPE cDrawType = showCurrent ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(cBuffer, true); + SetIndexBuffer(cBufferIndex, cBuffer, INDICATOR_DATA); + PlotIndexSetInteger(cBufferIndex, PLOT_ARROW, cArrowCode); + PlotIndexSetDouble(cBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + PlotIndexSetInteger(cBufferIndex, PLOT_SHOW_DATA, showCurrent); + PlotIndexSetInteger(cBufferIndex, PLOT_DRAW_TYPE, cDrawType); + + // + // SHORT ... + + // + ENUM_DRAW_TYPE sDrawType = showShort ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(sBuffer, true); + SetIndexBuffer(sBufferIndex, sBuffer, INDICATOR_DATA); + PlotIndexSetInteger(mBufferIndex, PLOT_ARROW, sArrowCode); + PlotIndexSetDouble(mBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + PlotIndexSetInteger(sBufferIndex, PLOT_SHOW_DATA, showShort); + PlotIndexSetInteger(sBufferIndex, PLOT_DRAW_TYPE, sDrawType); + + // + // MEDIUM ... + + // + ENUM_DRAW_TYPE mDrawType = showMedium ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(mBuffer, true); + SetIndexBuffer(mBufferIndex, mBuffer, INDICATOR_DATA); + PlotIndexSetInteger(mBufferIndex, PLOT_ARROW, mArrowCode); + PlotIndexSetDouble(mBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + PlotIndexSetInteger(mBufferIndex, PLOT_SHOW_DATA, showMedium); + PlotIndexSetInteger(mBufferIndex, PLOT_DRAW_TYPE, mDrawType); + + // + // LONG ... + + // + ENUM_DRAW_TYPE lDrawType = showLong ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(lBuffer, true); + SetIndexBuffer(lBufferIndex, lBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lBufferIndex, PLOT_ARROW, lArrowCode); + PlotIndexSetDouble(lBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + PlotIndexSetInteger(lBufferIndex, PLOT_SHOW_DATA, showLong); + PlotIndexSetInteger(lBufferIndex, PLOT_DRAW_TYPE, lDrawType); + + // + // HIND ... + + // + ENUM_DRAW_TYPE hDrawType = showHind ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(hBuffer, true); + SetIndexBuffer(hBufferIndex, hBuffer, INDICATOR_DATA); + PlotIndexSetInteger(hBufferIndex, PLOT_ARROW, hArrowCode); + PlotIndexSetDouble(hBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + PlotIndexSetInteger(hBufferIndex, PLOT_SHOW_DATA, showHind); + PlotIndexSetInteger(hBufferIndex, PLOT_DRAW_TYPE, hDrawType); +} + +// +// Initial Market Cycles ... +bool InitMarketCycles() +{ + // + bool result = false; + + // + // Current Cycle Initialization ... + + // + int cPeriodSeconds = PeriodSeconds(_Period); + + // + // Initialize Handlers ... + + // + // Current ... + cHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMax // + ); + result = cHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Short Cycle Initialization ... + + // + // Find Cycle Period ... + if (scMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mSCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_SHORT, + _Period // + ); + } + else + { + mSCPeriod = scPeriod; + } + + // + result = IsValid(mSCPeriod); + if (!result) + { + return result; + } + + // + sHandler = iSAR( + _Symbol, + mSCPeriod, + sarStep, + sarMax // + ); + result = sHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Medium Cycle Initialization ... + + // + // Find Cycle Period ... + if (mcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mMCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_MEDIUM, + _Period // + ); + } + else + { + mMCPeriod = mcPeriod; + } + + // + result = IsValid(mMCPeriod); + if (!result) + { + return result; + } + + // + mHandler = iSAR( + _Symbol, + mMCPeriod, + sarStep, + sarMax // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Long Cycle Initialization ... + + // + // Find Cycle Period ... + if (lcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mLCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_LONG, + _Period // + ); + } + else + { + mLCPeriod = lcPeriod; + } + + // + result = IsValid(mLCPeriod); + if (!result) + { + return result; + } + + // + lHandler = iSAR( + _Symbol, + mLCPeriod, + sarStep, + sarMax // + ); + result = lHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Hind Cycle Initialization ... + + // + // Find Cycle Period ... + if (hcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mHCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_HIND, + _Period // + ); + } + else + { + mHCPeriod = hcPeriod; + } + + // + result = IsValid(mHCPeriod); + if (!result) + { + return result; + } + + // + hHandler = iSAR( + _Symbol, + mHCPeriod, + sarStep, + sarMax // + ); + result = hHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; +} + +// +// Do all Custom Calculations ... +void CalculateBuffers(int barIndex) +{ +} + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/Indicators/x-saherelm.xpv.mq5 b/BKPS/14030923/Documents/BKP/Indicators/x-saherelm.xpv.mq5 new file mode 100644 index 0000000..022910f --- /dev/null +++ b/BKPS/14030923/Documents/BKP/Indicators/x-saherelm.xpv.mq5 @@ -0,0 +1,1292 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XPV +// Description: Peaks and Vales ... +// +// +// 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 XPV Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "XPV" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input group "Makret Cycles"; + +// +input group "Short"; +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES scPeriod = NULL; // Time Period + +// +input group "Medium"; +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES mcPeriod = NULL; // Time Period + +// +input group "Long"; +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES lcPeriod = NULL; // Time Period + +// +input group "Hind"; +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES hcPeriod = NULL; // Time Period + +// +input group "Fibonacci"; +input double fiboLevel1 = 0.236; // Fibio 1st Level +input double fiboLevel2 = 0.382; // Fibio 2st Level +input double fiboLevel3 = 0.5; // Fibio 3rd Level +input double fiboLevel4 = 0.618; // Fibio 4th Level +input double fiboLevel5 = 0.764; // Fibio 5th Level + +// +input group "Boundary Detection Modes"; +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE llMode = MODE_LOW; // Lowest Low Calculation Method + +// +input group "Presentation"; +input bool showPeaksAndVales = true; // Show Peaks and Vales +input bool showLevels = false; // Show Levels +input bool showConsolidations = false; // Show Consolidations +input bool showFibo1Levels = false; // Show Fibo 1st Level +input bool showFibo2Levels = false; // Show Fibo 2nd Level +input bool showFibo3Levels = false; // Show Fibo 3rd Level +input bool showFibo4Levels = false; // Show Fibo 4th Level +input bool showFibo5Levels = false; // Show Fibo 5th Level + +// +// Buffers ... + +// +#property indicator_chart_window + +// +#property indicator_buffers 32 +#property indicator_plots 32 + +// +// PEAKS ... + +// +#define peaksBufferIndex 0 +double peaksBuffer[]; + +// +#property indicator_label1 "XPV PEAKS" +#property indicator_type1 DRAW_ARROW +#property indicator_color1 clrAqua +#property indicator_width1 1 + +// +// VALES ... + +// +#define valesBufferIndex 1 +double valesBuffer[]; + +// +#property indicator_label2 "XPV VALES" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrMagenta +#property indicator_width2 1 + +// +#define rBufferIndex 2 +double rBuffer[]; + +// +#define rColorBufferIndex 3 +double rColorBuffer[]; + +// +#property indicator_label3 "XPV R" +#property indicator_type3 DRAW_COLOR_LINE +#property indicator_color3 CLR_NONE, clrAqua +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +#define sBufferIndex 4 +#define sBufferPlotIndex 3 +double sBuffer[]; + +// +#define sColorBufferIndex 5 +double sColorBuffer[]; + +// +#property indicator_label4 "XPV S" +#property indicator_type4 DRAW_COLOR_LINE +#property indicator_color4 CLR_NONE, clrMagenta +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +// FIBBO Level 1 ... + +// +#define fl1BufferIndex 6 +#define fl1BufferPlotIndex 4 +double fl1Buffer[]; + +// +#define fl1ColorBufferIndex 7 +double fl1ColorBuffer[]; + +// +#property indicator_label5 "XPV FL1" +#property indicator_type5 DRAW_COLOR_LINE +#property indicator_color5 CLR_NONE, clrGold +#property indicator_style5 STYLE_DASHDOTDOT +#property indicator_width5 1 + +// +// FIBBO Level 2 ... + +// +#define fl2BufferIndex 8 +#define fl2BufferPlotIndex 5 +double fl2Buffer[]; + +// +#define fl2ColorBufferIndex 9 +double fl2ColorBuffer[]; + +// +#property indicator_label6 "XPV FL2" +#property indicator_type6 DRAW_COLOR_LINE +#property indicator_color6 CLR_NONE, clrGold +#property indicator_style6 STYLE_DASHDOTDOT +#property indicator_width6 1 + +// +// FIBBO Level 3 ... + +// +#define fl3BufferIndex 10 +#define fl3BufferPlotIndex 6 +double fl3Buffer[]; + +// +#define fl3ColorBufferIndex 11 +double fl3ColorBuffer[]; + +// +#property indicator_label7 "XPV FL3" +#property indicator_type7 DRAW_COLOR_LINE +#property indicator_color7 CLR_NONE, clrGold +#property indicator_style7 STYLE_DASHDOTDOT +#property indicator_width7 1 + +// +// FIBBO Level 4 ... + +// +#define fl4BufferIndex 12 +#define fl4BufferPlotIndex 7 +double fl4Buffer[]; + +// +#define fl4ColorBufferIndex 13 +double fl4ColorBuffer[]; + +// +#property indicator_label8 "XPV FL4" +#property indicator_type8 DRAW_COLOR_LINE +#property indicator_color8 CLR_NONE, clrGold +#property indicator_style8 STYLE_DASHDOTDOT +#property indicator_width8 1 + +// +// FIBBO Level 5 ... + +// +#define fl5BufferIndex 14 +#define fl5BufferPlotIndex 8 +double fl5Buffer[]; + +// +#define fl5ColorBufferIndex 15 +double fl5ColorBuffer[]; + +// +#property indicator_label9 "XPV FL5" +#property indicator_type9 DRAW_COLOR_LINE +#property indicator_color9 CLR_NONE, clrGold +#property indicator_style9 STYLE_DASHDOTDOT +#property indicator_width9 1 + +// +// LEVELS ... + +// +#define scHHBufferIndex 16 +#define scHHBufferPlotIndex 9 +double scHHBuffer[]; + +// +#define scHHColorBufferIndex 17 +double scHHColorBuffer[]; + +// +#property indicator_label10 "XPV SHH" +#property indicator_type10 DRAW_COLOR_LINE +#property indicator_color10 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style10 STYLE_DOT +#property indicator_width10 1 + +#define scLLBufferIndex 18 +#define scLLBufferPlotIndex 10 +double scLLBuffer[]; + +// +#define scLLColorBufferIndex 19 +double scLLColorBuffer[]; + +// +#property indicator_label11 "XPV SLL" +#property indicator_type11 DRAW_COLOR_LINE +#property indicator_color11 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style11 STYLE_DOT +#property indicator_width11 1 + +// +#define mcHHBufferIndex 20 +#define mcHHBufferPlotIndex 11 +double mcHHBuffer[]; + +// +#define mcHHColorBufferIndex 21 +double mcHHColorBuffer[]; + +// +#property indicator_label12 "XPV MHH" +#property indicator_type12 DRAW_COLOR_LINE +#property indicator_color12 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style12 STYLE_DOT +#property indicator_width12 1 + +// +#define mcLLBufferIndex 22 +#define mcLLBufferPlotIndex 12 +double mcLLBuffer[]; + +// +#define mcLLColorBufferIndex 23 +double mcLLColorBuffer[]; + +// +#property indicator_label13 "XPV MLL" +#property indicator_type13 DRAW_COLOR_LINE +#property indicator_color13 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style13 STYLE_DOT +#property indicator_width13 1 + +// +#define lcHHBufferIndex 24 +#define lcHHBufferPlotIndex 13 +double lcHHBuffer[]; + +// +#define lcHHColorBufferIndex 25 +double lcHHColorBuffer[]; + +// +#property indicator_label14 "XPV LHH" +#property indicator_type14 DRAW_COLOR_LINE +#property indicator_color14 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style14 STYLE_DOT +#property indicator_width14 1 + +// +#define lcLLBufferIndex 26 +#define lcLLBufferPlotIndex 14 +double lcLLBuffer[]; + +// +#define lcLLColorBufferIndex 27 +double lcLLColorBuffer[]; + +// +#property indicator_label15 "XPV LLL" +#property indicator_type15 DRAW_COLOR_LINE +#property indicator_color15 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style15 STYLE_DOT +#property indicator_width15 1 + +// +#define hcHHBufferIndex 28 +#define hcHHBufferPlotIndex 15 +double hcHHBuffer[]; + +// +#define hcHHColorBufferIndex 29 +double hcHHColorBuffer[]; + +// +#property indicator_label16 "XPV HHH" +#property indicator_type16 DRAW_COLOR_LINE +#property indicator_color16 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style16 STYLE_DOT +#property indicator_width16 1 + +// +#define hcLLBufferIndex 30 +#define hcLLBufferPlotIndex 16 +double hcLLBuffer[]; + +// +#define hcLLColorBufferIndex 31 +double hcLLColorBuffer[]; + +// +#property indicator_label17 "XPV HLL" +#property indicator_type17 DRAW_COLOR_LINE +#property indicator_color17 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style17 STYLE_DOT +#property indicator_width17 1 + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +double mHideColorIDX = 0; + +// +// XMarketCycle sc; +int mSCLength = 0; +double mLastSCHH = 0; +double mLastSCLL = 0; +ENUM_TIMEFRAMES mSCPeriod = NULL; + +// +// XMarketCycle mc; +int mMCLength = 0; +double mLastMCHH = 0; +double mLastMCLL = 0; +ENUM_TIMEFRAMES mMCPeriod = NULL; + +// +// XMarketCycle lc; +int mLCLength = 0; +double mLastLCHH = 0; +double mLastLCLL = 0; +ENUM_TIMEFRAMES mLCPeriod = NULL; + +// +// XMarketCycle hc; +int mHCLength = 0; +double mLastHCHH = 0; +double mLastHCLL = 0; +ENUM_TIMEFRAMES mHCPeriod = NULL; + +// +double lastPeak = 0; +double lastVale = 0; + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + if (!InitMarketCycles()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // 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(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +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 +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... + // +) +{ + // + // 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); + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + if (i <= 1000) + { + CalculateBuffers(i); + } + } + + // + return rates_total; +} + +// +// Functions ... + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(mSCLength, mMCLength); + result = MathMax(result, mLCLength); + result = MathMax(result, mHCLength); + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // PEAKS and VALES ... + ENUM_DRAW_TYPE pvDrawType = showPeaksAndVales ? DRAW_ARROW : DRAW_NONE; + + // + // PEAKS ... + ArraySetAsSeries(peaksBuffer, true); + SetIndexBuffer(peaksBufferIndex, peaksBuffer, INDICATOR_DATA); + PlotIndexSetInteger(peaksBufferIndex, PLOT_ARROW, 225); + PlotIndexSetDouble(peaksBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + PlotIndexSetInteger(peaksBufferIndex, PLOT_SHOW_DATA, showPeaksAndVales); + PlotIndexSetInteger(peaksBufferIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + // VALES ... + ArraySetAsSeries(valesBuffer, true); + SetIndexBuffer(valesBufferIndex, valesBuffer, INDICATOR_DATA); + PlotIndexSetInteger(valesBufferIndex, PLOT_ARROW, 225); + PlotIndexSetDouble(valesBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + PlotIndexSetInteger(valesBufferIndex, PLOT_SHOW_DATA, showPeaksAndVales); + PlotIndexSetInteger(valesBufferIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + // SUPPORT and RESISTANCE ... + // + + // + // RESISTANCE ... + ArraySetAsSeries(rBuffer, true); + SetIndexBuffer(rBufferIndex, rBuffer, INDICATOR_DATA); + PlotIndexSetInteger(rBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(rBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // RESISTANCE Color ... + ArraySetAsSeries(rColorBuffer, true); + SetIndexBuffer(rColorBufferIndex, rColorBuffer, INDICATOR_COLOR_INDEX); + + // + // SUPPORT ... + ArraySetAsSeries(sBuffer, true); + SetIndexBuffer(sBufferIndex, sBuffer, INDICATOR_DATA); + PlotIndexSetInteger(sBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(sBufferPlotIndex, PLOT_SHOW_DATA, false); + + // + // SUPPORT Color ... + ArraySetAsSeries(sColorBuffer, true); + SetIndexBuffer(sColorBufferIndex, sColorBuffer, INDICATOR_COLOR_INDEX); + + // + // FIBBO Levels ... + + // + // LEVEL 1 ... + + // + // Buffer ... + ArraySetAsSeries(fl1Buffer, true); + SetIndexBuffer(fl1BufferIndex, fl1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fl1BufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fl1BufferPlotIndex, PLOT_SHOW_DATA, showFibo1Levels); + + // + // Color ... + ArraySetAsSeries(fl1ColorBuffer, true); + SetIndexBuffer(fl1ColorBufferIndex, fl1ColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LEVEL 2 ... + + // + // Buffer ... + ArraySetAsSeries(fl2Buffer, true); + SetIndexBuffer(fl2BufferIndex, fl2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fl2BufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fl2BufferPlotIndex, PLOT_SHOW_DATA, showFibo2Levels); + + // + // Color ... + ArraySetAsSeries(fl2ColorBuffer, true); + SetIndexBuffer(fl2ColorBufferIndex, fl2ColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LEVEL 3 ... + + // + // Buffer ... + ArraySetAsSeries(fl3Buffer, true); + SetIndexBuffer(fl3BufferIndex, fl3Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fl3BufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fl3BufferPlotIndex, PLOT_SHOW_DATA, showFibo3Levels); + + // + // Color ... + ArraySetAsSeries(fl3ColorBuffer, true); + SetIndexBuffer(fl3ColorBufferIndex, fl3ColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LEVEL 4 ... + + // + // Buffer ... + ArraySetAsSeries(fl4Buffer, true); + SetIndexBuffer(fl4BufferIndex, fl4Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fl4BufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fl4BufferPlotIndex, PLOT_SHOW_DATA, showFibo4Levels); + + // + // Color ... + ArraySetAsSeries(fl4ColorBuffer, true); + SetIndexBuffer(fl4ColorBufferIndex, fl4ColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LEVEL 5 ... + + // + // Buffer ... + ArraySetAsSeries(fl5Buffer, true); + SetIndexBuffer(fl5BufferIndex, fl5Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fl5BufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fl5BufferPlotIndex, PLOT_SHOW_DATA, showFibo5Levels); + + // + // Color ... + ArraySetAsSeries(fl5ColorBuffer, true); + SetIndexBuffer(fl5ColorBufferIndex, fl5ColorBuffer, INDICATOR_COLOR_INDEX); + + // + // SHORT Buffers ... + + // + // HIGH ... + ArraySetAsSeries(scHHBuffer, true); + SetIndexBuffer(scHHBufferIndex, scHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(scHHBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(scHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(scHHColorBuffer, true); + SetIndexBuffer(scHHColorBufferIndex, scHHColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LOW ... + ArraySetAsSeries(scLLBuffer, true); + SetIndexBuffer(scLLBufferIndex, scLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(scLLBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(scLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(scLLColorBuffer, true); + SetIndexBuffer(scLLColorBufferIndex, scLLColorBuffer, INDICATOR_COLOR_INDEX); + + // + // MEDIUM Buffer ... + + // + // HIGH ... + ArraySetAsSeries(mcHHBuffer, true); + SetIndexBuffer(mcHHBufferIndex, mcHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mcHHBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(mcHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(mcHHColorBuffer, true); + SetIndexBuffer(mcHHColorBufferIndex, mcHHColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LOW ... + ArraySetAsSeries(mcLLBuffer, true); + SetIndexBuffer(mcLLBufferIndex, mcLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mcLLBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(mcLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(mcLLColorBuffer, true); + SetIndexBuffer(mcLLColorBufferIndex, mcLLColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LONG Buffer ... + + // + // HIGH ... + ArraySetAsSeries(lcHHBuffer, true); + SetIndexBuffer(lcHHBufferIndex, lcHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lcHHBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(lcHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(lcHHColorBuffer, true); + SetIndexBuffer(lcHHColorBufferIndex, lcHHColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LOW ... + ArraySetAsSeries(lcLLBuffer, true); + SetIndexBuffer(lcLLBufferIndex, lcLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lcLLBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(lcLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(lcLLColorBuffer, true); + SetIndexBuffer(lcLLColorBufferIndex, lcLLColorBuffer, INDICATOR_COLOR_INDEX); + + // + // HIND Buffer ... + + // + // HIGH ... + ArraySetAsSeries(hcHHBuffer, true); + SetIndexBuffer(hcHHBufferIndex, hcHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hcHHBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(hcHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(hcHHColorBuffer, true); + SetIndexBuffer(hcHHColorBufferIndex, hcHHColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LOW ... + ArraySetAsSeries(hcLLBuffer, true); + SetIndexBuffer(hcLLBufferIndex, hcLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hcLLBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(hcLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(hcLLColorBuffer, true); + SetIndexBuffer(hcLLColorBufferIndex, hcLLColorBuffer, INDICATOR_COLOR_INDEX); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + // Calculate Cycles ... + CalculateCycles(bar_index); + + // + // Calculate Peaks and Vales ... + CalculatePeaksAndVales(bar_index); + + // + // Calculate Fibonnaci ... + CalculateFibonacci(bar_index); +} + +// +// Custom ... + +// +// Initial Market Cycles ... +bool InitMarketCycles() +{ + // + bool result = false; + + // + int cPeriodSeconds = PeriodSeconds(_Period); + + // + // Find Cycle Period ... + if (scMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mSCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_SHORT, + _Period // + ); + } + else + { + mSCPeriod = scPeriod; + } + + // + if (IsValid(mSCPeriod)) + { + mSCLength = PeriodSeconds(mSCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (mcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mMCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_MEDIUM, + _Period // + ); + } + else + { + mMCPeriod = mcPeriod; + } + + // + if (IsValid(mMCPeriod)) + { + mMCLength = PeriodSeconds(mMCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (lcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mLCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_LONG, + _Period // + ); + } + else + { + mLCPeriod = lcPeriod; + } + + // + if (IsValid(mLCPeriod)) + { + mLCLength = PeriodSeconds(mLCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (hcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mHCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_HIND, + _Period // + ); + } + else + { + mHCPeriod = hcPeriod; + } + + // + if (IsValid(mHCPeriod)) + { + mHCLength = PeriodSeconds(mHCPeriod) / cPeriodSeconds; + } + + // + result = mSCLength > 0 && + mMCLength > mSCLength && + mLCLength > mMCLength && + mHCLength > mLCLength; + + // + return result; +} + +// +// Calculate Specified Cycles HH and LL ... +void CalculateCycle( + int barIndex, + ENUM_X_MARKET_CYCLES cycle, + double &lastHH, + double &hhBuffer[], + double &hhColorBuffer[], + double &lastLL, + double &llBuffer[], + double &llColorBuffer[] // +) +{ + // + XOHCL bar; + bar.Init( + _Symbol, + _Period, + barIndex + // + ); + + // + int mLength = 0; + switch (cycle) + { + // + case X_MARKET_CYCLE_SHORT: + mLength = mSCLength; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + mLength = mMCLength; + break; + + // + case X_MARKET_CYCLE_LONG: + mLength = mLCLength; + break; + + // + case X_MARKET_CYCLE_HIND: + mLength = mHCLength; + break; + } + + // + if (mLength <= 0) + { + return; + } + + // + double hhValue = bar.FindHighest( + mLength, + hhMode + // + ); + hhBuffer[barIndex] = hhValue; + + // + double hhColorIDX = + !showLevels + ? mHideColorIDX + : (hhValue == lastHH) + ? !showConsolidations + ? mHideColorIDX + : 1 + : hhValue > lastHH + ? 2 + : hhValue < lastHH + ? 3 + : mHideColorIDX; + hhColorBuffer[barIndex] = hhColorIDX; + + // + lastHH = hhValue; + + // + double llValue = bar.FindLowest( + mLength, + llMode + // + ); + llBuffer[barIndex] = llValue; + + // + double llColorIDX = + !showLevels + ? mHideColorIDX + : (llValue == lastLL) + ? !showConsolidations + ? mHideColorIDX + : 1 + : llValue > lastLL + ? 2 + : llValue < lastLL + ? 3 + : mHideColorIDX; + llColorBuffer[barIndex] = llColorIDX; + + // + lastLL = llValue; +} + +// +// Calculate Cycles Up and Down Boundaries ... +void CalculateCycles( + int barIndex // Bar Index +) +{ + // + // Short ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_SHORT, + // + mLastSCHH, + scHHBuffer, + scHHColorBuffer, + // + mLastSCLL, + scLLBuffer, + scLLColorBuffer + // + ); + + // + // Medium ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_MEDIUM, + // + mLastMCHH, + mcHHBuffer, + mcHHColorBuffer, + // + mLastMCLL, + mcLLBuffer, + mcLLColorBuffer + // + ); + + // + // Long ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_LONG, + // + mLastLCHH, + lcHHBuffer, + lcHHColorBuffer, + // + mLastLCLL, + lcLLBuffer, + lcLLColorBuffer + // + ); + + // + // Hind ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_HIND, + // + mLastHCHH, + hcHHBuffer, + hcHHColorBuffer, + // + mLastHCLL, + hcLLBuffer, + hcLLColorBuffer + // + ); +} + +// +// Calculate Peaks and Values ... +void CalculatePeaksAndVales( + int barIndex // Bar Index +) +{ + // + // Retrieve Requirements ... + + // + // Short ... + double scHHValue = scHHBuffer[barIndex]; + double scLLValue = scLLBuffer[barIndex]; + + // + // Medium ... + double mcHHValue = mcHHBuffer[barIndex]; + double mcLLValue = mcLLBuffer[barIndex]; + + // + // Long ... + double lcHHValue = lcHHBuffer[barIndex]; + double lcLLValue = lcLLBuffer[barIndex]; + + // + // Hind ... + double hcHHValue = hcHHBuffer[barIndex]; + double hcLLValue = hcLLBuffer[barIndex]; + + // + double rColorIDX = mHideColorIDX; + double sColorIDX = mHideColorIDX; + + // + // RESISTANCE ... + double rValue = (scHHValue + mcHHValue + lcHHValue + hcHHValue) / 4; + + // + // PEAKS ... + bool isPeak = rValue == hcHHValue && + hcHHValue == lcHHValue && + lcHHValue == mcHHValue && + mcHHValue == scHHValue; + + // + if (isPeak && lastPeak != rValue) + { + // + rColorIDX = 1; + lastPeak = rValue; + } + + // + // SUPPORT ... + double sValue = (scLLValue + mcLLValue + lcLLValue + hcLLValue) / 4; + + // + // VALES ... + bool isVale = sValue == hcLLValue && + hcLLValue == lcLLValue && + lcLLValue == mcLLValue && + mcLLValue == scLLValue; + + // + if (isVale && lastVale != sValue) + { + // + sColorIDX = 1; + + // + lastVale = sValue; + } + + // + rBuffer[barIndex] = rValue; + sBuffer[barIndex] = sValue; + peaksBuffer[barIndex] = lastPeak; + valesBuffer[barIndex] = lastVale; + + // + if (showPeaksAndVales) + { + // + rColorBuffer[barIndex] = rColorIDX; + sColorBuffer[barIndex] = sColorIDX; + } + else + { + // + rColorBuffer[barIndex] = mHideColorIDX; + sColorBuffer[barIndex] = mHideColorIDX; + } +} + +// +// Calculate Fibonacci Level 1 ... +void CalculateFibonacci( + int barIndex // Bar Index +) +{ + // + // Select Requirements ... + double upPrice = peaksBuffer[barIndex]; + double downPrice = valesBuffer[barIndex]; + + // + // Level 1 ... + double fibLevel1Value = GetFibonacciLevel( + upPrice, + downPrice, + fiboLevel1, + 1); + // + // Level 2 ... + double fibLevel2Value = GetFibonacciLevel( + upPrice, + downPrice, + fiboLevel2, + 1); + + // + // Level 3 ... + double fibLevel3Value = GetFibonacciLevel( + upPrice, + downPrice, + fiboLevel3, + 1); + + // + // Level 4 ... + double fibLevel4Value = GetFibonacciLevel( + upPrice, + downPrice, + fiboLevel4, + 1); + + // + // Level 5 ... + double fibLevel5Value = GetFibonacciLevel( + upPrice, + downPrice, + fiboLevel5, + 1); + + // + fl1Buffer[barIndex] = fibLevel1Value; + fl2Buffer[barIndex] = fibLevel2Value; + fl3Buffer[barIndex] = fibLevel3Value; + fl4Buffer[barIndex] = fibLevel4Value; + fl5Buffer[barIndex] = fibLevel5Value; + + // + double fl1ColorIdx = showFibo1Levels ? 1 : mHideColorIDX; + double fl2ColorIdx = showFibo2Levels ? 1 : mHideColorIDX; + double fl3ColorIdx = showFibo3Levels ? 1 : mHideColorIDX; + double fl4ColorIdx = showFibo4Levels ? 1 : mHideColorIDX; + double fl5ColorIdx = showFibo5Levels ? 1 : mHideColorIDX; + + // + fl1ColorBuffer[barIndex] = fl1ColorIdx; + fl2ColorBuffer[barIndex] = fl2ColorIdx; + fl3ColorBuffer[barIndex] = fl3ColorIdx; + fl4ColorBuffer[barIndex] = fl4ColorIdx; + fl5ColorBuffer[barIndex] = fl5ColorIdx; +} + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/Indicators/x-saherelm.xtick.osc.mq5 b/BKPS/14030923/Documents/BKP/Indicators/x-saherelm.xtick.osc.mq5 new file mode 100644 index 0000000..1e04174 --- /dev/null +++ b/BKPS/14030923/Documents/BKP/Indicators/x-saherelm.xtick.osc.mq5 @@ -0,0 +1,643 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XTick Oscillator +// Description: Tick Charts ... +// +// +// 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 XTick Oscillator" +#property strict + +// +// Definitions ... + +// +#define ShortName "XTick" + +// +// Declaration of the enumeration +enum ENUM_X_PRICE_TYPES +{ + X_Bid, // Bid + X_Ask // Ask +}; + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input group "Makret"; + +// +input group "Chart Config"; +input int ticksCount = 3; // Ticks Count +input ENUM_X_PRICE_TYPES appliedPrice = 0; // Price + +// +input group "Moving Average"; +input int maLength = 10; // Length +input int maShift = 0; // Shift +input ENUM_MA_METHOD maMethod = MODE_SMA; // Mode +input ENUM_X_PRICE maAppliedTo = X_PRICE_CLOSE; // Applied To + +// +input group "Presentation"; +input bool showBars = true; // Show Bars +input bool showMa = true; // Show Moving Average + +// +// Buffers ... + +// +#property indicator_separate_window + +// +#property indicator_buffers 8 +#property indicator_plots 2 + +// +double openBuffer[]; +#define openBufferIndex 0 + +// +double highBuffer[]; +#define highBufferIndex 1 + +// +double lowBuffer[]; +#define lowBufferIndex 2 + +// +double closeBuffer[]; +#define closeBufferIndex 3 + +// +double colorBuffer[]; +#define colorBufferIndex 4 + +// +#define barBufferIndex 0 +#property indicator_label1 "Open;High;Low;Close" +#property indicator_type1 DRAW_COLOR_CANDLES +#property indicator_color1 CLR_NONE, clrGray, clrAqua, clrMagenta + +// +double maBuffer[]; +#define maBufferIndex 5 +#define maPlotBufferIndex 1 + +// +#property indicator_label2 "MA" +#property indicator_type2 DRAW_LINE // DRAW_COLOR_LINE +#property indicator_color2 clrRoyalBlue // CLR_NONE, clrGreen, clrRed +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +double ticksBuffer[]; +#define ticksBufferIndex 6 + +// +double maPriceBuffer[]; +#define maPriceBufferIndex 7 + +// +#define hideColorIDX 0; +#define neuturalColorIDX 1; +#define bullishColorIDX 2; +#define bearishColorIDX 3; + +// +// The variable contains the number of stored quotes ... +int ticks_stored; + +// +// The variable specifies the path and prefix to the file name ... +string path_prefix = ""; // FileName Prefix + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // 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 +} + +/** + * 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); + + // + int file_handle; // is a file handle + int bidPosition; // are positions of Bid prices in the string + int askPosition; // are positions of Ask prices in the string + int line_string_len; // is a length of a string, read from the file + int barNumber; // number of candle, for which the prices OHLC are determined + int i; // loop counter + + // + // the recent received Bid price ... + double last_price_bid = SymbolInfoDouble(Symbol(), SYMBOL_BID); + + // + // the recent received Ask price ... + double last_price_ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK); + + // + string filename; // name of a file, the file_buffer is a string + string file_buffer; // a buffer for reading and writing of string data + + // + // Setting the size of ticksBuffer array ... + ArrayResize(ticksBuffer, ArraySize(closeBuffer)); + + // + // File name formation from the path_prefix variable, name + // of financial instrument and ".Txt" symbols + StringConcatenate(filename, path_prefix, Symbol(), ".txt"); + + // + // Opening a file for reading and writing, codepage ANSI, shared reading mode + file_handle = FileOpen(filename, FILE_READ | FILE_WRITE | FILE_ANSI | FILE_SHARE_READ); + if (prev_calculated == 0) + { + // + // Reading the first line from the file and determine the length of a string ... + line_string_len = StringLen(FileReadString(file_handle)) + 2; + + // + // if file is large (contains more quotes than rates_total/2) ... + if (FileSize(file_handle) > (ulong)line_string_len * rates_total / 2) + { + // + // Setting file pointer to read the latest rates_total/2 quotes + FileSeek(file_handle, -line_string_len * rates_total / 2, SEEK_END); + + // + // Moving file pointer to the beginning of the next line + FileReadString(file_handle); + } + + // + // if file size is small + else + { + // + // Moving file pointer at the beginning of a file + FileSeek(file_handle, 0, SEEK_SET); + } + + // + // Reset the counter of stored quotes + ticks_stored = 0; + + // + // Reading until the end of the file + while (FileIsEnding(file_handle) == false) + { + // + // Reading a string from thefile + file_buffer = FileReadString(file_handle); + + // + // Processing of string if its length is larger than 6 characters + if (StringLen(file_buffer) > 6) + { + // + // Finding the start position of Bid price in the line + bidPosition = StringFind(file_buffer, " ", StringFind(file_buffer, " ") + 1) + 1; + + // + // Finding the start position of Ask price in the line + askPosition = StringFind(file_buffer, " ", bidPosition) + 1; + + // + // If the Bid prices are used, adding the Bid price to ticksBuffer[] array + if (appliedPrice == 0) + { + ticksBuffer[ticks_stored] = StringToDouble(StringSubstr(file_buffer, bidPosition, askPosition - bidPosition - 1)); + } + + // + // If the Ask prices are used, adding the Ask price to ticksBuffer[] array + if (appliedPrice == 1) + { + ticksBuffer[ticks_stored] = StringToDouble(StringSubstr(file_buffer, askPosition)); + } + + // + // Increasing the counter of stored quotes + ticks_stored++; + } + } + } + // + // If the data have been read before + else + { + // + // Moving file pointer at the end of the file + FileSeek(file_handle, 0, SEEK_END); + + // + // Forming a string, that should be written to the file + StringConcatenate(file_buffer, TimeCurrent(), " ", DoubleToString(last_price_bid, _Digits), " ", DoubleToString(last_price_ask, _Digits)); + + // + // Writing a string to the file + FileWrite(file_handle, file_buffer); + + // + // If the Bid prices are used, adding the last Bid price to ticksBuffer[] array + if (appliedPrice == 0) + { + ticksBuffer[ticks_stored] = last_price_bid; + } + + // + // If the Ask prices are used, adding the last Ask price to ticksBuffer[] array + if (appliedPrice == 1) + { + ticksBuffer[ticks_stored] = last_price_ask; + } + + // + // Increasing the quotes counter + ticks_stored++; + } + + // + // Closing the file + FileClose(file_handle); + + // + // If number of quotes is more or equal than number of bars in the chart + if (ticks_stored >= rates_total) + { + // + // Removing the first tick_stored/2 quotes and shifting remaining quotes + for (i = ticks_stored / 2; i < ticks_stored; i++) + { + // + // Shifting the data to the beginning in the ticksBuffer[] array on tick_stored/2 + ticksBuffer[i - ticks_stored / 2] = ticksBuffer[i]; + } + + // + // Changing the quotes counter + ticks_stored -= ticks_stored / 2; + } + + // + // We assign the barNumber with a number of invalid candle + barNumber = -1; + + // + // Search for all the price data available for candle formation + for (i = 0; i < ticks_stored; i++) + { + // + // If this candle is forming already + if (barNumber == (int)(MathFloor((ticks_stored - 1) / ticksCount) - MathFloor(i / ticksCount))) + { + // + // The current quote is still closing price of the current candle + closeBuffer[barNumber] = ticksBuffer[i]; + + // + // If the current price is greater than the highest price of the current candle, it will be a new highest price of the candle + if (ticksBuffer[i] > highBuffer[barNumber]) + { + highBuffer[barNumber] = ticksBuffer[i]; + } + + // + // If the current price is lower than the lowest price of the current candle, it will be a new lowest price of the candle + if (ticksBuffer[i] < lowBuffer[barNumber]) + { + lowBuffer[barNumber] = ticksBuffer[i]; + } + + // + // If the candle is bullish ... + if (closeBuffer[barNumber] > openBuffer[barNumber]) + { + colorBuffer[barNumber] = bullishColorIDX; + } + + // + // If the candle is bearish ... + if (closeBuffer[barNumber] < openBuffer[barNumber]) + { + colorBuffer[barNumber] = bearishColorIDX; + } + + // + // If the opening and closing prices are equal, then the candle will have a color with index 0 (grey) + if (closeBuffer[barNumber] == openBuffer[barNumber]) + { + colorBuffer[barNumber] = neuturalColorIDX; + } + } + // + // If this candle hasn't benn calculated yet + else + { + // + // Let's determine the index of a candle + barNumber = (int)(MathFloor((ticks_stored - 1) / ticksCount) - MathFloor(i / ticksCount)); + + // + // The current quote will be the opening price of a candle + openBuffer[barNumber] = ticksBuffer[i]; + + // + // The current quote will be the highest price of a candle + highBuffer[barNumber] = ticksBuffer[i]; + + // + // The current quote will be the lowest price of a candle + lowBuffer[barNumber] = ticksBuffer[i]; + + // + // The current quote will be the closing price of a candle + closeBuffer[barNumber] = ticksBuffer[i]; + + // + // The candle will have a color with index 0 (gray) + colorBuffer[barNumber] = 0; + } + } + + // + // Custom Calculations ... + + // + int limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total // + ); + } + + // + // Return from OnCalculate(), return a value, different from zero + return (rates_total); +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = + // + ticksCount > 0 + // + ; + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Color ... + ArraySetAsSeries(colorBuffer, true); + SetIndexBuffer(colorBufferIndex, colorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on Bar Buffer ... + PlotIndexSetDouble(barBufferIndex, PLOT_EMPTY_VALUE, 0.0); + + // + PlotIndexSetInteger(barBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(colorBufferIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(openBuffer, true); + PlotIndexSetInteger(openBufferIndex, PLOT_SHOW_DATA, true); + SetIndexBuffer(openBufferIndex, openBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(highBuffer, true); + PlotIndexSetInteger(highBufferIndex, PLOT_SHOW_DATA, true); + SetIndexBuffer(highBufferIndex, highBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(closeBuffer, true); + PlotIndexSetInteger(closeBufferIndex, PLOT_SHOW_DATA, true); + SetIndexBuffer(closeBufferIndex, closeBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(lowBuffer, true); + PlotIndexSetInteger(lowBufferIndex, PLOT_SHOW_DATA, true); + SetIndexBuffer(lowBufferIndex, lowBuffer, INDICATOR_DATA); + + // + bool canShowMa = showMa; + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + PlotIndexSetDouble(maPlotBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(maPlotBufferIndex, PLOT_DRAW_BEGIN, maLength); + PlotIndexSetInteger(maPlotBufferIndex, PLOT_SHOW_DATA, showMa); + + // + // Data Buffers ... + + // + // The TicksBuffer[] array is used for intermediate calculations + SetIndexBuffer(ticksBufferIndex, ticksBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(maPriceBuffer, true); + SetIndexBuffer(maPriceBufferIndex, maPriceBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param barIndex: Integer ... + */ +void CalculateBuffers( + int barIndex, + int prevCalculated, + int ratesTotal // +) +{ + // + bool canDoMovingAverage = + maLength > 0 && + maAppliedTo != X_PRICE_UP && + maAppliedTo != X_PRICE_DOWN; + if (canDoMovingAverage) + { + // + // Do Moving Average Calculations ... + + // + // Select Ma Price ... + double iPrice = 0; + switch (maAppliedTo) + { + // + case X_PRICE_HIGH: + iPrice = highBuffer[barIndex]; + break; + + // + case X_PRICE_OPEN: + iPrice = openBuffer[barIndex]; + break; + + // + case X_PRICE_CLOSE: + iPrice = closeBuffer[barIndex]; + break; + + // + case X_PRICE_LOW: + iPrice = lowBuffer[barIndex]; + break; + } + + // + maPriceBuffer[barIndex] = iPrice; + int total = ArraySize(closeBuffer); + + // + int calculatedMas = iMAOnBuffer( + total, + prevCalculated, + barIndex, + maLength, + maPriceBuffer, + maBuffer, + maMethod // + ); + } +} + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/test.stategy.mq5 b/BKPS/14030923/Documents/BKP/test.stategy.mq5 new file mode 100644 index 0000000..16d7606 --- /dev/null +++ b/BKPS/14030923/Documents/BKP/test.stategy.mq5 @@ -0,0 +1,214 @@ + // + // Draw Last Sar Change ... + string iVLineName = sarChangeBar.GetTag("XSAR"); + CChartObjectVLine *iVLineObj; + iVLineObj = new CChartObjectVLine(); + result = iVLineObj.Create( + ChartID(), + iVLineName, + 0, + sarChangeBar.time // + ); + if (result) + { + iVLineObj.Color(clrYellow); + } + + + + // + // Draw Last Decision Bar ... + string iVLineNameDecision = decisionBar.GetTag("XDECISION"); + CChartObjectVLine *iVLineDecisionObj; + iVLineDecisionObj = new CChartObjectVLine(); + result = iVLineDecisionObj.Create( + ChartID(), + iVLineNameDecision, + 0, + decisionBar.time // + ); + if (result) + { + iVLineDecisionObj.Color(clrYellow); + } + + + // + // Draw Breaker Bar ... + string iVLineNameBreaker = breakerBar.GetTag("XBREAKER"); + CChartObjectVLine *iVLineBreakerObj; + iVLineBreakerObj = new CChartObjectVLine(); + result = iVLineBreakerObj.Create( + ChartID(), + iVLineNameBreaker, + 0, + breakerBar.time // + ); + if (result) + { + iVLineBreakerObj.Color(clrMagenta); + } + + + + // + // TODO: Remove This ... + bool ignoreSwingHighs = true; + bool ignoreSwingLows = true; + bool ignoreSupportZones = true; + bool ignoreResistanceZones = true; + bool ignoreSupplyZones = true; + bool ignoreDemandZones = true; + bool ignoreBullishOrderBlocks = true; + bool ignoreBearishOrderBlocks = true; + bool ignoreBullishFairValueGaps = true; + bool ignoreBearishFairValueGaps = true; + bool ignoreBullishRejectionBars = true; + bool ignoreBearishRejectionBars = true; + bool ignoreBullishMomentumBars = true; + bool ignoreBearishMomentumBars = true; + + // + if (IsBullish(marketStructureDir)) + { + // + ignoreSwingLows = true; + ignoreSupportZones = true; + ignoreDemandZones = true; + ignoreBullishOrderBlocks = true; + ignoreBullishFairValueGaps = false; + ignoreBullishRejectionBars = false; + ignoreBullishMomentumBars = false; + + // + ignoreSwingHighs = true; + ignoreResistanceZones = true; + ignoreSupplyZones = true; + ignoreBearishOrderBlocks = true; + ignoreBearishFairValueGaps = true; + ignoreBearishRejectionBars = true; + ignoreBearishMomentumBars = true; + } + else + { + // + ignoreSwingLows = true; + ignoreSupportZones = true; + ignoreDemandZones = true; + ignoreBullishOrderBlocks = true; + ignoreBullishFairValueGaps = true; + ignoreBullishRejectionBars = true; + ignoreBullishMomentumBars = true; + + // + ignoreSwingHighs = true; + ignoreResistanceZones = true; + ignoreSupplyZones = true; + ignoreBearishOrderBlocks = true; + ignoreBearishFairValueGaps = false; + ignoreBearishRejectionBars = false; + ignoreBearishMomentumBars = false; + } + + // + RedrawOrderFlow( + true, // Force Clean ... + false, // Same Period ... + true, // Order Flow ... + true, // Order Flow State ... + false, // Only Last Order Flow ... + true, // Only Last Order Flow State ... + // + marketStructureDir, // Direction Force ... + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + + + +///////////////////////////////////////////////////// + + /** + * Validate an Order Block is Not Touched ... + * + * @param bar: XOHCL instance, start bar ... + * + * @return ( bool ) + */ + bool ValidateOrderBlock( + XCOrderBlock *ob, + XOHCL &bar // + ) + { + // + bool result = false; + + // + result = + bar.IsValid() && + ob.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = ob.IsBullish(); + + // + XOHCL mBar; + result = bar.BarIn(ob.GetPeriod(), mBar); + if (!result) { + return result; + } + + // + int start = mBar.Index(); + int end = mBar.Index(ob.From()); + result = IsValidIndex(start) && + IsValidIndex(end); + if (!result) + { + return result; + } + + // + for (int i = start; i < end; i++) + { + // + XOHCL iBar; + result = mBar.BarAt( + i, + iBar // + ); + if (!result) + { + break; + } + + // + result = + isBullish + ? iBar.low > ob.Upper() + : iBar.high < ob.Lower(); + if (!result) + { + break; + } + } + + // + return result; + } diff --git a/BKPS/14030923/Documents/BKP/tmp.base.x121.mq5 b/BKPS/14030923/Documents/BKP/tmp.base.x121.mq5 new file mode 100644 index 0000000..8647e57 --- /dev/null +++ b/BKPS/14030923/Documents/BKP/tmp.base.x121.mq5 @@ -0,0 +1,153 @@ + + /** + * Check Ticks is Bullish or not ... + * + * @return ( bool ) + */ + bool IsTicksBullish() + { + // + bool result = false; + + // + int start = -1; + int end = -1; + int requiredBullishTicks = 5; + CalculateTicksParams( + start, + end, + requiredBullishTicks // + ); + result = IsValidIndex(start) && + IsValidIndex(end); + if (!result) + { + return result; + } + + // + result = true; + for (int i = start + 1; i < end; i++) + { + // + XTick iTick = mTicks[i]; + XTick prevTick = mTicks[i - 1]; + + // + bool isBullish = iTick.bid >= prevTick.bid; + result = result && isBullish; + if (!result) + { + break; + } + } + + // + return result; + } + + /** + * Check Ticks is Bearish or not ... + * + * @return ( bool ) + */ + bool IsTicksBearish() + { + // + bool result = false; + + // + int start = -1; + int end = -1; + int requiredBearishTicks = 5; + CalculateTicksParams( + start, + end, + requiredBearishTicks // + ); + result = IsValidIndex(start) && + IsValidIndex(end); + if (!result) + { + return result; + } + + // + result = true; + for (int i = start + 1; i < end; i++) + { + // + XTick iTick = mTicks[i]; + XTick prevTick = mTicks[i - 1]; + + // + bool isBearish = iTick.bid <= prevTick.bid; + result = result && isBearish; + if (!result) + { + break; + } + } + + // + return result; + } + + /** + * Check Ticks Has Momentum or not ... + * + * @return ( bool ) + */ + bool IsTicksHasMomentum() + { + // + bool result = false; + + // + int start = -1; + int end = -1; + int requiredTicksForMomentum = 5; + CalculateTicksParams( + start, + end, + requiredTicksForMomentum // + ); + result = IsValidIndex(start) && + IsValidIndex(end); + if (!result) + { + return result; + } + + // + result = true; + int lastDiff = 0; + for (int i = start + 1; i < end; i++) + { + // + XTick iTick = mTicks[i]; + XTick prevTick = mTicks[i - 1]; + + // + int timeDiff = MathAbs((int)iTick.time - (int)prevTick.bid); + if (lastDiff <= 0) + { + lastDiff = timeDiff; + } + result = result && timeDiff >= lastDiff; + if (!result) + { + break; + } + + // + lastDiff = timeDiff; + } + + // + return result; + } + + +/////////////////////////////////////////////////////////////////////// + diff --git a/BKPS/14030923/Documents/BKP/tmp.x121.smc.mq5 b/BKPS/14030923/Documents/BKP/tmp.x121.smc.mq5 new file mode 100644 index 0000000..e150fef --- /dev/null +++ b/BKPS/14030923/Documents/BKP/tmp.x121.smc.mq5 @@ -0,0 +1,9403 @@ + +// +// Peaks ... +int peaksCount = ArraySize(conditions.peaks); +if (IsValidSize(peaksCount)) +{ + // + for (int i = 0; i < peaksCount; i++) + { + // + XPVPivot iPivot = conditions.peaks[i]; + + // + XCXPVPivotObject *iObj; + iObj = new XCXPVPivotObject(); + + // + bool isCreated = iObj.Create( + mPOIDrawer.ChartIdentification(), + mPOIDrawer.SubWindowIdentification(), + iPivot // + ); + if (isCreated) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotColor(clrAqua); + iObj.PivotStyle(STYLE_SOLID); + + // + AddObjectIfNotExists(iObj); + } + } +} + +// +// Vales ... +int valesCount = ArraySize(conditions.vales); +if (IsValidSize(valesCount)) +{ + // + for (int i = 0; i < valesCount; i++) + { + // + XPVPivot iPivot = conditions.vales[i]; + + // + XCXPVPivotObject *iObj; + iObj = new XCXPVPivotObject(); + + // + bool isCreated = iObj.Create( + mPOIDrawer.ChartIdentification(), + mPOIDrawer.SubWindowIdentification(), + iPivot // + ); + if (isCreated) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotStyle(STYLE_SOLID); + iObj.PivotColor(clrMagenta); + + // + AddObjectIfNotExists(iObj); + } + } +} + +/////////////////////////////////////////////////////////////////// +// Conditions Parsing ... +/////////////////////////////////////////////////////////////////// + +// +// Conditions Props ... + +// +// D1 ... + +// +XPOIState d1State; +ENUM_X_DIRECTION d1MarketDirection; +XCSupportZone *d1SupportZones[]; +XCResistanceZone *d1ResistanceZones[]; + +// +XCSwing *d1SwingHigh; +XCSwing *d1SwingLow; + +// +// H4 ... + +// +XPOIState h4State; +ENUM_X_DIRECTION h4MarketDirection; +XCSupportZone *h4SupportZones[]; +XCResistanceZone *h4ResistanceZones[]; + +// +XCSwing *h4SwingHigh; +XCSwing *h4SwingLow; + +// +// H2 ... + +// +XPOIState h2State; +ENUM_X_DIRECTION h2MarketDirection; +XCSupportZone *h2SupportZones[]; +XCResistanceZone *h2ResistanceZones[]; + +// +XCSwing *h2SwingHigh; +XCSwing *h2SwingLow; + +// +// H1 ... + +// +XPOIState h1State; +ENUM_X_DIRECTION h1MarketDirection; +XCSupportZone *h1SupportZones[]; +XCResistanceZone *h1ResistanceZones[]; + +// +XCSwing *h1SwingHigh; +XCSwing *h1SwingLow; + +// +// M15 ... + +// +XPOIState m15State; +ENUM_X_DIRECTION m15MarketDirection; +XCSupportZone *m15SupportZones[]; +XCResistanceZone *m15ResistanceZones[]; + +// +XCSwing *m15SwingHigh; +XCSwing *m15SwingLow; + +// +// M5 ... + +// +XPOIState m5State; +ENUM_X_DIRECTION m5MarketDirection; +XCSupportZone *m5SupportZones[]; +XCResistanceZone *m5ResistanceZones[]; + +// +XCSwing *m5SwingHigh; +XCSwing *m5SwingLow; + +// +// M1 ... + +// +XPOIState m1State; +ENUM_X_DIRECTION m1MarketDirection; +XCSupportZone *m1SupportZones[]; +XCResistanceZone *m1ResistanceZones[]; + +// +XCSwing *m1SwingHigh; +XCSwing *m1SwingLow; + +// +// Clean Method ... + +// +// D1 ... + +// +d1State.Clean(); +d1MarketDirection = X_DIRECTION_NONE; +Clean(d1SupportZones); +Clean(d1ResistanceZones); + +// +d1SwingHigh = NULL; +d1SwingLow = NULL; + +// +// H4 ... + +// +h4State.Clean(); +h4MarketDirection = X_DIRECTION_NONE; +Clean(h4SupportZones); +Clean(h4ResistanceZones); + +// +h4SwingHigh = NULL; +h4SwingLow = NULL; + +// +// H2 ... + +// +h2State.Clean(); +h2MarketDirection = X_DIRECTION_NONE; +Clean(h2SupportZones); +Clean(h2ResistanceZones); + +// +h2SwingHigh = NULL; +h2SwingLow = NULL; + +// +// H1 ... + +// +h1State.Clean(); +h1MarketDirection = X_DIRECTION_NONE; +Clean(h1SupportZones); +Clean(h1ResistanceZones); + +// +h1SwingHigh = NULL; +h1SwingLow = NULL; + +// +// M15 ... + +// +m15State.Clean(); +m15MarketDirection = X_DIRECTION_NONE; +Clean(m15SupportZones); +Clean(m15ResistanceZones); + +// +m15SwingHigh = NULL; +m15SwingLow = NULL; + +// +// M5 ... + +// +m5State.Clean(); +m5MarketDirection = X_DIRECTION_NONE; +Clean(m5SupportZones); +Clean(m5ResistanceZones); + +// +m5SwingHigh = NULL; +m5SwingLow = NULL; + +// +// M1 ... + +// +m1State.Clean(); +m1MarketDirection = X_DIRECTION_NONE; +Clean(m1SupportZones); +Clean(m1ResistanceZones); + +// +m1SwingHigh = NULL; +m1SwingLow = NULL; + +// +// Tools Functions ... +// + +// +// Custom Tools ... + +/** + * Check Conditions for Detect Market Structure ... + * + * @param structure: ENUM_X_DIRECTION member, Market Structure Direction reference ... + * + * @return ( bool ) + */ +bool HasMarketStructure( + ENUM_X_DIRECTION &structure // +) +{ + // + bool result = false; + + // + structure = X_DIRECTION_NONE; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + bool is1DBullish = IsBullish(d1MarketDirection); + bool is1DBearish = IsBearish(d1MarketDirection); + + // + bool is4HBullish = IsBullish(h4MarketDirection); + bool is4HBearish = IsBearish(h4MarketDirection); + + // + bool is2HBullish = IsBullish(h2MarketDirection); + bool is2HBearish = IsBearish(h2MarketDirection); + + // + bool is1HBullish = IsBullish(h1MarketDirection); + bool is1HBearish = IsBearish(h1MarketDirection); + + // + bool is15MBullish = IsBullish(m15MarketDirection); + bool is15MBearish = IsBearish(m15MarketDirection); + + // + bool is5MBullish = IsBullish(m5MarketDirection); + bool is5MBearish = IsBearish(m5MarketDirection); + + // + bool is1MBullish = IsBullish(m1MarketDirection); + bool is1MBearish = IsBearish(m1MarketDirection); + + // + bool isStructuresBullish = + // + is1HBullish && + is15MBullish && + is5MBullish + // + ; + + // + bool isStructuresBearish = + // + is1HBearish && + is15MBearish && + is5MBearish + // + ; + + // + bool hasMarketStructure = + isStructuresBullish || + isStructuresBearish; + result = hasMarketStructure; + if (!result) + { + return result; + } + + // + structure = + isStructuresBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; +} + +// +// Strategy Class Calling on Conditions Detections ... + +// +// Detect Market Structures ... + +// +// 1D ... +conditions.d1State = _1DState; +result = DetectMarketStructure( + conditions.d1MarketDirection, + conditions.d1SupportZones, + conditions.d1ResistanceZones, + _1DState // +); +if (!result) +{ + return result; +} + +// +// 4H ... +conditions.h4State = _4HState; +result = DetectMarketStructure( + conditions.h4MarketDirection, + conditions.h4SupportZones, + conditions.h4ResistanceZones, + _4HState // +); +if (!result) +{ + return result; +} + +// +// 2H ... +conditions.h2State = _2HState; +result = DetectMarketStructure( + conditions.h2MarketDirection, + conditions.h2SupportZones, + conditions.h2ResistanceZones, + _2HState // +); +if (!result) +{ + return result; +} + +// +// 1H ... +conditions.h1State = _1HState; +result = DetectMarketStructure( + conditions.h1MarketDirection, + conditions.h1SupportZones, + conditions.h1ResistanceZones, + _1HState // +); +if (!result) +{ + return result; +} + +// +// 15M ... +conditions.m15State = _15MState; +result = DetectMarketStructure( + conditions.m15MarketDirection, + conditions.m15SupportZones, + conditions.m15ResistanceZones, + _15MState // +); +if (!result) +{ + return result; +} + +// +// 5M ... +conditions.m5State = _5MState; +result = DetectMarketStructure( + conditions.m5MarketDirection, + conditions.m5SupportZones, + conditions.m5ResistanceZones, + _5MState // +); +if (!result) +{ + return result; +} + +// +// 1M ... +conditions.m1State = _1MState; +result = DetectMarketStructure( + conditions.m1MarketDirection, + conditions.m1SupportZones, + conditions.m1ResistanceZones, + _1MState // +); +if (!result) +{ + return result; +} + +// +// 1H-15M-5M ... +ENUM_X_DIRECTION marketStructure = X_DIRECTION_NONE; +result = conditions.HasMarketStructure(marketStructure); +if (!result) +{ + return result; +} + +// +// Detect Swing High and Swing Low ... +// 1H-15M-5M ... +int count = 0; + +// +// 1H ... + +// +XCSwing *h1SwingLows[]; +XCSwing *h1SwingHighs[]; +XCSupportZone *h1SupportZone = NULL; +XCResistanceZone *h1ResistanceZone = NULL; + +// +count = ArraySize(conditions.h1SupportZones); +if (IsValidSize(count)) +{ + // + for (int i = 0; i < count; i++) + { + // + XCSupportZone *item = conditions.h1SupportZones[i]; + + // + bool canSelect = + h1SupportZone == NULL || + h1SupportZone.Lower() < item.Lower(); + if (canSelect) + { + h1SupportZone = item; + } + } +} +if (h1SupportZone != NULL) +{ + // + // Detect Swings ... + count = ArraySize(conditions.h1State.swingLows); + if (IsValidSize(count)) + { + // + double upper = h1SupportZone.Upper(); + double lower = h1SupportZone.Lower(); + + // + for (int i = 0; i < count; i++) + { + // + XCSwing *item = conditions.h1State.swingLows[i]; + + // + XOHCL iBar; + bool isFilled = item.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool canSelect = (iBar.high <= upper && + iBar.low >= lower) || + (iBar.high >= upper && + iBar.low <= lower); + if (canSelect) + { + // + Add( + item, + h1SwingLows // + ); + + // + // Draw ... + XCSwingLowObject *iObj; + bool isCreated = mPOIDrawer.CreateSwingLow( + item, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + } + } + + // + // Draw ... + XCSupportZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateSupportZone( + h1SupportZone, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } +} + +// +count = ArraySize(conditions.h1ResistanceZones); +if (IsValidSize(count)) +{ + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZone *item = conditions.h1ResistanceZones[i]; + + // + bool canSelect = + h1ResistanceZone == NULL || + h1ResistanceZone.Upper() > item.Upper(); + if (canSelect) + { + h1ResistanceZone = item; + } + } +} +if (h1ResistanceZone != NULL) +{ + // + // Detect Swings ... + count = ArraySize(conditions.h1State.swingHighs); + if (IsValidSize(count)) + { + // + double upper = h1ResistanceZone.Upper(); + double lower = h1ResistanceZone.Lower(); + + // + for (int i = 0; i < count; i++) + { + // + XCSwing *item = conditions.h1State.swingHighs[i]; + + // + XOHCL iBar; + bool isFilled = item.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool canSelect = (iBar.high <= upper && + iBar.low >= lower) || + (iBar.high >= upper && + iBar.low <= lower); + if (canSelect) + { + // + Add( + item, + h1SwingHighs // + ); + + // + // Draw ... + XCSwingHighObject *iObj; + bool isCreated = mPOIDrawer.CreateSwingHigh( + item, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + } + } + + // + // Draw ... + XCResistanceZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateResistanceZone( + h1ResistanceZone, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } +} + +// +// 15M ... + +// +XCSupportZone *m15SupportZone = NULL; +count = ArraySize(conditions.m15SupportZones); +if (IsValidSize(count)) +{ + // + for (int i = 0; i < count; i++) + { + // + XCSupportZone *item = conditions.m15SupportZones[i]; + + // + bool canSelect = + m15SupportZone == NULL || + m15SupportZone.Lower() < item.Lower(); + if (canSelect) + { + m15SupportZone = item; + } + } +} +if (m15SupportZone != NULL) +{ + // + XCSupportZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateSupportZone( + m15SupportZone, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } +} + +// +XCResistanceZone *m15ResistanceZone = NULL; +count = ArraySize(conditions.m15ResistanceZones); +if (IsValidSize(count)) +{ + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZone *item = conditions.m15ResistanceZones[i]; + + // + bool canSelect = + m15ResistanceZone == NULL || + m15ResistanceZone.Upper() > item.Upper(); + if (canSelect) + { + m15ResistanceZone = item; + } + } +} +if (m15ResistanceZone != NULL) +{ + // + XCResistanceZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateResistanceZone( + m15ResistanceZone, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } +} + +// +// 5M ... + +// +XCSupportZone *m5SupportZone = NULL; +count = ArraySize(conditions.m5SupportZones); +if (IsValidSize(count)) +{ + // + for (int i = 0; i < count; i++) + { + // + XCSupportZone *item = conditions.m5SupportZones[i]; + + // + bool canSelect = + m5SupportZone == NULL || + m5SupportZone.Lower() < item.Lower(); + if (canSelect) + { + m5SupportZone = item; + } + } +} +if (m5SupportZone != NULL) +{ + // + XCSupportZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateSupportZone( + m5SupportZone, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } +} + +// +XCResistanceZone *m5ResistanceZone = NULL; +count = ArraySize(conditions.m5ResistanceZones); +if (IsValidSize(count)) +{ + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZone *item = conditions.m5ResistanceZones[i]; + + // + bool canSelect = + m5ResistanceZone == NULL || + m5ResistanceZone.Upper() > item.Upper(); + if (canSelect) + { + m5ResistanceZone = item; + } + } +} +if (m5ResistanceZone != NULL) +{ + // + XCResistanceZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateResistanceZone( + m5ResistanceZone, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } +} + +// +// DrawState(_5MState); + +// +// +// Strategy Class Tools Functions ... + +/** + * Detect Specified States Market Structure ... + * + * @param dir: ENUM_X_DIRECTION member, Refrence ... + * @param state: XPOIState instance ... + * + * @return ( bool ) + */ +bool DetectMarketStructure( + ENUM_X_DIRECTION &dir, + XCSupportZone *&supportZones[], + XCResistanceZone *&resistanceZones[], + XPOIState &state // +) +{ + // + bool result = false; + + // + int count = 0; + + // + // Filter Untouched Supports ... + Clean(supportZones); + int untouchedSupportsCount = 0; + count = ArraySize(state.supportZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZone *item = state.supportZones[i]; + + // + // Find Breakout Bar + XOHCL iBar; + bool isFilled = item.FillBar(iBar); + if (!isFilled) + { + break; + } + + // + int iBarIndex = iBar.Index(); + int iBarUnTouchedCount = 0; + for (int j = 0; j < iBarIndex; j++) + { + // + XOHCL jBar; + bool isInited = jBar.Init( + iBar.symbol, + iBar.period, + j // + ); + if (!isInited) + { + break; + } + + // + bool isUntouched = + jBar.low > item.Upper(); + if (isUntouched) + { + iBarUnTouchedCount++; + } + else + { + iBarUnTouchedCount--; + } + } + + // + if (iBarUnTouchedCount > 0) + { + // + Add( + item, + supportZones // + ); + } + } + + // + untouchedSupportsCount = ArraySize(supportZones); + if (IsValidSize(untouchedSupportsCount)) + { + // + // Draw ... + // for (int i = 0; i < untouchedSupportsCount; i++) + // { + // // + // XCSupportZone *item = supportZones[i]; + + // // + // XCSupportZoneObject *iObj; + // bool isCreated = mPOIDrawer.CreateSupportZone( + // item, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + // } + } + } + + // + // Filter Untouched Resistances ... + Clean(resistanceZones); + int untouchedResistancesCount = 0; + count = ArraySize(state.resistanceZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZone *item = state.resistanceZones[i]; + + // + // Find Breakout Bar + XOHCL iBar; + bool isFilled = item.FillBar(iBar); + if (!isFilled) + { + break; + } + + // + int iBarIndex = iBar.Index(); + int iBarUnTouchedCount = 0; + for (int j = 0; j < iBarIndex; j++) + { + // + XOHCL jBar; + bool isInited = jBar.Init( + iBar.symbol, + iBar.period, + j // + ); + if (!isInited) + { + break; + } + + // + bool isUntouched = + jBar.high < item.Lower(); + if (isUntouched) + { + iBarUnTouchedCount++; + } + else + { + iBarUnTouchedCount--; + } + } + + // + if (iBarUnTouchedCount > 0) + { + // + Add( + item, + resistanceZones // + ); + } + } + + // + untouchedResistancesCount = ArraySize(resistanceZones); + if (IsValidSize(untouchedResistancesCount)) + { + // + // Draw ... + // for (int i = 0; i < untouchedResistancesCount; i++) + // { + // // + // XCResistanceZone *item = resistanceZones[i]; + + // // + // XCResistanceZoneObject *iObj; + // bool isCreated = mPOIDrawer.CreateResistanceZone( + // item, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + // } + } + } + + // + bool hasBullishStructure = + IsValidSize(untouchedSupportsCount) && + untouchedSupportsCount > untouchedResistancesCount; + bool hasBearishStructure = + IsValidSize(untouchedResistancesCount) && + untouchedResistancesCount > untouchedSupportsCount; + + // + result = (hasBullishStructure && + !hasBearishStructure) || + (hasBearishStructure && + !hasBullishStructure); + + // + if (result) + { + // + dir = + hasBullishStructure + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; +} + +//////////////////////////////////////////////////////////////////////////// + +// +// Detect Order Blocks ... +// int obsCount = 0; + +// +// Find Bullish Order Block ... +// XCOrderBlock *bullishOB = NULL; +// XCRejectionBar *bullishOBRejectionBar = NULL; +// obsCount = lastPivot.state.CountBullishOrderBlocks(); +// if (IsValidSize(obsCount)) +// { +// // +// for (int i = 0; i < obsCount; i++) +// { +// // +// XCOrderBlock *iOB = lastPivot.state.bullishOrderBlocks[i]; + +// // +// XOHCL iBar; +// bool hasBar = iOB.FillBar(iBar); +// bool isPeriodSame = hasBar && +// iBar.period == _period; + +// // +// if (iOB.Upper() <= pivotMid && +// iOB.Lower() >= lastPivot.lower) +// { +// // +// bullishOB = iOB; +// break; +// } +// } +// } +// bool hasBullishOB = bullishOB != NULL; +// bool isBullishOBRejected = false; +// if (hasBullishOB) +// { +// // +// int bullishRejectedBarsCount = lastPivot.state.CountBullishRejectionBars(); +// if (IsValidSize(bullishRejectedBarsCount)) +// { +// // +// for (int i = 0; i < bullishRejectedBarsCount; i++) +// { +// // +// XCRejectionBar *item = lastPivot.state.bullishRejectionBars[i]; + +// // +// XOHCL iBar; +// bool isFilled = item.FillBar(iBar); +// if (!isFilled) +// { +// continue; +// } + +// // +// bool isRejected = iBar.low <= bullishOB.Lower() && +// (iBar.GetDown() <= bullishOB.Upper() || +// iBar.GetDown() > bullishOB.Upper()); + +// // +// isBullishOBRejected = +// bullishOBRejectionBar == NULL +// ? isRejected +// : isRejected && +// item.From() > bullishOBRejectionBar.From(); +// if (isBullishOBRejected) +// { +// bullishOBRejectionBar = item; +// } +// } +// } +// if (isBullishOBRejected) +// { +// // +// bullishOBRejectionBar.To(cTime); +// XCBullishRejectionBarObject *iObj; +// bool isCreated = mPOIDrawer.CreateBullishRejectionBar( +// bullishOBRejectionBar, +// iObj // +// ); +// if (isCreated) +// { +// AddObjectIfNotExists(iObj); +// } +// } + +// // +// bullishOB.To(cTime); +// XCBullishOrderBlockObject *iObj; +// bool isCreated = mPOIDrawer.CreateBullishOrderBlock( +// bullishOB, +// iObj // +// ); +// if (isCreated) +// { +// AddObjectIfNotExists(iObj); +// } +// } + +// +// Find Bearish Order Block ... +// XCOrderBlock *bearishOB = NULL; +// XCRejectionBar *bearishOBRejectionBar = NULL; +// obsCount = lastPivot.state.CountBearishOrderBlocks(); +// if (IsValidSize(obsCount)) +// { +// // +// for (int i = 0; i < obsCount; i++) +// { +// // +// XCOrderBlock *iOB = lastPivot.state.bearishOrderBlocks[i]; + +// // +// XOHCL iBar; +// bool hasBar = iOB.FillBar(iBar); +// bool isPeriodSame = hasBar && +// iBar.period == _period; + +// // +// if (iOB.Lower() >= pivotMid && +// iOB.Upper() <= lastPivot.upper) +// { +// // +// bearishOB = iOB; +// break; +// } +// } +// } +// bool hasBearishOB = bearishOB != NULL; +// bool isBearishOBRejected = false; +// if (hasBearishOB) +// { +// // +// int bearishRejectedBarsCount = lastPivot.state.CountBearishRejectionBars(); +// if (IsValidSize(bearishRejectedBarsCount)) +// { +// // +// for (int i = 0; i < bearishRejectedBarsCount; i++) +// { +// // +// XCRejectionBar *item = lastPivot.state.bearishRejectionBars[i]; + +// // +// XOHCL iBar; +// bool isFilled = item.FillBar(iBar); +// if (!isFilled) +// { +// continue; +// } + +// // +// bool isRejected = iBar.high >= bearishOB.Upper() && +// (iBar.GetUp() <= bearishOB.Lower() || +// iBar.GetUp() > bearishOB.Lower()); + +// // +// isBearishOBRejected = +// bearishOBRejectionBar == NULL +// ? isRejected +// : isRejected && +// item.From() > bearishOBRejectionBar.From(); +// if (isBearishOBRejected) +// { +// bearishOBRejectionBar = item; +// } +// } +// } +// if (isBearishOBRejected) +// { +// // +// bearishOBRejectionBar.To(cTime); +// XCBearishRejectionBarObject *iObj; +// bool isCreated = mPOIDrawer.CreateBearishRejectionBar( +// bearishOBRejectionBar, +// iObj // +// ); +// if (isCreated) +// { +// AddObjectIfNotExists(iObj); +// } +// } + +// // +// bearishOB.To(cTime); +// XCBearishOrderBlockObject *iObj; +// bool isCreated = mPOIDrawer.CreateBearishOrderBlock( +// bearishOB, +// iObj // +// ); +// if (isCreated) +// { +// AddObjectIfNotExists(iObj); +// } +// } + +// // +// // Find an Order Block ... +// bool isBearishOrderBlockRejected = false; + +///////////////////////////////////////////////////////////////////////////// + +// +RedrawOrderFlow(); + +// +// Check Candlestick PullBacks ... +ENUM_X_DIRECTION pullBackDir; +bool hasPullBack = mBarAnalyser.HasPullBack( + pullBackDir, + cBar, + 3, // Loopback ... + true // Force Body ... +); +bool hasBullishPullback = + hasPullBack && + pullBackDir == X_DIRECTION_BULLISH; +bool hasBearishPullback = + hasPullBack && + pullBackDir == X_DIRECTION_BEARISH; + +// +bool isInDiscount = + bid < pivotMid && + bid > lastPivot.lower; + +// +bool isInPremium = + bid > pivotMid && + bid < lastPivot.upper; + +// +// Check Order Flow Validation ... + +// +// For Bullish Order Flow ... +// if Price Breakes Lower to Down, means Change of Charcter Happens ... +bool isCHOCHHappens = + isBullishOrderFlow ? bid < lastPivot.lower - pip + : bid > lastPivot.upper + pip; + +// +// For Bullish Order Flow ... +// if Price Breakes Upper to Up, means Breake of Structure Happens ... +bool isBOSHappens = + isBullishOrderFlow ? bid > lastPivot.upper + pip + : bid < lastPivot.lower - pip; + +// +if (isBOSHappens) +{ + // + // RedrawOrderFlow(); + Print(""); +} + +// +if (isCHOCHHappens) +{ + // + result = false; + ResetOrderFlow(); + return result; +} + +// +// Check 3MA and 3VWAP State ... + +// +bool isVWAPBullishOrdered = + // + ( + // + (conditions.x3vwapConditions.isBullishOrdered || + conditions.x3vwapConditions.isSwitchedToBullishOrdered) + // + || + // + conditions.x3vwapConditions.fasts[cIndex] > conditions.x3vwapConditions.mids[cIndex] + // + || + // + conditions.x3vwapConditions.mids[cIndex] > conditions.x3vwapConditions.slows[cIndex] + // + ) + // + ; + +// +bool isVWAPBearishOrdered = + // + ( + // + (conditions.x3vwapConditions.isBearishOrdered || + conditions.x3vwapConditions.isSwitchedToBearishOrdered) + // + || + // + conditions.x3vwapConditions.fasts[cIndex] < conditions.x3vwapConditions.mids[cIndex] + // + || + // + conditions.x3vwapConditions.mids[cIndex] < conditions.x3vwapConditions.slows[cIndex] + // + ) + // + ; + +// +bool isVWapBullishState = + // + ( + // + (conditions.x3vwapConditions.isBullishState || + conditions.x3vwapConditions.isSwitchedToBullishState) + // + || + // + (x3vwapHelper.IsBullish(conditions.x3vwapConditions.fastStates[cIndex]) && + x3vwapHelper.IsBullish(conditions.x3vwapConditions.midStates[cIndex])) + // + || + // + (x3vwapHelper.IsBullish(conditions.x3vwapConditions.midStates[cIndex]) && + x3vwapHelper.IsBullish(conditions.x3vwapConditions.slowStates[cIndex])) + // + ) + // + ; + +// +bool isVWapBearishState = + // + ( + // + (conditions.x3vwapConditions.isBearishState || + conditions.x3vwapConditions.isSwitchedToBearishState) + // + || + // + (x3vwapHelper.IsBearish(conditions.x3vwapConditions.fastStates[cIndex]) && + x3vwapHelper.IsBearish(conditions.x3vwapConditions.midStates[cIndex])) + // + || + // + (x3vwapHelper.IsBearish(conditions.x3vwapConditions.midStates[cIndex]) && + x3vwapHelper.IsBearish(conditions.x3vwapConditions.slowStates[cIndex])) + // + ) + // + ; + +// +bool isVWapOverFastMA = + // + ( + // + (conditions.x3vwapConditions.fasts[cIndex] > conditions.x3maConditions.fasts[cIndex] && + conditions.x3vwapConditions.mids[cIndex] > conditions.x3maConditions.fasts[cIndex]) + // + || + // + (conditions.x3vwapConditions.fasts[cIndex] > conditions.x3maConditions.fasts[cIndex] && + conditions.x3vwapConditions.mids[cIndex] > conditions.x3maConditions.fasts[cIndex] && + conditions.x3vwapConditions.slows[cIndex] > conditions.x3maConditions.fasts[cIndex]) + // + ) + // + ; + +// +bool isVWapUnderFastMA = + // + ( + // + (conditions.x3vwapConditions.fasts[cIndex] < conditions.x3maConditions.fasts[cIndex] && + conditions.x3vwapConditions.mids[cIndex] < conditions.x3maConditions.fasts[cIndex]) + // + || + // + (conditions.x3vwapConditions.fasts[cIndex] < conditions.x3maConditions.fasts[cIndex] && + conditions.x3vwapConditions.mids[cIndex] < conditions.x3maConditions.fasts[cIndex] && + conditions.x3vwapConditions.slows[cIndex] < conditions.x3maConditions.fasts[cIndex]) + // + ) + // + ; + +// +bool is3Bullish = + // + ( + // + (isVWAPBullishOrdered && + isVWapBullishState) + // + || + // + (isVWAPBullishOrdered && + isVWapOverFastMA) + // + || + // + (isVWapBullishState && + isVWapOverFastMA) + // + ) + // + ; + +// +bool is3Bearish = + // + ( + // + (isVWAPBearishOrdered && + isVWapBearishState) + // + || + // + (isVWAPBearishOrdered && + isVWapUnderFastMA) + // + || + // + (isVWapBearishState && + isVWapUnderFastMA) + // + ) + // + ; + +// +// Check Parabolic Sars State ... + +// +bool isSarBullish = + // + (conditions.xchsarConditions.isCBullish && + conditions.xchsarConditions.isSSwitchedBullish) + // + || + // + (conditions.xchsarConditions.isSBullish && + conditions.xchsarConditions.isCSwitchedBullish) + // + ; +bool isSarBearish = + // + (conditions.xchsarConditions.isCBearish && + conditions.xchsarConditions.isSSwitchedBearish) + // + || + // + (conditions.xchsarConditions.isSBearish && + conditions.xchsarConditions.isCSwitchedBearish) + // + ; + +// // +// hasLong = +// // +// is3Bullish && +// // isInDiscount && +// isSarBullish // && +// // hasBullishPullback && +// // bullishLiquidityPercent > 30 +// // +// ; + +// // +// hasShort = +// // +// is3Bearish && +// // isInPremium && +// isSarBearish // && +// // hasBearishPullback && +// // bearishLiquidityPercent > 30 +// // +// ; + +////////////////////// + +// +XPVPivot lastPivot; +result = GetLastItem( + lastPivot, + mOrderFlow // +); +if (!result) +{ + return result; +} +bool isBullishOrderFlow = IsBullish(mOrderFlowDir); +bool isBearishOrderFlow = IsBearish(mOrderFlowDir); +double pivotMid = lastPivot.CalculateMid(); + +// +// Calculate Liquidity Percent ... +double bullishLiquidityPercent = lastPivot + .CalculateLiquidityPercent(X_DIRECTION_BULLISH); +double bearishLiquidityPercent = lastPivot + .CalculateLiquidityPercent(X_DIRECTION_BEARISH); +double minLiquidityPercent = 35; +bool hasBullishLiquidity = bullishLiquidityPercent >= minLiquidityPercent; +bool hasBearishLiquidity = bearishLiquidityPercent >= minLiquidityPercent; +result = hasBullishLiquidity || + hasBearishLiquidity; +if (!result) +{ + return result; +} + +///////////////////////////////////////////////////////////////// + +// // +// // 1D Period ... +// // POI Detector ... +// m1DPOI = new XCPOIDetector( +// symbol, +// PERIOD_D1 // +// ); + +// // +// m1DPOI.MaxNumberOfRequiredPOIs(poiRequired); + +// // +// m1DPOI.Init(); + +// // +// // 4H Period ... +// // POI Detector ... +// m4HPOI = new XCPOIDetector( +// symbol, +// PERIOD_H4 // +// ); + +// // +// m4HPOI.MaxNumberOfRequiredPOIs(poiRequired); + +// // +// m4HPOI.Init(); + +// // +// // 2H Period ... +// // POI Detector ... +// m2HPOI = new XCPOIDetector( +// symbol, +// PERIOD_H2 // +// ); + +// // +// m2HPOI.MaxNumberOfRequiredPOIs(poiRequired); + +// // +// m2HPOI.Init(); + +// +// 1H Period ... +// POI Detector ... +// m1HPOI = new XCPOIDetector( +// symbol, +// PERIOD_H1 // +// ); + +// // +// m1HPOI.MaxNumberOfRequiredPOIs(poiRequired); + +// // +// m1HPOI.Init(); + +// +// 15M Period ... +// POI Detector ... +// m15MPOI = new XCPOIDetector( +// symbol, +// PERIOD_M15 // +// ); + +// // +// m15MPOI.MaxNumberOfRequiredPOIs(poiRequired); + +// // +// m15MPOI.Init(); + +// // +// // 5M Period ... +// // POI Detector ... +// m5MPOI = new XCPOIDetector( +// symbol, +// PERIOD_M5 // +// ); + +// // +// m5MPOI.MaxNumberOfRequiredPOIs(poiRequired); + +// // +// m5MPOI.Init(); + +// // +// // 1M Period ... +// // POI Detector ... +// m1MPOI = new XCPOIDetector( +// symbol, +// PERIOD_M1 // +// ); + +// // +// m1MPOI.MaxNumberOfRequiredPOIs(poiRequired); + +// // +// m1MPOI.Init(); + +//////////////////////////////// + +// delete m1DPOI; +// delete m4HPOI; +// delete m2HPOI; +delete m1HPOI; +delete m15MPOI; +// delete m5MPOI; +// delete m1MPOI; + +/////////////////////////////////// + +// +// Point Of Interests ... +XCPOIDetector *mTriggerPOIDetector; +XCPOIDetector *mAnalysePOIDetector; +XCPOIDetector *mVisionPOIDetector; + +// +// XCPOIDetector *m1DPOI; +// XCPOIDetector *m4HPOI; +// XCPOIDetector *m2HPOI; +// XCPOIDetector *m1HPOI; +// XCPOIDetector *m15MPOI; +// XCPOIDetector *m5MPOI; +// XCPOIDetector *m1MPOI; + +// +XPOIState mTriggerPOIState; +XPOIState mAnalysePOIState; +XPOIState mVisionPOIState; + +// XPOIState _1DState; +// XPOIState _4HState; +// XPOIState _2HState; +// XPOIState _1HState; +// XPOIState _15MState; +// XPOIState _5MState; +// XPOIState _1MState; +// XPOIState _CombineState; + +/////////////////////////////////////////// + +// +// Update POIs ... + +// +ENUM_XPOI_EVENTS _events[]; +mPOIDetector.Update(_events); + +// // +// ENUM_XPOI_EVENTS _1DStates[]; +// m1DPOI.Update(_1DStates); + +// // +// ENUM_XPOI_EVENTS _4HStates[]; +// m4HPOI.Update(_4HStates); + +// // +// ENUM_XPOI_EVENTS _2HStates[]; +// m2HPOI.Update(_2HStates); + +// +ENUM_XPOI_EVENTS _1HStates[]; +m1HPOI.Update(_1HStates); + +// // +// ENUM_XPOI_EVENTS _15MStates[]; +// m15MPOI.Update(_15MStates); + +// // +// ENUM_XPOI_EVENTS _5MStates[]; +// m5MPOI.Update(_5MStates); + +// // +// ENUM_XPOI_EVENTS _1MStates[]; +// m1MPOI.Update(_1MStates); + +// // +// // Read all POI States ... +mPOIDetector.GetState(_state); +// m1DPOI.GetState(_1DState); +// m4HPOI.GetState(_4HState); +// m2HPOI.GetState(_2HState); +m1HPOI.GetState(_1HState); +// m15MPOI.GetState(_15MState); +// m5MPOI.GetState(_5MState); +// m1MPOI.GetState(_1MState); + +// +// Combine States ... +// XPOIState _States[]; +// AddRef( +// _1DState, +// _States // +// ); +// AddRef( +// _4HState, +// _States // +// ); +// AddRef( +// _2HState, +// _States // +// ); +// AddRef( +// _1HState, +// _States // +// ); +// AddRef( +// _15MState, +// _States // +// ); +// AddRef( +// _5MState, +// _States // +// ); +// AddRef( +// _1MState, +// _States // +// ); +// CombineStates( +// _CombineState, +// _States // +// ); + +//////////////////////////////////////////////////////////////// + +// +// Works by WVAP and PSar ... +bool long1 = + // + conditions.x3vwapConditions.isBullishState && + conditions.x3vwapConditions.isBullishOrdered && + // conditions.xpvConditions.vales[cIndex] == conditions.xchsarConditions.cSars[cIndex] && + conditions.xchsarConditions.cSars[cIndex] < conditions.x3vwapConditions.slows[cIndex] + // + ; +if (long1) +{ + // + CustomStateDrawing(_1HState); + selectedSL = conditions.xpvConditions.vales[cIndex]; +} + +// +// Works by WVAP and PSar ... +bool short1 = + // + conditions.x3vwapConditions.isBearishState && + conditions.x3vwapConditions.isBearishOrdered && + // conditions.xpvConditions.peaks[cIndex] == conditions.xchsarConditions.cSars[cIndex] && + conditions.xchsarConditions.cSars[cIndex] > conditions.x3vwapConditions.slows[cIndex] + // + ; +if (short1) +{ + // + CustomStateDrawing(_1HState); + selectedSL = conditions.xpvConditions.peaks[cIndex]; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// + +// mOrderFlow[pivotIDX].state.ticksZone = +//_15MState.ticksZone; + +// // +// // D1 ... +// XPOIState d1; +// if (_1DState.HasChild()) +// { +// // +// DetectPivotPOIs( +// mOrderFlow[pivotIDX], +// _1DState, +// d1, +// lookupSwingHighs, +// lookupSwingLows, +// lookupSupportZones, +// lookupResistanceZones, +// lookupSupplyZones, +// lookupDemandZones, +// lookupBullishOrderBlocks, +// lookupBearishOrderBlocks, +// lookupBullishFairValueGaps, +// lookupBearishFairValueGaps, +// lookupBullishRejectionBars, +// lookupBearishRejectionBars, +// lookupBullishMomentumBars, +// lookupBearishMomentumBars // +// ); + +// // +// if (d1.HasChild()) +// { +// d1.Fill(mOrderFlow[pivotIDX].state); +// } +// } + +// // +// // H4 ... +// XPOIState h4; +// if (_4HState.HasChild()) +// { +// // +// DetectPivotPOIs( +// mOrderFlow[pivotIDX], +// _4HState, +// h4, +// lookupSwingHighs, +// lookupSwingLows, +// lookupSupportZones, +// lookupResistanceZones, +// lookupSupplyZones, +// lookupDemandZones, +// lookupBullishOrderBlocks, +// lookupBearishOrderBlocks, +// lookupBullishFairValueGaps, +// lookupBearishFairValueGaps, +// lookupBullishRejectionBars, +// lookupBearishRejectionBars, +// lookupBullishMomentumBars, +// lookupBearishMomentumBars // +// ); + +// // +// if (h4.HasChild()) +// { +// h4.Fill(mOrderFlow[pivotIDX].state); +// } +// } + +// +// H2 ... +// XPOIState h2; +// if (_2HState.HasChild()) +// { +// // +// DetectPivotPOIs( +// mOrderFlow[pivotIDX], +// _2HState, +// h2, +// lookupSwingHighs, +// lookupSwingLows, +// lookupSupportZones, +// lookupResistanceZones, +// lookupSupplyZones, +// lookupDemandZones, +// lookupBullishOrderBlocks, +// lookupBearishOrderBlocks, +// lookupBullishFairValueGaps, +// lookupBearishFairValueGaps, +// lookupBullishRejectionBars, +// lookupBearishRejectionBars, +// lookupBullishMomentumBars, +// lookupBearishMomentumBars // +// ); + +// // +// if (h2.HasChild()) +// { +// h2.Fill(mOrderFlow[pivotIDX].state); +// } +// } + +// +// H1 ... +XPOIState h1; +if (_1HState.HasChild()) +{ + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + _1HState, + h1, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (h1.HasChild()) + { + h1.Fill(mOrderFlow[pivotIDX].state); + } +} + +// +// M15 ... +// XPOIState m15; +// if (_15MState.HasChild()) +// { +// // +// DetectPivotPOIs( +// mOrderFlow[pivotIDX], +// _15MState, +// m15, +// lookupSwingHighs, +// lookupSwingLows, +// lookupSupportZones, +// lookupResistanceZones, +// lookupSupplyZones, +// lookupDemandZones, +// lookupBullishOrderBlocks, +// lookupBearishOrderBlocks, +// lookupBullishFairValueGaps, +// lookupBearishFairValueGaps, +// lookupBullishRejectionBars, +// lookupBearishRejectionBars, +// lookupBullishMomentumBars, +// lookupBearishMomentumBars // +// ); + +// // +// if (m15.HasChild()) +// { +// m15.Fill(mOrderFlow[pivotIDX].state); +// } +// } + +// +// M5 ... +// XPOIState m5; +// if (_5MState.HasChild()) +// { +// // +// DetectPivotPOIs( +// mOrderFlow[pivotIDX], +// _5MState, +// m5, +// lookupSwingHighs, +// lookupSwingLows, +// lookupSupportZones, +// lookupResistanceZones, +// lookupSupplyZones, +// lookupDemandZones, +// lookupBullishOrderBlocks, +// lookupBearishOrderBlocks, +// lookupBullishFairValueGaps, +// lookupBearishFairValueGaps, +// lookupBullishRejectionBars, +// lookupBearishRejectionBars, +// lookupBullishMomentumBars, +// lookupBearishMomentumBars // +// ); + +// // +// if (m5.HasChild()) +// { +// m5.Fill(mOrderFlow[pivotIDX].state); +// } +// } + +// +// M1 ... +// XPOIState m1; +// if (_1MState.HasChild()) +// { +// // +// DetectPivotPOIs( +// mOrderFlow[pivotIDX], +// _1MState, +// m1, +// lookupSwingHighs, +// lookupSwingLows, +// lookupSupportZones, +// lookupResistanceZones, +// lookupSupplyZones, +// lookupDemandZones, +// lookupBullishOrderBlocks, +// lookupBearishOrderBlocks, +// lookupBullishFairValueGaps, +// lookupBearishFairValueGaps, +// lookupBullishRejectionBars, +// lookupBearishRejectionBars, +// lookupBullishMomentumBars, +// lookupBearishMomentumBars // +// ); + +// // +// if (m1.HasChild()) +// { +// m1.Fill(mOrderFlow[pivotIDX].state); +// } +// } + +////////////////////////////////// + +/** + * Detect SL Candidates based on Strategy and Conditions ... + * + * @param result: Double array reference ... + * @param entry: Double, Position Entry Price ... + * @param conditions: X121SMCStrategyConditions instance, Provides Configurations ... + * @param type: ENUM_X_POSITION_TYPES member, Specified Position Type ... + */ +void DetectSLCandidates( + double &result[], + double entry, + X121SMCStrategyConditions &conditions, + ENUM_X_POSITION_TYPES type // + ) override +{ + // + Clean(result); + + // + int cIndex = 1; + + // + if (entry <= 0 || + !conditions.IsValid() || + type == X_POSITION_TYPE_ALL || + type == X_POSITION_TYPE_NONE) + { + return; + } + + // + Add( + conditions.x3vwapConditions.fasts[cIndex], + result // + ); + + // + Add( + conditions.x3vwapConditions.mids[cIndex], + result // + ); + + // + Add( + conditions.x3vwapConditions.slows[cIndex], + result // + ); + + // + Add( + conditions.x3maConditions.fasts[cIndex], + result // + ); + + // + Add( + conditions.xpvConditions.vales[cIndex], + result // + ); + + // + Add( + conditions.xpvConditions.peaks[cIndex], + result // + ); + + // +} + +//////////////////////////////////////// + +bool canContinue = true; +while (canContinue) +{ + // + XOHCL iBar; + bool isBarInited = iBar.Init( + mBar.symbol, + mBar.period, + barIndex // + ); + if (!isBarInited) + { + break; + } + + // + if (bullOB == NULL) + { + // + XCOrderBlock *ob; + bool isBullOB = cycleHelper + .mPOIDetector + .DetectBullishOrderBlock( + mBar, + ob // + ); + if (isBullOB) + { + // + bool isPricePassed = bar.low > ob.Upper(); + if (isPricePassed) + { + // + if (mBullOB == NULL) + { + // + mBullOB = ob; + } + else + { + // + bool isRefined = mBullOB.Upper() < ob.Upper(); + if (isRefined) + { + mBullOB = ob; + } + } + } + } + } + + // + if (bearOB == NULL) + { + // + XCOrderBlock *ob; + bool isBearOB = cycleHelper + .mPOIDetector + .DetectBearishOrderBlock( + mBar, + ob // + ); + if (isBearOB) + { + // + bool isPricePassed = bar.high < ob.Lower(); + if (isPricePassed) + { + // + if (mBearOB == NULL) + { + // + mBearOB = ob; + } + else + { + // + bool isRefined = mBearOB.Lower() > ob.Lower(); + if (isRefined) + { + mBearOB = ob; + } + } + } + } + } + + // + canContinue = + (bullOB == NULL && mBullOB == NULL) || + (bearOB == NULL && mBearOB == NULL); + if (canContinue) + { + barIndex++; + } +} + +// +if (mBullOB != NULL) +{ + bullOB = mBullOB; +} + +// +if (mBearOB != NULL) +{ + bearOB = mBearOB; +} + +//////////////////////////////////////////////////////////// + +// +// Detect an Order Block in Vision ... +if (conditions.visionBullOB == NULL || + conditions.visionBearOB == NULL) +{ + // + result = DetectOrderBlocks( + NULL, + NULL, + conditions.visionBullOB, + conditions.visionBearOB, + cBar, + mVisionState // + ); + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + XCBullishOrderBlockObject *iBullOBObj; + conditions.visionBullOB.To(cTime); + result = mPOIDrawer.CreateBullishOrderBlock( + conditions.visionBullOB, + iBullOBObj // + ); + if (result) + { + AddObjectIfNotExists(iBullOBObj); + } + + // + XCBearishOrderBlockObject *iBearOBObj; + conditions.visionBearOB.To(cTime); + result = mPOIDrawer.CreateBearishOrderBlock( + conditions.visionBearOB, + iBearOBObj // + ); + if (result) + { + AddObjectIfNotExists(iBearOBObj); + } +} + +// +// Consolidation Order Blocks ... +if (conditions.consolidationBullOB == NULL || + conditions.consolidationBearOB == NULL) +{ + // + result = DetectOrderBlocks( + conditions.visionBullOB, + conditions.visionBearOB, + conditions.consolidationBullOB, + conditions.consolidationBearOB, + cBar, + mConsolidationState // + ); + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + XCBullishOrderBlockObject *iBullOBObj; + conditions.consolidationBullOB.To(cTime); + result = mPOIDrawer.CreateBullishOrderBlock( + conditions.consolidationBullOB, + iBullOBObj // + ); + if (result) + { + AddObjectIfNotExists(iBullOBObj); + } + + // + XCBearishOrderBlockObject *iBearOBObj; + conditions.consolidationBearOB.To(cTime); + result = mPOIDrawer.CreateBearishOrderBlock( + conditions.consolidationBearOB, + iBearOBObj // + ); + if (result) + { + AddObjectIfNotExists(iBearOBObj); + } +} + +// +msg = "OrderBlocks Detected ..."; +Alert(msg); + +// +// Detect Trigger Order Flow ... +if (!HasValidOrderFlow()) +{ + // + int samePivots = 40; + int requiredPivots = 10; + + // + bool useVisionState = false; + bool useConsolidationState = false; + bool useVerificationState = false; + bool useAnalyseState = false; + bool useDecisionState = true; + bool useTriggerState = false; + + // + DetectOrderFlow( + cIndex, + samePivots, + requiredPivots, + mTriggerCycleHelper, + mOrderFlow, + mOrderFlowDir, + // + // Filling Pivot State ... + useVisionState, // Use Vision State ... + useConsolidationState, // Use Consolidation State ... + useVerificationState, // Use Verification State ... + useAnalyseState, // Use Analyse State ... + useDecisionState, // Use Decision State ... + useTriggerState // Use Trigger State ... + ); + + // + result = HasValidOrderFlow(); + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + bool ignoreSwingHighs = true; + bool ignoreSwingLows = true; + bool ignoreSupportZones = true; + bool ignoreResistanceZones = true; + bool ignoreSupplyZones = true; + bool ignoreDemandZones = true; + bool ignoreBullishOrderBlocks = true; + bool ignoreBearishOrderBlocks = true; + bool ignoreBullishFairValueGaps = true; + bool ignoreBearishFairValueGaps = true; + bool ignoreBullishRejectionBars = true; + bool ignoreBearishRejectionBars = true; + bool ignoreBullishMomentumBars = true; + bool ignoreBearishMomentumBars = true; + + // + RedrawOrderFlow( + false, // Force Clean ... + false, // Same Period ... + true, // Order Flow ... + true, // Order Flow State ... + false, // Only Last Order Flow ... + true, // Only Last Order Flow State ... + // + mOrderFlowDir, // Direction Force ... + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); +} + +// +msg = "Found OrderFlow : " + (IsBullish(mOrderFlowDir) ? "Bullish" : "Berish"); +Alert(msg); + +// +// Check Market Conditions for +// Specified Structure ... +// ENUM_X_DIRECTION marketStructureDir = X_DIRECTION_NONE; +// result = conditions.HasDirection( +// marketStructureDir, +// cBar // +// ); +// if (!result) +// { +// // +// conditions.Clean(); +// return result; +// } +// msg = "Found Market Strucutre : " + (IsBullish(marketStructureDir) ? "Bullish" : "Berish"); +// Alert(msg); + +// +// conditions.marketStructureDir = marketStructureDir; + +// // +// XPVPivot lastPivot; +// result = GetLastItem( +// lastPivot, +// mOrderFlow // +// ); +// if (!result) +// { +// // +// conditions.Clean(); +// return result; +// } + +// +// Detect Last FVG ... +// XOHCL breakerBar; +// result = DetectLastBreakerBar( +// cBar, +// breakerBar, +// lastPivot, +// marketStructureDir // +// ); +// if (!result) +// { +// // +// conditions.Clean(); +// return result; +// } +// msg = "Found Breaker Bar: " + breakerBar.GetTag(); +// Alert(msg); + +// // +// // Detect Nearest Momentum or Rejection Bar ... +// XOHCL decisionBar; +// result = mDecisionCycleHelper.DetectNearestDecisionBar( +// decisionBar, +// marketStructureDir, +// cBar // +// ); +// if (!result) +// { +// return result; +// } +// msg = "Found Decision Bar: " + decisionBar.GetTag(); +// Alert(msg); + +// // +// // Detect Nearest Sar Change ... +// XOHCL sarChangeBar; +// result = mTriggerCycleHelper.DetectNearestCSARChange( +// sarChangeBar, +// cBar // +// ); +// if (!result) +// { +// // +// conditions.Clean(); +// return result; +// } +// msg = "Found Sar Change Bar: " + sarChangeBar.GetTag(); +// Alert(msg); + +// // +// // Now we Hvae to Check Other Conditions ... +// result = +// // breakerBar.time > sarChangeBar.time && +// // decisionBar.time > breakerBar.time; +// decisionBar.time > sarChangeBar.time; +// if (!result) +// { +// // +// conditions.Clean(); +// return result; +// } + +// // +// // Now we Have Check Direction Related Conditions ... +// if (IsBullish(marketStructureDir)) +// { +// // +// result = +// // bid > decisionBar.high && +// // bid > breakerBar.high && +// bid > sarChangeBar.high && +// bid > conditions.triggerConditions.xchsarConditions.cSars[0]; +// } +// else +// { +// // +// result = +// // bid < decisionBar.low && +// // bid < breakerBar.low && +// bid < sarChangeBar.high && +// bid < conditions.triggerConditions.xchsarConditions.cSars[0]; +// } +// if (!result) +// { +// // +// conditions.Clean(); +// return result; +// } + +// // +// conditions.provider = "X121SMC"; +// if (IsBullish(marketStructureDir)) +// { +// // +// // conditions.sl = decisionBar.low; +// // conditions.sl = breakerBar.low; +// conditions.sl = conditions.triggerConditions.xchsarConditions.cSars[0]; +// } +// else +// { +// // +// // conditions.sl = decisionBar.high; +// // conditions.sl = breakerBar.high; +// conditions.sl = conditions.triggerConditions.xchsarConditions.cSars[0]; +// } + +////////////////////////////////////////////////////////////////// + +// +bool isSamePeaks = + // + conditions.triggerConditions.x121Conditions.peaksBuffer[0] == conditions.decisionConditions.x121Conditions.peaksBuffer[0] && + conditions.decisionConditions.x121Conditions.peaksBuffer[0] == conditions.analyseConditions.x121Conditions.peaksBuffer[0] + // && + // conditions.analyseConditions.x121Conditions.peaksBuffer[0] == conditions.verificationConditions.x121Conditions.peaksBuffer[0] && + // conditions.verificationConditions.x121Conditions.peaksBuffer[0] == conditions.consolidationConditions.x121Conditions.peaksBuffer[0] && + // conditions.consolidationConditions.x121Conditions.peaksBuffer[0] == conditions.visionConditions.x121Conditions.peaksBuffer[0] + // + ; +if (isSamePeaks) +{ + Print("isSamePeaks"); +} + +// +bool isSameVales = + // + conditions.triggerConditions.x121Conditions.valesBuffer[0] == conditions.decisionConditions.x121Conditions.valesBuffer[0] && + conditions.decisionConditions.x121Conditions.valesBuffer[0] == conditions.analyseConditions.x121Conditions.valesBuffer[0] + // && + // conditions.analyseConditions.x121Conditions.valesBuffer[0] == conditions.verificationConditions.x121Conditions.valesBuffer[0] && + // conditions.verificationConditions.x121Conditions.valesBuffer[0] == conditions.consolidationConditions.x121Conditions.valesBuffer[0] && + // conditions.consolidationConditions.x121Conditions.valesBuffer[0] == conditions.visionConditions.x121Conditions.valesBuffer[0] + // + ; +if (isSameVales) +{ + Print("isSameVales"); +} + +////////////////////////////////////////////////////////////////////// + +// +// Detect Valid Supply and Demand Zones ... +XCSupplyZone *supplyZone; +XCDemandZone *demandZone; +result = mTriggerCycleHelper + .DetectValisSupplyZone( + cBar, + supplyZone, + demandZone // + ); +if (!result) +{ + // + conditions.Clean(); + return result; +} + +// +supplyZone.To(cTime); +XCSupplyZoneObject *iSupplyZoneObj; +result = mPOIDrawer.CreateSupplyZone( + supplyZone, + iSupplyZoneObj // +); +if (!result) +{ + // + conditions.Clean(); + return result; +} + +// +demandZone.To(cTime); +XCDemandZoneObject *iDemandZoneObj; +result = mPOIDrawer.CreateDemandZone( + demandZone, + iDemandZoneObj // +); +if (!result) +{ + // + conditions.Clean(); + return result; +} + +// +Print("Supply and Demand Zone Created ..."); + +////////////////////////////////////////////////////////////////////// + +// +int consolidationsCount = mTriggerCycleHelper.CountConsolidationZones(); +result = IsValidSize(consolidationsCount); +if (!result) +{ + // + conditions.Clean(); + return result; +} +XConsolidationZone consolidations[]; +mTriggerCycleHelper.FillConsolidationZones(consolidations); + +// +// Detect Bid inside Of Zones ... +bool hasSupply = false; +bool hasDemand = false; +XCSupplyZone *supplyZone; +XCDemandZone *demandZone; +bool isBidInsideZone = false; +XConsolidationZone bidContainsConsolidationZone; +for (int i = consolidationsCount - 1; i >= 0; i--) +{ + // + XConsolidationZone iZone = consolidations[i]; + + // + // Check Supply or Demand Zone ... + hasSupply = iZone.HasSupplyZone(supplyZone); + hasDemand = iZone.HasDemandZone(demandZone); + + // + result = hasSupply || + hasDemand; + if (!result) + { + continue; + } + + // + // Check Bid inside Zone ... + if (hasSupply) + { + // + result = bid < supplyZone.Upper() && + bid > supplyZone.Lower(); + } + else + { + // + result = bid < demandZone.Upper() && + bid > demandZone.Lower(); + } + + // + if (result) + { + break; + } +} +if (!result) +{ + // + conditions.Clean(); + return result; +} + +// +if (hasSupply) +{ + // + supplyZone.To(cTime); + XCSupplyZoneObject *iSupplyZoneObj; + result = mPOIDrawer.CreateSupplyZone( + supplyZone, + iSupplyZoneObj // + ); + if (!result) + { + // + conditions.Clean(); + return result; + } +} + +// +if (hasDemand) +{ + // + demandZone.To(cTime); + XCDemandZoneObject *iDemandZoneObj; + result = mPOIDrawer.CreateDemandZone( + demandZone, + iDemandZoneObj // + ); + if (!result) + { + // + conditions.Clean(); + return result; + } +} + +// +Print("BID Inside Zone ..."); + +////////////////////////////////////////////////////////////////////////// + +bool DetectCandlestic( + ENUM_X_DIRECTION &dir, + X121SMCStrategyConditions &conditions // +) +{ + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + int cIndex = 1; + int pIndex = cIndex + 1; + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = pBar.Init( + symbol, + period, + pIndex // + ); + if (!result) + { + return result; + } + + // + // Momentum Bars ... + XCMomentumBar *cBullishMomentum = NULL; + XCMomentumBar *cBearishMomentum = NULL; + XCMomentumBar *pBullishMomentum = NULL; + XCMomentumBar *pBearishMomentum = NULL; + int bullishMomentumBarsCount = conditions.triggerConditions.state + .CountBullishMomentumBars(); + int bearishMomentumBarsCount = conditions.triggerConditions.state + .CountBearishMomentumBars(); + if (IsValidSize(bullishMomentumBarsCount)) + { + // + cBullishMomentum = conditions.triggerConditions.state.bullishMomentumBars[bullishMomentumBarsCount - 1]; + pBullishMomentum = conditions.triggerConditions.state.bullishMomentumBars[bullishMomentumBarsCount - 2]; + } + if (IsValidSize(bearishMomentumBarsCount)) + { + // + cBearishMomentum = conditions.triggerConditions.state.bearishMomentumBars[bearishMomentumBarsCount - 1]; + pBearishMomentum = conditions.triggerConditions.state.bearishMomentumBars[bearishMomentumBarsCount - 2]; + } + + // + // Rejection Bars ... + XCRejectionBar *cBullishRejection = NULL; + XCRejectionBar *cBearishRejection = NULL; + XCRejectionBar *pBullishRejection = NULL; + XCRejectionBar *pBearishRejection = NULL; + int bullishRejectionBarsCount = conditions.triggerConditions.state + .CountBullishRejectionBars(); + int bearishRejectionBarsCount = conditions.triggerConditions.state + .CountBearishRejectionBars(); + if (IsValidSize(bullishRejectionBarsCount)) + { + // + cBullishRejection = conditions.triggerConditions.state.bullishRejectionBars[bullishRejectionBarsCount - 1]; + pBullishRejection = conditions.triggerConditions.state.bullishRejectionBars[bullishRejectionBarsCount - 2]; + } + if (IsValidSize(bearishRejectionBarsCount)) + { + // + cBearishRejection = conditions.triggerConditions.state.bearishRejectionBars[bearishRejectionBarsCount - 1]; + pBearishRejection = conditions.triggerConditions.state.bearishRejectionBars[bearishRejectionBarsCount - 2]; + } + + // + bool isBullish = + // + // pBar is Rejection and cBar is Momentum ... + // pBar is Momentum and cBar is Rejection ... + // cBar is Momentum and Rejection ... + // + pBullishMomentum != NULL && + pBullishMomentum.IsValid() && + // + cBullishMomentum != NULL && + cBullishMomentum.IsValid() && + // + // + pBullishRejection != NULL && + pBullishRejection.IsValid() && + // + cBullishRejection != NULL && + cBullishRejection.IsValid() && + // + ( + // + (pBar.time == pBullishRejection.BarTime() && + cBar.time == cBullishMomentum.BarTime()) + // + || + // + (pBar.time == pBullishMomentum.BarTime() && + cBar.time == cBullishRejection.BarTime()) + // + || + // + (cBar.time == cBullishMomentum.BarTime() && + cBar.time == cBullishRejection.BarTime()) + // + ) + // + ; + + // + bool isBearish = + // + // pBar is Rejection and cBar is Momentum ... + // pBar is Momentum and cBar is Rejection ... + // cBar is Momentum and Rejection ... + // + pBearishMomentum != NULL && + pBearishMomentum.IsValid() && + // + cBearishMomentum != NULL && + cBearishMomentum.IsValid() && + // + // + pBearishRejection != NULL && + pBearishRejection.IsValid() && + // + cBearishRejection != NULL && + cBearishRejection.IsValid() && + // + ( + // + (pBar.time == pBearishRejection.BarTime() && + cBar.time == cBearishMomentum.BarTime()) + // + || + // + (pBar.time == pBearishMomentum.BarTime() && + cBar.time == cBearishRejection.BarTime()) + // + || + // + (cBar.time == cBearishMomentum.BarTime() && + cBar.time == cBearishRejection.BarTime()) + // + ) + // + ; + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; +} + +///////////////////////////////////////////////////////////////////////////////////// + +/** + * Detect Nearest Supply/Demand Zones ... + * + * @param bar: XOHCL instance, Start Bar ... + * + * @return ( bool ) + */ +bool DetectValisSupplyZone( + XOHCL &bar, + XCSupplyZone *&supplyZone, + XCDemandZone *&demandZone // +) +{ + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int index = bar.Index(); + + // + double bid = GetBid(bar.symbol); + double ask = GetAsk(bar.symbol); + + // + // Retrieve X121 Cnditions ... + int conditionsLoopback = 10; + X121Conditions x121Conditions; + result = mX121Helper.GetConditions( + x121Conditions, + index, + conditionsLoopback // + ); + if (!result) + { + return result; + } + int validPeaksCount = ArraySize(x121Conditions.validPeaksBuffer); + int validValesCount = ArraySize(x121Conditions.validValesBuffer); + + // + XPOIState state; + ENUM_XPOI_EVENTS events[]; + mPOIDetector.Update(events); + mPOIDetector.GetState(state); + result = state.IsValid() && + state.HasChild(); + if (!result) + { + return result; + } + + // + // Supply Zones ... + XCSupplyZone *supplies[]; + int suppliesCount = state.CountSupplyZones(); + + // + // Select Bar Validated Supply Zones ... + if (IsValidSize(suppliesCount)) + { + // + for (int i = 0; i < suppliesCount; i++) + { + // + XCSupplyZone *iZone = state.supplyZones[i]; + + // + // Check Zone is Valid For Bar ... + bool isValid = bar.high < iZone.Lower() && + ask < iZone.Lower() && + bid < iZone.Lower(); + if (isValid) + { + // + Add( + iZone, + supplies // + ); + } + } + } + suppliesCount = ArraySize(supplies); + + // + // Select Valid Peaks Filtered Supplies ... + if (IsValidSize(suppliesCount)) + { + // + // Check Valid Peaks ... + XCSupplyZone *tmp[]; + if (IsValidSize(validPeaksCount)) + { + // + for (int i = 0; i < suppliesCount; i++) + { + // + XCSupplyZone *iZone = supplies[i]; + + // + for (int j = 0; j < validPeaksCount; j++) + { + // + double value = x121Conditions.validPeaksBuffer[j]; + + // + // Check Valid Peaks in Zone ... + bool isZoneContainsValidValue = + value >= iZone.Lower() && + value <= iZone.Upper(); + if (isZoneContainsValidValue) + { + // + Add( + iZone, + tmp // + ); + } + } + } + } + + // + Clean(supplies); + Copy( + tmp, + supplies // + ); + } + suppliesCount = ArraySize(supplies); + + // + // Select Nearest Supply Zone ... + if (IsValidSize(suppliesCount)) + { + // + // Check Nearest Supplies ... + for (int i = 0; i < suppliesCount; i++) + { + // + XCSupplyZone *iZone = supplies[i]; + if (supplyZone == NULL) + { + supplyZone = iZone; + } + else + { + // + bool canChange = + iZone.Lower() < supplyZone.Lower(); + if (canChange) + { + supplyZone = iZone; + } + } + } + } + + // + // Demand Zones ... + XCDemandZone *demands[]; + int demandsCount = state.CountDemandZones(); + + // + // Select Bar Validated Demand Zones ... + if (IsValidSize(demandsCount)) + { + // + for (int i = 0; i < demandsCount; i++) + { + // + XCDemandZone *iZone = state.demandZones[i]; + + // + // Check Zone is Valid For Bar ... + bool isValid = bar.low > iZone.Upper() && + ask > iZone.Upper() && + bid > iZone.Upper(); + if (isValid) + { + // + Add( + iZone, + demands // + ); + } + } + } + demandsCount = ArraySize(demands); + + // + // Select Valid Vales Filtered Demands ... + if (IsValidSize(demandsCount)) + { + // + // Check Valid Vales ... + XCDemandZone *tmp[]; + if (IsValidSize(validValesCount)) + { + // + for (int i = 0; i < demandsCount; i++) + { + // + XCDemandZone *iZone = demands[i]; + + // + for (int j = 0; j < validValesCount; j++) + { + // + double value = x121Conditions.validValesBuffer[j]; + + // + // Check Valid Peaks in Zone ... + bool isZoneContainsValidValue = + value >= iZone.Lower() && + value <= iZone.Upper(); + if (isZoneContainsValidValue) + { + // + Add( + iZone, + tmp // + ); + } + } + } + } + + // + Clean(demands); + Copy( + tmp, + demands // + ); + } + demandsCount = ArraySize(demands); + + // + // Select Nearest Demand Zone ... + if (IsValidSize(demandsCount)) + { + // + // Check Nearest Demands ... + for (int i = 0; i < demandsCount; i++) + { + // + XCDemandZone *iZone = demands[i]; + if (demandZone == NULL) + { + demandZone = iZone; + } + else + { + // + bool canChange = + iZone.Upper() > demandZone.Upper(); + if (canChange) + { + demandZone = iZone; + } + } + } + } + + // + // Validate Founded Zones ... + result = (supplyZone != NULL && + supplyZone.IsValid()) && + (demandZone != NULL && + demandZone.IsValid()); + + // + return result; +} + +//////////////////////////////////////////////////////////////////// + + // + CustomStateDrawing( + conditions.consolidationConditions.state, + false, // + X_DIRECTION_NONE, + false, // ignoreSwingHighs + false, // ignoreSwingLows + false, // ignoreSupportZones + false, // ignoreResistanceZones + false, // ignoreSupplyZones + false, // ignoreDemandZones + true, // ignoreBullishOrderBlocks + true, // ignoreBearishOrderBlocks + true, // ignoreBullishFairValueGaps + true, // ignoreBearishFairValueGaps + true, // ignoreBullishRejectionBars + true, // ignoreBearishRejectionBars + true, // ignoreBullishMomentumBars + true // ignoreBearishMomentumBars + ); + + // + // TODO: Remove ... + // Draw ... + if (hasVisionSupplyZone && visionSupplyZone != NULL) + { + // + visionSupplyZone.To(TimeCurrent()); + XCSupplyZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateSupplyZone( + visionSupplyZone, + iObj // + ); + if (isCreated) + { + // + iObj.ZoneWidth(4); + iObj.ZoneColor(clrMagenta); + AddObjectIfNotExists(iObj); + } + } + + // + // TODO: Remove ... + // Draw ... + if (hasVisionDemandZone && visionDemandZone != NULL) + { + // + visionDemandZone.To(TimeCurrent()); + XCDemandZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateDemandZone( + visionDemandZone, + iObj // + ); + if (isCreated) + { + // + iObj.ZoneWidth(4); + iObj.ZoneColor(clrAqua); + AddObjectIfNotExists(iObj); + } + } + + // + if (result) + { + ClearDraws(); + } + + + // + // TODO: Remove this ... + // Draw ... + if (hasConsolidationSupportZone && + consolidationSupportZone != NULL) + { + // + consolidationSupportZone.To(TimeCurrent()); + XCSupportZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateSupportZone( + consolidationSupportZone, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + + // + // TODO: Remove this ... + // Draw ... + if (hasConsolidationResistanceZone && + consolidationResistanceZone != NULL) + { + // + consolidationResistanceZone.To(TimeCurrent()); + XCResistanceZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateResistanceZone( + consolidationResistanceZone, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + +//////////////////////////////////////////////////////////////////////////////////// + + // + XCSwing *swingLow = NULL; + XCSwing *swingHigh = NULL; + bool isSwingLowRejected = false; + bool isSwingHighRejected = false; + int swingLowsCount = decisionConditions.state.CountSwingLows(); + int swingHighsCount = decisionConditions.state.CountSwingHighs(); + if (IsValidSize(swingLowsCount)) + { + swingLow = decisionConditions.state.swingLows[swingLowsCount - 1]; + } + if (IsValidSize(swingHighsCount)) + { + swingHigh = decisionConditions.state.swingHighs[swingHighsCount - 1]; + } + + // + isSwingLowRejected = swingLow != NULL && + swingLow.IsValid() && + decisionCBar.low > swingLow.GetValue(); + + // + isSwingHighRejected = swingHigh != NULL && + swingHigh.IsValid() && + decisionCBar.high < swingHigh.GetValue(); + + +/////////////////////////////////////////////////////////////////////////////////////////// + + + // + // TODO: Remove this ... + XTestProiderConditions mTestConditions; + bool DetectTestSignal( + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + ENUM_X_121_SMC_PROVIDERS provider = X_121_SMC_PROVIDER_SMPV; + string providerStr = ToString(provider); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + + // + double selectedSL = 0; + + // + // Retrieve Peak and Vale ... + double peak = conditions.triggerConditions.x121Conditions.peaksBuffer[0]; + double vale = conditions.triggerConditions.x121Conditions.valesBuffer[0]; + + // + X121SMCCycleConditions triggerConditions = conditions.triggerConditions; + X121SMCCycleConditions decisionConditions = conditions.decisionConditions; + X121SMCCycleConditions analyseConditions = conditions.analyseConditions; + X121SMCCycleConditions verificationConditions = conditions.verificationConditions; + X121SMCCycleConditions consolidationConditions = conditions.consolidationConditions; + X121SMCCycleConditions visionConditions = conditions.visionConditions; + + // + XPOIState triggerState = triggerConditions.state; + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState verificationState = verificationConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + int zoneValidationDivider = 10; + + // + // Try to Detect Setup Conditions ... + ENUM_X_DIRECTION setupDir; + result = mTestConditions.IsSetuped(setupDir); + if (!result) + { + // + // First we must check a new Peak or Vale Happens ... + bool isNewPeak = conditions.triggerConditions.x121Conditions.isNewPeak; + bool isNewVale = conditions.triggerConditions.x121Conditions.isNewVale; + + // + result = isNewPeak || + isNewVale; + if (!result) + { + return result; + } + + // + mTestConditions.isNewPeak = isNewPeak; + mTestConditions.isNewVale = isNewVale; + + // + // We have to Check the Peaks and Vales Happens inside a Demand or Supply Zone ... + // in Vision State ... + + // + bool hasVisionSupplyZone = false; + XCSupplyZone *visionSupplyZone = NULL; + int visionSupplyZonesCount = visionState.CountSupplyZones(); + if (isNewPeak && + IsValidSize(visionSupplyZonesCount)) + { + // + // Try to Find Inside Zone ... + for (int i = 0; i < visionSupplyZonesCount; i++) + { + // + XCSupplyZone *iZone = visionState.supplyZones[i]; + double zoneValidRange = (iZone.Upper() - iZone.Lower()) / zoneValidationDivider; + + // + hasVisionSupplyZone = + // + peak >= iZone.Lower() && + peak <= iZone.Upper() && + peak > iZone.Upper() - zoneValidRange + // + ; + if (hasVisionSupplyZone) + { + // + visionSupplyZone = iZone; + break; + } + } + } + + // + bool hasVisionDemandZone = false; + XCDemandZone *visionDemandZone = NULL; + int visionDemandZonesCount = visionState.CountDemandZones(); + if (isNewVale && + IsValidSize(visionDemandZonesCount)) + { + // + // Try to Find Inside Zone ... + for (int i = 0; i < visionDemandZonesCount; i++) + { + // + XCDemandZone *iZone = visionState.demandZones[i]; + double zoneValidRange = (iZone.Upper() - iZone.Lower()) / zoneValidationDivider; + + // + hasVisionDemandZone = + // + vale >= iZone.Lower() && + vale <= iZone.Upper() && + vale < iZone.Lower() + zoneValidRange + // + ; + if (hasVisionDemandZone) + { + // + visionDemandZone = iZone; + break; + } + } + } + + // + result = hasVisionSupplyZone || + hasVisionDemandZone; + if (!result) + { + return result; + } + + // + mTestConditions.visionSupplyZone = visionSupplyZone; + mTestConditions.visionDemandZone = visionDemandZone; + + // + mTestConditions.hasVisionSupplyZone = hasVisionSupplyZone; + mTestConditions.hasVisionDemandZone = hasVisionDemandZone; + + // + double triggerPeak = conditions.triggerConditions.x121Conditions.peaksBuffer[0]; + double decisionPeak = conditions.decisionConditions.x121Conditions.peaksBuffer[0]; + double analysePeak = conditions.analyseConditions.x121Conditions.peaksBuffer[0]; + double verificationPeak = conditions.verificationConditions.x121Conditions.peaksBuffer[0]; + double consolidationPeak = conditions.consolidationConditions.x121Conditions.peaksBuffer[0]; + double visionPeak = conditions.visionConditions.x121Conditions.peaksBuffer[0]; + + // + bool isPeaksSame = + // + triggerPeak && + decisionPeak && + analysePeak && + verificationPeak && + consolidationPeak && + visionPeak + // + ; + + // + double triggerVale = conditions.triggerConditions.x121Conditions.valesBuffer[0]; + double decisionVale = conditions.decisionConditions.x121Conditions.valesBuffer[0]; + double analyseVale = conditions.analyseConditions.x121Conditions.valesBuffer[0]; + double verificationVale = conditions.verificationConditions.x121Conditions.valesBuffer[0]; + double consolidationVale = conditions.consolidationConditions.x121Conditions.valesBuffer[0]; + double visionVale = conditions.visionConditions.x121Conditions.valesBuffer[0]; + + // + bool isValesSame = + // + triggerVale && + decisionVale && + analyseVale && + verificationVale && + consolidationVale && + visionVale + // + ; + + // + mTestConditions.hasSamePeaks = isPeaksSame; + mTestConditions.hasSameVales = isValesSame; + + // + isBullish = + // + isNewVale && + isPeaksSame && + isValesSame && + hasVisionDemandZone + // + ; + + // + isBearish = + // + isNewPeak && + isPeaksSame && + isValesSame && + hasVisionSupplyZone + // + ; + + // + result = + isBullish || + isBearish; + if (!result) + { + return result; + } + + // + mTestConditions.setupTime = TimeCurrent(); + + // + result = mTestConditions.IsSetuped(setupDir); + if (!result) + { + return result; + } + + // + // Alert ... + string message = providerStr + " Conditions Set Upped: " + ToString(setupDir); + Alert(message); + } + else + { + // + // Try to Detect Trigger Conditions ... + mTestConditions.symbol = symbol; + mTestConditions.period = period; + + // + // Try to Find Support Zone which Vales Inside it ... + bool hasConsolidationSupportZone = false; + XCSupportZone *consolidationSupportZone = NULL; + int consolidationSupportZonesCount = consolidationState.CountSupportZones(); + if (IsValidSize(consolidationSupportZonesCount)) + { + // + for (int i = 0; i < consolidationSupportZonesCount; i++) + { + // + XCSupportZone *iZone = consolidationState.supportZones[i]; + // double zoneValidRange = (iZone.Upper() - iZone.Lower()) / zoneValidationDivider; + + // + hasConsolidationSupportZone = + // + peak >= iZone.Lower() && + peak <= iZone.Upper() + // && + // vale < iZone.Upper() - zoneValidRange + // + ; + if (hasConsolidationSupportZone) + { + // + consolidationSupportZone = iZone; + break; + } + } + } + + // + // Try to Find Resistance Zone which Peaks Inside it ... + bool hasConsolidationResistanceZone = false; + XCResistanceZone *consolidationResistanceZone = NULL; + int consolidationResistanceZonesCount = consolidationState.CountResistanceZones(); + if (IsValidSize(consolidationResistanceZonesCount)) + { + // + for (int i = 0; i < consolidationResistanceZonesCount; i++) + { + // + XCResistanceZone *iZone = consolidationState.resistanceZones[i]; + // double zoneValidRange = (iZone.Upper() - iZone.Lower()) / zoneValidationDivider; + + // + hasConsolidationResistanceZone = + // + vale >= iZone.Lower() && + vale <= iZone.Upper() + // && + // peak > iZone.Lower() + zoneValidRange + // + ; + if (hasConsolidationResistanceZone) + { + // + consolidationResistanceZone = iZone; + break; + } + } + } + + // + result = hasConsolidationSupportZone || + hasConsolidationResistanceZone; + if (!result) + { + return result; + } + + // + result = + // + (IsBullish(setupDir) && + hasConsolidationResistanceZone) + // + || + // + (IsBearish(setupDir) && + hasConsolidationSupportZone) + // + ; + if (!result) + { + return result; + } + + // + // Detect State Conditions ... + + // + // Vision ... + + // + bool isVisionBullishPassed = + // + // Sar ... + visionConditions.x121Conditions.isSarBullish + // + && + // + // VWap ... + visionConditions.x121Conditions.isVWapFastBullish + // + ; + + // + bool isVisionBearishPassed = + // + // Sar ... + visionConditions.x121Conditions.isSarBearish + // + && + // + // VWap ... + visionConditions.x121Conditions.isVWapFastBearish + // + ; + + // + bool isVisionPassed = isVisionBullishPassed || + isVisionBearishPassed; + result = isVisionPassed; + if (!result) + { + return result; + } + + // + // Consolidation ... + + // + bool isConsolidationBullishPassed = + // + // Sar ... + consolidationConditions.x121Conditions.isSarBullish + // + && + // + // VWap State ... + consolidationConditions.x121Conditions.isVWapBullishState + // + && + // + // VWap Order ... + consolidationConditions.x121Conditions.isVWapBullishOrdered + // + ; + + // + bool isConsolidationBearishPassed = + // + // + // Sar ... + consolidationConditions.x121Conditions.isSarBearish + // + && + // + // VWap State ... + consolidationConditions.x121Conditions.isVWapBearishState + // + && + // + // VWap Order ... + consolidationConditions.x121Conditions.isVWapBearishOrdered + // + ; + + // + bool isConsolidationPassed = isConsolidationBullishPassed || + isConsolidationBearishPassed; + result = isConsolidationPassed; + if (!result) + { + return result; + } + + // + // Verification ... + + // + bool isVerificationBullishPassed = + // + // Sar ... + verificationConditions.x121Conditions.isSarBullish + // + && + // + // VWap State ... + verificationConditions.x121Conditions.isVWapBullishState + // + && + // + // VWap Order ... + verificationConditions.x121Conditions.isVWapBullishOrdered + // + ; + + // + bool isVerificationBearishPassed = + // + // Sar ... + verificationConditions.x121Conditions.isSarBearish + // + && + // + // VWap State ... + verificationConditions.x121Conditions.isVWapBearishState + // + && + // + // VWap Order ... + verificationConditions.x121Conditions.isVWapBearishOrdered + // + ; + + // + bool isVerificationPassed = isVerificationBullishPassed || + isVerificationBearishPassed; + result = isVerificationPassed; + if (!result) + { + return result; + } + + // + // Analyse ... + + // + bool isAnalyseBullishPassed = + // + // Sar ... + analyseConditions.x121Conditions.isSarBullish + // + && + // + // VWap Order ... + analyseConditions.x121Conditions.isVWapBullishOrdered + // + && + // + // VWap State ... + (analyseConditions.x121Conditions.isVWapBullishState || + (analyseConditions.x121Conditions.isVWapMidBullish && + analyseConditions.x121Conditions.isVWapSlowBullish)) + // + ; + + // + bool isAnalyseBearishPassed = + // + // Sar ... + analyseConditions.x121Conditions.isSarBearish + // + && + // + // VWap Order ... + analyseConditions.x121Conditions.isVWapBearishOrdered + // + && + // + // VWap State ... + (analyseConditions.x121Conditions.isVWapBearishState || + (analyseConditions.x121Conditions.isVWapMidBearish && + analyseConditions.x121Conditions.isVWapSlowBearish)) + // + ; + + // + bool isAnalysePassed = isAnalyseBullishPassed || + isAnalyseBearishPassed; + result = isAnalysePassed; + if (!result) + { + return result; + } + + // + // Decision ... + + // + double decisionPeak = decisionConditions.x121Conditions.peaksBuffer[1]; + double decisionVale = decisionConditions.x121Conditions.valesBuffer[1]; + + // + XOHCL decisionCBar; + result = mDecisionCycleHelper.GetBar( + decisionCBar, + cIndex // + ); + + // + // Check Fibo Pressure ... + ENUM_X_DIRECTION pressureDir; + bool hasPressurePin = mBarAnalyser.HasFiboPressure( + decisionCBar, + pressureDir // + ); + + // + bool isBarBullish = + // + (hasPressurePin && + IsBullish(pressureDir)) + // + && + // + decisionCBar.low == decisionVale + // + ; + + // + bool isBarBearish = + // + (hasPressurePin && + IsBearish(pressureDir)) + // + && + // + decisionCBar.high == decisionPeak + // + ; + + // + bool isBarPassed = isBarBullish || + isBarBearish; + result = isBarPassed; + if (!result) + { + return result; + } + + // + bool isDecisionBullishPassed = + // + // Bar ... + isBarBullish + // + && + // + // VWap Order ... + decisionConditions.x121Conditions.isVWapBullishOrdered + // + ; + + // + bool isDecisionBearishPassed = + // + // Bar ... + isBarBearish + // + && + // + // VWap Order ... + decisionConditions.x121Conditions.isVWapBearishOrdered + // + ; + + // + bool isDecisionPassed = isDecisionBullishPassed || + isDecisionBearishPassed; + result = isDecisionPassed; + if (!result) + { + return result; + } + + // + // Trigger ... + + // + double donOpenUpper = triggerConditions.x121Conditions.donOpenUpperBuffer[1]; + double donOpenLower = triggerConditions.x121Conditions.donOpenLowerBuffer[1]; + + // + double donCloseUpper = triggerConditions.x121Conditions.donCloseUpperBuffer[1]; + double donCloseLower = triggerConditions.x121Conditions.donCloseLowerBuffer[1]; + + // + bool isDonBullish = + // + donCloseLower > donOpenUpper + // + && + // + cBar.low > donCloseLower && + cBar.high > donCloseLower + // + ; + + // + bool isDonBearish = + // + donOpenUpper > donCloseUpper + // + && + // + cBar.low < donCloseUpper && + cBar.high < donCloseUpper + // + ; + + // + bool isTriggerBullishPassed = + // + // Don ... + isDonBullish + // + && + // + // Sar ... + triggerConditions.x121Conditions.isSarBullish + // + ; + + // + bool isTriggerBearishPassed = + // + // Don ... + isDonBearish + // + && + // + // Sar ... + triggerConditions.x121Conditions.isSarBearish + // + ; + + // + bool isTriggerPassed = isTriggerBullishPassed || + isTriggerBearishPassed; + result = isTriggerPassed; + if (!result) + { + return result; + } + + // + // + // + + // + bool isBullishTriggerConditionsPassed = + // + isConsolidationBullishPassed && + isVerificationBullishPassed && + isAnalyseBullishPassed && + isDecisionBullishPassed && + isTriggerBullishPassed + // + ; + + // + bool isBearishTriggerConditionsPassed = + // + isConsolidationBearishPassed && + isVerificationBearishPassed && + isAnalyseBearishPassed && + isDecisionBearishPassed && + isTriggerBearishPassed + // + ; + + // + // + // + + // + bool isBullish = + // + IsBullish(setupDir) && + hasConsolidationSupportZone && + isBullishTriggerConditionsPassed + // + ; + + // + bool isBearish = + // + IsBearish(setupDir) && + hasConsolidationResistanceZone && + isBearishTriggerConditionsPassed + // + ; + + // + result = + isBullish || + isBearish; + if (!result) + { + return result; + } + + // + double entry = GetEntry( + symbol, + setupDir // + ); + double spread = GetSpread( + symbol // + ); + + // + zoneValidationDivider = 8; + double selectedSL = isBullish + ? consolidationResistanceZone.Upper() - spread - + ((consolidationResistanceZone.Upper() - consolidationResistanceZone.Lower()) / + zoneValidationDivider) + : consolidationSupportZone.Lower() + spread + + ((consolidationSupportZone.Upper() - consolidationSupportZone.Lower()) / + zoneValidationDivider); + + // + mTestConditions.sl = selectedSL; + mTestConditions.type = + isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + mTestConditions.triggerTime = TimeCurrent(); + } + + // + // Check Conditions is Prepared for Trigger ... + result = mTestConditions.CanTrigger(); + if (!result) + { + return result; + } + + // + conditions.signalDir = setupDir; + conditions.provider = providerStr; + conditions.sl = mTestConditions.sl; + + // + mTestConditions.Clean(); + + // + return result; + } + + +/////////////////////////////////////////////////////////////////////////////////////////////// + + // + // Detect Supply and Demand Zones inside Order Block ... + XCOrderBlock *orderBlock = NULL; + if (isNewPeakInsideBearihOrderBlock) + { + orderBlock = mTestConditions.bearishOrderBlock; + } + else + { + orderBlock = mTestConditions.bullishOrderBlock; + } + + // + // Supply Zone ... + XPOIState selectedState = visionState; + bool hasSupplyZone = mTestConditions.HasSupplyZone(); + int supplyZonesCount = selectedState.CountSupplyZones(); + if (!hasSupplyZone) + { + // + if (IsValidSize(supplyZonesCount)) + { + // + XCSupplyZone *supplyZones[]; + for (int i = 0; i < supplyZonesCount; i++) + { + // + XCSupplyZone *iZone = selectedState.supplyZones[i]; + + // + bool isValid = iZone.Upper() <= orderBlock.Upper() && + iZone.Lower() >= orderBlock.Lower(); + if (isValid) + { + // + Add( + iZone, + supplyZones // + ); + } + } + + // + XCSupplyZone *supply = NULL; + supplyZonesCount = ArraySize(supplyZones); + for (int i = 0; i < supplyZonesCount; i++) + { + // + XCSupplyZone *iZone = supplyZones[i]; + + // + bool isValid = supply == NULL + ? true + : supply.Upper() < iZone.Upper(); + if (isValid) + { + supply = iZone; + } + } + if (supply != NULL && supply.IsValid()) + { + mTestConditions.supplyZone = supply; + } + + // + hasSupplyZone = mTestConditions.HasSupplyZone(); + } + } + // + // TODO: Remove ... + else + { + // + mTestConditions.supplyZone.To(TimeCurrent()); + XCSupplyZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateSupplyZone( + mTestConditions.supplyZone, + iObj // + ); + if (isCreated) + { + // + iObj.ZoneWidth(3); + + // + AddObjectIfNotExists(iObj); + } + } + + // + // Demand Zone ... + bool hasDemandZone = mTestConditions.HasDemandZone(); + int demandZonesCount = selectedState.CountDemandZones(); + if (!hasDemandZone) + { + // + if (IsValidSize(demandZonesCount)) + { + // + XCDemandZone *demandZones[]; + for (int i = 0; i < demandZonesCount; i++) + { + // + XCDemandZone *iZone = selectedState.demandZones[i]; + + // + bool isValid = iZone.Upper() <= orderBlock.Upper() && + iZone.Lower() >= orderBlock.Lower(); + if (isValid) + { + // + Add( + iZone, + demandZones // + ); + } + } + + // + XCDemandZone *demand = NULL; + demandZonesCount = ArraySize(demandZones); + for (int i = 0; i < demandZonesCount; i++) + { + // + XCDemandZone *iZone = demandZones[i]; + + // + bool isValid = demand == NULL + ? true + : demand.Upper() < iZone.Upper(); + if (isValid) + { + demand = iZone; + } + } + if (demand != NULL && demand.IsValid()) + { + mTestConditions.demandZone = demand; + } + + // + hasDemandZone = mTestConditions.HasDemandZone(); + } + } + // + // TODO: Remove ... + else + { + // + mTestConditions.demandZone.To(TimeCurrent()); + XCDemandZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateDemandZone( + mTestConditions.demandZone, + iObj // + ); + if (isCreated) + { + // + iObj.ZoneWidth(3); + + // + AddObjectIfNotExists(iObj); + } + } + + + + // + // Supply and Demand Zone ... + XCSupplyZone *supplyZone; + XCDemandZone *demandZone; + + // + supplyZone = NULL; + demandZone = NULL; + + // + // Supply and Demand ... + + bool HasSupplyZone() + { + // + bool result = false; + + // + result = + // + supplyZone != NULL && + supplyZone.IsValid() + // + ; + + // + return result; + } + + bool HasDemandZone() + { + // + bool result = false; + + // + result = + // + demandZone != NULL && + demandZone.IsValid() + // + ; + + // + return result; + } + +//////////////////////////////////////////////////////////////////////////////////////////////// + + // else + // // + // // Draw ... + // { + // // + // // TODO: Remove this ... + + // // + // bool hasBullishOB = mTestConditions.HasBullishOrderBlock(); + // if (hasBullishOB) + // { + // // + // mTestConditions.bullishOrderBlock.To(TimeCurrent()); + // XCBullishOrderBlockObject *iObj; + // bool isCreated = mPOIDrawer.CreateBullishOrderBlock( + // mTestConditions.bullishOrderBlock, + // iObj // + // ); + // if (isCreated) + // { + // // + // iObj.ZoneWidth(4); + // iObj.ZoneColor(clrAqua); + + // // + // AddObjectIfNotExists(iObj); + // } + // } + + // // + // bool hasBearishOB = mTestConditions.HasBearishOrderBlock(); + // if (hasBearishOB) + // { + // // + // mTestConditions.bearishOrderBlock.To(TimeCurrent()); + // XCBearishOrderBlockObject *iObj; + // bool isCreated = mPOIDrawer.CreateBearishOrderBlock( + // mTestConditions.bearishOrderBlock, + // iObj // + // ); + // if (isCreated) + // { + // // + // iObj.ZoneWidth(4); + // iObj.ZoneColor(clrMagenta); + + // // + // AddObjectIfNotExists(iObj); + // } + // } + // } + + // + // Detect Supply and Demand Zone inside Order Block ... + +/////////////////////////////////////////////////////////////////////////////////////////////// + + + // + // TODO: Remove this ... + XSMCStrategySetupConditions mTestConditions; + bool DetectTestSignal( + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + ENUM_X_121_SMC_PROVIDERS provider = X_121_SMC_PROVIDER_SMPV; + string providerStr = ToString(provider); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + + // + double selectedSL = 0; + + // + // Retrieve Peak and Vale ... + double peak = conditions.triggerConditions.x121Conditions.peaksBuffer[0]; + double vale = conditions.triggerConditions.x121Conditions.valesBuffer[0]; + + // + X121SMCCycleConditions triggerConditions = conditions.triggerConditions; + X121SMCCycleConditions decisionConditions = conditions.decisionConditions; + X121SMCCycleConditions analyseConditions = conditions.analyseConditions; + X121SMCCycleConditions verificationConditions = conditions.verificationConditions; + X121SMCCycleConditions consolidationConditions = conditions.consolidationConditions; + X121SMCCycleConditions visionConditions = conditions.visionConditions; + + // + XPOIState triggerState = triggerConditions.state; + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState verificationState = verificationConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + int zoneValidationDivider = 10; + + // + // Try to Detect Setup Conditions ... + result = mTestConditions.IsSetuped(); + + // + // Try to Validate if not Pssed ... + if (result) + { + // + bool canReset = false; + bool iBullish = IsBullish(mTestConditions.dir); + if (isBullish) + { + // + canReset = + // + bid < mTestConditions.bullishOrderBlock.Lower() && + ask < mTestConditions.bullishOrderBlock.Lower() && + cBar.high < mTestConditions.bullishOrderBlock.Lower() + // + ; + } + else + { + // + canReset = + // + bid < mTestConditions.bearishOrderBlock.Upper() && + ask < mTestConditions.bearishOrderBlock.Upper() && + cBar.high < mTestConditions.bearishOrderBlock.Upper() + // + ; + } + + // + if (canReset) + { + // + string message = providerStr + " Conditions Resetted ..."; + Alert(message); + mTestConditions.Clean(); + } + + // + result = mTestConditions.IsSetuped(); + } + + // + if (!result) + { + // + // Check has Order Block ... + bool hasOrderBlock = mTestConditions.HasOrderBlock(); + if (!hasOrderBlock) + { + // + // Detect Order Blocks ... + + // + // Bullish ... + bool hasBullishOB = mTestConditions.HasBullishOrderBlock(); + if (!hasBullishOB) + { + // + // Bullish ... + int bullishOBsCount = visionState.CountBullishOrderBlocks(); + if (IsValidSize(bullishOBsCount)) + { + // + XCOrderBlock *bullishOBs[]; + for (int i = 0; i < bullishOBsCount; i++) + { + // + XCOrderBlock *iZone = visionState.bullishOrderBlocks[i]; + + // + bool isValid = cBar.low > iZone.Upper(); + if (isValid) + { + // + Add( + iZone, + bullishOBs // + ); + } + } + + // + XCOrderBlock *ob = NULL; + bullishOBsCount = ArraySize(bullishOBs); + if (IsValidSize(bullishOBsCount)) + { + // + for (int i = 0; i < bullishOBsCount; i++) + { + // + XCOrderBlock *iZone = bullishOBs[i]; + + // + bool isValid = ob == NULL + ? true + : ob.Upper() < iZone.Upper(); + if (isValid) + { + ob = iZone; + } + } + } + + // + if (ob != NULL && ob.IsValid()) + { + mTestConditions.bullishOrderBlock = ob; + } + } + } + + // + // Bearish ... + bool hasBearishOB = mTestConditions.HasBearishOrderBlock(); + if (!hasBearishOB) + { + // + // Bearish ... + int bearishOBsCount = visionState.CountBearishOrderBlocks(); + if (IsValidSize(bearishOBsCount)) + { + // + XCOrderBlock *bearishOBs[]; + for (int i = 0; i < bearishOBsCount; i++) + { + // + XCOrderBlock *iZone = visionState.bearishOrderBlocks[i]; + + // + bool isValid = cBar.high < iZone.Lower(); + if (isValid) + { + // + Add( + iZone, + bearishOBs // + ); + } + } + + // + XCOrderBlock *ob = NULL; + bearishOBsCount = ArraySize(bearishOBs); + if (IsValidSize(bearishOBsCount)) + { + // + for (int i = 0; i < bearishOBsCount; i++) + { + // + XCOrderBlock *iZone = bearishOBs[i]; + + // + bool isValid = ob == NULL + ? true + : ob.Lower() > iZone.Lower(); + if (isValid) + { + ob = iZone; + } + } + } + + // + if (ob != NULL && ob.IsValid()) + { + mTestConditions.bearishOrderBlock = ob; + } + } + } + + // + result = mTestConditions.HasOrderBlock(); + if (!result) + { + return result; + } + } + + // + // Wait for new Vale or Peaks ... + double visionPeak = visionConditions.x121Conditions.peaksBuffer[0]; + double visionVale = visionConditions.x121Conditions.valesBuffer[0]; + bool isNewVisionPeak = visionConditions.x121Conditions.isNewPeak; + bool isNewVisionVale = visionConditions.x121Conditions.isNewVale; + + // + bool isNewPeakInsideBearihOrderBlock = + // + isNewVisionPeak && + visionPeak > mTestConditions.bearishOrderBlock.Lower() && + visionPeak < mTestConditions.bearishOrderBlock.Upper() + // + ; + + // + bool isNewValeInsideBullishOrderBlock = + // + isNewVisionVale && + visionVale > mTestConditions.bullishOrderBlock.Lower() && + visionVale < mTestConditions.bullishOrderBlock.Upper() + // + ; + + // + result = isNewPeakInsideBearihOrderBlock || + isNewValeInsideBullishOrderBlock; + if (!result) + { + return result; + } + + // + // Lookig for a Valid Peaks and Vales Formes ... + // Peaks Inside Bearish Order Block ... + // Vales inside Bullish Order Block ... + + // + int validPivotRepetition = mTriggerCycleHelper.mX121Helper + .GetDonChainLength(); + double triggerPeak = triggerConditions.x121Conditions.peaksBuffer[0]; + double triggerVale = triggerConditions.x121Conditions.valesBuffer[0]; + + // + // Valid Peaks ... + XPVPivotPoint validPeak; + XPVPivotPoint peaksChanges[]; + int peaksChangesCount = mTriggerCycleHelper.FillPeakPivotPoints(peaksChanges); + if (IsValidSize(peaksChangesCount)) + { + validPeak = peaksChanges[peaksChangesCount - 1]; + } + + // + // Valid Vales ... + XPVPivotPoint validVale; + XPVPivotPoint valesChanges[]; + int valesChangesCount = mTriggerCycleHelper.FillValePivotPoints(valesChanges); + if (IsValidSize(valesChangesCount)) + { + validVale = valesChanges[valesChangesCount - 1]; + } + + // + bool hasValidPeak = (validPeak.IsValid() && + validPeak.value < mTestConditions.bearishOrderBlock.Upper() && + validPeak.value > mTestConditions.bearishOrderBlock.Lower()); + + // + bool hasValidVale = (validVale.IsValid() && + validVale.value < mTestConditions.bullishOrderBlock.Upper() && + validVale.value > mTestConditions.bullishOrderBlock.Lower()); + + // + result = hasValidPeak || + hasValidVale; + if (!result) + { + return result; + } + + // + if (hasValidPeak) + { + mTestConditions.validPeak = validPeak; + } + if (hasValidVale) + { + mTestConditions.validVale = validVale; + } + + // + bool isBullish = + // + hasValidVale && + isNewValeInsideBullishOrderBlock + // + ; + + // + bool isBearish = + // + hasValidPeak && + isNewPeakInsideBearihOrderBlock + // + ; + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + mTestConditions.dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + mTestConditions.setupTime = TimeCurrent(); + + // + result = mTestConditions.IsSetuped(); + if (!result) + { + return result; + } + + // + // Alert ... + string message = providerStr + " Conditions Set Upped: " + ToString(mTestConditions.dir); + Alert(message); + } + else + { + // + // Waits for Sar Change Under Valid Value or Above Valid Peak ... + double triggerPeak = triggerConditions.x121Conditions.peaksBuffer[1]; + double triggerVale = triggerConditions.x121Conditions.valesBuffer[1]; + double triggerSar = triggerConditions.x121Conditions.sarBuffer[1]; + bool isSarSwitchedToBullish = triggerConditions.x121Conditions.isSarSwitchedToBullish; + bool isSarSwitchedToBearish = triggerConditions.x121Conditions.isSarSwitchedToBearish; + + // + bool isBullish = + // + isSarSwitchedToBullish && + triggerSar == triggerVale && + IsBullish(mTestConditions.dir) && + mTestConditions.validVale.IsValid() && + triggerSar < mTestConditions.validVale.value + // + ; + + // + bool isBearish = + // + isSarSwitchedToBearish && + triggerSar == triggerPeak && + IsBearish(mTestConditions.dir) && + mTestConditions.validPeak.IsValid() && + triggerSar < mTestConditions.validPeak.value + // + ; + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Try to Detect Trigger Conditions ... + + // + mTestConditions.symbol = symbol; + mTestConditions.period = period; + + // + mTestConditions.Clean(); + } + + // + // Check Conditions is Prepared for Trigger ... + result = mTestConditions.CanTrigger(); + if (!result) + { + return result; + } + + // + conditions.signalDir = mTestConditions.dir; + conditions.provider = providerStr; + conditions.sl = mTestConditions.sl; + + // + mTestConditions.Clean(); + + // + return result; + } + + +///////////////////////////////////////////////////////////////////////////////////////// + + + + // + // TODO: Remove this ... + XSMCStrategySetupConditions mTestConditions; + bool DetectTestSignal( + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + ENUM_X_121_SMC_PROVIDERS provider = X_121_SMC_PROVIDER_SMPV; + string providerStr = ToString(provider); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + + // + double selectedSL = 0; + + // + // Retrieve Peak and Vale ... + double peak = conditions.triggerConditions.x121Conditions.peaksBuffer[0]; + double vale = conditions.triggerConditions.x121Conditions.valesBuffer[0]; + + // + X121SMCCycleConditions triggerConditions = conditions.triggerConditions; + X121SMCCycleConditions decisionConditions = conditions.decisionConditions; + X121SMCCycleConditions analyseConditions = conditions.analyseConditions; + X121SMCCycleConditions verificationConditions = conditions.verificationConditions; + X121SMCCycleConditions consolidationConditions = conditions.consolidationConditions; + X121SMCCycleConditions visionConditions = conditions.visionConditions; + + // + XPOIState triggerState = triggerConditions.state; + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState verificationState = verificationConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + int zoneValidationDivider = 10; + + // + // Try to Detect Setup Conditions ... + result = mTestConditions.IsSetuped(); + + // + // Try to Validate if not Pssed ... + if (result) + { + // + bool canReset = false; + bool iBullish = IsBullish(mTestConditions.dir); + if (isBullish) + { + // + canReset = + // + bid < mTestConditions.bullishOrderBlock.Lower() && + ask < mTestConditions.bullishOrderBlock.Lower() && + cBar.high < mTestConditions.bullishOrderBlock.Lower() + // + ; + } + else + { + // + canReset = + // + bid < mTestConditions.bearishOrderBlock.Upper() && + ask < mTestConditions.bearishOrderBlock.Upper() && + cBar.high < mTestConditions.bearishOrderBlock.Upper() + // + ; + } + + // + if (canReset) + { + // + string message = providerStr + " Conditions Resetted ..."; + Alert(message); + mTestConditions.Clean(); + } + + // + result = mTestConditions.IsSetuped(); + } + + // + if (!result) + { + // + // Check has Order Block ... + bool hasOrderBlock = mTestConditions.HasOrderBlock(); + if (!hasOrderBlock) + { + // + // Detect Order Blocks ... + + // + // Bullish ... + bool hasBullishOB = mTestConditions.HasBullishOrderBlock(); + if (!hasBullishOB) + { + // + // Bullish ... + int bullishOBsCount = visionState.CountBullishOrderBlocks(); + if (IsValidSize(bullishOBsCount)) + { + // + XCOrderBlock *bullishOBs[]; + for (int i = 0; i < bullishOBsCount; i++) + { + // + XCOrderBlock *iZone = visionState.bullishOrderBlocks[i]; + + // + bool isValid = cBar.low > iZone.Upper(); + if (isValid) + { + // + Add( + iZone, + bullishOBs // + ); + } + } + + // + XCOrderBlock *ob = NULL; + bullishOBsCount = ArraySize(bullishOBs); + if (IsValidSize(bullishOBsCount)) + { + // + for (int i = 0; i < bullishOBsCount; i++) + { + // + XCOrderBlock *iZone = bullishOBs[i]; + + // + bool isValid = ob == NULL + ? true + : ob.Upper() < iZone.Upper(); + if (isValid) + { + ob = iZone; + } + } + } + + // + if (ob != NULL && ob.IsValid()) + { + mTestConditions.bullishOrderBlock = ob; + } + } + } + + // + // Bearish ... + bool hasBearishOB = mTestConditions.HasBearishOrderBlock(); + if (!hasBearishOB) + { + // + // Bearish ... + int bearishOBsCount = visionState.CountBearishOrderBlocks(); + if (IsValidSize(bearishOBsCount)) + { + // + XCOrderBlock *bearishOBs[]; + for (int i = 0; i < bearishOBsCount; i++) + { + // + XCOrderBlock *iZone = visionState.bearishOrderBlocks[i]; + + // + bool isValid = cBar.high < iZone.Lower(); + if (isValid) + { + // + Add( + iZone, + bearishOBs // + ); + } + } + + // + XCOrderBlock *ob = NULL; + bearishOBsCount = ArraySize(bearishOBs); + if (IsValidSize(bearishOBsCount)) + { + // + for (int i = 0; i < bearishOBsCount; i++) + { + // + XCOrderBlock *iZone = bearishOBs[i]; + + // + bool isValid = ob == NULL + ? true + : ob.Lower() > iZone.Lower(); + if (isValid) + { + ob = iZone; + } + } + } + + // + if (ob != NULL && ob.IsValid()) + { + mTestConditions.bearishOrderBlock = ob; + } + } + } + + // + result = mTestConditions.HasOrderBlock(); + if (!result) + { + return result; + } + } + + // + // Wait for new Vale or Peaks ... + double visionPeak = visionConditions.x121Conditions.peaksBuffer[0]; + double visionVale = visionConditions.x121Conditions.valesBuffer[0]; + bool isNewVisionPeak = visionConditions.x121Conditions.isNewPeak; + bool isNewVisionVale = visionConditions.x121Conditions.isNewVale; + + // + bool isNewPeakInsideBearihOrderBlock = + // + isNewVisionPeak && + visionPeak > mTestConditions.bearishOrderBlock.Lower() && + visionPeak < mTestConditions.bearishOrderBlock.Upper() + // + ; + + // + bool isNewValeInsideBullishOrderBlock = + // + isNewVisionVale && + visionVale > mTestConditions.bullishOrderBlock.Lower() && + visionVale < mTestConditions.bullishOrderBlock.Upper() + // + ; + + // + result = isNewPeakInsideBearihOrderBlock || + isNewValeInsideBullishOrderBlock; + if (!result) + { + return result; + } + + // + // Lookig for a Valid Peaks and Vales Formes ... + // Peaks Inside Bearish Order Block ... + // Vales inside Bullish Order Block ... + + // + int validPivotRepetition = mTriggerCycleHelper.mX121Helper + .GetDonChainLength(); + double triggerPeak = triggerConditions.x121Conditions.peaksBuffer[0]; + double triggerVale = triggerConditions.x121Conditions.valesBuffer[0]; + + // + // Valid Peaks ... + XPVPivotPoint validPeak; + XPVPivotPoint peaksChanges[]; + int peaksChangesCount = mTriggerCycleHelper.FillPeakPivotPoints(peaksChanges); + if (IsValidSize(peaksChangesCount)) + { + validPeak = peaksChanges[peaksChangesCount - 1]; + } + + // + // Valid Vales ... + XPVPivotPoint validVale; + XPVPivotPoint valesChanges[]; + int valesChangesCount = mTriggerCycleHelper.FillValePivotPoints(valesChanges); + if (IsValidSize(valesChangesCount)) + { + validVale = valesChanges[valesChangesCount - 1]; + } + + // + bool hasValidPeak = (validPeak.IsValid() && + validPeak.value < mTestConditions.bearishOrderBlock.Upper() && + validPeak.value > mTestConditions.bearishOrderBlock.Lower()); + + // + bool hasValidVale = (validVale.IsValid() && + validVale.value < mTestConditions.bullishOrderBlock.Upper() && + validVale.value > mTestConditions.bullishOrderBlock.Lower()); + + // + result = hasValidPeak || + hasValidVale; + if (!result) + { + return result; + } + + // + if (hasValidPeak) + { + mTestConditions.validPeak = validPeak; + } + if (hasValidVale) + { + mTestConditions.validVale = validVale; + } + + // + bool isBullish = + // + hasValidVale && + isNewValeInsideBullishOrderBlock + // + ; + + // + bool isBearish = + // + hasValidPeak && + isNewPeakInsideBearihOrderBlock + // + ; + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + mTestConditions.dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + mTestConditions.setupTime = TimeCurrent(); + + // + result = mTestConditions.IsSetuped(); + if (!result) + { + return result; + } + + // + // Alert ... + string message = providerStr + " Conditions Set Upped: " + ToString(mTestConditions.dir); + Alert(message); + } + else + { + // + // Waits for Sar Change Under Valid Value or Above Valid Peak ... + double triggerPeak = triggerConditions.x121Conditions.peaksBuffer[1]; + double triggerVale = triggerConditions.x121Conditions.valesBuffer[1]; + double triggerSar = triggerConditions.x121Conditions.sarBuffer[1]; + bool isSarSwitchedToBullish = triggerConditions.x121Conditions.isSarSwitchedToBullish; + bool isSarSwitchedToBearish = triggerConditions.x121Conditions.isSarSwitchedToBearish; + + // + bool isBullish = + // + isSarSwitchedToBullish && + triggerSar == triggerVale && + IsBullish(mTestConditions.dir) && + mTestConditions.validVale.IsValid() && + triggerSar < mTestConditions.validVale.value + // + ; + + // + bool isBearish = + // + isSarSwitchedToBearish && + triggerSar == triggerPeak && + IsBearish(mTestConditions.dir) && + mTestConditions.validPeak.IsValid() && + triggerSar < mTestConditions.validPeak.value + // + ; + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Try to Detect Trigger Conditions ... + + // + mTestConditions.symbol = symbol; + mTestConditions.period = period; + + // + mTestConditions.Clean(); + } + + // + // Check Conditions is Prepared for Trigger ... + result = mTestConditions.CanTrigger(); + if (!result) + { + return result; + } + + // + conditions.signalDir = mTestConditions.dir; + conditions.provider = providerStr; + conditions.sl = mTestConditions.sl; + + // + mTestConditions.Clean(); + + // + return result; + } + + +///////////////////////////////////////////////////////////////////////////// + + + // + // TODO: Remove this ... + XSMCStrategySetupConditions mTestConditions; + bool DetectTestSignal( + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + ENUM_X_121_SMC_PROVIDERS provider = X_121_SMC_PROVIDER_SMPV; + string providerStr = ToString(provider); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + + // + double selectedSL = 0; + + // + // Retrieve Peak and Vale ... + double triggerPeak = conditions.triggerConditions.x121Conditions.peaksBuffer[0]; + double triggerVale = conditions.triggerConditions.x121Conditions.valesBuffer[0]; + + // + X121SMCCycleConditions triggerConditions = conditions.triggerConditions; + X121SMCCycleConditions decisionConditions = conditions.decisionConditions; + X121SMCCycleConditions analyseConditions = conditions.analyseConditions; + X121SMCCycleConditions verificationConditions = conditions.verificationConditions; + X121SMCCycleConditions consolidationConditions = conditions.consolidationConditions; + X121SMCCycleConditions visionConditions = conditions.visionConditions; + + // + XPOIState triggerState = triggerConditions.state; + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState verificationState = verificationConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + int zoneValidationDivider = 10; + int validPivotRepetition = mTriggerCycleHelper.mX121Helper + .GetDonChainLength(); + + // + // Check Setting Upped ... + result = mTestConditions.IsSetuped(); + + // + // Try to Validate if not Pssed ... + if (result) + { + // + double upper = 0; + double lower = 0; + + // + double hh = cBar.FindHighest(9, MODE_HIGH); + double ll = cBar.FindLowest(9, MODE_LOW); + + // + bool canReset = false; + isBullish = IsBullish(mTestConditions.dir); + if (isBullish) + { + // + upper = mTestConditions.bullishOrderBlock.Upper(); + lower = mTestConditions.bullishOrderBlock.Lower(); + + // + canReset = + // + (ll > upper && + bid > upper && + ask > upper) + // + || + // + (hh < lower && + bid < lower && + ask < lower) + // + ; + } + else + { + // + upper = mTestConditions.bearishOrderBlock.Upper(); + lower = mTestConditions.bearishOrderBlock.Lower(); + + // + canReset = + // + (hh < lower && + bid < lower && + ask < lower) + // + || + // + (ll > upper && + bid > upper && + ask > upper) + // + ; + } + + // + if (canReset) + { + // + string message = providerStr + " Conditions Resetted ..."; + Alert(message); + + // + ClearDraws(); + mTestConditions.Clean(); + } + + // + result = mTestConditions.IsSetuped(); + } + + // + // Try to Detect Setting Up Conditions ... + if (!result) + { + // + // Check has Order Block ... + bool hasOrderBlock = mTestConditions.HasOrderBlock(); + if (!hasOrderBlock) + { + // + // Detect Order Blocks ... + + // + // Bullish ... + bool hasBullishOB = mTestConditions.HasBullishOrderBlock(); + if (!hasBullishOB) + { + // + // Bullish ... + int bullishOBsCount = visionState.CountBullishOrderBlocks(); + if (IsValidSize(bullishOBsCount)) + { + // + XCOrderBlock *bullishOBs[]; + for (int i = 0; i < bullishOBsCount; i++) + { + // + XCOrderBlock *iZone = visionState.bullishOrderBlocks[i]; + + // + bool isValid = cBar.low > iZone.Upper(); + if (isValid) + { + // + Add( + iZone, + bullishOBs // + ); + } + } + + // + XCOrderBlock *ob = NULL; + bullishOBsCount = ArraySize(bullishOBs); + if (IsValidSize(bullishOBsCount)) + { + // + for (int i = 0; i < bullishOBsCount; i++) + { + // + XCOrderBlock *iZone = bullishOBs[i]; + + // + bool isValid = ob == NULL + ? true + : ob.Upper() < iZone.Upper(); + if (isValid) + { + ob = iZone; + } + } + } + + // + if (ob != NULL && ob.IsValid()) + { + // + mTestConditions.bullishOrderBlock = ob; + mTestConditions.bullishOrderBlockTime = TimeCurrent(); + } + } + } + + // + // Bearish ... + bool hasBearishOB = mTestConditions.HasBearishOrderBlock(); + if (!hasBearishOB) + { + // + // Bearish ... + int bearishOBsCount = visionState.CountBearishOrderBlocks(); + if (IsValidSize(bearishOBsCount)) + { + // + XCOrderBlock *bearishOBs[]; + for (int i = 0; i < bearishOBsCount; i++) + { + // + XCOrderBlock *iZone = visionState.bearishOrderBlocks[i]; + + // + bool isValid = cBar.high < iZone.Lower(); + if (isValid) + { + // + Add( + iZone, + bearishOBs // + ); + } + } + + // + XCOrderBlock *ob = NULL; + bearishOBsCount = ArraySize(bearishOBs); + if (IsValidSize(bearishOBsCount)) + { + // + for (int i = 0; i < bearishOBsCount; i++) + { + // + XCOrderBlock *iZone = bearishOBs[i]; + + // + bool isValid = ob == NULL + ? true + : ob.Lower() > iZone.Lower(); + if (isValid) + { + ob = iZone; + } + } + } + + // + if (ob != NULL && ob.IsValid()) + { + // + mTestConditions.bearishOrderBlock = ob; + mTestConditions.bearishOrderBlockTime = TimeCurrent(); + } + } + } + + // + hasOrderBlock = mTestConditions.HasOrderBlock(); + result = hasOrderBlock; + if (!result) + { + return result; + } + } + else + { + // + datetime nearestTime = NULL; + + // + bool hasBullishOB = mTestConditions.HasBullishOrderBlock(); + if (hasBullishOB) + { + // + nearestTime = + !IsValid(nearestTime) + ? mTestConditions.bullishOrderBlockTime + : nearestTime < mTestConditions.bullishOrderBlockTime + ? mTestConditions.bullishOrderBlockTime + : nearestTime; + + // + mTestConditions.bullishOrderBlock.To(TimeCurrent()); + XCBullishOrderBlockObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishOrderBlock( + mTestConditions.bullishOrderBlock, + iObj // + ); + if (isCreated) + { + // + iObj.ZoneWidth(4); + iObj.ZoneColor(clrAqua); + + // + AddObjectIfNotExists(iObj); + } + } + + // + bool hasBearishOB = mTestConditions.HasBearishOrderBlock(); + if (hasBearishOB) + { + // + nearestTime = + !IsValid(nearestTime) + ? mTestConditions.bearishOrderBlockTime + : nearestTime < mTestConditions.bearishOrderBlockTime + ? mTestConditions.bearishOrderBlockTime + : nearestTime; + + // + mTestConditions.bearishOrderBlock.To(TimeCurrent()); + XCBearishOrderBlockObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishOrderBlock( + mTestConditions.bearishOrderBlock, + iObj // + ); + if (isCreated) + { + // + iObj.ZoneWidth(4); + iObj.ZoneColor(clrMagenta); + + // + AddObjectIfNotExists(iObj); + } + } + + // + if (IsValid(nearestTime)) + { + // + datetime cTime = TimeCurrent(); + int periodSeconds = PeriodSeconds(period); + int passedTime = (int)cTime - (int)nearestTime; + + // + int barsPassed = passedTime / periodSeconds; + bool canReset = barsPassed >= validPivotRepetition * 5; + if (canReset && + !mTestConditions.isOrderBlockAttacked) + { + // + ClearDraws(); + mTestConditions.Clean(); + result = false; + + // + return result; + } + } + } + + // + // Check Order Block Attacks ... + if (!mTestConditions.isOrderBlockAttacked) + { + // + bool isBullishOrderBlockAttacked = + // + (mTestConditions.HasBullishOrderBlock() && + cBar.high < mTestConditions.bullishOrderBlock.Upper() && + cBar.low > mTestConditions.bullishOrderBlock.Lower()) + // + ; + bool isBearishOrderBlockAttacked = + // + (mTestConditions.HasBearishOrderBlock() && + cBar.high < mTestConditions.bearishOrderBlock.Upper() && + cBar.low > mTestConditions.bearishOrderBlock.Lower()) + // + ; + bool isOrderBlockAttacked = isBullishOrderBlockAttacked || + isBearishOrderBlockAttacked; + result = isOrderBlockAttacked; + if (!result) + { + return result; + } + + // + mTestConditions.isOrderBlockAttacked = isOrderBlockAttacked; + } + + // + // Other Conditions ... + bool isNewTriggerPeak = triggerConditions.x121Conditions.isNewPeak; + bool isNewTriggerVale = triggerConditions.x121Conditions.isNewVale; + + // + bool isNewPeakInsideBearihOrderBlock = + // + isNewTriggerPeak && + triggerPeak > mTestConditions.bearishOrderBlock.Lower() && + triggerPeak < mTestConditions.bearishOrderBlock.Upper() + // + ; + + // + bool isNewValeInsideBullishOrderBlock = + // + isNewTriggerVale && + triggerVale > mTestConditions.bullishOrderBlock.Lower() && + triggerVale < mTestConditions.bullishOrderBlock.Upper() + // + ; + + // + result = isNewPeakInsideBearihOrderBlock || + isNewValeInsideBullishOrderBlock; + if (!result) + { + return result; + } + + // + // Lookig for a Valid Peaks and Vales Formes ... + // Peaks Inside Bearish Order Block ... + // Vales inside Bullish Order Block ... + + // + double triggerPeak = triggerConditions.x121Conditions.peaksBuffer[0]; + double triggerVale = triggerConditions.x121Conditions.valesBuffer[0]; + + // + // Valid Peaks ... + XPVPivotPoint validPeak; + XPVPivotPoint peaksChanges[]; + int peaksChangesCount = mTriggerCycleHelper.FillPeakPivotPoints(peaksChanges); + if (IsValidSize(peaksChangesCount)) + { + validPeak = peaksChanges[peaksChangesCount - 1]; + } + + // + // Valid Vales ... + XPVPivotPoint validVale; + XPVPivotPoint valesChanges[]; + int valesChangesCount = mTriggerCycleHelper.FillValePivotPoints(valesChanges); + if (IsValidSize(valesChangesCount)) + { + validVale = valesChanges[valesChangesCount - 1]; + } + + // + bool hasValidPeak = (validPeak.IsValid() && + validPeak.value < mTestConditions.bearishOrderBlock.Upper() && + validPeak.value > mTestConditions.bearishOrderBlock.Lower()); + + // + bool hasValidVale = (validVale.IsValid() && + validVale.value < mTestConditions.bullishOrderBlock.Upper() && + validVale.value > mTestConditions.bullishOrderBlock.Lower()); + + // + result = hasValidPeak || + hasValidVale; + if (!result) + { + return result; + } + + // + if (hasValidPeak) + { + mTestConditions.validPeak = validPeak; + } + if (hasValidVale) + { + mTestConditions.validVale = validVale; + } + + // + isBullish = + // + hasValidVale && + isNewValeInsideBullishOrderBlock + // + ; + + // + isBearish = + // + hasValidPeak && + isNewPeakInsideBearihOrderBlock + // + ; + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + ENUM_X_DIRECTION setupDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + mTestConditions.dir = setupDir; + mTestConditions.setupTime = TimeCurrent(); + + // + // Alert ... + string message = providerStr + " Conditions Set Upped: " + ToString(mTestConditions.dir); + Alert(message); + } + + // + // Try To Detect Trigger Conditions ... + + // + // Check Conditions is Prepared for Trigger ... + result = mTestConditions.CanTrigger(); + if (!result) + { + return result; + } + + // + // Issues Signal on Conditions ... + conditions.signalDir = mTestConditions.dir; + conditions.provider = providerStr; + conditions.sl = mTestConditions.sl; + + // + // mTestConditions.Clean(); + + // + return result; + } + + +////////////////////////////////////////////////////////////////////////////////// + + + /** + * Detect and Parse Market Conditions for Signalling ... + * + * @param conditions: X121SMCStrategyConditions instance Reference ... + * + * @return ( bool ) + */ + bool DetectSamePeaksAndValesSignal( + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + ENUM_X_121_SMC_PROVIDERS provider = X_121_SMC_PROVIDER_SMPV; + string providerStr = ToString(provider); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + string msg = NULL; + + // + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + + // + double selectedSL = 0; + + // + // Here We Select Cycles For Conditions Check ... + ENUM_X_CYCLES cycles[5] = { + X_CYCLE_TRIGGER, + X_CYCLE_DECISION, + X_CYCLE_ANALYSE, + X_CYCLE_VERIFICATION, + X_CYCLE_CONSOLIDATION // + }; + bool hasSamePeaks = DetectSamePeaks( + cycles, + conditions // + ); + bool hasSameVales = DetectSameVales( + cycles, + conditions // + ); + result = + hasSamePeaks || + hasSameVales; + if (!result) + { + return result; + } + + // + // Check Peaks And Vales Order ... + bool hasPeakBreak = false; + bool hasValeBreak = false; + + // + // Retrieve Last Sar Change ... + XOHCL cSarChangeBar; + XOHCL pSarChangeBar; + XValueChange cSarChange; // Current Sar Change (IsDirect) ... + XValueChange pSarChange; // Prev Sar Change (Direct) ... + XValueChange sarChanges[]; + int sarChangesCount = mTriggerCycleHelper + .FillSarChanges(sarChanges); + if (IsValidSize(sarChangesCount) && + sarChangesCount > 2) + { + // + cSarChange = sarChanges[sarChangesCount - 1]; + pSarChange = sarChanges[sarChangesCount - 2]; + + // + result = cSarChange.FillBar( + cSarChangeBar, + symbol, + period // + ); + if (!result) + { + return result; + } + + // + result = pSarChange.FillBar( + pSarChangeBar, + symbol, + period // + ); + if (!result) + { + return result; + } + + // + int start = cSarChangeBar.Index(); + int end = pSarChangeBar.Index(); + for (int i = start; i < end; i++) + { + // + ENUM_X_CYCLE_EVENTS iEvents[]; + X121SMCCycleConditions iConditions; + result = mTriggerCycleHelper.GetConditions( + iEvents, + iConditions, + i // + ); + if (!result) + { + continue; + } + + // + hasPeakBreak = + iConditions.x121Conditions.isNewPeakOverLast; + hasValeBreak = + iConditions.x121Conditions.isNewValeUnderLast; + result = hasPeakBreak || + hasValeBreak; + if (result) + { + break; + } + } + } + if (!result) + { + return result; + } + + // + // Check Sar State ... + ENUM_X_DIRECTION sarDir; + result = DetectSarState( + provider, + sarDir, + conditions // + ); + if (!result) + { + return result; + } + + // + // Check VWAP State ... + ENUM_X_DIRECTION vwapDir; + result = DetectVWapState( + provider, + vwapDir, + conditions // + ); + if (!result) + { + return result; + } + + // + // Detect a Valid Peaks Break ... + + // + // Find Supply and Demand Zones ... + // XPOIState state = conditions.visionConditions.state; + // int supplyZonesCount = + + // + bool isBullish = + // + hasSamePeaks && + hasPeakBreak && + IsBullish(sarDir) && + IsBullish(vwapDir) + // + ; + + // + bool isBearish = + // + hasSameVales && + hasValeBreak && + IsBearish(sarDir) && + IsBearish(vwapDir) + // + ; + + // + result = + isBullish || + isBearish; + if (!result) + { + return result; + } + + // + CustomStateDrawing( + conditions.visionConditions.state, + false, // + X_DIRECTION_NONE, + false, // ignoreSwingHighs + false, // ignoreSwingLows + true, // ignoreSupportZones + true, // ignoreResistanceZones + false, // ignoreSupplyZones + false, // ignoreDemandZones + true, // ignoreBullishOrderBlocks + true, // ignoreBearishOrderBlocks + true, // ignoreBullishFairValueGaps + true, // ignoreBearishFairValueGaps + true, // ignoreBullishRejectionBars + true, // ignoreBearishRejectionBars + true, // ignoreBullishMomentumBars + true // ignoreBearishMomentumBars + ); + + // + // Set SL, Provider and Direction ... + conditions.signalDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + conditions.provider = providerStr; + + // + // Selectiong SL ... + double selectedSLRJ = SelectSL( + conditions, + conditions.signalDir, + X_121_SMC_SL_TYPE_REJECTION // + ); + double selectedSLMN = SelectSL( + conditions, + conditions.signalDir, + X_121_SMC_SL_TYPE_MOMENTUM // + ); + double selectedSLSW = SelectSL( + conditions, + conditions.signalDir, + X_121_SMC_SL_TYPE_SWING // + ); + double selectedSLSR = SelectSL( + conditions, + conditions.signalDir, + X_121_SMC_SL_TYPE_CURRENT_SAR // + ); + + // + double slCandidates[4] = { + selectedSLRJ, + selectedSLMN, + selectedSLSW, + selectedSLSR // + }; + selectedSL = isBullish + ? GetMin(slCandidates) + : GetMax(slCandidates); + + // + // Normalizing SL ... + double entry = GetEntry( + symbol, + conditions.signalDir // + ); + double pip = GetPipPrice(symbol); + double spread = GetSpread(symbol); + double points = GetPoints(symbol); + + // + if (isBullish && selectedSL <= entry) + { + selectedSL -= (points * 30) - spread; + } + else if (isBearish && selectedSL >= entry) + { + selectedSL += (points * 30) + spread; + } + + // + // Detect SL and TP ... + conditions.sl = selectedSL; + + // + return result; + } + + /** + * Detect and Parse Market Conditions for Signalling ... + * + * @param conditions: X121SMCStrategyConditions instance Reference ... + * + * @return ( bool ) + */ + bool DetectRJBPVSignal( + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = pBar.Init( + symbol, + period, + pIndex // + ); + if (!result) + { + return result; + } + + // + string msg = NULL; + + // + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + + // + ENUM_X_121_SMC_PROVIDERS provider = X_121_SMC_PROVIDER_RJBPV; + string providerStr = ToString(provider); + + // + // Bar High Eqauls to Peaks or Vale ... + double peak = conditions.triggerConditions.x121Conditions.peaksBuffer[2]; + double vale = conditions.triggerConditions.x121Conditions.valesBuffer[2]; + bool isNewPeak = conditions.triggerConditions.x121Conditions.peaksBuffer[2] != conditions.triggerConditions.x121Conditions.peaksBuffer[3]; + bool isNewVale = conditions.triggerConditions.x121Conditions.valesBuffer[2] != conditions.triggerConditions.x121Conditions.valesBuffer[3]; + bool isClosedUnderDonCloseUpper = cBar.close < + conditions.triggerConditions.x121Conditions.donCloseUpperBuffer[1]; + bool isClosedOverDonCloseLower = cBar.close > + conditions.triggerConditions.x121Conditions.donCloseLowerBuffer[1]; + bool isSarBullish = + zBar.low > conditions.triggerConditions.x121Conditions.sarBuffer[0]; + bool isSarBearish = + zBar.high < conditions.triggerConditions.x121Conditions.sarBuffer[0]; + + // + // XPVPivot orderFlow[]; + // ENUM_X_DIRECTION orderFlowDir; + // mTriggerCycleHelper + // .DetectOrderFlow( + // zIndex, + // orderFlow, + // orderFlowDir // + // ); + // int pivotsCount = ArraySize(orderFlow); + // result = IsValidSize(pivotsCount); + // if (!result) + // { + // return result; + // } + // XPVPivot lastPivot = orderFlow[pivotsCount - 1]; + + // + double zoneVerificationDivider = 10; + bool isPeakInsideSupplyZone = false; + bool isValeInsideDemandZone = false; + + // + XPOIState state = conditions.verificationConditions.state; + + // // + // // Detect Order Block ... + // XCOrderBlock *orderBlock = NULL; + + // // + // int bullishOBCount = state.CountBullishOrderBlocks(); + // if (IsValidSize(bullishOBCount)) + // { + // // + // for (int i = 0; i < bullishOBCount; i++) + // { + // // + // XCOrderBlock *iZone = state.bullishOrderBlocks[i]; + + // // + // bool isInside = vale >= iZone.Lower() && + // vale <= iZone.Upper() && + // bid <= iZone.Lower() + ((iZone.Upper() - iZone.Lower()) / zoneVerificationDivider); + // if (isInside) + // { + // // + // orderBlock = iZone; + // break; + // } + // } + // } + + // // + // int bearishOBCount = state.CountBearishOrderBlocks(); + // if (IsValidSize(bearishOBCount)) + // { + // // + // for (int i = 0; i < bearishOBCount; i++) + // { + // // + // XCOrderBlock *iZone = state.bearishOrderBlocks[i]; + + // // + // bool isInside = peak >= iZone.Lower() && + // peak <= iZone.Upper() && + // bid >= iZone.Upper() - ((iZone.Upper() - iZone.Lower()) / zoneVerificationDivider); + // if (isInside) + // { + // // + // orderBlock = iZone; + // break; + // } + // } + // } + + // // + // result = orderBlock != NULL && + // orderBlock.IsValid(); + // if (!result) + // { + // return result; + // } + + // // + // // Draw Order Block ... + // orderBlock.To(TimeCurrent()); + // if (orderBlock.IsBullish()) + // { + // // + // XCBullishOrderBlockObject *iObj; + // bool isCreated = mPOIDrawer.CreateBullishOrderBlock( + // orderBlock, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + // } + // else + // { + // // + // XCBearishOrderBlockObject *iObj; + // bool isCreated = mPOIDrawer.CreateBearishOrderBlock( + // orderBlock, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + // } + + // + XCSupplyZone *supplyZone; + int supplyCount = state.CountSupplyZones(); + if (IsValidSize(supplyCount)) + { + // + for (int i = 0; i < supplyCount; i++) + { + // + XCSupplyZone *iZone = state.supplyZones[i]; + isPeakInsideSupplyZone = peak >= iZone.Lower() && + peak <= iZone.Upper() && + bid >= iZone.Lower() + ((iZone.Upper() - iZone.Lower()) / zoneVerificationDivider); + if (isPeakInsideSupplyZone) + { + // + supplyZone = iZone; + break; + } + } + } + + // + XCDemandZone *demandZone; + int demandCount = state.CountDemandZones(); + if (IsValidSize(demandCount)) + { + // + for (int i = 0; i < demandCount; i++) + { + // + XCDemandZone *iZone = state.demandZones[i]; + isValeInsideDemandZone = vale >= iZone.Lower() && + vale <= iZone.Upper() && + bid <= iZone.Lower() + ((iZone.Upper() - iZone.Lower()) / zoneVerificationDivider); + if (isValeInsideDemandZone) + { + // + demandZone = iZone; + break; + } + } + } + + // + bool isPeakAttacked = + isNewPeak && + isSarBearish && + pBar.high == peak && + isPeakInsideSupplyZone && + isClosedUnderDonCloseUpper; + + // + bool isValeAttacked = + isNewVale && + isSarBullish && + pBar.low == vale && + isValeInsideDemandZone && + isClosedOverDonCloseLower; + + // + result = isPeakAttacked || + isValeAttacked; + if (!result) + { + return result; + } + + // + if (isPeakAttacked) + { + // + supplyZone.To(TimeCurrent()); + XCSupplyZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateSupplyZone( + supplyZone, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + else + { + // + demandZone.To(TimeCurrent()); + XCDemandZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateDemandZone( + demandZone, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + + // + bool isBullish = + // + isValeAttacked + // + ; + + // + bool isBearish = + // + isPeakAttacked + // + ; + + // + result = + // + isBullish || + isBearish + // + ; + if (!result) + { + return result; + } + + // + // Set SL, Provider and Direction ... + conditions.signalDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + conditions.provider = providerStr; + + // + conditions.sl = + isBullish + ? demandZone.Lower() + : supplyZone.Upper(); + + // + return result; + } + + /** + * Detect and Parse Market Conditions for Signalling ... + * + * @param conditions: X121SMCStrategyConditions instance Reference ... + * + * @return ( bool ) + */ + // TODO: Required Calibrate ... + bool DetectVWAPCSignal( + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + return false; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + string msg = NULL; + + // + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + + // + ENUM_X_121_SMC_PROVIDERS provider = X_121_SMC_PROVIDER_VWAPC; + string providerStr = ToString(provider); + + // + // Check Candlestic State ... + ENUM_X_DIRECTION candlesticDir; + result = DetectCandlestic( + provider, + candlesticDir, + conditions // + ); + if (!result) + { + return result; + } + + // + // Check Sar State ... + ENUM_X_DIRECTION sarDir; + result = DetectSarState( + provider, + sarDir, + conditions // + ); + if (!result) + { + return result; + } + + // + // Check VWAP State ... + ENUM_X_DIRECTION vwapDir; + result = DetectVWapState( + provider, + vwapDir, + conditions // + ); + if (!result) + { + return result; + } + + // + bool isBullish = + // + IsBullish(sarDir) && + IsBullish(vwapDir) && + IsBullish(candlesticDir) + // + ; + + // + bool isBearish = + // + IsBearish(sarDir) && + IsBearish(vwapDir) && + IsBearish(candlesticDir) + // + ; + + // + result = + // + isBullish || + isBearish + // + ; + + // + Print("VWap Signal ..."); + + // + if (!result) + { + return result; + } + + // + return result; + } + + + + /** + * Detect Where Cycles has Same Peaks ... + * + * @param cycles: ENUM_X_CYCLES members, Array ... + * @param conditions: X121SMCStrategyConditions instance, Reference ... + * + * @return ( bool ) + */ + bool DetectSamePeaks( + ENUM_X_CYCLES &cycles[], + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + int count = ArraySize(cycles); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + double value = -1; + for (int i = 0; i < count; i++) + { + // + ENUM_X_CYCLES iCycle = cycles[i]; + + // + double iValue = -1; + switch (iCycle) + { + // + case X_CYCLE_TRIGGER: + iValue = conditions.triggerConditions.x121Conditions.peaksBuffer[0]; + break; + + // + case X_CYCLE_DECISION: + iValue = conditions.decisionConditions.x121Conditions.peaksBuffer[0]; + break; + + // + case X_CYCLE_ANALYSE: + iValue = conditions.analyseConditions.x121Conditions.peaksBuffer[0]; + break; + + // + case X_CYCLE_VERIFICATION: + iValue = conditions.verificationConditions.x121Conditions.peaksBuffer[0]; + break; + + // + case X_CYCLE_CONSOLIDATION: + iValue = conditions.consolidationConditions.x121Conditions.peaksBuffer[0]; + break; + + // + case X_CYCLE_VISION: + iValue = conditions.visionConditions.x121Conditions.peaksBuffer[0]; + break; + } + + // + if (iValue > 0) + { + // + if (value <= 0) + { + value = iValue; + } + + // + result = value == iValue; + if (!result) + { + break; + } + } + } + + // + return result; + } + + /** + * Detect Where Cycles has Same Vales ... + * + * @param cycles: ENUM_X_CYCLES members, Array ... + * @param conditions: X121SMCStrategyConditions instance, Reference ... + * + * @return ( bool ) + */ + bool DetectSameVales( + ENUM_X_CYCLES &cycles[], + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + int count = ArraySize(cycles); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + double value = -1; + for (int i = 0; i < count; i++) + { + // + ENUM_X_CYCLES iCycle = cycles[i]; + + // + double iValue = -1; + switch (iCycle) + { + // + case X_CYCLE_TRIGGER: + iValue = conditions.triggerConditions.x121Conditions.valesBuffer[0]; + break; + + // + case X_CYCLE_DECISION: + iValue = conditions.decisionConditions.x121Conditions.valesBuffer[0]; + break; + + // + case X_CYCLE_ANALYSE: + iValue = conditions.analyseConditions.x121Conditions.valesBuffer[0]; + break; + + // + case X_CYCLE_VERIFICATION: + iValue = conditions.verificationConditions.x121Conditions.valesBuffer[0]; + break; + + // + case X_CYCLE_CONSOLIDATION: + iValue = conditions.consolidationConditions.x121Conditions.valesBuffer[0]; + break; + + // + case X_CYCLE_VISION: + iValue = conditions.visionConditions.x121Conditions.valesBuffer[0]; + break; + } + + // + if (iValue > 0) + { + // + if (value <= 0) + { + value = iValue; + } + + // + result = value == iValue; + if (!result) + { + break; + } + } + } + + // + return result; + } + + /** + * Detect Sar State for Signalling ... + * + * @param forProvider: ENUM_X_121_SMC_PROVIDERS member ... + * @param dir: ENUM_X_DIRECTION member Reference ... + * @param conditions: X121SMCStrategyConditions instance, Reference ... + * + * @return ( bool ) + */ + bool DetectSarState( + ENUM_X_121_SMC_PROVIDERS forProvider, + ENUM_X_DIRECTION &dir, + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + bool isBullish = false; + bool isBearish = false; + + // + if (forProvider == X_121_SMC_PROVIDER_SMPV) + { + // + isBullish = + // + // Check One of Verification or Consolidation Cycles Must be Sar Bullish ... + (conditions.verificationConditions.x121Conditions.isSarBullish || + conditions.consolidationConditions.x121Conditions.isSarBullish) + // + && + // + // Decision and Analyse Cycles Must be Bullish ... + (conditions.decisionConditions.x121Conditions.isSarBullish && + conditions.analyseConditions.x121Conditions.isSarBullish) + // + && + // + // Trigger State Must be Bearish ... + conditions.triggerConditions.x121Conditions.isSarBearish + // + ; + + // + isBearish = + // + // Check One of Verification or Consolidation Cycles Must be Sar Bearish ... + (conditions.verificationConditions.x121Conditions.isSarBearish || + conditions.consolidationConditions.x121Conditions.isSarBearish) + // + && + // + // Decision and Analyse Cycles Must be Bearish ... + (conditions.decisionConditions.x121Conditions.isSarBearish && + conditions.analyseConditions.x121Conditions.isSarBearish) + // + && + // + // Trigger State Must be Bullish ... + conditions.triggerConditions.x121Conditions.isSarBullish + // + ; + } + + // + if (forProvider == X_121_SMC_PROVIDER_RJBPV) + { + // + isBullish = + // + // Trigger, Decision and Analyse must be Directional ... + conditions.triggerConditions.x121Conditions.isSarBullish && + conditions.decisionConditions.x121Conditions.isSarBullish && + conditions.analyseConditions.x121Conditions.isSarBullish + // + ; + + // + isBearish = + // + // Trigger, Decision and Analyse must be Directional ... + conditions.triggerConditions.x121Conditions.isSarBearish && + conditions.decisionConditions.x121Conditions.isSarBearish && + conditions.analyseConditions.x121Conditions.isSarBearish + // + ; + } + + // + if (forProvider == X_121_SMC_PROVIDER_VWAPC) + { + // + isBullish = + // + // All Cycles Sars Must be Directional exept Vision ... + conditions.triggerConditions.x121Conditions.isSarBullish && + conditions.decisionConditions.x121Conditions.isSarBullish && + conditions.analyseConditions.x121Conditions.isSarBullish && + conditions.verificationConditions.x121Conditions.isSarBullish && + conditions.consolidationConditions.x121Conditions.isSarBullish + // + ; + + // + isBearish = + // + // All Cycles Sars Must be Directional exept Vision ... + conditions.triggerConditions.x121Conditions.isSarBearish && + conditions.decisionConditions.x121Conditions.isSarBearish && + conditions.analyseConditions.x121Conditions.isSarBearish && + conditions.verificationConditions.x121Conditions.isSarBearish && + conditions.consolidationConditions.x121Conditions.isSarBearish + // + ; + } + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + /** + * Detect Sar State for Signalling ... + * + * @param forProvider: ENUM_X_121_SMC_PROVIDERS member ... + * @param dir: ENUM_X_DIRECTION member Reference ... + * @param conditions: X121SMCStrategyConditions instance, Reference ... + * + * @return ( bool ) + */ + bool DetectVWapState( + ENUM_X_121_SMC_PROVIDERS forProvider, + ENUM_X_DIRECTION &dir, + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + bool isBullish = false; + bool isBearish = false; + + // + if (forProvider == X_121_SMC_PROVIDER_SMPV) + { + // + isBullish = + // + // Trigger, Decision and Analyse Cycles Must be in Direction Order and State ... + // + // Orders ... + (conditions.triggerConditions.x121Conditions.isVWapBullishOrdered && + conditions.decisionConditions.x121Conditions.isVWapBullishOrdered && + conditions.analyseConditions.x121Conditions.isVWapBullishOrdered) + // + && + // + // State ... + (conditions.triggerConditions.x121Conditions.isVWapBullishState && + conditions.decisionConditions.x121Conditions.isVWapBullishState && + conditions.analyseConditions.x121Conditions.isVWapBullishState) + // + && + // + // One of Verification and Consolidation must Be in Direction State ... + (conditions.verificationConditions.x121Conditions.isVWapBullishState || + conditions.consolidationConditions.x121Conditions.isVWapBullishState) + // + ; + + // + isBearish = + // + // Trigger, Decision and Analyse Cycles Must be in Direction Order and State ... + // + // Orders ... + (conditions.triggerConditions.x121Conditions.isVWapBearishOrdered && + conditions.decisionConditions.x121Conditions.isVWapBearishOrdered && + conditions.analyseConditions.x121Conditions.isVWapBearishOrdered) + // + && + // + // State ... + (conditions.triggerConditions.x121Conditions.isVWapBearishState && + conditions.decisionConditions.x121Conditions.isVWapBearishState && + conditions.analyseConditions.x121Conditions.isVWapBearishState) + // + && + // + // One of Verification and Consolidation must Be in Direction State ... + (conditions.verificationConditions.x121Conditions.isVWapBearishState || + conditions.consolidationConditions.x121Conditions.isVWapBearishState) + // + ; + } + + // + if (forProvider == X_121_SMC_PROVIDER_VWAPC) + { + // + isBullish = + // + // All Cycles Must be State and Ordered Directional Except Vision ... + // State ... + conditions.triggerConditions.x121Conditions.isVWapBullishState && + conditions.decisionConditions.x121Conditions.isVWapBullishState && + conditions.analyseConditions.x121Conditions.isVWapBullishState && + conditions.verificationConditions.x121Conditions.isVWapBullishState && + conditions.consolidationConditions.x121Conditions.isVWapBullishState + // + && + // Order ... + conditions.triggerConditions.x121Conditions.isVWapBullishOrdered && + conditions.decisionConditions.x121Conditions.isVWapBullishOrdered && + conditions.analyseConditions.x121Conditions.isVWapBullishOrdered && + conditions.verificationConditions.x121Conditions.isVWapBullishOrdered && + conditions.consolidationConditions.x121Conditions.isVWapBullishOrdered + // + ; + + // + isBearish = + // + // All Cycles Must be State and Ordered Directional Except Vision ... + // State ... + conditions.triggerConditions.x121Conditions.isVWapBearishState && + conditions.decisionConditions.x121Conditions.isVWapBearishState && + conditions.analyseConditions.x121Conditions.isVWapBearishState && + conditions.verificationConditions.x121Conditions.isVWapBearishState && + conditions.consolidationConditions.x121Conditions.isVWapBearishState + // + && + // Order ... + conditions.triggerConditions.x121Conditions.isVWapBearishOrdered && + conditions.decisionConditions.x121Conditions.isVWapBearishOrdered && + conditions.analyseConditions.x121Conditions.isVWapBearishOrdered && + conditions.verificationConditions.x121Conditions.isVWapBearishOrdered && + conditions.consolidationConditions.x121Conditions.isVWapBearishOrdered + // + ; + } + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + /** + * Detect Candlestic Patters for Signalling ... + * + * @param forProvider: ENUM_X_121_SMC_PROVIDERS member ... + * @param dir: ENUM_X_DIRECTION member Reference ... + * @param conditions: X121SMCStrategyConditions instance, Reference ... + * + * @return ( bool ) + */ + bool DetectCandlestic( + ENUM_X_121_SMC_PROVIDERS forProvider, + ENUM_X_DIRECTION &dir, + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + int cIndex = 1; + int pIndex = cIndex + 1; + + // + // Select Specified Cycle Helper ... + XC121SMCCycleHelper *cycleHelper = mTriggerCycleHelper; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = cycleHelper.GetPeriod(); + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + // Momentum Bar ... + ENUM_X_DIRECTION cBarMomentumDir; + bool isCBarMomentum = cycleHelper.mBarAnalyser.IsMomentumBar( + cBar, + cBarMomentumDir // + ); + + // + // Rejection Bar ... + ENUM_X_DIRECTION cBarRejectionDir; + bool isCBarRejection = cycleHelper.mBarAnalyser.IsRejectionBar( + cBar, + cBarRejectionDir // + ); + + // + // Engulf Bar ... + ENUM_X_DIRECTION cBarEngulfDir; + bool isCBarEngulf = cycleHelper.mBarAnalyser.IsEngulfBar( + cBar, + cBarEngulfDir // + ); + + // + // Pin Bar ... + ENUM_X_DIRECTION cBarPinDir; + bool isCBarPin = cycleHelper.mBarAnalyser.IsPinBar( + cBar, + cBarPinDir // + ); + + // + XOHCL pBar; + result = pBar.Init( + symbol, + period, + pIndex // + ); + if (!result) + { + return result; + } + + // + // Momentum Bar ... + ENUM_X_DIRECTION pBarMomentumDir; + bool isPBarMomentum = cycleHelper.mBarAnalyser.IsMomentumBar( + pBar, + pBarMomentumDir // + ); + + // + // Rejection Bar ... + ENUM_X_DIRECTION pBarRejectionDir; + bool isPBarRejection = cycleHelper.mBarAnalyser.IsRejectionBar( + pBar, + pBarRejectionDir // + ); + + // + // Engulf Bar ... + ENUM_X_DIRECTION pBarEngulfDir; + bool isPBarEngulf = cycleHelper.mBarAnalyser.IsEngulfBar( + pBar, + pBarEngulfDir // + ); + + // + // Pin Bar ... + ENUM_X_DIRECTION pBarPinDir; + bool isPBarPin = cycleHelper.mBarAnalyser.IsPinBar( + pBar, + pBarPinDir // + ); + + // + bool isBullish = false; + bool isBearish = false; + + // + if (forProvider == X_121_SMC_PROVIDER_VWAPC) + { + // + isBullish = + // + // pBar is Pin and cBar is Momentum or Rejection or Engulf + ( + // + (isPBarPin && + IsBullish(pBarPinDir) && + ( + // + (isCBarMomentum && + IsBullish(cBarMomentumDir)) + // + || + // + (isCBarRejection && + IsBullish(cBarRejectionDir)) + // + || + // + (isCBarEngulf && + IsBullish(cBarEngulfDir)) + // + ) + // + ) + // + || + // + // pBar is Engulf and cBar is Momentum or Rejection or Pin ... + (isPBarEngulf && + IsBullish(pBarEngulfDir) && + ( + // + (isCBarMomentum && + IsBullish(cBarMomentumDir)) + // + || + // + (isCBarRejection && + IsBullish(cBarRejectionDir)) + // + || + // + (isCBarPin && + IsBullish(cBarPinDir)) + // + ) + // + ) + // + || + // + // pBar is Rejection and cBar is Momentum or Engulf or Pin ... + (isPBarRejection && + IsBullish(pBarRejectionDir) && + ( + // + (isCBarMomentum && + IsBullish(cBarMomentumDir)) + // + || + // + (isCBarEngulf && + IsBullish(cBarEngulfDir)) + // + || + // + (isCBarPin && + IsBullish(cBarPinDir)) + // + ) + // + ) + // + || + // + // pBar is Momentum and cBar is Rejection or Engulf or Pin ... + (isPBarMomentum && + IsBullish(pBarMomentumDir) && + ( + // + (isCBarRejection && + IsBullish(cBarRejectionDir)) + // + || + // + (isCBarEngulf && + IsBullish(cBarEngulfDir)) + // + || + // + (isCBarPin && + IsBullish(cBarPinDir)) + // + ) + // + ) + // + || + // + // cBar is Pin and Momentum and Rejection and Engulf ... + ( + // + (isCBarPin && + IsBullish(cBarPinDir)) + // + && + // + (isCBarMomentum && + IsBullish(cBarMomentumDir)) + // + && + // + (isCBarRejection && + IsBullish(cBarRejectionDir)) + // + && + // + (isCBarEngulf && + IsBullish(cBarEngulfDir)) + // + ) + // + ) + // + ; + + // + isBearish = + // + // pBar is Pin and cBar is Momentum or Rejection or Engulf + ( + // + (isPBarPin && + IsBearish(pBarPinDir) && + ( + // + (isCBarMomentum && + IsBearish(cBarMomentumDir)) + // + || + // + (isCBarRejection && + IsBearish(cBarRejectionDir)) + // + || + // + (isCBarEngulf && + IsBearish(cBarEngulfDir)) + // + ) + // + ) + // + || + // + // pBar is Engulf and cBar is Momentum or Rejection or Pin ... + (isPBarEngulf && + IsBearish(pBarEngulfDir) && + ( + // + (isCBarMomentum && + IsBearish(cBarMomentumDir)) + // + || + // + (isCBarRejection && + IsBearish(cBarRejectionDir)) + // + || + // + (isCBarPin && + IsBearish(cBarPinDir)) + // + ) + // + ) + // + || + // + // pBar is Rejection and cBar is Momentum or Engulf or Pin ... + (isPBarRejection && + IsBearish(pBarRejectionDir) && + ( + // + (isCBarMomentum && + IsBearish(cBarMomentumDir)) + // + || + // + (isCBarEngulf && + IsBearish(cBarEngulfDir)) + // + || + // + (isCBarPin && + IsBearish(cBarPinDir)) + // + ) + // + ) + // + || + // + // pBar is Momentum and cBar is Rejection or Engulf or Pin ... + (isPBarMomentum && + IsBearish(pBarMomentumDir) && + ( + // + (isCBarRejection && + IsBearish(cBarRejectionDir)) + // + || + // + (isCBarEngulf && + IsBearish(cBarEngulfDir)) + // + || + // + (isCBarPin && + IsBearish(cBarPinDir)) + // + ) + // + ) + // + || + // + // cBar is Pin and Momentum and Rejection and Engulf ... + ( + // + (isCBarPin && + IsBearish(cBarPinDir)) + // + && + // + (isCBarMomentum && + IsBearish(cBarMomentumDir)) + // + && + // + (isCBarRejection && + IsBearish(cBarRejectionDir)) + // + && + // + (isCBarEngulf && + IsBearish(cBarEngulfDir)) + // + ) + // + ) + // + ; + } + + // + if (forProvider == X_121_SMC_PROVIDER_RJBPV) + { + // + isBullish = + // + // CBar is Pin, Engulf, Momentum or Rejection ... + ( + // // + // (isCBarMomentum && + // IsBullish(cBarMomentumDir)) + // // + // || + // // + (isCBarRejection && + IsBullish(cBarRejectionDir)) + // // + // || + // // + // (isCBarEngulf && + // IsBullish(cBarEngulfDir)) + // + || + // + (isCBarPin && + IsBullish(cBarPinDir)) + // + ) + // + ; + + // + isBearish = + // + // CBar is Pin, Engulf, Momentum or Rejection ... + ( + // + // (isCBarMomentum && + // IsBearish(cBarMomentumDir)) + // // + // || + // // + (isCBarRejection && + IsBearish(cBarRejectionDir)) + // // + // || + // // + // (isCBarEngulf && + // IsBearish(cBarEngulfDir)) + // + || + // + (isCBarPin && + IsBearish(cBarPinDir)) + // + ) + // + ; + } + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + +//////////////////////////////////////////////////////////////////////////////////// + + // + // TODO: Remove this ... + XSMCStrategySetupConditions mTestConditions; + bool DetectTestSignal( + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + ENUM_X_121_SMC_PROVIDERS provider = X_121_SMC_PROVIDER_SMPV; + string providerStr = ToString(provider); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + + // + double ll = cBar.FindLowest(9, MODE_LOW); + double hh = cBar.FindHighest(9, MODE_HIGH); + + // + double selectedSL = 0; + + // + // Retrieve Peak and Vale ... + double triggerPeak = conditions.triggerConditions.x121Conditions.peaksBuffer[0]; + double triggerVale = conditions.triggerConditions.x121Conditions.valesBuffer[0]; + + // + X121SMCCycleConditions triggerConditions = conditions.triggerConditions; + X121SMCCycleConditions decisionConditions = conditions.decisionConditions; + X121SMCCycleConditions analyseConditions = conditions.analyseConditions; + X121SMCCycleConditions verificationConditions = conditions.verificationConditions; + X121SMCCycleConditions consolidationConditions = conditions.consolidationConditions; + X121SMCCycleConditions visionConditions = conditions.visionConditions; + + // + XPOIState triggerState = triggerConditions.state; + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState verificationState = verificationConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + int zoneValidationDivider = 10; + int validPivotRepetition = mTriggerCycleHelper.mX121Helper + .GetDonChainLength(); + + // + // Waits For Bullish Or Bearish Order Block Forms ... + bool hasBullishOB = mTestConditions.HasBullishOrderBlock(); + bool hasBearishOB = mTestConditions.HasBearishOrderBlock(); + result = mTestConditions.HasOrderBlock(); + if (!result) + { + // + // Try to Detect Order Blocks ... + XPOIState state = consolidationState; + + // + // Bullish ... + if (!hasBullishOB) + { + // + // Bullish ... + int bullishOBsCount = state.CountBullishOrderBlocks(); + if (IsValidSize(bullishOBsCount)) + { + // + XCFVG *fvg = NULL; + XCOrderBlock *ob = NULL; + XCOrderBlock *bullishOBs[]; + for (int i = 0; i < bullishOBsCount; i++) + { + // + XCOrderBlock *iZone = state.bullishOrderBlocks[i]; + + // + bool isValid = cBar.low > iZone.Upper() && + HasValidBullishFVG( + analyseState, + iZone, + fvg, + cBar // + ); + if (isValid) + { + // + Add( + iZone, + bullishOBs // + ); + } + } + + // + bullishOBsCount = ArraySize(bullishOBs); + if (IsValidSize(bullishOBsCount)) + { + // + for (int i = 0; i < bullishOBsCount; i++) + { + // + XCOrderBlock *iZone = bullishOBs[i]; + + // + bool isValid = ob == NULL + ? true + : ob.Upper() < iZone.Upper(); + if (isValid) + { + ob = iZone; + } + } + } + + // + if ( + ob != NULL && + fvg != NULL && + ob.IsValid() && + fvg.IsValid()) + { + // + mTestConditions.bullishFVG = fvg; + mTestConditions.bullishFVGTime = cTime; + mTestConditions.bullishOrderBlock = ob; + mTestConditions.bullishOrderBlockTime = cTime; + } + } + } + + // + // Bearish ... + if (!hasBearishOB) + { + // + // Bearish ... + int bearishOBsCount = state.CountBearishOrderBlocks(); + if (IsValidSize(bearishOBsCount)) + { + // + XCFVG *fvg = NULL; + XCOrderBlock *ob = NULL; + XCOrderBlock *bearishOBs[]; + for (int i = 0; i < bearishOBsCount; i++) + { + // + XCOrderBlock *iZone = state.bearishOrderBlocks[i]; + + // + bool isValid = cBar.high < iZone.Lower() && + HasValidBearishFVG( + analyseState, + iZone, + fvg, + cBar // + ); + if (isValid) + { + // + Add( + iZone, + bearishOBs // + ); + } + } + + // + bearishOBsCount = ArraySize(bearishOBs); + if (IsValidSize(bearishOBsCount)) + { + // + for (int i = 0; i < bearishOBsCount; i++) + { + // + XCOrderBlock *iZone = bearishOBs[i]; + + // + bool isValid = ob == NULL + ? true + : ob.Lower() > iZone.Lower(); + if (isValid) + { + ob = iZone; + } + } + } + + // + if ( + ob != NULL && + fvg != NULL && + ob.IsValid() && + fvg.IsValid()) + { + // + mTestConditions.bearishFVG = fvg; + mTestConditions.bearishFVGTime = cTime; + mTestConditions.bearishOrderBlock = ob; + mTestConditions.bearishOrderBlockTime = cTime; + } + } + } + + // + hasBullishOB = mTestConditions.HasBullishOrderBlock(); + hasBearishOB = mTestConditions.HasBearishOrderBlock(); + result = mTestConditions.HasOrderBlock(); + if (!result) + { + return result; + } + } + + // + // Renew and Draw Order Blocks ... + + // + if (hasBullishOB) + { + // + mTestConditions.bullishFVG.To(cTime); + mTestConditions.bullishOrderBlock.To(cTime); + + // + XCBullishOrderBlockObject *iOBObj; + bool isCreated = mPOIDrawer.CreateBullishOrderBlock( + mTestConditions.bullishOrderBlock, + iOBObj // + ); + if (isCreated) + { + // + iOBObj.ZoneWidth(4); + iOBObj.ZoneColor(clrAqua); + + // + AddObjectIfNotExists(iOBObj); + } + + // + XCBullishFairValueGapObject *iFVGObj; + isCreated = mPOIDrawer.CreateBullishFairValueGap( + mTestConditions.bullishFVG, + iFVGObj // + ); + if (isCreated) + { + // + iFVGObj.ZoneWidth(4); + + // + AddObjectIfNotExists(iFVGObj); + } + } + + // + if (hasBearishOB) + { + // + mTestConditions.bearishFVG.To(cTime); + mTestConditions.bearishOrderBlock.To(cTime); + + // + XCBearishOrderBlockObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishOrderBlock( + mTestConditions.bearishOrderBlock, + iObj // + ); + if (isCreated) + { + // + iObj.ZoneWidth(4); + iObj.ZoneColor(clrMagenta); + + // + AddObjectIfNotExists(iObj); + } + + // + XCBearishFairValueGapObject *iFVGObj; + isCreated = mPOIDrawer.CreateBearishFairValueGap( + mTestConditions.bearishFVG, + iFVGObj // + ); + if (isCreated) + { + // + iFVGObj.ZoneWidth(4); + + // + AddObjectIfNotExists(iFVGObj); + } + } + + // + // Here we Make Sure we Have Valid Order Blocks ... + // we have to Validate Order Block Attacks ... + bool isBullishOBAttacked = mTestConditions.isBullishOrderBlockAttacked; + bool isBearishOBAttacked = mTestConditions.isBearishOrderBlockAttacked; + result = mTestConditions.IsOrderBlockAttacked(); + if (!result) + { + // + // Detect Order Blocks Attack ... + + // + // Bullish Order Block ... + XCOrderBlock *bullishOb = mTestConditions.bullishOrderBlock; + isBullishOBAttacked = + // + bullishOb.IsValid() && + cBar.high <= bullishOb.Upper() && + cBar.low >= bullishOb.Lower() + // + ; + if (!isBullishOBAttacked) + { + // + // Try to Reset Bullish Ob if Needed ... + int timePassed = (int)cTime - (int)mTestConditions.bullishOrderBlockTime; + int barsPassed = timePassed / PeriodSeconds(period); + bool canReset = barsPassed >= validPivotRepetition * 10; + if (canReset) + { + // + ClearDraws(); + mTestConditions.ResetBullishOrderBlock(); + } + } + + // + // Bearish Order Block ... + XCOrderBlock *bearishOb = mTestConditions.bearishOrderBlock; + isBearishOBAttacked = + // + bearishOb.IsValid() && + cBar.high <= bearishOb.Upper() && + cBar.low >= bearishOb.Lower() + // + ; + if (!isBearishOBAttacked) + { + // + // Try to Reset Bullish Ob if Needed ... + int timePassed = (int)cTime - (int)mTestConditions.bearishOrderBlockTime; + int barsPassed = timePassed / PeriodSeconds(period); + bool canReset = barsPassed >= validPivotRepetition * 10; + if (canReset) + { + // + ClearDraws(); + mTestConditions.ResetBearishOrderBlock(); + } + } + + // + bool isOrderBlockAttacked = isBullishOBAttacked || + isBearishOBAttacked; + if (isOrderBlockAttacked) + { + // + if (isBullishOBAttacked) + { + mTestConditions.isBullishOrderBlockAttacked = isBullishOBAttacked; + } + + // + if (isBearishOBAttacked) + { + mTestConditions.isBearishOrderBlockAttacked = isBearishOBAttacked; + } + } + + // + result = mTestConditions.IsOrderBlockAttacked(); + if (!result) + { + return result; + } + } + + // + // Detect Analyse State FVG ... + + // + // here We Make Sure Order Block is ttacked Before ... + // Loockup For Zone Break ... + bool isBullishOrderBlockBreaked = false; + bool isBearishOrderBlockBreaked = false; + if (isBullishOBAttacked) + { + // + isBullishOrderBlockBreaked = + // + mTestConditions.HasBullishOrderBlock() + // + && + // + ( + // + // Break From Bottom to Top ... + (ll < mTestConditions.bullishOrderBlock.Upper() && + hh > mTestConditions.bullishOrderBlock.Upper()) + // + || + // + // Break From Top to Bottom ... + (hh > mTestConditions.bullishOrderBlock.Lower() && + ll < mTestConditions.bullishOrderBlock.Lower()) + // + ) + // + ; + } + if (isBearishOBAttacked) + { + // + isBearishOrderBlockBreaked = + // + mTestConditions.HasBearishOrderBlock() + // + && + // + ( + // + // Break From Bottom to Top ... + (ll < mTestConditions.bearishOrderBlock.Upper() && + hh > mTestConditions.bearishOrderBlock.Upper()) + // + || + // + // Break From Top to Bottom ... + (hh > mTestConditions.bearishOrderBlock.Lower() && + ll < mTestConditions.bearishOrderBlock.Lower()) + // + ) + // + ; + } + + // + bool isOrderBlockBreaked = isBullishOrderBlockBreaked || + isBearishOrderBlockBreaked; + if (isOrderBlockBreaked) + { + // + // Clean Order Block ... + + // + if (isBullishOrderBlockBreaked) + { + // + ClearDraws(); + mTestConditions.ResetBullishOrderBlock(); + } + + // + if (isBearishOrderBlockBreaked) + { + // + ClearDraws(); + mTestConditions.ResetBearishOrderBlock(); + } + } + result = !isOrderBlockBreaked; + if (!result) + { + return result; + } + + // + // Try to Getting Setup Conditions ... + + // + // Check Setting Upped ... + result = mTestConditions.IsSetuped(); + if (!result) + { + return result; + } + + // + // Try To Detect Trigger Conditions ... + + // + // Check Conditions is Prepared for Trigger ... + result = mTestConditions.CanTrigger(); + if (!result) + { + return result; + } + + // + // Issues Signal on Conditions ... + conditions.signalDir = mTestConditions.dir; + conditions.provider = providerStr; + conditions.sl = mTestConditions.sl; + + // + mTestConditions.Clean(); + + // + return result; + } + + // + // Helper Functions ... + + /** + * Detect Valid Order Block's FVG ... + * + * @return ( bool ) + */ + bool HasValidBullishFVG( + XPOIState &state, + XCOrderBlock *ob, + XCFVG *&fvg, + XOHCL &bar // + ) + { + // + bool result = false; + + // + fvg = NULL; + + // + // Validate ... + result = + // + ob != NULL && + bar.IsValid() && + state.IsValid() && + ob.IsBullish() && + state.HasChild() + // + ; + if (!result) + { + return result; + } + + // + // Counting FVGs ... + int count = state.CountBullishFairValueGaps(); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iFVG = state.bullishFairValueGaps[i]; + + // + bool isValid = + // + // Must be Happens After Order Block ... + iFVG.From() > ob.From() + // + && + // + // Must Happens Inside or Boundary of Order Blocks ... + iFVG.Lower() > ob.Lower() && + iFVG.Lower() < ob.Upper() + // + // && + // + // Must Not Touched till bar ... + // + ; + if (isValid) + { + // + bool canSet = fvg == NULL; + if (canSet) + { + // + fvg = iFVG; + break; + } + } + } + + // + return result; + } + + /** + * Detect Valid Order Block's FVG ... + * + * @return ( bool ) + */ + bool HasValidBearishFVG( + XPOIState &state, + XCOrderBlock *ob, + XCFVG *&fvg, + XOHCL &bar // + ) + { + // + bool result = false; + + // + fvg = NULL; + + // + // Validate ... + result = + // + ob != NULL && + bar.IsValid() && + state.IsValid() && + ob.IsBearish() && + state.HasChild() + // + ; + if (!result) + { + return result; + } + + // + // Counting FVGs ... + int count = state.CountBearishFairValueGaps(); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iFVG = state.bearishFairValueGaps[i]; + + // + bool isValid = + // + // Must be Happens After Order Block ... + iFVG.From() > ob.From() + // + && + // + // Must Happens Inside or Boundary of Order Blocks ... + iFVG.Upper() < ob.Upper() && + iFVG.Upper() > ob.Lower() + // + // && + // + // Must Not Touched till bar ... + // + ; + if (isValid) + { + // + bool canSet = fvg == NULL; + if (canSet) + { + // + fvg = iFVG; + break; + } + } + } + + // + return result; + } + +struct XSMCStrategySetupConditions +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double sl; + ENUM_X_DIRECTION dir; + ENUM_X_POSITION_TYPES type; + + // + // Setup Props ... + + // + datetime setupTime; + datetime triggerTime; + + // + datetime bullishOrderBlockTime; + XCOrderBlock *bullishOrderBlock; + bool isBullishOrderBlockAttacked; + + // + datetime bearishOrderBlockTime; + XCOrderBlock *bearishOrderBlock; + bool isBearishOrderBlockAttacked; + + // + datetime bullishFVGTime; + XCFVG *bullishFVG; + bool isBullishFVGRejected; + + // + datetime bearishFVGTime; + XCFVG *bearishFVG; + bool isBearishFVGRejected; + + // + XPVPivotPoint validPeak; + XPVPivotPoint validVale; + + // + // Trigger Props ... + + // + // Constructor ... + XSMCStrategySetupConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + sl = 0; + + // + dir = X_DIRECTION_NONE; + type = X_POSITION_TYPE_NONE; + + // + symbol = NULL; + period = NULL; + setupTime = NULL; + triggerTime = NULL; + + // + validPeak.Clean(); + validVale.Clean(); + + // + bullishOrderBlock = NULL; + bearishOrderBlock = NULL; + bullishOrderBlockTime = NULL; + bearishOrderBlockTime = NULL; + + // + bullishFVG = NULL; + bullishFVGTime = NULL; + isBullishFVGRejected = false; + + // + bearishFVG = NULL; + bearishFVGTime = NULL; + isBearishFVGRejected = false; + + // + isBullishOrderBlockAttacked = false; + isBearishOrderBlockAttacked = false; + } + + /** + * Check Condition is Setting Up ... + * + * @param dir: ENUM_X_DIRECTION member, Setting Up Direction ... + * + * @return ( bool ) + */ + bool IsSetuped() + { + // + bool result = false; + + // + result = IsValid(setupTime) && + HasDirection(dir); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Detect How we Can Trigger Signal ... + * + * @return ( bool ) + */ + bool CanTrigger() + { + // + bool result = false; + + // + result = + // + sl > 0 && + IsValid(symbol) && + IsValid(period) && + IsValid(triggerTime) && + type != X_POSITION_TYPE_ALL && + type != X_POSITION_TYPE_NONE + // + ; + + // + return result; + } + + // + // Helpers ... + + // + // Order Block ... + + /** + * Check has Order Block ... + * + * @return ( bool ) + */ + bool HasOrderBlock() + { + // + bool result = false; + + // + result = HasBullishOrderBlock() && + HasBearishOrderBlock(); + + // + return result; + } + + bool HasBullishOrderBlock() + { + // + bool result = false; + + // + result = + // + (bullishOrderBlock != NULL && + bullishOrderBlock.IsValid()) + // + ; + + // + return result; + } + + bool HasBearishOrderBlock() + { + // + bool result = false; + + // + result = + // + (bearishOrderBlock != NULL && + bearishOrderBlock.IsValid()) + // + ; + + // + return result; + } + + bool IsOrderBlockAttacked() + { + // + bool result = isBullishOrderBlockAttacked || + isBearishOrderBlockAttacked; + + // + return result; + } + + void ResetBullishOrderBlock() + { + // + bullishOrderBlock = NULL; + bullishOrderBlockTime = NULL; + isBullishOrderBlockAttacked = false; + } + + void ResetBearishOrderBlock() + { + // + bearishOrderBlock = NULL; + bearishOrderBlockTime = NULL; + isBearishOrderBlockAttacked = false; + } + + bool HasFVG() + { + // + bool result = false; + + // + result = HasBullishFVG() || + HasBearishFVG(); + + // + return result; + } + + bool HasBullishFVG() + { + // + bool result = false; + + // + result = IsValid(bullishFVGTime) && + bullishFVG != NULL && + bullishFVG.IsValid(); + + // + return result; + } + + bool HasBearishFVG() + { + // + bool result = false; + + // + result = IsValid(bearishFVGTime) && + bearishFVG != NULL && + bearishFVG.IsValid(); + + // + return result; + } + + // +}; + +////////////////////////////////////////////////////////////////////////////////// + + + // + // TODO: Remove this ... + XSMCStrategySetupConditions mTestConditions; + bool DetectTestSignal( + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + ENUM_X_121_SMC_PROVIDERS provider = X_121_SMC_PROVIDER_SMPV; + string providerStr = ToString(provider); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + + // + double ll = cBar.FindLowest(9, MODE_LOW); + double hh = cBar.FindHighest(9, MODE_HIGH); + + // + double selectedSL = 0; + + // + X121SMCCycleConditions triggerConditions = conditions.triggerConditions; + X121SMCCycleConditions decisionConditions = conditions.decisionConditions; + X121SMCCycleConditions analyseConditions = conditions.analyseConditions; + X121SMCCycleConditions verificationConditions = conditions.verificationConditions; + X121SMCCycleConditions consolidationConditions = conditions.consolidationConditions; + X121SMCCycleConditions visionConditions = conditions.visionConditions; + + // + XPOIState triggerState = triggerConditions.state; + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState verificationState = verificationConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + // Retrieve Peak and Vale ... + double triggerPeak = triggerConditions.x121Conditions.peaksBuffer[0]; + double triggerVale = triggerConditions.x121Conditions.valesBuffer[0]; + + // + int zoneValidationDivider = 10; + int validPivotRepetition = mTriggerCycleHelper.mX121Helper + .GetDonChainLength(); + + // + bool hasZone = false; + XPVPivotPoint validPeak; + XPVPivotPoint validVale; + bool canTrigger = false; + bool hasValidPeak = false; + bool hasValidVale = false; + datetime setupTime = NULL; + bool isZoneBreaked = false; + bool hasConsolidation = false; + XConsolidationZone lastConsolidation; + + // + setupTime = mTestConditions.setupTime; + bool isSetuped = mTestConditions.IsSetuped(); + ENUM_X_DIRECTION setupDir = mTestConditions.dir; + if (!isSetuped) + { + // + // Detect Valid Peaks and Vales ... + + // + // Peaks ... + validPeak = mTestConditions.validPeak; + hasValidPeak = validPeak.IsValid(); + if (!hasValidPeak) + { + // + // Detecte Valid Peaks ... + + // + XPVPivotPoint triggerValidPeaks[]; + int triggerValidPeaksCount = mTriggerCycleHelper + .FillPeakPivotPoints(triggerValidPeaks); + + // + bool isValid = + IsValidSize(triggerValidPeaksCount); + if (isValid) + { + // + // Try to Find ... + for (int i = triggerValidPeaksCount - 1; i >= 0; i--) + { + // + XPVPivotPoint iPivot = triggerValidPeaks[i]; + double iValue = iPivot.value; + + // + bool isValid = // iValue == triggerConditions.x121Conditions.peaksBuffer[0] && + iValue == decisionConditions.x121Conditions.peaksBuffer[0] && + iValue == analyseConditions.x121Conditions.peaksBuffer[0] && + iValue == verificationConditions.x121Conditions.peaksBuffer[0]; + if (isValid) + { + // + validPeak = iPivot; + break; + } + } + + // + hasValidPeak = validPeak.IsValid(); + if (hasValidPeak) + { + // + mTestConditions.validPeak = validPeak; + + // + if (!mTestConditions.validVale.IsValid()) + { + // + XValueChange valesChanges[]; + int valeChangesCount = mTriggerCycleHelper.FillValesChanges(valesChanges); + if (IsValidSize(valeChangesCount)) + { + // + XValueChange lastChange = valesChanges[valeChangesCount - 1]; + if (lastChange.IsValid()) + { + // + XPVPivotPoint iPivot; + iPivot.repetition = 1; + iPivot.type = XPV_VALE; + iPivot.time = lastChange.time; + iPivot.value = lastChange.after; + if (iPivot.IsValid()) + { + mTestConditions.validVale = iPivot; + } + } + } + } + } + } + } + + // + // Vales ... + validVale = mTestConditions.validVale; + hasValidVale = validVale.IsValid(); + if (!hasValidVale) + { + // + // Detecte Valid Vale ... + + // + XPVPivotPoint triggerValidVales[]; + int triggerValidValesCount = mTriggerCycleHelper + .FillValePivotPoints(triggerValidVales); + + // + bool isValid = + IsValidSize(triggerValidValesCount); + if (isValid) + { + // + // Try to Find ... + for (int i = triggerValidValesCount - 1; i >= 0; i--) + { + // + XPVPivotPoint iPivot = triggerValidVales[i]; + double iValue = iPivot.value; + + // + bool isValid = // iValue == triggerConditions.x121Conditions.valesBuffer[0] && + iValue == decisionConditions.x121Conditions.valesBuffer[0] && + iValue == analyseConditions.x121Conditions.valesBuffer[0] && + iValue == verificationConditions.x121Conditions.valesBuffer[0]; + if (isValid) + { + // + validVale = iPivot; + break; + } + } + + // + hasValidVale = validVale.IsValid(); + if (hasValidVale) + { + // + mTestConditions.validVale = validVale; + + // + if (!mTestConditions.validPeak.IsValid()) + { + // + XValueChange valesChanges[]; + int valeChangesCount = mTriggerCycleHelper.FillPeaksChanges(valesChanges); + if (IsValidSize(valeChangesCount)) + { + // + XValueChange lastChange = valesChanges[valeChangesCount - 1]; + if (lastChange.IsValid()) + { + // + XPVPivotPoint iPivot; + iPivot.repetition = 1; + iPivot.type = XPV_PEAK; + iPivot.time = lastChange.time; + iPivot.value = lastChange.after; + if (iPivot.IsValid()) + { + mTestConditions.validPeak = iPivot; + } + } + } + } + } + } + } + bool hasValidPivot = hasValidPeak && + hasValidVale; + result = hasValidPivot; + if (!result) + { + return result; + } + + // + mTestConditions.peak = triggerPeak; + mTestConditions.vale = triggerVale; + + // + // We Sure we Have Valid Peak and Valid Vale ... + // Create a Zone ... + hasZone = mTestConditions.zone.IsValid(); + if (!hasZone) + { + // + double pvZoneUpper = validPeak.value; + double pvZoneLower = validVale.value; + datetime pvZoneFrom = + validPeak.time < validVale.time + ? validPeak.time + : validVale.time; + int pvZoneLoopback = iBarShift( + symbol, + period, + pvZoneFrom // + ); + + // + XConsolidationZone pvZone; + result = pvZone.Init( + symbol, + period, + pvZoneUpper, + pvZoneLower, + pvZoneLoopback // + ); + if (!result) + { + return result; + } + + // + mTestConditions.zone = pvZone; + hasZone = mTestConditions.zone.IsValid(); + } + if (hasZone) + { + // + // Update Zone ... + mTestConditions.UpdateZone(); + + // + XCConsolidationZoneObject *iPVZoneObj; + iPVZoneObj = new XCConsolidationZoneObject(); + bool isCreated = iPVZoneObj.Create( + mPOIDrawer.ChartIdentification(), + mPOIDrawer.SubWindowIdentification(), + mTestConditions.zone // + ); + if (isCreated) + { + // + iPVZoneObj.ZoneWidth(4); + iPVZoneObj.ZoneColor(clrGold); + + // + AddObjectIfNotExists(iPVZoneObj); + } + } + + // + // Here we Have to Check Price Go into Zone ... + isZoneBreaked = mTestConditions.zone.IsBreaked(); + result = isZoneBreaked; + if (!result) + { + return result; + } + + // + isSetuped = true; + setupTime = cTime; + mTestConditions.setupTime = setupTime; + setupDir = mTestConditions.zone.breakDirection; + mTestConditions.dir = setupDir; + } + + // + // Detect Trigger Conditions ... + canTrigger = mTestConditions.CanTrigger(); + datetime triggerTime = mTestConditions.triggerTime; + if (!canTrigger) + { + // + // Detect Consolidations ... + lastConsolidation = mTestConditions.consolidation; + hasConsolidation = lastConsolidation.IsValid(); + if (!hasConsolidation) + { + // + XConsolidationZone consolidations[]; + int consolidationsCount = mTriggerCycleHelper + .FillConsolidationZones(consolidations); + if (IsValidSize(consolidationsCount)) + { + lastConsolidation = consolidations[consolidationsCount - 1]; + } + result = lastConsolidation.IsValid(); + if (!result) + { + return result; + } + XCConsolidationZoneObject *iConsolidationObj; + iConsolidationObj = new XCConsolidationZoneObject(); + bool isCreated = iConsolidationObj.Create( + mPOIDrawer.ChartIdentification(), + mPOIDrawer.SubWindowIdentification(), + lastConsolidation // + ); + if (isCreated) + { + // + iConsolidationObj.ZoneWidth(2); + iConsolidationObj.ZoneColor(clrLightBlue); + + // + AddObjectIfNotExists(iConsolidationObj); + } + + // + mTestConditions.consolidation = lastConsolidation; + hasConsolidation = mTestConditions.consolidation.IsValid(); + result = hasConsolidation; + if (!result) + { + return result; + } + } + + // + result = + // + hasConsolidation && + lastConsolidation.IsBreaked() && + lastConsolidation.breakDirection == setupDir; + if (!result) + { + // + ClearDraws(); + mTestConditions.consolidation.Clean(); + + // + return result; + } + + // + result = + setupDir == mTestConditions.zone.breakDirection && + setupDir == mTestConditions.consolidation.breakDirection; + if (!result) + { + // + // Check Trigger Consitions ... + if (cTime - setupTime > 2400) + { + // + ClearDraws(); + + // + mTestConditions.Clean(); + } + return result; + } + + // + isBullish = IsBullish(setupDir); + isBearish = IsBearish(setupDir); + result = isBullish || + isBearish; + if (!result) + { + // + // Check Trigger Consitions ... + if (cTime - setupTime > 2400) + { + // + ClearDraws(); + + // + mTestConditions.Clean(); + } + return result; + } + + // + mTestConditions.symbol = symbol; + mTestConditions.period = period; + mTestConditions.triggerTime = cTime; + mTestConditions.sl = lastConsolidation.upper; + mTestConditions.type = isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + canTrigger = mTestConditions.CanTrigger(); + triggerTime = mTestConditions.triggerTime; + result = canTrigger; + if (!result) + { + // + // Check Trigger Consitions ... + if (cTime - setupTime > 2400) + { + // + ClearDraws(); + + // + mTestConditions.Clean(); + } + + // + return result; + } + } + + // + if (cTime - setupTime > 2400) + { + // + ClearDraws(); + + // + mTestConditions.Clean(); + } + + // + Print("Trigger Time ..."); + + // + // Issues Signal on Conditions ... + // conditions.signalDir = mTestConditions.dir; + // conditions.provider = providerStr; + // conditions.sl = mTestConditions.sl; + + // + // mTestConditions.Clean(); + + // + return result; + } + + + + +// +// Custom Providers Conditions ... +struct XSMCStrategySetupConditions +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double sl; + ENUM_X_DIRECTION dir; + ENUM_X_POSITION_TYPES type; + + // + // Setup Props ... + + // + datetime setupTime; + datetime triggerTime; + XConsolidationZone zone; + XConsolidationZone consolidation; + + // + double peak; + double vale; + XPVPivotPoint validPeak; + XPVPivotPoint validVale; + + // + // Trigger Props ... + + // + // Constructor ... + XSMCStrategySetupConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + sl = 0; + + // + zone.Clean(); + consolidation.Clean(); + dir = X_DIRECTION_NONE; + type = X_POSITION_TYPE_NONE; + + // + symbol = NULL; + period = NULL; + setupTime = NULL; + triggerTime = NULL; + + // + peak = 0; + vale = 0; + validPeak.Clean(); + validVale.Clean(); + } + + /** + * Check Condition is Setting Up ... + * + * @param dir: ENUM_X_DIRECTION member, Setting Up Direction ... + * + * @return ( bool ) + */ + bool IsSetuped() + { + // + bool result = false; + + // + result = IsValid(setupTime) && + HasDirection(dir); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Detect How we Can Trigger Signal ... + * + * @return ( bool ) + */ + bool CanTrigger() + { + // + bool result = false; + + // + result = + // + sl > 0 && + IsValid(symbol) && + IsValid(period) && + IsValid(triggerTime) && + type != X_POSITION_TYPE_ALL && + type != X_POSITION_TYPE_NONE + // + ; + + // + return result; + } + + // + // Helpers ... + + void UpdateZone() + { + // + if (!zone.IsValid() || + !validPeak.IsValid() || + !validVale.IsValid()) + { + return; + } + + // + zone.upper = validPeak.value; + zone.lower = validVale.value; + + // + zone.Update(); + + // + if (consolidation.IsValid()) + { + consolidation.Update(); + } + } + + // +}; + + +/////////////////////////////////////////////////////////////////////////////////// + diff --git a/BKPS/14030923/Documents/BKP/x-121.poi.expert.class copy.ex5 b/BKPS/14030923/Documents/BKP/x-121.poi.expert.class copy.ex5 new file mode 100644 index 0000000..b509bc3 Binary files /dev/null and b/BKPS/14030923/Documents/BKP/x-121.poi.expert.class copy.ex5 differ diff --git a/BKPS/14030923/Documents/BKP/x-121.poi.expert.class copy.mq5 b/BKPS/14030923/Documents/BKP/x-121.poi.expert.class copy.mq5 new file mode 100644 index 0000000..ffb094a --- /dev/null +++ b/BKPS/14030923/Documents/BKP/x-121.poi.expert.class copy.mq5 @@ -0,0 +1,830 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XC121SMCExpert +// Description: provides all based classes for use ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-expert.class.mq5" +#include "../../Classes/x-saherelm.x-poi.class.mq5" +// #include "../Classes/x-121.smc.xtradehandler.class.mq5" + +// +// Definitions ... +string XC121SMCExpertToken = "XC121SMCEA"; + +// +// Implementation ... + +class XC121SMCExpert : public XCBaseExpert +{ + // + public: + // + + // + // Signal Event Listener ... + TOnStopLoss OnPositionSLEventListener; + TOnTakeProfit OnPositionTPEventListener; + TOnPartialClose OnPositionPartialCloseEventListener; + TOnModify OnPositionModifiedEventListener; + TOnForceClose OnPositionForceCloseEventListener; + + // + // Getter(s) / Setter(s) ... + + /** + * Get Use Dynamic Volume State ... + * + * @return ( bool ) + */ + bool UseDynamicVolume() + { + return mUseDynamicVolume; + } + + /** + * Set Use Dynamic Volume State ... + * + * @param value: Boolean ... + */ + void UseDynamicVolume(bool value) + { + mUseDynamicVolume = value; + } + + /** + * Get Increase Volume Step ... + * + * @return ( double ) + */ + double DynamicVolumeStep() + { + return mDynamicVolumeStep; + } + + /** + * Set Increase Volume Step ... + * + * @param value: Double ... + */ + void DynamicVolumeStep(double value) + { + // + if (value < 0.01) + { + value = 0.01; + } + + // + mDynamicVolumeStep = value; + } + + /** + * Get Balance Factor for Generate Dynamic Volume ... + * + * @return ( double ) + */ + double DynamicVolumeBalanceFactor() + { + return mDynamicVolumeBalanceFactor; + } + + /** + * Set Balance Factor for Generate Dynamic Volume ... + * + * @param value: Double ... + */ + void DynamicVolumeBalanceFactor(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mDynamicVolumeBalanceFactor = value; + } + + /** + * Get Static Volume ... + * + * @return ( double ) + */ + double Volume() + { + return mVolume; + } + + /** + * Set Static Volume ... + * + * @param value: Double ... + */ + void Volume(double value) + { + // + if (value < 0.01) + { + value = 0.01; + } + + // + mVolume = value; + } + + // + // Actions ... + + // + // Override Actions ... + + /** + * Apply Default Configurations ... + */ + void DefaultConfigure() override + { + // + // Commons ... + Slippage(10); + TagPrefix(""); + MagicNumber(1694056); + + // + // Symbol ... + SetSymbol(_Symbol); + SetPeriod(_Period); + MultiSymbol(false); + Symbols("EURUSDb,GBPUSDb,USDJPYb,USDCHFb,DowJones30,XAUUSDb"); + + // + // Signalling ... + Disabled(false); + AllowLong(true); + AllowShort(true); + + // + string tag = GetTag(); + + // + // Alert ... + SetAlertPrefix(tag); + SetAlertLogAlerts(true); + SetAlertPushAlerts(true); + SetAlertMailAlerts(false); + SetAlertEnableAlerts(true); + SetAlertTerminalAlerts(false); + + // + // Reports ... + ReportNewDays(true); + ReportNewWeeks(false); + ReportNewHours(false); + ReportNewMonths(false); + + // + // Volume Default Configurations ... + Volume(0.01); + UseDynamicVolume(false); + DynamicVolumeStep(0.01); + DynamicVolumeBalanceFactor(200); + } + + /** + * Vaslidate Inputs ... + * + * @return ( bool ) + */ + bool ValidateInputs() override + { + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + Slippage() > 0 && + MagicNumber() > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + // Checking Volume ... + bool isVolumeValid = true; + if (UseDynamicVolume()) + { + // + isVolumeValid = + DynamicVolumeStep() > 0 && + DynamicVolumeBalanceFactor() > 0; + if (!isVolumeValid) + { + errMessage += "Dynamic Volume configurations error;" + "\n"; + } + } + isVolumeValid = isVolumeValid && + Volume() > 0; + if (!isVolumeValid) + { + errMessage += "Static Volume configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Volume Coniguration ... + isVolumeValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + errMessage = " Errors: \n" + errMessage; + Alert(errMessage); + } + + // + return result; + } + + // + // Initializers and DeInitializers ... + + /** + * Initial EA Requirements ... + * + * @return ( bool ) + */ + bool InitEA() override + { + // + bool result = false; + + // + // Initialize Indicator Helpers ... + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + mPOIDetector = new XCPOIDetector( + symbol, + period // + ); + mPOIDetector.Init(); + + // + // Bar Timer ... + XCTInputs ctInputs; + ctInputs.Default(); // Default Configurations ... + mCTHelper = new XCXCTHelper(); + result = mCTHelper.Init( + GetSymbol(), + GetPeriod(), + ctInputs // + ); + if (!result) + { + return result; + } + + // + // Bar Styles ... + XCCInputs ccInputs; + ccInputs.Default(); // Default Configurations ... + mCCHelper = new XCXCCHelper(); + result = mCCHelper.Init( + GetSymbol(), + GetPeriod(), + ccInputs // + ); + if (!result) + { + return result; + } + + // + // Create Trader Instance and Configure it ... + mTrader = new XCTrade( + Slippage(), + MagicNumber() // + ); + mTrader.AddOnStopLossEventHandler(OnPositionSLEventListener); + mTrader.AddOnTakeProfitEventHandler(OnPositionTPEventListener); + mTrader.AddOnModifyPositionEventHandler(OnPositionModifiedEventListener); + mTrader.AddOnForceClosePositionEventHandler(OnPositionForceCloseEventListener); + mTrader.AddOnPartialClosePositionEventHandler(OnPositionPartialCloseEventListener); + + // // + // // Initialize Trade Handler ... + // mTradeHandler = new XC121SMCTradeHandler(mTrader); + // mTradeHandler.SaveTrades(true); + // mTradeHandler.SaveSignals(true); + // mTradeHandler.SaveConditions(true); + + // // + // // Configure Alerts ... + // mTradeHandler.SetAlertPrefix(GetTag()); + // mTradeHandler.SetAlertEnableAlerts(GetAlertEnableAlerts()); + // mTradeHandler.SetAlertLogAlerts(GetAlertLogAlerts()); + // mTradeHandler.SetAlertMailAlerts(GetAlertMailAlerts()); + // mTradeHandler.SetAlertPushAlerts(GetAlertPushAlerts()); + // mTradeHandler.SetAlertTerminalAlerts(GetAlertTerminalAlerts()); + + // // + // // TODO: Make This Configurable Later ... + + // // + // mTradeHandler.DelayBarBetweenTwoSignal(3); + // mTradeHandler.MaxAllowedSLToPause(0); + // mTradeHandler.MaxAllowedSLReachedPauseDelay(HoursToSeconds(24)); + + // // + // // Configure Trade Management ... + // mTradeHandler.AllowLong(AllowLong()); + // mTradeHandler.AllowShort(AllowShort()); + // mTradeHandler.MaxAllowedLongs(0); + // mTradeHandler.MaxAllowedShorts(0); + // mTradeHandler.UseMaxAllowedTradesPerSymbol(true); + // mTradeHandler.MaxDrawdownPercentForOpenTrades(5); + + // // + // // Configure Position Protector ... + + // // + // mTradeHandler.UseForceMomentumsInProtection(true); + // mTradeHandler.DelayBarBetweenTwoSignal(2); + + // // + // // Configure Hedging ... + // mTradeHandler.AllowHedge(false); + // mTradeHandler.HedgeMinVolumeStep(0.01); + // mTradeHandler.MinimumOpenPositionsForHEHedge(2); + // mTradeHandler.HedgeHEMinProfitPerVolumeStep(0.2); + // mTradeHandler.HedgeBEMinProfitPerVolumeStep(0.06); + + // // + // // In Profit Position Protecting ... + + // // + // // Trail ... + // mTradeHandler.AllowTrail(false); + // mTradeHandler.TrailStep(15); + // mTradeHandler.TrailStartDistance(30); + // mTradeHandler.OnlyTrailUnprotected(true); + // mTradeHandler.RemoveTPAfterTrailedLevel(4); + + // // + // // Partial Close (In Profit) ... + // mTradeHandler.PartialCloseInProfitDistance(0); + // mTradeHandler.PartialCloseInProfitVolume(0); + + // // + // // In Drawdown Positions Protecting ... + + // // + // // Protect ... + // mTradeHandler.AllowProtect(false); + // mTradeHandler.ProtectionDelay(20); + // mTradeHandler.MaxAllowedProtection(0); + // mTradeHandler.UseEntryAsProtectionSL(true); + // mTradeHandler.ProtectOnConditions(true); + // mTradeHandler.AllowDirectionProtct(false); + // mTradeHandler.ProtectionStartDistance(50); + // mTradeHandler.ProtectionVolumeMultiplier(2); + + // // + // // Partial Close (In Profit) ... + // mTradeHandler.PartialCloseInDrawdownDistance(0); + // mTradeHandler.PartialCloseInDrawdownVolume(0); + + // + // Parsers ... + XSymbolParser _symbolParser; + + // + // Single Symbol ... + if (!MultiSymbol()) + { + // + // Register Strategy ... + + // + // Create Class Instance ... + // XCX121SMCBaseStrategy *iX121SMCStrategy; + // iX121SMCStrategy = new XCX121SMCTestStrategy( + // _Symbol, + // _Period // + // ); + + // // + // iX121SMCStrategy.AddXSignalEventHandler(OnSignalEventListener); + + // // + // ConfigureStrategy(iX121SMCStrategy); + // RegisterStrategy(iX121SMCStrategy); + } + // + // Multi Symbol ... + else + { + // + // Parse Symbols ... + string symbols[]; + int symbolsCount = SplitContent( + symbols, + Symbols() // + ); + result = IsValidSize(symbolsCount); + if (!result) + { + return result; + } + + // + for (int i = 0; i < symbolsCount; i++) + { + // + // Select Symbol ... + string iSymbol = symbols[i]; + + // + // Register Strategy Based On Symbol ... + + // + // Parse Symbol ... + bool isEURUSD = _symbolParser.IsEURUSD(_Symbol); + bool isGBPUSD = _symbolParser.IsGBPUSD(_Symbol); + bool isEURGBP = _symbolParser.IsEURGBP(_Symbol); + bool isUSDCHF = _symbolParser.IsUSDCHF(_Symbol); + bool isEURCHF = _symbolParser.IsEURCHF(_Symbol); + bool isUSDJPY = _symbolParser.IsUSDJPY(_Symbol); + bool isEURJPY = _symbolParser.IsEURJPY(_Symbol); + bool isUSDCAD = _symbolParser.IsUSDCAD(_Symbol); + bool isEURCAD = _symbolParser.IsEURCAD(_Symbol); + bool isAUDUSD = _symbolParser.IsAUDUSD(_Symbol); + bool isEURAUD = _symbolParser.IsEURAUD(_Symbol); + bool isNZDUSD = _symbolParser.IsNZDUSD(_Symbol); + bool isEURNZD = _symbolParser.IsEURNZD(_Symbol); + + // + // Check Symbol Can Register or not ... + bool canRegisterStrategy = true; + + // + if (canRegisterStrategy) + { + // // + // // Create Class Instance ... + // XCX121SMCBaseStrategy *iX121SMCStrategy; + // iX121SMCStrategy = new XCX121SMCTestStrategy( + // iSymbol, + // _Period // + // ); + + // // + // iX121SMCStrategy.AddXSignalEventHandler(OnSignalEventListener); + + // // + // // Register Strategy ... + // ConfigureStrategy(iX121SMCStrategy); + // RegisterStrategy(iX121SMCStrategy); + } + } + } + + // + return result; + } + + /** + * Destroy all Initialized EA Requirements ... + */ + void DestroyEA() override + { + // + delete mCTHelper; + delete mCCHelper; + // delete mTradeHandler; + + // + // Clean(mStrategies); + } + + /** + * Call all Registered Strategies On Tick ... + */ + void HandleStrategiesOnTick() override + { + // + ENUM_XPOI_EVENTS events[]; + mPOIDetector.Update(events); + + // + // int count = ArraySize(mStrategies); + // if (!IsValidSize(count)) + // { + // return; + // } + + // // + // for (int i = 0; i < count; i++) + // { + // // + // // Call Tick Handler Function ... + // mStrategies[i].HandleTick(); + // } + } + + // + // Event Handlers ... + + /** + * Calls When a Position's SL Triggered ... + * + * @param deal: XDeal instance ... + */ + void HandleOnStopLossTriggered(const XDeal &deal) override + { + // + // Finish ... + // mTradeHandler.Finish(deal); + + // + HandleReportBalance(); + } + + /** + * Calls When a Position's TP Triggered ... + * + * @param deal: XDeal instance ... + */ + void HandleOnTakeProfitTriggered(const XDeal &deal) override + { + // + // Finish ... + // mTradeHandler.Finish(deal); + + // + HandleReportBalance(); + } + + /** + * Handle Force Close a Position ... + * + * @param ticket: Position Ticket ... + * @param position: XPosition ... + * @param comment: Closing Comment ... + */ + void HandleOnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // + ) override + { + // + // Finish ... + // mTradeHandler.Finish( + // ticket, + // position, + // comment // + // ); + + // + HandleReportBalance(); + } + + /** + * Reset All Paused Symbols on Each New Days ... + */ + void HandleOnNewDay() override + { + // mTradeHandler.ResumePausedSymbols(); + } + + /** + * Generate Identifier Tag ... + * + * @return ( string ) + */ + string GetTag() override + { + // + string result = NULL; + + // + string tagPrefix = TagPrefix(); + if (IsValid(tagPrefix)) + { + result = tagPrefix; + } + else + { + result = ""; + } + + // + result = + XCBaseExpertToken + result; + + // + return result; + } + + // + protected: + // + + // + // Props ... + + // + datetime mLastSignalOn; + + // + XCPOIDetector *mPOIDetector; + + // + // XC121SMCTradeHandler *mTradeHandler; // Trade Handler ... + // XCX121SMCBaseStrategy *mStrategies[]; // Registere Strategies in EA ... + + // + // Actions ... + + /** + * Apply Volume Based On Configurations on Signal ... + * + * @param signal: XSignal instance + */ + void ApplyVolumeOnSignal(XSignal &signal) + { + // + // Prepare Signal Dynamic Volume + // if Provided ... + if (UseDynamicVolume() && + DynamicVolumeStep() > 0 && + DynamicVolumeBalanceFactor() > 0) + { + // + double dVolume = mTrader.GetDynamicVolume( + signal.symbol, + DynamicVolumeBalanceFactor(), + DynamicVolumeStep() // + ); + + // + if (dVolume > 0) + { + signal.volume = dVolume; + } + else + { + signal.volume = Volume(); + } + } + else + { + signal.volume = Volume(); + } + + // + // mTradeHandler.UpdateSignal(signal); + } + + /** + * Configure Startegy ... + */ + // void ConfigureStrategy(XCX121SMCBaseStrategy *&strategy) + // { + // // + // if (strategy == NULL) + // { + // return; + // } + + // // + // // Configure Alerts ... + // strategy.SetAlertPrefix(GetTag()); + // strategy.SetAlertLogAlerts(GetAlertLogAlerts()); + // strategy.SetAlertMailAlerts(GetAlertMailAlerts()); + // strategy.SetAlertPushAlerts(GetAlertPushAlerts()); + // strategy.SetAlertEnableAlerts(GetAlertEnableAlerts()); + // strategy.SetAlertTerminalAlerts(GetAlertTerminalAlerts()); + + // // + // // Confiugre Signalling ... + + // // + // strategy.R2R(2); + // strategy.AllowLong(AllowLong()); + // strategy.AllowShort(AllowShort()); + + // // + // if (Disabled()) + // { + // strategy.Disable(); + // } + // else + // { + // strategy.Enable(); + // } + + // // + // } + + /** + * Register an Strategy in EA ... + * + * @param strategy: XCX121SMCBaseStrategy instance ... + */ + // void RegisterStrategy(XCX121SMCBaseStrategy *strategy) + // { + // // + // if (strategy == NULL) + // { + // return; + // } + + // // + // ArrayResize( + // mStrategies, + // ArraySize(mStrategies) + 1 // + // ); + + // // + // mStrategies[ArraySize(mStrategies) - 1] = strategy; + // } + + /** + * Re Configure All Registered Strategies ... + */ + // void ReConfigureAllStrategies() + // { + // // + // int count = ArraySize(mStrategies); + // if (!IsValidSize(count)) + // { + // return; + // } + + // // + // for (int i = 0; i < count; i++) + // { + // // + // ConfigureStrategy(mStrategies[i]); + // } + // } + + // + private: + // + + // + // Props ... + + // + // Volume Management ... + bool mUseDynamicVolume; // Use Dynamic Volume ... + double mDynamicVolumeStep; // Increase Volume Step ... + double mDynamicVolumeBalanceFactor; // Balance Factor for Generate Dynamic Volume ... + double mVolume; // Static Volume ... + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/x-121.poi.expert.class.mq5 b/BKPS/14030923/Documents/BKP/x-121.poi.expert.class.mq5 new file mode 100644 index 0000000..ffb094a --- /dev/null +++ b/BKPS/14030923/Documents/BKP/x-121.poi.expert.class.mq5 @@ -0,0 +1,830 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XC121SMCExpert +// Description: provides all based classes for use ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-expert.class.mq5" +#include "../../Classes/x-saherelm.x-poi.class.mq5" +// #include "../Classes/x-121.smc.xtradehandler.class.mq5" + +// +// Definitions ... +string XC121SMCExpertToken = "XC121SMCEA"; + +// +// Implementation ... + +class XC121SMCExpert : public XCBaseExpert +{ + // + public: + // + + // + // Signal Event Listener ... + TOnStopLoss OnPositionSLEventListener; + TOnTakeProfit OnPositionTPEventListener; + TOnPartialClose OnPositionPartialCloseEventListener; + TOnModify OnPositionModifiedEventListener; + TOnForceClose OnPositionForceCloseEventListener; + + // + // Getter(s) / Setter(s) ... + + /** + * Get Use Dynamic Volume State ... + * + * @return ( bool ) + */ + bool UseDynamicVolume() + { + return mUseDynamicVolume; + } + + /** + * Set Use Dynamic Volume State ... + * + * @param value: Boolean ... + */ + void UseDynamicVolume(bool value) + { + mUseDynamicVolume = value; + } + + /** + * Get Increase Volume Step ... + * + * @return ( double ) + */ + double DynamicVolumeStep() + { + return mDynamicVolumeStep; + } + + /** + * Set Increase Volume Step ... + * + * @param value: Double ... + */ + void DynamicVolumeStep(double value) + { + // + if (value < 0.01) + { + value = 0.01; + } + + // + mDynamicVolumeStep = value; + } + + /** + * Get Balance Factor for Generate Dynamic Volume ... + * + * @return ( double ) + */ + double DynamicVolumeBalanceFactor() + { + return mDynamicVolumeBalanceFactor; + } + + /** + * Set Balance Factor for Generate Dynamic Volume ... + * + * @param value: Double ... + */ + void DynamicVolumeBalanceFactor(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mDynamicVolumeBalanceFactor = value; + } + + /** + * Get Static Volume ... + * + * @return ( double ) + */ + double Volume() + { + return mVolume; + } + + /** + * Set Static Volume ... + * + * @param value: Double ... + */ + void Volume(double value) + { + // + if (value < 0.01) + { + value = 0.01; + } + + // + mVolume = value; + } + + // + // Actions ... + + // + // Override Actions ... + + /** + * Apply Default Configurations ... + */ + void DefaultConfigure() override + { + // + // Commons ... + Slippage(10); + TagPrefix(""); + MagicNumber(1694056); + + // + // Symbol ... + SetSymbol(_Symbol); + SetPeriod(_Period); + MultiSymbol(false); + Symbols("EURUSDb,GBPUSDb,USDJPYb,USDCHFb,DowJones30,XAUUSDb"); + + // + // Signalling ... + Disabled(false); + AllowLong(true); + AllowShort(true); + + // + string tag = GetTag(); + + // + // Alert ... + SetAlertPrefix(tag); + SetAlertLogAlerts(true); + SetAlertPushAlerts(true); + SetAlertMailAlerts(false); + SetAlertEnableAlerts(true); + SetAlertTerminalAlerts(false); + + // + // Reports ... + ReportNewDays(true); + ReportNewWeeks(false); + ReportNewHours(false); + ReportNewMonths(false); + + // + // Volume Default Configurations ... + Volume(0.01); + UseDynamicVolume(false); + DynamicVolumeStep(0.01); + DynamicVolumeBalanceFactor(200); + } + + /** + * Vaslidate Inputs ... + * + * @return ( bool ) + */ + bool ValidateInputs() override + { + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + Slippage() > 0 && + MagicNumber() > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + // Checking Volume ... + bool isVolumeValid = true; + if (UseDynamicVolume()) + { + // + isVolumeValid = + DynamicVolumeStep() > 0 && + DynamicVolumeBalanceFactor() > 0; + if (!isVolumeValid) + { + errMessage += "Dynamic Volume configurations error;" + "\n"; + } + } + isVolumeValid = isVolumeValid && + Volume() > 0; + if (!isVolumeValid) + { + errMessage += "Static Volume configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Volume Coniguration ... + isVolumeValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + errMessage = " Errors: \n" + errMessage; + Alert(errMessage); + } + + // + return result; + } + + // + // Initializers and DeInitializers ... + + /** + * Initial EA Requirements ... + * + * @return ( bool ) + */ + bool InitEA() override + { + // + bool result = false; + + // + // Initialize Indicator Helpers ... + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + mPOIDetector = new XCPOIDetector( + symbol, + period // + ); + mPOIDetector.Init(); + + // + // Bar Timer ... + XCTInputs ctInputs; + ctInputs.Default(); // Default Configurations ... + mCTHelper = new XCXCTHelper(); + result = mCTHelper.Init( + GetSymbol(), + GetPeriod(), + ctInputs // + ); + if (!result) + { + return result; + } + + // + // Bar Styles ... + XCCInputs ccInputs; + ccInputs.Default(); // Default Configurations ... + mCCHelper = new XCXCCHelper(); + result = mCCHelper.Init( + GetSymbol(), + GetPeriod(), + ccInputs // + ); + if (!result) + { + return result; + } + + // + // Create Trader Instance and Configure it ... + mTrader = new XCTrade( + Slippage(), + MagicNumber() // + ); + mTrader.AddOnStopLossEventHandler(OnPositionSLEventListener); + mTrader.AddOnTakeProfitEventHandler(OnPositionTPEventListener); + mTrader.AddOnModifyPositionEventHandler(OnPositionModifiedEventListener); + mTrader.AddOnForceClosePositionEventHandler(OnPositionForceCloseEventListener); + mTrader.AddOnPartialClosePositionEventHandler(OnPositionPartialCloseEventListener); + + // // + // // Initialize Trade Handler ... + // mTradeHandler = new XC121SMCTradeHandler(mTrader); + // mTradeHandler.SaveTrades(true); + // mTradeHandler.SaveSignals(true); + // mTradeHandler.SaveConditions(true); + + // // + // // Configure Alerts ... + // mTradeHandler.SetAlertPrefix(GetTag()); + // mTradeHandler.SetAlertEnableAlerts(GetAlertEnableAlerts()); + // mTradeHandler.SetAlertLogAlerts(GetAlertLogAlerts()); + // mTradeHandler.SetAlertMailAlerts(GetAlertMailAlerts()); + // mTradeHandler.SetAlertPushAlerts(GetAlertPushAlerts()); + // mTradeHandler.SetAlertTerminalAlerts(GetAlertTerminalAlerts()); + + // // + // // TODO: Make This Configurable Later ... + + // // + // mTradeHandler.DelayBarBetweenTwoSignal(3); + // mTradeHandler.MaxAllowedSLToPause(0); + // mTradeHandler.MaxAllowedSLReachedPauseDelay(HoursToSeconds(24)); + + // // + // // Configure Trade Management ... + // mTradeHandler.AllowLong(AllowLong()); + // mTradeHandler.AllowShort(AllowShort()); + // mTradeHandler.MaxAllowedLongs(0); + // mTradeHandler.MaxAllowedShorts(0); + // mTradeHandler.UseMaxAllowedTradesPerSymbol(true); + // mTradeHandler.MaxDrawdownPercentForOpenTrades(5); + + // // + // // Configure Position Protector ... + + // // + // mTradeHandler.UseForceMomentumsInProtection(true); + // mTradeHandler.DelayBarBetweenTwoSignal(2); + + // // + // // Configure Hedging ... + // mTradeHandler.AllowHedge(false); + // mTradeHandler.HedgeMinVolumeStep(0.01); + // mTradeHandler.MinimumOpenPositionsForHEHedge(2); + // mTradeHandler.HedgeHEMinProfitPerVolumeStep(0.2); + // mTradeHandler.HedgeBEMinProfitPerVolumeStep(0.06); + + // // + // // In Profit Position Protecting ... + + // // + // // Trail ... + // mTradeHandler.AllowTrail(false); + // mTradeHandler.TrailStep(15); + // mTradeHandler.TrailStartDistance(30); + // mTradeHandler.OnlyTrailUnprotected(true); + // mTradeHandler.RemoveTPAfterTrailedLevel(4); + + // // + // // Partial Close (In Profit) ... + // mTradeHandler.PartialCloseInProfitDistance(0); + // mTradeHandler.PartialCloseInProfitVolume(0); + + // // + // // In Drawdown Positions Protecting ... + + // // + // // Protect ... + // mTradeHandler.AllowProtect(false); + // mTradeHandler.ProtectionDelay(20); + // mTradeHandler.MaxAllowedProtection(0); + // mTradeHandler.UseEntryAsProtectionSL(true); + // mTradeHandler.ProtectOnConditions(true); + // mTradeHandler.AllowDirectionProtct(false); + // mTradeHandler.ProtectionStartDistance(50); + // mTradeHandler.ProtectionVolumeMultiplier(2); + + // // + // // Partial Close (In Profit) ... + // mTradeHandler.PartialCloseInDrawdownDistance(0); + // mTradeHandler.PartialCloseInDrawdownVolume(0); + + // + // Parsers ... + XSymbolParser _symbolParser; + + // + // Single Symbol ... + if (!MultiSymbol()) + { + // + // Register Strategy ... + + // + // Create Class Instance ... + // XCX121SMCBaseStrategy *iX121SMCStrategy; + // iX121SMCStrategy = new XCX121SMCTestStrategy( + // _Symbol, + // _Period // + // ); + + // // + // iX121SMCStrategy.AddXSignalEventHandler(OnSignalEventListener); + + // // + // ConfigureStrategy(iX121SMCStrategy); + // RegisterStrategy(iX121SMCStrategy); + } + // + // Multi Symbol ... + else + { + // + // Parse Symbols ... + string symbols[]; + int symbolsCount = SplitContent( + symbols, + Symbols() // + ); + result = IsValidSize(symbolsCount); + if (!result) + { + return result; + } + + // + for (int i = 0; i < symbolsCount; i++) + { + // + // Select Symbol ... + string iSymbol = symbols[i]; + + // + // Register Strategy Based On Symbol ... + + // + // Parse Symbol ... + bool isEURUSD = _symbolParser.IsEURUSD(_Symbol); + bool isGBPUSD = _symbolParser.IsGBPUSD(_Symbol); + bool isEURGBP = _symbolParser.IsEURGBP(_Symbol); + bool isUSDCHF = _symbolParser.IsUSDCHF(_Symbol); + bool isEURCHF = _symbolParser.IsEURCHF(_Symbol); + bool isUSDJPY = _symbolParser.IsUSDJPY(_Symbol); + bool isEURJPY = _symbolParser.IsEURJPY(_Symbol); + bool isUSDCAD = _symbolParser.IsUSDCAD(_Symbol); + bool isEURCAD = _symbolParser.IsEURCAD(_Symbol); + bool isAUDUSD = _symbolParser.IsAUDUSD(_Symbol); + bool isEURAUD = _symbolParser.IsEURAUD(_Symbol); + bool isNZDUSD = _symbolParser.IsNZDUSD(_Symbol); + bool isEURNZD = _symbolParser.IsEURNZD(_Symbol); + + // + // Check Symbol Can Register or not ... + bool canRegisterStrategy = true; + + // + if (canRegisterStrategy) + { + // // + // // Create Class Instance ... + // XCX121SMCBaseStrategy *iX121SMCStrategy; + // iX121SMCStrategy = new XCX121SMCTestStrategy( + // iSymbol, + // _Period // + // ); + + // // + // iX121SMCStrategy.AddXSignalEventHandler(OnSignalEventListener); + + // // + // // Register Strategy ... + // ConfigureStrategy(iX121SMCStrategy); + // RegisterStrategy(iX121SMCStrategy); + } + } + } + + // + return result; + } + + /** + * Destroy all Initialized EA Requirements ... + */ + void DestroyEA() override + { + // + delete mCTHelper; + delete mCCHelper; + // delete mTradeHandler; + + // + // Clean(mStrategies); + } + + /** + * Call all Registered Strategies On Tick ... + */ + void HandleStrategiesOnTick() override + { + // + ENUM_XPOI_EVENTS events[]; + mPOIDetector.Update(events); + + // + // int count = ArraySize(mStrategies); + // if (!IsValidSize(count)) + // { + // return; + // } + + // // + // for (int i = 0; i < count; i++) + // { + // // + // // Call Tick Handler Function ... + // mStrategies[i].HandleTick(); + // } + } + + // + // Event Handlers ... + + /** + * Calls When a Position's SL Triggered ... + * + * @param deal: XDeal instance ... + */ + void HandleOnStopLossTriggered(const XDeal &deal) override + { + // + // Finish ... + // mTradeHandler.Finish(deal); + + // + HandleReportBalance(); + } + + /** + * Calls When a Position's TP Triggered ... + * + * @param deal: XDeal instance ... + */ + void HandleOnTakeProfitTriggered(const XDeal &deal) override + { + // + // Finish ... + // mTradeHandler.Finish(deal); + + // + HandleReportBalance(); + } + + /** + * Handle Force Close a Position ... + * + * @param ticket: Position Ticket ... + * @param position: XPosition ... + * @param comment: Closing Comment ... + */ + void HandleOnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // + ) override + { + // + // Finish ... + // mTradeHandler.Finish( + // ticket, + // position, + // comment // + // ); + + // + HandleReportBalance(); + } + + /** + * Reset All Paused Symbols on Each New Days ... + */ + void HandleOnNewDay() override + { + // mTradeHandler.ResumePausedSymbols(); + } + + /** + * Generate Identifier Tag ... + * + * @return ( string ) + */ + string GetTag() override + { + // + string result = NULL; + + // + string tagPrefix = TagPrefix(); + if (IsValid(tagPrefix)) + { + result = tagPrefix; + } + else + { + result = ""; + } + + // + result = + XCBaseExpertToken + result; + + // + return result; + } + + // + protected: + // + + // + // Props ... + + // + datetime mLastSignalOn; + + // + XCPOIDetector *mPOIDetector; + + // + // XC121SMCTradeHandler *mTradeHandler; // Trade Handler ... + // XCX121SMCBaseStrategy *mStrategies[]; // Registere Strategies in EA ... + + // + // Actions ... + + /** + * Apply Volume Based On Configurations on Signal ... + * + * @param signal: XSignal instance + */ + void ApplyVolumeOnSignal(XSignal &signal) + { + // + // Prepare Signal Dynamic Volume + // if Provided ... + if (UseDynamicVolume() && + DynamicVolumeStep() > 0 && + DynamicVolumeBalanceFactor() > 0) + { + // + double dVolume = mTrader.GetDynamicVolume( + signal.symbol, + DynamicVolumeBalanceFactor(), + DynamicVolumeStep() // + ); + + // + if (dVolume > 0) + { + signal.volume = dVolume; + } + else + { + signal.volume = Volume(); + } + } + else + { + signal.volume = Volume(); + } + + // + // mTradeHandler.UpdateSignal(signal); + } + + /** + * Configure Startegy ... + */ + // void ConfigureStrategy(XCX121SMCBaseStrategy *&strategy) + // { + // // + // if (strategy == NULL) + // { + // return; + // } + + // // + // // Configure Alerts ... + // strategy.SetAlertPrefix(GetTag()); + // strategy.SetAlertLogAlerts(GetAlertLogAlerts()); + // strategy.SetAlertMailAlerts(GetAlertMailAlerts()); + // strategy.SetAlertPushAlerts(GetAlertPushAlerts()); + // strategy.SetAlertEnableAlerts(GetAlertEnableAlerts()); + // strategy.SetAlertTerminalAlerts(GetAlertTerminalAlerts()); + + // // + // // Confiugre Signalling ... + + // // + // strategy.R2R(2); + // strategy.AllowLong(AllowLong()); + // strategy.AllowShort(AllowShort()); + + // // + // if (Disabled()) + // { + // strategy.Disable(); + // } + // else + // { + // strategy.Enable(); + // } + + // // + // } + + /** + * Register an Strategy in EA ... + * + * @param strategy: XCX121SMCBaseStrategy instance ... + */ + // void RegisterStrategy(XCX121SMCBaseStrategy *strategy) + // { + // // + // if (strategy == NULL) + // { + // return; + // } + + // // + // ArrayResize( + // mStrategies, + // ArraySize(mStrategies) + 1 // + // ); + + // // + // mStrategies[ArraySize(mStrategies) - 1] = strategy; + // } + + /** + * Re Configure All Registered Strategies ... + */ + // void ReConfigureAllStrategies() + // { + // // + // int count = ArraySize(mStrategies); + // if (!IsValidSize(count)) + // { + // return; + // } + + // // + // for (int i = 0; i < count; i++) + // { + // // + // ConfigureStrategy(mStrategies[i]); + // } + // } + + // + private: + // + + // + // Props ... + + // + // Volume Management ... + bool mUseDynamicVolume; // Use Dynamic Volume ... + double mDynamicVolumeStep; // Increase Volume Step ... + double mDynamicVolumeBalanceFactor; // Balance Factor for Generate Dynamic Volume ... + double mVolume; // Static Volume ... + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/x-121.smc.FULL.lib.mq5 b/BKPS/14030923/Documents/BKP/x-121.smc.FULL.lib.mq5 new file mode 100644 index 0000000..e88a3ac --- /dev/null +++ b/BKPS/14030923/Documents/BKP/x-121.smc.FULL.lib.mq5 @@ -0,0 +1,1798 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: X121SMCLib +// Description: provide all commonly used functions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.base.class.mq5" +#include "../../Helpers/x-saherelm.x3ma.helper.mq5" +#include "../../Helpers/x-saherelm.x3vwap.helper.mq5" +#include "../../Helpers/x-saherelm.xchsar.helper.mq5" +#include "../../Helpers/x-saherelm.xpv.helper.mq5" +#include "../../Libraries/x-saherelm.common.lib.mq5" +#include "../../Libraries/x-saherelm.x-poi.lib.mq5" +#include "../../Libraries/x-saherelm.x-trade.lib.mq5" + +// +// Definitions ... + +const string X121SMCStrategyToken = "X121SMC"; + +const string X121SMCPVToken = "X121SMCPV"; +const string X121SMCBOSToken = "X121SMCBOS"; +const string X121SMCSARToken = "X121SMCSAR"; +const string X121SMCCHOCHToken = "X121SMCCHOCH"; +const string X121SMCPULLBKToken = "X121SMCPULLBK"; + +enum ENUM_X_121_SMC_PROVIDERS +{ + // + X_121_SMC_PROVIDER_NONE, + X_121_SMC_PROVIDER_PV, + X_121_SMC_PROVIDER_BOS, + X_121_SMC_PROVIDER_SAR, + X_121_SMC_PROVIDER_CHOCH, + X_121_SMC_PROVIDER_PULLBK, +}; + +enum ENUM_XPV_PIVOTS +{ + XPV_NONE, + XPV_PEAK, + XPV_VALE, +}; + +struct XPVPivot +{ + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double upper; + double lower; + + // + datetime from; + datetime to; + + // + int repetition; + + // + ENUM_XPV_PIVOTS type; + + // + // Combined all States ... + XPOIState state; + + // + XPVPivot() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + upper = 0; + lower = 0; + + // + to = NULL; + from = NULL; + symbol = NULL; + period = NULL; + + // + repetition = 0; + + // + type = XPV_NONE; + + // + state.Clean(); + } + + /** + * Validation ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(to) && + IsValid(from) && + IsValid(symbol) && + IsValid(period) && + repetition > 0 && + type != XPV_NONE && + (upper > 0 || lower > 0) + // + ; + + // + return result; + } + + /** + * Check Pivot is Peak ... + * + * @return ( bool ) + */ + bool IsPeak() + { + // + bool result = false; + + // + result = IsValid() && + type == XPV_PEAK; + + // + return result; + } + + /** + * Check Pivot is Vale ... + * + * @return ( bool ) + */ + bool IsVale() + { + // + bool result = false; + + // + result = IsValid() && + type == XPV_VALE; + + // + return result; + } + + /** + * Calculate Lower for Peaks ... + * + * @return ( double ) + */ + double CalculateLower() + { + // + double result = 0; + + // + if (!IsValid() || + !IsPeak()) + { + return result; + } + + // + int fromIndex = iBarShift( + symbol, + period, + from // + ); + + // + int toIndex = iBarShift( + symbol, + period, + to // + ); + + // + int count = + fromIndex - toIndex; + + // + int llIDX = iLowest( + symbol, + period, + MODE_LOW, + count, + toIndex // + ); + + // + result = + iLow( + symbol, + period, + llIDX // + ); + + // + return result; + } + + /** + * Calculate Upper for Vales ... + * + * @return ( double ) + */ + double CalculateUpper() + { + // + double result = 0; + + // + if (!IsValid() || + !IsVale()) + { + return result; + } + + // + int fromIndex = iBarShift( + symbol, + period, + from // + ); + + // + int toIndex = iBarShift( + symbol, + period, + to // + ); + + // + int count = + fromIndex - toIndex; + + // + int hhIDX = iHighest( + symbol, + period, + MODE_HIGH, + count, + toIndex // + ); + + // + result = + iHigh( + symbol, + period, + hhIDX // + ); + + // + return result; + } + + /** + * Calculate Range of Pivot ... + * + * @return ( double ) + */ + double CalculateRange() + { + // + double result = 0; + + // + if (!IsValid() || + upper <= 0 || + lower <= 0) + { + return result; + } + + // + result = upper - lower; + + // + return result; + } + + /** + * Calculate Middle of Pivot ... + * Used for + * @return ( double ) + */ + double CalculateMid() + { + // + double result = 0; + + // + double range = CalculateRange(); + if (range <= 0) + { + return result; + } + + // + result = lower + (range / 2); + + // + return result; + } + + /** + * Calculate Liquidity Percent for Specified Direction ... + * + * @param forDirection: ENUM_X_DIRECTION member, Specified Liquidity ... + * @param price: Double, Specified Price ... + * + * @return ( double ) + */ + double CalculateLiquidityPercent( + ENUM_X_DIRECTION forDirection, + double price = 0 // + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = state + .CalculateLiquidityPercent( + forDirection, + price // + ); + + // + return result; + } + + // + + /** + * Get Unique Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + string hash = symbol + "_" + + ToString(period) + "_" + + ToString(upper) + "," + + ToString(lower) + "_" + + ToString(from) + "," + + ToString(to); + hash = ToMD5(hash); + + // + string typeStr = + type == XPV_PEAK + ? "Peak" + : "Vale"; + + // + result = + // + "XPV_" + + typeStr + "_" + + symbol + "_" + + ToString(period) + + "_" + hash + // + ; + + // + return result; + } + + // +}; + +// +// Model Signalling Conditions ... +struct X121SMCStrategyConditions +{ + // + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + XPVConditions xpvConditions; + X3MAConditions x3maConditions; + X3VWAPConditions x3vwapConditions; + XCHSARConditions xchsarConditions; + + // + void X121SMCStrategyConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + symbol = NULL; + period = NULL; + time = NULL; + + // + xpvConditions.Clean(); + x3maConditions.Clean(); + x3vwapConditions.Clean(); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(time); + + // + return result; + } + + // + // Reporter Functions ... + + /** + * Generate Provided Scores ... + * + * @param bullishScore: Integer, reference ... + * @param bearishScore: Integer, referenceF ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + if (!IsValid()) + { + return; + } + + // + double bullScore = 0; + double bearScore = 0; + + // // + // // XPV ... + // pvConditions.GenerateScore( + // bullScore, + // bearScore // + // ); + // bullishScore += bullScore; + // bearishScore += bearScore; + } + + /** + * Generate Summary ... + * + * @param onlyCommons: Boolean ... + * @param onlyConditions: Boolean ... + * @param includeScores: Boolean ... + * @param ignoreFalseConditions: Boolean ... + * @param separator: String ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores, + true // + ); + + // // + // // XPV ... + // string pvStr = pvConditions.GenerateSummary( + // false, + // true, + // false, + // ignoreFalseConditions // + // ); + + // + string conditionsStr = + // + // pvStr + separator + + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + "----------" + separator + + (onlyConditions + ? "" + : commonStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Get Unique Identifier ... + * + * @param forObject: Boolean ... + * + * @return ( string ) + */ + string GetTag( + bool forObject = false // + ) + { + // + string result = NULL; + + // + if (!forObject) + { + result = X121SMCStrategyToken; + } + else + { + // + result = X121SMCStrategyToken + "_" + + symbol + "_" + ToString(period) + "_" + + ToMD5(time); + } + + // + return result; + } + + // +}; + +typedef void (*TOnX121SMCSignal)( + XSignal &signal, + X121SMCStrategyConditions &conditions // +); + +// +// Time Frames Tools ... + +/** + * Calculate Analyse Period ... + * + * @param value: ENUM_TIMEFRAMES member, Specified Trigger Period ... + * + * @return ( ENUM_TIMEFRAMES ) + */ +ENUM_TIMEFRAMES GetAnalysePeriod(ENUM_TIMEFRAMES value) +{ + // + ENUM_TIMEFRAMES result = NULL; + + // + value = NormalizePeriod(value); + + // + switch (value) + { + // + case PERIOD_M1: + case PERIOD_M2: + case PERIOD_M3: + case PERIOD_M4: + case PERIOD_M5: + case PERIOD_M6: + case PERIOD_M10: + case PERIOD_M12: + result = PERIOD_M15; + break; + + // + case PERIOD_M15: + case PERIOD_M20: + result = PERIOD_M30; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + result = PERIOD_H4; + break; + + // + case PERIOD_H4: + case PERIOD_H6: + case PERIOD_H8: + result = PERIOD_H12; + break; + + // + default: + result = NULL; + } + + // + return result; +} +bool HasValidAnalysePeriod( + ENUM_TIMEFRAMES value, + ENUM_TIMEFRAMES &period // +) +{ + // + bool result = false; + + period = GetAnalysePeriod(value); + result = IsValid(period); + + // + return result; +} + +/** + * Calculate Vision Period ... + * + * @param value: ENUM_TIMEFRAMES member, Specified Trigger Period ... + * + * @return ( ENUM_TIMEFRAMES ) + */ +ENUM_TIMEFRAMES GetVisionPeriod(ENUM_TIMEFRAMES value) +{ + // + ENUM_TIMEFRAMES result = NULL; + + // + value = NormalizePeriod(value); + + // + switch (value) + { + // + case PERIOD_M1: + case PERIOD_M2: + case PERIOD_M3: + case PERIOD_M4: + case PERIOD_M5: + case PERIOD_M6: + case PERIOD_M10: + case PERIOD_M12: + result = PERIOD_H1; + break; + + // + case PERIOD_M15: + case PERIOD_M20: + result = PERIOD_H2; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + result = PERIOD_H6; + break; + + // + case PERIOD_H4: + case PERIOD_H6: + case PERIOD_H8: + result = PERIOD_D1; + break; + + // + default: + result = NULL; + } + + // + return result; +} +bool HasValidVisionPeriod( + ENUM_TIMEFRAMES value, + ENUM_TIMEFRAMES &period // +) +{ + // + bool result = false; + + period = GetVisionPeriod(value); + result = IsValid(period); + + // + return result; +} + +// +// Extentions ... + +/** + * Find Oldest Pivot Index ... + * + * @param pivots: XPVPivot instance ... + * @return ( int ) + */ +int FindOldestPivotIndex( + XPVPivot &pivots[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(pivots); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = pivots[i]; + + // + bool isOldest = true; + for (int j = 0; j < count; j++) + { + // + XPVPivot jPivot = pivots[j]; + + // + isOldest = iPivot.from <= jPivot.from; + if (!isOldest) + { + break; + } + } + + // + if (isOldest) + { + // + result = i; + break; + } + } + + // + return result; +} + +/** + * Sort Pivots Based On From Date ... + * + * @param pivots: XPVPivot instance Collection reference ... + */ +void SortPivots( + XPVPivot &pivots[] // +) +{ + // + XPVPivot tmp[]; + Copy( + pivots, + tmp // + ); + + // + Clean(pivots); + + // + while (ArraySize(tmp) > 0) + { + // + if (ArraySize(tmp) == 1) + { + // + AddRef( + tmp[0], + pivots // + ); + + // + ArrayRemove( + tmp, + 0, + 1); + } + else + { + // + int idx = FindOldestPivotIndex(tmp); + if (IsValidIndex(idx)) + { + // + AddRef( + tmp[idx], + pivots // + ); + + // + ArrayRemove( + tmp, + idx, + 1 // + ); + } + } + } + + // + Clean(tmp); +} + +bool IsPivotBreaked( + XPVPivot &pivot, + XPVPivot &pivots[] // +) +{ + // + bool result = false; + + // + result = pivot.IsValid(); + if (!result) + { + return result; + } + + // + int count = ArraySize(pivots); + result = IsValidSize(pivots); + if (!result) + { + return result; + } + + // + // For Peaks Highs Must not Broked ... + // For Vales Lows Must not Broked ... + bool isPeak = pivot.IsPeak(); + + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = pivots[i]; + + // + result = isPeak + ? iPivot.upper > pivot.upper + : iPivot.lower < pivot.lower; + if (result) + { + break; + } + } + + // + return result; +} + +/** + * Filter Broken Pivots for Detect Order Flow ... + * + * @param pivots: XPVPivot instance Collection reference ... + */ +void FilterBrokenPivots( + XPVPivot &pivots[] // +) +{ + // + XPVPivot tmp[]; + Copy( + pivots, + tmp // + ); + + // + Clean(pivots); + + // + while (ArraySize(tmp) > 0) + { + // + if (ArraySize(tmp) == 1) + { + // + AddRef( + tmp[0], + pivots // + ); + + // + ArrayRemove( + tmp, + 0, + 1 // + ); + } + else + { + // + XPVPivot pivot = tmp[0]; + + // + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + bool isBreaked = IsPivotBreaked( + pivot, + tmp // + ); + if (!isBreaked) + { + // + AddRef( + pivot, + pivots // + ); + } + } + } + + // + Clean(tmp); +} + +/** + * Calculate Order Flow Direction ... + * + * @param orderFlow: XPVPivot instance Collection reference ... + * @param dir: ENUM_X_DIRECTION member reference, Hold's Calculated Direction ... + * + * @return ( bool ) + */ +bool DetectPivotDirection( + XPVPivot &orderFlow[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + int count = ArraySize(orderFlow); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + // For Bullish Direction all Exists lowers must be Greater or Equal Prev ... + bool isBullish = false; + bool canLookupForBullish = true; + + // + // For Bearish Direction all Exists uppers must be Lesser or Equal Prev ... + bool isBearish = false; + bool canLookupForBearish = true; + + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = orderFlow[i]; + + // + XPVPivot tmp[]; + Copy( + orderFlow, + tmp // + ); + ArrayRemove( + tmp, + 0, + i + 1 // + ); + + // + int tmpCount = ArraySize(tmp); + if (IsValidSize(tmpCount)) + { + // + for (int j = 0; j < tmpCount; j++) + { + // + XPVPivot jPivot = tmp[j]; + + // + // Check Bullish Direction ... + isBullish = + canLookupForBullish && + jPivot.lower >= iPivot.lower; + if (!isBullish) + { + canLookupForBullish = false; + } + + // + // Check Bearish Direction ... + isBearish = + canLookupForBearish && + jPivot.upper <= iPivot.upper; + if (!isBearish) + { + canLookupForBearish = false; + } + + // + if (!canLookupForBullish && + !canLookupForBearish) + { + break; + } + } + } + Clean(tmp); + } + + // + if (isBullish && + !isBearish) + { + dir = X_DIRECTION_BULLISH; + } + else if (isBearish && + !isBullish) + { + dir = X_DIRECTION_BEARISH; + } + + // + result = dir != X_DIRECTION_NONE; + + // + return result; +} + +/** + * Detect all POIs which inside a Pivot ... + * + * @param pivot: XPVPivot instance, Specified Pivot ... + * @param source: XPOIState instance, Reference to Source State ... + * @param state: XPOIState instance, Reference to Detected Pivots ... + * @param lookupSwingHighs: Boolean ... + * @param lookupSwingLows: Boolean ... + * @param lookupSupportZones: Boolean ... + * @param lookupResistanceZones: Boolean ... + * @param lookupSupplyZones: Boolean ... + * @param lookupDemandZones: Boolean ... + * @param lookupBullishOrderBlocks: Boolean ... + * @param lookupBearishOrderBlocks: Boolean ... + * @param lookupBullishFairValueGaps: Boolean ... + * @param lookupBearishFairValueGaps: Boolean ... + * @param lookupBullishRejectionBars: Boolean ... + * @param lookupBearishRejectionBars: Boolean ... + * @param lookupBullishMomentumBars: Boolean ... + * @param lookupBearishMomentumBars: Boolean ... + */ +void DetectPivotPOIs( + XPVPivot &pivot, + XPOIState &source, + XPOIState &state, + bool lookupSwingHighs = true, + bool lookupSwingLows = true, + bool lookupSupportZones = true, + bool lookupResistanceZones = true, + bool lookupSupplyZones = true, + bool lookupDemandZones = true, + bool lookupBullishOrderBlocks = true, + bool lookupBearishOrderBlocks = true, + bool lookupBullishFairValueGaps = true, + bool lookupBearishFairValueGaps = true, + bool lookupBullishRejectionBars = true, + bool lookupBearishRejectionBars = true, + bool lookupBullishMomentumBars = true, + bool lookupBearishMomentumBars = true // +) +{ + // + state.Clean(); + + // + if (!pivot.IsValid()) + { + return; + } + + // + int count = 0; + + // + state.symbol = pivot.symbol; + state.period = pivot.period; + state.time = TimeCurrent(); + + // + // Swings ... + + // + // Swing High ... + if (lookupSwingHighs) + { + // + count = ArraySize(source.swingHighs); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing *iSwing = source.swingHighs[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.high <= pivot.upper; + if (isInside) + { + // + Add( + iSwing, + state.swingHighs // + ); + } + } + } + } + + // + // Swing Low ... + if (lookupSwingLows) + { + // + count = ArraySize(source.swingLows); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing *iSwing = source.swingLows[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.low >= pivot.lower; + if (isInside) + { + // + Add( + iSwing, + state.swingLows // + ); + } + } + } + } + + // + // Support and Resistance Zones ... + + // + // Support Zones ... + if (lookupSupportZones) + { + // + count = ArraySize(source.supportZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZone *iZone = source.supportZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.supportZones // + ); + } + } + } + } + + // + // Resistance Zones ... + if (lookupResistanceZones) + { + // + count = ArraySize(source.resistanceZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZone *iZone = source.resistanceZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.resistanceZones // + ); + } + } + } + } + + // + // Supply and Demand Zones ... + + // + // Supply Zones ... + if (lookupSupplyZones) + { + // + count = ArraySize(source.supplyZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupplyZone *iZone = source.supplyZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.supplyZones // + ); + } + } + } + } + + // + // Demand Zones ... + if (lookupDemandZones) + { + // + count = ArraySize(source.demandZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCDemandZone *iZone = source.demandZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.demandZones // + ); + } + } + } + } + + // + // Order Blocks ... + + // + // Bullish Order Blocks ... + if (lookupBullishOrderBlocks) + { + // + count = ArraySize(source.bullishOrderBlocks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = source.bullishOrderBlocks[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bullishOrderBlocks // + ); + } + } + } + } + + // + // Bearish Order Blocks ... + if (lookupBearishOrderBlocks) + { + // + count = ArraySize(source.bearishOrderBlocks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = source.bearishOrderBlocks[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bearishOrderBlocks // + ); + } + } + } + } + + // + // Fair Value Gaps ... + + // + // Bullish Fair Value Gaps ... + if (lookupBullishFairValueGaps) + { + // + count = ArraySize(source.bullishFairValueGaps); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = source.bullishFairValueGaps[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bullishFairValueGaps // + ); + } + } + } + } + + // + // Bearish Fair Value Gaps ... + if (lookupBearishFairValueGaps) + { + // + count = ArraySize(source.bearishFairValueGaps); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = source.bearishFairValueGaps[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bearishFairValueGaps // + ); + } + } + } + } + + // + // Rejection Bars ... + + // + // Bullish Rejection Bars ... + if (lookupBullishRejectionBars) + { + // + count = ArraySize(source.bullishRejectionBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar *iRejection = source.bullishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.low <= pivot.upper && + iBar.low >= pivot.lower; + if (isInside) + { + // + Add( + iRejection, + state.bullishRejectionBars // + ); + } + } + } + } + + // + // Bearish Rejection Bars ... + if (lookupBearishRejectionBars) + { + // + count = ArraySize(source.bearishRejectionBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar *iRejection = source.bearishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.high <= pivot.upper && + iBar.high >= pivot.lower; + if (isInside) + { + // + Add( + iRejection, + state.bearishRejectionBars // + ); + } + } + } + } + + // + // Momentum Bars ... + + // + // Bullish Momentum Bars ... + if (lookupBullishMomentumBars) + { + // + count = ArraySize(source.bullishMomentumBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar *iMomentum = source.bullishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.low <= pivot.upper && + iBar.low >= pivot.lower; + if (isInside) + { + // + Add( + iMomentum, + state.bullishMomentumBars // + ); + } + } + } + } + + // + // Bearish Momenum Bars ... + if (lookupBearishMomentumBars) + { + // + count = ArraySize(source.bearishMomentumBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar *iMomentum = source.bearishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.high <= pivot.upper && + iBar.high >= pivot.lower; + if (isInside) + { + // + Add( + iMomentum, + state.bearishMomentumBars // + ); + } + } + } + } +} + +// +// Provider Extensions ... + +/** + * Validate a Signal Provider ... + * + * @param value: ENUM_X_121_SMC_PROVIDERS member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_121_SMC_PROVIDERS value) +{ + // + bool result = false; + + // + result = value != X_121_SMC_PROVIDER_NONE; + + // + return result; +} + +/** + * Converts a Signal Provider to String ... + * + * @param value: ENUM_X_121_SMC_PROVIDERS member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_121_SMC_PROVIDERS value) +{ + // + string result = NULL; + + // + if (!IsValid(value)) + { + return result; + } + + // + switch (value) + { + // + case X_121_SMC_PROVIDER_PV: + result = X121SMCPVToken; + break; + + // + case X_121_SMC_PROVIDER_BOS: + result = X121SMCBOSToken; + break; + + // + case X_121_SMC_PROVIDER_SAR: + result = X121SMCSARToken; + break; + + // + case X_121_SMC_PROVIDER_CHOCH: + result = X121SMCCHOCHToken; + break; + + // + case X_121_SMC_PROVIDER_PULLBK: + result = X121SMCPULLBKToken; + break; + } + + // + return result; +} + +/** + * Parse Specified String as a Signal Provider ... + * + * @param value: String ... + * + * @return ( ENUM_X_121_SMC_PROVIDERS ) + */ +ENUM_X_121_SMC_PROVIDERS ParseProvider(string value) +{ + // + ENUM_X_121_SMC_PROVIDERS result = X_121_SMC_PROVIDER_NONE; + + // + if (!IsValid(value)) + { + return result; + } + + // + if (Contains(X121SMCPVToken, value)) + { + result = X_121_SMC_PROVIDER_PV; + } + else if (Contains(X121SMCBOSToken, value)) + { + result = X_121_SMC_PROVIDER_BOS; + } + else if (Contains(X121SMCSARToken, value)) + { + result = X_121_SMC_PROVIDER_SAR; + } + else if (Contains(X121SMCCHOCHToken, value)) + { + result = X_121_SMC_PROVIDER_CHOCH; + } + else if (Contains(X121SMCPULLBKToken, value)) + { + result = X_121_SMC_PROVIDER_PULLBK; + } + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/x-121.smc.chart.objects.class.mq5 b/BKPS/14030923/Documents/BKP/x-121.smc.chart.objects.class.mq5 new file mode 100644 index 0000000..686d4a4 --- /dev/null +++ b/BKPS/14030923/Documents/BKP/x-121.smc.chart.objects.class.mq5 @@ -0,0 +1,991 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XChartObjects +// Description: provides all require Chart Objects ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +#include "../../Classes/x-saherelm.x-chart-objects.class.mq5" +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../../Libraries/x-saherelm.x-poi.lib.mq5" +#include "../Libraries/x-121.smc.lib.mq5" + +// +#include + +// +// Definitions ... + +enum ENUM_X121SMC_CHARTOBJECTS +{ + // + // Global ... + X_121SMC_CONDITIONS_OBJ = 110121, + X_121SMC_MARKET_STRUCTURE_OBJ = 110122, +}; + +// +// Implementations ... + +// +// Market Conditions ... +class XC121SMCConditionsObject : public XCBaseObject +{ + // + public: + // + + // + // Constructor ... + void XC121SMCConditionsObject(XCPOIDrawer *_poiDrawer) + { + mPOIDrawer = _poiDrawer; + } + + // + // Deconstructor ... + void ~XC121SMCConditionsObject() + { + } + + /** + * Create a Conditions Object on Chart ... + * + * @param chart_id: Long ... + * @param name: String ... + * @param window: Integer ... + * @param conditions: X121SMCStrategyConditions instance ... + * + * @return ( bool ) + */ + bool CreateByConditions( + long chart_id, + const string name, + const int window, + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + result = IsValid(name); + if (!result) + { + return result; + } + + // + string nameMD5 = ToMD5(name); + string suffix = "_" + nameMD5; + + // + // Supply Zone ... + bool isCreated = mPOIDrawer.CreateSupplyZone( + conditions.supplyZone, + mSupplyZoneObj // + ); + + // + // Demnd Zone ... + isCreated = mPOIDrawer.CreateDemandZone( + conditions.demandZone, + mDemandZoneObj // + ); + + // + // Bullish Order Block ... + isCreated = mPOIDrawer.CreateBullishOrderBlock( + conditions.bullishOrderBlock, + mBullishOBObj // + ); + + // + // Bearish Order Block ... + isCreated = mPOIDrawer.CreateBearishOrderBlock( + conditions.bearishOrderBlock, + mBearishOBObj // + ); + + // + // Collections ... + + // + // Order Blocks ... + + // + // Bullish ... + int count = ArraySize(conditions.bullishOrderBlocks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XZone iZone = conditions.bullishOrderBlocks[i]; + + // + XCBullishOrderBlockObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishOrderBlock( + iZone, + iObj // + ); + + // + if (isCreated) + { + mBullishOBObjs.Add(iObj); + } + } + } + + // + // Bearish ... + count = ArraySize(conditions.bearishOrderBlocks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XZone iZone = conditions.bearishOrderBlocks[i]; + + // + XCBearishOrderBlockObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishOrderBlock( + iZone, + iObj // + ); + + // + if (isCreated) + { + mBearishOBObjs.Add(iObj); + } + } + } + + // + // Fair Value Gaps ... + + // + // Bullish ... + count = ArraySize(conditions.bullishFVGs); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XZone iZone = conditions.bullishFVGs[i]; + + // + XCBullishFVGObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishFVG( + iZone, + iObj // + ); + + // + if (isCreated) + { + mBullishFVGObjs.Add(iObj); + } + } + } + + // + // Bearish ... + count = ArraySize(conditions.bearishFVGs); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XZone iZone = conditions.bearishFVGs[i]; + + // + XCBearishFVGObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishFVG( + iZone, + iObj // + ); + + // + if (isCreated) + { + mBearishFVGObjs.Add(iObj); + } + } + } + + // + // Support and Resistance Zones ... + + // + // Supports ... + count = ArraySize(conditions.supports); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XOHCL iBar = conditions.supports[i]; + + // + XCSupportZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateSupportZone( + iBar, + iObj // + ); + + // + if (isCreated) + { + mSupportZoneObjs.Add(iObj); + } + } + } + + // + // Resistances ... + count = ArraySize(conditions.resistances); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XOHCL iBar = conditions.resistances[i]; + + // + XCResistanceZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateResistanceZone( + iBar, + iObj // + ); + + // + if (isCreated) + { + mResistanceZoneObjs.Add(iObj); + } + } + } + + // + // Swings ... + + // + // High ... + count = ArraySize(conditions.swingHighs); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XOHCL iBar = conditions.swingHighs[i]; + + // + XCSwingHighObject *iObj; + bool isCreated = mPOIDrawer.CreateSwingHigh( + iBar, + iObj // + ); + + // + if (isCreated) + { + mSwingHighObjs.Add(iObj); + } + } + } + + // + // Low ... + count = ArraySize(conditions.swingLows); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XOHCL iBar = conditions.swingLows[i]; + + // + XCSwingLowObject *iObj; + bool isCreated = mPOIDrawer.CreateSwingLow( + iBar, + iObj // + ); + + // + if (isCreated) + { + mSwingLowObjs.Add(iObj); + } + } + } + + // + // Momentum Bars ... + + // + // Bullish ... + count = ArraySize(conditions.bullishMomentumBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XOHCL iBar = conditions.bullishMomentumBars[i]; + + // + XCBullishMomentumBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishMomentumBar( + iBar, + iObj // + ); + + // + if (isCreated) + { + mBullishMomentumBarObjs.Add(iObj); + } + } + } + + // + // Bearish ... + count = ArraySize(conditions.bearishMomentumBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XOHCL iBar = conditions.bearishMomentumBars[i]; + + // + XCBearishMomentumBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishMomentumBar( + iBar, + iObj // + ); + + // + if (isCreated) + { + mBearishMomentumBarObjs.Add(iObj); + } + } + } + + // + // Rejection Bars ... + + // + // Bullish ... + count = ArraySize(conditions.bullishRejectionBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XOHCL iBar = conditions.bullishRejectionBars[i]; + + // + XCBullishRejectionBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishRejectionBar( + iBar, + iObj // + ); + + // + if (isCreated) + { + mBullishRejectionBarObjs.Add(iObj); + } + } + } + + // + // Bearish ... + count = ArraySize(conditions.bearishRejectionBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XOHCL iBar = conditions.bearishRejectionBars[i]; + + // + XCBearishRejectionBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishRejectionBar( + iBar, + iObj // + ); + + // + if (isCreated) + { + mBearishRejectionBarObjs.Add(iObj); + } + } + } + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_X121SMC_CHARTOBJECTS ) + */ + virtual ENUM_X121SMC_CHARTOBJECTS Type() + { + return X_121SMC_CONDITIONS_OBJ; + } + + // + private: + // + XCPOIDrawer *mPOIDrawer; + + // + XCSupplyZoneObject *mSupplyZoneObj; + XCDemandZoneObject *mDemandZoneObj; + + // + XCBullishOrderBlockObject *mBullishOBObj; + XCBearishOrderBlockObject *mBearishOBObj; + + // + CArrayObj mBullishOBObjs; + CArrayObj mBearishOBObjs; + + // + CArrayObj mBullishFVGObjs; + CArrayObj mBearishFVGObjs; + + // + CArrayObj mSupportZoneObjs; + CArrayObj mResistanceZoneObjs; + + // + CArrayObj mSwingHighObjs; + CArrayObj mSwingLowObjs; + + // + CArrayObj mBullishMomentumBarObjs; + CArrayObj mBearishMomentumBarObjs; + + // + CArrayObj mBullishRejectionBarObjs; + CArrayObj mBearishRejectionBarObjs; + + // +}; + +// +// Market Structure ... +class XC121SMCMarketStructureObject : public XCBaseObject +{ + // + public: + // + + // + // Constructor ... + void XC121SMCMarketStructureObject(XCPOIDrawer *_poiDrawer) + { + mPOIDrawer = _poiDrawer; + } + + // + // Deconstructor ... + void ~XC121SMCMarketStructureObject() + { + } + + /** + * Create a Conditions Object on Chart ... + * + * @param chart_id: Long ... + * @param name: String ... + * @param window: Integer ... + * @param conditions: X121SMCStrategyConditions instance ... + * + * @return ( bool ) + */ + bool CreateByStructure( + long chart_id, + const string name, + const int window, + X121SMCMarketStructure &structure // + ) + { + // + bool result = false; + + // + result = IsValid(name); + if (!result) + { + return result; + } + + // + string nameMD5 = ToMD5(name); + string suffix = "_" + nameMD5; + + // + // Supply Zone ... + bool isCreated = mPOIDrawer.CreateSupplyZone( + structure.supplyZone, + mSupplyZoneObj // + ); + + // + // Demnd Zone ... + isCreated = mPOIDrawer.CreateDemandZone( + structure.demandZone, + mDemandZoneObj // + ); + + // + // Bullish Order Block ... + isCreated = mPOIDrawer.CreateBullishOrderBlock( + structure.bullishOrderBlock, + mBullishOBObj // + ); + + // + // Bearish Order Block ... + isCreated = mPOIDrawer.CreateBearishOrderBlock( + structure.bearishOrderBlock, + mBearishOBObj // + ); + + // + // Collections ... + + // + // Order Blocks ... + + // + // Bullish ... + int count = ArraySize(structure.bullishOrderBlocks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XZone iZone = structure.bullishOrderBlocks[i]; + + // + XCBullishOrderBlockObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishOrderBlock( + iZone, + iObj // + ); + + // + if (isCreated) + { + mBullishOBObjs.Add(iObj); + } + } + } + + // + // Bearish ... + count = ArraySize(structure.bearishOrderBlocks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XZone iZone = structure.bearishOrderBlocks[i]; + + // + XCBearishOrderBlockObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishOrderBlock( + iZone, + iObj // + ); + + // + if (isCreated) + { + mBearishOBObjs.Add(iObj); + } + } + } + + // + // Fair Value Gaps ... + + // + // Bullish ... + count = ArraySize(structure.bullishFVGs); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XZone iZone = structure.bullishFVGs[i]; + + // + XCBullishFVGObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishFVG( + iZone, + iObj // + ); + + // + if (isCreated) + { + mBullishFVGObjs.Add(iObj); + } + } + } + + // + // Bearish ... + count = ArraySize(structure.bearishFVGs); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XZone iZone = structure.bearishFVGs[i]; + + // + XCBearishFVGObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishFVG( + iZone, + iObj // + ); + + // + if (isCreated) + { + mBearishFVGObjs.Add(iObj); + } + } + } + + // + // Support and Resistance Zones ... + + // + // Supports ... + count = ArraySize(structure.supports); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XOHCL iBar = structure.supports[i]; + + // + XCSupportZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateSupportZone( + iBar, + iObj // + ); + + // + if (isCreated) + { + mSupportZoneObjs.Add(iObj); + } + } + } + + // + // Resistances ... + count = ArraySize(structure.resistances); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XOHCL iBar = structure.resistances[i]; + + // + XCResistanceZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateResistanceZone( + iBar, + iObj // + ); + + // + if (isCreated) + { + mResistanceZoneObjs.Add(iObj); + } + } + } + + // + // Swings ... + + // + // High ... + count = ArraySize(structure.swingHighs); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XOHCL iBar = structure.swingHighs[i]; + + // + XCSwingHighObject *iObj; + bool isCreated = mPOIDrawer.CreateSwingHigh( + iBar, + iObj // + ); + + // + if (isCreated) + { + mSwingHighObjs.Add(iObj); + } + } + } + + // + // Low ... + count = ArraySize(structure.swingLows); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XOHCL iBar = structure.swingLows[i]; + + // + XCSwingLowObject *iObj; + bool isCreated = mPOIDrawer.CreateSwingLow( + iBar, + iObj // + ); + + // + if (isCreated) + { + mSwingLowObjs.Add(iObj); + } + } + } + + // + // Momentum Bars ... + + // + // Bullish ... + count = ArraySize(structure.bullishMomentumBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XOHCL iBar = structure.bullishMomentumBars[i]; + + // + XCBullishMomentumBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishMomentumBar( + iBar, + iObj // + ); + + // + if (isCreated) + { + mBullishMomentumBarObjs.Add(iObj); + } + } + } + + // + // Bearish ... + count = ArraySize(structure.bearishMomentumBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XOHCL iBar = structure.bearishMomentumBars[i]; + + // + XCBearishMomentumBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishMomentumBar( + iBar, + iObj // + ); + + // + if (isCreated) + { + mBearishMomentumBarObjs.Add(iObj); + } + } + } + + // + // Rejection Bars ... + + // + // Bullish ... + count = ArraySize(structure.bullishRejectionBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XOHCL iBar = structure.bullishRejectionBars[i]; + + // + XCBullishRejectionBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishRejectionBar( + iBar, + iObj // + ); + + // + if (isCreated) + { + mBullishRejectionBarObjs.Add(iObj); + } + } + } + + // + // Bearish ... + count = ArraySize(structure.bearishRejectionBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XOHCL iBar = structure.bearishRejectionBars[i]; + + // + XCBearishRejectionBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishRejectionBar( + iBar, + iObj // + ); + + // + if (isCreated) + { + mBearishRejectionBarObjs.Add(iObj); + } + } + } + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_X121SMC_CHARTOBJECTS ) + */ + virtual ENUM_X121SMC_CHARTOBJECTS Type() + { + return X_121SMC_MARKET_STRUCTURE_OBJ; + } + + // + private: + // + XCPOIDrawer *mPOIDrawer; + + // + XCSupplyZoneObject *mSupplyZoneObj; + XCDemandZoneObject *mDemandZoneObj; + + // + XCBullishOrderBlockObject *mBullishOBObj; + XCBearishOrderBlockObject *mBearishOBObj; + + // + CArrayObj mBullishOBObjs; + CArrayObj mBearishOBObjs; + + // + CArrayObj mBullishFVGObjs; + CArrayObj mBearishFVGObjs; + + // + CArrayObj mSupportZoneObjs; + CArrayObj mResistanceZoneObjs; + + // + CArrayObj mSwingHighObjs; + CArrayObj mSwingLowObjs; + + // + CArrayObj mBullishMomentumBarObjs; + CArrayObj mBearishMomentumBarObjs; + + // + CArrayObj mBullishRejectionBarObjs; + CArrayObj mBearishRejectionBarObjs; + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/x-121.smc.expert.class.mq5 b/BKPS/14030923/Documents/BKP/x-121.smc.expert.class.mq5 new file mode 100644 index 0000000..d20f581 --- /dev/null +++ b/BKPS/14030923/Documents/BKP/x-121.smc.expert.class.mq5 @@ -0,0 +1,1113 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XC121SMCExpert +// Description: provides all based classes for use ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-expert.class.mq5" +#include "../Classes/x-121.smc.x-tradehandler.class.mq5" +#include "../Libraries/x-121.smc.lib.mq5" +#include "../Strategy/x-121.smc.test.strategy.class.mq5" + +// +// Definitions ... +string XC121SMCExpertToken = "XC121SMCEA"; + +// +// Implementation ... + +class XC121SMCExpert : public XCBaseExpert +{ + // + public: + // + + // + // Signal Event Listener ... + TOnStopLoss OnPositionSLEventListener; + TOnTakeProfit OnPositionTPEventListener; + TOnPartialClose OnPositionPartialCloseEventListener; + TOnModify OnPositionModifiedEventListener; + TOnForceClose OnPositionForceCloseEventListener; + + // + TOnX121SMCSignal OnSignalEventListener; + + // + // Getter(s) / Setter(s) ... + + /** + * Get Risk to Reward Ratio ... + * + * @return ( double ) + */ + double R2R() + { + return mR2R; + } + + /** + * Set Risk to Reward Ratio ... + * + * @param value: Double ... + */ + void R2R(double value) + { + // + if (value < 1) + { + value = 1; + } + + // + mR2R = value; + ReConfigureAllStrategies(); + } + + /** + * Get Use Dynamic Volume State ... + * + * @return ( bool ) + */ + bool UseDynamicVolume() + { + return mUseDynamicVolume; + } + + /** + * Set Use Dynamic Volume State ... + * + * @param value: Boolean ... + */ + void UseDynamicVolume(bool value) + { + mUseDynamicVolume = value; + } + + /** + * Get Increase Volume Step ... + * + * @return ( double ) + */ + double DynamicVolumeStep() + { + return mDynamicVolumeStep; + } + + /** + * Set Increase Volume Step ... + * + * @param value: Double ... + */ + void DynamicVolumeStep(double value) + { + // + if (value < 0.01) + { + value = 0.01; + } + + // + mDynamicVolumeStep = value; + } + + /** + * Get Balance Factor for Generate Dynamic Volume ... + * + * @return ( double ) + */ + double DynamicVolumeBalanceFactor() + { + return mDynamicVolumeBalanceFactor; + } + + /** + * Set Balance Factor for Generate Dynamic Volume ... + * + * @param value: Double ... + */ + void DynamicVolumeBalanceFactor(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mDynamicVolumeBalanceFactor = value; + } + + /** + * Get Risk Percent Per Balance in Each Trade ... + * + * @return ( double ) + */ + double RiskPercentPerBalance() + { + return mRiskPercentPerBalance; + } + + /** + * Set Risk Percent Per Balance in Each Trade ... + * + * @param value: Double + */ + void RiskPercentPerBalance(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mRiskPercentPerBalance = value; + } + + /** + * Get Dynamic Risk Management State ... + * + * @return ( bool ) + */ + bool DynamicRiskManagement() + { + return mDynamicRiskManagement; + } + + /** + * Set Dynamic Risk Management State ... + * + * @param value: Boolean ... + */ + void DynamicRiskManagement(bool value) + { + mDynamicRiskManagement = value; + } + + /** + * Get Static Volume ... + * + * @return ( double ) + */ + double Volume() + { + return mVolume; + } + + /** + * Set Static Volume ... + * + * @param value: Double ... + */ + void Volume(double value) + { + // + if (value < 0.01) + { + value = 0.01; + } + + // + mVolume = value; + } + + // + // Actions ... + + /** + * Handle OnSignalRecieved Event ... + * + * @param signal: XSignal instance ... + * @param conditions: X121SMCStrategyConditions instance ... + */ + void HandleOnSignalRecieved( + XSignal &signal, + X121SMCStrategyConditions &conditions // + ) + { + // + // Check Signal and Conditions Validations ... + + // + if (!signal.IsValid()) + { + return; + } + + // + if (!conditions.IsValid()) + { + return; + } + + // + bool isLong = IsLong(signal.type); + + // + // Notify When a Raw (Unfiltered) Signal Recieved + // if it's Provided ... + bool mAlertRawSignals = false; + if (mAlertRawSignals) + { + // + string msg = "Raw " + (IsLong(signal.type) ? "Long" : "Short") + " Signal Recieved: (" + signal.provider + "," + signal.symbol + "," + ToString(signal.period) + ") ..."; + Alert(msg); + } + + // + // Apply Volume On Signal ... + ApplyVolumeOnSignal(signal); + + // + // Chekc Signalling Enable or not ... + bool canContinue = + isLong + ? AllowLong() + : AllowShort(); + if (!canContinue) + { + return; + } + + // + // TODO: Apply Filtering On Signal ... + bool isFiltered = false; + if (isFiltered) + { + // + mTradeHandler.RemoveSignal(signal); + return; + } + + // + // Attach Conditions Summary to Signal ... + string conditionsSummary = conditions.GenerateSummary( + false, + false, + true, + false // + ); + + // + // TODO: Retrieve Conditions Summary based on Filter ... + signal.conditions = conditionsSummary; + + // + datetime currentTime = TimeCurrent(); + + // + // Check Signal Protections ... + bool canTrail = false; + ENUM_X_121_SMC_PROVIDERS signalProvider = ParseProvider(signal.provider); + if (IsValid(signalProvider)) + { + // + // Complete this in Force States ... + // canTrail = true; + } + + // + // Execute Signal Using Trade Handler ... + ENUM_X_SIGNAL_EXECUTION_RESULT state; + bool isExecuted = mTradeHandler.ExecuteSignal( + signal, + state, + false, // ignore Policies ... + // + // Force Protections ... + canTrail // + ); + + // + if (isExecuted) + { + mLastSignalOn = currentTime; + } + } + + // + // Override Actions ... + + /** + * Apply Default Configurations ... + */ + void DefaultConfigure() override + { + // + // Commons ... + Slippage(10); + TagPrefix(""); + MagicNumber(1694056); + + // + // Symbol ... + SetSymbol(_Symbol); + SetPeriod(_Period); + MultiSymbol(false); + Symbols("EURUSDb,GBPUSDb,USDJPYb,USDCHFb,DowJones30,XAUUSDb"); + + // + // Signalling ... + Disabled(false); + AllowLong(true); + AllowShort(true); + + // + string tag = GetTag(); + + // + // Alert ... + SetAlertPrefix(tag); + SetAlertLogAlerts(true); + SetAlertPushAlerts(true); + SetAlertMailAlerts(false); + SetAlertEnableAlerts(true); + SetAlertTerminalAlerts(false); + + // + // Reports ... + ReportNewDays(true); + ReportNewWeeks(false); + ReportNewHours(false); + ReportNewMonths(false); + + // + R2R(1); + + // + // Volume Default Configurations ... + Volume(0.01); + UseDynamicVolume(false); + DynamicVolumeStep(0.01); + DynamicVolumeBalanceFactor(200); + + // + RiskPercentPerBalance(0); + DynamicRiskManagement(false); + } + + /** + * Vaslidate Inputs ... + * + * @return ( bool ) + */ + bool ValidateInputs() override + { + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + Slippage() > 0 && + MagicNumber() > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + // Checking Volume ... + bool isVolumeValid = true; + if (UseDynamicVolume()) + { + // + isVolumeValid = + DynamicVolumeStep() > 0 && + DynamicVolumeBalanceFactor() > 0; + if (!isVolumeValid) + { + errMessage += "Dynamic Volume configurations error;" + "\n"; + } + } + isVolumeValid = isVolumeValid && + Volume() > 0; + if (!isVolumeValid) + { + errMessage += "Static Volume configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Volume Coniguration ... + isVolumeValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + errMessage = " Errors: \n" + errMessage; + Alert(errMessage); + } + + // + return result; + } + + // + // Initializers and DeInitializers ... + + /** + * Initial EA Requirements ... + * + * @return ( bool ) + */ + bool InitEA() override + { + // + bool result = false; + + // + // Initialize Indicator Helpers ... + + // + // Bar Timer ... + XCTInputs ctInputs; + ctInputs.Default(); // Default Configurations ... + mCTHelper = new XCXCTHelper(); + result = mCTHelper.Init( + GetSymbol(), + GetPeriod(), + ctInputs // + ); + if (!result) + { + return result; + } + + // + // Bar Styles ... + XCCInputs ccInputs; + ccInputs.Default(); // Default Configurations ... + mCCHelper = new XCXCCHelper(); + result = mCCHelper.Init( + GetSymbol(), + GetPeriod(), + ccInputs // + ); + if (!result) + { + return result; + } + + // + // Configure Alerts ... + SetAlertPrefix(GetTag()); + SetAlertEnableAlerts(GetAlertEnableAlerts()); + SetAlertLogAlerts(GetAlertLogAlerts()); + SetAlertMailAlerts(GetAlertMailAlerts()); + SetAlertPushAlerts(GetAlertPushAlerts()); + SetAlertTerminalAlerts(GetAlertTerminalAlerts()); + + // + // Create Trader Instance and Configure it ... + mTrader = new XCTrade( + Slippage(), + MagicNumber() // + ); + mTrader.AddOnStopLossEventHandler(OnPositionSLEventListener); + mTrader.AddOnTakeProfitEventHandler(OnPositionTPEventListener); + mTrader.AddOnModifyPositionEventHandler(OnPositionModifiedEventListener); + mTrader.AddOnForceClosePositionEventHandler(OnPositionForceCloseEventListener); + mTrader.AddOnPartialClosePositionEventHandler(OnPositionPartialCloseEventListener); + + // + // Initialize Trade Handler ... + mTradeHandler = new XC121SMCTradeHandler(mTrader); + mTradeHandler.SaveTrades(true); + mTradeHandler.SaveSignals(true); + mTradeHandler.SaveConditions(true); + + // + // Configure Alerts ... + mTradeHandler.SetAlertPrefix(GetTag()); + mTradeHandler.SetAlertEnableAlerts(GetAlertEnableAlerts()); + mTradeHandler.SetAlertLogAlerts(GetAlertLogAlerts()); + mTradeHandler.SetAlertMailAlerts(GetAlertMailAlerts()); + mTradeHandler.SetAlertPushAlerts(GetAlertPushAlerts()); + mTradeHandler.SetAlertTerminalAlerts(GetAlertTerminalAlerts()); + + // + // TODO: Make This Configurable Later ... + + // + mTradeHandler.MaxAllowedSLToPause(0); + mTradeHandler.DelayBarBetweenTwoSignal(3); + mTradeHandler.MaxAllowedSLReachedPauseDelay(HoursToSeconds(24)); + + // + // Configure Trade Management ... + mTradeHandler.AllowLong(AllowLong()); + mTradeHandler.AllowShort(AllowShort()); + mTradeHandler.MaxAllowedLongs(0); + mTradeHandler.MaxAllowedShorts(0); + mTradeHandler.UseMaxAllowedTradesPerSymbol(true); + mTradeHandler.MaxDrawdownPercentForOpenTrades(5); + + // + // Configure Position Protector ... + + // + mTradeHandler.UseForceMomentumsInProtection(true); + mTradeHandler.DelayBarBetweenTwoSignal(2); + + // + // Configure Hedging ... + mTradeHandler.AllowHedge(false); + mTradeHandler.HedgeMinVolumeStep(0.01); + mTradeHandler.MinimumOpenPositionsForHEHedge(2); + mTradeHandler.HedgeHEMinProfitPerVolumeStep(0.2); + mTradeHandler.HedgeBEMinProfitPerVolumeStep(0.06); + + // + // In Profit Position Protecting ... + + // + // Trail ... + mTradeHandler.AllowTrail(false); + mTradeHandler.TrailStep(15); + mTradeHandler.TrailStartDistance(30); + mTradeHandler.OnlyTrailUnprotected(true); + mTradeHandler.RemoveTPAfterTrailedLevel(3); + + // + // Partial Close (In Profit) ... + mTradeHandler.PartialCloseInProfitDistance(0); + mTradeHandler.PartialCloseInProfitVolume(0); + + // + // In Drawdown Positions Protecting ... + + // + // Protect ... + mTradeHandler.AllowProtect(false); + mTradeHandler.ProtectionDelay(20); + mTradeHandler.MaxAllowedProtection(0); + mTradeHandler.UseEntryAsProtectionSL(true); + mTradeHandler.ProtectOnConditions(true); + mTradeHandler.AllowDirectionProtct(false); + mTradeHandler.ProtectionStartDistance(50); + mTradeHandler.ProtectionVolumeMultiplier(2); + + // + // Partial Close (In Profit) ... + mTradeHandler.PartialCloseInDrawdownDistance(0); + mTradeHandler.PartialCloseInDrawdownVolume(0); + + // + // Parsers ... + XSymbolParser _symbolParser; + + // + // Single Symbol ... + if (!MultiSymbol()) + { + // + // Register Strategy ... + + // + // Create Class Instance ... + XCX121SMCBaseStrategy *iX121SMCStrategy; + iX121SMCStrategy = new XCX121SMCTestStrategy( + _Symbol, + _Period // + ); + + // + iX121SMCStrategy.AddXSignalEventHandler(OnSignalEventListener); + + // + ConfigureStrategy(iX121SMCStrategy); + RegisterStrategy(iX121SMCStrategy); + } + // + // Multi Symbol ... + else + { + // + // Parse Symbols ... + string symbols[]; + int symbolsCount = SplitContent( + symbols, + Symbols() // + ); + result = IsValidSize(symbolsCount); + if (!result) + { + return result; + } + + // + for (int i = 0; i < symbolsCount; i++) + { + // + // Select Symbol ... + string iSymbol = symbols[i]; + + // + // Register Strategy Based On Symbol ... + + // + // Parse Symbol ... + bool isEURUSD = _symbolParser.IsEURUSD(_Symbol); + bool isGBPUSD = _symbolParser.IsGBPUSD(_Symbol); + bool isEURGBP = _symbolParser.IsEURGBP(_Symbol); + bool isUSDCHF = _symbolParser.IsUSDCHF(_Symbol); + bool isEURCHF = _symbolParser.IsEURCHF(_Symbol); + bool isUSDJPY = _symbolParser.IsUSDJPY(_Symbol); + bool isEURJPY = _symbolParser.IsEURJPY(_Symbol); + bool isUSDCAD = _symbolParser.IsUSDCAD(_Symbol); + bool isEURCAD = _symbolParser.IsEURCAD(_Symbol); + bool isAUDUSD = _symbolParser.IsAUDUSD(_Symbol); + bool isEURAUD = _symbolParser.IsEURAUD(_Symbol); + bool isNZDUSD = _symbolParser.IsNZDUSD(_Symbol); + bool isEURNZD = _symbolParser.IsEURNZD(_Symbol); + + // + // Check Symbol Can Register or not ... + bool canRegisterStrategy = true; + + // + if (canRegisterStrategy) + { + // + // Create Class Instance ... + XCX121SMCBaseStrategy *iX121SMCStrategy; + iX121SMCStrategy = new XCX121SMCTestStrategy( + iSymbol, + _Period // + ); + + // + iX121SMCStrategy.AddXSignalEventHandler(OnSignalEventListener); + + // + // Register Strategy ... + ConfigureStrategy(iX121SMCStrategy); + RegisterStrategy(iX121SMCStrategy); + } + } + } + + // + return result; + } + + /** + * Destroy all Initialized EA Requirements ... + */ + void DestroyEA() override + { + // + delete mCTHelper; + delete mCCHelper; + delete mTradeHandler; + + // + Clean(mStrategies); + } + + /** + * Call all Registered Strategies On Tick ... + */ + void HandleStrategiesOnTick() override + { + // + // Calling Protection Handler of TradeHandler ... + mTradeHandler.HandleProtection(); + + // + int count = ArraySize(mStrategies); + if (!IsValidSize(count)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + // Call Tick Handler Function ... + mStrategies[i].HandleTick(); + } + } + + // + // Event Handlers ... + + /** + * Calls When a Position's SL Triggered ... + * + * @param deal: XDeal instance ... + */ + void HandleOnStopLossTriggered(const XDeal &deal) override + { + // + // Finish ... + mTradeHandler.Finish(deal); + + // + HandleReportBalance(); + } + + /** + * Calls When a Position's TP Triggered ... + * + * @param deal: XDeal instance ... + */ + void HandleOnTakeProfitTriggered(const XDeal &deal) override + { + // + // Finish ... + mTradeHandler.Finish(deal); + + // + bool useDynamicRiskManagement = DynamicRiskManagement(); + if (useDynamicRiskManagement) + { + mTradeHandler.ResetSymbolInfo(deal.symbol); + } + + // + HandleReportBalance(); + } + + /** + * Handle Force Close a Position ... + * + * @param ticket: Position Ticket ... + * @param position: XPosition ... + * @param comment: Closing Comment ... + */ + void HandleOnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // + ) override + { + // + // Finish ... + mTradeHandler.Finish( + ticket, + position, + comment // + ); + + // + HandleReportBalance(); + } + + /** + * Reset All Paused Symbols on Each New Days ... + */ + void HandleOnNewDay() override + { + mTradeHandler.ResumePausedSymbols(); + } + + /** + * Generate Identifier Tag ... + * + * @return ( string ) + */ + string GetTag() override + { + // + string result = NULL; + + // + string tagPrefix = TagPrefix(); + if (IsValid(tagPrefix)) + { + result = tagPrefix; + } + else + { + result = ""; + } + + // + result = + XC121SMCExpertToken + result; + + // + return result; + } + + // + protected: + // + + // + // Props ... + + // + datetime mLastSignalOn; + + // + XC121SMCTradeHandler *mTradeHandler; // Trade Handler ... + XCX121SMCBaseStrategy *mStrategies[]; // Registere Strategies in EA ... + + // + // Actions ... + + /** + * Apply Volume Based On Configurations on Signal ... + * + * @param signal: XSignal instance + */ + void ApplyVolumeOnSignal(XSignal &signal) + { + // + // Prepare Signal Dynamic Volume + // if Provided ... + if (UseDynamicVolume() && + DynamicVolumeStep() > 0 && + DynamicVolumeBalanceFactor() > 0) + { + // + double dVolume = mTrader.GetDynamicVolume( + signal.symbol, + DynamicVolumeBalanceFactor(), + DynamicVolumeStep() // + ); + + // + if (dVolume > 0) + { + signal.volume = dVolume; + } + else + { + signal.volume = Volume(); + } + } + else if (RiskPercentPerBalance() > 0) + { + // + double riskPercent = RiskPercentPerBalance(); + + // + double balance = mTrader.mAccount.GetBalance(); + double riskAmountPerBalance = (riskPercent * balance) / 100; + + // + double risk = signal.GetRisk(); + double points = GetPoints(signal.symbol); + double riskInPoints = risk / points; + + // + double volume = mTrader.mAccount.CalculateVolume( + signal.symbol, + riskAmountPerBalance, + riskInPoints // + ); + + // + // Check Dynamic Risk Management ... + bool allowDynamicRiskManagement = DynamicRiskManagement(); + if (allowDynamicRiskManagement) + { + // + // Calculate Dynamic Additional Risk Management Volume Multiplier ... + double mAdditionalRiskMultiplier = CalculateAdditionalVolumeMultiplier(signal); + if (mAdditionalRiskMultiplier < 1) + { + mAdditionalRiskMultiplier = 1; + } + + // + volume *= mAdditionalRiskMultiplier; + } + + // + if (volume > 0) + { + volume = NormalizeVolume(volume, signal.symbol); + } + + // + signal.volume = volume; + } + else + { + signal.volume = Volume(); + } + + // + mTradeHandler.UpdateSignal(signal); + } + + /** + * Configure Startegy ... + */ + void ConfigureStrategy(XCX121SMCBaseStrategy *&strategy) + { + // + if (strategy == NULL) + { + return; + } + + // + // Configure Alerts ... + strategy.SetAlertPrefix(GetTag()); + strategy.SetAlertLogAlerts(GetAlertLogAlerts()); + strategy.SetAlertMailAlerts(GetAlertMailAlerts()); + strategy.SetAlertPushAlerts(GetAlertPushAlerts()); + strategy.SetAlertEnableAlerts(GetAlertEnableAlerts()); + strategy.SetAlertTerminalAlerts(GetAlertTerminalAlerts()); + + // + // Confiugre Signalling ... + + // + strategy.R2R(R2R()); + strategy.AllowLong(AllowLong()); + strategy.AllowShort(AllowShort()); + strategy.MaxAllowedSpread(20); + + // + if (Disabled()) + { + strategy.Disable(); + } + else + { + strategy.Enable(); + } + + // + } + + /** + * Register an Strategy in EA ... + * + * @param strategy: XCX121SMCBaseStrategy instance ... + */ + void RegisterStrategy(XCX121SMCBaseStrategy *strategy) + { + // + if (strategy == NULL) + { + return; + } + + // + ArrayResize( + mStrategies, + ArraySize(mStrategies) + 1 // + ); + + // + mStrategies[ArraySize(mStrategies) - 1] = strategy; + } + + /** + * Re Configure All Registered Strategies ... + */ + void ReConfigureAllStrategies() + { + // + int count = ArraySize(mStrategies); + if (!IsValidSize(count)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + ConfigureStrategy(mStrategies[i]); + } + } + + // + private: + // + + // + // Props ... + + // + // Volume Management ... + double mR2R; // Signallers Risk to Reward Ratio ... + bool mUseDynamicVolume; // Use Dynamic Volume ... + double mDynamicVolumeStep; // Increase Volume Step ... + double mDynamicVolumeBalanceFactor; // Balance Factor for Generate Dynamic Volume ... + double mVolume; // Static Volume ... + bool mDynamicRiskManagement; // Dynamic Risk Management ... + double mRiskPercentPerBalance; // Risk Percent Per Balance in Each Trade ... + + // + double CalculateAdditionalVolumeMultiplier(XSignal &signal) + { + // + double result = 0; + + // + if (!signal.IsValid()) + { + return result; + } + + // + X121SMCSymbolPositionInfo info; + bool hasInfo = mTradeHandler.GetSymbolInfo( + signal.symbol, + info // + ); + if (!hasInfo) + { + return result; + } + + // + if (info.countedSLs >= 2) + { + result = (info.countedSLs / 2) + 1; + } + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/x-121.smc.lib copy.mq5 b/BKPS/14030923/Documents/BKP/x-121.smc.lib copy.mq5 new file mode 100644 index 0000000..898b58d --- /dev/null +++ b/BKPS/14030923/Documents/BKP/x-121.smc.lib copy.mq5 @@ -0,0 +1,2144 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: X121SMCLib +// Description: provide all commonly used functions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.base.class.mq5" +#include "../../Helpers/x-saherelm.x121.helper.mq5" +#include "../../Libraries/x-saherelm.common.lib.mq5" +#include "../../Libraries/x-saherelm.x-poi.lib.mq5" +#include "../../Libraries/x-saherelm.x-trade.lib.mq5" + +// +// Definitions ... + +const string X121SMCStrategyToken = "X121SMC"; + +const string X121SMCPVToken = "X121SMCPV"; +const string X121SMCBOSToken = "X121SMCBOS"; +const string X121SMCSARToken = "X121SMCSAR"; +const string X121SMCCHOCHToken = "X121SMCCHOCH"; +const string X121SMCPULLBKToken = "X121SMCPULLBK"; + +enum ENUM_X_121_SMC_PROVIDERS +{ + // + X_121_SMC_PROVIDER_NONE, + X_121_SMC_PROVIDER_PV, + X_121_SMC_PROVIDER_BOS, + X_121_SMC_PROVIDER_SAR, + X_121_SMC_PROVIDER_CHOCH, + X_121_SMC_PROVIDER_PULLBK, +}; + +enum ENUM_XPV_PIVOTS +{ + XPV_NONE, + XPV_PEAK, + XPV_VALE, +}; + +struct XPVPivot +{ + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double upper; + double lower; + + // + datetime from; + datetime to; + + // + int repetition; + + // + ENUM_XPV_PIVOTS type; + + // + // Combined all States ... + XPOIState state; + + // + XPVPivot() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + upper = 0; + lower = 0; + + // + to = NULL; + from = NULL; + symbol = NULL; + period = NULL; + + // + repetition = 0; + + // + type = XPV_NONE; + + // + state.Clean(); + } + + /** + * Validation ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(to) && + IsValid(from) && + IsValid(symbol) && + IsValid(period) && + repetition > 0 && + type != XPV_NONE && + (upper > 0 || lower > 0) + // + ; + + // + return result; + } + + /** + * Check Pivot is Peak ... + * + * @return ( bool ) + */ + bool IsPeak() + { + // + bool result = false; + + // + result = IsValid() && + type == XPV_PEAK; + + // + return result; + } + + /** + * Check Pivot is Vale ... + * + * @return ( bool ) + */ + bool IsVale() + { + // + bool result = false; + + // + result = IsValid() && + type == XPV_VALE; + + // + return result; + } + + /** + * Calculate Lower for Peaks ... + * + * @return ( double ) + */ + double CalculateLower() + { + // + double result = 0; + + // + if (!IsValid() || + !IsPeak()) + { + return result; + } + + // + int fromIndex = iBarShift( + symbol, + period, + from // + ); + + // + int toIndex = iBarShift( + symbol, + period, + to // + ); + + // + int count = + fromIndex - toIndex; + + // + int llIDX = iLowest( + symbol, + period, + MODE_LOW, + count, + toIndex // + ); + + // + result = + iLow( + symbol, + period, + llIDX // + ); + + // + return result; + } + + /** + * Calculate Upper for Vales ... + * + * @return ( double ) + */ + double CalculateUpper() + { + // + double result = 0; + + // + if (!IsValid() || + !IsVale()) + { + return result; + } + + // + int fromIndex = iBarShift( + symbol, + period, + from // + ); + + // + int toIndex = iBarShift( + symbol, + period, + to // + ); + + // + int count = + fromIndex - toIndex; + + // + int hhIDX = iHighest( + symbol, + period, + MODE_HIGH, + count, + toIndex // + ); + + // + result = + iHigh( + symbol, + period, + hhIDX // + ); + + // + return result; + } + + /** + * Calculate Range of Pivot ... + * + * @return ( double ) + */ + double CalculateRange() + { + // + double result = 0; + + // + if (!IsValid() || + upper <= 0 || + lower <= 0) + { + return result; + } + + // + result = upper - lower; + + // + return result; + } + + /** + * Calculate Middle of Pivot ... + * Used for + * @return ( double ) + */ + double CalculateMid() + { + // + double result = 0; + + // + double range = CalculateRange(); + if (range <= 0) + { + return result; + } + + // + result = lower + (range / 2); + + // + return result; + } + + /** + * Calculate Liquidity Percent for Specified Direction ... + * + * @param forDirection: ENUM_X_DIRECTION member, Specified Liquidity ... + * @param price: Double, Specified Price ... + * + * @return ( double ) + */ + double CalculateLiquidityPercent( + ENUM_X_DIRECTION forDirection, + double price = 0 // + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = state + .CalculateLiquidityPercent( + forDirection, + price // + ); + + // + return result; + } + + // + + /** + * Get Unique Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + string hash = symbol + "_" + + ToString(period) + "_" + + ToString(upper) + "," + + ToString(lower) + "_" + + ToString(from) + "," + + ToString(to); + hash = ToMD5(hash); + + // + string typeStr = + type == XPV_PEAK + ? "Peak" + : "Vale"; + + // + result = + // + "XPV_" + + typeStr + "_" + + symbol + "_" + + ToString(period) + + "_" + hash + // + ; + + // + return result; + } + + // +}; + +// +// Each Market Cycle (Time Frame) Conditions +// Model as this Structure ... +struct X121SMCCycleConditions +{ + // + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + X121Conditions x121Conditions; + + // + XPOIState state; + + // + void X121SMCStrategyConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + symbol = NULL; + period = NULL; + time = NULL; + + // + state.Clean(); + x121Conditions.Clean(); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(time); + // + ; + + // + return result; + } + + /** + * Check Cycle Conditions Has Bullish State ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool IsBullish( + XOHCL &bar // + ) + { + // + bool result = false; + + // + int index = bar.Index(); + + // + result = + // + // Check Conditions Validation ... + IsValid() && + // + // Check Bar Validation ... + bar.IsValid() && + // + // Check XCHSar Current is Bullish ... + xchsarConditions.isCBullish && + // + // Check X3VWAP is Bullish State ... + x3vwapConditions.isBullishState && + // + // Check X3VWAP is Bullish Ordered ... + x3vwapConditions.isBullishOrdered && + // + // Check Close Over X3MA Fast ... + bar.close > x3maConditions.fasts[index] + // + ; + + // + return result; + } + + /** + * Check Cycle Conditions Has Bearish State ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool IsBearish( + XOHCL &bar // + ) + { + // + bool result = false; + + // + int index = bar.Index(); + + // + result = + // + // Check Conditions Validation ... + IsValid() && + // + // Check Bar Validation ... + bar.IsValid() && + // + // Check XCHSar Current is Bearish ... + xchsarConditions.isCBearish && + // + // Check X3VWAP is Bearish State ... + x3vwapConditions.isBearishState && + // + // Check X3VWAP is Bearish Ordered ... + x3vwapConditions.isBearishOrdered && + // + // Check Close Under X3MA Fast ... + bar.close < x3maConditions.fasts[index] + // + ; + + // + return result; + } + + // + // Reporter Functions ... + + /** + * Generate Provided Scores ... + * + * @param bullishScore: Integer, reference ... + * @param bearishScore: Integer, referenceF ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + if (!IsValid()) + { + return; + } + + // + double bullScore = 0; + double bearScore = 0; + + // // + // // XPV ... + // pvConditions.GenerateScore( + // bullScore, + // bearScore // + // ); + // bullishScore += bullScore; + // bearishScore += bearScore; + } + + /** + * Generate Summary ... + * + * @param onlyCommons: Boolean ... + * @param onlyConditions: Boolean ... + * @param includeScores: Boolean ... + * @param ignoreFalseConditions: Boolean ... + * @param separator: String ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores, + true // + ); + + // // + // // XPV ... + // string pvStr = pvConditions.GenerateSummary( + // false, + // true, + // false, + // ignoreFalseConditions // + // ); + + // + string conditionsStr = + // + // pvStr + separator + + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + "----------" + separator + + (onlyConditions + ? "" + : commonStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Get Unique Identifier ... + * + * @param forObject: Boolean ... + * + * @return ( string ) + */ + string GetTag( + bool forObject = false // + ) + { + // + string result = NULL; + + // + string typeName = GetTypeName(this); + + // + if (!forObject) + { + result = typeName; + } + else + { + // + result = typeName + "_" + + symbol + "_" + ToString(period) + "_" + + ToMD5(time); + } + + // + return result; + } + + // +}; + +// +// Model Signalling Conditions ... +struct X121SMCStrategyConditions +{ + // + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Cycles Conditions here ... + X121SMCCycleConditions triggerConditions; + X121SMCCycleConditions decisionConditions; + X121SMCCycleConditions analyseConditions; + X121SMCCycleConditions verificationConditions; + X121SMCCycleConditions consolidationConditions; + X121SMCCycleConditions visionConditions; + + // + double sl; + string provider; + ENUM_X_DIRECTION marketStructureDir; + + // + void X121SMCStrategyConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + symbol = NULL; + period = NULL; + time = NULL; + + // + sl = 0; + provider = NULL; + marketStructureDir = X_DIRECTION_NONE; + + // + triggerConditions.Clean(); + decisionConditions.Clean(); + analyseConditions.Clean(); + verificationConditions.Clean(); + consolidationConditions.Clean(); + visionConditions.Clean(); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(time); + + // + return result; + } + + /** + * Check Conditions has Ddirection or not ... + * + * @param dir: ENUM_X_DIRECTIOn member ... + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool HasDirection( + ENUM_X_DIRECTION &dir, + XOHCL &bar // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + result = IsValid() && + bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + int index = bar.Index(); + + // + // Parse Cycles Conditions ... + + // + // Vision ... + + // + bool isVisionBullish = + // + // XCHSar Current is Bullish ... + visionConditions.xchsarConditions.isCBullish && + // + // Close Over X3MA Fast ... + bar.close > visionConditions.x3maConditions.fasts[index] && + // + // X3VWap Fast is Bullish ... + visionConditions.x3vwapConditions.fastStates[index] == + X3VWAP_STATE_BULLISH + // + ; + + // + bool isVisionBearish = + // + // XCHSar Current is Bearish ... + visionConditions.xchsarConditions.isCBearish && + // + // Close Under X3MA Fast ... + bar.close < visionConditions.x3maConditions.fasts[index] && + // + // X3VWap Fast is Bearish ... + visionConditions.x3vwapConditions.fastStates[index] == + X3VWAP_STATE_BEARISH + // + ; + + // + // Check Vision Has Conditions or not ... + bool hasVisionConditions = + isVisionBullish || + isVisionBearish; + result = hasVisionConditions; + if (!result) + { + return result; + } + + // + // Consolidation ... + + // + bool isConsolidationBullish = consolidationConditions.IsBullish(bar); + bool isConsolidationBearish = consolidationConditions.IsBearish(bar); + bool hasConsolidationConditions = + isConsolidationBullish || + isConsolidationBearish; + result = hasConsolidationConditions; + if (!result) + { + return result; + } + + // + // Verification ... + + // + bool isVerificationBullish = verificationConditions.IsBullish(bar); + bool isVerificationBearish = verificationConditions.IsBearish(bar); + bool hasVerificationConditions = + isVerificationBullish || + isVerificationBearish; + result = hasVerificationConditions; + if (!result) + { + return result; + } + + // + // Analyse ... + + // + bool isAnalyseBullish = analyseConditions.IsBullish(bar); + bool isAnalyseBearish = analyseConditions.IsBearish(bar); + bool hasAnalyseConditions = + isAnalyseBullish || + isAnalyseBearish; + result = hasAnalyseConditions; + if (!result) + { + return result; + } + + // + // Decision ... + + // + bool isDecisionBullish = decisionConditions.IsBullish(bar); + bool isDecisionBearish = decisionConditions.IsBearish(bar); + bool hasDecisionConditions = + isDecisionBullish || + isDecisionBearish; + result = hasDecisionConditions; + if (!result) + { + return result; + } + + // + // Analyse Conditions ... + bool hasBullishConditions = + // + isVisionBullish && + isConsolidationBullish && + isVerificationBullish && + isAnalyseBullish && + isDecisionBullish + // + ; + bool hasBearishConditions = + // + isVisionBearish && + isConsolidationBearish && + isVerificationBearish && + isAnalyseBearish && + isDecisionBearish + // + ; + result = hasBullishConditions || + hasBearishConditions; + if (!result) + { + return result; + } + + // + // Specified Conditions Direction ... + dir = + hasBullishConditions + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Reporter Functions ... + + /** + * Generate Provided Scores ... + * + * @param bullishScore: Integer, reference ... + * @param bearishScore: Integer, referenceF ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + if (!IsValid()) + { + return; + } + + // + double bullScore = 0; + double bearScore = 0; + + // // + // // XPV ... + // pvConditions.GenerateScore( + // bullScore, + // bearScore // + // ); + // bullishScore += bullScore; + // bearishScore += bearScore; + } + + /** + * Generate Summary ... + * + * @param onlyCommons: Boolean ... + * @param onlyConditions: Boolean ... + * @param includeScores: Boolean ... + * @param ignoreFalseConditions: Boolean ... + * @param separator: String ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores, + true // + ); + + // // + // // XPV ... + // string pvStr = pvConditions.GenerateSummary( + // false, + // true, + // false, + // ignoreFalseConditions // + // ); + + // + string conditionsStr = + // + // pvStr + separator + + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + "----------" + separator + + (onlyConditions + ? "" + : commonStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Get Unique Identifier ... + * + * @param forObject: Boolean ... + * + * @return ( string ) + */ + string GetTag( + bool forObject = false // + ) + { + // + string result = NULL; + + // + string typeName = GetTypeName(this); + + // + if (!forObject) + { + result = typeName; + } + else + { + // + result = typeName + "_" + + symbol + "_" + ToString(period) + "_" + + ToMD5(time); + } + + // + return result; + } + + // +}; + +// +// +// + +typedef void (*TOnX121SMCSignal)( + XSignal &signal, + X121SMCStrategyConditions &conditions // +); + +// +// Extentions ... + +/** + * Find Oldest Pivot Index ... + * + * @param pivots: XPVPivot instance ... + * @return ( int ) + */ +int FindOldestPivotIndex( + XPVPivot &pivots[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(pivots); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = pivots[i]; + + // + bool isOldest = true; + for (int j = 0; j < count; j++) + { + // + XPVPivot jPivot = pivots[j]; + + // + isOldest = iPivot.from <= jPivot.from; + if (!isOldest) + { + break; + } + } + + // + if (isOldest) + { + // + result = i; + break; + } + } + + // + return result; +} + +/** + * Sort Pivots Based On From Date ... + * + * @param pivots: XPVPivot instance Collection reference ... + */ +void SortPivots( + XPVPivot &pivots[] // +) +{ + // + XPVPivot tmp[]; + Copy( + pivots, + tmp // + ); + + // + Clean(pivots); + + // + while (ArraySize(tmp) > 0) + { + // + if (ArraySize(tmp) == 1) + { + // + AddRef( + tmp[0], + pivots // + ); + + // + ArrayRemove( + tmp, + 0, + 1); + } + else + { + // + int idx = FindOldestPivotIndex(tmp); + if (IsValidIndex(idx)) + { + // + AddRef( + tmp[idx], + pivots // + ); + + // + ArrayRemove( + tmp, + idx, + 1 // + ); + } + } + } + + // + Clean(tmp); +} + +bool IsPivotBreaked( + XPVPivot &pivot, + XPVPivot &pivots[] // +) +{ + // + bool result = false; + + // + result = pivot.IsValid(); + if (!result) + { + return result; + } + + // + int count = ArraySize(pivots); + result = IsValidSize(pivots); + if (!result) + { + return result; + } + + // + // For Peaks Highs Must not Broked ... + // For Vales Lows Must not Broked ... + bool isPeak = pivot.IsPeak(); + + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = pivots[i]; + + // + result = isPeak + ? iPivot.upper > pivot.upper + : iPivot.lower < pivot.lower; + if (result) + { + break; + } + } + + // + return result; +} + +/** + * Filter Broken Pivots for Detect Order Flow ... + * + * @param pivots: XPVPivot instance Collection reference ... + */ +void FilterBrokenPivots( + XPVPivot &pivots[] // +) +{ + // + XPVPivot tmp[]; + Copy( + pivots, + tmp // + ); + + // + Clean(pivots); + + // + while (ArraySize(tmp) > 0) + { + // + if (ArraySize(tmp) == 1) + { + // + AddRef( + tmp[0], + pivots // + ); + + // + ArrayRemove( + tmp, + 0, + 1 // + ); + } + else + { + // + XPVPivot pivot = tmp[0]; + + // + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + bool isBreaked = IsPivotBreaked( + pivot, + tmp // + ); + if (!isBreaked) + { + // + AddRef( + pivot, + pivots // + ); + } + } + } + + // + Clean(tmp); +} + +/** + * Calculate Order Flow Direction ... + * + * @param orderFlow: XPVPivot instance Collection reference ... + * @param dir: ENUM_X_DIRECTION member reference, Hold's Calculated Direction ... + * + * @return ( bool ) + */ +bool DetectPivotDirection( + XPVPivot &orderFlow[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + int count = ArraySize(orderFlow); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + // For Bullish Direction all Exists lowers must be Greater or Equal Prev ... + bool isBullish = false; + bool canLookupForBullish = true; + + // + // For Bearish Direction all Exists uppers must be Lesser or Equal Prev ... + bool isBearish = false; + bool canLookupForBearish = true; + + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = orderFlow[i]; + + // + XPVPivot tmp[]; + Copy( + orderFlow, + tmp // + ); + ArrayRemove( + tmp, + 0, + i + 1 // + ); + + // + int tmpCount = ArraySize(tmp); + if (IsValidSize(tmpCount)) + { + // + for (int j = 0; j < tmpCount; j++) + { + // + XPVPivot jPivot = tmp[j]; + + // + // Check Bullish Direction ... + isBullish = + canLookupForBullish && + jPivot.lower >= iPivot.lower; + if (!isBullish) + { + canLookupForBullish = false; + } + + // + // Check Bearish Direction ... + isBearish = + canLookupForBearish && + jPivot.upper <= iPivot.upper; + if (!isBearish) + { + canLookupForBearish = false; + } + + // + if (!canLookupForBullish && + !canLookupForBearish) + { + break; + } + } + } + Clean(tmp); + } + + // + if (isBullish && + !isBearish) + { + dir = X_DIRECTION_BULLISH; + } + else if (isBearish && + !isBullish) + { + dir = X_DIRECTION_BEARISH; + } + + // + result = dir != X_DIRECTION_NONE; + + // + return result; +} + +/** + * Detect all POIs which inside a Pivot ... + * + * @param pivot: XPVPivot instance, Specified Pivot ... + * @param source: XPOIState instance, Reference to Source State ... + * @param state: XPOIState instance, Reference to Detected Pivots ... + * @param lookupSwingHighs: Boolean ... + * @param lookupSwingLows: Boolean ... + * @param lookupSupportZones: Boolean ... + * @param lookupResistanceZones: Boolean ... + * @param lookupSupplyZones: Boolean ... + * @param lookupDemandZones: Boolean ... + * @param lookupBullishOrderBlocks: Boolean ... + * @param lookupBearishOrderBlocks: Boolean ... + * @param lookupBullishFairValueGaps: Boolean ... + * @param lookupBearishFairValueGaps: Boolean ... + * @param lookupBullishRejectionBars: Boolean ... + * @param lookupBearishRejectionBars: Boolean ... + * @param lookupBullishMomentumBars: Boolean ... + * @param lookupBearishMomentumBars: Boolean ... + */ +void DetectPivotPOIs( + XPVPivot &pivot, + XPOIState &source, + XPOIState &state, + bool lookupSwingHighs = true, + bool lookupSwingLows = true, + bool lookupSupportZones = true, + bool lookupResistanceZones = true, + bool lookupSupplyZones = true, + bool lookupDemandZones = true, + bool lookupBullishOrderBlocks = true, + bool lookupBearishOrderBlocks = true, + bool lookupBullishFairValueGaps = true, + bool lookupBearishFairValueGaps = true, + bool lookupBullishRejectionBars = true, + bool lookupBearishRejectionBars = true, + bool lookupBullishMomentumBars = true, + bool lookupBearishMomentumBars = true // +) +{ + // + state.Clean(); + + // + if (!pivot.IsValid()) + { + return; + } + + // + int count = 0; + + // + state.symbol = pivot.symbol; + state.period = pivot.period; + state.time = TimeCurrent(); + + // + // Swings ... + + // + // Swing High ... + if (lookupSwingHighs) + { + // + count = ArraySize(source.swingHighs); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing *iSwing = source.swingHighs[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.high <= pivot.upper; + if (isInside) + { + // + Add( + iSwing, + state.swingHighs // + ); + } + } + } + } + + // + // Swing Low ... + if (lookupSwingLows) + { + // + count = ArraySize(source.swingLows); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing *iSwing = source.swingLows[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.low >= pivot.lower; + if (isInside) + { + // + Add( + iSwing, + state.swingLows // + ); + } + } + } + } + + // + // Support and Resistance Zones ... + + // + // Support Zones ... + if (lookupSupportZones) + { + // + count = ArraySize(source.supportZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZone *iZone = source.supportZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.supportZones // + ); + } + } + } + } + + // + // Resistance Zones ... + if (lookupResistanceZones) + { + // + count = ArraySize(source.resistanceZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZone *iZone = source.resistanceZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.resistanceZones // + ); + } + } + } + } + + // + // Supply and Demand Zones ... + + // + // Supply Zones ... + if (lookupSupplyZones) + { + // + count = ArraySize(source.supplyZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupplyZone *iZone = source.supplyZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.supplyZones // + ); + } + } + } + } + + // + // Demand Zones ... + if (lookupDemandZones) + { + // + count = ArraySize(source.demandZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCDemandZone *iZone = source.demandZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.demandZones // + ); + } + } + } + } + + // + // Order Blocks ... + + // + // Bullish Order Blocks ... + if (lookupBullishOrderBlocks) + { + // + count = ArraySize(source.bullishOrderBlocks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = source.bullishOrderBlocks[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bullishOrderBlocks // + ); + } + } + } + } + + // + // Bearish Order Blocks ... + if (lookupBearishOrderBlocks) + { + // + count = ArraySize(source.bearishOrderBlocks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = source.bearishOrderBlocks[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bearishOrderBlocks // + ); + } + } + } + } + + // + // Fair Value Gaps ... + + // + // Bullish Fair Value Gaps ... + if (lookupBullishFairValueGaps) + { + // + count = ArraySize(source.bullishFairValueGaps); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = source.bullishFairValueGaps[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bullishFairValueGaps // + ); + } + } + } + } + + // + // Bearish Fair Value Gaps ... + if (lookupBearishFairValueGaps) + { + // + count = ArraySize(source.bearishFairValueGaps); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = source.bearishFairValueGaps[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bearishFairValueGaps // + ); + } + } + } + } + + // + // Rejection Bars ... + + // + // Bullish Rejection Bars ... + if (lookupBullishRejectionBars) + { + // + count = ArraySize(source.bullishRejectionBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar *iRejection = source.bullishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.low <= pivot.upper && + iBar.low >= pivot.lower; + if (isInside) + { + // + Add( + iRejection, + state.bullishRejectionBars // + ); + } + } + } + } + + // + // Bearish Rejection Bars ... + if (lookupBearishRejectionBars) + { + // + count = ArraySize(source.bearishRejectionBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar *iRejection = source.bearishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.high <= pivot.upper && + iBar.high >= pivot.lower; + if (isInside) + { + // + Add( + iRejection, + state.bearishRejectionBars // + ); + } + } + } + } + + // + // Momentum Bars ... + + // + // Bullish Momentum Bars ... + if (lookupBullishMomentumBars) + { + // + count = ArraySize(source.bullishMomentumBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar *iMomentum = source.bullishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.low <= pivot.upper && + iBar.low >= pivot.lower; + if (isInside) + { + // + Add( + iMomentum, + state.bullishMomentumBars // + ); + } + } + } + } + + // + // Bearish Momenum Bars ... + if (lookupBearishMomentumBars) + { + // + count = ArraySize(source.bearishMomentumBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar *iMomentum = source.bearishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.high <= pivot.upper && + iBar.high >= pivot.lower; + if (isInside) + { + // + Add( + iMomentum, + state.bearishMomentumBars // + ); + } + } + } + } +} + +// +// Provider Extensions ... + +/** + * Validate a Signal Provider ... + * + * @param value: ENUM_X_121_SMC_PROVIDERS member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_121_SMC_PROVIDERS value) +{ + // + bool result = false; + + // + result = value != X_121_SMC_PROVIDER_NONE; + + // + return result; +} + +/** + * Converts a Signal Provider to String ... + * + * @param value: ENUM_X_121_SMC_PROVIDERS member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_121_SMC_PROVIDERS value) +{ + // + string result = NULL; + + // + if (!IsValid(value)) + { + return result; + } + + // + switch (value) + { + // + case X_121_SMC_PROVIDER_PV: + result = X121SMCPVToken; + break; + + // + case X_121_SMC_PROVIDER_BOS: + result = X121SMCBOSToken; + break; + + // + case X_121_SMC_PROVIDER_SAR: + result = X121SMCSARToken; + break; + + // + case X_121_SMC_PROVIDER_CHOCH: + result = X121SMCCHOCHToken; + break; + + // + case X_121_SMC_PROVIDER_PULLBK: + result = X121SMCPULLBKToken; + break; + } + + // + return result; +} + +/** + * Parse Specified String as a Signal Provider ... + * + * @param value: String ... + * + * @return ( ENUM_X_121_SMC_PROVIDERS ) + */ +ENUM_X_121_SMC_PROVIDERS ParseProvider(string value) +{ + // + ENUM_X_121_SMC_PROVIDERS result = X_121_SMC_PROVIDER_NONE; + + // + if (!IsValid(value)) + { + return result; + } + + // + if (Contains(X121SMCPVToken, value)) + { + result = X_121_SMC_PROVIDER_PV; + } + else if (Contains(X121SMCBOSToken, value)) + { + result = X_121_SMC_PROVIDER_BOS; + } + else if (Contains(X121SMCSARToken, value)) + { + result = X_121_SMC_PROVIDER_SAR; + } + else if (Contains(X121SMCCHOCHToken, value)) + { + result = X_121_SMC_PROVIDER_CHOCH; + } + else if (Contains(X121SMCPULLBKToken, value)) + { + result = X_121_SMC_PROVIDER_PULLBK; + } + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/x-121.smc.lib.mq5 b/BKPS/14030923/Documents/BKP/x-121.smc.lib.mq5 new file mode 100644 index 0000000..19d97b4 --- /dev/null +++ b/BKPS/14030923/Documents/BKP/x-121.smc.lib.mq5 @@ -0,0 +1,2161 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: X121SMCLib +// Description: provide all commonly used functions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.base.class.mq5" +#include "../../Helpers/x-saherelm.x3ma.helper.mq5" +#include "../../Helpers/x-saherelm.x3vwap.helper.mq5" +#include "../../Helpers/x-saherelm.xchsar.helper.mq5" +#include "../../Helpers/x-saherelm.xpv.helper.mq5" +#include "../../Libraries/x-saherelm.common.lib.mq5" +#include "../../Libraries/x-saherelm.x-poi.lib.mq5" +#include "../../Libraries/x-saherelm.x-trade.lib.mq5" + +// +// Definitions ... + +const string X121SMCStrategyToken = "X121SMC"; + +const string X121SMCPVToken = "X121SMCPV"; +const string X121SMCBOSToken = "X121SMCBOS"; +const string X121SMCSARToken = "X121SMCSAR"; +const string X121SMCCHOCHToken = "X121SMCCHOCH"; +const string X121SMCPULLBKToken = "X121SMCPULLBK"; + +enum ENUM_X_121_SMC_PROVIDERS +{ + // + X_121_SMC_PROVIDER_NONE, + X_121_SMC_PROVIDER_PV, + X_121_SMC_PROVIDER_BOS, + X_121_SMC_PROVIDER_SAR, + X_121_SMC_PROVIDER_CHOCH, + X_121_SMC_PROVIDER_PULLBK, +}; + +enum ENUM_XPV_PIVOTS +{ + XPV_NONE, + XPV_PEAK, + XPV_VALE, +}; + +struct XPVPivot +{ + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double upper; + double lower; + + // + datetime from; + datetime to; + + // + int repetition; + + // + ENUM_XPV_PIVOTS type; + + // + // Combined all States ... + XPOIState state; + + // + XPVPivot() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + upper = 0; + lower = 0; + + // + to = NULL; + from = NULL; + symbol = NULL; + period = NULL; + + // + repetition = 0; + + // + type = XPV_NONE; + + // + state.Clean(); + } + + /** + * Validation ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(to) && + IsValid(from) && + IsValid(symbol) && + IsValid(period) && + repetition > 0 && + type != XPV_NONE && + (upper > 0 || lower > 0) + // + ; + + // + return result; + } + + /** + * Check Pivot is Peak ... + * + * @return ( bool ) + */ + bool IsPeak() + { + // + bool result = false; + + // + result = IsValid() && + type == XPV_PEAK; + + // + return result; + } + + /** + * Check Pivot is Vale ... + * + * @return ( bool ) + */ + bool IsVale() + { + // + bool result = false; + + // + result = IsValid() && + type == XPV_VALE; + + // + return result; + } + + /** + * Calculate Lower for Peaks ... + * + * @return ( double ) + */ + double CalculateLower() + { + // + double result = 0; + + // + if (!IsValid() || + !IsPeak()) + { + return result; + } + + // + int fromIndex = iBarShift( + symbol, + period, + from // + ); + + // + int toIndex = iBarShift( + symbol, + period, + to // + ); + + // + int count = + fromIndex - toIndex; + + // + int llIDX = iLowest( + symbol, + period, + MODE_LOW, + count, + toIndex // + ); + + // + result = + iLow( + symbol, + period, + llIDX // + ); + + // + return result; + } + + /** + * Calculate Upper for Vales ... + * + * @return ( double ) + */ + double CalculateUpper() + { + // + double result = 0; + + // + if (!IsValid() || + !IsVale()) + { + return result; + } + + // + int fromIndex = iBarShift( + symbol, + period, + from // + ); + + // + int toIndex = iBarShift( + symbol, + period, + to // + ); + + // + int count = + fromIndex - toIndex; + + // + int hhIDX = iHighest( + symbol, + period, + MODE_HIGH, + count, + toIndex // + ); + + // + result = + iHigh( + symbol, + period, + hhIDX // + ); + + // + return result; + } + + /** + * Calculate Range of Pivot ... + * + * @return ( double ) + */ + double CalculateRange() + { + // + double result = 0; + + // + if (!IsValid() || + upper <= 0 || + lower <= 0) + { + return result; + } + + // + result = upper - lower; + + // + return result; + } + + /** + * Calculate Middle of Pivot ... + * Used for + * @return ( double ) + */ + double CalculateMid() + { + // + double result = 0; + + // + double range = CalculateRange(); + if (range <= 0) + { + return result; + } + + // + result = lower + (range / 2); + + // + return result; + } + + /** + * Calculate Liquidity Percent for Specified Direction ... + * + * @param forDirection: ENUM_X_DIRECTION member, Specified Liquidity ... + * @param price: Double, Specified Price ... + * + * @return ( double ) + */ + double CalculateLiquidityPercent( + ENUM_X_DIRECTION forDirection, + double price = 0 // + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = state + .CalculateLiquidityPercent( + forDirection, + price // + ); + + // + return result; + } + + // + + /** + * Get Unique Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + string hash = symbol + "_" + + ToString(period) + "_" + + ToString(upper) + "," + + ToString(lower) + "_" + + ToString(from) + "," + + ToString(to); + hash = ToMD5(hash); + + // + string typeStr = + type == XPV_PEAK + ? "Peak" + : "Vale"; + + // + result = + // + "XPV_" + + typeStr + "_" + + symbol + "_" + + ToString(period) + + "_" + hash + // + ; + + // + return result; + } + + // +}; + +// +// Each Market Cycle (Time Frame) Conditions +// Model as this Structure ... +struct X121SMCCycleConditions +{ + // + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + XPVConditions xpvConditions; + X3MAConditions x3maConditions; + X3VWAPConditions x3vwapConditions; + XCHSARConditions xchsarConditions; + + // + XPOIState state; + + // + void X121SMCStrategyConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + symbol = NULL; + period = NULL; + time = NULL; + + // + state.Clean(); + xpvConditions.Clean(); + x3maConditions.Clean(); + x3vwapConditions.Clean(); + xchsarConditions.Clean(); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(time); + // + ; + + // + return result; + } + + /** + * Check Cycle Conditions Has Bullish State ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool IsBullish( + XOHCL &bar // + ) + { + // + bool result = false; + + // + int index = bar.Index(); + + // + result = + // + // Check Conditions Validation ... + IsValid() && + // + // Check Bar Validation ... + bar.IsValid() && + // + // Check XCHSar Current is Bullish ... + xchsarConditions.isCBullish && + // + // Check X3VWAP is Bullish State ... + x3vwapConditions.isBullishState && + // + // Check X3VWAP is Bullish Ordered ... + x3vwapConditions.isBullishOrdered && + // + // Check Close Over X3MA Fast ... + bar.close > x3maConditions.fasts[index] + // + ; + + // + return result; + } + + /** + * Check Cycle Conditions Has Bearish State ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool IsBearish( + XOHCL &bar // + ) + { + // + bool result = false; + + // + int index = bar.Index(); + + // + result = + // + // Check Conditions Validation ... + IsValid() && + // + // Check Bar Validation ... + bar.IsValid() && + // + // Check XCHSar Current is Bearish ... + xchsarConditions.isCBearish && + // + // Check X3VWAP is Bearish State ... + x3vwapConditions.isBearishState && + // + // Check X3VWAP is Bearish Ordered ... + x3vwapConditions.isBearishOrdered && + // + // Check Close Under X3MA Fast ... + bar.close < x3maConditions.fasts[index] + // + ; + + // + return result; + } + + // + // Reporter Functions ... + + /** + * Generate Provided Scores ... + * + * @param bullishScore: Integer, reference ... + * @param bearishScore: Integer, referenceF ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + if (!IsValid()) + { + return; + } + + // + double bullScore = 0; + double bearScore = 0; + + // // + // // XPV ... + // pvConditions.GenerateScore( + // bullScore, + // bearScore // + // ); + // bullishScore += bullScore; + // bearishScore += bearScore; + } + + /** + * Generate Summary ... + * + * @param onlyCommons: Boolean ... + * @param onlyConditions: Boolean ... + * @param includeScores: Boolean ... + * @param ignoreFalseConditions: Boolean ... + * @param separator: String ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores, + true // + ); + + // // + // // XPV ... + // string pvStr = pvConditions.GenerateSummary( + // false, + // true, + // false, + // ignoreFalseConditions // + // ); + + // + string conditionsStr = + // + // pvStr + separator + + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + "----------" + separator + + (onlyConditions + ? "" + : commonStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Get Unique Identifier ... + * + * @param forObject: Boolean ... + * + * @return ( string ) + */ + string GetTag( + bool forObject = false // + ) + { + // + string result = NULL; + + // + string typeName = GetTypeName(this); + + // + if (!forObject) + { + result = typeName; + } + else + { + // + result = typeName + "_" + + symbol + "_" + ToString(period) + "_" + + ToMD5(time); + } + + // + return result; + } + + // +}; + +// +// Model Signalling Conditions ... +struct X121SMCStrategyConditions +{ + // + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Cycles Conditions here ... + X121SMCCycleConditions triggerConditions; + X121SMCCycleConditions decisionConditions; + X121SMCCycleConditions analyseConditions; + X121SMCCycleConditions verificationConditions; + X121SMCCycleConditions consolidationConditions; + X121SMCCycleConditions visionConditions; + + // + double sl; + string provider; + XCOrderBlock *visionBullOB; + XCOrderBlock *visionBearOB; + XCOrderBlock *consolidationBullOB; + XCOrderBlock *consolidationBearOB; + ENUM_X_DIRECTION marketStructureDir; + + // + void X121SMCStrategyConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + symbol = NULL; + period = NULL; + time = NULL; + + // + sl = 0; + provider = NULL; + visionBullOB = NULL; + visionBearOB = NULL; + consolidationBullOB = NULL; + consolidationBearOB = NULL; + marketStructureDir = X_DIRECTION_NONE; + + // + triggerConditions.Clean(); + decisionConditions.Clean(); + analyseConditions.Clean(); + verificationConditions.Clean(); + consolidationConditions.Clean(); + visionConditions.Clean(); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(time); + + // + return result; + } + + /** + * Check Conditions has Ddirection or not ... + * + * @param dir: ENUM_X_DIRECTIOn member ... + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool HasDirection( + ENUM_X_DIRECTION &dir, + XOHCL &bar // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + result = IsValid() && + bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + int index = bar.Index(); + + // + // Parse Cycles Conditions ... + + // + // Vision ... + + // + bool isVisionBullish = + // + // XCHSar Current is Bullish ... + visionConditions.xchsarConditions.isCBullish && + // + // Close Over X3MA Fast ... + bar.close > visionConditions.x3maConditions.fasts[index] && + // + // X3VWap Fast is Bullish ... + visionConditions.x3vwapConditions.fastStates[index] == + X3VWAP_STATE_BULLISH + // + ; + + // + bool isVisionBearish = + // + // XCHSar Current is Bearish ... + visionConditions.xchsarConditions.isCBearish && + // + // Close Under X3MA Fast ... + bar.close < visionConditions.x3maConditions.fasts[index] && + // + // X3VWap Fast is Bearish ... + visionConditions.x3vwapConditions.fastStates[index] == + X3VWAP_STATE_BEARISH + // + ; + + // + // Check Vision Has Conditions or not ... + bool hasVisionConditions = + isVisionBullish || + isVisionBearish; + result = hasVisionConditions; + if (!result) + { + return result; + } + + // + // Consolidation ... + + // + bool isConsolidationBullish = consolidationConditions.IsBullish(bar); + bool isConsolidationBearish = consolidationConditions.IsBearish(bar); + bool hasConsolidationConditions = + isConsolidationBullish || + isConsolidationBearish; + result = hasConsolidationConditions; + if (!result) + { + return result; + } + + // + // Verification ... + + // + bool isVerificationBullish = verificationConditions.IsBullish(bar); + bool isVerificationBearish = verificationConditions.IsBearish(bar); + bool hasVerificationConditions = + isVerificationBullish || + isVerificationBearish; + result = hasVerificationConditions; + if (!result) + { + return result; + } + + // + // Analyse ... + + // + bool isAnalyseBullish = analyseConditions.IsBullish(bar); + bool isAnalyseBearish = analyseConditions.IsBearish(bar); + bool hasAnalyseConditions = + isAnalyseBullish || + isAnalyseBearish; + result = hasAnalyseConditions; + if (!result) + { + return result; + } + + // + // Decision ... + + // + bool isDecisionBullish = decisionConditions.IsBullish(bar); + bool isDecisionBearish = decisionConditions.IsBearish(bar); + bool hasDecisionConditions = + isDecisionBullish || + isDecisionBearish; + result = hasDecisionConditions; + if (!result) + { + return result; + } + + // + // Analyse Conditions ... + bool hasBullishConditions = + // + isVisionBullish && + isConsolidationBullish && + isVerificationBullish && + isAnalyseBullish && + isDecisionBullish + // + ; + bool hasBearishConditions = + // + isVisionBearish && + isConsolidationBearish && + isVerificationBearish && + isAnalyseBearish && + isDecisionBearish + // + ; + result = hasBullishConditions || + hasBearishConditions; + if (!result) + { + return result; + } + + // + // Specified Conditions Direction ... + dir = + hasBullishConditions + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Reporter Functions ... + + /** + * Generate Provided Scores ... + * + * @param bullishScore: Integer, reference ... + * @param bearishScore: Integer, referenceF ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + if (!IsValid()) + { + return; + } + + // + double bullScore = 0; + double bearScore = 0; + + // // + // // XPV ... + // pvConditions.GenerateScore( + // bullScore, + // bearScore // + // ); + // bullishScore += bullScore; + // bearishScore += bearScore; + } + + /** + * Generate Summary ... + * + * @param onlyCommons: Boolean ... + * @param onlyConditions: Boolean ... + * @param includeScores: Boolean ... + * @param ignoreFalseConditions: Boolean ... + * @param separator: String ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores, + true // + ); + + // // + // // XPV ... + // string pvStr = pvConditions.GenerateSummary( + // false, + // true, + // false, + // ignoreFalseConditions // + // ); + + // + string conditionsStr = + // + // pvStr + separator + + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + "----------" + separator + + (onlyConditions + ? "" + : commonStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Get Unique Identifier ... + * + * @param forObject: Boolean ... + * + * @return ( string ) + */ + string GetTag( + bool forObject = false // + ) + { + // + string result = NULL; + + // + string typeName = GetTypeName(this); + + // + if (!forObject) + { + result = typeName; + } + else + { + // + result = typeName + "_" + + symbol + "_" + ToString(period) + "_" + + ToMD5(time); + } + + // + return result; + } + + // +}; + +// +// +// + +typedef void (*TOnX121SMCSignal)( + XSignal &signal, + X121SMCStrategyConditions &conditions // +); + +// +// Extentions ... + +/** + * Find Oldest Pivot Index ... + * + * @param pivots: XPVPivot instance ... + * @return ( int ) + */ +int FindOldestPivotIndex( + XPVPivot &pivots[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(pivots); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = pivots[i]; + + // + bool isOldest = true; + for (int j = 0; j < count; j++) + { + // + XPVPivot jPivot = pivots[j]; + + // + isOldest = iPivot.from <= jPivot.from; + if (!isOldest) + { + break; + } + } + + // + if (isOldest) + { + // + result = i; + break; + } + } + + // + return result; +} + +/** + * Sort Pivots Based On From Date ... + * + * @param pivots: XPVPivot instance Collection reference ... + */ +void SortPivots( + XPVPivot &pivots[] // +) +{ + // + XPVPivot tmp[]; + Copy( + pivots, + tmp // + ); + + // + Clean(pivots); + + // + while (ArraySize(tmp) > 0) + { + // + if (ArraySize(tmp) == 1) + { + // + AddRef( + tmp[0], + pivots // + ); + + // + ArrayRemove( + tmp, + 0, + 1); + } + else + { + // + int idx = FindOldestPivotIndex(tmp); + if (IsValidIndex(idx)) + { + // + AddRef( + tmp[idx], + pivots // + ); + + // + ArrayRemove( + tmp, + idx, + 1 // + ); + } + } + } + + // + Clean(tmp); +} + +bool IsPivotBreaked( + XPVPivot &pivot, + XPVPivot &pivots[] // +) +{ + // + bool result = false; + + // + result = pivot.IsValid(); + if (!result) + { + return result; + } + + // + int count = ArraySize(pivots); + result = IsValidSize(pivots); + if (!result) + { + return result; + } + + // + // For Peaks Highs Must not Broked ... + // For Vales Lows Must not Broked ... + bool isPeak = pivot.IsPeak(); + + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = pivots[i]; + + // + result = isPeak + ? iPivot.upper > pivot.upper + : iPivot.lower < pivot.lower; + if (result) + { + break; + } + } + + // + return result; +} + +/** + * Filter Broken Pivots for Detect Order Flow ... + * + * @param pivots: XPVPivot instance Collection reference ... + */ +void FilterBrokenPivots( + XPVPivot &pivots[] // +) +{ + // + XPVPivot tmp[]; + Copy( + pivots, + tmp // + ); + + // + Clean(pivots); + + // + while (ArraySize(tmp) > 0) + { + // + if (ArraySize(tmp) == 1) + { + // + AddRef( + tmp[0], + pivots // + ); + + // + ArrayRemove( + tmp, + 0, + 1 // + ); + } + else + { + // + XPVPivot pivot = tmp[0]; + + // + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + bool isBreaked = IsPivotBreaked( + pivot, + tmp // + ); + if (!isBreaked) + { + // + AddRef( + pivot, + pivots // + ); + } + } + } + + // + Clean(tmp); +} + +/** + * Calculate Order Flow Direction ... + * + * @param orderFlow: XPVPivot instance Collection reference ... + * @param dir: ENUM_X_DIRECTION member reference, Hold's Calculated Direction ... + * + * @return ( bool ) + */ +bool DetectPivotDirection( + XPVPivot &orderFlow[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + int count = ArraySize(orderFlow); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + // For Bullish Direction all Exists lowers must be Greater or Equal Prev ... + bool isBullish = false; + bool canLookupForBullish = true; + + // + // For Bearish Direction all Exists uppers must be Lesser or Equal Prev ... + bool isBearish = false; + bool canLookupForBearish = true; + + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = orderFlow[i]; + + // + XPVPivot tmp[]; + Copy( + orderFlow, + tmp // + ); + ArrayRemove( + tmp, + 0, + i + 1 // + ); + + // + int tmpCount = ArraySize(tmp); + if (IsValidSize(tmpCount)) + { + // + for (int j = 0; j < tmpCount; j++) + { + // + XPVPivot jPivot = tmp[j]; + + // + // Check Bullish Direction ... + isBullish = + canLookupForBullish && + jPivot.lower >= iPivot.lower; + if (!isBullish) + { + canLookupForBullish = false; + } + + // + // Check Bearish Direction ... + isBearish = + canLookupForBearish && + jPivot.upper <= iPivot.upper; + if (!isBearish) + { + canLookupForBearish = false; + } + + // + if (!canLookupForBullish && + !canLookupForBearish) + { + break; + } + } + } + Clean(tmp); + } + + // + if (isBullish && + !isBearish) + { + dir = X_DIRECTION_BULLISH; + } + else if (isBearish && + !isBullish) + { + dir = X_DIRECTION_BEARISH; + } + + // + result = dir != X_DIRECTION_NONE; + + // + return result; +} + +/** + * Detect all POIs which inside a Pivot ... + * + * @param pivot: XPVPivot instance, Specified Pivot ... + * @param source: XPOIState instance, Reference to Source State ... + * @param state: XPOIState instance, Reference to Detected Pivots ... + * @param lookupSwingHighs: Boolean ... + * @param lookupSwingLows: Boolean ... + * @param lookupSupportZones: Boolean ... + * @param lookupResistanceZones: Boolean ... + * @param lookupSupplyZones: Boolean ... + * @param lookupDemandZones: Boolean ... + * @param lookupBullishOrderBlocks: Boolean ... + * @param lookupBearishOrderBlocks: Boolean ... + * @param lookupBullishFairValueGaps: Boolean ... + * @param lookupBearishFairValueGaps: Boolean ... + * @param lookupBullishRejectionBars: Boolean ... + * @param lookupBearishRejectionBars: Boolean ... + * @param lookupBullishMomentumBars: Boolean ... + * @param lookupBearishMomentumBars: Boolean ... + */ +void DetectPivotPOIs( + XPVPivot &pivot, + XPOIState &source, + XPOIState &state, + bool lookupSwingHighs = true, + bool lookupSwingLows = true, + bool lookupSupportZones = true, + bool lookupResistanceZones = true, + bool lookupSupplyZones = true, + bool lookupDemandZones = true, + bool lookupBullishOrderBlocks = true, + bool lookupBearishOrderBlocks = true, + bool lookupBullishFairValueGaps = true, + bool lookupBearishFairValueGaps = true, + bool lookupBullishRejectionBars = true, + bool lookupBearishRejectionBars = true, + bool lookupBullishMomentumBars = true, + bool lookupBearishMomentumBars = true // +) +{ + // + state.Clean(); + + // + if (!pivot.IsValid()) + { + return; + } + + // + int count = 0; + + // + state.symbol = pivot.symbol; + state.period = pivot.period; + state.time = TimeCurrent(); + + // + // Swings ... + + // + // Swing High ... + if (lookupSwingHighs) + { + // + count = ArraySize(source.swingHighs); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing *iSwing = source.swingHighs[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.high <= pivot.upper; + if (isInside) + { + // + Add( + iSwing, + state.swingHighs // + ); + } + } + } + } + + // + // Swing Low ... + if (lookupSwingLows) + { + // + count = ArraySize(source.swingLows); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing *iSwing = source.swingLows[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.low >= pivot.lower; + if (isInside) + { + // + Add( + iSwing, + state.swingLows // + ); + } + } + } + } + + // + // Support and Resistance Zones ... + + // + // Support Zones ... + if (lookupSupportZones) + { + // + count = ArraySize(source.supportZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZone *iZone = source.supportZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.supportZones // + ); + } + } + } + } + + // + // Resistance Zones ... + if (lookupResistanceZones) + { + // + count = ArraySize(source.resistanceZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZone *iZone = source.resistanceZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.resistanceZones // + ); + } + } + } + } + + // + // Supply and Demand Zones ... + + // + // Supply Zones ... + if (lookupSupplyZones) + { + // + count = ArraySize(source.supplyZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupplyZone *iZone = source.supplyZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.supplyZones // + ); + } + } + } + } + + // + // Demand Zones ... + if (lookupDemandZones) + { + // + count = ArraySize(source.demandZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCDemandZone *iZone = source.demandZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.demandZones // + ); + } + } + } + } + + // + // Order Blocks ... + + // + // Bullish Order Blocks ... + if (lookupBullishOrderBlocks) + { + // + count = ArraySize(source.bullishOrderBlocks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = source.bullishOrderBlocks[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bullishOrderBlocks // + ); + } + } + } + } + + // + // Bearish Order Blocks ... + if (lookupBearishOrderBlocks) + { + // + count = ArraySize(source.bearishOrderBlocks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = source.bearishOrderBlocks[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bearishOrderBlocks // + ); + } + } + } + } + + // + // Fair Value Gaps ... + + // + // Bullish Fair Value Gaps ... + if (lookupBullishFairValueGaps) + { + // + count = ArraySize(source.bullishFairValueGaps); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = source.bullishFairValueGaps[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bullishFairValueGaps // + ); + } + } + } + } + + // + // Bearish Fair Value Gaps ... + if (lookupBearishFairValueGaps) + { + // + count = ArraySize(source.bearishFairValueGaps); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = source.bearishFairValueGaps[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bearishFairValueGaps // + ); + } + } + } + } + + // + // Rejection Bars ... + + // + // Bullish Rejection Bars ... + if (lookupBullishRejectionBars) + { + // + count = ArraySize(source.bullishRejectionBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar *iRejection = source.bullishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.low <= pivot.upper && + iBar.low >= pivot.lower; + if (isInside) + { + // + Add( + iRejection, + state.bullishRejectionBars // + ); + } + } + } + } + + // + // Bearish Rejection Bars ... + if (lookupBearishRejectionBars) + { + // + count = ArraySize(source.bearishRejectionBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar *iRejection = source.bearishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.high <= pivot.upper && + iBar.high >= pivot.lower; + if (isInside) + { + // + Add( + iRejection, + state.bearishRejectionBars // + ); + } + } + } + } + + // + // Momentum Bars ... + + // + // Bullish Momentum Bars ... + if (lookupBullishMomentumBars) + { + // + count = ArraySize(source.bullishMomentumBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar *iMomentum = source.bullishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.low <= pivot.upper && + iBar.low >= pivot.lower; + if (isInside) + { + // + Add( + iMomentum, + state.bullishMomentumBars // + ); + } + } + } + } + + // + // Bearish Momenum Bars ... + if (lookupBearishMomentumBars) + { + // + count = ArraySize(source.bearishMomentumBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar *iMomentum = source.bearishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.high <= pivot.upper && + iBar.high >= pivot.lower; + if (isInside) + { + // + Add( + iMomentum, + state.bearishMomentumBars // + ); + } + } + } + } +} + +// +// Provider Extensions ... + +/** + * Validate a Signal Provider ... + * + * @param value: ENUM_X_121_SMC_PROVIDERS member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_121_SMC_PROVIDERS value) +{ + // + bool result = false; + + // + result = value != X_121_SMC_PROVIDER_NONE; + + // + return result; +} + +/** + * Converts a Signal Provider to String ... + * + * @param value: ENUM_X_121_SMC_PROVIDERS member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_121_SMC_PROVIDERS value) +{ + // + string result = NULL; + + // + if (!IsValid(value)) + { + return result; + } + + // + switch (value) + { + // + case X_121_SMC_PROVIDER_PV: + result = X121SMCPVToken; + break; + + // + case X_121_SMC_PROVIDER_BOS: + result = X121SMCBOSToken; + break; + + // + case X_121_SMC_PROVIDER_SAR: + result = X121SMCSARToken; + break; + + // + case X_121_SMC_PROVIDER_CHOCH: + result = X121SMCCHOCHToken; + break; + + // + case X_121_SMC_PROVIDER_PULLBK: + result = X121SMCPULLBKToken; + break; + } + + // + return result; +} + +/** + * Parse Specified String as a Signal Provider ... + * + * @param value: String ... + * + * @return ( ENUM_X_121_SMC_PROVIDERS ) + */ +ENUM_X_121_SMC_PROVIDERS ParseProvider(string value) +{ + // + ENUM_X_121_SMC_PROVIDERS result = X_121_SMC_PROVIDER_NONE; + + // + if (!IsValid(value)) + { + return result; + } + + // + if (Contains(X121SMCPVToken, value)) + { + result = X_121_SMC_PROVIDER_PV; + } + else if (Contains(X121SMCBOSToken, value)) + { + result = X_121_SMC_PROVIDER_BOS; + } + else if (Contains(X121SMCSARToken, value)) + { + result = X_121_SMC_PROVIDER_SAR; + } + else if (Contains(X121SMCCHOCHToken, value)) + { + result = X_121_SMC_PROVIDER_CHOCH; + } + else if (Contains(X121SMCPULLBKToken, value)) + { + result = X_121_SMC_PROVIDER_PULLBK; + } + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/x-121.smc.market.cycle.helper.class.mq5 b/BKPS/14030923/Documents/BKP/x-121.smc.market.cycle.helper.class.mq5 new file mode 100644 index 0000000..826e673 --- /dev/null +++ b/BKPS/14030923/Documents/BKP/x-121.smc.market.cycle.helper.class.mq5 @@ -0,0 +1,1483 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XC121SMCCycleHelper +// Description: provides all based classes for use ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../../Classes/x-saherelm.x-poi.class.mq5" +#include "../../Helpers/x-saherelm.x121.helper.mq5" +#include "../Libraries/x-121.smc.lib.mq5" + +// +// Definitions ... +struct XSarChange +{ + // + // Props ... + ENUM_X_DIRECTION dir; // Sar Changed To Direction ... + datetime time; // Sar Changed Time ... + double last; // Sar Value Before Change ... + double value; // Sar Value After Change ... + + // + // Constructor ... + XSarChange() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + last = 0; + value = 0; + time = NULL; + dir = X_DIRECTION_NONE; + } + + /** + * Validation ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + last > 0 && + value > 0 && + IsValid(time) && + HasDirection(dir); + + // + return result; + } + + /** + * Initialize ... + * + * @param _last: Last Sar Value ... + * @param _current: Current Sar Value ... + * + * @return ( bool ) + */ + bool Init( + double _last, + double _current, + datetime _time, + ENUM_X_DIRECTION _dir // + ) + { + // + bool result = false; + + // + result = + _last > 0 && + _current > 0 && + IsValid(_time) && + HasDirection(_dir); + if (!result) + { + return result; + } + + // + dir = _dir; + last = _last; + time = _time; + value = _current; + + // + result = IsValid(); + + // + return result; + } + + /** + * Check Change is Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + // + bool result = false; + + // + result = + IsValid() && + IsBullish(dir); + + // + return result; + } + + /** + * Check Change is Bearish ... + * + * @return ( bool ) + */ + bool IsBearishÙ‘() + { + // + bool result = false; + + // + result = + IsValid() && + IsBearish(dir); + + // + return result; + } + + // +}; + +// +// Implementations ... + +class XC121SMCCycleHelper : public XCBase +{ + // + public: + // + // Props ... + + // + // XPV ... + XCXPVHelper *mXPVHelper; + XPVPivot pivots[]; + XPVPivot orderFlow[]; + + // + // X3MA ... + XCX3MAHelper *mX3MAHelper; + + // + // X3VWAP ... + XCX3VWAPHelper *mX3VWAPHelper; + + // + // XCHSAR ... + XCXCHSARHelper *mXCHSARHelper; + XSarChange sarChanges[]; + + // + // X121 ... + XCX121Helper *mX121Helper; + + // + // POI Detector ... + XCPOIDetector *mPOIDetector; + + // + // Constructor(s) ... + XC121SMCCycleHelper() + { + } + + // + // Deconstructor ... + ~XC121SMCCycleHelper() + { + DeInit(); + } + + // + // Getter/Setter(s) ... + + // + // Actions ... + + /** + * Initialize ... + * + * @param symbol: String ... + * @param period: ENUM_TIMEFRAMES member ... + * @param xpvInputs: XPVInputs instance ... + * @param x3maInputs: X3MAInputs instance ... + * @param x3vwapInputs: X3VWAPInputs instance ... + * @param xchsarInputs: XCHSARInputs instance ... + * + * @return ( bool ) + */ + bool Init( + string symbol, + ENUM_TIMEFRAMES period, + XPVInputs &xpvInputs, + X3MAInputs &x3maInputs, + X3VWAPInputs &x3vwapInputs, + XCHSARInputs &xchsarInputs // + ) + { + // + bool result = false; + + // + result = IsValid(symbol) && + IsValid(period); + if (!result) + { + return result; + } + + // + // XPV ... + + // + result = xpvInputs.IsValid(); + if (!result) + { + return result; + } + + // + mXPVHelper = new XCXPVHelper(); + result = mXPVHelper.Init( + symbol, + period, + xpvInputs // + ); + if (!result) + { + return result; + } + + // + // X3MA ... + + // + result = x3maInputs.IsValid(); + if (!result) + { + return result; + } + + // + mX3MAHelper = new XCX3MAHelper(); + result = mX3MAHelper.Init( + symbol, + period, + x3maInputs // + ); + if (!result) + { + return result; + } + + // + // X3VWAP ... + + // + result = x3vwapInputs.IsValid(); + if (!result) + { + return result; + } + + // + mX3VWAPHelper = new XCX3VWAPHelper(); + result = mX3VWAPHelper.Init( + symbol, + period, + x3vwapInputs // + ); + if (!result) + { + return result; + } + + // + // XCHSAR ... + + // + result = xchsarInputs.IsValid(); + if (!result) + { + return result; + } + + // + mXCHSARHelper = new XCXCHSARHelper(); + result = mXCHSARHelper.Init( + symbol, + period, + xchsarInputs // + ); + if (!result) + { + return result; + } + + // + mPOIDetector = new XCPOIDetector( + symbol, + period // + ); + mPOIDetector.MaxNumberOfRequiredPOIs(0); + mPOIDetector.Init(); + + // + // Initialize Bar Analyser Class Instance ... + mBarAnalyser = new XCBarAnalyser(); + + // + // Set Chart Style ... + ApplyChartStyle(); + + // + return result; + } + + /** + * Get Specified Bar ... + * + * @param source: XOHCL instance, Source Bar ... + * @param bar: XOHCL instance, Dest Bar ... + * + * @return ( bool ) + */ + bool GetBar( + XOHCL &source, + XOHCL &bar // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + result = + IsValid(symbol) && + IsValid(period) && + source.IsValid(); + if (!result) + { + return result; + } + + // + int index = iBarShift( + symbol, + period, + source.time // + ); + result = bar.Init( + symbol, + period, + index // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + return result; + } + + /** + * Retrieve Specified Bar ... + * + * @param bar: XOHCL instance ... + * @param index: Integer ... + * + * @return ( bool ) + */ + bool GetBar( + XOHCL &bar, + int index = 0 // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (index < 0) + { + index = 0; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + result = bar.Init( + symbol, + period, + index // + ); + + // + return result; + } + + /** + * Retrieve Specified Bar ... + * + * @param bar: XOHCL instance ... + * @param time: Datetime ... + * + * @return ( bool ) + */ + bool GetBar( + XOHCL &bar, + datetime time = NULL // + ) + { + // + bool result = false; + + // + int index = GetBarIndex(time); + result = GetBar(bar, + index // + ); + + // + return result; + } + + /** + * Retrieve Specified Time Bar Index ... + * + * @param time: DateTime ... + * + * @return ( int ) + */ + int GetBarIndex(datetime time = NULL) + { + // + int result = -1; + + // + time = NormalizeTime(time); + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + result = iBarShift( + symbol, + period, + time // + ); + + // + return result; + } + + /** + * Retrieve Cycle Conditions ... + * + * @param conditions: X121SMCCycleConditions instance ... + * @param barIndex: Integer ... + * @param loopback: Integer ... + * + * @return ( bool ) + */ + bool GetConditions( + X121SMCCycleConditions &conditions, + int barIndex = 0, + int loopback = 7 // + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (loopback < 5) + { + loopback = 5; + } + + // + conditions.Clean(); + + // + result = mXPVHelper.GetConditions( + conditions.xpvConditions, + barIndex, + loopback // + ); + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + result = mX3MAHelper.GetConditions( + conditions.x3maConditions, + barIndex, + loopback // + ); + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + result = mX3VWAPHelper.GetConditions( + conditions.x3vwapConditions, + barIndex, + loopback // + ); + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + result = mXCHSARHelper.GetConditions( + conditions.xchsarConditions, + barIndex, + loopback // + ); + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + conditions.symbol = conditions.xpvConditions.symbol; + conditions.period = conditions.xpvConditions.period; + conditions.time = TimeCurrent(); + + // + result = conditions.IsValid(); + + // + return result; + } + + // + // POI Tools ... + + /** + * Detect Nearest Current SAR Change ... + * + * @param changeBar: XOHCL instance, Holds Nearest Change Bar ... + * @param bar: XOHCL instance, represents Current Bar for Loopback ... + * + * @return ( bool ) + */ + bool DetectNearestCSARChange( + XOHCL &changeBar, + XOHCL &bar // + ) + { + // + bool result = false; + + // + changeBar.Clean(); + + // + result = + bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL mBar; + result = GetBar( + bar, + mBar // + ); + if (!result) + { + return result; + } + + // + int barIndex = mBar.Index(); + double sar = mXCHSARHelper.GetC(barIndex); + bool isBullish = sar > 0 && + sar < mBar.low; + bool isBearish = sar > 0 && + sar > mBar.high; + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Loop Back to Find Nearest Sar Change ... + bool canContinue = true; + while (canContinue) + { + // + barIndex++; + + // + XOHCL iBar; + canContinue = iBar.Init( + mBar.symbol, + mBar.period, + barIndex // + ); + if (!canContinue) + { + break; + } + + // + double iSar = mXCHSARHelper.GetC(barIndex); + bool isISarBullish = + iSar > 0 && + iSar < iBar.low; + bool isISarBearish = + iSar > 0 && + iSar > iBar.high; + bool isSarChanged = + isBullish + ? !isISarBullish + : !isISarBearish; + + // + if (isSarChanged) + { + // + result = iBar.GetNextBar(changeBar); + canContinue = false; + break; + } + } + + // + result = changeBar.IsValid(); + + // + return result; + } + + /** + * Detect Last Decision Bar ( Rejection, Pin, Momentum ) ... + * + * @param decisionBar: XOHCL instance, Holds Decision Bar ... + * @param forDir: ENUM_X_DIRECTION member, Specified Bar Direction ... + * @param bar: XOHCL instance, represents Current Bar for Loopback ... + * + * @return ( bool ) + */ + bool DetectNearestDecisionBar( + XOHCL &decisionBar, + ENUM_X_DIRECTION forDir, + XOHCL &bar // + ) + { + // + bool result = false; + + // + decisionBar.Clean(); + + // + result = + bar.IsValid() && + forDir != X_DIRECTION_ALL && + forDir != X_DIRECTION_NONE; + if (!result) + { + return result; + } + + // + XOHCL mBar; + result = GetBar( + bar, + mBar // + ); + if (!result) + { + return result; + } + + // + int barIndex = mBar.Index(); + bool isBullish = IsBullish(forDir); + + // + bool canContinue = true; + while (canContinue) + { + // + barIndex++; + + // + XOHCL iBar; + canContinue = iBar.Init( + mBar.symbol, + mBar.period, + barIndex // + ); + if (!canContinue) + { + break; + } + + // + ENUM_X_DIRECTION decisionDir; + bool isDecisionBar = mBarAnalyser + .IsDecisionBar( + iBar, + decisionDir // + ); + if (isDecisionBar) + { + // + if (decisionDir == forDir) + { + // + decisionBar = mBar; + canContinue = false; + break; + } + } + + // + canContinue = !decisionBar.IsValid(); + } + + // + result = decisionBar + .IsValid(); + + // + return result; + } + + // + // Parabolic Sar Extensions ... + + /** + * Check Sar Changes and Save it ... + * + * @param change: XSarChange instance ... + * @param time: DateTime ... + * + * @return ( bool ) + */ + bool IsSarChanged( + XSarChange &change, + datetime time = NULL // + ) + { + // + bool result = false; + + // + change.Clean(); + + // + XOHCL bar; + result = GetBar( + bar, + time // + ); + if (!result) + { + return result; + } + + // + XOHCL prevBar; + result = bar.GetPreviousBar(prevBar); + if (!result) + { + return result; + } + + // + XOHCL prevPrevBar; + result = prevBar.GetPreviousBar(prevPrevBar); + if (!result) + { + return result; + } + + // + prevPrevBar = prevBar; + prevBar = bar; + + // + int index = prevBar.Index(); + + // + double current = mXCHSARHelper.GetC(index); + double prev = mXCHSARHelper.GetC(index + 1); + + // + bool isCurrentBullish = + current < prevBar.low; + bool isPrevBullish = + prev < prevPrevBar.low; + + // + bool isCurrentBearish = + current > prevBar.high; + bool isPrevBearish = + prev > prevPrevBar.high; + + // + bool isChangedToBullish = + isCurrentBullish && + !isPrevBullish; + + // + bool isChangedToBearish = + isCurrentBearish && + !isPrevBearish; + + // + result = isChangedToBullish || + isChangedToBearish; + if (!result) + { + return result; + } + ENUM_X_DIRECTION dir = + isChangedToBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = change + .Init( + prev, + current, + prevBar.time, + dir // + ); + if (!result) + { + return result; + } + + // + XSarChange lastChange; + bool hasLastItem = GetLastItem( + lastChange, + sarChanges // + ); + bool canAdd = !hasLastItem + ? true + : lastChange.time < change.time; + if (canAdd) + { + // + AddRef( + change, + sarChanges // + ); + } + + // + CleanSarChanges(); + + // + return result; + } + + /** + * Cleanup Unused Sar Changes ... + */ + void CleanSarChanges() + { + // + int required = 10; + int count = ArraySize(sarChanges); + if (!IsValidSize(count) || count <= required) + { + return; + } + + // + int mustRemove = count - required; + ArrayRemove( + sarChanges, + 0, + mustRemove // + ); + } + + // + // XPV Extensions ... + + /** + * Detect First Pivot ... + * + * @param pivot: XPVPivot instance ... + * @param time: DateTime ... + * @param minRepetition: Integer, Minimum Repetition ... + * @param maxAllowedLoopbackBars: Integer, Max Allowed LoopBack Bars ... + * + * @return ( bool ) + */ + bool DetectLastPivot( + XPVPivot &pivot, + datetime time = NULL, + int minRepetition = 40, + int maxAllowedLoopbackBars = 576 // + ) + { + // + bool result = false; + + // + pivot.Clean(); + + // + int index = GetBarIndex(time); + result = DetectPivot( + pivot, + index, + minRepetition, + maxAllowedLoopbackBars // + ); + + // + return result; + } + + /** + * Detect Pivot ... + * + * @param pivot: XPVPivot instance ... + * @param barIndex: Integer ... + * @param minRepetition: Integer, Minimum Repetition ... + * @param maxAllowedLoopbackBars: Integer, Max Allowed LoopBack Bars ... + * + * @return ( bool ) + */ + bool DetectPivot( + XPVPivot &pivot, + int barIndex = 0, + int minRepetition = 40, + int maxAllowedLoopbackBars = 576 // + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + int start = barIndex; + int end = start + maxAllowedLoopbackBars; + + // + double peak = 0; + int peakRepeate = 0; + int peakToBarIndex = 0; + int peakFromBarIndex = 0; + + // + double vale = 0; + int valeRepeate = 0; + int valeToBarIndex = 0; + int valeFromBarIndex = 0; + + // + bool canLookupPeak = true; + bool canLookupVale = true; + bool canLookup = true; + while (canLookup) + { + // + // Check Peak ... + double iPeak = mXPVHelper.GetPeak(barIndex); + if (iPeak != peak) + { + // + if (peak != 0 && + peakRepeate >= minRepetition) + { + // + XPVPivot iPivot; + + // + iPivot.lower = 0; + iPivot.upper = peak; + iPivot.symbol = symbol; + iPivot.period = period; + iPivot.type = XPV_PEAK; + iPivot.repetition = peakRepeate; + iPivot.to = iTime( + symbol, + period, + peakToBarIndex // + ); + iPivot.from = iTime( + symbol, + period, + peakFromBarIndex // + ); + + // + iPivot.lower = iPivot.CalculateLower(); + + // + bool isValid = iPivot.IsValid(); + if (isValid) + { + // + pivot = iPivot; + break; + } + } + + // + peak = iPeak; + peakRepeate = 0; + peakFromBarIndex = 0; + peakToBarIndex = barIndex; + } + else if (iPeak == peak) + { + // + peakRepeate++; + peakFromBarIndex = barIndex; + } + + // + // Check Vale ... + double iVale = mXPVHelper.GetVale(barIndex); + if (iVale != vale) + { + // + if (vale != 0 && + valeRepeate >= minRepetition) + { + // + XPVPivot iPivot; + + // + iPivot.upper = 0; + iPivot.lower = vale; + iPivot.symbol = symbol; + iPivot.period = period; + iPivot.type = XPV_VALE; + iPivot.repetition = valeRepeate; + iPivot.to = iTime( + symbol, + period, + valeToBarIndex // + ); + iPivot.from = iTime( + symbol, + period, + valeFromBarIndex // + ); + + // + iPivot.upper = iPivot.CalculateUpper(); + + // + bool isValid = iPivot.IsValid(); + if (isValid) + { + // + pivot = iPivot; + break; + } + } + + // + vale = iVale; + valeRepeate = 0; + valeFromBarIndex = 0; + valeToBarIndex = barIndex; + } + else if (iVale == vale) + { + // + valeRepeate++; + valeFromBarIndex = barIndex; + } + + // + canLookupPeak = !pivot.IsValid(); + canLookupVale = !pivot.IsValid(); + canLookup = barIndex < end && + (canLookupPeak || + canLookupVale); + if (canLookup) + { + barIndex++; + } + } + + // + result = pivot.IsValid(); + if (result) + { + // + XPVPivot last; + bool hasLastPivot = GetLastPivot(last); + + // + if (hasLastPivot) + { + // + // Check For Pivot Update ... + bool isLastPivotSameAsCurrent = + pivot.IsValid() && + last.IsValid() && + pivot.from == last.from && + pivot.type == last.type; + if (!isLastPivotSameAsCurrent) + { + // + AddRef( + pivot, + pivots // + ); + + // + CleanPivots(); + } + else + { + // + // Update Last Pivot ... + RemoveLastItem(pivots); + + // + pivot.to = TimeCurrent(); + + // + AddRef( + pivot, + pivots // + ); + + // + CleanPivots(); + } + } + else + { + // + // Add New Pivot ... + AddRef( + pivot, + pivots // + ); + + // + CleanPivots(); + } + } + + // + // DetectOrderFlow(); + + // + return result; + } + + /** + * Retriece Last Pivot if Exists ... + * + * @param pivot: XPVPivot instane ... + * + * @return ( bool ) + */ + bool GetLastPivot(XPVPivot &pivot) + { + // + bool result = false; + + // + pivot.Clean(); + + // + int count = ArraySize(pivots); + if (!IsValidSize(count)) + { + return result; + } + + // + result = GetLastItem( + pivot, + pivots // + ); + + // + return result; + } + + /** + * Detect Order Flow ... + * + * @param dir: ENUM_X_DIRECTION member, Hold's Order Flow Direction ... + * @param minPivots: Integer, minimum Required Pivots for Order Flow ... + * + * @return ( bool ) + */ + bool DetectOrderFlow( + ENUM_X_DIRECTION &dir, + int minPivots = 3 // + ) + { + // + bool result = false; + + // + // Normalize Minimum Pivots ... + if (minPivots < 2) + { + minPivots = 2; + } + + // + Clean(orderFlow); + Copy( + pivots, + orderFlow // + ); + + // + // Sort Pivots ... + SortPivots(orderFlow); + + // + // Filter Broken Order Flows ... + FilterBrokenPivots(orderFlow); + + // + int count = ArraySize(orderFlow); + result = IsValidSize(count) && + count >= minPivots; + if (!result) + { + return result; + } + + // + // Detect Order Flow Direction ... + result = DetectPivotDirection( + orderFlow, + dir // + ); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Cleanup Unused Pivots ... + */ + void CleanPivots() + { + // + int required = 10; + int count = ArraySize(pivots); + if (!IsValidSize(count) || count <= required) + { + return; + } + + // + int mustRemove = count - required; + ArrayRemove( + pivots, + 0, + mustRemove // + ); + } + + // + // Virtuals ... + + // + protected: + // + + // + private: + // + // Props ... + XCBarAnalyser *mBarAnalyser; + + // + // Actions ... + + /** + * Release All Resources ... + */ + void DeInit() + { + // + delete mXPVHelper; + delete mX3MAHelper; + delete mX3VWAPHelper; + delete mXCHSARHelper; + + // + delete mBarAnalyser; + } + + /** + * Apply Chart Style ... + */ + void ApplyChartStyle() + { + // + // Retrieve Current Chart ID ... + long chartId = ChartID(); + + // + ENUM_CHART_MODE mMode = CHART_CANDLES; // chart's mMode + bool mShowBidLine = true; // show bid line + bool mShowAskLine = true; // show ask line + bool mShowGrid = false; // show grids on chart + bool mShowVolumes = false; // show volumes + bool mShowTradeLevels = true; // Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders) + bool mAutoScroll = true; // chart autoscroll + bool mQuickNavigation = true; // chart quick navigation state + color mForeGroundColor = clrWhite; // chart's foreground color + color mBackGroundColor = clrBlack; // chart's background color + color mUpColor = clrGreen; // Up Color + color mDownColor = clrRed; // Down Color + color mBullishColor = clrGreen; // Bullish color + color mBearishColor = clrRed; // Bearish color + color mGridColor = clrGray; // grid color + color mBidLineColor = clrGray; // bid line color + color mAskLineColor = clrRed; // ask line color + color mLineColor = clrLime; // line mMode and doji candlestick color + color mStopColor = clrGold; // Color of stop order levels (Stop Loss and Take Profit) + color mVolumesColor = clrGreen; // volumes color + + // + ChartSetInteger(chartId, CHART_MODE, mMode); + ChartSetInteger(chartId, CHART_SHOW_BID_LINE, mShowBidLine); + ChartSetInteger(chartId, CHART_SHOW_ASK_LINE, mShowAskLine); + ChartSetInteger(chartId, CHART_SHOW_GRID, mShowGrid); + ChartSetInteger(chartId, CHART_SHOW_VOLUMES, mShowVolumes); + ChartSetInteger(chartId, CHART_SHOW_TRADE_LEVELS, mShowTradeLevels); + ChartSetInteger(chartId, CHART_AUTOSCROLL, mAutoScroll); + ChartSetInteger(chartId, CHART_QUICK_NAVIGATION, mQuickNavigation); + ChartSetInteger(chartId, CHART_COLOR_FOREGROUND, mForeGroundColor); + ChartSetInteger(chartId, CHART_COLOR_BACKGROUND, mBackGroundColor); + ChartSetInteger(chartId, CHART_COLOR_CHART_UP, mUpColor); + ChartSetInteger(chartId, CHART_COLOR_CHART_DOWN, mDownColor); + ChartSetInteger(chartId, CHART_COLOR_CANDLE_BULL, mBullishColor); + ChartSetInteger(chartId, CHART_COLOR_CANDLE_BEAR, mBearishColor); + ChartSetInteger(chartId, CHART_COLOR_GRID, mGridColor); + ChartSetInteger(chartId, CHART_COLOR_BID, mBidLineColor); + ChartSetInteger(chartId, CHART_COLOR_ASK, mAskLineColor); + ChartSetInteger(chartId, CHART_COLOR_STOP_LEVEL, mStopColor); + ChartSetInteger(chartId, CHART_COLOR_CHART_LINE, mLineColor); + ChartSetInteger(chartId, CHART_COLOR_VOLUME, mVolumesColor); + } + + /** + * Retrieve Symbol ... + * + * @return ( string ) + */ + string GetSymbol() + { + // + string result = NULL; + + // + result = mXPVHelper.GetSymbol(); + + // + return result; + } + + /** + * Retrieve TimeFrame (Period) ... + * + * @return ( ENUM_TIMEFRAMES ) + */ + ENUM_TIMEFRAMES GetPeriod() + { + // + ENUM_TIMEFRAMES result = NULL; + + // + result = mXPVHelper.GetPeriod(); + + // + return result; + } +}; diff --git a/BKPS/14030923/Documents/BKP/x-121.smc.test.signal.class.mq5 b/BKPS/14030923/Documents/BKP/x-121.smc.test.signal.class.mq5 new file mode 100644 index 0000000..c6b9dbf --- /dev/null +++ b/BKPS/14030923/Documents/BKP/x-121.smc.test.signal.class.mq5 @@ -0,0 +1,934 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121 SMC Signal Class +// ------------------------------------------------- +// Name: +// Description: provide all Signalling functions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-121.smc.market.cycle.helper.class.mq5" +#include "../Libraries/x-121.smc.lib.mq5" + +// +// Definitions ... +struct X121SMCStrategyTestSignalConditions +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double sl; + ENUM_X_DIRECTION dir; + ENUM_X_POSITION_TYPES type; + + // + // Setup Props ... + + // + datetime setupTime; + datetime triggerTime; + + // + // Bullish Order Blocks ... + datetime bullishOrderBlockTime; + XCOrderBlock *bullishOrderBlock; + + // + // Bearish Order Blocks ... + XCOrderBlock *bearishOrderBlock; + datetime bearishOrderBlockTime; + + // + // Trigger Props ... + + // + // Constructor ... + X121SMCStrategyTestSignalConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + sl = 0; + + // + dir = X_DIRECTION_NONE; + type = X_POSITION_TYPE_NONE; + + // + symbol = NULL; + period = NULL; + setupTime = NULL; + triggerTime = NULL; + + // + // Additional ... + + // + bullishOrderBlock = NULL; + bearishOrderBlock = NULL; + bullishOrderBlockTime = NULL; + bearishOrderBlockTime = NULL; + } + + /** + * Check Condition is Setting Up ... + * + * @param dir: ENUM_X_DIRECTION member, Setting Up Direction ... + * + * @return ( bool ) + */ + bool IsSetuped() + { + // + bool result = false; + + // + result = IsValid(setupTime) && + HasDirection(dir); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Detect How we Can Trigger Signal ... + * + * @return ( bool ) + */ + bool CanTrigger() + { + // + bool result = false; + + // + result = + // + sl > 0 && + IsValid(symbol) && + IsValid(period) && + IsValid(triggerTime) && + type != X_POSITION_TYPE_ALL && + type != X_POSITION_TYPE_NONE + // + ; + + // + return result; + } + + // + // Extensions ... + + bool HasBullishOrderBlock() + { + // + bool result = + bullishOrderBlock != NULL && + bullishOrderBlock.IsValid() && + bullishOrderBlock.IsBullish() && + IsValid(bullishOrderBlockTime); + + // + return result; + } + + bool HasBearishOrderBlock() + { + // + bool result = + bearishOrderBlock != NULL && + bearishOrderBlock.IsValid() && + bearishOrderBlock.IsBullish() && + IsValid(bearishOrderBlockTime); + + // + return result; + } + + bool HasOrderBlock() + { + // + bool result = HasBullishOrderBlock() && + HasBearishOrderBlock(); + + // + return result; + } + + // +}; + +// +// Extension Functions ... + +// +// Detect Setup Conditions ... +bool DetectX121SMCTestSiganlSetup( + string _symbol, + ENUM_TIMEFRAMES _period, + // + X121SMCStrategyTestSignalConditions &conditions, + // + XC121SMCCycleHelper *triggerCycleHelper, + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *verificationCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper + // +) +{ + // + bool result = false; + + // + bool isBullish = false; + bool isBearish = false; + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + string symbol = _symbol; + ENUM_TIMEFRAMES period = _period; + + // + conditions.symbol = symbol; + conditions.period = period; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + + // + double ll = cBar.FindLowest(9, MODE_LOW); + double hh = cBar.FindHighest(9, MODE_HIGH); + + // + int zoneValidationDivider = 10; + int validPivotRepetition = triggerCycleHelper.mX121Helper + .GetDonChainLength(); + + // + double selectedSL = 0; + + // + // Cycles Conditions ... + + // + // Trigger ... + ENUM_XPOI_EVENTS triggerPoiEvents[]; + ENUM_X_CYCLE_EVENTS triggerCycleEvents[]; + X121SMCCycleConditions triggerConditions; + result = triggerCycleHelper.GetConditions( + triggerCycleEvents, + triggerPoiEvents, + triggerConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Decision ... + ENUM_XPOI_EVENTS decisionPoiEvents[]; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Analyse ... + ENUM_XPOI_EVENTS analysePoiEvents[]; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Verification ... + ENUM_XPOI_EVENTS verificationPoiEvents[]; + ENUM_X_CYCLE_EVENTS verificationCycleEvents[]; + X121SMCCycleConditions verificationConditions; + result = verificationCycleHelper.GetConditions( + verificationCycleEvents, + verificationPoiEvents, + verificationConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Consolidation ... + ENUM_XPOI_EVENTS consolidationPoiEvents[]; + ENUM_X_CYCLE_EVENTS consolidationCycleEvents[]; + X121SMCCycleConditions consolidationConditions; + result = consolidationCycleHelper.GetConditions( + consolidationCycleEvents, + consolidationPoiEvents, + consolidationConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Vision ... + ENUM_XPOI_EVENTS visionPoiEvents[]; + ENUM_X_CYCLE_EVENTS visionCycleEvents[]; + X121SMCCycleConditions visionConditions; + result = visionCycleHelper.GetConditions( + visionCycleEvents, + visionPoiEvents, + visionConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Cycles POI States ... + XPOIState triggerState = triggerConditions.state; + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState verificationState = verificationConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + // Check Order Block ... + // TODO: Later ... + // bool hasOrderBlock = conditions.HasOrderBlock(); + // if (hasOrderBlock) + // { + // // + // DetectX121SMCTestSiganlOrderBlock( + // zBar, + // consolidationState, + // conditions // + // ); + // } + + // + bool isMarketBullish = + // + // VWap State ... + decisionConditions.x121Conditions.isVWapBullishState && + analyseConditions.x121Conditions.isVWapBullishState && + verificationConditions.x121Conditions.isVWapBullishState + // + && + // + // VWap Order ... + decisionConditions.x121Conditions.isVWapBullishOrdered && + analyseConditions.x121Conditions.isVWapBullishOrdered && + verificationConditions.x121Conditions.isVWapBullishOrdered + // + && + // + // Sar ... + decisionConditions.x121Conditions.isSarBullish && + analyseConditions.x121Conditions.isSarBullish && + verificationConditions.x121Conditions.isSarBullish + // + ; + + // + bool isMarketBearish = + // + // VWap State ... + decisionConditions.x121Conditions.isVWapBearishState && + analyseConditions.x121Conditions.isVWapBearishState && + verificationConditions.x121Conditions.isVWapBearishState + // + && + // + // VWap Order ... + decisionConditions.x121Conditions.isVWapBearishOrdered && + analyseConditions.x121Conditions.isVWapBearishOrdered && + verificationConditions.x121Conditions.isVWapBearishOrdered + // + && + // + // Sar ... + decisionConditions.x121Conditions.isSarBearish && + analyseConditions.x121Conditions.isSarBearish && + verificationConditions.x121Conditions.isSarBearish + // + ; + + // + // Step 1 + // Detect Market Direction ... + isBullish = isMarketBullish; + isBearish = isMarketBearish; + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Step 2 + // VWap Switches or Sar Switches ... + + // + bool isSarBullish = triggerConditions.x121Conditions.isSarBullish; + bool isSarBearish = triggerConditions.x121Conditions.isSarBearish; + + // + bool isSarSwitchedToBullish = triggerConditions.x121Conditions.isSarSwitchedToBullish; + bool isSarSwitchedToBearish = triggerConditions.x121Conditions.isSarSwitchedToBearish; + + // + bool isVWapBullishState = triggerConditions.x121Conditions.isVWapBullishState; + bool isVWapBearishState = triggerConditions.x121Conditions.isVWapBearishState; + + // + bool isVWapSwitchedToBullishState = triggerConditions.x121Conditions.isVWapSwitchedToBullishState; + bool isVWapSwitchedToBearishState = triggerConditions.x121Conditions.isVWapSwitchedToBearishState; + + // + bool isVWapBullishOrdered = triggerConditions.x121Conditions.isVWapBullishOrdered; + bool isVWapBearishOrdered = triggerConditions.x121Conditions.isVWapBearishOrdered; + + // + bool isVWapSwitchedToBullishOrdered = triggerConditions.x121Conditions.isVWapSwitchedToBullishOrdered; + bool isVWapSwitchedToBearishOrdered = triggerConditions.x121Conditions.isVWapSwitchedToBearishOrdered; + + // + // + // + + // + bool isSarStartedBullishStructure = + // + isSarSwitchedToBullish && + isVWapBullishState && + isVWapBullishOrdered + // + ; + + // + bool isSarStartedBearishStructure = + // + isSarSwitchedToBearish && + isVWapBearishState && + isVWapBearishOrdered + // + ; + + // + // + // + + // + bool isVWapStateStartedBullishStructure = + // + isVWapSwitchedToBullishState && + isSarBullish && + isVWapBullishOrdered + // + ; + + // + bool isVWapStateStartedBearishStructure = + // + isVWapSwitchedToBearishState && + isSarBearish && + isVWapBearishOrdered + // + ; + + // + // + // + + // + bool isVWapOrderStartedBullishStructure = + // + isVWapSwitchedToBullishOrdered && + isSarBullish && + isVWapBullishState + // + ; + + // + bool isVWapOrderStartedBearishStructure = + // + isVWapSwitchedToBearishOrdered && + isSarBearish && + isVWapBearishState + // + ; + + // + // + // + + // + isBullish = + // + isBullish + // + && + // + ( + // + isSarStartedBullishStructure || + isVWapStateStartedBullishStructure || + isVWapOrderStartedBullishStructure + // + ) + // + ; + + // + isBearish = + // + isBearish + // + && + // + ( + // + isSarStartedBearishStructure || + isVWapStateStartedBearishStructure || + isVWapOrderStartedBearishStructure + // + ) + // + ; + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + conditions.setupTime = cTime; + conditions.dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; +} + +// +// Detect Trigger Conditions ... +bool DetectX121SMCTestSiganlTrigger( + // + X121SMCStrategyTestSignalConditions &conditions, + // + string _symbol, + ENUM_TIMEFRAMES _period, + // + XC121SMCCycleHelper *triggerCycleHelper, + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *verificationCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper + // +) +{ + // + bool result = false; + + // + result = conditions.IsSetuped(); + if (!result) + { + return result; + } + + // + ENUM_X_DIRECTION setupDir = conditions.dir; + + // + bool isBullish = false; + bool isBearish = false; + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + ENUM_X_121_SMC_PROVIDERS provider = X_121_SMC_PROVIDER_SMPV; + string providerStr = ToString(provider); + + // + string symbol = _symbol; + ENUM_TIMEFRAMES period = _period; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + + // + double ll = cBar.FindLowest(9, MODE_LOW); + double hh = cBar.FindHighest(9, MODE_HIGH); + + // + int zoneValidationDivider = 10; + int validPivotRepetition = triggerCycleHelper.mX121Helper + .GetDonChainLength(); + + // + double selectedSL = 0; + + // + // Cycles Conditions ... + + // + // Trigger ... + ENUM_XPOI_EVENTS triggerPoiEvents[]; + ENUM_X_CYCLE_EVENTS triggerCycleEvents[]; + X121SMCCycleConditions triggerConditions; + result = triggerCycleHelper.GetConditions( + triggerCycleEvents, + triggerPoiEvents, + triggerConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Decision ... + ENUM_XPOI_EVENTS decisionPoiEvents[]; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Analyse ... + ENUM_XPOI_EVENTS analysePoiEvents[]; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Verification ... + ENUM_XPOI_EVENTS verificationPoiEvents[]; + ENUM_X_CYCLE_EVENTS verificationCycleEvents[]; + X121SMCCycleConditions verificationConditions; + result = verificationCycleHelper.GetConditions( + verificationCycleEvents, + verificationPoiEvents, + verificationConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Consolidation ... + ENUM_XPOI_EVENTS consolidationPoiEvents[]; + ENUM_X_CYCLE_EVENTS consolidationCycleEvents[]; + X121SMCCycleConditions consolidationConditions; + result = consolidationCycleHelper.GetConditions( + consolidationCycleEvents, + consolidationPoiEvents, + consolidationConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Vision ... + ENUM_XPOI_EVENTS visionPoiEvents[]; + ENUM_X_CYCLE_EVENTS visionCycleEvents[]; + X121SMCCycleConditions visionConditions; + result = visionCycleHelper.GetConditions( + visionCycleEvents, + visionPoiEvents, + visionConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Cycles POI States ... + XPOIState triggerState = triggerConditions.state; + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState verificationState = verificationConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + result = false; + + // + return result; +} + +// +// Tools Functions ... + +// +// We Have to Find Valid Order Blocks ... +// - Order Block Must Not Touched; +bool DetectX121SMCTestSiganlOrderBlock( + XOHCL &bar, + XPOIState &state, + X121SMCStrategyTestSignalConditions &conditions // +) +{ + // + bool result = false; + + // + result = bar.IsValid() && + state.IsValid() && + state.HasChild(); + if (!result) + { + return result; + } + + // + int start = bar.Index(); + + // + // Bullish Order Block Check ... + bool hasBullishOB = conditions.HasBullishOrderBlock(); + if (!hasBullishOB) + { + // + int count = state.CountBullishOrderBlocks(); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + XCOrderBlock *tmpOB[]; + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iOB = state.bullishOrderBlocks[i]; + + // + bool isOBTouched = DetectOrderBlockTouch(iOB); + } + + // + hasBullishOB = conditions.HasBullishOrderBlock(); + result = hasBullishOB; + if (!result) + { + return result; + } + } + + // + // Bearish Order Block Check ... + bool hasBearishOB = conditions.HasBearishOrderBlock(); + if (!hasBearishOB) + { + // + + // + hasBearishOB = conditions.HasBearishOrderBlock(); + result = hasBearishOB; + if (!result) + { + return result; + } + } + + // + return result; +} + +// +// TODO: Complete this ... +bool DetectOrderBlockTouch( + XCOrderBlock *ob // +) +{ + // + bool result = false; + + // + result = ob != NULL && + ob.IsValid(); + if (!result) + { + return result; + } + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/x-121.smc.test.strategy.FULL.class.mq5 b/BKPS/14030923/Documents/BKP/x-121.smc.test.strategy.FULL.class.mq5 new file mode 100644 index 0000000..365ab16 --- /dev/null +++ b/BKPS/14030923/Documents/BKP/x-121.smc.test.strategy.FULL.class.mq5 @@ -0,0 +1,2830 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCX121SMCTestStrategy +// Description: provides all based classes for use ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... + +// +#include "../../Helpers/x-saherelm.x3ma.helper.mq5" +#include "../../Helpers/x-saherelm.x3vwap.helper.mq5" +#include "../../Helpers/x-saherelm.xchsar.helper.mq5" +#include "../../Helpers/x-saherelm.xpv.helper.mq5" +#include "../Classes/x-121.smc.base.strategy.class.mq5" + +// +// Definitions ... + +// +// XStrategy Class Implementation(s) ... +class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy +{ + // + // Public ... + public: + // + + // + // Constructor(s) ... + void XCX121SMCTestStrategy( + // + // Base ... + string _symbol, // Trading Symbol + ENUM_TIMEFRAMES _period // Trading TimeFrame + ) + : XCX121SMCBaseStrategy(_symbol, _period) + { + InitialHelpers(); + } + + // + // Deconstructur ... + void ~XCX121SMCTestStrategy() + { + } + + // + // Overrides Actions ... + + /** + * Destroy All Class Implementations ... + */ + void Destroy() override + { + // + delete xpvHelper; + delete x3maHelper; + delete xchsarHelper; + delete x3vwapHelper; + } + + /** + * Check Conditions For Signal ... + */ + bool HasSignal( + XSignal &signal, + X121SMCStrategyConditions &conditions // + ) override + { + // + bool result = false; + + // + signal.Clean(); + conditions.Clean(); + + // + int pushers = 0; + + // + double sl = 0; + double tp = 0; + double risk = 0; + double entry = 0; + double reward = 0; + double r2r = R2R(); + string provider = ""; + double volume = Volume(); + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY; + ENUM_X_ORDER_MODES mode = X_ORDER_MODE_MARKET; + + // + bool hasLong = false; + bool hasShort = false; + + // + double selectedSL = 0; + + // + // Start Calculations ... + + // + string _symbol = GetSymbol(); + ENUM_TIMEFRAMES _period = GetPeriod(); + + // + double points = GetPoints(_symbol); + double pip = GetPipPrice(_symbol); + double pip2 = 2 * pip; + + // + datetime cTime = TimeCurrent(); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + // Retrieve Bars ... + + // + // Zero Bar ... + XOHCL zBar; + result = zBar.Init( + _symbol, + _period, + zIndex // + ); + if (!result) + { + return result; + } + + // + // Last Bar ... + XOHCL cBar; + result = cBar.Init( + _symbol, + _period, + cIndex // + ); + if (!result) + { + return result; + } + + // + // Previous Bar ... + XOHCL pBar; + result = pBar.Init( + _symbol, + _period, + pIndex // + ); + if (!result) + { + return result; + } + + // + // Prepare Areas ... + double bid = GetBid(_symbol); + + // + // Check Momentum Bar ... + ENUM_X_DIRECTION momentumCBarDir; + bool isCMomentumBar = mBarAnalyser.IsMomentumBar( + cBar, + momentumCBarDir // + ); + bool isCBullishMomentumBar = + isCMomentumBar && + IsBullish(momentumCBarDir); + bool isCBearishMomentumBar = + isCMomentumBar && + IsBearish(momentumCBarDir); + + // + // Check Momentum Bar ... + ENUM_X_DIRECTION momentumPBarDir; + bool isPMomentumBar = mBarAnalyser.IsMomentumBar( + pBar, + momentumPBarDir // + ); + bool isPBullishMomentumBar = + isPMomentumBar && + IsBullish(momentumPBarDir); + bool isPBearishMomentumBar = + isPMomentumBar && + IsBearish(momentumPBarDir); + + // + // Check Rejection Bar ... + ENUM_X_DIRECTION rejectionCBarDir; + bool isCRejectionBar = mBarAnalyser.IsRejectionBar( + cBar, + rejectionCBarDir // + ); + bool isCBullishRejectionBar = + isCRejectionBar && + IsBullish(rejectionCBarDir); + bool isCBearishRejectionBar = + isCRejectionBar && + IsBearish(rejectionCBarDir); + + // + // Check Rejection Bar ... + ENUM_X_DIRECTION rejectionPBarDir; + bool isPRejectionBar = mBarAnalyser.IsRejectionBar( + pBar, + rejectionPBarDir // + ); + bool isPBullishRejectionBar = + isPRejectionBar && + IsBullish(rejectionPBarDir); + bool isPBearishRejectionBar = + isPRejectionBar && + IsBearish(rejectionPBarDir); + + // + // Check Engulfing ... + ENUM_X_DIRECTION engulfCBarDir; + bool isCEngulfed = mBarAnalyser.IsEngulfBar( + cBar, + engulfCBarDir // + ); + bool isCBullishEngulfed = + isCEngulfed && + IsBullish(engulfCBarDir); + bool isCBearishEngulfed = + isCEngulfed && + IsBearish(engulfCBarDir); + + // + // Check Engulfing ... + ENUM_X_DIRECTION engulfPBarDir; + bool isPEngulfed = mBarAnalyser.IsEngulfBar( + pBar, + engulfPBarDir // + ); + bool isPBullishEngulfed = + isPEngulfed && + IsBullish(engulfPBarDir); + bool isPBearishEngulfed = + isPEngulfed && + IsBearish(engulfPBarDir); + + // + bool isCRMEBullish = + // + isCBullishEngulfed + // + || + // + isCBullishMomentumBar + // + || + // + isCBullishRejectionBar + // + ; + + // + bool isPRMEBullish = + // + isPBullishEngulfed + // + || + // + isPBullishMomentumBar + // + || + // + isPBullishRejectionBar + // + ; + + // + bool isCRMEBearish = + // + isCBearishEngulfed + // + || + // + isCBearishMomentumBar + // + || + // + isCBearishRejectionBar + // + ; + + // + bool isPRMEBearish = + // + isPBearishEngulfed + // + || + // + isPBearishMomentumBar + // + || + // + isPBearishRejectionBar + // + ; + + // + bool isSpreadPassed = IsSpreadPass(); + result = isSpreadPassed; + if (!result) + { + return result; + } + + // + // Try to Implement SMC Based Conditions ... + result = DetectConditions(conditions); + if (!result) + { + return result; + } + + // + // Validate Order Flow ... + bool isValidOrderFlow = HasValidOrderFlow(); + result = isValidOrderFlow; + if (!result) + { + return result; + } + + // + XPVPivot lastPivot; + result = GetLastItem( + lastPivot, + mOrderFlow // + ); + if (!result) + { + return result; + } + + // + // Detect Fair Value Gaps ... + XCBasePOI *mPOIs[]; + bool hasPOI = FindPOIInPivot( + mPOIs, + X_POI_SWING_HIGH, + lastPivot, + mVisionPOIState // + ); + // TODO: + + // + bool isOrderFlowBullish = IsBullish(mOrderFlowDir); + + // + // Check Parabolic Sar is in Order of Order Flow ... + bool isPSarInDirectionOfOrderFlow = + isOrderFlowBullish + ? conditions.xchsarConditions.cSars[0] < cBar.low && + conditions.xchsarConditions.cSars[1] >= pBar.low + : conditions.xchsarConditions.cSars[0] > cBar.high && + conditions.xchsarConditions.cSars[1] <= pBar.high; + + // + // Check BOS or CHOCH Happens ... + bool hasBOS = + isOrderFlowBullish + ? + // + // Price Close Over Pivot's High ... + cBar.IsBullish() && + cBar.close > lastPivot.upper && + (pBar.close < lastPivot.upper || + pBar.low < lastPivot.upper) + // + : + // + // Price Must Close Under Pivots Low ... + cBar.IsBearish() && + cBar.close < lastPivot.lower && + (pBar.close > lastPivot.lower || + pBar.high > lastPivot.lower) + // + ; + + // + if (hasBOS) + { + mLastBOSOn = TimeCurrent(); + } + + bool hasCHOCH = + isOrderFlowBullish + ? + // + // Price Close Under Pivot's Low ... + cBar.IsBearish() && + cBar.close < lastPivot.lower && + (pBar.close > lastPivot.lower || + pBar.high > lastPivot.lower) + // + : + // + // Price Must Close Over Pivots High ... + cBar.IsBullish() && + cBar.close > lastPivot.upper && + (pBar.close < lastPivot.upper || + pBar.low < lastPivot.upper) + // + ; + + // + // Check PSar is Equals to Peak or Vale ... + bool isSAREqualsToPeak = + conditions.xchsarConditions.cSars[0] == conditions.xpvConditions.peaks[1]; + bool isSAREqualsToVale = + conditions.xchsarConditions.cSars[0] == conditions.xpvConditions.vales[1]; + + // + bool hasNewPeak = + conditions.xpvConditions.peaks[0] != conditions.xpvConditions.peaks[1]; + bool hasNewPeakOverLast = + hasNewPeak && + conditions.xpvConditions.peaks[0] > conditions.xpvConditions.peaks[1]; + bool hasNewPeakUnderLast = + hasNewPeak && + conditions.xpvConditions.peaks[0] < conditions.xpvConditions.peaks[1]; + + // + bool hasNewVale = + conditions.xpvConditions.vales[0] != conditions.xpvConditions.vales[1]; + bool hasNewValeOverLast = + hasNewVale && + conditions.xpvConditions.vales[0] > conditions.xpvConditions.vales[1]; + bool hasNewValeUnderLast = + hasNewVale && + conditions.xpvConditions.vales[0] < conditions.xpvConditions.vales[1]; + + // + // START Signalling ... + // + + // + // BOS Signals ... + bool has_BOS_Long = false; + bool has_BOS_Short = false; + + // + // CHOCH Signals ... + bool has_CHOCH_Long = false; + bool has_CHOCH_Short = false; + + // + // SAR Signals ... + bool has_SAR_Long = false; + bool has_SAR_Short = false; + + // + // PULLBACK Signals ... + bool has_PULLBK_Long = false; + bool has_PULLBK_Short = false; + + // + // PV Signals ... + bool has_PV_Long = false; + bool has_PV_Short = false; + + // + // BOS Signals ... + // + has_BOS_Long = + // + hasBOS && + isOrderFlowBullish && + isCRMEBullish && + cBar.IsBullish() && + conditions.xchsarConditions.cSars[0] < cBar.low + // + ; + + // + if (has_BOS_Long) + { + // + selectedSL = cBar.low; + provider = ToString(X_121_SMC_PROVIDER_BOS); + } + + // + has_BOS_Short = + // + hasBOS && + !isOrderFlowBullish && + isCRMEBearish && + cBar.IsBearish() && + conditions.xchsarConditions.cSars[0] > cBar.high + // + ; + if (has_BOS_Short) + { + // + selectedSL = cBar.high; + provider = ToString(X_121_SMC_PROVIDER_BOS); + } + + // + // CHOCH Signals ... + + // + has_CHOCH_Long = + // + hasCHOCH && + isCRMEBullish && + cBar.IsBullish() && + !isOrderFlowBullish && + conditions.xchsarConditions.cSars[0] < cBar.low + // + ; + if (has_CHOCH_Long) + { + // + selectedSL = cBar.low; + provider = ToString(X_121_SMC_PROVIDER_CHOCH); + } + + // + has_CHOCH_Short = + // + hasCHOCH && + isCRMEBearish && + cBar.IsBearish() && + isOrderFlowBullish && + conditions.xchsarConditions.cSars[0] > cBar.high + // + ; + if (has_CHOCH_Short) + { + // + selectedSL = cBar.high; + provider = ToString(X_121_SMC_PROVIDER_CHOCH); + } + + // + // SAR Signals ... + + // + has_SAR_Long = + // + isSAREqualsToVale && + isOrderFlowBullish && + isPSarInDirectionOfOrderFlow + // + ; + if (has_SAR_Long) + { + // + provider = ToString(X_121_SMC_PROVIDER_SAR); + selectedSL = conditions.xchsarConditions.cSars[0]; + } + + // + has_SAR_Short = + // + isSAREqualsToPeak && + !isOrderFlowBullish && + isPSarInDirectionOfOrderFlow + // + ; + if (has_SAR_Short) + { + // + provider = ToString(X_121_SMC_PROVIDER_SAR); + selectedSL = conditions.xchsarConditions.cSars[0]; + } + + // + // PULLBK Signals ... + + // + has_PULLBK_Long = + // + isCRMEBullish && + isPSarInDirectionOfOrderFlow && + (cBar.low < conditions.x3maConditions.fasts[0] && + cBar.GetDown() > conditions.x3maConditions.fasts[0]) + // + ; + if (has_PULLBK_Long) + { + // + selectedSL = cBar.low; + provider = ToString(X_121_SMC_PROVIDER_PULLBK); + } + + // + has_PULLBK_Short = + // + isCRMEBearish && + isPSarInDirectionOfOrderFlow && + (cBar.high > conditions.x3maConditions.fasts[0] && + cBar.GetUp() < conditions.x3maConditions.fasts[0]) + // + ; + if (has_PULLBK_Short) + { + // + selectedSL = cBar.high; + provider = ToString(X_121_SMC_PROVIDER_PULLBK); + } + + // + // PV Signals ... + + // + has_PV_Long = + // + isCRMEBullish && + isOrderFlowBullish && + !hasNewValeUnderLast && + cBar.low == conditions.xpvConditions.vales[0] + // + ; + if (has_PV_Long) + { + // + selectedSL = cBar.low; + provider = ToString(X_121_SMC_PROVIDER_PV); + } + + // + has_PV_Short = + // + isCRMEBearish && + !isOrderFlowBullish && + !hasNewPeakOverLast && + cBar.high == conditions.xpvConditions.peaks[0] + // + ; + if (has_PV_Short) + { + // + selectedSL = cBar.high; + provider = ToString(X_121_SMC_PROVIDER_PV); + } + + // + // END Signalling ... + // + + // + // Combine all Signals Conditions ... + + // + hasLong = + // + has_BOS_Long + // + || + // + has_CHOCH_Long + // + || + // + has_SAR_Long + // + || + // + has_PULLBK_Long + // + || + // + has_PV_Long + // + ; + + // + hasShort = + // + has_BOS_Short + // + || + // + has_CHOCH_Short + // + || + // + has_SAR_Short + // + || + // + has_PULLBK_Short + // + || + // + has_PV_Short + // + ; + + // + result = hasLong || + hasShort; + + // + // Reset Order Flow ... + if (hasCHOCH && !result) + { + ResetOrderFlow(); + } + else if (hasBOS && !result) + { + UpdateOrderFlow(); + } + + // + // Rmove Signal Condition ... + if (result) + { + // + // TYPE ... + type = + hasLong + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + ENUM_X_POSITION_TYPES xType = + hasLong + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + entry = GetEntry( + conditions.symbol, + type // + ); + + // + sl = + hasLong + ? selectedSL - pip2 + : selectedSL + pip2; + + // + // RISK Reward ... + risk = + hasLong + ? entry - sl + : sl - entry; + reward = risk * r2r; + tp = + hasLong + ? entry + reward + : entry - reward; + + // + signal.sl = sl; + signal.tp = tp; + signal.type = type; + signal.mode = mode; + signal.entry = entry; + signal.volume = volume; + signal.symbol = _symbol; + signal.period = _period; + signal.pushers = pushers; + signal.provider = provider; + signal.time = TimeCurrent(); + + // + result = PrepareSignal(signal); + if (result) + { + // + Print("PRV: ", provider); + + // + ENUM_X_DIRECTION forDir = ToDirection(signal.type); + bool ignoreSwingHighs = false; + bool ignoreSwingLows = false; + bool ignoreSupportZones = false; + bool ignoreResistanceZones = false; + bool ignoreSupplyZones = false; + bool ignoreDemandZones = false; + bool ignoreBullishOrderBlocks = false; + bool ignoreBearishOrderBlocks = false; + bool ignoreBullishFairValueGaps = false; + bool ignoreBearishFairValueGaps = false; + bool ignoreBullishRejectionBars = false; + bool ignoreBearishRejectionBars = false; + bool ignoreBullishMomentumBars = false; + bool ignoreBearishMomentumBars = false; + if (IsBullish(forDir)) + { + // + ignoreSwingLows = false; + ignoreDemandZones = false; + ignoreSupportZones = false; + ignoreBullishOrderBlocks = false; + ignoreBullishFairValueGaps = false; + ignoreBullishRejectionBars = false; + ignoreBullishMomentumBars = false; + } + else + { + // + ignoreSwingHighs = true; + ignoreSupplyZones = true; + ignoreResistanceZones = true; + ignoreBearishOrderBlocks = true; + ignoreBearishFairValueGaps = false; + ignoreBearishRejectionBars = true; + ignoreBearishMomentumBars = true; + } + + // + RedrawOrderFlow( + true, // Force Clean ... + false, // Same Period ... + true, // Order Flow ... + true, // Order Flow State ... + false, // Only Last Order Flow ... + true, // Only Last Order Flow State ... + // + forDir, // Direction Force ... + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars, + // + false, // Vision State ... + false, // Analyse State ... + false // Trigger State ... + ); + DrawSignal(signal); + ClearDraws(); + + // + ResetOrderFlow(); + } + + // + hasLong = false; + hasShort = false; + } + + // + return result; + } + + /** + * Customize Strategy Identifier ... + */ + string GetTag() override + { + return X121SMCStrategyToken; + } + + // + // Protected ... + protected: + // + + // + // Props ... + + // + // XPV ... + XPVInputs xpvInputs; + XCXPVHelper *xpvHelper; + + // + // X3MA ... + X3MAInputs x3maInputs; + XCX3MAHelper *x3maHelper; + + // + // X3VWAP ... + X3VWAPInputs x3vwapInputs; + XCX3VWAPHelper *x3vwapHelper; + + // + // XCHSAR ... + XCHSARInputs xchsarInputs; + XCXCHSARHelper *xchsarHelper; + + // + XPVPivot mOrderFlow[]; + ENUM_X_DIRECTION mOrderFlowDir; + + // + // Holds Last CHOCH and BOS time ... + datetime mLastBOSOn; + datetime mLastCHOCHOn; + + // + // Actions ... + + /** + * Detect and Parse Market Conditions ... + * + * @return ( bool ) + */ + bool DetectConditions( + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + conditions.symbol = symbol; + conditions.period = period; + conditions.time = TimeCurrent(); + + // + int conditionsLoopback = 7; + + // + // XPV ... + result = xpvHelper.GetConditions( + conditions.xpvConditions, + cIndex, + conditionsLoopback // + ); + if (!result) + { + return result; + } + + // + // X3MA ... + result = x3maHelper.GetConditions( + conditions.x3maConditions, + cIndex, + conditionsLoopback // + ); + if (!result) + { + return result; + } + + // + // X3VWAP ... + result = x3vwapHelper.GetConditions( + conditions.x3vwapConditions, + cIndex, + conditionsLoopback // + ); + if (!result) + { + return result; + } + + // + // XCHSAR ... + result = xchsarHelper.GetConditions( + conditions.xchsarConditions, + cIndex, + conditionsLoopback // + ); + if (!result) + { + return result; + } + + // + // Only Detect Order Flow when there isn't ... + if (ArraySize(mOrderFlow) == 0 || + mOrderFlowDir == X_DIRECTION_NONE) + { + // + int samePivots = 40; + int requiredPivots = 10; + + // + DetectOrderFlow( + cIndex, + samePivots, + requiredPivots, + mOrderFlow, + mOrderFlowDir // + ); + + // + result = IsValidSize(ArraySize(mOrderFlow)); + if (!result) + { + return result; + } + } + + // + if (result) + { + // + int lastPivotIDX = ArraySize(mOrderFlow) - 1; + if (IsValidSize(lastPivotIDX)) + { + // + FillPivotSate( + lastPivotIDX, + true, // Use Vision State ... + true, // Use Analyse State ... + false // Use Trigger State ... + ); + } + } + + // + return result; + } + + /** + * Detect XPV Based POI(s) ... + * + * @param barIndex: Start Bar Index ... + * @param minRepetition: minimum Repeate of POI for Validation ... + * @param requiredPivots: Number of Min Requirement POI(s) ... + * @param orderFlow: XPVPivot instance Array Reference ... + * @param orderFlowDirection: ENUM_X_DIRECTION member Reference which represents OrderFlow Direction ... + * @param maxAllowedLoopbackBars: Integer, Max Allowed Loopback Bars ... + * + * @return ( bool ) + */ + bool DetectOrderFlow( + int barIndex, + int minRepetition, + int requiredPivots, + XPVPivot &orderFlow[], // OrderFlows ... + ENUM_X_DIRECTION &orderFlowDirection, // Order Flow Direction ... + int maxAllowedLoopbackBars = 576 // + ) + { + // + bool result = false; + + // + orderFlowDirection = X_DIRECTION_NONE; + + // + if (maxAllowedLoopbackBars <= 0) + { + maxAllowedLoopbackBars = 1000; + } + + // + int start = barIndex; + int end = start + maxAllowedLoopbackBars; + + // + Clean(orderFlow); + + // + result = minRepetition > 0 && + requiredPivots > 0; + if (!result) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + double peak = 0; + XPVPivot peaks[]; + int peakRepeate = 0; + int peakToBarIndex = 0; + int peakFromBarIndex = 0; + + // + double vale = 0; + XPVPivot vales[]; + int valeRepeate = 0; + int valeToBarIndex = 0; + int valeFromBarIndex = 0; + + // + bool canLookupPeak = true; + bool canLookupVale = true; + bool canLookup = true; + while (canLookup) + { + // + // Check Peak ... + double iPeak = xpvHelper.GetPeak(barIndex); + if (iPeak != peak) + { + // + if (peak != 0 && + peakRepeate >= minRepetition) + { + // + bool isExists = false; + int count = ArraySize(peaks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = peaks[i]; + + // + if (iPivot.upper == iPeak) + { + // + isExists = true; + break; + } + } + } + if (!isExists) + { + // + XPVPivot iPivot; + + // + iPivot.lower = 0; + iPivot.upper = peak; + iPivot.symbol = symbol; + iPivot.period = period; + iPivot.type = XPV_PEAK; + iPivot.repetition = peakRepeate; + iPivot.to = iTime( + symbol, + period, + peakToBarIndex // + ); + iPivot.from = iTime( + symbol, + period, + peakFromBarIndex // + ); + + // + iPivot.lower = iPivot.CalculateLower(); + + // + bool isValid = iPivot.IsValid(); + if (isValid) + { + // + AddRef( + iPivot, + peaks // + ); + } + } + } + + // + peak = iPeak; + peakRepeate = 0; + peakFromBarIndex = 0; + peakToBarIndex = barIndex; + } + else if (iPeak == peak) + { + // + peakRepeate++; + peakFromBarIndex = barIndex; + } + + // + // Check Vale ... + double iVale = xpvHelper.GetVale(barIndex); + if (iVale != vale) + { + // + if (vale != 0 && + valeRepeate >= minRepetition) + { + // + bool isExists = false; + int count = ArraySize(vales); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = vales[i]; + + // + if (iPivot.lower == iVale) + { + // + isExists = true; + break; + } + } + } + if (!isExists) + { + // + XPVPivot iPivot; + + // + iPivot.upper = 0; + iPivot.lower = vale; + iPivot.symbol = symbol; + iPivot.period = period; + iPivot.type = XPV_VALE; + iPivot.repetition = valeRepeate; + iPivot.to = iTime( + symbol, + period, + valeToBarIndex // + ); + iPivot.from = iTime( + symbol, + period, + valeFromBarIndex // + ); + + // + iPivot.upper = iPivot.CalculateUpper(); + + // + bool isValid = iPivot.IsValid(); + if (isValid) + { + // + AddRef( + iPivot, + vales // + ); + } + } + } + + // + vale = iVale; + valeRepeate = 0; + valeFromBarIndex = 0; + valeToBarIndex = barIndex; + } + else if (iVale == vale) + { + // + valeRepeate++; + valeFromBarIndex = barIndex; + } + + // + canLookupPeak = ArraySize(peaks) < requiredPivots; + canLookupVale = ArraySize(vales) < requiredPivots; + canLookup = barIndex < end && + (canLookupPeak || + canLookupVale); + if (canLookup) + { + barIndex++; + } + } + + // + result = IsValidSize(ArraySize(peaks)) || + IsValidSize(ArraySize(vales)); + if (!result) + { + return result; + } + + // + // Detect Order Flow ... + Copy( + peaks, + orderFlow, + false // + ); + Copy( + vales, + orderFlow, + false // + ); + int count = ArraySize(orderFlow); + result = IsValidSize(orderFlow); + if (!result) + { + return result; + } + + // + // Sort Pivots ... + SortPivots(orderFlow); + + // + // Filter Broken Order Flows ... + FilterBrokenPivots(orderFlow); + + // + // Detect Order Flow Direction ... + result = DetectPivotDirection( + orderFlow, + orderFlowDirection // + ); + if (!result) + { + return result; + } + + // + // Find State Inside Pivots and Attached Them to Pivot ... + int orderFlowCount = ArraySize(mOrderFlow); + if (IsValidSize(orderFlowCount)) + { + // + // Loop Through Order Flow ... + for (int i = 0; i < orderFlowCount; i++) + { + // + FillPivotSate( + i, + true, // Use Vision State ... + true, // Use Analyse State ... + false // Use Trigger State ... + ); + } + } + + // + return result; + } + + /** + * Filling Specified Orer Flow Index ... + * + * @param pivotIDX: Integer ... + * @param lookupSwingHighs: Boolean ... + * @param lookupSwingLows: Boolean ... + * @param lookupSupportZones: Boolean ... + * @param lookupResistanceZones: Boolean ... + * @param lookupSupplyZones: Boolean ... + * @param lookupDemandZones: Boolean ... + * @param lookupBullishOrderBlocks: Boolean ... + * @param lookupBearishOrderBlocks: Boolean ... + * @param lookupBullishFairValueGaps: Boolean ... + * @param lookupBearishFairValueGaps: Boolean ... + * @param lookupBullishRejectionBars: Boolean ... + * @param lookupBearishRejectionBars: Boolean ... + * @param lookupBullishMomentumBars: Boolean ... + * @param lookupBearishMomentumBars: Boolean ... + */ + void FillPivotSate( + int pivotIDX, // + bool useVisionState = true, // Use Vision State ... + bool useAnalyseState = true, // Use Analyse State ... + bool useTriggerState = true, // Use Trigger State ... + bool lookupSwingHighs = true, + bool lookupSwingLows = true, + bool lookupSupportZones = true, + bool lookupResistanceZones = true, + bool lookupSupplyZones = true, + bool lookupDemandZones = true, + bool lookupBullishOrderBlocks = true, + bool lookupBearishOrderBlocks = true, + bool lookupBullishFairValueGaps = true, + bool lookupBearishFairValueGaps = true, + bool lookupBullishRejectionBars = true, + bool lookupBearishRejectionBars = true, + bool lookupBullishMomentumBars = true, + bool lookupBearishMomentumBars = true // + ) + { + // + CalculatePivotTickZone(pivotIDX); + + // + // Trigger ... + XPOIState mTriggerState; + if (useTriggerState && + mTriggerPOIState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mTriggerPOIState, + mTriggerState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mTriggerState.HasChild()) + { + mTriggerState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Analyse ... + XPOIState mAnalyseState; + if (useAnalyseState && + mAnalysePOIState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mAnalysePOIState, + mAnalyseState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mAnalyseState.HasChild()) + { + mAnalyseState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Vision ... + XPOIState mVisionState; + if (useVisionState && + mVisionPOIState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mVisionPOIState, + mVisionState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mVisionState.HasChild()) + { + mVisionState.Fill(mOrderFlow[pivotIDX].state); + } + } + } + + /** + * When a BOS Happens ... + * we have to Update Order Flow ... + */ + void UpdateOrderFlow() + { + ResetOrderFlow(); + } + + /** + * Fill Pivot Tick Zone ... + * + * @param pivotIDX: Integer ... + */ + void CalculatePivotTickZone(int pivotIDX) + { + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + bool isInited = false; + + // + datetime from = mOrderFlow[pivotIDX].from; + XOHCL iFromBar; + int iFromBarIndex = iBarShift( + symbol, + period, + from // + ); + isInited = iFromBar.Init( + symbol, + period, + iFromBarIndex // + ); + if (!isInited) + { + return; + } + + // + datetime to = mOrderFlow[pivotIDX].to; + XOHCL iToBar; + int iToBarIndex = iBarShift( + symbol, + period, + to // + ); + isInited = iToBar.Init( + symbol, + period, + iToBarIndex // + ); + if (!isInited) + { + return; + } + + // + XCTicksZone *iZone; + iZone = new XCTicksZone(); + + // + int ticksLevels = mTriggerPOIDetector.TicksRangeZoneLevel(); + int ticksRange = mTriggerPOIDetector.TicksRangeZoneRange(); + isInited = ticksLevels > 0 && + ticksRange > 0; + if (!isInited) + { + return; + } + + // + isInited = iZone.Init( + iFromBar, + iToBar // + ); + if (!isInited) + { + return; + } + + // + mOrderFlow[pivotIDX].state.ticksZone = iZone; + } + + /** + * Validate Order Flow ... + * + * @return ( bool ) + */ + bool HasValidOrderFlow() + { + // + bool result = false; + + // + int orderFlowCount = ArraySize(mOrderFlow); + result = + IsValidSize(orderFlowCount) && + mOrderFlowDir != X_DIRECTION_ALL && + mOrderFlowDir != X_DIRECTION_NONE; + + // + return result; + } + + /** + * Reset Order Flow ... + */ + void ResetOrderFlow() + { + // + Clean(mOrderFlow); + mOrderFlowDir = X_DIRECTION_NONE; + + // + ClearDraws(); + } + + bool FindPOIInPivot( + XCBasePOI *&pois[], + ENUM_XPOIS type, + XPVPivot &pivot, + XPOIState &state, + ENUM_X_DIRECTION dir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + Clean(pois); + + // + // Validate Inputs ... + result = + // + type != X_POI_NONE && + pivot.IsValid() && + state.IsValid() && + state.HasChild() + // + ; + if (!result) + { + return result; + } + + // + int swingHighsCunt = state.CountSwingHighs(); + int swingLowsCunt = state.CountSwingLows(); + int bullishMomentumBarsCunt = state.CountBullishMomentumBars(); + int bearishMomentumBarsCunt = state.CountBearishMomentumBars(); + int bullishRejectionBarsCunt = state.CountBullishRejectionBars(); + int bearishRejectionBarsCunt = state.CountBearishRejectionBars(); + int supportZonesCunt = state.CountSupportZones(); + int resistanceZonesCunt = state.CountResistanceZones(); + int supplyZonesCunt = state.CountSupplyZones(); + int demandZonesCunt = state.CountDemandZones(); + int bullishOrderBlocksCunt = state.CountBullishOrderBlocks(); + int bearishOrderBlocksCunt = state.CountBearishOrderBlocks(); + int bullishFairValueGapsCunt = state.CountBullishFairValueGaps(); + int bearishFairValueGapsCunt = state.CountBearishFairValueGaps(); + + // + switch (type) + { + // + case X_POI_MOMENTUM_BAR: { + // + // Validate Direction ... + result = HasDirection(dir); + if (!result) + { + return result; + } + + // + bool isBullishDir = IsBullish(dir); + + // + // Validate State POI(s) ... + result = + isBullishDir + ? IsValidSize(bullishMomentumBarsCunt) + : IsValidSize(bearishMomentumBarsCunt); + if (!result) + { + break; + } + + // + if (isBullishDir) + { + // + for (int i = 0; i < bullishMomentumBarsCunt; i++) + { + // + } + } + else + { + // + for (int i = 0; i < bullishMomentumBarsCunt; i++) + { + // + } + } + + // + break; + }; + + // + case X_POI_REJECTION_BAR: { + // + // Validate Direction ... + result = HasDirection(dir); + if (!result) + { + return result; + } + + // + bool isBullishDir = IsBullish(dir); + + // + // Validate State POI(s) ... + result = + isBullishDir + ? IsValidSize(bullishMomentumBarsCunt) + : IsValidSize(bearishMomentumBarsCunt); + if (!result) + { + break; + } + + // + if (isBullishDir) + { + // + for (int i = 0; i < bullishMomentumBarsCunt; i++) + { + // + } + } + else + { + // + for (int i = 0; i < bullishMomentumBarsCunt; i++) + { + // + } + } + + // + break; + }; + + // + case X_POI_SWING_HIGH: + break; + + // + case X_POI_SWING_LOW: + break; + + // + case X_POI_SUPPORT_ZONE: + break; + + // + case X_POI_RESISTANCE_ZONE: + break; + + // + case X_POI_SUPPLY_ZONE: + break; + + // + case X_POI_DEMAND_ZONE: + break; + + // + case X_POI_BULLISH_ORDERBLOCK: + break; + + // + case X_POI_BEARISH_ORDERBLOCK: + break; + + // + case X_POI_BULLISH_FVG: + break; + + // + case X_POI_BEARISH_FVG: + break; + } + + // + return result; + } + + // + // Drawings ... + + /** + * Draw Order Flow ... + */ + void + RedrawOrderFlow( + bool forceClearDraws = true, + bool forceDrawSamePeriod = true, + bool drawOrderFlow = true, + bool drawOrderFlowState = true, + bool drawOnlyLastOrderFlow = false, + bool drawOnlyLastOrderFlowState = true, + // + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + // + // Ignores List ... + bool ignoreSwingHighs = false, + bool ignoreSwingLows = false, + bool ignoreSupportZones = false, + bool ignoreResistanceZones = false, + bool ignoreSupplyZones = false, + bool ignoreDemandZones = false, + bool ignoreBullishOrderBlocks = false, + bool ignoreBearishOrderBlocks = false, + bool ignoreBullishFairValueGaps = false, + bool ignoreBearishFairValueGaps = false, + bool ignoreBullishRejectionBars = false, + bool ignoreBearishRejectionBars = false, + bool ignoreBullishMomentumBars = false, + bool ignoreBearishMomentumBars = false, + // + // States Drawing ... + bool drawVisionState = false, + bool drawAnalyseState = false, + bool drawTriggerState = false // + ) + { + // + if (forceClearDraws) + { + ClearDraws(); + } + + // + if (!drawOrderFlow || + !HasValidOrderFlow()) + { + return; + } + + // + int orderFlowCount = ArraySize(mOrderFlow); + for (int i = 0; i < orderFlowCount; i++) + { + // + bool isLast = i == orderFlowCount - 1; + bool canDraw = + !drawOnlyLastOrderFlow || + (isLast && + drawOnlyLastOrderFlow); + if (!canDraw) + { + continue; + } + + // + XPVPivot iPivot = mOrderFlow[i]; + + // + XCXPVPivotObject *iObj; + iObj = new XCXPVPivotObject(); + bool isCreated = iObj.Create( + mPOIDrawer.ChartIdentification(), + mPOIDrawer.SubWindowIdentification(), + iPivot // + ); + if (isCreated) + { + // + bool canDrawState = + drawOrderFlowState && + (!drawOnlyLastOrderFlowState || + (isLast && + drawOnlyLastOrderFlowState)); + if (canDrawState) + { + // + CustomStateDrawing( + iPivot.state, + forceDrawSamePeriod, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + if (iPivot.IsPeak()) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotColor(clrAqua); + iObj.PivotStyle(STYLE_SOLID); + } + + // + if (iPivot.IsVale()) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotStyle(STYLE_SOLID); + iObj.PivotColor(clrMagenta); + } + + // + AddObjectIfNotExists(iObj); + } + } + + // + // Vision ... + if (drawVisionState) + { + // + CustomStateDrawing( + mTriggerPOIState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Analyse ... + if (drawAnalyseState) + { + // + CustomStateDrawing( + mAnalysePOIState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Trigger ... + if (drawTriggerState) + { + // + CustomStateDrawing( + mVisionPOIState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + } + + /** + * Custom Drawing State ... + * + * @param state: XPOIState instance reference, Specified Which state to Draw ... + * @param forceDrawSamePeriod: Boolean ... + */ + void CustomStateDrawing( + XPOIState &state, + bool forceDrawSamePeriod = false, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + // + // Ignores List ... + bool ignoreSwingHighs = false, + bool ignoreSwingLows = false, + bool ignoreSupportZones = false, + bool ignoreResistanceZones = false, + bool ignoreSupplyZones = false, + bool ignoreDemandZones = false, + bool ignoreBullishOrderBlocks = false, + bool ignoreBearishOrderBlocks = false, + bool ignoreBullishFairValueGaps = false, + bool ignoreBearishFairValueGaps = false, + bool ignoreBullishRejectionBars = false, + bool ignoreBearishRejectionBars = false, + bool ignoreBullishMomentumBars = false, + bool ignoreBearishMomentumBars = false // + ) + { + // + XPOIState tmpState = state; + if (forceDrawSamePeriod) + { + // + int count = 0; + ENUM_TIMEFRAMES period = GetPeriod(); + + // + count = state.CountSwingHighs(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing iSwing = state.swingHighs[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.swingHighs, + i, + 1 // + ); + } + } + } + + // + count = state.CountSwingLows(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing iSwing = state.swingLows[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.swingLows, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishMomentumBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar iMomentum = state.bullishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishMomentumBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishMomentumBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar iMomentum = state.bearishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishMomentumBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishRejectionBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar iRejection = state.bullishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishRejectionBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishRejectionBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar iRejection = state.bearishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishRejectionBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountSupportZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZone iZone = state.supportZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.supportZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountResistanceZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZone iZone = state.resistanceZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.resistanceZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountSupplyZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupplyZone iZone = state.supplyZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.supplyZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountDemandZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCDemandZone iZone = state.demandZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.demandZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock iZone = state.bullishOrderBlocks[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishOrderBlocks, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock iZone = state.bearishOrderBlocks[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishOrderBlocks, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishFairValueGaps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG iZone = state.bullishFairValueGaps[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillStartBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishFairValueGaps, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishFairValueGaps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG iZone = state.bearishFairValueGaps[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillStartBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishFairValueGaps, + i, + 1 // + ); + } + } + } + + // + } + + // + bool drawSwingHighs = true; + bool drawSwingLows = true; + bool drawSupportZones = true; + bool drawResistanceZones = true; + bool drawSupplyZones = true; + bool drawDemandZones = true; + bool drawBullishOrderBlocks = true; + bool drawBearishOrderBlocks = true; + bool drawBullishFairValueGaps = true; + bool drawBearishFairValueGaps = true; + bool drawBullishRejectionBars = true; + bool drawBearishRejectionBars = true; + bool drawBullishMomentumBars = true; + bool drawBearishMomentumBars = true; + + // + // Change Drawing Specs Conditions based on + // Provided Direction ... + if (forDir == X_DIRECTION_BULLISH) + { + // + drawSwingLows = true; + drawDemandZones = true; + drawSupportZones = true; + drawBullishOrderBlocks = true; + drawBullishFairValueGaps = true; + drawBullishRejectionBars = true; + drawBullishMomentumBars = true; + + // + drawSwingHighs = false; + drawSupplyZones = false; + drawResistanceZones = false; + drawBearishOrderBlocks = false; + drawBearishFairValueGaps = false; + drawBearishRejectionBars = false; + drawBearishMomentumBars = false; + } + else if (forDir == X_DIRECTION_BEARISH) + { + // + drawSwingLows = false; + drawDemandZones = false; + drawSupportZones = false; + drawBullishOrderBlocks = false; + drawBullishFairValueGaps = false; + drawBullishRejectionBars = false; + drawBullishMomentumBars = false; + + // + drawSwingHighs = true; + drawSupplyZones = true; + drawResistanceZones = true; + drawBearishOrderBlocks = true; + drawBearishFairValueGaps = true; + drawBearishRejectionBars = true; + drawBearishMomentumBars = true; + } + + // + // Apply Ignore List ... + + // + if (ignoreSwingHighs) + { + drawSwingHighs = false; + } + + // + if (ignoreSwingLows) + { + drawSwingLows = false; + } + + // + if (ignoreSupportZones) + { + drawSupportZones = false; + } + + // + if (ignoreResistanceZones) + { + drawResistanceZones = false; + } + + // + if (ignoreSupplyZones) + { + drawSupplyZones = false; + } + + // + if (ignoreDemandZones) + { + drawDemandZones = false; + } + + // + if (ignoreBullishOrderBlocks) + { + drawBullishOrderBlocks = false; + } + + // + if (ignoreBearishOrderBlocks) + { + drawBearishOrderBlocks = false; + } + + // + if (ignoreBullishFairValueGaps) + { + drawBullishFairValueGaps = false; + } + + // + if (ignoreBearishFairValueGaps) + { + drawBearishFairValueGaps = false; + } + + // + if (ignoreBullishRejectionBars) + { + drawBullishRejectionBars = false; + } + + // + if (ignoreBearishRejectionBars) + { + drawBearishRejectionBars = false; + } + + // + if (ignoreBullishMomentumBars) + { + drawBullishMomentumBars = false; + } + + // + if (ignoreBearishMomentumBars) + { + drawBearishMomentumBars = false; + } + + // + DrawState( + tmpState, // State ... + true, // Update To of all Drawings Till now ... + drawSwingHighs, // Draw SwingHighs .. + drawSwingLows, // Draw SwingLows .. + drawSupportZones, // Draw SupportZones .. + drawResistanceZones, // Draw ResistanceZones .. + drawSupplyZones, // Draw SupplyZones .. + drawDemandZones, // Draw DemandZones .. + drawBullishOrderBlocks, // Draw BullishOrderBlocks .. + drawBearishOrderBlocks, // Draw BearishOrderBlocks .. + drawBullishFairValueGaps, // Draw BullishFairValueGaps .. + drawBearishFairValueGaps, // Draw BearishFairValueGaps .. + drawBullishRejectionBars, // Draw BullishRejectionBars .. + drawBearishRejectionBars, // Draw BearishRejectionBars .. + drawBullishMomentumBars, // Draw BullishMomentumBars .. + drawBearishMomentumBars, // Draw BearishMomentumBars .. + true // Draw Ticks Zone ... + ); + } + + // + // Private ... + private: + // + // Props ... + + /** + * Initial Required Indicators Helper ... + */ + void InitialHelpers() + { + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + // Short ... + ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES scPeriod = NULL; // Time Period + + // + // Medium ... + ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES mcPeriod = NULL; // Time Period + + // + // Long ... + ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES lcPeriod = NULL; // Time Period + + // + // Hind ... + ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES hcPeriod = NULL; // Time Period + + // + // XPV ... + + // + xpvInputs.Default(); + + // + xpvInputs.scMethod = scMethod; + xpvInputs.scPeriod = scPeriod; + xpvInputs.mcMethod = mcMethod; + xpvInputs.mcPeriod = mcPeriod; + xpvInputs.lcMethod = lcMethod; + xpvInputs.lcPeriod = lcPeriod; + xpvInputs.hcMethod = hcMethod; + xpvInputs.hcPeriod = hcPeriod; + + // + xpvInputs.showPeaksAndVales = true; + xpvInputs.showLevels = false; + xpvInputs.showConsolidations = false; + xpvInputs.showFibo1Levels = false; + xpvInputs.showFibo2Levels = false; + xpvInputs.showFibo3Levels = false; + xpvInputs.showFibo4Levels = false; + xpvInputs.showFibo5Levels = false; + + // + xpvHelper = new XCXPVHelper(); + xpvHelper.Init( + symbol, + period, + xpvInputs // + ); + + // + // X3MA ... + + // + x3maInputs.Default(); + + // + x3maInputs.showFast = true; + x3maInputs.showMid = false; + x3maInputs.showSlow = false; + + // + x3maHelper = new XCX3MAHelper(); + x3maHelper.Init( + symbol, + period, + x3maInputs // + ); + + // + // X3VWAP ... + + // + x3vwapInputs.Default(); + + // + x3vwapInputs.showFast = true; + x3vwapInputs.showMid = true; + x3vwapInputs.showSlow = true; + + // + x3vwapHelper = new XCX3VWAPHelper(); + x3vwapHelper.Init( + symbol, + period, + x3vwapInputs // + ); + + // + // XCHCHSAR ... + + // + xchsarInputs.Default(); + + // + xchsarInputs.scMethod = scMethod; + xchsarInputs.scPeriod = scPeriod; + xchsarInputs.mcMethod = mcMethod; + xchsarInputs.mcPeriod = mcPeriod; + xchsarInputs.lcMethod = lcMethod; + xchsarInputs.lcPeriod = lcPeriod; + xchsarInputs.hcMethod = hcMethod; + xchsarInputs.hcPeriod = hcPeriod; + + // + xchsarInputs.showCurrent = true; + xchsarInputs.showShort = false; + xchsarInputs.showMedium = false; + xchsarInputs.showLong = false; + xchsarInputs.showHind = false; + + // + xchsarHelper = new XCXCHSARHelper(); + xchsarHelper.Init( + symbol, + period, + xchsarInputs // + ); + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/x-121.smc.test.strategy.class copy 2.mq5 b/BKPS/14030923/Documents/BKP/x-121.smc.test.strategy.class copy 2.mq5 new file mode 100644 index 0000000..d9966ca --- /dev/null +++ b/BKPS/14030923/Documents/BKP/x-121.smc.test.strategy.class copy 2.mq5 @@ -0,0 +1,2793 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCX121SMCTestStrategy +// Description: provides all based classes for use ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... + +// +#include "../Classes/x-121.smc.base.strategy.class.mq5" +#include "../Classes/x-121.smc.market.cycle.helper.class.mq5" + +// +// Definitions ... + +// +// XStrategy Class Implementation(s) ... +class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy +{ + // + // Public ... + public: + // + + // + // Constructor(s) ... + void XCX121SMCTestStrategy( + // + // Base ... + string _symbol, // Trading Symbol + ENUM_TIMEFRAMES _period // Trading TimeFrame + ) + : XCX121SMCBaseStrategy(_symbol, _period) + { + InitialHelpers(); + } + + // + // Deconstructur ... + void ~XCX121SMCTestStrategy() + { + } + + // + // Overrides Actions ... + + /** + * Destroy All Class Implementations ... + */ + void Destroy() override + { + // + delete mTriggerCycleHelper; + delete mDecisionCycleHelper; + delete mAnalyseCycleHelper; + delete mVerificationCycleHelper; + delete mConsolidationCycleHelper; + delete mVisionCycleHelper; + } + + /** + * Check Conditions For Signal ... + */ + bool HasSignal( + XSignal &signal, + X121SMCStrategyConditions &conditions // + ) override + { + // + bool result = false; + + // + signal.Clean(); + conditions.Clean(); + + // + int pushers = 0; + + // + double sl = 0; + double tp = 0; + double risk = 0; + double entry = 0; + double reward = 0; + double r2r = R2R(); + string provider = ""; + double volume = Volume(); + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY; + ENUM_X_ORDER_MODES mode = X_ORDER_MODE_MARKET; + + // + bool hasLong = false; + bool hasShort = false; + + // + double selectedSL = 0; + + // + // Start Calculations ... + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + double points = GetPoints(symbol); + double pip = GetPipPrice(symbol); + double pip2 = 2 * pip; + + // + // Detect Conditions ... + result = DetectConditions(conditions); + if (!result) + { + conditions.Clean(); + return result; + } + + // + // Check Spread ... + bool isSpreadPassed = IsSpreadPass(); + result = isSpreadPassed; + if (!result) + { + // + // string message = "Spread is not Passed for Analysing ..."; + // LogAlert(message); + + // + return result; + } + + // + // Combine all Signals Conditions ... + selectedSL = conditions.sl; + provider = conditions.provider; + + // + hasLong = + // + IsBullish(conditions.marketStructureDir) + // + ; + + // + hasShort = + // + IsBearish(conditions.marketStructureDir) + // + ; + + // + result = hasLong || + hasShort; + + // + // Rmove Signal Condition ... + if (result) + { + // + // TYPE ... + type = + hasLong + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + ENUM_X_POSITION_TYPES xType = + hasLong + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + entry = GetEntry( + conditions.symbol, + type // + ); + + // + sl = + hasLong + ? selectedSL - pip2 + : selectedSL + pip2; + + // + // RISK Reward ... + risk = + hasLong + ? entry - sl + : sl - entry; + reward = risk * r2r; + tp = + hasLong + ? entry + reward + : entry - reward; + + // + signal.sl = sl; + signal.tp = tp; + signal.type = type; + signal.mode = mode; + signal.entry = entry; + signal.volume = volume; + signal.symbol = symbol; + signal.period = period; + signal.pushers = pushers; + signal.provider = provider; + signal.time = TimeCurrent(); + + // + result = PrepareSignal(signal); + if (result) + { + // + Print("PRV: ", provider); + + // + ENUM_X_DIRECTION forDir = ToDirection(signal.type); + bool ignoreSwingHighs = false; + bool ignoreSwingLows = false; + bool ignoreSupportZones = false; + bool ignoreResistanceZones = false; + bool ignoreSupplyZones = false; + bool ignoreDemandZones = false; + bool ignoreBullishOrderBlocks = false; + bool ignoreBearishOrderBlocks = false; + bool ignoreBullishFairValueGaps = false; + bool ignoreBearishFairValueGaps = false; + bool ignoreBullishRejectionBars = false; + bool ignoreBearishRejectionBars = false; + bool ignoreBullishMomentumBars = false; + bool ignoreBearishMomentumBars = false; + if (IsBullish(forDir)) + { + // + ignoreSwingLows = false; + ignoreDemandZones = false; + ignoreSupportZones = false; + ignoreBullishOrderBlocks = false; + ignoreBullishFairValueGaps = false; + ignoreBullishRejectionBars = false; + ignoreBullishMomentumBars = false; + } + else + { + // + ignoreSwingHighs = true; + ignoreSupplyZones = true; + ignoreResistanceZones = true; + ignoreBearishOrderBlocks = true; + ignoreBearishFairValueGaps = false; + ignoreBearishRejectionBars = true; + ignoreBearishMomentumBars = true; + } + + // + RedrawOrderFlow( + true, // Force Clean ... + false, // Same Period ... + true, // Order Flow ... + true, // Order Flow State ... + false, // Only Last Order Flow ... + true, // Only Last Order Flow State ... + // + forDir, // Direction Force ... + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + DrawSignal(signal); + ClearDraws(); + + // + ResetOrderFlow(); + } + + // + hasLong = false; + hasShort = false; + } + + // + return result; + } + + /** + * Customize Strategy Identifier ... + */ + string GetTag() override + { + return X121SMCStrategyToken; + } + + // + // Protected ... + protected: + // + + // + // Props ... + + // + // Trigger Order Flow ... + XPVPivot mOrderFlow[]; + ENUM_X_DIRECTION mOrderFlowDir; + + // + XC121SMCCycleHelper *mTriggerCycleHelper; + XC121SMCCycleHelper *mDecisionCycleHelper; + XC121SMCCycleHelper *mAnalyseCycleHelper; + XC121SMCCycleHelper *mVerificationCycleHelper; + XC121SMCCycleHelper *mConsolidationCycleHelper; + XC121SMCCycleHelper *mVisionCycleHelper; + + // + // Actions ... + + /** + * Detect and Parse Market Conditions ... + * + * @return ( bool ) + */ + bool DetectConditions( + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + string msg = NULL; + + // + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + + // + conditions.time = cTime; + conditions.symbol = symbol; + conditions.period = period; + + // + int conditionsLoopback = 7; + + // + // Fill Cycles Conditions ... + + // + // Trigger ... + mTriggerCycleHelper.GetConditions( + conditions.triggerConditions, + zIndex, + conditionsLoopback // + ); + conditions.triggerConditions.state = mTriggerState; + + // + // Decision ... + mDecisionCycleHelper.GetConditions( + conditions.decisionConditions, + zIndex, + conditionsLoopback // + ); + conditions.decisionConditions.state = mDecisionState; + + // + // Analyse ... + mAnalyseCycleHelper.GetConditions( + conditions.analyseConditions, + zIndex, + conditionsLoopback // + ); + conditions.analyseConditions.state = mAnalyseState; + + // + // Verification ... + mVerificationCycleHelper.GetConditions( + conditions.verificationConditions, + zIndex, + conditionsLoopback // + ); + conditions.verificationConditions.state = mVerificationState; + + // + // Consolidation ... + mConsolidationCycleHelper.GetConditions( + conditions.consolidationConditions, + zIndex, + conditionsLoopback // + ); + conditions.consolidationConditions.state = mConsolidationState; + + // + // Vision ... + mVisionCycleHelper.GetConditions( + conditions.visionConditions, + zIndex, + conditionsLoopback // + ); + conditions.visionConditions.state = mVisionState; + + // + // Detect and Store Parabolic Sar Changes ... + XSarChange sarChange; + bool isSarChanged = mTriggerCycleHelper + .IsSarChanged( + sarChange, + cTime // + ); + + // + // Detect and Store Pivots ... + XPVPivot pivot; + bool isPivotDetected = mTriggerCycleHelper + .DetectPivot(pivot); + if (isPivotDetected) { + // + Print("Pivot Detected ..."); + + // + ClearDraws(); + XCXPVPivotObject *iObj; + iObj = new XCXPVPivotObject(); + bool isCreated = iObj.Create( + mPOIDrawer.ChartIdentification(), + mPOIDrawer.SubWindowIdentification(), + pivot // + ); + if (isCreated) + { + // + if (pivot.IsPeak()) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotColor(clrAqua); + iObj.PivotStyle(STYLE_SOLID); + } + + // + if (pivot.IsVale()) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotStyle(STYLE_SOLID); + iObj.PivotColor(clrMagenta); + } + + // + AddObjectIfNotExists(iObj); + } + } + + // + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + return result; + } + + /** + * Detect XPV Based POI(s) ... + * + * @param barIndex: Start Bar Index ... + * @param minRepetition: minimum Repeate of POI for Validation ... + * @param requiredPivots: Number of Min Requirement POI(s) ... + * @param pivotHelper: XC121SMCCycleHelper instance Pointer ... + * @param orderFlow: XPVPivot instance Array Reference ... + * @param orderFlowDirection: ENUM_X_DIRECTION member Reference which represents OrderFlow Direction ... + * @param maxAllowedLoopbackBars: Integer, Max Allowed Loopback Bars ... + * + * @return ( bool ) + */ + bool DetectOrderFlow( + int barIndex, + int minRepetition, + int requiredPivots, + XC121SMCCycleHelper *pivotHelper, // XPV Helper ... + XPVPivot &orderFlow[], // OrderFlows ... + ENUM_X_DIRECTION &orderFlowDirection, // Order Flow Direction ... + // + bool useVisionState = true, // Use Vision State ... + bool useConsolidationState = true, // Use Consolidation State ... + bool useVerificationState = true, // Use Verification State ... + bool useAnalyseState = true, // Use Analyse State ... + bool useDecisionState = true, // Use Decision State ... + bool useTriggerState = true, // Use Trigger State ... + // + int maxAllowedLoopbackBars = 576 // + ) + { + // + bool result = false; + + // + orderFlowDirection = X_DIRECTION_NONE; + + // + if (maxAllowedLoopbackBars <= 0) + { + maxAllowedLoopbackBars = 1000; + } + + // + int start = barIndex; + int end = start + maxAllowedLoopbackBars; + + // + Clean(orderFlow); + + // + result = minRepetition > 0 && + requiredPivots > 0 && + pivotHelper != NULL; + if (!result) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + double peak = 0; + XPVPivot peaks[]; + int peakRepeate = 0; + int peakToBarIndex = 0; + int peakFromBarIndex = 0; + + // + double vale = 0; + XPVPivot vales[]; + int valeRepeate = 0; + int valeToBarIndex = 0; + int valeFromBarIndex = 0; + + // + bool canLookupPeak = true; + bool canLookupVale = true; + bool canLookup = true; + while (canLookup) + { + // + // Check Peak ... + double iPeak = pivotHelper.mXPVHelper.GetPeak(barIndex); + if (iPeak != peak) + { + // + if (peak != 0 && + peakRepeate >= minRepetition) + { + // + bool isExists = false; + int count = ArraySize(peaks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = peaks[i]; + + // + if (iPivot.upper == iPeak) + { + // + isExists = true; + break; + } + } + } + if (!isExists) + { + // + XPVPivot iPivot; + + // + iPivot.lower = 0; + iPivot.upper = peak; + iPivot.symbol = symbol; + iPivot.period = period; + iPivot.type = XPV_PEAK; + iPivot.repetition = peakRepeate; + iPivot.to = iTime( + symbol, + period, + peakToBarIndex // + ); + iPivot.from = iTime( + symbol, + period, + peakFromBarIndex // + ); + + // + iPivot.lower = iPivot.CalculateLower(); + + // + bool isValid = iPivot.IsValid(); + if (isValid) + { + // + AddRef( + iPivot, + peaks // + ); + } + } + } + + // + peak = iPeak; + peakRepeate = 0; + peakFromBarIndex = 0; + peakToBarIndex = barIndex; + } + else if (iPeak == peak) + { + // + peakRepeate++; + peakFromBarIndex = barIndex; + } + + // + // Check Vale ... + double iVale = pivotHelper.mXPVHelper.GetVale(barIndex); + if (iVale != vale) + { + // + if (vale != 0 && + valeRepeate >= minRepetition) + { + // + bool isExists = false; + int count = ArraySize(vales); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = vales[i]; + + // + if (iPivot.lower == iVale) + { + // + isExists = true; + break; + } + } + } + if (!isExists) + { + // + XPVPivot iPivot; + + // + iPivot.upper = 0; + iPivot.lower = vale; + iPivot.symbol = symbol; + iPivot.period = period; + iPivot.type = XPV_VALE; + iPivot.repetition = valeRepeate; + iPivot.to = iTime( + symbol, + period, + valeToBarIndex // + ); + iPivot.from = iTime( + symbol, + period, + valeFromBarIndex // + ); + + // + iPivot.upper = iPivot.CalculateUpper(); + + // + bool isValid = iPivot.IsValid(); + if (isValid) + { + // + AddRef( + iPivot, + vales // + ); + } + } + } + + // + vale = iVale; + valeRepeate = 0; + valeFromBarIndex = 0; + valeToBarIndex = barIndex; + } + else if (iVale == vale) + { + // + valeRepeate++; + valeFromBarIndex = barIndex; + } + + // + canLookupPeak = ArraySize(peaks) < requiredPivots; + canLookupVale = ArraySize(vales) < requiredPivots; + canLookup = barIndex < end && + (canLookupPeak || + canLookupVale); + if (canLookup) + { + barIndex++; + } + } + + // + result = IsValidSize(ArraySize(peaks)) || + IsValidSize(ArraySize(vales)); + if (!result) + { + return result; + } + + // + // Detect Order Flow ... + Copy( + peaks, + orderFlow, + false // + ); + Copy( + vales, + orderFlow, + false // + ); + int count = ArraySize(orderFlow); + result = IsValidSize(orderFlow); + if (!result) + { + return result; + } + + // + // Sort Pivots ... + SortPivots(orderFlow); + + // + // Filter Broken Order Flows ... + FilterBrokenPivots(orderFlow); + + // + // Detect Order Flow Direction ... + result = DetectPivotDirection( + orderFlow, + orderFlowDirection // + ); + if (!result) + { + return result; + } + + // + // Find State Inside Pivots and Attached Them to Pivot ... + int orderFlowCount = ArraySize(mOrderFlow); + if (IsValidSize(orderFlowCount)) + { + // + // Loop Through Order Flow ... + for (int i = 0; i < orderFlowCount; i++) + { + // + FillPivotSate( + i, + useVisionState, // Use Vision State ... + useConsolidationState, // Use Consolidation State ... + useVerificationState, // Use Verification State ... + useAnalyseState, // Use Analyse State ... + useDecisionState, // Use Decision State ... + useTriggerState // Use Trigger State ... + ); + } + } + + // + return result; + } + + /** + * Filling Specified Orer Flow Index ... + * + * @param pivotIDX: Integer ... + * @param lookupSwingHighs: Boolean ... + * @param lookupSwingLows: Boolean ... + * @param lookupSupportZones: Boolean ... + * @param lookupResistanceZones: Boolean ... + * @param lookupSupplyZones: Boolean ... + * @param lookupDemandZones: Boolean ... + * @param lookupBullishOrderBlocks: Boolean ... + * @param lookupBearishOrderBlocks: Boolean ... + * @param lookupBullishFairValueGaps: Boolean ... + * @param lookupBearishFairValueGaps: Boolean ... + * @param lookupBullishRejectionBars: Boolean ... + * @param lookupBearishRejectionBars: Boolean ... + * @param lookupBullishMomentumBars: Boolean ... + * @param lookupBearishMomentumBars: Boolean ... + */ + void FillPivotSate( + int pivotIDX, // + bool useVisionState = true, // Use Vision State ... + bool useConsolidationState = true, // Use Consolidation State ... + bool useVerificationState = true, // Use Verification State ... + bool useAnalyseState = true, // Use Analyse State ... + bool useDecisionState = true, // Use Decision State ... + bool useTriggerState = true, // Use Trigger State ... + bool lookupSwingHighs = true, + bool lookupSwingLows = true, + bool lookupSupportZones = true, + bool lookupResistanceZones = true, + bool lookupSupplyZones = true, + bool lookupDemandZones = true, + bool lookupBullishOrderBlocks = true, + bool lookupBearishOrderBlocks = true, + bool lookupBullishFairValueGaps = true, + bool lookupBearishFairValueGaps = true, + bool lookupBullishRejectionBars = true, + bool lookupBearishRejectionBars = true, + bool lookupBullishMomentumBars = true, + bool lookupBearishMomentumBars = true // + ) + { + // + CalculatePivotTickZone(pivotIDX); + + // + // Trigger ... + XPOIState mPivotTriggerState; + if (useTriggerState && + mTriggerState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mTriggerState, + mPivotTriggerState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotTriggerState.HasChild()) + { + mPivotTriggerState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Decision ... + XPOIState mPivotDecisionState; + if (useDecisionState && + mDecisionState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mDecisionState, + mPivotDecisionState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotDecisionState.HasChild()) + { + mPivotDecisionState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Analyse ... + XPOIState mPivotAnalyseState; + if (useAnalyseState && + mAnalyseState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mAnalyseState, + mPivotAnalyseState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotAnalyseState.HasChild()) + { + mPivotAnalyseState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Verification ... + XPOIState mPivotVerificationState; + if (useVerificationState && + mVerificationState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mVerificationState, + mPivotVerificationState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotVerificationState.HasChild()) + { + mPivotVerificationState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Consolidation ... + XPOIState mPivotConsolidationState; + if (useConsolidationState && + mConsolidationState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mConsolidationState, + mPivotConsolidationState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotConsolidationState.HasChild()) + { + mPivotConsolidationState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Vision ... + XPOIState mPivotVisionState; + if (useVisionState && + mVisionState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mVisionState, + mPivotVisionState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotVisionState.HasChild()) + { + mPivotVisionState.Fill(mOrderFlow[pivotIDX].state); + } + } + } + + /** + * When a BOS Happens ... + * we have to Update Order Flow ... + */ + void UpdateOrderFlow() + { + ResetOrderFlow(); + } + + /** + * Fill Pivot Tick Zone ... + * + * @param pivotIDX: Integer ... + */ + void CalculatePivotTickZone(int pivotIDX) + { + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + bool isInited = false; + + // + datetime from = mOrderFlow[pivotIDX].from; + XOHCL iFromBar; + int iFromBarIndex = iBarShift( + symbol, + period, + from // + ); + isInited = iFromBar.Init( + symbol, + period, + iFromBarIndex // + ); + if (!isInited) + { + return; + } + + // + datetime to = mOrderFlow[pivotIDX].to; + XOHCL iToBar; + int iToBarIndex = iBarShift( + symbol, + period, + to // + ); + isInited = iToBar.Init( + symbol, + period, + iToBarIndex // + ); + if (!isInited) + { + return; + } + + // + XCTicksZone *iZone; + iZone = new XCTicksZone(); + + // + int ticksLevels = mTriggerDetector.TicksRangeZoneLevel(); + int ticksRange = mTriggerDetector.TicksRangeZoneRange(); + isInited = ticksLevels > 0 && + ticksRange > 0; + if (!isInited) + { + return; + } + + // + isInited = iZone.Init( + iFromBar, + iToBar // + ); + if (!isInited) + { + return; + } + + // + mOrderFlow[pivotIDX].state.ticksZone = iZone; + } + + /** + * Validate Order Flow ... + * + * @return ( bool ) + */ + bool HasValidOrderFlow() + { + // + bool result = false; + + // + int orderFlowCount = ArraySize(mOrderFlow); + result = + IsValidSize(orderFlowCount) && + mOrderFlowDir != X_DIRECTION_ALL && + mOrderFlowDir != X_DIRECTION_NONE; + + // + return result; + } + + /** + * Reset Order Flow ... + */ + void ResetOrderFlow() + { + // + Clean(mOrderFlow); + mOrderFlowDir = X_DIRECTION_NONE; + + // + ClearDraws(); + } + + /** + * Detect Breaker Bar ... + * + * @param bar: XOHCL instance ... + * @param breakerBar: XOHCL instance, Breaker Bar ... + * @param pivot: XPVPivot instance ... + * @param forDir: ENUM_X_DIRECTION member, Market Structure Direction ... + * + * @return ( bool ) + */ + bool DetectLastBreakerBar( + XOHCL &bar, + XOHCL &breakerBar, + XPVPivot &pivot, + ENUM_X_DIRECTION forDir // + ) + { + // + bool result = false; + + // + result = + bar.IsValid() && + pivot.IsValid() && + forDir != X_DIRECTION_ALL && + forDir != X_DIRECTION_NONE; + if (!result) + { + return result; + } + + // + // FVG ... + result = DetectLastFVGBreakerBar( + bar, + breakerBar, + pivot, + forDir // + ); + if (result) + { + return result; + } + + // + // Order Block ... + // result = DetectLastOBBreakerBar( + // bar, + // breakerBar, + // pivot, + // forDir // + // ); + // if (result) + // { + // return result; + // } + + // + return result; + } + + bool DetectLastFVGBreakerBar( + XOHCL &bar, + XOHCL &breakerBar, + XPVPivot &pivot, + ENUM_X_DIRECTION forDir // + ) + { + // + bool result = false; + + // + result = + bar.IsValid() && + pivot.IsValid() && + forDir != X_DIRECTION_ALL && + forDir != X_DIRECTION_NONE; + if (!result) + { + return result; + } + + // + bool isBullishDir = IsBullish(forDir); + + // + int fvgsCount = + isBullishDir + ? pivot.state.CountBullishFairValueGaps() + : pivot.state.CountBearishFairValueGaps(); + result = IsValidSize(fvgsCount); + if (!result) + { + return result; + } + + // + int idx = -1; + XCFVG *zone = NULL; + for (int i = 0; i < fvgsCount; i++) + { + // + if (isBullishDir) + { + // + // Bullish FVG ... + if (zone == NULL) + { + // + zone = pivot.state.bullishFairValueGaps[i]; + + // + bool isBreaked = CheckZoneBreak( + forDir, + bar, + breakerBar, + zone // + ); + if (isBreaked) + { + idx = i; + } + } + else + { + // + bool isNewer = ((int)zone.From() - (int)bar.time) > ((int)pivot.state.bullishFairValueGaps[i].From() - (int)bar.time); + if (isNewer) + { + // + zone = pivot.state.bullishFairValueGaps[i]; + + // + bool isBreaked = CheckZoneBreak( + forDir, + bar, + breakerBar, + zone // + ); + if (isBreaked) + { + idx = i; + } + } + } + } + else + { + // + // Bearish FVG ... + if (zone == NULL) + { + // + zone = pivot.state.bearishFairValueGaps[i]; + + // + bool isBreaked = CheckZoneBreak( + forDir, + bar, + breakerBar, + zone // + ); + if (isBreaked) + { + idx = i; + } + } + else + { + // + bool isNewer = ((int)zone.From() - (int)bar.time) > ((int)pivot.state.bearishFairValueGaps[i].From() - (int)bar.time); + if (isNewer) + { + // + zone = pivot.state.bearishFairValueGaps[i]; + + // + bool isBreaked = CheckZoneBreak( + forDir, + bar, + breakerBar, + zone // + ); + if (isBreaked) + { + idx = i; + } + } + } + } + } + + // + result = + breakerBar.IsValid() && + IsValidIndex(idx) && + zone.IsValid(); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Check an FVG is Breaked or not ... + * + * @param forDir: ENUM_X_DIRECTION member, Market Structure Direction ... + * @param bar: XOHCL instance ... + * @param breakerBar: XOHCL instance, Breaker Bar ... + * + * @return ( bool ) + */ + bool CheckZoneBreak( + ENUM_X_DIRECTION forDir, + XOHCL &bar, + XOHCL &breakerBar, + XCFVG *&zone // + ) + { + // + bool result = false; + + // + breakerBar.Clean(); + + // + result = bar.IsValid() && + zone.IsValid() && + forDir != X_DIRECTION_ALL && + forDir != X_DIRECTION_NONE; + if (!result) + { + return result; + } + + // + int start = bar.Index(); + int end = iBarShift( + bar.symbol, + bar.period, + zone.From()); + for (int i = start; i < end; i++) + { + // + XOHCL iBar; + result = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + break; + } + + // + if (IsBullish(forDir)) + { + // + // Bullish Break ... + result = iBar.low < zone.Upper() && + iBar.high > zone.Upper() && + iBar.GetDown() < zone.Upper() && + iBar.GetUp() > zone.Upper() && + iBar.IsBullish(); + } + else + { + // + // Bearish Break ... + result = iBar.low < zone.Lower() && + iBar.high > zone.Lower() && + iBar.GetDown() < zone.Lower() && + iBar.GetUp() > zone.Lower() && + iBar.IsBearish(); + } + + // + if (result) + { + // + breakerBar = iBar; + break; + } + } + + // + result = breakerBar.IsValid(); + + // + return result; + } + + /** + * Detect most Upper and Lower Order Blocks ... + * + * @return ( bool ) + */ + bool DetectOrderBlocks( + XCOrderBlock *bullOBBoundary, + XCOrderBlock *bearOBBoundary, + XCOrderBlock *&bullOB, + XCOrderBlock *&bearOB, + XOHCL &bar, + XPOIState &state // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + state.IsValid(); + if (!result) + { + return result; + } + + // + XCOrderBlock *mBullOB = NULL; + if (bullOB == NULL) + { + // + for (int i = 0; i < state.CountBullishOrderBlocks(); i++) + { + // + XCOrderBlock *ob = state.bullishOrderBlocks[i]; + bool isPricePassed = bar.low > ob.Upper(); + if (isPricePassed) + { + // + bool isBoundaryPassed = + bullOBBoundary == NULL + ? true + : ob.Lower() < bullOBBoundary.Upper(); + if (isBoundaryPassed) + { + // + if (mBullOB == NULL) + { + mBullOB = ob; + } + else + { + // + bool isRefined = + mBullOB.Upper() < ob.Upper(); + if (isRefined) + { + mBullOB = ob; + } + } + } + } + } + + // + if (mBullOB != NULL) + { + bullOB = mBullOB; + } + } + + // + XCOrderBlock *mBearOB = NULL; + if (bearOB == NULL) + { + // + for (int i = 0; i < state.CountBearishOrderBlocks(); i++) + { + // + XCOrderBlock *ob = state.bearishOrderBlocks[i]; + bool isPricePassed = bar.high < ob.Lower(); + if (isPricePassed) + { + // + bool isBoundaryPassed = + bearOBBoundary == NULL + ? true + : ob.Upper() > bearOBBoundary.Lower(); + if (isBoundaryPassed) + { + // + if (mBearOB == NULL) + { + mBearOB = ob; + } + else + { + // + bool isRefined = + mBearOB.Lower() > ob.Lower(); + if (isRefined) + { + mBearOB = ob; + } + } + } + } + } + + // + if (mBearOB != NULL) + { + bearOB = mBearOB; + } + } + + // + result = bullOB != NULL && + bearOB != NULL; + + // + return result; + } + + // + // Drawings ... + + /** + * Draw Order Flow ... + */ + void RedrawOrderFlow( + bool forceClearDraws = true, + bool forceDrawSamePeriod = true, + bool drawOrderFlow = true, + bool drawOrderFlowState = true, + bool drawOnlyLastOrderFlow = false, + bool drawOnlyLastOrderFlowState = true, + // + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + // + // Ignores List ... + bool ignoreSwingHighs = false, + bool ignoreSwingLows = false, + bool ignoreSupportZones = false, + bool ignoreResistanceZones = false, + bool ignoreSupplyZones = false, + bool ignoreDemandZones = false, + bool ignoreBullishOrderBlocks = false, + bool ignoreBearishOrderBlocks = false, + bool ignoreBullishFairValueGaps = false, + bool ignoreBearishFairValueGaps = false, + bool ignoreBullishRejectionBars = false, + bool ignoreBearishRejectionBars = false, + bool ignoreBullishMomentumBars = false, + bool ignoreBearishMomentumBars = false, + // + // States Drawing ... + bool drawVisionState = false, + bool drawConsolidationState = false, + bool drawVerificationState = false, + bool drawAnalyseState = false, + bool drawDecisionState = false, + bool drawTriggerState = false // + ) + { + // + if (forceClearDraws) + { + ClearDraws(); + } + + // + if (!drawOrderFlow || + !HasValidOrderFlow()) + { + return; + } + + // + int orderFlowCount = ArraySize(mOrderFlow); + for (int i = 0; i < orderFlowCount; i++) + { + // + bool isLast = i == orderFlowCount - 1; + bool canDraw = + !drawOnlyLastOrderFlow || + (isLast && + drawOnlyLastOrderFlow); + if (!canDraw) + { + continue; + } + + // + XPVPivot iPivot = mOrderFlow[i]; + + // + XCXPVPivotObject *iObj; + iObj = new XCXPVPivotObject(); + bool isCreated = iObj.Create( + mPOIDrawer.ChartIdentification(), + mPOIDrawer.SubWindowIdentification(), + iPivot // + ); + if (isCreated) + { + // + bool canDrawState = + drawOrderFlowState && + (!drawOnlyLastOrderFlowState || + (isLast && + drawOnlyLastOrderFlowState)); + if (canDrawState) + { + // + CustomStateDrawing( + iPivot.state, + forceDrawSamePeriod, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + if (iPivot.IsPeak()) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotColor(clrAqua); + iObj.PivotStyle(STYLE_SOLID); + } + + // + if (iPivot.IsVale()) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotStyle(STYLE_SOLID); + iObj.PivotColor(clrMagenta); + } + + // + AddObjectIfNotExists(iObj); + } + } + + // + // Draw States ... + + // + // Vision ... + if (drawVisionState) + { + // + CustomStateDrawing( + mVisionState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Consolidation ... + if (drawConsolidationState) + { + // + CustomStateDrawing( + mConsolidationState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Verification ... + if (drawVerificationState) + { + // + CustomStateDrawing( + mVerificationState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Analyse ... + if (drawAnalyseState) + { + // + CustomStateDrawing( + mAnalyseState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Decision ... + if (drawDecisionState) + { + // + CustomStateDrawing( + mDecisionState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Trigger ... + if (drawTriggerState) + { + // + CustomStateDrawing( + mTriggerState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + } + + /** + * Custom Drawing State ... + * + * @param state: XPOIState instance reference, Specified Which state to Draw ... + * @param forceDrawSamePeriod: Boolean ... + */ + void CustomStateDrawing( + XPOIState &state, + bool forceDrawSamePeriod = false, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + // + // Ignores List ... + bool ignoreSwingHighs = false, + bool ignoreSwingLows = false, + bool ignoreSupportZones = false, + bool ignoreResistanceZones = false, + bool ignoreSupplyZones = false, + bool ignoreDemandZones = false, + bool ignoreBullishOrderBlocks = false, + bool ignoreBearishOrderBlocks = false, + bool ignoreBullishFairValueGaps = false, + bool ignoreBearishFairValueGaps = false, + bool ignoreBullishRejectionBars = false, + bool ignoreBearishRejectionBars = false, + bool ignoreBullishMomentumBars = false, + bool ignoreBearishMomentumBars = false // + ) + { + // + XPOIState tmpState = state; + if (forceDrawSamePeriod) + { + // + int count = 0; + ENUM_TIMEFRAMES period = GetPeriod(); + + // + count = state.CountSwingHighs(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing iSwing = state.swingHighs[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.swingHighs, + i, + 1 // + ); + } + } + } + + // + count = state.CountSwingLows(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing iSwing = state.swingLows[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.swingLows, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishMomentumBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar iMomentum = state.bullishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishMomentumBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishMomentumBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar iMomentum = state.bearishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishMomentumBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishRejectionBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar iRejection = state.bullishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishRejectionBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishRejectionBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar iRejection = state.bearishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishRejectionBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountSupportZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZone iZone = state.supportZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.supportZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountResistanceZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZone iZone = state.resistanceZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.resistanceZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountSupplyZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupplyZone iZone = state.supplyZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.supplyZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountDemandZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCDemandZone iZone = state.demandZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.demandZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock iZone = state.bullishOrderBlocks[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishOrderBlocks, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock iZone = state.bearishOrderBlocks[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishOrderBlocks, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishFairValueGaps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG iZone = state.bullishFairValueGaps[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillStartBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishFairValueGaps, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishFairValueGaps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG iZone = state.bearishFairValueGaps[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillStartBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishFairValueGaps, + i, + 1 // + ); + } + } + } + + // + } + + // + bool drawSwingHighs = true; + bool drawSwingLows = true; + bool drawSupportZones = true; + bool drawResistanceZones = true; + bool drawSupplyZones = true; + bool drawDemandZones = true; + bool drawBullishOrderBlocks = true; + bool drawBearishOrderBlocks = true; + bool drawBullishFairValueGaps = true; + bool drawBearishFairValueGaps = true; + bool drawBullishRejectionBars = true; + bool drawBearishRejectionBars = true; + bool drawBullishMomentumBars = true; + bool drawBearishMomentumBars = true; + + // + // Change Drawing Specs Conditions based on + // Provided Direction ... + if (forDir == X_DIRECTION_BULLISH) + { + // + drawSwingLows = true; + drawDemandZones = true; + drawSupportZones = true; + drawBullishOrderBlocks = true; + drawBullishFairValueGaps = true; + drawBullishRejectionBars = true; + drawBullishMomentumBars = true; + + // + drawSwingHighs = false; + drawSupplyZones = false; + drawResistanceZones = false; + drawBearishOrderBlocks = false; + drawBearishFairValueGaps = false; + drawBearishRejectionBars = false; + drawBearishMomentumBars = false; + } + else if (forDir == X_DIRECTION_BEARISH) + { + // + drawSwingLows = false; + drawDemandZones = false; + drawSupportZones = false; + drawBullishOrderBlocks = false; + drawBullishFairValueGaps = false; + drawBullishRejectionBars = false; + drawBullishMomentumBars = false; + + // + drawSwingHighs = true; + drawSupplyZones = true; + drawResistanceZones = true; + drawBearishOrderBlocks = true; + drawBearishFairValueGaps = true; + drawBearishRejectionBars = true; + drawBearishMomentumBars = true; + } + + // + // Apply Ignore List ... + + // + if (ignoreSwingHighs) + { + drawSwingHighs = false; + } + + // + if (ignoreSwingLows) + { + drawSwingLows = false; + } + + // + if (ignoreSupportZones) + { + drawSupportZones = false; + } + + // + if (ignoreResistanceZones) + { + drawResistanceZones = false; + } + + // + if (ignoreSupplyZones) + { + drawSupplyZones = false; + } + + // + if (ignoreDemandZones) + { + drawDemandZones = false; + } + + // + if (ignoreBullishOrderBlocks) + { + drawBullishOrderBlocks = false; + } + + // + if (ignoreBearishOrderBlocks) + { + drawBearishOrderBlocks = false; + } + + // + if (ignoreBullishFairValueGaps) + { + drawBullishFairValueGaps = false; + } + + // + if (ignoreBearishFairValueGaps) + { + drawBearishFairValueGaps = false; + } + + // + if (ignoreBullishRejectionBars) + { + drawBullishRejectionBars = false; + } + + // + if (ignoreBearishRejectionBars) + { + drawBearishRejectionBars = false; + } + + // + if (ignoreBullishMomentumBars) + { + drawBullishMomentumBars = false; + } + + // + if (ignoreBearishMomentumBars) + { + drawBearishMomentumBars = false; + } + + // + DrawState( + tmpState, // State ... + true, // Update To of all Drawings Till now ... + drawSwingHighs, // Draw SwingHighs .. + drawSwingLows, // Draw SwingLows .. + drawSupportZones, // Draw SupportZones .. + drawResistanceZones, // Draw ResistanceZones .. + drawSupplyZones, // Draw SupplyZones .. + drawDemandZones, // Draw DemandZones .. + drawBullishOrderBlocks, // Draw BullishOrderBlocks .. + drawBearishOrderBlocks, // Draw BearishOrderBlocks .. + drawBullishFairValueGaps, // Draw BullishFairValueGaps .. + drawBearishFairValueGaps, // Draw BearishFairValueGaps .. + drawBullishRejectionBars, // Draw BullishRejectionBars .. + drawBearishRejectionBars, // Draw BearishRejectionBars .. + drawBullishMomentumBars, // Draw BullishMomentumBars .. + drawBearishMomentumBars, // Draw BearishMomentumBars .. + true // Draw Ticks Zone ... + ); + } + + // + // Private ... + private: + // + // Props ... + + /** + * Initial Required Indicators Helper ... + */ + void InitialHelpers() + { + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + // Short ... + ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES scPeriod = NULL; // Time Period + + // + // Medium ... + ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES mcPeriod = NULL; // Time Period + + // + // Long ... + ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES lcPeriod = NULL; // Time Period + + // + // Hind ... + ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES hcPeriod = NULL; // Time Period + + // + // XPV ... + XPVInputs xpvInputs; + + // + xpvInputs.Default(); + + // + xpvInputs.scMethod = scMethod; + xpvInputs.scPeriod = scPeriod; + xpvInputs.mcMethod = mcMethod; + xpvInputs.mcPeriod = mcPeriod; + xpvInputs.lcMethod = lcMethod; + xpvInputs.lcPeriod = lcPeriod; + xpvInputs.hcMethod = hcMethod; + xpvInputs.hcPeriod = hcPeriod; + + // + xpvInputs.showPeaksAndVales = true; + xpvInputs.showLevels = false; + xpvInputs.showConsolidations = false; + xpvInputs.showFibo1Levels = false; + xpvInputs.showFibo2Levels = false; + xpvInputs.showFibo3Levels = false; + xpvInputs.showFibo4Levels = false; + xpvInputs.showFibo5Levels = false; + + // + // X3MA ... + X3MAInputs x3maInputs; + + // + x3maInputs.Default(); + + // + // x3maInputs.fastLength = 10; + // x3maInputs.midLength = 25; + // x3maInputs.slowLength = 50; + + // + x3maInputs.showFast = true; + x3maInputs.showMid = false; + x3maInputs.showSlow = false; + + // + // X3VWAP ... + X3VWAPInputs x3vwapInputs; + + // + x3vwapInputs.Default(); + + // + // x3vwapInputs.fastLength = 10; + // x3vwapInputs.midLength = 25; + // x3vwapInputs.slowLength = 50; + + // + x3vwapInputs.showFast = true; + x3vwapInputs.showMid = true; + x3vwapInputs.showSlow = true; + + // + // XCHSAR ... + XCHSARInputs xchsarInputs; + + // + xchsarInputs.Default(); + + // + xchsarInputs.scMethod = scMethod; + xchsarInputs.scPeriod = scPeriod; + xchsarInputs.mcMethod = mcMethod; + xchsarInputs.mcPeriod = mcPeriod; + xchsarInputs.lcMethod = lcMethod; + xchsarInputs.lcPeriod = lcPeriod; + xchsarInputs.hcMethod = hcMethod; + xchsarInputs.hcPeriod = hcPeriod; + + // + xchsarInputs.showCurrent = true; + xchsarInputs.showShort = false; + xchsarInputs.showMedium = false; + xchsarInputs.showLong = false; + xchsarInputs.showHind = false; + + // + // Initialize Cycle Helpers ... + + // + mTriggerCycleHelper = new XC121SMCCycleHelper(); + mTriggerCycleHelper.Init( + symbol, + PERIOD_M1, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mDecisionCycleHelper = new XC121SMCCycleHelper(); + mDecisionCycleHelper.Init( + symbol, + PERIOD_M5, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mAnalyseCycleHelper = new XC121SMCCycleHelper(); + mAnalyseCycleHelper.Init( + symbol, + PERIOD_M15, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mVerificationCycleHelper = new XC121SMCCycleHelper(); + mVerificationCycleHelper.Init( + symbol, + PERIOD_M30, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mConsolidationCycleHelper = new XC121SMCCycleHelper(); + mConsolidationCycleHelper.Init( + symbol, + PERIOD_H1, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mVisionCycleHelper = new XC121SMCCycleHelper(); + mVisionCycleHelper.Init( + symbol, + PERIOD_H4, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/x-121.smc.test.strategy.class copy.mq5 b/BKPS/14030923/Documents/BKP/x-121.smc.test.strategy.class copy.mq5 new file mode 100644 index 0000000..046a000 --- /dev/null +++ b/BKPS/14030923/Documents/BKP/x-121.smc.test.strategy.class copy.mq5 @@ -0,0 +1,3064 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCX121SMCTestStrategy +// Description: provides all based classes for use ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... + +// +#include "../Classes/x-121.smc.base.strategy.class.mq5" +#include "../Classes/x-121.smc.market.cycle.helper.class.mq5" + +// +// Definitions ... + +// +// XStrategy Class Implementation(s) ... +class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy +{ + // + // Public ... + public: + // + + // + // Constructor(s) ... + void XCX121SMCTestStrategy( + // + // Base ... + string _symbol, // Trading Symbol + ENUM_TIMEFRAMES _period // Trading TimeFrame + ) + : XCX121SMCBaseStrategy(_symbol, _period) + { + InitialHelpers(); + } + + // + // Deconstructur ... + void ~XCX121SMCTestStrategy() + { + } + + // + // Overrides Actions ... + + /** + * Destroy All Class Implementations ... + */ + void Destroy() override + { + // + delete mTriggerCycleHelper; + delete mDecisionCycleHelper; + delete mAnalyseCycleHelper; + delete mVerificationCycleHelper; + delete mConsolidationCycleHelper; + delete mVisionCycleHelper; + } + + /** + * Check Conditions For Signal ... + */ + bool HasSignal( + XSignal &signal, + X121SMCStrategyConditions &conditions // + ) override + { + // + bool result = false; + + // + signal.Clean(); + conditions.Clean(); + + // + int pushers = 0; + + // + double sl = 0; + double tp = 0; + double risk = 0; + double entry = 0; + double reward = 0; + double r2r = R2R(); + string provider = ""; + double volume = Volume(); + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY; + ENUM_X_ORDER_MODES mode = X_ORDER_MODE_MARKET; + + // + bool hasLong = false; + bool hasShort = false; + + // + double selectedSL = 0; + + // + // Start Calculations ... + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + double points = GetPoints(symbol); + double pip = GetPipPrice(symbol); + double pip2 = 2 * pip; + + // + // Check Spread ... + bool isSpreadPassed = IsSpreadPass(); + result = isSpreadPassed; + if (!result) + { + // + // string message = "Spread is not Passed for Analysing ..."; + // LogAlert(message); + + // + return result; + } + + // + // Detect Conditions ... + result = DetectConditions(conditions); + if (!result) + { + conditions.Clean(); + return result; + } + + // + // Combine all Signals Conditions ... + selectedSL = conditions.sl; + provider = conditions.provider; + + // + hasLong = + // + IsBullish(conditions.marketStructureDir) + // + ; + + // + hasShort = + // + IsBearish(conditions.marketStructureDir) + // + ; + + // + result = hasLong || + hasShort; + + // + // Rmove Signal Condition ... + if (result) + { + // + // TYPE ... + type = + hasLong + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + ENUM_X_POSITION_TYPES xType = + hasLong + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + entry = GetEntry( + conditions.symbol, + type // + ); + + // + sl = + hasLong + ? selectedSL - pip2 + : selectedSL + pip2; + + // + // RISK Reward ... + risk = + hasLong + ? entry - sl + : sl - entry; + reward = risk * r2r; + tp = + hasLong + ? entry + reward + : entry - reward; + + // + signal.sl = sl; + signal.tp = tp; + signal.type = type; + signal.mode = mode; + signal.entry = entry; + signal.volume = volume; + signal.symbol = symbol; + signal.period = period; + signal.pushers = pushers; + signal.provider = provider; + signal.time = TimeCurrent(); + + // + result = PrepareSignal(signal); + if (result) + { + // + Print("PRV: ", provider); + + // + ENUM_X_DIRECTION forDir = ToDirection(signal.type); + bool ignoreSwingHighs = false; + bool ignoreSwingLows = false; + bool ignoreSupportZones = false; + bool ignoreResistanceZones = false; + bool ignoreSupplyZones = false; + bool ignoreDemandZones = false; + bool ignoreBullishOrderBlocks = false; + bool ignoreBearishOrderBlocks = false; + bool ignoreBullishFairValueGaps = false; + bool ignoreBearishFairValueGaps = false; + bool ignoreBullishRejectionBars = false; + bool ignoreBearishRejectionBars = false; + bool ignoreBullishMomentumBars = false; + bool ignoreBearishMomentumBars = false; + if (IsBullish(forDir)) + { + // + ignoreSwingLows = false; + ignoreDemandZones = false; + ignoreSupportZones = false; + ignoreBullishOrderBlocks = false; + ignoreBullishFairValueGaps = false; + ignoreBullishRejectionBars = false; + ignoreBullishMomentumBars = false; + } + else + { + // + ignoreSwingHighs = true; + ignoreSupplyZones = true; + ignoreResistanceZones = true; + ignoreBearishOrderBlocks = true; + ignoreBearishFairValueGaps = false; + ignoreBearishRejectionBars = true; + ignoreBearishMomentumBars = true; + } + + // + RedrawOrderFlow( + true, // Force Clean ... + false, // Same Period ... + true, // Order Flow ... + true, // Order Flow State ... + false, // Only Last Order Flow ... + true, // Only Last Order Flow State ... + // + forDir, // Direction Force ... + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + DrawSignal(signal); + ClearDraws(); + + // + ResetOrderFlow(); + } + + // + hasLong = false; + hasShort = false; + } + + // + return result; + } + + /** + * Customize Strategy Identifier ... + */ + string GetTag() override + { + return X121SMCStrategyToken; + } + + // + // Protected ... + protected: + // + + // + // Props ... + + // + // Trigger Order Flow ... + XPVPivot mOrderFlow[]; + ENUM_X_DIRECTION mOrderFlowDir; + + // + XC121SMCCycleHelper *mTriggerCycleHelper; + XC121SMCCycleHelper *mDecisionCycleHelper; + XC121SMCCycleHelper *mAnalyseCycleHelper; + XC121SMCCycleHelper *mVerificationCycleHelper; + XC121SMCCycleHelper *mConsolidationCycleHelper; + XC121SMCCycleHelper *mVisionCycleHelper; + + // + // Actions ... + + /** + * Detect and Parse Market Conditions ... + * + * @return ( bool ) + */ + bool DetectConditions( + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + string msg = NULL; + + // + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + + // + conditions.time = cTime; + conditions.symbol = symbol; + conditions.period = period; + + // + int conditionsLoopback = 7; + + // + // Fill Cycles Conditions ... + + // + // Trigger ... + mTriggerCycleHelper.GetConditions( + conditions.triggerConditions, + zIndex, + conditionsLoopback // + ); + conditions.triggerConditions.state = mTriggerState; + + // + // Decision ... + mDecisionCycleHelper.GetConditions( + conditions.decisionConditions, + zIndex, + conditionsLoopback // + ); + conditions.decisionConditions.state = mDecisionState; + + // + // Analyse ... + mAnalyseCycleHelper.GetConditions( + conditions.analyseConditions, + zIndex, + conditionsLoopback // + ); + conditions.analyseConditions.state = mAnalyseState; + + // + // Verification ... + mVerificationCycleHelper.GetConditions( + conditions.verificationConditions, + zIndex, + conditionsLoopback // + ); + conditions.verificationConditions.state = mVerificationState; + + // + // Consolidation ... + mConsolidationCycleHelper.GetConditions( + conditions.consolidationConditions, + zIndex, + conditionsLoopback // + ); + conditions.consolidationConditions.state = mConsolidationState; + + // + // Vision ... + mVisionCycleHelper.GetConditions( + conditions.visionConditions, + zIndex, + conditionsLoopback // + ); + conditions.visionConditions.state = mVisionState; + + // + // Detect an Order Block in Vision ... + if (conditions.visionBullOB == NULL || + conditions.visionBearOB == NULL) + { + // + result = DetectOrderBlocks( + NULL, + NULL, + conditions.visionBullOB, + conditions.visionBearOB, + cBar, + mVisionState // + ); + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + XCBullishOrderBlockObject *iBullOBObj; + conditions.visionBullOB.To(cTime); + result = mPOIDrawer.CreateBullishOrderBlock( + conditions.visionBullOB, + iBullOBObj // + ); + if (result) + { + AddObjectIfNotExists(iBullOBObj); + } + + // + XCBearishOrderBlockObject *iBearOBObj; + conditions.visionBearOB.To(cTime); + result = mPOIDrawer.CreateBearishOrderBlock( + conditions.visionBearOB, + iBearOBObj // + ); + if (result) + { + AddObjectIfNotExists(iBearOBObj); + } + } + + // + // Consolidation Order Blocks ... + if (conditions.consolidationBullOB == NULL || + conditions.consolidationBearOB == NULL) + { + // + result = DetectOrderBlocks( + conditions.visionBullOB, + conditions.visionBearOB, + conditions.consolidationBullOB, + conditions.consolidationBearOB, + cBar, + mConsolidationState // + ); + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + XCBullishOrderBlockObject *iBullOBObj; + conditions.consolidationBullOB.To(cTime); + result = mPOIDrawer.CreateBullishOrderBlock( + conditions.consolidationBullOB, + iBullOBObj // + ); + if (result) + { + AddObjectIfNotExists(iBullOBObj); + } + + // + XCBearishOrderBlockObject *iBearOBObj; + conditions.consolidationBearOB.To(cTime); + result = mPOIDrawer.CreateBearishOrderBlock( + conditions.consolidationBearOB, + iBearOBObj // + ); + if (result) + { + AddObjectIfNotExists(iBearOBObj); + } + } + + // + msg = "OrderBlocks Detected ..."; + Alert(msg); + + // + // Detect Trigger Order Flow ... + if (!HasValidOrderFlow()) + { + // + int samePivots = 40; + int requiredPivots = 10; + + // + bool useVisionState = false; + bool useConsolidationState = false; + bool useVerificationState = false; + bool useAnalyseState = false; + bool useDecisionState = true; + bool useTriggerState = false; + + // + DetectOrderFlow( + cIndex, + samePivots, + requiredPivots, + mTriggerCycleHelper, + mOrderFlow, + mOrderFlowDir, + // + // Filling Pivot State ... + useVisionState, // Use Vision State ... + useConsolidationState, // Use Consolidation State ... + useVerificationState, // Use Verification State ... + useAnalyseState, // Use Analyse State ... + useDecisionState, // Use Decision State ... + useTriggerState // Use Trigger State ... + ); + + // + result = HasValidOrderFlow(); + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + bool ignoreSwingHighs = true; + bool ignoreSwingLows = true; + bool ignoreSupportZones = true; + bool ignoreResistanceZones = true; + bool ignoreSupplyZones = true; + bool ignoreDemandZones = true; + bool ignoreBullishOrderBlocks = true; + bool ignoreBearishOrderBlocks = true; + bool ignoreBullishFairValueGaps = true; + bool ignoreBearishFairValueGaps = true; + bool ignoreBullishRejectionBars = true; + bool ignoreBearishRejectionBars = true; + bool ignoreBullishMomentumBars = true; + bool ignoreBearishMomentumBars = true; + + // + RedrawOrderFlow( + false, // Force Clean ... + false, // Same Period ... + true, // Order Flow ... + true, // Order Flow State ... + false, // Only Last Order Flow ... + true, // Only Last Order Flow State ... + // + mOrderFlowDir, // Direction Force ... + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + msg = "Found OrderFlow : " + (IsBullish(mOrderFlowDir) ? "Bullish" : "Berish"); + Alert(msg); + + // + // Check Market Conditions for + // Specified Structure ... + // ENUM_X_DIRECTION marketStructureDir = X_DIRECTION_NONE; + // result = conditions.HasDirection( + // marketStructureDir, + // cBar // + // ); + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + // msg = "Found Market Strucutre : " + (IsBullish(marketStructureDir) ? "Bullish" : "Berish"); + // Alert(msg); + + // + // conditions.marketStructureDir = marketStructureDir; + + // // + // XPVPivot lastPivot; + // result = GetLastItem( + // lastPivot, + // mOrderFlow // + // ); + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + + // + // Detect Last FVG ... + // XOHCL breakerBar; + // result = DetectLastBreakerBar( + // cBar, + // breakerBar, + // lastPivot, + // marketStructureDir // + // ); + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + // msg = "Found Breaker Bar: " + breakerBar.GetTag(); + // Alert(msg); + + // // + // // Detect Nearest Momentum or Rejection Bar ... + // XOHCL decisionBar; + // result = mDecisionCycleHelper.DetectNearestDecisionBar( + // decisionBar, + // marketStructureDir, + // cBar // + // ); + // if (!result) + // { + // return result; + // } + // msg = "Found Decision Bar: " + decisionBar.GetTag(); + // Alert(msg); + + // // + // // Detect Nearest Sar Change ... + // XOHCL sarChangeBar; + // result = mTriggerCycleHelper.DetectNearestCSARChange( + // sarChangeBar, + // cBar // + // ); + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + // msg = "Found Sar Change Bar: " + sarChangeBar.GetTag(); + // Alert(msg); + + // // + // // Now we Hvae to Check Other Conditions ... + // result = + // // breakerBar.time > sarChangeBar.time && + // // decisionBar.time > breakerBar.time; + // decisionBar.time > sarChangeBar.time; + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + + // // + // // Now we Have Check Direction Related Conditions ... + // if (IsBullish(marketStructureDir)) + // { + // // + // result = + // // bid > decisionBar.high && + // // bid > breakerBar.high && + // bid > sarChangeBar.high && + // bid > conditions.triggerConditions.xchsarConditions.cSars[0]; + // } + // else + // { + // // + // result = + // // bid < decisionBar.low && + // // bid < breakerBar.low && + // bid < sarChangeBar.high && + // bid < conditions.triggerConditions.xchsarConditions.cSars[0]; + // } + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + + // // + // conditions.provider = "X121SMC"; + // if (IsBullish(marketStructureDir)) + // { + // // + // // conditions.sl = decisionBar.low; + // // conditions.sl = breakerBar.low; + // conditions.sl = conditions.triggerConditions.xchsarConditions.cSars[0]; + // } + // else + // { + // // + // // conditions.sl = decisionBar.high; + // // conditions.sl = breakerBar.high; + // conditions.sl = conditions.triggerConditions.xchsarConditions.cSars[0]; + // } + + // + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + return result; + } + + /** + * Detect XPV Based POI(s) ... + * + * @param barIndex: Start Bar Index ... + * @param minRepetition: minimum Repeate of POI for Validation ... + * @param requiredPivots: Number of Min Requirement POI(s) ... + * @param pivotHelper: XC121SMCCycleHelper instance Pointer ... + * @param orderFlow: XPVPivot instance Array Reference ... + * @param orderFlowDirection: ENUM_X_DIRECTION member Reference which represents OrderFlow Direction ... + * @param maxAllowedLoopbackBars: Integer, Max Allowed Loopback Bars ... + * + * @return ( bool ) + */ + bool DetectOrderFlow( + int barIndex, + int minRepetition, + int requiredPivots, + XC121SMCCycleHelper *pivotHelper, // XPV Helper ... + XPVPivot &orderFlow[], // OrderFlows ... + ENUM_X_DIRECTION &orderFlowDirection, // Order Flow Direction ... + // + bool useVisionState = true, // Use Vision State ... + bool useConsolidationState = true, // Use Consolidation State ... + bool useVerificationState = true, // Use Verification State ... + bool useAnalyseState = true, // Use Analyse State ... + bool useDecisionState = true, // Use Decision State ... + bool useTriggerState = true, // Use Trigger State ... + // + int maxAllowedLoopbackBars = 576 // + ) + { + // + bool result = false; + + // + orderFlowDirection = X_DIRECTION_NONE; + + // + if (maxAllowedLoopbackBars <= 0) + { + maxAllowedLoopbackBars = 1000; + } + + // + int start = barIndex; + int end = start + maxAllowedLoopbackBars; + + // + Clean(orderFlow); + + // + result = minRepetition > 0 && + requiredPivots > 0 && + pivotHelper != NULL; + if (!result) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + double peak = 0; + XPVPivot peaks[]; + int peakRepeate = 0; + int peakToBarIndex = 0; + int peakFromBarIndex = 0; + + // + double vale = 0; + XPVPivot vales[]; + int valeRepeate = 0; + int valeToBarIndex = 0; + int valeFromBarIndex = 0; + + // + bool canLookupPeak = true; + bool canLookupVale = true; + bool canLookup = true; + while (canLookup) + { + // + // Check Peak ... + double iPeak = pivotHelper.mXPVHelper.GetPeak(barIndex); + if (iPeak != peak) + { + // + if (peak != 0 && + peakRepeate >= minRepetition) + { + // + bool isExists = false; + int count = ArraySize(peaks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = peaks[i]; + + // + if (iPivot.upper == iPeak) + { + // + isExists = true; + break; + } + } + } + if (!isExists) + { + // + XPVPivot iPivot; + + // + iPivot.lower = 0; + iPivot.upper = peak; + iPivot.symbol = symbol; + iPivot.period = period; + iPivot.type = XPV_PEAK; + iPivot.repetition = peakRepeate; + iPivot.to = iTime( + symbol, + period, + peakToBarIndex // + ); + iPivot.from = iTime( + symbol, + period, + peakFromBarIndex // + ); + + // + iPivot.lower = iPivot.CalculateLower(); + + // + bool isValid = iPivot.IsValid(); + if (isValid) + { + // + AddRef( + iPivot, + peaks // + ); + } + } + } + + // + peak = iPeak; + peakRepeate = 0; + peakFromBarIndex = 0; + peakToBarIndex = barIndex; + } + else if (iPeak == peak) + { + // + peakRepeate++; + peakFromBarIndex = barIndex; + } + + // + // Check Vale ... + double iVale = pivotHelper.mXPVHelper.GetVale(barIndex); + if (iVale != vale) + { + // + if (vale != 0 && + valeRepeate >= minRepetition) + { + // + bool isExists = false; + int count = ArraySize(vales); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = vales[i]; + + // + if (iPivot.lower == iVale) + { + // + isExists = true; + break; + } + } + } + if (!isExists) + { + // + XPVPivot iPivot; + + // + iPivot.upper = 0; + iPivot.lower = vale; + iPivot.symbol = symbol; + iPivot.period = period; + iPivot.type = XPV_VALE; + iPivot.repetition = valeRepeate; + iPivot.to = iTime( + symbol, + period, + valeToBarIndex // + ); + iPivot.from = iTime( + symbol, + period, + valeFromBarIndex // + ); + + // + iPivot.upper = iPivot.CalculateUpper(); + + // + bool isValid = iPivot.IsValid(); + if (isValid) + { + // + AddRef( + iPivot, + vales // + ); + } + } + } + + // + vale = iVale; + valeRepeate = 0; + valeFromBarIndex = 0; + valeToBarIndex = barIndex; + } + else if (iVale == vale) + { + // + valeRepeate++; + valeFromBarIndex = barIndex; + } + + // + canLookupPeak = ArraySize(peaks) < requiredPivots; + canLookupVale = ArraySize(vales) < requiredPivots; + canLookup = barIndex < end && + (canLookupPeak || + canLookupVale); + if (canLookup) + { + barIndex++; + } + } + + // + result = IsValidSize(ArraySize(peaks)) || + IsValidSize(ArraySize(vales)); + if (!result) + { + return result; + } + + // + // Detect Order Flow ... + Copy( + peaks, + orderFlow, + false // + ); + Copy( + vales, + orderFlow, + false // + ); + int count = ArraySize(orderFlow); + result = IsValidSize(orderFlow); + if (!result) + { + return result; + } + + // + // Sort Pivots ... + SortPivots(orderFlow); + + // + // Filter Broken Order Flows ... + FilterBrokenPivots(orderFlow); + + // + // Detect Order Flow Direction ... + result = DetectPivotDirection( + orderFlow, + orderFlowDirection // + ); + if (!result) + { + return result; + } + + // + // Find State Inside Pivots and Attached Them to Pivot ... + int orderFlowCount = ArraySize(mOrderFlow); + if (IsValidSize(orderFlowCount)) + { + // + // Loop Through Order Flow ... + for (int i = 0; i < orderFlowCount; i++) + { + // + FillPivotSate( + i, + useVisionState, // Use Vision State ... + useConsolidationState, // Use Consolidation State ... + useVerificationState, // Use Verification State ... + useAnalyseState, // Use Analyse State ... + useDecisionState, // Use Decision State ... + useTriggerState // Use Trigger State ... + ); + } + } + + // + return result; + } + + /** + * Filling Specified Orer Flow Index ... + * + * @param pivotIDX: Integer ... + * @param lookupSwingHighs: Boolean ... + * @param lookupSwingLows: Boolean ... + * @param lookupSupportZones: Boolean ... + * @param lookupResistanceZones: Boolean ... + * @param lookupSupplyZones: Boolean ... + * @param lookupDemandZones: Boolean ... + * @param lookupBullishOrderBlocks: Boolean ... + * @param lookupBearishOrderBlocks: Boolean ... + * @param lookupBullishFairValueGaps: Boolean ... + * @param lookupBearishFairValueGaps: Boolean ... + * @param lookupBullishRejectionBars: Boolean ... + * @param lookupBearishRejectionBars: Boolean ... + * @param lookupBullishMomentumBars: Boolean ... + * @param lookupBearishMomentumBars: Boolean ... + */ + void FillPivotSate( + int pivotIDX, // + bool useVisionState = true, // Use Vision State ... + bool useConsolidationState = true, // Use Consolidation State ... + bool useVerificationState = true, // Use Verification State ... + bool useAnalyseState = true, // Use Analyse State ... + bool useDecisionState = true, // Use Decision State ... + bool useTriggerState = true, // Use Trigger State ... + bool lookupSwingHighs = true, + bool lookupSwingLows = true, + bool lookupSupportZones = true, + bool lookupResistanceZones = true, + bool lookupSupplyZones = true, + bool lookupDemandZones = true, + bool lookupBullishOrderBlocks = true, + bool lookupBearishOrderBlocks = true, + bool lookupBullishFairValueGaps = true, + bool lookupBearishFairValueGaps = true, + bool lookupBullishRejectionBars = true, + bool lookupBearishRejectionBars = true, + bool lookupBullishMomentumBars = true, + bool lookupBearishMomentumBars = true // + ) + { + // + CalculatePivotTickZone(pivotIDX); + + // + // Trigger ... + XPOIState mPivotTriggerState; + if (useTriggerState && + mTriggerState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mTriggerState, + mPivotTriggerState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotTriggerState.HasChild()) + { + mPivotTriggerState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Decision ... + XPOIState mPivotDecisionState; + if (useDecisionState && + mDecisionState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mDecisionState, + mPivotDecisionState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotDecisionState.HasChild()) + { + mPivotDecisionState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Analyse ... + XPOIState mPivotAnalyseState; + if (useAnalyseState && + mAnalyseState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mAnalyseState, + mPivotAnalyseState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotAnalyseState.HasChild()) + { + mPivotAnalyseState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Verification ... + XPOIState mPivotVerificationState; + if (useVerificationState && + mVerificationState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mVerificationState, + mPivotVerificationState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotVerificationState.HasChild()) + { + mPivotVerificationState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Consolidation ... + XPOIState mPivotConsolidationState; + if (useConsolidationState && + mConsolidationState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mConsolidationState, + mPivotConsolidationState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotConsolidationState.HasChild()) + { + mPivotConsolidationState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Vision ... + XPOIState mPivotVisionState; + if (useVisionState && + mVisionState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mVisionState, + mPivotVisionState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotVisionState.HasChild()) + { + mPivotVisionState.Fill(mOrderFlow[pivotIDX].state); + } + } + } + + /** + * When a BOS Happens ... + * we have to Update Order Flow ... + */ + void UpdateOrderFlow() + { + ResetOrderFlow(); + } + + /** + * Fill Pivot Tick Zone ... + * + * @param pivotIDX: Integer ... + */ + void CalculatePivotTickZone(int pivotIDX) + { + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + bool isInited = false; + + // + datetime from = mOrderFlow[pivotIDX].from; + XOHCL iFromBar; + int iFromBarIndex = iBarShift( + symbol, + period, + from // + ); + isInited = iFromBar.Init( + symbol, + period, + iFromBarIndex // + ); + if (!isInited) + { + return; + } + + // + datetime to = mOrderFlow[pivotIDX].to; + XOHCL iToBar; + int iToBarIndex = iBarShift( + symbol, + period, + to // + ); + isInited = iToBar.Init( + symbol, + period, + iToBarIndex // + ); + if (!isInited) + { + return; + } + + // + XCTicksZone *iZone; + iZone = new XCTicksZone(); + + // + int ticksLevels = mTriggerDetector.TicksRangeZoneLevel(); + int ticksRange = mTriggerDetector.TicksRangeZoneRange(); + isInited = ticksLevels > 0 && + ticksRange > 0; + if (!isInited) + { + return; + } + + // + isInited = iZone.Init( + iFromBar, + iToBar // + ); + if (!isInited) + { + return; + } + + // + mOrderFlow[pivotIDX].state.ticksZone = iZone; + } + + /** + * Validate Order Flow ... + * + * @return ( bool ) + */ + bool HasValidOrderFlow() + { + // + bool result = false; + + // + int orderFlowCount = ArraySize(mOrderFlow); + result = + IsValidSize(orderFlowCount) && + mOrderFlowDir != X_DIRECTION_ALL && + mOrderFlowDir != X_DIRECTION_NONE; + + // + return result; + } + + /** + * Reset Order Flow ... + */ + void ResetOrderFlow() + { + // + Clean(mOrderFlow); + mOrderFlowDir = X_DIRECTION_NONE; + + // + ClearDraws(); + } + + /** + * Detect Breaker Bar ... + * + * @param bar: XOHCL instance ... + * @param breakerBar: XOHCL instance, Breaker Bar ... + * @param pivot: XPVPivot instance ... + * @param forDir: ENUM_X_DIRECTION member, Market Structure Direction ... + * + * @return ( bool ) + */ + bool DetectLastBreakerBar( + XOHCL &bar, + XOHCL &breakerBar, + XPVPivot &pivot, + ENUM_X_DIRECTION forDir // + ) + { + // + bool result = false; + + // + result = + bar.IsValid() && + pivot.IsValid() && + forDir != X_DIRECTION_ALL && + forDir != X_DIRECTION_NONE; + if (!result) + { + return result; + } + + // + // FVG ... + result = DetectLastFVGBreakerBar( + bar, + breakerBar, + pivot, + forDir // + ); + if (result) + { + return result; + } + + // + // Order Block ... + // result = DetectLastOBBreakerBar( + // bar, + // breakerBar, + // pivot, + // forDir // + // ); + // if (result) + // { + // return result; + // } + + // + return result; + } + + bool DetectLastFVGBreakerBar( + XOHCL &bar, + XOHCL &breakerBar, + XPVPivot &pivot, + ENUM_X_DIRECTION forDir // + ) + { + // + bool result = false; + + // + result = + bar.IsValid() && + pivot.IsValid() && + forDir != X_DIRECTION_ALL && + forDir != X_DIRECTION_NONE; + if (!result) + { + return result; + } + + // + bool isBullishDir = IsBullish(forDir); + + // + int fvgsCount = + isBullishDir + ? pivot.state.CountBullishFairValueGaps() + : pivot.state.CountBearishFairValueGaps(); + result = IsValidSize(fvgsCount); + if (!result) + { + return result; + } + + // + int idx = -1; + XCFVG *zone = NULL; + for (int i = 0; i < fvgsCount; i++) + { + // + if (isBullishDir) + { + // + // Bullish FVG ... + if (zone == NULL) + { + // + zone = pivot.state.bullishFairValueGaps[i]; + + // + bool isBreaked = CheckZoneBreak( + forDir, + bar, + breakerBar, + zone // + ); + if (isBreaked) + { + idx = i; + } + } + else + { + // + bool isNewer = ((int)zone.From() - (int)bar.time) > ((int)pivot.state.bullishFairValueGaps[i].From() - (int)bar.time); + if (isNewer) + { + // + zone = pivot.state.bullishFairValueGaps[i]; + + // + bool isBreaked = CheckZoneBreak( + forDir, + bar, + breakerBar, + zone // + ); + if (isBreaked) + { + idx = i; + } + } + } + } + else + { + // + // Bearish FVG ... + if (zone == NULL) + { + // + zone = pivot.state.bearishFairValueGaps[i]; + + // + bool isBreaked = CheckZoneBreak( + forDir, + bar, + breakerBar, + zone // + ); + if (isBreaked) + { + idx = i; + } + } + else + { + // + bool isNewer = ((int)zone.From() - (int)bar.time) > ((int)pivot.state.bearishFairValueGaps[i].From() - (int)bar.time); + if (isNewer) + { + // + zone = pivot.state.bearishFairValueGaps[i]; + + // + bool isBreaked = CheckZoneBreak( + forDir, + bar, + breakerBar, + zone // + ); + if (isBreaked) + { + idx = i; + } + } + } + } + } + + // + result = + breakerBar.IsValid() && + IsValidIndex(idx) && + zone.IsValid(); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Check an FVG is Breaked or not ... + * + * @param forDir: ENUM_X_DIRECTION member, Market Structure Direction ... + * @param bar: XOHCL instance ... + * @param breakerBar: XOHCL instance, Breaker Bar ... + * + * @return ( bool ) + */ + bool CheckZoneBreak( + ENUM_X_DIRECTION forDir, + XOHCL &bar, + XOHCL &breakerBar, + XCFVG *&zone // + ) + { + // + bool result = false; + + // + breakerBar.Clean(); + + // + result = bar.IsValid() && + zone.IsValid() && + forDir != X_DIRECTION_ALL && + forDir != X_DIRECTION_NONE; + if (!result) + { + return result; + } + + // + int start = bar.Index(); + int end = iBarShift( + bar.symbol, + bar.period, + zone.From()); + for (int i = start; i < end; i++) + { + // + XOHCL iBar; + result = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + break; + } + + // + if (IsBullish(forDir)) + { + // + // Bullish Break ... + result = iBar.low < zone.Upper() && + iBar.high > zone.Upper() && + iBar.GetDown() < zone.Upper() && + iBar.GetUp() > zone.Upper() && + iBar.IsBullish(); + } + else + { + // + // Bearish Break ... + result = iBar.low < zone.Lower() && + iBar.high > zone.Lower() && + iBar.GetDown() < zone.Lower() && + iBar.GetUp() > zone.Lower() && + iBar.IsBearish(); + } + + // + if (result) + { + // + breakerBar = iBar; + break; + } + } + + // + result = breakerBar.IsValid(); + + // + return result; + } + + /** + * Detect most Upper and Lower Order Blocks ... + * + * @return ( bool ) + */ + bool DetectOrderBlocks( + XCOrderBlock *bullOBBoundary, + XCOrderBlock *bearOBBoundary, + XCOrderBlock *&bullOB, + XCOrderBlock *&bearOB, + XOHCL &bar, + XPOIState &state // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + state.IsValid(); + if (!result) + { + return result; + } + + // + XCOrderBlock *mBullOB = NULL; + if (bullOB == NULL) + { + // + for (int i = 0; i < state.CountBullishOrderBlocks(); i++) + { + // + XCOrderBlock *ob = state.bullishOrderBlocks[i]; + bool isPricePassed = bar.low > ob.Upper(); + if (isPricePassed) + { + // + bool isBoundaryPassed = + bullOBBoundary == NULL + ? true + : ob.Lower() < bullOBBoundary.Upper(); + if (isBoundaryPassed) + { + // + if (mBullOB == NULL) + { + mBullOB = ob; + } + else + { + // + bool isRefined = + mBullOB.Upper() < ob.Upper(); + if (isRefined) + { + mBullOB = ob; + } + } + } + } + } + + // + if (mBullOB != NULL) + { + bullOB = mBullOB; + } + } + + // + XCOrderBlock *mBearOB = NULL; + if (bearOB == NULL) + { + // + for (int i = 0; i < state.CountBearishOrderBlocks(); i++) + { + // + XCOrderBlock *ob = state.bearishOrderBlocks[i]; + bool isPricePassed = bar.high < ob.Lower(); + if (isPricePassed) + { + // + bool isBoundaryPassed = + bearOBBoundary == NULL + ? true + : ob.Upper() > bearOBBoundary.Lower(); + if (isBoundaryPassed) + { + // + if (mBearOB == NULL) + { + mBearOB = ob; + } + else + { + // + bool isRefined = + mBearOB.Lower() > ob.Lower(); + if (isRefined) + { + mBearOB = ob; + } + } + } + } + } + + // + if (mBearOB != NULL) + { + bearOB = mBearOB; + } + } + + // + result = bullOB != NULL && + bearOB != NULL; + + // + return result; + } + + // + // Drawings ... + + /** + * Draw Order Flow ... + */ + void RedrawOrderFlow( + bool forceClearDraws = true, + bool forceDrawSamePeriod = true, + bool drawOrderFlow = true, + bool drawOrderFlowState = true, + bool drawOnlyLastOrderFlow = false, + bool drawOnlyLastOrderFlowState = true, + // + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + // + // Ignores List ... + bool ignoreSwingHighs = false, + bool ignoreSwingLows = false, + bool ignoreSupportZones = false, + bool ignoreResistanceZones = false, + bool ignoreSupplyZones = false, + bool ignoreDemandZones = false, + bool ignoreBullishOrderBlocks = false, + bool ignoreBearishOrderBlocks = false, + bool ignoreBullishFairValueGaps = false, + bool ignoreBearishFairValueGaps = false, + bool ignoreBullishRejectionBars = false, + bool ignoreBearishRejectionBars = false, + bool ignoreBullishMomentumBars = false, + bool ignoreBearishMomentumBars = false, + // + // States Drawing ... + bool drawVisionState = false, + bool drawConsolidationState = false, + bool drawVerificationState = false, + bool drawAnalyseState = false, + bool drawDecisionState = false, + bool drawTriggerState = false // + ) + { + // + if (forceClearDraws) + { + ClearDraws(); + } + + // + if (!drawOrderFlow || + !HasValidOrderFlow()) + { + return; + } + + // + int orderFlowCount = ArraySize(mOrderFlow); + for (int i = 0; i < orderFlowCount; i++) + { + // + bool isLast = i == orderFlowCount - 1; + bool canDraw = + !drawOnlyLastOrderFlow || + (isLast && + drawOnlyLastOrderFlow); + if (!canDraw) + { + continue; + } + + // + XPVPivot iPivot = mOrderFlow[i]; + + // + XCXPVPivotObject *iObj; + iObj = new XCXPVPivotObject(); + bool isCreated = iObj.Create( + mPOIDrawer.ChartIdentification(), + mPOIDrawer.SubWindowIdentification(), + iPivot // + ); + if (isCreated) + { + // + bool canDrawState = + drawOrderFlowState && + (!drawOnlyLastOrderFlowState || + (isLast && + drawOnlyLastOrderFlowState)); + if (canDrawState) + { + // + CustomStateDrawing( + iPivot.state, + forceDrawSamePeriod, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + if (iPivot.IsPeak()) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotColor(clrAqua); + iObj.PivotStyle(STYLE_SOLID); + } + + // + if (iPivot.IsVale()) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotStyle(STYLE_SOLID); + iObj.PivotColor(clrMagenta); + } + + // + AddObjectIfNotExists(iObj); + } + } + + // + // Draw States ... + + // + // Vision ... + if (drawVisionState) + { + // + CustomStateDrawing( + mVisionState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Consolidation ... + if (drawConsolidationState) + { + // + CustomStateDrawing( + mConsolidationState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Verification ... + if (drawVerificationState) + { + // + CustomStateDrawing( + mVerificationState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Analyse ... + if (drawAnalyseState) + { + // + CustomStateDrawing( + mAnalyseState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Decision ... + if (drawDecisionState) + { + // + CustomStateDrawing( + mDecisionState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Trigger ... + if (drawTriggerState) + { + // + CustomStateDrawing( + mTriggerState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + } + + /** + * Custom Drawing State ... + * + * @param state: XPOIState instance reference, Specified Which state to Draw ... + * @param forceDrawSamePeriod: Boolean ... + */ + void CustomStateDrawing( + XPOIState &state, + bool forceDrawSamePeriod = false, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + // + // Ignores List ... + bool ignoreSwingHighs = false, + bool ignoreSwingLows = false, + bool ignoreSupportZones = false, + bool ignoreResistanceZones = false, + bool ignoreSupplyZones = false, + bool ignoreDemandZones = false, + bool ignoreBullishOrderBlocks = false, + bool ignoreBearishOrderBlocks = false, + bool ignoreBullishFairValueGaps = false, + bool ignoreBearishFairValueGaps = false, + bool ignoreBullishRejectionBars = false, + bool ignoreBearishRejectionBars = false, + bool ignoreBullishMomentumBars = false, + bool ignoreBearishMomentumBars = false // + ) + { + // + XPOIState tmpState = state; + if (forceDrawSamePeriod) + { + // + int count = 0; + ENUM_TIMEFRAMES period = GetPeriod(); + + // + count = state.CountSwingHighs(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing iSwing = state.swingHighs[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.swingHighs, + i, + 1 // + ); + } + } + } + + // + count = state.CountSwingLows(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing iSwing = state.swingLows[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.swingLows, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishMomentumBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar iMomentum = state.bullishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishMomentumBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishMomentumBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar iMomentum = state.bearishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishMomentumBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishRejectionBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar iRejection = state.bullishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishRejectionBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishRejectionBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar iRejection = state.bearishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishRejectionBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountSupportZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZone iZone = state.supportZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.supportZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountResistanceZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZone iZone = state.resistanceZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.resistanceZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountSupplyZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupplyZone iZone = state.supplyZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.supplyZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountDemandZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCDemandZone iZone = state.demandZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.demandZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock iZone = state.bullishOrderBlocks[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishOrderBlocks, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock iZone = state.bearishOrderBlocks[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishOrderBlocks, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishFairValueGaps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG iZone = state.bullishFairValueGaps[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillStartBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishFairValueGaps, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishFairValueGaps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG iZone = state.bearishFairValueGaps[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillStartBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishFairValueGaps, + i, + 1 // + ); + } + } + } + + // + } + + // + bool drawSwingHighs = true; + bool drawSwingLows = true; + bool drawSupportZones = true; + bool drawResistanceZones = true; + bool drawSupplyZones = true; + bool drawDemandZones = true; + bool drawBullishOrderBlocks = true; + bool drawBearishOrderBlocks = true; + bool drawBullishFairValueGaps = true; + bool drawBearishFairValueGaps = true; + bool drawBullishRejectionBars = true; + bool drawBearishRejectionBars = true; + bool drawBullishMomentumBars = true; + bool drawBearishMomentumBars = true; + + // + // Change Drawing Specs Conditions based on + // Provided Direction ... + if (forDir == X_DIRECTION_BULLISH) + { + // + drawSwingLows = true; + drawDemandZones = true; + drawSupportZones = true; + drawBullishOrderBlocks = true; + drawBullishFairValueGaps = true; + drawBullishRejectionBars = true; + drawBullishMomentumBars = true; + + // + drawSwingHighs = false; + drawSupplyZones = false; + drawResistanceZones = false; + drawBearishOrderBlocks = false; + drawBearishFairValueGaps = false; + drawBearishRejectionBars = false; + drawBearishMomentumBars = false; + } + else if (forDir == X_DIRECTION_BEARISH) + { + // + drawSwingLows = false; + drawDemandZones = false; + drawSupportZones = false; + drawBullishOrderBlocks = false; + drawBullishFairValueGaps = false; + drawBullishRejectionBars = false; + drawBullishMomentumBars = false; + + // + drawSwingHighs = true; + drawSupplyZones = true; + drawResistanceZones = true; + drawBearishOrderBlocks = true; + drawBearishFairValueGaps = true; + drawBearishRejectionBars = true; + drawBearishMomentumBars = true; + } + + // + // Apply Ignore List ... + + // + if (ignoreSwingHighs) + { + drawSwingHighs = false; + } + + // + if (ignoreSwingLows) + { + drawSwingLows = false; + } + + // + if (ignoreSupportZones) + { + drawSupportZones = false; + } + + // + if (ignoreResistanceZones) + { + drawResistanceZones = false; + } + + // + if (ignoreSupplyZones) + { + drawSupplyZones = false; + } + + // + if (ignoreDemandZones) + { + drawDemandZones = false; + } + + // + if (ignoreBullishOrderBlocks) + { + drawBullishOrderBlocks = false; + } + + // + if (ignoreBearishOrderBlocks) + { + drawBearishOrderBlocks = false; + } + + // + if (ignoreBullishFairValueGaps) + { + drawBullishFairValueGaps = false; + } + + // + if (ignoreBearishFairValueGaps) + { + drawBearishFairValueGaps = false; + } + + // + if (ignoreBullishRejectionBars) + { + drawBullishRejectionBars = false; + } + + // + if (ignoreBearishRejectionBars) + { + drawBearishRejectionBars = false; + } + + // + if (ignoreBullishMomentumBars) + { + drawBullishMomentumBars = false; + } + + // + if (ignoreBearishMomentumBars) + { + drawBearishMomentumBars = false; + } + + // + DrawState( + tmpState, // State ... + true, // Update To of all Drawings Till now ... + drawSwingHighs, // Draw SwingHighs .. + drawSwingLows, // Draw SwingLows .. + drawSupportZones, // Draw SupportZones .. + drawResistanceZones, // Draw ResistanceZones .. + drawSupplyZones, // Draw SupplyZones .. + drawDemandZones, // Draw DemandZones .. + drawBullishOrderBlocks, // Draw BullishOrderBlocks .. + drawBearishOrderBlocks, // Draw BearishOrderBlocks .. + drawBullishFairValueGaps, // Draw BullishFairValueGaps .. + drawBearishFairValueGaps, // Draw BearishFairValueGaps .. + drawBullishRejectionBars, // Draw BullishRejectionBars .. + drawBearishRejectionBars, // Draw BearishRejectionBars .. + drawBullishMomentumBars, // Draw BullishMomentumBars .. + drawBearishMomentumBars, // Draw BearishMomentumBars .. + true // Draw Ticks Zone ... + ); + } + + // + // Private ... + private: + // + // Props ... + + /** + * Initial Required Indicators Helper ... + */ + void InitialHelpers() + { + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + // Short ... + ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES scPeriod = NULL; // Time Period + + // + // Medium ... + ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES mcPeriod = NULL; // Time Period + + // + // Long ... + ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES lcPeriod = NULL; // Time Period + + // + // Hind ... + ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES hcPeriod = NULL; // Time Period + + // + // XPV ... + XPVInputs xpvInputs; + + // + xpvInputs.Default(); + + // + xpvInputs.scMethod = scMethod; + xpvInputs.scPeriod = scPeriod; + xpvInputs.mcMethod = mcMethod; + xpvInputs.mcPeriod = mcPeriod; + xpvInputs.lcMethod = lcMethod; + xpvInputs.lcPeriod = lcPeriod; + xpvInputs.hcMethod = hcMethod; + xpvInputs.hcPeriod = hcPeriod; + + // + xpvInputs.showPeaksAndVales = true; + xpvInputs.showLevels = false; + xpvInputs.showConsolidations = false; + xpvInputs.showFibo1Levels = false; + xpvInputs.showFibo2Levels = false; + xpvInputs.showFibo3Levels = false; + xpvInputs.showFibo4Levels = false; + xpvInputs.showFibo5Levels = false; + + // + // X3MA ... + X3MAInputs x3maInputs; + + // + x3maInputs.Default(); + + // + // x3maInputs.fastLength = 10; + // x3maInputs.midLength = 25; + // x3maInputs.slowLength = 50; + + // + x3maInputs.showFast = true; + x3maInputs.showMid = false; + x3maInputs.showSlow = false; + + // + // X3VWAP ... + X3VWAPInputs x3vwapInputs; + + // + x3vwapInputs.Default(); + + // + // x3vwapInputs.fastLength = 10; + // x3vwapInputs.midLength = 25; + // x3vwapInputs.slowLength = 50; + + // + x3vwapInputs.showFast = true; + x3vwapInputs.showMid = true; + x3vwapInputs.showSlow = true; + + // + // XCHSAR ... + XCHSARInputs xchsarInputs; + + // + xchsarInputs.Default(); + + // + xchsarInputs.scMethod = scMethod; + xchsarInputs.scPeriod = scPeriod; + xchsarInputs.mcMethod = mcMethod; + xchsarInputs.mcPeriod = mcPeriod; + xchsarInputs.lcMethod = lcMethod; + xchsarInputs.lcPeriod = lcPeriod; + xchsarInputs.hcMethod = hcMethod; + xchsarInputs.hcPeriod = hcPeriod; + + // + xchsarInputs.showCurrent = true; + xchsarInputs.showShort = false; + xchsarInputs.showMedium = false; + xchsarInputs.showLong = false; + xchsarInputs.showHind = false; + + // + // Initialize Cycle Helpers ... + + // + mTriggerCycleHelper = new XC121SMCCycleHelper(); + mTriggerCycleHelper.Init( + symbol, + PERIOD_M1, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mDecisionCycleHelper = new XC121SMCCycleHelper(); + mDecisionCycleHelper.Init( + symbol, + PERIOD_M5, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mAnalyseCycleHelper = new XC121SMCCycleHelper(); + mAnalyseCycleHelper.Init( + symbol, + PERIOD_M15, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mVerificationCycleHelper = new XC121SMCCycleHelper(); + mVerificationCycleHelper.Init( + symbol, + PERIOD_M30, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mConsolidationCycleHelper = new XC121SMCCycleHelper(); + mConsolidationCycleHelper.Init( + symbol, + PERIOD_H1, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mVisionCycleHelper = new XC121SMCCycleHelper(); + mVisionCycleHelper.Init( + symbol, + PERIOD_H4, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/x-121.smc.test.strategy.class.mq5 b/BKPS/14030923/Documents/BKP/x-121.smc.test.strategy.class.mq5 new file mode 100644 index 0000000..7402356 --- /dev/null +++ b/BKPS/14030923/Documents/BKP/x-121.smc.test.strategy.class.mq5 @@ -0,0 +1,2807 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCX121SMCTestStrategy +// Description: provides all based classes for use ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... + +// +#include "../Classes/x-121.smc.base.strategy.class.mq5" +#include "../Classes/x-121.smc.market.cycle.helper.class.mq5" + +// +// Definitions ... + +// +// XStrategy Class Implementation(s) ... +class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy +{ + // + // Public ... + public: + // + + // + // Constructor(s) ... + void XCX121SMCTestStrategy( + // + // Base ... + string _symbol, // Trading Symbol + ENUM_TIMEFRAMES _period // Trading TimeFrame + ) + : XCX121SMCBaseStrategy(_symbol, _period) + { + InitialHelpers(); + } + + // + // Deconstructur ... + void ~XCX121SMCTestStrategy() + { + } + + // + // Overrides Actions ... + + /** + * Destroy All Class Implementations ... + */ + void Destroy() override + { + // + delete mTriggerCycleHelper; + delete mDecisionCycleHelper; + delete mAnalyseCycleHelper; + delete mVerificationCycleHelper; + delete mConsolidationCycleHelper; + delete mVisionCycleHelper; + } + + /** + * Check Conditions For Signal ... + */ + bool HasSignal( + XSignal &signal, + X121SMCStrategyConditions &conditions // + ) override + { + // + bool result = false; + + // + signal.Clean(); + conditions.Clean(); + + // + int pushers = 0; + + // + double sl = 0; + double tp = 0; + double risk = 0; + double entry = 0; + double reward = 0; + double r2r = R2R(); + string provider = ""; + double volume = Volume(); + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY; + ENUM_X_ORDER_MODES mode = X_ORDER_MODE_MARKET; + + // + bool hasLong = false; + bool hasShort = false; + + // + double selectedSL = 0; + + // + // Start Calculations ... + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + double points = GetPoints(symbol); + double pip = GetPipPrice(symbol); + double pip2 = 2 * pip; + + // + // Check Spread ... + bool isSpreadPassed = IsSpreadPass(); + result = isSpreadPassed; + if (!result) + { + // + // string message = "Spread is not Passed for Analysing ..."; + // LogAlert(message); + + // + return result; + } + + // + // Detect Conditions ... + result = DetectConditions(conditions); + if (!result) + { + conditions.Clean(); + return result; + } + + // + // Combine all Signals Conditions ... + selectedSL = conditions.sl; + provider = conditions.provider; + + // + hasLong = + // + IsBullish(conditions.marketStructureDir) + // + ; + + // + hasShort = + // + IsBearish(conditions.marketStructureDir) + // + ; + + // + result = hasLong || + hasShort; + + // + // Rmove Signal Condition ... + if (result) + { + // + // TYPE ... + type = + hasLong + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + ENUM_X_POSITION_TYPES xType = + hasLong + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + entry = GetEntry( + conditions.symbol, + type // + ); + + // + sl = + hasLong + ? selectedSL - pip2 + : selectedSL + pip2; + + // + // RISK Reward ... + risk = + hasLong + ? entry - sl + : sl - entry; + reward = risk * r2r; + tp = + hasLong + ? entry + reward + : entry - reward; + + // + signal.sl = sl; + signal.tp = tp; + signal.type = type; + signal.mode = mode; + signal.entry = entry; + signal.volume = volume; + signal.symbol = symbol; + signal.period = period; + signal.pushers = pushers; + signal.provider = provider; + signal.time = TimeCurrent(); + + // + result = PrepareSignal(signal); + if (result) + { + // + Print("PRV: ", provider); + + // + ENUM_X_DIRECTION forDir = ToDirection(signal.type); + bool ignoreSwingHighs = false; + bool ignoreSwingLows = false; + bool ignoreSupportZones = false; + bool ignoreResistanceZones = false; + bool ignoreSupplyZones = false; + bool ignoreDemandZones = false; + bool ignoreBullishOrderBlocks = false; + bool ignoreBearishOrderBlocks = false; + bool ignoreBullishFairValueGaps = false; + bool ignoreBearishFairValueGaps = false; + bool ignoreBullishRejectionBars = false; + bool ignoreBearishRejectionBars = false; + bool ignoreBullishMomentumBars = false; + bool ignoreBearishMomentumBars = false; + if (IsBullish(forDir)) + { + // + ignoreSwingLows = false; + ignoreDemandZones = false; + ignoreSupportZones = false; + ignoreBullishOrderBlocks = false; + ignoreBullishFairValueGaps = false; + ignoreBullishRejectionBars = false; + ignoreBullishMomentumBars = false; + } + else + { + // + ignoreSwingHighs = true; + ignoreSupplyZones = true; + ignoreResistanceZones = true; + ignoreBearishOrderBlocks = true; + ignoreBearishFairValueGaps = false; + ignoreBearishRejectionBars = true; + ignoreBearishMomentumBars = true; + } + + // + RedrawOrderFlow( + true, // Force Clean ... + false, // Same Period ... + true, // Order Flow ... + true, // Order Flow State ... + false, // Only Last Order Flow ... + true, // Only Last Order Flow State ... + // + forDir, // Direction Force ... + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + DrawSignal(signal); + ClearDraws(); + + // + ResetOrderFlow(); + } + + // + hasLong = false; + hasShort = false; + } + + // + return result; + } + + /** + * Customize Strategy Identifier ... + */ + string GetTag() override + { + return X121SMCStrategyToken; + } + + // + // Protected ... + protected: + // + + // + // Props ... + + // + // Trigger Order Flow ... + XPVPivot mOrderFlow[]; + ENUM_X_DIRECTION mOrderFlowDir; + + // + XC121SMCCycleHelper *mTriggerCycleHelper; + XC121SMCCycleHelper *mDecisionCycleHelper; + XC121SMCCycleHelper *mAnalyseCycleHelper; + XC121SMCCycleHelper *mVerificationCycleHelper; + XC121SMCCycleHelper *mConsolidationCycleHelper; + XC121SMCCycleHelper *mVisionCycleHelper; + + // + // Actions ... + + /** + * Detect and Parse Market Conditions ... + * + * @return ( bool ) + */ + bool DetectConditions( + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + string msg = NULL; + + // + double bid = GetBid(symbol); + + // + conditions.symbol = symbol; + conditions.period = period; + conditions.time = TimeCurrent(); + + // + int conditionsLoopback = 7; + + // + // Fill Cycles Conditions ... + + // + // Trigger ... + mTriggerCycleHelper.GetConditions( + conditions.triggerConditions, + zIndex, + conditionsLoopback // + ); + conditions.triggerConditions.state = mTriggerState; + + // + // Decision ... + mDecisionCycleHelper.GetConditions( + conditions.decisionConditions, + zIndex, + conditionsLoopback // + ); + conditions.decisionConditions.state = mDecisionState; + + // + // Analyse ... + mAnalyseCycleHelper.GetConditions( + conditions.analyseConditions, + zIndex, + conditionsLoopback // + ); + conditions.analyseConditions.state = mAnalyseState; + + // + // Verification ... + mVerificationCycleHelper.GetConditions( + conditions.verificationConditions, + zIndex, + conditionsLoopback // + ); + conditions.verificationConditions.state = mVerificationState; + + // + // Consolidation ... + mConsolidationCycleHelper.GetConditions( + conditions.consolidationConditions, + zIndex, + conditionsLoopback // + ); + conditions.consolidationConditions.state = mConsolidationState; + + // + // Vision ... + mVisionCycleHelper.GetConditions( + conditions.visionConditions, + zIndex, + conditionsLoopback // + ); + conditions.visionConditions.state = mVisionState; + + // + // Check Market Conditions for + // Specified Structure ... + ENUM_X_DIRECTION marketStructureDir = X_DIRECTION_NONE; + result = conditions.HasDirection( + marketStructureDir, + cBar // + ); + if (!result) + { + // + conditions.Clean(); + return result; + } + msg = "Found Market Strucutre : " + (IsBullish(marketStructureDir) ? "Bullish" : "Berish"); + Alert(msg); + + // // + // // Detect Trigger Order Flow ... + // if (ArraySize(mOrderFlow) == 0 || + // mOrderFlowDir == X_DIRECTION_NONE) + // { + // // + // int samePivots = 40; + // int requiredPivots = 10; + + // // + // bool useVisionState = false; + // bool useConsolidationState = false; + // bool useVerificationState = false; + // bool useAnalyseState = false; + // bool useDecisionState = true; + // bool useTriggerState = false; + + // // + // DetectOrderFlow( + // cIndex, + // samePivots, + // requiredPivots, + // mTriggerCycleHelper, + // mOrderFlow, + // mOrderFlowDir, + // // + // // Filling Pivot State ... + // useVisionState, // Use Vision State ... + // useConsolidationState, // Use Consolidation State ... + // useVerificationState, // Use Verification State ... + // useAnalyseState, // Use Analyse State ... + // useDecisionState, // Use Decision State ... + // useTriggerState // Use Trigger State ... + // ); + + // // + // result = IsValidSize(ArraySize(mOrderFlow)); + // if (!result) + // { + // return result; + // } + // } + // result = HasValidOrderFlow() && + // mOrderFlowDir == marketStructureDir; + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + // msg = "Found OrderFlow : " + (IsBullish(mOrderFlowDir) ? "Bullish" : "Berish"); + // Alert(msg); + + // + conditions.marketStructureDir = marketStructureDir; + + // // + // XPVPivot lastPivot; + // result = GetLastItem( + // lastPivot, + // mOrderFlow // + // ); + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + + // + // Detect Last FVG ... + // XOHCL breakerBar; + // result = DetectLastBreakerBar( + // cBar, + // breakerBar, + // lastPivot, + // marketStructureDir // + // ); + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + // msg = "Found Breaker Bar: " + breakerBar.GetTag(); + // Alert(msg); + + // + // Detect Nearest Momentum or Rejection Bar ... + XOHCL decisionBar; + result = mDecisionCycleHelper.DetectNearestDecisionBar( + decisionBar, + marketStructureDir, + cBar // + ); + if (!result) + { + return result; + } + msg = "Found Decision Bar: " + decisionBar.GetTag(); + Alert(msg); + + // + // Detect Nearest Sar Change ... + XOHCL sarChangeBar; + result = mTriggerCycleHelper.DetectNearestCSARChange( + sarChangeBar, + cBar // + ); + if (!result) + { + // + conditions.Clean(); + return result; + } + msg = "Found Sar Change Bar: " + sarChangeBar.GetTag(); + Alert(msg); + + // + // Now we Hvae to Check Other Conditions ... + result = + // breakerBar.time > sarChangeBar.time && + // decisionBar.time > breakerBar.time; + decisionBar.time > sarChangeBar.time; + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + // Now we Have Check Direction Related Conditions ... + if (IsBullish(marketStructureDir)) + { + // + result = + // bid > decisionBar.high && + // bid > breakerBar.high && + bid > sarChangeBar.high && + bid > conditions.triggerConditions.xchsarConditions.cSars[0]; + } + else + { + // + result = + // bid < decisionBar.low && + // bid < breakerBar.low && + bid < sarChangeBar.high && + bid < conditions.triggerConditions.xchsarConditions.cSars[0]; + } + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + conditions.provider = "X121SMC"; + if (IsBullish(marketStructureDir)) + { + // + // conditions.sl = decisionBar.low; + // conditions.sl = breakerBar.low; + conditions.sl = conditions.triggerConditions.xchsarConditions.cSars[0]; + } + else + { + // + // conditions.sl = decisionBar.high; + // conditions.sl = breakerBar.high; + conditions.sl = conditions.triggerConditions.xchsarConditions.cSars[0]; + } + + // + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + return result; + } + + /** + * Detect XPV Based POI(s) ... + * + * @param barIndex: Start Bar Index ... + * @param minRepetition: minimum Repeate of POI for Validation ... + * @param requiredPivots: Number of Min Requirement POI(s) ... + * @param pivotHelper: XC121SMCCycleHelper instance Pointer ... + * @param orderFlow: XPVPivot instance Array Reference ... + * @param orderFlowDirection: ENUM_X_DIRECTION member Reference which represents OrderFlow Direction ... + * @param maxAllowedLoopbackBars: Integer, Max Allowed Loopback Bars ... + * + * @return ( bool ) + */ + bool DetectOrderFlow( + int barIndex, + int minRepetition, + int requiredPivots, + XC121SMCCycleHelper *pivotHelper, // XPV Helper ... + XPVPivot &orderFlow[], // OrderFlows ... + ENUM_X_DIRECTION &orderFlowDirection, // Order Flow Direction ... + // + bool useVisionState = true, // Use Vision State ... + bool useConsolidationState = true, // Use Consolidation State ... + bool useVerificationState = true, // Use Verification State ... + bool useAnalyseState = true, // Use Analyse State ... + bool useDecisionState = true, // Use Decision State ... + bool useTriggerState = true, // Use Trigger State ... + // + int maxAllowedLoopbackBars = 576 // + ) + { + // + bool result = false; + + // + orderFlowDirection = X_DIRECTION_NONE; + + // + if (maxAllowedLoopbackBars <= 0) + { + maxAllowedLoopbackBars = 1000; + } + + // + int start = barIndex; + int end = start + maxAllowedLoopbackBars; + + // + Clean(orderFlow); + + // + result = minRepetition > 0 && + requiredPivots > 0 && + pivotHelper != NULL; + if (!result) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + double peak = 0; + XPVPivot peaks[]; + int peakRepeate = 0; + int peakToBarIndex = 0; + int peakFromBarIndex = 0; + + // + double vale = 0; + XPVPivot vales[]; + int valeRepeate = 0; + int valeToBarIndex = 0; + int valeFromBarIndex = 0; + + // + bool canLookupPeak = true; + bool canLookupVale = true; + bool canLookup = true; + while (canLookup) + { + // + // Check Peak ... + double iPeak = pivotHelper.mXPVHelper.GetPeak(barIndex); + if (iPeak != peak) + { + // + if (peak != 0 && + peakRepeate >= minRepetition) + { + // + bool isExists = false; + int count = ArraySize(peaks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = peaks[i]; + + // + if (iPivot.upper == iPeak) + { + // + isExists = true; + break; + } + } + } + if (!isExists) + { + // + XPVPivot iPivot; + + // + iPivot.lower = 0; + iPivot.upper = peak; + iPivot.symbol = symbol; + iPivot.period = period; + iPivot.type = XPV_PEAK; + iPivot.repetition = peakRepeate; + iPivot.to = iTime( + symbol, + period, + peakToBarIndex // + ); + iPivot.from = iTime( + symbol, + period, + peakFromBarIndex // + ); + + // + iPivot.lower = iPivot.CalculateLower(); + + // + bool isValid = iPivot.IsValid(); + if (isValid) + { + // + AddRef( + iPivot, + peaks // + ); + } + } + } + + // + peak = iPeak; + peakRepeate = 0; + peakFromBarIndex = 0; + peakToBarIndex = barIndex; + } + else if (iPeak == peak) + { + // + peakRepeate++; + peakFromBarIndex = barIndex; + } + + // + // Check Vale ... + double iVale = pivotHelper.mXPVHelper.GetVale(barIndex); + if (iVale != vale) + { + // + if (vale != 0 && + valeRepeate >= minRepetition) + { + // + bool isExists = false; + int count = ArraySize(vales); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = vales[i]; + + // + if (iPivot.lower == iVale) + { + // + isExists = true; + break; + } + } + } + if (!isExists) + { + // + XPVPivot iPivot; + + // + iPivot.upper = 0; + iPivot.lower = vale; + iPivot.symbol = symbol; + iPivot.period = period; + iPivot.type = XPV_VALE; + iPivot.repetition = valeRepeate; + iPivot.to = iTime( + symbol, + period, + valeToBarIndex // + ); + iPivot.from = iTime( + symbol, + period, + valeFromBarIndex // + ); + + // + iPivot.upper = iPivot.CalculateUpper(); + + // + bool isValid = iPivot.IsValid(); + if (isValid) + { + // + AddRef( + iPivot, + vales // + ); + } + } + } + + // + vale = iVale; + valeRepeate = 0; + valeFromBarIndex = 0; + valeToBarIndex = barIndex; + } + else if (iVale == vale) + { + // + valeRepeate++; + valeFromBarIndex = barIndex; + } + + // + canLookupPeak = ArraySize(peaks) < requiredPivots; + canLookupVale = ArraySize(vales) < requiredPivots; + canLookup = barIndex < end && + (canLookupPeak || + canLookupVale); + if (canLookup) + { + barIndex++; + } + } + + // + result = IsValidSize(ArraySize(peaks)) || + IsValidSize(ArraySize(vales)); + if (!result) + { + return result; + } + + // + // Detect Order Flow ... + Copy( + peaks, + orderFlow, + false // + ); + Copy( + vales, + orderFlow, + false // + ); + int count = ArraySize(orderFlow); + result = IsValidSize(orderFlow); + if (!result) + { + return result; + } + + // + // Sort Pivots ... + SortPivots(orderFlow); + + // + // Filter Broken Order Flows ... + FilterBrokenPivots(orderFlow); + + // + // Detect Order Flow Direction ... + result = DetectPivotDirection( + orderFlow, + orderFlowDirection // + ); + if (!result) + { + return result; + } + + // + // Find State Inside Pivots and Attached Them to Pivot ... + int orderFlowCount = ArraySize(mOrderFlow); + if (IsValidSize(orderFlowCount)) + { + // + // Loop Through Order Flow ... + for (int i = 0; i < orderFlowCount; i++) + { + // + FillPivotSate( + i, + useVisionState, // Use Vision State ... + useConsolidationState, // Use Consolidation State ... + useVerificationState, // Use Verification State ... + useAnalyseState, // Use Analyse State ... + useDecisionState, // Use Decision State ... + useTriggerState // Use Trigger State ... + ); + } + } + + // + return result; + } + + /** + * Filling Specified Orer Flow Index ... + * + * @param pivotIDX: Integer ... + * @param lookupSwingHighs: Boolean ... + * @param lookupSwingLows: Boolean ... + * @param lookupSupportZones: Boolean ... + * @param lookupResistanceZones: Boolean ... + * @param lookupSupplyZones: Boolean ... + * @param lookupDemandZones: Boolean ... + * @param lookupBullishOrderBlocks: Boolean ... + * @param lookupBearishOrderBlocks: Boolean ... + * @param lookupBullishFairValueGaps: Boolean ... + * @param lookupBearishFairValueGaps: Boolean ... + * @param lookupBullishRejectionBars: Boolean ... + * @param lookupBearishRejectionBars: Boolean ... + * @param lookupBullishMomentumBars: Boolean ... + * @param lookupBearishMomentumBars: Boolean ... + */ + void FillPivotSate( + int pivotIDX, // + bool useVisionState = true, // Use Vision State ... + bool useConsolidationState = true, // Use Consolidation State ... + bool useVerificationState = true, // Use Verification State ... + bool useAnalyseState = true, // Use Analyse State ... + bool useDecisionState = true, // Use Decision State ... + bool useTriggerState = true, // Use Trigger State ... + bool lookupSwingHighs = true, + bool lookupSwingLows = true, + bool lookupSupportZones = true, + bool lookupResistanceZones = true, + bool lookupSupplyZones = true, + bool lookupDemandZones = true, + bool lookupBullishOrderBlocks = true, + bool lookupBearishOrderBlocks = true, + bool lookupBullishFairValueGaps = true, + bool lookupBearishFairValueGaps = true, + bool lookupBullishRejectionBars = true, + bool lookupBearishRejectionBars = true, + bool lookupBullishMomentumBars = true, + bool lookupBearishMomentumBars = true // + ) + { + // + CalculatePivotTickZone(pivotIDX); + + // + // Trigger ... + XPOIState mPivotTriggerState; + if (useTriggerState && + mTriggerState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mTriggerState, + mPivotTriggerState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotTriggerState.HasChild()) + { + mPivotTriggerState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Decision ... + XPOIState mPivotDecisionState; + if (useDecisionState && + mDecisionState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mDecisionState, + mPivotDecisionState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotDecisionState.HasChild()) + { + mPivotDecisionState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Analyse ... + XPOIState mPivotAnalyseState; + if (useAnalyseState && + mAnalyseState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mAnalyseState, + mPivotAnalyseState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotAnalyseState.HasChild()) + { + mPivotAnalyseState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Verification ... + XPOIState mPivotVerificationState; + if (useVerificationState && + mVerificationState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mVerificationState, + mPivotVerificationState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotVerificationState.HasChild()) + { + mPivotVerificationState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Consolidation ... + XPOIState mPivotConsolidationState; + if (useConsolidationState && + mConsolidationState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mConsolidationState, + mPivotConsolidationState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotConsolidationState.HasChild()) + { + mPivotConsolidationState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Vision ... + XPOIState mPivotVisionState; + if (useVisionState && + mVisionState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mVisionState, + mPivotVisionState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotVisionState.HasChild()) + { + mPivotVisionState.Fill(mOrderFlow[pivotIDX].state); + } + } + } + + /** + * When a BOS Happens ... + * we have to Update Order Flow ... + */ + void UpdateOrderFlow() + { + ResetOrderFlow(); + } + + /** + * Fill Pivot Tick Zone ... + * + * @param pivotIDX: Integer ... + */ + void CalculatePivotTickZone(int pivotIDX) + { + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + bool isInited = false; + + // + datetime from = mOrderFlow[pivotIDX].from; + XOHCL iFromBar; + int iFromBarIndex = iBarShift( + symbol, + period, + from // + ); + isInited = iFromBar.Init( + symbol, + period, + iFromBarIndex // + ); + if (!isInited) + { + return; + } + + // + datetime to = mOrderFlow[pivotIDX].to; + XOHCL iToBar; + int iToBarIndex = iBarShift( + symbol, + period, + to // + ); + isInited = iToBar.Init( + symbol, + period, + iToBarIndex // + ); + if (!isInited) + { + return; + } + + // + XCTicksZone *iZone; + iZone = new XCTicksZone(); + + // + int ticksLevels = mTriggerDetector.TicksRangeZoneLevel(); + int ticksRange = mTriggerDetector.TicksRangeZoneRange(); + isInited = ticksLevels > 0 && + ticksRange > 0; + if (!isInited) + { + return; + } + + // + isInited = iZone.Init( + iFromBar, + iToBar // + ); + if (!isInited) + { + return; + } + + // + mOrderFlow[pivotIDX].state.ticksZone = iZone; + } + + /** + * Validate Order Flow ... + * + * @return ( bool ) + */ + bool HasValidOrderFlow() + { + // + bool result = false; + + // + int orderFlowCount = ArraySize(mOrderFlow); + result = + IsValidSize(orderFlowCount) && + mOrderFlowDir != X_DIRECTION_ALL && + mOrderFlowDir != X_DIRECTION_NONE; + + // + return result; + } + + /** + * Reset Order Flow ... + */ + void ResetOrderFlow() + { + // + Clean(mOrderFlow); + mOrderFlowDir = X_DIRECTION_NONE; + + // + ClearDraws(); + } + + /** + * Detect Breaker Bar ... + * + * @param bar: XOHCL instance ... + * @param breakerBar: XOHCL instance, Breaker Bar ... + * @param pivot: XPVPivot instance ... + * @param forDir: ENUM_X_DIRECTION member, Market Structure Direction ... + * + * @return ( bool ) + */ + bool DetectLastBreakerBar( + XOHCL &bar, + XOHCL &breakerBar, + XPVPivot &pivot, + ENUM_X_DIRECTION forDir // + ) + { + // + bool result = false; + + // + result = + bar.IsValid() && + pivot.IsValid() && + forDir != X_DIRECTION_ALL && + forDir != X_DIRECTION_NONE; + if (!result) + { + return result; + } + + // + // FVG ... + result = DetectLastFVGBreakerBar( + bar, + breakerBar, + pivot, + forDir // + ); + if (result) + { + return result; + } + + // + // Order Block ... + // result = DetectLastOBBreakerBar( + // bar, + // breakerBar, + // pivot, + // forDir // + // ); + // if (result) + // { + // return result; + // } + + // + return result; + } + + bool DetectLastFVGBreakerBar( + XOHCL &bar, + XOHCL &breakerBar, + XPVPivot &pivot, + ENUM_X_DIRECTION forDir // + ) + { + // + bool result = false; + + // + result = + bar.IsValid() && + pivot.IsValid() && + forDir != X_DIRECTION_ALL && + forDir != X_DIRECTION_NONE; + if (!result) + { + return result; + } + + // + bool isBullishDir = IsBullish(forDir); + + // + int fvgsCount = + isBullishDir + ? pivot.state.CountBullishFairValueGaps() + : pivot.state.CountBearishFairValueGaps(); + result = IsValidSize(fvgsCount); + if (!result) + { + return result; + } + + // + int idx = -1; + XCFVG *zone = NULL; + for (int i = 0; i < fvgsCount; i++) + { + // + if (isBullishDir) + { + // + // Bullish FVG ... + if (zone == NULL) + { + // + zone = pivot.state.bullishFairValueGaps[i]; + + // + bool isBreaked = CheckZoneBreak( + forDir, + bar, + breakerBar, + zone // + ); + if (isBreaked) + { + idx = i; + } + } + else + { + // + bool isNewer = ((int)zone.From() - (int)bar.time) > ((int)pivot.state.bullishFairValueGaps[i].From() - (int)bar.time); + if (isNewer) + { + // + zone = pivot.state.bullishFairValueGaps[i]; + + // + bool isBreaked = CheckZoneBreak( + forDir, + bar, + breakerBar, + zone // + ); + if (isBreaked) + { + idx = i; + } + } + } + } + else + { + // + // Bearish FVG ... + if (zone == NULL) + { + // + zone = pivot.state.bearishFairValueGaps[i]; + + // + bool isBreaked = CheckZoneBreak( + forDir, + bar, + breakerBar, + zone // + ); + if (isBreaked) + { + idx = i; + } + } + else + { + // + bool isNewer = ((int)zone.From() - (int)bar.time) > ((int)pivot.state.bearishFairValueGaps[i].From() - (int)bar.time); + if (isNewer) + { + // + zone = pivot.state.bearishFairValueGaps[i]; + + // + bool isBreaked = CheckZoneBreak( + forDir, + bar, + breakerBar, + zone // + ); + if (isBreaked) + { + idx = i; + } + } + } + } + } + + // + result = + breakerBar.IsValid() && + IsValidIndex(idx) && + zone.IsValid(); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Check an FVG is Breaked or not ... + * + * @param forDir: ENUM_X_DIRECTION member, Market Structure Direction ... + * @param bar: XOHCL instance ... + * @param breakerBar: XOHCL instance, Breaker Bar ... + * + * @return ( bool ) + */ + bool CheckZoneBreak( + ENUM_X_DIRECTION forDir, + XOHCL &bar, + XOHCL &breakerBar, + XCFVG *&zone // + ) + { + // + bool result = false; + + // + breakerBar.Clean(); + + // + result = bar.IsValid() && + zone.IsValid() && + forDir != X_DIRECTION_ALL && + forDir != X_DIRECTION_NONE; + if (!result) + { + return result; + } + + // + int start = bar.Index(); + int end = iBarShift( + bar.symbol, + bar.period, + zone.From()); + for (int i = start; i < end; i++) + { + // + XOHCL iBar; + result = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + break; + } + + // + if (IsBullish(forDir)) + { + // + // Bullish Break ... + result = iBar.low < zone.Upper() && + iBar.high > zone.Upper() && + iBar.GetDown() < zone.Upper() && + iBar.GetUp() > zone.Upper() && + iBar.IsBullish(); + } + else + { + // + // Bearish Break ... + result = iBar.low < zone.Lower() && + iBar.high > zone.Lower() && + iBar.GetDown() < zone.Lower() && + iBar.GetUp() > zone.Lower() && + iBar.IsBearish(); + } + + // + if (result) + { + // + breakerBar = iBar; + break; + } + } + + // + result = breakerBar.IsValid(); + + // + return result; + } + + // + // Drawings ... + + /** + * Draw Order Flow ... + */ + void RedrawOrderFlow( + bool forceClearDraws = true, + bool forceDrawSamePeriod = true, + bool drawOrderFlow = true, + bool drawOrderFlowState = true, + bool drawOnlyLastOrderFlow = false, + bool drawOnlyLastOrderFlowState = true, + // + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + // + // Ignores List ... + bool ignoreSwingHighs = false, + bool ignoreSwingLows = false, + bool ignoreSupportZones = false, + bool ignoreResistanceZones = false, + bool ignoreSupplyZones = false, + bool ignoreDemandZones = false, + bool ignoreBullishOrderBlocks = false, + bool ignoreBearishOrderBlocks = false, + bool ignoreBullishFairValueGaps = false, + bool ignoreBearishFairValueGaps = false, + bool ignoreBullishRejectionBars = false, + bool ignoreBearishRejectionBars = false, + bool ignoreBullishMomentumBars = false, + bool ignoreBearishMomentumBars = false, + // + // States Drawing ... + bool drawVisionState = false, + bool drawConsolidationState = false, + bool drawVerificationState = false, + bool drawAnalyseState = false, + bool drawDecisionState = false, + bool drawTriggerState = false // + ) + { + // + if (forceClearDraws) + { + ClearDraws(); + } + + // + if (!drawOrderFlow || + !HasValidOrderFlow()) + { + return; + } + + // + int orderFlowCount = ArraySize(mOrderFlow); + for (int i = 0; i < orderFlowCount; i++) + { + // + bool isLast = i == orderFlowCount - 1; + bool canDraw = + !drawOnlyLastOrderFlow || + (isLast && + drawOnlyLastOrderFlow); + if (!canDraw) + { + continue; + } + + // + XPVPivot iPivot = mOrderFlow[i]; + + // + XCXPVPivotObject *iObj; + iObj = new XCXPVPivotObject(); + bool isCreated = iObj.Create( + mPOIDrawer.ChartIdentification(), + mPOIDrawer.SubWindowIdentification(), + iPivot // + ); + if (isCreated) + { + // + bool canDrawState = + drawOrderFlowState && + (!drawOnlyLastOrderFlowState || + (isLast && + drawOnlyLastOrderFlowState)); + if (canDrawState) + { + // + CustomStateDrawing( + iPivot.state, + forceDrawSamePeriod, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + if (iPivot.IsPeak()) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotColor(clrAqua); + iObj.PivotStyle(STYLE_SOLID); + } + + // + if (iPivot.IsVale()) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotStyle(STYLE_SOLID); + iObj.PivotColor(clrMagenta); + } + + // + AddObjectIfNotExists(iObj); + } + } + + // + // Draw States ... + + // + // Vision ... + if (drawVisionState) + { + // + CustomStateDrawing( + mVisionState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Consolidation ... + if (drawConsolidationState) + { + // + CustomStateDrawing( + mConsolidationState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Verification ... + if (drawVerificationState) + { + // + CustomStateDrawing( + mVerificationState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Analyse ... + if (drawAnalyseState) + { + // + CustomStateDrawing( + mAnalyseState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Decision ... + if (drawDecisionState) + { + // + CustomStateDrawing( + mDecisionState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Trigger ... + if (drawTriggerState) + { + // + CustomStateDrawing( + mTriggerState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + } + + /** + * Custom Drawing State ... + * + * @param state: XPOIState instance reference, Specified Which state to Draw ... + * @param forceDrawSamePeriod: Boolean ... + */ + void CustomStateDrawing( + XPOIState &state, + bool forceDrawSamePeriod = false, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + // + // Ignores List ... + bool ignoreSwingHighs = false, + bool ignoreSwingLows = false, + bool ignoreSupportZones = false, + bool ignoreResistanceZones = false, + bool ignoreSupplyZones = false, + bool ignoreDemandZones = false, + bool ignoreBullishOrderBlocks = false, + bool ignoreBearishOrderBlocks = false, + bool ignoreBullishFairValueGaps = false, + bool ignoreBearishFairValueGaps = false, + bool ignoreBullishRejectionBars = false, + bool ignoreBearishRejectionBars = false, + bool ignoreBullishMomentumBars = false, + bool ignoreBearishMomentumBars = false // + ) + { + // + XPOIState tmpState = state; + if (forceDrawSamePeriod) + { + // + int count = 0; + ENUM_TIMEFRAMES period = GetPeriod(); + + // + count = state.CountSwingHighs(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing iSwing = state.swingHighs[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.swingHighs, + i, + 1 // + ); + } + } + } + + // + count = state.CountSwingLows(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing iSwing = state.swingLows[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.swingLows, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishMomentumBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar iMomentum = state.bullishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishMomentumBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishMomentumBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar iMomentum = state.bearishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishMomentumBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishRejectionBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar iRejection = state.bullishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishRejectionBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishRejectionBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar iRejection = state.bearishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishRejectionBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountSupportZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZone iZone = state.supportZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.supportZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountResistanceZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZone iZone = state.resistanceZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.resistanceZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountSupplyZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupplyZone iZone = state.supplyZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.supplyZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountDemandZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCDemandZone iZone = state.demandZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.demandZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock iZone = state.bullishOrderBlocks[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishOrderBlocks, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock iZone = state.bearishOrderBlocks[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishOrderBlocks, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishFairValueGaps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG iZone = state.bullishFairValueGaps[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillStartBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishFairValueGaps, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishFairValueGaps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG iZone = state.bearishFairValueGaps[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillStartBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishFairValueGaps, + i, + 1 // + ); + } + } + } + + // + } + + // + bool drawSwingHighs = true; + bool drawSwingLows = true; + bool drawSupportZones = true; + bool drawResistanceZones = true; + bool drawSupplyZones = true; + bool drawDemandZones = true; + bool drawBullishOrderBlocks = true; + bool drawBearishOrderBlocks = true; + bool drawBullishFairValueGaps = true; + bool drawBearishFairValueGaps = true; + bool drawBullishRejectionBars = true; + bool drawBearishRejectionBars = true; + bool drawBullishMomentumBars = true; + bool drawBearishMomentumBars = true; + + // + // Change Drawing Specs Conditions based on + // Provided Direction ... + if (forDir == X_DIRECTION_BULLISH) + { + // + drawSwingLows = true; + drawDemandZones = true; + drawSupportZones = true; + drawBullishOrderBlocks = true; + drawBullishFairValueGaps = true; + drawBullishRejectionBars = true; + drawBullishMomentumBars = true; + + // + drawSwingHighs = false; + drawSupplyZones = false; + drawResistanceZones = false; + drawBearishOrderBlocks = false; + drawBearishFairValueGaps = false; + drawBearishRejectionBars = false; + drawBearishMomentumBars = false; + } + else if (forDir == X_DIRECTION_BEARISH) + { + // + drawSwingLows = false; + drawDemandZones = false; + drawSupportZones = false; + drawBullishOrderBlocks = false; + drawBullishFairValueGaps = false; + drawBullishRejectionBars = false; + drawBullishMomentumBars = false; + + // + drawSwingHighs = true; + drawSupplyZones = true; + drawResistanceZones = true; + drawBearishOrderBlocks = true; + drawBearishFairValueGaps = true; + drawBearishRejectionBars = true; + drawBearishMomentumBars = true; + } + + // + // Apply Ignore List ... + + // + if (ignoreSwingHighs) + { + drawSwingHighs = false; + } + + // + if (ignoreSwingLows) + { + drawSwingLows = false; + } + + // + if (ignoreSupportZones) + { + drawSupportZones = false; + } + + // + if (ignoreResistanceZones) + { + drawResistanceZones = false; + } + + // + if (ignoreSupplyZones) + { + drawSupplyZones = false; + } + + // + if (ignoreDemandZones) + { + drawDemandZones = false; + } + + // + if (ignoreBullishOrderBlocks) + { + drawBullishOrderBlocks = false; + } + + // + if (ignoreBearishOrderBlocks) + { + drawBearishOrderBlocks = false; + } + + // + if (ignoreBullishFairValueGaps) + { + drawBullishFairValueGaps = false; + } + + // + if (ignoreBearishFairValueGaps) + { + drawBearishFairValueGaps = false; + } + + // + if (ignoreBullishRejectionBars) + { + drawBullishRejectionBars = false; + } + + // + if (ignoreBearishRejectionBars) + { + drawBearishRejectionBars = false; + } + + // + if (ignoreBullishMomentumBars) + { + drawBullishMomentumBars = false; + } + + // + if (ignoreBearishMomentumBars) + { + drawBearishMomentumBars = false; + } + + // + DrawState( + tmpState, // State ... + true, // Update To of all Drawings Till now ... + drawSwingHighs, // Draw SwingHighs .. + drawSwingLows, // Draw SwingLows .. + drawSupportZones, // Draw SupportZones .. + drawResistanceZones, // Draw ResistanceZones .. + drawSupplyZones, // Draw SupplyZones .. + drawDemandZones, // Draw DemandZones .. + drawBullishOrderBlocks, // Draw BullishOrderBlocks .. + drawBearishOrderBlocks, // Draw BearishOrderBlocks .. + drawBullishFairValueGaps, // Draw BullishFairValueGaps .. + drawBearishFairValueGaps, // Draw BearishFairValueGaps .. + drawBullishRejectionBars, // Draw BullishRejectionBars .. + drawBearishRejectionBars, // Draw BearishRejectionBars .. + drawBullishMomentumBars, // Draw BullishMomentumBars .. + drawBearishMomentumBars, // Draw BearishMomentumBars .. + true // Draw Ticks Zone ... + ); + } + + // + // Private ... + private: + // + // Props ... + + /** + * Initial Required Indicators Helper ... + */ + void InitialHelpers() + { + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + // Short ... + ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES scPeriod = NULL; // Time Period + + // + // Medium ... + ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES mcPeriod = NULL; // Time Period + + // + // Long ... + ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES lcPeriod = NULL; // Time Period + + // + // Hind ... + ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES hcPeriod = NULL; // Time Period + + // + // XPV ... + XPVInputs xpvInputs; + + // + xpvInputs.Default(); + + // + xpvInputs.scMethod = scMethod; + xpvInputs.scPeriod = scPeriod; + xpvInputs.mcMethod = mcMethod; + xpvInputs.mcPeriod = mcPeriod; + xpvInputs.lcMethod = lcMethod; + xpvInputs.lcPeriod = lcPeriod; + xpvInputs.hcMethod = hcMethod; + xpvInputs.hcPeriod = hcPeriod; + + // + xpvInputs.showPeaksAndVales = true; + xpvInputs.showLevels = false; + xpvInputs.showConsolidations = false; + xpvInputs.showFibo1Levels = false; + xpvInputs.showFibo2Levels = false; + xpvInputs.showFibo3Levels = false; + xpvInputs.showFibo4Levels = false; + xpvInputs.showFibo5Levels = false; + + // + // X3MA ... + X3MAInputs x3maInputs; + + // + x3maInputs.Default(); + + // + // x3maInputs.fastLength = 10; + // x3maInputs.midLength = 25; + // x3maInputs.slowLength = 50; + + // + x3maInputs.showFast = true; + x3maInputs.showMid = false; + x3maInputs.showSlow = false; + + // + // X3VWAP ... + X3VWAPInputs x3vwapInputs; + + // + x3vwapInputs.Default(); + + // + // x3vwapInputs.fastLength = 10; + // x3vwapInputs.midLength = 25; + // x3vwapInputs.slowLength = 50; + + // + x3vwapInputs.showFast = true; + x3vwapInputs.showMid = true; + x3vwapInputs.showSlow = true; + + // + // XCHSAR ... + XCHSARInputs xchsarInputs; + + // + xchsarInputs.Default(); + + // + xchsarInputs.scMethod = scMethod; + xchsarInputs.scPeriod = scPeriod; + xchsarInputs.mcMethod = mcMethod; + xchsarInputs.mcPeriod = mcPeriod; + xchsarInputs.lcMethod = lcMethod; + xchsarInputs.lcPeriod = lcPeriod; + xchsarInputs.hcMethod = hcMethod; + xchsarInputs.hcPeriod = hcPeriod; + + // + xchsarInputs.showCurrent = true; + xchsarInputs.showShort = false; + xchsarInputs.showMedium = false; + xchsarInputs.showLong = false; + xchsarInputs.showHind = false; + + // + // Initialize Cycle Helpers ... + + // + mTriggerCycleHelper = new XC121SMCCycleHelper(); + mTriggerCycleHelper.Init( + symbol, + PERIOD_M1, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mDecisionCycleHelper = new XC121SMCCycleHelper(); + mDecisionCycleHelper.Init( + symbol, + PERIOD_M5, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mAnalyseCycleHelper = new XC121SMCCycleHelper(); + mAnalyseCycleHelper.Init( + symbol, + PERIOD_M15, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mVerificationCycleHelper = new XC121SMCCycleHelper(); + mVerificationCycleHelper.Init( + symbol, + PERIOD_M30, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mConsolidationCycleHelper = new XC121SMCCycleHelper(); + mConsolidationCycleHelper.Init( + symbol, + PERIOD_H1, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mVisionCycleHelper = new XC121SMCCycleHelper(); + mVisionCycleHelper.Init( + symbol, + PERIOD_H4, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/x-saherelm.common.lib.mq5 b/BKPS/14030923/Documents/BKP/x-saherelm.common.lib.mq5 new file mode 100644 index 0000000..afbe8bc --- /dev/null +++ b/BKPS/14030923/Documents/BKP/x-saherelm.common.lib.mq5 @@ -0,0 +1,13323 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XCommonLib +// Description: provide all commonly used functions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-md5.class.mq5" + +// +// Models ... + +// +// Specified Price Type ... +enum ENUM_X_PRICE +{ + X_PRICE_HIGH, + X_PRICE_OPEN, + X_PRICE_CLOSE, + X_PRICE_LOW, + X_PRICE_UP, + X_PRICE_DOWN +}; + +// +enum ENUM_X_DIRECTION +{ + X_DIRECTION_ALL, + X_DIRECTION_NONE, + X_DIRECTION_BULLISH, + X_DIRECTION_BEARISH, +}; + +// +// Swing Types Enum ... +enum ENUM_X_SWING_TYPE +{ + X_NO_SWING = 0, + X_SWING_HIGH = 1, + X_SWING_LOW = -1, +}; + +// +ENUM_SERIESMODE ToSeriesMode(ENUM_X_SWING_TYPE value) +{ + // + ENUM_SERIESMODE result = MODE_HIGH; + + // + switch (value) + { + // + case X_SWING_HIGH: + result = MODE_HIGH; + break; + + // + case X_SWING_LOW: + result = MODE_LOW; + break; + } + + // + return result; +} + +// +// Find Swing Points ... +int FindSwing( + string mSymbol, // Trading Symbol ... + ENUM_TIMEFRAMES mPeriod, // Trading Period ... + ENUM_X_SWING_TYPE mMode, // Swing Based On Price mode ... + int mLength, // Loopback ... + int bar_index // BarIndex ... +) +{ + // + int result = -1; + + // + if (StringLen(mSymbol) == 0 || (mMode != X_SWING_HIGH && mMode != X_SWING_LOW)) + { + return result; + } + + // + int current = bar_index; + int founded = FindNextSwing( + mSymbol, + mPeriod, + mMode, + (mLength * 2) + 1, + current - mLength); + + // + while (founded != current) + { + // + current = FindNextSwing( + mSymbol, + mPeriod, + mMode, + mLength, + current + 1); + + // + founded = FindNextSwing( + mSymbol, + mPeriod, + mMode, + (mLength * 2) + 1, + current - mLength); + } + + // + result = current; + + // + return result; +} + +// +// Find Next Swing ... +int FindNextSwing( + string mSymbol, // Trading Symbol ... + ENUM_TIMEFRAMES mPeriod, // Trading Period ... + ENUM_X_SWING_TYPE mMode, // Swing Based On Price mode ... + int mLength, // Loopback ... + int bar_index // BarIndex ... +) +{ + // + int result = -1; + + // + if (bar_index < 0) + { + mLength += bar_index; + bar_index = 0; + } + + // + ENUM_SERIESMODE mSeriesMode = ToSeriesMode(mMode); + + // + result = mMode == X_SWING_HIGH + ? iHighest( + mSymbol, + mPeriod, + mSeriesMode, + mLength, + bar_index) + : iLowest( + mSymbol, + mPeriod, + mSeriesMode, + mLength, + bar_index); + + // + return result; +} + +// +// XPERIOD Calculation Method ... +enum ENUM_X_PERIOD_METHOD +{ + // + X_PERIOD_NOTHING, // Nothing + X_PERIOD_AUTO, // Auto Select + X_PERIOD_MANUALLY // Manually +}; + +// +// Available Market Cycles ... +enum ENUM_X_MARKET_CYCLES +{ + // + X_MARKET_CYCLE_UNKNOWN, // Unknown Cycle + X_MARKET_CYCLE_SHORT, // Short Cycle + X_MARKET_CYCLE_MEDIUM, // Medium Cycle + X_MARKET_CYCLE_LONG, // Long Cycle + X_MARKET_CYCLE_HIND, // Hind Cycle +}; + +// +// Structs ... + +// +// Model Specified Ticks Info ... +struct XTick +{ + // + string symbol; // Symbol ... + datetime time; // Time ... + double bid; // Bid ... + double ask; // Ask ... + double spread; // Spread ... + + // + // Constructor ... + void XTick() + { + Clean(); + } + + // + // Tools Functions ... + + /** + * Initial ... + * + * @param _symbol: Symbol ... + * @param _time: Time ... + * @param _bid: Bid Price ... + * @param _ask: Ask Price ... + */ + bool Init( + string _symbol, + datetime _time, + double _bid, + double _ask, + double _spread // + ) + { + // + bool result = false; + + // + result = IsValid(_symbol) && + IsValid(_time) && + _bid > 0 && + _ask > 0; + if (!result) + { + return result; + } + + // + bid = _bid; + ask = _ask; + time = _time; + symbol = _symbol; + spread = _spread; + + // + result = IsValid(); + + // + return result; + } + + /** + * Init Tick by Symbol ... + * + * @param _symbol: String ... + * + * @return ( bool ) + */ + bool Init(string _symbol) + { + // + bool result = false; + + // + result = IsValid(_symbol); + if (!result) + { + return result; + } + + // + datetime _time = TimeCurrent(); + double _bid = GetBid(_symbol); + double _ask = GetAsk(_symbol); + double _spread = GetSpread(_symbol); + + // + result = Init( + _symbol, + _time, + _bid, + _ask, + _spread // + ); + + // + return result; + } + + /** + * Cleanup ... + */ + void Clean() + { + // + bid = 0; + ask = 0; + time = NULL; + symbol = NULL; + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = IsValid(symbol) && + IsValid(time) && + bid > 0 && + ask > 0; + + // + return result; + } + + // +}; + +// +// Model a Bar Remains Time ... +struct XBarRemainsTime +{ + // + int days; + int hours; + int minutes; + int seconds; + + // + // Constructor ... + XBarRemainsTime() + { + Clean(); + } + + // + // Always Calculate Current 0 Bar Timing ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL // Trading Period + ) + { + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int minuteSecoonds = 60; + int hourSeconds = minuteSecoonds * 60; + int daySeconds = 24 * hourSeconds; + + // + int periodSeconds = PeriodSeconds( + mPeriod); + datetime startTime = GetBarTime( + mSymbol, + mPeriod, + 0 + // + ); + + // + int secondsDiff = (int)startTime + periodSeconds - (int)TimeCurrent(); + + // + int mWorkingSecondsDiff = secondsDiff; + if (mWorkingSecondsDiff > daySeconds) + { + // + days = mWorkingSecondsDiff / daySeconds; + mWorkingSecondsDiff -= days * daySeconds; + } + if (mWorkingSecondsDiff > hourSeconds) + { + // + hours = mWorkingSecondsDiff / hourSeconds; + mWorkingSecondsDiff -= hours * hourSeconds; + } + if (mWorkingSecondsDiff > minuteSecoonds) + { + // + minutes = mWorkingSecondsDiff / minuteSecoonds; + mWorkingSecondsDiff -= minutes * minuteSecoonds; + } + seconds = mWorkingSecondsDiff; + + // + result = true; + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + days = 0; + hours = 0; + minutes = 0; + seconds = 0; + } + + // + // To String Representation ... + string ToString( + string dayId = "d", + string hourId = "h", + string minuteId = "m", + string secondId = "s", + string idSeparator = ": ", + string separator = ", ", + bool ignoreZeroValues = true + // + ) + { + // + string result = ""; + + // + // Days ... + if (!ignoreZeroValues || days > 0) + { + result += dayId + idSeparator + (string)days + separator; + } + + // + // Hours ... + if (!ignoreZeroValues || hours > 0) + { + // + string strHour = ToString(hours); + if (StringLen(strHour) == 1) + { + strHour = "0" + strHour; + } + + // + result += hourId + idSeparator + strHour + separator; + } + + // + // Minutes ... + if (!ignoreZeroValues || minutes > 0) + { + // + string strMinute = ToString(minutes); + if (StringLen(strMinute) == 1) + { + strMinute = "0" + strMinute; + } + + // + result += minuteId + idSeparator + strMinute + separator; + } + + // + // Seconds ... + if (!ignoreZeroValues || seconds > 0) + { + // + string strSec = ToString(seconds); + if (StringLen(strSec) == 1) + { + strSec = "0" + strSec; + } + + // + result += secondId + idSeparator + strSec; + } + + // + return result; + } +}; + +// +// Describe an Specific Candle ... +struct XOHCL +{ + // + // Props ... + + // + double high; + double open; + double close; + double low; + + // + string symbol; + datetime time; + ENUM_TIMEFRAMES period; + + // + // Constructor ... + XOHCL() + { + Clean(); + } + + // + // Init a Bar ... + // Using Bar Index ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + int barIndex = 0 // Bar Index + ) + { + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + symbol = mSymbol; + period = mPeriod; + + // + time = iTime( + mSymbol, + mPeriod, + barIndex // + ); + + // + open = iOpen( + mSymbol, + mPeriod, + barIndex // + ); + open = NormalizePrice(open, mSymbol); + + // + close = iClose( + mSymbol, + mPeriod, + barIndex // + ); + close = NormalizePrice(close, mSymbol); + + // + high = iHigh( + mSymbol, + mPeriod, + barIndex // + ); + high = NormalizePrice(high, mSymbol); + + // + low = iLow( + mSymbol, + mPeriod, + barIndex // + ); + low = NormalizePrice(low, mSymbol); + + // + bool result = IsValid(); + + // + return result; + } + + // + // Init a Bar ... + // Using Bar Time ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + datetime mTime = NULL // Bar Time + ) + { + // + mTime = NormalizeTime(mTime); + + // + int barIndex = iBarShift( + mSymbol, + mPeriod, + mTime, + false // + ); + + // + bool result = Init( + mSymbol, + mPeriod, + barIndex + // + ); + + // + return result; + } + + // + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + double mOpen = 0, // Open + double mHigh = 0, // High + double mClose = 0, // Close + double mLow = 0, // Low + int barIndex = 0 // Bar Index + ) + { + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + symbol = mSymbol; + period = mPeriod; + + // + time = iTime( + mSymbol, + mPeriod, + barIndex + // + ); + + // + open = mOpen; + high = mHigh; + close = mClose; + low = mLow; + + // + return IsValid(); + } + + // + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + double mOpen = 0, // Open + double mHigh = 0, // High + double mClose = 0, // Close + double mLow = 0, // Low + datetime mTime = NULL // Bar Time + ) + { + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + symbol = mSymbol; + period = mPeriod; + + // + int barIndex = iBarShift( + symbol, + period, + mTime); + + // + time = iTime( + mSymbol, + mPeriod, + barIndex + // + ); + + // + open = mOpen; + high = mHigh; + close = mClose; + low = mLow; + + // + return IsValid(); + } + + // + // Tools ... + + // + void Clean() + { + // + high = 0; + open = 0; + close = 0; + low = 0; + + // + time = NULL; + symbol = NULL; + period = NULL; + } + + // + // Validate Bar ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + high > 0 && + open > 0 && + close > 0 && + low > 0 + // + ; + + // + return result; + } + + // + int TotalBars() + { + // + int result = 0; + + // + result = iBars( + symbol, + period // + ); + + // + return result; + } + + // + // Calculate X_PRICE Specified Type ... + double GetPrice(ENUM_X_PRICE mPType) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + switch (mPType) + { + // + case X_PRICE_OPEN: + result = open; + break; + // + case X_PRICE_HIGH: + result = high; + break; + // + case X_PRICE_CLOSE: + result = close; + break; + // + case X_PRICE_LOW: + result = low; + break; + // + case X_PRICE_UP: + result = GetUp(); + break; + // + case X_PRICE_DOWN: + result = GetDown(); + break; + } + + // + return result; + } + + // + // Retrieve Price base On Series Mode ... + double GetPrice(ENUM_SERIESMODE mMode) + { + // + ENUM_X_PRICE mXMode = ToPrice(mMode); + + // + return GetPrice(mXMode); + } + + // + // Calculate Applied Price ... + double GetPrice( + ENUM_APPLIED_PRICE mAppliedTo // Select Application Method + ) + { + // + double result = 0; + + // + // Calculate Applied Price ... + switch (mAppliedTo) + { + // + case PRICE_CLOSE: + result = close; + break; + + // + case PRICE_OPEN: + result = open; + break; + + // + case PRICE_HIGH: + result = high; + break; + + // + case PRICE_LOW: + result = low; + break; + + // + case PRICE_MEDIAN: + result = (high + low) / 2; + break; + + // + case PRICE_TYPICAL: + result = (high + low + close) / 3; + break; + + // + case PRICE_WEIGHTED: + result = (high + low + close + close) / 4; + break; + } + + // + return result; + } + + // + // Find Specific Price ... + bool FindHigherPriceBar( + XOHCL &bar, + double price, + ENUM_X_PRICE _type = X_PRICE_HIGH // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = TotalBars(); + result = IsValidSize(totalBars); + if (!result) + { + return result; + } + + // + int start = Index(); + int maxAllowedLoopback = totalBars / 5; + for (int i = start; i < maxAllowedLoopback; i++) + { + // + result = bar.Init( + symbol, + period, + i // + ); + + // + if (!result) + { + break; + } + + // + double iPrice = bar.GetPrice(_type); + + // + result = + // + iPrice > 0 && + iPrice > price + // + ; + if (result) + { + break; + } + } + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + // Find Specific Price ... + bool FindLowerPriceBar( + XOHCL &bar, + double price, + ENUM_X_PRICE _type = X_PRICE_HIGH // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = TotalBars(); + result = IsValidSize(totalBars); + if (!result) + { + return result; + } + + // + int start = Index(); + int maxAllowedLoopback = totalBars / 5; + for (int i = start; i < maxAllowedLoopback; i++) + { + // + result = bar.Init( + symbol, + period, + i // + ); + + // + if (!result) + { + break; + } + + // + double iPrice = bar.GetPrice(_type); + + // + result = + // + iPrice > 0 && + iPrice < price + // + ; + if (result) + { + break; + } + } + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + // Calculate Bar Mid Line ... + double GetMid() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = (high + low) / 2; + + // + return result; + } + + // + // Calculate up Price ... + double GetUp() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathMax(open, close); + + // + return result; + } + + // + // Calculate Down Price ... + double GetDown() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathMin(open, close); + + // + return result; + } + + // + // Calculate Bar Body ... + double GetBody() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetUp() - GetDown(); + + // + return result; + } + + // + // Calculate Bar Range ... + double GetRange() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = high - low; + + // + return result; + } + + // + // Calculate Bar Shadows ... + double GetShadows() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetRange() - GetBody(); + + // + return result; + } + + // + // Calculate Bar High Shadow ... + double GetHighShadow() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + high - GetUp() + // + ; + + // + return result; + } + + // + // Calculate Bar Low Shadow ... + double GetLowShadow() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + GetDown() - low; + // + ; + + // + return result; + } + + // + // Check Bar is Bullish ... + bool IsBullish() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = open < close; + + // + return result; + } + + // + // Check Bar is Bearish ... + bool IsBearish() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = open > close; + + // + return result; + } + + // + // Get Direction of Bar ... + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + bool isBullish = IsBullish(); + bool isBearish = IsBearish(); + + // + result = + isBullish && isBearish + ? X_DIRECTION_ALL + : !isBullish && !isBearish + ? X_DIRECTION_NONE + : isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Find Next Bar Time ... + datetime NextAt() + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int prSeconds = PeriodSeconds(period); + + // + result = time + prSeconds; + + // + return result; + } + + // + // Find Prev Bar Time ... + datetime BeforeOn() + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int prSeconds = PeriodSeconds(period); + + // + result = time - prSeconds; + + // + return result; + } + + // + // Calculate Last Bar Open Time in Smaller Period ... + datetime GetLastBarTimeOfPeriod( + ENUM_TIMEFRAMES smallerPeriod // + ) + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int sourceSeconds = PeriodSeconds(period); + int destSeconds = PeriodSeconds(smallerPeriod); + if (destSeconds >= sourceSeconds) + { + // + result = time; + return result; + } + + // + result = (datetime)((((int)time) + sourceSeconds) - destSeconds); + + // + return result; + } + + // + // Calculate Close Time ... + datetime GetCloseTime() + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int seconds = PeriodSeconds(period); + + // + result = (datetime)(((int)time) + seconds); + + // + return result; + } + + // + // Find Current Bar Index on Chart ... + int Index() + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + result = iBarShift( + symbol, + period, + time + // + ); + + // + return result; + } + + // + bool GetNextBar(XOHCL &bar) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int idx = Index(); + result = idx > 0; + if (!result) + { + return result; + } + + // + result = bar.Init( + this.symbol, + this.period, + idx - 1 // + ); + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + bool GetPreviousBar(XOHCL &bar) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int idx = Index(); + + // + result = bar.Init( + this.symbol, + this.period, + idx + 1 // + ); + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + bool IsStrong( + double percent = 50 // Percent of Body + ) + { + // + bool result = false; + + // + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + result = + (GetRange() * percent) / 100 <= GetBody(); + + // + return result; + } + + // + bool HasStrongLowShadow( + double percent = 50, // Percent of Body + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + result = + (GetRange() * percent) / 100 <= GetLowShadow(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + result = Index() > __loopback; + if (!result) + { + return result; + } + + // + // Get Highest High and Lowest Low in loopback Range ... + int startIndex = Index() - __loopback; + int endIndex = Index() + __loopback; + int requiredBars = MathAbs(endIndex - startIndex); + + // + // Highs ... + double highs[]; + int copiedHighs = CopyHigh( + symbol, + period, + startIndex, + requiredBars, + highs // + ); + + // + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + int highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + double highestHigh = highs[highestHighIDX]; + + // + // Lows ... + double lows[]; + int copiedLows = CopyLow( + symbol, + period, + startIndex, + requiredBars, + lows // + ); + + // + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + int lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + double lowestLow = lows[lowestLowIDX]; + + // + result = low == lowestLow && + highestHigh > high; + if (!result) + { + return result; + } + + // + // Try to Validate Sharp Ratio ... + + // + Clean(highs); + Clean(lows); + + // + // Left Side ... + startIndex = Index() + 1; + endIndex = startIndex + (__loopback / 2) - 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + symbol, + period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + symbol, + period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double leftDiff = highestHigh - lowestLow; + + // + Clean(highs); + Clean(lows); + + // + // Right Side ... + startIndex = Index() - 1; + endIndex = startIndex - (__loopback / 2) + 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + symbol, + period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + symbol, + period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double rightDiff = highestHigh - lowestLow; + double diff = MathMax(leftDiff, rightDiff); + result = GetLowShadow() >= (diff / 100) * _sharpRatio; + + // + return result; + } + + // + bool HasStrongHighShadow( + double percent = 50, // Percent of Body + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + result = + (GetRange() * percent) / 100 <= GetHighShadow(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + result = Index() > __loopback; + if (!result) + { + return result; + } + + // + // Get Highest High and Lowest Low in loopback Range ... + int startIndex = Index() - __loopback; + int endIndex = Index() + __loopback; + int requiredBars = MathAbs(endIndex - startIndex); + + // + // Highs ... + double highs[]; + int copiedHighs = CopyHigh( + symbol, + period, + startIndex, + requiredBars, + highs // + ); + + // + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + int highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + double highestHigh = highs[highestHighIDX]; + + // + // Lows ... + double lows[]; + int copiedLows = CopyLow( + symbol, + period, + startIndex, + requiredBars, + lows // + ); + + // + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + int lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + double lowestLow = lows[lowestLowIDX]; + + // + result = high == highestHigh && + lowestLow < low; + if (!result) + { + return result; + } + + // + // Try to Validate Sharp Ratio ... + + // + Clean(highs); + Clean(lows); + + // + // Left Side ... + startIndex = Index() + 1; + endIndex = startIndex + (__loopback / 2) - 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + symbol, + period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + symbol, + period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double leftDiff = highestHigh - lowestLow; + + // + Clean(highs); + Clean(lows); + + // + // Right Side ... + startIndex = Index() - 1; + endIndex = startIndex - (__loopback / 2) + 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + symbol, + period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + symbol, + period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double rightDiff = highestHigh - lowestLow; + double diff = MathMax(leftDiff, rightDiff); + result = GetHighShadow() >= (diff / 100) * _sharpRatio; + + // + return result; + } + + // + bool IsStrongBullish( + double percent = 50 // Percent of Body + ) + { + // + bool result = false; + + // + result = + IsStrong(percent) && IsBullish(); + + // + return result; + } + + // + bool IsStrongBearish( + double percent = 50 // Percent of Body + ) + { + // + bool result = false; + + // + result = + IsStrong(percent) && IsBearish(); + + // + return result; + } + + // + bool IsSharpBullish( + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + int hIDX = FindHighestIndex( + __loopback, + MODE_HIGH // + ); + int lIDX = FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + result = + // + hIDX >= 0 && + lIDX >= 0 && + MathAbs(hIDX - Index()) < 2 + // + ; + + // + if (!result) + { + return result; + } + + // + XOHCL hBar; + result = hBar.Init( + symbol, + period, + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL lBar; + result = lBar.Init( + symbol, + period, + lIDX // + ); + if (!result) + { + return result; + } + + // + double lhDif = hBar.high - lBar.low; + + // + int hhIDX = hBar.FindHighestIndex( + __loopback, + MODE_HIGH // + ); + + // + int llIDX = lBar.FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + XOHCL hhBar; + result = hhBar.Init( + symbol, + period, + hhIDX + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL llBar; + result = llBar.Init( + symbol, + period, + llIDX + lIDX // + ); + if (!result) + { + return result; + } + + // + double llhhDif = hhBar.high - llBar.low; + + // + result = + // + lBar.low > llBar.low && + hBar.high > hhBar.high && + lhDif >= llhhDif * _sharpRatio + // + ; + + // + return result; + } + + // + bool IsSharpBearish( + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + int hIDX = FindHighestIndex( + __loopback, + MODE_HIGH // + ); + int lIDX = FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + result = + // + hIDX >= 0 && + lIDX >= 0 && + MathAbs(hIDX - Index()) < 2 + // + ; + + // + if (!result) + { + return result; + } + + // + XOHCL hBar; + result = hBar.Init( + symbol, + period, + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL lBar; + result = lBar.Init( + symbol, + period, + lIDX // + ); + if (!result) + { + return result; + } + + // + double lhDif = hBar.high - lBar.low; + + // + int hhIDX = hBar.FindHighestIndex( + __loopback, + MODE_HIGH // + ); + + // + int llIDX = lBar.FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + XOHCL hhBar; + result = hhBar.Init( + symbol, + period, + hhIDX + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL llBar; + result = llBar.Init( + symbol, + period, + llIDX + lIDX // + ); + if (!result) + { + return result; + } + + // + double llhhDif = hhBar.high - llBar.low; + + // + result = + // + lBar.low < llBar.low && + hBar.high < hhBar.high && + lhDif >= llhhDif * _sharpRatio + // + ; + + // + return result; + } + + // + // Find Lowest Bar Index ... + int FindHighestIndex( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (mLength < 2) + { + mLength = 2; + } + + // + result = iHighest( + symbol, + period, + mMode, + mLength, + Index()); + + // + return result; + } + + // + // Find Lowest ... + double FindHighest( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + int idx = FindHighestIndex( + mLength, + mMode); + if (idx <= -1) + { + return result; + } + + // + XOHCL iH; + result = iH.Init( + symbol, + period, + idx + // + ); + if (!result) + { + return result; + } + + // + result = iH.GetPrice(mMode); + + // + return result; + } + + // + // Find Lowest Bar Index ... + int FindLowestIndex( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (mLength < 2) + { + mLength = 2; + } + + // + result = iLowest( + symbol, + period, + mMode, + mLength, + Index()); + + // + return result; + } + + // + // Find Lowest ... + double FindLowest( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + int idx = FindLowestIndex( + mLength, + mMode); + if (idx <= -1) + { + return result; + } + + // + XOHCL iL; + result = iL.Init( + symbol, + period, + idx + // + ); + if (!result) + { + return result; + } + + // + result = iL.GetPrice(mMode); + + // + return result; + } + + // + // Retrieve Bullish Pressure ... + double GetBullishPressure( + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + symbol, + period, + Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + result += bars[i].GetLowShadow(); + } + + // + return result; + } + + // + // Retrieve Bearish Pressure ... + double GetBearishPressure( + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + symbol, + period, + Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + result += bars[i].GetHighShadow(); + } + + // + return result; + } + + // + bool HasBullishPressure( + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + double bullishPressure = GetBullishPressure(__loopback); + double bearishPressure = GetBearishPressure(__loopback); + + // + result = + // + bullishPressure > 0 && + bearishPressure >= 0 && + bullishPressure > bearishPressure + // + ; + + // + return result; + } + + // + bool HasBearishPressure( + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + double bullishPressure = GetBullishPressure(__loopback); + double bearishPressure = GetBearishPressure(__loopback); + + // + result = + // + bearishPressure > 0 && + bullishPressure >= 0 && + bearishPressure > bullishPressure + // + ; + + // + return result; + } + + // + // Retrieve Bullish Power ... + double GetBullishPower( + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + symbol, + period, + Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + // + if (bars[i].IsBullish()) + { + result += bars[i].GetBody(); + } + } + + // + return result; + } + + // + // Retrieve Bearish Pressure ... + double GetBearishPower( + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + symbol, + period, + Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + // + if (bars[i].IsBearish()) + { + result += bars[i].GetBody(); + } + } + + // + return result; + } + + // + bool HasBullishPower( + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + double bullishPressure = GetBullishPower(__loopback); + double bearishPressure = GetBearishPower(__loopback); + + // + result = + // + bullishPressure > 0 && + bearishPressure >= 0 && + bullishPressure > bearishPressure + // + ; + + // + return result; + } + + // + bool HasBearishPower( + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + double bullishPressure = GetBullishPower(__loopback); + double bearishPressure = GetBearishPower(__loopback); + + // + result = + // + bearishPressure > 0 && + bullishPressure >= 0 && + bearishPressure > bullishPressure + // + ; + + // + return result; + } + + // + // Decisions ... + + // + bool IsBullishDecision( + double percent = 70 // Percent of Body + ) + { + // + bool result = false; + + // + result = + // + IsValid() && + Index() > 0 && + IsBullish() && + (GetRange() * percent) / 100 <= GetBody() + // + ; + + // + return result; + } + + // + bool IsBearishDecision( + double percent = 70 // Percent of Body + ) + { + // + bool result = false; + + // + result = + // + IsValid() && + Index() > 0 && + IsBearish() && + (GetRange() * percent) / 100 <= GetBody() + // + ; + + // + return result; + } + + // + // Touches ... + + // + bool IsBullishTouched(double price) + { + // + bool result = false; + + // + result = + // + IsValid() + // + && + // + price > 0 + // + ; + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + result = + // + (pBar.low <= price || + pBar.GetDown() <= price) + // + && + // + (pBar.high > price || + pBar.GetUp() > price) + // + && + // + open > price && + low > price + // + ; + + // + return result; + } + + // + bool IsBearishTouched(double price) + { + // + bool result = false; + + // + result = + // + IsValid() + // + && + // + price > 0 + // + ; + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + result = + // + (pBar.high >= price || + pBar.GetUp() >= price) + // + && + // + (pBar.low < price || + pBar.GetDown() < price) + // + && + // + open < price && + high < price + // + ; + + // + return result; + } + + // + // Candlestic Patterns ... + + // + // Check Doji ... + bool IsDoji() + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + result = open == close; + + // + return result; + } + + // + // Check Hammer ... + bool IsHammer( + double _upShadowFactor = 0.1, + double _downShadowFactor = 0.6, + bool applyFib382Check = true, + bool applyPrevShadowCheck = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + if (_upShadowFactor < 0) + { + _upShadowFactor = 0.1; + } + + // + if (_downShadowFactor < 0) + { + _upShadowFactor = 0.6; + } + + // + double range = GetRange(); + + // + // Check Upper Shadow Must be 0 or Under 10% ... + double upShadow = GetHighShadow(); + result = upShadow < range * _upShadowFactor; + if (!result) + { + return result; + } + + // + // Check Down Shadow Must at least 60% ... + double downShadow = GetLowShadow(); + result = downShadow > range * _downShadowFactor; + if (!result) + { + return result; + } + + // + // Check Fib 382 ... + if (result && applyFib382Check) + { + // + double fib382 = GetFibonacciLevel( + high, + low, + 0.382, + -1 // + ); + result = GetDown() > fib382; + } + + // + // Check Shadow Based on Prev Bar ... + if (result && applyPrevShadowCheck) + { + // + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + result = low < pBar.low; + } + + // + return result; + } + + // + // Check Sgooting Star ... + // Reversal Hammer ... + bool IsShootingStar( + double _upShadowFactor = 0.6, + double _downShadowFactor = 0.1, + bool applyFib382Check = true, + bool applyPrevShadowCheck = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + if (_upShadowFactor < 0) + { + _upShadowFactor = 0.6; + } + + // + if (_downShadowFactor < 0) + { + _upShadowFactor = 0.1; + } + + // + double range = GetRange(); + + // + // Check Upper Shadow Must be 0 or Under 10% ... + double upShadow = GetHighShadow(); + result = upShadow > range * _upShadowFactor; + if (!result) + { + return result; + } + + // + // Check Down Shadow Must at least 60% ... + double downShadow = GetLowShadow(); + result = downShadow < range * _downShadowFactor; + if (!result) + { + return result; + } + + // + // Check Fib 382 ... + if (result && applyFib382Check) + { + // + double fib382 = GetFibonacciLevel( + high, + low, + 0.382, + 1 // + ); + result = GetUp() < fib382; + } + + // + // Check Shadow Based on Prev Bar ... + if (result && applyPrevShadowCheck) + { + // + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + result = high > pBar.high; + } + + // + return result; + } + + // + // Check Bullish Engulfing ... + bool IsBullishEngulfing( + double _engulfBarBodyFactor = 0.7 // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + if (_engulfBarBodyFactor < 0) + { + _engulfBarBodyFactor = 0.7; + } + + // + // Check Bar Is Bullish ... + result = IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + double range = GetRange(); + double body = GetBody(); + + // + // Check Prev Bar Must Bearish ... + result = pBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Check Shadows Engulf Prev Bar ... + result = + // + high > pBar.high && + low <= pBar.low + // + ; + if (!result) + { + return result; + } + + // + // Check Engulfed Bar Must Inside Engulfer Body ... + result = + // + GetUp() > pBar.GetUp() && + GetDown() < pBar.GetDown() + // + ; + if (!result) + { + return result; + } + + // + // Check Body of Engulfing Bar ... + if (result && _engulfBarBodyFactor > 0) + { + result = body >= range * _engulfBarBodyFactor; + } + + // + return result; + } + + // + // Check Bearish Engulfing ... + bool IsBearishEngulfing( + double _engulfBarBodyFactor = 0.7 // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + if (_engulfBarBodyFactor < 0) + { + _engulfBarBodyFactor = 0.7; + } + + // + // Check Bar Is Bearish ... + result = IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + double range = GetRange(); + double body = GetBody(); + + // + // Check Prev Bar Must Bullish ... + result = pBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Check Shadows Engulf Prev Bar ... + result = high >= pBar.high && low < pBar.low; + if (!result) + { + return result; + } + + // + // Check Engulfed Bar Must Inside Engulfer Body ... + result = + // + GetUp() > pBar.GetUp() && + GetDown() < pBar.GetDown() + // + ; + if (!result) + { + return result; + } + + // + // Check Body of Engulfing Bar ... + if (result && _engulfBarBodyFactor > 0) + { + result = body >= range * _engulfBarBodyFactor; + } + + // + return result; + } + + // + // Check Morning Star Pattern ... + bool IsMorningStar( + double _middleRangeFactor = 0.3, + double _startBodyFactor = 0.6, + bool forceCheckMiddleBarDirection = true, + bool forceCheckStartBody = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + if (_middleRangeFactor < 0) + { + _middleRangeFactor = 0.3; + } + + // + if (_startBodyFactor < 0) + { + _startBodyFactor = 0.6; + } + + // + // Current Bar Must be Bullish ... + result = IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar must be Bearish ... + if (result && forceCheckMiddleBarDirection) + { + // + result = pBar.IsBearish(); + if (!result) + { + return result; + } + } + + // + // Retrieve Previous Bar of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev Of Prev Bar Must be Bearish ... + result = ppBar.IsBearish(); + if (!result) + { + return result; + } + + // + double range = GetRange(); + double pRange = pBar.GetRange(); + double ppRange = ppBar.GetRange(); + + // + // Middle Bar must be Smaller than Ratio of other ... + result = + // + pRange < range * _middleRangeFactor && + pRange < ppRange * _middleRangeFactor + // + ; + if (!result) + { + return result; + } + + // + if (result && forceCheckStartBody) + { + // + result = ppBar.GetBody() > ppRange * _startBodyFactor; + if (!result) + { + return result; + } + } + + // + return result; + } + + // + // Check Evening Star Pattern ... + bool IsEveningStar( + double _middleRangeFactor = 0.3, + double _startBodyFactor = 0.6, + bool forceCheckMiddleBarDirection = true, + bool forceCheckStartBody = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + if (_middleRangeFactor < 0) + { + _middleRangeFactor = 0.3; + } + + // + if (_startBodyFactor < 0) + { + _startBodyFactor = 0.6; + } + + // + // Current Bar Must be Bearish ... + result = IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar must be Bullish ... + if (result && forceCheckMiddleBarDirection) + { + // + result = pBar.IsBullish(); + if (!result) + { + return result; + } + } + + // + // Retrieve Previous Bar of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev Of Prev Bar Must be Bullish ... + result = ppBar.IsBullish(); + if (!result) + { + return result; + } + + // + double range = GetRange(); + double pRange = pBar.GetRange(); + double ppRange = ppBar.GetRange(); + + // + // Middle Bar must be Smaller than Ratio of other ... + result = + // + pRange < range * _middleRangeFactor && + pRange < ppRange * _middleRangeFactor + // + ; + if (!result) + { + return result; + } + + // + if (result && forceCheckStartBody) + { + // + result = ppBar.GetBody() > ppRange * _startBodyFactor; + if (!result) + { + return result; + } + } + + // + return result; + } + + // + // Bullish Marubozu ... + bool IsBullishMarubozu() + { + // + bool result = false; + + // + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + result = IsBullish(); + if (!result) + { + return result; + } + + // + result = + // + GetUp() == high && + GetDown() == low + // + ; + + // + return result; + } + + // + // Bearish Marubozu ... + bool IsBearishMarubozu() + { + // + bool result = false; + + // + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + result = IsBearish(); + if (!result) + { + return result; + } + + // + result = + // + GetUp() == high && + GetDown() == low + // + ; + + // + return result; + } + + // + // Contextual Patterns ... + + // + // Check Swing High ... + bool IsSwingHigh() + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bearish ... + result = IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bullish ... + result = pBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bullish ... + result = ppBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Check All Highs ... + result = + // + high < pBar.high && + pBar.high > ppBar.high + // + ; + + // + return result; + } + + // + // Find Simple 3 Candle Based Swing High ... + bool IsSimpleSwingHigh(double thresholdInPoint = 1) + { + // + bool result = false; + + // + int index = Index(); + result = index > 0; + if (!result) + { + return result; + } + + // + XOHCL nextBar; + result = GetNextBar(nextBar); + if (!result) + { + return result; + } + + // + XOHCL prevBar; + result = GetPreviousBar(prevBar); + if (!result) + { + return result; + } + + // + double point = GetPoints(symbol); + double requiredOffset = point * thresholdInPoint; + + // + result = + high > nextBar.high && + high > prevBar.high && + (thresholdInPoint <= 0 + ? true + : MathAbs( + MathMax( + nextBar.high, + prevBar.high) - + high) >= requiredOffset); + + // + return result; + } + + // + // Find Last Swing High ... + bool FindLastSwingHigh(XOHCL &swing) + { + // + bool result = false; + + // + swing.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = iBars( + symbol, + period // + ); + int maxAllowed = MathMin(100, (totalBars / 100)); + + // + int idx = Index(); + for (int i = idx; i <= idx + maxAllowed; i++) + { + // + swing.Clean(); + result = swing.Init( + symbol, + period, + i // + ); + if (!result) + { + // + swing.Clean(); + break; + } + + // + result = swing.IsSwingHigh(); + if (result) + { + break; + } + } + + // + return result; + } + + // + // Check Swing Low ... + bool IsSwingLow() + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bullish ... + result = IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bearish ... + result = pBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bearish ... + result = ppBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Check All Lows ... + result = + // + low > pBar.low && + pBar.low < ppBar.low + // + ; + + // + return result; + } + + // + // Find Simple 3 Candle Based Swing Low ... + bool IsSimpleSwingLow(double thresholdInPoint = 1) + { + // + bool result = false; + + // + int index = Index(); + result = index > 0; + if (!result) + { + return result; + } + + // + XOHCL nextBar; + result = GetNextBar(nextBar); + if (!result) + { + return result; + } + + // + XOHCL prevBar; + result = GetPreviousBar(prevBar); + if (!result) + { + return result; + } + + // + double point = GetPoints(symbol); + double requiredOffset = point * thresholdInPoint; + + // + result = + low < nextBar.low && + low < prevBar.low && + (thresholdInPoint <= 0 + ? true + : MathAbs( + MathMax( + nextBar.low, + prevBar.low) - + low) >= requiredOffset); + + // + return result; + } + + // + // Find Last Swing Low ... + bool FindLastSwingLow(XOHCL &swing) + { + // + bool result = false; + + // + swing.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = iBars( + symbol, + period // + ); + int maxAllowed = MathMin(100, (totalBars / 100)); + + // + int idx = Index(); + for (int i = idx; i <= idx + maxAllowed; i++) + { + // + swing.Clean(); + result = swing.Init( + symbol, + period, + i // + ); + if (!result) + { + // + swing.Clean(); + break; + } + + // + result = swing.IsSwingLow(); + if (result) + { + break; + } + } + + // + return result; + } + + // + // Check Bullish FVG ... + bool HasBullishFVG( + double &upper, + double &lower, + datetime &start, + datetime &end, + bool forceMiddleBarCheck = true, + bool forceCheckLastBarDirection = false // + ) + { + // + bool result = false; + + // + upper = 0; + lower = 0; + + // + end = NULL; + start = NULL; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bullish ... + result = + !forceCheckLastBarDirection + ? true + : IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bullish ... + result = pBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bullish ... + result = ppBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Other Conditions ... + result = + // + low > ppBar.high + // + ; + + // + // Check Middle Bar Range ... + if (result && forceMiddleBarCheck) + { + // + result = + // + pBar.high > low && + pBar.low < ppBar.high + // + ; + + // + if (!result) + { + return result; + } + } + + // + if (result) + { + // + end = time; + upper = low; + lower = ppBar.high; + start = ppBar.time; + } + + // + return result; + } + + // + // Check Bearish FVG ... + bool HasBearishFVG( + double &upper, + double &lower, + datetime &start, + datetime &end, + bool forceMiddleBarCheck = true, + bool forceCheckLastBarDirection = false // + ) + { + // + bool result = false; + + // + upper = 0; + lower = 0; + + // + end = NULL; + start = NULL; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bearish ... + result = + !forceCheckLastBarDirection + ? true + : IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bearish ... + result = pBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bearish ... + result = ppBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Other Conditions ... + result = + // + high < ppBar.low + // + ; + + // + // Check Middle Bar Range ... + if (result && forceMiddleBarCheck) + { + // + result = + // + pBar.high > low && + pBar.low < ppBar.high + // + ; + + // + if (!result) + { + return result; + } + } + + // + if (result) + { + // + end = time; + lower = high; + upper = ppBar.low; + start = ppBar.time; + } + + // + return result; + } + + // + // Find Support ... + bool HasSupport( + XOHCL &bar, + ENUM_X_PRICE type = X_PRICE_CLOSE, + int _loopback = 21, + int tries = 100 // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (_loopback < 0) + { + _loopback = 21; + } + + // + if (tries < 0) + { + tries = 100; + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + double price = GetPrice(type); + + // + for (int i = 1; i < tries; i++) + { + // + int _length = _loopback * i; + + // + int lowestIDX = FindLowestIndex( + _length, + MODE_LOW // + ); + result = IsValidSize(lowestIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + symbol, + period, + lowestIDX // + ); + if (!result) + { + break; + } + + // + result = + // + price > iLBar.high + // + ; + if (result) + { + // + bar = iLBar; + break; + } + } + + // + return result; + } + + // + // Find Resistance ... + bool HasResistance( + XOHCL &bar, + ENUM_X_PRICE type = X_PRICE_CLOSE, + int _loopback = 21, + int tries = 100 // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (_loopback < 0) + { + _loopback = 21; + } + + // + if (tries < 0) + { + tries = 100; + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + double price = GetPrice(type); + + // + for (int i = 1; i < tries; i++) + { + // + int _length = _loopback * i; + + // + int highestIDX = FindHighestIndex( + _length, + MODE_LOW // + ); + result = IsValidSize(highestIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + symbol, + period, + highestIDX // + ); + if (!result) + { + break; + } + + // + result = + // + price < iHBar.high + // + ; + if (result) + { + // + bar = iHBar; + break; + } + } + + // + return result; + } + + // + // Trend Detection ... + + // + // Find Bullish Trend ... + bool HasBullishTrend( + XOHCL &highSwingBars[], + XOHCL &lowSwingBars[], + bool forceMethod2 = false, + int _loopback = 3, + int tries = 3, + ENUM_X_PRICE type = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + Clean(lowSwingBars); + Clean(highSwingBars); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + double price = GetPrice(type); + + // + int lastIDX = Index(); + double lastH = 0; + double lastL = 0; + for (int i = 1; i < tries + 1; i++) + { + // + // Use Regular Method ... + if (!forceMethod2) + { + // + int iHIDX = FindSwing( + symbol, + period, + X_SWING_HIGH, + _loopback, + lastIDX // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + symbol, + period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH < lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = FindSwing( + symbol, + period, + X_SWING_LOW, + _loopback, + lastIDX // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + symbol, + period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL < lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + // + // Use Other MEthod ... + else + { + // + int _length = i * _loopback; + int start = + // + i == 1 + ? 1 + : _length - _loopback + // + ; + + // + int iHIDX = iHighest( + symbol, + period, + MODE_HIGH, + _loopback, + start // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + symbol, + period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH < lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = iLowest( + symbol, + period, + MODE_LOW, + _loopback, + start // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + symbol, + period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL < lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + } + + // + if (result) + { + // + result = + // + ArraySize(lowSwingBars) == tries && + ArraySize(highSwingBars) == tries + // + ; + } + + // + if (!result) + { + // + Clean(lowSwingBars); + Clean(highSwingBars); + } + + // + return result; + } + + // + // Find Bearish Trend ... + bool HasBearishTrend( + XOHCL &highSwingBars[], + XOHCL &lowSwingBars[], + bool forceMethod2 = false, + int _loopback = 3, + int tries = 3, + ENUM_X_PRICE type = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + Clean(lowSwingBars); + Clean(highSwingBars); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + double price = GetPrice(type); + + // + int lastIDX = Index(); + double lastH = 0; + double lastL = 0; + for (int i = 1; i < tries + 1; i++) + { + // + // Use Regular Method ... + if (!forceMethod2) + { + // + int iHIDX = FindSwing( + symbol, + period, + X_SWING_HIGH, + _loopback, + lastIDX // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + symbol, + period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH > lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = FindSwing( + symbol, + period, + X_SWING_LOW, + _loopback, + lastIDX // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + symbol, + period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL > lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + // + // Use Other MEthod ... + else + { + // + int _length = i * _loopback; + int start = + // + i == 1 + ? 1 + : _length - _loopback + // + ; + + // + int iHIDX = iHighest( + symbol, + period, + MODE_HIGH, + _loopback, + start // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + symbol, + period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH > lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = iLowest( + symbol, + period, + MODE_LOW, + _loopback, + start // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + symbol, + period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL > lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + } + + // + if (result) + { + // + result = + // + ArraySize(lowSwingBars) == tries && + ArraySize(highSwingBars) == tries + // + ; + } + + // + if (!result) + { + // + Clean(lowSwingBars); + Clean(highSwingBars); + } + + // + return result; + } + + // + // Order Blocks ... + + // + // Find Bullish Order Block ... + bool HasBullishOrderBlock( + XOHCL &orderBlock, + int _minimumSameBars = 4 // + ) + { + // + bool result = false; + + // + orderBlock.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + if (_minimumSameBars < 0) + { + _minimumSameBars = 4; + } + + // + XOHCL cBar; + int founded = 0; + int cIDX = Index(); + bool isEnough = false; + while (!isEnough) + { + // + result = cBar.Init( + symbol, + period, + cIDX // + ); + if (!result) + { + break; + } + + // + result = cBar.IsBullish(); + if (!result && cBar.IsBearish()) + { + break; + } + + // + cIDX++; + founded++; + } + + // + // Here we have to check founded and if it's fill + // our requirements ... + // cIDX is Order Block Index ... + result = + // + cBar.IsValid() && + high > cBar.high && + founded >= _minimumSameBars + // + ; + if (!result) + { + return result; + } + + // + result = orderBlock.Init( + symbol, + period, + cIDX // + ); + if (!result) + { + // + orderBlock.Clean(); + return result; + } + + // + return result; + } + + // + // Find Bearish Order Block ... + bool HasBearishOrderBlock( + XOHCL &orderBlock, + int _minimumSameBars = 4 // + ) + { + // + bool result = false; + + // + orderBlock.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + if (_minimumSameBars < 0) + { + _minimumSameBars = 4; + } + + // + XOHCL cBar; + int founded = 0; + int cIDX = Index(); + bool isEnough = false; + while (!isEnough) + { + // + bool isInited = cBar.Init( + symbol, + period, + cIDX // + ); + + // + result = cBar.IsBearish(); + if (!result && cBar.IsBullish()) + { + break; + } + + // + cIDX++; + founded++; + } + + // + // Here we have to check founded and if it's fill + // our requirements ... + // cIDX is Order Block Index ... + result = + // + cBar.IsValid() && + high < cBar.low && + founded >= _minimumSameBars + // + ; + if (!result) + { + return result; + } + + // + result = orderBlock.Init( + symbol, + period, + cIDX // + ); + if (!result) + { + // + orderBlock.Clean(); + return result; + } + + // + return result; + } + + // + // Order Blocks ... + + // + // Supply and Demand ... + + // + // Other ... + string GetTag(string prefix = "") + { + // + string result = NULL; + + // + result = + (IsValid(prefix) + ? prefix + "_" + : "") + + "XOHCL_" + symbol + "_" + ToString(period) + "_" + ToFormatString(time); + + // + return result; + } + + // + // Convert to String Representation ... + string ToString() + { + // + string result = ""; + + // + result = GetTypeName(this) + + "(O(" + ToString(open) + "),H(" + ToString(high) + "),C(" + ToString(close) + "),L(" + ToString(low) + "))"; + + // + return result; + } +}; + +// +struct XTrend +{ + // + string symbol; + ENUM_TIMEFRAMES period; + + // + datetime at; + + // + XOHCL swingHighs[]; + XOHCL swingLows[]; + + // + bool isBullish; + bool isBearish; + + // + void XTrend() + { + Clean(); + } + + // + // Tools ... + + /** + * Initialize ... + * + * @param _symbol: String ... + * @param _period: ENUM_TIMEFRAMES member ... + * + * @return ( bool ) + */ + bool Init( + string _symbol, + ENUM_TIMEFRAMES _period = NULL // + ) + { + // + bool result = false; + + // + NormalizePeriod(_period); + + // + result = IsValid(_symbol) && + IsValid(_period); + if (!result) + { + return result; + } + + // + symbol = _symbol; + period = _period; + + // + XOHCL bar; + result = bar.Init( + symbol, + period, + 0 // + ); + if (!result) + { + return result; + } + + // + XOHCL tmpBULLSWH[]; + XOHCL tmpBULLSWL[]; + bool hasBullishTrend = bar.HasBullishTrend( + tmpBULLSWH, + tmpBULLSWL, + true // + ); + + // + XOHCL tmpBEARSWH[]; + XOHCL tmpBEARSWL[]; + bool hasBearishTrend = bar.HasBearishTrend( + tmpBEARSWH, + tmpBEARSWL, + true // + ); + + // + if (hasBullishTrend) + { + // + Copy( + tmpBULLSWH, + swingHighs // + ); + + // + Copy( + tmpBULLSWL, + swingLows // + ); + } + // + else if (hasBearishTrend) + { + // + Copy( + tmpBEARSWH, + swingHighs // + ); + + // + Copy( + tmpBEARSWL, + swingLows // + ); + } + + // + if (hasBullishTrend || + hasBullishTrend) + { + at = TimeCurrent(); + } + + // + result = IsValid(); + + // + return result; + } + + /** + * Clean ... + */ + void Clean() + { + // + symbol = NULL; + period = NULL; + at = NULL; + + // + isBullish = false; + isBearish = false; + + // + Clean(swingLows); + Clean(swingHighs); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + IsValid(symbol) && + IsValid(period) && + IsValid(at) && + (isBullish || + isBearish) && + (ArraySize(swingHighs) > 0 || + ArraySize(swingLows) > 0); + + // + return result; + } + + /** + * Generate Unique Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + string hash = symbol + "," + ToString(period) + "," + ToFormatString(at); + hash = ToMD5(hash); + + // + result = + // + "XTrend_" + + (isBullish ? "Bullish_" : "Bearish_") + + symbol + "_" + + ToString(period) + "_" + + hash + // + ; + + // + return result; + } + + // +}; + +// +// Tracking Times ... +struct XTimeTracker +{ + // + // Props ... + int xMonth; + int xDayOfWeek; + int xForWeekDay; + int xDay; + int xHour; + int xMinute; + + // + // Constructor ... + XTimeTracker() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + xDay = -1; + xHour = -1; + xMonth = -1; + xMinute = -1; + xDayOfWeek = -1; + xForWeekDay = -1; + } + + // + // Detecting New Minute ... + bool IsNewMinute() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.min != xMinute; + if (result) + { + xMinute = timeStruct.min; + } + + // + return result; + } + + // + // Detecting New Houre ... + bool IsNewHour() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.hour != xHour; + if (result) + { + xHour = timeStruct.hour; + } + + // + return result; + } + + // + // Detecting New Day ... + bool IsNewDay() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.day_of_year != xDay; + if (result) + { + xDay = timeStruct.day_of_year; + } + + // + return result; + } + + // + // Detecting New Week ... + bool IsNewWeek() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Week ... + // Since Week Starts From Monday in Forex World ... + // we Calculate Start of Week by 1-Monday ... + result = + xDayOfWeek == -1 && + xForWeekDay == -1 + ? true + : timeStruct.day_of_week == 1 && + timeStruct.day_of_year > xForWeekDay; + + // + xForWeekDay = timeStruct.day_of_year; + xDayOfWeek = timeStruct.day_of_week; + + // + return result; + } + + // + // Detecting End Of Week ... + bool IsWeekEnd() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check WeekEnd ... + // Since Week Starts From Monday in Forex World ... + // we Calculate End of Week by 5-Friday ... + result = + xDayOfWeek != -1 && + timeStruct.day_of_week == 5 && + timeStruct.hour == 23 && + timeStruct.min == 59 && + timeStruct.sec == 59; + + // + return result; + } + + // + // Detecting New Month ... + bool IsNewMonth() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.mon != xMonth; + if (result) + { + xMonth = timeStruct.mon; + } + + // + return result; + } +}; + +// +// Tracking Bars on Specified Environment ... +struct XBarTracker +{ + // + string symbol; // Tracking Symbol + ENUM_TIMEFRAMES period; // Tracking Time Frame + + // + int lastTrackedBar; // Last Tracked Bar ... + + // + bool waitsUntilNext; // Waits Until Next Bar ... + + // + // Constructor ... + XBarTracker() + { + Clean(); + } + + // + // Initializer ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL // Trading Period + ) + { + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + this.symbol = mSymbol; + this.period = mPeriod; + + // + this.lastTrackedBar = 0; + + // + result = true; + + // + return result; + } + + // + // Retrieve all Bars ... + int CountBars() + { + // + return iBars( + symbol, + period + // + ); + } + + // + // Check if it's New Bar ... + bool IsNewBar() + { + // + bool result = false; + + // + int currentBars = CountBars(); + + // + result = currentBars > lastTrackedBar; + if (result) + { + lastTrackedBar = currentBars; + } + + // + return result; + } + + // + bool CanProcessBar() + { + // + bool _isInTestMode = IsRunningOnTestMode(); + + // + bool isNewBar = IsNewBar(); + + // + bool result = + _isInTestMode + ? isNewBar + : !waitsUntilNext + ? true + : isNewBar; + if (result && waitsUntilNext) + { + waitsUntilNext = false; + } + + // + return result; + } + + // + void Waits() + { + this.waitsUntilNext = true; + } + + // + // Tools ... + void Clean() + { + // + symbol = NormalizeSymbol(NULL); + period = NormalizePeriod(NULL); + } + + // + bool GetBar( + XOHCL &bar, + int index = 0 // + ) + { + // + bool result = false; + + // + result = bar.Init( + symbol, + period, + index // + ); + + // + return result; + } + + // + bool GetBar( + XOHCL &bar, + datetime time = NULL // + ) + { + // + bool result = false; + + // + NormalizeTime(time); + + // + int barIndex = iBarShift( + symbol, + period, + time, + false // + ); + + // + result = barIndex >= 0; + if (!result) + { + return result; + } + + // + result = bar.Init( + symbol, + period, + barIndex // + ); + + // + return result; + } + + // + int Index(datetime time = NULL) + { + // + int result = 0; + + // + NormalizeTime(time); + + // + result = iBarShift( + symbol, + period, + time, + false // + ); + + // + return result; + } +}; + +// +// Model a Market Cycle ... +struct XMarketCycle +{ + // + // Props ... + + // + string prefix; // Prefix Trag ... + + // + string symbol; // Market Symbol ... + + // + ENUM_TIMEFRAMES period; // Period of Cycle ... + ENUM_X_PERIOD_METHOD method; // Period Selection Method ... + ENUM_X_MARKET_CYCLES cycle; // Cycles of MArket ... + + // + int length; // Number Of Candles per Current Time Frame ... + ENUM_TIMEFRAMES hostPeriod; // Current Time Frame ... + + // + datetime lastStart; // Last Candle Bar Time ... + + // + XBarTracker barTracker; // Bar Tracker ... + XBarRemainsTime remains; // Current Bar Remains Model ... + + // + // Constructor ... + XMarketCycle() + { + Clean(); + } + + // + // Init Cycle ... + bool Init( + string mSymbol, // Trading Symbol + ENUM_TIMEFRAMES mHostPeriod, // Host Period + ENUM_X_MARKET_CYCLES mCycle, // Init Cycle + string mPrefix = "" // Prefix + ) + { + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + mHostPeriod = NormalizePeriod(mHostPeriod); + + // + result = IsValid(mCycle); + if (!result) + { + return result; + } + + // + this.cycle = mCycle; + + // + // Set Automatically Prefix ... + if (StringLen(mPrefix) == 0) + { + this.prefix = ToString(cycle); + } + + // + result = IsValid( + method, + period // + ); + if (!result) + { + return result; + } + + // + this.symbol = mSymbol; + this.hostPeriod = mHostPeriod; + + // + // Find Cycle Period ... + if (method == X_PERIOD_AUTO) + { + // + // Select Period ... + this.period = GetCyclePeriod( + this.cycle, + this.hostPeriod); + } + + // + // Set Prefix if Provided ... + if (StringLen(mPrefix) > 0) + { + this.prefix = mPrefix; + } + + // + // Calculate Required Info ... + + // + // Length ... + this.length = PeriodSeconds(this.period) / PeriodSeconds(this.hostPeriod); + + // + // Update Additional Data ... + result = this.Update(0); + + // + return result; + } + + // + bool Init( + string mSymbol, // Trading Symbol + ENUM_TIMEFRAMES mHostPeriod, // Host Period + ENUM_X_MARKET_CYCLES mCycle, // Init Cycle + ENUM_X_PERIOD_METHOD mMethod, // Period Selection Method + ENUM_TIMEFRAMES mPeriod, // Provided Period + string mPrefix = "" // Prefix + ) + { + // + this.period = mPeriod; + this.method = mMethod; + + // + return Init( + mSymbol, + mHostPeriod, + mCycle, + mPrefix + // + ); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + length = 0; + lastStart = 0; + + // + cycle = NULL; + prefix = NULL; + symbol = NULL; + period = NULL; + method = NULL; + hostPeriod = NULL; + + // + remains.Clean(); + barTracker.Clean(); + } + + // + // Check Structure Valid ... + bool IsValid() + { + // + bool result = false; + + // + result = IsValid( + method, + period); + if (!result) + { + return result; + } + + // + result = + // + length > 0 && + symbol != NULL && + period != NULL && + method != NULL && + hostPeriod != NULL && + method != X_PERIOD_NOTHING + // + ; + + // + return result; + } + + // + // Update Market Cycle Additional Info ... + bool Update(int hostBarIndex) + { + // + bool result = false; + + // + result = this.IsValid(); + if (!result) + { + return result; + } + + // + // Init Remains ... + result = remains.Init( + this.symbol, + this.period); + if (!result) + { + return result; + } + + // + // Init Bar Tracker ... + result = barTracker.Init( + this.symbol, + this.period); + if (!result) + { + return result; + } + + // + return result; + } + + // + // Count Bars ... + int CountBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = barTracker.CountBars(); + + // + return result; + } + + // + // Check New Bar ... + bool IsNewBar() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = barTracker.IsNewBar(); + + // + return result; + } + + // + // Retrieve Current Bar Index based on Host Period bar Index ... + int GetBarIndex(int barIndex) + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + if (barIndex < 0) + { + return result; + } + + // + int totalBars = CountBars(); + if (barIndex >= totalBars) + { + // + result = totalBars - 1; + return result; + } + + // + datetime hostBarTime = iTime( + this.symbol, + this.hostPeriod, + barIndex + // + ); + + // + result = iBarShift( + this.symbol, + this.period, + hostBarTime + // + ); + + // + return result; + } + + // + // Retrieve Current Cycles Specific Bar ... + XOHCL GetBar(int barIndex) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int totalBars = CountBars(); + if (barIndex >= totalBars) + { + barIndex = totalBars - 1; + } + + // + XOHCL result; + result.Init( + this.symbol, + this.period, + barIndex + // + ); + + // + return result; + } + + // + // Extract Specific Range of Bars ... + // using Start Bar Index ... + int GetBars( + XOHCL &result[], // Hold Result + int from = 0, // Start Bar Index + int count = 1, // Number of Bars + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + if (from < 0) + { + from = 0; + } + + // + int total = Bars( + symbol, + period); + if (from > total - 2) + { + from = total - 2; + } + + // + if (count < 0) + { + count = 1; + } + + // + int start = from; + int end = start + count; + if (end > total - 1) + { + end = total - 1; + } + + // + if (forceClean) + { + Clean(result); + } + + // + int beforeSize = ArraySize(result); + + // + for (int i = start; i < end; i++) + { + // + XOHCL iBar; + bool isValid = iBar.Init( + symbol, + period, + i + // + ); + + // + if (isValid) + { + // + AddRef( + iBar, + result + // + ); + } + } + + // + int afterSize = ArraySize(result); + + // + mResult = afterSize - beforeSize; + + // + return mResult; + } + + // + // Extract Specific Range of Bars ... + // using Start Bar Time ... + int GetBars( + XOHCL &result[], // Hold Result + datetime from = NULL, // Start Bar Time + int count = 1, // Number of Bars + bool forceClean = true // Clean Result Array + ) + { + // + from = NormalizeTime(from); + + // + int barIndex = iBarShift( + symbol, + period, + from, + false + // + ); + + // + return GetBars( + result, + symbol, + period, + barIndex, + count, + forceClean + // + ); + } + + // + // Retrieve Bar Time ... + datetime GetBarTime(int barIndex) + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int totalBars = CountBars(); + if (barIndex >= totalBars) + { + barIndex = totalBars - 1; + } + + // + result = iTime( + this.symbol, + this.period, + barIndex + // + ); + + // + return result; + } + + // + // Find Chart ID ... + ulong GetChartID() + { + // + ulong result = 0; + + // + long firstChart = ChartFirst(); + result = firstChart; + + // + while (result >= 0) + { + // + string chSymbol = ChartSymbol(result); + ENUM_TIMEFRAMES chPeriod = ChartPeriod(result); + + // + bool isOwnChart = + // + symbol == chSymbol && + period == chPeriod + // + ; + if (isOwnChart) + { + break; + } + + // + result = ChartNext(result); + if (result < 0) + { + break; + } + } + + // + return result; + } + + // + // Create and String Representation for Unique Taging ... + string ToString() + { + // + string result = ""; + + // + if (!IsValid()) + { + return result; + } + + // + result = + GetTypeName(this) + "(" + + "PRFX(" + this.prefix + ")" + + "SMBL(" + this.symbol + ")" + + "CYC(" + ToString(this.cycle) + ")" + + "PRD(" + ToString(this.period) + ")" + + "PRDHST(" + ToString(this.hostPeriod) + ")" + + "MTH(" + EnumToString(this.method) + ")" + + ")"; + + // + return result; + } + + // + // Here we Produce a Summary brief of + // state of Cycle ... + string GenerateSummary() + { + // + string result = ""; + + // + bool hasPrefix = + StringLen(this.prefix) > 0 && + this.prefix != ToString(this.cycle); + result += (hasPrefix ? this.prefix + "[" : "") + + ToString(this.cycle) + + (hasPrefix ? "]" : "") + "\n"; + + // + result += " - PR: " + ToString(this.period) + "\n"; + + // + XOHCL cBar = GetBar(0); + + // + result += " - State: " + (cBar.IsBullish() ? "Bullish" : cBar.IsBearish() ? "Bearish" + : "Neutural"); + + // + return result; + } +}; + +// +// Linear Regression ... + +// +struct XLinearRegressionWorkStruct +{ + // + struct sDataStruct + { + // + double value; + double sumY; + double sumXY; + }; + + // + sDataStruct data[]; + + // + int dataSize; + int period; + double sumX; + double sumXX; + double divisor; + + // + // Constructor ... + XLinearRegressionWorkStruct() + : dataSize(-1), period(-1) + { + } +}; + +// +struct XLinearRegression +{ + // + XLinearRegressionWorkStruct m_work; + + // + // Calculate Linear Regression ... + double Calculate( + double value, + int period, + double &_slope, + double &_intercept, + int r, + int bars // + ) + { + // + if (m_work.dataSize <= bars) + { + m_work.dataSize = ArrayResize(m_work.data, bars + 500, 2000); + } + + // + if (period < 1) + { + period = 1; + } + + // + if (m_work.period != (int)period) + { + // + m_work.period = (int)period; + m_work.sumX = m_work.period * (m_work.period - 1.0) / 2.0; + m_work.sumXX = m_work.period * (m_work.period - 1.0) * (2.0 * m_work.period - 1.0) / 6.0; + m_work.divisor = m_work.sumX * m_work.sumX - m_work.period * m_work.sumXX; + + // + if (m_work.divisor) + { + m_work.divisor = 1.0 / m_work.divisor; + } + } + + // + m_work.data[r].value = value; + + // + if (r >= m_work.period) + { + // + m_work.data[r].sumY = m_work.data[r - 1].sumY + value - m_work.data[r - m_work.period].value; + m_work.data[r].sumXY = m_work.data[r - 1].sumXY + m_work.data[r].sumY - m_work.data[r - m_work.period].value * (m_work.period - 1.0) - value; + } + else + { + // + m_work.data[r].sumY = value; + m_work.data[r].sumXY = 0; + + // + for (int _k = 1; _k < m_work.period && r >= _k; _k++) + { + // + m_work.data[r].sumY += m_work.data[r - _k].value; + m_work.data[r].sumXY += _k * m_work.data[r - _k].value; + } + } + + // + _slope = (m_work.period * m_work.data[r].sumXY - m_work.sumX * m_work.data[r].sumY) * m_work.divisor; + _intercept = (m_work.data[r].sumY - _slope * m_work.sumX) / (double)m_work.period; + + // + double result = (_intercept + _slope * (m_work.period - 1.0)); + + // + return result; + } + + // +}; + +// +// Use To Parse Symbols for +// Ignore Brokers Additional Suffixes ... +struct XSymbolParser +{ + // + string version; // Temp ... + + // + // Symbol Parsing ... + + // + // Forext ... + + // + bool IsEURUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsUSDJPY(string symbol) + { + // + string symbolIdentifiers[] = { + "USD", + "JPY" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURJPY(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "JPY" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsUSDCHF(string symbol) + { + // + string symbolIdentifiers[] = { + "USD", + "CHF" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURCHF(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "CHF" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsGBPUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "GBP", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURGBP(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "GBP" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsAUDUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "AUD", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURAUD(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "AUD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsUSDCAD(string symbol) + { + // + string symbolIdentifiers[] = { + "USD", + "CAD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURCAD(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "CAD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsNZDUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "NZD", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURNZD(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "NZD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + // Metals ... + + // + bool IsXAUUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "XAU", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsXAGUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "XAG", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + // Indexes ... + + // + bool IsDowJones(string symbol) + { + // + bool result = Contains( + "DowJones30", + symbol // + ); + + // + return result; + } + + // + // Oil ... + + // + bool IsBrent(string symbol) + { + // + bool result = Contains( + "BRENT", + symbol // + ); + + // + return result; + } + + // + // Symbol Finder ... + string GetEURUSDSymbol() + { + // + string result = NULL; + + // + string symbols[]; + int symbolsCount = GetAllSymbols( + symbols // + ); + if (!IsValidSize(symbolsCount)) + { + return result; + } + + // + for (int i = 0; i < symbolsCount; i++) + { + // + string iSymbol = symbols[i]; + if (IsEURUSD(iSymbol)) + { + // + result = iSymbol; + break; + } + } + + // + return result; + } +}; + +// +struct XSymbolSessionParser +{ + // + string version; // Temp ... + + // + // Check Market Is Open for Specific Symbol + // in Current Time ... + bool CanTrade( + string symbol // Trading Symbol + ) + { + // + bool result = false; + + // + result = IsValid(symbol); + if (!result) + { + return result; + } + + // + MqlDateTime timeStruct; + result = TimeCurrent(timeStruct); + if (!result) + { + return result; + } + + // + ENUM_DAY_OF_WEEK dayOfWeek = (ENUM_DAY_OF_WEEK)timeStruct.day_of_week; + + // + datetime cTime = TimeCurrent(); + + // + datetime from; + datetime to; + result = SymbolInfoSessionTrade( + symbol, + dayOfWeek, + 0, // Session Index ... + from, + to // + ); + if (!result) + { + return result; + } + + // + result = cTime > from && cTime < to; + + // + return result; + } +}; + +// +// Parsing Market Names ... +struct XMarketParser +{ + // + string _version; // Temp ... + + // + bool IsIngot(string market) + { + // + bool result = false; + + // + // result = IsValid(market) && + // market == ""; + + // + return result; + } + + // + bool IsErrante(string market) + { + // + bool result = false; + + // + // result = IsValid(market) && + // market == ""; + + // + return result; + } + + // + bool IsAMarkets(string market) + { + // + bool result = false; + + // + result = IsValid(market) && + market == "AMarkets LLC"; + + // + return result; + } + + // + bool IsIFCMarkets(string market) + { + // + bool result = false; + + // + // result = IsValid(market) && + // market == ""; + + // + return result; + } + + // + bool IsOtetMarkets(string market) + { + // + bool result = false; + + // + // result = IsValid(market) && + // market == ""; + + // + return result; + } + + // +}; + +// +// Styling Buffers ... + +// +struct XBufferPlotStyle +{ + // + int width; // Width + color clr; // Color + uchar arrow; // Arrow Code + ENUM_DRAW_TYPE type; // Type + ENUM_LINE_STYLE style; // Style + + // + // Constructor ... + XBufferPlotStyle() + { + Default(); + } + + // + // Tools ... + + // + // Default ... + void Default() + { + // + width = 1; + arrow = 0; + clr = CLR_NONE; + type = DRAW_NONE; + style = STYLE_SOLID; + } +}; + +// +// Register a Buffer as Indexed Buffer ... +void SetIndexBuffer( + int &index, // the Index refrence for Buffer + double &buffer[], // Buffer to Set + XBufferPlotStyle &style, // Style to Apply to Buffer + double &colorBuffer[], // Color Buffer + string label = NULL, // Buffer Label + bool showData = true, // Show Data on Data Window + double empty = -1, // Set 0 or EMPTY_VALUE used for setting Empty Value + int drawBegin = -1 // if Set More Than -1 applied +) +{ + // + // Set Buffer Index ... + SetIndexBuffer(index, buffer, INDICATOR_DATA); + + // + // Show Date ... + PlotIndexSetInteger(index, PLOT_SHOW_DATA, showData); + + // + // Set Buffer Label ... + if (IsValid(label)) + { + PlotIndexSetString(index, PLOT_LABEL, label); + } + + // + if (empty == 0 || empty == EMPTY_VALUE) + { + PlotIndexSetDouble(index, PLOT_EMPTY_VALUE, empty); + } + + // + if (drawBegin > -1) + { + PlotIndexSetInteger(index, PLOT_DRAW_BEGIN, drawBegin); + } + + // + if (style.type == DRAW_ARROW) + { + PlotIndexSetInteger(index, PLOT_ARROW, style.arrow); + } + + // + PlotIndexSetInteger(index, PLOT_LINE_STYLE, style.style); + PlotIndexSetInteger(index, PLOT_LINE_WIDTH, style.width); + + // + string drawTypeStr = EnumToString(style.type); + bool hasColorBuffer = Contains("COLOR", drawTypeStr); + + // + if (!hasColorBuffer) + { + PlotIndexSetInteger(index, PLOT_LINE_COLOR, style.clr); + } + else + { + // + // Since Color Buffers must add as next Index of it's own Buffer + // here before applied Color Buffer increase index ... + index++; + + // + SetIndexBuffer(index, colorBuffer, INDICATOR_COLOR_INDEX); + } + + // + // Increase Index for Next Buffer ... + index++; +} + +// +void SetIndexCandleBuffers( + int &index, // the Index refrence for Buffer + string openLabel, // Open Label + double &open[], // Open Buffer + string highLabel, // High Label + double &high[], // High Buffer + string lowLabel, // Low Label + double &low[], // Low Buffer + string closeLabel, // Close Label + double &close[], // Close Buffer + bool showData = true, // Show Data on Data Window + double empty = -1, // Set 0 or EMPTY_VALUE used for setting Empty Value + int drawBegin = -1 // if Set More Than -1 applied +) +{ + // + bool hasLabel = + // + IsValid(openLabel) && + IsValid(highLabel) && + IsValid(lowLabel) && + IsValid(closeLabel) + // + ; + + // + string label = + !hasLabel + ? NULL + : openLabel + ";" + highLabel + ";" + lowLabel + ";" + closeLabel; + + // + // Set Buffer Index ... + SetIndexBuffer(index, open, INDICATOR_DATA); + + // + // Set Draw Candles Type ... + PlotIndexSetInteger(index, PLOT_LINE_STYLE, DRAW_CANDLES); + + // + // Show Date ... + PlotIndexSetInteger(index, PLOT_SHOW_DATA, showData); + + // + // Set Buffer Label ... + if (IsValid(label)) + { + PlotIndexSetString(index, PLOT_LABEL, label); + } + + // + if (empty == 0 || empty == EMPTY_VALUE) + { + PlotIndexSetDouble(index, PLOT_EMPTY_VALUE, empty); + } + + // + if (drawBegin > -1) + { + PlotIndexSetInteger(index, PLOT_DRAW_BEGIN, drawBegin); + } + + // + index++; + + // + // Set Buffer Index ... + SetIndexBuffer(index, high, INDICATOR_DATA); + index++; + + // + // Set Buffer Index ... + SetIndexBuffer(index, low, INDICATOR_DATA); + index++; + + // + // Set Buffer Index ... + SetIndexBuffer(index, close, INDICATOR_DATA); + index++; +} + +// +void SetIndexCandleBuffers( + int &index, // the Index refrence for Buffer + string openLabel, // Open Label + double &open[], // Open Buffer + string highLabel, // High Label + double &high[], // High Buffer + string lowLabel, // Low Label + double &low[], // Low Buffer + string closeLabel, // Close Label + double &close[], // Close Buffer + double &colorBuffer[], // Candle Color Buffer + bool showData = true, // Show Data on Data Window + double empty = -1, // Set 0 or EMPTY_VALUE used for setting Empty Value + int drawBegin = -1 // if Set More Than -1 applied +) +{ + // + SetIndexCandleBuffers( + index, + openLabel, + open, + highLabel, + high, + lowLabel, + low, + closeLabel, + close, + showData, + empty, + drawBegin // + ); + + // + int mFirstIndex = index - 4; + + // + // Set Draw Candles Type ... + PlotIndexSetInteger(mFirstIndex, PLOT_LINE_STYLE, DRAW_COLOR_CANDLES); + + // + // Set Color Buffer ... + SetIndexBuffer(index, colorBuffer, INDICATOR_COLOR_INDEX); + + // + index++; +} + +// +// Functions ... + +// +// Validators ... + +// +// Validate an String has length and not NULL ... +bool IsValid(string value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + StringLen(value) > 0 + // + ; + + // + return result; +} +bool IsSpecifiedValid(string value) +{ + return IsValid(value); +} + +// +// Validate a Date ... +bool IsValid(datetime value) +{ + // + bool result = false; + + // + result = NotEmpty(value) && value != NULL; + + // + return result; +} +bool IsSpecifiedValid(datetime value) +{ + return IsValid(value); +} + +// +// Validate a Period Param ... +bool IsValid(ENUM_TIMEFRAMES value) +{ + // + bool result = false; + + // + result = + // + value != NULL + // + ; + + // + return result; +} +bool IsSpecifiedValid(ENUM_TIMEFRAMES value) +{ + // + return IsValid(value); +} + +// +// Validate Specified Cycle ... +bool IsValid(ENUM_X_MARKET_CYCLES value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + value != X_MARKET_CYCLE_UNKNOWN + // + ; + + // + return result; +} + +// +// Validate Specific Period Mode ... +bool IsValid( + ENUM_X_PERIOD_METHOD mMethod, // Period Select Method + ENUM_TIMEFRAMES mPeriod // Selected Period +) +{ + // + bool result = false; + + // + result = + // + mMethod == X_PERIOD_NOTHING + ? false + : mMethod == X_PERIOD_MANUALLY + ? mPeriod != NULL + : mMethod == X_PERIOD_AUTO + ? true + : false + // + ; + + // + return result; +} + +// +bool IsSpecifiedValid( + ENUM_X_PERIOD_METHOD mMethod, // Period Select Method + ENUM_TIMEFRAMES mPeriod // Selected Period +) +{ + return IsValid(mMethod, + mPeriod // + ); +} + +// +// Validate Swing Mode ... +bool IsValid(ENUM_X_SWING_TYPE value) +{ + // + bool result = false; + + // + result = + // + value == X_SWING_HIGH || + value == X_SWING_LOW + // + ; + + // + return result; +} + +// +// As IS ... + +// +// Determine a Position type is Long or not ... +bool IsLong(ENUM_POSITION_TYPE type) +{ + // + bool result = type == POSITION_TYPE_BUY; + + // + return result; +} +bool IsLong(ENUM_ORDER_TYPE type) +{ + // + bool result = type == ORDER_TYPE_BUY; + + // + return result; +} + +// +// Determine a Position type is Short or not ... +bool IsShort(ENUM_POSITION_TYPE type) +{ + // + bool result = type == POSITION_TYPE_SELL; + + // + return result; +} +bool IsShort(ENUM_ORDER_TYPE type) +{ + // + bool result = type == ORDER_TYPE_SELL; + + // + return result; +} + +// +// Retrieve Opposit Direction Type ... +ENUM_POSITION_TYPE GetOpposit(ENUM_POSITION_TYPE type) +{ + // + ENUM_POSITION_TYPE result = NULL; + + // + bool isLong = IsLong(type); + result = isLong + ? POSITION_TYPE_SELL + : POSITION_TYPE_BUY; + + // + return result; +} +ENUM_ORDER_TYPE GetOpposit(ENUM_ORDER_TYPE type) +{ + // + ENUM_ORDER_TYPE result = NULL; + + // + bool isLong = IsLong(type); + result = isLong + ? ORDER_TYPE_SELL + : ORDER_TYPE_BUY; + + // + return result; +} + +// +string ToString(ENUM_POSITION_TYPE value) +{ + // + string result = NULL; + + // + result = + // + IsLong(value) + ? "Long" + : "Short" + // + ; + + // + return result; +} +string ToString(ENUM_ORDER_TYPE value) +{ + // + string result = NULL; + + // + result = + // + IsLong(value) + ? "Long" + : "Short" + // + ; + + // + return result; +} + +// +// Check Expert Running in Testing Mode or not ... +bool IsRunningOnTestMode() +{ + // + bool result = false; + + // + // check programm mode ... + result = MQL5InfoInteger(MQL5_TESTING); + + // + return result; +} + +// +// Find Chart ID ... +long FindChartID( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL // Trading Period +) +{ + // + long result = ChartFirst(); + long first = result; + + // + while (result > 0) + { + // + string chSymbol = ChartSymbol(result); + ENUM_TIMEFRAMES chPeriod = ChartPeriod(result); + + // + bool isOwn = + // + chSymbol == mSymbol && + chPeriod == mPeriod + // + ; + if (isOwn) + { + break; + } + + // + result = ChartNext(result); + } + + // + return result; +} + +// +// Normalizers ... + +// +// Check a Symbol provided or not ... +// if not use Default ... +string NormalizeSymbol(string value) +{ + // + string result = value; + + // + if (!IsValid(result)) + { + result = _Symbol; + } + + // + return result; +} + +// +// Check a Datetime provided or not ... +// if not use Current ... +datetime NormalizeTime(datetime value) +{ + // + datetime result = value; + + // + if (!IsValid(result)) + { + result = TimeCurrent(); + } + + // + return result; +} + +// +// Check a Period provided or not ... +// if not use Default ... +ENUM_TIMEFRAMES NormalizePeriod(ENUM_TIMEFRAMES value) +{ + // + ENUM_TIMEFRAMES result = value; + + // + if (!IsValid(value)) + { + result = _Period; + } + + // + return result; +} + +// +// Normalize Cycle ... +ENUM_X_MARKET_CYCLES NormalizeCycle(ENUM_X_MARKET_CYCLES value) +{ + // + ENUM_X_MARKET_CYCLES result = value; + + // + if (!IsValid(result)) + { + result = X_MARKET_CYCLE_SHORT; + } + + // + return value; +} + +// +// Validate a Buffer Size for Looping or etc ... +bool IsValidSize(int size) +{ + // + bool result = size > 0; + + // + return result; +} + +template +bool IsValidSize(T &buffer[]) +{ + // + bool result = false; + + // + result = + // + IsValidSize(ArraySize(buffer)) + // + ; + + // + return result; +} + +// +// Check a Given Index is Valid or not ... +bool IsValidIndex(int index) +{ + return index >= 0; +} + +// +// Normalize Index Based On Specified Buffer ... +template +void NormalizeIndex( + int &index, + T &buffer[] // +) +{ + // + int bufferSize = ArraySize(buffer); + + // + if (bufferSize <= 0) + { + index = 0; + } + + // + if (index <= 0) + { + index = 0; + } + + // + if (index > bufferSize - 1) + { + index = bufferSize - 1; + } +} + +// +// Normalize Start and Count based on Specified Buffer ... +template +void NormalizeCount( + int &start, + int &count, + T &buffer[] // +) +{ + // + // Validate Buffer Size ... + int bufferSize = ArraySize(buffer); + if (!IsValidSize(bufferSize)) + { + return; + } + + // + // Normalization Start ... + NormalizeIndex( + start, + buffer // + ); + + // + if (count < start) + { + count = (start - count); + } + + // + // Normalization Count ... + + // + if (count < 0) + { + count = start; + } + + // + if (count > bufferSize) + { + count = bufferSize; + } +} + +// +// Normalize a give Volume ... +double NormalizeVolume( + double mVolume, // desired volume to normalize + string mSymbol = NULL, // Trading Symbol + int mLength = 2 // Length of Digits +) +{ + // + double result = mVolume; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + // Normalize Digits ... + int digits = GetDigits(mSymbol); + + // + mLength = + mLength == 0 || mLength > digits + ? digits + : MathMin(mLength, digits); + + // + // Normalize Volume ... + result = NormalizeDouble(result, mLength); + + // + double maxAvailableVolume = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_MAX); + double minAvailableVolume = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_MIN); + + // + // Validate Result ... + if (result > maxAvailableVolume) + { + result = maxAvailableVolume; + } + else if (result < minAvailableVolume) + { + result = minAvailableVolume; + } + + // + return result; +} + +// +// Normallize Price ... +double NormalizePrice( + double mPrice, // desired Price for normalization + string mSymbol = NULL // Trading Symbol +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double tickSize = 0; + result = SymbolInfoDouble(mSymbol, SYMBOL_TRADE_TICK_SIZE, tickSize); + + // + int digits = GetDigits(mSymbol); + result = NormalizeDouble(MathRound(mPrice / tickSize) * tickSize, digits); + + // + return result; +} + +// +// Prices ... + +// +// Retrieve Ask Price ... +double GetAsk( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_ASK); + + // + return result; +} + +// +// Retrieve Bid Price ... +double GetBid( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_BID); + + // + return result; +} + +// +// Retrieve Spread Price ... +double GetSpread( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double ask = GetAsk(mSymbol); + double bid = GetBid(mSymbol); + + // + double result = MathAbs(ask - bid); + + // + return result; +} + +// +// Retrieve Point Value ... +double GetPoints( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_POINT); + + // + return result; +} + +// +// Retrieve Point Digits ... +int GetDigits( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + int result = (int)SymbolInfoInteger(mSymbol, SYMBOL_DIGITS); + + // + return result; +} + +// +// Retrieve Entry Price ... +double GetEntry( + string mSymbol = NULL, // Trading Symbol + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? GetAsk(mSymbol) + : GetBid(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +// +// Retrieve Exit Price ... +double GetExit( + string mSymbol = NULL, // Trading Symbol + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? GetBid(mSymbol) + : GetAsk(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +// +// Get 1 Pip in Price Value ... +double GetPipPrice( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double symbolPoint = GetPoints(mSymbol); + int symbolDigits = GetDigits(mSymbol); + + // + double result = symbolPoint; + if (symbolDigits == 3 || symbolDigits == 5) + { + result *= 10; + } + + // + return result; +} + +// +// Converts Pips To Price ... +double PipsToPrice( + double mPips, // pips amount + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + int digits = GetDigits(mSymbol); + double pipValue = GetPipPrice(mSymbol); + double result = mPips * pipValue; + + // + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +// +// Converts Price to Pips ... +double PriceToPips( + double mPrice, // the price amount which required to calculate + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + mPrice = NormalizePrice(mPrice, mSymbol); + + // + int digits = GetDigits(mSymbol); + double pipPrice = GetPipPrice(mSymbol); + + // + double result = mPrice / pipPrice; + + // + result = NormalizeDouble(result, digits); + + // + return result; +} + +// +// Convert Price to Point ... +double PriceToPoint( + double price, // the price amount which required to calculate + string mSymbol = NULL // Trading Symbol +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + price = NormalizePrice(price, mSymbol); + + // + double point = GetPoints(mSymbol); + result = price / point; + + // + return result; +} + +// +// Converts Point to Price ... +double PointToPrice( + double points, // Points Amount + string mSymbol = NULL // Trading Symbol +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double point = GetPoints(mSymbol); + result = points * point; + + // + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +// +// Converts Series Mode to XPRICE ... +ENUM_X_PRICE ToPrice( + ENUM_SERIESMODE mMode // Specified Series Mode ... +) +{ + // + ENUM_X_PRICE result = X_PRICE_CLOSE; + + // + switch (mMode) + { + // + // High ... + case MODE_HIGH: + result = X_PRICE_HIGH; + break; + + // + // Open ... + case MODE_OPEN: + result = X_PRICE_OPEN; + break; + + // + // Low ... + case MODE_LOW: + result = X_PRICE_LOW; + break; + + // + // Close ... + // Default ... + case MODE_CLOSE: + default: + result = X_PRICE_CLOSE; + break; + } + + // + return result; +} + +// +// Retrieve Applied Price ... +template +double GetAppliedPrice( + ENUM_APPLIED_PRICE tprice, // Type of Price Selection + T &open[], // Open Prices + T &high[], // High Preices + T &low[], // Low Prices + T &close[], // Close Prices + int i // Bar Index +) +{ + switch (tprice) + { + case PRICE_CLOSE: + return (close[i]); + case PRICE_OPEN: + return (open[i]); + case PRICE_HIGH: + return (high[i]); + case PRICE_LOW: + return (low[i]); + case PRICE_MEDIAN: + return ((high[i] + low[i]) / 2.0); + case PRICE_TYPICAL: + return ((high[i] + low[i] + close[i]) / 3.0); + case PRICE_WEIGHTED: + return ((high[i] + low[i] + close[i] + close[i]) / 4.0); + } + return (0); +} + +// +double iGetPrice( + int tprice, + double open, + double high, + const double low, + const double close // +) +{ + // + switch (tprice) + { + case PRICE_CLOSE: + return (close); + case PRICE_OPEN: + return (open); + case PRICE_HIGH: + return (high); + case PRICE_LOW: + return (low); + case PRICE_MEDIAN: + return ((high + low) / 2.0); + case PRICE_TYPICAL: + return ((high + low + close) / 3.0); + case PRICE_WEIGHTED: + return ((high + low + close + close) / 4.0); + } + + // + return (0); +} + +/** + * Calculates Price Change Percentage based on + * Several Params ... + * + * @param _symbol: Symbol ... + * @param _period: Time Frame ... + * @param _from: start Bar Index ... + * @param _length: Length of Bars ... + * + * @return ( double ) + */ +double GetPriceChanged( + string _symbol = NULL, + ENUM_TIMEFRAMES _period = NULL, + int _from = 0, + int _length = 3 // +) +{ + // + double result = 0; + + // + NormalizeSymbol(_symbol); + NormalizePeriod(_period); + + // + if (_from < 0) + { + _from = 0; + } + + // + if (_length < 2) + { + _length = 2; + } + + // + double closes[]; + int copiedCloses = CopyClose( + _symbol, + _period, + _from, + _length, + closes // + ); + if (copiedCloses < _length) + { + return result; + } + ArrayReverse(closes); + + // + double change = (closes[0] - closes[_length - 1]) / closes[_length - 1] * 100; + result = change; + + // + return result; +} + +// +// Calculate TP/SL for Specified Type of Positions ... +void CalculateTPSL( + double &mSL, // Hold SL + double &mTP, // Hold TP + ENUM_POSITION_TYPE mType, // Position Type Long (Buy) / Short (Sell) + double mEntry, // Entry Price + double mR2R = 1, // Provided Risk To Reward Ratio + double slPrice = 0, // Provided SL Price + double tpPrice = 0, // Provided TP Price + double priceToRisk = 0, // If Entry equal to Provided SL Price Risk Point + double priceToReward = 0 // If Entry equal to Provided TP Price Reward Point +) +{ + // + // if Both TP and SL Provided, ignore R2R and Calculate direct ... + // if SL provided, Calculate TP based on Provided R2R ... + // if TP provided, Calculate SL based on Provided R2R ... + // default R2R is set to 1 ... + + // + mSL = 0; + mTP = 0; + + // + bool isLong = IsLong(mType); + + // + // Set Default R2R ... + if (mR2R < 1) + { + mR2R = 1; + } + + // + if (mEntry <= 0 || + (tpPrice <= 0 && slPrice <= 0)) + { + return; + } + + // + double risk = 0; + double reward = 0; + + // + bool canCalculateBasedOnSL = slPrice > 0 && + (isLong + ? slPrice <= mEntry + : slPrice >= mEntry); + + // + bool canCalculateBasedOnTP = tpPrice > 0 && + (isLong + ? tpPrice >= mEntry + : tpPrice <= mEntry); + + // + if (canCalculateBasedOnSL && !canCalculateBasedOnTP) + { + // + risk = MathAbs(mEntry - slPrice); + if (risk == 0) + { + risk = priceToRisk; + } + reward = risk * mR2R; + } + else if (!canCalculateBasedOnSL && canCalculateBasedOnTP) + { + // + reward = MathAbs(mEntry - tpPrice); + if (reward == 0) + { + reward = priceToReward; + } + risk = reward / mR2R; + } + else if (!canCalculateBasedOnSL && !canCalculateBasedOnTP) + { + // + bool canSetTPPrice = isLong + ? tpPrice > mEntry + : tpPrice < mEntry; + if (canSetTPPrice) + { + mTP = tpPrice; + } + + // + bool canSetSLPrice = isLong + ? slPrice < mEntry + : slPrice > mEntry; + if (canSetSLPrice) + { + mSL = slPrice; + } + + // + return; + } + else if (canCalculateBasedOnSL && canCalculateBasedOnTP) + { + // + bool canSetTPPrice = isLong + ? tpPrice > mEntry + : tpPrice < mEntry; + if (canSetTPPrice) + { + mTP = tpPrice; + } + + // + bool canSetSLPrice = isLong + ? slPrice < mEntry + : slPrice > mEntry; + if (canSetSLPrice) + { + mSL = slPrice; + } + + // + return; + } + + // + mTP = isLong + ? mEntry + reward + : mEntry - reward; + + // + mSL = isLong + ? mEntry - risk + : mEntry + risk; +} + +// +bool CalculateTPSLByPoint( + double &mSL, // Hold SL + double &mTP, // Hold TP + ENUM_POSITION_TYPE mType, // Position Type Long (Buy) / Short (Sell) + double mEntry, // Entry Price + double mPointValue, // Point Value + double mR2R = 1, // Provided Risk To Reward Ratio + double slPoint = 0, // Provided SL Point + double tpPoint = 0 // Provided TP Point +) +{ + // + bool result = false; + + // + mSL = 0; + mTP = 0; + + // + bool isLong = IsLong(mType); + + // + // Set Default R2R ... + if (mR2R < 1) + { + mR2R = 1; + } + + // + if (mEntry <= 0 || + mPointValue <= 0 || + (slPoint <= 0 && tpPoint <= 0)) + { + return result; + } + + // + double risk = 0; + double reward = 0; + + // + bool canCalculateBasedOnSL = slPoint > 0; + + // + bool canCalculateBasedOnTP = tpPoint > 0; + + // + if (!canCalculateBasedOnSL && !canCalculateBasedOnTP) + { + return result; + } + + // + if (canCalculateBasedOnSL && canCalculateBasedOnTP) + { + // + reward = tpPoint * mPointValue; + risk = slPoint * mPointValue; + } + else if (!canCalculateBasedOnSL && canCalculateBasedOnTP) + { + // + reward = tpPoint * mPointValue; + risk = reward / mR2R; + } + else if (canCalculateBasedOnSL && !canCalculateBasedOnTP) + { + // + risk = slPoint * mPointValue; + reward = risk * mR2R; + } + + // + result = risk > 0 && reward > 0; + if (!result) + { + return result; + } + + // + mTP = isLong + ? mEntry + reward + : mEntry - reward; + + // + mSL = isLong + ? mEntry - risk + : mEntry + risk; + + // + return result; +} + +// +bool CalculateTPSLByPrice( + double &mSL, // Hold SL + double &mTP, // Hold TP + ENUM_POSITION_TYPE mType, // Position Type Long (Buy) / Short (Sell) + double mEntry, // Entry Price + double mR2R = 1 // Provided Risk To Reward Ratio +) +{ + // + bool result = false; + + // + bool isLong = IsLong(mType); + + // + // Set Default R2R ... + if (mR2R < 1) + { + mR2R = 1; + } + + // + if (mEntry <= 0 || + (mSL <= 0 && mTP <= 0)) + { + return result; + } + + // + double risk = 0; + double reward = 0; + + // + bool canCalculateBasedOnSL = mSL > 0; + bool canCalculateBasedOnTP = mTP > 0; + + // + if ( + !canCalculateBasedOnSL && + !canCalculateBasedOnTP) + { + return result; + } + + // + if (!canCalculateBasedOnSL && canCalculateBasedOnTP) + { + // + reward = MathAbs(mTP - mEntry); + risk = reward / mR2R; + } + else if (canCalculateBasedOnSL && !canCalculateBasedOnTP) + { + // + risk = MathAbs(mEntry - mSL); + reward = risk * mR2R; + } + + // + result = risk > 0 && reward > 0; + if (!result) + { + return result; + } + + // + mTP = isLong + ? mEntry + reward + : mEntry - reward; + + // + mSL = isLong + ? mEntry - risk + : mEntry + risk; + + // + return result; +} + +/** + * Retrieve Current Tick ... + */ +bool GetTick( + string mSymbol, + MqlTick &tick // +) +{ + return SymbolInfoTick(mSymbol, tick); +} + +/** + * Retrieve Tick Entry ... + */ +double GetTickEntry( + MqlTick &mTick, + ENUM_POSITION_TYPE type, + string mSymbol = NULL // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? mTick.ask + : mTick.bid; + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +/** + * Retrieve Tick Exit ... + */ +double GetTickExit( + MqlTick &mTick, + ENUM_POSITION_TYPE type, + string mSymbol = NULL // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? mTick.bid + : mTick.ask; + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +/** + * Calculate Momentum Changes based on Given Price + */ +double CalculateMomentum( + double currentPrice, + double previousPrice // +) +{ + // + double result = 0; + + // + return result; +} + +/** + * Detect Possible Momentum Changes + * Using MqlTick ... + */ +bool DetectMomentumChange( + ENUM_POSITION_TYPE type, + string mSymbol = NULL, + int mLength = 14 // +) +{ + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + MqlTick ticks[]; + int copied = CopyTicks( + mSymbol, + ticks, + COPY_TICKS_ALL, + 0, + mLength + 1 // + ); + + // + result = copied > mLength; + if (!result) + { + return result; + } + + // + double previousPrice = GetTickExit( + ticks[mLength], + type, + mSymbol // + ); + for (int i = mLength - 1; i >= 0; i--) + { + // + double currentPrice = GetTickExit( + ticks[i], + type, + mSymbol // + ); + + // + double momentum = CalculateMomentum( + currentPrice, + previousPrice // + ); + + // + if (fabs(momentum) > 1.0) + { + // + result = true; + break; + } + } + + // + return result; +} + +// +// Symbols ... + +// +// Retrieve Available Symbols ... +int GetAllSymbols( + string &symbols[], // Hold Result + bool onlyInWatchList = false, // Specified Retrieve only Symbols which in Watch List + bool forceClean = true // Force To Clean Result Array +) +{ + // + int result = 0; + + // + if (forceClean) + { + Clean(symbols); + } + + // + int beforeSize = ArraySize(symbols); + + // + int symbolsCount = SymbolsTotal(onlyInWatchList); + if (symbolsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < symbolsCount; i++) + { + // + string iSymbol = SymbolName( + i, + onlyInWatchList + // + ); + if (!IsValid(iSymbol)) + { + continue; + } + + // + Add( + iSymbol, + symbols + // + ); + } + + // + int afterSize = ArraySize(symbols); + + // + result = afterSize - beforeSize; + + // + return result; +} + +// +// This is a Global Way to Filter Symbols +// you can pass Specific string as Query or a List String for Filtering ... +int FilterSymbols( + string query, // Which Query to Search Symbol + string &symbols[], // Hold Result + bool onlyInWatchList = false, // Specified Retrieve only Symbols which in Watch List + bool forceClean = true, // Force To Clean Result Array + bool ignoreCase = true, // Ignore Case + string querySeparator = "," // If Provided means query is a COllection of Queries and need to be Splitted +) +{ + // + int result = 0; + + // + if (forceClean) + { + Clean(symbols); + } + + // + if (!IsValid(query)) + { + return result; + } + + // + // Check Query is an String array or not ... + string mQueries[]; + int queriesCount = 0; + if (IsValid(querySeparator) && Contains(querySeparator, query, true)) + { + // + queriesCount = SplitContent( + mQueries, + query, + querySeparator + // + ); + } + + // + int beforeSize = ArraySize(symbols); + + // + string allSymbols[]; + int allSymbolsCount = GetAllSymbols( + allSymbols, + onlyInWatchList, + forceClean); + if (allSymbolsCount <= 0) + { + return result; + } + + // + // Loop Through all Symbols ... + for (int i = 0; i < allSymbolsCount; i++) + { + // + string iSymbol = allSymbols[i]; + + // + bool isFilterPassed = false; + if (queriesCount == 0) + { + // + isFilterPassed = Contains( + query, + iSymbol, + ignoreCase + // + ); + } + else if (queriesCount > 0) + { + // + isFilterPassed = Contains( + mQueries, + iSymbol, + ignoreCase + // + ); + } + + // + if (isFilterPassed) + { + // + Add( + iSymbol, + symbols + // + ); + } + } + + // + int afterSize = ArraySize(symbols); + + // + result = afterSize - beforeSize; + + // + return result; +} + +// +int FilterUSDSymbols( + string &symbols[], // Hold Result + bool onlyInWatchList = false, // Specified Retrieve only Symbols which in Watch List + bool forceClean = true, // Force To Clean Result Array + bool ignoreCase = true, // Ignore Case + string querySeparator = "," // If Provided means query is a COllection of Queries and need to be Splitted +) +{ + // + return FilterSymbols( + "USD", + symbols, + onlyInWatchList, + forceClean, + ignoreCase, + querySeparator + // + ); +} + +// +// Time / Date ... + +// +// Representation of Time Struct ... +// struct MqlDateTime +// { +// int year; // Year +// int mon; // Month +// int day; // Day +// int hour; // Hour +// int min; // Minutes +// int sec; // Seconds +// int day_of_week; // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday) +// int day_of_year; // Day number of the year (January 1st is assigned the number value of zero) +// }; + +// +// Converts Time to Seconds ... +ulong TimeToSeconds( + datetime time // Specify time to Convert ... +) +{ + // + ulong result = (ulong)time; + + // + return result; +} +ulong TimeToSeconds( + MqlDateTime &time // Specify time to Convert ... +) +{ + // + datetime dTime = StructToTime(time); + + // + ulong result = TimeToSeconds(dTime); + + // + return result; +} + +// +// Converts Seconds To Time ... +datetime SecondsToTime( + ulong seconds // Specify Seconds to Convert ... +) +{ + // + datetime result = (datetime)seconds; + + // + return result; +} +MqlDateTime SecondsToStruct( + ulong seconds // Specify Seconds to Convert ... +) +{ + // + datetime dTime = SecondsToTime(seconds); + + // + MqlDateTime result = {}; + TimeToStruct( + dTime, + result); + + // + return result; +} + +// +// Converts Time to MilliSeconds ... +ulong TimeToMilliSeconds( + datetime time // Specify time to Convert ... +) +{ + // + ulong result = TimeToSeconds(time) * 1000; + + // + return result; +} +ulong TimeToMilliSeconds( + MqlDateTime &time // Specify time to Convert ... +) +{ + // + datetime dTime = StructToTime(time); + + // + ulong result = TimeToMilliSeconds(dTime); + + // + return result; +} + +// +// Converts MillisSeconds to Time ... +datetime MilliSecondsToTiem( + ulong milliSeconds // Specify MilliSeconds to Convert ... +) +{ + // + ulong seconds = milliSeconds / 1000; + + // + datetime result = SecondsToTime(seconds); + + // + return result; +} +MqlDateTime MilliSecondsToStruct( + ulong milliSeconds // Specify MilliSeconds to Convert ... +) +{ + // + datetime dTime = MilliSecondsToTiem(milliSeconds); + + // + MqlDateTime result = {}; + TimeToStruct( + dTime, + result); + + // + return result; +} + +// +// Converts Hours to Seconds ... +int HoursToSeconds(int value) +{ + // + int result = 0; + + // + if (value < 0) + { + value = 0; + } + + // + if (value == 0) + { + return result; + } + + // + result = value * 60 * 60; + + // + return result; +} + +// +// Retrieve DateTime Structure ... +MqlDateTime GetCurrentTime() +{ + // + MqlDateTime result = {}; + + // + datetime cTime = TimeCurrent(); + TimeToStruct(cTime, result); + + // + return result; +} + +// +// Retrieve Current Time as Seconds ... +ulong GetCurrentTimeAsSeconds() +{ + // + datetime time = TimeCurrent(); + + // + ulong result = TimeToSeconds(time); + + // + return result; +} + +// +// Retrieve Current Time as MilliSeconds ... +ulong GetCurrentTimeAsMilliSeconds() +{ + // + datetime time = TimeCurrent(); + + // + ulong result = TimeToMilliSeconds(time); + + // + return result; +} + +// +int GetLocalOffset() +{ + // + MqlDateTime cTimeStruct; + datetime cTime = TimeCurrent(cTimeStruct); + + // + MqlDateTime cLTimeStruct; + datetime cLTime = TimeLocal(cLTimeStruct); + + // + cTimeStruct.sec = 0; + cTime = StructToTime(cTimeStruct); + + // + cLTimeStruct.sec = 0; + cLTime = StructToTime(cLTimeStruct); + + // + int result = ((int)cLTime - (int)cTime); + + // + return result; +} + +// +int GetUTCRequiredTimeOffset() +{ + // + int utcOffset = TimeGMTOffset(); + int localOffset = GetLocalOffset(); + + // + int result = utcOffset + localOffset; + + // + return result; +} + +// +datetime GetUTCTime( + datetime time = NULL, + bool applyTradeServerTime = false // +) +{ + // + datetime result = NULL; + + // + NormalizeTime(time); + + // + datetime cTime = TimeCurrent(); + datetime cTimeLocal = TimeLocal(); + + // + int cLocalOffset = ((int)cTimeLocal - (int)cTime); + int gmtOffset = TimeGMTOffset(); + int offsetDelte = gmtOffset + cLocalOffset; + int requiredUTCOffset = GetUTCRequiredTimeOffset(); + if (requiredUTCOffset > 0) + { + requiredUTCOffset = -1 * requiredUTCOffset; + } + + // + int timeSeconds = (int)time; + int resultSeconds = timeSeconds + requiredUTCOffset; + + // + result = (datetime)(resultSeconds); + + // + return result; +} + +// +// Retrieve only Hour and Minute as String ... +string GetTimeString( + datetime time = NULL // +) +{ + // + NormalizeTime(time); + + // + string result = NULL; + + // + MqlDateTime tStruct; + bool isStructed = TimeToStruct(time, tStruct); + if (!isStructed) + { + return result; + } + + // + string hour = ToString(tStruct.hour); + hour = + StringLen(hour) == 1 + ? "0" + hour + : hour; + + // + string minute = ToString(tStruct.min); + minute = + StringLen(minute) == 1 + ? "0" + minute + : minute; + + // + result = hour + ":" + minute; + + // + return result; +} + +// +// Converts a Date time to File Format ... +string ToFormatString( + datetime mTime, + string separator = "_" // +) +{ + // + string result = NULL; + + // + if (!IsValid(mTime)) + { + return result; + } + + // + MqlDateTime timeStruct; + bool isConverts = TimeToStruct( + mTime, + timeStruct // + ); + if (!isConverts) + { + return result; + } + + // + string year = ToString(timeStruct.year); + string month = ToString(timeStruct.mon); + string day = ToString(timeStruct.day); + string hour = ToString(timeStruct.hour); + string minute = ToString(timeStruct.min); + string second = ToString(timeStruct.sec); + + // + result = + // + // Year ... + year + separator + + // + // Month ... + (StringLen(month) == 1 + ? "0" + month + : month) + + separator + + // + // Day ... + (StringLen(day) == 1 + ? "0" + day + : day) + + separator + + // + // Hour ... + (StringLen(hour) == 1 + ? "0" + hour + : hour) + + separator + + // + // Minute ... + (StringLen(minute) == 1 + ? "0" + minute + : minute) + + separator + + // + // Seconds ... + (StringLen(second) == 1 + ? "0" + second + : second) + + separator + + // + "" + // + ; + + // + return result; +} + +// +// Check Specific Time in Range of another Time ... +bool IsTimeInRange( + datetime currentTime = NULL, + datetime startTime = NULL, + datetime stopTime = NULL // +) +{ + // + bool result = false; + + // + // Normallize Current Time ... + NormalizeTime(currentTime); + + // + result = !IsValid(startTime) && + !IsValid(stopTime); + if (result) + { + return result; + } + + // + result = IsValid(startTime) && + IsValid(stopTime); + if (!result) + { + // + result = IsValid(startTime) && + currentTime >= startTime; + + // + return result; + } + + // + result = currentTime >= startTime && + currentTime < stopTime; + + // + return result; +} + +// +// Bar Times ... + +// +// Retrieve Specified Bar Time ... +datetime GetBarTime( + string mSymbol = "", // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + // Validate and Normalize Args ... + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + // Retrieve Bar Time ... + datetime result = iTime( + mSymbol, + mPeriod, + barIndex); + + // + return result; +} + +// +// Retrieve Specified Bar Time ... +ulong GetBarTimeAsSeconds( + string mSymbol = "", // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + // Retrieve Bar Time ... + datetime time = GetBarTime( + mSymbol, + mPeriod, + barIndex); + + // + ulong result = TimeToSeconds(time); + + // + return result; +} + +// +// Retrieve Specified Bar Time ... +ulong GetBarTimeAsMilliSeconds( + string mSymbol = "", // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + // Retrieve Bar Time ... + datetime time = GetBarTime( + mSymbol, + mPeriod, + barIndex); + + // + ulong result = TimeToMilliSeconds(time); + + // + return result; +} + +// +// Retrieve a Bar Time Structure ... +MqlDateTime GetBarTimeStruct( + string mSymbol = "", // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + MqlDateTime result = {}; + + // + // Retrieve Bar Time ... + datetime barTime = GetBarTime( + mSymbol, + mPeriod, + barIndex); + + // + // Convert to Structure ... + TimeToStruct(barTime, result); + + // + return result; +} + +// +// Retrieve Last Available Bar Time of +// Dest Period inside Source Period ... +datetime GetLastBarTime( + ENUM_TIMEFRAMES sourcePeriod, + ENUM_TIMEFRAMES destPeriod // +) +{ + // + datetime result = NULL; + + // + if (!IsValid(sourcePeriod) || + !IsValid(destPeriod)) + { + return result; + } + + // + int sourceSeconds = PeriodSeconds(sourcePeriod); + int destSeconds = PeriodSeconds(destPeriod); + if (sourceSeconds < destSeconds) + { + return result; + } + + // + XOHCL sourceBar; + bool isInited = sourceBar.Init( + _Symbol, + sourcePeriod, + 0 // + ); + if (!isInited) + { + return result; + } + + // + result = (datetime)((((int)sourceBar.time) + sourceSeconds) - destSeconds); + + // + return result; +} + +// +// Other Tools ... + +// +template +bool IsSame( + T &buffer[], // Search Buffer + int count = 5, // Number of Searchs + int start = 0 // Start ... +) +{ + // + bool result = false; + + // + int bufferSize = ArraySize(buffer); + result = bufferSize > 0; + if (!result) + { + return result; + } + + // + // Validate Count ... + result = start + count < bufferSize; + if (!result) + { + return result; + } + + // + T iTem = buffer[start]; + for (int i = start; i < start + count; i++) + { + // + if (iTem != buffer[i]) + { + result = false; + break; + } + + // + if (!result) + { + result = true; + } + } + + // + return result; +} + +// +// Check first Cross Over second at index ... +bool IsCrossedOver( + const double &first[], // the buffer which check crossing over second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] > second[index] && + !(first[index + 1] > second[index + 1]); + + // + return result; +} + +// +// Check first is Over second at index ... +bool IsOver( + const double &first[], // the buffer which check over second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] > second[index] && + first[index + 1] > second[index + 1]; + + // + return result; +} + +// +// Check first Cross Under second at index ... +bool IsCrossedUnder( + const double &first[], // the buffer which check crossing under second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] < second[index] && + !(first[index + 1] < second[index + 1]); + + // + return result; +} + +// +// Check first is Under second at index ... +bool IsUnder( + const double &first[], // the buffer which check under second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] < second[index] && + first[index + 1] < second[index + 1]; + + // + return result; +} + +// +// Check if a Value Increasing in Loopback ... +bool IsIncreasing( + const int from, // Last Time Index + const int to, // Fisrs Tima Index + const double &buffer[] // the Buffer which required to search +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + from <= to || + ArraySize(buffer) < from + 1) + { + return result; + } + + // + // Loop through Items ... + double toValue = buffer[to]; + double fromValue = buffer[from]; + result = toValue > fromValue; + for (int i = to + 1; i <= from - 1; i++) + { + // + double iValue = buffer[i]; + bool isPassed = toValue >= iValue; + + // + bool isIIncreasing = IsIncreasing( + from, + i, + buffer); + + // + // Check Result ... + result = result && isPassed && isIIncreasing; + if (!result) + { + break; + } + } + + // + return result; +} + +// +// Check if a Value Decreasing in Loopback ... +bool IsDecreasing( + const int from, // Last Time Index + const int to, // Fisr Tima Index + const double &buffer[] // the Buffer which required to search +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + from <= to || + ArraySize(buffer) < from + 1) + { + return result; + } + + // + // Loop through Items ... + double toValue = buffer[to]; + double fromValue = buffer[from]; + result = toValue < fromValue; + for (int i = to + 1; i <= from - 1; i++) + { + // + double iValue = buffer[i]; + bool isPassed = toValue <= iValue; + + // + bool isIDecreasing = IsDecreasing( + from, + i, + buffer); + + // + // Check Result ... + result = result && isPassed && isIDecreasing; + if (!result) + { + break; + } + } + + // + return result; +} + +// +bool IsTrendingUp( + const double &buffer1[], // First Buffer + const double &buffer2[] // Seccend Buffer +) +{ + // + bool result = false; + + // + int buffer1Count = ArraySize(buffer1); + int buffer2Count = ArraySize(buffer2); + if (buffer1Count <= 0 || buffer2Count <= 0) + { + return result; + } + + // + int count = MathMin(buffer1Count, buffer2Count); + if (count <= 1) + { + return result; + } + + // + int upCounts = 0; + int downCounts = 0; + double value = MathAbs(buffer1[0] - buffer2[0]); + for (int i = 1; i < count; i++) + { + // + double iValue = MathAbs(buffer1[i] - buffer2[i]); + + // + if (value > iValue) + { + upCounts++; + } + + // + if (value < iValue) + { + downCounts++; + } + } + + // + result = upCounts > 1 && upCounts > downCounts; + + // + return result; +} + +// +bool IsTrendingDown( + const double &buffer1[], // First Buffer + const double &buffer2[] // Seccend Buffer +) +{ + // + bool result = false; + + // + int buffer1Count = ArraySize(buffer1); + int buffer2Count = ArraySize(buffer2); + if (buffer1Count <= 0 || buffer2Count <= 0) + { + return result; + } + + // + int count = MathMin(buffer1Count, buffer2Count); + if (count <= 1) + { + return result; + } + + // + int upCounts = 0; + int downCounts = 0; + double value = MathAbs(buffer1[0] - buffer2[0]); + for (int i = 1; i < count; i++) + { + // + double iValue = MathAbs(buffer1[i] - buffer2[i]); + + // + if (value > iValue) + { + upCounts++; + } + + // + if (value < iValue) + { + downCounts++; + } + } + + // + result = downCounts > 1 && downCounts > upCounts; + + // + return result; +} + +// +// Calculate Slope of Specified Buffer at Specified Index ... +double GetSlope( + const double &buffer[], // Buffer + int from, // In Past Index ... + int to // In Past Index ... +) +{ + // + double result = 0; + + // + if (from > ArraySize(buffer) || to > ArraySize(buffer)) + { + return result; + } + + // + double toValue = buffer[to]; + double fromValue = buffer[from]; + double deltaValue = toValue - fromValue; + double deltaTime = from - to; + + // + result = deltaValue / deltaTime; + + // + return result; +} + +// +// Calculate Fib Level ... +double GetFibonacciLevel( + double upPrice, // Upper Bound + double downPrice, // Downer Bound + double level, // Level Multiplier Factor + int direction // From Down to Up < 0, other wise Vice Versa + // +) +{ + // + double ling = upPrice - downPrice; + double pLevel = (ling / 100) * (level * 100); + + // + double result = direction > 0 ? upPrice - pLevel : downPrice + pLevel; + + // + return result; +} + +// +double MAOnArray( + double &array[], + int total, + int period, + int ma_shift, + int ma_method, + int shift // +) +{ + // + double result = 0; + + // + double buf[]; + double arr[]; + + // + if (total == 0) + { + total = ArraySize(array); + } + + // + if (total > 0 && total <= period) + { + return result; + } + + // + if (shift > total - period - ma_shift) + { + return result; + } + + // + // MA Method ... + switch (ma_method) + { + // + // Mode SMA ... + case MODE_SMA: { + // + total = ArrayCopy(arr, array, 0, shift + ma_shift, period); + if (ArrayResize(buf, total) < 0) + { + return result; + } + + // + double sum = 0; + int i, pos = total - 1; + for (i = 1; i < period; i++, pos--) + { + sum += arr[pos]; + } + + // + while (pos >= 0) + { + // + sum += arr[pos]; + buf[pos] = sum / period; + sum -= arr[pos + period - 1]; + pos--; + } + + // + result = buf[0]; + return result; + } + + // + // Mode EMA ... + case MODE_EMA: { + // + if (ArrayResize(buf, total) < 0) + { + return result; + } + + // + int pos = total - 2; + double pr = 2.0 / (period + 1); + + // + while (pos >= 0) + { + // + if (pos == total - 2) + { + buf[pos + 1] = array[pos + 1]; + } + + // + buf[pos] = array[pos] * pr + buf[pos + 1] * (1 - pr); + pos--; + } + + // + result = buf[shift + ma_shift]; + return result; + } + + // + // Mode SMMA ... + case MODE_SMMA: { + // + if (ArrayResize(buf, total) < 0) + { + return result; + } + + // + int i, kk, pos; + double sum = 0; + pos = total - period; + + // + while (pos >= 0) + { + // + if (pos == total - period) + { + // + for (i = 0, kk = pos; i < period; i++, kk++) + { + // + sum += array[kk]; + buf[kk] = 0; + } + } + else + { + sum = buf[pos + 1] * (period - 1) + array[pos]; + } + + // + buf[pos] = sum / period; + pos--; + } + + // + result = buf[shift + ma_shift]; + return result; + } + + // + // Mode LWMA ... + case MODE_LWMA: { + // + if (ArrayResize(buf, total) < 0) + { + return result; + } + + // + double price; + double sum = 0.0, lsum = 0.0; + int i, weight = 0, pos = total - 1; + + // + for (i = 1; i <= period; i++, pos--) + { + // + price = array[pos]; + sum += price * i; + lsum += price; + weight += i; + } + + // + pos++; + i = pos + period; + while (pos >= 0) + { + // + buf[pos] = sum / weight; + if (pos == 0) + { + break; + } + + // + i--; + pos--; + price = array[pos]; + sum = sum - lsum + price * period; + lsum -= array[i]; + lsum += price; + } + + // + result = buf[shift + ma_shift]; + return result; + } + + // + default: + return result; + } + + // + return result; +} + +// +// Method 1 +// Normalize between 1 and 0 ... +template +double GetNormalizedValueMethod1( + T &buffer[], // Array which required to Normalize + int mLength, // Length of Normalization + int mStart = 0, // start index + int digits = 5 // Normalization Digits +) +{ + // + double result = 0; + + // + if (digits <= 5) + { + digits = 5; + } + + // + int bufferSize = ArraySize(buffer); + if (!IsValidSize(bufferSize)) + { + return result; + } + + // + // Normalize Count ... + NormalizeCount( + mStart, + mLength, + buffer // + ); + + // + T max = 0; + T min = 0; + + // + if (bufferSize != mLength) + { + // + T tmp[]; + Copy( + mStart, + mLength, + buffer, + tmp // + ); + + // + max = GetMax(tmp); + min = GetMin(tmp); + } + + // + if (bufferSize == mLength) + { + // + max = GetMax(buffer); + min = GetMin(buffer); + } + + // + T iValue = buffer[mStart]; + + // + double minMaxDiff = (max - min); + if (minMaxDiff <= 0) + { + return result; + } + + // + result = (iValue - min) / minMaxDiff; + + // + result = NormalizeDouble(result, digits); + + // + return result; +} + +// +// Method 2 +// Normalize Between Specified Upper and Lower ... +template +double GetNormalizedValueMethod2( + T &buffer[], // Array which required to Normalize + int mLength, // Length of Normalization + int mUpper, // Specified Upper Value + int mLower, // Specified Lower Value + int mStart = 0, // start index + int digits = 5 // Normalization Digits +) +{ + // + double result = 0; + + // + if (digits <= 5) + { + digits = 5; + } + + // + int bufferSize = ArraySize(buffer); + if (!IsValidSize(bufferSize)) + { + return result; + } + + // + // Normalize Count ... + NormalizeCount( + mStart, + mLength, + buffer // + ); + + // + T max = 0; + T min = 0; + + // + if (bufferSize != mLength) + { + // + T tmp[]; + Copy( + mStart, + mLength, + buffer, + tmp // + ); + + // + max = GetMax(tmp); + min = GetMin(tmp); + } + + // + if (bufferSize == mLength) + { + // + max = GetMax(buffer); + min = GetMin(buffer); + } + + // + T iValue = buffer[mStart]; + + // + double minMaxDiff = (max - min); + double boundaryDiff = (mUpper - mLower); + if (minMaxDiff <= 0 || boundaryDiff <= 0) + { + return result; + } + + // + result = boundaryDiff / (minMaxDiff * (iValue - max) + max); + + // + result = NormalizeDouble(result, digits); + + // + return result; +} + +// +void NormalizeBuffer( + double &source[], // Source Buffer + double &dest[], // Result Buffer + double upper = 100, // Upper Value to Normalize + double lower = -100, // Lower Value to Normalize + int size = -1, // Size Of Normalization + int digits = 5 // Digits for Result +) +{ + // + if (size <= 0) + { + size = ArraySize(source); + } + + // + bool asSeriesFlag = ArrayGetAsSeries(source); + + // + ArraySetAsSeries(source, false); + ArraySetAsSeries(dest, false); + + // + double min = ArrayMinimum(source, 0, size); + double max = ArrayMaximum(source, 0, size); + + // + for (int i = 0; i < size; i++) + { + // + double iNormal = lower + ((source[i] - min) / (max - min)) * (upper - lower); + + // + if (digits > 0) + { + iNormal = NormalizeDouble(iNormal, digits); + } + + // + dest[i] = iNormal; + } + + // + ArraySetAsSeries(source, asSeriesFlag); + ArraySetAsSeries(dest, asSeriesFlag); +} + +// +// Templates ... + +// +// Retrieve Specific Object Types Name ... +template +string GetTypeName(const T &t) +{ + return typename(T); +} + +// +template +string GetToken(T &item) +{ + // + string mType = GetTypeName(item); + + // + string result = mType; + + // + string parts[]; + int partsCount = SplitContent( + parts, + result, + " " + // + ); + if (partsCount <= 0) + { + // + result = mType; + return result; + } + + // + bool hasLastPart = GetLastItem( + result, + parts + // + ); + if (!hasLastPart) + { + // + result = mType; + return result; + } + + // + return result; +} + +// +// Same as Get Token for Use in Classes ... +template +string GetSpecificToken(T &item) +{ + // + string mType = GetTypeName(item); + + // + string result = mType; + + // + string parts[]; + int partsCount = SplitContent( + parts, + result, + " " + // + ); + if (partsCount <= 0) + { + // + result = mType; + return result; + } + + // + bool hasLastPart = GetLastItem( + result, + parts + // + ); + if (!hasLastPart) + { + // + result = mType; + return result; + } + + // + return result; +} + +// +// Generate Unique Tags ... +template +string GenerateTag(T &model) +{ + // + string result = ""; + + // + string tag = model.ToString(); + if (StringLen(tag) == 0) + { + return result; + } + + // + static XSCMD5 md5; + + // + result = md5.Hash(tag); + + // + return result; +} + +// +// Hash Specified Content ... +template +string ToMD5(T content) +{ + // + string result = ""; + + // + string strContent = ToString(content); + if (StringLen(strContent) == 0) + { + return result; + } + + // + static XCMD5 md5; + + // + result = md5.Hash(strContent); + + // + return result; +} + +// +// Check a Value Not Empty ... +template +bool NotEmpty(T value) +{ + return value != EMPTY_VALUE; +} + +// +// Check a Value Not Empty and Zero ... +template +bool NotEmptyZero(T value) +{ + return value != EMPTY_VALUE && value != 0; +} + +// +// Add Specified Item to Array ... +template +int Add( + T item, // item want to add + T &buffer[] // Destination buffer +) +{ + // + int result = 0; + + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; + + // + result = ArraySize(buffer); + + // + return result; +} +template +int AddSpecific( + T item, // item want to add + T &buffer[] // Destination buffer +) +{ + // + return Add( + item, + buffer // + ); +} +template +int AddRef( + T &item, // item want to add + T &buffer[] // Destination buffer +) +{ + // + int result = 0; + + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; + + // + result = ArraySize(buffer); + + // + return result; +} + +// +// Remove Specified Item from an Array ... +template +bool Remove( + T item, + T &buffer[]) +{ + // + bool result = false; + + // + int itemIndex = FindIndex( + item, + buffer); + if (itemIndex < 0) + { + return result; + } + + // + result = ArrayRemove( + buffer, + itemIndex, + 1); + + // + return result; +} + +// +// Clean Specified Array ... +template +void Clean(T &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +template +void SpecificClean(T &buffer[]) +{ + Clean(buffer); +} + +// +// Copy Whole Content of Source to Dest array ... +template +void Copy( + T &source[], // Source Buffer ... + T &dest[], // Dest Buffer ... + bool cleanDest = true // Force Clen Dest Buffer ... +) +{ + // + if (cleanDest) + { + Clean(dest); + } + + // + int sourceCount = ArraySize(source); + if (sourceCount <= 0) + { + return; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + T iSource = source[i]; + + // + AddRef( + iSource, + dest); + } +} + +// +// Copy Items from a Buffer ... +template +int Copy( + int start, // Start + int count, // Number of Items for read + T &source[], // Source Buffer + T &dest[], // Dest Buffer + bool forceClean = true, // Force To Clean buffer + bool forceStart = true // Force To Clean buffer +) +{ + // + int result = 0; + + // + if (forceClean) + { + Clean(dest); + } + + // + if (start < 0 && forceStart) + { + start = 0; + } + + // + if (start >= ArraySize(source)) + { + start = ArraySize(source) - 1; + } + + // + if (count == 0) + { + count = ArraySize(source) - 1 - start; + } + + // + if (start + count > ArraySize(source)) + { + return result; + } + + // + int beforeSize = ArraySize(dest); + + // + bool asSeriesDest = ArrayGetAsSeries(dest); + bool asSeriesSource = ArrayGetAsSeries(source); + + // + ArraySetAsSeries(dest, true); + ArraySetAsSeries(source, true); + + // + ArrayCopy( + dest, + source, + 0, + start, + count + // + ); + + // + int afterSize = ArraySize(dest); + + // + result = afterSize - beforeSize; + + // + ArraySetAsSeries(dest, asSeriesDest); + ArraySetAsSeries(source, asSeriesSource); + + // + return result; +} + +// +// Copy Items from a Buffer ... +template +int CopyRef( + int start, // Start + int count, // Number of Items for read + T &source[], // Source Buffer + T &dest[], // Dest Buffer + bool forceClean = true // Force To Clean buffer +) +{ + // + int result = 0; + + // + if (forceClean) + { + Clean(dest); + } + + // + if (start < 0) + { + start = 0; + } + + // + if (start >= ArraySize(source)) + { + start = ArraySize(source) - 1; + } + + // + int beforeSize = ArraySize(dest); + + // + bool asSeriesDest = ArrayGetAsSeries(dest); + bool asSeriesSource = ArrayGetAsSeries(source); + + // + ArraySetAsSeries(dest, true); + ArraySetAsSeries(source, true); + + // + for (int i = start; i < start + count; i++) + { + // + AddRef( + source[i], + dest + // + ); + } + + // + int afterSize = ArraySize(dest); + + // + result = afterSize - beforeSize; + + // + ArraySetAsSeries(dest, asSeriesDest); + ArraySetAsSeries(source, asSeriesSource); + + // + return result; +} + +// +// Retrive Last Item of Specified Buffer ... +template +bool GetLastItem( + T &item, // Holds Result + T &buffer[] // Specified Buffer +) +{ + // + bool result = false; + + // + int bufferSize = ArraySize(buffer); + if (bufferSize <= 0) + { + return result; + } + + // + item = buffer[bufferSize - 1]; + + // + result = true; + return result; +} + +// +// Search Array For Specific Item ... +template +int FindIndex( + T item, // What is Search ... + T &buffer[] // Search in ... +) +{ + // + int result = -1; + + // + int count = ArraySize(buffer); + if (count <= 0) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + T iT = buffer[i]; + + // + if (iT == item) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// Check an Array Contains Specified Value ... +template +bool Contains( + T item, // What is Search ... + T &buffer[] // Search in ... +) +{ + // + bool result = false; + + // + int idx = FindIndex( + item, + buffer); + result = idx > -1; + + // + return result; +} + +// +// Calculate a Buffer's Sum ... +template +double GetSum( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + double result = 0; + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Calculate Summary ... + for (int i = 0; i < tmpCount; i++) + { + result += buffer[i]; + } + + // + return result; +} + +// +// Calculate a Buffer's Average ... +template +double GetAverage( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + double result = 0; + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Calculate Summary ... + for (int i = 0; i < tmpCount; i++) + { + result += buffer[i]; + } + + // + // Calculate Average ... + result = result / tmpCount; + + // + return result; +} + +// +// Get Max of Specific Loopback of a Buffer ... +template +T GetMax( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T result = 0; + + // + if (count <= 0) + { + count = ArraySize(buffer); + } + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + result = + // + result == 0 || result < iValue + // + ? iValue + // + : result + // + ; + } + + // + return result; +} +template +T GetSpecifiedMax( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMax( + buffer, + start, + count // + ); +} + +// +// Get Min of Specific Loopback of a Buffer ... +template +T GetMin( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T result = 0; + + // + if (count <= 0) + { + count = ArraySize(buffer); + } + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + result = + // + result == 0 || result > iValue + // + ? iValue + // + : result + // + ; + } + + // + return result; +} +template +T GetSpecifiedMin( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMin( + buffer, + start, + count // + ); +} + +// +// Find a Value less than Specified ... +template +T FindLesserThan( + T value, // Specified Value ... + const T &source[], // Source ... + bool isDescend = false // Find Biggest Lesser Value ... +) +{ + // + T result = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source)); + + // + ArrayCopy( + tmp, + source); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue < value) + { + // + result = iValue; + break; + } + } + + // + return result; +} + +// +// Find a Value less than Specified ... +template +T FindBiggerThan( + T value, // Specified Value ... + const T &source[], // Source ... + bool isDescend = false // Find Smallest Bigger Value ... +) +{ + // + T result = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source)); + + // + ArrayCopy( + tmp, + source); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (!isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue > value) + { + // + result = iValue; + break; + } + } + + // + return result; +} + +// +// Find Same Values in Array ... +template +void FindSames( + T &result[], // Holds Result ... + T &source[], // Source ... + int verifications = 3 // Number of Consequence Repeat ... +) +{ + // + Clean(result); + + // + // TenkanSen Flats ... + int sourceCount = ArraySize(source); + if (sourceCount > verifications) + { + // + T mLast = 0; + int mVerified = 0; + for (int i = 0; i < sourceCount; i++) + { + // + T iVal = source[i]; + if (mLast == 0) + { + mLast = iVal; + } + else if (mLast == iVal) + { + mVerified++; + } + else + { + mLast = iVal; + mVerified = 0; + } + + // + if (iVal == mLast && mVerified >= verifications) + { + // + Add( + iVal, + result); + + // + mLast = 0; + mVerified = 0; + } + } + } +} + +// +// Add an Item to a Buffer if not Exists ... +void AddIfNotExists( + double value, + double &values[], + double smoothingPoint = 3) +{ + // + double smoothingValue = smoothingPoint * GetPoints(_Symbol); + + // + int valuesCount = ArraySize(values); + if (valuesCount <= 0) + { + // + Add(value, + values); + } + else + { + // + bool isExists = false; + for (int i = 0; i < valuesCount; i++) + { + // + double iVal = values[i]; + + // + double diff = MathAbs(iVal - value); + + // + if (iVal == value || diff < smoothingValue) + { + // + isExists = true; + break; + } + } + + // + if (!isExists) + { + // + Add(value, + values); + } + } +} + +// +// Add a Buffers Child to another Buffer +// if it's not Contains them ... +void AddsIfNotExists( + double &source[], + double &dest[], + double smoothingPoint = 3) +{ + // + double smoothingValue = smoothingPoint * GetPoints(_Symbol); + + // + int sourceCount = ArraySize(source); + if (sourceCount <= 0) + { + return; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + double iSource = source[i]; + + // + AddIfNotExists( + iSource, + dest, + smoothingPoint); + } +} + +// +// Bar XOHCL ... + +// +// Extract Specific Range of Bars ... +// using Start Bar Index ... +int GetBars( + XOHCL &result[], // Hold Result + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Time Frame + int from = 0, // Start Bar Index + int count = 1, // Number of Bars + bool forceClean = true // Clean Result Array +) +{ + // + int mResult = 0; + + // + if (from < 0) + { + from = 0; + } + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int total = Bars( + mSymbol, + mPeriod); + if (from > total - 2) + { + from = total - 2; + } + + // + if (count < 0) + { + count = 1; + } + + // + int start = from; + int end = start + count; + if (end > total - 1) + { + end = total - 1; + } + + // + if (forceClean) + { + Clean(result); + } + + // + int beforeSize = ArraySize(result); + + // + for (int i = start; i < end; i++) + { + // + XOHCL iBar; + bool isValid = iBar.Init( + mSymbol, + mPeriod, + i + // + ); + + // + if (isValid) + { + // + AddRef( + iBar, + result + // + ); + } + } + + // + int afterSize = ArraySize(result); + + // + mResult = afterSize - beforeSize; + + // + return mResult; +} + +// +// Extract Specific Range of Bars ... +// using Start Bar Time ... +int GetBars( + XOHCL &result[], // Hold Result + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Time Frame + datetime from = NULL, // Start Bar Time + int count = 1, // Number of Bars + bool forceClean = true // Clean Result Array +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + from = NormalizeTime(from); + + // + int barIndex = iBarShift( + mSymbol, + mPeriod, + from, + false + // + ); + + // + return GetBars( + result, + mSymbol, + mPeriod, + barIndex, + count, + forceClean + // + ); +} + +// +// String ... + +// +// Search a Content Contains Specific String or not ... +bool Contains( + string mQuery, // Search String + string mContent, // Search Content + bool ignoreCase = true // Ignore Case +) +{ + // + bool result = false; + + // + // Validate Query ... + result = IsValid(mQuery); + if (!result) + { + return result; + } + + // + // Validate Content ... + result = IsValid(mContent); + if (!result) + { + return result; + } + + // + // Normalize Inputs ... + string query = mQuery; + string content = mContent; + if (ignoreCase) + { + // + StringToLower(query); + StringToLower(content); + } + + // + int queryIdx = StringFind( + content, + query); + + // + result = queryIdx >= 0; + + // + return result; +} + +// +bool Contains( + string &mQueries[], // Search Strings + string mContent, // Search Content + bool ignoreCase = true // Ignore Case +) +{ + // + bool result = false; + + // + // Validate Queries ... + int queriesCount = ArraySize(mQueries); + result = queriesCount > 0; + if (!result) + { + return result; + } + + // + // Validate Content ... + result = IsValid(mContent); + if (!result) + { + return result; + } + + // + int containsCount = 0; + for (int i = 0; i < queriesCount; i++) + { + // + bool isContains = Contains( + mQueries[i], + mContent, + ignoreCase); + + // + if (!isContains) + { + // + result = false; + break; + } + + // + containsCount++; + } + + // + result = containsCount == queriesCount; + + // + return result; +} + +// +int FindIndexes( + string mQuery, // Search String + string mContent, // Search Content + int &result[], // Holding Results + bool ignoreCase = false // Ignore Case +) +{ + // + int mResult = 0; + + // + Clean(result); + + // + // Validate Inputs ... + if (!IsValid(mQuery) || + !IsValid(mContent)) + { + return mResult; + } + + // + // Apply Ignore Case if Provided ... + if (ignoreCase) + { + // + bool isConverted = StringToLower(mQuery); + if (!isConverted) + { + return mResult; + } + + // + isConverted = StringToLower(mContent); + if (!isConverted) + { + return mResult; + } + } + + // + // Search First Index ... + int lastPos = 0; + int idx = StringFind( + mContent, + mQuery, + lastPos // + ); + while (idx >= 0) + { + // + // Add Position to Result ... + Add( + idx, + result // + ); + + // + lastPos = idx + StringLen(mQuery); + idx = StringFind( + mContent, + mQuery, + lastPos // + ); + } + + // + mResult = ArraySize(result); + + // + return mResult; +} + +// +// Convert From String ... +template +T FromString(string value) +{ + // + T result = NULL; + + // + if (!IsValid(value)) + { + return result; + } + + // + result = (T)value; + + // + return result; +} + +// +// Converts an item to String ... +template +string ToString(T value) +{ + return (string)value; +} + +// +// Used In Report or Summary Generators ... +string ToString( + string prefix, // Title + bool value, // Value + bool ignoreFalseConditions = true, // Ignore False Conditions + string lineSeparator = "\n", // Line Separator + string prefixSeparator = ":" // Title Separator +) +{ + // + string result = NULL; + + // + result = (value || !ignoreFalseConditions) + ? prefix + + prefixSeparator + " " + + ToString(value) + + lineSeparator + : ""; + + // + return result; +} + +// +template +string ToString( + string prefix, // Title + T value, // Value + string lineSeparator = "\n", // Line Separator + string prefixSeparator = ":" // Title Separator +) +{ + // + string result = NULL; + + // + result = prefix + + prefixSeparator + " " + + ToString(value) + + lineSeparator; + + // + return result; +} + +// +string SetLabel( + string mLabel, // Provided Label ... + string value, // Source Value ... + string separator = "\n", // Line Separator + bool addTopEmptyLine = true // Add Empty Line On top +) +{ + // + string result = value; + + // + if (StringLen(mLabel) <= 0) + { + return result; + } + + // + result = (StringLen(value) > 0) + ? (addTopEmptyLine ? separator : "") + + mLabel + + separator + + "-----------------------------" + + separator + + value + : value; + + // + return result; +} + +// +// Converts a Buffer to String Representation ... +template +string ToString( + const T &buffer[], // Specified Buffer + string separator = ",", // Specified Separator + bool addIndex = false, // Specified Add Items Indexes or Not + string indexLabel = "i:", // Specified Index Label + string indexSeparator = ">" // Specified Index Separator +) +{ + // + string result = ""; + + // + int bufferSize = ArraySize(buffer); + if (bufferSize <= 0) + { + return result; + } + + // + for (int i = 0; i < bufferSize; i++) + { + // + if (addIndex) + { + // + if (StringLen(indexLabel) > 0) + { + result += indexLabel + " "; + } + + // + result += (string)i + " "; + + // + if (StringLen(indexSeparator) > 0) + { + result += indexSeparator + " "; + } + } + + // + string iItemString = (string)buffer[i]; + + // + result += iItemString; + + // + if (i < bufferSize - 1) + { + result += separator; + } + } + + // + return result; +} + +// +// Converts String to boolean ... +bool ToBoolean(string value) +{ + // + bool result = false; + + // + if (StringLen(value) <= 0) + { + return result; + } + + // + StringToLower(value); + result = value == "true"; + + // + return result; +} + +// +// Split an String Representation of an Array ... +int SplitContent( + string &result[], // Hold Result ... + string content, // Source ... + string separator = ",", // Separator ... + bool forceCleanResult = true // Clean Result ... +) +{ + // + int mResult = 0; + + // + if (forceCleanResult) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + if (separator == NULL || StringLen(separator) == 0) + { + separator = ","; + } + + // + if (StringLen(content) == 0) + { + return mResult; + } + + // + StringSplit( + content, + StringGetCharacter( + separator, + 0), + result); + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; +} + +// +// Extract Data from String ... +string ExtractString( + const string source, // Source String used for Extracting + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + string result = ""; + + // + // Validate String ... + if ( + StringLen(source) == 0 || + StringLen(endString) == 0 || + StringLen(startString) == 0) + { + return result; + } + + // + // Find Start String Position ... + int sPos = StringFind( + source, + startString); + if (sPos < 0) + { + return result; + } + + // + // Find End String Position after Start String ... + int searchEndFromPos = sPos + StringLen(startString); + int ePos = StringFind( + source, + endString, + searchEndFromPos); + if (ePos < 0) + { + return result; + } + + // + // Extract Data from Source ... + int dLength = ePos - searchEndFromPos; + result = StringSubstr( + source, + searchEndFromPos, + dLength); + + // + return result; +} + +// +// Extract an Array of Contents ... +int ExtractStrings( + string &result[], // Hold Result + const string source, // Source String used for Extracting + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + int mResult = 0; + + // + Clean(result); + + // + // Validate Args ... + int sourceLength = StringLen(source); + int startLength = StringLen(startString); + int endLength = StringLen(endString); + + // + int minRequiredLength = startLength + endLength; + + // + if ( + endLength <= 0 || + startLength <= 0 || + sourceLength <= 0 || + sourceLength < minRequiredLength) + { + return mResult; + } + + // + // Make a Copy of Source for Manipulating ... + string workStr = source; + + // + // Define a Loop ... + while (StringLen(workStr) > minRequiredLength) + { + // + // Find Item ... + string item = ExtractString( + workStr, + startString, + endString); + + // + // Breakout when couldn't find anymore item ... + int itemLength = StringLen(item); + if (itemLength <= 0) + { + break; + } + + // + // Prepare Item Source String for Replacing in Work String ... + string itemSource = startString + item + endString; + + // + // Add Item to Result Array ... + Add( + item, + result); + + // + // Replace Item Soure in Work String ... + StringReplace( + workStr, + itemSource, + ""); + } + + // + // Calculate Size of Array ... + mResult = ArraySize(result); + + // + return mResult; +} + +// +string ExtractSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + return ExtractString( + surrounded, + mToken + startString, + endString + // + ); +} + +// +int ParseIntSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + int result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (int)strContent; + + // + return result; +} +long ParseLongSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + long result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (long)strContent; + + // + return result; +} +string ParseStringSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + string result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (string)strContent; + + // + return result; +} +double ParseDoubleSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + double result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (double)strContent; + + // + return result; +} +datetime ParseTimeSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + datetime result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (datetime)strContent; + + // + return result; +} + +// +int ParseIntArraySurrounded( + int &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + int iValue = (int)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} +int ParseLongArraySurrounded( + long &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + long iValue = (long)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} +int ParseDoubleArraySurrounded( + double &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + double iValue = (double)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} +int ParseTimeArraySurrounded( + datetime &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + datetime iValue = (datetime)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} + +// +// Surround an String by Specific Token ... +template +string Surround( + string mToken, // an String which used to Tokenize + T &value, // a Value for Tokenize it + string startString = "(", // Token Start Content + string endString = ")" // Token End Content +) +{ + // + string result = NULL; + + // + string strValue = ToString(value); + if (!IsValid(strValue)) + { + return result; + } + + // + result = + // + (IsValid(mToken) + ? mToken + : "") + + // + startString + + strValue + + endString + // + ; + + // + return result; +} + +// +template +string SurroundArray( + string mToken, + T &value[], + string startString = "(", // Token Start Content + string endString = ")" // Token End Content +) +{ + // + string result = NULL; + + // + string valueStr = ToString(value); + if (!IsValid(valueStr)) + { + return result; + } + + // + result = Surround( + mToken, + valueStr, + startString, + endString + // + ); + + // + return result; +} + +// +// Periods / Cycles ... + +// +// Converts an String to TimeFrame ... +ENUM_TIMEFRAMES ToPeriod(string value) +{ + // + if (StringLen(value) == 0) + { + return _Period; + } + + // + StringTrimLeft(value); + StringTrimRight(value); + + // + ENUM_TIMEFRAMES result = _Period; + + // + if (value == "M1") + { + result = PERIOD_M1; + } + else if (value == "M2") + { + result = PERIOD_M2; + } + else if (value == "M3") + { + result = PERIOD_M3; + } + else if (value == "M4") + { + result = PERIOD_M4; + } + else if (value == "M5") + { + result = PERIOD_M5; + } + else if (value == "M6") + { + result = PERIOD_M6; + } + else if (value == "M10") + { + result = PERIOD_M10; + } + else if (value == "M12") + { + result = PERIOD_M12; + } + else if (value == "M15") + { + result = PERIOD_M15; + } + else if (value == "M20") + { + result = PERIOD_M20; + } + else if (value == "M30") + { + result = PERIOD_M30; + } + else if (value == "H1") + { + result = PERIOD_H1; + } + else if (value == "H2") + { + result = PERIOD_H2; + } + else if (value == "H3") + { + result = PERIOD_H3; + } + else if (value == "H4") + { + result = PERIOD_H4; + } + else if (value == "H6") + { + result = PERIOD_H6; + } + else if (value == "H8") + { + result = PERIOD_H8; + } + else if (value == "H12") + { + result = PERIOD_H12; + } + else if (value == "D1") + { + result = PERIOD_D1; + } + else if (value == "W1") + { + result = PERIOD_W1; + } + else if (value == "MN1") + { + result = PERIOD_MN1; + } + + // + return result; +} + +// +// Converts Period to String ... +string ToString(ENUM_TIMEFRAMES mPeriod) +{ + // + string result = ""; + + // + string mPStr = EnumToString(mPeriod); + + string mPStrParts[]; + int partsCount = StringSplit( + mPStr, + StringGetCharacter("_", 0), + mPStrParts); + if (partsCount <= 0) + { + return result; + } + + // + result = mPStrParts[1]; + + // + return result; +} + +// +// Retrieve All Available Period as an Array ...s +int GetAllAvailablePeriods( + ENUM_TIMEFRAMES &result[] // Holds Result ... +) +{ + // + Clean(result); + + // + Add( + PERIOD_M1, + result + // + ); + + // + Add( + PERIOD_M2, + result + // + ); + + // + Add( + PERIOD_M3, + result + // + ); + + // + Add( + PERIOD_M4, + result + // + ); + + // + Add( + PERIOD_M5, + result + // + ); + + // + Add( + PERIOD_M6, + result + // + ); + + // + Add( + PERIOD_M10, + result + // + ); + + // + Add( + PERIOD_M12, + result + // + ); + + // + Add( + PERIOD_M15, + result + // + ); + + // + Add( + PERIOD_M20, + result + // + ); + + // + Add( + PERIOD_M30, + result + // + ); + + // + Add( + PERIOD_H1, + result + // + ); + + // + Add( + PERIOD_H2, + result + // + ); + + // + Add( + PERIOD_H3, + result + // + ); + + // + Add( + PERIOD_H4, + result + // + ); + + // + Add( + PERIOD_H6, + result + // + ); + + // + Add( + PERIOD_H8, + result + // + ); + + // + Add( + PERIOD_H12, + result + // + ); + + // + Add( + PERIOD_D1, + result + // + ); + + // + Add( + PERIOD_W1, + result + // + ); + + // + Add( + PERIOD_MN1, + result + // + ); + + // + int mResult = ArraySize(result); + + // + return mResult; +} + +// +// Get Specific Time Frame Start Candle Time ... +datetime GetPeriodStartTime( + string mSymbol = NULL, // Specified Symbol ... + ENUM_TIMEFRAMES mPeriod = NULL, // Specified Period ... + datetime mTime = NULL // Specified Bar Time of Host Period ... +) +{ + // + // Normalize Arg ... + mTime = NormalizeTime(mTime); + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int barIndex = iBarShift( + mSymbol, + mPeriod, + mTime, + false + // + ); + + // + datetime result = GetBarTime( + mSymbol, + mPeriod, + barIndex + // + ); + + // + return result; +} + +// +// Converts an String to it's related Market Cycle ... +ENUM_X_MARKET_CYCLES ToCycle(string value) +{ + // + ENUM_X_MARKET_CYCLES result = X_MARKET_CYCLE_UNKNOWN; + + // + ENUM_X_MARKET_CYCLES cycles[]; + int count = GetAllMarketCycles(cycles); + for (int i = 0; i < count; i++) + { + // + ENUM_X_MARKET_CYCLES iCycle = cycles[i]; + string iStr = ToString(iCycle); + + // + if (value == iStr) + { + // + result = iCycle; + break; + } + } + + // + return result; +} + +// +// Converts a Cycle to it's String Representation ... +string ToString(ENUM_X_MARKET_CYCLES cycle) +{ + // + string result = ""; + + // + string mPStr = EnumToString(cycle); + + string mPStrParts[]; + int partsCount = StringSplit( + mPStr, + StringGetCharacter("_", 0), + mPStrParts); + if (partsCount <= 0) + { + return result; + } + + // + result = mPStrParts[3]; + + // + return result; +} + +// +// Retrieve all Available Cycles ... +int GetAllMarketCycles(ENUM_X_MARKET_CYCLES &result[]) +{ + // + int mResult = 0; + + // + Clean(result); + + // + ENUM_X_MARKET_CYCLES tmp[] = { + X_MARKET_CYCLE_UNKNOWN, + X_MARKET_CYCLE_SHORT, + X_MARKET_CYCLE_MEDIUM, + X_MARKET_CYCLE_LONG, + X_MARKET_CYCLE_HIND}; + + // + Copy( + tmp, + result // + ); + + // + Clean(tmp); + + // + mResult = ArraySize(result); + + // + return mResult; +} + +// +// Retrieve Nearest Period base on Given Period ... +ENUM_TIMEFRAMES GetNearestPeriod(ENUM_TIMEFRAMES mPeriod) +{ + // + ENUM_TIMEFRAMES result = _Period; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + result = PERIOD_M4; + break; + + // + case PERIOD_M3: + case PERIOD_M4: + result = PERIOD_M6; + break; + + // + case PERIOD_M5: + case PERIOD_M6: + case PERIOD_M10: + case PERIOD_M12: + result = PERIOD_M15; + break; + + // + case PERIOD_M15: + case PERIOD_M20: + result = PERIOD_M30; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + result = PERIOD_H4; + break; + + // + case PERIOD_H6: + case PERIOD_H8: + result = PERIOD_H12; + break; + + // + case PERIOD_H12: + result = PERIOD_D1; + break; + + // + case PERIOD_D1: + result = PERIOD_W1; + break; + + // + default: + result = PERIOD_MN1; + break; + } + + // + return result; +} + +// +// Retrieve Mediest Period base on Given Period ... +ENUM_TIMEFRAMES GetMediestPeriod(ENUM_TIMEFRAMES mPeriod) +{ + // + ENUM_TIMEFRAMES result = _Period; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + result = PERIOD_M15; + break; + + // + case PERIOD_M3: + case PERIOD_M4: + result = PERIOD_M30; + break; + + // + case PERIOD_M5: + case PERIOD_M6: + case PERIOD_M10: + case PERIOD_M12: + result = PERIOD_H1; + break; + + // + case PERIOD_M15: + case PERIOD_M20: + result = PERIOD_H2; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + result = PERIOD_H8; + break; + + // + case PERIOD_H6: + case PERIOD_H8: + result = PERIOD_D1; + break; + + // + case PERIOD_H12: + result = PERIOD_W1; + break; + + // + case PERIOD_D1: + result = PERIOD_MN1; + break; + + // + default: + result = PERIOD_MN1; + break; + } + + // + return result; +} + +// +// Retrieve Longest Period base on Given Period ... +ENUM_TIMEFRAMES GetLongestPeriod(ENUM_TIMEFRAMES mPeriod) +{ + // + ENUM_TIMEFRAMES result = _Period; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + result = PERIOD_M30; + break; + + // + case PERIOD_M3: + case PERIOD_M4: + result = PERIOD_H1; + break; + + // + case PERIOD_M5: + case PERIOD_M6: + case PERIOD_M10: + case PERIOD_M12: + result = PERIOD_H2; + break; + + // + case PERIOD_M15: + case PERIOD_M20: + result = PERIOD_H4; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + result = PERIOD_H12; + break; + + // + case PERIOD_H6: + case PERIOD_H8: + result = PERIOD_W1; + break; + + // + case PERIOD_H12: + result = PERIOD_MN1; + break; + + // + case PERIOD_D1: + result = PERIOD_MN1; + break; + + // + default: + result = PERIOD_MN1; + break; + } + + // + return result; +} + +// +// Retrieve Hindmost Period base on Given Period ... +ENUM_TIMEFRAMES GetHindMostPeriod(ENUM_TIMEFRAMES mPeriod) +{ + // + ENUM_TIMEFRAMES result = _Period; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + result = PERIOD_H1; + break; + + // + case PERIOD_M3: + case PERIOD_M4: + result = PERIOD_H2; + break; + + // + case PERIOD_M5: + case PERIOD_M6: + case PERIOD_M10: + case PERIOD_M12: + result = PERIOD_H4; + break; + + // + case PERIOD_M15: + case PERIOD_M20: + result = PERIOD_H8; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + result = PERIOD_D1; + break; + + // + case PERIOD_H6: + case PERIOD_H8: + result = PERIOD_MN1; + break; + + // + case PERIOD_H12: + result = PERIOD_MN1; + break; + + // + case PERIOD_D1: + result = PERIOD_MN1; + break; + + // + default: + result = PERIOD_MN1; + break; + } + + // + return result; +} + +// +// Retrieve Specified Cycles Period related to Host Period ... +ENUM_TIMEFRAMES GetCyclePeriod( + ENUM_X_MARKET_CYCLES mCycle = NULL, // Specified Cycle + ENUM_TIMEFRAMES mPeriod = NULL // Host Period +) +{ + // + ENUM_TIMEFRAMES result = NULL; + + // + mPeriod = NormalizePeriod(mPeriod); + mCycle = NormalizeCycle(mCycle); + + // + switch (mCycle) + { + // + // Short ... + case X_MARKET_CYCLE_SHORT: + result = GetNearestPeriod(mPeriod); + break; + + // + // Medium ... + case X_MARKET_CYCLE_MEDIUM: + result = GetMediestPeriod(mPeriod); + break; + + // + // Long ... + case X_MARKET_CYCLE_LONG: + result = GetLongestPeriod(mPeriod); + break; + + // + // Hind ... + case X_MARKET_CYCLE_HIND: + result = GetHindMostPeriod(mPeriod); + break; + } + + // + return result; +} + +// +// Calculate a Cycle Length based on Host Period ... +int GetCycleLengthOn( + ENUM_TIMEFRAMES _hostPeriod, + ENUM_X_MARKET_CYCLES _cycle, + ENUM_X_PERIOD_METHOD _method, + ENUM_TIMEFRAMES _period // +) +{ + // + int result = 0; + + // + // Validate ... + bool isValid = + // + IsValid(_hostPeriod) && + IsValid(_method, _Period) + // + ; + if (!isValid) + { + return result; + } + + // + // Calculate Period ... + isValid = + _method != X_PERIOD_NOTHING && + _cycle != X_MARKET_CYCLE_UNKNOWN; + if (!isValid) + { + return result; + } + + // + if (_method == X_PERIOD_AUTO) + { + // + _period = GetCyclePeriod( + _cycle, + _hostPeriod // + ); + } + isValid = IsValid(_period); + if (!isValid) + { + return result; + } + + // + int _hostPeriodSeconds = PeriodSeconds(_hostPeriod); + int _periodSeconds = PeriodSeconds(_period); + + // + isValid = _periodSeconds >= _hostPeriodSeconds; + if (!isValid) + { + return result; + } + + // + result = _periodSeconds / _hostPeriodSeconds; + + // + return result; +} + +// +// Direction ... + +// +bool HasDirection(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value != X_DIRECTION_NONE && + value != X_DIRECTION_ALL; + + // + return result; +} + +// +bool IsBullish(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value == X_DIRECTION_BULLISH; + + // + return result; +} +bool IsSpecifiedBullish(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value == X_DIRECTION_BULLISH; + + // + return result; +} + +// +bool IsBearish(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value == X_DIRECTION_BEARISH; + + // + return result; +} +bool IsSpecifiedBearish(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value == X_DIRECTION_BEARISH; + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/x-saherelm.x121.mq5 b/BKPS/14030923/Documents/BKP/x-saherelm.x121.mq5 new file mode 100644 index 0000000..09a94ab --- /dev/null +++ b/BKPS/14030923/Documents/BKP/x-saherelm.x121.mq5 @@ -0,0 +1,2734 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 +// Description: Peaks and Vales ... +// +// +// 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 Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121" + +// +// Includes Common Library ... +#include "../Classes/x-saherelm.x-poi.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input group "Makret Cycles"; + +// +input group "Short"; +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES scPeriod = NULL; // Time Period + +// +input group "Medium"; +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES mcPeriod = NULL; // Time Period + +// +input group "Long"; +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES lcPeriod = NULL; // Time Period + +// +input group "Hind"; +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES hcPeriod = NULL; // Time Period + +// +input group "Boundary Detection Modes"; +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE llMode = MODE_LOW; // Lowest Low Calculation Method + +// +input group "Paraboli Sar Detection"; +input double sarStep = 0.02; // Step +input double sarMax = 0.2; // Maximum + +// +input group "VWap Detection"; +input int vwapFastLength = 20; // Fast Length +input int vwapMidLength = 40; // Mid Length +input int vwapSlowLength = 60; // Slow Length +input ENUM_APPLIED_PRICE vwapAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "Donchain Detection"; +input int donchainLength = 40; // Donchain Length + +// +input group "POI Detector"; +input int poiRequiredItems = 20; // Required POI Detects On Start +input int poiMaxItems = 20; // Max POI Detects Holding +input ENUM_X_MARKET_CYCLES poiCycle = X_MARKET_CYCLE_UNKNOWN; // POI Detector Cycle + +// +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input int sarArrowCode = 159; // Parabolic Sar Arrow Code +input int peaksArrowCode = 159; // Peaks Arrow Code +input int valesArrowCode = 159; // Vales Arrow Code + +// +input bool showSar = true; // Show Parabolic Sar +input bool showPeaks = true; // Show Peaks +input bool showVales = true; // Show Vales +input bool showVWap = true; // Show VWap +input bool showDonchain = true; // Show Donchain +input bool showPOIs = false; // Show POIs + +// +input group "VWap Presentation"; +input bool showVWapFast = false; // Show VWap Fast +input bool showVWapMedium = false; // Show VWap Medium +input bool showVWapSlow = false; // Show VWap Slow + +// +input group "Donchain Presentation"; +input bool showUpper = true; // Show Upper Band +input bool showLower = true; // Show Lower Band +input bool showOpen = true; // Show Open +input bool showHigh = false; // Show High +input bool showClose = true; // Show Close +input bool showLow = false; // Show Low + +// +// Define Variables to Draw POI(s) ... +input group "POI Presentation"; +input bool drawSwingHighs = false; // Draw Swing Highs +input bool drawSwingLows = false; // Draw Swing Lows +input bool drawSupportZones = false; // Draw Support Zones +input bool drawResistanceZones = false; // Draw Resistance Zones +input bool drawSupplyZones = false; // Draw Supply Zones +input bool drawDemandZones = false; // Draw Demand Zones +input bool drawBullishOrderBlocks = false; // Draw Bullish Order Blocks +input bool drawBearishOrderBlocks = false; // Draw Bearish Order Blocks +input bool drawBullishFairValueGaps = false; // Draw Bullish FairValue Gaps +input bool drawBearishFairValueGaps = false; // Draw Bearish FairValue Gaps +input bool drawBullishRejectionBars = false; // Draw Bullish Rejection Bars +input bool drawBearishRejectionBars = false; // Draw Bearish Rejection Bars +input bool drawBullishMomentumBars = false; // Draw Bullish Momentum Bars +input bool drawBearishMomentumBars = false; // Draw Bearish Momentum Bars + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 34 +#property indicator_plots 14 + +// +// PEAKS ... + +// +#define peaksBufferIndex 0 +double peaksBuffer[]; + +// +#property indicator_label1 "X121 PEAKS" +#property indicator_type1 DRAW_ARROW +#property indicator_color1 clrAqua +#property indicator_width1 1 + +// +// VALES ... + +// +#define valesBufferIndex 1 +double valesBuffer[]; + +// +#property indicator_label2 "X121 VALES" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrMagenta +#property indicator_width2 1 + +// +#define sarBufferIndex 2 +double sarBuffer[]; + +// +#property indicator_label3 "X121 SAR" +#property indicator_type3 DRAW_ARROW +#property indicator_color3 clrYellow +#property indicator_width3 1 + +// +// FAST ... +#define vwapFastBufferIndex 3 +double vwapFastBuffer[]; + +#define vwapFastColorBufferIndex 4 +double vwapFastColorBuffer[]; + +// +#define vwapFastPlotBufferIndex 3 +#property indicator_label4 "X121 VWF" +#property indicator_type4 DRAW_COLOR_LINE +#property indicator_color4 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style4 STYLE_SOLID +#property indicator_width4 2 + +// +// MID ... +#define vwapMidBufferIndex 5 +double vwapMidBuffer[]; + +#define vwapMidColorBufferIndex 6 +double vwapMidColorBuffer[]; + +// +#define vwapMidPlotBufferIndex 4 +#property indicator_label5 "X121 VWM" +#property indicator_type5 DRAW_COLOR_LINE +#property indicator_color5 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style5 STYLE_SOLID +#property indicator_width5 2 + +// +// SLOW ... +#define vwapSlowBufferIndex 7 +double vwapSlowBuffer[]; + +#define vwapSlowColorBufferIndex 8 +double vwapSlowColorBuffer[]; + +// +#define vwapSlowPlotBufferIndex 5 +#property indicator_label6 "X121 VWS" +#property indicator_type6 DRAW_COLOR_LINE +#property indicator_color6 CLR_NONE, clrSteelBlue, clrDarkRed, clrGray +#property indicator_style6 STYLE_SOLID +#property indicator_width6 2 + +// +// XDON ... + +// +// Open ... + +// +#define donOpenUpperBufferIndex 9 +double donOpenUpperBuffer[]; + +// +#define donOpenUpperPlotBufferIndex 6 +#property indicator_label7 "X121 O U" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrCornflowerBlue +#property indicator_width7 1 + +// +#define donOpenLowerBufferIndex 10 +double donOpenLowerBuffer[]; + +// +#define donOpenLowerPlotBufferIndex 7 +#property indicator_label8 "X121 O L" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrCornflowerBlue +#property indicator_width8 1 + +// +// High ... + +// +#define donHighUpperBufferIndex 11 +double donHighUpperBuffer[]; + +// +#define donHighUpperPlotBufferIndex 8 +#property indicator_label9 "X121 H U" +#property indicator_type9 DRAW_LINE +#property indicator_color9 clrAquamarine +#property indicator_width9 1 + +// +#define donHighLowerBufferIndex 12 +double donHighLowerBuffer[]; + +// +#define donHighLowerPlotBufferIndex 9 +#property indicator_label10 "X121 H L" +#property indicator_type10 DRAW_LINE +#property indicator_color10 clrAquamarine +#property indicator_width10 1 + +// +// Low ... + +// +#define donLowUpperBufferIndex 13 +double donLowUpperBuffer[]; + +// +#define donLowUpperPlotBufferIndex 10 +#property indicator_label11 "X121 L U" +#property indicator_type11 DRAW_LINE +#property indicator_color11 clrDarkOrchid +#property indicator_width11 1 + +// +#define donLowLowerBufferIndex 14 +double donLowLowerBuffer[]; + +// +#define donLowLowerPlotBufferIndex 11 +#property indicator_label12 "X121 L L" +#property indicator_type12 DRAW_LINE +#property indicator_color12 clrDarkOrchid +#property indicator_width12 1 + +// +// Close ... + +// +#define donCloseUpperBufferIndex 15 +double donCloseUpperBuffer[]; + +// +#define donCloseUpperPlotBufferIndex 12 +#property indicator_label13 "X121 C U" +#property indicator_type13 DRAW_LINE +#property indicator_color13 clrCoral +#property indicator_width13 1 + +// +#define donCloseLowerBufferIndex 16 +double donCloseLowerBuffer[]; + +// +#define donCloseLowerPlotBufferIndex 13 +#property indicator_label14 "X121 C L" +#property indicator_type14 DRAW_LINE +#property indicator_color14 clrCoral +#property indicator_width14 1 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 16; + +// +// CURRENT ... + +// +#define cHHBufferIndex mLastBufferIndex + 1 +double cHHBuffer[]; + +// +#define cLLBufferIndex mLastBufferIndex + 2 +double cLLBuffer[]; + +// +// SHORT ... + +// +#define sHHBufferIndex mLastBufferIndex + 3 +double sHHBuffer[]; + +// +#define sLLBufferIndex mLastBufferIndex + 4 +double sLLBuffer[]; + +// +// MEDIUM ... + +// +#define mHHBufferIndex mLastBufferIndex + 5 +double mHHBuffer[]; + +// +#define mLLBufferIndex mLastBufferIndex + 6 +double mLLBuffer[]; + +// +// LONG ... + +// +#define lHHBufferIndex mLastBufferIndex + 7 +double lHHBuffer[]; + +// +#define lLLBufferIndex mLastBufferIndex + 8 +double lLLBuffer[]; + +// +// HIND ... + +// +#define hHHBufferIndex mLastBufferIndex + 9 +double hHHBuffer[]; + +// +#define hLLBufferIndex mLastBufferIndex + 10 +double hLLBuffer[]; + +// +// VOLUME ... +#define vwapVolumeBufferIndex mLastBufferIndex + 11 +double vwapVolumeBuffer[]; + +// +// Price ... +#define vwapPriceBufferIndex mLastBufferIndex + 12 +double vwapPriceBuffer[]; + +// +// Fast State ... +#define vwapFastStateBufferIndex mLastBufferIndex + 13 +double vwapFastStateBuffer[]; + +// +// Mid State ... +#define vwapMidStateBufferIndex mLastBufferIndex + 14 +double vwapMidStateBuffer[]; + +// +// Slow State ... +#define vwapSlowStateBufferIndex mLastBufferIndex + 15 +double vwapSlowStateBuffer[]; + +// +// Valid Peaks and Vales ... + +#define validPeaksBufferIndex mLastBufferIndex + 16 +double validPeaksBuffer[]; + +#define validValesBufferIndex mLastBufferIndex + 17 +double validValesBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// SAR Handler ... +int sarHandler = INVALID_HANDLE; + +// +double mHideColorIDX = 0; + +// +// XMarketCycle sc; +int mSCLength = 0; +ENUM_TIMEFRAMES mSCPeriod = NULL; + +// +// XMarketCycle mc; +int mMCLength = 0; +ENUM_TIMEFRAMES mMCPeriod = NULL; + +// +// XMarketCycle lc; +int mLCLength = 0; +ENUM_TIMEFRAMES mLCPeriod = NULL; + +// +// XMarketCycle hc; +int mHCLength = 0; +ENUM_TIMEFRAMES mHCPeriod = NULL; + +// +// XPOI ... +XCPOIDrawer *mPOIDrawer; +CArrayObj mDrawnObjects; +XCPOIDetector *mPOIDetector; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMax // + ); + bool isInited = sarHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // XPOI Drawer ... + mPOIDrawer = new XCPOIDrawer(); + + // + // Initialize POI Detector ... + int mPoiMaxItems = poiMaxItems > 0 + ? poiMaxItems + : 5; + int mPoiRequiredItems = poiRequiredItems > 0 + ? poiRequiredItems + : 5; + // + ENUM_TIMEFRAMES mPOIPeriod = NULL; + switch (poiCycle) + { + // + case X_MARKET_CYCLE_UNKNOWN: + mPOIPeriod = _Period; + break; + + // + case X_MARKET_CYCLE_SHORT: + mPOIPeriod = mSCPeriod; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + mPOIPeriod = mMCPeriod; + break; + + // + case X_MARKET_CYCLE_LONG: + mPOIPeriod = mLCPeriod; + break; + + // + case X_MARKET_CYCLE_HIND: + mPOIPeriod = mHCPeriod; + break; + } + mPOIPeriod = NormalizePeriod(mPOIPeriod); + mPOIDetector = new XCPOIDetector( + _Symbol, + mPOIPeriod // + ); + mPOIDetector.MaxNumberOfPOIs(mPoiMaxItems); + mPOIDetector.MaxNumberOfRequiredPOIs(mPoiRequiredItems); + mPOIDetector.Init(); + + // + if (!InitMarketCycles()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // 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(); + + // + // 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 + + // + delete mPOIDrawer; + delete mPOIDetector; + + // + mDrawnObjects.Clear(); + + // + IndicatorRelease(sarHandler); +} + +/** + * 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); + + // + // Fill All Buffers by Zero ... + if (prev_calculated == 0) + { + // + ArrayInitialize(peaksBuffer, 0); + ArrayInitialize(valesBuffer, 0); + ArrayInitialize(sarBuffer, 0); + } + + // + // Validate Calculated Bars ... + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // SAR ... + sarCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // SAR ... + int copiedSars = CopyBuffer(sarHandler, 0, 0, limit, sarBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // + // SAR ... + copiedSars > 0 + // + ; + 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 = + // + // PSAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // XDON ... + donchainLength > 0 && + // + // VWAP ... + vwapFastLength > 2 && + vwapMidLength > vwapFastLength && + vwapSlowLength > vwapMidLength && + // + // XPV ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // XPV ... + result = MathMax(mSCLength, mMCLength); + result = MathMax(result, mLCLength); + result = MathMax(result, mHCLength); + + // + // XVWAP ... + result = MathMax(result, vwapFastLength); + result = MathMax(result, vwapMidLength); + result = MathMax(result, vwapSlowLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // PEAKS ... + + // + ENUM_DRAW_TYPE peaksDrawType = showPeaks ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(peaksBuffer, true); + SetIndexBuffer(peaksBufferIndex, peaksBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peaksBufferIndex, PLOT_SHOW_DATA, showPeaks); + PlotIndexSetInteger(peaksBufferIndex, PLOT_DRAW_TYPE, peaksDrawType); + + // + PlotIndexSetDouble(peaksBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(peaksBufferIndex, PLOT_ARROW, peaksArrowCode); + + // + // VALES ... + // + ENUM_DRAW_TYPE valesDrawType = showVales ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(valesBuffer, true); + SetIndexBuffer(valesBufferIndex, valesBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valesBufferIndex, PLOT_SHOW_DATA, showVales); + PlotIndexSetInteger(valesBufferIndex, PLOT_DRAW_TYPE, valesDrawType); + + // + PlotIndexSetDouble(valesBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(valesBufferIndex, PLOT_ARROW, valesArrowCode); + + // + // SAR ... + // + ENUM_DRAW_TYPE sarDrawType = showSar ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(sarBuffer, true); + SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sarBufferIndex, PLOT_SHOW_DATA, showSar); + PlotIndexSetInteger(sarBufferIndex, PLOT_DRAW_TYPE, sarDrawType); + + // + PlotIndexSetDouble(sarBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(sarBufferIndex, PLOT_ARROW, sarArrowCode); + + // + // XVWAP ... + + // + // Fast ... + ArraySetAsSeries(vwapFastBuffer, true); + ArraySetAsSeries(vwapFastColorBuffer, true); + SetIndexBuffer(vwapFastBufferIndex, vwapFastBuffer, INDICATOR_DATA); + SetIndexBuffer(vwapFastColorBufferIndex, vwapFastColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Mid ... + ArraySetAsSeries(vwapMidBuffer, true); + ArraySetAsSeries(vwapMidColorBuffer, true); + SetIndexBuffer(vwapMidBufferIndex, vwapMidBuffer, INDICATOR_DATA); + SetIndexBuffer(vwapMidColorBufferIndex, vwapMidColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Slow ... + ArraySetAsSeries(vwapSlowBuffer, true); + ArraySetAsSeries(vwapSlowColorBuffer, true); + SetIndexBuffer(vwapSlowBufferIndex, vwapSlowBuffer, INDICATOR_DATA); + SetIndexBuffer(vwapSlowColorBufferIndex, vwapSlowColorBuffer, INDICATOR_COLOR_INDEX); + + // + // XDON ... + + // + // Open ... + + // + // UPPER ... + bool canShowCOpenUpper = showDonchain && showUpper && showOpen; + ENUM_DRAW_TYPE donOpenUpperDrawType = canShowCOpenUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donOpenUpperBuffer, true); + SetIndexBuffer(donOpenUpperBufferIndex, donOpenUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donOpenUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donOpenUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCOpenUpper); + PlotIndexSetInteger(donOpenUpperPlotBufferIndex, PLOT_DRAW_TYPE, donOpenUpperDrawType); + + // + // LOWER ... + bool canShowCOpenLower = showDonchain && showLower && showOpen; + ENUM_DRAW_TYPE donOpenLowerDrawType = canShowCOpenLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donOpenLowerBuffer, true); + SetIndexBuffer(donOpenLowerBufferIndex, donOpenLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donOpenLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donOpenLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCOpenLower); + PlotIndexSetInteger(donOpenLowerPlotBufferIndex, PLOT_DRAW_TYPE, donOpenLowerDrawType); + + // + // Close ... + + // + // UPPER ... + bool canShowCCloseUpper = showDonchain && showUpper && showClose; + ENUM_DRAW_TYPE donCloseUpperDrawType = canShowCCloseUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donCloseUpperBuffer, true); + SetIndexBuffer(donCloseUpperBufferIndex, donCloseUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donCloseUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donCloseUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCCloseUpper); + PlotIndexSetInteger(donCloseUpperPlotBufferIndex, PLOT_DRAW_TYPE, donCloseUpperDrawType); + + // + // LOWER ... + bool canShowCCloseLower = showDonchain && showLower && showClose; + ENUM_DRAW_TYPE donCloseLowerDrawType = canShowCCloseLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donCloseLowerBuffer, true); + SetIndexBuffer(donCloseLowerBufferIndex, donCloseLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donCloseLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donCloseLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCCloseLower); + PlotIndexSetInteger(donCloseLowerPlotBufferIndex, PLOT_DRAW_TYPE, donCloseLowerDrawType); + + // + // High ... + + // + // UPPER ... + bool canShowCHighUpper = showDonchain && showUpper && showHigh; + ENUM_DRAW_TYPE donHighUpperDrawType = canShowCHighUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donHighUpperBuffer, true); + SetIndexBuffer(donHighUpperBufferIndex, donHighUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donHighUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donHighUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCHighUpper); + PlotIndexSetInteger(donHighUpperPlotBufferIndex, PLOT_DRAW_TYPE, donHighUpperDrawType); + + // + // LOWER ... + bool canShowCHighLower = showDonchain && showLower && showHigh; + ENUM_DRAW_TYPE donHighLowerDrawType = canShowCHighLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donHighLowerBuffer, true); + SetIndexBuffer(donHighLowerBufferIndex, donHighLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donHighLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donHighLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCHighLower); + PlotIndexSetInteger(donHighLowerPlotBufferIndex, PLOT_DRAW_TYPE, donHighLowerDrawType); + + // + // Low ... + + // + // UPPER ... + bool canShowCLowUpper = showDonchain && showUpper && showLow; + ENUM_DRAW_TYPE donLowUpperDrawType = canShowCLowUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donLowUpperBuffer, true); + SetIndexBuffer(donLowUpperBufferIndex, donLowUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donLowUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donLowUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCLowUpper); + PlotIndexSetInteger(donLowUpperPlotBufferIndex, PLOT_DRAW_TYPE, donLowUpperDrawType); + + // + // LOWER ... + bool canShowCLowLower = showDonchain && showLower && showLow; + ENUM_DRAW_TYPE donLowLowerDrawType = canShowCLowLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donLowLowerBuffer, true); + SetIndexBuffer(donLowLowerBufferIndex, donLowLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donLowLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donLowLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCLowLower); + PlotIndexSetInteger(donLowLowerPlotBufferIndex, PLOT_DRAW_TYPE, donLowLowerDrawType); + + // + // Data Buffers ... + + // + // CURRENT ... + + // + ArraySetAsSeries(cHHBuffer, true); + SetIndexBuffer(cHHBufferIndex, cHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(cLLBuffer, true); + SetIndexBuffer(cLLBufferIndex, cLLBuffer, INDICATOR_CALCULATIONS); + + // + // SHORT ... + + // + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_CALCULATIONS); + + // + // MEDIUM ... + + // + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_CALCULATIONS); + + // + // LONG ... + + // + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_CALCULATIONS); + + // + // HIND ... + + // + ArraySetAsSeries(hHHBuffer, true); + SetIndexBuffer(hHHBufferIndex, hHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(hLLBuffer, true); + SetIndexBuffer(hLLBufferIndex, hLLBuffer, INDICATOR_CALCULATIONS); + + // + // XVWAP ... + + // + // Volumes ... + ArraySetAsSeries(vwapVolumeBuffer, true); + SetIndexBuffer(vwapVolumeBufferIndex, vwapVolumeBuffer, INDICATOR_CALCULATIONS); + + // + // Price ... + ArraySetAsSeries(vwapPriceBuffer, true); + SetIndexBuffer(vwapPriceBufferIndex, vwapPriceBuffer, INDICATOR_CALCULATIONS); + + // + // Fast State ... + ArraySetAsSeries(vwapFastStateBuffer, true); + SetIndexBuffer(vwapFastStateBufferIndex, vwapFastStateBuffer, INDICATOR_CALCULATIONS); + + // + // Mid State ... + ArraySetAsSeries(vwapMidStateBuffer, true); + SetIndexBuffer(vwapMidStateBufferIndex, vwapMidStateBuffer, INDICATOR_CALCULATIONS); + + // + // Slow State ... + ArraySetAsSeries(vwapSlowStateBuffer, true); + SetIndexBuffer(vwapSlowStateBufferIndex, vwapSlowStateBuffer, INDICATOR_CALCULATIONS); + + // + // VALID Peaks and Vales ... + + // + ArraySetAsSeries(validPeaksBuffer, true); + SetIndexBuffer(validPeaksBufferIndex, validPeaksBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(validValesBuffer, true); + SetIndexBuffer(validValesBufferIndex, validValesBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + 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; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + // Calculate Cycles ... + CalculateCycles(bar_index); + + // + // Calculate Peaks and Vales ... + CalculatePeaksAndVales(bar_index); + + // + CalculatePOIS(bar_index); + + // + CalculateDonchains( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + CalculateValidPeaksAndVales( + bar_index, + prevCalculated // + ); + + // + // Calculate Required VWAP Data Buffers ... + if (ratesTotal - bar_index <= maxLength) + { + // + CalculateVWAPDataBuffers( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Prevent Moving Forward ... + } + else + { + // + CalculateVWAPDataBuffers( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + CalculateVWAPS( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + } + else + { + FillBuffersZero(bar_index); + } +} + +// +// Custom ... + +/** + * Initial Market Cycles ... + * + * @return ( bool ) + */ +bool InitMarketCycles() +{ + // + bool result = false; + + // + int cPeriodSeconds = PeriodSeconds(_Period); + + // + // Find Cycle Period ... + if (scMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mSCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_SHORT, + _Period // + ); + } + else + { + mSCPeriod = scPeriod; + } + + // + if (IsValid(mSCPeriod)) + { + mSCLength = PeriodSeconds(mSCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (mcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mMCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_MEDIUM, + _Period // + ); + } + else + { + mMCPeriod = mcPeriod; + } + + // + if (IsValid(mMCPeriod)) + { + mMCLength = PeriodSeconds(mMCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (lcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mLCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_LONG, + _Period // + ); + } + else + { + mLCPeriod = lcPeriod; + } + + // + if (IsValid(mLCPeriod)) + { + mLCLength = PeriodSeconds(mLCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (hcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mHCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_HIND, + _Period // + ); + } + else + { + mHCPeriod = hcPeriod; + } + + // + if (IsValid(mHCPeriod)) + { + mHCLength = PeriodSeconds(mHCPeriod) / cPeriodSeconds; + } + + // + result = mSCLength > 0 && + mMCLength > mSCLength && + mLCLength > mMCLength && + mHCLength > mLCLength; + + // + return result; +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + // CURRENT ... + cHHBuffer[barIndex] = 0; + cLLBuffer[barIndex] = 0; + + // + // SHORT ... + sHHBuffer[barIndex] = 0; + sLLBuffer[barIndex] = 0; + + // + // MEDIUM ... + mHHBuffer[barIndex] = 0; + mLLBuffer[barIndex] = 0; + + // + // LONG ... + lHHBuffer[barIndex] = 0; + lLLBuffer[barIndex] = 0; + + // + // HIND ... + hHHBuffer[barIndex] = 0; + hLLBuffer[barIndex] = 0; + + // + // PEAKS ... + peaksBuffer[barIndex] = 0; + + // + // VALES ... + valesBuffer[barIndex] = 0; + + // + // SARS ... + sarBuffer[barIndex] = 0; + + // + // VWAP ... + + // + vwapFastBuffer[barIndex] = 0; + vwapMidBuffer[barIndex] = 0; + vwapSlowBuffer[barIndex] = 0; + vwapVolumeBuffer[barIndex] = 0; + vwapPriceBuffer[barIndex] = 0; + + // + vwapFastColorBuffer[barIndex] = hideColorIDX; + vwapMidColorBuffer[barIndex] = hideColorIDX; + vwapSlowColorBuffer[barIndex] = hideColorIDX; + vwapFastStateBuffer[barIndex] = hideColorIDX; + vwapMidStateBuffer[barIndex] = hideColorIDX; + vwapSlowStateBuffer[barIndex] = hideColorIDX; + + // + validPeaksBuffer[barIndex] = 0; + validValesBuffer[barIndex] = 0; + + // + donOpenUpperBuffer[barIndex] = 0; + donOpenLowerBuffer[barIndex] = 0; + donCloseUpperBuffer[barIndex] = 0; + donCloseLowerBuffer[barIndex] = 0; + donHighUpperBuffer[barIndex] = 0; + donHighLowerBuffer[barIndex] = 0; + donLowUpperBuffer[barIndex] = 0; + donLowLowerBuffer[barIndex] = 0; +} + +/** + * Calculate Specified Market Cycle Info ... + * + * @param barIndex: Integer, Bar Index ... + * @param cycle: ENUM_X_MARKET_CYCLES member, Specified Cycle ... + * @param hhBuffer: Highest High Buffer Reference ... + * @param llBuffer: Lowest Low Buffer Reference ... + */ +void CalculateCycle( + int barIndex, + ENUM_X_MARKET_CYCLES cycle, + double &hhBuffer[], + double &llBuffer[] // +) +{ + // + XOHCL bar; + bool isBarInited = bar.Init( + _Symbol, + _Period, + barIndex + // + ); + if (!isBarInited) + { + return; + } + + // + int mLength = 0; + switch (cycle) + { + // + case X_MARKET_CYCLE_SHORT: + mLength = mSCLength; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + mLength = mMCLength; + break; + + // + case X_MARKET_CYCLE_LONG: + mLength = mLCLength; + break; + + // + case X_MARKET_CYCLE_HIND: + mLength = mHCLength; + break; + } + + // + if (mLength == 0) + { + return; + } + + // + // Find Highest High ... + double hhValue = bar.FindHighest( + mLength, + hhMode + // + ); + hhBuffer[barIndex] = hhValue; + + // + // Find Lowest Low ... + double llValue = bar.FindLowest( + mLength, + llMode + // + ); + llBuffer[barIndex] = llValue; +} + +/** + * Claculate Cycles ... + * + * @param barIndex: Integer, Bar Index ... + */ +void CalculateCycles(int barIndex) +{ + // + // SHORT ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_SHORT, + sHHBuffer, + sLLBuffer // + ); + + // + // MEDIUM ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_MEDIUM, + mHHBuffer, + mLLBuffer // + ); + + // + // LONG ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_LONG, + lHHBuffer, + lLLBuffer // + ); + + // + // HIND ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_HIND, + hHHBuffer, + hLLBuffer // + ); +} + +/** + * Calculate Peaks and Vales ... + * + * @param barIndex: Integer, Bar Index ... + */ +void CalculatePeaksAndVales(int barIndex) +{ + // + int lastIndex = barIndex + 1; + int barsCount = iBars(_Symbol, _Period); + + // + // PEAKS ... + double lastPeak = + lastIndex < barsCount + ? peaksBuffer[lastIndex] + : 0; + + // + double isHH = sHHBuffer[barIndex]; + double imHH = mHHBuffer[barIndex]; + double ilHH = lHHBuffer[barIndex]; + double ihHH = hHHBuffer[barIndex]; + + // + double iHHs[4] = { + isHH, + imHH, + ilHH, + ihHH // + }; + double rValue = GetAverage(iHHs); + bool isPeak = rValue == isHH && + isHH == imHH && + imHH == ilHH && + ilHH == ihHH; + double iPeak = + isPeak + ? rValue + : lastPeak; + peaksBuffer[barIndex] = iPeak; + + // + // VALES ... + double lastVale = + lastIndex < barsCount + ? valesBuffer[lastIndex] + : 0; + + // + double isLL = sLLBuffer[barIndex]; + double imLL = mLLBuffer[barIndex]; + double ilLL = lLLBuffer[barIndex]; + double ihLL = hLLBuffer[barIndex]; + + // + double iLLs[4] = { + isLL, + imLL, + ilLL, + ihLL // + }; + double sValue = GetAverage(iLLs); + bool isVale = sValue == isLL && + isLL == imLL && + imLL == ilLL && + ilLL == ihLL; + double iVale = + isVale + ? sValue + : lastVale; + valesBuffer[barIndex] = iVale; +} + +/** + * Calculate VWAP Value for Specified Bar ... + * + * @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 ... + * @param _length: Integer, Specified VWAP Length ... + * @param _show: Boolean, Specified Show Buffer or not ... + * @param _buffer: Double Array Reference, Points to Buffer ... + * @param _colorBuffer: Double Array Reference, Points to Color Buffer ... + * @param _stateBuffer: Double Array Reference, Points to State Buffer ... + */ +void CalculateVWAP( + 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 _length, // Calculation Length + bool _show, + double &_buffer[], + double &_colorBuffer[], + double &_stateBuffer[] // +) +{ + // + double vSum = 0; + double pSum = 0; + double mSum = 0; + for (int x = 0; x < _length; x++) + { + // + pSum += vwapPriceBuffer[x + bar_index]; + vSum += vwapVolumeBuffer[x + bar_index]; + mSum += vwapPriceBuffer[x + bar_index] * vwapVolumeBuffer[x + bar_index]; + } + + // + double iValue = mSum / vSum; + iValue = NormalizeDouble(iValue, _Digits); + + // + _buffer[bar_index] = iValue; + + // + bool isBullish = low[bar_index] > iValue; + bool isBearish = high[bar_index] < iValue; + + // + double iColor = + isBullish + ? bullishColorIDX + : isBearish + ? bearishColorIDX + : neuturalColorIDX; + + // + _colorBuffer[bar_index] = hideColorIDX; + _stateBuffer[bar_index] = iColor; + if (showVWap && _show) + { + _colorBuffer[bar_index] = iColor; + } +} + +/** + * Calculate Donchain ... + * + * @param bar_index: Integer, Bar Index ... + * @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 ... + * @param _length: Integer, Donchain Length ... + * @param _ouBuffer: Double Array Reference ... + * @param _olBuffer: Double Array Reference ... + * @param _huBuffer: Double Array Reference ... + * @param _hlBuffer: Double Array Reference ... + * @param _luBuffer: Double Array Reference ... + * @param _llBuffer: Double Array Reference ... + * @param _cuBuffer: Double Array Reference ... + * @param _clBuffer: Double Array Reference ... + */ +void CalculateDonchain( + 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 _length, + // + double &_ouBuffer[], + double &_olBuffer[], + double &_huBuffer[], + double &_hlBuffer[], + double &_luBuffer[], + double &_llBuffer[], + double &_cuBuffer[], + double &_clBuffer[] // +) +{ + // + double iUpper = 0; + double iLower = 0; + + // + // OPEN ... + + // + int from = bar_index; + + // + iUpper = open[ArrayMaximum(open, from, _length)]; + iLower = open[ArrayMinimum(open, from, _length)]; + + // + _ouBuffer[bar_index] = iUpper; + _olBuffer[bar_index] = iLower; + + // + // HIGH ... + + // + iUpper = high[ArrayMaximum(high, from, _length)]; + iLower = high[ArrayMinimum(high, from, _length)]; + + // + _huBuffer[bar_index] = iUpper; + _hlBuffer[bar_index] = iLower; + + // + // LOW ... + + // + iUpper = low[ArrayMaximum(low, from, _length)]; + iLower = low[ArrayMinimum(low, from, _length)]; + + // + _luBuffer[bar_index] = iUpper; + _llBuffer[bar_index] = iLower; + + // + // CLOSE ... + + // + iUpper = close[ArrayMaximum(close, from, _length)]; + iLower = close[ArrayMinimum(close, from, _length)]; + + // + _cuBuffer[bar_index] = iUpper; + _clBuffer[bar_index] = iLower; +} + +/** + * Calculate VWAP Required Data 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 CalculateVWAPDataBuffers( + 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[] // +) +{ + // + double price = GetAppliedPrice( + vwapAppliedTo, + open, + high, + low, + close, + bar_index // + ); + vwapPriceBuffer[bar_index] = price; + vwapVolumeBuffer[bar_index] = (double)tickVolume[bar_index]; +} + +/** + * Calculate Different VWaps ... + * + * @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 CalculateVWAPS( + 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[] // +) +{ + // + // Fast ... + CalculateVWAP( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + // + vwapFastLength, + showVWapFast, + vwapFastBuffer, + vwapFastColorBuffer, + vwapFastStateBuffer // + ); + + // + // Mid ... + CalculateVWAP( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + // + vwapMidLength, + showVWapMedium, + vwapMidBuffer, + vwapMidColorBuffer, + vwapMidStateBuffer // + ); + + // + // Fast ... + CalculateVWAP( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + // + vwapSlowLength, + showVWapSlow, + vwapSlowBuffer, + vwapSlowColorBuffer, + vwapSlowStateBuffer // + ); +} + +/** + * Calculate Different VWaps ... + * + * @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 CalculateDonchains( + 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[] // +) +{ + // + CalculateDonchain( + // + bar_index, + prevCalculated, + ratesTotal, + // + open, + high, + close, + low, + tickVolume, + // + donchainLength, + // + donOpenUpperBuffer, + donOpenLowerBuffer, + donHighUpperBuffer, + donHighLowerBuffer, + donLowUpperBuffer, + donLowLowerBuffer, + donCloseUpperBuffer, + donCloseLowerBuffer // + ); +} + +/** + * Calculate POIs ... + * + * @param bar_index: Integer, Current Bar ... + */ +void CalculatePOIS(int bar_index) +{ + // + ENUM_XPOI_EVENTS events[]; + int eventsCount = mPOIDetector.Update(events); + + // + XPOIState poiState; + mPOIDetector.GetState(poiState); + + // + bool redrawState = true; + if (redrawState) + { + ReDrawPOIState(poiState); + } + + // + if (!IsValidSize(eventsCount)) + { + return; + } + + // + string msg = ToString(eventsCount) + " POI Events: " + "\n"; + for (int i = 0; i < eventsCount; i++) + { + // + ENUM_XPOI_EVENTS iEvent = events[i]; + + // + string iMSG = ToString(i) + "_ " + ToString(iEvent); + msg += iMSG + "\n"; + + // + // Drawn Objects ... + + // + // Swing High ... + if (iEvent == X_SWING_HIGH_DETECTED) + { + // + XCSwing *iSwing; + bool hasSwing = GetLastItem( + iSwing, + poiState.swingHighs // + ); + } + + // + // Swing Low ... + if (iEvent == X_SWING_HIGH_DETECTED) + { + // + XCSwing *iSwing; + bool hasSwing = GetLastItem( + iSwing, + poiState.swingLows // + ); + } + + // + // Bullish Rejection Bar ... + if (iEvent == X_BULLISH_REJECTION_BAR_DETECTED) + { + // + XCRejectionBar *iRejectionBar; + bool hasBar = GetLastItem( + iRejectionBar, + poiState.bullishRejectionBars // + ); + } + + // + // Bearish Rejection Bar ... + if (iEvent == X_BEARISH_REJECTION_BAR_DETECTED) + { + // + XCRejectionBar *iRejectionBar; + bool hasBar = GetLastItem( + iRejectionBar, + poiState.bearishRejectionBars // + ); + } + + // + // Bullish Momentum Bar ... + if (iEvent == X_BULLISH_MOMENTUM_BAR_DETECTED) + { + // + XCMomentumBar *iMomentumBar; + bool hasBar = GetLastItem( + iMomentumBar, + poiState.bullishMomentumBars // + ); + } + + // + // Bearish Momentum Bar ... + if (iEvent == X_BEARISH_MOMENTUM_BAR_DETECTED) + { + // + XCMomentumBar *iMomentumBar; + bool hasBar = GetLastItem( + iMomentumBar, + poiState.bearishMomentumBars // + ); + } + + // + // Support Zone ... + if (iEvent == X_SUPPORT_ZONE_DETECTED) + { + // + XCSupportZone *iZone; + bool hasZone = GetLastItem( + iZone, + poiState.supportZones // + ); + } + + // + // Demand Zone ... + if (iEvent == X_DEMAND_ZONE_DETECTED) + { + // + XCDemandZone *iZone; + bool hasZone = GetLastItem( + iZone, + poiState.demandZones // + ); + } + + // + // Bullish Order Block ... + if (iEvent == X_BULLISH_ORDERBLOCK_DETECTED) + { + // + XCOrderBlock *iZone; + bool hasZone = GetLastItem( + iZone, + poiState.bullishOrderBlocks // + ); + } + + // + // Bullish Fair Value Gap ... + if (iEvent == X_BULLISH_FVG_DETECTED) + { + // + XCFVG *iZone; + bool hasZone = GetLastItem( + iZone, + poiState.bullishFairValueGaps // + ); + } + + // + // Resistance Zone ... + if (iEvent == X_RESISTANCE_ZONE_DETECTED) + { + // + XCResistanceZone *iZone; + bool hasZone = GetLastItem( + iZone, + poiState.resistanceZones // + ); + } + + // + // Supply Zone ... + if (iEvent == X_SUPPLY_ZONE_DETECTED) + { + // + XCSupplyZone *iZone; + bool hasZone = GetLastItem( + iZone, + poiState.supplyZones // + ); + } + + // + // Bearish Order Block ... + if (iEvent == X_BEARISH_ORDERBLOCK_DETECTED) + { + // + XCOrderBlock *iZone; + bool hasZone = GetLastItem( + iZone, + poiState.bearishOrderBlocks // + ); + } + + // + // Bearish Fair Value Gap ... + if (iEvent == X_BEARISH_FVG_DETECTED) + { + // + XCFVG *iZone; + bool hasZone = GetLastItem( + iZone, + poiState.bearishFairValueGaps // + ); + } + } + + // + // Update Drawn Objects ... + ReDrawPOIState( + poiState // + ); +} + +/** + * Calculate Valid Vales and Peaks ... + * + * @param bar_index: Integer, current Bar Index ... + */ +void CalculateValidPeaksAndVales( + int bar_index, + int prevCalculated // +) +{ + // + int minRepetition = 40; + int maxAllowedLoopbackBars = 576; + + // + int barIndex = bar_index; + int start = barIndex; + int end = start + maxAllowedLoopbackBars; + + // + double peak = 0; + int peakRepeate = 0; + int peakToBarIndex = 0; + int peakFromBarIndex = 0; + + // + double vale = 0; + int valeRepeate = 0; + int valeToBarIndex = 0; + int valeFromBarIndex = 0; + + // + bool canLookupPeak = true; + bool canLookupVale = true; + bool canLookup = true; + + // + while (canLookup) + { + // + // Check Peak ... + if (canLookupPeak) + { + // + double iPeak = peaksBuffer[barIndex]; + if (iPeak != peak) + { + // + if (peak != 0 && + peakRepeate >= minRepetition) + { + // + canLookupPeak = false; + } + else + { + // + peak = iPeak; + peakRepeate = 0; + peakFromBarIndex = 0; + peakToBarIndex = barIndex; + } + } + else if (iPeak == peak) + { + // + peakRepeate++; + peakFromBarIndex = barIndex; + } + } + + // + // Check Vale ... + if (canLookupVale) + { + // + double iVale = valesBuffer[barIndex]; + if (iVale != vale) + { + // + if (vale != 0 && + valeRepeate >= minRepetition) + { + canLookupVale = false; + } + else + { + // + vale = iVale; + valeRepeate = 0; + valeFromBarIndex = 0; + valeToBarIndex = barIndex; + } + } + else if (iVale == vale) + { + // + valeRepeate++; + valeFromBarIndex = barIndex; + } + } + + // + canLookup = barIndex < end && + (canLookupPeak || + canLookupVale); + if (canLookup) + { + barIndex++; + } + } + + // + if (!canLookupPeak) + { + validPeaksBuffer[bar_index] = peak; + } + else + { + // + double lastValidPeak = prevCalculated == 0 + ? 0 + : validPeaksBuffer[bar_index + 1]; + + // + validPeaksBuffer[bar_index] = lastValidPeak; + } + + // + if (!canLookupVale) + { + validValesBuffer[bar_index] = vale; + } + else + { + // + double lastValidVale = prevCalculated == 0 + ? 0 + : validValesBuffer[bar_index + 1]; + + // + validValesBuffer[bar_index] = lastValidVale; + } +} + +// +// Draw Functions ... + +/** + * Add Drawn Specified Object to Collection ... + */ +void AddDrawnObject(XCBaseObject *object) +{ + // + string name = object.ObjName(); + + // + bool canAdd = true; + int count = mDrawnObjects.Total(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + string iName = ((XCBaseObject *)mDrawnObjects.At(i)).ObjName(); + + // + if (name == iName) + { + // + canAdd = false; + break; + } + } + } + + // + if (canAdd) + { + mDrawnObjects.Add(object); + } +} + +/** + * Update Drawn Objects ... + */ +void UpdateDrawnObjects() +{ + // + int count = mDrawnObjects.Total(); + if (!IsValidSize(count)) + { + return; + } + + // + // Loop Through Drawn Objects ... + // TODO: Implement this ... +} + +/** + * ReDraw State POI ... + * + * @param state: XPOIState instance + */ +void ReDrawPOIState( + XPOIState &state, + bool forceUpdateZones = true, + bool clearDraws = false // +) +{ + // + if (!showPOIs || + !state.IsValid() || + !state.HasChild()) + { + return; + } + + // + // Clear Draws ... + if (clearDraws) + { + mDrawnObjects.Clear(); + } + + // + datetime cTime = TimeCurrent(); + + // + int swingHighsCount = state.CountSwingHighs(); + if (drawSwingHighs && IsValidSize(swingHighsCount)) + { + // + for (int i = 0; i < swingHighsCount; i++) + { + // + XCSwing *iSwing = state.swingHighs[i]; + XCSwingHighObject *iObj; + bool isCreated = mPOIDrawer.CreateSwingHigh( + iSwing, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int swingLowsCount = state.CountSwingLows(); + if (drawSwingLows && IsValidSize(swingLowsCount)) + { + // + for (int i = 0; i < swingLowsCount; i++) + { + // + XCSwing *iSwing = state.swingLows[i]; + XCSwingLowObject *iObj; + bool isCreated = mPOIDrawer.CreateSwingLow( + iSwing, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int supportZonesCount = state.CountSupportZones(); + if (drawSupportZones && + IsValidSize(supportZonesCount)) + { + // + for (int i = 0; i < supportZonesCount; i++) + { + // + XCSupportZone *iZone = state.supportZones[i]; + if (forceUpdateZones) + { + iZone.To(cTime); + } + XCSupportZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateSupportZone( + iZone, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int resistanceZonesCount = state.CountResistanceZones(); + if (drawResistanceZones && + IsValidSize(resistanceZonesCount)) + { + // + for (int i = 0; i < resistanceZonesCount; i++) + { + // + XCResistanceZone *iZone = state.resistanceZones[i]; + if (forceUpdateZones) + { + iZone.To(cTime); + } + XCResistanceZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateResistanceZone( + iZone, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int supplyZonesCount = state.CountSupplyZones(); + if (drawSupplyZones && + IsValidSize(supplyZonesCount)) + { + // + for (int i = 0; i < supplyZonesCount; i++) + { + // + XCSupplyZone *iZone = state.supplyZones[i]; + if (forceUpdateZones) + { + iZone.To(cTime); + } + XCSupplyZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateSupplyZone( + iZone, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int demandZonesCount = state.CountDemandZones(); + if (drawDemandZones && + IsValidSize(demandZonesCount)) + { + // + for (int i = 0; i < demandZonesCount; i++) + { + // + XCDemandZone *iZone = state.demandZones[i]; + if (forceUpdateZones) + { + iZone.To(cTime); + } + XCDemandZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateDemandZone( + iZone, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int bullishOrderBlocksCount = state.CountBullishOrderBlocks(); + if (drawBullishOrderBlocks && + IsValidSize(bullishOrderBlocksCount)) + { + // + for (int i = 0; i < bullishOrderBlocksCount; i++) + { + // + XCOrderBlock *iZone = state.bullishOrderBlocks[i]; + if (forceUpdateZones) + { + iZone.To(cTime); + } + XCBullishOrderBlockObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishOrderBlock( + iZone, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int bearishOrderBlocksCount = state.CountBearishOrderBlocks(); + if (drawBearishOrderBlocks && + IsValidSize(bearishOrderBlocksCount)) + { + // + for (int i = 0; i < bearishOrderBlocksCount; i++) + { + // + XCOrderBlock *iZone = state.bearishOrderBlocks[i]; + if (forceUpdateZones) + { + iZone.To(cTime); + } + XCBearishOrderBlockObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishOrderBlock( + iZone, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int bullishFairValueGapsCount = state.CountBullishFairValueGaps(); + if (drawBullishFairValueGaps && + IsValidSize(bullishFairValueGapsCount)) + { + // + for (int i = 0; i < bullishFairValueGapsCount; i++) + { + // + XCFVG *iZone = state.bullishFairValueGaps[i]; + if (forceUpdateZones) + { + iZone.To(cTime); + } + XCBullishFairValueGapObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishFairValueGap( + iZone, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int bearishFairValueGapsCount = state.CountBearishFairValueGaps(); + if (drawBearishFairValueGaps && + IsValidSize(bearishFairValueGapsCount)) + { + // + for (int i = 0; i < bearishFairValueGapsCount; i++) + { + // + XCFVG *iZone = state.bearishFairValueGaps[i]; + if (forceUpdateZones) + { + iZone.To(cTime); + } + XCBearishFairValueGapObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishFairValueGap( + iZone, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int bullishRejectionBarsCount = state.CountBullishRejectionBars(); + if (drawBullishRejectionBars && + IsValidSize(bullishRejectionBarsCount)) + { + // + for (int i = 0; i < bullishRejectionBarsCount; i++) + { + // + XCRejectionBar *iRejectionBar = state.bullishRejectionBars[i]; + XCBullishRejectionBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishRejectionBar( + iRejectionBar, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int bearishRejectionBarsCount = state.CountBearishRejectionBars(); + if (drawBearishRejectionBars && + IsValidSize(bearishRejectionBarsCount)) + { + // + for (int i = 0; i < bearishRejectionBarsCount; i++) + { + // + XCRejectionBar *iRejectionBar = state.bearishRejectionBars[i]; + XCBearishRejectionBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishRejectionBar( + iRejectionBar, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int bullishMomentumBarsCount = state.CountBullishMomentumBars(); + if (drawBullishMomentumBars && + IsValidSize(bullishMomentumBarsCount)) + { + // + for (int i = 0; i < bullishMomentumBarsCount; i++) + { + // + XCMomentumBar *iMomentumBar = state.bullishMomentumBars[i]; + XCBullishMomentumBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishMomentumBar( + iMomentumBar, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int bearishMomentumBarsCount = state.CountBearishMomentumBars(); + if (drawBearishMomentumBars && + IsValidSize(bearishMomentumBarsCount)) + { + // + for (int i = 0; i < bearishMomentumBarsCount; i++) + { + // + XCMomentumBar *iMomentumBar = state.bearishMomentumBars[i]; + XCBearishMomentumBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishMomentumBar( + iMomentumBar, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } +} + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/x-saherelm.xpvpm.mq5 b/BKPS/14030923/Documents/BKP/x-saherelm.xpvpm.mq5 new file mode 100644 index 0000000..171f185 --- /dev/null +++ b/BKPS/14030923/Documents/BKP/x-saherelm.xpvpm.mq5 @@ -0,0 +1,2623 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XPVPM +// Description: Peaks and Vales ... +// +// +// 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 XPVPM Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "XPVPM" + +// +// Includes Common Library ... +#include "../Classes/x-saherelm.x-poi.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input group "Makret Cycles"; + +// +input group "Short"; +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES scPeriod = NULL; // Time Period + +// +input group "Medium"; +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES mcPeriod = NULL; // Time Period + +// +input group "Long"; +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES lcPeriod = NULL; // Time Period + +// +input group "Hind"; +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES hcPeriod = NULL; // Time Period + +// +input group "Boundary Detection Modes"; +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE llMode = MODE_LOW; // Lowest Low Calculation Method + +// +input group "Paraboli Sar Detection"; +input double sarStep = 0.02; // Step +input double sarMax = 0.2; // Maximum + +// +input group "VWap Detection"; +input int vwapFastLength = 20; // Fast Length +input int vwapMidLength = 50; // Mid Length +input int vwapSlowLength = 100; // Slow Length +input ENUM_APPLIED_PRICE vwapAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "POI Detector"; +input int poiRequiredItems = 20; // Required POI Detects On Start +input int poiMaxItems = 20; // Max POI Detects Holding +input ENUM_X_MARKET_CYCLES poiCycle = X_MARKET_CYCLE_UNKNOWN; // POI Detector Cycle + +// +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input int sarArrowCode = 159; // Parabolic Sar Arrow Code +input int peaksArrowCode = 159; // Peaks Arrow Code +input int valesArrowCode = 159; // Vales Arrow Code + +// +input bool showSar = true; // Show Parabolic Sar +input bool showPeaks = true; // Show Peaks +input bool showVales = true; // Show Vales +input bool showVWapFast = true; // Show VWap Fast +input bool showVWapMedium = true; // Show VWap Medium +input bool showVWapSlow = true; // Show VWap Slow +input bool showPOIs = false; // Show POIs + +// +// Define Variables to Draw POI(s) ... +input group "POI Presentation"; +input bool drawSwingHighs = false; // Draw Swing Highs +input bool drawSwingLows = false; // Draw Swing Lows +input bool drawSupportZones = false; // Draw Support Zones +input bool drawResistanceZones = false; // Draw Resistance Zones +input bool drawSupplyZones = false; // Draw Supply Zones +input bool drawDemandZones = false; // Draw Demand Zones +input bool drawBullishOrderBlocks = false; // Draw Bullish Order Blocks +input bool drawBearishOrderBlocks = false; // Draw Bearish Order Blocks +input bool drawBullishFairValueGaps = false; // Draw Bullish FairValue Gaps +input bool drawBearishFairValueGaps = false; // Draw Bearish FairValue Gaps +input bool drawBullishRejectionBars = false; // Draw Bullish Rejection Bars +input bool drawBearishRejectionBars = false; // Draw Bearish Rejection Bars +input bool drawBullishMomentumBars = false; // Draw Bullish Momentum Bars +input bool drawBearishMomentumBars = false; // Draw Bearish Momentum Bars + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 26 +#property indicator_plots 6 +// #property indicator_plots 8 + +// +// PEAKS ... + +// +#define peaksBufferIndex 0 +double peaksBuffer[]; + +// +#property indicator_label1 "XPVPM PEAKS" +#property indicator_type1 DRAW_ARROW +#property indicator_color1 clrAqua +#property indicator_width1 1 + +// +// VALES ... + +// +#define valesBufferIndex 1 +double valesBuffer[]; + +// +#property indicator_label2 "XPVPM VALES" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrMagenta +#property indicator_width2 1 + +// +#define sarBufferIndex 2 +double sarBuffer[]; + +// +#property indicator_label3 "XPVPM SAR" +#property indicator_type3 DRAW_ARROW +#property indicator_color3 clrYellow +#property indicator_width3 1 + +// +// FAST ... +#define vwapFastBufferIndex 3 +double vwapFastBuffer[]; + +#define vwapFastColorBufferIndex 4 +double vwapFastColorBuffer[]; + +// +#define vwapFastPlotBufferIndex 3 +#property indicator_label4 "XPVPM VWF" +#property indicator_type4 DRAW_COLOR_LINE +#property indicator_color4 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style4 STYLE_SOLID +#property indicator_width4 2 + +// +// MID ... +#define vwapMidBufferIndex 5 +double vwapMidBuffer[]; + +#define vwapMidColorBufferIndex 6 +double vwapMidColorBuffer[]; + +// +#define vwapMidPlotBufferIndex 4 +#property indicator_label5 "XPVPM VWM" +#property indicator_type5 DRAW_COLOR_LINE +#property indicator_color5 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style5 STYLE_SOLID +#property indicator_width5 2 + +// +// SLOW ... +#define vwapSlowBufferIndex 7 +double vwapSlowBuffer[]; + +#define vwapSlowColorBufferIndex 8 +double vwapSlowColorBuffer[]; + +// +#define vwapSlowPlotBufferIndex 5 +#property indicator_label6 "XPVPM VWS" +#property indicator_type6 DRAW_COLOR_LINE +#property indicator_color6 CLR_NONE, clrSteelBlue, clrDarkRed, clrGray +#property indicator_style6 STYLE_SOLID +#property indicator_width6 2 + +// // +// // VALID PEAKS ... + +// #define validPeaksBufferIndex 9 +// double validPeaksBuffer[]; + +// // +// #define validPeaksBufferPlotIndex 6 +// #property indicator_label7 "XPVPM VALID PEAKS" +// #property indicator_type7 DRAW_ARROW +// #property indicator_color7 clrLime +// #property indicator_width7 1 + +// // +// // VALES ... + +// // +// #define validValesBufferIndex 10 +// double validValesBuffer[]; + +// // +// #define validValesBufferPlotIndex 7 +// #property indicator_label8 "XPVPM VALID VALES" +// #property indicator_type8 DRAW_ARROW +// #property indicator_color8 clrRed +// #property indicator_width8 1 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 8; +// int mLastBufferIndex = 10; + +// +// CURRENT ... + +// +#define cHHBufferIndex mLastBufferIndex + 1 +double cHHBuffer[]; + +// +#define cLLBufferIndex mLastBufferIndex + 2 +double cLLBuffer[]; + +// +// SHORT ... + +// +#define sHHBufferIndex mLastBufferIndex + 3 +double sHHBuffer[]; + +// +#define sLLBufferIndex mLastBufferIndex + 4 +double sLLBuffer[]; + +// +// MEDIUM ... + +// +#define mHHBufferIndex mLastBufferIndex + 5 +double mHHBuffer[]; + +// +#define mLLBufferIndex mLastBufferIndex + 6 +double mLLBuffer[]; + +// +// LONG ... + +// +#define lHHBufferIndex mLastBufferIndex + 7 +double lHHBuffer[]; + +// +#define lLLBufferIndex mLastBufferIndex + 8 +double lLLBuffer[]; + +// +// HIND ... + +// +#define hHHBufferIndex mLastBufferIndex + 9 +double hHHBuffer[]; + +// +#define hLLBufferIndex mLastBufferIndex + 10 +double hLLBuffer[]; + +// +// VOLUME ... +#define vwapVolumeBufferIndex mLastBufferIndex + 11 +double vwapVolumeBuffer[]; + +// +// Price ... +#define vwapPriceBufferIndex mLastBufferIndex + 12 +double vwapPriceBuffer[]; + +// +// Fast State ... +#define vwapFastStateBufferIndex mLastBufferIndex + 13 +double vwapFastStateBuffer[]; + +// +// Mid State ... +#define vwapMidStateBufferIndex mLastBufferIndex + 14 +double vwapMidStateBuffer[]; + +// +// Slow State ... +#define vwapSlowStateBufferIndex mLastBufferIndex + 15 +double vwapSlowStateBuffer[]; + +// +// Valid Peaks and Vales ... + +#define validPeaksBufferIndex mLastBufferIndex + 16 +double validPeaksBuffer[]; + +#define validValesBufferIndex mLastBufferIndex + 17 +double validValesBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// SAR Handler ... +int sarHandler = INVALID_HANDLE; + +// +double mHideColorIDX = 0; + +// +// XMarketCycle sc; +int mSCLength = 0; +ENUM_TIMEFRAMES mSCPeriod = NULL; + +// +// XMarketCycle mc; +int mMCLength = 0; +ENUM_TIMEFRAMES mMCPeriod = NULL; + +// +// XMarketCycle lc; +int mLCLength = 0; +ENUM_TIMEFRAMES mLCPeriod = NULL; + +// +// XMarketCycle hc; +int mHCLength = 0; +ENUM_TIMEFRAMES mHCPeriod = NULL; + +// +// XPOI ... +XCPOIDrawer *mPOIDrawer; +CArrayObj mDrawnObjects; +XCPOIDetector *mPOIDetector; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMax // + ); + bool isInited = sarHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // XPOI Drawer ... + mPOIDrawer = new XCPOIDrawer(); + + // + // Initialize POI Detector ... + int mPoiMaxItems = poiMaxItems > 0 + ? poiMaxItems + : 5; + int mPoiRequiredItems = poiRequiredItems > 0 + ? poiRequiredItems + : 5; + // + ENUM_TIMEFRAMES mPOIPeriod = NULL; + switch (poiCycle) + { + // + case X_MARKET_CYCLE_UNKNOWN: + mPOIPeriod = _Period; + break; + + // + case X_MARKET_CYCLE_SHORT: + mPOIPeriod = mSCPeriod; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + mPOIPeriod = mMCPeriod; + break; + + // + case X_MARKET_CYCLE_LONG: + mPOIPeriod = mLCPeriod; + break; + + // + case X_MARKET_CYCLE_HIND: + mPOIPeriod = mHCPeriod; + break; + } + mPOIPeriod = NormalizePeriod(mPOIPeriod); + mPOIDetector = new XCPOIDetector( + _Symbol, + mPOIPeriod // + ); + mPOIDetector.MaxNumberOfPOIs(mPoiMaxItems); + mPOIDetector.MaxNumberOfRequiredPOIs(mPoiRequiredItems); + mPOIDetector.Init(); + + // + if (!InitMarketCycles()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // 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(); + + // + // 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 + + // + delete mPOIDrawer; + delete mPOIDetector; + + // + mDrawnObjects.Clear(); + + // + IndicatorRelease(sarHandler); +} + +/** + * 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); + + // + // Fill All Buffers by Zero ... + if (prev_calculated == 0) + { + // + ArrayInitialize(peaksBuffer, 0); + ArrayInitialize(valesBuffer, 0); + ArrayInitialize(sarBuffer, 0); + } + + // + // Validate Calculated Bars ... + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // SAR ... + sarCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // SAR ... + int copiedSars = CopyBuffer(sarHandler, 0, 0, limit, sarBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // + // SAR ... + copiedSars > 0 + // + ; + 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 = + // + // PSAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // VWAP ... + vwapFastLength > 2 && + vwapMidLength > vwapFastLength && + vwapSlowLength > vwapMidLength && + // + // XPV ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // XPV ... + result = MathMax(mSCLength, mMCLength); + result = MathMax(result, mLCLength); + result = MathMax(result, mHCLength); + + // + // XVWAP ... + result = MathMax(result, vwapFastLength); + result = MathMax(result, vwapMidLength); + result = MathMax(result, vwapSlowLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // PEAKS ... + + // + ENUM_DRAW_TYPE peaksDrawType = showPeaks ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(peaksBuffer, true); + SetIndexBuffer(peaksBufferIndex, peaksBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peaksBufferIndex, PLOT_SHOW_DATA, showPeaks); + PlotIndexSetInteger(peaksBufferIndex, PLOT_DRAW_TYPE, peaksDrawType); + + // + PlotIndexSetDouble(peaksBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(peaksBufferIndex, PLOT_ARROW, peaksArrowCode); + + // + // VALES ... + // + ENUM_DRAW_TYPE valesDrawType = showVales ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(valesBuffer, true); + SetIndexBuffer(valesBufferIndex, valesBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valesBufferIndex, PLOT_SHOW_DATA, showVales); + PlotIndexSetInteger(valesBufferIndex, PLOT_DRAW_TYPE, valesDrawType); + + // + PlotIndexSetDouble(valesBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(valesBufferIndex, PLOT_ARROW, valesArrowCode); + + // + // SAR ... + // + ENUM_DRAW_TYPE sarDrawType = showSar ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(sarBuffer, true); + SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sarBufferIndex, PLOT_SHOW_DATA, showSar); + PlotIndexSetInteger(sarBufferIndex, PLOT_DRAW_TYPE, sarDrawType); + + // + PlotIndexSetDouble(sarBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(sarBufferIndex, PLOT_ARROW, sarArrowCode); + + // + // XVWAP ... + + // + // Fast ... + ArraySetAsSeries(vwapFastBuffer, true); + ArraySetAsSeries(vwapFastColorBuffer, true); + SetIndexBuffer(vwapFastBufferIndex, vwapFastBuffer, INDICATOR_DATA); + SetIndexBuffer(vwapFastColorBufferIndex, vwapFastColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Mid ... + ArraySetAsSeries(vwapMidBuffer, true); + ArraySetAsSeries(vwapMidColorBuffer, true); + SetIndexBuffer(vwapMidBufferIndex, vwapMidBuffer, INDICATOR_DATA); + SetIndexBuffer(vwapMidColorBufferIndex, vwapMidColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Slow ... + ArraySetAsSeries(vwapSlowBuffer, true); + ArraySetAsSeries(vwapSlowColorBuffer, true); + SetIndexBuffer(vwapSlowBufferIndex, vwapSlowBuffer, INDICATOR_DATA); + SetIndexBuffer(vwapSlowColorBufferIndex, vwapSlowColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Data Buffers ... + + // + // CURRENT ... + + // + ArraySetAsSeries(cHHBuffer, true); + SetIndexBuffer(cHHBufferIndex, cHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(cLLBuffer, true); + SetIndexBuffer(cLLBufferIndex, cLLBuffer, INDICATOR_CALCULATIONS); + + // + // SHORT ... + + // + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_CALCULATIONS); + + // + // MEDIUM ... + + // + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_CALCULATIONS); + + // + // LONG ... + + // + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_CALCULATIONS); + + // + // HIND ... + + // + ArraySetAsSeries(hHHBuffer, true); + SetIndexBuffer(hHHBufferIndex, hHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(hLLBuffer, true); + SetIndexBuffer(hLLBufferIndex, hLLBuffer, INDICATOR_CALCULATIONS); + + // + // XVWAP ... + + // + // Volumes ... + ArraySetAsSeries(vwapVolumeBuffer, true); + SetIndexBuffer(vwapVolumeBufferIndex, vwapVolumeBuffer, INDICATOR_CALCULATIONS); + + // + // Price ... + ArraySetAsSeries(vwapPriceBuffer, true); + SetIndexBuffer(vwapPriceBufferIndex, vwapPriceBuffer, INDICATOR_CALCULATIONS); + + // + // Fast State ... + ArraySetAsSeries(vwapFastStateBuffer, true); + SetIndexBuffer(vwapFastStateBufferIndex, vwapFastStateBuffer, INDICATOR_CALCULATIONS); + + // + // Mid State ... + ArraySetAsSeries(vwapMidStateBuffer, true); + SetIndexBuffer(vwapMidStateBufferIndex, vwapMidStateBuffer, INDICATOR_CALCULATIONS); + + // + // Slow State ... + ArraySetAsSeries(vwapSlowStateBuffer, true); + SetIndexBuffer(vwapSlowStateBufferIndex, vwapSlowStateBuffer, INDICATOR_CALCULATIONS); + + // + // VALID Peaks and Vales ... + + // + // PEAKS ... + + // // + // ArraySetAsSeries(validPeaksBuffer, true); + // SetIndexBuffer(validPeaksBufferIndex, validPeaksBuffer, INDICATOR_DATA); + + // // + // PlotIndexSetDouble(validPeaksBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + // PlotIndexSetInteger(validPeaksBufferPlotIndex, PLOT_ARROW, peaksArrowCode); + + // // + // // VALES ... + // ArraySetAsSeries(validValesBuffer, true); + // SetIndexBuffer(validValesBufferIndex, validValesBuffer, INDICATOR_DATA); + + // // + // PlotIndexSetDouble(validValesBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + // PlotIndexSetInteger(validValesBufferPlotIndex, PLOT_ARROW, valesArrowCode); + + // + ArraySetAsSeries(validPeaksBuffer, true); + SetIndexBuffer(validPeaksBufferIndex, validPeaksBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(validValesBuffer, true); + SetIndexBuffer(validValesBufferIndex, validValesBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + 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; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + // Calculate Cycles ... + CalculateCycles(bar_index); + + // + // Calculate Peaks and Vales ... + CalculatePeaksAndVales(bar_index); + + // + // Calculate Required VWAP Data Buffers ... + if (ratesTotal - bar_index <= maxLength) + { + // + CalculateVWAPDataBuffers( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Prevent Moving Forward ... + return; + } + + // + CalculateVWAPDataBuffers( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + CalculateVWAPS( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + CalculatePOIS(bar_index); + + // + CalculateValidPeaksAndVales( + bar_index, + prevCalculated // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +// +// Custom ... + +/** + * Initial Market Cycles ... + * + * @return ( bool ) + */ +bool InitMarketCycles() +{ + // + bool result = false; + + // + int cPeriodSeconds = PeriodSeconds(_Period); + + // + // Find Cycle Period ... + if (scMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mSCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_SHORT, + _Period // + ); + } + else + { + mSCPeriod = scPeriod; + } + + // + if (IsValid(mSCPeriod)) + { + mSCLength = PeriodSeconds(mSCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (mcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mMCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_MEDIUM, + _Period // + ); + } + else + { + mMCPeriod = mcPeriod; + } + + // + if (IsValid(mMCPeriod)) + { + mMCLength = PeriodSeconds(mMCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (lcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mLCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_LONG, + _Period // + ); + } + else + { + mLCPeriod = lcPeriod; + } + + // + if (IsValid(mLCPeriod)) + { + mLCLength = PeriodSeconds(mLCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (hcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mHCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_HIND, + _Period // + ); + } + else + { + mHCPeriod = hcPeriod; + } + + // + if (IsValid(mHCPeriod)) + { + mHCLength = PeriodSeconds(mHCPeriod) / cPeriodSeconds; + } + + // + result = mSCLength > 0 && + mMCLength > mSCLength && + mLCLength > mMCLength && + mHCLength > mLCLength; + + // + return result; +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + // CURRENT ... + cHHBuffer[barIndex] = 0; + cLLBuffer[barIndex] = 0; + + // + // SHORT ... + sHHBuffer[barIndex] = 0; + sLLBuffer[barIndex] = 0; + + // + // MEDIUM ... + mHHBuffer[barIndex] = 0; + mLLBuffer[barIndex] = 0; + + // + // LONG ... + lHHBuffer[barIndex] = 0; + lLLBuffer[barIndex] = 0; + + // + // HIND ... + hHHBuffer[barIndex] = 0; + hLLBuffer[barIndex] = 0; + + // + // PEAKS ... + peaksBuffer[barIndex] = 0; + + // + // VALES ... + valesBuffer[barIndex] = 0; + + // + // SARS ... + sarBuffer[barIndex] = 0; + + // + // VWAP ... + + // + vwapFastBuffer[barIndex] = 0; + vwapMidBuffer[barIndex] = 0; + vwapSlowBuffer[barIndex] = 0; + vwapVolumeBuffer[barIndex] = 0; + vwapPriceBuffer[barIndex] = 0; + + // + vwapFastColorBuffer[barIndex] = hideColorIDX; + vwapMidColorBuffer[barIndex] = hideColorIDX; + vwapSlowColorBuffer[barIndex] = hideColorIDX; + vwapFastStateBuffer[barIndex] = hideColorIDX; + vwapMidStateBuffer[barIndex] = hideColorIDX; + vwapSlowStateBuffer[barIndex] = hideColorIDX; + + // + validPeaksBuffer[barIndex] = 0; + validValesBuffer[barIndex] = 0; +} + +/** + * Calculate Specified Market Cycle Info ... + * + * @param barIndex: Integer, Bar Index ... + * @param cycle: ENUM_X_MARKET_CYCLES member, Specified Cycle ... + * @param hhBuffer: Highest High Buffer Reference ... + * @param llBuffer: Lowest Low Buffer Reference ... + */ +void CalculateCycle( + int barIndex, + ENUM_X_MARKET_CYCLES cycle, + double &hhBuffer[], + double &llBuffer[] // +) +{ + // + XOHCL bar; + bool isBarInited = bar.Init( + _Symbol, + _Period, + barIndex + // + ); + if (!isBarInited) + { + return; + } + + // + int mLength = 0; + switch (cycle) + { + // + case X_MARKET_CYCLE_SHORT: + mLength = mSCLength; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + mLength = mMCLength; + break; + + // + case X_MARKET_CYCLE_LONG: + mLength = mLCLength; + break; + + // + case X_MARKET_CYCLE_HIND: + mLength = mHCLength; + break; + } + + // + if (mLength == 0) + { + return; + } + + // + // Find Highest High ... + double hhValue = bar.FindHighest( + mLength, + hhMode + // + ); + hhBuffer[barIndex] = hhValue; + + // + // Find Lowest Low ... + double llValue = bar.FindLowest( + mLength, + llMode + // + ); + llBuffer[barIndex] = llValue; +} + +/** + * Claculate Cycles ... + * + * @param barIndex: Integer, Bar Index ... + */ +void CalculateCycles(int barIndex) +{ + // + // SHORT ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_SHORT, + sHHBuffer, + sLLBuffer // + ); + + // + // MEDIUM ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_MEDIUM, + mHHBuffer, + mLLBuffer // + ); + + // + // LONG ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_LONG, + lHHBuffer, + lLLBuffer // + ); + + // + // HIND ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_HIND, + hHHBuffer, + hLLBuffer // + ); +} + +/** + * Calculate Peaks and Vales ... + * + * @param barIndex: Integer, Bar Index ... + */ +void CalculatePeaksAndVales(int barIndex) +{ + // + int lastIndex = barIndex + 1; + int barsCount = iBars(_Symbol, _Period); + + // + // PEAKS ... + double lastPeak = + lastIndex < barsCount + ? peaksBuffer[lastIndex] + : 0; + + // + double isHH = sHHBuffer[barIndex]; + double imHH = mHHBuffer[barIndex]; + double ilHH = lHHBuffer[barIndex]; + double ihHH = hHHBuffer[barIndex]; + + // + double iHHs[4] = { + isHH, + imHH, + ilHH, + ihHH // + }; + double rValue = GetAverage(iHHs); + bool isPeak = rValue == isHH && + isHH == imHH && + imHH == ilHH && + ilHH == ihHH; + double iPeak = + isPeak + ? rValue + : lastPeak; + peaksBuffer[barIndex] = iPeak; + + // + // VALES ... + double lastVale = + lastIndex < barsCount + ? valesBuffer[lastIndex] + : 0; + + // + double isLL = sLLBuffer[barIndex]; + double imLL = mLLBuffer[barIndex]; + double ilLL = lLLBuffer[barIndex]; + double ihLL = hLLBuffer[barIndex]; + + // + double iLLs[4] = { + isLL, + imLL, + ilLL, + ihLL // + }; + double sValue = GetAverage(iLLs); + bool isVale = sValue == isLL && + isLL == imLL && + imLL == ilLL && + ilLL == ihLL; + double iVale = + isVale + ? sValue + : lastVale; + valesBuffer[barIndex] = iVale; +} + +/** + * Calculate VWAP Value for Specified Bar ... + * + * @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 ... + * @param _length: Integer, Specified VWAP Length ... + * @param _show: Boolean, Specified Show Buffer or not ... + * @param _buffer: Double Array Reference, Points to Buffer ... + * @param _colorBuffer: Double Array Reference, Points to Color Buffer ... + * @param _stateBuffer: Double Array Reference, Points to State Buffer ... + */ +void CalculateVWAP( + 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 _length, // Calculation Length + bool _show, + double &_buffer[], + double &_colorBuffer[], + double &_stateBuffer[] // +) +{ + // + double vSum = 0; + double pSum = 0; + double mSum = 0; + for (int x = 0; x < _length; x++) + { + // + pSum += vwapPriceBuffer[x + bar_index]; + vSum += vwapVolumeBuffer[x + bar_index]; + mSum += vwapPriceBuffer[x + bar_index] * vwapVolumeBuffer[x + bar_index]; + } + + // + double iValue = mSum / vSum; + iValue = NormalizeDouble(iValue, _Digits); + + // + _buffer[bar_index] = iValue; + + // + bool isBullish = low[bar_index] > iValue; + bool isBearish = high[bar_index] < iValue; + + // + double iColor = + isBullish + ? bullishColorIDX + : isBearish + ? bearishColorIDX + : neuturalColorIDX; + + // + _colorBuffer[bar_index] = hideColorIDX; + _stateBuffer[bar_index] = iColor; + if (_show) + { + _colorBuffer[bar_index] = iColor; + } +} + +/** + * Calculate VWAP Required Data 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 CalculateVWAPDataBuffers( + 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[] // +) +{ + // + double price = GetAppliedPrice( + vwapAppliedTo, + open, + high, + low, + close, + bar_index // + ); + vwapPriceBuffer[bar_index] = price; + vwapVolumeBuffer[bar_index] = (double)tickVolume[bar_index]; +} + +/** + * Calculate Different VWaps ... + * + * @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 CalculateVWAPS( + 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[] // +) +{ + // + // Fast ... + CalculateVWAP( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + // + vwapFastLength, + showVWapFast, + vwapFastBuffer, + vwapFastColorBuffer, + vwapFastStateBuffer // + ); + + // + // Mid ... + CalculateVWAP( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + // + vwapMidLength, + showVWapMedium, + vwapMidBuffer, + vwapMidColorBuffer, + vwapMidStateBuffer // + ); + + // + // Fast ... + CalculateVWAP( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + // + vwapSlowLength, + showVWapSlow, + vwapSlowBuffer, + vwapSlowColorBuffer, + vwapSlowStateBuffer // + ); +} + +/** + * Calculate POIs ... + * + * @param bar_index: Integer, Current Bar ... + */ +void CalculatePOIS(int bar_index) +{ + // + ENUM_XPOI_EVENTS events[]; + int eventsCount = mPOIDetector.Update(events); + + // + XPOIState poiState; + mPOIDetector.GetState(poiState); + + // + bool redrawState = true; + if (redrawState) + { + ReDrawPOIState(poiState); + } + + // + if (!IsValidSize(eventsCount)) + { + return; + } + + // + string msg = ToString(eventsCount) + " POI Events: " + "\n"; + for (int i = 0; i < eventsCount; i++) + { + // + ENUM_XPOI_EVENTS iEvent = events[i]; + + // + string iMSG = ToString(i) + "_ " + ToString(iEvent); + msg += iMSG + "\n"; + + // + // Drawn Objects ... + + // + // Swing High ... + if (iEvent == X_SWING_HIGH_DETECTED) + { + // + XCSwing *iSwing; + bool hasSwing = GetLastItem( + iSwing, + poiState.swingHighs // + ); + // if (hasSwing && + // drawSwingHighs) + // { + // // + // XCSwingHighObject *iObj; + // bool isCreated = mPOIDrawer.CreateSwingHigh( + // iSwing, + // iObj // + // ); + + // // + // if (isCreated) + // { + // AddDrawnObject(iObj); + // } + // } + } + + // + // Swing Low ... + if (iEvent == X_SWING_HIGH_DETECTED) + { + // + XCSwing *iSwing; + bool hasSwing = GetLastItem( + iSwing, + poiState.swingLows // + ); + // if (hasSwing && + // drawSwingLows) + // { + // // + // XCSwingLowObject *iObj; + // bool isCreated = mPOIDrawer.CreateSwingLow( + // iSwing, + // iObj // + // ); + + // // + // if (isCreated) + // { + // AddDrawnObject(iObj); + // } + // } + } + + // + // Bullish Rejection Bar ... + if (iEvent == X_BULLISH_REJECTION_BAR_DETECTED) + { + // + XCRejectionBar *iRejectionBar; + bool hasBar = GetLastItem( + iRejectionBar, + poiState.bullishRejectionBars // + ); + // if (hasBar && + // drawBullishRejectionBars) + // { + // // + // XCBullishRejectionBarObject *iObj; + // bool isCreated = mPOIDrawer.CreateBullishRejectionBar( + // iRejectionBar, + // iObj // + // ); + + // // + // if (isCreated) + // { + // AddDrawnObject(iObj); + // } + // } + } + + // + // Bearish Rejection Bar ... + if (iEvent == X_BEARISH_REJECTION_BAR_DETECTED) + { + // + XCRejectionBar *iRejectionBar; + bool hasBar = GetLastItem( + iRejectionBar, + poiState.bearishRejectionBars // + ); + // if (hasBar && + // drawBearishRejectionBars) + // { + // // + // XCBearishRejectionBarObject *iObj; + // bool isCreated = mPOIDrawer.CreateBearishRejectionBar( + // iRejectionBar, + // iObj // + // ); + + // // + // if (isCreated) + // { + // AddDrawnObject(iObj); + // } + // } + } + + // + // Bullish Momentum Bar ... + if (iEvent == X_BULLISH_MOMENTUM_BAR_DETECTED) + { + // + XCMomentumBar *iMomentumBar; + bool hasBar = GetLastItem( + iMomentumBar, + poiState.bullishMomentumBars // + ); + // if (hasBar && + // drawBullishMomentumBars) + // { + // // + // XCBullishMomentumBarObject *iObj; + // bool isCreated = mPOIDrawer.CreateBullishMomentumBar( + // iMomentumBar, + // iObj // + // ); + + // // + // if (isCreated) + // { + // AddDrawnObject(iObj); + // } + // } + } + + // + // Bearish Momentum Bar ... + if (iEvent == X_BEARISH_MOMENTUM_BAR_DETECTED) + { + // + XCMomentumBar *iMomentumBar; + bool hasBar = GetLastItem( + iMomentumBar, + poiState.bearishMomentumBars // + ); + // if (hasBar && + // drawBearishMomentumBars) + // { + // // + // XCBearishMomentumBarObject *iObj; + // bool isCreated = mPOIDrawer.CreateBearishMomentumBar( + // iMomentumBar, + // iObj // + // ); + + // // + // if (isCreated) + // { + // AddDrawnObject(iObj); + // } + // } + } + + // + // Support Zone ... + if (iEvent == X_SUPPORT_ZONE_DETECTED) + { + // + XCSupportZone *iZone; + bool hasZone = GetLastItem( + iZone, + poiState.supportZones // + ); + // if (hasZone && + // drawSupportZones) + // { + // // + // XCSupportZoneObject *iObj; + // bool isCreated = mPOIDrawer.CreateSupportZone( + // iZone, + // iObj // + // ); + + // // + // if (isCreated) + // { + // AddDrawnObject(iObj); + // } + // } + } + + // + // Demand Zone ... + if (iEvent == X_DEMAND_ZONE_DETECTED) + { + // + XCDemandZone *iZone; + bool hasZone = GetLastItem( + iZone, + poiState.demandZones // + ); + // if (hasZone && + // drawDemandZones) + // { + // // + // XCDemandZoneObject *iObj; + // bool isCreated = mPOIDrawer.CreateDemandZone( + // iZone, + // iObj // + // ); + + // // + // if (isCreated) + // { + // AddDrawnObject(iObj); + // } + // } + } + + // + // Bullish Order Block ... + if (iEvent == X_BULLISH_ORDERBLOCK_DETECTED) + { + // + XCOrderBlock *iZone; + bool hasZone = GetLastItem( + iZone, + poiState.bullishOrderBlocks // + ); + // if (hasZone && + // drawBullishOrderBlocks) + // { + // // + // XCBullishOrderBlockObject *iObj; + // bool isCreated = mPOIDrawer.CreateBullishOrderBlock( + // iZone, + // iObj // + // ); + + // // + // if (isCreated) + // { + // AddDrawnObject(iObj); + // } + // } + } + + // + // Bullish Fair Value Gap ... + if (iEvent == X_BULLISH_FVG_DETECTED) + { + // + XCFVG *iZone; + bool hasZone = GetLastItem( + iZone, + poiState.bullishFairValueGaps // + ); + // if (hasZone && + // drawBullishFairValueGaps) + // { + // // + // XCBullishFairValueGapObject *iObj; + // bool isCreated = mPOIDrawer.CreateBullishFairValueGap( + // iZone, + // iObj // + // ); + + // // + // if (isCreated) + // { + // AddDrawnObject(iObj); + // } + // } + } + + // + // Resistance Zone ... + if (iEvent == X_RESISTANCE_ZONE_DETECTED) + { + // + XCResistanceZone *iZone; + bool hasZone = GetLastItem( + iZone, + poiState.resistanceZones // + ); + // if (hasZone && + // drawResistanceZones) + // { + // // + // XCResistanceZoneObject *iObj; + // bool isCreated = mPOIDrawer.CreateResistanceZone( + // iZone, + // iObj // + // ); + + // // + // if (isCreated) + // { + // AddDrawnObject(iObj); + // } + // } + } + + // + // Supply Zone ... + if (iEvent == X_SUPPLY_ZONE_DETECTED) + { + // + XCSupplyZone *iZone; + bool hasZone = GetLastItem( + iZone, + poiState.supplyZones // + ); + // if (hasZone && + // drawSupplyZones) + // { + // // + // XCSupplyZoneObject *iObj; + // bool isCreated = mPOIDrawer.CreateSupplyZone( + // iZone, + // iObj // + // ); + + // // + // if (isCreated) + // { + // AddDrawnObject(iObj); + // } + // } + } + + // + // Bearish Order Block ... + if (iEvent == X_BEARISH_ORDERBLOCK_DETECTED) + { + // + XCOrderBlock *iZone; + bool hasZone = GetLastItem( + iZone, + poiState.bearishOrderBlocks // + ); + // if (hasZone && + // drawBearishOrderBlocks) + // { + // // + // XCBearishOrderBlockObject *iObj; + // bool isCreated = mPOIDrawer.CreateBearishOrderBlock( + // iZone, + // iObj // + // ); + + // // + // if (isCreated) + // { + // AddDrawnObject(iObj); + // } + // } + } + + // + // Bearish Fair Value Gap ... + if (iEvent == X_BEARISH_FVG_DETECTED) + { + // + XCFVG *iZone; + bool hasZone = GetLastItem( + iZone, + poiState.bearishFairValueGaps // + ); + // if (hasZone && + // drawBearishFairValueGaps) + // { + // // + // XCBearishFairValueGapObject *iObj; + // bool isCreated = mPOIDrawer.CreateBearishFairValueGap( + // iZone, + // iObj // + // ); + + // // + // if (isCreated) + // { + // AddDrawnObject(iObj); + // } + // } + } + } + + // + // Update Drawn Objects ... + ReDrawPOIState( + poiState // + ); + + // + // Print(msg); +} + +/** + * Calculate Valid Vales and Peaks ... + * + * @param bar_index: Integer, current Bar Index ... + */ +void CalculateValidPeaksAndVales( + int bar_index, + int prevCalculated // +) +{ + // + int minRepetition = 40; + int maxAllowedLoopbackBars = 576; + + // + int barIndex = bar_index; + int start = barIndex; + int end = start + maxAllowedLoopbackBars; + + // + double peak = 0; + int peakRepeate = 0; + int peakToBarIndex = 0; + int peakFromBarIndex = 0; + + // + double vale = 0; + int valeRepeate = 0; + int valeToBarIndex = 0; + int valeFromBarIndex = 0; + + // + bool canLookupPeak = true; + bool canLookupVale = true; + bool canLookup = true; + + // + while (canLookup) + { + // + // Check Peak ... + if (canLookupPeak) + { + // + double iPeak = peaksBuffer[barIndex]; + if (iPeak != peak) + { + // + if (peak != 0 && + peakRepeate >= minRepetition) + { + // + canLookupPeak = false; + } + else + { + // + peak = iPeak; + peakRepeate = 0; + peakFromBarIndex = 0; + peakToBarIndex = barIndex; + } + } + else if (iPeak == peak) + { + // + peakRepeate++; + peakFromBarIndex = barIndex; + } + } + + // + // Check Vale ... + if (canLookupVale) + { + // + double iVale = valesBuffer[barIndex]; + if (iVale != vale) + { + // + if (vale != 0 && + valeRepeate >= minRepetition) + { + canLookupVale = false; + } + else + { + // + vale = iVale; + valeRepeate = 0; + valeFromBarIndex = 0; + valeToBarIndex = barIndex; + } + } + else if (iVale == vale) + { + // + valeRepeate++; + valeFromBarIndex = barIndex; + } + } + + // + canLookup = barIndex < end && + (canLookupPeak || + canLookupVale); + if (canLookup) + { + barIndex++; + } + } + + // + if (!canLookupPeak) + { + validPeaksBuffer[bar_index] = peak; + } + else + { + // + double lastValidPeak = prevCalculated == 0 + ? 0 + : validPeaksBuffer[bar_index + 1]; + + // + validPeaksBuffer[bar_index] = lastValidPeak; + } + + // + if (!canLookupVale) + { + validValesBuffer[bar_index] = vale; + } + else + { + // + double lastValidVale = prevCalculated == 0 + ? 0 + : validValesBuffer[bar_index + 1]; + + // + validValesBuffer[bar_index] = lastValidVale; + } +} + +// +// Draw Functions ... + +/** + * Add Drawn Specified Object to Collection ... + */ +void AddDrawnObject(XCBaseObject *object) +{ + // + string name = object.ObjName(); + + // + bool canAdd = true; + int count = mDrawnObjects.Total(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + string iName = ((XCBaseObject *)mDrawnObjects.At(i)).ObjName(); + + // + if (name == iName) + { + // + canAdd = false; + break; + } + } + } + + // + if (canAdd) + { + mDrawnObjects.Add(object); + } +} + +/** + * Update Drawn Objects ... + */ +void UpdateDrawnObjects() +{ + // + int count = mDrawnObjects.Total(); + if (!IsValidSize(count)) + { + return; + } + + // + // Loop Through Drawn Objects ... + // TODO: Implement this ... +} + +/** + * ReDraw State POI ... + * + * @param state: XPOIState instance + */ +void ReDrawPOIState( + XPOIState &state, + bool forceUpdateZones = true, + bool clearDraws = false // +) +{ + // + if (!showPOIs || + !state.IsValid() || + !state.HasChild()) + { + return; + } + + // + // Clear Draws ... + if (clearDraws) + { + mDrawnObjects.Clear(); + } + + // + datetime cTime = TimeCurrent(); + + // + int swingHighsCount = state.CountSwingHighs(); + if (drawSwingHighs && IsValidSize(swingHighsCount)) + { + // + for (int i = 0; i < swingHighsCount; i++) + { + // + XCSwing *iSwing = state.swingHighs[i]; + XCSwingHighObject *iObj; + bool isCreated = mPOIDrawer.CreateSwingHigh( + iSwing, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int swingLowsCount = state.CountSwingLows(); + if (drawSwingLows && IsValidSize(swingLowsCount)) + { + // + for (int i = 0; i < swingLowsCount; i++) + { + // + XCSwing *iSwing = state.swingLows[i]; + XCSwingLowObject *iObj; + bool isCreated = mPOIDrawer.CreateSwingLow( + iSwing, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int supportZonesCount = state.CountSupportZones(); + if (drawSupportZones && + IsValidSize(supportZonesCount)) + { + // + for (int i = 0; i < supportZonesCount; i++) + { + // + XCSupportZone *iZone = state.supportZones[i]; + if (forceUpdateZones) + { + iZone.To(cTime); + } + XCSupportZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateSupportZone( + iZone, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int resistanceZonesCount = state.CountResistanceZones(); + if (drawResistanceZones && + IsValidSize(resistanceZonesCount)) + { + // + for (int i = 0; i < resistanceZonesCount; i++) + { + // + XCResistanceZone *iZone = state.resistanceZones[i]; + if (forceUpdateZones) + { + iZone.To(cTime); + } + XCResistanceZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateResistanceZone( + iZone, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int supplyZonesCount = state.CountSupplyZones(); + if (drawSupplyZones && + IsValidSize(supplyZonesCount)) + { + // + for (int i = 0; i < supplyZonesCount; i++) + { + // + XCSupplyZone *iZone = state.supplyZones[i]; + if (forceUpdateZones) + { + iZone.To(cTime); + } + XCSupplyZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateSupplyZone( + iZone, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int demandZonesCount = state.CountDemandZones(); + if (drawDemandZones && + IsValidSize(demandZonesCount)) + { + // + for (int i = 0; i < demandZonesCount; i++) + { + // + XCDemandZone *iZone = state.demandZones[i]; + if (forceUpdateZones) + { + iZone.To(cTime); + } + XCDemandZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateDemandZone( + iZone, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int bullishOrderBlocksCount = state.CountBullishOrderBlocks(); + if (drawBullishOrderBlocks && + IsValidSize(bullishOrderBlocksCount)) + { + // + for (int i = 0; i < bullishOrderBlocksCount; i++) + { + // + XCOrderBlock *iZone = state.bullishOrderBlocks[i]; + if (forceUpdateZones) + { + iZone.To(cTime); + } + XCBullishOrderBlockObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishOrderBlock( + iZone, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int bearishOrderBlocksCount = state.CountBearishOrderBlocks(); + if (drawBearishOrderBlocks && + IsValidSize(bearishOrderBlocksCount)) + { + // + for (int i = 0; i < bearishOrderBlocksCount; i++) + { + // + XCOrderBlock *iZone = state.bearishOrderBlocks[i]; + if (forceUpdateZones) + { + iZone.To(cTime); + } + XCBearishOrderBlockObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishOrderBlock( + iZone, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int bullishFairValueGapsCount = state.CountBullishFairValueGaps(); + if (drawBullishFairValueGaps && + IsValidSize(bullishFairValueGapsCount)) + { + // + for (int i = 0; i < bullishFairValueGapsCount; i++) + { + // + XCFVG *iZone = state.bullishFairValueGaps[i]; + if (forceUpdateZones) + { + iZone.To(cTime); + } + XCBullishFairValueGapObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishFairValueGap( + iZone, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int bearishFairValueGapsCount = state.CountBearishFairValueGaps(); + if (drawBearishFairValueGaps && + IsValidSize(bearishFairValueGapsCount)) + { + // + for (int i = 0; i < bearishFairValueGapsCount; i++) + { + // + XCFVG *iZone = state.bearishFairValueGaps[i]; + if (forceUpdateZones) + { + iZone.To(cTime); + } + XCBearishFairValueGapObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishFairValueGap( + iZone, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int bullishRejectionBarsCount = state.CountBullishRejectionBars(); + if (drawBullishRejectionBars && + IsValidSize(bullishRejectionBarsCount)) + { + // + for (int i = 0; i < bullishRejectionBarsCount; i++) + { + // + XCRejectionBar *iRejectionBar = state.bullishRejectionBars[i]; + XCBullishRejectionBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishRejectionBar( + iRejectionBar, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int bearishRejectionBarsCount = state.CountBearishRejectionBars(); + if (drawBearishRejectionBars && + IsValidSize(bearishRejectionBarsCount)) + { + // + for (int i = 0; i < bearishRejectionBarsCount; i++) + { + // + XCRejectionBar *iRejectionBar = state.bearishRejectionBars[i]; + XCBearishRejectionBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishRejectionBar( + iRejectionBar, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int bullishMomentumBarsCount = state.CountBullishMomentumBars(); + if (drawBullishMomentumBars && + IsValidSize(bullishMomentumBarsCount)) + { + // + for (int i = 0; i < bullishMomentumBarsCount; i++) + { + // + XCMomentumBar *iMomentumBar = state.bullishMomentumBars[i]; + XCBullishMomentumBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishMomentumBar( + iMomentumBar, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } + + // + int bearishMomentumBarsCount = state.CountBearishMomentumBars(); + if (drawBearishMomentumBars && + IsValidSize(bearishMomentumBarsCount)) + { + // + for (int i = 0; i < bearishMomentumBarsCount; i++) + { + // + XCMomentumBar *iMomentumBar = state.bearishMomentumBars[i]; + XCBearishMomentumBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishMomentumBar( + iMomentumBar, + iObj // + ); + + // + if (isCreated) + { + AddDrawnObject(iObj); + } + } + } +} + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/x-saherelm.xpvt.mq5 b/BKPS/14030923/Documents/BKP/x-saherelm.xpvt.mq5 new file mode 100644 index 0000000..f0d17eb --- /dev/null +++ b/BKPS/14030923/Documents/BKP/x-saherelm.xpvt.mq5 @@ -0,0 +1,1298 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XPV +// Description: Peaks and Vales ... +// +// +// 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 XPV Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "XPV" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input group "Makret Cycles"; + +// +input group "Short"; +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_MANUALLY; // How to Find Period +input ENUM_TIMEFRAMES scPeriod = PERIOD_M15; // Time Period + +// +input group "Medium"; +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_MANUALLY; // How to Find Period +input ENUM_TIMEFRAMES mcPeriod = PERIOD_M30; // Time Period + +// +input group "Long"; +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_MANUALLY; // How to Find Period +input ENUM_TIMEFRAMES lcPeriod = PERIOD_H1; // Time Period + +// +input group "Hind"; +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_MANUALLY; // How to Find Period +input ENUM_TIMEFRAMES hcPeriod = PERIOD_H2; // Time Period + +// +input group "Fibonacci"; +input double fiboLevel1 = 0.236; // Fibio 1st Level +input double fiboLevel2 = 0.382; // Fibio 2st Level +input double fiboLevel3 = 0.5; // Fibio 3rd Level +input double fiboLevel4 = 0.618; // Fibio 4th Level +input double fiboLevel5 = 0.764; // Fibio 5th Level + +// +input group "Boundary Detection Modes"; +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE llMode = MODE_LOW; // Lowest Low Calculation Method + +// +input group "Presentation"; +input bool showPeaksAndVales = true; // Show Peaks and Vales +input bool showLevels = false; // Show Levels +input bool showConsolidations = false; // Show Consolidations +input bool showFibo1Levels = false; // Show Fibo 1st Level +input bool showFibo2Levels = false; // Show Fibo 2nd Level +input bool showFibo3Levels = false; // Show Fibo 3rd Level +input bool showFibo4Levels = false; // Show Fibo 4th Level +input bool showFibo5Levels = false; // Show Fibo 5th Level + +// +// Buffers ... + +// +#property indicator_chart_window + +// +#property indicator_buffers 32 +#property indicator_plots 32 + +// +// PEAKS ... + +// +#define peaksBufferIndex 0 +double peaksBuffer[]; + +// +#property indicator_label1 "XPV PEAKS" +#property indicator_type1 DRAW_ARROW +#property indicator_color1 clrAqua +#property indicator_width1 1 + +// +// VALES ... + +// +#define valesBufferIndex 1 +double valesBuffer[]; + +// +#property indicator_label2 "XPV VALES" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrMagenta +#property indicator_width2 1 + +// +#define rBufferIndex 2 +double rBuffer[]; + +// +#define rColorBufferIndex 3 +double rColorBuffer[]; + +// +#property indicator_label3 "XPV R" +#property indicator_type3 DRAW_COLOR_LINE +#property indicator_color3 CLR_NONE, clrAqua +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +#define sBufferIndex 4 +#define sBufferPlotIndex 3 +double sBuffer[]; + +// +#define sColorBufferIndex 5 +double sColorBuffer[]; + +// +#property indicator_label4 "XPV S" +#property indicator_type4 DRAW_COLOR_LINE +#property indicator_color4 CLR_NONE, clrMagenta +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +// FIBBO Level 1 ... + +// +#define fl1BufferIndex 6 +#define fl1BufferPlotIndex 4 +double fl1Buffer[]; + +// +#define fl1ColorBufferIndex 7 +double fl1ColorBuffer[]; + +// +#property indicator_label5 "XPV FL1" +#property indicator_type5 DRAW_COLOR_LINE +#property indicator_color5 CLR_NONE, clrGold +#property indicator_style5 STYLE_DASHDOTDOT +#property indicator_width5 1 + +// +// FIBBO Level 2 ... + +// +#define fl2BufferIndex 8 +#define fl2BufferPlotIndex 5 +double fl2Buffer[]; + +// +#define fl2ColorBufferIndex 9 +double fl2ColorBuffer[]; + +// +#property indicator_label6 "XPV FL2" +#property indicator_type6 DRAW_COLOR_LINE +#property indicator_color6 CLR_NONE, clrGold +#property indicator_style6 STYLE_DASHDOTDOT +#property indicator_width6 1 + +// +// FIBBO Level 3 ... + +// +#define fl3BufferIndex 10 +#define fl3BufferPlotIndex 6 +double fl3Buffer[]; + +// +#define fl3ColorBufferIndex 11 +double fl3ColorBuffer[]; + +// +#property indicator_label7 "XPV FL3" +#property indicator_type7 DRAW_COLOR_LINE +#property indicator_color7 CLR_NONE, clrGold +#property indicator_style7 STYLE_DASHDOTDOT +#property indicator_width7 1 + +// +// FIBBO Level 4 ... + +// +#define fl4BufferIndex 12 +#define fl4BufferPlotIndex 7 +double fl4Buffer[]; + +// +#define fl4ColorBufferIndex 13 +double fl4ColorBuffer[]; + +// +#property indicator_label8 "XPV FL4" +#property indicator_type8 DRAW_COLOR_LINE +#property indicator_color8 CLR_NONE, clrGold +#property indicator_style8 STYLE_DASHDOTDOT +#property indicator_width8 1 + +// +// FIBBO Level 5 ... + +// +#define fl5BufferIndex 14 +#define fl5BufferPlotIndex 8 +double fl5Buffer[]; + +// +#define fl5ColorBufferIndex 15 +double fl5ColorBuffer[]; + +// +#property indicator_label9 "XPV FL5" +#property indicator_type9 DRAW_COLOR_LINE +#property indicator_color9 CLR_NONE, clrGold +#property indicator_style9 STYLE_DASHDOTDOT +#property indicator_width9 1 + +// +// LEVELS ... + +// +#define scHHBufferIndex 16 +#define scHHBufferPlotIndex 9 +double scHHBuffer[]; + +// +#define scHHColorBufferIndex 17 +double scHHColorBuffer[]; + +// +#property indicator_label10 "XPV SHH" +#property indicator_type10 DRAW_COLOR_LINE +#property indicator_color10 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style10 STYLE_DOT +#property indicator_width10 1 + +#define scLLBufferIndex 18 +#define scLLBufferPlotIndex 10 +double scLLBuffer[]; + +// +#define scLLColorBufferIndex 19 +double scLLColorBuffer[]; + +// +#property indicator_label11 "XPV SLL" +#property indicator_type11 DRAW_COLOR_LINE +#property indicator_color11 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style11 STYLE_DOT +#property indicator_width11 1 + +// +#define mcHHBufferIndex 20 +#define mcHHBufferPlotIndex 11 +double mcHHBuffer[]; + +// +#define mcHHColorBufferIndex 21 +double mcHHColorBuffer[]; + +// +#property indicator_label12 "XPV MHH" +#property indicator_type12 DRAW_COLOR_LINE +#property indicator_color12 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style12 STYLE_DOT +#property indicator_width12 1 + +// +#define mcLLBufferIndex 22 +#define mcLLBufferPlotIndex 12 +double mcLLBuffer[]; + +// +#define mcLLColorBufferIndex 23 +double mcLLColorBuffer[]; + +// +#property indicator_label13 "XPV MLL" +#property indicator_type13 DRAW_COLOR_LINE +#property indicator_color13 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style13 STYLE_DOT +#property indicator_width13 1 + +// +#define lcHHBufferIndex 24 +#define lcHHBufferPlotIndex 13 +double lcHHBuffer[]; + +// +#define lcHHColorBufferIndex 25 +double lcHHColorBuffer[]; + +// +#property indicator_label14 "XPV LHH" +#property indicator_type14 DRAW_COLOR_LINE +#property indicator_color14 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style14 STYLE_DOT +#property indicator_width14 1 + +// +#define lcLLBufferIndex 26 +#define lcLLBufferPlotIndex 14 +double lcLLBuffer[]; + +// +#define lcLLColorBufferIndex 27 +double lcLLColorBuffer[]; + +// +#property indicator_label15 "XPV LLL" +#property indicator_type15 DRAW_COLOR_LINE +#property indicator_color15 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style15 STYLE_DOT +#property indicator_width15 1 + +// +#define hcHHBufferIndex 28 +#define hcHHBufferPlotIndex 15 +double hcHHBuffer[]; + +// +#define hcHHColorBufferIndex 29 +double hcHHColorBuffer[]; + +// +#property indicator_label16 "XPV HHH" +#property indicator_type16 DRAW_COLOR_LINE +#property indicator_color16 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style16 STYLE_DOT +#property indicator_width16 1 + +// +#define hcLLBufferIndex 30 +#define hcLLBufferPlotIndex 16 +double hcLLBuffer[]; + +// +#define hcLLColorBufferIndex 31 +double hcLLColorBuffer[]; + +// +#property indicator_label17 "XPV HLL" +#property indicator_type17 DRAW_COLOR_LINE +#property indicator_color17 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style17 STYLE_DOT +#property indicator_width17 1 + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +double mHideColorIDX = 0; + +// +// XMarketCycle sc; +int mSCLength = 0; +double mLastSCHH = 0; +double mLastSCLL = 0; +ENUM_TIMEFRAMES mSCPeriod = NULL; + +// +// XMarketCycle mc; +int mMCLength = 0; +double mLastMCHH = 0; +double mLastMCLL = 0; +ENUM_TIMEFRAMES mMCPeriod = NULL; + +// +// XMarketCycle lc; +int mLCLength = 0; +double mLastLCHH = 0; +double mLastLCLL = 0; +ENUM_TIMEFRAMES mLCPeriod = NULL; + +// +// XMarketCycle hc; +int mHCLength = 0; +double mLastHCHH = 0; +double mLastHCLL = 0; +ENUM_TIMEFRAMES mHCPeriod = NULL; + +// +double lastPeak = 0; +double lastVale = 0; + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + if (!InitMarketCycles()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // 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(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +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 +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... + // +) +{ + // + // 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); + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + if (i < 1000) + { + CalculateBuffers(i); + } + } + + // + return rates_total; +} + +// +// Functions ... + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(mSCLength, mMCLength); + result = MathMax(result, mLCLength); + result = MathMax(result, mHCLength); + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // PEAKS and VALES ... + ENUM_DRAW_TYPE pvDrawType = showPeaksAndVales ? DRAW_ARROW : DRAW_NONE; + + // + // PEAKS ... + ArraySetAsSeries(peaksBuffer, true); + SetIndexBuffer(peaksBufferIndex, peaksBuffer, INDICATOR_DATA); + PlotIndexSetInteger(peaksBufferIndex, PLOT_ARROW, 225); + PlotIndexSetDouble(peaksBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + PlotIndexSetInteger(peaksBufferIndex, PLOT_SHOW_DATA, showPeaksAndVales); + PlotIndexSetInteger(peaksBufferIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + // VALES ... + ArraySetAsSeries(valesBuffer, true); + SetIndexBuffer(valesBufferIndex, valesBuffer, INDICATOR_DATA); + PlotIndexSetInteger(valesBufferIndex, PLOT_ARROW, 225); + PlotIndexSetDouble(valesBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + PlotIndexSetInteger(valesBufferIndex, PLOT_SHOW_DATA, showPeaksAndVales); + PlotIndexSetInteger(valesBufferIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + // SUPPORT and RESISTANCE ... + // + + // + // RESISTANCE ... + ArraySetAsSeries(rBuffer, true); + SetIndexBuffer(rBufferIndex, rBuffer, INDICATOR_DATA); + PlotIndexSetInteger(rBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(rBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // RESISTANCE Color ... + ArraySetAsSeries(rColorBuffer, true); + SetIndexBuffer(rColorBufferIndex, rColorBuffer, INDICATOR_COLOR_INDEX); + + // + // SUPPORT ... + ArraySetAsSeries(sBuffer, true); + SetIndexBuffer(sBufferIndex, sBuffer, INDICATOR_DATA); + PlotIndexSetInteger(sBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(sBufferPlotIndex, PLOT_SHOW_DATA, false); + + // + // SUPPORT Color ... + ArraySetAsSeries(sColorBuffer, true); + SetIndexBuffer(sColorBufferIndex, sColorBuffer, INDICATOR_COLOR_INDEX); + + // + // FIBBO Levels ... + + // + // LEVEL 1 ... + + // + // Buffer ... + ArraySetAsSeries(fl1Buffer, true); + SetIndexBuffer(fl1BufferIndex, fl1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fl1BufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fl1BufferPlotIndex, PLOT_SHOW_DATA, showFibo1Levels); + + // + // Color ... + ArraySetAsSeries(fl1ColorBuffer, true); + SetIndexBuffer(fl1ColorBufferIndex, fl1ColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LEVEL 2 ... + + // + // Buffer ... + ArraySetAsSeries(fl2Buffer, true); + SetIndexBuffer(fl2BufferIndex, fl2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fl2BufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fl2BufferPlotIndex, PLOT_SHOW_DATA, showFibo2Levels); + + // + // Color ... + ArraySetAsSeries(fl2ColorBuffer, true); + SetIndexBuffer(fl2ColorBufferIndex, fl2ColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LEVEL 3 ... + + // + // Buffer ... + ArraySetAsSeries(fl3Buffer, true); + SetIndexBuffer(fl3BufferIndex, fl3Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fl3BufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fl3BufferPlotIndex, PLOT_SHOW_DATA, showFibo3Levels); + + // + // Color ... + ArraySetAsSeries(fl3ColorBuffer, true); + SetIndexBuffer(fl3ColorBufferIndex, fl3ColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LEVEL 4 ... + + // + // Buffer ... + ArraySetAsSeries(fl4Buffer, true); + SetIndexBuffer(fl4BufferIndex, fl4Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fl4BufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fl4BufferPlotIndex, PLOT_SHOW_DATA, showFibo4Levels); + + // + // Color ... + ArraySetAsSeries(fl4ColorBuffer, true); + SetIndexBuffer(fl4ColorBufferIndex, fl4ColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LEVEL 5 ... + + // + // Buffer ... + ArraySetAsSeries(fl5Buffer, true); + SetIndexBuffer(fl5BufferIndex, fl5Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fl5BufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fl5BufferPlotIndex, PLOT_SHOW_DATA, showFibo5Levels); + + // + // Color ... + ArraySetAsSeries(fl5ColorBuffer, true); + SetIndexBuffer(fl5ColorBufferIndex, fl5ColorBuffer, INDICATOR_COLOR_INDEX); + + // + // SHORT Buffers ... + + // + // HIGH ... + ArraySetAsSeries(scHHBuffer, true); + SetIndexBuffer(scHHBufferIndex, scHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(scHHBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(scHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(scHHColorBuffer, true); + SetIndexBuffer(scHHColorBufferIndex, scHHColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LOW ... + ArraySetAsSeries(scLLBuffer, true); + SetIndexBuffer(scLLBufferIndex, scLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(scLLBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(scLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(scLLColorBuffer, true); + SetIndexBuffer(scLLColorBufferIndex, scLLColorBuffer, INDICATOR_COLOR_INDEX); + + // + // MEDIUM Buffer ... + + // + // HIGH ... + ArraySetAsSeries(mcHHBuffer, true); + SetIndexBuffer(mcHHBufferIndex, mcHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mcHHBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(mcHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(mcHHColorBuffer, true); + SetIndexBuffer(mcHHColorBufferIndex, mcHHColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LOW ... + ArraySetAsSeries(mcLLBuffer, true); + SetIndexBuffer(mcLLBufferIndex, mcLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mcLLBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(mcLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(mcLLColorBuffer, true); + SetIndexBuffer(mcLLColorBufferIndex, mcLLColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LONG Buffer ... + + // + // HIGH ... + ArraySetAsSeries(lcHHBuffer, true); + SetIndexBuffer(lcHHBufferIndex, lcHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lcHHBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(lcHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(lcHHColorBuffer, true); + SetIndexBuffer(lcHHColorBufferIndex, lcHHColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LOW ... + ArraySetAsSeries(lcLLBuffer, true); + SetIndexBuffer(lcLLBufferIndex, lcLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lcLLBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(lcLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(lcLLColorBuffer, true); + SetIndexBuffer(lcLLColorBufferIndex, lcLLColorBuffer, INDICATOR_COLOR_INDEX); + + // + // HIND Buffer ... + + // + // HIGH ... + ArraySetAsSeries(hcHHBuffer, true); + SetIndexBuffer(hcHHBufferIndex, hcHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hcHHBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(hcHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(hcHHColorBuffer, true); + SetIndexBuffer(hcHHColorBufferIndex, hcHHColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LOW ... + ArraySetAsSeries(hcLLBuffer, true); + SetIndexBuffer(hcLLBufferIndex, hcLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hcLLBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(hcLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(hcLLColorBuffer, true); + SetIndexBuffer(hcLLColorBufferIndex, hcLLColorBuffer, INDICATOR_COLOR_INDEX); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + // Calculate Cycles ... + CalculateCycles(bar_index); + + // + // Calculate Peaks and Vales ... + CalculatePeaksAndVales(bar_index); + + // + // Calculate Fibonnaci ... + CalculateFibonacci(bar_index); +} + +// +// Custom ... + +// +// Initial Market Cycles ... +bool InitMarketCycles() +{ + // + bool result = false; + + // + int cPeriodSeconds = PeriodSeconds(_Period); + + // + // Find Cycle Period ... + if (scMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mSCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_SHORT, + _Period // + ); + } + else + { + mSCPeriod = scPeriod; + } + + // + if (IsValid(mSCPeriod)) + { + mSCLength = PeriodSeconds(mSCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (mcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mMCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_MEDIUM, + _Period // + ); + } + else + { + mMCPeriod = mcPeriod; + } + + // + if (IsValid(mMCPeriod)) + { + mMCLength = PeriodSeconds(mMCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (lcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mLCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_LONG, + _Period // + ); + } + else + { + mLCPeriod = lcPeriod; + } + + // + if (IsValid(mLCPeriod)) + { + mLCLength = PeriodSeconds(mLCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (hcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mHCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_HIND, + _Period // + ); + } + else + { + mHCPeriod = hcPeriod; + } + + // + if (IsValid(mHCPeriod)) + { + mHCLength = PeriodSeconds(mHCPeriod) / cPeriodSeconds; + } + + // + result = mSCLength > 0 && + mMCLength > mSCLength && + mLCLength > mMCLength && + mHCLength > mLCLength; + + // + return result; +} + +// +// Calculate Specified Cycles HH and LL ... +void CalculateCycle( + int barIndex, + ENUM_X_MARKET_CYCLES cycle, + double &lastHH, + double &hhBuffer[], + double &hhColorBuffer[], + double &lastLL, + double &llBuffer[], + double &llColorBuffer[] // +) +{ + // + XOHCL bar; + bar.Init( + _Symbol, + _Period, + barIndex + // + ); + + // + int mLength = 0; + switch (cycle) + { + // + case X_MARKET_CYCLE_SHORT: + mLength = mSCLength; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + mLength = mMCLength; + break; + + // + case X_MARKET_CYCLE_LONG: + mLength = mLCLength; + break; + + // + case X_MARKET_CYCLE_HIND: + mLength = mHCLength; + break; + } + + // + if (mLength <= 0) + { + return; + } + + // + double hhValue = bar.FindHighest( + mLength, + hhMode + // + ); + hhBuffer[barIndex] = hhValue; + + // + double hhColorIDX = + !showLevels + ? mHideColorIDX + : (hhValue == lastHH) + ? !showConsolidations + ? mHideColorIDX + : 1 + : hhValue > lastHH + ? 2 + : hhValue < lastHH + ? 3 + : mHideColorIDX; + hhColorBuffer[barIndex] = hhColorIDX; + + // + lastHH = hhValue; + + // + double llValue = bar.FindLowest( + mLength, + llMode + // + ); + llBuffer[barIndex] = llValue; + + // + double llColorIDX = + !showLevels + ? mHideColorIDX + : (llValue == lastLL) + ? !showConsolidations + ? mHideColorIDX + : 1 + : llValue > lastLL + ? 2 + : llValue < lastLL + ? 3 + : mHideColorIDX; + llColorBuffer[barIndex] = llColorIDX; + + // + lastLL = llValue; +} + +// +// Calculate Cycles Up and Down Boundaries ... +void CalculateCycles( + int barIndex // Bar Index +) +{ + // + // Short ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_SHORT, + // + mLastSCHH, + scHHBuffer, + scHHColorBuffer, + // + mLastSCLL, + scLLBuffer, + scLLColorBuffer + // + ); + + // + // Medium ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_MEDIUM, + // + mLastMCHH, + mcHHBuffer, + mcHHColorBuffer, + // + mLastMCLL, + mcLLBuffer, + mcLLColorBuffer + // + ); + + // + // Long ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_LONG, + // + mLastLCHH, + lcHHBuffer, + lcHHColorBuffer, + // + mLastLCLL, + lcLLBuffer, + lcLLColorBuffer + // + ); + + // + // Hind ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_HIND, + // + mLastHCHH, + hcHHBuffer, + hcHHColorBuffer, + // + mLastHCLL, + hcLLBuffer, + hcLLColorBuffer + // + ); +} + +// +// Calculate Peaks and Values ... +void CalculatePeaksAndVales( + int barIndex // Bar Index +) +{ + // + // Retrieve Requirements ... + + // + // Short ... + double scHHValue = scHHBuffer[barIndex]; + double scLLValue = scLLBuffer[barIndex]; + + // + // Medium ... + double mcHHValue = mcHHBuffer[barIndex]; + double mcLLValue = mcLLBuffer[barIndex]; + + // + // Long ... + double lcHHValue = lcHHBuffer[barIndex]; + double lcLLValue = lcLLBuffer[barIndex]; + + // + // Hind ... + double hcHHValue = hcHHBuffer[barIndex]; + double hcLLValue = hcLLBuffer[barIndex]; + + // + double rColorIDX = mHideColorIDX; + double sColorIDX = mHideColorIDX; + + // + // RESISTANCE ... + double rValue = (scHHValue + mcHHValue + lcHHValue + hcHHValue) / 4; + + // + // PEAKS ... + bool isPeak = rValue == hcHHValue && + hcHHValue == lcHHValue && + lcHHValue == mcHHValue && + mcHHValue == scHHValue; + + // + if (isPeak && lastPeak != rValue) + { + // + rColorIDX = 1; + lastPeak = rValue; + } + + // + // SUPPORT ... + double sValue = (scLLValue + mcLLValue + lcLLValue + hcLLValue) / 4; + + // + // VALES ... + bool isVale = sValue == hcLLValue && + hcLLValue == lcLLValue && + lcLLValue == mcLLValue && + mcLLValue == scLLValue; + + // + if (isVale && lastVale != sValue) + { + // + sColorIDX = 1; + + // + lastVale = sValue; + } + + // + rBuffer[barIndex] = rValue; + sBuffer[barIndex] = sValue; + peaksBuffer[barIndex] = lastPeak; + valesBuffer[barIndex] = lastVale; + + // + if (showPeaksAndVales) + { + // + rColorBuffer[barIndex] = rColorIDX; + sColorBuffer[barIndex] = sColorIDX; + } + else + { + // + rColorBuffer[barIndex] = mHideColorIDX; + sColorBuffer[barIndex] = mHideColorIDX; + } +} + +// +// Calculate Fibonacci Level 1 ... +void CalculateFibonacci( + int barIndex // Bar Index +) +{ + // + // Select Requirements ... + double upPrice = peaksBuffer[barIndex]; + double downPrice = valesBuffer[barIndex]; + + // + // Level 1 ... + double fibLevel1Value = GetFibonacciLevel( + upPrice, + downPrice, + fiboLevel1, + 1 // + ); + + // + // Level 2 ... + double fibLevel2Value = GetFibonacciLevel( + upPrice, + downPrice, + fiboLevel2, + 1 // + ); + + // + // Level 3 ... + double fibLevel3Value = GetFibonacciLevel( + upPrice, + downPrice, + fiboLevel3, + 1 // + ); + + // + // Level 4 ... + double fibLevel4Value = GetFibonacciLevel( + upPrice, + downPrice, + fiboLevel4, + 1 // + ); + + // + // Level 5 ... + double fibLevel5Value = GetFibonacciLevel( + upPrice, + downPrice, + fiboLevel5, + 1 // + ); + + // + fl1Buffer[barIndex] = fibLevel1Value; + fl2Buffer[barIndex] = fibLevel2Value; + fl3Buffer[barIndex] = fibLevel3Value; + fl4Buffer[barIndex] = fibLevel4Value; + fl5Buffer[barIndex] = fibLevel5Value; + + // + double fl1ColorIdx = showFibo1Levels ? 1 : mHideColorIDX; + double fl2ColorIdx = showFibo2Levels ? 1 : mHideColorIDX; + double fl3ColorIdx = showFibo3Levels ? 1 : mHideColorIDX; + double fl4ColorIdx = showFibo4Levels ? 1 : mHideColorIDX; + double fl5ColorIdx = showFibo5Levels ? 1 : mHideColorIDX; + + // + fl1ColorBuffer[barIndex] = fl1ColorIdx; + fl2ColorBuffer[barIndex] = fl2ColorIdx; + fl3ColorBuffer[barIndex] = fl3ColorIdx; + fl4ColorBuffer[barIndex] = fl4ColorIdx; + fl5ColorBuffer[barIndex] = fl5ColorIdx; +} + +// \ No newline at end of file diff --git a/BKPS/14030923/Documents/BKP/x121.tmp.strategise.mq5 b/BKPS/14030923/Documents/BKP/x121.tmp.strategise.mq5 new file mode 100644 index 0000000..b8ae0a0 --- /dev/null +++ b/BKPS/14030923/Documents/BKP/x121.tmp.strategise.mq5 @@ -0,0 +1,883 @@ + + +////////////////////////////////////////////////////////////////////////////////////////// +// +// Temp Test Strategy: +// +////////////////////////////////////////////////////////////////////////////////////////// + + + // + // TODO: Remove this ... + XSMCStrategySetupConditions mTestConditions; + bool DetectTestSignal( + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + ENUM_X_121_SMC_PROVIDERS provider = X_121_SMC_PROVIDER_SMPV; + string providerStr = ToString(provider); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + + // + double ll = cBar.FindLowest(9, MODE_LOW); + double hh = cBar.FindHighest(9, MODE_HIGH); + + // + double selectedSL = 0; + + // + X121SMCCycleConditions triggerConditions = conditions.triggerConditions; + X121SMCCycleConditions decisionConditions = conditions.decisionConditions; + X121SMCCycleConditions analyseConditions = conditions.analyseConditions; + X121SMCCycleConditions verificationConditions = conditions.verificationConditions; + X121SMCCycleConditions consolidationConditions = conditions.consolidationConditions; + X121SMCCycleConditions visionConditions = conditions.visionConditions; + + // + XPOIState triggerState = triggerConditions.state; + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState verificationState = verificationConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + // Retrieve Peak and Vale ... + double triggerPeak = triggerConditions.x121Conditions.peaksBuffer[0]; + double triggerVale = triggerConditions.x121Conditions.valesBuffer[0]; + + // + int zoneValidationDivider = 10; + int validPivotRepetition = mTriggerCycleHelper.mX121Helper + .GetDonChainLength(); + + // + datetime setupTime = mTestConditions.setupTime; + bool isSetuped = mTestConditions.IsSetuped(); + ENUM_X_DIRECTION setupDir = mTestConditions.dir; + if (!isSetuped) + { + // + // Detect Signal Setup ... + + // + if (!result) + { + return result; + } + } + + // + // Detect Trigger Conditions ... + bool canTrigger = mTestConditions.CanTrigger(); + datetime triggerTime = mTestConditions.triggerTime; + result = canTrigger; + if (!canTrigger) + { + // + if (!result) + { + return result; + } + + // + isBullish = IsBullish(setupDir); + isBearish = IsBearish(setupDir); + result = isBullish || + isBearish; + if (!result) + { + // + // Check Trigger Consitions ... + if (cTime - setupTime > 2400) + { + // + ClearDraws(); + + // + mTestConditions.Clean(); + } + return result; + } + + // + mTestConditions.symbol = symbol; + mTestConditions.period = period; + mTestConditions.triggerTime = cTime; + mTestConditions.sl = isBullish + ? 0 + : 0; + mTestConditions.type = isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + canTrigger = mTestConditions.CanTrigger(); + triggerTime = mTestConditions.triggerTime; + result = canTrigger; + if (!result) + { + // + // Check Trigger Consitions ... + if (cTime - setupTime > 2400) + { + // + ClearDraws(); + + // + mTestConditions.Clean(); + } + + // + return result; + } + } + + // + // Check Signal Direction ... + + // + isBullish = IsBullish(setupDir); + isBearish = IsBearish(setupDir); + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + if (cTime - setupTime > 2400) + { + // + ClearDraws(); + + // + mTestConditions.Clean(); + } + + // + // Issues Signal on Conditions ... + conditions.signalDir = mTestConditions.dir; + conditions.provider = providerStr; + conditions.sl = mTestConditions.sl; + + // + mTestConditions.Clean(); + + // + return result; + } + + // + // Custom Providers Conditions ... + struct XSMCStrategySetupConditions + { + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double sl; + ENUM_X_DIRECTION dir; + ENUM_X_POSITION_TYPES type; + + // + // Setup Props ... + + // + datetime setupTime; + datetime triggerTime; + + // + // Trigger Props ... + + // + // Constructor ... + XSMCStrategySetupConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + sl = 0; + + // + dir = X_DIRECTION_NONE; + type = X_POSITION_TYPE_NONE; + + // + symbol = NULL; + period = NULL; + setupTime = NULL; + triggerTime = NULL; + } + + /** + * Check Condition is Setting Up ... + * + * @param dir: ENUM_X_DIRECTION member, Setting Up Direction ... + * + * @return ( bool ) + */ + bool IsSetuped() + { + // + bool result = false; + + // + result = IsValid(setupTime) && + HasDirection(dir); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Detect How we Can Trigger Signal ... + * + * @return ( bool ) + */ + bool CanTrigger() + { + // + bool result = false; + + // + result = + // + sl > 0 && + IsValid(symbol) && + IsValid(period) && + IsValid(triggerTime) && + type != X_POSITION_TYPE_ALL && + type != X_POSITION_TYPE_NONE + // + ; + + // + return result; + } + + // + }; + + +////////////////////////////////////////////////////////////////////////////////////////// +// +// Consolidation Based Strategy: +// +////////////////////////////////////////////////////////////////////////////////////////// + + + // + // TODO: Remove this ... + XSMCStrategySetupConditions mTestConditions; + bool DetectTestSignal( + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + ENUM_X_121_SMC_PROVIDERS provider = X_121_SMC_PROVIDER_SMPV; + string providerStr = ToString(provider); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + + // + double ll = cBar.FindLowest(9, MODE_LOW); + double hh = cBar.FindHighest(9, MODE_HIGH); + + // + double selectedSL = 0; + + // + X121SMCCycleConditions triggerConditions = conditions.triggerConditions; + X121SMCCycleConditions decisionConditions = conditions.decisionConditions; + X121SMCCycleConditions analyseConditions = conditions.analyseConditions; + X121SMCCycleConditions verificationConditions = conditions.verificationConditions; + X121SMCCycleConditions consolidationConditions = conditions.consolidationConditions; + X121SMCCycleConditions visionConditions = conditions.visionConditions; + + // + XPOIState triggerState = triggerConditions.state; + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState verificationState = verificationConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + // Retrieve Peak and Vale ... + double triggerPeak = triggerConditions.x121Conditions.peaksBuffer[0]; + double triggerVale = triggerConditions.x121Conditions.valesBuffer[0]; + + // + int zoneValidationDivider = 10; + int validPivotRepetition = mTriggerCycleHelper.mX121Helper + .GetDonChainLength(); + + // + XOHCL breakerBar; + bool hasZone = false; + XPVPivotPoint validPeak; + XPVPivotPoint validVale; + bool canTrigger = false; + bool hasValidPeak = false; + bool hasValidVale = false; + datetime setupTime = NULL; + bool isZoneBreaked = false; + bool hasConsolidation = false; + XConsolidationZone consolidation; + + // + setupTime = mTestConditions.setupTime; + bool isSetuped = mTestConditions.IsSetuped(); + ENUM_X_DIRECTION setupDir = mTestConditions.dir; + if (!isSetuped) + { + // + bool isNewPeak = triggerConditions.x121Conditions.isNewPeak; + bool isNewVale = triggerConditions.x121Conditions.isNewVale; + bool isNewPivot = isNewPeak || + isNewVale; + result = isNewPivot; + if (!result) + { + return result; + } + + // + mTestConditions.peak = triggerPeak; + mTestConditions.vale = triggerVale; + hasConsolidation = Contains( + CONSOLIDATION_BREAKED_DETECTED, + mTriggerCycleEvents // + ); + + // + result = hasConsolidation; + if (!result) + { + return result; + } + + // + result = mTriggerCycleHelper + .GetLastConsolidationZone(consolidation); + if (!result) + { + return result; + } + + // + // Validate Breaker Bar ... + result = consolidation.breakerBar + .GetPreviousBar(breakerBar); + + // + // Find Momentum, Engulf Bar ... + + // + // Engulfing ... + ENUM_X_DIRECTION engulfDir; + bool isEngulf = mTriggerCycleHelper.mBarAnalyser.IsEngulfBar( + breakerBar, + engulfDir // + ); + + // + // Momentum ... + ENUM_X_DIRECTION momentumDir; + bool isMomentum = mTriggerCycleHelper.mBarAnalyser.IsMomentumBar( + breakerBar, + momentumDir // + ); + + // + // Rejection ... + ENUM_X_DIRECTION rejectionDir; + bool isRejection = mTriggerCycleHelper.mBarAnalyser.IsRejectionBar( + breakerBar, + rejectionDir // + ); + + // + // Fibo Pressure ... + ENUM_X_DIRECTION fiboPresureDir; + bool hasFiboPressure = mTriggerCycleHelper.mBarAnalyser.HasFiboPressure( + breakerBar, + fiboPresureDir // + ); + + // + // Check Bar is Bullished ... + bool isBarBullish = + // + // Fibo Pressure ... + (hasFiboPressure && + IsBullish(fiboPresureDir)) + // + || + // + ( + // + // Engulfing ... + (isEngulf && + IsBullish(engulfDir)) + // + || + // + // Momentum ... + (isMomentum && + IsBullish(momentumDir)) + // + || + // + // Rejection ... + (isRejection && + IsBullish(rejectionDir)) + // + ) + // + ; + + // + // Check Bar is Bearish ... + bool isBarBearish = + // + // Fibo Pressure ... + (hasFiboPressure && + IsBearish(fiboPresureDir)) + // + || + // + ( + // + // Engulfing ... + (isEngulf && + IsBearish(engulfDir)) + // + || + // + // Momentum ... + (isMomentum && + IsBearish(momentumDir)) + // + || + // + // Rejection ... + (isRejection && + IsBearish(rejectionDir)) + // + ) + // + ; + + // + bool isBarPassed = isBarBullish || + isBarBearish; + result = isBarPassed; + if (!result) + { + return result; + } + + // + isBullish = + // + isBarBullish && + IsBullish(consolidation.breakDirection) + // + ; + + // + isBearish = + // + isBarBearish && + IsBearish(consolidation.breakDirection) + // + ; + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + XCConsolidationZoneObject *iConsolidationObj; + iConsolidationObj = new XCConsolidationZoneObject(); + bool isCreated = iConsolidationObj.Create( + mPOIDrawer.ChartIdentification(), + mPOIDrawer.SubWindowIdentification(), + consolidation // + ); + if (isCreated) + { + // + iConsolidationObj.ZoneWidth(2); + iConsolidationObj.ZoneColor(clrLightBlue); + + // + AddObjectIfNotExists(iConsolidationObj); + } + + // + isSetuped = true; + setupTime = cTime; + mTestConditions.setupTime = setupTime; + setupDir = consolidation.breakDirection; + mTestConditions.dir = setupDir; + } + + // + // Detect Trigger Conditions ... + canTrigger = mTestConditions.CanTrigger(); + datetime triggerTime = mTestConditions.triggerTime; + if (!canTrigger) + { + // + isBullish = IsBullish(setupDir); + isBearish = IsBearish(setupDir); + result = isBullish || + isBearish; + if (!result) + { + // + // Check Trigger Consitions ... + if (cTime - setupTime > 2400) + { + // + ClearDraws(); + + // + mTestConditions.Clean(); + } + return result; + } + + // + mTestConditions.symbol = symbol; + mTestConditions.period = period; + mTestConditions.triggerTime = cTime; + mTestConditions.sl = isBullish + ? consolidation.lower + : consolidation.upper; + mTestConditions.type = isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + canTrigger = mTestConditions.CanTrigger(); + triggerTime = mTestConditions.triggerTime; + result = canTrigger; + if (!result) + { + // + // Check Trigger Consitions ... + if (cTime - setupTime > 2400) + { + // + ClearDraws(); + + // + mTestConditions.Clean(); + } + + // + return result; + } + } + + // + if (cTime - setupTime > 2400) + { + // + ClearDraws(); + + // + mTestConditions.Clean(); + } + + // + // Issues Signal on Conditions ... + conditions.signalDir = mTestConditions.dir; + conditions.provider = providerStr; + conditions.sl = mTestConditions.sl; + + // + mTestConditions.Clean(); + + // + return result; + } + + // + // Custom Providers Conditions ... + struct XSMCStrategySetupConditions + { + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double sl; + ENUM_X_DIRECTION dir; + ENUM_X_POSITION_TYPES type; + + // + // Setup Props ... + + // + datetime setupTime; + datetime triggerTime; + XConsolidationZone zone; + XConsolidationZone consolidation; + + // + double peak; + double vale; + XPVPivotPoint validPeak; + XPVPivotPoint validVale; + + // + // Trigger Props ... + + // + // Constructor ... + XSMCStrategySetupConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + sl = 0; + + // + zone.Clean(); + consolidation.Clean(); + dir = X_DIRECTION_NONE; + type = X_POSITION_TYPE_NONE; + + // + symbol = NULL; + period = NULL; + setupTime = NULL; + triggerTime = NULL; + + // + peak = 0; + vale = 0; + validPeak.Clean(); + validVale.Clean(); + } + + /** + * Check Condition is Setting Up ... + * + * @param dir: ENUM_X_DIRECTION member, Setting Up Direction ... + * + * @return ( bool ) + */ + bool IsSetuped() + { + // + bool result = false; + + // + result = IsValid(setupTime) && + HasDirection(dir); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Detect How we Can Trigger Signal ... + * + * @return ( bool ) + */ + bool CanTrigger() + { + // + bool result = false; + + // + result = + // + sl > 0 && + IsValid(symbol) && + IsValid(period) && + IsValid(triggerTime) && + type != X_POSITION_TYPE_ALL && + type != X_POSITION_TYPE_NONE + // + ; + + // + return result; + } + + // + // Helpers ... + + void UpdateZone() + { + // + if (!zone.IsValid() || + !validPeak.IsValid() || + !validVale.IsValid()) + { + return; + } + + // + zone.upper = validPeak.value; + zone.lower = validVale.value; + + // + zone.Update(); + + // + if (consolidation.IsValid()) + { + consolidation.Update(); + } + } + + // + }; + + +////////////////////////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////////////////////// +// +// Consolidation Based Strategy: +// +////////////////////////////////////////////////////////////////////////////////////////// diff --git a/BKPS/14030923/Documents/Diagrams/Position Protection.drawio b/BKPS/14030923/Documents/Diagrams/Position Protection.drawio new file mode 100644 index 0000000..d425cb2 --- /dev/null +++ b/BKPS/14030923/Documents/Diagrams/Position Protection.drawio @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BKPS/14030923/Documents/JsModules/x-color.tools.js b/BKPS/14030923/Documents/JsModules/x-color.tools.js new file mode 100644 index 0000000..c3ac5f9 --- /dev/null +++ b/BKPS/14030923/Documents/JsModules/x-color.tools.js @@ -0,0 +1,506 @@ +/** + * XColor Tools Module ... + * a module for handle colorify text contents in node js ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +//#region Module Imports ... +const XValueTools = require("./x-value.tools"); +//#endregion + +// +//#region Constants ... +/** + * these are available style which can applied to an string ... + */ +const AVAILABLE_STYLES = { + // + Bold: "\x1b[1m", + Dim: "\x1b[2m", + Underlined: "\x1b[4m", + Blink: "\x1b[5m", + ReverseFandB: "\x1b[7m", + Hidden: "\x1b[8m", + // + // Commonly used for reset all Styles ... + Reset: "\x1b[0m" +}; + +/** + * these are available foreground colors which can applied to an string ... + */ +const AVAILABLE_FOREGROUND_COLORS = { + Default: "\x1b[39m", + Black: "\x1b[30m", + Red: "\x1b[31m", + Green: "\x1b[32m", + Yellow: "\x1b[33m", + Blue: "\x1b[34m", + Magenta: "\x1b[35m", + Cyan: "\x1b[36m", + LightGray: "\x1b[37m", + DarkGray: "\x1b[90m", + LightRed: "\x1b[91m", + LightGreen: "\x1b[92m", + LightYellow: "\x1b[93m", + LightBlue: "\x1b[94m", + LightMagenta: "\x1b[95m", + LightCyan: "\x1b[96m", + White: "\x1b[97m", +}; + +/** + * these are available background colors which can applied to an string ... + */ +const AVAILABLE_BACKGROUND_COLORS = { + Default: "\x1b[49m", + Black: "\x1b[40m", + Red: "\x1b[41m", + Green: "\x1b[42m", + Yellow: "\x1b[43m", + Blue: "\x1b[44m", + Magenta: "\x1b[45m", + Cyan: "\x1b[46m", + LightGray: "\x1b[47m", + DarkGray: "\x1b[100m", + LightRed: "\x1b[101m", + LightGreen: "\x1b[102m", + LightYellow: "\x1b[103m", + LightBlue: "\x1b[104m", + LightMagenta: "\x1b[105m", + LightCyan: "\x1b[106m", + White: "\x1b[107m", +}; + +/** + * these are available style names, which exports from module and + * users can use them ... + */ +const STYLE_NAMES = { + Bold: "Bold", + Dim: "Dim", + Underlined: "Underlined", + Blink: "Blink", + ReverseFandB: "ReverseFandB", + Hidden: "Hidden", + Reset: "Reset", +}; + +/** + * these are available color names, which exports from module and + * users can use them ... + */ +const COLOR_NAMES = { + Default: "Default", + Black: "Black", + Red: "Red", + Green: "Green", + Yellow: "Yellow", + Blue: "Blue", + Magenta: "Magenta", + Cyan: "Cyan", + LightGray: "LightGray", + DarkGray: "DarkGray", + LightRed: "LightRed", + LightGreen: "LightGreen", + LightYellow: "LightYellow", + LightBlue: "LightBlue", + LightMagenta: "LightMagenta", + LightCyan: "LightCyan", + White: "White", +}; +//#endregion + +// +//#region Actions ... +/** + * apply specified style and color on a content ... + * + * @param {string} content specified content for styling ... + * @param {string} color specific color name for using to styling ... + * @param {string} style soecufic style name to use ... + * @param {boolean} toForeground apply specified color as foreground ... + * @param {boolean} toBackground apply specified color as background ... + * @returns {string} styled content ... + */ +function apply( + content, + color, + style, + toForeground = true, + toBackground = false +) { + // + let result = content; + + // + // Validate Arg ... + if (!XValueTools.isValidArg(content)) { + return result; + } + + // + // Detect and Validate Style and Apply it ... + let eStyle = AVAILABLE_STYLES[style]; + if (XValueTools.isValidArg(eStyle)) { + result = `${eStyle}${result}${AVAILABLE_STYLES.Reset}`; + } + + // + // Detect and Validate Foreground Color and Apply it ... + let eFColor = AVAILABLE_FOREGROUND_COLORS[color]; + if ( + !!toForeground + && XValueTools.isValidArg(eFColor) + ) { + result = `${eFColor}${result}${AVAILABLE_STYLES.Reset}`; + } + + // + // Detect and Validate Background Color and Apply it ... + let eBColor = AVAILABLE_BACKGROUND_COLORS[color]; + if ( + !!toBackground + && XValueTools.isValidArg(eBColor) + ) { + result = `${eBColor}${result}${AVAILABLE_STYLES.Reset}`; + } + +} + +/** + * apply specific style on a content ... + * + * @param {string} content specific content which going to styled ... + * @param {string} style a member of STYLE_NAMES which specified that which style going to applied to content ... + * @returns {string} styled content ... + */ +function applyStyle(content, style) { + // + // Validate Arg ... + if (!XValueTools.isValidArg(content)) { + return content; + } + + // + let eStyle = AVAILABLE_STYLES[style]; + if (eStyle === undefined) { + return content; + } + + // + return `${eStyle}${content}${AVAILABLE_STYLES.Reset}`; +} + +/** + * apply specific foreground color on a content ... + * + * @param {string} content specific content which going to colorified ... + * @param {string} color a member of COLOR_NAMES which specified that which color going to applied to content ... + * @returns {string} colorified content ... + */ +function applyForegroundColor(content, color) { + // + // Validate Arg ... + if (!XValueTools.isValidArg(content)) { + return content; + } + + // + let eColor = AVAILABLE_FOREGROUND_COLORS[color]; + if (eColor === undefined) { + return content; + } + + // + return `${eColor}${content}${AVAILABLE_STYLES.Reset}`; +} + +/** + * apply specific background color on a content ... + * + * @param {string} content specific content which going to colorified ... + * @param {string} color a member of COLOR_NAMES which specified that which color going to applied to content ... + * @returns {string} colorified content ... + */ +function applyBackgroundColor(content, color) { + // + // Validate Arg ... + if (!XValueTools.isValidArg(content)) { + return content; + } + + // + let eColor = AVAILABLE_BACKGROUND_COLORS[color]; + if (eColor === undefined) { + return content; + } + + // + return `${eColor}${content}${AVAILABLE_STYLES.Reset}`; +} + +/** + * generate style and color applier expression ... + * + * @param {string} color specific color name for using to styling ... + * @param {string} style soecufic style name to use ... + * @param {boolean} reset close applier string by reset styles ... + * @param {boolean} toForeground apply specified color as foreground ... + * @param {boolean} toBackground apply specified color as background ... + * @returns {string} style and color applier string ... + */ +function getApplier( + style = "", + color = "", + reset = false, + toForeground = true, + toBackground = false +) { + // + let result = ""; + + // + // Detect and Validate Style and Apply it ... + let eStyle = AVAILABLE_STYLES[style]; + if (XValueTools.isValidArg(eStyle)) { + result = `${eStyle}`; + } + + // + // Detect and Validate Foreground Color and Apply it ... + let eFColor = AVAILABLE_FOREGROUND_COLORS[color]; + if ( + !!toForeground + && XValueTools.isValidArg(eFColor) + ) { + result = `${eFColor}`; + } + + // + // Detect and Validate Background Color and Apply it ... + let eBColor = AVAILABLE_BACKGROUND_COLORS[color]; + if ( + !!toBackground + && XValueTools.isValidArg(eBColor) + ) { + result = `${eBColor}`; + } + + // + if ( + !!reset && + result.length > 0 + ) { + result = `${result}${AVAILABLE_STYLES.Reset}`; + } + + // + return result; +} + +/** + * generate style applier expression ... + * + * @param {string} style soecufic style name to use ... + * @param {boolean} reset close applier string by reset styles ... + * @returns {string} style applier string ... + */ +function getStyleApplier( + style = "", + reset = false +) { + // + let result = ""; + + // + // Detect and Validate Style and Apply it ... + let eStyle = AVAILABLE_STYLES[style]; + if (XValueTools.isValidArg(eStyle)) { + result = `${eStyle}`; + } + + // + if ( + !!reset && + result.length > 0 + ) { + result = `${result}${AVAILABLE_STYLES.Reset}`; + } + + // + return result; +} + +/** + * generate color applier expression ... + * + * @param {string} color specific color name for using to styling ... + * @param {boolean} reset close applier string by reset styles ... + * @param {boolean} toForeground apply specified color as foreground ... + * @param {boolean} toBackground apply specified color as background ... + * @returns {string} color applier string ... + */ +function getColorApplier( + color = "", + reset = false, + toForeground = true, + toBackground = false +) { + // + let result = ""; + + // + // Detect and Validate Foreground Color and Apply it ... + let eFColor = AVAILABLE_FOREGROUND_COLORS[color]; + if ( + !!toForeground + && XValueTools.isValidArg(eFColor) + ) { + result = `${eFColor}`; + } + + // + // Detect and Validate Background Color and Apply it ... + let eBColor = AVAILABLE_BACKGROUND_COLORS[color]; + if ( + !!toBackground + && XValueTools.isValidArg(eBColor) + ) { + result = `${eBColor}`; + } + + // + if ( + !!reset && + result.length > 0 + ) { + result = `${result}${AVAILABLE_STYLES.Reset}`; + } + + // + return result; +} + +/** + * colorified specific content ... + * + * @param {string} content specified content for styling ... + * @param {string} color specific color name for using to styling ... + * @param {boolean} toForeground apply specified color as foreground ... + * @param {boolean} toBackground apply specified color as background ... + * @returns {string} + */ +function colorifyContent( + content = "", + color = "", + toForeground = true, + toBackground = false +) { + // + let result = content; + + // + if (!XValueTools.isValidArg(content)) { + return result; + } + + // + // Finde Colors ... + + // + // Detect and Validate Foreground Color and Apply it ... + let eFColor = AVAILABLE_FOREGROUND_COLORS[color]; + if ( + !!toForeground + && XValueTools.isValidArg(eFColor) + ) { + result = `${eFColor}${result}`; + } + + // + // Detect and Validate Background Color and Apply it ... + let eBColor = AVAILABLE_BACKGROUND_COLORS[color]; + if ( + !!toBackground + && XValueTools.isValidArg(eBColor) + ) { + result = `${eBColor}${result}`; + } + + // + if ( + result.length > 0 + && ( + XValueTools.isValidArg(eFColor) || + XValueTools.isValidArg(eBColor) + ) + ) { + result = `${result}${AVAILABLE_STYLES.Reset}`; + } + + // + return result; +} + +/** + * apply style on specific content ... + * + * @param {string} content specified content for styling ... + * @param {string} style soecufic style name to use ... + * @returns {string} + */ +function stylifiyContent( + content = "", + style = "", +) { + // + let result = content; + + // + if (!XValueTools.isValidArg(content)) { + return result; + } + + // + // Detect and Validate Style and Apply it ... + let eStyle = AVAILABLE_STYLES[style]; + if (XValueTools.isValidArg(eStyle)) { + result = `${eStyle}${result}`; + } + + // + if ( + result.length > 0 + && XValueTools.isValidArg(eStyle) + ) { + result = `${result}${AVAILABLE_STYLES.Reset}`; + } + + // + return result; +} +//#endregion + +// +//#region Module Exports ... +module.exports = { + // + STYLE_NAMES, + COLOR_NAMES, + // + apply, + applyStyle, + getApplier, + getColorApplier, + getStyleApplier, + colorifyContent, + stylifiyContent, + applyForegroundColor, + applyBackgroundColor, +} +//#endregion \ No newline at end of file diff --git a/BKPS/14030923/Documents/JsModules/x-file.tools.js b/BKPS/14030923/Documents/JsModules/x-file.tools.js new file mode 100644 index 0000000..2a3535d --- /dev/null +++ b/BKPS/14030923/Documents/JsModules/x-file.tools.js @@ -0,0 +1,887 @@ +/** + * XFile Tools Module ... + * a module for handle all file/folder manipulating task in node js ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +//#region Module Imports ... +const fs = require('fs'); +const os = require('os'); +const Path = require('path'); +const http = require('http'); +const https = require('https'); +const XValueTools = require('./x-value.tools'); +//#endregion + +// +//#region Constants ... +/** + * current os path separators ... + */ +const PathSeparator = Path.sep; + +/** + * current directory ... + */ +const CurrentDir = __dirname; +//#endregion + +// +//#region Actions ... +// +//#region Global ... +/** + * retrieve a path status ... + * + * @param {string} path a path value to check ... + * @returns an stat object ... + */ +function getStatus(path = '') { + // + if (!XValueTools.isValidArg(path)) { + return undefined; + } + + // + return fs.statSync(path); +} + +/** + * retrieve user's Home path ... + * + * @returns {string} a path ... + */ +function getHomePath() { + return os.homedir(); +} +//#endregion + +// +//#region Path ... +/** + * retrieve the base name of specific address path ... + * + * @param {string} path address of file or folder ... + * @returns string ... + */ +function basename(path = '') { + // + if (!XValueTools.isValidArg(path)) { + return ''; + } + + // + const result = Path.basename(path); + return result; +} + +/** + * join several path segments together ... + * + * @param {...string} path path params ... + * @returns a joined paths ... + */ +function joinPath(...path) { + return Path.join(...path); +} + +/** + * resolve a relative path to absolute ... + * + * @param {string[]} path a path value to check ... + * @returns {string} + */ +function resolvePath(...path) { + return Path.resolve(...path); +} +//#endregion + +// +//#region File ... +/** + * determines a path destination is a file or not ... + * + * @param {string} path a path value to check ... + * @returns a boolean value ... + */ +function isFileExists(path = '') { + // + if (!XValueTools.isValidArg(path)) { + return false; + } + + // + try { + const stat = getStatus(path); + if (!stat) { + return false; + } + + // + return stat.isFile(); + } catch { + return false; + } +} + +/** + * remove a file ... + * + * @param {string} path a file path ... + * @returns {Promise} action done or not ... + */ +function removeFile(path = '') { + return new Promise((resolve) => { + // + if (!isFileExists(path)) { + resolve(false); + } + + // + fs.unlink(path, (err) => { + // + if (err) { + resolve(false); + return; + } + + // + resolve(true); + }); + }); +} + +/** + * copy a file to destination path ... + * + * @param {string} source source file path ... + * @param {string} dest dest folder path ... + * @returns {Promise} action done or not ... + */ +function copyFile( + source = '', + dest = '' +) { + return new Promise((resolve) => { + // + if ( + !isFileExists(source) || + !isDirectoryExists(dest) + ) { + resolve(false); + return; + } + + // + const destFilePath = Path.join(dest, Path.basename(source)); + fs.copyFile(source, destFilePath, (err) => { + // + if (err) { + resolve(false); + return; + } + + // + resolve(true); + }); + }); +} + +/** + * reading specified file content ... + * + * @param {string} path a file path ... + * @returns {Promise} file content ... + */ +function readFile(path = '') { + return new Promise((resolve) => { + // + if (!isFileExists(path)) { + resolve(''); + return; + } + + // + fs.readFile(path, 'utf8', (err, content) => { + // + if (err) { + resolve(undefined); + return; + } + + // + resolve(content); + }); + }); +} + +/** + * write content to a file ... + * + * @param {string} path a file path ... + * @param {string} content the content which going to write to the file ... + * @param {bool} overwrite determines file overwrite if exists ... + * @returns {Promise} action done or not ... + */ +function writeFile( + path = '', + content = '', + overwrite = true +) { + return new Promise((resolve) => { + // + if (isFileExists(path) && !overwrite) { + // + resolve(false); + return; + } + + // + // Normalize Content ... + content = XValueTools.isValidArg(content) ? + content : + ''; + + // + fs.writeFile(path, content, (err) => { + // + if (err) { + // + resolve(false); + return; + } + + // + resolve(true); + }); + }); +} + +/** + * create a file ... + * + * @param {string} path file path ... + * @param {string} fileName file name ... + * @returns {Promise} action done or not ... + */ +function createFile( + path = '', + fileName = '' +) { + return new Promise((resolve) => { + // + const filePath = Path.join(path, fileName); + if ( + isFileExists(filePath) || + !XValueTools.isValidArg(path) || + !XValueTools.isValidArg(fileName) + ) { + // + resolve(false); + return; + } + + // + fs.writeFile(filePath, '', (err) => { + // + if (err) { + // + resolve(false); + return; + } + + // + resolve(true); + }); + }); +} + +/** + * remove a file name extension ... + * + * @param {string} name + * @returns {string} name without extension ... + */ +function removeFileExtension(name = '') { + return name.substring(0, name.lastIndexOf('.')) || name; +} + +/** + * retrieve a file extension ... + * + * @param {string} path a path which locate a file ... + * @returns {string} + */ +function getFileExtension(path = '') { + // + let result = ""; + + // + // Validate Arg ... + if ( + !XValueTools.isValidArg(path) + || !isFileExists(path) + ) { + return result; + } + + // + // Retrieve just file name ... + const fileName = basename(path); + result = fileName.replace( + removeFileExtension(fileName), + "" + ); + + // + return result; +} + +/** + * retrieve all files list recursively from specific path ... + * + * @param {string} path a source folder path ... + * @param {string[]} extensions which file extensions need to be listed, live empty for all files ... + * @returns {Promise} + */ +async function getRecursiveFilesList( + path = "", + extensions = [] +) { + // + let result = []; + + // + // Validate Args ... + if ( + !XValueTools.isValidArg(path) + || !isDirectoryExists(path) + ) { + return result; + } + + // + const contents = await getDirectoryContents(path); + for (const item of contents) { + // + const itemPath = joinPath( + path, + item + ); + + // + const isItemFile = isFileExists(itemPath); + if (isItemFile) { + // + const itemFileExtension = getFileExtension(itemPath); + const isFileInSupportedExtensions = + extensions === undefined || extensions.length === 0 + ? true + : extensions.includes(itemFileExtension) + ; + if (isFileInSupportedExtensions) { + result.push(itemPath); + } + } else if (isDirectoryExists(itemPath)) { + // + const itemPathFiles = await getRecursiveFilesList(itemPath, extensions); + result.push(...itemPathFiles); + } + } + + // + return result; +} + +/** + * Extract Specific files from a folder and it's content ... + * + * @param {string} path Folder Path ... + * @returns + */ +async function extractFiles(path = "", ext = [], excludeWorkspaceFolders = []) { + // + const result = []; + + // + if (!ext || ext.length == 0) { + return result; + } + + // + const pathContent = await getDirectoryContents(path); + if (!pathContent || pathContent.length == 0) { + return result; + } + + // + // Loop through Content ... + for (const c of pathContent) { + // + // Prepare full path ... + const cPath = joinPath(path, c); + + // + // check content path is file or not ... + const isCFile = isFileExists(cPath); + const isCDirectory = isDirectoryExists(cPath); + if (isCFile) { + // + // Check it is MQL file or not ... + const cExt = getFileExtension(cPath); + if (ext.includes(cExt)) { + result.push(cPath); + } + } else if (isCDirectory) { + // + const destFolderName = basename(cPath); + const isExcluded = excludeWorkspaceFolders.includes(destFolderName); + if (isExcluded) { + continue; + } + + // + const cFiles = await extractFiles(cPath, ext); + if (cFiles && cFiles.length > 0) { + result.push(...cFiles); + } + } + } + + // + return result; +} +//#endregion + +// +//#region Directory ... +/** + * create a directory ... + * + * @param {string} path destination path including dir name ... + * @param {boolean} recursive create directories recursively ... + * @returns action done or not ... + */ +function createDirectory( + path = '', + recursive = true +) { + // + let result = false; + + // + if ( + isDirectoryExists(path) || + !XValueTools.isValidArg(path) + ) { + return false; + } + + // + try { + // + fs.mkdirSync(path, { recursive: recursive }); + result = true; + return result; + } catch { + return false; + } +} + +/** + * remove a directory ... + * + * @param {string} path destination path including dir name ... + * @param {boolean} recursive removes directories recursively ... + * @returns {Promise} action done or not ... + */ +function removeDirectory( + path = '', + recursive = false +) { + return new Promise((resolve) => { + // + if (!isDirectoryExists(path)) { + resolve(false); + return; + } + + // + fs.rm(path, { + recursive + }, (err) => { + // + if (err) { + resolve(false); + return; + } + + // + resolve(true); + }); + }); +} + +/** + * determines a path destination is a directory or not ... + * + * @param {string} path a folder path ... + * @returns represent destnation path is Directory or not ... + */ +function isDirectoryExists(path = '') { + // + if (!XValueTools.isValidArg(path)) { + return false; + } + + // + try { + // + const isExists = fs.existsSync(path); + if (!isExists) { + return false; + } + + // + const stat = getStatus(path); + if (!stat) { + return false; + } + + // + const result = stat.isDirectory(); + return result; + } catch { + return false; + } +} + +/** + * retrieve a directory content ... + * + * @param {string} path a folder path ... + * @returns {Promise} a collection of folder files ... + */ +function getDirectoryContents(path = '') { + return new Promise((resolve) => { + // + if (!isDirectoryExists(path)) { + resolve([]); + return; + } + + // + fs.readdir(path, (err, content) => { + // + if (err) { + resolve([]); + return; + } + + // + resolve(content); + }); + }); +} + +/** + * retrieve a directory files ... + * + * @param {string} path a folder path ... + * @returns {Promise} a collection of folder files ... + */ +function getDirectoryFiles( + path = '', + containsHiddenFiles = false +) { + return new Promise((resolve) => { + // + if (!isDirectoryExists(path)) { + resolve([]); + return; + } + + // + fs.readdir(path, (err, content) => { + // + if (err) { + resolve([]); + return; + } + + // + if (!containsHiddenFiles) { + content = content.filter(c => !c.startsWith('.')); + } + + // + const result = []; + content + .forEach(c => { + // + const cPath = Path.join(path, c); + if (isFileExists(cPath)) { + result.push(c); + } + }); + + // + resolve(result); + }); + }); +} + +/** + * retrieve a directory folders ... + * + * @param {string} path a folder path ... + * @returns {Promise} a collection of folder names ... + */ +function getDirectoryFolders(path = '') { + return new Promise((resolve) => { + // + if (!isDirectoryExists(path)) { + resolve([]); + return; + } + + // + fs.readdir(path, (err, content) => { + // + if (err) { + resolve([]); + return; + } + + // + const result = []; + content.forEach(c => { + // + const cPath = Path.join(path, c); + if (isDirectoryExists(cPath)) { + result.push(c); + } + }); + + // + resolve(result); + }); + }); +} + +/** + * copy a folder with all of it's content to dest ... + * + * @param {string} source source folder path ... + * @param {string} dest dest folder path ... + * @returns {Promise} action done or not ... + */ +async function copyFolder( + source = '', + dest = '' +) { + // + if ( + !isDirectoryExists(source) || + !XValueTools.isValidArg(dest) || + !XValueTools.isValidArg(source) + ) { + return false; + } + + // + const folderName = Path.basename(source); + const destPath = Path.join(dest, folderName); + + // + // Create Dest Path folder if not exists ... + if (!isDirectoryExists(destPath)) { + // + let result = createDirectory(destPath, true); + if (!result) { + return false; + } + } + + // + // Files ... + const files = await getDirectoryFiles(source); + if (files && files.constructor === Array && files.length > 0) { + // + const filesPromises = files.map(file => copyFile(Path.join(source, file), destPath)); + const filesResult = (await Promise.all(filesPromises)).every(r => !!r); + if (!filesResult) { + return false; + } + } + + // + // Folders ... + const folders = await getDirectoryFolders(source); + if (folders && folders.constructor === Array && folders.length > 0) { + // + const folderPromises = folders.map(folder => copyFolder(Path.join(source, folder), destPath)); + const filesResult = (await Promise.all(folderPromises)).every(r => !!r); + if (!filesResult) { + return false; + } + } + + // + return true; +} +//#endregion + +// +//#region Downloader ... +/** + * download a file from specific url and store it ... + * + * @param {string} filepath the file name and path which required to put download file on it ... + * @param {string} url the web url for downloading ... + */ +function download(filepath, url) { + // + // Validate Args ... + if ( + !XValueTools.isValidArg(url) + || !XValueTools.isValidURL(url) + || !XValueTools.isValidArg(filepath) + ) { + return; + } + + // + var file = fs.createWriteStream(filepath); + + // + if (url.startsWith('https:')) { + https.get(url, function (response) { + response.pipe(file); + }); + } else if (url.startsWith('http:')) { + http.get(url, function (response) { + response.pipe(file); + }); + } +} +//#endregion + +// +//#region JSON ... +/** + * read and parse a JSON content from a file ... + * + * @param {string} path source file path ... + * @returns {any} + */ +function readJSON(path = "") { + // + // Validate Args ... + if (!isFileExists(path)) { + return undefined; + } + + // + let result = undefined; + try { + result = require(path); + } catch { + result = undefined; + } + + // + return result; +} + +/** + * write a JSON Object content into a file ... + * + * @param {string} path dest file path ... + * @param {any} content an object which required to write to file ... + * @returns {Promise} + */ +async function writeJSON( + path = "", + content = undefined +) { + // + let result = false; + + // + // Validate Args ... + if (!XValueTools.isValidArg(path)) { + return result; + } + + // + // Normallize Content ... + if (content === undefined) { + content = {}; + } + + // + const contentString = XValueTools.beautifyJSON(content); + + // + result = await writeFile( + path, + contentString, + true + ); + + // + return result; +} +//#endregion +//#endregion + +// +//#region Module Exports ... +module.exports = { + // + CurrentDir, + PathSeparator, + + // + getStatus, + getHomePath, + + // + basename, + joinPath, + resolvePath, + + // + download, + + // + readJSON, + writeJSON, + + // + copyFile, + readFile, + writeFile, + createFile, + removeFile, + isFileExists, + getFileExtension, + removeFileExtension, + getRecursiveFilesList, + extractFiles, + + // + copyFolder, + createDirectory, + removeDirectory, + isDirectoryExists, + getDirectoryFiles, + getDirectoryFolders, + getDirectoryContents, +}; +//#endregion \ No newline at end of file diff --git a/BKPS/14030923/Documents/JsModules/x-shell.tools.js b/BKPS/14030923/Documents/JsModules/x-shell.tools.js new file mode 100644 index 0000000..0ee13de --- /dev/null +++ b/BKPS/14030923/Documents/JsModules/x-shell.tools.js @@ -0,0 +1,219 @@ +/** + * XShell Tools Module ... + * a module for handling shell actions and retrieve OS Info in node js ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +//#region Imports ... +const os = require('os'); +const process = require('process'); +const { exec } = require("child_process"); +const XFileTools = require('./x-file.tools'); +//#endregion + +// +//#region Constants ... +// +const OS = { + Aix: 'aix', + Darwin: 'darwin', + FreeBSD: 'freebsd', + Linux: 'linux', + OpenBSD: 'openbsd', + SnOS: 'sunos', + Windows: 'win32' +}; + +// +const isWindows = process.platform === OS.Windows; +//#endregion + +// +//#region Actions ... +// +//#region Pure shell commands ... +/** + * execute a command using NodeJS on shell ... + * + * @param {string} cmd command to execute ... + * @param {string} cwd working directory ... + * + * @returns Promise instance ... + */ +function execute(cmd, cwd) { + return new Promise((resolve, reject) => { + // + if (!cmd || cmd.toString().length === 0 || (cwd && !XFileTools.isDirectoryExists(cwd))) { + reject('invalid args ...'); + return; + } + + // + exec(cmd, { cwd }, (err, result, stdError) => { + // + if (err) { + reject(err); + return; + } + + // + if (stdError) { + // + // reject(stdError); + // return; + } + + // + resolve(result); + }); + }); +}; + +/** + * determines a command exists on host or not ... + * + * @param {string} name specific command name ... + * + * @returns boolean Promise ... + */ +function checkCommandExists(name) { + return new Promise(resolve => { + // + if (!name) { + resolve(false); + return; + } + + // + const cmd = isWindows ? `${name} >nul 2>&1` : `type ${name} >/dev/null 2>&1`; + execute(cmd).then(result => { + resolve(true); + }) + .catch(err => { + resolve(false); + }); + }); +} +//#endregion + +// +//#region required commands state ... +/** + * check al required commands exists or not ... + * + * @returns + */ +async function isRequiredCommandsExists() { + // + let result = false; + + // + // const isTarExists = await isTarCommandExists(); + // const isCatExists = await isCatCommandExists(); + // const isGrepExists = await isGrepCommandExists(); + // const isSedExists = await isSedCommandExists(); + const isNpmExists = await isNpmCommandExists(); + const isNgExists = await isNgCommandExists(); + const isIonicExists = await isIonicCommandExists(); + const isCordovaExists = await isCordovaCommandExists(); + + // + result = isNpmExists + && isNgExists + && isIonicExists + && isCordovaExists + ; + + // + return result; +} + +/** + * retrieve required commands state object ... + * + * @returns + */ +async function getRequiredCommandsStates() { + // + const result = {}; + + // + // const isTarExists = await isTarCommandExists(); + // const isCatExists = await isCatCommandExists(); + // const isGrepExists = await isGrepCommandExists(); + // const isSedExists = await isSedCommandExists(); + const isNpmExists = await isNpmCommandExists(); + const isNgExists = await isNgCommandExists(); + const isIonicExists = await isIonicCommandExists(); + const isCordovaExists = await isCordovaCommandExists(); + + // + result['npm'] = isNpmExists; + result['ng'] = isNgExists; + result['ionic'] = isIonicExists; + result['cordova'] = isCordovaExists; + + // + return result; +} +//#endregion + +// +//#region Commonly used Command Checkers ... +/** + * determines npm command exists or not ... + * + * @returns + */ +function isNpmCommandExists() { + return checkCommandExists('npm'); +} + +/** + * determines ng command exists or not ... + * + * @returns + */ +function isNgCommandExists() { + return checkCommandExists('ng'); +} + +/** + * determines ionic command exists or not ... + * + * @returns + */ +function isIonicCommandExists() { + return checkCommandExists('ionic'); +} + +/** + * determines cordova command exists or not ... + * + * @returns + */ +function isCordovaCommandExists() { + return checkCommandExists('cordova'); +} +//#endregion +//#endregion + +// +//#region Module Exports ... +module.exports = { + // + execute, + checkCommandExists, + isRequiredCommandsExists, + getRequiredCommandsStates, + + // + isNgCommandExists, + isIonicCommandExists, + isCordovaCommandExists, +} +//#endregion \ No newline at end of file diff --git a/BKPS/14030923/Documents/JsModules/x-type-detector.tools.js b/BKPS/14030923/Documents/JsModules/x-type-detector.tools.js new file mode 100644 index 0000000..86ed3d8 --- /dev/null +++ b/BKPS/14030923/Documents/JsModules/x-type-detector.tools.js @@ -0,0 +1,268 @@ +/** + * DataType Tools Module ... + * a module for manipulate and detect supported data types in node js ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +//#region Constants ... +/** + * all supported data types ... + */ +const DataTypes = { + Null: 'null', + Date: 'date', + Array: 'array', + Object: 'object', + String: 'string', + Number: 'number', + Unknown: 'unknown', + Boolean: 'boolean', + Function: 'function', + Undefined: 'undefined', +}; +//#endregion + +// +//#region Actions ... +/** + * detect type of a content ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function getType(value) { + // + const type = typeof value; + + // + let result = DataTypes.Unknown; + let dateIdentifier = '[object Date]'; + let constructor = value && value.constructor ? + value.constructor.toString() : + ''; + + // + switch (type) { + // + case 'undefined': + result = DataTypes.Undefined; + break; + + // + case 'boolean': + result = DataTypes.Boolean; + break; + + // + case 'string': + result = DataTypes.String; + break; + + // + case 'number': + result = DataTypes.Number; + break; + + // + case 'function': + result = DataTypes.Function; + break; + + // + case 'object': + // + // Null ... + if (value === null) { + result = DataTypes.Null; + } else + // + // Array ... + if (Array.isArray(value)) { + result = DataTypes.Array; + } else + // + // Data ... + if ( + value instanceof Date || + isFunction(value.getMonth) || + constructor.includes(dateIdentifier) || + Object.prototype.toString.call(value) === dateIdentifier + ) { + result = DataTypes.Date; + } else + // + // Object ... + { + result = DataTypes.Object; + } + break; + + // + default: + result = DataTypes.Unknown; + break; + } + + // + return result; +} + +/** + * retrieve an object constructor ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function getConstructor(value) { + // + const result = value && value.constructor ? + value.constructor.toString() : + ''; + + // + return result; +} + +/** + * retrieve an object prototype ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function getPrototype(value) { + // + const result = value ? + Object.prototype.toString.call(value) : + ''; + + // + return result; +} + +/** + * check an object is null or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isNull(value) { + return getType(value) === DataTypes.Null; +} + +/** + * check an object is undefined or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isUndefined(value) { + return getType(value) === DataTypes.Undefined; +} + +/** + * check an object is null or undefined or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isNullOrUndefined(value) { + return isNull(value) || isUndefined(value); +} + +/** + * check an object is a date or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isDate(value) { + return getType(value) === DataTypes.Date; +} + +/** + * check an object is number or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isNumber(value) { + return getType(value) === DataTypes.Number; +} + +/** + * check an object is string or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isString(value) { + return getType(value) === DataTypes.String; +} + +/** + * check an object is boolean or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isBoolean(value) { + return getType(value) === DataTypes.Boolean; +} + +/** + * check an object is an Array or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isArray(value) { + return getType(value) === DataTypes.Array; +} + +/** + * check an object is and Object or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isObject(value) { + return getType(value) === DataTypes.Object; +} + +/** + * check an object is a Function or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isFunction(value) { + return getType(value) === DataTypes.Function; +} +//#endregion + +// +//#region Module Exports ... +module.exports = { + // + DataTypes, + + // + getType, + getConstructor, + getPrototype, + isNull, + isUndefined, + isNullOrUndefined, + isDate, + isNumber, + isString, + isBoolean, + isArray, + isObject, + isFunction, +} +//#endregion \ No newline at end of file diff --git a/BKPS/14030923/Documents/JsModules/x-value.tools.js b/BKPS/14030923/Documents/JsModules/x-value.tools.js new file mode 100644 index 0000000..81cfcc4 --- /dev/null +++ b/BKPS/14030923/Documents/JsModules/x-value.tools.js @@ -0,0 +1,1528 @@ +/** + * Value Tools Module ... + * a module for Validate args and values ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +//#region Imports ... +const XTypeTools = require('./x-type-detector.tools'); +//#endregion + +// +//#region Actions ... +/** +* validate a value as an argument ... +* +* @param {string} value the value which going to validate ... +* @returns +*/ +function isValidArg(value) { + // + let result = false; + + // + result = value && + value.length > 0; + + // + return result; +} + +/** + * validate a collection of valuea as an arguments ... + * + * @param {string|string[]} values the value collection which going to checked ... + * @returns + */ +function isValidArgs(values) { + // + // Normalize Values ... + const normalValues = toNormalArray(values); + if (!hasChildArray(normalValues)) { + return false; + } + + // + let result = normalValues.every(nv => isValidArg(nv)); + return result; +} + +/** + * converts content to an array object ... + * + * @param {string|string[]} content the content which required to normalized ... + * @returns {string[]} array object ... + */ +function toNormalArray(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return []; + } + + // + const result = Array.isArray(content) ? + [...content] : + content.includes(',') && + content !== ',' ? + [...content.split(',')] : + [content]; + + // + return result; +} + +/** + * determines value is array and has atleast one child ... + * + * @param {any} value the value which going to checked ... + * @returns {boolean} result of checking ... + */ +function hasChildArray(value) { + // + let result = false; + result = value && + Array.isArray(value) && + value.length > 0; + + // + return result; +} + +/** + * check an string is ends with specified symbol ... + * + * @param {string} symbol specified search symbol ... + * @param {string} value specified search content ... + * @param {boolean} ignoreCase specified search case sensitive or not ... + * @returns + */ +function endsWidth( + symbol = '', + value = '', + ignoreCase = true +) { + // + if (!isValidArg(value)) { + return false; + } + + // + if (!isValidArg(symbol)) { + return true; + } + + // + // TODO: uncomment it if necessary ... + // symbol = symbol.trim(); + + // + let result = false; + const subtractedContent = value.substring(value.length - symbol.length); + result = !!ignoreCase ? + subtractedContent + .toLowerCase() === symbol + .toLowerCase() : + subtractedContent === symbol; + + // + return result; +} + +/** + * surround specified content by provided symbol ... + * + * @param {string} symbol surround string ... + * @param {string} content used content to surrounded by symbol ... + * @returns surrounded content ... + */ +function surroundBy( + symbol = '', + content = '' +) { + // + // Validate Args ... + if (!isValidArg(content)) { + content = ''; + } + + // + if (!isValidArg(symbol)) { + symbol = ''; + } + + // + if (isSurrounded(symbol, content)) { + return content; + } + + // + const result = `${symbol}${content}${symbol}`; + return result; +} + +/** + * convert a parsed sign to clear string ... + * + * @param {string} value a parsed content ... + * @returns clear parsed signs ... + */ +function toStringExpression(value) { + // + let result = ''; + result = value; + + // + if ( + !value || + !isValidArg(value) || + !isSurroundedString(value) + ) { + return result; + } + + // + const startSymbol = value.charAt(0); + const endSymbol = value.charAt(value.length - 1); + + // + if (startSymbol !== endSymbol) { + return result; + } + + // + if ( + startSymbol === "\"" || + startSymbol === "\'" + ) { + result = clearSurround(startSymbol, value); + } + + // + return result; +} + + + +/** + * find and cleare proposed candidates from specified content ... + * + * @param {string|string[]} candidates the proposed string(s) whic going to cleared from content ... + * @param {string} content the destination content which used to find and replace candidates on it ... + * @returns cleared content ... + */ +function clearContent( + candidates, + content +) { + // + // Validate Args ... + if ( + !candidates || + !isValidArg(content) + ) { + return ''; + } + + // + // Normalize candidates ... + const normalCandidates = toNormalArray(candidates) + .filter(c => isValidArg(c)); + if (!hasChildArray(normalCandidates)) { + return content; + } + + // + // define regexp for content ... + const regExpExpression = normalCandidates.join('|'); + const regExp = new RegExp( + regExpExpression, + 'gi' + ); + + // + let result = ''; + result = content.replace(regExp, ''); + + // + return result; +} + +/** + * clear surrounded symbol from content ... + * + * @param {string} symbol specified search symbol ... + * @param {string} content specified content to clear ... + * @returns + */ +function clearSurround( + symbol = '', + content = '' +) { + // + // Validate Args ... + if ( + !isValidArg(content) || + (isValidArg(symbol) && + symbol.length >= content.length - 1) + ) { + return ''; + } + + // + // Validate Surround ... + if (!isSurrounded(symbol, content)) { + return content; + } + + // + if (!isValidArg(symbol)) { + return content; + } + + // + let result = content.substring(symbol.length, content.length - symbol.length); + return result; +} + +/** + * clear object sign ... + * + * @param {string} content + * @returns cleared content ... + */ +function clearObjectSurround(content = '') { + // + // Validate Args ... + if ( + !isValidArg(content) || + !isSurroundedObject(content) + ) { + return content; + } + + // + const endIndex = content.length - ( + endsWidth('}', content) ? + 1 : + endsWidth('},', content) || + endsWidth('};', content) || + endsWidth('}\n', content) ? + 2 : + 0 + ); + + // + const result = content.substring(1, endIndex); + return result; +} + +/** + * clear array sign ... + * + * @param {string} content + * @returns cleared content ... + */ +function clearArraySurround(content = '') { + // + // Validate Args ... + if ( + !isValidArg(content) || + !isSurroundedArray(content) + ) { + return content; + } + + // + const endIndex = content.length - ( + endsWidth(']', content) ? + 1 : + endsWidth('],', content) || + endsWidth('];', content) || + endsWidth(']\n', content) ? + 2 : + 0 + ); + + // + const result = content.substring(1, endIndex); + return result; +} + +/** + * slice a content to individual parts ... + * + * @param {number|number[]} indexes which indexes used to slice ... + * @param {strng} content the content which going to sliced ... + * @returns sliced parts of content ... + */ +function sliceContent(indexes, content) { + // + // Validate Args ... + if ( + !isValidArg(indexes) || + !isValidArg(content) + ) { + return []; + } + + // + // Normalize indexes ... + const normalIndexes = toNormalArray(indexes) + .filter(index => index > -1 && index < content.length); + if (!hasChildArray(normalIndexes)) { + return []; + } + + // + let result = ['']; + result.pop(); + + // + let lastIndex = 0; + for (const index of normalIndexes) { + // + const part = content.substring(lastIndex, index); + if (isValidArg(part)) { + result.push(part.trim()); + } + + // + lastIndex = index + 1; + } + + // + // check remained parts ... + if (lastIndex < content.length) { + // + const part = content.substring(lastIndex); + if (isValidArg(part)) { + result.push(part.trim()); + } + } + + // + return result; +} + + + +/** + * check an string is starts and ends with specified symbol ... + * + * @param {string} symbol specified search symbol ... + * @param {string} content specified search content ... + * @param {boolean} ignoreCase specified search case sensitive or not ... + * @returns + */ +function isSurrounded( + symbol = '', + content = '', + ignoreCase = true +) { + // + // Validate Args ... + if (!isValidArg(content)) { + return false; + } + + // + if (!isValidArg(symbol)) { + return true; + } + + // + symbol = symbol.trim(); + + // + let result = false; + result = (!!ignoreCase ? + content + .toLowerCase() + .startsWith(symbol.toLowerCase()) : + content.startsWith(symbol) + ) && + endsWidth(symbol, content, ignoreCase); + + // + return result; +} + +/** + * determines a content is an string surrounded value or not ... + * + * @param {string} content a content which going to check ... + * @returns + */ +function isSurroundedString(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return false; + } + + // + let result = false; + result = ( + content.startsWith('\'') && + ( + endsWidth('\'', content) || + endsWidth('\',', content) || + endsWidth('\';', content) || + endsWidth('\'\n', content) + ) || + content.startsWith('\"') && + ( + endsWidth('\"', content) || + endsWidth('\",', content) || + endsWidth('\";', content) || + endsWidth('\"\n', content) + ) || + content.startsWith('`') && + ( + endsWidth('\`', content) || + endsWidth('\`,', content) || + endsWidth('\`;', content) || + endsWidth('\`\n', content) + ) + ); + return result; +} + +/** + * check a content is an array content or not ... + * + * @param {string} content + * @returns + */ +function isSurroundedArray(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return false; + } + + // + let result = false; + result = content.startsWith('[') && + ( + endsWidth(']', content) || + endsWidth('],', content) || + endsWidth('];', content) || + endsWidth(']\n', content) + ); + return result; +} + +/** + * check a content is an object content or not ... + * + * @param {string} content + * @returns + */ +function isSurroundedObject(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return false; + } + + // + let result = false; + result = content.startsWith('{') && + ( + endsWidth('}', content) || + endsWidth('},', content) || + endsWidth('};', content) || + endsWidth('}\n', content) + ); + return result; +} + +/** + * check an index model is contains inside anothers or not ... + * + * @param {{ start: number, end: number}} source the source index model to check ... + * @param {...{ start: number, end: number}} dest the collection of index models which going to check ... + * @returns + */ +function isIndexInside(source, ...dest) { + // + let result = false; + + // + // Validate Args ... + if (!source || !dest) { + return result; + } + + // + // Check idx is standard ... + if ( + !source || + !source.end || + !source.start || + source.start > source.end + ) { + return false; + } + + // + // Check types of destinations ... + for (let index of dest) { + // + // Check idx is standard ... + if ( + !index || + !index.end || + !index.start || + index.start > index.end + ) { + return false; + } + } + + // + if (dest.includes(source)) { + dest = dest.filter(d => d !== source); + } + + // + const insideContentIndex = dest.find(dIndex => { + // + const result = source.start >= dIndex.start && + source.start <= dIndex.end && + source.end >= dIndex.start && + source.end <= dIndex.end; + return result; + }); + + // + result = insideContentIndex; + return result; +} + +/** + * check a number exists in + * @param {number} idx the number which going to check ... + * @param {{ start: number, end: number}} index the index model + * @returns + */ +function isInsideIndex(idx = -1, index) { + // + let result = false; + + // + // Validate Args ... + if ( + !index || + !index.hasOwnProperty('end') || + !index.hasOwnProperty('start') + ) { + return result; + } + + // + result = idx > index.start && idx < index.end; + return result; +} + +/** + * determines an object is key/value and type ... + * + * @param {any} content the object which we are going to check ... + * @returns + */ +function isKeyValueType(content) { + // + const result = content && + content.hasOwnProperty('key') && + content.hasOwnProperty('type') && + content.hasOwnProperty('value'); + + // + return result; +} + + + +/** + * find all indexes of token(s) in content ... + * + * @param {string|string[]} tokens the tokens which require to search ... + * @param {string} content the content which using to search ... + * @returns {number[]} all occured indexes ... + */ +function findAllIndexes( + tokens, + content +) { + // + // Validate Args ... + if ( + !isValidArg(tokens) || + !isValidArg(content) + ) { + return []; + } + + // + // normalize tokens ... + const normalTokens = toNormalArray(tokens); + if (!hasChildArray(normalTokens)) { + return []; + } + + // + // Parse contents ... + let match; + const result = []; + const regExp = new RegExp( + normalTokens.join('|'), + 'g' + ); + while ((match = regExp.exec(content)) !== null) { + result.push(match.index); + } + if (!hasChildArray(result)) { + return []; + } + + // + return result; +} + +/** + * find nearest symbol in a content from specified index ... + * + * @param {string|string[]} candidates specifies which symbols to find ... + * @param {string} content te content for seasrch ... + * @param {number} startFromIndex the index of start position ... + * @returns + */ +function findNearest( + candidates, + content = '', + startFromIndex = 0 +) { + // + // Validate Args ... + if ( + !isValidArg(content) || + !isValidArg(candidates) || + !isValidArg(content.trim()) + ) { + return ''; + } + + // + // Normalize Content ... + content = content.trim(); + + // + // Normalize Starts From ... + startFromIndex = startFromIndex < 0 || startFromIndex > content.length - 1 ? 0 : startFromIndex; + + // + // Normalize Symbols ... + const normalCandidates = toNormalArray(candidates); + if (!hasChildArray(normalCandidates)) { + return ''; + } + + // + let nearestIndex = findNearestIndex( + normalCandidates, + content, + startFromIndex + ); + if (nearestIndex < 0) { + return ''; + } + + // + let result = content.substring( + nearestIndex, + nearestIndex + Math.max(...normalCandidates.map(nc => nc.length)) + ).trim(); + return result; +} + +/** + * search candidates in content and find nearest one and return it ... + * + * @param {string|string[]} candidates which candidates required to check ... + * @param {string} content the content which required to search candidates ... + * @param {number} startFromIndex the proposed index to start searching content from on ... + * @returns + */ +function findNearestIndex( + candidates = [''], + content = '', + startFromIndex = 0, + ignoreClosedItems = false +) { + // + // Validate Args ... + if ( + !isValidArg(content) || + !isValidArg(candidates) + ) { + return -1; + } + + // + // Mormalize startFromIndex value ... + startFromIndex = startFromIndex < 0 ? + 0 : + startFromIndex > content.length - 1 ? + content.length - 1 : + startFromIndex; + + // + // Normalize candidates ... + let normalCandidates = toNormalArray(candidates); + + // + if (!!ignoreClosedItems) { + normalCandidates = normalCandidates + .map(c => content.indexOf( + c, + startFromIndex + ) + ).map(c => +c) + .filter(c => +c > -1); + } else { + normalCandidates = findAllIndexesOutOfCloseds(normalCandidates, content) + .filter(c => c >= startFromIndex); + } + if (!hasChildArray(normalCandidates)) { + return -1; + } + + // + let result = -1; + result = Math.min(...normalCandidates); + + // + return result; +} + +/** + * find close index of specific sign in destination content ... + * + * @param {string} openSymbol open of area sign ... + * @param {string} closeSymbol close of area sign ... + * @param {string} content the destination content for parsing ... + * @param {number} startsFrom an start index of content for start parsing ... + * @returns + */ +function findCloseIndex( + openSymbol = '', + closeSymbol = '', + content = '', + startsFrom = -1 +) { + // + // Validate Args ... + if ( + startsFrom < 0 || + !isValidArg(content) || + !isValidArg(openSymbol) || + !isValidArg(closeSymbol) || + openSymbol === closeSymbol || + !content.includes(openSymbol) || + !content.includes(closeSymbol) || + startsFrom > content.length - 1 + ) { + return -1; + } + + // + let result = -1; + + // + let index = startsFrom; + const openSignStack = []; + while (index < content.length) { + // + const openCandidate = content.substring(index, index + openSymbol.length); + const closeCandidate = content.substring(index, index + closeSymbol.length); + + // + if (openCandidate === openSymbol) { + openSignStack.push(index); + } else if (closeCandidate === closeSymbol) { + // + if (openSignStack.length > 0) { + openSignStack.pop(); + } + + // + if (openSignStack.length === 0) { + result = index; + break; + } + } + + // + index++; + } + + // + return result; +} + +/** + * find closed contents of specific sign in destination content ... + * + * @param {string} openSymbol open of area sign ... + * @param {string} closeSymbol close of area sign ... + * @param {string} content the destination content for parsing ... + * @param {number} startsFrom an start index of content for start parsing ... + * @returns + */ +function findClosedContent( + openSymbol = '', + closeSymbol = '', + content = '', + startsFrom = 0, +) { + // + let result = [{ + start: -1, + end: -1, + content: '' + }]; + result.pop(); + + // + // Validate Args ... + if ( + !isValidArg(content) || + !isValidArg(openSymbol) || + !isValidArg(closeSymbol) || + !content.includes(openSymbol) || + !content.includes(closeSymbol) || + openSymbol.length >= content.length || + closeSymbol.length >= content.length + ) { + return result; + } + + // + // Normalize Start From ... + startsFrom = startsFrom < 0 || startsFrom >= content.length ? 0 : startsFrom; + + // + let canContinue = true; + while (!!canContinue) { + // + let openSymbolIndex = content.indexOf(openSymbol, startsFrom); + if (openSymbolIndex < 0) { + // + canContinue = false; + continue; + } + + // + let closeSymbolIndex = findCloseIndex( + openSymbol, + closeSymbol, + content, + openSymbolIndex + ); + if (closeSymbolIndex < 0) { + // + canContinue = false; + continue; + } + if (content.charAt(closeSymbolIndex) !== closeSymbol) { + closeSymbolIndex++; + } + + // + // Prevent ${} string interpolations ... + if ( + openSymbol === '{' && + openSymbolIndex - 1 >= 0 + ) { + // + const prevChar = content.charAt(openSymbolIndex - 1); + if (prevChar === '$') { + continue; + } + } + + // + const item = content + .substring(openSymbolIndex, closeSymbolIndex + 1) + .trim(); + startsFrom = closeSymbolIndex + 1; + result.push({ + start: openSymbolIndex, + end: closeSymbolIndex, + content: item + }); + } + + // + if (!hasChildArray(result)) { + return result; + } + + // + return result; +} + +/** + * extract a collection of closed contents exists in a content ... + * + * @param symbols a collection of open and close contents ... + * @param {string} content a content for searching inside it ... + * @returns a collection of closed content ... + */ +function findClosedContents( + symbols = [ + { + openSymbol: '', + closeSymbol: '' + } + ], + content = '' +) { + // + let result = [{ + start: -1, + end: -1, + content: '' + }]; + result.pop(); + + // + if ( + !isValidArg(content) || + !hasChildArray(symbols) + ) { + return []; + } + + // + symbols.forEach(symbol => { + // + const closedContent = findClosedContent( + symbol.openSymbol, + symbol.closeSymbol, + content + ); + + // + if (hasChildArray(closedContent)) { + result.push( + ...closedContent + ); + } + }); + + // + return result; +} + +/** + * find all string content closed items ... + * + * @param {string} content a content which going to search ... + * @returns a collection of index descriptors ... + */ +function findClosedStrings(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return []; + } + + // + // there are 3 types of strings ... + // ' " and ` + + // + const token1 = '\''; + const token1Stack = [0]; + token1Stack.pop(); + + // + const token2 = '"'; + const token2Stack = [0]; + token2Stack.pop(); + + // + const token3 = '`'; + const token3Stack = [0]; + token3Stack.pop(); + + // + const result = [ + { + start: -1, + end: -1, + content: '' + } + ]; + result.pop(); + + // + for (let i = 0; i < content.length; i++) { + // + const currentChart = content.charAt(i); + + // + //#region Token 1 ... + if (currentChart === token1) { + // + if (!hasChildArray(token1Stack)) { + token1Stack.push(i); + } else { + // + const start = token1Stack.pop(); + const end = i + 1; + const pContent = content.substring(start, end); + result.push({ + start, + end, + content: pContent + }); + } + } + //#endregion + + // + //#region Token 2 ... + if (currentChart === token2) { + // + if (!hasChildArray(token2Stack)) { + token2Stack.push(i); + } else { + // + const start = token2Stack.pop(); + const end = i + 1; + const pContent = content.substring(start, end); + result.push({ + start, + end, + content: pContent + }); + } + } + //#endregion + + // + //#region Token 3 ... + if (currentChart === token3) { + // + if (!hasChildArray(token3Stack)) { + token3Stack.push(i); + } else { + // + const start = token3Stack.pop(); + const end = i + 1; + const pContent = content.substring(start, end); + result.push({ + start, + end, + content: pContent + }); + } + } + //#endregion + } + + // + return result; +} + +/** + * find container indexes from within indexes ... + * + * @param {...{start: number, end: number}} index the collection of indexes to find beiggers inside ... + * @returns + */ +function findContainerIndexes(...index) { + // + let result = [ + { + start: -1, + end: -1, + content: '' + } + ]; + result.pop(); + + // + let concatedIndexes = []; + for (let idx of index) { + // + // Index Childs ... + for (let iix of idx) { + // + // Check idx is standard ... + if ( + !iix || + !iix.end || + !iix.start || + iix.start > iix.end + ) { + continue; + } + + // + // Check index inside another index ... + concatedIndexes.push(iix); + } + } + + // + if (!hasChildArray(concatedIndexes)) { + return result; + } + + // + for (let ccIdx of concatedIndexes) { + // + const isInside = isIndexInside(ccIdx, ...concatedIndexes); + if (isInside) { + continue; + } + + // + if (hasChildArray(result)) { + // + const isInsideResult = isIndexInside(ccIdx, ...result); + if (isInsideResult) { + continue; + } + } + + // + result.push(ccIdx); + } + + // + return result; +} + +/** + * find all tokens indexes inside a content which they are not inside closed items ... + * + * @param {string|string[]} tokens the tokens which require to search ... + * @param {string} content the content which using to search ... + * @returns + */ +function findAllIndexesOutOfCloseds1( + tokens, + content, +) { + // + // Validate Args ... + if (!isValidArg(content)) { + return []; + } + + // + // Extract token Indexes ... + const tokensIndexes = findAllIndexes(tokens, content); + if (!hasChildArray(tokensIndexes)) { + return []; + } + + // + // Extract Closed Objects Indexes ... + const closedArrays = findClosedContent('[', ']', content); + const closedObjects = findClosedContent('{', '}', content); + const closedStrings = findClosedStrings(content); + if ( + !hasChildArray(closedObjects) && + !hasChildArray(closedArrays) && + !hasChildArray(closedStrings) + ) { + return tokensIndexes; + } + + // + // find bigger sloded ... + let containerClosedItems = findContainerIndexes( + closedArrays, + closedObjects, + closedStrings + ).filter(i => !isSurroundedString(i.content)); + + // + let result = [-1]; + result.pop(); + + // + for (let tIdx of tokensIndexes) { + // + let canAdd = true; + for (let ccIndex of containerClosedItems) { + // + canAdd = isInsideIndex(tIdx, ccIndex); + if (canAdd) { + break; + } + } + + // + if (!canAdd) { + result.push(tIdx); + } + } + + // + return result; +} + +/** + * find all tokens indexes inside a content which they are not inside closed items ... + * + * @param {string|string[]} tokens the tokens which require to search ... + * @param {string} content the content which using to search ... + * @returns + */ +function findAllIndexesOutOfCloseds( + tokens, + content, +) { + // + // Define Result ... + let result = [-1]; + result.pop(); + + // + // Validate Args ... + if (!isValidArg(content)) { + return []; + } + + // + // Normalize Tokens ... + const normalizeTokens = toNormalArray(tokens); + if (!hasChildArray(normalizeTokens)) { + return result; + } + + // + // Extract Closed Objects Indexes ... + let openSymbols = [ + '{', + '[', + '\'', + '"', + '`' + ]; + let closeSymbols = [ + '}', + ']', + '\'', + '"', + '`' + ]; + let openStack = []; + let lastOpenSymbol = ''; + let lastClosedIndex = -1; + for (let i = 0; i < content.length; i++) { + // + const prevChar = content.charAt(i - 1) || ''; + const char = content.charAt(i); + const nextChar = content.charAt(i + 1) || ''; + + // + const isToken = normalizeTokens.includes(char); + const isOpenSymbol = openSymbols.includes(char); + const isCloseSymbol = closeSymbols.includes(char); + + // + if (isOpenSymbol && lastOpenSymbol !== char) { + openStack.push(i); + lastOpenSymbol = char === '\'' || char === '"' || char === '`' ? char : lastOpenSymbol; + } else if (isCloseSymbol) { + // + lastOpenSymbol = char === '\'' || char === '"' || char === '`' ? '' : lastOpenSymbol; + let lastPop = openStack.pop(); + if (openStack.length === 0) { + lastClosedIndex = lastPop; + } + } else if (isToken) { + if ( + i > lastClosedIndex && + openStack.length === 0 + ) { + result.push(i); + } + } + } + + // + return result; +} +//#endregion + +// +//#region Validator Actions ... +/** + * check specified value is Valid URL Address or not ... + * + * @param {string} value specified string which required to check + * @returns {boolean} + */ +function isValidURL(value = "") { + // + if (!isValidArg(value)) { + return false; + } + + const pattern = new RegExp( + '^([a-zA-Z]+:\\/\\/)?' + // protocol + '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name + '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR IP (v4) address + '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path + '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string + '(\\#[-a-z\\d_]*)?$', // fragment locator + 'i' + ); + + // + const result = pattern.test(value); + return result; +} + +/** + * check specified value is Valid URL Address or not ... + * + * @param {string} value specified string which required to check + */ +function isValidEmail(value = "") { + // + if (!isValidArg(value)) { + return false; + } + + // + const pattern = /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}/gim; + + // + const result = pattern.test(value); + return result; +} +//#endregion + +// +//#region Normallizers ... +/** + * normallize an string ... + * + * @param {string} value specified value ... + * @returns {string} + */ +function toNormalString(value = "") { + // + if (!XTypeTools.isString(value)) { + value = ""; + } + + // + const result = value + .trim() + .toLowerCase(); + + // + return result; +} +//#endregion + +// +//#region Beautifiers ... +/** + * converts an object to string based on json and beautify result ... + * + * @param {any} object + * @returns {string} + */ +function beautifyJSON(object = undefined) { + // + // TODO: Complete this ... + let result = ""; + + // + // validate object ... + if (object === undefined) { + return result; + } + + // + // Convert result ... + result = JSON.stringify( + object, + null, + 4 + ); + + // + return result; +} +//#endregion + +// +//#region Module Exports ... +module.exports = { + // + endsWidth, + surroundBy, + isValidArg, + isValidArgs, + toNormalArray, + hasChildArray, + toStringExpression, + + // + sliceContent, + clearContent, + clearSurround, + clearArraySurround, + clearObjectSurround, + + // + isSurrounded, + isIndexInside, + isInsideIndex, + isKeyValueType, + isSurroundedArray, + isSurroundedString, + isSurroundedObject, + + // + findNearest, + findAllIndexes, + findCloseIndex, + findNearestIndex, + findClosedContent, + findClosedStrings, + findClosedContents, + findAllIndexesOutOfCloseds, + + // + // Validator Actions ... + isValidURL, + isValidEmail, + + // + // Normallizers ... + toNormalString, + + // + beautifyJSON, +} +//#endregion \ No newline at end of file diff --git a/BKPS/14030923/Documents/Temlates/x-saherelm.x-ea.template.ea.mq5 b/BKPS/14030923/Documents/Temlates/x-saherelm.x-ea.template.ea.mq5 new file mode 100644 index 0000000..ec3e257 --- /dev/null +++ b/BKPS/14030923/Documents/Temlates/x-saherelm.x-ea.template.ea.mq5 @@ -0,0 +1,542 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XTest MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XEATemplate +// Description: a Template For Exper Advisors +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +//////////////////////////////////////////////////////x +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XEATemplate" +#property strict + +// +#define ShortName "XEATemplate" + +// +// Imports ... +#include "../Classes/x-saherelm.xalert.class.mq5" +#include "../Classes/x-saherelm.xtrade.class.mq5" +#include "../Helpers/x-saherelm.xcc.helper.mq5" +#include "../Helpers/x-saherelm.xct.helper.mq5" + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 78692110; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Alert ... +// Here we Provider All Requirements for +// Configuring Alert Provider ... +input group "Alert"; +input bool eAEnableAlerts = true; // Enable Alerts +input bool eALogAlerts = true; // Log Alerts +input bool eAMailAlerts = false; // Mail Alerts +input bool eAPushAlerts = false; // Push Alerts +input bool eATerminalAlerts = false; // Terminal Alerts + +// +// Time Report ... +input group "Reports"; +input bool eaReportNewMonths = false; // Report New Month +input bool eaReportNewWeeks = false; // Report New Weeks +input bool eaReportNewDays = false; // Report New Days +input bool eaReportNewHours = false; // Report New Hours + +// +// Define Local Variables ... + +// +string eaLogTag; // EA Log Prefix ... +XSCAlert *eaAlert; // Alert Provider for Expert Adviser ... +XSCTrade *eaTrader; // Trader of Expert Adviser ... +XTimeTracker eaTimeTracker; // Time Tracker for Providing Reports ... +XSCXCTHelper *eaCHelper; // Bar Timer Indicator Helper class ... +XSCXCCHelper *eaCCHelper; // Chart Styler Indicator Helper Class ... + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs and Required Parameters + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) { + return INIT_FAILED; + } + + // + // Initialize all Requirements ... + if (!InitEA()) + { + return INIT_FAILED; + } + + // + // Initialize all GUI Objects and Classes ... + if (!InitGUI()) + { + return INIT_FAILED; + } + + // + // Alert Initialization ... + string msg = "Initialized Successfully ..."; + eaAlert.Alert(msg); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +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 + + // + // Destroy Timer ... + DestroyTimer(); + + // + // Destroy all GUI Requirements ... + DestroyGUI(); + + // + // Alert De Initialization Succeeded ... + string msg = "De Initialized Successfully ..."; + eaAlert.Alert(msg); + + // + // Destroy all EA Requirements ... + DestroyEA(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + UpdateGUI(); + HandleReportTime(); + UpdatePositionsState(); + + // + // TODO: Implemetn Tick Processors Algorithm ... +} + +// +// Handle On Trade Event ... +void OnTrade() +{ + eaTrader.HandleOnTrade(); +} + +// +// On Timer ... +void OnTimer() +{ + // + // TODO: Implement Time Based Functionalities ... +} + +// +// Chart Event Handler ... +void OnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // +) +{ + // + // Handle OnClick Event ... + if (id == CHARTEVENT_OBJECT_CLICK) + { + HandleOnClickEvent(sparam); + } +} + +// +// Custom Event Handlers ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + // + HandleReportBalance(); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + // + HandleReportBalance(); +} + +/** + * Handle Force Close a Position ... + * + * @param ticket: Position Ticket ... + * @param position: XPosition ... + * @param comment: Closing Comment ... + */ +void OnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // +) +{ + // + HandleReportBalance(); +} + +// +// Custom Functions ... + +/** + * Validate all Inputs of Expert Adviser ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + eaSlippage > 0 && + eaMagicNumber > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + Print(ShortName + " Errors: \n", errMessage); + } + + // + return result; +} + +/** + * Initialize Timer ... + * + * @return ( bool ) + */ +bool InitTimer() { + // + bool result = false; + + // + // TODO: Initialize Timer if necessary ... + // result = EventSetTimer(1); + // result = EventSetMillisecondTimer(100); + result = true; + + // + return result; +} + +/** + * Destroy Timer ... + */ +void DestroyTimer() { + // + // TODO: Use This ... + // EventKillTimer(); +} + +/** + * Initialize all Requirements for Working Fine ... + * + * @return ( bool ) + */ +bool InitEA() +{ + // + bool result = false; + + // + // Locally Apply Changes on Prefix ... + eaLogTag = ShortName + ">" + eaLogSuffix; + + // + // Bar Timer ... + XCTInputs ctInputs; + ctInputs.Default(); // Default Configurations ... + eaCHelper = new XSCXCTHelper(); + result = eaCHelper.Init( + _Symbol, + _Period, + ctInputs // + ); + if (!result) + { + return result; + } + + // + // Bar Styles ... + XCCInputs ccInputs; + ccInputs.Default(); // Default Configurations ... + eaCCHelper = new XSCXCCHelper(); + result = eaCCHelper.Init( + _Symbol, + _Period, + ccInputs // + ); + if (!result) + { + return result; + } + + // + // Create Instance of Alert Class and Configure it ... + eaAlert = new XSCAlert(); + eaAlert.SetPrefix(eaLogTag); + eaAlert.SetLogAlerts(eALogAlerts); + eaAlert.SetMailAlerts(eAMailAlerts); + eaAlert.SetPushAlerts(eAPushAlerts); + eaAlert.SetEnableAlerts(eAEnableAlerts); + eaAlert.SetTerminalAlerts(eATerminalAlerts); + + // + // Create Trader Instance and Configure it ... + eaTrader = new XSCTrade( + eaSlippage, + eaMagicNumber // + ); + eaTrader.AddOnStopLossEventHandler(OnStopLossTriggered); + eaTrader.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaTrader.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + + // + return result; +} + +/** + * Destroy all Initialized EA Requirements ... + */ +void DestroyEA() +{ + // + delete eaCHelper; + delete eaCCHelper; + + // + delete eaAlert; +} + +/** + * Initialize all GUI Requirements for EA ... + * + * @return ( bool ) + */ +bool InitGUI() +{ + // + bool result = false; + + // + // TODO: Fix This ... + result = true; + + // + return result; +} + +/** + * Update GUI based on Each Ticks ... + */ +void UpdateGUI() +{ + // + // TODO: Implement this ... +} + +/** + * Destroy all Initialized GUi Requirements ... + */ +void DestroyGUI() +{ + // + // TODO: Complete this ... +} + +// +// Others ... + +/** + * Update Positions States ... + */ +void UpdatePositionsState() +{ + // + // TODO: Implement this ... +} + +/** + * Handle On Click Event for GUI Components ... + * + * @param name: Object Name ... + */ +void HandleOnClickEvent(string name) +{ + // + if (!IsValid(name)) + { + return; + } + + // + bool isClicked = false; + + // + // TODO: Implement Chart Objects On Click ... + + // + if (isClicked) + { + UpdateGUI(); + } +} + +/** + * Report Account Balance ... + */ +void HandleReportBalance() +{ + // + if (!IsRunningOnTestMode()) + { + return; + } + + // + string msg = "Balance: " + ToString(eaTrader.mAccount.GetBalance()); + eaAlert.Log(msg); +} + +/** + * Time Reporting based on Inputs ... + */ +void HandleReportTime() +{ + // + // Monthly Report .... + if (eaReportNewMonths && + eaTimeTracker.IsNewMonth()) + { + // + string msg = "New Month ..."; + + // + eaAlert.Alert(msg); + } + + // + // Weekly Report .... + if (eaReportNewWeeks && + eaTimeTracker.IsNewWeek()) + { + // + string msg = "New Week ..."; + + // + eaAlert.Alert(msg); + } + + // + // Daily Report .... + if (eaReportNewDays && + eaTimeTracker.IsNewDay()) + { + // + string msg = "New Day ..."; + + // + eaAlert.Alert(msg); + } + + // + // Hourly Report .... + if (eaReportNewHours && + eaTimeTracker.IsNewHour()) + { + // + string msg = "New Hour ..."; + + // + eaAlert.Alert(msg); + } +} + +// diff --git a/BKPS/14030923/Documents/Temlates/x-saherelm.x-panel.ea.mq5 b/BKPS/14030923/Documents/Temlates/x-saherelm.x-panel.ea.mq5 new file mode 100644 index 0000000..c04228d --- /dev/null +++ b/BKPS/14030923/Documents/Temlates/x-saherelm.x-panel.ea.mq5 @@ -0,0 +1,575 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XTest MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XPanelEA +// Description: an Exper Advisor which used Panels +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +//////////////////////////////////////////////////////x +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XPanelEA" +#property strict + +// +#define ShortName "XPANELEA" + +// +// Imports ... +#include "../Classes/x-saherelm.x-app-dialog.class.mq5" +#include "../Classes/x-saherelm.xalert.class.mq5" +#include "../Classes/x-saherelm.xtrade.class.mq5" +#include "../Helpers/x-saherelm.xcc.helper.mq5" +#include "../Helpers/x-saherelm.xct.helper.mq5" + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 78692110; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Alert ... +// Here we Provider All Requirements for +// Configuring Alert Provider ... +input group "Alert"; +input bool eAEnableAlerts = true; // Enable Alerts +input bool eALogAlerts = true; // Log Alerts +input bool eAMailAlerts = false; // Mail Alerts +input bool eAPushAlerts = false; // Push Alerts +input bool eATerminalAlerts = false; // Terminal Alerts + +// +// Time Report ... +input group "Reports"; +input bool eaReportNewMonths = false; // Report New Month +input bool eaReportNewWeeks = false; // Report New Weeks +input bool eaReportNewDays = false; // Report New Days +input bool eaReportNewHours = false; // Report New Hours + +// +// Define Local Variables ... + +// +string eaLogTag; // EA Log Prefix ... +XSCAlert *eaAlert; // Alert Provider for Expert Adviser ... +XSCTrade *eaTrader; // Trader of Expert Adviser ... +XTimeTracker eaTimeTracker; // Time Tracker for Providing Reports ... +XSCXCTHelper *eaCTHelper; // Bar Timer Indicator Helper class ... +XSCXCCHelper *eaCCHelper; // Chart Styler Indicator Helper Class ... + +// +XCAppDialog eaMainWindow; // EA Main Dialog ... + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs and Required Parameters + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) + { + return INIT_FAILED; + } + + // + // Initialize all Requirements ... + if (!InitEA()) + { + return INIT_FAILED; + } + + // + // Initialize all GUI Objects and Classes ... + if (!InitGUI()) + { + return INIT_FAILED; + } + + // + // Alert Initialization ... + string msg = "Initialized Successfully ..."; + eaAlert.Alert(msg); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +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 + + // + // Destroy Timer ... + DestroyTimer(); + + // + // Destroy all GUI Requirements ... + DestroyGUI(); + + // + // Alert De Initialization Succeeded ... + string msg = "De Initialized Successfully ..."; + eaAlert.Alert(msg); + + // + // Destroy all EA Requirements ... + DestroyEA(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + UpdateGUI(); + HandleReportTime(); + UpdatePositionsState(); + + // + // TODO: Implemetn Tick Processors Algorithm ... +} + +// +// Handle On Trade Event ... +void OnTrade() +{ + eaTrader.HandleOnTrade(); +} + +// +// On Timer ... +void OnTimer() +{ + // + // TODO: Implement Time Based Functionalities ... +} + +// +// Chart Event Handler ... +void OnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // +) +{ + // + // Apply Chart Event on Main Window ... + eaMainWindow.ChartEvent(id, lparam, dparam, sparam); + + // + // Handle OnClick Event ... + if (id == CHARTEVENT_OBJECT_CLICK) + { + HandleOnClickEvent(sparam); + } +} + +// +// Custom Event Handlers ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + // + HandleReportBalance(); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + // + HandleReportBalance(); +} + +/** + * Handle Force Close a Position ... + * + * @param ticket: Position Ticket ... + * @param position: XPosition ... + * @param comment: Closing Comment ... + */ +void OnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // +) +{ + // + HandleReportBalance(); +} + +// +// Custom Functions ... + +/** + * Validate all Inputs of Expert Adviser ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + eaSlippage > 0 && + eaMagicNumber > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + Print(ShortName + " Errors: \n", errMessage); + } + + // + return result; +} + +/** + * Initialize Timer ... + * + * @return ( bool ) + */ +bool InitTimer() +{ + // + bool result = false; + + // + // TODO: Initialize Timer if necessary ... + // result = EventSetTimer(1); + // result = EventSetMillisecondTimer(100); + result = true; + + // + return result; +} + +/** + * Destroy Timer ... + */ +void DestroyTimer() +{ + // + // TODO: Use This ... + // EventKillTimer(); +} + +/** + * Initialize all Requirements for Working Fine ... + * + * @return ( bool ) + */ +bool InitEA() +{ + // + bool result = false; + + // + // Locally Apply Changes on Prefix ... + eaLogTag = ShortName + ">" + eaLogSuffix; + + // + // Bar Timer ... + XCTInputs ctInputs; + ctInputs.Default(); // Default Configurations ... + eaCTHelper = new XSCXCTHelper(); + result = eaCTHelper.Init( + _Symbol, + _Period, + ctInputs // + ); + if (!result) + { + return result; + } + + // + // Bar Styles ... + XCCInputs ccInputs; + ccInputs.Default(); // Default Configurations ... + eaCCHelper = new XSCXCCHelper(); + result = eaCCHelper.Init( + _Symbol, + _Period, + ccInputs // + ); + if (!result) + { + return result; + } + + // + // Create Instance of Alert Class and Configure it ... + eaAlert = new XSCAlert(); + eaAlert.SetPrefix(eaLogTag); + eaAlert.SetLogAlerts(eALogAlerts); + eaAlert.SetMailAlerts(eAMailAlerts); + eaAlert.SetPushAlerts(eAPushAlerts); + eaAlert.SetEnableAlerts(eAEnableAlerts); + eaAlert.SetTerminalAlerts(eATerminalAlerts); + + // + // Create Trader Instance and Configure it ... + eaTrader = new XSCTrade( + eaSlippage, + eaMagicNumber // + ); + eaTrader.AddOnStopLossEventHandler(OnStopLossTriggered); + eaTrader.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaTrader.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + + // + return result; +} + +/** + * Destroy all Initialized EA Requirements ... + */ +void DestroyEA() +{ + // + delete eaCTHelper; + delete eaCCHelper; + + // + delete eaAlert; +} + +/** + * Initialize all GUI Requirements for EA ... + * + * @return ( bool ) + */ +bool InitGUI() +{ + // + bool result = false; + + // + // Initialize Application Main Window ... + result = eaMainWindow.Create( + ChartID(), + ShortName, // Dialog Name ... + 0, // SubWindow ... + 10, // X1 ... + 35, // Y1 ... + 300, // X2 ... + 200 // Y2 ... + ); + + // + // Configuring Dialog ... + // eaMainWindow.MinimizeButton(false); // Hide Minimize Button ... + // eaMainWindow.CloseButton(false); // Hide Close Button ... + eaMainWindow.BackgroundColor(clrBlack); + // result = true; + + // + // Try To Run Main Window ... + if (result) + { + eaMainWindow.Run(); + } + + // + return result; +} + +/** + * Update GUI based on Each Ticks ... + */ +void UpdateGUI() +{ + // + // TODO: Implement this ... +} + +/** + * Destroy all Initialized GUi Requirements ... + */ +void DestroyGUI() +{ + // + eaMainWindow.Destroy(); +} + +// +// Others ... + +/** + * Update Positions States ... + */ +void UpdatePositionsState() +{ + // + // TODO: Implement this ... +} + +/** + * Handle On Click Event for GUI Components ... + * + * @param name: Object Name ... + */ +void HandleOnClickEvent(string name) +{ + // + if (!IsValid(name)) + { + return; + } + + // + bool isClicked = false; + + // + // TODO: Implement Chart Objects On Click ... + + // + if (isClicked) + { + UpdateGUI(); + } +} + +/** + * Report Account Balance ... + */ +void HandleReportBalance() +{ + // + if (!IsRunningOnTestMode()) + { + return; + } + + // + string msg = "Balance: " + ToString(eaTrader.mAccount.GetBalance()); + eaAlert.Log(msg); +} + +/** + * Time Reporting based on Inputs ... + */ +void HandleReportTime() +{ + // + // Monthly Report .... + if (eaReportNewMonths && + eaTimeTracker.IsNewMonth()) + { + // + string msg = "New Month ..."; + + // + eaAlert.Alert(msg); + } + + // + // Weekly Report .... + if (eaReportNewWeeks && + eaTimeTracker.IsNewWeek()) + { + // + string msg = "New Week ..."; + + // + eaAlert.Alert(msg); + } + + // + // Daily Report .... + if (eaReportNewDays && + eaTimeTracker.IsNewDay()) + { + // + string msg = "New Day ..."; + + // + eaAlert.Alert(msg); + } + + // + // Hourly Report .... + if (eaReportNewHours && + eaTimeTracker.IsNewHour()) + { + // + string msg = "New Hour ..."; + + // + eaAlert.Alert(msg); + } +} + +//