From 983764ad0a09e78d793e12d8a73a461e0d694000 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 4 Jan 2024 16:44:17 +0100 Subject: [PATCH] Add "migrate funding fee timeframe" logic --- freqtrade/data/history/history_utils.py | 2 +- freqtrade/data/history/idatahandler.py | 24 ++++++++++++++++ freqtrade/optimize/backtesting.py | 2 +- freqtrade/util/migrations/__init__.py | 8 +++++- freqtrade/util/migrations/funding_fee_mig.py | 29 ++++++++++++++++++++ 5 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 freqtrade/util/migrations/funding_fee_mig.py diff --git a/freqtrade/data/history/history_utils.py b/freqtrade/data/history/history_utils.py index ad8eedfc5..ca8a173bf 100644 --- a/freqtrade/data/history/history_utils.py +++ b/freqtrade/data/history/history_utils.py @@ -531,7 +531,7 @@ def download_data_main(config: Config) -> None: "Please use `--dl-trades` instead for this exchange " "(will unfortunately take a long time)." ) - migrate_data(config) + migrate_data(config, exchange) pairs_not_available = refresh_backtest_ohlcv_data( exchange, pairs=expanded_pairs, timeframes=config['timeframes'], datadir=config['datadir'], timerange=timerange, diff --git a/freqtrade/data/history/idatahandler.py b/freqtrade/data/history/idatahandler.py index d8c063f2a..f7f0a0e35 100644 --- a/freqtrade/data/history/idatahandler.py +++ b/freqtrade/data/history/idatahandler.py @@ -403,6 +403,30 @@ class IDataHandler(ABC): return file_old.rename(file_new) + def fix_funding_fee_timeframe(self, ff_timeframe: str): + """ + Temporary method to migrate data from old funding fee timeframe to the correct timeframe + Applies to bybit and okx, where funding-fee and mark candles have different timeframes. + """ + paircombs = self.ohlcv_get_available_data(self._datadir, TradingMode.FUTURES) + funding_rate_combs = [ + f for f in paircombs if f[2] == CandleType.FUNDING_RATE and f[1] != ff_timeframe + ] + + for pair, timeframe, candletype in funding_rate_combs: + old_name = self._pair_data_filename(self._datadir, pair, timeframe, candletype) + new_name = self._pair_data_filename(self._datadir, pair, ff_timeframe, candletype) + + if not Path(old_name).exists(): + logger.warning(f'{old_name} does not exist, skipping.') + continue + + if Path(new_name).exists(): + logger.warning(f'{new_name} already exists, skipping.') + continue + + Path(old_name).rename(new_name) + def get_datahandlerclass(datatype: str) -> Type[IDataHandler]: """ diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 3827f90c9..ce37a0dcc 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -158,7 +158,7 @@ class Backtesting: self._can_short = self.trading_mode != TradingMode.SPOT self._position_stacking: bool = self.config.get('position_stacking', False) self.enable_protections: bool = self.config.get('enable_protections', False) - migrate_data(config) + migrate_data(config, self.exchange) self.init_backtest() diff --git a/freqtrade/util/migrations/__init__.py b/freqtrade/util/migrations/__init__.py index a8ac5e7f9..647e2d1dd 100644 --- a/freqtrade/util/migrations/__init__.py +++ b/freqtrade/util/migrations/__init__.py @@ -1,6 +1,12 @@ +from typing import Optional + +from freqtrade.exchange import Exchange from freqtrade.util.migrations.binance_mig import migrate_binance_futures_names # noqa F401 from freqtrade.util.migrations.binance_mig import migrate_binance_futures_data +from freqtrade.util.migrations.funding_fee_mig import migrate_funding_fee_timeframe -def migrate_data(config): +def migrate_data(config, exchange: Optional[Exchange] = None): migrate_binance_futures_data(config) + + migrate_funding_fee_timeframe(config, exchange) diff --git a/freqtrade/util/migrations/funding_fee_mig.py b/freqtrade/util/migrations/funding_fee_mig.py new file mode 100644 index 000000000..5f734f545 --- /dev/null +++ b/freqtrade/util/migrations/funding_fee_mig.py @@ -0,0 +1,29 @@ +import logging +from typing import Optional + +from freqtrade.constants import Config +from freqtrade.data.history.idatahandler import get_datahandler +from freqtrade.enums import TradingMode +from freqtrade.exchange import Exchange + + +logger = logging.getLogger(__name__) + + +def migrate_funding_fee_timeframe(config: Config, exchange: Optional[Exchange]): + if ( + config.get('trading_mode', TradingMode.SPOT) != TradingMode.FUTURES + ): + # only act on futures + return + + if not exchange: + from freqtrade.resolvers import ExchangeResolver + exchange = ExchangeResolver.load_exchange(config, validate=False) + + ff_timeframe = exchange.get_option('funding_fee_timeframe') + + logger.warning('Migrating funding fees to correct timeframe.') + + dhc = get_datahandler(config['datadir'], config['dataformat_ohlcv']) + dhc.fix_funding_fee_timeframe(ff_timeframe)