diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 657f382d8..3d2bf07c7 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -6,7 +6,7 @@ import asyncio import inspect import logging from copy import deepcopy -from datetime import datetime +from datetime import datetime, timezone from math import ceil, floor from random import randint from typing import Any, Dict, List, Optional, Tuple @@ -781,13 +781,25 @@ def timeframe_to_seconds(ticker_interval: str) -> int: def timeframe_to_minutes(ticker_interval: str) -> int: """ - Same as above, but returns minutes. + Same as timeframe_to_seconds, but returns minutes. """ return ccxt.Exchange.parse_timeframe(ticker_interval) // 60 def timeframe_to_msecs(ticker_interval: str) -> int: """ - Same as above, but returns milliseconds. + Same as timeframe_to_seconds, but returns milliseconds. """ return ccxt.Exchange.parse_timeframe(ticker_interval) * 1000 + + +def timeframe_to_next_date(timeframe: str, date: datetime = None): + """ + Use Timeframe and determine next candle. + """ + if not date: + date = datetime.utcnow() + timeframe_secs = timeframe_to_seconds(timeframe) + offset = date.timestamp() % timeframe_secs + new_timestamp = date.timestamp() + (timeframe_secs - offset) + return datetime.fromtimestamp(new_timestamp, tz=timezone.utc) diff --git a/freqtrade/tests/exchange/test_exchange.py b/freqtrade/tests/exchange/test_exchange.py index 245814a36..23384aebe 100644 --- a/freqtrade/tests/exchange/test_exchange.py +++ b/freqtrade/tests/exchange/test_exchange.py @@ -14,7 +14,9 @@ from pandas import DataFrame from freqtrade import (DependencyException, InvalidOrderException, OperationalException, TemporaryError) from freqtrade.exchange import Binance, Exchange, Kraken -from freqtrade.exchange.exchange import (API_RETRY_COUNT, timeframe_to_minutes, +from freqtrade.exchange.exchange import (API_RETRY_COUNT, + timeframe_to_next_date, + timeframe_to_minutes, timeframe_to_msecs, timeframe_to_seconds) from freqtrade.resolvers.exchange_resolver import ExchangeResolver @@ -1563,3 +1565,27 @@ def test_timeframe_to_msecs(): assert timeframe_to_msecs("10m") == 600000 assert timeframe_to_msecs("1h") == 3600000 assert timeframe_to_msecs("1d") == 86400000 + + +def test_timeframe_to_next_date(): + # 2019-08-12 13:22:08 + date = datetime.fromtimestamp(1565616128, tz=timezone.utc) + + # 5m -> 2019-08-12 13:25:00 + assert timeframe_to_next_date("5m", date) == datetime( + 2019, 8, 12, 13, 25, 0, tzinfo=timezone.utc) + # 10m -> 2019-08-12 13:30:00 + assert timeframe_to_next_date("10m", date) == datetime( + 2019, 8, 12, 13, 30, 0, tzinfo=timezone.utc) + # 1h -> 2019-08-12 14:00:00 + assert timeframe_to_next_date("1h", date) == datetime( + 2019, 8, 12, 14, 00, 0, tzinfo=timezone.utc) + # 2h -> 2019-08-12 14:00:00 + assert timeframe_to_next_date("2h", date) == datetime( + 2019, 8, 12, 14, 00, 0, tzinfo=timezone.utc) + # 4h -> 2019-08-12 14:00:00 + assert timeframe_to_next_date("4h", date) == datetime( + 2019, 8, 12, 16, 00, 0, tzinfo=timezone.utc) + # 1d -> 2019-08-13 00:00:00 + assert timeframe_to_next_date("1d", date) == datetime( + 2019, 8, 13, 0, 0, 0, tzinfo=timezone.utc)