//+------------------------------------------------------------------+ //| RangeBars.mqh ver:1.47.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 "Market\\Range Bars Charting" #define RANGEBAR_MA1 0 #define RANGEBAR_MA2 1 #define RANGEBAR_CHANNEL_HIGH 2 #define RANGEBAR_CHANNEL_MID 3 #define RANGEBAR_CHANNEL_LOW 4 #define RANGEBAR_OPEN 5 #define RANGEBAR_HIGH 6 #define RANGEBAR_LOW 7 #define RANGEBAR_CLOSE 8 #define RANGEBAR_COLOR_CODE 9 #define RANGEBAR_BAR_OPEN_TIME 10 #define RANGEBAR_TICK_VOLUME 11 #include class RangeBars { private: RangeBarSettings * rangeBarSettings; // // Median renko indicator handle // int rangeBarsHandle; string rangeBarsSymbol; public: RangeBars(); RangeBars(string symbol); ~RangeBars(void); int Init(); void Deinit(); bool Reload(); int GetHandle(void) { return rangeBarsHandle; }; bool GetMqlRates(MqlRates &ratesInfoArray[], int start, int count); int GetOLHCForIndicatorCalc(double &o[],double &l[],double &h[],double &c[], int start, int count); int GetOLHCAndApplPriceForIndicatorCalc(double &o[],double &l[],double &h[],double &c[],double &price[],ENUM_APPLIED_PRICE applied_price, int start, int count); double CalcAppliedPrice(const MqlRates &_rates, ENUM_APPLIED_PRICE applied_price); double CalcAppliedPrice(const double &o,const double &l,const double &h,const double &c,ENUM_APPLIED_PRICE applied_price); bool GetMA1(double &MA[], int start, int count); bool GetMA2(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); }; RangeBars::RangeBars(void) { rangeBarSettings = new RangeBarSettings(); rangeBarsHandle = INVALID_HANDLE; rangeBarsSymbol = _Symbol; } RangeBars::RangeBars(string symbol) { rangeBarSettings = new RangeBarSettings(); rangeBarsHandle = INVALID_HANDLE; rangeBarsSymbol = symbol; } 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(!rangeBarSettings.Load()) { if(rangeBarsHandle != INVALID_HANDLE) { // could not read new settings - keep old settings return rangeBarsHandle; } else { Print("Failed to load indicator settings."); Alert("You need to put the Median Renko indicator on your chart first!"); return INVALID_HANDLE; } } if(rangeBarsHandle != INVALID_HANDLE) Deinit(); } 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.Get(); //RangeBarSettings.Debug(); rangeBarsHandle = iCustom(this.rangeBarsSymbol,PERIOD_M1,RANGEBAR_INDICATOR_NAME, s.barSizeInTicks, s._startFromDateTime, s.resetOpenOnNewTradingDay, showNextBarLevels, HighThresholdIndicatorColor, LowThresholdIndicatorColor, showCurrentBarOpenTime, InfoTextColor, UseSoundSignalOnNewBar, OnlySignalReversalBars, UseAlertWindow, SendPushNotifications, SoundFileBull, SoundFileBear, s.MA1on, s.MA1period, s.MA1method, s.MA1applyTo, s.MA1shift, s.MA2on, s.MA2period, s.MA2method, s.MA2applyTo, s.MA2shift, s.ShowChannel, "", s.DonchianPeriod, s.BBapplyTo, s.BollingerBandsPeriod, s.BollingerBandsDeviations, s.SuperTrendPeriod, s.SuperTrendMultiplier, "", UsedInEA); if(rangeBarsHandle == INVALID_HANDLE) { Print("RangeBars indicator init failed on error ",GetLastError()); } else { Print("RangeBars 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(IndicatorRelease(rangeBarsHandle)) Print("RangeBars indicator handle released"); else Print("Failed to release RangeBars indicator handle"); } // // Function for detecting a new Renko bar // bool RangeBars::IsNewBar() { MqlRates currentRenko[1]; static MqlRates prevRenko; GetMqlRates(currentRenko,1,1); if((prevRenko.open != currentRenko[0].open) || (prevRenko.high != currentRenko[0].high) || (prevRenko.low != currentRenko[0].low) || (prevRenko.close != currentRenko[0].close)) { prevRenko.open = currentRenko[0].open; prevRenko.high = currentRenko[0].high; prevRenko.low = currentRenko[0].low; prevRenko.close = currentRenko[0].close; 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[],time[],tick_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(time,count) == -1) return false; if(ArrayResize(tick_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_TICK_VOLUME,start,count,tick_volume) == -1) return false; if(ArrayResize(ratesInfoArray,count) == -1) return false; int tempOffset = count-1; for(int i=0; i