diff --git a/freqtrade/data/converter/converter.py b/freqtrade/data/converter/converter.py index 9969e382a..a34cc0f4c 100644 --- a/freqtrade/data/converter/converter.py +++ b/freqtrade/data/converter/converter.py @@ -84,7 +84,7 @@ def ohlcv_fill_up_missing_data(dataframe: DataFrame, timeframe: str, pair: str) using the previous close as price for "open", "high" "low" and "close", volume is set to 0 """ - from freqtrade.exchange import timeframe_to_seconds + from freqtrade.exchange import timeframe_as_resample_freq ohlcv_dict = { 'open': 'first', @@ -93,14 +93,7 @@ def ohlcv_fill_up_missing_data(dataframe: DataFrame, timeframe: str, pair: str) 'close': 'last', 'volume': 'sum' } - timeframe_seconds = timeframe_to_seconds(timeframe) - timeframe_minutes = timeframe_seconds // 60 - resample_interval = f'{timeframe_seconds}s' - if timeframe_minutes >= 43200 and timeframe_minutes < 525600: - # Monthly candles need special treatment to stick to the 1st of the month - resample_interval = f'{timeframe}S' - elif timeframe_minutes > 43200: - resample_interval = timeframe + resample_interval = timeframe_as_resample_freq(timeframe) # Resample to create "NAN" values df = dataframe.resample(resample_interval, on='date').agg(ohlcv_dict) diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py index 938b3e770..86331a9b8 100644 --- a/freqtrade/exchange/__init__.py +++ b/freqtrade/exchange/__init__.py @@ -15,9 +15,10 @@ from freqtrade.exchange.exchange_utils import (ROUND_DOWN, ROUND_UP, amount_to_c contracts_to_amount, date_minus_candles, is_exchange_known_ccxt, list_available_exchanges, market_is_active, price_to_precision, - timeframe_to_minutes, timeframe_to_msecs, - timeframe_to_next_date, timeframe_to_prev_date, - timeframe_to_seconds, validate_exchange) + timeframe_as_resample_freq, timeframe_to_minutes, + timeframe_to_msecs, timeframe_to_next_date, + timeframe_to_prev_date, timeframe_to_seconds, + validate_exchange) from freqtrade.exchange.gate import Gate from freqtrade.exchange.hitbtc import Hitbtc from freqtrade.exchange.htx import Htx diff --git a/freqtrade/exchange/exchange_utils.py b/freqtrade/exchange/exchange_utils.py index 4dfa97b28..2f8191372 100644 --- a/freqtrade/exchange/exchange_utils.py +++ b/freqtrade/exchange/exchange_utils.py @@ -118,6 +118,23 @@ def timeframe_to_msecs(timeframe: str) -> int: return ccxt.Exchange.parse_timeframe(timeframe) * 1000 +def timeframe_as_resample_freq(timeframe: str) -> str: + """ + Translates the timeframe interval value written in the human readable + form ('1m', '5m', '1h', '1d', '1w', etc.) to the resample frequency + used by pandas ('1T', '5T', '1H', '1D', '1W', etc.) + """ + timeframe_seconds = timeframe_to_seconds(timeframe) + timeframe_minutes = timeframe_seconds // 60 + resample_interval = f'{timeframe_seconds}s' + if timeframe_minutes >= 43200 and timeframe_minutes < 525600: + # Monthly candles need special treatment to stick to the 1st of the month + resample_interval = f'{timeframe}S' + elif timeframe_minutes > 43200: + resample_interval = timeframe + return resample_interval + + def timeframe_to_prev_date(timeframe: str, date: Optional[datetime] = None) -> datetime: """ Use Timeframe and determine the candle start date for this date. diff --git a/tests/exchange/test_exchange_utils.py b/tests/exchange/test_exchange_utils.py index 6a4137369..1217ec07a 100644 --- a/tests/exchange/test_exchange_utils.py +++ b/tests/exchange/test_exchange_utils.py @@ -8,9 +8,9 @@ from ccxt import (DECIMAL_PLACES, ROUND, ROUND_DOWN, ROUND_UP, SIGNIFICANT_DIGIT from freqtrade.enums import RunMode from freqtrade.exceptions import OperationalException from freqtrade.exchange import (amount_to_contract_precision, amount_to_precision, - date_minus_candles, price_to_precision, timeframe_to_minutes, - timeframe_to_msecs, timeframe_to_next_date, timeframe_to_prev_date, - timeframe_to_seconds) + date_minus_candles, price_to_precision, timeframe_as_resample_freq, + timeframe_to_minutes, timeframe_to_msecs, timeframe_to_next_date, + timeframe_to_prev_date, timeframe_to_seconds) from freqtrade.exchange.check_exchange import check_exchange from tests.conftest import log_has_re @@ -124,6 +124,20 @@ def test_timeframe_to_msecs(): assert timeframe_to_msecs("1d") == 86400000 +@pytest.mark.parametrize("timeframe,expected", [ + ("1s", '1s'), + ("15s", '15s'), + ("5m", '300s'), + ("10m", '600s'), + ("1h", '3600s'), + ("1d", '86400s'), + ("1w", '604800s'), + ("1M", '1MS'), +]) +def test_timeframe_as_resample_freq(timeframe, expected): + assert timeframe_as_resample_freq(timeframe) == expected + + def test_timeframe_to_prev_date(): # 2019-08-12 13:22:08 date = datetime.fromtimestamp(1565616128, tz=timezone.utc)