Update to version 2.02
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,766 @@
|
||||
#property copyright "Copyright 2017, AZ-iNVEST"
|
||||
#property link "http://www.az-invest.eu"
|
||||
#property version "2.02"
|
||||
#include <AZ-INVEST/SDK/RangeBars.mqh>
|
||||
|
||||
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<size; i++)
|
||||
buffer[i-1] = buffer[i];
|
||||
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
#property copyright "Copyright 2017, AZ-iNVEST"
|
||||
#property link "http://www.az-invest.eu"
|
||||
|
||||
#include <AZ-INVEST/SDK/CommonSettings.mqh>
|
||||
#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;
|
||||
}
|
||||
@@ -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 <RangeBarSettings.mqh>
|
||||
#include <AZ-INVEST/SDK/RangeBarSettings.mqh>
|
||||
|
||||
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<count; i++)
|
||||
{
|
||||
if(CopyBuffer(rangeBarsHandle,RANGEBAR_CLOSE,start,_count,price) == -1)
|
||||
return -1;
|
||||
}
|
||||
else if(applied_price == PRICE_OPEN)
|
||||
{
|
||||
if(CopyBuffer(rangeBarsHandle,RANGEBAR_OPEN,start,_count,price) == -1)
|
||||
return -1;
|
||||
}
|
||||
else if(applied_price == PRICE_HIGH)
|
||||
{
|
||||
if(CopyBuffer(rangeBarsHandle,RANGEBAR_HIGH,start,_count,price) == -1)
|
||||
return -1;
|
||||
}
|
||||
else if(applied_price == PRICE_LOW)
|
||||
{
|
||||
if(CopyBuffer(rangeBarsHandle,RANGEBAR_LOW,start,_count,price) == -1)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i=0; i<_count; i++)
|
||||
{
|
||||
price[i] = CalcAppliedPrice(o[i],l[i],h[i],c[i],applied_price);
|
||||
}
|
||||
buy[tempOffset-i] = b[i];
|
||||
sell[tempOffset-i] = s[i];
|
||||
buySell[tempOffset-i] = bs[i];
|
||||
}
|
||||
|
||||
ArrayFree(b);
|
||||
ArrayFree(s);
|
||||
ArrayFree(bs);
|
||||
|
||||
return _count;
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
@@ -448,6 +434,31 @@ bool RangeBars::GetMA2(double &MA[], int start, int count)
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Get "count" MovingAverage3 values into "MA[]" starting from "start" bar
|
||||
//
|
||||
|
||||
bool RangeBars::GetMA3(double &MA[], int start, int count)
|
||||
{
|
||||
double tempMA[];
|
||||
if(ArrayResize(tempMA,count) == -1)
|
||||
return false;
|
||||
|
||||
if(ArrayResize(MA,count) == -1)
|
||||
return false;
|
||||
|
||||
if(CopyBuffer(rangeBarsHandle,RANGEBAR_MA3,start,count,tempMA) == -1)
|
||||
return false;
|
||||
|
||||
for(int i=0; i<count; i++)
|
||||
{
|
||||
MA[count-1-i] = tempMA[i];
|
||||
}
|
||||
|
||||
ArrayFree(tempMA);
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Get "count" Renko Donchian channel values into "HighArray[]", "MidArray[]", and "LowArray[]" arrays starting from "start" bar
|
||||
//
|
||||
@@ -484,6 +495,9 @@ bool RangeBars::GetChannel(double &HighArray[], double &MidArray[], double &LowA
|
||||
{
|
||||
double tempH[], tempM[], tempL[];
|
||||
|
||||
#ifdef P_RANGEBAR_BR
|
||||
return false;
|
||||
#else
|
||||
if(ArrayResize(tempH,count) == -1)
|
||||
return false;
|
||||
if(ArrayResize(tempM,count) == -1)
|
||||
@@ -518,48 +532,6 @@ bool RangeBars::GetChannel(double &HighArray[], double &MidArray[], double &LowA
|
||||
ArrayFree(tempL);
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Function used for calculating the Apllied Price based on Renko OLHC values
|
||||
//
|
||||
|
||||
double RangeBars::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 RangeBars::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;
|
||||
}
|
||||
@@ -0,0 +1,611 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| TradeFunctions.mqh |
|
||||
//| Copyright 2017, AZ-iNVEST |
|
||||
//| http://www.az-invest.eu |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2017, AZ-iNVEST"
|
||||
#property link "http://www.az-invest.eu"
|
||||
#include <Trade\Trade.mqh>
|
||||
|
||||
#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<positions;i++)
|
||||
{
|
||||
ResetLastError();
|
||||
|
||||
ulong _ticket=PositionGetTicket(i);
|
||||
|
||||
if(_ticket!=0)
|
||||
{
|
||||
if(PositionSelectByTicket(_ticket))
|
||||
{
|
||||
if(magicNumber > 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<positions;i++)
|
||||
{
|
||||
ResetLastError();
|
||||
|
||||
ulong _ticket=PositionGetTicket(i);
|
||||
|
||||
if(_ticket!=0)
|
||||
{
|
||||
if(PositionSelectByTicket(_ticket))
|
||||
{
|
||||
|
||||
if(magicNumber > 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<positions;i++)
|
||||
{
|
||||
ResetLastError();
|
||||
|
||||
ulong _ticket=PositionGetTicket(i);
|
||||
|
||||
if(_ticket!=0)
|
||||
{
|
||||
if(PositionSelectByTicket(_ticket))
|
||||
{
|
||||
if(magicNumber > 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);
|
||||
}
|
||||
|
||||
@@ -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 <RangeBars.mqh>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user