diff --git a/Indicators/x-saherelm.xpvpm.mq5 b/Indicators/x-saherelm.xpvpm.mq5 new file mode 100644 index 00000000..72526fe6 --- /dev/null +++ b/Indicators/x-saherelm.xpvpm.mq5 @@ -0,0 +1,1951 @@ +/////////////////////////////////////////////////////// +// +// 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 ENUM_TIMEFRAMES poiPeriod = PERIOD_CURRENT; // POI Detector Period + +// +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 + +// +// Define Variables to Draw POI(s) ... +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 24 +#property indicator_plots 6 + +// +// 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 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 8; + +// +// 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[]; + +// +// 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; +datetime mCStartOnS = NULL; +ENUM_TIMEFRAMES mSCPeriod = NULL; + +// +// XMarketCycle mc; +int mMCLength = 0; +datetime mCStartOnM = NULL; +ENUM_TIMEFRAMES mMCPeriod = NULL; + +// +// XMarketCycle lc; +int mLCLength = 0; +datetime mCStartOnL = NULL; +ENUM_TIMEFRAMES mLCPeriod = NULL; + +// +// XMarketCycle hc; +int mHCLength = 0; +datetime mCStartOnH = NULL; +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 ... + ENUM_TIMEFRAMES mPOIPeriod = NormalizePeriod(poiPeriod); + mPOIDetector = new XCPOIDetector( + _Symbol, + mPOIPeriod // + ); + mPOIDetector.MaxNumberOfPOIs(5); + mPOIDetector.MaxNumberOfRequiredPOIs(1); + 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); +} + +/** + * 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); + } + 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; +} + +/** + * 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); + + // + 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 ... + + // + // Print(msg); +} + +/** + * 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); + } +} + +void UpdateDrawnObjects() +{ + // + int count = mDrawnObjects.Total(); + if (!IsValidSize(count)) + { + return; + } + + // + // Loop Through Drawn Objects ... +} + +// \ No newline at end of file