diff --git a/Classes/x-saherelm.x-poi.drawer.class.mq5 b/Classes/x-saherelm.x-poi.drawer.class.mq5 index ffb62cac..e0c6437a 100644 --- a/Classes/x-saherelm.x-poi.drawer.class.mq5 +++ b/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -889,6 +889,71 @@ class XCPOIDrawer : public XCBase return result; } + /** + * Draw Specified Trend Line ... + * + * @param fromPrice: double, from Price ... + * @param fromTime: datetime, from Time ... + * @param toPrice: double, to Price ... + * @param toTime: datetime, to Time ... + * @param name: Object Name ... + * @param rayRight: bool, ray to Right ... + * @param rayLeft: boo, ray to Left ... + * + * @return ( bool ) + */ + bool DrawTrendLine( + double fromPrice, + datetime fromTime, + double toPrice, + datetime toTime, + CChartObjectTrend *&object, + string name, + bool rayRight = false, + bool rayLeft = false // + ) + { + // + bool result = false; + + // + // Prepare ... + object = new CChartObjectTrend(); + + // + // Validate ... + result = + toPrice > 0 && + fromPrice > 0 && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime) && + toTime > fromTime; + if (!result) + { + return result; + } + + // + // Create Object ... + result = object.Create( + ChartIdentification(), + name, + SubWindowIdentification(), + fromTime, + fromPrice, + toTime, + toPrice // + ); + if (result) { + // + object.RayLeft(rayLeft); + object.RayRight(rayRight); + } + + // + return result; + } + /** * Draw Trend Line based on Swings Points ... * diff --git a/Documents/Indicators/x-saherelm.xfima.mq5 b/Documents/Indicators/x-saherelm.xfima.mq5 new file mode 100644 index 00000000..d13d3ff6 --- /dev/null +++ b/Documents/Indicators/x-saherelm.xfima.mq5 @@ -0,0 +1,2404 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XFIMA +// Description: Integrates All Requirements inside +// this indicator for analyse Markets Based on OM1 ... +// +// +// 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 XFIMA Indicator" +#property icon "../Images/SaherElm_Logo_Color.ico" +#property strict + +// +// Definitions ... + +// +// Definitions ... +enum ENUM_X_ZG_SEARCH_MODE +{ + X_ZG_SEARCH_EXTREMUM = 0, // searching for the first extremum + X_ZG_SEARCH_PEAK = 1, // searching for the next ZigZag peak + X_ZG_SEARCH_VALE = -1 // searching for the next ZigZag vale +}; + +// +#define ShortName "XFIMA" + +// +// Imports ... +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input group "Calculation"; + +// +// Short ... +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Short Period +input ENUM_TIMEFRAMES scPeriod = NULL; // Short Period + +// +// Medium ... +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Medium Period +input ENUM_TIMEFRAMES mcPeriod = NULL; // Medium Period + +// +// Long ... +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Long Period +input ENUM_TIMEFRAMES lcPeriod = NULL; // Long Period + +// +// Hind ... +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Hind Period +input ENUM_TIMEFRAMES hcPeriod = NULL; // Hind Period + +// +// PV ... +input ENUM_SERIESMODE upperMode = MODE_HIGH; // Peak Method +input ENUM_SERIESMODE lowerMode = MODE_LOW; // Vale Method + +// +// Others ... +input ENUM_X_FIBO_LEVELS fiboUpperZoneLevel = X_FIBO_LEVEL_382; // Upper Zone Level +input ENUM_X_FIBO_LEVELS fiboMiddleZoneLevel = X_FIBO_LEVEL_500; // Upper Zone Level +input ENUM_X_FIBO_LEVELS fiboLowerZoneLevel = X_FIBO_LEVEL_618; // Lower Zone Level +input double sarStep = 0.02; // SAR Step +input double sarMax = 0.2; // SAR Maximum +input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Method +input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // MA Applied To +input int maFastLength = 7; // Fast MA Length +input int maSlowLength = 20; // Slow MA Length +input int maBandLength = 7; // MA Band Length +input int zigzagDepth = 12; // ZigZag Depth +input int zigzagDeviation = 5; // ZigZag Deviation +input int zigzagBackStep = 3; // ZigZag Back Step +input ENUM_X_PRICE zigzagUppersMode = X_PRICE_HIGH; // ZigZag High Detect Mode +input ENUM_X_PRICE zigzagLowersMode = X_PRICE_LOW; // ZigZag Low Detect Mode + +// +// Presentation ... +input group "Presentation"; +input bool showPV = true; // Show PV +input bool showSAR = true; // Show Sar +input bool showMAFast = true; // Show MA Fast +input bool showMASlow = true; // Show MA Slow +input bool showMABand = true; // Show MA Band +input bool showZigZag = true; // Show ZigZag +input bool showZigZagPV = true; // Show ZigZag PV +input bool showFiboZone = true; // Show Fibo Zone + +// +input int startCalculationForLastBars = 1500; // Calculate Last n Bars + +// +input int sarArrowCode = 159; // Parabolic Sar Arrow Code +input int peakArrowCode = 159; // Peaks Arrow Code +input int valeArrowCode = 159; // Vales Arrow Code + +// +// Non Inputs ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#define bullishState 1 +#define neuturalState 0 +#define bearishState -1 + +// +#define emptyValue 0.0 + +// +// Buffers ... + +// +#property indicator_chart_window + +// +#property indicator_buffers 31 +#property indicator_plots 13 + +// +// Plot Buffers ... + +// +// Fast MA ... + +// +#define maFastBufferIndex 0 +#define maFastBufferPlotIndex 0 +double maFastBuffer[]; + +// +#define maFastColorBufferIndex 1 +double maFastColorBuffer[]; + +// +#property indicator_label1 "FastMA" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrAquamarine, clrAquamarine, clrAquamarine // clrYellow, clrOrangeRed, clrGray +#property indicator_width1 3 + +// +// Slow MA ... + +// +#define maSlowBufferIndex 2 +#define maSlowBufferPlotIndex 1 +double maSlowBuffer[]; + +// +#define maSlowColorBufferIndex 3 +double maSlowColorBuffer[]; + +// +#property indicator_label2 "SlowMA" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 CLR_NONE, clrLightCoral, clrLightCoral, clrLightCoral // clrLime, clrRed, clrGray +#property indicator_width2 3 + +// +// SAR ... + +// +#define sarBufferIndex 4 +#define sarBufferPlotIndex 2 +double sarBuffer[]; + +// +#define sarColorBufferIndex 5 +double sarColorBuffer[]; + +// +#property indicator_label3 "SAR" +#property indicator_type3 DRAW_COLOR_ARROW +#property indicator_color3 CLR_NONE, clrLime, clrRed, clrGray +#property indicator_width3 2 + +// +// PEAKS ... + +// +#define peakBufferIndex 6 +#define peakBufferPlotIndex 3 +double peakBuffer[]; + +// +#property indicator_label4 "PEAK" +#property indicator_type4 DRAW_ARROW +#property indicator_color4 clrMagenta +#property indicator_width4 3 + +// +// VALES ... + +// +#define valeBufferIndex 7 +#define valeBufferPlotIndex 4 +double valeBuffer[]; + +// +#property indicator_label5 "VALE" +#property indicator_type5 DRAW_ARROW +#property indicator_color5 clrAqua +#property indicator_width5 3 + +// +// FIBO Upper ... + +// +#define fiboUpperBufferIndex 8 +#define fiboUpperBufferPlotIndex 5 +double fiboUpperBuffer[]; + +// +#property indicator_label6 "FIBUP" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrAqua +#property indicator_width6 2 + +// +// FIBO Middle ... + +// +#define fiboMiddleBufferIndex 9 +#define fiboMiddleBufferPlotIndex 6 +double fiboMiddleBuffer[]; + +// +#property indicator_label7 "FIBMID" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrBrown +#property indicator_width7 2 + +// +// FIBO Lower ... + +// +#define fiboLowerBufferIndex 10 +#define fiboLowerBufferPlotIndex 7 +double fiboLowerBuffer[]; + +// +#property indicator_label8 "FIBLO" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrMagenta +#property indicator_width8 2 + +// +// ZigZag ... + +// +#define zigzagBufferIndex 11 +#define zigzagBufferPlotIndex 8 +double zigzagBuffer[]; + +// +#property indicator_label9 "XZG" +#property indicator_type9 DRAW_SECTION +#property indicator_color9 clrYellow +#property indicator_width9 2 + +// +// ZG Peak ... + +// +#define zigzagPeakBufferIndex 12 +#define zigzagPeakBufferPlotIndex 9 +double zigzagPeakBuffer[]; + +// +#property indicator_label10 "XZG Peak" +#property indicator_type10 DRAW_ARROW +#property indicator_color10 clrYellow +#property indicator_width10 3 + +// +// ZG Vale ... + +// +#define zigzagValeBufferIndex 13 +#define zigzagValeBufferPlotIndex 10 +double zigzagValeBuffer[]; + +// +#property indicator_label11 "XZG Peak" +#property indicator_type11 DRAW_ARROW +#property indicator_color11 clrDarkOrange +#property indicator_width11 3 + +// +// MA Upper Boundary ... + +// +#define maUpperBufferIndex 14 +#define maUpperBufferPlotIndex 11 +double maUpperBuffer[]; + +// +#property indicator_label12 "UpperMA" +#property indicator_type12 DRAW_LINE +#property indicator_color12 clrAqua +#property indicator_width12 3 + +// +// MA Lower Boundary ... + +// +#define maLowerBufferIndex 15 +#define maLowerBufferPlotIndex 12 +double maLowerBuffer[]; + +// +#property indicator_label13 "LowerMA" +#property indicator_type13 DRAW_LINE +#property indicator_color13 clrMagenta +#property indicator_width13 3 + +// +// Data Buffers ... + +// +#define mLastBufferIndex 15 + +// +// MA ... + +// +#define maFastStateBufferIndex mLastBufferIndex + 1 +double maFastStateBuffer[]; + +// +#define maSlowStateBufferIndex mLastBufferIndex + 2 +double maSlowStateBuffer[]; + +// +// SAR ... + +// +#define sarStateBufferIndex mLastBufferIndex + 3 +double sarStateBuffer[]; + +// +// CYCLES ... + +// +// SC ... + +// +#define sHHBufferIndex mLastBufferIndex + 4 +double sHHBuffer[]; + +// +#define sLLBufferIndex mLastBufferIndex + 5 +double sLLBuffer[]; + +// +// MC ... + +// +#define mHHBufferIndex mLastBufferIndex + 6 +double mHHBuffer[]; + +// +#define mLLBufferIndex mLastBufferIndex + 7 +double mLLBuffer[]; + +// +// LC ... + +// +#define lHHBufferIndex mLastBufferIndex + 8 +double lHHBuffer[]; + +// +#define lLLBufferIndex mLastBufferIndex + 9 +double lLLBuffer[]; + +// +// HC ... + +// +#define hHHBufferIndex mLastBufferIndex + 10 +double hHHBuffer[]; + +// +#define hLLBufferIndex mLastBufferIndex + 11 +double hLLBuffer[]; + +// +// ZigZag ... + +// +#define highsBufferIndex mLastBufferIndex + 12 +double highsBuffer[]; + +// +#define highsTimeBufferIndex mLastBufferIndex + 13 +double highsTimeBuffer[]; + +// +#define lowsBufferIndex mLastBufferIndex + 14 +double lowsBuffer[]; + +// +#define lowsTimeBufferIndex mLastBufferIndex + 15 +double lowsTimeBuffer[]; + +// +// Variables, Properties and etc ... + +// +// 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; + +// +int sarHandler = INVALID_HANDLE; +int maFastHandler = INVALID_HANDLE; +int maSlowHandler = INVALID_HANDLE; +int maUpperHandler = INVALID_HANDLE; +int maLowerHandler = INVALID_HANDLE; + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Requirements ... +CArrayObj mObjects; +XCPOIDrawer *mDrawer; + +// +double zigzagUppers[]; +double zigzagLowers[]; +int zigzagLowersCount = 0; +int zigzagUppersCount = 0; +int zigzagRecalc = 3; // Number of last extremes for recalculation + +// +double lastZigZagPeak = 0; +datetime lastZigZagPeakTime = NULL; + +// +double lastZigZagVale = 0; +datetime lastZigZagValeTime = NULL; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + bool has = false; + + // + // Validate Inputs ... + has = ValidateInputs(); + if (!has) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + has = InitCycles(); + if (!has) + { + return INIT_FAILED; + } + + // + // 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(); + + // + // Initial Requirements ... + has = InitRequirements(); + if (!has) + { + return INIT_FAILED; + } + + // + // 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 mDrawer; + ZeroMemory(mDrawer); + + // + mObjects.Clear(); + + // + // De Initialize all Handlers and etc ... + IndicatorRelease(sarHandler); + IndicatorRelease(maFastHandler); + IndicatorRelease(maSlowHandler); + IndicatorRelease(maUpperHandler); + IndicatorRelease(maLowerHandler); +} + +/** + * 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[] // +) +{ + // + // Do ZigZag Calculations Before ArraySet As Series ... + int calculatedZigZags = CalculateZigZag( + 0, + prev_calculated, + rates_total, + open, + high, + close, + low, + tick_volume // + ); + if (calculatedZigZags != rates_total) + { + return prev_calculated; + } + + // + // Calculating Limit ... + limit = prev_calculated == 0 + ? rates_total - 1 + : rates_total - prev_calculated; + if (limit <= 0) + { + limit = rates_total - 1; + } + + // + // Main Loop ... + for (int i = limit; i < rates_total - 1 && !IsStopped(); i++) + { + // + Print("Calculating Bar Index: ", i); + + // + // Calculate Peaks and Vales ... + CalculateZigZagPV( + i, + prev_calculated, + rates_total // + ); + } + + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Validate Calculated Bars ... + + // + // MA ... + int maFastCalculatedBars = BarsCalculated(maFastHandler); + int maSlowCalculatedBars = BarsCalculated(maSlowHandler); + int maUpperCalculatedBars = BarsCalculated(maUpperHandler); + int maLowerCalculatedBars = BarsCalculated(maLowerHandler); + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // MA ... + maFastCalculatedBars >= maxLength && + maSlowCalculatedBars >= maxLength && + maUpperCalculatedBars >= maxLength && + maLowerCalculatedBars >= maxLength && + // + // 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 ... + + // + // MA ... + int copiedMAFasts = CopyBuffer(maFastHandler, MAIN_LINE, 0, limit, maFastBuffer); + int copiedMASlows = CopyBuffer(maSlowHandler, MAIN_LINE, 0, limit, maSlowBuffer); + int copiedMAUppers = CopyBuffer(maUpperHandler, MAIN_LINE, 0, limit, maUpperBuffer); + int copiedMALowers = CopyBuffer(maLowerHandler, MAIN_LINE, 0, limit, maLowerBuffer); + + // + // SAR ... + int copiedSARs = CopyBuffer(sarHandler, MAIN_LINE, 0, limit, sarBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // MA ... + copiedMAFasts >= limit && + copiedMASlows >= limit && + copiedMAUppers >= limit && + copiedMALowers >= limit && + // + // SAR ... + copiedSARs >= limit + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Custom Functions ... + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + // MA ... + maFastLength >= 2 && + maSlowLength >= 2 && + maBandLength >= 2 && + maSlowLength > maFastLength && + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // CYCLES ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) && + // + // ZIGZAG ... + zigzagDepth > 0 && + zigzagDeviation > 0 && + zigzagBackStep > 0 && + // + // Validate Upper Mode Detection ... + IsXValid(zigzagUppersMode) && + // + // Validate Lower Mode Detection ... + IsXValid(zigzagLowersMode) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(mSCLength, mMCLength); + result = MathMax(result, mLCLength); + result = MathMax(result, mHCLength); + result = MathMax(result, maFastLength); + result = MathMax(result, maSlowLength); + result = MathMax(result, maBandLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Fast MA ... + + // + ArraySetAsSeries(maFastBuffer, true); + SetIndexBuffer(maFastBufferIndex, maFastBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maFastBufferPlotIndex, PLOT_SHOW_DATA, showMAFast); + PlotIndexSetDouble(maFastBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(maFastColorBuffer, true); + SetIndexBuffer(maFastColorBufferIndex, maFastColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(maFastStateBuffer, true); + SetIndexBuffer(maFastStateBufferIndex, maFastStateBuffer, INDICATOR_CALCULATIONS); + + // + // Slow MA ... + + // + ArraySetAsSeries(maSlowBuffer, true); + SetIndexBuffer(maSlowBufferIndex, maSlowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maSlowBufferPlotIndex, PLOT_SHOW_DATA, showMASlow); + PlotIndexSetDouble(maSlowBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(maSlowColorBuffer, true); + SetIndexBuffer(maSlowColorBufferIndex, maSlowColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(maSlowStateBuffer, true); + SetIndexBuffer(maSlowStateBufferIndex, maSlowStateBuffer, INDICATOR_CALCULATIONS); + + // + // SAR ... + + // + ArraySetAsSeries(sarBuffer, true); + SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_SHOW_DATA, showSAR); + PlotIndexSetDouble(sarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_ARROW, sarArrowCode); + + // + ArraySetAsSeries(sarColorBuffer, true); + SetIndexBuffer(sarColorBufferIndex, sarColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(sarStateBuffer, true); + SetIndexBuffer(sarStateBufferIndex, sarStateBuffer, INDICATOR_CALCULATIONS); + + // + // PEAK / VALE ... + + // + ENUM_DRAW_TYPE pvDrawType = showPV ? DRAW_ARROW : DRAW_NONE; + + // + // PEAK ... + + // + ArraySetAsSeries(peakBuffer, true); + SetIndexBuffer(peakBufferIndex, peakBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_SHOW_DATA, showPV); + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + PlotIndexSetDouble(peakBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_ARROW, peakArrowCode); + + // + // VALE ... + + // + ArraySetAsSeries(valeBuffer, true); + SetIndexBuffer(valeBufferIndex, valeBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_SHOW_DATA, showPV); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + PlotIndexSetDouble(valeBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_ARROW, valeArrowCode); + + // + // FIBO Zone ... + + // + ENUM_DRAW_TYPE fiboZoneDrawType = showFiboZone ? DRAW_LINE : DRAW_NONE; + + // + // Upper ... + ArraySetAsSeries(fiboUpperBuffer, true); + SetIndexBuffer(fiboUpperBufferIndex, fiboUpperBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboUpperBufferPlotIndex, PLOT_SHOW_DATA, showFiboZone); + PlotIndexSetInteger(fiboUpperBufferPlotIndex, PLOT_DRAW_TYPE, fiboZoneDrawType); + PlotIndexSetDouble(fiboUpperBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // Middle ... + ArraySetAsSeries(fiboMiddleBuffer, true); + SetIndexBuffer(fiboMiddleBufferIndex, fiboMiddleBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboMiddleBufferPlotIndex, PLOT_SHOW_DATA, showFiboZone); + PlotIndexSetInteger(fiboMiddleBufferPlotIndex, PLOT_DRAW_TYPE, fiboZoneDrawType); + PlotIndexSetDouble(fiboMiddleBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // Lower ... + ArraySetAsSeries(fiboLowerBuffer, true); + SetIndexBuffer(fiboLowerBufferIndex, fiboLowerBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboLowerBufferPlotIndex, PLOT_SHOW_DATA, showFiboZone); + PlotIndexSetInteger(fiboLowerBufferPlotIndex, PLOT_DRAW_TYPE, fiboZoneDrawType); + PlotIndexSetDouble(fiboLowerBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // ZigZag ... + + // + ENUM_DRAW_TYPE zigzagDrawType = showZigZag ? DRAW_SECTION : DRAW_NONE; + + // + SetIndexBuffer(zigzagBufferIndex, zigzagBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_SHOW_DATA, showZigZag); + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_DRAW_TYPE, zigzagDrawType); + + PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(zigzagBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // ZigZag PV ... + + // + ENUM_DRAW_TYPE zigzagPVDrawType = showZigZagPV ? DRAW_ARROW : DRAW_NONE; + + // + // ZG Peak ... + + // + SetIndexBuffer(zigzagPeakBufferIndex, zigzagPeakBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(zigzagPeakBufferPlotIndex, PLOT_SHOW_DATA, showZigZagPV); + PlotIndexSetInteger(zigzagPeakBufferPlotIndex, PLOT_DRAW_TYPE, zigzagPVDrawType); + + PlotIndexSetInteger(zigzagPeakBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(zigzagPeakBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // ZG Vale ... + + // + SetIndexBuffer(zigzagValeBufferIndex, zigzagValeBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(zigzagValeBufferPlotIndex, PLOT_SHOW_DATA, showZigZagPV); + PlotIndexSetInteger(zigzagValeBufferPlotIndex, PLOT_DRAW_TYPE, zigzagPVDrawType); + + PlotIndexSetInteger(zigzagValeBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(zigzagValeBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // MA Band ... + + // + ENUM_DRAW_TYPE maBandDrawType = showMABand ? DRAW_LINE : DRAW_NONE; + + // + // MA Upper Band ... + + // + ArraySetAsSeries(maUpperBuffer, true); + SetIndexBuffer(maUpperBufferIndex, maUpperBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maUpperBufferPlotIndex, PLOT_SHOW_DATA, showMABand); + PlotIndexSetInteger(maUpperBufferPlotIndex, PLOT_DRAW_TYPE, maBandDrawType); + + PlotIndexSetInteger(maUpperBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(maUpperBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // MA Lower Band ... + + // + ArraySetAsSeries(maLowerBuffer, true); + SetIndexBuffer(maLowerBufferIndex, maLowerBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maLowerBufferPlotIndex, PLOT_SHOW_DATA, showMABand); + PlotIndexSetInteger(maLowerBufferPlotIndex, PLOT_DRAW_TYPE, maBandDrawType); + + PlotIndexSetInteger(maLowerBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(maLowerBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // Data Buffers ... + + // + // CYCLES ... + + // + // SC ... + + // + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_DATA); + + // + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_DATA); + + // + // MC ... + + // + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_DATA); + + // + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_DATA); + + // + // LC ... + + // + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_DATA); + + // + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_DATA); + + // + // HC ... + + // + ArraySetAsSeries(hHHBuffer, true); + SetIndexBuffer(hHHBufferIndex, hHHBuffer, INDICATOR_DATA); + + // + ArraySetAsSeries(hLLBuffer, true); + SetIndexBuffer(hLLBufferIndex, hLLBuffer, INDICATOR_DATA); + + // + // Highs ... + SetIndexBuffer(highsBufferIndex, highsBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(highsTimeBufferIndex, highsTimeBuffer, INDICATOR_CALCULATIONS); + + // + // Lows ... + SetIndexBuffer(lowsBufferIndex, lowsBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(lowsTimeBufferIndex, lowsTimeBuffer, INDICATOR_CALCULATIONS); + + // +} + +/** + * Initial Market Cycles ... + * + * @return ( bool ) + */ +bool InitCycles() +{ + // + 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; +} + +/** + * Initial all Indicator Requirements ... + * + * @return ( false ) + * + */ +bool InitRequirements() +{ + // + bool result = false; + + // + // Handlers ... + + // + // Fast MA ... + maFastHandler = iMA( + _Symbol, + _Period, + maFastLength, + 0, + maMethod, + maAppliedTo // + ); + result = maFastHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Slow MA ... + maSlowHandler = iMA( + _Symbol, + _Period, + maSlowLength, + 0, + maMethod, + maAppliedTo // + ); + result = maSlowHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // MA Band Upper ... + maUpperHandler = iMA( + _Symbol, + _Period, + maBandLength, + 0, + maMethod, + PRICE_HIGH // + ); + result = maUpperHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // MA Band Lower ... + maLowerHandler = iMA( + _Symbol, + _Period, + maBandLength, + 0, + maMethod, + PRICE_LOW // + ); + result = maLowerHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMax // + ); + result = sarHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + mDrawer = new XCPOIDrawer(); + + // + return result; +} + +/** + * Calculate Custom Buffers ... + * + * @param barIndex: 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 barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Calculate Bars Limit and First Bar Index ... + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + barIndex <= barsLimit; + if (canCalculate) + { + // + // Calculate Values ... + CalculateValues( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(barIndex); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + // TODO: Fill Buffers as Empty ... +} + +/** + * Calculate Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateValues( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + // Common Requirements ... + + // + // CYCLES Ranges ... + CalculateCycleRanges( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // PV ... + CalculatePV( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Fast MA ... + double iFastMa = maFastBuffer[barIndex]; + double maFastState = close[barIndex] > iFastMa + ? bullishState + : close[barIndex] < iFastMa + ? bearishState + : neuturalState; + double maFastColor = close[barIndex] > iFastMa + ? bullishColorIDX + : close[barIndex] < iFastMa + ? bearishColorIDX + : neuturalColorIDX; + maFastStateBuffer[barIndex] = maFastState; + maFastColorBuffer[barIndex] = showMAFast + ? maFastColor + : hideColorIDX; + + // + // Slow MA ... + double iSlowMa = maSlowBuffer[barIndex]; + double maSlowState = close[barIndex] > iSlowMa + ? bullishState + : close[barIndex] < iSlowMa + ? bearishState + : neuturalState; + double maSlowColor = close[barIndex] > iSlowMa + ? bullishColorIDX + : close[barIndex] < iSlowMa + ? bearishColorIDX + : neuturalColorIDX; + maSlowStateBuffer[barIndex] = maSlowState; + maSlowColorBuffer[barIndex] = showMASlow + ? maSlowColor + : hideColorIDX; + + // + // SAR ... + double iSar = sarBuffer[barIndex]; + double sarState = low[barIndex] > iSar + ? bullishState + : high[barIndex] < iSar + ? bearishState + : neuturalState; + double sarColor = low[barIndex] > iSar + ? bullishColorIDX + : high[barIndex] < iSar + ? bearishColorIDX + : neuturalColorIDX; + sarStateBuffer[barIndex] = sarState; + sarColorBuffer[barIndex] = showSAR + ? sarColor + : hideColorIDX; + + // + // FIBO Zone ... + + // + double iPeak = peakBuffer[barIndex]; + double iVale = valeBuffer[barIndex]; + + // + double iFiboUp = GetFibonacciLevel( + iPeak, + iVale, + fiboUpperZoneLevel, + X_DIRECTION_BULLISH // + ); + + // + double iFiboMid = GetFibonacciLevel( + iPeak, + iVale, + fiboMiddleZoneLevel, + X_DIRECTION_BULLISH // + ); + + // + double iFiboLo = GetFibonacciLevel( + iPeak, + iVale, + fiboLowerZoneLevel, + X_DIRECTION_BULLISH // + ); + + // + fiboUpperBuffer[barIndex] = iFiboUp; + fiboMiddleBuffer[barIndex] = iFiboMid; + fiboLowerBuffer[barIndex] = iFiboLo; +} + +// +void CalculatePV( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + double iSHH = sHHBuffer[barIndex]; + double iSLL = sLLBuffer[barIndex]; + + // + double iMHH = mHHBuffer[barIndex]; + double iMLL = mLLBuffer[barIndex]; + + // + double iLHH = lHHBuffer[barIndex]; + double iLLL = lLLBuffer[barIndex]; + + // + double iHHH = hHHBuffer[barIndex]; + double iHLL = hLLBuffer[barIndex]; + + // + // Calculate VALE ... + bool isVale = iSLL == iMLL && + iMLL == iLLL && + iLLL == iHLL; + double iPVale = + isFirstBar + ? emptyValue + : valeBuffer[lastBarIndex]; + double iVale = + isVale + ? iSLL + : iPVale; + valeBuffer[barIndex] = iVale; + + // + // Calculate PEAK ... + bool isPeak = iSHH == iMHH && + iMHH == iLHH && + iLHH == iHHH; + double iPPeak = + isFirstBar + ? emptyValue + : peakBuffer[lastBarIndex]; + double iPeak = + isPeak + ? iSHH + : iPPeak; + peakBuffer[barIndex] = iPeak; +} + +/** + * Calculate Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + * + * @return ( int ) + */ +int CalculateZigZag( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int result = 0; + + // + // Define Variables ... + int i = 0; + + // + int start = 0; + int extreme_counter = 0; + int extreme_search = X_ZG_SEARCH_EXTREMUM; + int shift = 0; + int back = 0; + int last_high_pos = 0; + int last_low_pos = 0; + + // + double val = 0; + double res = 0; + double curlow = 0; + double curhigh = 0; + double last_high = 0; + double last_low = 0; + + // + // Initializing ... + if (prevCalculated == 0) + { + // + ArrayInitialize(lowsBuffer, 0); + ArrayInitialize(highsBuffer, 0); + ArrayInitialize(zigzagBuffer, 0); + ArrayInitialize(lowsTimeBuffer, 0); + ArrayInitialize(highsTimeBuffer, 0); + + // + start = zigzagDepth; + } + + // + // Preparing ZigZag Calculation High and Lows ... + + // + if (zigzagLowersCount != zigzagUppersCount || zigzagLowersCount != ratesTotal) + { + // + // Filling Upper ... + zigzagUppersCount = FillPrice( + zigzagUppersMode, + zigzagUppers, + open, + high, + close, + low // + ); + + // + // Filling Lower ... + zigzagLowersCount = FillPrice( + zigzagLowersMode, + zigzagLowers, + open, + high, + close, + low // + ); + } + + // + // Already Calculated Before ... + if (prevCalculated > 0) + { + // + i = ratesTotal - 1; + + // + // Searching for the third X_ZG_SEARCH_EXTREMUM from the last UnComplete Bar ... + while (extreme_counter < zigzagRecalc && i > ratesTotal - 100) + { + // + res = zigzagBuffer[i]; + if (res != 0) + { + extreme_counter++; + } + + // + i--; + } + + // + i++; + start = i; + + // + // What type of X_ZG_SEARCH_EXTREMUM we Search for ... + if (lowsBuffer[i] != 0) + { + // + curlow = lowsBuffer[i]; + extreme_search = X_ZG_SEARCH_PEAK; + } + else + { + // + curhigh = highsBuffer[i]; + extreme_search = X_ZG_SEARCH_VALE; + } + + // + // Clear Values ... + for (i = start + 1; i < ratesTotal && !IsStopped(); i++) + { + // + lowsBuffer[i] = 0; + highsBuffer[i] = 0; + zigzagBuffer[i] = 0; + lowsTimeBuffer[i] = 0; + highsTimeBuffer[i] = 0; + } + } + + // + // Search for High and Low Extremes ... + for (shift = start; shift < ratesTotal && !IsStopped(); shift++) + { + // + // Low ... + val = zigzagLowers[Lowest(zigzagLowers, zigzagDepth, shift)]; + if (val == last_low) + { + val = 0; + } + else + { + // + last_low = val; + + // + if ((zigzagLowers[shift] - val) > zigzagDeviation * _Point) + { + val = 0; + } + else + { + // + for (back = 1; back <= zigzagBackStep; back++) + { + // + res = lowsBuffer[shift - back]; + if ((res != 0) && (res > val)) + { + // + lowsBuffer[shift - back] = 0; + lowsTimeBuffer[shift - back] = 0; + } + } + } + } + + // + if (zigzagLowers[shift] == val) + { + // + lowsBuffer[shift] = val; + lowsTimeBuffer[shift] = GetZigZagBarTime(shift); + } + else + { + // + lowsBuffer[shift] = 0; + lowsTimeBuffer[shift] = 0; + } + + // + // High ... + val = zigzagUppers[Highest(zigzagUppers, zigzagDepth, shift)]; + if (val == last_high) + { + val = 0; + } + else + { + // + last_high = val; + + // + if ((val - zigzagUppers[shift]) > zigzagDeviation * _Point) + { + val = 0; + } + else + { + // + for (back = 1; back <= zigzagBackStep; back++) + { + // + res = highsBuffer[shift - back]; + if ((res != 0) && (res < val)) + { + // + highsBuffer[shift - back] = 0; + highsTimeBuffer[shift - back] = 0; + } + } + } + } + + // + if (zigzagUppers[shift] == val) + { + // + highsBuffer[shift] = val; + highsTimeBuffer[shift] = GetZigZagBarTime(shift); + } + else + { + highsBuffer[shift] = 0; + highsTimeBuffer[shift] = 0; + } + } + + // + // Set Last Value ... + if (extreme_search == 0) // Undefined Values ... + { + // + last_low = 0; + last_high = 0; + } + else + { + // + last_low = curlow; + last_high = curhigh; + } + + // + // Final Selection of Extreme Points for ZigZag ... + for (shift = start; shift < ratesTotal && !IsStopped(); shift++) + { + // + res = 0; + + // + switch (extreme_search) + { + // + case X_ZG_SEARCH_EXTREMUM: + // + if (last_low == 0 && last_high == 0) + { + // + if (highsBuffer[shift] != 0) + { + // + last_high_pos = shift; + last_high = zigzagUppers[shift]; + + // + extreme_search = X_ZG_SEARCH_VALE; + + // + zigzagBuffer[shift] = last_high; + + // + res = 1; + } + + // + if (lowsBuffer[shift] != 0) + { + // + last_low_pos = shift; + last_low = zigzagLowers[shift]; + + // + extreme_search = X_ZG_SEARCH_PEAK; + + // + zigzagBuffer[shift] = last_low; + + // + res = 1; + } + } + break; + + // + case X_ZG_SEARCH_PEAK: + // + if (lowsBuffer[shift] != 0 && lowsBuffer[shift] < last_low && highsBuffer[shift] == 0) + { + // + zigzagBuffer[last_low_pos] = 0; + + // + last_low_pos = shift; + last_low = lowsBuffer[shift]; + + // + zigzagBuffer[shift] = last_low; + + // + res = 1; + } + + // + if (highsBuffer[shift] != 0 && lowsBuffer[shift] == 0) + { + // + last_high_pos = shift; + last_high = highsBuffer[shift]; + + // + zigzagBuffer[shift] = last_high; + + // + extreme_search = X_ZG_SEARCH_VALE; + + // + res = 1; + } + break; + + // + case X_ZG_SEARCH_VALE: + // + if (highsBuffer[shift] != 0 && highsBuffer[shift] > last_high && lowsBuffer[shift] == 0) + { + // + zigzagBuffer[last_high_pos] = 0; + + // + last_high_pos = shift; + last_high = highsBuffer[shift]; + + // + zigzagBuffer[shift] = last_high; + } + + // + if (lowsBuffer[shift] != 0 && highsBuffer[shift] == 0) + { + // + last_low_pos = shift; + last_low = lowsBuffer[shift]; + + // + zigzagBuffer[shift] = last_low; + + // + extreme_search = X_ZG_SEARCH_PEAK; + } + break; + } + } + + // + result = ratesTotal; + + // + return result; +} + +/** + * Calculate Peaks and Vales ... + * + * @param barIndex: 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 CalculateZigZagPV( + int barIndex, + const int prevCalculated, + const int ratesTotal // +) +{ + // + double iZigZagValue = zigzagBuffer[barIndex]; + + // + // Print("Calculate Bar Index: ", barIndex, ", ZG: ", iZigZagValue, ", ", prevCalculated, ", ", ratesTotal); + + // + // Peak ... + double iHighValue = highsBuffer[barIndex]; + double iHighTimeDouble = highsTimeBuffer[barIndex]; + datetime iHighTime = (datetime)((int)iHighTimeDouble); + if (iHighValue != 0 && iHighValue != EMPTY_VALUE && iZigZagValue == iHighValue) + { + // + peakBuffer[barIndex] = iHighValue; + + // + lastZigZagPeak = iHighValue; + lastZigZagPeakTime = iHighTime; + } + else + { + // + double iValue = emptyValue; + if ( + lastZigZagPeak != emptyValue && + lastZigZagPeak != EMPTY_VALUE && + IsSpecifiedValid(lastZigZagPeakTime)) + { + iValue = lastZigZagPeak; + } + + // + peakBuffer[barIndex] = iValue; + } + + // + // Vale ... + double iLowValue = lowsBuffer[barIndex]; + double iLowTimeDouble = lowsTimeBuffer[barIndex]; + datetime iLowTime = (datetime)((int)iLowTimeDouble); + if (iLowValue != 0 && iLowValue != EMPTY_VALUE && iZigZagValue == iLowValue) + { + // + valeBuffer[barIndex] = iLowValue; + + // + lastZigZagVale = iLowValue; + lastZigZagValeTime = iLowTime; + } + else + { + // + double iValue = emptyValue; + if ( + lastZigZagVale != emptyValue && + lastZigZagVale != EMPTY_VALUE && + IsSpecifiedValid(lastZigZagValeTime)) + { + iValue = lastZigZagVale; + } + + // + valeBuffer[barIndex] = iValue; + } + + // + // ChartRedraw(); +} + +// +void CalculateCycleRanges( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // 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 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, + upperMode // + ); + hhBuffer[barIndex] = hhValue; + + // + // Find Lowest Low ... + double llValue = bar.FindLowest( + mLength, + lowerMode // + ); + llBuffer[barIndex] = llValue; + + // + bar.Clean(); +} + +// +// +// + +// +// Get Specified Bar Time as Double ... +double GetZigZagBarTime(int barIndex) +{ + // + if (barIndex <= 0) + { + barIndex = 0; + } + + // + datetime time = iTime(_Symbol, _Period, barIndex); + + // + double result = (double)((int)time); + + // + return result; +} + +// +// Filling Required Prices Based on MODE ... +int FillPrice( + ENUM_X_PRICE mode, + double &dest[], + const double &open[], + const double &high[], + const double &close[], + const double &low[] // +) +{ + // + int result = 0; + + // + SpecifiedClean(dest); + + // + if (!IsXValid(mode)) + { + return result; + } + + // + switch (mode) + { + // + case X_PRICE_HIGH: + // + result = ArrayCopy( + dest, + high // + ); + break; + + // + case X_PRICE_LOW: + // + result = ArrayCopy( + dest, + low // + ); + break; + + // + case X_PRICE_OPEN: + // + result = ArrayCopy( + dest, + open // + ); + break; + + // + case X_PRICE_CLOSE: + // + result = ArrayCopy( + dest, + close // + ); + break; + + // + default: + // + result = ArrayCopy( + dest, + close // + ); + break; + } + + // + return result; +} + +// +// Search for the index of the highest bar ... +int Highest( + const double &mArray[], + const int mDepth, + const int mStart // +) +{ + // + int result = 0; + + // + if (mStart < 0) + { + return result; + } + + // + double max = mArray[mStart]; + result = mStart; + + // + // Start searching ... + for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) + { + // + if (mArray[i] > max) + { + // + result = i; + max = mArray[i]; + } + } + + // + // Return index of the highest bar + return result; +} + +// +// Search for the index of the lowest bar ... +int Lowest( + const double &mArray[], + const int mDepth, + const int mStart // +) +{ + // + int result = 0; + + // + if (mStart < 0) + { + return result; + } + + // + double min = mArray[mStart]; + result = mStart; + + // + // Start searching ... + for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) + { + // + if (mArray[i] < min) + { + // + result = i; + min = mArray[i]; + } + } + + // + // Return index of the lowest bar + return result; +} + +// \ No newline at end of file diff --git a/Experts/x-saherelm.xfima.backtester.ea.mq5 b/Experts/x-saherelm.xfima.backtester.ea.mq5 index 15a4eccd..7b8e8a4a 100644 --- a/Experts/x-saherelm.xfima.backtester.ea.mq5 +++ b/Experts/x-saherelm.xfima.backtester.ea.mq5 @@ -164,6 +164,7 @@ int eaCTHandler = INVALID_HANDLE; // Candle Timer Handler ... // bool eaIsNewBar; // Check New Bar ... +XZigZagAnalysis zigzagAnalysis; ENUM_X_DIRECTION trendDir = X_DIRECTION_NONE; // @@ -1198,13 +1199,88 @@ void DetectPatterns() cBar, fima2Signaller.fimaHelper, zigzags, - 3 // + 15 // ); has = IsValidSize(zigzagsCount); if (has) { // - Print("Detected ZigZags Points: ", zigzagsCount); + // Analyse Using ZigZag ... + XZigZagAnalysis cZGAnalysis; + + // + // Check ZG Analysis Exists ... + has = cZGAnalysis.Analyse( + cBar, + zigzags // + ); + + // + // Check Exists ZG Analysis isn't Same Trend as Prev ... + has = + has && + (!zigzagAnalysis.IsValid() + ? true + : !zigzagAnalysis.IsSameTrendAs(cZGAnalysis)); + if (has) + { + // + // Update Prev Analysis ... + zigzagAnalysis = cZGAnalysis; + + // + // Notify Only When New Trending Happens ... + Print("Detected ZigZags Pivots Analysis: ", zigzagAnalysis.GetMessage()); + + // + // Draw Trend Line ... + + // + string iObjID = zigzagAnalysis.GetObjectID(); + string iNameType = ToXString(zigzagAnalysis.dir) + "_Trend"; + + // + // Upper Line ... + string iUpperName = iNameType + "_Upper_" + iObjID; + CChartObjectTrend *iUpperObj; + has = eaDrawer.DrawTrendLine( + zigzagAnalysis.lastPeak.value, + zigzagAnalysis.lastPeak.time, + zigzagAnalysis.recentPeak.value, + zigzagAnalysis.recentPeak.time, + iUpperObj, + ToMD5(iUpperName), + true // + ); + + // + // Lower Line ... + string iLowerName = iNameType + "_Lower_" + iObjID; + CChartObjectTrend *iLowerObj; + has = + has && + eaDrawer.DrawTrendLine( + zigzagAnalysis.lastVale.value, + zigzagAnalysis.lastVale.time, + zigzagAnalysis.recentVale.value, + zigzagAnalysis.recentVale.time, + iLowerObj, + ToMD5(iLowerName), + true // + ); + + // + if (has) { + // + // Apply Style on Trend Lines ... + + // + draws.Add(iUpperObj); + draws.Add(iLowerObj); + } + } + + // } } } diff --git a/Indicators/x-saherelm.xfima.mq5 b/Indicators/x-saherelm.xfima.mq5 index d13d3ff6..e6aa0216 100644 --- a/Indicators/x-saherelm.xfima.mq5 +++ b/Indicators/x-saherelm.xfima.mq5 @@ -99,7 +99,6 @@ input bool showMAFast = true; // Show MA Fast input bool showMASlow = true; // Show MA Slow input bool showMABand = true; // Show MA Band input bool showZigZag = true; // Show ZigZag -input bool showZigZagPV = true; // Show ZigZag PV input bool showFiboZone = true; // Show Fibo Zone // @@ -134,8 +133,8 @@ input int valeArrowCode = 159; // Vales Arrow Code #property indicator_chart_window // -#property indicator_buffers 31 -#property indicator_plots 13 +#property indicator_buffers 29 +#property indicator_plots 11 // // Plot Buffers ... @@ -155,7 +154,7 @@ double maFastColorBuffer[]; // #property indicator_label1 "FastMA" #property indicator_type1 DRAW_COLOR_LINE -#property indicator_color1 CLR_NONE, clrAquamarine, clrAquamarine, clrAquamarine // clrYellow, clrOrangeRed, clrGray +#property indicator_color1 CLR_NONE, clrLime, clrLime, clrLime // clrYellow, clrOrangeRed, clrGray #property indicator_width1 3 // @@ -173,7 +172,7 @@ double maSlowColorBuffer[]; // #property indicator_label2 "SlowMA" #property indicator_type2 DRAW_COLOR_LINE -#property indicator_color2 CLR_NONE, clrLightCoral, clrLightCoral, clrLightCoral // clrLime, clrRed, clrGray +#property indicator_color2 CLR_NONE, clrRed, clrRed, clrRed // clrLime, clrRed, clrGray #property indicator_width2 3 // @@ -278,67 +277,39 @@ double zigzagBuffer[]; #property indicator_color9 clrYellow #property indicator_width9 2 -// -// ZG Peak ... - -// -#define zigzagPeakBufferIndex 12 -#define zigzagPeakBufferPlotIndex 9 -double zigzagPeakBuffer[]; - -// -#property indicator_label10 "XZG Peak" -#property indicator_type10 DRAW_ARROW -#property indicator_color10 clrYellow -#property indicator_width10 3 - -// -// ZG Vale ... - -// -#define zigzagValeBufferIndex 13 -#define zigzagValeBufferPlotIndex 10 -double zigzagValeBuffer[]; - -// -#property indicator_label11 "XZG Peak" -#property indicator_type11 DRAW_ARROW -#property indicator_color11 clrDarkOrange -#property indicator_width11 3 - // // MA Upper Boundary ... // -#define maUpperBufferIndex 14 -#define maUpperBufferPlotIndex 11 +#define maUpperBufferIndex 12 +#define maUpperBufferPlotIndex 9 double maUpperBuffer[]; // -#property indicator_label12 "UpperMA" -#property indicator_type12 DRAW_LINE -#property indicator_color12 clrAqua -#property indicator_width12 3 +#property indicator_label10 "UpperMA" +#property indicator_type10 DRAW_LINE +#property indicator_color10 clrAqua +#property indicator_width10 3 // // MA Lower Boundary ... // -#define maLowerBufferIndex 15 -#define maLowerBufferPlotIndex 12 +#define maLowerBufferIndex 13 +#define maLowerBufferPlotIndex 10 double maLowerBuffer[]; // -#property indicator_label13 "LowerMA" -#property indicator_type13 DRAW_LINE -#property indicator_color13 clrMagenta -#property indicator_width13 3 +#property indicator_label11 "LowerMA" +#property indicator_type11 DRAW_LINE +#property indicator_color11 clrMagenta +#property indicator_width11 3 // // Data Buffers ... // -#define mLastBufferIndex 15 +#define mLastBufferIndex 13 // // MA ... @@ -622,32 +593,6 @@ int OnCalculate( return prev_calculated; } - // - // Calculating Limit ... - limit = prev_calculated == 0 - ? rates_total - 1 - : rates_total - prev_calculated; - if (limit <= 0) - { - limit = rates_total - 1; - } - - // - // Main Loop ... - for (int i = limit; i < rates_total - 1 && !IsStopped(); i++) - { - // - Print("Calculating Bar Index: ", i); - - // - // Calculate Peaks and Vales ... - CalculateZigZagPV( - i, - prev_calculated, - rates_total // - ); - } - // // Prepare Buffers ... ArraySetAsSeries(time, true); @@ -984,38 +929,6 @@ void DefineBuffers() PlotIndexSetInteger(zigzagBufferPlotIndex, PLOT_DRAW_BEGIN, 0); PlotIndexSetDouble(zigzagBufferPlotIndex, PLOT_EMPTY_VALUE, 0); - // - // ZigZag PV ... - - // - ENUM_DRAW_TYPE zigzagPVDrawType = showZigZagPV ? DRAW_ARROW : DRAW_NONE; - - // - // ZG Peak ... - - // - SetIndexBuffer(zigzagPeakBufferIndex, zigzagPeakBuffer, INDICATOR_DATA); - - // - PlotIndexSetInteger(zigzagPeakBufferPlotIndex, PLOT_SHOW_DATA, showZigZagPV); - PlotIndexSetInteger(zigzagPeakBufferPlotIndex, PLOT_DRAW_TYPE, zigzagPVDrawType); - - PlotIndexSetInteger(zigzagPeakBufferPlotIndex, PLOT_DRAW_BEGIN, 0); - PlotIndexSetDouble(zigzagPeakBufferPlotIndex, PLOT_EMPTY_VALUE, 0); - - // - // ZG Vale ... - - // - SetIndexBuffer(zigzagValeBufferIndex, zigzagValeBuffer, INDICATOR_DATA); - - // - PlotIndexSetInteger(zigzagValeBufferPlotIndex, PLOT_SHOW_DATA, showZigZagPV); - PlotIndexSetInteger(zigzagValeBufferPlotIndex, PLOT_DRAW_TYPE, zigzagPVDrawType); - - PlotIndexSetInteger(zigzagValeBufferPlotIndex, PLOT_DRAW_BEGIN, 0); - PlotIndexSetDouble(zigzagValeBufferPlotIndex, PLOT_EMPTY_VALUE, 0); - // // MA Band ... @@ -2007,94 +1920,6 @@ int CalculateZigZag( return result; } -/** - * Calculate Peaks and Vales ... - * - * @param barIndex: 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 CalculateZigZagPV( - int barIndex, - const int prevCalculated, - const int ratesTotal // -) -{ - // - double iZigZagValue = zigzagBuffer[barIndex]; - - // - // Print("Calculate Bar Index: ", barIndex, ", ZG: ", iZigZagValue, ", ", prevCalculated, ", ", ratesTotal); - - // - // Peak ... - double iHighValue = highsBuffer[barIndex]; - double iHighTimeDouble = highsTimeBuffer[barIndex]; - datetime iHighTime = (datetime)((int)iHighTimeDouble); - if (iHighValue != 0 && iHighValue != EMPTY_VALUE && iZigZagValue == iHighValue) - { - // - peakBuffer[barIndex] = iHighValue; - - // - lastZigZagPeak = iHighValue; - lastZigZagPeakTime = iHighTime; - } - else - { - // - double iValue = emptyValue; - if ( - lastZigZagPeak != emptyValue && - lastZigZagPeak != EMPTY_VALUE && - IsSpecifiedValid(lastZigZagPeakTime)) - { - iValue = lastZigZagPeak; - } - - // - peakBuffer[barIndex] = iValue; - } - - // - // Vale ... - double iLowValue = lowsBuffer[barIndex]; - double iLowTimeDouble = lowsTimeBuffer[barIndex]; - datetime iLowTime = (datetime)((int)iLowTimeDouble); - if (iLowValue != 0 && iLowValue != EMPTY_VALUE && iZigZagValue == iLowValue) - { - // - valeBuffer[barIndex] = iLowValue; - - // - lastZigZagVale = iLowValue; - lastZigZagValeTime = iLowTime; - } - else - { - // - double iValue = emptyValue; - if ( - lastZigZagVale != emptyValue && - lastZigZagVale != EMPTY_VALUE && - IsSpecifiedValid(lastZigZagValeTime)) - { - iValue = lastZigZagVale; - } - - // - valeBuffer[barIndex] = iValue; - } - - // - // ChartRedraw(); -} - // void CalculateCycleRanges( int barIndex, diff --git a/Indicators/x-saherelm.xzg.mq5 b/Indicators/x-saherelm.xzg.mq5 index a31407e0..0492a503 100644 --- a/Indicators/x-saherelm.xzg.mq5 +++ b/Indicators/x-saherelm.xzg.mq5 @@ -17,6 +17,7 @@ #property link "https://saherelm.ir" #property version "1.00" #property description "SaherElm XZG Indicator" +#property icon "../Images/SaherElm_Logo_Color.ico" #property strict // diff --git a/XFIMAEA/Libraries/x-saherelm.xfima.lib.mq5 b/XFIMAEA/Libraries/x-saherelm.xfima.lib.mq5 index 5149a4ad..ca2405cc 100644 --- a/XFIMAEA/Libraries/x-saherelm.xfima.lib.mq5 +++ b/XFIMAEA/Libraries/x-saherelm.xfima.lib.mq5 @@ -341,6 +341,9 @@ struct XZigZagPoint } } + // + // Logging Tools ... + /** * Extract Specified Token of Struct ... * @@ -368,7 +371,7 @@ struct XZigZagPoint } // - result = GetTag() + "_" + ToXString(dir) + "_" + ToXString(type) + "_" + ToXString(TimeToSeconds(time)); + result = GetTag() + "_" + symbol + "_" + ToXString(period) + "_" + ToXString(dir) + "_" + ToXString(type) + "_" + ToXString(TimeToSeconds(time)); // return result; @@ -403,6 +406,10 @@ struct XZigZagPoint // result = ToXString(dir) + spacer + GetTag() + ":" + spacer + + "Symbol: " + symbol + spacer + + "Period: " + ToXString(period) + spacer + + "Type: " + ToXString(type) + spacer + + "Direction: " + ToXString(dir) + spacer + "Value: " + ToXString(value) + spacer + "Time: " + ToXString(time) + spacer; @@ -426,6 +433,17 @@ struct XZigZagAnalysis // ENUM_X_DIRECTION dir; // Direction ... + // + // Pivots ... + + // + XZigZagPoint lastPeak; + XZigZagPoint recentPeak; + + // + XZigZagPoint lastVale; + XZigZagPoint recentVale; + // // Constructor ... XZigZagAnalysis() @@ -433,6 +451,253 @@ struct XZigZagAnalysis Clean(); } + // + // Initialize ... + + /** + * Analyse Market Structure ... + * + * @param bar: XOHCL, Specified Bar ... + * @param points: XZigZagPoint, Specified ZigZag Points Collection ... + * + * @return ( bool ) + */ + bool Analyse( + XOHCL &bar, + XZigZagPoint &points[] // + ) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasChild(points) && + bar.symbol == points[0].symbol; + if (!result) + { + // + Clean(); + return result; + } + + // + // AssignSymbol and Period ... + time = bar.time; + symbol = bar.symbol; + period = bar.period; + + // + // Detect At lease Two PEAK and Two Vale ... + XZigZagPoint tmpPoints[]; + Copy( + points, + tmpPoints // + ); + + // + // Detect Highs ... + + // + // Highest High ... + + // + XZigZagPoint iZGPeak1; + XZigZagPoint iZGPeak2; + + // + // First ... + int idx = GetHighest( + tmpPoints, + X_ZIGZAG_POINT_TYPE_PEAK // + ); + result = IsValidIndex(idx); + if (!result) + { + // + Clean(); + iZGPeak1.Clean(); + iZGPeak2.Clean(); + SpecifiedClean(tmpPoints); + + // + return result; + } + iZGPeak1 = tmpPoints[idx]; + ArrayRemove( + tmpPoints, + idx, + 1 // + ); + + // + // Second ... + idx = GetHighest( + tmpPoints, + X_ZIGZAG_POINT_TYPE_PEAK // + ); + result = IsValidIndex(idx); + if (!result) + { + // + Clean(); + iZGPeak1.Clean(); + iZGPeak2.Clean(); + SpecifiedClean(tmpPoints); + + // + return result; + } + iZGPeak2 = tmpPoints[idx]; + ArrayRemove( + tmpPoints, + idx, + 1 // + ); + + // + // Detect Lows ... + + // + XZigZagPoint iZGVale1; + XZigZagPoint iZGVale2; + + // + // First ... + idx = GetLowest( + tmpPoints, + X_ZIGZAG_POINT_TYPE_VALE // + ); + result = IsValidIndex(idx); + if (!result) + { + // + Clean(); + iZGPeak1.Clean(); + iZGPeak2.Clean(); + iZGVale1.Clean(); + iZGVale2.Clean(); + SpecifiedClean(tmpPoints); + + // + return result; + } + iZGVale1 = tmpPoints[idx]; + ArrayRemove( + tmpPoints, + idx, + 1 // + ); + + // + // Second ... + idx = GetLowest( + tmpPoints, + X_ZIGZAG_POINT_TYPE_VALE // + ); + result = IsValidIndex(idx); + if (!result) + { + // + Clean(); + iZGPeak1.Clean(); + iZGPeak2.Clean(); + iZGVale1.Clean(); + iZGVale2.Clean(); + SpecifiedClean(tmpPoints); + + // + return result; + } + iZGVale2 = tmpPoints[idx]; + ArrayRemove( + tmpPoints, + idx, + 1 // + ); + + // + // Check Directions ... + bool isBullish = + // + (iZGPeak1.time > iZGPeak2.time && + iZGVale1.time < iZGVale2.time) + // + ; + bool isBearish = + // + (iZGPeak1.time < iZGPeak2.time && + iZGVale1.time > iZGVale2.time) + // + ; + result = + (isBullish && !isBearish) || + (isBearish && !isBullish); + if (!result) + { + // + Clean(); + iZGPeak1.Clean(); + iZGPeak2.Clean(); + iZGVale1.Clean(); + iZGVale2.Clean(); + SpecifiedClean(tmpPoints); + + // + return result; + } + + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + // Setting Points ... + Copy( + points, + pivots // + ); + + // + // Assigning Peaks and Vales ... + if (result) + { + // + lastPeak = iZGPeak1; + lastVale = iZGVale1; + recentPeak = iZGPeak2; + recentVale = iZGVale2; + } + + // + // Calculate Support and Resistance ... + + // + // Validate ... + result = IsValid(); + if (!result) + { + Clean(); + } + + // + // Cleanup Resources ... + iZGPeak1.Clean(); + iZGPeak2.Clean(); + iZGVale1.Clean(); + iZGVale2.Clean(); + SpecifiedClean(tmpPoints); + + // + return result; + } + // // Tools ... @@ -448,6 +713,12 @@ struct XZigZagAnalysis dir = X_DIRECTION_NONE; SpecifiedClean(pivots); + // + lastPeak.Clean(); + lastVale.Clean(); + recentPeak.Clean(); + recentVale.Clean(); + // ZeroMemory(this); } @@ -464,11 +735,19 @@ struct XZigZagAnalysis // result = + // HasChild(pivots) && HasDirection(dir) && IsSpecifiedValid(time) && IsSpecifiedValid(symbol) && - IsSpecifiedValid(period); + IsSpecifiedValid(period) && + // + lastPeak.IsValid() && + lastVale.IsValid() && + recentPeak.IsValid() && + recentVale.IsValid() + // + ; // return result; @@ -603,7 +882,269 @@ struct XZigZagAnalysis return result; } + /** + * Check to model Has Same Direction ... + * + * @param item: XZigZagAnalysis, dest model for Checking ... + * + * @return ( bool ) + */ + bool IsSameDirectionAs(XZigZagAnalysis &item) + { + // + bool result = false; + + // + result = + IsValid() && + item.IsValid() && + dir == item.dir; + + // + return result; + } + + /** + * Check to model Has Analysis Trend ... + * + * @param item: XZigZagAnalysis, dest model for Checking ... + * + * @return ( bool ) + */ + bool IsSameTrendAs(XZigZagAnalysis &item) + { + // + bool result = false; + + // + result = + IsValid() && + item.IsValid() && + IsSameMarketAs(item) && + IsSameDirectionAs(item); + + // + return result; + } + + // + // Loggint Tools ... + + /** + * Extract Specified Token of Struct ... + * + * @return ( string ) + */ + string GetTag() + { + return GetToken(this); + } + + /** + * Represent an String Unique Identifier for Chart Objects ... + * + * @return ( string ) + */ + string GetObjectID() + { + // + string result = ""; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetTag() + "_" + symbol + "_" + ToXString(period) + "_" + ToXString(dir) + "_" + ToXString(TimeToSeconds(time)); + + // + return result; + } + + /** + * Represent a Point as String ... + * + * @param spacer: string, How to Represent Spaces ... + * + * @return ( string ) + */ + string GetMessage(string spacer = NULL) + { + // + string result = ""; + + // + // Normalize Spacer ... + if (!IsSpecifiedValid(spacer)) + { + spacer = " "; + } + + // + // Validate ... + if (!IsValid()) + { + return result; + } + + // + result = + ToXString(dir) + spacer + GetTag() + ":" + spacer + + "Symbol: " + symbol + spacer + + "Period: " + ToXString(period) + spacer + + "Direction: " + ToXString(dir) + spacer + + "Time: " + ToXString(time) + spacer; + + // + return result; + } + // }; // +// Extensions ... + +/** + * Get Highest ZigZagPoint Index in Specified Collection ... + * + * @param items: XZigZagPoint, Specified Points Collection to Search ... + * @param type: ENUM_X_ZIGZAG_POINT_TYPE, Specified Points Type ... + * + * @return ( int ) + */ +int GetHighest( + XZigZagPoint &items[], + ENUM_X_ZIGZAG_POINT_TYPE type = X_ZIGZAG_POINT_TYPE_NONE // +) +{ + // + int result = -1; + + // + // Validate ... + if (!HasChild(items)) + { + return result; + } + + // + bool has = false; + XZigZagPoint iPoint; + int count = ArraySize(items); + for (int i = 0; i < count; i++) + { + // + // Passed Type ... + has = !IsXValid(type) + ? true + : type == items[i].type; + + // + // Check Can Assign ... + has = + has && + (!iPoint.IsValid() || + (iPoint.IsValid() && + items[i].value > iPoint.value)); + if (has) + { + // + result = i; + iPoint = items[i]; + } + } + + // + // Validate Result ... + has = + iPoint.IsValid() && + IsValidIndex(result); + if (!has) + { + // + result = -1; + iPoint.Clean(); + return result; + } + + // + iPoint.Clean(); + + // + return result; +} + +/** + * Get Lowest ZigZagPoint Index in Specified Collection ... + * + * @param items: XZigZagPoint, Specified Points Collection to Search ... + * @param type: ENUM_X_ZIGZAG_POINT_TYPE, Specified Points Type ... + * + * @return ( int ) + */ +int GetLowest( + XZigZagPoint &items[], + ENUM_X_ZIGZAG_POINT_TYPE type = X_ZIGZAG_POINT_TYPE_NONE // +) +{ + // + int result = -1; + + // + // Validate ... + if (!HasChild(items)) + { + return result; + } + + // + bool has = false; + XZigZagPoint iPoint; + int count = ArraySize(items); + for (int i = 0; i < count; i++) + { + // + // Passed Type ... + has = !IsXValid(type) + ? true + : type == items[i].type; + + // + // Check Can Assign ... + has = + has && + (!iPoint.IsValid() || + (iPoint.IsValid() && + items[i].value < iPoint.value)); + if (has) + { + // + result = i; + iPoint = items[i]; + } + } + + // + // Validate Result ... + has = + iPoint.IsValid() && + IsValidIndex(result); + if (!has) + { + // + result = -1; + iPoint.Clean(); + return result; + } + + // + iPoint.Clean(); + + // + return result; +} + +// \ No newline at end of file