Skip to content

Commit

Permalink
Probably working scenario of AMA <- IndicatorTfDummy(IndicatorCandle)…
Browse files Browse the repository at this point in the history
… <- IndicatorTickReal(IndicatorTick) <- platform ticks' ask/bid prices.
  • Loading branch information
nseam committed Dec 3, 2021
1 parent 3537a04 commit f92dda0
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 81 deletions.
10 changes: 8 additions & 2 deletions Indicator/IndicatorCandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class IndicatorCandle : public IndicatorBase {
void Init() {
icdata.AddFlags(DICT_FLAG_FILL_HOLES_UNSORTED);
icdata.SetOverflowListener(IndicatorCandleOverflowListener, 10);
icparams.SetMaxModes(4);
}

public:
Expand Down Expand Up @@ -91,7 +92,9 @@ class IndicatorCandle : public IndicatorBase {
CandleOCTOHLC<TV> _candle = icdata.GetByKey(_candle_time);

if (!_candle.IsValid()) {
Print(GetName(), ": Missing candle at shift ", _index, " (", _candle_time, ")");
Print(GetFullName(), ": Missing candle at shift ", _index, " (", TimeToString(_candle_time), ")");
} else {
Print(GetFullName(), ": Retrieving candle at shift ", _index, " (", TimeToString(_candle_time), ")");
}

return CandleToEntry(_candle_time, _candle);
Expand Down Expand Up @@ -166,6 +169,9 @@ class IndicatorCandle : public IndicatorBase {
void UpdateCandle(long _tick_timestamp, double _price) {
long _candle_timestamp = CalcCandleTimestamp(_tick_timestamp);

Print("Updating candle for ", GetFullName(), " at candle ", TimeToString(_candle_timestamp), " from tick at ",
TimeToString(_tick_timestamp));

CandleOCTOHLC<double> _candle(_price, _price, _price, _price, _tick_timestamp, _tick_timestamp);
if (icdata.KeyExists(_candle_timestamp)) {
// Candle already exists.
Expand All @@ -180,7 +186,7 @@ class IndicatorCandle : public IndicatorBase {
* Calculates candle's timestamp from tick's timestamp.
*/
long CalcCandleTimestamp(long _tick_timestamp) {
return _tick_timestamp - _tick_timestamp % (icparams.GetSecsPerCandle() * 1000);
return _tick_timestamp - _tick_timestamp % (icparams.GetSecsPerCandle());
}

/**
Expand Down
66 changes: 15 additions & 51 deletions Indicator/IndicatorTick.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class IndicatorTick : public IndicatorBase {
void Init() {
itdata.AddFlags(DICT_FLAG_FILL_HOLES_UNSORTED);
itdata.SetOverflowListener(IndicatorTickOverflowListener, 10);
// Ask and Bid price.
itparams.SetMaxModes(2);
}

public:
Expand Down Expand Up @@ -106,61 +108,23 @@ class IndicatorTick : public IndicatorBase {
* @return
* Returns IndicatorDataEntry struct filled with indicator values.
*/
IndicatorDataEntry GetEntry(int _timestamp = 0) {
IndicatorDataEntry GetEntry(int _timestamp = 0) override {
ResetLastError();
TickAB<TV> _entry = itdata.GetByKey(_timestamp);
/*
IndicatorDataEntry _entry = itdata.GetByKey(_timestamp);
if (!_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) {
_entry.Resize(itparams.GetMaxModes());
_entry.timestamp = _timestamp;
for (int _mode = 0; _mode < (int)itparams.GetMaxModes(); _mode++) {
switch (itparams.GetDataValueType()) {
case TYPE_BOOL:
case TYPE_CHAR:
case TYPE_INT:
_entry.values[_mode] = GetValue<int>(_mode, _timestamp);
break;
case TYPE_LONG:
_entry.values[_mode] = GetValue<long>(_mode, _timestamp);
break;
case TYPE_UINT:
_entry.values[_mode] = GetValue<uint>(_mode, _timestamp);
break;
case TYPE_ULONG:
_entry.values[_mode] = GetValue<ulong>(_mode, _timestamp);
break;
case TYPE_DOUBLE:
_entry.values[_mode] = GetValue<double>(_mode, _timestamp);
break;
case TYPE_FLOAT:
_entry.values[_mode] = GetValue<float>(_mode, _timestamp);
break;
case TYPE_STRING:
case TYPE_UCHAR:
default:
SetUserError(ERR_INVALID_PARAMETER);
break;
}
}
GetEntryAlter(_entry, _timestamp);
_entry.SetFlag(INDI_ENTRY_FLAG_IS_VALID, IsValidEntry(_entry));
if (_entry.IsValid()) {
itdata.Add(_entry, _timestamp);
istate.is_changed = false;
istate.is_ready = true;
} else {
_entry.AddFlags(INDI_ENTRY_FLAG_INSUFFICIENT_DATA);
}
if (itdata.KeyExists(_timestamp)) {
TickAB<TV> _tick = itdata.GetByKey(_timestamp);
return TickToEntry(_timestamp, _tick);
}
if (_LastError != ERR_NO_ERROR) {
istate.is_ready = false;
ResetLastError();

// No tick at given timestamp. Returning invalid entry.
IndicatorDataEntry _entry(itparams.GetMaxModes());
GetEntryAlter(_entry, _timestamp);

for (int i = 0; i < itparams.GetMaxModes(); ++i) {
_entry.values[i] = (double)0;
}

_entry.SetFlag(INDI_ENTRY_FLAG_IS_VALID, false);
return _entry;
*/
IndicatorDataEntry _foo;
return _foo;
}

/**
Expand Down
32 changes: 20 additions & 12 deletions Indicator/tests/IndicatorTf.test.mq5
Original file line number Diff line number Diff line change
Expand Up @@ -51,54 +51,62 @@ int OnInit() {
indicators.Add(indi_tick = new IndicatorTickReal(_Symbol));

// 1-second candles.
indicators.Add(indi_tf = new IndicatorTfDummy(1));
// indicators.Add(indi_tf = new IndicatorTfDummy(1));

// 1:1 candles from platform using current timeframe.
indicators.Add(indi_tf_orig_sim = new IndicatorTfDummy(ChartTf::TfToSeconds(PERIOD_CURRENT)));

// 1-second candles.
indicators.Add(indi_ama = new Indi_AMA());
// indicators.Add(indi_ama = new Indi_AMA());

IndiAMAParams _ama_params;
_ama_params.applied_price = PRICE_OPEN;

// AMA on platform candles.
indicators.Add(indi_ama_orig_sim = new Indi_AMA());
indicators.Add(indi_ama_orig_sim = new Indi_AMA(_ama_params));

// Original built-in or OnCalculate()-based AMA indicator on platform OHLCs.
indicators.Add(indi_ama_orig = new Indi_AMA());
indicators.Add(indi_ama_orig = new Indi_AMA(_ama_params));

// Candles will be initialized from tick's history.
indi_tf.Ptr().SetDataSource(indi_tick.Ptr());
// indi_tf.Ptr().SetDataSource(indi_tick.Ptr());
indi_tf_orig_sim.Ptr().SetDataSource(indi_tick.Ptr());

// AMA will work on the candle indicator.
indi_ama.Ptr().SetDataSource(indi_tf.Ptr());
// indi_ama.Ptr().SetDataSource(indi_tf.Ptr());

// AMA will work on the simulation of real candles.
indi_ama_orig_sim.Ptr().SetDataSource(indi_tf_orig_sim.Ptr());

// Checking if there are candles for last 100 ticks.
Print(indi_tf.Ptr().GetName(), "'s historic candles (from 100 ticks):");
Print(indi_tf.Ptr().CandlesToString());
// Print(indi_tf.Ptr().GetName(), "'s historic candles (from 100 ticks):");
// Print(indi_tf.Ptr().CandlesToString());
return (INIT_SUCCEEDED);
}

/**
* Implements OnTick().
*/
void OnTick() {
indicators.Tick();
string o = DoubleToStr(iOpen(_Symbol, PERIOD_CURRENT, 0), 5);
string h = DoubleToStr(iHigh(_Symbol, PERIOD_CURRENT, 0), 5);
string l = DoubleToStr(iLow(_Symbol, PERIOD_CURRENT, 0), 5);
string c = DoubleToStr(iClose(_Symbol, PERIOD_CURRENT, 0), 5);
string time = TimeToString(iTime(_Symbol, PERIOD_CURRENT, 0));

Util::Print("Tick: " + IntegerToString((long)iTime(_Symbol, PERIOD_CURRENT, 0)) + " (" + time + "), real = " + o +
", " + h + ", " + l + ", " + c);

indicators.Tick();

Util::Print("Tick: real = " + o + ", " + h + ", " + l + ", " + c + "\n" + indicators.ToString(0));
Util::Print(indicators.ToString(0));
}

/**
* Implements OnDeinit().
*/
void OnDeinit(const int reason) {
// Printing all grouped candles.
Print(indi_tf.Ptr().GetName(), "'s all candles:");
Print(indi_tf.Ptr().CandlesToString());
// Print(indi_tf.Ptr().GetName(), "'s all candles:");
// Print(indi_tf.Ptr().CandlesToString());
}
63 changes: 48 additions & 15 deletions Indicator/tests/classes/IndicatorTickReal.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
#pragma once
#endif

// Includes.
#include "../../../Chart.struct.static.h"
#include "../../IndicatorTick.h"

// Params for real tick-based indicator.
struct IndicatorTickRealParams : IndicatorParams {
IndicatorTickRealParams() : IndicatorParams(INDI_TICK, 3, TYPE_DOUBLE) {}
Expand All @@ -48,25 +52,54 @@ class IndicatorTickReal : public IndicatorTick<IndicatorTickRealParams, double>
// Feeding base indicator with historic entries of this indicator.
Print(GetFullName(), " became a data source for ", _base_indi.GetFullName());

int _ticks_to_emit = 100;
#ifndef __MQL4__
int _ticks_to_emit = 1000;

Print(_base_indi.GetFullName(), " will be now filled with ", _ticks_to_emit,
" historical entries generated by " + GetFullName());

static MqlTick _ticks[];
ArrayResize(_ticks, 0);

int _tries = 10;
int _num_copied = -1;

while (_tries-- > 0) {
_num_copied = CopyTicks(GetSymbol(), _ticks, COPY_TICKS_ALL);

Print(_base_indi.GetFullName(), " will be now filled with 100 historical entries generated by " + GetFullName());
if (_num_copied == -1) {
Sleep(1000);
} else {
break;
}
}

// For testing purposes we are emitting 100 last ticks.
for (int i = 0; i < MathMin(Bars(GetSymbol(), GetTf()), _ticks_to_emit); ++i) {
long _timestamp = ChartStatic::iTime(GetSymbol(), GetTf(), _ticks_to_emit - i - 1);
double _bid = ChartStatic::iClose(GetSymbol(), GetTf(), _ticks_to_emit - i - 1);
TickAB<double> _tick(0.0f, _bid);
// We can't call EmitTick() here, as tick would go to multiple sources at the same time!
_base_indi.OnDataSourceEntry(TickToEntry(_timestamp, _tick));
for (int i = 0; i < _num_copied; ++i) {
TickAB<double> _tick(_ticks[i].ask, _ticks[i].bid);
// We can't call EmitEntry() here, as tick would go to multiple sources at the same time!
_base_indi.OnDataSourceEntry(TickToEntry(_ticks[i].time, _tick));
}
};
#endif
}

void OnTick() override {
long _timestamp = ChartStatic::iTime(GetSymbol(), GetTf());
double _bid = ChartStatic::iClose(GetSymbol(), GetTf());
// MT doesn't provide historical ask prices, so we're filling tick with bid price only.
TickAB<double> _tick(_bid, _bid);
EmitEntry(TickToEntry(_timestamp, _tick));
#ifdef __MQL4__
// Refreshes Ask/Bid constants.
RefreshRates();
double _ask = Ask;
double _bid = Bid;
long _time = TimeCurrent();
#else
static MqlTick _ticks[];
// Copying only the last tick.
int _num_copied = CopyTicks(GetSymbol(), _ticks, COPY_TICKS_INFO, 0, 1);

Print("TickReal: ", TimeToString(_ticks[0].time), " = ", _ticks[0].bid);
double _ask = _ticks[0].ask;
double _bid = _ticks[0].bid;
long _time = _ticks[0].time;
#endif
TickAB<double> _tick(_ask, _bid);
EmitEntry(TickToEntry(_time, _tick));
}
};
3 changes: 2 additions & 1 deletion Indicators/Indi_AMA.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ class Indi_AMA : public Indicator<IndiAMAParams> {
int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) {
INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS(
_indi, _symbol, _tf, _ap,
Util::MakeKey("INDI_AMA", _ama_period, _fast_ema_period, _slow_ema_period, _ama_shift, (int)_ap));
Util::MakeKey("INDI_AMA_ON_" + _indi.GetFullName(), _ama_period, _fast_ema_period, _slow_ema_period, _ama_shift,
(int)_ap));
return iAMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _ama_period, _fast_ema_period, _slow_ema_period,
_ama_shift, _mode, _shift, _cache);
}
Expand Down

0 comments on commit f92dda0

Please sign in to comment.