Simplify timerange handling
This commit is contained in:
parent
57313dd961
commit
0f9c5f8d41
@ -8,6 +8,7 @@ from typing import Optional
|
|||||||
|
|
||||||
import arrow
|
import arrow
|
||||||
|
|
||||||
|
from freqtrade.constants import DATETIME_PRINT_FORMAT
|
||||||
from freqtrade.exceptions import OperationalException
|
from freqtrade.exceptions import OperationalException
|
||||||
|
|
||||||
|
|
||||||
@ -41,6 +42,40 @@ class TimeRange:
|
|||||||
return datetime.fromtimestamp(self.stopts, tz=timezone.utc)
|
return datetime.fromtimestamp(self.stopts, tz=timezone.utc)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def timerange_str(self) -> str:
|
||||||
|
"""
|
||||||
|
Returns a string representation of the timerange as used by parse_timerange.
|
||||||
|
Follows the format yyyymmdd-yyyymmdd - leaving out the parts that are not set.
|
||||||
|
"""
|
||||||
|
start = ''
|
||||||
|
stop = ''
|
||||||
|
if startdt := self.startdt:
|
||||||
|
start = startdt.strftime('%Y%m%d')
|
||||||
|
if stopdt := self.stopdt:
|
||||||
|
stop = stopdt.strftime('%Y%m%d')
|
||||||
|
return f"{start}-{stop}"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def start_fmt(self) -> str:
|
||||||
|
"""
|
||||||
|
Returns a string representation of the start date
|
||||||
|
"""
|
||||||
|
val = 'unbounded'
|
||||||
|
if (startdt := self.startdt) is not None:
|
||||||
|
val = startdt.strftime(DATETIME_PRINT_FORMAT)
|
||||||
|
return val
|
||||||
|
|
||||||
|
@property
|
||||||
|
def stop_fmt(self) -> str:
|
||||||
|
"""
|
||||||
|
Returns a string representation of the stop date
|
||||||
|
"""
|
||||||
|
val = 'unbounded'
|
||||||
|
if (stopdt := self.stopdt) is not None:
|
||||||
|
val = stopdt.strftime(DATETIME_PRINT_FORMAT)
|
||||||
|
return val
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
"""Override the default Equals behavior"""
|
"""Override the default Equals behavior"""
|
||||||
return (self.starttype == other.starttype and self.stoptype == other.stoptype
|
return (self.starttype == other.starttype and self.stoptype == other.stoptype
|
||||||
|
@ -432,9 +432,7 @@ class FreqaiDataKitchen:
|
|||||||
timerange_train.stopts = timerange_train.startts + train_period_days
|
timerange_train.stopts = timerange_train.startts + train_period_days
|
||||||
|
|
||||||
first = False
|
first = False
|
||||||
start = timerange_train.startdt
|
tr_training_list.append(timerange_train.timerange_str)
|
||||||
stop = timerange_train.stopdt
|
|
||||||
tr_training_list.append(start.strftime("%Y%m%d") + "-" + stop.strftime("%Y%m%d"))
|
|
||||||
tr_training_list_timerange.append(copy.deepcopy(timerange_train))
|
tr_training_list_timerange.append(copy.deepcopy(timerange_train))
|
||||||
|
|
||||||
# associated backtest period
|
# associated backtest period
|
||||||
@ -446,9 +444,7 @@ class FreqaiDataKitchen:
|
|||||||
if timerange_backtest.stopts > config_timerange.stopts:
|
if timerange_backtest.stopts > config_timerange.stopts:
|
||||||
timerange_backtest.stopts = config_timerange.stopts
|
timerange_backtest.stopts = config_timerange.stopts
|
||||||
|
|
||||||
start = timerange_backtest.startdt
|
tr_backtesting_list.append(timerange_backtest.timerange_str)
|
||||||
stop = timerange_backtest.stopdt
|
|
||||||
tr_backtesting_list.append(start.strftime("%Y%m%d") + "-" + stop.strftime("%Y%m%d"))
|
|
||||||
tr_backtesting_list_timerange.append(copy.deepcopy(timerange_backtest))
|
tr_backtesting_list_timerange.append(copy.deepcopy(timerange_backtest))
|
||||||
|
|
||||||
# ensure we are predicting on exactly same amount of data as requested by user defined
|
# ensure we are predicting on exactly same amount of data as requested by user defined
|
||||||
@ -1055,9 +1051,7 @@ class FreqaiDataKitchen:
|
|||||||
backtest_timerange.startts = (
|
backtest_timerange.startts = (
|
||||||
backtest_timerange.startts - backtest_period_days * SECONDS_IN_DAY
|
backtest_timerange.startts - backtest_period_days * SECONDS_IN_DAY
|
||||||
)
|
)
|
||||||
start = backtest_timerange.startdt
|
full_timerange = backtest_timerange.timerange_str
|
||||||
stop = backtest_timerange.stopdt
|
|
||||||
full_timerange = start.strftime("%Y%m%d") + "-" + stop.strftime("%Y%m%d")
|
|
||||||
config_path = Path(self.config["config_files"][0])
|
config_path = Path(self.config["config_files"][0])
|
||||||
|
|
||||||
if not self.full_path.is_dir():
|
if not self.full_path.is_dir():
|
||||||
|
@ -13,7 +13,7 @@ from numpy.typing import NDArray
|
|||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
|
|
||||||
from freqtrade.configuration import TimeRange
|
from freqtrade.configuration import TimeRange
|
||||||
from freqtrade.constants import DATETIME_PRINT_FORMAT, Config
|
from freqtrade.constants import Config
|
||||||
from freqtrade.enums import RunMode
|
from freqtrade.enums import RunMode
|
||||||
from freqtrade.exceptions import OperationalException
|
from freqtrade.exceptions import OperationalException
|
||||||
from freqtrade.exchange import timeframe_to_seconds
|
from freqtrade.exchange import timeframe_to_seconds
|
||||||
@ -788,14 +788,8 @@ class IFreqaiModel(ABC):
|
|||||||
:return: if the data exists or not
|
:return: if the data exists or not
|
||||||
"""
|
"""
|
||||||
if self.config.get("freqai_backtest_live_models", False) and len(dataframe_backtest) == 0:
|
if self.config.get("freqai_backtest_live_models", False) and len(dataframe_backtest) == 0:
|
||||||
tr_backtest_startts_str = datetime.fromtimestamp(
|
logger.info(f"No data found for pair {pair} from "
|
||||||
tr_backtest.startts,
|
f"from { tr_backtest.start_fmt} to {tr_backtest.stop_fmt}. "
|
||||||
tz=timezone.utc).strftime(DATETIME_PRINT_FORMAT)
|
|
||||||
tr_backtest_stopts_str = datetime.fromtimestamp(
|
|
||||||
tr_backtest.stopts,
|
|
||||||
tz=timezone.utc).strftime(DATETIME_PRINT_FORMAT)
|
|
||||||
logger.info(f"No data found for pair {pair} from {tr_backtest_startts_str} "
|
|
||||||
f" from {tr_backtest_startts_str} to {tr_backtest_stopts_str}. "
|
|
||||||
"Probably more than one training within the same candle period.")
|
"Probably more than one training within the same candle period.")
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
@ -810,18 +804,11 @@ class IFreqaiModel(ABC):
|
|||||||
:param pair: the current pair
|
:param pair: the current pair
|
||||||
:param total_trains: total trains (total number of slides for the sliding window)
|
:param total_trains: total trains (total number of slides for the sliding window)
|
||||||
"""
|
"""
|
||||||
tr_train_startts_str = datetime.fromtimestamp(
|
|
||||||
tr_train.startts,
|
|
||||||
tz=timezone.utc).strftime(DATETIME_PRINT_FORMAT)
|
|
||||||
tr_train_stopts_str = datetime.fromtimestamp(
|
|
||||||
tr_train.stopts,
|
|
||||||
tz=timezone.utc).strftime(DATETIME_PRINT_FORMAT)
|
|
||||||
|
|
||||||
if not self.config.get("freqai_backtest_live_models", False):
|
if not self.config.get("freqai_backtest_live_models", False):
|
||||||
logger.info(
|
logger.info(
|
||||||
f"Training {pair}, {self.pair_it}/{self.total_pairs} pairs"
|
f"Training {pair}, {self.pair_it}/{self.total_pairs} pairs"
|
||||||
f" from {tr_train_startts_str} "
|
f" from {tr_train.start_fmt} "
|
||||||
f"to {tr_train_stopts_str}, {train_it}/{total_trains} "
|
f"to {tr_train.stop_fmt}, {train_it}/{total_trains} "
|
||||||
"trains"
|
"trains"
|
||||||
)
|
)
|
||||||
# Following methods which are overridden by user made prediction models.
|
# Following methods which are overridden by user made prediction models.
|
||||||
|
@ -230,5 +230,4 @@ def get_timerange_backtest_live_models(config: Config) -> str:
|
|||||||
dk = FreqaiDataKitchen(config)
|
dk = FreqaiDataKitchen(config)
|
||||||
models_path = dk.get_full_models_path(config)
|
models_path = dk.get_full_models_path(config)
|
||||||
timerange, _ = dk.get_timerange_and_assets_end_dates_from_ready_models(models_path)
|
timerange, _ = dk.get_timerange_and_assets_end_dates_from_ready_models(models_path)
|
||||||
tr = f"{timerange.startdt.strftime('%Y%m%d')}-{timerange.stopdt.strftime('%Y%m%d')}"
|
return timerange.timerange_str
|
||||||
return tr
|
|
||||||
|
@ -1286,8 +1286,7 @@ class Backtesting:
|
|||||||
def _get_min_cached_backtest_date(self):
|
def _get_min_cached_backtest_date(self):
|
||||||
min_backtest_date = None
|
min_backtest_date = None
|
||||||
backtest_cache_age = self.config.get('backtest_cache', constants.BACKTEST_CACHE_DEFAULT)
|
backtest_cache_age = self.config.get('backtest_cache', constants.BACKTEST_CACHE_DEFAULT)
|
||||||
if self.timerange.stopts == 0 or datetime.fromtimestamp(
|
if self.timerange.stopts == 0 or self.timerange.stopdt > datetime.now(tz=timezone.utc):
|
||||||
self.timerange.stopts, tz=timezone.utc) > datetime.now(tz=timezone.utc):
|
|
||||||
logger.warning('Backtest result caching disabled due to use of open-ended timerange.')
|
logger.warning('Backtest result caching disabled due to use of open-ended timerange.')
|
||||||
elif backtest_cache_age == 'day':
|
elif backtest_cache_age == 'day':
|
||||||
min_backtest_date = datetime.now(tz=timezone.utc) - timedelta(days=1)
|
min_backtest_date = datetime.now(tz=timezone.utc) - timedelta(days=1)
|
||||||
|
@ -10,10 +10,17 @@ from freqtrade.exceptions import OperationalException
|
|||||||
|
|
||||||
def test_parse_timerange_incorrect():
|
def test_parse_timerange_incorrect():
|
||||||
|
|
||||||
assert TimeRange('date', None, 1274486400, 0) == TimeRange.parse_timerange('20100522-')
|
timerange = TimeRange.parse_timerange('20100522-')
|
||||||
assert TimeRange(None, 'date', 0, 1274486400) == TimeRange.parse_timerange('-20100522')
|
assert TimeRange('date', None, 1274486400, 0) == timerange
|
||||||
|
assert timerange.timerange_str == '20100522-'
|
||||||
|
timerange = TimeRange.parse_timerange('-20100522')
|
||||||
|
assert TimeRange(None, 'date', 0, 1274486400) == timerange
|
||||||
|
assert timerange.timerange_str == '-20100522'
|
||||||
timerange = TimeRange.parse_timerange('20100522-20150730')
|
timerange = TimeRange.parse_timerange('20100522-20150730')
|
||||||
assert timerange == TimeRange('date', 'date', 1274486400, 1438214400)
|
assert timerange == TimeRange('date', 'date', 1274486400, 1438214400)
|
||||||
|
assert timerange.timerange_str == '20100522-20150730'
|
||||||
|
assert timerange.start_fmt == '2010-05-22 00:00:00'
|
||||||
|
assert timerange.stop_fmt == '2015-07-30 00:00:00'
|
||||||
|
|
||||||
# Added test for unix timestamp - BTC genesis date
|
# Added test for unix timestamp - BTC genesis date
|
||||||
assert TimeRange('date', None, 1231006505, 0) == TimeRange.parse_timerange('1231006505-')
|
assert TimeRange('date', None, 1231006505, 0) == TimeRange.parse_timerange('1231006505-')
|
||||||
@ -24,6 +31,7 @@ def test_parse_timerange_incorrect():
|
|||||||
assert isinstance(timerange.stopdt, datetime)
|
assert isinstance(timerange.stopdt, datetime)
|
||||||
assert timerange.startdt == datetime.fromtimestamp(1231006505, tz=timezone.utc)
|
assert timerange.startdt == datetime.fromtimestamp(1231006505, tz=timezone.utc)
|
||||||
assert timerange.stopdt == datetime.fromtimestamp(1233360000, tz=timezone.utc)
|
assert timerange.stopdt == datetime.fromtimestamp(1233360000, tz=timezone.utc)
|
||||||
|
assert timerange.timerange_str == '20090103-20090131'
|
||||||
|
|
||||||
timerange = TimeRange.parse_timerange('1231006505000-1233360000000')
|
timerange = TimeRange.parse_timerange('1231006505000-1233360000000')
|
||||||
assert TimeRange('date', 'date', 1231006505, 1233360000) == timerange
|
assert TimeRange('date', 'date', 1231006505, 1233360000) == timerange
|
||||||
|
Loading…
Reference in New Issue
Block a user