Updated files for verison 1.47 of the plug-in
This commit is contained in:
@@ -0,0 +1,309 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,318 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,564 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RangeBars.mqh ver:1.47.0 |
|
||||
//| Copyright 2017, AZ-iNVEST |
|
||||
//| http://www.az-invest.eu |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2017, AZ-iNVEST"
|
||||
#property link "http://www.az-invest.eu"
|
||||
|
||||
#define RANGEBAR_INDICATOR_NAME "Market\\Range Bars Charting"
|
||||
|
||||
#define RANGEBAR_MA1 0
|
||||
#define RANGEBAR_MA2 1
|
||||
#define RANGEBAR_CHANNEL_HIGH 2
|
||||
#define RANGEBAR_CHANNEL_MID 3
|
||||
#define RANGEBAR_CHANNEL_LOW 4
|
||||
#define RANGEBAR_OPEN 5
|
||||
#define RANGEBAR_HIGH 6
|
||||
#define RANGEBAR_LOW 7
|
||||
#define RANGEBAR_CLOSE 8
|
||||
#define RANGEBAR_BAR_OPEN_TIME 9
|
||||
#define RANGEBAR_TICK_VOLUME 10
|
||||
|
||||
#include <RangeBarSettings.mqh>
|
||||
|
||||
class RangeBars
|
||||
{
|
||||
private:
|
||||
|
||||
RangeBarSettings * rangeBarSettings;
|
||||
|
||||
//
|
||||
// Median renko indicator handle
|
||||
//
|
||||
|
||||
int rangeBarsHandle;
|
||||
string rangeBarsSymbol;
|
||||
|
||||
public:
|
||||
|
||||
RangeBars();
|
||||
RangeBars(string symbol);
|
||||
~RangeBars(void);
|
||||
|
||||
int Init();
|
||||
void Deinit();
|
||||
bool Reload();
|
||||
|
||||
int GetHandle(void) { return rangeBarsHandle; };
|
||||
bool GetMqlRates(MqlRates &ratesInfoArray[], int start, int count);
|
||||
int GetOLHCForIndicatorCalc(double &o[],double &l[],double &h[],double &c[], int start, int count);
|
||||
int GetOLHCAndApplPriceForIndicatorCalc(double &o[],double &l[],double &h[],double &c[],double &price[],ENUM_APPLIED_PRICE applied_price, int start, int count);
|
||||
double CalcAppliedPrice(const MqlRates &_rates, ENUM_APPLIED_PRICE applied_price);
|
||||
double CalcAppliedPrice(const double &o,const double &l,const double &h,const double &c,ENUM_APPLIED_PRICE applied_price);
|
||||
bool GetMA1(double &MA[], int start, int count);
|
||||
bool GetMA2(double &MA[], int start, int count);
|
||||
bool GetDonchian(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count);
|
||||
bool GetBollingerBands(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count);
|
||||
bool GetSuperTrend(double &SuperTrendHighArray[], double &SuperTrendArray[], double &SuperTrendLowArray[], int start, int count);
|
||||
bool IsNewBar();
|
||||
|
||||
private:
|
||||
|
||||
bool GetChannel(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count);
|
||||
|
||||
};
|
||||
|
||||
RangeBars::RangeBars(void)
|
||||
{
|
||||
rangeBarSettings = new RangeBarSettings();
|
||||
rangeBarsHandle = INVALID_HANDLE;
|
||||
rangeBarsSymbol = _Symbol;
|
||||
}
|
||||
|
||||
RangeBars::RangeBars(string symbol)
|
||||
{
|
||||
rangeBarSettings = new RangeBarSettings();
|
||||
rangeBarsHandle = INVALID_HANDLE;
|
||||
rangeBarsSymbol = symbol;
|
||||
}
|
||||
|
||||
RangeBars::~RangeBars(void)
|
||||
{
|
||||
if(rangeBarSettings != NULL)
|
||||
delete rangeBarSettings;
|
||||
}
|
||||
|
||||
//
|
||||
// Function for initializing the median renko indicator handle
|
||||
//
|
||||
|
||||
int RangeBars::Init()
|
||||
{
|
||||
if(!MQLInfoInteger((int)MQL5_TESTING))
|
||||
{
|
||||
if(!rangeBarSettings.Load())
|
||||
{
|
||||
if(rangeBarsHandle != INVALID_HANDLE)
|
||||
{
|
||||
// could not read new settings - keep old settings
|
||||
|
||||
return rangeBarsHandle;
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to load indicator settings.");
|
||||
Alert("You need to put the Median Renko indicator on your chart first!");
|
||||
return INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
if(rangeBarsHandle != INVALID_HANDLE)
|
||||
Deinit();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef SHOW_INDICATOR_INPUTS
|
||||
//
|
||||
// Load settings from EA inputs
|
||||
//
|
||||
rangeBarSettings.Load();
|
||||
#else
|
||||
//
|
||||
// Save indicator inputs for use by EA attached to same chart.
|
||||
//
|
||||
rangeBarSettings.Save();
|
||||
#endif
|
||||
}
|
||||
|
||||
RANGEBAR_SETTINGS s = rangeBarSettings.Get();
|
||||
|
||||
//RangeBarSettings.Debug();
|
||||
|
||||
rangeBarsHandle = iCustom(this.rangeBarsSymbol,PERIOD_M1,RANGEBAR_INDICATOR_NAME,
|
||||
s.barSizeInTicks,
|
||||
s._startFromDateTime,
|
||||
s.resetOpenOnNewTradingDay,
|
||||
showNextBarLevels,
|
||||
HighThresholdIndicatorColor,
|
||||
LowThresholdIndicatorColor,
|
||||
showCurrentBarOpenTime,
|
||||
InfoTextColor,
|
||||
UseSoundSignalOnNewBar,
|
||||
OnlySignalReversalBars,
|
||||
UseAlertWindow,
|
||||
SendPushNotifications,
|
||||
SoundFileBull,
|
||||
SoundFileBear,
|
||||
s.MA1on,
|
||||
s.MA1period,
|
||||
s.MA1method,
|
||||
s.MA1applyTo,
|
||||
s.MA1shift,
|
||||
s.MA2on,
|
||||
s.MA2period,
|
||||
s.MA2method,
|
||||
s.MA2applyTo,
|
||||
s.MA2shift,
|
||||
s.ShowChannel,
|
||||
"",
|
||||
s.DonchianPeriod,
|
||||
s.BBapplyTo,
|
||||
s.BollingerBandsPeriod,
|
||||
s.BollingerBandsDeviations,
|
||||
s.SuperTrendPeriod,
|
||||
s.SuperTrendMultiplier,
|
||||
"",
|
||||
UsedInEA);
|
||||
|
||||
if(rangeBarsHandle == INVALID_HANDLE)
|
||||
{
|
||||
Print("RangeBars indicator init failed on error ",GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("RangeBars indicator init OK");
|
||||
}
|
||||
|
||||
return rangeBarsHandle;
|
||||
}
|
||||
|
||||
//
|
||||
// Function for reloading the Median Renko indicator if needed
|
||||
//
|
||||
|
||||
bool RangeBars::Reload()
|
||||
{
|
||||
if(rangeBarSettings.Changed())
|
||||
{
|
||||
if(Init() == INVALID_HANDLE)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Function for releasing the Median Renko indicator hanlde - free resources
|
||||
//
|
||||
|
||||
void RangeBars::Deinit()
|
||||
{
|
||||
if(rangeBarsHandle == INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
if(IndicatorRelease(rangeBarsHandle))
|
||||
Print("RangeBars indicator handle released");
|
||||
else
|
||||
Print("Failed to release RangeBars indicator handle");
|
||||
}
|
||||
|
||||
//
|
||||
// Function for detecting a new Renko bar
|
||||
//
|
||||
|
||||
bool RangeBars::IsNewBar()
|
||||
{
|
||||
MqlRates currentRenko[1];
|
||||
static MqlRates prevRenko;
|
||||
|
||||
GetMqlRates(currentRenko,1,1);
|
||||
|
||||
if((prevRenko.open != currentRenko[0].open) ||
|
||||
(prevRenko.high != currentRenko[0].high) ||
|
||||
(prevRenko.low != currentRenko[0].low) ||
|
||||
(prevRenko.close != currentRenko[0].close))
|
||||
{
|
||||
prevRenko.open = currentRenko[0].open;
|
||||
prevRenko.high = currentRenko[0].high;
|
||||
prevRenko.low = currentRenko[0].low;
|
||||
prevRenko.close = currentRenko[0].close;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Get "count" Renko MqlRates into "ratesInfoArray[]" array starting from "start" bar
|
||||
//
|
||||
|
||||
bool RangeBars::GetMqlRates(MqlRates &ratesInfoArray[], int start, int count)
|
||||
{
|
||||
double o[],l[],h[],c[],time[],tick_volume[];
|
||||
|
||||
if(ArrayResize(o,count) == -1)
|
||||
return false;
|
||||
if(ArrayResize(l,count) == -1)
|
||||
return false;
|
||||
if(ArrayResize(h,count) == -1)
|
||||
return false;
|
||||
if(ArrayResize(c,count) == -1)
|
||||
return false;
|
||||
if(ArrayResize(time,count) == -1)
|
||||
return false;
|
||||
if(ArrayResize(tick_volume,count) == -1)
|
||||
return false;
|
||||
|
||||
|
||||
if(CopyBuffer(rangeBarsHandle,RANGEBAR_OPEN,start,count,o) == -1)
|
||||
return false;
|
||||
if(CopyBuffer(rangeBarsHandle,RANGEBAR_LOW,start,count,l) == -1)
|
||||
return false;
|
||||
if(CopyBuffer(rangeBarsHandle,RANGEBAR_HIGH,start,count,h) == -1)
|
||||
return false;
|
||||
if(CopyBuffer(rangeBarsHandle,RANGEBAR_CLOSE,start,count,c) == -1)
|
||||
return false;
|
||||
if(CopyBuffer(rangeBarsHandle,RANGEBAR_BAR_OPEN_TIME,start,count,time) == -1)
|
||||
return false;
|
||||
if(CopyBuffer(rangeBarsHandle,RANGEBAR_TICK_VOLUME,start,count,tick_volume) == -1)
|
||||
return false;
|
||||
|
||||
if(ArrayResize(ratesInfoArray,count) == -1)
|
||||
return false;
|
||||
|
||||
int tempOffset = count-1;
|
||||
for(int i=0; i<count; i++)
|
||||
{
|
||||
ratesInfoArray[tempOffset-i].open = o[i];
|
||||
ratesInfoArray[tempOffset-i].low = l[i];
|
||||
ratesInfoArray[tempOffset-i].high = h[i];
|
||||
ratesInfoArray[tempOffset-i].close = c[i];
|
||||
ratesInfoArray[tempOffset-i].time = (datetime)time[i];
|
||||
ratesInfoArray[tempOffset-i].tick_volume = (long)tick_volume[i];
|
||||
}
|
||||
|
||||
ArrayFree(o);
|
||||
ArrayFree(l);
|
||||
ArrayFree(h);
|
||||
ArrayFree(c);
|
||||
ArrayFree(time);
|
||||
ArrayFree(tick_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)
|
||||
{
|
||||
if(ArrayResize(o,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)
|
||||
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(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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return _count;
|
||||
}
|
||||
|
||||
//
|
||||
// Get "count" MovingAverage1 values into "MA[]" array starting from "start" bar
|
||||
//
|
||||
|
||||
bool RangeBars::GetMA1(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_MA1,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" MovingAverage2 values into "MA[]" starting from "start" bar
|
||||
//
|
||||
|
||||
bool RangeBars::GetMA2(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_MA2,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
|
||||
//
|
||||
|
||||
bool RangeBars::GetDonchian(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count)
|
||||
{
|
||||
return GetChannel(HighArray,MidArray,LowArray,start,count);
|
||||
}
|
||||
|
||||
//
|
||||
// Get "count" Bollinger band values into "HighArray[]", "MidArray[]", and "LowArray[]" arrays starting from "start" bar
|
||||
//
|
||||
|
||||
bool RangeBars::GetBollingerBands(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count)
|
||||
{
|
||||
return GetChannel(HighArray,MidArray,LowArray,start,count);
|
||||
}
|
||||
|
||||
//
|
||||
// Get "count" SuperTrend values into "HighArray[]", "MidArray[]", and "LowArray[]" arrays starting from "start" bar
|
||||
//
|
||||
|
||||
bool RangeBars::GetSuperTrend(double &SuperTrendHighArray[], double &SuperTrendArray[], double &SuperTrendLowArray[], int start, int count)
|
||||
{
|
||||
return GetChannel(SuperTrendHighArray,SuperTrendArray,SuperTrendLowArray,start,count);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Private function used by GetRenkoDonchian and GetRenkoBollingerBands functions to get data
|
||||
//
|
||||
|
||||
bool RangeBars::GetChannel(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count)
|
||||
{
|
||||
double tempH[], tempM[], tempL[];
|
||||
|
||||
if(ArrayResize(tempH,count) == -1)
|
||||
return false;
|
||||
if(ArrayResize(tempM,count) == -1)
|
||||
return false;
|
||||
if(ArrayResize(tempL,count) == -1)
|
||||
return false;
|
||||
|
||||
if(ArrayResize(HighArray,count) == -1)
|
||||
return false;
|
||||
if(ArrayResize(MidArray,count) == -1)
|
||||
return false;
|
||||
if(ArrayResize(LowArray,count) == -1)
|
||||
return false;
|
||||
|
||||
if(CopyBuffer(rangeBarsHandle,RANGEBAR_CHANNEL_HIGH,start,count,tempH) == -1)
|
||||
return false;
|
||||
if(CopyBuffer(rangeBarsHandle,RANGEBAR_CHANNEL_MID,start,count,tempM) == -1)
|
||||
return false;
|
||||
if(CopyBuffer(rangeBarsHandle,RANGEBAR_CHANNEL_LOW,start,count,tempL) == -1)
|
||||
return false;
|
||||
|
||||
int tempOffset = count-1;
|
||||
for(int i=0; i<count; i++)
|
||||
{
|
||||
HighArray[tempOffset-i] = tempH[i];
|
||||
MidArray[tempOffset-i] = tempM[i];
|
||||
LowArray[tempOffset-i] = tempL[i];
|
||||
}
|
||||
|
||||
ArrayFree(tempH);
|
||||
ArrayFree(tempM);
|
||||
ArrayFree(tempL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
Reference in New Issue
Block a user