//+------------------------------------------------------------------+ //| RangeBars.mqh ver:2.03.0 | //| Copyright 2017, AZ-iNVEST | //| http://www.az-invest.eu | //+------------------------------------------------------------------+ #property copyright "Copyright 2017, AZ-iNVEST" #property link "http://www.az-invest.eu" //#define RANGEBAR_INDICATOR_NAME "RangeBars\\RangeBarsOverlay211" #define RANGEBAR_INDICATOR_NAME "Market\\Range Bars Charting" #define RANGEBAR_OPEN 00 #define RANGEBAR_HIGH 01 #define RANGEBAR_LOW 02 #define RANGEBAR_CLOSE 03 #define RANGEBAR_BAR_COLOR 04 #define RANGEBAR_MA1 05 #define RANGEBAR_MA2 06 #define RANGEBAR_MA3 07 #define RANGEBAR_CHANNEL_HIGH 08 #define RANGEBAR_CHANNEL_MID 09 #define RANGEBAR_CHANNEL_LOW 10 #define RANGEBAR_BAR_OPEN_TIME 11 #define RANGEBAR_TICK_VOLUME 12 #define RANGEBAR_REAL_VOLUME 13 #define RANGEBAR_BUY_VOLUME 14 #define RANGEBAR_SELL_VOLUME 15 #define RANGEBAR_BUYSELL_VOLUME 16 #include class RangeBars { private: RangeBarSettings * rangeBarSettings; // // Median renko indicator handle // int rangeBarsHandle; string rangeBarsSymbol; bool usedByIndicatorOnRangeBarChart; public: RangeBars(); RangeBars(bool isUsedByIndicatorOnRangeBarChart); RangeBars(string symbol); ~RangeBars(void); int Init(); void Deinit(); bool Reload(); int GetHandle(void) { return rangeBarsHandle; }; bool GetMqlRates(MqlRates &ratesInfoArray[], int start, int count); bool GetBuySellVolumeBreakdown(double &buy[], double &sell[], double &buySell[], int start, int count); 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); bool IsNewBar(); private: bool GetChannel(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count); int GetIndicatorHandle(void); }; RangeBars::RangeBars(void) { #define CONSTRUCTOR1 rangeBarSettings = new RangeBarSettings(); rangeBarsHandle = INVALID_HANDLE; rangeBarsSymbol = _Symbol; usedByIndicatorOnRangeBarChart = false; } RangeBars::RangeBars(bool isUsedByIndicatorOnRangeBarChart) { rangeBarSettings = new RangeBarSettings(); rangeBarsHandle = INVALID_HANDLE; rangeBarsSymbol = _Symbol; usedByIndicatorOnRangeBarChart = isUsedByIndicatorOnRangeBarChart; } RangeBars::RangeBars(string symbol) { #define CONSTRUCTOR2 rangeBarSettings = new RangeBarSettings(); rangeBarsHandle = INVALID_HANDLE; rangeBarsSymbol = symbol; usedByIndicatorOnRangeBarChart = false; } RangeBars::~RangeBars(void) { if(rangeBarSettings != NULL) delete rangeBarSettings; } // // 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 // 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(); #else // // Save indicator inputs for use by EA attached to same chart. // rangeBarSettings.Save(); #endif } } RANGEBAR_SETTINGS s = rangeBarSettings.GetRangeBarSettings(); CHART_INDICATOR_SETTINGS cis = rangeBarSettings.GetChartIndicatorSettings(); //RangeBarSettings.Debug(); rangeBarsHandle = iCustom(this.rangeBarsSymbol,_Period,RANGEBAR_INDICATOR_NAME, s.barSizeInTicks, s.atrEnabled, //s.atrTimeFrame, s.atrPeriod, s.atrPercentage, s.showNumberOfDays, s.resetOpenOnNewTradingDay, TopBottomPaddingPercentage, showPivots, pivotPointCalculationType, RColor, PColor, SColor, PDHColor, PDLColor, PDCColor, showNextBarLevels, HighThresholdIndicatorColor, LowThresholdIndicatorColor, showCurrentBarOpenTime, InfoTextColor, NewBarAlert, ReversalBarAlert, MaCrossAlert, UseAlertWindow, UseSound, UsePushNotifications, SoundFileBull, SoundFileBear, cis.MA1on, cis.MA1period, cis.MA1method, cis.MA1applyTo, cis.MA1shift, cis.MA2on, cis.MA2period, cis.MA2method, cis.MA2applyTo, cis.MA2shift, cis.MA3on, cis.MA3period, cis.MA3method, cis.MA3applyTo, cis.MA3shift, cis.ShowChannel, "", cis.DonchianPeriod, cis.BBapplyTo, cis.BollingerBandsPeriod, cis.BollingerBandsDeviations, cis.SuperTrendPeriod, cis.SuperTrendMultiplier, "", DisplayAsBarChart, ShiftObj, UsedInEA); if(rangeBarsHandle == INVALID_HANDLE) { Print("RangeBar indicator init failed on error ",GetLastError()); } else { Print("RangeBar indicator init OK"); } return rangeBarsHandle; } // // Function for reloading the Median Renko indicator if needed // bool RangeBars::Reload() { if(rangeBarSettings.Changed()) { 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 handle released"); else Print("Failed to release RangeBar indicator handle"); } } // // Function for detecting a new Renko bar // bool RangeBars::IsNewBar() { MqlRates currentBar[1]; static datetime prevBarTime; 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