/////////////////////////////////////////////////////// // SaherElm IT Center MQL5 Indicator // ------------------------------------------- // Name: XCHSTR // Description: Smoothed HikenAshi Cycles ... // // 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 XCHSTR Indicator" #property strict // #define ShortName "XCHSTR" // // Includes Common Library ... #include "../Libraries/x-saherelm.common.lib.mq5" // // Inputs ... // input group "Market"; // input int atrLength = 14; // Length input double atrMultiplier = 3.0; // Multiplier input ENUM_APPLIED_PRICE atrAppliedTo = PRICE_MEDIAN; // Applied To // input group "Cycles"; // input group "Short"; input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Period input ENUM_TIMEFRAMES scPeriod = NULL; // Time Period // input group "Medium"; input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Period input ENUM_TIMEFRAMES mcPeriod = NULL; // Time Period // input group "Long"; input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Period input ENUM_TIMEFRAMES lcPeriod = NULL; // Time Period // input group "Hind"; input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Period input ENUM_TIMEFRAMES hcPeriod = NULL; // Time Period // // Presentation ... input group "Presentation"; // input bool showCurrent = true; // Show Current Cycle input bool showShort = true; // Show Short Cycle input bool showMedium = true; // Show Medium Cycle input bool showLong = true; // Show Long Cycle input bool showHind = true; // Show Hind Cycle // // Buffers ... // #define hideColorIDX 0 #define bullishColorIDX 1 #define bearishColorIDX 2 // #property indicator_chart_window // #property indicator_buffers 35 #property indicator_plots 10 // // Current ... // #define cBufferIndex 0 #define cPlotBufferIndex 0 double cBuffer[]; // #define cColorBufferIndex 1 double cColorBuffer[]; // #property indicator_label1 "C XSTR" #property indicator_type1 DRAW_COLOR_LINE #property indicator_color1 CLR_NONE, clrGreen, clrDarkRed #property indicator_style1 STYLE_DOT // // Short ... // #define sBufferIndex 2 #define sPlotBufferIndex 1 double sBuffer[]; // #define sColorBufferIndex 3 double sColorBuffer[]; // #property indicator_label2 "S XSTR" #property indicator_type2 DRAW_COLOR_LINE #property indicator_color2 CLR_NONE, clrGreen, clrDarkRed #property indicator_style2 STYLE_DOT // // Medium ... // #define mBufferIndex 4 #define mPlotBufferIndex 2 double mBuffer[]; // #define mColorBufferIndex 5 double mColorBuffer[]; // #property indicator_label3 "M XSTR" #property indicator_type3 DRAW_COLOR_LINE #property indicator_color3 CLR_NONE, clrGreen, clrDarkRed #property indicator_style3 STYLE_DOT // // Long ... // #define lBufferIndex 6 #define lPlotBufferIndex 3 double lBuffer[]; // #define lColorBufferIndex 7 double lColorBuffer[]; // #property indicator_label4 "L XSTR" #property indicator_type4 DRAW_COLOR_LINE #property indicator_color4 CLR_NONE, clrGreen, clrDarkRed #property indicator_style4 STYLE_DOT // // Hind ... // #define hBufferIndex 8 #define hPlotBufferIndex 4 double hBuffer[]; // #define hColorBufferIndex 9 double hColorBuffer[]; // #property indicator_label5 "H XSTR" #property indicator_type5 DRAW_COLOR_LINE #property indicator_color5 CLR_NONE, clrGreen, clrDarkRed #property indicator_style5 STYLE_DOT // // Data Buffers ... // // Current ... // #define cAtrBufferIndex 10 double cAtrBuffer[]; // #define cTrendBufferIndex 11 double cTrendBuffer[]; // #define cUpBufferIndex 12 double cUpBuffer[]; // #define cDownBufferIndex 13 double cDownBuffer[]; // #define cPriceBufferIndex 14 double cPriceBuffer[]; // // Short ... // #define sAtrBufferIndex 15 double sAtrBuffer[]; // #define sTrendBufferIndex 16 double sTrendBuffer[]; // #define sUpBufferIndex 17 double sUpBuffer[]; // #define sDownBufferIndex 18 double sDownBuffer[]; // #define sPriceBufferIndex 19 double sPriceBuffer[]; // // Medium ... // #define mAtrBufferIndex 20 double mAtrBuffer[]; // #define mTrendBufferIndex 21 double mTrendBuffer[]; // #define mUpBufferIndex 22 double mUpBuffer[]; // #define mDownBufferIndex 23 double mDownBuffer[]; // #define mPriceBufferIndex 24 double mPriceBuffer[]; // // Long ... // #define lAtrBufferIndex 25 double lAtrBuffer[]; // #define lTrendBufferIndex 26 double lTrendBuffer[]; // #define lUpBufferIndex 27 double lUpBuffer[]; // #define lDownBufferIndex 28 double lDownBuffer[]; // #define lPriceBufferIndex 29 double lPriceBuffer[]; // // Hind ... // #define hAtrBufferIndex 30 double hAtrBuffer[]; // #define hTrendBufferIndex 31 double hTrendBuffer[]; // #define hUpBufferIndex 32 double hUpBuffer[]; // #define hDownBufferIndex 33 double hDownBuffer[]; // #define hPriceBufferIndex 34 double hPriceBuffer[]; // // Variables, Properties and etc ... // int changeOfTrend; int startBearishTrend; int startBullishTrend; // int maxLength; // // Current ... int mCSMLength = atrLength; int mCAtrHandler = INVALID_HANDLE; // // Short ... int mSCLength = 0; int mSSMLength = 0; int mSAtrHandler = INVALID_HANDLE; ENUM_TIMEFRAMES mSCPeriod = NULL; // // Medium ... int mMCLength = 0; int mMSMLength = 0; int mMAtrHandler = INVALID_HANDLE; ENUM_TIMEFRAMES mMCPeriod = NULL; // // Long ... int mLCLength = 0; int mLSMLength = 0; int mLAtrHandler = INVALID_HANDLE; ENUM_TIMEFRAMES mLCPeriod = NULL; // // Hind ... int mHCLength = 0; int mHSMLength = 0; int mHAtrHandler = INVALID_HANDLE; ENUM_TIMEFRAMES mHCPeriod = NULL; // // Event Handlers ... // // Initialization ... int OnInit() { // // Validate Inputs ... if (!ValidateInputs()) { return INIT_PARAMETERS_INCORRECT; } // if (!InitMarketCycles()) { return INIT_PARAMETERS_INCORRECT; } // // because in some cases we may have more than one input for // calculation and we must prevent any calculation // untill we pass the biggest input length, here we get max Input length // and then wait until pass it ... maxLength = ExtractMaxLengthOfInputs(); // // Define Index Buffers ... DefineBuffers(); // // Set Indicator ShortName ... SetIndicatorName(); // // Init Succeed ... return INIT_SUCCEEDED; } // // DeInitialization ... void OnDeinit(const int reason) { // // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function // REASON_REMOVE 1 Program removed from a chart // REASON_RECOMPILE 2 Program recompiled // REASON_CHARTCHANGE 3 A symbol or a chart period is changed // REASON_CHARTCLOSE 4 Chart closed // REASON_PARAMETERS 5 Inputs changed by a user // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings // REASON_TEMPLATE 7 Another chart template applied // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value // REASON_CLOSE 9 Terminal closed } // // Calculating what we want ... int OnCalculate( const int rates_total, // Total Bars on Chart ... const int prev_calculated, // Total Calculated Bars on Charts ... const datetime &time[], // History of Open Time ... const double &open[], // History of Open Price ... const double &high[], // History of High Price ... const double &low[], // History of Low Price ... const double &close[], // History of Close Price ... const long &tick_volume[], // History of Tick Volumes on Bar ... const long &volume[], // History of Trade Volumes ... const int &spread[] // History of Spread Price ... ) { // int numOfRequiredAtrs; if (prev_calculated > rates_total || prev_calculated < 0) { numOfRequiredAtrs = rates_total; } else { // numOfRequiredAtrs = rates_total - prev_calculated; if (prev_calculated > 0) { numOfRequiredAtrs++; } } // // Checking for stop ... if (IsStopped()) { return 0; } // // Check Number of items Copy or not ... int copiedCATRs = CopyBuffer(mCAtrHandler, 0, 0, numOfRequiredAtrs, cAtrBuffer); int copiedSATRs = CopyBuffer(mSAtrHandler, 0, 0, numOfRequiredAtrs, sAtrBuffer); int copiedMATRs = CopyBuffer(mMAtrHandler, 0, 0, numOfRequiredAtrs, mAtrBuffer); int copiedLATRs = CopyBuffer(mLAtrHandler, 0, 0, numOfRequiredAtrs, lAtrBuffer); int copiedHATRs = CopyBuffer(mHAtrHandler, 0, 0, numOfRequiredAtrs, hAtrBuffer); if (copiedCATRs <= 0 || copiedSATRs <= 0 || copiedMATRs <= 0 || copiedLATRs <= 0 || copiedHATRs <= 0) { return 0; } // int limit; // // checking for the limit start of calculation of an indicator ... if (prev_calculated > rates_total || prev_calculated <= 0) { // // starting index for calculation of all bars ... limit = maxLength; } else { // // starting number for calculation of new bars limit = prev_calculated - 1; } // // Main Loop ... for (int i = limit; i < rates_total && !IsStopped(); i++) { // CalculateBuffers( open, high, low, close, i // ); } // return rates_total; } // // Functions ... // // Validate Input Args for Initialization ... bool ValidateInputs() { // bool result = false; // result = // atrLength >= 2 && atrMultiplier > 0 && // (IsValid(scMethod, scPeriod) && IsValid(mcMethod, mcPeriod) && IsValid(lcMethod, lcPeriod) && IsValid(hcMethod, hcPeriod)) // ; // return result; } // // Initialize Market Cycles ... bool InitMarketCycles() { // bool result = false; // // Current Cycle Initialization ... // int cPeriodSeconds = PeriodSeconds(_Period); // mCAtrHandler = iATR( _Symbol, _Period, mCSMLength // ); result = mCAtrHandler != INVALID_HANDLE; if (!result) { return result; } // // Short Cycle Initialization ... // // Find Cycle Period ... if (scMethod == X_PERIOD_AUTO) { // // Select Period ... mSCPeriod = GetCyclePeriod( X_MARKET_CYCLE_SHORT, _Period // ); } else { mSCPeriod = scPeriod; } // result = IsValid(mSCPeriod); if (!result) { return result; } // mSCLength = PeriodSeconds(mSCPeriod) / cPeriodSeconds; mSSMLength = mSCLength * mCSMLength; result = mSCLength > 0; if (!result) { return result; } // mSAtrHandler = iATR( _Symbol, _Period, mSSMLength // ); result = mSAtrHandler != INVALID_HANDLE; if (!result) { return result; } // // Medium Cycle Initialization ... // // Find Cycle Period ... if (mcMethod == X_PERIOD_AUTO) { // // Select Period ... mMCPeriod = GetCyclePeriod( X_MARKET_CYCLE_MEDIUM, _Period // ); } else { mMCPeriod = mcPeriod; } // result = IsValid(mMCPeriod); if (!result) { return result; } // mMCLength = PeriodSeconds(mMCPeriod) / cPeriodSeconds; mMSMLength = mMCLength * mCSMLength; result = mMCLength > 0; if (!result) { return result; } // mMAtrHandler = iATR( _Symbol, _Period, mMSMLength // ); result = mMAtrHandler != INVALID_HANDLE; if (!result) { return result; } // // Long Cycle Initialization ... // // Find Cycle Period ... if (lcMethod == X_PERIOD_AUTO) { // // Select Period ... mLCPeriod = GetCyclePeriod( X_MARKET_CYCLE_LONG, _Period // ); } else { mLCPeriod = lcPeriod; } // result = IsValid(mLCPeriod); if (!result) { return result; } // mLCLength = PeriodSeconds(mLCPeriod) / cPeriodSeconds; mLSMLength = mLCLength * mCSMLength; result = mLCLength > 0; if (!result) { return result; } // mLAtrHandler = iATR( _Symbol, _Period, mLSMLength // ); result = mLAtrHandler != INVALID_HANDLE; if (!result) { return result; } // // Hind Cycle Initialization ... // // Find Cycle Period ... if (hcMethod == X_PERIOD_AUTO) { // // Select Period ... mHCPeriod = GetCyclePeriod( X_MARKET_CYCLE_HIND, _Period // ); } else { mHCPeriod = hcPeriod; } // result = IsValid(mHCPeriod); if (!result) { return result; } // mHCLength = PeriodSeconds(mHCPeriod) / cPeriodSeconds; mHSMLength = mHCLength * mCSMLength; result = mHCLength > 0; if (!result) { return result; } // mHAtrHandler = iATR( _Symbol, _Period, mHSMLength // ); result = mHAtrHandler != INVALID_HANDLE; if (!result) { return result; } // return result; } // // Retrieve all Exists Input Max Length ... // use for Start Of Drawing ... int ExtractMaxLengthOfInputs() { // int result = 0; // result = MathMax(mCSMLength, mSSMLength); result = MathMax(result, mMSMLength); result = MathMax(result, mLSMLength); result = MathMax(result, mHSMLength); // return result; } // // Define Indexes and Styles ... void DefineBuffers() { // // CURRENT Cycle ... // // STR ... SetIndexBuffer(cBufferIndex, cBuffer, INDICATOR_DATA); // // Color ... SetIndexBuffer(cColorBufferIndex, cColorBuffer, INDICATOR_COLOR_INDEX); // // Set EMPTY_VALUE on Bar Buffer ... PlotIndexSetDouble(cPlotBufferIndex, PLOT_EMPTY_VALUE, 0.0); PlotIndexSetInteger(cPlotBufferIndex, PLOT_SHOW_DATA, showCurrent); // // Data Buffers ... // // ATR ... SetIndexBuffer(cAtrBufferIndex, cAtrBuffer, INDICATOR_CALCULATIONS); // // Price ... SetIndexBuffer(cPriceBufferIndex, cPriceBuffer, INDICATOR_CALCULATIONS); // // Trend ... SetIndexBuffer(cTrendBufferIndex, cTrendBuffer, INDICATOR_CALCULATIONS); // // Up ... SetIndexBuffer(cUpBufferIndex, cUpBuffer, INDICATOR_CALCULATIONS); // // Down ... SetIndexBuffer(cDownBufferIndex, cDownBuffer, INDICATOR_CALCULATIONS); // // SHORT Cycle ... // // STR ... SetIndexBuffer(sBufferIndex, sBuffer, INDICATOR_DATA); // // Color ... SetIndexBuffer(sColorBufferIndex, sColorBuffer, INDICATOR_COLOR_INDEX); // // Set EMPTY_VALUE on Bar Buffer ... PlotIndexSetDouble(sPlotBufferIndex, PLOT_EMPTY_VALUE, 0.0); PlotIndexSetInteger(sPlotBufferIndex, PLOT_SHOW_DATA, showShort); // // Data Buffers ... // // ATR ... SetIndexBuffer(sAtrBufferIndex, sAtrBuffer, INDICATOR_CALCULATIONS); // // Price ... SetIndexBuffer(sPriceBufferIndex, sPriceBuffer, INDICATOR_CALCULATIONS); // // Trend ... SetIndexBuffer(sTrendBufferIndex, sTrendBuffer, INDICATOR_CALCULATIONS); // // Up ... SetIndexBuffer(sUpBufferIndex, sUpBuffer, INDICATOR_CALCULATIONS); // // Down ... SetIndexBuffer(sDownBufferIndex, sDownBuffer, INDICATOR_CALCULATIONS); // // MEDIUM Cycle ... // // STR ... SetIndexBuffer(mBufferIndex, mBuffer, INDICATOR_DATA); // // Color ... SetIndexBuffer(mColorBufferIndex, mColorBuffer, INDICATOR_COLOR_INDEX); // // Set EMPTY_VALUE on Bar Buffer ... PlotIndexSetDouble(mPlotBufferIndex, PLOT_EMPTY_VALUE, 0.0); PlotIndexSetInteger(mPlotBufferIndex, PLOT_SHOW_DATA, showMedium); // // Data Buffers ... // // ATR ... SetIndexBuffer(mAtrBufferIndex, mAtrBuffer, INDICATOR_CALCULATIONS); // // Price ... SetIndexBuffer(mPriceBufferIndex, mPriceBuffer, INDICATOR_CALCULATIONS); // // Trend ... SetIndexBuffer(mTrendBufferIndex, mTrendBuffer, INDICATOR_CALCULATIONS); // // Up ... SetIndexBuffer(mUpBufferIndex, mUpBuffer, INDICATOR_CALCULATIONS); // // Down ... SetIndexBuffer(mDownBufferIndex, mDownBuffer, INDICATOR_CALCULATIONS); // // LONG Cycle ... // // STR ... SetIndexBuffer(lBufferIndex, lBuffer, INDICATOR_DATA); // // Color ... SetIndexBuffer(lColorBufferIndex, lColorBuffer, INDICATOR_COLOR_INDEX); // // Set EMPTY_VALUE on Bar Buffer ... PlotIndexSetDouble(lPlotBufferIndex, PLOT_EMPTY_VALUE, 0.0); PlotIndexSetInteger(lPlotBufferIndex, PLOT_SHOW_DATA, showLong); // // Data Buffers ... // // ATR ... SetIndexBuffer(lAtrBufferIndex, lAtrBuffer, INDICATOR_CALCULATIONS); // // Price ... SetIndexBuffer(lPriceBufferIndex, lPriceBuffer, INDICATOR_CALCULATIONS); // // Trend ... SetIndexBuffer(lTrendBufferIndex, lTrendBuffer, INDICATOR_CALCULATIONS); // // Up ... SetIndexBuffer(lUpBufferIndex, lUpBuffer, INDICATOR_CALCULATIONS); // // Down ... SetIndexBuffer(lDownBufferIndex, lDownBuffer, INDICATOR_CALCULATIONS); // // HIND Cycle ... // // STR ... SetIndexBuffer(hBufferIndex, hBuffer, INDICATOR_DATA); // // Color ... SetIndexBuffer(hColorBufferIndex, hColorBuffer, INDICATOR_COLOR_INDEX); // // Set EMPTY_VALUE on Bar Buffer ... PlotIndexSetDouble(hPlotBufferIndex, PLOT_EMPTY_VALUE, 0.0); PlotIndexSetInteger(hPlotBufferIndex, PLOT_SHOW_DATA, showHind); // // Data Buffers ... // // ATR ... SetIndexBuffer(hAtrBufferIndex, hAtrBuffer, INDICATOR_CALCULATIONS); // // Price ... SetIndexBuffer(hPriceBufferIndex, hPriceBuffer, INDICATOR_CALCULATIONS); // // Trend ... SetIndexBuffer(hTrendBufferIndex, hTrendBuffer, INDICATOR_CALCULATIONS); // // Up ... SetIndexBuffer(hUpBufferIndex, hUpBuffer, INDICATOR_CALCULATIONS); // // Down ... SetIndexBuffer(hDownBufferIndex, hDownBuffer, INDICATOR_CALCULATIONS); } // // Set Indicator Short Name and also we can define Buffers Labels ... void SetIndicatorName() { IndicatorSetString(INDICATOR_SHORTNAME, ShortName); } // // Calculations ... // // Calculate Hiken Ashi ... void CalculateBuffers( const double &open[], const double &high[], const double &low[], const double &close[], int barIndex // ) { // // Current ... CalculateCycle( open, high, low, close, barIndex, cAtrBuffer, cPriceBuffer, cUpBuffer, cDownBuffer, cTrendBuffer, cBuffer, cColorBuffer, showCurrent // ); // // Short ... CalculateCycle( open, high, low, close, barIndex, sAtrBuffer, sPriceBuffer, sUpBuffer, sDownBuffer, sTrendBuffer, sBuffer, sColorBuffer, showShort // ); // // Short ... CalculateCycle( open, high, low, close, barIndex, mAtrBuffer, mPriceBuffer, mUpBuffer, mDownBuffer, mTrendBuffer, mBuffer, mColorBuffer, showMedium // ); // // Short ... CalculateCycle( open, high, low, close, barIndex, lAtrBuffer, lPriceBuffer, lUpBuffer, lDownBuffer, lTrendBuffer, lBuffer, lColorBuffer, showLong // ); // // Hind ... CalculateCycle( open, high, low, close, barIndex, hAtrBuffer, hPriceBuffer, hUpBuffer, hDownBuffer, hTrendBuffer, hBuffer, hColorBuffer, showHind // ); } // void CalculateCycle( const double &open[], const double &high[], const double &low[], const double &close[], int barIndex, double &atr[], double &price[], double &up[], double &down[], double &trend[], double &main[], double &clr[], // Color Index Buffer bool show // ) { // // Calculated Price ... double _price = getPrice( atrAppliedTo, open, high, low, close, barIndex // ); price[barIndex] = _price; // double _atr = atr[barIndex]; // // Up ... up[barIndex] = _price + (atrMultiplier * _atr); // // Down ... down[barIndex] = _price - (atrMultiplier * _atr); // if (close[barIndex] > up[barIndex - 1]) { // trend[barIndex] = 1; if (trend[barIndex - 1] == -1) { changeOfTrend = 1; } } else if (close[barIndex] < down[barIndex - 1]) { // trend[barIndex] = -1; if (trend[barIndex - 1] == 1) { changeOfTrend = 1; } } else if (trend[barIndex - 1] == 1) { // trend[barIndex] = 1; changeOfTrend = 0; } else if (trend[barIndex - 1] == -1) { // trend[barIndex] = -1; changeOfTrend = 0; } // // Down Trend Starting ... if (trend[barIndex] < 0 && trend[barIndex - 1] > 0) { startBearishTrend = 1; } else { startBearishTrend = 0; } // // Up Trend Starting ... if (trend[barIndex] > 0 && trend[barIndex - 1] < 0) { startBullishTrend = 1; } else { startBullishTrend = 0; } // if (trend[barIndex] > 0 && down[barIndex] < down[barIndex - 1]) { down[barIndex] = down[barIndex - 1]; } // if (trend[barIndex] < 0 && up[barIndex] > up[barIndex - 1]) { up[barIndex] = up[barIndex - 1]; } // if (startBearishTrend == 1) { up[barIndex] = price[barIndex] + (atrMultiplier * _atr); } // if (startBullishTrend == 1) { down[barIndex] = price[barIndex] - (atrMultiplier * _atr); } // double colorIDX = hideColorIDX; clr[barIndex] = colorIDX; // if (trend[barIndex] == 1) { // main[barIndex] = down[barIndex]; if (changeOfTrend == 1) { // main[barIndex - 1] = main[barIndex - 2]; changeOfTrend = 0; } // colorIDX = bullishColorIDX; } else if (trend[barIndex] == -1) { // main[barIndex] = up[barIndex]; if (changeOfTrend == 1) { // main[barIndex - 1] = main[barIndex - 2]; changeOfTrend = 0; } // colorIDX = bearishColorIDX; } // if (show) { clr[barIndex] = colorIDX; } // } // // TEMPLATE Function ... template double getPrice(ENUM_APPLIED_PRICE tprice, T &open[], T &high[], T &low[], T &close[], int i) { switch (tprice) { case PRICE_CLOSE: return (close[i]); case PRICE_OPEN: return (open[i]); case PRICE_HIGH: return (high[i]); case PRICE_LOW: return (low[i]); case PRICE_MEDIAN: return ((high[i] + low[i]) / 2.0); case PRICE_TYPICAL: return ((high[i] + low[i] + close[i]) / 3.0); case PRICE_WEIGHTED: return ((high[i] + low[i] + close[i] + close[i]) / 4.0); } return (0); } //