#property copyright "Copyright 2018-2021, Level Up Software" #property link "http://www.az-invest.eu" #ifdef DEVELOPER_VERSION #define RANGEBAR_INDICATOR_NAME "RangeBars\\RangeBarsOverlay316" #else #ifdef RANGEBAR_LICENSE #ifdef MQL5_MARKET_VERSION #define RANGEBAR_INDICATOR_NAME "Market\\Range Bars Charting" #else #define RANGEBAR_INDICATOR_NAME "RangeBars" #endif #else #define RANGEBAR_INDICATOR_NAME "Market\\Range Bars Charting" #endif #endif #define RANGEBAR_OPEN 00 #define RANGEBAR_HIGH 01 #define RANGEBAR_LOW 02 #define RANGEBAR_CLOSE 03 #define RANGEBAR_BAR_COLOR 04 #define RANGEBAR_SESSION_RECT_H 05 #define RANGEBAR_SESSION_RECT_L 06 #define RANGEBAR_MA1 07 #define RANGEBAR_MA2 08 #define RANGEBAR_MA3 09 #define RANGEBAR_MA4 10 #define RANGEBAR_CHANNEL_HIGH 11 #define RANGEBAR_CHANNEL_MID 12 #define RANGEBAR_CHANNEL_LOW 13 #define RANGEBAR_BAR_OPEN_TIME 14 #define RANGEBAR_TICK_VOLUME 15 #define RANGEBAR_REAL_VOLUME 16 #define RANGEBAR_BUY_VOLUME 17 #define RANGEBAR_SELL_VOLUME 18 #define RANGEBAR_BUYSELL_VOLUME 19 #define RANGEBAR_RUNTIME_ID 20 #include class RangeBars { private: CRangeBarCustomChartSettigns * rangeBarSettings; int rangeBarsHandle; // range bar indicator handle string rangeBarsSymbol; bool usedByIndicatorOnRangeBarChart; datetime prevBarTime; public: RangeBars(); RangeBars(bool isUsedByIndicatorOnRangeBarChart); RangeBars(string symbol); ~RangeBars(void); int Init(); void Deinit(); bool Reload(); void ReleaseHandle(); int GetHandle(void) { return rangeBarsHandle; }; double GetRuntimeId(); bool IsNewBar(); bool GetMqlRates(MqlRates &ratesInfoArray[], int start, int count); bool GetBuySellVolumeBreakdown(double &buy[], double &sell[], double &buySell[], int start, int count); bool GetMA(int MaBufferId, double &MA[], int start, int count); bool GetChannel(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count); // The following 6 functions are deprecated, please use GetMA & GetChannelData functions instead bool GetMA1(double &MA[], int start, int count); bool GetMA2(double &MA[], int start, int count); bool GetMA3(double &MA[], int start, int count); bool GetDonchian(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count); bool GetBollingerBands(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count); bool GetSuperTrend(double &SuperTrendHighArray[], double &SuperTrendArray[], double &SuperTrendLowArray[], int start, int count); // private: int GetIndicatorHandle(void); bool GetChannelData(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count); }; RangeBars::RangeBars(void) { #define CONSTRUCTOR1 rangeBarSettings = new CRangeBarCustomChartSettigns(); rangeBarsHandle = INVALID_HANDLE; rangeBarsSymbol = _Symbol; usedByIndicatorOnRangeBarChart = false; prevBarTime = 0; } RangeBars::RangeBars(bool isUsedByIndicatorOnRangeBarChart) { rangeBarSettings = new CRangeBarCustomChartSettigns(); rangeBarsHandle = INVALID_HANDLE; rangeBarsSymbol = _Symbol; usedByIndicatorOnRangeBarChart = isUsedByIndicatorOnRangeBarChart; prevBarTime = 0; } RangeBars::RangeBars(string symbol) { #define CONSTRUCTOR2 rangeBarSettings = new CRangeBarCustomChartSettigns(); rangeBarsHandle = INVALID_HANDLE; rangeBarsSymbol = symbol; usedByIndicatorOnRangeBarChart = false; prevBarTime = 0; } RangeBars::~RangeBars(void) { if(rangeBarSettings != NULL) delete rangeBarSettings; } void RangeBars::ReleaseHandle() { if(rangeBarsHandle != INVALID_HANDLE) { IndicatorRelease(rangeBarsHandle); } } // // Function for initializing the median renko indicator handle // int RangeBars::Init() { if(!MQLInfoInteger((int)MQL5_TESTING)) { if(usedByIndicatorOnRangeBarChart) { // // Indicator on RangeBar chart uses the values of the RangeBar chart for calculations // IndicatorRelease(rangeBarsHandle); rangeBarsHandle = GetIndicatorHandle(); return rangeBarsHandle; } if(!rangeBarSettings.Load()) { if(rangeBarsHandle != INVALID_HANDLE) { // could not read new settings - keep old settings return rangeBarsHandle; } else { Print("Failed to load indicator settings - RangeBar indicator not on chart"); return INVALID_HANDLE; } } if(rangeBarsHandle != INVALID_HANDLE) Deinit(); } else { if(usedByIndicatorOnRangeBarChart) { // // Indicator on RangeBar chart uses the values of the RangeBar chart for calculations // rangeBarsHandle = GetIndicatorHandle(); return rangeBarsHandle; } else { #ifdef SHOW_INDICATOR_INPUTS // // Load settings from EA inputs // rangeBarSettings.Load(); #endif } } RANGEBAR_SETTINGS s = rangeBarSettings.GetCustomChartSettings(); CHART_INDICATOR_SETTINGS cis = rangeBarSettings.GetChartIndicatorSettings(); ALERT_INFO_SETTINGS als = rangeBarSettings.GetAlertInfoSettings(); rangeBarsHandle = iCustom(this.rangeBarsSymbol, _Period, RANGEBAR_INDICATOR_NAME, s.barSize, s.barSizeCalcMode, s.showNumberOfDays, s.showFromDate, "=", s.atrTimeFrame, s.atrPeriod, "=", s.resetOpenOnNewTradingDay, "=", als.showPivots, als.pivotPointCalculationType, "=", InpAlertMeWhen, InpAlertNotificationType, "=", cis.MA1lineType, cis.MA1period, cis.MA1method, cis.MA1applyTo, cis.MA1shift, cis.MA1priceLabel, cis.MA2lineType, cis.MA2period, cis.MA2method, cis.MA2applyTo, cis.MA2shift, cis.MA2priceLabel, cis.MA3lineType, cis.MA3period, cis.MA3method, cis.MA3applyTo, cis.MA3shift, cis.MA3priceLabel, cis.MA4lineType, cis.MA4period, cis.MA4method, cis.MA4applyTo, cis.MA4shift, cis.MA4priceLabel, "=", cis.ShowChannel, cis.ChannelPeriod, cis.ChannelAtrPeriod, cis.ChannelAppliedPrice, cis.ChannelMultiplier, cis.ChannelBandsDeviations, cis.ChannelPriceLabels, "=", true); // used in EA // TopBottomPaddingPercentage, // showCurrentBarOpenTime, // SoundFileBull, // SoundFileBear, // DisplayAsBarChart // ShiftObj; all letft at defaults if(rangeBarsHandle == INVALID_HANDLE) { Print(RANGEBAR_INDICATOR_NAME+" indicator init failed on error ",GetLastError()); } else { Print(RANGEBAR_INDICATOR_NAME+" indicator init OK"); } return rangeBarsHandle; } // // Function for reloading the Median Renko indicator if needed // bool RangeBars::Reload() { bool actionNeeded = false; int temp = GetIndicatorHandle(); if(temp != rangeBarsHandle) { IndicatorRelease(rangeBarsHandle); rangeBarsHandle = INVALID_HANDLE; actionNeeded = true; } if(rangeBarSettings.Changed(GetRuntimeId())) { actionNeeded = true; } if(actionNeeded) { if(rangeBarsHandle != INVALID_HANDLE) { IndicatorRelease(rangeBarsHandle); rangeBarsHandle = INVALID_HANDLE; } if(Init() == INVALID_HANDLE) return false; return true; } return false; } // // Function for releasing the Median Renko indicator hanlde - free resources // void RangeBars::Deinit() { if(rangeBarsHandle == INVALID_HANDLE) return; if(!usedByIndicatorOnRangeBarChart) { if(IndicatorRelease(rangeBarsHandle)) Print(RANGEBAR_INDICATOR_NAME+" indicator handle released"); else Print("Failed to release "+RANGEBAR_INDICATOR_NAME+" indicator handle"); } } // // Function for detecting a new Renko bar // bool RangeBars::IsNewBar() { MqlRates currentBar[1]; GetMqlRates(currentBar,0,1); if(currentBar[0].time == 0) { return false; } if(prevBarTime < currentBar[0].time) { prevBarTime = currentBar[0].time; return true; } return false; } // // Get "count" Renko MqlRates into "ratesInfoArray[]" array starting from "start" bar // bool RangeBars::GetMqlRates(MqlRates &ratesInfoArray[], int start, int count) { double o[],l[],h[],c[],barColor[],time[],tick_volume[],real_volume[]; if(ArrayResize(o,count) == -1) return false; if(ArrayResize(l,count) == -1) return false; if(ArrayResize(h,count) == -1) return false; if(ArrayResize(c,count) == -1) return false; if(ArrayResize(barColor,count) == -1) return false; if(ArrayResize(time,count) == -1) return false; if(ArrayResize(tick_volume,count) == -1) return false; if(ArrayResize(real_volume,count) == -1) return false; if(CopyBuffer(rangeBarsHandle,RANGEBAR_OPEN,start,count,o) == -1) return false; if(CopyBuffer(rangeBarsHandle,RANGEBAR_LOW,start,count,l) == -1) return false; if(CopyBuffer(rangeBarsHandle,RANGEBAR_HIGH,start,count,h) == -1) return false; if(CopyBuffer(rangeBarsHandle,RANGEBAR_CLOSE,start,count,c) == -1) return false; if(CopyBuffer(rangeBarsHandle,RANGEBAR_BAR_OPEN_TIME,start,count,time) == -1) return false; if(CopyBuffer(rangeBarsHandle,RANGEBAR_BAR_COLOR,start,count,barColor) == -1) return false; if(CopyBuffer(rangeBarsHandle,RANGEBAR_TICK_VOLUME,start,count,tick_volume) == -1) return false; if(CopyBuffer(rangeBarsHandle,RANGEBAR_REAL_VOLUME,start,count,real_volume) == -1) return false; if(ArrayResize(ratesInfoArray,count) == -1) return false; int tempOffset = count-1; for(int i=0; i