From 549321267260960a116143a38281460172cc2035 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 3 Dec 2021 13:04:31 +0100 Subject: [PATCH] More candletype changes --- freqtrade/constants.py | 2 ++ freqtrade/data/dataprovider.py | 13 ++++++++----- freqtrade/data/history/hdf5datahandler.py | 8 ++++++-- freqtrade/data/history/jsondatahandler.py | 8 ++++++-- freqtrade/optimize/backtesting.py | 4 +++- freqtrade/strategy/interface.py | 4 +++- tests/data/test_dataprovider.py | 5 +++-- tests/rpc/test_rpc_apiserver.py | 3 ++- 8 files changed, 33 insertions(+), 14 deletions(-) diff --git a/freqtrade/constants.py b/freqtrade/constants.py index 59c709980..ebb817e8d 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -475,6 +475,8 @@ CANCEL_REASON = { } # List of pairs with their timeframes +# TODO-lev: This should really be +# PairWithTimeframe = Tuple[str, str, CandleType] PairWithTimeframe = Tuple[str, str, str] ListPairsWithTimeframes = List[PairWithTimeframe] diff --git a/freqtrade/data/dataprovider.py b/freqtrade/data/dataprovider.py index 0e8031554..3e6eccdc8 100644 --- a/freqtrade/data/dataprovider.py +++ b/freqtrade/data/dataprovider.py @@ -14,6 +14,7 @@ from freqtrade.configuration import TimeRange from freqtrade.constants import ListPairsWithTimeframes, PairWithTimeframe from freqtrade.data.history import load_pair_history from freqtrade.enums import RunMode +from freqtrade.enums.candletype import CandleType from freqtrade.exceptions import ExchangeError, OperationalException from freqtrade.exchange import Exchange, timeframe_to_seconds @@ -46,7 +47,7 @@ class DataProvider: pair: str, timeframe: str, dataframe: DataFrame, - candle_type: str = '' + candle_type: CandleType ) -> None: """ Store cached Dataframe. @@ -55,7 +56,7 @@ class DataProvider: :param pair: pair to get the data for :param timeframe: Timeframe to get data for :param dataframe: analyzed dataframe - :param candle_type: '', mark, index, premiumIndex, or funding_rate + :param candle_type: Any of the enum CandleType (must match trading mode!) """ self.__cached_pairs[(pair, timeframe, candle_type)] = ( dataframe, datetime.now(timezone.utc)) @@ -78,7 +79,8 @@ class DataProvider: :param timeframe: timeframe to get data for :param candle_type: '', mark, index, premiumIndex, or funding_rate """ - saved_pair = (pair, str(timeframe), candle_type) + candleType = CandleType.from_string(candle_type) + saved_pair = (pair, str(timeframe), candleType) if saved_pair not in self.__cached_pairs_backtesting: timerange = TimeRange.parse_timerange(None if self._config.get( 'timerange') is None else str(self._config.get('timerange'))) @@ -92,7 +94,8 @@ class DataProvider: datadir=self._config['datadir'], timerange=timerange, data_format=self._config.get('dataformat_ohlcv', 'json'), - candle_type=candle_type + candle_type=candleType, + ) return self.__cached_pairs_backtesting[saved_pair].copy() @@ -132,7 +135,7 @@ class DataProvider: combination. Returns empty dataframe and Epoch 0 (1970-01-01) if no dataframe was cached. """ - pair_key = (pair, timeframe, '') + pair_key = (pair, timeframe, CandleType.SPOT) if pair_key in self.__cached_pairs: if self.runmode in (RunMode.DRY_RUN, RunMode.LIVE): df, date = self.__cached_pairs[pair_key] diff --git a/freqtrade/data/history/hdf5datahandler.py b/freqtrade/data/history/hdf5datahandler.py index 35e01f279..b9585e22a 100644 --- a/freqtrade/data/history/hdf5datahandler.py +++ b/freqtrade/data/history/hdf5datahandler.py @@ -36,8 +36,12 @@ class HDF5DataHandler(IDataHandler): cls._OHLCV_REGEX, p.name ) for p in datadir.glob("*.h5") ] - return [(cls.rebuild_pair_from_filename(match[1]), match[2], match[3]) for match in _tmp - if match and len(match.groups()) > 1] + return [ + ( + cls.rebuild_pair_from_filename(match[1]), + match[2], + CandleType.from_string(match[3]) + ) for match in _tmp if match and len(match.groups()) > 1] @classmethod def ohlcv_get_pairs( diff --git a/freqtrade/data/history/jsondatahandler.py b/freqtrade/data/history/jsondatahandler.py index 1f5439c27..b4775f271 100644 --- a/freqtrade/data/history/jsondatahandler.py +++ b/freqtrade/data/history/jsondatahandler.py @@ -37,8 +37,12 @@ class JsonDataHandler(IDataHandler): re.search( cls._OHLCV_REGEX, p.name ) for p in datadir.glob(f"*.{cls._get_file_extension()}")] - return [(cls.rebuild_pair_from_filename(match[1]), match[2], match[3]) for match in _tmp - if match and len(match.groups()) > 1] + return [ + ( + cls.rebuild_pair_from_filename(match[1]), + match[2], + CandleType.from_string(match[3]) + ) for match in _tmp if match and len(match.groups()) > 1] @classmethod def ohlcv_get_pairs( diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 6c5a44da0..95c92ee0b 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -18,6 +18,7 @@ from freqtrade.data.btanalysis import trade_list_to_dataframe from freqtrade.data.converter import trim_dataframe, trim_dataframes from freqtrade.data.dataprovider import DataProvider from freqtrade.enums import BacktestState, SellType +from freqtrade.enums.candletype import CandleType from freqtrade.enums.tradingmode import TradingMode from freqtrade.exceptions import DependencyException, OperationalException from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds @@ -290,7 +291,8 @@ class Backtesting: df_analyzed.loc[:, col] = 0 if col not in ('enter_tag', 'exit_tag') else None # Update dataprovider cache - self.dataprovider._set_cached_df(pair, self.timeframe, df_analyzed) + self.dataprovider._set_cached_df(pair, self.timeframe, df_analyzed, CandleType.SPOT) + # TODO-lev: Candle-type should be conditional, either "spot" or futures df_analyzed = df_analyzed.drop(df_analyzed.head(1).index) diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index bcb0a93b4..8abb10bc7 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -14,6 +14,7 @@ from pandas import DataFrame from freqtrade.constants import ListPairsWithTimeframes from freqtrade.data.dataprovider import DataProvider from freqtrade.enums import SellType, SignalDirection, SignalTagType, SignalType +from freqtrade.enums.candletype import CandleType from freqtrade.exceptions import OperationalException, StrategyError from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds from freqtrade.exchange.exchange import timeframe_to_next_date @@ -528,7 +529,8 @@ class IStrategy(ABC, HyperStrategyMixin): dataframe = self.analyze_ticker(dataframe, metadata) self._last_candle_seen_per_pair[pair] = dataframe.iloc[-1]['date'] if self.dp: - self.dp._set_cached_df(pair, self.timeframe, dataframe) + self.dp._set_cached_df(pair, self.timeframe, dataframe, CandleType.SPOT) + # TODO-lev: CandleType should be set conditionally else: logger.debug("Skipping TA Analysis for already analyzed candle") dataframe[SignalType.ENTER_LONG.value] = 0 diff --git a/tests/data/test_dataprovider.py b/tests/data/test_dataprovider.py index 4f01f816f..42e2bcdea 100644 --- a/tests/data/test_dataprovider.py +++ b/tests/data/test_dataprovider.py @@ -6,6 +6,7 @@ from pandas import DataFrame from freqtrade.data.dataprovider import DataProvider from freqtrade.enums import RunMode +from freqtrade.enums.candletype import CandleType from freqtrade.exceptions import ExchangeError, OperationalException from freqtrade.plugins.pairlistmanager import PairListManager from tests.conftest import get_patched_exchange @@ -247,8 +248,8 @@ def test_get_analyzed_dataframe(mocker, default_conf, ohlcv_history): exchange = get_patched_exchange(mocker, default_conf) dp = DataProvider(default_conf, exchange) - dp._set_cached_df("XRP/BTC", timeframe, ohlcv_history) - dp._set_cached_df("UNITTEST/BTC", timeframe, ohlcv_history) + dp._set_cached_df("XRP/BTC", timeframe, ohlcv_history, CandleType.SPOT) + dp._set_cached_df("UNITTEST/BTC", timeframe, ohlcv_history, CandleType.SPOT) assert dp.runmode == RunMode.DRY_RUN dataframe, time = dp.get_analyzed_dataframe("UNITTEST/BTC", timeframe) diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index bb540dc94..0823c7aee 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -17,6 +17,7 @@ from requests.auth import _basic_auth_str from freqtrade.__init__ import __version__ from freqtrade.enums import RunMode, State +from freqtrade.enums.candletype import CandleType from freqtrade.exceptions import DependencyException, ExchangeError, OperationalException from freqtrade.loggers import setup_logging, setup_logging_pre from freqtrade.persistence import PairLocks, Trade @@ -1179,7 +1180,7 @@ def test_api_pair_candles(botclient, ohlcv_history): ohlcv_history['enter_short'] = 0 ohlcv_history['exit_short'] = 0 - ftbot.dataprovider._set_cached_df("XRP/BTC", timeframe, ohlcv_history) + ftbot.dataprovider._set_cached_df("XRP/BTC", timeframe, ohlcv_history, CandleType.SPOT) rc = client_get(client, f"{BASE_URI}/pair_candles?limit={amount}&pair=XRP%2FBTC&timeframe={timeframe}")