diff --git a/Experts/RangeBarsExample.mq5 b/Experts/RangeBars_ExampleEA.mq5 similarity index 68% rename from Experts/RangeBarsExample.mq5 rename to Experts/RangeBars_ExampleEA.mq5 index 8922d39..02222d3 100644 --- a/Experts/RangeBarsExample.mq5 +++ b/Experts/RangeBars_ExampleEA.mq5 @@ -1,6 +1,6 @@ #property copyright "Copyright 2017, AZ-iNVEST" #property link "http://www.az-invest.eu" -#property version "2.03" +#property version "2.05" #property description "Example EA showing the way to use the RangeBars class defined in RangeBars.mqh" // @@ -11,14 +11,13 @@ // the RangeBars indicator attached. // -#define SHOW_INDICATOR_INPUTS +//#define SHOW_INDICATOR_INPUTS // -// You need to include the rangeBars.mqh header file +// You need to include the RangeBars.mqh header file // -#include - +#include // // To use the RangeBars indicator in your EA you need do instantiate the indicator class (RangeBars) // and call the Init() method in your EA's OnInit() function. @@ -64,7 +63,7 @@ void OnDeinit(const int reason) } // -// At this point you may use the rangebars data fetching methods in your EA. +// At this point you may use the range bars data fetching methods in your EA. // Brief demonstration presented below in the OnTick() function: // @@ -107,7 +106,8 @@ void OnTick() // MA1[2] contains the 1st moving average value for the 2nd bar to the left from the latest (uncompleted) bar // MA1[3]..MA1[n] do not exist since we retrieved the values for 3 bars (defined by "numnberOfBars") // - // The values for the 2nd moving average are stored in MA2[] and are accessed identically to values of MA1[] (shown above) + // The values for the 2nd and 3rd moving average are stored in MA2[] & MA3[] + // and are accessed identically to values of MA1[] (shown above) } // @@ -117,25 +117,68 @@ void OnTick() // MqlRates RangeBarRatesInfoArray[]; // This array will store the MqlRates data for range bars - startAtBar = 1; // get values starting from the last completed bar. - numberOfBars = 2; // gat a total of 2 MqlRates values (for 2 bars starting from bar 1 (last completed)) + startAtBar = 0; // get values starting from the last completed bar. + numberOfBars = 3; // gat a total of 3 MqlRates values (for 3 bars starting from bar 0 (current uncompleted)) if(rangeBars.GetMqlRates(RangeBarRatesInfoArray,startAtBar,numberOfBars)) - { + { // - // Check if a range bars reversal bar has formed + // Check if a range bar reversal bar has formed // + + string infoString; - if((RangeBarRatesInfoArray[0].open < RangeBarRatesInfoArray[0].close) && - (RangeBarRatesInfoArray[1].open > RangeBarRatesInfoArray[1].close)) + if((RangeBarRatesInfoArray[1].open < RangeBarRatesInfoArray[1].close) && + (RangeBarRatesInfoArray[2].open > RangeBarRatesInfoArray[2].close)) { // bullish reversal + infoString = "Previous bar formed bullish reversal"; } - else if((RangeBarRatesInfoArray[0].open > RangeBarRatesInfoArray[0].close) && - (RangeBarRatesInfoArray[1].open < RangeBarRatesInfoArray[1].close)) + else if((RangeBarRatesInfoArray[1].open > RangeBarRatesInfoArray[1].close) && + (RangeBarRatesInfoArray[2].open < RangeBarRatesInfoArray[2].close)) { // bearish reversal + infoString = "Previous bar formed bearish reversal"; } + else + { + infoString = ""; + } + + // + // Output some data to chart + // + + Comment("\nNew bar opened on "+(string)RangeBarRatesInfoArray[0].time+ + "\nPrevious bar OPEN price:"+DoubleToString(RangeBarRatesInfoArray[1].open,_Digits)+", bar opened on "+(string)RangeBarRatesInfoArray[1].time+ + "\n"+infoString+ + "\n"); + } + + // + // All charts that contain real volume information (i.e. stocks, futures, ...) + // also contain the brekdown of volume into BUY, SELL and BUY/SELL volume. + // This data is accessed using the + // GetBuySellVolumeBreakdown(long &buy[], long &sell[], long &buySell[], int start, int count) + // method. Example below: + + double buyVolume[]; // This array will store the values of the BUY volume + double sellVolume[]; // This array will store the values of the SELL volume + double buySellVolume[]; // This array will store the values of the BUY/SELL volume + + // When you add BUY, SELL and BUY/SELL volume numbers for a bar they will be equal + // to the Real Volume number that can be accessed using the + // GetMqlRates(MqlRates &ratesInfoArray[], int start, int count) + // metod described above. + + startAtBar = 1; // get values starting from the last completed bar. + numberOfBars = 2; // gat a total of 2 values (for 2 bars starting from bar 1 (last completed)) + + if(rangeBars.GetBuySellVolumeBreakdown(buyVolume,sellVolume,buySellVolume,startAtBar,numberOfBars)) + { + // + // Apply your real volume analysis logic here... + // } // @@ -147,7 +190,8 @@ void OnTick() double HighArray[]; // This array will store the values of the high band double MidArray[]; // This array will store the values of the middle band double LowArray[]; // This array will store the values of the low band - startAtBar = 1; // get values starting from the last completed bar. + + startAtBar = 1; // get values starting from the last completed bar. numberOfBars = 20; // gat a total of 20 values (for 20 bars starting from bar 1 (last completed)) if(rangeBars.GetDonchian(HighArray,MidArray,LowArray,startAtBar,numberOfBars)) @@ -167,7 +211,7 @@ void OnTick() // MidArray[] array will store the values of the middle band // LowArray[] array will store the values of the low band - startAtBar = 1; // get values starting from the last completed bar. + startAtBar = 1; // get values starting from the last completed bar. numberOfBars = 10; // gat a total of 10 values (for 10 bars starting from bar 1 (last completed)) if(rangeBars.GetBollingerBands(HighArray,MidArray,LowArray,startAtBar,numberOfBars)) @@ -187,7 +231,7 @@ void OnTick() // MidArray[] array will store the values of the SuperTrend value // LowArray[] array will store the values of the low SuperTrend line - startAtBar = 1; // get values starting from the last completed bar. + startAtBar = 1; // get values starting from the last completed bar. numberOfBars = 3; // gat a total of 3 values (for 3 bars starting from bar 1 (last completed)) if(rangeBars.GetSuperTrend(HighArray,MidArray,LowArray,startAtBar,numberOfBars)) diff --git a/Experts/RangeBars_ExampleEA2.mq5 b/Experts/RangeBars_ExampleEA2.mq5 new file mode 100644 index 0000000..012476d --- /dev/null +++ b/Experts/RangeBars_ExampleEA2.mq5 @@ -0,0 +1,233 @@ +#property copyright "Copyright 2017, AZ-iNVEST" +#property link "http://www.az-invest.eu" +#property version "1.00" +#property description "Example EA: Trading based on RangeBars SuperTrend signals." +#property description "One trade at a time. Each trade has TP & SL" + +// +// Helper functions for placing market orders. +// + +#include + +// +// Inputs +// + +input double InpLotSize = 0.1; +input int InpSLPoints = 200; +input int InpTPPoints = 600; + +input ulong InpMagicNumber=5150; +input ulong InpDeviationPoints = 0; +input int InpNumberOfRetries = 50; +input int InpBusyTimeout_ms = 1000; +input int InpRequoteTimeout_ms = 250; + +// +// Globa variables +// + +ENUM_POSITION_TYPE Signal; +ulong currentTicket; + +// +// SHOW_INDICATOR_INPUTS *NEEDS* to be defined, if the EA needs to be *tested in MT5's backtester* +// ------------------------------------------------------------------------------------------------- +// Using '#define SHOW_INDICATOR_INPUTS' will show the RangeBars indicator's inputs +// NOT using the '#define SHOW_INDICATOR_INPUTS' statement will read the settigns a chart with +// the RangeBars indicator attached. +// + +//#define SHOW_INDICATOR_INPUTS + +// +// You need to include the RangeBars.mqh header file +// + +#include +// +// To use the RangeBars indicator in your EA you need do instantiate the indicator class (RangeBars) +// and call the Init() method in your EA's OnInit() function. +// Don't forget to release the indicator when you're done by calling the Deinit() method. +// Example shown in OnInit & OnDeinit functions below: +// + +RangeBars * rangeBars; +CMarketOrder * marketOrder; + +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() +{ + rangeBars = new RangeBars(); + if(rangeBars == NULL) + return(INIT_FAILED); + + rangeBars.Init(); + if(rangeBars.GetHandle() == INVALID_HANDLE) + return(INIT_FAILED); + + // + // Init MarketOrder class - used for placing market ortders. + // + + CMarketOrderParameters params; + { + params.m_async_mode = false; + params.m_magic = InpMagicNumber; + params.m_deviation = InpDeviationPoints; + params.m_type_filling = ORDER_FILLING_FOK; + + params.numberOfRetries = InpNumberOfRetries; + params.busyTimeout_ms = InpBusyTimeout_ms; + params.requoteTimeout_ms = InpRequoteTimeout_ms; + } + marketOrder = new CMarketOrder(params); + + return(INIT_SUCCEEDED); +} +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) +{ + if(rangeBars != NULL) + { + rangeBars.Deinit(); + delete rangeBars; + } + + // + // delete MarketOrder class + // + + if(marketOrder != NULL) + { + delete marketOrder; + } +} + +// +// At this point you may use the range bar data fetching methods in your EA. +// Brief demonstration presented below in the OnTick() function: +// + +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() +{ + // + // It is considered good trading & EA coding practice to perform calculations + // when a new bar is fully formed. + // The IsNewBar() method is used for checking if a new range bar has formed + // + + if(rangeBars.IsNewBar()) + { + + // + // Getting SuperTrend values is done using the + // GetSuperTrend(double &SuperTrendHighArray[], double &SuperTrendArray[], double &SuperTrendLowArray[], int start, int count) + // method. Example below: + // + + double HighArray[]; // This array will store the values of the high SuperTrend line + double MidArray[]; // This array will store the values of the middle SuperTrend line + double LowArray[]; // This array will store the values of the low SuperTrend line + + int startAtBar = 1; // get values starting from the last completed bar. + int numberOfBars = 2; // gat a total of 3 values (for 3 bars starting from bar 1 (last completed)) + + if(rangeBars.GetSuperTrend(HighArray,MidArray,LowArray,startAtBar,numberOfBars)) + { + // + // Read signal bar's time for optional debug log + // + + string barTime = ""; + MqlRates RangeBarRatesInfoArray[]; // This array will store the MqlRates data for range bars + if(rangeBars.GetMqlRates(RangeBarRatesInfoArray,startAtBar,numberOfBars)) + barTime = (string)RangeBarRatesInfoArray[0].time; + // + // + // + + if(SuperTrendSignal(HighArray,MidArray,LowArray,Signal,barTime)) + { + if(Signal == POSITION_TYPE_NONE) + return; + + // + // Trade signal on the SuperTrend indicator + // Open trade only if there are currntly no active trades + // + + if(!marketOrder.IsOpen(currentTicket,_Symbol,InpMagicNumber)) + { + if(Signal == POSITION_TYPE_BUY) + { + Print("BUY signal at "+barTime); // optional debug log + + if(marketOrder.Long(_Symbol,InpLotSize,InpSLPoints,InpTPPoints)) + Print("Long position opened."); + } + else if(Signal == POSITION_TYPE_SELL) + { + Print("SELL singal at "+barTime); // optional debug log + + if(marketOrder.Short(_Symbol,InpLotSize,InpSLPoints,InpTPPoints)) + Print("Short position opened."); + } + } + + + } + } + + } +} + +// +// Function determines the trade signal on the SuperTrend indicator +// + +bool SuperTrendSignal(double &H[], double &M[], double &L[], ENUM_POSITION_TYPE &signal,string time) +{ + if((H[1] == 0) && (L[1] == 0)) // no data to process + { + signal = POSITION_TYPE_NONE; + return false; + } + + // Uncomment line below for optional debug output: + //Print(time+": H[1] = "+DoubleToString(H[1],_Digits)+" L[0] = "+DoubleToString(L[0],_Digits)+" | L[1] = "+DoubleToString(L[1],_Digits)+" H[0] = "+DoubleToString(H[0],_Digits)); + + if((H[1] == M[1]) && (L[0] == M[0])) + { + // + // Super trend shifted from Low to High band => Buy Signal + // + + signal = POSITION_TYPE_BUY; + return true; + } + else if((L[1] == M[1]) && (H[0] == M[0])) + { + // + // Super trend shifted from High to Low band => Sell Signal + // + + signal = POSITION_TYPE_SELL; + return true; + } + + // + // No signal detected + // + + signal = POSITION_TYPE_NONE; + return false; +} \ No newline at end of file diff --git a/Include/AZ-INVEST/SDK/CommonSettings.mqh b/Include/AZ-INVEST/SDK/CommonSettings.mqh new file mode 100644 index 0000000..33fcdbf Binary files /dev/null and b/Include/AZ-INVEST/SDK/CommonSettings.mqh differ diff --git a/Include/AZ-INVEST/SDK/RangeBarIndicator.mqh b/Include/AZ-INVEST/SDK/RangeBarIndicator.mqh new file mode 100644 index 0000000..2f2b386 --- /dev/null +++ b/Include/AZ-INVEST/SDK/RangeBarIndicator.mqh @@ -0,0 +1,766 @@ +#property copyright "Copyright 2017, AZ-iNVEST" +#property link "http://www.az-invest.eu" +#property version "2.02" +#include + +class RangeBarIndicator +{ + private: + + RangeBars * rangeBars; + int rates_total; + int prev_calculated; + bool getVolumes; + bool getVolumeBreakdown; + bool getTime; + bool useAppliedPrice; + ENUM_APPLIED_PRICE applied_price; + + bool dataReady; + + public: + + datetime Time[]; + double Open[]; + double Low[]; + double High[]; + double Close[]; + double Price[]; + long Tick_volume[]; + long Real_volume[]; + double Buy_volume[]; + double Sell_volume[]; + double BuySell_volume[]; + bool IsNewBar; + + RangeBarIndicator(); + ~RangeBarIndicator(); + + void SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) { this.useAppliedPrice = true; this.applied_price = _applied_price; }; + void SetGetVolumesFlag() { this.getVolumes = true; }; + void SetGetVolumeBreakdownFlag() { this.getVolumeBreakdown = true; }; + void SetGetTimeFlag() { this.getTime = true; }; + + bool OnCalculate(const int rates_total,const int prev_calculated, const datetime &_Time[]); + int GetPrevCalculated() { return prev_calculated; }; + void BufferShiftLeft(double &buffer[]); + + private: + + bool CheckStatus(); + bool NeedsReload(); + int GetOLHC(int start, int count); + int GetOLHCForIndicatorCalc(double &o[],double &l[],double &h[],double &c[],datetime &t[],long &tickVolume[],long &realVolume[], double &buyVolume[], double &sellVolume[], double &buySellVolume[], int start, int count); + int GetOLHCAndApplPriceForIndicatorCalc(double &o[],double &l[],double &h[],double &c[],datetime &t[],long &tickVolume[],long &realVolume[], double &buyVolume[], double &sellVolume[], double &buySellVolume[], double &price[],ENUM_APPLIED_PRICE applied_price, int start, int count); + void OLHCShiftRight(); + void OLHCResize(); + + bool Canvas_IsNewBar(const datetime &_Time[]); + bool Canvas_IsRatesTotalChanged(int ratesTotalNow); + int Canvas_RatesTotalChangedBy(int ratesTotalNow); + + 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); + + ENUM_TIMEFRAMES TFMigrate(int tf); + datetime iTime(string symbol,int tf,int index); +}; + +RangeBarIndicator::RangeBarIndicator(void) +{ + rangeBars = new RangeBars(); + if(rangeBars != NULL) + rangeBars.Init(); + + useAppliedPrice = false; + getVolumes = false; + getTime = false; + + dataReady = false; +} + +RangeBarIndicator::~RangeBarIndicator(void) +{ + if(rangeBars != NULL) + { + rangeBars.Deinit(); + delete rangeBars; + } +} + +bool RangeBarIndicator::CheckStatus(void) +{ + int handle = rangeBars.GetHandle(); + if(handle == INVALID_HANDLE) + return false; + + return true; +} + +bool RangeBarIndicator::NeedsReload(void) +{ + if(rangeBars.Reload()) + { + Print("Chart settings changed - reloading indicator with new settings"); + return true; + } + + return false; +} + +bool RangeBarIndicator::OnCalculate(const int _rates_total,const int _prev_calculated, const datetime &_Time[]) +{ + static bool firstRun = true; + + if(firstRun) + { + Canvas_IsNewBar(_Time); + Canvas_RatesTotalChangedBy(_rates_total); + IsNewBar = rangeBars.IsNewBar(); + + firstRun = false; + } + + if(!CheckStatus()) + { + if(rangeBars != NULL) + delete rangeBars; + + rangeBars = new RangeBars(); + if(rangeBars != NULL) + rangeBars.Init(); + + return false; + } + + ArraySetAsSeries(this.Time,false); + ArraySetAsSeries(this.Open,false); + ArraySetAsSeries(this.High,false); + ArraySetAsSeries(this.Low,false); + ArraySetAsSeries(this.Close,false); + ArraySetAsSeries(this.Price,false); + ArraySetAsSeries(this.Tick_volume,false); + ArraySetAsSeries(this.Real_volume,false); + ArraySetAsSeries(this.Buy_volume,false); + ArraySetAsSeries(this.Sell_volume,false); + ArraySetAsSeries(this.BuySell_volume,false); + + bool needsReload = (NeedsReload() || (!this.dataReady)); + + if(needsReload) + { + GetOLHC(0,_rates_total); + this.prev_calculated = 0; + return false; + } + + /* + if(needsReload || IsNewBar || canvasIsNewTime || (change != 0)) + { + Print("reload="+needsReload+", renkoisnewbar="+IsNewBar+", canvasIsNewTime="+canvasIsNewTime+", change="+change); + GetOLHC(0,_rates_total); + this.prev_calculated = ArraySize(this.Open); + return true; + } + */ + bool change = Canvas_RatesTotalChangedBy(_rates_total); + if(change != 0) + { + #ifdef DISPLAY_DEBUG_MSG + Print("rates total changed to:"+_rates_total); + #endif + if(change == 1) + { + #ifdef DISPLAY_DEBUG_MSG + Print("changed by 1 => Resize called"); + #endif + OLHCResize(); + } + else + { + #ifdef DISPLAY_DEBUG_MSG + Print("changed by "+change+" => getting ALL"); + #endif + GetOLHC(0,_rates_total); + } + this.prev_calculated = 0;//_prev_calculated; + Canvas_IsNewBar(_Time); + return true; + } + else if(Canvas_IsNewBar(_Time)) + { + #ifdef DISPLAY_DEBUG_MSG + Print("Got Canvas_IsNewBar"); + #endif + + if(ArraySize(this.Open) == 0) + { + GetOLHC(0,_rates_total); + this.prev_calculated = 0; + return true; ///////// false + } + + OLHCShiftRight(); + this.prev_calculated = _prev_calculated; + return true; + } + + IsNewBar = rangeBars.IsNewBar(); + if(IsNewBar) + { + GetOLHC(0,_rates_total); + this.prev_calculated = 0; + return true; + } + + + // + // Only recalculate last bar + // + + GetOLHC(0,0); + this.prev_calculated = _prev_calculated; + + return true; +} + +int RangeBarIndicator::GetOLHC(int start, int count) +{ + if((start == 0) && (count == 0) && dataReady) + { + MqlRates tempRates[1]; + double b[1],s[1],bs[1]; + + int last = ArraySize(Open)-1; + + if(last < 0) + return 0; + + rangeBars.GetMqlRates(tempRates,0,1); + this.Open[last] = tempRates[0].open; + this.Low[last] = tempRates[0].low; + this.High[last] = tempRates[0].high; + this.Close[last] = tempRates[0].close; + if(getTime) + { + this.Time[last] = tempRates[0].time; + } + if(getVolumes) + { + this.Tick_volume[last] = tempRates[0].tick_volume; + this.Real_volume[last] = tempRates[0].real_volume; + } + if(useAppliedPrice) + { + this.Price[last] = CalcAppliedPrice(tempRates[0],this.applied_price); + } + if(getVolumeBreakdown) + { + rangeBars.GetBuySellVolumeBreakdown(b,s,bs,0,1); + this.Buy_volume[last] = b[0]; + this.Sell_volume[last] = s[0]; + this.BuySell_volume[last] = bs[0]; + } + + return 1; + } + else + { + return GetOLHCAndApplPriceForIndicatorCalc(this.Open,this.Low,this.High,this.Close,this.Time,this.Tick_volume,this.Real_volume, this.Buy_volume, this.Sell_volume, this.BuySell_volume, this.Price,this.applied_price,0,count); + } +} + + +void RangeBarIndicator::OLHCShiftRight() +{ + int count = ArraySize(this.Open); + + if(count <= 0) + return; + + count--; + + for(int i=count; i>0; i--) + { + this.Open[i] = this.Open[i-1]; + this.High[i] = this.High[i-1]; + this.Low[i] = this.Low[i-1]; + this.Close[i] = this.Close[i-1]; + if(getTime) + this.Time[i] = this.Time[i-1]; + if(useAppliedPrice) + this.Price[i] = this.Price[i-1]; + if(getVolumes) + { + this.Tick_volume[i] = this.Tick_volume[i-1]; + this.Real_volume[i] = this.Real_volume[i-1]; + } + if(getVolumeBreakdown) + { + this.Buy_volume[i] = this.Buy_volume[i-1]; + this.Sell_volume[i] = this.Sell_volume[i-1]; + this.BuySell_volume[i] = this.BuySell_volume[i-1]; + } + } + + this.Open[0] = 0.0; + this.High[0] = 0.0; + this.Low[0] = 0.0; + this.Close[0] = 0.0; + + if(getTime) + this.Time[0] = 0; + if(useAppliedPrice) + this.Price[0] = 0.0; + if(getVolumes) + { + this.Tick_volume[0] = 0.0; + this.Real_volume[0] = 0.0; + } + if(getVolumeBreakdown) + { + this.Buy_volume[0] = 0; + this.Sell_volume[0] = 0; + this.BuySell_volume[0] = 0; + } +} + +void RangeBarIndicator::OLHCResize() +{ + int count = ArraySize(this.Open); + + if(count <= 0) + return; + + ArrayResize(this.Open,count+1); + ArrayResize(this.Low,count+1); + ArrayResize(this.High,count+1); + ArrayResize(this.Close,count+1); + + if(getTime) + ArrayResize(this.Time,count+1); + if(useAppliedPrice) + ArrayResize(this.Price,count+1); + if(getVolumes) + { + ArrayResize(this.Tick_volume,count+1); + ArrayResize(this.Real_volume,count+1); + } + if(getVolumeBreakdown) + { + ArrayResize(this.Buy_volume,count+1); + ArrayResize(this.Sell_volume,count+1); + ArrayResize(this.BuySell_volume,count+1); + } + + OLHCShiftRight(); +} + +bool RangeBarIndicator::Canvas_IsNewBar(const datetime &_Time[]) +{ + ArraySetAsSeries(_Time,true); + datetime now = _Time[0]; + ArraySetAsSeries(_Time,false); + + static datetime prevTime = 0; + + if(prevTime != now) + { + prevTime = now; + return true; + } + + return false; +} + +bool RangeBarIndicator::Canvas_IsRatesTotalChanged(int ratesTotalNow) +{ + static int prevRatesTotal = 0; + + if(prevRatesTotal == 0) + prevRatesTotal = ratesTotalNow; + + if(prevRatesTotal != ratesTotalNow) + { + prevRatesTotal = ratesTotalNow; + return true; + } + + return false; +} + +int RangeBarIndicator::Canvas_RatesTotalChangedBy(int ratesTotalNow) +{ + int changedBy = 0; + static int prevRatesTotal = 0; + + if(prevRatesTotal == 0) + prevRatesTotal = ratesTotalNow; + + if(prevRatesTotal != ratesTotalNow) + { + changedBy = (ratesTotalNow - prevRatesTotal); + prevRatesTotal = ratesTotalNow; + return changedBy; + } + + return 0; +} + +int RangeBarIndicator::GetOLHCForIndicatorCalc(double &o[],double &l[],double &h[],double &c[],datetime &t[], long &tickVolume[],long &realVolume[], double &buyVolume[], double &sellVolume[], double &buySellVolume[], int start, int count) +{ + int handle; + double temp[]; + + if(ArrayResize(temp,count) == -1) + return -1; + if(ArrayResize(o,count) == -1) + return -1; + if(ArrayResize(l,count) == -1) + return -1; + if(ArrayResize(h,count) == -1) + return -1; + if(ArrayResize(c,count) == -1) + return -1; + + if(getVolumes) + { + if(ArrayResize(tickVolume,count) == -1) + return -1; + if(ArrayResize(realVolume,count) == -1) + return -1; + } + + if(getTime) + { + if(ArrayResize(t,count) == -1) + return -1; + } + + if(getVolumeBreakdown) + { + if(ArrayResize(buyVolume,count) == -1) + return -1; + if(ArrayResize(sellVolume,count) == -1) + return -1; + if(ArrayResize(buySellVolume,count) == -1) + return -1; + } + + handle = rangeBars.GetHandle(); + if(handle == INVALID_HANDLE) + return -1; + int _count = CopyBuffer(handle,RANGEBAR_OPEN,start,count,temp); + if(_count == -1) + { + int errorCode = GetLastError(); + if(errorCode == ERR_INDICATOR_DATA_NOT_FOUND) + { + Print("Waiting for buffers ready flag"); + return -2; + } + else + return -1; + } + + if(_count < count) + { + #ifdef DISPLAY_DEBUG_MSG + Print("Fixing offset (req:"+count+" res:"+_count+")"); + #endif + + ArrayInitialize(o,0x0); + ArrayInitialize(l,0x0); + ArrayInitialize(h,0x0); + ArrayInitialize(c,0x0); + if(getTime) + ArrayInitialize(t,0x0); + if(getVolumes) + { + ArrayInitialize(tickVolume,0x0); + ArrayInitialize(realVolume,0x0); + } + if(getVolumeBreakdown) + { + ArrayInitialize(buyVolume,0x0); + ArrayInitialize(sellVolume,0x0); + ArrayInitialize(buySellVolume,0x0); + } + // less data - indicator requres more + + ArrayCopy(o,temp,(count-_count),0); + + if(CopyBuffer(handle,RANGEBAR_LOW,start,_count,temp) == -1) + return -1; + ArrayCopy(l,temp,(count-_count),0); + + if(CopyBuffer(handle,RANGEBAR_HIGH,start,_count,temp) == -1) + return -1; + ArrayCopy(h,temp,(count-_count),0); + + if(CopyBuffer(handle,RANGEBAR_CLOSE,start,_count,temp) == -1) + return -1; + ArrayCopy(c,temp,(count-_count),0); + + if(getTime) + { + if(CopyBuffer(handle,RANGEBAR_BAR_OPEN_TIME,start,_count,temp) == -1) + return -1; + ArrayCopy(t,temp,(count-_count),0); + } + + if(getVolumes) + { + if(CopyBuffer(handle,RANGEBAR_TICK_VOLUME,start,_count,temp) == -1) + return -1; + ArrayCopy(tickVolume,temp,(count-_count),0); + + if(CopyBuffer(handle,RANGEBAR_REAL_VOLUME,start,_count,temp) == -1) + return -1; + ArrayCopy(realVolume,temp,(count-_count),0); + } + +#ifdef P_RANGEBAR_BR + #ifdef P_RANGEBAR_BR_PRO + if(getVolumeBreakdown) + { + if(CopyBuffer(handle,RANGEBAR_BUY_VOLUME,start,_count,temp) == -1) + return -1; + ArrayCopy(buyVolume,temp,(count-_count),0); + + if(CopyBuffer(handle,RANGEBAR_SELL_VOLUME,start,_count,temp) == -1) + return -1; + ArrayCopy(sellVolume,temp,(count-_count),0); + + if(CopyBuffer(handle,RANGEBAR_BUYSELL_VOLUME,start,_count,temp) == -1) + return -1; + ArrayCopy(buySellVolume,temp,(count-_count),0); + } + #else + #endif +#else + if(getVolumeBreakdown) + { + if(CopyBuffer(handle,RANGEBAR_BUY_VOLUME,start,_count,temp) == -1) + return -1; + ArrayCopy(buyVolume,temp,(count-_count),0); + + if(CopyBuffer(handle,RANGEBAR_SELL_VOLUME,start,_count,temp) == -1) + return -1; + ArrayCopy(sellVolume,temp,(count-_count),0); + + if(CopyBuffer(handle,RANGEBAR_BUYSELL_VOLUME,start,_count,temp) == -1) + return -1; + ArrayCopy(buySellVolume,temp,(count-_count),0); + } +#endif + + } + else + { + if(CopyBuffer(handle,RANGEBAR_OPEN,start,count,o) == -1) + return -1; + if(CopyBuffer(handle,RANGEBAR_LOW,start,count,l) == -1) + return -1; + if(CopyBuffer(handle,RANGEBAR_HIGH,start,count,h) == -1) + return -1; + if(CopyBuffer(handle,RANGEBAR_CLOSE,start,count,c) == -1) + return -1; + + if(getTime) + { + if(CopyBuffer(handle,RANGEBAR_BAR_OPEN_TIME,start,count,temp) == -1) + return -1; + ArrayCopy(t,temp); + } + + if(getVolumes) + { + if(CopyBuffer(handle,RANGEBAR_TICK_VOLUME,start,count,temp) == -1) + return -1; + ArrayCopy(tickVolume,temp); + if(CopyBuffer(handle,RANGEBAR_REAL_VOLUME,start,count,temp) == -1) + return -1; + ArrayCopy(realVolume,temp); + } + +#ifdef P_RANGEBAR_BR + #ifdef P_RANGEBAR_BR_PRO + if(getVolumeBreakdown) + { + if(CopyBuffer(handle,RANGEBAR_BUY_VOLUME,start,count,temp) == -1) + return -1; + ArrayCopy(buyVolume,temp); + + if(CopyBuffer(handle,RANGEBAR_SELL_VOLUME,start,count,temp) == -1) + return -1; + ArrayCopy(sellVolume,temp); + + if(CopyBuffer(handle,RANGEBAR_BUYSELL_VOLUME,start,count,temp) == -1) + return -1; + ArrayCopy(buySellVolume,temp); + } + #else + #endif +#else + if(getVolumeBreakdown) + { + if(CopyBuffer(handle,RANGEBAR_BUY_VOLUME,start,count,temp) == -1) + return -1; + ArrayCopy(buyVolume,temp); + + if(CopyBuffer(handle,RANGEBAR_SELL_VOLUME,start,count,temp) == -1) + return -1; + ArrayCopy(sellVolume,temp); + + if(CopyBuffer(handle,RANGEBAR_BUYSELL_VOLUME,start,count,temp) == -1) + return -1; + ArrayCopy(buySellVolume,temp); + } +#endif + } + + return count; +} + +// +// Get "count" Renko MqlRates into "ratesInfoArray[]" array starting from "start" bar +// + +int RangeBarIndicator::GetOLHCAndApplPriceForIndicatorCalc(double &o[],double &l[],double &h[],double &c[],datetime &t[],long &tickVolume[],long &realVolume[],double &buyVolume[], double &sellVolume[], double &buySellVolume[],double &price[],ENUM_APPLIED_PRICE _applied_price, int start, int count) +{ + dataReady = true; + + int _count = GetOLHCForIndicatorCalc(o,l,h,c,t,tickVolume,realVolume,buyVolume,sellVolume,buySellVolume,start,count); + if(_count < 0) + { + dataReady = false; + return _count; + } + if(applied_price == PRICE_CLOSE) + { + return ArrayCopy(price,c); + } + else if(applied_price == PRICE_OPEN) + { + return ArrayCopy(price,o); + } + else if(applied_price == PRICE_HIGH) + { + return ArrayCopy(price,h); + } + else if(applied_price == PRICE_LOW) + { + return ArrayCopy(price,l); + } + else + { + if(ArrayResize(price,_count) == -1) + return -1; + + for(int i=0; i<_count; i++) + { + price[i] = CalcAppliedPrice(o[i],l[i],h[i],c[i],_applied_price); + } + } + + return _count; +} + +ENUM_TIMEFRAMES RangeBarIndicator::TFMigrate(int tf) + { + switch(tf) + { + case 0: return(PERIOD_CURRENT); + case 1: return(PERIOD_M1); + case 5: return(PERIOD_M5); + case 15: return(PERIOD_M15); + case 30: return(PERIOD_M30); + case 60: return(PERIOD_H1); + case 240: return(PERIOD_H4); + case 1440: return(PERIOD_D1); + case 10080: return(PERIOD_W1); + case 43200: return(PERIOD_MN1); + + case 2: return(PERIOD_M2); + case 3: return(PERIOD_M3); + case 4: return(PERIOD_M4); + case 6: return(PERIOD_M6); + case 10: return(PERIOD_M10); + case 12: return(PERIOD_M12); + case 16385: return(PERIOD_H1); + case 16386: return(PERIOD_H2); + case 16387: return(PERIOD_H3); + case 16388: return(PERIOD_H4); + case 16390: return(PERIOD_H6); + case 16392: return(PERIOD_H8); + case 16396: return(PERIOD_H12); + case 16408: return(PERIOD_D1); + case 32769: return(PERIOD_W1); + case 49153: return(PERIOD_MN1); + default: return(PERIOD_CURRENT); + } + } + +datetime RangeBarIndicator::iTime(string symbol,int tf,int index) +{ + if(index < 0) return(-1); + ENUM_TIMEFRAMES timeframe=TFMigrate(tf); + datetime Arr[]; + if(CopyTime(symbol, timeframe, index, 1, Arr)>0) + return(Arr[0]); + else return(-1); +} + +// +// Function used for calculating the Apllied Price based on Renko OLHC values +// + +double RangeBarIndicator::CalcAppliedPrice(const MqlRates &_rates, ENUM_APPLIED_PRICE _applied_price) +{ + if(_applied_price == PRICE_CLOSE) + return _rates.close; + else if (_applied_price == PRICE_OPEN) + return _rates.open; + else if (_applied_price == PRICE_HIGH) + return _rates.high; + else if (_applied_price == PRICE_LOW) + return _rates.low; + else if (_applied_price == PRICE_MEDIAN) + return (_rates.high + _rates.low) / 2; + else if (_applied_price == PRICE_TYPICAL) + return (_rates.high + _rates.low + _rates.close) / 3; + else if (_applied_price == PRICE_WEIGHTED) + return (_rates.high + _rates.low + _rates.close + _rates.close) / 4; + + return 0.0; +} + +double RangeBarIndicator::CalcAppliedPrice(const double &o,const double &l,const double &h,const double &c, ENUM_APPLIED_PRICE _applied_price) +{ + if(_applied_price == PRICE_CLOSE) + return c; + else if (_applied_price == PRICE_OPEN) + return o; + else if (_applied_price == PRICE_HIGH) + return h; + else if (_applied_price == PRICE_LOW) + return l; + else if (_applied_price == PRICE_MEDIAN) + return (h + l) / 2; + else if (_applied_price == PRICE_TYPICAL) + return (h + l + c) / 3; + else if (_applied_price == PRICE_WEIGHTED) + return (h + l + c +c) / 4; + + return 0.0; +} + +void RangeBarIndicator::BufferShiftLeft(double &buffer[]) +{ + int size = ArraySize(buffer); + + for(int i=1; i +#define CUSTOM_CHART_NAME "Range Bars" + +#ifdef SHOW_INDICATOR_INPUTS + +input int barSizeInTicks = 100; // Range bar size (in points) +input ENUM_BOOL atrEnabled = false; // Enable ATR based bar size calculation + ENUM_TIMEFRAMES atrTimeFrame = PERIOD_D1; // Use ATR period +input int atrPeriod = 14; // ATR period +input int atrPercentage = 10; // Use percentage of ATR + ENUM_BOOL useRealVolume = false; // Use real volume ( false for FX ) + ENUM_TICK_PRICE_TYPE plotPrice = tickBid; // Build chart using +input int showNumberOfDays = 14; // Show history for number of days +input ENUM_BOOL resetOpenOnNewTradingDay = true; // Synchronize first bar's open on new day +input double TopBottomPaddingPercentage = 0.30; // Use padding top/bottom (0.0 - 1.0) +input ENUM_PIVOT_POINTS showPivots = ppNone; // Show pivot levels +input ENUM_PIVOT_TYPE pivotPointCalculationType = ppHLC3; // Pivot point calculation method +input color RColor = clrDodgerBlue; // Resistance line color +input color PColor = clrGold; // Pivot line color +input color SColor = clrFireBrick; // Support line color +input color PDHColor = clrHotPink; // Previous day's high +input color PDLColor = clrLightSkyBlue; // Previous day's low +input color PDCColor = clrGainsboro; // Previous day's close +input ENUM_BOOL showNextBarLevels = true; // Show current bar's close projections +input color HighThresholdIndicatorColor = clrLime; // Bullish bar projection color +input color LowThresholdIndicatorColor = clrRed; // Bearish bar projection color +input ENUM_BOOL showCurrentBarOpenTime = true; // Display chart info and current bar's open time +input color InfoTextColor = clrWhite; // Current bar's open time info color +input ENUM_BOOL UseSoundSignalOnNewBar = false; // Play sound on new bar +input ENUM_BOOL OnlySignalReversalBars = false; // Only signal reversals +input ENUM_BOOL UseAlertWindow = false; // Display Alert window with new bar info +input ENUM_BOOL SendPushNotifications = false; // Send new bar info push notification to smartphone +input string SoundFileBull = "news.wav"; // Use sound file for bullish bar close +input string SoundFileBear = "timeout.wav"; // Use sound file for bearish bar close +input ENUM_BOOL MA1on = false; // Show first MA +input int MA1period = 20; // 1st MA period +input ENUM_MA_METHOD_EXT MA1method = _MODE_SMA; // 1st MA method +input ENUM_APPLIED_PRICE MA1applyTo = PRICE_CLOSE; // 1st MA apply to +input int MA1shift = 0; // 1st MA shift +input ENUM_BOOL MA2on = false; // Show second MA +input int MA2period = 50; // 2nd MA period +input ENUM_MA_METHOD_EXT MA2method = _MODE_EMA; // 2nd MA method +input ENUM_APPLIED_PRICE MA2applyTo = PRICE_CLOSE; // 2nd MA apply to +input int MA2shift = 0; // 2nd MA shift +input ENUM_BOOL MA3on = false; // Show third MA +input int MA3period = 20; // 3rd MA period +input ENUM_MA_METHOD_EXT MA3method = _VWAP_TICKVOL; // 3rd MA method +input ENUM_APPLIED_PRICE MA3applyTo = PRICE_CLOSE; // 3rd MA apply to +input int MA3shift = 0; // 3rd MA shift +input ENUM_CHANNEL_TYPE ShowChannel = None; // Show Channel +input string Channel_Settings = "-------------------"; // Channel settings +input int DonchianPeriod = 20; // Donchian Channel period +input ENUM_APPLIED_PRICE BBapplyTo = PRICE_CLOSE; // Bollinger Bands apply to +input int BollingerBandsPeriod = 20; // Bollinger Bands period +input double BollingerBandsDeviations = 2.0; // Bollinger Bands deviations +input int SuperTrendPeriod = 10; // Super Trend period +input double SuperTrendMultiplier=1.7; // Super Trend multiplier +input string Misc_Settings = "-------------------"; // Misc settings +input ENUM_BOOL DisplayAsBarChart = false; // Display as bar chart +input ENUM_BOOL UsedInEA = false; // Indicator used in EA via iCustom() + +#else + + // + // This block should always be set to the following values + // + + double TopBottomPaddingPercentage = 0; + ENUM_PIVOT_POINTS showPivots = ppNone; + ENUM_PIVOT_TYPE pivotPointCalculationType = ppHLC3; + color RColor = clrNONE; + color PColor = clrNONE; + color SColor = clrNONE; + color PDHColor = clrNONE; + color PDLColor = clrNONE; + color PDCColor = clrNONE; + ENUM_BOOL showNextBarLevels = false; + color HighThresholdIndicatorColor = clrNONE; + color LowThresholdIndicatorColor = clrNONE; + ENUM_BOOL showCurrentBarOpenTime = false; + color InfoTextColor = clrNONE; + ENUM_BOOL UseSoundSignalOnNewBar = false; + ENUM_BOOL OnlySignalReversalBars = false; + ENUM_BOOL UseAlertWindow = false; + ENUM_BOOL SendPushNotifications = false; + string SoundFileBull = ""; + string SoundFileBear = ""; + ENUM_BOOL DisplayAsBarChart = true; + ENUM_BOOL UsedInEA = true; // This should always be set to TRUE for EAs & Indicators + + // + // + // + + +#endif + +struct RANGEBAR_SETTINGS +{ + int barSizeInTicks; + ENUM_BOOL atrEnabled; + ENUM_TIMEFRAMES atrTimeFrame; + int atrPeriod; + int atrPercentage; + ENUM_BOOL useRealVolume; + ENUM_TICK_PRICE_TYPE plotPrice; + int showNumberOfDays; + ENUM_BOOL resetOpenOnNewTradingDay; +}; + +class RangeBarSettings +{ + protected: + + string settingsFileName; + string chartTypeFileName; + + RANGEBAR_SETTINGS settings; + CHART_INDICATOR_SETTINGS chartIndicatorSettings; + ALERT_INFO_SETTINGS alertInfoSettings; + + public: + + RangeBarSettings(void); + ~RangeBarSettings(void); + + RANGEBAR_SETTINGS GetRangeBarSettings(void); + ALERT_INFO_SETTINGS GetAlertInfoSettings(void); + CHART_INDICATOR_SETTINGS GetChartIndicatorSettings(void); + + void Set(void); + + void Save(void); + bool Load(void); + void Delete(void); + bool Changed(void); +}; + +void RangeBarSettings::RangeBarSettings(void) +{ + this.settingsFileName = CUSTOM_CHART_NAME+(string)ChartID()+".set"; + this.chartTypeFileName = (string)ChartID()+".id"; +} + +void RangeBarSettings::~RangeBarSettings(void) +{ + +} + +void RangeBarSettings::Save(void) +{ + if(IS_TESTING || this.chartIndicatorSettings.UsedInEA) + return; + + this.Delete(); + + // + // Store indicator settings + // + + int handle = FileOpen(this.settingsFileName,FILE_SHARE_READ|FILE_WRITE|FILE_BIN); + uint result = 0; + + result += FileWriteStruct(handle,this.settings); + result += FileWriteStruct(handle,this.chartIndicatorSettings); + //FileWriteStruct(handle,this.alertInfoSettings); + FileClose(handle); + + // + // Store chart type identifier + // + + handle = FileOpen(this.chartTypeFileName,FILE_SHARE_READ|FILE_WRITE|FILE_ANSI); + FileWriteString(handle,CUSTOM_CHART_NAME); + FileClose(handle); +} + +void RangeBarSettings::Delete(void) +{ + if(IS_TESTING || this.chartIndicatorSettings.UsedInEA) + return; + + if(FileIsExist(this.settingsFileName)) + FileDelete(this.settingsFileName); +} + +bool RangeBarSettings::Load(void) +{ +#ifdef SHOW_INDICATOR_INPUTS + Set(); + return true; +#else + + if(!FileIsExist(this.settingsFileName)) + return false; + + int handle = FileOpen(this.settingsFileName,FILE_SHARE_READ|FILE_BIN); + if(handle == INVALID_HANDLE) + return false; + + if(FileReadStruct(handle,this.settings) <= 0) + { + Print("Failed loading settings(1)!"); + FileClose(handle); + return false; + } + + if(FileReadStruct(handle,this.chartIndicatorSettings) <= 0) + { + Print("Failed loading settings(2)!"); + FileClose(handle); + return false; + } + /* + if(FileReadStruct(handle,this.alertInfoSettings) <= 0) + { + Print("Failed loading settings(3)!"); + FileClose(handle); + return false; + } + */ + + FileClose(handle); + return true; + +#endif +} + +ALERT_INFO_SETTINGS RangeBarSettings::GetAlertInfoSettings(void) +{ + return this.alertInfoSettings; +} + +CHART_INDICATOR_SETTINGS RangeBarSettings::GetChartIndicatorSettings(void) +{ + return this.chartIndicatorSettings; +} + +RANGEBAR_SETTINGS RangeBarSettings::GetRangeBarSettings(void) +{ + return this.settings; +} + +void RangeBarSettings::Set(void) +{ +#ifdef SHOW_INDICATOR_INPUTS + + settings.barSizeInTicks = barSizeInTicks; + settings.atrEnabled = atrEnabled; + settings.atrTimeFrame = atrTimeFrame; + settings.atrPeriod = atrPeriod; + settings.atrPercentage = atrPercentage; + settings.useRealVolume = useRealVolume; + settings.plotPrice = plotPrice; + settings.showNumberOfDays = showNumberOfDays; + settings.resetOpenOnNewTradingDay = resetOpenOnNewTradingDay; + + // + // + // + + chartIndicatorSettings.MA1on = MA1on; + chartIndicatorSettings.MA1period = MA1period; + chartIndicatorSettings.MA1method = MA1method; + chartIndicatorSettings.MA1applyTo = MA1applyTo; + chartIndicatorSettings.MA1shift = MA1shift; + chartIndicatorSettings.MA2on = MA2on; + chartIndicatorSettings.MA2period = MA2period; + chartIndicatorSettings.MA2method = MA2method; + chartIndicatorSettings.MA2applyTo = MA2applyTo; + chartIndicatorSettings.MA2shift = MA2shift; + /* + chartIndicatorSettings.ShowVWAP = ShowVWAP; + chartIndicatorSettings.VWAP_Period = VWAP_Period; + chartIndicatorSettings.VWAPapplyTo = VWAPapplyTo; + chartIndicatorSettings.VWAPvolume = VWAPvolume; + */ + chartIndicatorSettings.MA3on = MA3on; + chartIndicatorSettings.MA3period = MA3period; + chartIndicatorSettings.MA3method = MA3method; + chartIndicatorSettings.MA3applyTo = MA3applyTo; + chartIndicatorSettings.MA3shift = MA3shift; + chartIndicatorSettings.ShowChannel = ShowChannel; + chartIndicatorSettings.DonchianPeriod = DonchianPeriod; + chartIndicatorSettings.BBapplyTo = BBapplyTo; + chartIndicatorSettings.BollingerBandsPeriod = BollingerBandsPeriod; + chartIndicatorSettings.BollingerBandsDeviations = BollingerBandsDeviations; + chartIndicatorSettings.SuperTrendPeriod = SuperTrendPeriod; + chartIndicatorSettings.SuperTrendMultiplier = SuperTrendMultiplier; + chartIndicatorSettings.UsedInEA = UsedInEA; + + // + // + // + + alertInfoSettings.TopBottomPaddingPercentage = TopBottomPaddingPercentage; + alertInfoSettings.showPiovots = showPivots; + alertInfoSettings.pivotPointCalculationType = pivotPointCalculationType; + alertInfoSettings.Rcolor = RColor; + alertInfoSettings.Pcolor = PColor; + alertInfoSettings.Scolor = SColor; + alertInfoSettings.PDHColor = PDHColor; + alertInfoSettings.PDLColor = PDLColor; + alertInfoSettings.PDCColor = PDCColor; + alertInfoSettings.showNextBarLevels = showNextBarLevels; + alertInfoSettings.HighThresholdIndicatorColor = HighThresholdIndicatorColor; + alertInfoSettings.LowThresholdIndicatorColor = LowThresholdIndicatorColor; + alertInfoSettings.showCurrentBarOpenTime = showCurrentBarOpenTime; + alertInfoSettings.InfoTextColor = InfoTextColor; + alertInfoSettings.UseSoundSignalOnNewBar = UseSoundSignalOnNewBar; + alertInfoSettings.OnlySignalReversalBars = OnlySignalReversalBars; + alertInfoSettings.UseAlertWindow = UseAlertWindow; + alertInfoSettings.SendPushNotifications = SendPushNotifications; + alertInfoSettings.SoundFileBull = SoundFileBull; + alertInfoSettings.SoundFileBear = SoundFileBear; + alertInfoSettings.DisplayAsBarChart = DisplayAsBarChart; + +#endif +} + +bool RangeBarSettings::Changed(void) +{ + if(MQLInfoInteger((int)MQL5_TESTING)) + return false; + + static datetime prevFileTime = 0; + + if(!FileIsExist(this.settingsFileName)) + return false; + + int handle = FileOpen(this.settingsFileName,FILE_SHARE_READ|FILE_BIN); + datetime currFileTime = (datetime)FileGetInteger(handle,FILE_CREATE_DATE); + FileClose(handle); + + if(prevFileTime != currFileTime) + { + prevFileTime = currFileTime; + return true; + } + + return false; +} diff --git a/Include/RangeBars.mqh b/Include/AZ-INVEST/SDK/RangeBars.mqh similarity index 57% rename from Include/RangeBars.mqh rename to Include/AZ-INVEST/SDK/RangeBars.mqh index 007091d..8e5e853 100644 --- a/Include/RangeBars.mqh +++ b/Include/AZ-INVEST/SDK/RangeBars.mqh @@ -1,5 +1,5 @@ //+------------------------------------------------------------------+ -//| RangeBars.mqh ver:1.47.0 | +//| RangeBars.mqh ver:2.03.0 | //| Copyright 2017, AZ-iNVEST | //| http://www.az-invest.eu | //+------------------------------------------------------------------+ @@ -7,21 +7,27 @@ #property link "http://www.az-invest.eu" #define RANGEBAR_INDICATOR_NAME "Market\\Range Bars Charting" +//#define RANGEBAR_INDICATOR_NAME "RangeBars\\RangeBarsOverlay203" -#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 +#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 +#include class RangeBars { @@ -48,15 +54,14 @@ class RangeBars 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 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: @@ -67,6 +72,7 @@ class RangeBars RangeBars::RangeBars(void) { +#define CONSTRUCTOR1 rangeBarSettings = new RangeBarSettings(); rangeBarsHandle = INVALID_HANDLE; rangeBarsSymbol = _Symbol; @@ -74,6 +80,7 @@ RangeBars::RangeBars(void) RangeBars::RangeBars(string symbol) { +#define CONSTRUCTOR2 rangeBarSettings = new RangeBarSettings(); rangeBarsHandle = INVALID_HANDLE; rangeBarsSymbol = symbol; @@ -103,8 +110,7 @@ int RangeBars::Init() } else { - Print("Failed to load indicator settings."); - Alert("You need to put the Median Renko indicator on your chart first!"); + Print("Failed to load indicator settings - RangeBar indicator not on chart"); return INVALID_HANDLE; } } @@ -128,14 +134,28 @@ int RangeBars::Init() #endif } - RANGEBAR_SETTINGS s = rangeBarSettings.Get(); + RANGEBAR_SETTINGS s = rangeBarSettings.GetRangeBarSettings(); + CHART_INDICATOR_SETTINGS cis = rangeBarSettings.GetChartIndicatorSettings(); //RangeBarSettings.Debug(); - rangeBarsHandle = iCustom(this.rangeBarsSymbol,PERIOD_M1,RANGEBAR_INDICATOR_NAME, + rangeBarsHandle = iCustom(this.rangeBarsSymbol,_Period,RANGEBAR_INDICATOR_NAME, s.barSizeInTicks, - s._startFromDateTime, + s.atrEnabled, + //s.atrTimeFrame, + s.atrPeriod, + s.atrPercentage, + s.showNumberOfDays, s.resetOpenOnNewTradingDay, + TopBottomPaddingPercentage, + showPivots, + pivotPointCalculationType, + RColor, + PColor, + SColor, + PDHColor, + PDLColor, + PDCColor, showNextBarLevels, HighThresholdIndicatorColor, LowThresholdIndicatorColor, @@ -147,34 +167,41 @@ int RangeBars::Init() 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, + 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, "", - s.DonchianPeriod, - s.BBapplyTo, - s.BollingerBandsPeriod, - s.BollingerBandsDeviations, - s.SuperTrendPeriod, - s.SuperTrendMultiplier, + cis.DonchianPeriod, + cis.BBapplyTo, + cis.BollingerBandsPeriod, + cis.BollingerBandsDeviations, + cis.SuperTrendPeriod, + cis.SuperTrendMultiplier, "", + DisplayAsBarChart, UsedInEA); + if(rangeBarsHandle == INVALID_HANDLE) { - Print("RangeBars indicator init failed on error ",GetLastError()); + Print("RangeBar indicator init failed on error ",GetLastError()); } else { - Print("RangeBars indicator init OK"); + Print("RangeBar indicator init OK"); } return rangeBarsHandle; @@ -207,9 +234,9 @@ void RangeBars::Deinit() return; if(IndicatorRelease(rangeBarsHandle)) - Print("RangeBars indicator handle released"); + Print("RangeBar indicator handle released"); else - Print("Failed to release RangeBars indicator handle"); + Print("Failed to release RangeBar indicator handle"); } // @@ -218,25 +245,21 @@ void RangeBars::Deinit() bool RangeBars::IsNewBar() { - MqlRates currentRenko[1]; - static MqlRates prevRenko; + MqlRates currentBar[1]; + static datetime prevBarTime; - GetMqlRates(currentRenko,1,1); + GetMqlRates(currentBar,0,1); - if((prevRenko.open != currentRenko[0].open) || - (prevRenko.high != currentRenko[0].high) || - (prevRenko.low != currentRenko[0].low) || - (prevRenko.close != currentRenko[0].close)) + if(currentBar[0].time == 0) + return false; + + if(prevBarTime < currentBar[0].time) { - prevRenko.open = currentRenko[0].open; - prevRenko.high = currentRenko[0].high; - prevRenko.low = currentRenko[0].low; - prevRenko.close = currentRenko[0].close; + prevBarTime = currentBar[0].time; return true; } - - return false; -} + + return false;} // // Get "count" Renko MqlRates into "ratesInfoArray[]" array starting from "start" bar @@ -244,7 +267,7 @@ bool RangeBars::IsNewBar() bool RangeBars::GetMqlRates(MqlRates &ratesInfoArray[], int start, int count) { - double o[],l[],h[],c[],time[],tick_volume[]; + double o[],l[],h[],c[],barColor[],time[],tick_volume[],real_volume[]; if(ArrayResize(o,count) == -1) return false; @@ -254,10 +277,14 @@ bool RangeBars::GetMqlRates(MqlRates &ratesInfoArray[], int start, int count) 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) @@ -270,8 +297,12 @@ bool RangeBars::GetMqlRates(MqlRates &ratesInfoArray[], int start, int count) 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; @@ -285,117 +316,72 @@ bool RangeBars::GetMqlRates(MqlRates &ratesInfoArray[], int start, int count) ratesInfoArray[tempOffset-i].close = c[i]; ratesInfoArray[tempOffset-i].time = (datetime)time[i]; ratesInfoArray[tempOffset-i].tick_volume = (long)tick_volume[i]; + ratesInfoArray[tempOffset-i].real_volume = (long)real_volume[i]; + ratesInfoArray[tempOffset-i].spread = (int)barColor[i]; } ArrayFree(o); ArrayFree(l); ArrayFree(h); ArrayFree(c); + ArrayFree(barColor); ArrayFree(time); ArrayFree(tick_volume); + ArrayFree(real_volume); return true; } - -// -// Get "count" Renko MqlRates into "ratesInfoArray[]" array starting from "start" bar -// - -int RangeBars::GetOLHCForIndicatorCalc(double &o[],double &l[],double &h[],double &c[], int start, int count) +bool RangeBars::GetBuySellVolumeBreakdown(double &buy[], double &sell[], double &buySell[], int start, int count) { - if(ArrayResize(o,count) == -1) + double b[],s[],bs[]; + + if(ArrayResize(b,count) == -1) + return false; + if(ArrayResize(s,count) == -1) + return false; + if(ArrayResize(bs,count) == -1) return false; - int _count = CopyBuffer(rangeBarsHandle,RANGEBAR_OPEN,start,count,o); - if(_count == -1) - return _count; - - - if(ArrayResize(o,_count) == -1) - return -1; - if(ArrayResize(l,_count) == -1) - return -1; - if(ArrayResize(h,_count) == -1) - return -1; - if(ArrayResize(c,_count) == -1) - return -1; - - if(CopyBuffer(rangeBarsHandle,RANGEBAR_OPEN,start,_count,o) == -1) - return -1; - if(CopyBuffer(rangeBarsHandle,RANGEBAR_LOW,start,_count,l) == -1) - return -1; - if(CopyBuffer(rangeBarsHandle,RANGEBAR_HIGH,start,_count,h) == -1) - return -1; - if(CopyBuffer(rangeBarsHandle,RANGEBAR_CLOSE,start,_count,c) == -1) - return -1; - - return _count; -} - -// -// Get "count" Renko MqlRates into "ratesInfoArray[]" array starting from "start" bar -// - -int RangeBars::GetOLHCAndApplPriceForIndicatorCalc(double &o[],double &l[],double &h[],double &c[],double &price[],ENUM_APPLIED_PRICE applied_price, int start, int count) -{ - if(ArrayResize(o,count) == -1) +#ifdef P_RANGEBAR_BR + #ifdef P_RANGEBAR_BR_PRO + if(CopyBuffer(rangeBarsHandle,RANGEBAR_BUY_VOLUME,start,count,b) == -1) return false; + if(CopyBuffer(rangeBarsHandle,RANGEBAR_SELL_VOLUME,start,count,s) == -1) + return false; + if(CopyBuffer(rangeBarsHandle,RANGEBAR_BUYSELL_VOLUME,start,count,bs) == -1) + return false; + #endif +#else + if(CopyBuffer(rangeBarsHandle,RANGEBAR_BUY_VOLUME,start,count,b) == -1) + return false; + if(CopyBuffer(rangeBarsHandle,RANGEBAR_SELL_VOLUME,start,count,s) == -1) + return false; + if(CopyBuffer(rangeBarsHandle,RANGEBAR_BUYSELL_VOLUME,start,count,bs) == -1) + return false; +#endif - int _count = CopyBuffer(rangeBarsHandle,RANGEBAR_OPEN,start,count,o); - if(_count == -1) - return _count; + if(ArrayResize(buy,count) == -1) + return false; + if(ArrayResize(sell,count) == -1) + return false; + if(ArrayResize(buySell,count) == -1) + return false; - - if(ArrayResize(o,_count) == -1) - return -1; - if(ArrayResize(l,_count) == -1) - return -1; - if(ArrayResize(h,_count) == -1) - return -1; - if(ArrayResize(c,_count) == -1) - return -1; - if(ArrayResize(price,_count) == -1) - return -1; - - if(CopyBuffer(rangeBarsHandle,RANGEBAR_OPEN,start,_count,o) == -1) - return -1; - if(CopyBuffer(rangeBarsHandle,RANGEBAR_LOW,start,_count,l) == -1) - return -1; - if(CopyBuffer(rangeBarsHandle,RANGEBAR_HIGH,start,_count,h) == -1) - return -1; - if(CopyBuffer(rangeBarsHandle,RANGEBAR_CLOSE,start,_count,c) == -1) - return -1; - - if(applied_price == PRICE_CLOSE) + int tempOffset = count-1; + for(int i=0; i + +#define POSITION_TYPE_NONE -1 + +// +// Positions (market orders) +// + +struct CMarketOrderParameters +{ + bool m_async_mode; // trade mode + ulong m_magic; // expert magic number + ulong m_deviation; // deviation default + ENUM_ORDER_TYPE_FILLING m_type_filling; + + int numberOfRetries; + int busyTimeout_ms; + int requoteTimeout_ms; + +}; + +class CMarketOrder +{ + protected: + + CTrade * ctrade; + + int numberOfRetries; + int busyTimeout_ms; + int requoteTimeout_ms; + + public: + + CMarketOrder(CMarketOrderParameters ¶ms); + ~CMarketOrder(void); + + bool Long(string symbol, double lots, uint stoploss = 0, uint takeprofit = 0); + bool Long(string symbol,double lots, double priceSL=0,double priceTP=0); + bool Short(string symbol,double lots, uint stoploss = 0, uint takeprofit = 0); + bool Short(string symbol,double lots, double priceSL=0,double priceTP=0); + bool Modify(ulong ticket, uint stoploss = 0, uint takeprofit = 0); + bool Modify(ulong ticket, double priceSL=0,double priceTP=0); + bool Close(ulong ticket); + bool ClosePartial(ulong ticket, double lots); + bool Reverse(ulong ticket,double lots = 0, uint stoploss=0, uint takeprofit=0); + bool Reverse(ulong ticket,double lots = 0, double priceSL=0,double priceTP=0); + bool IsOpen(string symbol, ENUM_POSITION_TYPE type, long magicNumber = 0); + bool IsOpen(ulong &ticket, string symbol, ENUM_POSITION_TYPE type, long magicNumber = 0); + bool IsOpen(string symbol, long magicNumber = 0); + bool IsOpen(ulong &ticket, string symbol, long magicNumber = 0); + bool IsOpen(ulong &ticket, ENUM_POSITION_TYPE &type, string symbol, long magicNumber = 0); + + string PositionTypeToString(ENUM_POSITION_TYPE t); + bool RetryOrderRequest(int retryNumber); + + private: + + bool _IsOpen(ulong &ticket, string symbol, ENUM_POSITION_TYPE type, long magicNumber); + bool _IsOpen(ulong &ticket, string symbol, long magicNumber); + bool _IsNettingAccount() { return ((ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE) != ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) ? true : false; }; + +}; + +CMarketOrder::CMarketOrder(CMarketOrderParameters ¶ms) +{ + ctrade = new CTrade(); + + ctrade.SetExpertMagicNumber(params.m_magic); + ctrade.SetDeviationInPoints(params.m_deviation); + ctrade.SetTypeFilling(params.m_type_filling); + ctrade.SetAsyncMode(params.m_async_mode); + + this.numberOfRetries = (params.numberOfRetries == 0) ? 25 : params.numberOfRetries; + this.busyTimeout_ms = (params.busyTimeout_ms == 0) ? 1000 : params.busyTimeout_ms; + this.requoteTimeout_ms = (params.requoteTimeout_ms == 0) ? 250 : params.requoteTimeout_ms; + +} + +CMarketOrder::~CMarketOrder(void) +{ + if(ctrade != NULL) + delete ctrade; +} + +bool CMarketOrder::Long(string symbol, double lots,uint stoploss=0,uint takeprofit=0) +{ + bool result = false; + int counter = 0; + + while(!IsStopped() && !result) + { + double price = SymbolInfoDouble(symbol,SYMBOL_ASK); + double _point = SymbolInfoDouble(symbol,SYMBOL_POINT); + + //calc SL + TP + double priceSL = (stoploss ? NormalizePrice(symbol,price - stoploss*_point) : 0.0); + double priceTP = (takeprofit ? NormalizePrice(symbol,price + takeprofit*_point) : 0.0); + + //attempt to buy + result = ctrade.Buy(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP); + + if(result) + { + Sleep(500); + return true; + } + else + { + if(!RetryOrderRequest(++counter)) + return false; + } + } + + return false; +} + +bool CMarketOrder::Long(string symbol, double lots,double priceSL=0,double priceTP=0) +{ + bool result = false; + int counter = 0; + + while(!IsStopped() && !result) + { + double price = SymbolInfoDouble(symbol,SYMBOL_ASK); + + //attempt to buy + result = ctrade.Buy(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP); + + if(result) + { + Sleep(500); + return true; + } + else + { + if(!RetryOrderRequest(++counter)) + return false; + } + } + + return false; +} + +bool CMarketOrder::Short(string symbol, double lots,uint stoploss=0,uint takeprofit=0) +{ + bool result = false; + int counter = 0; + + while(!IsStopped() && !result) + { + double price = SymbolInfoDouble(symbol,SYMBOL_BID); + double _point = SymbolInfoDouble(symbol,SYMBOL_POINT); + + //calc SL + TP + double priceSL = (stoploss ? NormalizePrice(symbol,price + stoploss*_point) : 0.0); + double priceTP = (takeprofit ? NormalizePrice(symbol,price - takeprofit*_point) : 0.0); + + //attempt to sell + result = ctrade.Sell(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP); + + if(result) + { + Sleep(500); + return true; + } + else + { + if(!RetryOrderRequest(++counter)) + return false; + } + } + + return false; +} + +bool CMarketOrder::Short(string symbol, double lots,double priceSL=0,double priceTP=0) +{ + bool result = false; + int counter = 0; + + while(!IsStopped() && !result) + { + double price = SymbolInfoDouble(symbol,SYMBOL_BID); + + //attempt to sell + result = ctrade.Sell(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP); + + if(result) + { + Sleep(500); + return true; + } + else + { + if(!RetryOrderRequest(++counter)) + return false; + } + } + + return false; +} + +bool CMarketOrder::Modify(ulong ticket, uint stoploss = 0, uint takeprofit = 0) +{ + if(!PositionSelectByTicket(ticket)) + return false; + + string symbol = PositionGetString(POSITION_SYMBOL); + double price = PositionGetDouble(POSITION_PRICE_CURRENT); + double _point = SymbolInfoDouble(symbol,SYMBOL_POINT); + double priceSL; + double priceTP; + + if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY){ + priceSL = (stoploss ? NormalizePrice(symbol,price - stoploss*_point) : PositionGetDouble(POSITION_SL)); + priceTP = (takeprofit ? NormalizePrice(symbol,price + takeprofit*_point) : PositionGetDouble(POSITION_TP)); + } + else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL){ + priceSL = (stoploss ? NormalizePrice(symbol,price + stoploss*_point) : PositionGetDouble(POSITION_SL)); + priceTP = (takeprofit ? NormalizePrice(symbol,price - takeprofit*_point) : PositionGetDouble(POSITION_TP)); + } + else + return false; + + //there's no change in SL or TP - do nothing! + if (priceSL == PositionGetDouble(POSITION_SL) + && priceTP == PositionGetDouble(POSITION_TP)) + return true; + + bool result = false; + int counter = 0; + + while(!IsStopped() && !result) + { + //attempt to modify position + result = ctrade.PositionModify(symbol,priceSL,priceTP); + + if(result) + { + Sleep(500); + return true; + } + else + { + if(!RetryOrderRequest(++counter)) + return false; + } + } + + return false; +} + +bool CMarketOrder::Modify(ulong ticket, double priceSL=0,double priceTP=0) +{ + if(!PositionSelectByTicket(ticket)) + return false; + + string symbol = PositionGetString(POSITION_SYMBOL); + double price = PositionGetDouble(POSITION_PRICE_CURRENT); + double _point = SymbolInfoDouble(symbol,SYMBOL_POINT); + + //there's no change in SL or TP - do nothing! + if (priceSL == PositionGetDouble(POSITION_SL) + && priceTP == PositionGetDouble(POSITION_TP)) + return true; + + bool result = false; + int counter = 0; + + while(!IsStopped() && !result) + { + //attempt to modify position + result = ctrade.PositionModify(symbol,priceSL,priceTP); + + if(result) + { + Sleep(500); + return true; + } + else + { + if(!RetryOrderRequest(++counter)) + return false; + } + } + + return false; +} + +bool CMarketOrder::Close(ulong ticket) +{ + if(!PositionSelectByTicket(ticket)) + return false; + + bool result = false; + int counter = 0; + + while(!IsStopped() && !result) + { + result = ctrade.PositionClose(ticket); + + if(result) + { + Sleep(500); + return true; + } + else + { + if(!RetryOrderRequest(++counter)) + return false; + } + } + + return false; +} + +bool CMarketOrder::ClosePartial(ulong ticket, double lots) +{ + if(!PositionSelectByTicket(ticket)) + return false; + + string symbol = PositionGetString(POSITION_SYMBOL); + + bool result = false; + int counter = 0; + + while(!IsStopped() && !result) + { + result = ctrade.PositionClosePartial(ticket, NormalizeLots(symbol,lots)); + + if(result) + { + Sleep(500); + return true; + } + else + { + if(!RetryOrderRequest(++counter)) + return false; + } + } + + return false; +} + +bool CMarketOrder::Reverse(ulong ticket,double lots = 0, uint stoploss=0, uint takeprofit=0) +{ + if(!PositionSelectByTicket(ticket)) + return false; + + string symbol = PositionGetString(POSITION_SYMBOL); + double positionLots = PositionGetDouble(POSITION_VOLUME); + ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); + + if(!this.Close(ticket)) + return false; + + if(type == POSITION_TYPE_BUY) + { + return this.Short(symbol,(lots ? lots : positionLots),stoploss,takeprofit); + } + else if(type == POSITION_TYPE_SELL) + { + return this.Long(symbol,(lots ? lots : positionLots),stoploss,takeprofit); + } + + return false; +} + +bool CMarketOrder::Reverse(ulong ticket,double lots = 0, double priceSL=0,double priceTP=0) +{ + if(!PositionSelectByTicket(ticket)) + return false; + + string symbol = PositionGetString(POSITION_SYMBOL); + double positionLots = PositionGetDouble(POSITION_VOLUME); + ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); + + if(!this.Close(ticket)) + return false; + + if(type == POSITION_TYPE_BUY) + { + return this.Short(symbol,(lots ? lots : positionLots),priceSL,priceTP); + } + else if(type == POSITION_TYPE_SELL) + { + return this.Long(symbol,(lots ? lots : positionLots),priceSL,priceTP); + } + + return false; +} + +bool CMarketOrder::IsOpen(string symbol, ENUM_POSITION_TYPE type, long magicNumber = 0) +{ + ulong ticket; + return this._IsOpen(ticket,symbol,type,magicNumber); +} + +bool CMarketOrder::IsOpen(ulong &ticket, string symbol, ENUM_POSITION_TYPE type, long magicNumber = 0) +{ + return this._IsOpen(ticket, symbol,type,magicNumber); +} + +bool CMarketOrder::IsOpen(string symbol, long magicNumber = 0) +{ + ulong ticket; + return this._IsOpen(ticket,symbol,magicNumber); +} + +bool CMarketOrder::IsOpen(ulong &ticket, string symbol, long magicNumber = 0) +{ + return this._IsOpen(ticket,symbol,magicNumber); +} + +bool CMarketOrder::IsOpen(ulong &ticket,ENUM_POSITION_TYPE &type,string symbol,long magicNumber=0) +{ + int positions=PositionsTotal(); + + for(int i=0;i 0) + { + if(PositionGetInteger(POSITION_MAGIC) != magicNumber) + continue; + } + + if(PositionGetString(POSITION_SYMBOL) == symbol) + { + ticket = _ticket; + type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); + return true; + } + } + } + else + { + PrintFormat("Error when obtaining position from the list to the cache. Error code: %d",GetLastError()); + } + } + + return false; + +} + +bool CMarketOrder::_IsOpen(ulong &ticket, string symbol, ENUM_POSITION_TYPE type, long magicNumber) +{ + int positions=PositionsTotal(); + long _type; + + for(int i=0;i 0) + { + if(PositionGetInteger(POSITION_MAGIC) != magicNumber) + continue; + } + + if(!PositionGetInteger(POSITION_TYPE,_type)) + continue; + + if((_type == type) && (PositionGetString(POSITION_SYMBOL) == symbol)) + { + ticket = _ticket; + return true; + } + } + } + else + { + PrintFormat("Error when obtaining position from the list to the cache. Error code: %d",GetLastError()); + } + } + + return false; +} + +bool CMarketOrder::_IsOpen(ulong &ticket, string symbol, long magicNumber = 0) +{ + int positions=PositionsTotal(); + + + for(int i=0;i 0) + { + if(PositionGetInteger(POSITION_MAGIC) != magicNumber) + continue; + } + + if((PositionGetString(POSITION_SYMBOL) == symbol)) + { + ticket = _ticket; + return true; + } + } + } + else + { + PrintFormat("Error when obtaining position from the list to the cache. Error code: %d",GetLastError()); + } + } + + return false; +} + +string CMarketOrder::PositionTypeToString(ENUM_POSITION_TYPE t) +{ + if(t == POSITION_TYPE_BUY) + return "Buy"; + else if(t == POSITION_TYPE_SELL) + return "Sell"; + else + return "-"; +} + +bool CMarketOrder::RetryOrderRequest(int retryNumber) +{ + if(retryNumber >= this.numberOfRetries) + { + PrintFormat("Giving up on maximum number of retries (%d)",this.numberOfRetries); + return false; + } + + switch(ctrade.ResultRetcode()) + { + case TRADE_RETCODE_REQUOTE : + + Sleep(this.requoteTimeout_ms); + return true; + + break; + + case TRADE_RETCODE_REJECT : + case TRADE_RETCODE_ERROR : + case TRADE_RETCODE_TIMEOUT : + case TRADE_RETCODE_PRICE_OFF : + case TRADE_RETCODE_TOO_MANY_REQUESTS : + + Sleep(this.busyTimeout_ms); + return true; + + break; + + default: + return false; + } + +} + +//+------------------------------------------------------------------+ +//| Normalizing | +//+------------------------------------------------------------------+ + +double NormalizeLots(string symbol, double InputLots) +{ + double lotsMin = SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN); + double lotsMax = SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX); + int lotsDigits = (int) - MathLog10(SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP)); + + if(InputLots < lotsMin) + InputLots = lotsMin; + if(InputLots > lotsMax) + InputLots = lotsMax; + + return NormalizeDouble(InputLots, lotsDigits); +} + +double NormalizePrice(string symbol, double price, double tick = 0) +{ + double _tick = tick ? tick : SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE); + int _digits = (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); + + if (tick) + return NormalizeDouble(MathRound(price/_tick)*_tick,_digits); + else + return NormalizeDouble(price,_digits); +} + \ No newline at end of file diff --git a/Include/RangeBarIndicator.mqh b/Include/RangeBarIndicator.mqh deleted file mode 100644 index 79ad2e8..0000000 --- a/Include/RangeBarIndicator.mqh +++ /dev/null @@ -1,309 +0,0 @@ -//+------------------------------------------------------------------+ -//| RangeBarIndicator.mq5 | -//| Copyright 2017, AZ-iNVEST | -//| http://www.az-invest.eu | -//+------------------------------------------------------------------+ -#property library -#property copyright "Copyright 2017, AZ-iNVEST" -#property link "http://www.az-invest.eu" -#property version "1.10" -#include - -class RangeBarIndicator -{ - - private: - - RangeBars * rangeBars; - int rates_total; - int prev_calculated; - bool useAppliedPrice; - ENUM_APPLIED_PRICE applied_price; - - public: - - double Open[]; - double Low[]; - double High[]; - double Close[]; - double Price[]; - - RangeBarIndicator(); - ~RangeBarIndicator(); - - void SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) { this.useAppliedPrice = true; this.applied_price = _applied_price; }; - - bool OnCalculate(const int rates_total,const int prev_calculated, const datetime &Time[]); - int GetPrevCalculated() { return prev_calculated; }; - - private: - - bool CheckStatus(); - bool NeedsReload(); - int GetOLHC(int start, int count); - void OLHCShiftRight(); - void OLHCResize(); - - bool Canvas_IsNewBar(const datetime &_Time[]); - bool Canvas_IsRatesTotalChanged(int ratesTotalNow); - - ENUM_TIMEFRAMES TFMigrate(int tf); - datetime iTime(string symbol,int tf,int index); - -}; - -RangeBarIndicator::RangeBarIndicator(void) -{ - rangeBars = new RangeBars(); - if(rangeBars != NULL) - rangeBars.Init(); - - useAppliedPrice = false; -} - -RangeBarIndicator::~RangeBarIndicator(void) -{ - if(rangeBars != NULL) - { - rangeBars.Deinit(); - delete rangeBars; - } -} - -bool RangeBarIndicator::CheckStatus(void) -{ - int handle = rangeBars.GetHandle(); - - if(handle == INVALID_HANDLE) - return false; - - return true; -} - -bool RangeBarIndicator::NeedsReload(void) -{ - if(rangeBars.Reload()) - { - Print("Chart settings changed - reloading indicator with new settings"); - return true; - } - - return false; -} - -bool RangeBarIndicator::OnCalculate(const int _rates_total,const int _prev_calculated, const datetime &Time[]) -{ - static bool firstRun = true; - - if(firstRun) - { - Canvas_IsRatesTotalChanged(_rates_total); - firstRun = false; - } - - if(!CheckStatus()) - return false; - - ArraySetAsSeries(this.Open,false); - ArraySetAsSeries(this.High,false); - ArraySetAsSeries(this.Low,false); - ArraySetAsSeries(this.Close,false); - ArraySetAsSeries(this.Price,false); - - if(Canvas_IsRatesTotalChanged(_rates_total)) - { - OLHCResize(); - - this.prev_calculated = prev_calculated; - Canvas_IsNewBar(Time); - return true; - } - else if(Canvas_IsNewBar(Time)) - { - //Print("Got Canvas_IsNewBar"); - //GetOLHC(0,0); - if(ArraySize(this.Open) == 0) - { - GetOLHC(0,_rates_total); - this.prev_calculated = 0; - //Print("canvas new bar ZERO elements -> getting new : ArraySize of Open = "+ArraySize(this.Open)); - return false; - - } - - OLHCShiftRight(); - this.prev_calculated = prev_calculated; - return true; - } - - if(NeedsReload() || rangeBars.IsNewBar()) - { - GetOLHC(0,_rates_total); - this.prev_calculated = 0; - return false; - } - - // - // Recalculate lst bar - // - - GetOLHC(0,0); - this.prev_calculated = prev_calculated; - - return true; -} - -int RangeBarIndicator::GetOLHC(int start, int count) -{ - if((start == 0) && (count == 0)) - { - MqlRates tempRates[1]; - int last = ArraySize(Open)-1; - - if(last < 0) - return 0; - - rangeBars.GetMqlRates(tempRates,0,1); - this.Open[last] = tempRates[0].open; - this.Low[last] = tempRates[0].low; - this.High[last] = tempRates[0].high; - this.Close[last] = tempRates[0].close; - if(useAppliedPrice) - { - this.Price[last] = rangeBars.CalcAppliedPrice(tempRates[0],this.applied_price); - } - - return 1; - } - else - { - if(useAppliedPrice) - return rangeBars.GetOLHCAndApplPriceForIndicatorCalc(this.Open,this.Low,this.High,this.Close,this.Price,this.applied_price,0,count); - else - return rangeBars.GetOLHCForIndicatorCalc(this.Open,this.Low,this.High,this.Close,0,count); - - } -} - - -void RangeBarIndicator::OLHCShiftRight() -{ - int count = ArraySize(this.Open); - - if(count <= 0) - return; - - count--; - - for(int i=count; i>0; i--) - { - this.Open[i] = this.Open[i-1]; - this.High[i] = this.High[i-1]; - this.Low[i] = this.Low[i-1]; - this.Close[i] = this.Close[i-1]; - this.Price[i] = this.Price[i-1]; - } - - this.Open[0] = 0.0; - this.High[0] = 0.0; - this.Low[0] = 0.0; - this.Close[0] = 0.0; - this.Price[0] = 0.0; -} - -void RangeBarIndicator::OLHCResize() -{ - int count = ArraySize(this.Open); - - if(count <= 0) - return; - - ArrayResize(this.Open,count+1); - ArrayResize(this.Low,count+1); - ArrayResize(this.High,count+1); - ArrayResize(this.Close,count+1); - ArrayResize(this.Price,count+1); - - OLHCShiftRight(); -} - -bool RangeBarIndicator::Canvas_IsNewBar(const datetime &_Time[]) -{ - ArraySetAsSeries(_Time,true); - datetime now = _Time[0]; - ArraySetAsSeries(_Time,false); - - static datetime prevTime = 0; - - if(prevTime != now) - { - prevTime = now; - return true; - } - - return false; -} - -bool RangeBarIndicator::Canvas_IsRatesTotalChanged(int ratesTotalNow) -{ - static int prevRatesTotal = 0; - - if(prevRatesTotal == 0) - prevRatesTotal = ratesTotalNow; - - if(prevRatesTotal != ratesTotalNow) - { - prevRatesTotal = ratesTotalNow; - return true; - } - - return false; -} - - -ENUM_TIMEFRAMES RangeBarIndicator::TFMigrate(int tf) - { - switch(tf) - { - case 0: return(PERIOD_CURRENT); - case 1: return(PERIOD_M1); - case 5: return(PERIOD_M5); - case 15: return(PERIOD_M15); - case 30: return(PERIOD_M30); - case 60: return(PERIOD_H1); - case 240: return(PERIOD_H4); - case 1440: return(PERIOD_D1); - case 10080: return(PERIOD_W1); - case 43200: return(PERIOD_MN1); - - case 2: return(PERIOD_M2); - case 3: return(PERIOD_M3); - case 4: return(PERIOD_M4); - case 6: return(PERIOD_M6); - case 10: return(PERIOD_M10); - case 12: return(PERIOD_M12); - case 16385: return(PERIOD_H1); - case 16386: return(PERIOD_H2); - case 16387: return(PERIOD_H3); - case 16388: return(PERIOD_H4); - case 16390: return(PERIOD_H6); - case 16392: return(PERIOD_H8); - case 16396: return(PERIOD_H12); - case 16408: return(PERIOD_D1); - case 32769: return(PERIOD_W1); - case 49153: return(PERIOD_MN1); - default: return(PERIOD_CURRENT); - } - } - -datetime RangeBarIndicator::iTime(string symbol,int tf,int index) -{ - if(index < 0) return(-1); - ENUM_TIMEFRAMES timeframe=TFMigrate(tf); - datetime Arr[]; - if(CopyTime(symbol, timeframe, index, 1, Arr)>0) - return(Arr[0]); - else return(-1); -} - - diff --git a/Include/RangeBarSettings.mqh b/Include/RangeBarSettings.mqh deleted file mode 100644 index 87fdb58..0000000 --- a/Include/RangeBarSettings.mqh +++ /dev/null @@ -1,318 +0,0 @@ -//+------------------------------------------------------------------+ -//| RangeBarSettings.mqh ver 1.04 | -//| Copyright 2017, AZ-iNVEST | -//| http://www.az-invest.eu | -//+------------------------------------------------------------------+ - -#property copyright "Copyright 2017, AZ-iNVEST" -#property link "http://www.az-invest.eu" - -enum ENUM_CHANNEL_TYPE -{ - None = 0, // None - Donchian_Channel, // Donchian Channel - Bollinger_Bands, // Bollinger Bands - SuperTrend, // Super Trend -// VWAP, -}; - -#ifdef SHOW_INDICATOR_INPUTS - -input int barSizeInTicks = 100; // Range bar size (in points) - double customBarSize = barSizeInTicks * Point(); - bool useTickVolume = true; // Use tick volume (for FX) -input datetime _startFromDateTime = 0; // Start building chart from date/time - datetime startFromDateTime = 0; -input bool resetOpenOnNewTradingDay = false; // Synchronize first bar's open on new day -input bool showNextBarLevels = true; // Show current bar's close projections -input color HighThresholdIndicatorColor = clrLime; // Bullish bar projection color -input color LowThresholdIndicatorColor = clrRed; // Bearish bar projection color -input bool showCurrentBarOpenTime = true; // Display chart info and current bar's open time -input color InfoTextColor = clrWhite; // Current bar's open time info color -input bool UseSoundSignalOnNewBar = false; // Play sound on new bar -input bool OnlySignalReversalBars = false; // Only signal reversals -input bool UseAlertWindow = false; // Display Alert window with new bar info -input bool SendPushNotifications = false; // Send new bar info push notification to smartphone -input string SoundFileBull = "news.wav"; // Use sound file for bullish bar close -input string SoundFileBear = "news.wav"; // Use sound file for bearish bar close -input bool MA1on = false; // Show first MA -input int MA1period = 20; // 1st MA period -input ENUM_MA_METHOD MA1method = MODE_EMA; // 1st MA metod -input ENUM_APPLIED_PRICE MA1applyTo = PRICE_CLOSE; //1st MA apply to -input int MA1shift = 0; //1st MA shift -input bool MA2on = false; // Show second MA -input int MA2period = 50; // 2nd MA period -input ENUM_MA_METHOD MA2method = MODE_EMA; // 2nd MA method -input ENUM_APPLIED_PRICE MA2applyTo = PRICE_CLOSE; // 2nd MA apply to -input int MA2shift = 0; //2nd MA shift -input ENUM_CHANNEL_TYPE ShowChannel = None; // Show Channel -input string Channel_Settings = "--------------------------"; // Channel settings -input int DonchianPeriod = 20; // Donchian Channel period -input ENUM_APPLIED_PRICE BBapplyTo = PRICE_CLOSE; //Bollinger Bands apply to -input int BollingerBandsPeriod = 20; // Bollinger Bands period -input double BollingerBandsDeviations = 2.0; // Bollinger Bands deviations -input int SuperTrendPeriod = 10; // Super Trend period -input double SuperTrendMultiplier=1.7; // Super Trend multiplier -input string Misc_Settings = "--------------------------"; // Misc settings -input bool UsedInEA = false; // Indicator used in EA via iCustom() - -#else - - int barSizeInTicks; - bool useTickVolume = true; - datetime startFromDateTime; - datetime _startFromDateTime = 0; - bool resetOpenOnNewTradingDay; - - // - // This block should always be set to the follwong values - // - - bool showNextBarLevels = false; - color HighThresholdIndicatorColor = clrNONE; - color LowThresholdIndicatorColor = clrNONE; - bool showCurrentBarOpenTime = false; - color InfoTextColor = clrNONE; - bool UseSoundSignalOnNewBar = false; - bool OnlySignalReversalBars = false; - bool UseAlertWindow = false; - bool SendPushNotifications = false; - string SoundFileBull = ""; - string SoundFileBear = ""; - - bool UsedInEA = true; // This should always be set to TRUE for EAs & Indicators - - // - // - // - - bool MA1on; - int MA1period; - ENUM_MA_METHOD MA1method; - ENUM_APPLIED_PRICE MA1applyTo; - int MA1shift; - - bool MA2on; - int MA2period; - ENUM_MA_METHOD MA2method; - ENUM_APPLIED_PRICE MA2applyTo; - int MA2shift; - - ENUM_CHANNEL_TYPE ShowChannel; - int DonchianPeriod; - ENUM_APPLIED_PRICE BBapplyTo; - int BollingerBandsPeriod; - double BollingerBandsDeviations; - int SuperTrendPeriod = 10; - double SuperTrendMultiplier=1.7; - -#endif - -struct RANGEBAR_SETTINGS -{ - int barSizeInTicks; - bool useTickVolume; - datetime _startFromDateTime; - bool resetOpenOnNewTradingDay; - - bool MA1on; - int MA1period; - ENUM_MA_METHOD MA1method; - ENUM_APPLIED_PRICE MA1applyTo; - int MA1shift; - - bool MA2on; - int MA2period; - ENUM_MA_METHOD MA2method; - ENUM_APPLIED_PRICE MA2applyTo; - int MA2shift; - - ENUM_CHANNEL_TYPE ShowChannel; - - int DonchianPeriod; - - ENUM_APPLIED_PRICE BBapplyTo; - int BollingerBandsPeriod; - double BollingerBandsDeviations; - - int SuperTrendPeriod; - double SuperTrendMultiplier; -}; - -class RangeBarSettings -{ - protected: - - string settingsFileName; - RANGEBAR_SETTINGS settings; - - public: - - RangeBarSettings(void); - ~RangeBarSettings(void); - - void Save(void); - bool Load(void); - void Delete(void); - bool Changed(void); - - RANGEBAR_SETTINGS Get(void); - void Debug(void); -}; - -void RangeBarSettings::RangeBarSettings(void) -{ - this.settingsFileName = "RangeBars"+(string)ChartID()+".set"; - -} - -void RangeBarSettings::~RangeBarSettings(void) -{ - -} - -void RangeBarSettings::Save(void) -{ - settings.barSizeInTicks = barSizeInTicks; - settings.useTickVolume = useTickVolume; - settings._startFromDateTime = startFromDateTime; - settings.resetOpenOnNewTradingDay = resetOpenOnNewTradingDay; - settings.MA1on = MA1on; - settings.MA1period = MA1period; - settings.MA1method = MA1method; - settings.MA1applyTo = MA1applyTo; - settings.MA1shift = MA1shift; - settings.MA2on = MA2on; - settings.MA2period = MA2period; - settings.MA2method = MA2method; - settings.MA2applyTo = MA2applyTo; - settings.MA2shift = MA2shift; - settings.ShowChannel = ShowChannel; - settings.DonchianPeriod = DonchianPeriod; - settings.BBapplyTo = BBapplyTo; - settings.BollingerBandsPeriod = BollingerBandsPeriod; - settings.BollingerBandsDeviations = BollingerBandsDeviations; - settings.SuperTrendPeriod = SuperTrendPeriod; - settings.SuperTrendMultiplier = SuperTrendMultiplier; - - if(MQLInfoInteger((int)MQL5_TESTING)) - return; - - this.Delete(); - - int handle = FileOpen(this.settingsFileName,FILE_SHARE_READ|FILE_WRITE|FILE_BIN); - FileWriteStruct(handle,this.settings); - FileClose(handle); -} - -void RangeBarSettings::Delete(void) -{ - if(FileIsExist(this.settingsFileName)) - FileDelete(this.settingsFileName); -} - -bool RangeBarSettings::Load(void) -{ -#ifdef SHOW_INDICATOR_INPUTS - this.settings.barSizeInTicks = barSizeInTicks; - this.settings.useTickVolume = useTickVolume; - this.settings._startFromDateTime = _startFromDateTime; - this.settings.resetOpenOnNewTradingDay = resetOpenOnNewTradingDay; - this.settings.MA1on = MA1on; - this.settings.MA1period = MA1period; - this.settings.MA1method = MA1method; - this.settings.MA1applyTo = MA1applyTo; - this.settings.MA1shift = MA1shift; - this.settings.MA2on = MA2on; - this.settings.MA2period = MA2period; - this.settings.MA2method = MA2method; - this.settings.MA2applyTo = MA2applyTo; - this.settings.MA2shift = MA2shift; - this.settings.ShowChannel = ShowChannel; - this.settings.DonchianPeriod = DonchianPeriod; - this.settings.BBapplyTo = BBapplyTo; - this.settings.BollingerBandsPeriod = BollingerBandsPeriod; - this.settings.BollingerBandsDeviations = BollingerBandsDeviations; - this.settings.SuperTrendPeriod = SuperTrendPeriod; - this.settings.SuperTrendMultiplier = SuperTrendMultiplier; - return true; -#else - - if(!FileIsExist(this.settingsFileName)) - return false; - - int handle = FileOpen(this.settingsFileName,FILE_SHARE_READ|FILE_BIN); - if(handle == INVALID_HANDLE) - return false; - - if(FileReadStruct(handle,this.settings) <= 0) - { - Print("Failed loading settigns!"); - FileClose(handle); - return false; - } - - // this.Debug(); - FileClose(handle); - return true; - -#endif -} - -RANGEBAR_SETTINGS RangeBarSettings::Get(void) -{ - this.Debug(); - return this.settings; -} - -bool RangeBarSettings::Changed(void) -{ - if(MQLInfoInteger((int)MQL5_TESTING)) - return false; - - static datetime prevFileTime = 0; - - if(!FileIsExist(this.settingsFileName)) - return false; - - int handle = FileOpen(this.settingsFileName,FILE_SHARE_READ|FILE_BIN); - datetime currFileTime = (datetime)FileGetInteger(handle,FILE_CREATE_DATE); - FileClose(handle); - - if(prevFileTime != currFileTime) - { - prevFileTime = currFileTime; - return true; - } - - return false; -} - -void RangeBarSettings::Debug(void) -{ - Print("RangeBars settings:"); - Print("barSizeInTicks = "+(string)settings.barSizeInTicks); - Print("useTickVolume = "+(string)settings.useTickVolume); - Print("startFromDateTime = "+(string)settings._startFromDateTime); - Print("resetOpenOnNewTradingDay = "+(string)settings.resetOpenOnNewTradingDay); - Print("MA1on = "+(string)settings.MA1on); - Print("MA1period = "+(string)settings.MA1period); - Print("MA1method = "+(string)settings.MA1method); - Print("MA1applyTo = "+(string)settings.MA1applyTo); - Print("MA1shift = "+(string)settings.MA1shift); - Print("MA2on = "+(string)settings.MA2on); - Print("MA2period = "+(string)settings.MA2period); - Print("MA2method = "+(string)settings.MA2method); - Print("MA2applyTo = "+(string)settings.MA2applyTo); - Print("MA2shift = "+(string)settings.MA1shift); - Print("ShowChannel = "+(string)settings.ShowChannel); - Print("DonchianPeriod = "+(string)settings.DonchianPeriod); - Print("BBapplyTo = "+(string)settings.BBapplyTo); - Print("BBperiod = "+(string)settings.BollingerBandsPeriod); - Print("BBdeviations = "+(string)settings.BollingerBandsDeviations); - Print("SuperTrendPeriod = "+(string)settings.SuperTrendPeriod); - Print("SuperTrendMultiplier = "+(string)settings.SuperTrendMultiplier); - - Print("UsedInEA = "+(string)UsedInEA); - -} \ No newline at end of file diff --git a/Indicators/RangeBars/RangeBars_ADX.mq5 b/Indicators/RangeBars/RangeBars_ADX.mq5 new file mode 100644 index 0000000..ddfd34a --- /dev/null +++ b/Indicators/RangeBars/RangeBars_ADX.mq5 @@ -0,0 +1,203 @@ + + +//+------------------------------------------------------------------+ +//| ADX.mq5 | +//| Copyright 2009, MetaQuotes Software Corp. | +//| http://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "2009, MetaQuotes Software Corp." +#property link "http://www.mql5.com" +#property description "Average Directional Movement Index" +#include + +#property indicator_separate_window +#property indicator_buffers 6 +#property indicator_plots 3 +#property indicator_type1 DRAW_LINE +#property indicator_color1 LightSeaGreen +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 +#property indicator_type2 DRAW_LINE +#property indicator_color2 YellowGreen +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 +#property indicator_type3 DRAW_LINE +#property indicator_color3 Wheat +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 +#property indicator_label1 "ADX" +#property indicator_label2 "+DI" +#property indicator_label3 "-DI" +//--- input parameters +input int InpPeriodADX=14; // Period +//---- buffers +double ExtADXBuffer[]; +double ExtPDIBuffer[]; +double ExtNDIBuffer[]; +double ExtPDBuffer[]; +double ExtNDBuffer[]; +double ExtTmpBuffer[]; +//--- global variables +int ExtADXPeriod; + +// +// +// + +#include +RangeBarIndicator rangeBarsIndicator; + +// +// +// + + +//+------------------------------------------------------------------+ +//| Custom indicator initialization function | +//+------------------------------------------------------------------+ +void OnInit() + { +//--- check for input parameters + if(InpPeriodADX>=100 || InpPeriodADX<=0) + { + ExtADXPeriod=14; + printf("Incorrect value for input variable Period_ADX=%d. Indicator will use value=%d for calculations.",InpPeriodADX,ExtADXPeriod); + } + else ExtADXPeriod=InpPeriodADX; +//---- indicator buffers + SetIndexBuffer(0,ExtADXBuffer); + SetIndexBuffer(1,ExtPDIBuffer); + SetIndexBuffer(2,ExtNDIBuffer); + SetIndexBuffer(3,ExtPDBuffer,INDICATOR_CALCULATIONS); + SetIndexBuffer(4,ExtNDBuffer,INDICATOR_CALCULATIONS); + SetIndexBuffer(5,ExtTmpBuffer,INDICATOR_CALCULATIONS); +//--- indicator digits + IndicatorSetInteger(INDICATOR_DIGITS,2); +//--- set draw begin + PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtADXPeriod<<1); + PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,ExtADXPeriod); + PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,ExtADXPeriod); +//--- indicator short name + string short_name="ADX("+string(ExtADXPeriod)+")"; + IndicatorSetString(INDICATOR_SHORTNAME,short_name); +//--- change 1-st index label + PlotIndexSetString(0,PLOT_LABEL,short_name); +//---- end of initialization function + } +//+------------------------------------------------------------------+ +//| Custom indicator iteration function | +//+------------------------------------------------------------------+ +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 &TickVolume[], + const long &Volume[], + const int &Spread[]) + { + // + // Process data through MedianRenko indicator + // + + if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,Time)) + return(0); + + // + // Make the following modifications in the code below: + // + // rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated + // + // rangeBarsIndicator.Open[] should be used instead of open[] + // rangeBarsIndicator.Low[] should be used instead of low[] + // rangeBarsIndicator.High[] should be used instead of high[] + // rangeBarsIndicator.Close[] should be used instead of close[] + // + // rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed + // + // rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time. + // (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used + // + // rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[] + // rangeBarsIndicator.Real_volume[] should be used instead of Volume[] + // (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used + // + // rangeBarsIndicator.Price[] should be used instead of Price[] + // (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used + // + + int _prev_calculated = rangeBarsIndicator.GetPrevCalculated(); + + // + // + // + +//--- checking for bars count + if(rates_total1) start=_prev_calculated-1; + else + { + start=1; + ExtPDIBuffer[0]=0.0; + ExtNDIBuffer[0]=0.0; + ExtADXBuffer[0]=0.0; + } +//--- main cycle + for(int i=start;idTmpN) dTmpN=0.0; + else + { + if(dTmpP +//--- +#property indicator_separate_window +#property indicator_buffers 4 +#property indicator_plots 1 +#property indicator_type1 DRAW_LINE +#property indicator_color1 LightSeaGreen +#property indicator_level1 -100.0 +#property indicator_level2 100.0 +#property indicator_applied_price PRICE_TYPICAL +//--- input parametrs +input int InpCCIPeriod=14; // Period +input ENUM_APPLIED_PRICE InpApplyToPrice= PRICE_CLOSE; // Apply to +//--- global variable +int ExtCCIPeriod; +//---- indicator buffer +double ExtSPBuffer[]; +double ExtDBuffer[]; +double ExtMBuffer[]; +double ExtCCIBuffer[]; + +// +// +// + +#include +RangeBarIndicator rangeBarsIndicator; + +// +// +// + +//+------------------------------------------------------------------+ +//| Custom indicator initialization function | +//+------------------------------------------------------------------+ +void OnInit() + { + + // + // Indicator uses Price[] array for calculations so we need to set this in the MedianRenkoIndicator class + // + + rangeBarsIndicator.SetUseAppliedPriceFlag(InpApplyToPrice); + + // + // + // + +//--- check for input value of period + if(InpCCIPeriod<=0) + { + ExtCCIPeriod=14; + printf("Incorrect value for input variable InpCCIPeriod=%d. Indicator will use value=%d for calculations.",InpCCIPeriod,ExtCCIPeriod); + } + else ExtCCIPeriod=InpCCIPeriod; +//--- define buffers + SetIndexBuffer(0,ExtCCIBuffer); + SetIndexBuffer(1,ExtDBuffer,INDICATOR_CALCULATIONS); + SetIndexBuffer(2,ExtMBuffer,INDICATOR_CALCULATIONS); + SetIndexBuffer(3,ExtSPBuffer,INDICATOR_CALCULATIONS); +//--- indicator name + IndicatorSetString(INDICATOR_SHORTNAME,"CCI("+string(ExtCCIPeriod)+")"); +//--- indexes draw begin settings + PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtCCIPeriod-1); +//--- number of digits of indicator value + IndicatorSetInteger(INDICATOR_DIGITS,2); +//---- OnInit done + } +//+------------------------------------------------------------------+ +//| Custom indicator iteration function | +//+------------------------------------------------------------------+ +/* +int OnCalculate(const int rates_total, + const int prev_calculated, + const int begin, + const double &price[]) + { +*/ +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 &TickVolume[], + const long &Volume[], + const int &Spread[]) + { + // + // Process data through MedianRenko indicator + // + + if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,Time)) + return(0); + + // + // Make the following modifications in the code below: + // + // rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated + // + // rangeBarsIndicator.Open[] should be used instead of open[] + // rangeBarsIndicator.Low[] should be used instead of low[] + // rangeBarsIndicator.High[] should be used instead of high[] + // rangeBarsIndicator.Close[] should be used instead of close[] + // + // rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed + // + // rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time. + // (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used + // + // rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[] + // rangeBarsIndicator.Real_volume[] should be used instead of Volume[] + // (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used + // + // rangeBarsIndicator.Price[] should be used instead of Price[] + // (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used + // + + int _prev_calculated = rangeBarsIndicator.GetPrevCalculated(); + + // + // + // + +//--- variables + int i,j; + double dTmp,dMul=0.015/ExtCCIPeriod; +//--- start calculation + int StartCalcPosition=(ExtCCIPeriod-1);//+begin; +//--- check for bars count + if(rates_total0) PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,StartCalcPosition+(ExtCCIPeriod-1)); +//--- calculate position + int pos=_prev_calculated-1; + if(pos +RangeBarIndicator rangeBarsIndicator; + +// +// +// + +//+------------------------------------------------------------------+ +//| Custom indicator initialization function | +//+------------------------------------------------------------------+ +void OnInit() + { +//---- indicator buffers mapping + SetIndexBuffer(0,ExtUpperBuffer,INDICATOR_DATA); + SetIndexBuffer(1,ExtLowerBuffer,INDICATOR_DATA); + IndicatorSetInteger(INDICATOR_DIGITS,_Digits); +//---- sets first bar from what index will be drawn + PlotIndexSetInteger(0,PLOT_ARROW,217); + PlotIndexSetInteger(1,PLOT_ARROW,218); +//---- arrow shifts when drawing + PlotIndexSetInteger(0,PLOT_ARROW_SHIFT,ExtArrowShift); + PlotIndexSetInteger(1,PLOT_ARROW_SHIFT,-ExtArrowShift); +//---- sets drawing line empty value-- + PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,EMPTY_VALUE); + PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,EMPTY_VALUE); +//---- initialization done + } +//+------------------------------------------------------------------+ +//| Accelerator/Decelerator Oscillator | +//+------------------------------------------------------------------+ +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 &TickVolume[], + const long &Volume[], + const int &Spread[]) + { + // + // Process data through MedianRenko indicator + // + + if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,Time)) + return(0); + + // + // Make the following modifications in the code below: + // + // rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated + // + // rangeBarsIndicator.Open[] should be used instead of open[] + // rangeBarsIndicator.Low[] should be used instead of low[] + // rangeBarsIndicator.High[] should be used instead of high[] + // rangeBarsIndicator.Close[] should be used instead of close[] + // + // rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed + // + // rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time. + // (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used + // + // rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[] + // rangeBarsIndicator.Real_volume[] should be used instead of Volume[] + // (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used + // + // rangeBarsIndicator.Price[] should be used instead of Price[] + // (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used + // + + int _prev_calculated = rangeBarsIndicator.GetPrevCalculated(); + + // + // + // + + int i,limit; +//--- + if(rates_total<5) + return(0); +//--- + if(_prev_calculated<7) + { + limit=2; + //--- clean up arrays + ArrayInitialize(ExtUpperBuffer,EMPTY_VALUE); + ArrayInitialize(ExtLowerBuffer,EMPTY_VALUE); + } + else limit=rates_total-5; + + for(i=limit; irangeBarsIndicator.High[i+1] && rangeBarsIndicator.High[i]>rangeBarsIndicator.High[i+2] && rangeBarsIndicator.High[i]>=rangeBarsIndicator.High[i-1] && rangeBarsIndicator.High[i]>=rangeBarsIndicator.High[i-2]) + ExtUpperBuffer[i]=rangeBarsIndicator.High[i]; + else ExtUpperBuffer[i]=EMPTY_VALUE; + + //---- Lower Fractal + if(rangeBarsIndicator.Low[i] +RangeBarIndicator rangeBarsIndicator; + +// +// +// + +//+------------------------------------------------------------------+ +//| Custom indicator initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { +//--- check period + period=(int)fmax(InpPeriod,2); +//--- set buffers + SetIndexBuffer(0,GannBuffer); + SetIndexBuffer(1,ColorBuffer,INDICATOR_COLOR_INDEX); + SetIndexBuffer(2,MaHighBuffer,INDICATOR_CALCULATIONS); + SetIndexBuffer(3,MaLowBuffer,INDICATOR_CALCULATIONS); + SetIndexBuffer(4,TrendBuffer,INDICATOR_CALCULATIONS); +//--- set direction + ArraySetAsSeries(GannBuffer,true); + ArraySetAsSeries(ColorBuffer,true); + ArraySetAsSeries(MaHighBuffer,true); + ArraySetAsSeries(MaLowBuffer,true); + ArraySetAsSeries(TrendBuffer,true); +//--- get handles + ma_high_handle=iMA(NULL,0,period,0,InpMethod,PRICE_HIGH); + ma_low_handle =iMA(NULL,0,period,0,InpMethod,PRICE_LOW); + if(ma_high_handle==INVALID_HANDLE || ma_low_handle==INVALID_HANDLE) + { + Print("Unable to create handle for iMA"); + return(INIT_FAILED); + } +//--- set indicator properties + string short_name=StringFormat("Gann High-Low Activator SSL (%u, %s)",period,StringSubstr(EnumToString(InpMethod),5)); + IndicatorSetString(INDICATOR_SHORTNAME,short_name); + IndicatorSetInteger(INDICATOR_DIGITS,_Digits); +//--- set label + short_name=StringFormat("GHL (%u, %s)",period,StringSubstr(EnumToString(InpMethod),5)); + PlotIndexSetString(0,PLOT_LABEL,short_name); +//--- done + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Custom indicator iteration function | +//+------------------------------------------------------------------+ +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[]) + { + + if(rates_total=0 && !_StopFlag; i--) + { + TrendBuffer[i]=TrendBuffer[i+1]; + //--- + if(NormalizeDouble(rangeBarsIndicator.Close[i],_Digits)>NormalizeDouble(MaHighBuffer[i+1],_Digits)) TrendBuffer[i]=1; + if(NormalizeDouble(rangeBarsIndicator.Close[i],_Digits)0) + { + GannBuffer[i]=MaLowBuffer[i]; + ColorBuffer[i]=0; + } + } +//--- done + return(rates_total); + } +//+------------------------------------------------------------------+ diff --git a/Indicators/RangeBars/RangeBars_HA_Smoothed.mq5 b/Indicators/RangeBars/RangeBars_HA_Smoothed.mq5 new file mode 100644 index 0000000..343f657 Binary files /dev/null and b/Indicators/RangeBars/RangeBars_HA_Smoothed.mq5 differ diff --git a/Indicators/RangeBars/RangeBars_Heiken_Ashi.mq5 b/Indicators/RangeBars/RangeBars_Heiken_Ashi.mq5 new file mode 100644 index 0000000..dd542fd --- /dev/null +++ b/Indicators/RangeBars/RangeBars_Heiken_Ashi.mq5 @@ -0,0 +1,137 @@ + +//+------------------------------------------------------------------+ +//| Heiken_Ashi.mq5 | +//| Copyright 2009-2017, MetaQuotes Software Corp. | +//| http://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "2009-2017, MetaQuotes Software Corp." +#property link "http://www.mql5.com" +//--- indicator settings +#property indicator_chart_window +#property indicator_buffers 5 +#property indicator_plots 1 +#property indicator_type1 DRAW_COLOR_CANDLES +#property indicator_color1 DodgerBlue, Red +#property indicator_label1 "Heiken Ashi Open;Heiken Ashi High;Heiken Ashi Low;Heiken Ashi Close" +//--- indicator buffers +double ExtOBuffer[]; +double ExtHBuffer[]; +double ExtLBuffer[]; +double ExtCBuffer[]; +double ExtColorBuffer[]; + +// +// +// + +#include +RangeBarIndicator rangeBarsIndicator; + +// +// +// + +//+------------------------------------------------------------------+ +//| Custom indicator initialization function | +//+------------------------------------------------------------------+ +void OnInit() + { +//--- indicator buffers mapping + SetIndexBuffer(0,ExtOBuffer,INDICATOR_DATA); + SetIndexBuffer(1,ExtHBuffer,INDICATOR_DATA); + SetIndexBuffer(2,ExtLBuffer,INDICATOR_DATA); + SetIndexBuffer(3,ExtCBuffer,INDICATOR_DATA); + SetIndexBuffer(4,ExtColorBuffer,INDICATOR_COLOR_INDEX); +//--- + IndicatorSetInteger(INDICATOR_DIGITS,_Digits); +//--- sets first bar from what index will be drawn + IndicatorSetString(INDICATOR_SHORTNAME,"Heiken Ashi"); +//--- sets drawing line empty value + PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0); +//--- initialization done + } +//+------------------------------------------------------------------+ +//| Heiken Ashi | +//+------------------------------------------------------------------+ +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[]) + { + int i,limit; + + // + // Process data through MedianRenko indicator + // + + if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,time)) + return(0); + + // + // Make the following modifications in the code below: + // + // rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated + // + // rangeBarsIndicator.Open[] should be used instead of open[] + // rangeBarsIndicator.Low[] should be used instead of low[] + // rangeBarsIndicator.High[] should be used instead of high[] + // rangeBarsIndicator.Close[] should be used instead of close[] + // + // rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed + // + // rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time. + // (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used + // + // rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[] + // rangeBarsIndicator.Real_volume[] should be used instead of Volume[] + // (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used + // + // rangeBarsIndicator.Price[] should be used instead of Price[] + // (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used + // + + int _prev_calculated = rangeBarsIndicator.GetPrevCalculated(); + + // + // + // + +//--- preliminary calculations + if(_prev_calculated==0) + { + //--- set first candle + ExtLBuffer[0]=rangeBarsIndicator.Low[0]; + ExtHBuffer[0]=rangeBarsIndicator.High[0]; + ExtOBuffer[0]=rangeBarsIndicator.Open[0]; + ExtCBuffer[0]=rangeBarsIndicator.Close[0]; + limit=1; + } + else limit=_prev_calculated-1; + +//--- the main loop of calculations + for(i=limit;i +RangeBarIndicator rangeBarsIndicator; + +// +// +// + +//+------------------------------------------------------------------+ +//| Custom indicator initialization function | +//+------------------------------------------------------------------+ +void OnInit() + { +//--- indicator buffers mapping + SetIndexBuffer(0,ExtTenkanBuffer,INDICATOR_DATA); + SetIndexBuffer(1,ExtKijunBuffer,INDICATOR_DATA); + SetIndexBuffer(2,ExtSpanABuffer,INDICATOR_DATA); + SetIndexBuffer(3,ExtSpanBBuffer,INDICATOR_DATA); + SetIndexBuffer(4,ExtChikouBuffer,INDICATOR_DATA); +//--- + IndicatorSetInteger(INDICATOR_DIGITS,_Digits+1); +//--- sets first bar from what index will be drawn + PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpTenkan); + PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,InpKijun); + PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,InpSenkou-1); +//--- lines shifts when drawing + PlotIndexSetInteger(2,PLOT_SHIFT,InpKijun); + PlotIndexSetInteger(3,PLOT_SHIFT,-InpKijun); +//--- change labels for DataWindow + PlotIndexSetString(0,PLOT_LABEL,"Tenkan-sen("+string(InpTenkan)+")"); + PlotIndexSetString(1,PLOT_LABEL,"Kijun-sen("+string(InpKijun)+")"); + PlotIndexSetString(2,PLOT_LABEL,"Senkou Span A;Senkou Span B("+string(InpSenkou)+")"); +//--- initialization done + } +//+------------------------------------------------------------------+ +//| get highest value for range | +//+------------------------------------------------------------------+ +double Highest(const double&array[],int range,int fromIndex) + { + double res=0; +//--- + res=array[fromIndex]; + for(int i=fromIndex;i>fromIndex-range && i>=0;i--) + { + if(resfromIndex-range && i>=0;i--) + { + if(res>array[i]) res=array[i]; + } +//--- + return(res); + } +//+------------------------------------------------------------------+ +//| Ichimoku Kinko Hyo | +//+------------------------------------------------------------------+ +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[]) + { + // + // Process data through MedianRenko indicator + // + + if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,time)) + return(0); + + // + // Make the following modifications in the code below: + // + // rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated + // + // rangeBarsIndicator.Open[] should be used instead of open[] + // rangeBarsIndicator.Low[] should be used instead of low[] + // rangeBarsIndicator.High[] should be used instead of high[] + // rangeBarsIndicator.Close[] should be used instead of close[] + // + // rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed + // + // rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time. + // (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used + // + // rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[] + // rangeBarsIndicator.Real_volume[] should be used instead of Volume[] + // (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used + // + // rangeBarsIndicator.Price[] should be used instead of Price[] + // (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used + // + + int _prev_calculated = rangeBarsIndicator.GetPrevCalculated(); + + // + // + // + + int limit; +//--- + if(_prev_calculated==0) limit=0; + else limit=_prev_calculated-1; +//--- + for(int i=limit;i +RangeBarIndicator rangeBarsIndicator; + +// +// +// + +//+------------------------------------------------------------------+ +//| simple moving average | +//+------------------------------------------------------------------+ +void CalculateSimpleMA(int rates_total,int prev_calculated,int begin,const double &price[]) + { + int i,limit; +//--- first calculation or number of bars was changed + if(prev_calculated==0)// first calculation + { + limit=InpMAPeriod+begin; + //--- set empty value for first limit bars + for(i=0;i +#include RangeBarIndicator rangeBarsIndicator; // // // + //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ @@ -84,7 +84,7 @@ int OnCalculate(const int rates_total,const int prev_calculated, // if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,Time)) - return(rangeBarsIndicator.GetPrevCalculated()); + return(0); // // Make the following modifications in the code below: diff --git a/Indicators/RangeBars/RangeBars_Momentum.mq5 b/Indicators/RangeBars/RangeBars_Momentum.mq5 new file mode 100644 index 0000000..cf0da5a --- /dev/null +++ b/Indicators/RangeBars/RangeBars_Momentum.mq5 @@ -0,0 +1,147 @@ + + +//+------------------------------------------------------------------+ +//| Momentum.mq5 | +//| Copyright 2009, MetaQuotes Software Corp. | +//| http://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "2009, MetaQuotes Software Corp." +#property link "http://www.mql5.com" +//---- indicator settings +#property indicator_separate_window +#property indicator_buffers 1 +#property indicator_plots 1 +#property indicator_type1 DRAW_LINE +#property indicator_color1 DodgerBlue +//---- input parameters +input int InpMomentumPeriod=14; // Period +input ENUM_APPLIED_PRICE InpApplyToPrice= PRICE_CLOSE; // Apply to +//---- indicator buffers +double ExtMomentumBuffer[]; +//--- global variable +int ExtMomentumPeriod; + +// +// +// + +#include +RangeBarIndicator rangeBarsIndicator; + +// +// +// +//+------------------------------------------------------------------+ +//| Custom indicator initialization function | +//+------------------------------------------------------------------+ +void OnInit() + { + // + // Indicator uses Price[] array for calculations so we need to set this in the MedianRenkoIndicator class + // + + rangeBarsIndicator.SetUseAppliedPriceFlag(InpApplyToPrice); + + // + // + // + +//--- check for input value + if(InpMomentumPeriod<0) + { + ExtMomentumPeriod=14; + Print("Input parameter InpMomentumPeriod has wrong value. Indicator will use value ",ExtMomentumPeriod); + } + else ExtMomentumPeriod=InpMomentumPeriod; +//---- buffers + SetIndexBuffer(0,ExtMomentumBuffer,INDICATOR_DATA); +//---- name for DataWindow and indicator subwindow label + IndicatorSetString(INDICATOR_SHORTNAME,"Momentum"+"("+string(ExtMomentumPeriod)+")"); +//--- sets first bar from what index will be drawn + PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtMomentumPeriod-1); +//--- sets drawing line empty value + PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0); +//--- digits + IndicatorSetInteger(INDICATOR_DIGITS,2); + } +//+------------------------------------------------------------------+ +//| Momentum | +//+------------------------------------------------------------------+ +/* +int OnCalculate(const int rates_total, + const int prev_calculated, + const int begin, + const double &price[]) + { +*/ +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 &TickVolume[], + const long &Volume[], + const int &Spread[]) + { + + static int begin = 0; + + // + // Process data through MedianRenko indicator + // + + if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,Time)) + return(0); + + // + // Make the following modifications in the code below: + // + // rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated + // + // rangeBarsIndicator.Open[] should be used instead of open[] + // rangeBarsIndicator.Low[] should be used instead of low[] + // rangeBarsIndicator.High[] should be used instead of high[] + // rangeBarsIndicator.Close[] should be used instead of close[] + // + // rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed + // + // rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time. + // (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used + // + // rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[] + // rangeBarsIndicator.Real_volume[] should be used instead of Volume[] + // (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used + // + // rangeBarsIndicator.Price[] should be used instead of Price[] + // (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used + // + + int _prev_calculated = rangeBarsIndicator.GetPrevCalculated(); + + // + // + // + +//--- start calculation + int StartCalcPosition=(ExtMomentumPeriod-1)+begin; +//---- insufficient data + if(rates_total0) PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,StartCalcPosition+(ExtMomentumPeriod-1)); +//--- start working, detect position + int pos=_prev_calculated-1; + if(pos 0) + ExtMomentumBuffer[i]=rangeBarsIndicator.Price[i]*100/rangeBarsIndicator.Price[i-ExtMomentumPeriod]; + + } +//--- OnCalculate done. Return new prev_calculated. + return(rates_total); + } +//+------------------------------------------------------------------+ diff --git a/Indicators/RangeBars/RangeBars_ParabolicSAR.mq5 b/Indicators/RangeBars/RangeBars_ParabolicSAR.mq5 new file mode 100644 index 0000000..53d0e94 --- /dev/null +++ b/Indicators/RangeBars/RangeBars_ParabolicSAR.mq5 @@ -0,0 +1,248 @@ +//+------------------------------------------------------------------+ +//| ParabolicSAR.mq5 | +//| Copyright 2009-2017, MetaQuotes Software Corp. | +//| http://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "2009-2017, MetaQuotes Software Corp." +#property link "http://www.mql5.com" +//--- indicator settings +#property indicator_chart_window +#property indicator_buffers 3 +#property indicator_plots 1 +#property indicator_type1 DRAW_ARROW +#property indicator_color1 DodgerBlue +//--- External parametrs +input double InpSARStep=0.02; // Step +input double InpSARMaximum=0.2; // Maximum +//---- buffers +double ExtSARBuffer[]; +double ExtEPBuffer[]; +double ExtAFBuffer[]; +//--- global variables +int ExtLastRevPos; +bool ExtDirectionLong; +double ExtSarStep; +double ExtSarMaximum; + +// +// +// + +#include +RangeBarIndicator rangeBarsIndicator; + +// +// +// + +//+------------------------------------------------------------------+ +//| Custom indicator initialization function | +//+------------------------------------------------------------------+ +void OnInit() + { +//--- checking input data + if(InpSARStep<0.0) + { + ExtSarStep=0.02; + Print("Input parametr InpSARStep has incorrect value. Indicator will use value", + ExtSarStep,"for calculations."); + } + else ExtSarStep=InpSARStep; + if(InpSARMaximum<0.0) + { + ExtSarMaximum=0.2; + Print("Input parametr InpSARMaximum has incorrect value. Indicator will use value", + ExtSarMaximum,"for calculations."); + } + else ExtSarMaximum=InpSARMaximum; +//---- indicator buffers + SetIndexBuffer(0,ExtSARBuffer); + SetIndexBuffer(1,ExtEPBuffer,INDICATOR_CALCULATIONS); + SetIndexBuffer(2,ExtAFBuffer,INDICATOR_CALCULATIONS); +//--- set arrow symbol + PlotIndexSetInteger(0,PLOT_ARROW,159); +//--- set indicator digits + IndicatorSetInteger(INDICATOR_DIGITS,_Digits); +//--- set label name + PlotIndexSetString(0,PLOT_LABEL,"SAR("+ + DoubleToString(ExtSarStep,2)+","+ + DoubleToString(ExtSarMaximum,2)+")"); +//--- set global variables + ExtLastRevPos=0; + ExtDirectionLong=false; +//---- + } +//+------------------------------------------------------------------+ +//| Custom indicator iteration function | +//+------------------------------------------------------------------+ +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[]) + { +//--- check for minimum rates count + if(rates_total<3) + return(0); + + // + // Process data through MedianRenko indicator + // + + if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,time)) + return(0); + + // + // Make the following modifications in the code below: + // + // rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated + // + // rangeBarsIndicator.Open[] should be used instead of open[] + // rangeBarsIndicator.Low[] should be used instead of low[] + // rangeBarsIndicator.High[] should be used instead of high[] + // rangeBarsIndicator.Close[] should be used instead of close[] + // + // rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed + // + // rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time. + // (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used + // + // rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[] + // rangeBarsIndicator.Real_volume[] should be used instead of Volume[] + // (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used + // + // rangeBarsIndicator.Price[] should be used instead of Price[] + // (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used + // + + int _prev_calculated = rangeBarsIndicator.GetPrevCalculated(); + + // + // + // + +//--- detect current position + int pos=_prev_calculated-1; +//--- correct position + if(pos<1) + { + //--- first pass, set as SHORT + pos=1; + ExtAFBuffer[0]=ExtSarStep; + ExtAFBuffer[1]=ExtSarStep; + ExtSARBuffer[0]=rangeBarsIndicator.High[0]; + ExtLastRevPos=0; + ExtDirectionLong=false; + ExtSARBuffer[1]=GetHigh(pos,ExtLastRevPos,rangeBarsIndicator.High); + ExtEPBuffer[0]=rangeBarsIndicator.Low[pos]; + ExtEPBuffer[1]=rangeBarsIndicator.Low[pos]; + } +//---main cycle + for(int i=pos;irangeBarsIndicator.Low[i]) + { + //--- switch to SHORT + ExtDirectionLong=false; + ExtSARBuffer[i]=GetHigh(i,ExtLastRevPos,rangeBarsIndicator.High); + ExtEPBuffer[i]=rangeBarsIndicator.Low[i]; + ExtLastRevPos=i; + ExtAFBuffer[i]=ExtSarStep; + } + } + else + { + if(ExtSARBuffer[i]ExtEPBuffer[i-1] && i!=ExtLastRevPos) + { + ExtEPBuffer[i]=rangeBarsIndicator.High[i]; + ExtAFBuffer[i]=ExtAFBuffer[i-1]+ExtSarStep; + if(ExtAFBuffer[i]>ExtSarMaximum) + ExtAFBuffer[i]=ExtSarMaximum; + } + else + { + //--- when we haven't reversed + if(i!=ExtLastRevPos) + { + ExtAFBuffer[i]=ExtAFBuffer[i-1]; + ExtEPBuffer[i]=ExtEPBuffer[i-1]; + } + } + //--- calculate SAR for tomorrow + ExtSARBuffer[i+1]=ExtSARBuffer[i]+ExtAFBuffer[i]*(ExtEPBuffer[i]-ExtSARBuffer[i]); + //--- check for SAR + if(ExtSARBuffer[i+1]>rangeBarsIndicator.Low[i] || ExtSARBuffer[i+1]>rangeBarsIndicator.Low[i-1]) + ExtSARBuffer[i+1]=MathMin(rangeBarsIndicator.Low[i],rangeBarsIndicator.Low[i-1]); + } + else + { + //--- check for new Low + if(rangeBarsIndicator.Low[i]ExtSarMaximum) + ExtAFBuffer[i]=ExtSarMaximum; + } + else + { + //--- when we haven't reversed + if(i!=ExtLastRevPos) + { + ExtAFBuffer[i]=ExtAFBuffer[i-1]; + ExtEPBuffer[i]=ExtEPBuffer[i-1]; + } + } + //--- calculate SAR for tomorrow + ExtSARBuffer[i+1]=ExtSARBuffer[i]+ExtAFBuffer[i]*(ExtEPBuffer[i]-ExtSARBuffer[i]); + //--- check for SAR + if(ExtSARBuffer[i+1]LoData[i]) result=LoData[i]; + return(result); + } +//+------------------------------------------------------------------+ diff --git a/Indicators/RangeBars/RangeBars_ROC.mq5 b/Indicators/RangeBars/RangeBars_ROC.mq5 new file mode 100644 index 0000000..a328bcc --- /dev/null +++ b/Indicators/RangeBars/RangeBars_ROC.mq5 @@ -0,0 +1,136 @@ +//+------------------------------------------------------------------+ +//| ROC.mq5 | +//| Copyright 2009-2017, MetaQuotes Software Corp. | +//| http://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "2009-2017, MetaQuotes Software Corp." +#property link "http://www.mql5.com" +#property description "Rate of Change" +//--- indicator settings +#property indicator_separate_window +#property indicator_buffers 1 +#property indicator_plots 1 +#property indicator_type1 DRAW_LINE +#property indicator_color1 LightSeaGreen +//--- input parameters +input int InpRocPeriod=12; // Period +//--- indicator buffers +double ExtRocBuffer[]; +//--- global variable +int ExtRocPeriod; + +// +// +// + +#include +RangeBarIndicator rangeBarsIndicator; + +// +// +// + +//+------------------------------------------------------------------+ +//| Rate of Change initialization function | +//+------------------------------------------------------------------+ +void OnInit() + { +//--- check for input + if(InpRocPeriod<1) + { + ExtRocPeriod=12; + Print("Incorrect value for input variable InpRocPeriod =",InpRocPeriod, + "Indicator will use value =",ExtRocPeriod,"for calculations."); + } + else ExtRocPeriod=InpRocPeriod; +//--- indicator buffers mapping + SetIndexBuffer(0,ExtRocBuffer,INDICATOR_DATA); +//--- set accuracy + IndicatorSetInteger(INDICATOR_DIGITS,2); +//--- name for DataWindow and indicator subwindow label + IndicatorSetString(INDICATOR_SHORTNAME,"ROC("+string(ExtRocPeriod)+")"); +//--- sets first bar from what index will be drawn + PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtRocPeriod); +//--- initialization done + + // + // Indicator uses Price[] array for calculations so we need to set this in the MedianRenkoIndicator class + // + + rangeBarsIndicator.SetUseAppliedPriceFlag(PRICE_CLOSE); + + // + // + // + + } +//+------------------------------------------------------------------+ +//| Rate of Change | +//+------------------------------------------------------------------+ +//int OnCalculate(const int rates_total,const int prev_calculated,const int begin,const double &price[]) +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 &TickVolume[], + const long &Volume[], + const int &Spread[]) + + { + // + // Process data through MedianRenko indicator + // + + if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,Time)) + return(0); + + // + // Make the following modifications in the code below: + // + // rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated + // + // rangeBarsIndicator.Open[] should be used instead of open[] + // rangeBarsIndicator.Low[] should be used instead of low[] + // rangeBarsIndicator.High[] should be used instead of high[] + // rangeBarsIndicator.Close[] should be used instead of close[] + // + // rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed + // + // rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time. + // (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used + // + // rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[] + // rangeBarsIndicator.Real_volume[] should be used instead of Volume[] + // (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used + // + // rangeBarsIndicator.Price[] should be used instead of Price[] + // (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used + // + + int _prev_calculated = rangeBarsIndicator.GetPrevCalculated(); + + // + // + // + +//--- check for rates count + if(rates_total +#include RangeBarIndicator rangeBarsIndicator; - // // // @@ -79,26 +77,36 @@ int OnCalculate(const int rates_total,const int prev_calculated, const long &Volume[], const int &Spread[]) { - // - // Precoess data through MedianRenko indicator + // Process data through MedianRenko indicator // if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,Time)) - return(rates_total); - + return(0); + // // Make the following modifications in the code below: // - // medianRenkoIndicator.GetPrevCalculated() should be used instead of prev_calculated - // medianRenkoIndicator.Open[] should be used instead of open[] - // medianRenkoIndicator.Low[] should be used instead of low[] - // medianRenkoIndicator.High[] should be used instead of high[] - // medianRenkoIndicator.Close[] should be used instead of close[] - // if applied_price is used - // medianRenkoIndicator.Price[] should be used instead of price[] + // rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated // - + // rangeBarsIndicator.Open[] should be used instead of open[] + // rangeBarsIndicator.Low[] should be used instead of low[] + // rangeBarsIndicator.High[] should be used instead of high[] + // rangeBarsIndicator.Close[] should be used instead of close[] + // + // rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed + // + // rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time. + // (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used + // + // rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[] + // rangeBarsIndicator.Real_volume[] should be used instead of Volume[] + // (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used + // + // rangeBarsIndicator.Price[] should be used instead of Price[] + // (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used + // + int _prev_calculated = rangeBarsIndicator.GetPrevCalculated(); // diff --git a/Indicators/RangeBars_Stochastic.mq5 b/Indicators/RangeBars/RangeBars_Stochastic.mq5 similarity index 88% rename from Indicators/RangeBars_Stochastic.mq5 rename to Indicators/RangeBars/RangeBars_Stochastic.mq5 index 632eb34..4057eff 100644 --- a/Indicators/RangeBars_Stochastic.mq5 +++ b/Indicators/RangeBars/RangeBars_Stochastic.mq5 @@ -26,14 +26,12 @@ double ExtHighesBuffer[]; double ExtLowesBuffer[]; // -// Initialize MedianRenko indicator for data processing -// according to settings of the MedianRenko indicator already on chart +// // -#include +#include RangeBarIndicator rangeBarsIndicator; - // // // @@ -79,23 +77,14 @@ int OnCalculate(const int rates_total,const int prev_calculated, const long &Volume[], const int &Spread[]) { - + // - // Precoess data through MedianRenko indicator // - + // + if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,Time)) - return(rates_total); + return(0); - // - // Make the following modifications in the code below: - // - // medianRenkoIndicator.GetPrevCalculated() should be used instead of prev_calculated - // medianRenkoIndicator.Open[] should be used instead of open[] - // medianRenkoIndicator.Low[] should be used instead of low[] - // medianRenkoIndicator.High[] should be used instead of high[] - // medianRenkoIndicator.Close[] should be used instead of close[] - // int _prev_calculated = rangeBarsIndicator.GetPrevCalculated(); diff --git a/Indicators/RangeBars/RangeBars_VEMA_Wilders_DMI.mq5 b/Indicators/RangeBars/RangeBars_VEMA_Wilders_DMI.mq5 new file mode 100644 index 0000000..4ad2ff8 --- /dev/null +++ b/Indicators/RangeBars/RangeBars_VEMA_Wilders_DMI.mq5 @@ -0,0 +1,246 @@ +//------------------------------------------------------------------ + #property copyright "mladen" + #property link "www.forex-tsd.com" +//------------------------------------------------------------------ + +#property indicator_separate_window +#property indicator_buffers 5 +#property indicator_plots 4 + +#property indicator_label1 "ADX trend" +#property indicator_type1 DRAW_FILLING +#property indicator_color1 C'200,255,180',clrMistyRose +#property indicator_label2 "ADX" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrLimeGreen +#property indicator_style2 STYLE_SOLID +#property indicator_width2 2 +#property indicator_label3 "ADXR" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrGold +#property indicator_style3 STYLE_SOLID +#property indicator_width3 2 +#property indicator_label4 "Level" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrSilver +#property indicator_style4 STYLE_DOT + +// +// +// +// +// + +enum enVolume +{ + vol_noVolume, // do not use volume + vol_ticks, // use ticks + vol_real // use real volume +}; + +// +// +// +// +// + +input int AdxPeriod = 14; // ADX (DMI) period +input double AdxLevel = 20; // ADX level +input bool ShowADX = true; // ADX visible +input bool ShowADXR = false; // ADXR visible +input enVolume VolumeType = vol_ticks; // Volume to use + +// +// +// +// +// + +double DIp[]; +double DIm[]; +double ADX[]; +double ADXR[]; +double Level[]; + +// +// +// + +#include +RangeBarIndicator rangeBarsIndicator; + +// +// +// + +//------------------------------------------------------------------ +// +//------------------------------------------------------------------ +// +// +// +// +// + +int OnInit() +{ + SetIndexBuffer(0,DIp,INDICATOR_DATA); + SetIndexBuffer(1,DIm,INDICATOR_DATA); + SetIndexBuffer(2,ADX,INDICATOR_DATA); + SetIndexBuffer(3,ADXR,INDICATOR_DATA); + SetIndexBuffer(4,Level,INDICATOR_DATA); + + // + // + // + // + // + + IndicatorSetString(INDICATOR_SHORTNAME," VEMA Wilder's DMI ("+string(AdxPeriod)+")"); + + rangeBarsIndicator.SetGetVolumesFlag(); + + return(0); +} + +//------------------------------------------------------------------ +// +//------------------------------------------------------------------ +// +// +// +// +// + + +double averages[][9]; +#define _Vol 0 +#define _DIp 1 +#define _DIm 2 +#define _TR 3 +#define _Adx 4 +#define _DIpa 5 +#define _DIma 6 +#define _TRa 7 +#define _Adxa 8 + +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[]) +{ + // + // Process data through MedianRenko indicator + // + + if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,time)) + return(0); + + // + // Make the following modifications in the code below: + // + // rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated + // + // rangeBarsIndicator.Open[] should be used instead of open[] + // rangeBarsIndicator.Low[] should be used instead of low[] + // rangeBarsIndicator.High[] should be used instead of high[] + // rangeBarsIndicator.Close[] should be used instead of close[] + // + // rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed + // + // rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time. + // (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used + // + // rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[] + // rangeBarsIndicator.Real_volume[] should be used instead of Volume[] + // (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used + // + // rangeBarsIndicator.Price[] should be used instead of Price[] + // (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used + // + + int _prev_calculated = rangeBarsIndicator.GetPrevCalculated(); + + // + // + // + + if (ArrayRange(averages,0)!=rates_total) ArrayResize(averages,rates_total); + + // + // + // + // + // + + double sf = 1.0/(double)AdxPeriod; + for (int i=(int)MathMax(_prev_calculated-1,1); i DeltaLo) && (DeltaHi > 0)) plusDM = DeltaHi; + if ((DeltaLo > DeltaHi) && (DeltaLo > 0)) minusDM = DeltaLo; + + // + // + // + // + // + + + averages[i][_Vol] = averages[i-1][_Vol] + sf*(vol - averages[i-1][_Vol]); + averages[i][_DIp] = averages[i-1][_DIp] + sf*(vol*plusDM - averages[i-1][_DIp]); + averages[i][_DIm] = averages[i-1][_DIm] + sf*(vol*minusDM - averages[i-1][_DIm]); + averages[i][_TR] = averages[i-1][_TR] + sf*(vol*currTR - averages[i-1][_TR]); + averages[i][_DIpa] = averages[i][_DIp]/MathMax(averages[i][_Vol],1); + averages[i][_DIma] = averages[i][_DIm]/MathMax(averages[i][_Vol],1); + averages[i][_TRa] = averages[i][_TR] /MathMax(averages[i][_Vol],1); + Level[i] = AdxLevel; + + // + // + // + // + // + + DIp[i] = 0.00; + DIm[i] = 0.00; + ADX[i] = EMPTY_VALUE; + ADXR[i] = EMPTY_VALUE; + if (averages[i][_TRa] > 0) + { + DIp[i] = 100.00 * averages[i][_DIpa]/averages[i][_TRa]; + DIm[i] = 100.00 * averages[i][_DIma]/averages[i][_TRa]; + } + + if(ShowADX) + { + double DX; + if((DIp[i] + DIm[i])>0) + DX = 100*MathAbs(DIp[i] - DIm[i])/(DIp[i] + DIm[i]); + else DX = 0.00; + averages[i][_Adx] = averages[i-1][_Adx]+ sf*(vol*DX - averages[i-1][_Adx]); + averages[i][_Adxa] = averages[i][_Adx]/MathMax(averages[i][_Vol],1); + ADX[i] = averages[i][_Adxa]; + if(ShowADXR && i>=AdxPeriod) + ADXR[i] = 0.5*(ADX[i] + ADX[i-AdxPeriod]); + } + } + return(rates_total); +} diff --git a/Indicators/RangeBars/RangeBars_VWAP_lite.mq5 b/Indicators/RangeBars/RangeBars_VWAP_lite.mq5 new file mode 100644 index 0000000..156b7a1 --- /dev/null +++ b/Indicators/RangeBars/RangeBars_VWAP_lite.mq5 @@ -0,0 +1,388 @@ +//+------------------------------------------------------------------+ +//| VWAP_Lite.mq5 | +//| Copyright 2016, SOL Digital Consultoria LTDA | +//| http://www.soldigitalconsultoria.com.br | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2016, SOL Digital Consultoria LTDA" +#property link "http://www.soldigitalconsultoria.com.br" +#property version "1.49" + +#property indicator_chart_window +#property indicator_buffers 3 +#property indicator_plots 3 + +#property indicator_label1 "VWAP Daily" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrRed +#property indicator_style1 STYLE_DASH +#property indicator_width1 2 + +#property indicator_label2 "VWAP Weekly" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrBlue +#property indicator_style2 STYLE_DASH +#property indicator_width2 2 + +#property indicator_label3 "VWAP Monthly" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrGreen +#property indicator_style3 STYLE_DASH +#property indicator_width3 2 +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +enum DATE_TYPE + { + DAILY, + WEEKLY, + MONTHLY + }; +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +enum PRICE_TYPE + { + OPEN, + CLOSE, + HIGH, + LOW, + OPEN_CLOSE, + HIGH_LOW, + CLOSE_HIGH_LOW, + OPEN_CLOSE_HIGH_LOW + }; +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ + + +// +// +// + +#include +RangeBarIndicator rangeBarsIndicator; + +#define VWAP_Daily "cc__VWAP_Daily" +#define VWAP_Weekly "cc__VWAP_Weekly" +#define VWAP_Monthly "cc__VWAP_Monthly" + +// +// +// + +datetime CreateDateTime(DATE_TYPE nReturnType=DAILY,datetime dtDay=D'2000.01.01 00:00:00',int pHour=0,int pMinute=0,int pSecond=0) + { + datetime dtReturnDate; + MqlDateTime timeStruct; + + TimeToStruct(dtDay,timeStruct); + timeStruct.hour = pHour; + timeStruct.min = pMinute; + timeStruct.sec = pSecond; + dtReturnDate=(StructToTime(timeStruct)); + + if(nReturnType==WEEKLY) + { + while(timeStruct.day_of_week!=0) + { + dtReturnDate=(dtReturnDate-86400); + TimeToStruct(dtReturnDate,timeStruct); + } + } + + if(nReturnType==MONTHLY) + { + timeStruct.day=1; + dtReturnDate=(StructToTime(timeStruct)); + } + + return dtReturnDate; + } + +sinput string Indicator_Name = "Volume Weighted Average Price (VWAP)"; +input PRICE_TYPE Price_Type = CLOSE_HIGH_LOW; +input bool Calc_Every_Tick = false; +input bool Enable_Daily = true; +input bool Show_Daily_Value = true; +input bool Enable_Weekly = false; +input bool Show_Weekly_Value = false; +input bool Enable_Monthly = false; +input bool Show_Monthly_Value = false; + +double VWAP_Buffer_Daily[],VWAP_Buffer_Weekly[],VWAP_Buffer_Monthly[]; +double nPriceArr[],nTotalTPV[],nTotalVol[]; +double nSumDailyTPV = 0, nSumWeeklyTPV = 0, nSumMonthlyTPV = 0; +double nSumDailyVol = 0, nSumWeeklyVol = 0, nSumMonthlyVol = 0; +int nIdxDaily=0,nIdxWeekly=0,nIdxMonthly=0,nIdx=0; +bool bIsFirstRun=true; +string sDailyStr = "", sWeeklyStr = "", sMonthlyStr = ""; +datetime dtLastDay = CreateDateTime(DAILY), dtLastWeek = CreateDateTime(WEEKLY), dtLastMonth = CreateDateTime(MONTHLY); +ENUM_TIMEFRAMES LastTimePeriod=PERIOD_MN1; +int nStringYDistance=50; +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +int OnInit() + { + IndicatorSetInteger(INDICATOR_DIGITS,_Digits); + + SetIndexBuffer(0,VWAP_Buffer_Daily,INDICATOR_DATA); + SetIndexBuffer(1,VWAP_Buffer_Weekly,INDICATOR_DATA); + SetIndexBuffer(2,VWAP_Buffer_Monthly,INDICATOR_DATA); + + if(Show_Daily_Value) + { + ObjectCreate(0,VWAP_Daily,OBJ_LABEL,0,0,0); + ObjectSetInteger(0,VWAP_Daily,OBJPROP_CORNER,CORNER_LEFT_LOWER); + ObjectSetInteger(0,VWAP_Daily,OBJPROP_XDISTANCE,10);//180); + ObjectSetInteger(0,VWAP_Daily,OBJPROP_YDISTANCE,nStringYDistance); + ObjectSetInteger(0,VWAP_Daily,OBJPROP_COLOR,indicator_color1); + ObjectSetInteger(0,VWAP_Daily,OBJPROP_FONTSIZE,7); + ObjectSetString(0,VWAP_Daily,OBJPROP_FONT,"Verdana"); + ObjectSetString(0,VWAP_Daily,OBJPROP_TEXT," "); + nStringYDistance=nStringYDistance+20; + } + + if(Show_Weekly_Value) + { + ObjectCreate(0,VWAP_Weekly,OBJ_LABEL,0,0,0); + ObjectSetInteger(0,VWAP_Weekly,OBJPROP_CORNER,CORNER_LEFT_LOWER); + ObjectSetInteger(0,VWAP_Weekly,OBJPROP_XDISTANCE,10);//180); + ObjectSetInteger(0,VWAP_Weekly,OBJPROP_YDISTANCE,nStringYDistance); + ObjectSetInteger(0,VWAP_Weekly,OBJPROP_COLOR,indicator_color2); + ObjectSetInteger(0,VWAP_Weekly,OBJPROP_FONTSIZE,7); + ObjectSetString(0,VWAP_Weekly,OBJPROP_FONT,"Verdana"); + ObjectSetString(0,VWAP_Weekly,OBJPROP_TEXT," "); + nStringYDistance=nStringYDistance+20; + } + + if(Show_Monthly_Value) + { + ObjectCreate(0,VWAP_Monthly,OBJ_LABEL,0,0,0); + ObjectSetInteger(0,VWAP_Monthly,OBJPROP_CORNER,CORNER_LEFT_LOWER); + ObjectSetInteger(0,VWAP_Monthly,OBJPROP_XDISTANCE,10);//180); + ObjectSetInteger(0,VWAP_Monthly,OBJPROP_YDISTANCE,nStringYDistance); + ObjectSetInteger(0,VWAP_Monthly,OBJPROP_COLOR,indicator_color3); + ObjectSetInteger(0,VWAP_Monthly,OBJPROP_FONTSIZE,7); + ObjectSetString(0,VWAP_Monthly,OBJPROP_FONT,"Verdana"); + ObjectSetString(0,VWAP_Monthly,OBJPROP_TEXT," "); + } + + rangeBarsIndicator.SetGetVolumesFlag(); + rangeBarsIndicator.SetGetTimeFlag(); + + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +void OnDeinit(const int pReason) + { + if(Show_Daily_Value) ObjectDelete(0,VWAP_Daily); + if(Show_Weekly_Value) ObjectDelete(0,VWAP_Weekly); + if(Show_Monthly_Value) ObjectDelete(0,VWAP_Monthly); + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +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[]) + { + + // + // Process data through MedianRenko indicator + // + + if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,time)) + return(0); + + // + // Make the following modifications in the code below: + // + // rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated + // + // rangeBarsIndicator.Open[] should be used instead of open[] + // rangeBarsIndicator.Low[] should be used instead of low[] + // rangeBarsIndicator.High[] should be used instead of high[] + // rangeBarsIndicator.Close[] should be used instead of close[] + // + // rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed + // + // rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time. + // (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used + // + // rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[] + // rangeBarsIndicator.Real_volume[] should be used instead of Volume[] + // (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used + // + // rangeBarsIndicator.Price[] should be used instead of Price[] + // (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used + // + + int _prev_calculated = rangeBarsIndicator.GetPrevCalculated(); + + // + // + // + + if(PERIOD_CURRENT!=LastTimePeriod) + { + bIsFirstRun=true; + LastTimePeriod=PERIOD_CURRENT; + } + + if(rates_total>_prev_calculated || bIsFirstRun || Calc_Every_Tick || (_prev_calculated == 0) || rangeBarsIndicator.IsNewBar) + { + nIdxDaily = 0; + nIdxWeekly = 0; + nIdxMonthly = 0; + + ArrayResize(nPriceArr,rates_total); + ArrayResize(nTotalTPV,rates_total); + ArrayResize(nTotalVol,rates_total); + + if(Enable_Daily) {nIdx = nIdxDaily; nSumDailyTPV = 0; nSumDailyVol = 0;} + if(Enable_Weekly) {nIdx = nIdxWeekly; nSumWeeklyTPV = 0; nSumWeeklyVol = 0;} + if(Enable_Monthly) {nIdx = nIdxMonthly; nSumMonthlyTPV = 0; nSumMonthlyVol = 0;} + + for(; nIdx 0) && (rangeBarsIndicator.Real_volume[nIdx] == 0)) + { + // Print("tick vol = "+rangeBarsIndicator.Tick_volume[nIdx]); + nTotalTPV[nIdx] = (nPriceArr[nIdx] * rangeBarsIndicator.Tick_volume[nIdx]); + nTotalVol[nIdx] = (double)rangeBarsIndicator.Tick_volume[nIdx]; + } + else if(rangeBarsIndicator.Real_volume[nIdx] && rangeBarsIndicator.Tick_volume[nIdx] ) + { + // Print("real vol = "+rangeBarsIndicator.Real_volume[nIdx]); + nTotalTPV[nIdx] = (nPriceArr[nIdx] * rangeBarsIndicator.Real_volume[nIdx]); + nTotalVol[nIdx] = (double)rangeBarsIndicator.Real_volume[nIdx]; + } + + if(Enable_Daily && (nIdx>=nIdxDaily)) + { + nSumDailyTPV += nTotalTPV[nIdx]; + nSumDailyVol += nTotalVol[nIdx]; + + if(nSumDailyVol) + VWAP_Buffer_Daily[nIdx]=(nSumDailyTPV/nSumDailyVol); + + if((sDailyStr!="VWAP Daily: "+(string)NormalizeDouble(VWAP_Buffer_Daily[nIdx],_Digits)) && Show_Daily_Value) + { + sDailyStr="VWAP Daily: "+(string)NormalizeDouble(VWAP_Buffer_Daily[nIdx],_Digits); + ObjectSetString(0,VWAP_Daily,OBJPROP_TEXT,sDailyStr); + } + } + + if(Enable_Weekly && (nIdx>=nIdxWeekly)) + { + nSumWeeklyTPV += nTotalTPV[nIdx]; + nSumWeeklyVol += nTotalVol[nIdx]; + + if(nSumWeeklyVol) + VWAP_Buffer_Weekly[nIdx]=(nSumWeeklyTPV/nSumWeeklyVol); + + if((sWeeklyStr!="VWAP Weekly: "+(string)NormalizeDouble(VWAP_Buffer_Weekly[nIdx],_Digits)) && Show_Weekly_Value) + { + sWeeklyStr="VWAP Weekly: "+(string)NormalizeDouble(VWAP_Buffer_Weekly[nIdx],_Digits); + ObjectSetString(0,VWAP_Weekly,OBJPROP_TEXT,sWeeklyStr); + } + } + + if(Enable_Monthly && (nIdx>=nIdxMonthly)) + { + nSumMonthlyTPV += nTotalTPV[nIdx]; + nSumMonthlyVol += nTotalVol[nIdx]; + + if(nSumMonthlyVol) + VWAP_Buffer_Monthly[nIdx]=(nSumMonthlyTPV/nSumMonthlyVol); + + if((sMonthlyStr!="VWAP Monthly: "+(string)NormalizeDouble(VWAP_Buffer_Monthly[nIdx],_Digits)) && Show_Monthly_Value) + { + sMonthlyStr="VWAP Monthly: "+(string)NormalizeDouble(VWAP_Buffer_Monthly[nIdx],_Digits); + ObjectSetString(0,VWAP_Monthly,OBJPROP_TEXT,sMonthlyStr); + } + } + + dtLastDay=CreateDateTime(DAILY,rangeBarsIndicator.Time[nIdx]); + dtLastWeek=CreateDateTime(WEEKLY,rangeBarsIndicator.Time[nIdx]); + dtLastMonth=CreateDateTime(MONTHLY,rangeBarsIndicator.Time[nIdx]); + } + + bIsFirstRun=false; + } + + return(rates_total); + } +//+------------------------------------------------------------------+ diff --git a/Indicators/RangeBars/RangeBars_WPR.mq5 b/Indicators/RangeBars/RangeBars_WPR.mq5 new file mode 100644 index 0000000..fe92808 Binary files /dev/null and b/Indicators/RangeBars/RangeBars_WPR.mq5 differ diff --git a/Indicators/RangeBars/RangeBars_ZigZag.mq5 b/Indicators/RangeBars/RangeBars_ZigZag.mq5 new file mode 100644 index 0000000..b1c920b --- /dev/null +++ b/Indicators/RangeBars/RangeBars_ZigZag.mq5 @@ -0,0 +1,322 @@ +//+------------------------------------------------------------------+ +//| ZigZag.mq5 | +//| Copyright 2009, MetaQuotes Software Corp. | +//| http://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "2009, MetaQuotes Software Corp." +#property link "http://www.mql5.com" +#property version "1.00" +#property indicator_chart_window +#property indicator_buffers 3 +#property indicator_plots 1 +//---- plot Zigzag +#property indicator_label1 "Zigzag" +#property indicator_type1 DRAW_SECTION +#property indicator_color1 Red +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 +//--- input parameters +input int ExtDepth=12; +input int ExtDeviation=5; +input int ExtBackstep=3; +//--- indicator buffers +double ZigzagBuffer[]; // main buffer +double HighMapBuffer[]; // highs +double LowMapBuffer[]; // lows +int level=3; // recounting depth +double deviation; // deviation in points + +// +// +// + +#include +RangeBarIndicator rangeBarsIndicator; + +// +// +// + +//+------------------------------------------------------------------+ +//| Custom indicator initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { +//--- indicator buffers mapping + SetIndexBuffer(0,ZigzagBuffer,INDICATOR_DATA); + SetIndexBuffer(1,HighMapBuffer,INDICATOR_CALCULATIONS); + SetIndexBuffer(2,LowMapBuffer,INDICATOR_CALCULATIONS); + +//--- set short name and digits + PlotIndexSetString(0,PLOT_LABEL,"ZigZag("+(string)ExtDepth+","+(string)ExtDeviation+","+(string)ExtBackstep+")"); + IndicatorSetInteger(INDICATOR_DIGITS,_Digits); +//--- set empty value + PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0); +//--- to use in cycle + deviation=ExtDeviation*_Point; +//--- + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| searching index of the highest bar | +//+------------------------------------------------------------------+ +int iHighest(const double &array[], + int depth, + int startPos) + { + int index=startPos; +//--- start index validation + if(startPos<0) + { + Print("Invalid parameter in the function iHighest, startPos =",startPos); + return 0; + } + int size=ArraySize(array); +//--- depth correction if need + if(startPos-depth<0) depth=startPos; + double max=array[startPos]; +//--- start searching + for(int i=startPos;i>startPos-depth;i--) + { + if(array[i]>max) + { + index=i; + max=array[i]; + } + } +//--- return index of the highest bar + return(index); + } +//+------------------------------------------------------------------+ +//| searching index of the lowest bar | +//+------------------------------------------------------------------+ +int iLowest(const double &array[], + int depth, + int startPos) + { + int index=startPos; +//--- start index validation + if(startPos<0) + { + Print("Invalid parameter in the function iLowest, startPos =",startPos); + return 0; + } + int size=ArraySize(array); +//--- depth correction if need + if(startPos-depth<0) depth=startPos; + double min=array[startPos]; +//--- start searching + for(int i=startPos;i>startPos-depth;i--) + { + if(array[i]0) + { + i=rates_total-1; + //--- searching third extremum from the last uncompleted bar + while(counterZrates_total-100) + { + res=ZigzagBuffer[i]; + if(res!=0) counterZ++; + i--; + } + i++; + limit=i; + + //--- what type of exremum we are going to find + if(LowMapBuffer[i]!=0) + { + curlow=LowMapBuffer[i]; + whatlookfor=Pike; + } + else + { + curhigh=HighMapBuffer[i]; + whatlookfor=Sill; + } + //--- chipping + for(i=limit+1;ideviation) val=0.0; + else + { + for(back=1;back<=ExtBackstep;back++) + { + res=LowMapBuffer[shift-back]; + if((res!=0) && (res>val)) LowMapBuffer[shift-back]=0.0; + } + } + } + if(rangeBarsIndicator.Low[shift]==val) LowMapBuffer[shift]=val; else LowMapBuffer[shift]=0.0; + //--- high + val=rangeBarsIndicator.High[iHighest(rangeBarsIndicator.High,ExtDepth,shift)]; + if(val==lasthigh) val=0.0; + else + { + lasthigh=val; + if((val-rangeBarsIndicator.High[shift])>deviation) val=0.0; + else + { + for(back=1;back<=ExtBackstep;back++) + { + res=HighMapBuffer[shift-back]; + if((res!=0) && (reslasthigh && LowMapBuffer[shift]==0.0) + { + ZigzagBuffer[lasthighpos]=0.0; + lasthighpos=shift; + lasthigh=HighMapBuffer[shift]; + ZigzagBuffer[shift]=lasthigh; + } + if(LowMapBuffer[shift]!=0.0 && HighMapBuffer[shift]==0.0) + { + lastlow=LowMapBuffer[shift]; + lastlowpos=shift; + ZigzagBuffer[shift]=lastlow; + whatlookfor=Pike; + } + break; + default: return(rates_total); + } + } + +//--- return value of _prev_calculated for next call + return(rates_total); + } +//+------------------------------------------------------------------+ diff --git a/Indicators/RangeBars/RangeBars_dt_oscillator.mq5 b/Indicators/RangeBars/RangeBars_dt_oscillator.mq5 new file mode 100644 index 0000000..8737b07 --- /dev/null +++ b/Indicators/RangeBars/RangeBars_dt_oscillator.mq5 @@ -0,0 +1,247 @@ + + +//+------------------------------------------------------------------+ +//| DT oscillator.mq5 | +//+------------------------------------------------------------------+ +#property copyright "www.forex-tsd.com" +#property link "www.forex-tsd.com" +#property version "1.00" + +#property indicator_separate_window +#property indicator_buffers 4 +#property indicator_plots 3 +#property indicator_level1 70 +#property indicator_level2 30 + +// +// +// +// +// + +#property indicator_type1 DRAW_FILLING +#property indicator_color1 PowderBlue,MistyRose +#property indicator_label1 "DT oscillator filling" +#property indicator_type2 DRAW_LINE +#property indicator_color2 DeepSkyBlue +#property indicator_width2 2 +#property indicator_label2 "DT oscillator" +#property indicator_type3 DRAW_LINE +#property indicator_color3 PaleVioletRed +#property indicator_width3 1 +#property indicator_label3 "DT oscillator signal" + +// +// +// +// +// + +input int RsiPeriod = 13; // Rsi period +input int StochPeriod = 8; // Stochastic period +input int SlowingPeriod = 5; // Slowing +input int SignalPeriod = 3; // Signal period +input bool TapeVisible = true; // Tape visibility + +// +// +// +// +// +// + +double dtosc[]; +double dtoss[]; +double dtosf1[]; +double dtosf2[]; + +// +// +// + +#include +RangeBarIndicator rangeBarsIndicator; + +// +// +// + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +// +// +// +// +// + +int OnInit() +{ + SetIndexBuffer( 0,dtosf1,INDICATOR_DATA); + SetIndexBuffer( 1,dtosf2,INDICATOR_DATA); + SetIndexBuffer( 2,dtosc ,INDICATOR_DATA); + SetIndexBuffer( 3,dtoss ,INDICATOR_DATA); + return(0); +} + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +// +// +// +// +// + +double rsibuf[]; +double stobuf[]; + +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 &TickVolume[], + const long &Volume[], + const int &Spread[]) +{ + // + // Process data through MedianRenko indicator + // + + if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,Time)) + return(0); + + // + // Make the following modifications in the code below: + // + // rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated + // + // rangeBarsIndicator.Open[] should be used instead of open[] + // rangeBarsIndicator.Low[] should be used instead of low[] + // rangeBarsIndicator.High[] should be used instead of high[] + // rangeBarsIndicator.Close[] should be used instead of close[] + // + // rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed + // + // rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time. + // (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used + // + // rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[] + // rangeBarsIndicator.Real_volume[] should be used instead of Volume[] + // (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used + // + // rangeBarsIndicator.Price[] should be used instead of Price[] + // (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used + // + + int _prev_calculated = rangeBarsIndicator.GetPrevCalculated(); + + // + // + // + // + // + + if (ArraySize(rsibuf)!=rates_total) ArrayResize(rsibuf,rates_total); + if (ArraySize(stobuf)!=rates_total) ArrayResize(stobuf,rates_total); + + // + // + // + // + // + + for (int i=(int)MathMax(_prev_calculated-1,0); i=0; k++) + { + min = MathMin(rsibuf[i-k],min); + max = MathMax(rsibuf[i-k],max); + } + if (max!=min) + stobuf[i] = 100*(rsibuf[i]-min)/(max-min); + else stobuf[i] = 0; + + // + // + // + // + // + + dtosc[i] = 0; for (int k=0; k=0; k++) dtosc[i] += stobuf[i-k]; dtosc[i] /= SlowingPeriod; + dtoss[i] = 0; for (int k=0; k=0; k++) dtoss[i] += dtosc[i-k]; dtoss[i] /= SignalPeriod; + if (TapeVisible) + { dtosf1[i] = dtosc[i]; dtosf2[i] = dtoss[i]; } + else { dtosf1[i] = EMPTY_VALUE; dtosf2[i] = EMPTY_VALUE; } + } + + // + // + // + // + // + + return(rates_total); +} + + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +// +// +// +// +// + +double rsiWork[][3]; +#define _price 0 +#define _chgAvg 1 +#define _totChg 2 + +// +// +// +// +// + +double iRsi(double price, double period, int i, int bars) +{ + if (ArrayRange(rsiWork,0)!=bars) ArrayResize(rsiWork,bars); + + // + // + // + // + // + // + + rsiWork[i][_price] = price; + if (i==0) + { + rsiWork[i][_chgAvg] = 0; + rsiWork[i][_totChg] = 0; + return(50); + } + + // + // + // + // + // + + double sf = 1.0 / period; + double change = rsiWork[i][_price]-rsiWork[i-1][_price]; + + rsiWork[i][_chgAvg] = rsiWork[i-1][_chgAvg] + sf*( change -rsiWork[i-1][_chgAvg]); + rsiWork[i][_totChg] = rsiWork[i-1][_totChg] + sf*(MathAbs(change)-rsiWork[i-1][_totChg]); + + double changeRatio = (rsiWork[i][_totChg]!=0 ? rsiWork[i][_chgAvg]/rsiWork[i][_totChg] : 0 ); + return(50.0*(changeRatio+1.0)); +} diff --git a/Indicators/RangeBars/RangeBars_gmma.mq5 b/Indicators/RangeBars/RangeBars_gmma.mq5 new file mode 100644 index 0000000..c423ce3 Binary files /dev/null and b/Indicators/RangeBars/RangeBars_gmma.mq5 differ diff --git a/Indicators/RangeBars/RangeBars_volumes.mq5 b/Indicators/RangeBars/RangeBars_volumes.mq5 new file mode 100644 index 0000000..4b17645 --- /dev/null +++ b/Indicators/RangeBars/RangeBars_volumes.mq5 @@ -0,0 +1,139 @@ +//+------------------------------------------------------------------+ +//| Volumes.mq5 | +//| Copyright 2009-2017, MetaQuotes Software Corp. | +//| http://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "2009-2017, MetaQuotes Software Corp." +#property link "http://www.mql5.com" +//---- indicator settings +#property indicator_separate_window +#property indicator_buffers 2 +#property indicator_plots 1 +#property indicator_type1 DRAW_COLOR_HISTOGRAM +#property indicator_color1 Green,Red +#property indicator_style1 0 +#property indicator_width1 1 +#property indicator_minimum 0.0 +//--- input data +input ENUM_APPLIED_VOLUME InpVolumeType=VOLUME_TICK; // Volumes +//---- indicator buffers +double ExtVolumesBuffer[]; +double ExtColorsBuffer[]; + +// +// +// + +#include +RangeBarIndicator rangeBarsIndicator; + +// +// +// +//+------------------------------------------------------------------+ +//| Custom indicator initialization function | +//+------------------------------------------------------------------+ +void OnInit() + { +//---- buffers + SetIndexBuffer(0,ExtVolumesBuffer,INDICATOR_DATA); + SetIndexBuffer(1,ExtColorsBuffer,INDICATOR_COLOR_INDEX); +//---- name for DataWindow and indicator subwindow label + IndicatorSetString(INDICATOR_SHORTNAME,"Volumes"); +//---- indicator digits + IndicatorSetInteger(INDICATOR_DIGITS,0); + + rangeBarsIndicator.SetGetVolumesFlag(); +//---- + } +//+------------------------------------------------------------------+ +//| Volumes | +//+------------------------------------------------------------------+ +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[]) + { +//---check for rates total + if(rates_total<2) + return(0); + + // + // Process data through MedianRenko indicator + // + + if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,time)) + return(0); + + // + // Make the following modifications in the code below: + // + // rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated + // + // rangeBarsIndicator.Open[] should be used instead of open[] + // rangeBarsIndicator.Low[] should be used instead of low[] + // rangeBarsIndicator.High[] should be used instead of high[] + // rangeBarsIndicator.Close[] should be used instead of close[] + // + // rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed + // + // rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time. + // (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used + // + // rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[] + // rangeBarsIndicator.Real_volume[] should be used instead of Volume[] + // (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used + // + // rangeBarsIndicator.Price[] should be used instead of Price[] + // (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used + // + + int _prev_calculated = rangeBarsIndicator.GetPrevCalculated(); + + // + // + // + +//--- starting work + int start=_prev_calculated-1; +//--- correct position + if(start<1) start=1; +//--- main cycle + if(InpVolumeType==VOLUME_TICK) + CalculateVolume(start,rates_total,rangeBarsIndicator.Tick_volume); + else + CalculateVolume(start,rates_total,rangeBarsIndicator.Real_volume); +//--- OnCalculate done. Return new prev_calculated. + return(rates_total); + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +void CalculateVolume(const int nPosition, + const int nRatesCount, + const long &SrcBuffer[]) + { + ExtVolumesBuffer[0]=(double)SrcBuffer[0]; + ExtColorsBuffer[0]=0.0; +//--- + for(int i=nPosition;idPrevVolume) + ExtColorsBuffer[i]=0.0; + else + ExtColorsBuffer[i]=1.0; + } +//--- + } +//+------------------------------------------------------------------+