From 3242be2e293d079d2cc82c6daaeed135b1067e62 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 19 Mar 2026 07:19:07 +0100 Subject: [PATCH] fix: add dynamic timeframe_floor freq fixes problems where funding-rates may be on the 1st second of the hour (observed on gate from time to time) --- freqtrade/data/converter/converter.py | 6 +++++- freqtrade/exchange/__init__.py | 1 + freqtrade/exchange/exchange_utils_timeframe.py | 15 +++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/freqtrade/data/converter/converter.py b/freqtrade/data/converter/converter.py index 7e68439df..adce2c065 100644 --- a/freqtrade/data/converter/converter.py +++ b/freqtrade/data/converter/converter.py @@ -39,7 +39,11 @@ def ohlcv_to_dataframe( df = DataFrame(ohlcv, columns=cols) # Floor date to seconds to account for exchange imprecisions - df["date"] = to_datetime(df["date"], unit="ms", utc=True).dt.floor("s") + from freqtrade.exchange import timeframe_to_floor_freq + + resample_interval = timeframe_to_floor_freq(timeframe) + + df["date"] = to_datetime(df["date"], unit="ms", utc=True).dt.floor(resample_interval) # Some exchanges return int values for Volume and even for OHLC. # Convert them since TA-LIB indicators used in the strategy assume floats diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py index 075906e11..709738efc 100644 --- a/freqtrade/exchange/__init__.py +++ b/freqtrade/exchange/__init__.py @@ -30,6 +30,7 @@ from freqtrade.exchange.exchange_utils import ( validate_exchange, ) from freqtrade.exchange.exchange_utils_timeframe import ( + timeframe_to_floor_freq, timeframe_to_minutes, timeframe_to_msecs, timeframe_to_next_date, diff --git a/freqtrade/exchange/exchange_utils_timeframe.py b/freqtrade/exchange/exchange_utils_timeframe.py index 1897edf3b..ead8e0e18 100644 --- a/freqtrade/exchange/exchange_utils_timeframe.py +++ b/freqtrade/exchange/exchange_utils_timeframe.py @@ -29,6 +29,21 @@ def timeframe_to_msecs(timeframe: str) -> int: return ccxt.Exchange.parse_timeframe(timeframe) * 1000 +def timeframe_to_floor_freq(timeframe: str) -> str: + """ + Translates the timeframe interval value written in the human readable + form ('1m', '5m', '1h', '1d', '1w', etc.) to the desired floor frequency used by pandas + ("1m", "5m", "1h", "1d", "1w", etc.). + Will use minute for most higher timeframes. + """ + timeframe_seconds = timeframe_to_seconds(timeframe) + timeframe_minutes = timeframe_seconds // 60 + if timeframe_minutes <= 1: + return "1s" + else: + return "1min" + + def timeframe_to_resample_freq(timeframe: str) -> str: """ Translates the timeframe interval value written in the human readable