Skip to content

Commit

Permalink
Added missing files.
Browse files Browse the repository at this point in the history
  • Loading branch information
nseam committed Jun 27, 2024
1 parent 63f1ddb commit c132e9b
Show file tree
Hide file tree
Showing 2 changed files with 273 additions and 0 deletions.
100 changes: 100 additions & 0 deletions Indicators/Tf/Indi_TfMt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//+------------------------------------------------------------------+
//| EA31337 framework |
//| Copyright 2016-2023, EA31337 Ltd |
//| https://github.com/EA31337 |
//+------------------------------------------------------------------+

/*
* This file is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/**
* @file
* Tf-based candle indicator for MT.
*/

#ifndef __MQL__
// Allows the preprocessor to include a header file when it is needed.
#pragma once
#endif

// Includes.
#include "../../Indicator/IndicatorCandle.h"
#include "Indi_TfMt.provider.h"

// Params for MT Tf-based candle indicator.
struct Indi_TfMtParams : IndicatorTfParams {
Indi_TfMtParams(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : IndicatorTfParams("IndicatorTf", _tf) {}
};

/**
* Tf-based candle indicator for MT.
*/
class Indi_TfMt : public IndicatorCandle<Indi_TfMtParams, double, ItemsHistoryTfMtCandleProvider<double>> {
protected:
// Time-frame used to create candles.
ENUM_TIMEFRAMES tf;

/* Protected methods */

/**
* Initialize class.
*
* Called on constructor.
*/
void Init() { history.SetItemProvider(new ItemsHistoryTfMtCandleProvider<double>(THIS_PTR)); }

public:
/* Special methods */

/**
* Class constructor with timeframe enum.
*/
Indi_TfMt(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) {
tf = _tf;
Init();
}

/**
* Class constructor with timeframe index.
*/
Indi_TfMt(ENUM_TIMEFRAMES_INDEX _tfi = 0) {
tf = ChartTf::IndexToTf(_tfi);
Init();
}

/**
* Class constructor with parameters.
*/
Indi_TfMt(Indi_TfMtParams& _icparams, const IndicatorDataParams& _idparams) { Init(); }

/**
* Gets indicator's time-frame.
*/
ENUM_TIMEFRAMES GetTf() override { return tf; }

/**
* Returns current tick index (incremented every OnTick()).
*/
int GetTickIndex() override { return history.GetItemProvider() PTR_DEREF GetTickIndex(); }

/**
* Returns the number of bars on the chart decremented by iparams.shift.
*/
int GetBars() override {
// Will return number of bars prepended and appended to the history,
// even if those bars were cleaned up because of history's candle limit.
return ::Bars(GetSymbol(), GetTf()) - iparams.shift;
}
};
173 changes: 173 additions & 0 deletions Indicators/Tf/Indi_TfMt.provider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
//+------------------------------------------------------------------+
//| EA31337 framework |
//| Copyright 2016-2021, EA31337 Ltd |
//| https://github.com/EA31337 |
//+------------------------------------------------------------------+

/*
* This file is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

#ifndef __MQL__
// Allows the preprocessor to include a header file when it is needed.
#pragma once
#endif

/**
* Candle grouping and regeneration for time-frame based candles.
*/
template <typename TV>
class ItemsHistoryTfMtCandleProvider : public ItemsHistoryCandleProvider<TV> {
// Pointer to Tf Indicator, e.g., Indi_TfMt or IndicatorTfDummy. Used to fetch data by fixed timeframe candles.
IndicatorData* indi;

// Current tick index. Effectively a number of ticks generated by attached Tick indicator.
int tick_index;

public:
/**
* Constructor.
*/
ItemsHistoryTfMtCandleProvider(IndicatorData* _indi_tf) : indi(_indi_tf), tick_index(0) {}

/**
* Called when new tick was emitted from IndicatorTick-based source.
*/
virtual void OnTick(ItemsHistory<CandleOCTOHLC<TV>, ItemsHistoryTfMtCandleProvider<TV>>* _history, long _time_ms,
float _ask, float _bid) {
++tick_index;

// Seconds per candle calculated from TF.
int _spc = (int)ChartTf::TfToSeconds(indi PTR_DEREF GetTf());

Print("Indi_TfMt's history: New tick: ", TimeToString(_time_ms / 1000, TIME_DATE | TIME_MINUTES | TIME_SECONDS),
", ", _ask, ", ", _bid);

// We know that tick's timestamp will be ahead of the last tick and thus
// inside or ahead of the last created candle. In order to retrieve last
// valid candle, we need to use ItemsHistory::GetItemByShift(0) to check if
// we have to update last or create/append new candle.
CandleOCTOHLC<TV> _candle;

// Will regenerate candles up to the last added candle ever. We have to
// call it, because some of the previous actions may have removed some of
// the recent candles. Note that OnTick() advances its _time_ms in
// ascending order, so all we need to most recent history.
//
// Note that EnsureShiftExists() may return false when there never been any
// candle added.
_history PTR_DEREF EnsureShiftExists(0);

if (_history PTR_DEREF TryGetItemByShift(0, _candle, false) && _candle.ContainsTimeMs(_time_ms)) {
// Time given fits in the last added candle's time-frame, updating the candle with given price.
_candle.Update(_time_ms, _bid);

// Storing candle in the history.
_history PTR_DEREF Update(_candle, _history PTR_DEREF GetShiftIndex(0));
} else {
CandleOCTOHLC<TV> _candle_tmp;

// We don't want to regenerate history, because at the start there will bo no candle however.
if (_history PTR_DEREF TryGetItemByShift(0, _candle_tmp, false)) {
// Print("Completed candle: ", _candle_tmp.ToString());
// Print("Real candle: ", iOpen(NULL, Period(), 1), " ", iHigh(NULL, Period(), 1), " ",
// iLow(NULL, Period(), 1), " ", ChartStatic::iClose(NULL, (ENUM_TIMEFRAMES)Period(), 1));
// Print("--");
}

// Either there is no candle at shift 0 or given time doesn't fit in the #0 candle's time-frame.
_candle.Init(GetCandleTimeFromTimeMs(_time_ms, _spc), _spc, _time_ms, _bid);

// Adding candle as the most recent item in the history. It will now become the candle at shift 0.
_history PTR_DEREF Append(_candle);
}
}

/**
* Returns current tick index. Effectively a number of ticks generated by
* attached IndicatorTick.
*/
int GetTickIndex() { return tick_index; }

/**
* Returns start time of the candle (the place it's on the chart) for the given tick's time in milliseconds.
*/
int GetCandleTimeFromTimeMs(long _time_ms, int _length_in_secs) {
return (int)((_time_ms - _time_ms % ((long)_length_in_secs * 1000)) / 1000);
}

/**
* Retrieves given number of items starting from the given microseconds or index (inclusive). "_dir" identifies if we
* want previous or next items from selected starting point. Should return false if retrieving items by this method
* is not available.
*/
bool GetItems(ItemsHistory<CandleOCTOHLC<TV>, ItemsHistoryTfMtCandleProvider<TV>>* _history, long _from_time_ms,
ENUM_ITEMS_HISTORY_DIRECTION _dir, int _num_items, ARRAY_REF(CandleOCTOHLC<TV>, _out_arr)) {
return false;
}

/**
* Retrieves items between given indices (both indices inclusive). Should return false if retrieving items by this
* method is not available.
*/
bool GetItems(ItemsHistory<CandleOCTOHLC<TV>, ItemsHistoryTfMtCandleProvider<TV>>* _history, int _start_index,
int _end_index, ARRAY_REF(CandleOCTOHLC<TV>, _out_arr)) {
Print("Indi_TfMt::GetItems()");

// Converting absolute indices into MT shifts.
int _num_bars = _end_index - _start_index + 1;
// Current candle index. Could be 0 if no candles have been added or if there is only one candle added so far.
int _current_index = _history PTR_DEREF GetCurrentIndex();
int _start_shift = _current_index - _start_index;
int _end_shift = _current_index - _end_index;

Print("Indi_TfMt::GetItems(): Will fetch ", _num_bars, " bars between shift ", _start_shift, " and ", _end_shift);

// Seconds per candle calculated from TF.
int _spc = (int)ChartTf::TfToSeconds(indi PTR_DEREF GetTf());

// Static, reusable array of rates.
static ARRAY(MqlRates, _rates);
int _count = _end_index - _start_index + 1;
ArrayResize(_rates, _count);

Print("CopyRates(", indi PTR_DEREF GetSymbol(), ", ", EnumToString(indi PTR_DEREF GetTf()), ", ", _start_index,
", ", _count, ", ...)");

// As GetItems() will only be called for missing candles, we can just ask MT for OHLCs and return them.
// Note that we have to specify most recent shift and count of history ticks to return.
// Also note that CopyRates() will insert oldest candle at the start of _rates array, so we have to inverse items in
// the array in order all candles be from most recent to the oldest ones.
int _num_copied = CopyRates(indi PTR_DEREF GetSymbol(), indi PTR_DEREF GetTf(), _end_shift, _count, _rates);
ArrayResize(_out_arr, _num_copied);

for (int i = 0; i < _num_copied; ++i) {
MqlRates _rate = _rates[i];
int _start_secs = (int)(long)_rate.time;
CandleOCTOHLC<TV> _candle(_rate.open, _rate.high, _rate.low, _rate.close, _start_secs, _spc,
(long)_start_secs * 1000, long(_start_secs + _spc) * 1000 - 1, (int)_rate.tick_volume);
// Reversing output, so most recent candle will be at start.
_out_arr[_num_copied - i - 1] = _candle;
}

ArrayResize(_rates, 0);
return true;
}

/**
* Returns information about item provider.
*/
string const ToString() override { return "Indi_TfMt candle provider on " + indi PTR_DEREF GetFullName(); }
};

0 comments on commit c132e9b

Please sign in to comment.