version 3.14
This commit is contained in:
@@ -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.
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user