version 3.14

This commit is contained in:
Artur
2021-04-28 17:27:12 +02:00
parent a73e2c0713
commit 380071b195
131 changed files with 5283 additions and 235 deletions
+52
View File
@@ -0,0 +1,52 @@
//#define DEVELOPER_VERSION
//#define DISPLAY_DEBUG_MSG
#define MQL5_MARKET_VERSION
//#define P_RENKO_BR_PRO
//#define ULTIMATE_RENKO_LICENSE
#define RANGEBAR_LICENSE
//#define SECONDSCHART_LICENSE
//#define TICKCHART_LICENSE (obsolete)
//#define VOLUMECHART_LICENSE
//#define LINEBREAKCHART_LICENSE
#ifdef P_RENKO_BR_PRO
#include <AZ-INVEST/SDK/MedianRenkoIndicator.mqh>
#define AZINVEST_CCI MedianRenkoIndicator
#endif
#ifdef TICKCHART_LICENSE
#include <AZ-INVEST/SDK/TickChartIndicator.mqh>
#define AZINVEST_CCI TickChartIndicator
#endif
#ifdef RANGEBAR_LICENSE
#include <AZ-INVEST/SDK/RangeBarIndicator.mqh>
#define AZINVEST_CCI RangeBarIndicator
#endif
#ifdef ULTIMATE_RENKO_LICENSE
#include <AZ-INVEST/SDK/MedianRenkoIndicator.mqh>
#define AZINVEST_CCI MedianRenkoIndicator
#endif
#ifdef SECONDSCHART_LICENSE
#include <AZ-INVEST/SDK/SecondsChartIndicator.mqh>
#define AZINVEST_CCI SecondsChartIndicator
#endif
#ifdef VOLUMECHART_LICENSE
#include <AZ-INVEST/SDK/VolumeChartIndicator.mqh>
#define AZINVEST_CCI VolumeChartIndicator
#endif
#ifdef LINEBREAKCHART_LICENSE
#include <AZ-INVEST/SDK/LineBreakChartIndicator.mqh>
#define AZINVEST_CCI LineBreakChartIndicator
#endif
#ifdef AZINVEST_CCI
AZINVEST_CCI customChartIndicator;
#endif
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+83
View File
@@ -0,0 +1,83 @@
// RSI on Buffer
int RsiOnBuffer(const int rates_total,const int prev_calculated,const int begin,
const int period,const double& price[],double& rsiBuffer[], double &posBuffer[], double &negBuffer[])
{
int i, pos;
double diff;
//--- check for data
if(period<=1 || rates_total-begin<period) return(0);
//--- save as_series flags
bool as_series_price=ArrayGetAsSeries(price);
bool as_series_rsibuffer=ArrayGetAsSeries(rsiBuffer);
bool as_series_posbuffer=ArrayGetAsSeries(posBuffer);
bool as_series_negbuffer=ArrayGetAsSeries(negBuffer);
if(as_series_price) ArraySetAsSeries(price,false);
if(as_series_rsibuffer) ArraySetAsSeries(rsiBuffer,false);
if(as_series_posbuffer) ArraySetAsSeries(posBuffer,false);
if(as_series_negbuffer) ArraySetAsSeries(negBuffer,false);
//--- preliminary calculations
pos=prev_calculated-1;
if(pos<=period)
{
//--- first RSIPeriod values of the indicator are not calculated
rsiBuffer[0]=0.0;
posBuffer[0]=0.0;
negBuffer[0]=0.0;
double sump=0.0;
double sumn=0.0;
for(i=1; i<=period; i++)
{
rsiBuffer[i]=0.0;
posBuffer[i]=0.0;
negBuffer[i]=0.0;
diff=price[i]-price[i-1];
if(diff>0)
sump+=diff;
else
sumn-=diff;
}
//--- calculate first visible value
posBuffer[period]=sump/period;
negBuffer[period]=sumn/period;
if(negBuffer[period]!=0.0)
rsiBuffer[period]=100.0-(100.0/(1.0+posBuffer[period]/negBuffer[period]));
else
{
if(posBuffer[period]!=0.0)
rsiBuffer[period]=100.0;
else
rsiBuffer[period]=50.0;
}
//--- prepare the position value for main calculation
pos=period+1;
}
//--- the main loop of calculations
for(i=pos; i<rates_total && !IsStopped(); i++)
{
diff=price[i]-price[i-1];
posBuffer[i]=(posBuffer[i-1]*(period-1)+(diff>0.0?diff:0.0))/period;
negBuffer[i]=(negBuffer[i-1]*(period-1)+(diff<0.0?-diff:0.0))/period;
if(negBuffer[i]!=0.0)
rsiBuffer[i]=100.0-100.0/(1+posBuffer[i]/negBuffer[i]);
else
{
if(posBuffer[i]!=0.0)
rsiBuffer[i]=100.0;
else
rsiBuffer[i]=50.0;
}
}
//--- restore as_series flags
if(as_series_price) ArraySetAsSeries(price,true);
if(as_series_rsibuffer) ArraySetAsSeries(rsiBuffer,true);
if(as_series_posbuffer) ArraySetAsSeries(posBuffer,true);
if(as_series_negbuffer) ArraySetAsSeries(negBuffer,true);
//---
return(rates_total);
}
//+------------------------------------------------------------------+
@@ -23,13 +23,16 @@
#else // user defined settings
input int barSizeInTicks = 100; // Range bar size (in ticks)
input int barSizeInTicks = 100; // Range bar size (in ticks)
input int showNumberOfDays = 5; // Show history for number of days
input group "### ATR based bar size calculation"
input ENUM_BOOL atrEnabled = false; // Enable ATR based bar size calculation
ENUM_TIMEFRAMES atrTimeFrame = PERIOD_D1; // Use ATR period
input ENUM_TIMEFRAMES atrTimeFrame = PERIOD_D1; // Use ATR period
input int atrPeriod = 14; // ATR period
input int atrPercentage = 10; // Use percentage of ATR
input int showNumberOfDays = 5; // Show history for number of days
input group "### Chart synchronization"
input ENUM_BOOL resetOpenOnNewTradingDay = true; // Synchronize first bar's open on new day
#endif
+19 -14
View File
@@ -4,7 +4,15 @@
#ifdef DEVELOPER_VERSION
#define RANGEBAR_INDICATOR_NAME "RangeBars\\RangeBarsOverlay300"
#else
#define RANGEBAR_INDICATOR_NAME "Market\\Range Bars Charting"
#ifdef RANGEBAR_LICENSE
#ifdef MQL5_MARKET_VERSION
#define RANGEBAR_INDICATOR_NAME "Market\\Range Bars Charting"
#else
#define RANGEBAR_INDICATOR_NAME "RangeBars"
#endif
#else
#define RANGEBAR_INDICATOR_NAME "Market\\Range Bars Charting"
#endif
#endif
#define RANGEBAR_OPEN 00
@@ -188,50 +196,46 @@ int RangeBars::Init()
rangeBarsHandle = iCustom(this.rangeBarsSymbol, _Period, RANGEBAR_INDICATOR_NAME,
s.barSizeInTicks,
s.showNumberOfDays,
"=",
s.atrEnabled,
//s.atrTimeFrame,
s.atrTimeFrame,
s.atrPeriod,
s.atrPercentage,
s.showNumberOfDays, s.resetOpenOnNewTradingDay,
TradingSessionTime,
"=",
s.resetOpenOnNewTradingDay,
"=",
showPivots,
pivotPointCalculationType,
RColor,
PColor,
SColor,
PDHColor,
PDLColor,
PDCColor,
"=",
AlertMeWhen,
AlertNotificationType,
cis.MA1on,
"=",
cis.MA1lineType,
cis.MA1period,
cis.MA1method,
cis.MA1applyTo,
cis.MA1shift,
cis.MA1priceLabel,
cis.MA2on,
cis.MA2lineType,
cis.MA2period,
cis.MA2method,
cis.MA2applyTo,
cis.MA2shift,
cis.MA2priceLabel,
cis.MA3on,
cis.MA3lineType,
cis.MA3period,
cis.MA3method,
cis.MA3applyTo,
cis.MA3shift,
cis.MA3priceLabel,
cis.MA4on,
cis.MA4lineType,
cis.MA4period,
cis.MA4method,
cis.MA4applyTo,
cis.MA4shift,
cis.MA4priceLabel,
"=",
cis.ShowChannel,
cis.ChannelPeriod,
cis.ChannelAtrPeriod,
@@ -240,6 +244,7 @@ int RangeBars::Init()
cis.ChannelBandsDeviations,
cis.ChannelPriceLabel,
cis.ChannelMidPriceLabel,
"=",
true); // used in EA
// TopBottomPaddingPercentage,
// showCurrentBarOpenTime,
+76
View File
@@ -0,0 +1,76 @@
//
// Copyright 2018-19, Artur Zas
// https://www.az-invest.eu
// https://www.mql5.com/en/users/arturz
//
class CTimeControl
{
private:
int startHH;
int startMM;
string start;
int endHH;
int endMM;
string end;
bool scheduleEnabled;
public:
void SetValidTraingHours(string _from = "0:00", string _to = "0:00");
bool IsTradingTimeValid();
bool IsScheduleEnabled() { return scheduleEnabled; };
void StringToHHMM(string value, int &HH, int &MM);
};
void CTimeControl::SetValidTraingHours(string _from,string _to)
{
this.start = _from;
this.end = _to;
StringToHHMM(this.start, this.startHH, this.startMM);
StringToHHMM(this.end, this.endHH, this.endMM);
if(this.startHH == 0 && this.startMM == 0 && this.endHH == 0 && this.endMM == 0)
{
scheduleEnabled = false;
}
else
{
scheduleEnabled = true;
}
}
bool CTimeControl::IsTradingTimeValid()
{
if(scheduleEnabled == false)
return true;
datetime now = TimeCurrent();
MqlDateTime temp;
TimeToStruct(now,temp);
datetime _start = StringToTime((string)temp.year+"."+(string)temp.mon+"."+(string)temp.day+" "+this.start);
datetime _end = StringToTime((string)temp.year+"."+(string)temp.mon+"."+(string)temp.day+" "+this.end);
if((now >= _start) && (now <= _end))
return true;
else
return false;
}
void CTimeControl::StringToHHMM(string value, int &HH, int &MM)
{
MqlDateTime temp;
TimeToStruct(TimeCurrent(),temp);
datetime fullDateTime = StringToTime((string)temp.year+"."+(string)temp.mon+"."+(string)temp.day+" "+value);
TimeToStruct(fullDateTime,temp);
HH = temp.hour;
MM = temp.min;
}
@@ -0,0 +1,235 @@
//+------------------------------------------------------------------+
//| CADXOnRingBuffer.mqh |
//| Copyright 2012, Konstantin Gruzdev |
//| https://login.mql5.com/ru/users/Lizar |
//| Revision 01 Dec 2012 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, Konstantin Gruzdev"
#property link "https://login.mql5.com/ru/users/Lizar"
//--- Class to calculate the MA using the ring buffer:
#include <IncOnRingBuffer\CMAOnRingBuffer.mqh>
//+------------------------------------------------------------------+
//| Class CADXOnRingBuffer |
//| Appointment: class is designed for the calculation of the |
//| ADX indicator (Average Directional Movement Index, |
//| ADX) using the class for working with the ring |
//| buffer. |
//| Link: http://www.mql5.com/ru/code/1343 |
//+------------------------------------------------------------------+
class CADXOnRingBuffer
{
public:
CMAOnRingBuffer pdi; // positive directional index
CMAOnRingBuffer ndi; // negative directional index
private:
CMAOnRingBuffer m_adx; // average directional movement index
string m_name; // indicator name
bool m_as_series; // true, if the indexing as in time series
int m_bars_required; // number of elements required to calculate
int m_begin; // index of the first significant element
int m_start; // index of element to start the calculation
int m_index; // current element index
double m_high; // maximal value
double m_low; // minimal value
double m_close; // closing price
double m_phigh; // maximum value of the previous bar
double m_plow; // minimum value of the previous bar
double m_pclose; // closing price of the previous bar
double m_PD;
double m_ND;
public:
CADXOnRingBuffer() {}
~CADXOnRingBuffer() {}
//--- initialization method:
bool Init(int ma_period=14,
ENUM_MA_METHOD ma_method=MODE_EMA,
int size_buffer=256,
bool as_series=false);
//--- basic methods:
int MainOnArray(const int rates_total,
const int prev_calculated,
const double &high[],
const double &low[],
const double &close[]);
double MainOnValue(const int rates_total,
const int prev_calculated,
const int begin,
const double high,
const double low,
const double close,
const int index);
//--- methods to get access to private data:
int BarsRequired() { return(m_bars_required); }
string NameADX() { return("ADX"+m_name); }
string NameNDI() { return("-DI"+m_name); }
string NamePDI() { return("+DI"+m_name); }
string MAMethod() { return(m_adx.MAMethod()); }
int MAPeriod() { return(m_adx.MAPeriod()); }
int Size() { return(m_adx.Size()); }
//--- returns the value of element with the specified index:
double operator [](const int index) const { return(m_adx.At(index)); }
private:
//--- indicator calculation method:
void ADX(const int rates_total, const int prev_calculated);
};
//+------------------------------------------------------------------+
//| Initialization method |
//+------------------------------------------------------------------+
bool CADXOnRingBuffer :: Init(int ma_period=14,ENUM_MA_METHOD ma_method=MODE_EMA, int size_buffer=256, bool as_series=false)
{
//--- initialize the CMAOnRingBuffer class instances:
if(!pdi.Init(ma_period,ma_method,size_buffer)) return false;
if(!ndi.Init(ma_period,ma_method,size_buffer)) return false;
if(!m_adx.Init(ma_period,ma_method,size_buffer)) return false;
//---
m_name="("+IntegerToString(ma_period)+","+MAMethod()+")";
//---
m_as_series=as_series;
m_bars_required=m_adx.BarsRequired()+1;
return true;
}
//+------------------------------------------------------------------+
//| Indicator on array |
//+------------------------------------------------------------------+
int CADXOnRingBuffer :: MainOnArray(const int rates_total,
const int prev_calculated,
const double &high[],
const double &low[],
const double &close[])
{
//--- save as_series flags:
bool as_series_high = ArrayGetAsSeries(high);
bool as_series_low = ArrayGetAsSeries(low);
bool as_series_close = ArrayGetAsSeries(close);
if(as_series_high) ArraySetAsSeries(high, false);
if(as_series_low) ArraySetAsSeries(low, false);
if(as_series_close) ArraySetAsSeries(close,false);
//--- first calculation:
if(prev_calculated==0)
{
for(int i=0;i<rates_total;i++)
{
if(high[i]!=0 && high[i] != EMPTY_VALUE &&
low[i]!=0 && low[i] != EMPTY_VALUE &&
close[i]!=0 && close[i]!= EMPTY_VALUE)
{
m_start=MathMax(i+1,rates_total-Size()-m_bars_required);
break;
}
}
m_begin=m_start;
}
//--- number of bars was changed:
else m_start=prev_calculated-1;
//--- main loop:
for(m_index=m_start;m_index<rates_total;m_index++)
{
//--- fill main positive and main negative buffers:
m_phigh = high [m_index-1];
m_plow = low [m_index-1];
m_pclose = close[m_index-1];
m_high = high [m_index];
m_low = low [m_index];
//--- calculation of the average directional movement index:
ADX(rates_total,prev_calculated);
}
//--- restore as_series flags
if(as_series_high) ArraySetAsSeries(high, true);
if(as_series_low) ArraySetAsSeries(low, true);
if(as_series_close) ArraySetAsSeries(close,true);
//--- return value of prev_calculated for next call:
return(rates_total);
}
//+------------------------------------------------------------------+
//| Indicator on value |
//+------------------------------------------------------------------+
double CADXOnRingBuffer:: MainOnValue(const int rates_total,
const int prev_calculated,
const int begin,
const double high,
const double low,
const double close,
const int index)
{
//--- check as_series flags:
if(m_as_series) m_index=rates_total-1-index;
else m_index=index;
//--- check begin:
if(m_index<begin) return(EMPTY_VALUE);
//--- initial calculation:
if(m_index==begin)
{
m_high=high;
m_low=low;
m_close=close;
m_begin=begin+1;
return(EMPTY_VALUE);
}
//--- remember the prices:
if(prev_calculated-1!=m_index)
{
m_phigh = m_high;
m_plow = m_low;
m_pclose = m_close;
}
m_high = high;
m_low = low;
m_close = close;
//--- calculation of the average directional movement index:
ADX(rates_total,prev_calculated);
//--- result:
return(m_adx.Last());
}
//+------------------------------------------------------------------+
//| Average directional movement index |
//+------------------------------------------------------------------+
void CADXOnRingBuffer:: ADX(const int rates_total, const int prev_calculated)
{
//--- fill main positive and main negative buffers
double dTmpP=m_high-m_phigh;
double dTmpN=m_plow-m_low;
if(dTmpP<0.0) dTmpP=0.0;
if(dTmpN<0.0) dTmpN=0.0;
if(dTmpP>dTmpN) dTmpN=0.0;
else
{
if(dTmpP<dTmpN) dTmpP=0.0;
else
{
dTmpP=0.0;
dTmpN=0.0;
}
}
//--- define TR
double tr=MathMax(MathMax(MathAbs(m_high-m_low),MathAbs(m_high-m_pclose)),MathAbs(m_low-m_pclose));
//---
if(tr!=0.0)
{
m_PD=100.0*dTmpP/tr;
m_ND=100.0*dTmpN/tr;
}
else
{
m_PD=0.0;
m_ND=0.0;
}
//--- main calculation:
//--- fill smoothed positive and negative buffers
pdi.MainOnValue(rates_total,prev_calculated,m_begin,m_PD,m_index);
ndi.MainOnValue(rates_total,prev_calculated,m_begin,m_ND,m_index);
//--- fill ADXTmp buffer
double dTmp=pdi.Last()+ndi.Last();
if(dTmp!=0.0)
dTmp=100.0*MathAbs((pdi.Last()-ndi.Last())/dTmp);
else
dTmp=0.0;
//--- fill smoothed ADX buffer
m_adx.MainOnValue(rates_total,prev_calculated,m_begin,dTmp,m_index);
}
+153
View File
@@ -0,0 +1,153 @@
//+------------------------------------------------------------------+
//| CArrayRing.mqh |
//| Copyright 2012, Konstantin Gruzdev |
//| https://login.mql5.com/ru/users/Lizar |
//| Revision 03 Dec 2012 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, Konstantin Gruzdev"
#property link "https://login.mql5.com/ru/users/Lizar"
//+------------------------------------------------------------------+
//| Class CArrayRing |
//| Appointment: class is designed to work with tne finite ring |
//| buffers of data. When the buffer is crowded the oldest |
//| buffer element is replaced by the newest element. Herewith, |
//| the specified number of end elements are always |
//| available. |
//| Link: http://www.mql5.com/ru/code/1340 |
//| Remark: it should also be kept in mind that the element indexing |
//| in the ring buffer is executed as in timeseries. |
//+------------------------------------------------------------------+
class CArrayRing
{
private:
double m_data[]; // ring buffer of data
int m_size; // buffer size
int m_last_pos; // last buffer element position
double m_filling; // value, which used for the array filling
public:
CArrayRing();
~CArrayRing() { ArrayFree(m_data); }
//--- buffer initialization method:
bool Init(int size, double volue=EMPTY_VALUE);
//--- method returns the buffer size:
int Size() { return m_size-1; }
//--- method changes the ring buffer size:
bool Resize(const int size);
//--- method of adding a new element to the buffer:
void Add(const double element);
//--- method returns the value of element with the specified index:
double At(const int index) const;
double operator [](const int index) const { return(At(index)); }
//--- method returns the value of the last element stored in the buffer:
double Last() const { return(m_data[m_last_pos]); }
//--- method overwrites the value of the last element in the buffer:
void Last(const double element) { m_data[m_last_pos]=element; }
//--- method overwrites the value of element with the specified index:
bool Update(const double element,const int index=0);
};
//+------------------------------------------------------------------+
//| Constructor. |
//+------------------------------------------------------------------+
CArrayRing::CArrayRing()
{
m_last_pos=0; // last element position
m_filling=EMPTY_VALUE; // value for buffer filling
m_size=ArraySize(m_data); // get size of the ring buffer
}
//+------------------------------------------------------------------+
//| Buffer initialization method. |
//+------------------------------------------------------------------+
bool CArrayRing::Init(int size, double volue=EMPTY_VALUE)
{
m_last_pos=0; // last element position
m_filling=volue; // value for buffer filling
m_size=ArraySize(m_data); // get size of the buffer
bool result=Resize(size); // create a buffer with the desired size
ArrayFill(m_data,0,m_size,m_filling); // fill the buffer with default values
return(result);
}
//+------------------------------------------------------------------+
//| Set the new size of the array. |
//+------------------------------------------------------------------+
bool CArrayRing::Resize(const int new_size)
{
//--- check
if(new_size<0) return(false);
//--- increase array size:
if(new_size>m_size)
{
int set_size=ArrayResize(m_data,new_size);
if(set_size<0) return(false);
//--- copy elements to restore their order:
if(set_size>m_size)
{
for(int i=m_size-1,j=set_size-1;i>m_last_pos;i--,j--)
{
m_data[j]=m_data[i];
m_data[i]=m_filling;
}
}
m_size=set_size;
//--- result:
return(true);
}
//--- reduce array size:
//--- prepare array to reduce the size:
if(new_size>m_last_pos+1)
for(int i=m_size-1,j=new_size-1;j>m_last_pos;i--,j--) m_data[j]=m_data[i];
else
{
for(int i=m_last_pos+1-new_size,j=0;i<=m_last_pos;i++,j++) m_data[j]=m_data[i];
m_last_pos=new_size-1;
}
//--- reduce the size:
m_size=new_size;
ArrayResize(m_data,new_size);
//--- result:
return(true);
}
//+------------------------------------------------------------------+
//| Adding a new element to the buffer. |
//+------------------------------------------------------------------+
void CArrayRing::Add(const double element)
{
m_last_pos=++m_last_pos%m_size;
m_data[m_last_pos]=element;
}
//+------------------------------------------------------------------+
//| Gets the element at the specified index. |
//+------------------------------------------------------------------+
double CArrayRing::At(const int index) const
{
//--- check the index correctness:
if((index/m_size)==0)
//--- return the value of element with the specified index:
return(m_data[(m_size+m_last_pos-index)%m_size]);
//--- if the index is wrong:
return(DBL_MAX);
}
//+------------------------------------------------------------------+
//| Update the element at the specified position in the array. |
//+------------------------------------------------------------------+
bool CArrayRing::Update(const double element,const int index=0)
{
//--- check the index correctness:
if((index/m_size)==0)
{
//--- update
m_data[(m_size+m_last_pos-index)%m_size]=element;
//--- successful
return(true);
}
//--- if the index is wrong:
return(false);
}
@@ -0,0 +1,154 @@
//+------------------------------------------------------------------+
//| CATROnRingBuffer.mqh |
//| Copyright 2012, Konstantin Gruzdev |
//| https://login.mql5.com/ru/users/Lizar |
//| Revision 01 Dec 2012 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, Konstantin Gruzdev"
#property link "https://login.mql5.com/ru/users/Lizar"
//--- Class to calculate the MA using the ring buffer:
#include <IncOnRingBuffer\CMAOnRingBuffer.mqh>
//+------------------------------------------------------------------+
//| Class CATROnRingBuffer |
//| Appointment: class is designed for the calculation of the |
//| technical indicator Average True Range (Average |
//| True Range, ATR) using the class for working with |
//| the ring buffer. |
//| Link: http://www.mql5.com/ru/code/1344 |
//+------------------------------------------------------------------+
class CATROnRingBuffer
{
private:
CMAOnRingBuffer m_ma; // instance the class for MA calculation
double m_tr; // true range
double m_atr; // average true range
string m_name; // indicator name
bool m_as_series; // true, if the indexing as in time series
int m_bars_required; // number of elements required to calculate
int m_begin; // index of the first significant element
int m_start; // index of element to start the calculation
int m_index; // current element index
double m_close; // closing price of the current bar
double m_prev_close; // closing price of the previous bar
public:
CATROnRingBuffer() {}
~CATROnRingBuffer() {}
//--- initialization method:
bool Init(int ma_period=14,ENUM_MA_METHOD ma_method=MODE_SMA, int size_buffer=256, bool as_series=false);
//--- basic methods:
int MainOnArray(const int rates_total,
const int prev_calculated,
const double &high[],
const double &low[],
const double &close[]);
double MainOnValue(const int rates_total,
const int prev_calculated,
const int begin,
const double high,
const double low,
const double close,
const int index);
//--- methods to get access to private data:
int BarsRequired() { return(m_bars_required); }
string Name() { return(m_name); }
string MAMethod() { return(m_ma.MAMethod()); }
int MAPeriod() { return(m_ma.MAPeriod()); }
int Size() { return(m_ma.Size()); }
//--- returns the value of element with the specified index:
double operator [](const int index) const { return(m_ma.At(index)); }
};
//+------------------------------------------------------------------+
//| Initialization method |
//+------------------------------------------------------------------+
bool CATROnRingBuffer :: Init(int ma_period=14,ENUM_MA_METHOD ma_method=MODE_SMA, int size_buffer=256, bool as_series=false)
{
//--- Initialization for MA:
if(!m_ma.Init(ma_period,ma_method,size_buffer)) return false;
//---
m_as_series=as_series;
m_bars_required=m_ma.BarsRequired()+1;
m_name="ATR("+IntegerToString(ma_period)+","+MAMethod()+")";
//---
return true;
}
//+------------------------------------------------------------------+
//| Indicator on array |
//+------------------------------------------------------------------+
int CATROnRingBuffer :: MainOnArray(const int rates_total,
const int prev_calculated,
const double &high[],
const double &low[],
const double &close[])
{
//--- save as_series flags:
bool as_series_high = ArrayGetAsSeries(high);
bool as_series_low = ArrayGetAsSeries(low);
bool as_series_close = ArrayGetAsSeries(close);
if(as_series_high) ArraySetAsSeries(high, false);
if(as_series_low) ArraySetAsSeries(low, false);
if(as_series_close) ArraySetAsSeries(close,false);
//--- first calculation:
if(prev_calculated==0)
{
for(int i=0;i<rates_total;i++)
{
if(high[i]!=0 && high[i]!=EMPTY_VALUE &&
low[i]!=0 && low[i]!=EMPTY_VALUE &&
close[i]!=0 && close[i]!=EMPTY_VALUE)
{
m_start=MathMax(i+1,rates_total-Size()-m_bars_required);
break;
}
}
m_begin=m_start;
}
//--- number of bars was changed:
else m_start=prev_calculated-1;
//--- main loop:
for(int i=m_start;i<rates_total;i++)
{
m_tr=MathMax(high[i],close[i-1])-MathMin(low[i],close[i-1]);
m_ma.MainOnValue(rates_total,prev_calculated,m_begin,m_tr,i);
}
//--- restore as_series flags:
if(as_series_high) ArraySetAsSeries(high, true);
if(as_series_low) ArraySetAsSeries(low, true);
if(as_series_close) ArraySetAsSeries(close,true);
//--- return value of prev_calculated for next call:
return(rates_total);
}
//+------------------------------------------------------------------+
//| Indicator on value |
//+------------------------------------------------------------------+
double CATROnRingBuffer:: MainOnValue(const int rates_total,
const int prev_calculated,
const int begin,
const double high,
const double low,
const double close,
const int index)
{
//--- check as_series flags:
if(m_as_series) m_index=rates_total-1-index;
else m_index=index;
//--- check begin:
if(m_index<begin) return(EMPTY_VALUE);
//--- initial calculation:
if(m_index==begin)
{
m_close=close;
return (EMPTY_VALUE);
}
//--- remember the closing price:
if(prev_calculated-1!=m_index) m_prev_close=close;
m_close=close;
//--- main calculation:
m_tr=MathMax(high,m_prev_close)-MathMin(low,m_prev_close);
m_ma.MainOnValue(rates_total,prev_calculated,begin+1,m_tr,m_index);
//--- result:
return(m_ma.Last());
}
+364
View File
@@ -0,0 +1,364 @@
//+------------------------------------------------------------------+
//| CMAOnRingBuffer.mqh |
//| Copyright 2012, Konstantin Gruzdev |
//| https://login.mql5.com/ru/users/Lizar |
//| Revision 30 Nov 2012 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, Konstantin Gruzdev"
#property link "https://login.mql5.com/ru/users/Lizar"
//--- Class for working with the ring buffer of data:
#include <IncOnRingBuffer\CArrayRing.mqh>
//+------------------------------------------------------------------+
//| Class CMAOnRingBuffer |
//| Appointment: class is designed to calculate a moving averages |
//| using the class for working with the ring |
//| buffer. |
//| Link: http://www.mql5.com/ru/code/1342 |
//+------------------------------------------------------------------+
class CMAOnRingBuffer :public CArrayRing
{
private:
CArrayRing *m_array_in; // ring buffer for input data
int m_ma_period; // number of elements to analyze
ENUM_MA_METHOD m_ma_method; // MA calculation method
bool m_as_series; // true, if the indexing as in time series
double m_k1,m_k2;
double m_LK[];
string m_name; // indicator name
int m_bars_required; // number of elements required to calculate
int m_start; // index of element to start the calculation
int m_index; // current element index
public:
CMAOnRingBuffer() {}
~CMAOnRingBuffer();
//--- initialization method:
bool Init(int ma_period=14,ENUM_MA_METHOD ma_method=MODE_SMA, int size_buffer=256, bool as_series=false);
//--- basic methods:
int MainOnArray(const int rates_total, const int prev_calculated,const double &array[]);
double MainOnValue(const int rates_total, const int prev_calculated, const int begin, const double value, const int index);
//--- methods to get access to private data:
int BarsRequired() { return(m_bars_required); }
string Name() { return(m_name); }
string MAMethod() { return(MethodToString(m_ma_method)); }
int MAPeriod() { return(m_ma_period); }
//--- returns the value of element with the specified index:
double operator [](const int index) const { return(At(index)); }
private:
//--- methods of calculation based on the array of input data:
void SMAOnArray (const int rates_total, const int prev_calculated, const double &array[]);
void EMAOnArray (const int rates_total, const int prev_calculated, const double &array[]);
void LWMAOnArray(const int rates_total, const int prev_calculated, const double &array[]);
//--- methods to calculate the sequential values ??of the indicator elements:
double SMAOnValue (const int prev_calculated, const int begin, const double value, const int index);
double EMAOnValue (const int prev_calculated, const int begin, const double value, const int index);
double LWMAOnValue(const int prev_calculated, const int begin, const double value, const int index);
//--- auxiliary methods:
int Begin(const int rates_total,const double &array[]);
bool FillArrayIn(const int prev_calculated, const double value);
string MethodToString(ENUM_MA_METHOD method);
};
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
void CMAOnRingBuffer:: ~CMAOnRingBuffer()
{
if(CheckPointer(m_array_in)!=POINTER_INVALID) delete m_array_in;
}
//+------------------------------------------------------------------+
//| Indicator on array |
//+------------------------------------------------------------------+
int CMAOnRingBuffer:: MainOnArray(const int rates_total,const int prev_calculated,const double &array[])
{
//--- save as_series flags
bool as_series=ArrayGetAsSeries(array);
if(as_series) ArraySetAsSeries(array,false);
//--- main calculation:
switch(m_ma_method)
{
case MODE_SMA: SMAOnArray(rates_total,prev_calculated,array); break;
case MODE_EMA:
case MODE_SMMA: EMAOnArray(rates_total,prev_calculated,array); break;
case MODE_LWMA: LWMAOnArray(rates_total,prev_calculated,array); break;
}
//--- restore as_series flags
if(as_series) ArraySetAsSeries(array,true);
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
//| Indicator on value |
//+------------------------------------------------------------------+
double CMAOnRingBuffer:: MainOnValue(const int rates_total, const int prev_calculated, const int begin, const double value, const int index)
{
//--- check as_series flags:
if(m_as_series) m_index=rates_total-1-index;
else m_index=index;
//--- check begin:
if(m_index<begin) return(EMPTY_VALUE);
//--- main calculation:
switch(m_ma_method)
{
case MODE_SMA: return(SMAOnValue(prev_calculated,begin,value,index));
case MODE_EMA:
case MODE_SMMA: return(EMAOnValue(prev_calculated,begin,value,index));
case MODE_LWMA: return(LWMAOnValue(prev_calculated,begin,value,index));
}
//--- result:
return(EMPTY_VALUE);
}
//+------------------------------------------------------------------+
//| Simple moving average on array |
//+------------------------------------------------------------------+
void CMAOnRingBuffer:: SMAOnArray(const int rates_total, const int prev_calculated, const double &array[])
{
//--- first calculation:
if(prev_calculated==0)
{
m_start=Begin(rates_total,array)+m_ma_period-1;
double sum=0.0;
for(int i=m_start;i>m_start-m_ma_period;i--) sum+=array[i];
Last(sum/m_ma_period);
}
//--- number of bars was changed:
else
{
m_start=prev_calculated-1;
Last(At(1)-(array[m_start-m_ma_period]-array[m_start])/m_ma_period);
}
//--- main loop
for(int i=m_start+1;i<rates_total && !IsStopped();i++)
Add(Last()-(array[i-m_ma_period]-array[i])/m_ma_period);
}
//+------------------------------------------------------------------+
//| Exponential moving average on array |
//+------------------------------------------------------------------+
void CMAOnRingBuffer:: EMAOnArray(const int rates_total,const int prev_calculated,const double &array[])
{
//--- first calculation:
if(prev_calculated==0)
{
m_start=Begin(rates_total,array);
Last(array[m_start]);
}
//--- number of bars was changed:
else
{
m_start=prev_calculated-1;
Last(m_k1*array[m_start]+m_k2*At(1));
}
//--- main loop:
for(int i=m_start+1;i<rates_total && !IsStopped();i++)
Add(m_k1*array[i]+m_k2*Last());
}
//+------------------------------------------------------------------+
//| Linear weighted moving average on array |
//+------------------------------------------------------------------+
void CMAOnRingBuffer:: LWMAOnArray(const int rates_total, const int prev_calculated, const double &array[])
{
//--- first calculation:
if(prev_calculated==0)
m_start=Begin(rates_total,array)+m_ma_period-1;
//--- number of bars was changed:
else m_start=prev_calculated-1;
double volue=0.0;
for(int j=0;j<m_ma_period && !IsStopped();j++)
volue+=array[m_start-j]*m_LK[j];
Last(volue);
//--- main loop
for(int i=m_start+1;i<rates_total && !IsStopped();i++)
{
volue=0.0;
for(int j=0;j<m_ma_period && !IsStopped();j++)
volue+=array[i-j]*m_LK[j];
Add(volue);
}
}
//+------------------------------------------------------------------+
//| Simple moving average on value |
//+------------------------------------------------------------------+
double CMAOnRingBuffer:: SMAOnValue(const int prev_calculated, const int begin, const double value, const int index)
{
//--- fill the ring buffer of input data:
if(!FillArrayIn(prev_calculated,value)) return(EMPTY_VALUE);
//--- initial calculation:
m_start=begin+m_ma_period-1;
if(m_index<m_start) return (EMPTY_VALUE);
else if(m_index==m_start)
{
double sum=0.0;
for(int i=0;i<m_ma_period && !IsStopped();i++) sum+=m_array_in[i];
Last(sum/m_ma_period);
return(Last());
}
//--- main calculation:
if(prev_calculated-1==m_index)
Last(At(1)-(m_array_in[m_ma_period]-value)/m_ma_period);
else
Add(Last()-(m_array_in[m_ma_period]-value)/m_ma_period);
//--- result:
return(Last());
}
//+------------------------------------------------------------------+
//| Exponential moving average on value |
//+------------------------------------------------------------------+
double CMAOnRingBuffer:: EMAOnValue(const int prev_calculated, const int begin, const double value, const int index)
{
//--- initial calculation:
if(m_index==begin)
{
Last(value);
return(value);
}
//--- main calculation:
if(prev_calculated-1==m_index)
Last(m_k1*value+m_k2*At(1));
else
Add(m_k1*value+m_k2*Last());
//--- result:
return(Last());
}
//+------------------------------------------------------------------+
//| Linear weighted moving average on value |
//+------------------------------------------------------------------+
double CMAOnRingBuffer:: LWMAOnValue(const int prev_calculated, const int begin, const double value, const int index)
{
//--- fill the ring buffer of input data:
if(!FillArrayIn(prev_calculated,value)) return(EMPTY_VALUE);
//--- initial calculation:
if(m_index<begin+m_ma_period-1) return (EMPTY_VALUE);
//--- main calculation:
double volue=0.0;
for(int j=0;j<m_ma_period && !IsStopped();j++)
volue+=m_array_in[j]*m_LK[j];
if(prev_calculated-1==m_index) Last(volue);
else Add(volue);
//--- result:
return(Last());
}
//+------------------------------------------------------------------+
//| Defines the index of the first element for calculation |
//+------------------------------------------------------------------+
int CMAOnRingBuffer:: Begin(const int rates_total,const double &array[])
{
//--- looking the start of significant data:
int i=-1;
while(++i<rates_total && !IsStopped())
{
if(array[i]!=0 && array[i]!=EMPTY_VALUE) break;
}
//--- Return the index of the element from which start calculations:
return(MathMax(i,rates_total-Size()-m_bars_required));
}
//+------------------------------------------------------------------+
//| Fill the ring buffer by input data |
//+------------------------------------------------------------------+
bool CMAOnRingBuffer:: FillArrayIn(const int prev_calculated, const double value)
{
//--- check pointer:
if(CheckPointer(m_array_in)==POINTER_INVALID)
{
if((m_array_in=new CArrayRing())==NULL) return false;
if(!m_array_in.Init(Size())) return false;
}
//--- fill the ring buffer of input data:
if(prev_calculated-1==m_index) m_array_in.Last(value);
else m_array_in.Add(value);
//--- successful
return true;
}
//+------------------------------------------------------------------+
//| Initialization method |
//+------------------------------------------------------------------+
bool CMAOnRingBuffer:: Init(int ma_period=14,ENUM_MA_METHOD ma_method=MODE_SMA, int size_buffer=256, bool as_series=false)
{
//--- check for input values
if(ma_period<=0)
{
m_ma_period=14;
printf("Input parameter ma_period has incorrect value (%d). Indicator will use value %d for calculations.",
ma_period,m_ma_period);
}
else m_ma_period=ma_period;
if(size_buffer<=m_ma_period)
{
printf("Input parameter size_buffer has incorrect value (%d). Indicator will use value %d for calculations.",
size_buffer,m_ma_period);
size_buffer=m_ma_period;
}
//--- initialization of the ring buffer for the indicator data:
if(!CArrayRing::Init(size_buffer)) return false;
//--- data initialization:
int coeff_required=10;
m_as_series=as_series;
m_ma_method=ma_method;
switch(m_ma_method)
{
case MODE_SMA:
{
m_bars_required=m_ma_period;
break;
}
case MODE_EMA:
{
m_k1=2.0/(m_ma_period+1.0);
m_k2=1.0-m_k1;
m_bars_required=m_ma_period*coeff_required;
break;
}
case MODE_SMMA:
{
m_k1=1.0/m_ma_period;
m_k2=1.0-m_k1;
m_bars_required=m_ma_period*coeff_required;
break;
}
case MODE_LWMA:
{
ArrayResize(m_LK,m_ma_period);
double sum=0;
for(int j=0;j<m_ma_period;j++) sum+=m_LK[j]=m_ma_period-j;
for(int j=0;j<m_ma_period;j++) m_LK[j]/=sum;
sum=0;
for(int j=0;j<m_ma_period;j++) sum+=m_LK[j];
m_bars_required=m_ma_period;
break;
}
default:
break;
}
m_name=MethodToString(m_ma_method)+"("+IntegerToString(m_ma_period)+")";
//--- successful
return true;
}
//+------------------------------------------------------------------+
//| Transformation of moving method in the text representation |
//+------------------------------------------------------------------+
string CMAOnRingBuffer:: MethodToString(ENUM_MA_METHOD method)
{
switch(method)
{
case MODE_SMA: return("SMA");
case MODE_EMA: return("EMA");
case MODE_LWMA: return("LWMA");
case MODE_SMMA: return("SMMA");
}
return(EnumToString(method));
}