Skip to content

Commit

Permalink
WIP. Working DetrendedPrice indicator. Almost functional UltimateOsci…
Browse files Browse the repository at this point in the history
…llator indicator. Removed Indi_MarketFacilitationIndex indicator as it was a duplicate of Indi_BWMFI.
  • Loading branch information
nseam committed Sep 16, 2021
1 parent 8af012f commit 11cb93c
Show file tree
Hide file tree
Showing 9 changed files with 340 additions and 177 deletions.
8 changes: 8 additions & 0 deletions Chart.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,14 @@ class Chart : public Market {

/* Setters */

/**
* Sets a chart parameter value.
*/
template <typename T>
void Set(ENUM_CHART_PARAM _param, T _value) {
cparams.Set<T>(_param, _value);
}

/**
* Sets chart entry.
*/
Expand Down
31 changes: 30 additions & 1 deletion Indicator.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,14 @@ class Indicator : public Chart {

/* Setters */

/**
* Sets an indicator's chart parameter value.
*/
template <typename T>
void Set(ENUM_CHART_PARAM _param, T _value) {
Chart::Set<T>(_param, _value);
}

/**
* Sets name of the indicator.
*/
Expand All @@ -928,6 +936,11 @@ class Indicator : public Chart {
*/
void SetParams(IndicatorParams& _iparams) { iparams = _iparams; }

/**
* Sets indicator's symbol.
*/
void SetSymbol(string _symbol) { Set<string>(CHART_PARAM_SYMBOL, _symbol); }

/* Conditions */

/**
Expand Down Expand Up @@ -1293,7 +1306,23 @@ int BarsCalculated(Indicator* _indi, int _bars_required) {
// GetEntry() could end up with an error. It is okay.
ResetLastError();

return _entry.IsValid() ? _bars_required : 0;
int _valid_history_count = 0;

if (!_entry.IsValid()) {
// We don't have sufficient data. Counting how much data we have.

for (int i = 0; i < _bars_required; ++i) {
IndicatorDataEntry _check_entry = _indi.GetEntry(i);
if (!_check_entry.IsValid()) {
break;
}
++_valid_history_count;
}
} else {
_valid_history_count = _bars_required;
}

return _valid_history_count;
}

/**
Expand Down
28 changes: 21 additions & 7 deletions Indicators/Indi_ATR.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@ double iATR(string _symbol, int _tf, int _period, int _shift) {
struct ATRParams : IndicatorParams {
unsigned int period;
// Struct constructors.
void ATRParams(unsigned int _period, int _shift = 0) : period(_period) {
void ATRParams(unsigned int _period, int _shift = 0, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, string _symbol = NULL)
: period(_period) {
itype = INDI_ATR;
max_modes = 1;
shift = _shift;
SetDataValueType(TYPE_DOUBLE);
SetDataValueRange(IDATA_RANGE_MIXED);
SetCustomIndicatorName("Examples\\ATR");
tf = _tf;
};
void ATRParams(ATRParams &_params, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) {
this = _params;
Expand All @@ -60,8 +62,8 @@ class Indi_ATR : public Indicator {
/**
* Class constructor.
*/
Indi_ATR(ATRParams &_p) : params(_p.period), Indicator((IndicatorParams)_p) { params = _p; }
Indi_ATR(ATRParams &_p, ENUM_TIMEFRAMES _tf) : params(_p.period), Indicator(INDI_ATR, _tf) { params = _p; }
Indi_ATR(ATRParams &_p) : Indicator((IndicatorParams)_p), params(_p) {}
Indi_ATR(ATRParams &_p, ENUM_TIMEFRAMES _tf) : Indicator(INDI_ATR, _tf), params(_p) {}

/**
* Returns the indicator value.
Expand Down Expand Up @@ -113,12 +115,10 @@ class Indi_ATR : public Indicator {
switch (params.idstype) {
case IDATA_BUILTIN:
istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle;
_value = Indi_ATR::iATR(Get<string>(CHART_PARAM_SYMBOL), Get<ENUM_TIMEFRAMES>(CHART_PARAM_TF), GetPeriod(),
_shift, GetPointer(this));
_value = Indi_ATR::iATR(GetSymbol(), GetTf(), GetPeriod(), _shift, GetPointer(this));
break;
case IDATA_ICUSTOM:
_value = iCustom(istate.handle, Get<string>(CHART_PARAM_SYMBOL), Get<ENUM_TIMEFRAMES>(CHART_PARAM_TF),
params.GetCustomIndicatorName(), _mode, _shift);
_value = iCustom(istate.handle, GetSymbol(), GetTf(), params.GetCustomIndicatorName(), _mode, _shift);
break;
default:
SetUserError(ERR_INVALID_PARAMETER);
Expand Down Expand Up @@ -160,6 +160,20 @@ class Indi_ATR : public Indicator {
return _param;
}

/**
* Returns reusable indicator for a given parameters.
*/
static Indi_ATR *GetCached(string _symbol, ENUM_TIMEFRAMES _tf, int _period) {
Indi_ATR *_ptr;
string _key = Util::MakeKey(_symbol, (int)_tf, _period);
if (!Objects<Indi_ATR>::TryGet(_key, _ptr)) {
ATRParams _params(_period, _tf);
_ptr = Objects<Indi_ATR>::Set(_key, new Indi_ATR(_params));
_ptr.SetSymbol(_symbol);
}
return _ptr;
}

/* Getters */

/**
Expand Down
95 changes: 84 additions & 11 deletions Indicators/Indi_DetrendedPrice.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,24 @@
// Includes.
#include "../BufferStruct.mqh"
#include "../Indicator.mqh"
#include "Indi_MA.mqh"

// Structs.
struct DetrendedPriceParams : IndicatorParams {
unsigned int period;
unsigned int fast_period;
unsigned int slow_period;
unsigned int ama_shift;
ENUM_APPLIED_PRICE applied_price;
// Struct constructor.
void DetrendedPriceParams(int _period = 12, int _shift = 0, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) {
void DetrendedPriceParams(int _period = 12, ENUM_APPLIED_PRICE _ap = PRICE_CLOSE, int _shift = 0,
ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) {
applied_price = _ap;
itype = INDI_DETRENDED_PRICE;
max_modes = 1;
SetDataValueType(TYPE_DOUBLE);
SetDataValueRange(IDATA_RANGE_MIXED);
SetCustomIndicatorName("Examples\\DPO");
SetDataSourceType(IDATA_ICUSTOM);
// INDI_DETRENDED_PRICE[1]: bar 1: 1525392000,130,-0.00001143
// SetDataSourceType(IDATA_ICUSTOM);
SetDataSourceType(IDATA_BUILTIN);
period = _period;
shift = _shift;
tf = _tf;
Expand All @@ -49,7 +52,7 @@ struct DetrendedPriceParams : IndicatorParams {
};

/**
* Implements the Bill Williams' Accelerator/Decelerator oscillator.
* Implements Detrended Price Oscillator.
*/
class Indi_DetrendedPrice : public Indicator {
protected:
Expand All @@ -59,21 +62,78 @@ class Indi_DetrendedPrice : public Indicator {
/**
* Class constructor.
*/
Indi_DetrendedPrice(DetrendedPriceParams &_params) : params(_params.period), Indicator((IndicatorParams)_params) {
params = _params;
};
Indi_DetrendedPrice(DetrendedPriceParams &_params) : Indicator((IndicatorParams)_params) { params = _params; };
Indi_DetrendedPrice(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : Indicator(INDI_DETRENDED_PRICE, _tf) { params.tf = _tf; };

/**
* Built-in version of AMA.
*/
static double iDPO(string _symbol, ENUM_TIMEFRAMES _tf, int _period, ENUM_APPLIED_PRICE _ap, int _mode = 0,
int _shift = 0, Indicator *_obj = NULL) {
INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT(_symbol, _tf, _ap,
Util::MakeKey("Indi_DPO", _period, (int)_ap));
return iDPOOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _period, _mode, _shift, _cache);
}

/**
* Calculates DPO on the array of values.
*/
static double iDPOOnArray(INDICATOR_CALCULATE_PARAMS_SHORT, int _period, int _mode, int _shift,
IndicatorCalculateCache<double> *_cache, bool _recalculate = false) {
_cache.SetPriceBuffer(_price);

if (!_cache.HasBuffers()) {
_cache.AddBuffer<NativeValueStorage<double>>(1 + 1);
}

if (_recalculate) {
_cache.ResetPrevCalculated();
}

_cache.SetPrevCalculated(Indi_DetrendedPrice::Calculate(
INDICATOR_CALCULATE_GET_PARAMS_SHORT, _cache.GetBuffer<double>(0), _cache.GetBuffer<double>(1), _period));

return _cache.GetTailValue<double>(_mode, _shift);
}

/**
* OnCalculate() method for DPO indicator.
*/
static int Calculate(INDICATOR_CALCULATE_METHOD_PARAMS_SHORT, ValueStorage<double> &ExtDPOBuffer,
ValueStorage<double> &ExtMABuffer, int InpDetrendPeriod) {
int ExtMAPeriod = InpDetrendPeriod / 2 + 1;

int start;
int first_index = begin + ExtMAPeriod - 1;
//--- preliminary filling
if (prev_calculated < first_index) {
ArrayInitialize(ExtDPOBuffer, 0.0);
start = first_index;
if (begin > 0) PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, first_index);
} else
start = prev_calculated - 1;
//--- calculate simple moving average
Indi_MA::SimpleMAOnBuffer(rates_total, prev_calculated, begin, ExtMAPeriod, price, ExtMABuffer);
//--- the main loop of calculations
for (int i = start; i < rates_total && !IsStopped(); i++) ExtDPOBuffer[i] = price[i] - ExtMABuffer[i];
//--- OnCalculate done. Return new prev_calculated.
return (rates_total);
}

/**
* Returns the indicator's value.
*/
double GetValue(int _mode = 0, int _shift = 0) {
ResetLastError();
double _value = EMPTY_VALUE;
switch (params.idstype) {
case IDATA_BUILTIN:
_value = Indi_DetrendedPrice::iDPO(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetAppliedPrice() /*]*/, _mode,
_shift, THIS_PTR);
break;
case IDATA_ICUSTOM:
_value = iCustom(istate.handle, Get<string>(CHART_PARAM_SYMBOL), Get<ENUM_TIMEFRAMES>(CHART_PARAM_TF),
params.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, 0, _shift);
_value = iCustom(istate.handle, GetSymbol(), GetTf(), params.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/,
0, _shift);
break;
default:
SetUserError(ERR_INVALID_PARAMETER);
Expand Down Expand Up @@ -122,6 +182,11 @@ class Indi_DetrendedPrice : public Indicator {
*/
unsigned int GetPeriod() { return params.period; }

/**
* Get applied price.
*/
ENUM_APPLIED_PRICE GetAppliedPrice() { return params.applied_price; }

/* Setters */

/**
Expand All @@ -131,4 +196,12 @@ class Indi_DetrendedPrice : public Indicator {
istate.is_changed = true;
params.period = _period;
}

/**
* Set applied price.
*/
void SetAppliedPrice(ENUM_APPLIED_PRICE _applied_price) {
istate.is_changed = true;
params.applied_price = _applied_price;
}
};
9 changes: 9 additions & 0 deletions Indicators/Indi_MA.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,15 @@ class Indi_MA : public Indicator {
return result;
}

static double SimpleMA(const int position, const int period, ValueStorage<double> &price) {
double result = 0.0;
for (int i = 0; i < period; i++) {
result += price[i].Get();
}
result /= period;
return result;
}

/**
* Returns the indicator's value.
*/
Expand Down
Loading

0 comments on commit 11cb93c

Please sign in to comment.