Merge pull request #852 from freqtrade/timeframe_class
Refactor Timeframe fake-type into NamedTuple
This commit is contained in:
commit
c75b70463b
@ -7,11 +7,23 @@ import argparse
|
|||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import arrow
|
import arrow
|
||||||
from typing import List, Tuple, Optional
|
from typing import List, Optional, NamedTuple
|
||||||
|
|
||||||
from freqtrade import __version__, constants
|
from freqtrade import __version__, constants
|
||||||
|
|
||||||
|
|
||||||
|
class TimeRange(NamedTuple):
|
||||||
|
"""
|
||||||
|
NamedTuple Defining timerange inputs.
|
||||||
|
[start/stop]type defines if [start/stop]ts shall be used.
|
||||||
|
if *type is none, don't use corresponding startvalue.
|
||||||
|
"""
|
||||||
|
starttype: Optional[str] = None
|
||||||
|
stoptype: Optional[str] = None
|
||||||
|
startts: int = 0
|
||||||
|
stopts: int = 0
|
||||||
|
|
||||||
|
|
||||||
class Arguments(object):
|
class Arguments(object):
|
||||||
"""
|
"""
|
||||||
Arguments Class. Manage the arguments received by the cli
|
Arguments Class. Manage the arguments received by the cli
|
||||||
@ -222,15 +234,14 @@ class Arguments(object):
|
|||||||
self.hyperopt_options(hyperopt_cmd)
|
self.hyperopt_options(hyperopt_cmd)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_timerange(text: Optional[str]) -> \
|
def parse_timerange(text: Optional[str]) -> TimeRange:
|
||||||
Optional[Tuple[Tuple, Optional[int], Optional[int]]]:
|
|
||||||
"""
|
"""
|
||||||
Parse the value of the argument --timerange to determine what is the range desired
|
Parse the value of the argument --timerange to determine what is the range desired
|
||||||
:param text: value from --timerange
|
:param text: value from --timerange
|
||||||
:return: Start and End range period
|
:return: Start and End range period
|
||||||
"""
|
"""
|
||||||
if text is None:
|
if text is None:
|
||||||
return None
|
return TimeRange()
|
||||||
syntax = [(r'^-(\d{8})$', (None, 'date')),
|
syntax = [(r'^-(\d{8})$', (None, 'date')),
|
||||||
(r'^(\d{8})-$', ('date', None)),
|
(r'^(\d{8})-$', ('date', None)),
|
||||||
(r'^(\d{8})-(\d{8})$', ('date', 'date')),
|
(r'^(\d{8})-(\d{8})$', ('date', 'date')),
|
||||||
@ -246,8 +257,8 @@ class Arguments(object):
|
|||||||
if match: # Regex has matched
|
if match: # Regex has matched
|
||||||
rvals = match.groups()
|
rvals = match.groups()
|
||||||
index = 0
|
index = 0
|
||||||
start: Optional[int] = None
|
start: int = 0
|
||||||
stop: Optional[int] = None
|
stop: int = 0
|
||||||
if stype[0]:
|
if stype[0]:
|
||||||
starts = rvals[index]
|
starts = rvals[index]
|
||||||
if stype[0] == 'date':
|
if stype[0] == 'date':
|
||||||
@ -263,7 +274,7 @@ class Arguments(object):
|
|||||||
else arrow.get(stops, 'YYYYMMDD').timestamp
|
else arrow.get(stops, 'YYYYMMDD').timestamp
|
||||||
else:
|
else:
|
||||||
stop = int(stops)
|
stop = int(stops)
|
||||||
return stype, start, stop
|
return TimeRange(stype[0], stype[1], start, stop)
|
||||||
raise Exception('Incorrect syntax for timerange "%s"' % text)
|
raise Exception('Incorrect syntax for timerange "%s"' % text)
|
||||||
|
|
||||||
def scripts_options(self) -> None:
|
def scripts_options(self) -> None:
|
||||||
|
@ -9,39 +9,40 @@ import arrow
|
|||||||
|
|
||||||
from freqtrade import misc, constants
|
from freqtrade import misc, constants
|
||||||
from freqtrade.exchange import get_ticker_history
|
from freqtrade.exchange import get_ticker_history
|
||||||
|
from freqtrade.arguments import TimeRange
|
||||||
|
|
||||||
from user_data.hyperopt_conf import hyperopt_optimize_conf
|
from user_data.hyperopt_conf import hyperopt_optimize_conf
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def trim_tickerlist(tickerlist: List[Dict], timerange: Tuple[Tuple, int, int]) -> List[Dict]:
|
def trim_tickerlist(tickerlist: List[Dict], timerange: TimeRange) -> List[Dict]:
|
||||||
if not tickerlist:
|
if not tickerlist:
|
||||||
return tickerlist
|
return tickerlist
|
||||||
|
|
||||||
stype, start, stop = timerange
|
|
||||||
|
|
||||||
start_index = 0
|
start_index = 0
|
||||||
stop_index = len(tickerlist)
|
stop_index = len(tickerlist)
|
||||||
|
|
||||||
if stype[0] == 'line':
|
if timerange.starttype == 'line':
|
||||||
stop_index = start
|
stop_index = timerange.startts
|
||||||
if stype[0] == 'index':
|
if timerange.starttype == 'index':
|
||||||
start_index = start
|
start_index = timerange.startts
|
||||||
elif stype[0] == 'date':
|
elif timerange.starttype == 'date':
|
||||||
while start_index < len(tickerlist) and tickerlist[start_index][0] < start * 1000:
|
while (start_index < len(tickerlist) and
|
||||||
|
tickerlist[start_index][0] < timerange.startts * 1000):
|
||||||
start_index += 1
|
start_index += 1
|
||||||
|
|
||||||
if stype[1] == 'line':
|
if timerange.stoptype == 'line':
|
||||||
start_index = len(tickerlist) + stop
|
start_index = len(tickerlist) + timerange.stopts
|
||||||
if stype[1] == 'index':
|
if timerange.stoptype == 'index':
|
||||||
stop_index = stop
|
stop_index = timerange.stopts
|
||||||
elif stype[1] == 'date':
|
elif timerange.stoptype == 'date':
|
||||||
while stop_index > 0 and tickerlist[stop_index-1][0] > stop * 1000:
|
while (stop_index > 0 and
|
||||||
|
tickerlist[stop_index-1][0] > timerange.stopts * 1000):
|
||||||
stop_index -= 1
|
stop_index -= 1
|
||||||
|
|
||||||
if start_index > stop_index:
|
if start_index > stop_index:
|
||||||
raise ValueError(f'The timerange [{start},{stop}] is incorrect')
|
raise ValueError(f'The timerange [{timerange.startts},{timerange.stopts}] is incorrect')
|
||||||
|
|
||||||
return tickerlist[start_index:stop_index]
|
return tickerlist[start_index:stop_index]
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ def trim_tickerlist(tickerlist: List[Dict], timerange: Tuple[Tuple, int, int]) -
|
|||||||
def load_tickerdata_file(
|
def load_tickerdata_file(
|
||||||
datadir: str, pair: str,
|
datadir: str, pair: str,
|
||||||
ticker_interval: str,
|
ticker_interval: str,
|
||||||
timerange: Optional[Tuple[Tuple, int, int]] = None) -> Optional[List[Dict]]:
|
timerange: Optional[TimeRange] = None) -> Optional[List[Dict]]:
|
||||||
"""
|
"""
|
||||||
Load a pair from file,
|
Load a pair from file,
|
||||||
:return dict OR empty if unsuccesful
|
:return dict OR empty if unsuccesful
|
||||||
@ -84,7 +85,7 @@ def load_data(datadir: str,
|
|||||||
ticker_interval: str,
|
ticker_interval: str,
|
||||||
pairs: Optional[List[str]] = None,
|
pairs: Optional[List[str]] = None,
|
||||||
refresh_pairs: Optional[bool] = False,
|
refresh_pairs: Optional[bool] = False,
|
||||||
timerange: Optional[Tuple[Tuple, int, int]] = None) -> Dict[str, List]:
|
timerange: TimeRange = TimeRange()) -> Dict[str, List]:
|
||||||
"""
|
"""
|
||||||
Loads ticker history data for the given parameters
|
Loads ticker history data for the given parameters
|
||||||
:return: dict
|
:return: dict
|
||||||
@ -124,7 +125,7 @@ def make_testdata_path(datadir: str) -> str:
|
|||||||
|
|
||||||
def download_pairs(datadir, pairs: List[str],
|
def download_pairs(datadir, pairs: List[str],
|
||||||
ticker_interval: str,
|
ticker_interval: str,
|
||||||
timerange: Optional[Tuple[Tuple, int, int]] = None) -> bool:
|
timerange: TimeRange = TimeRange()) -> bool:
|
||||||
"""For each pairs passed in parameters, download the ticker intervals"""
|
"""For each pairs passed in parameters, download the ticker intervals"""
|
||||||
for pair in pairs:
|
for pair in pairs:
|
||||||
try:
|
try:
|
||||||
@ -144,7 +145,7 @@ def download_pairs(datadir, pairs: List[str],
|
|||||||
|
|
||||||
def load_cached_data_for_updating(filename: str,
|
def load_cached_data_for_updating(filename: str,
|
||||||
tick_interval: str,
|
tick_interval: str,
|
||||||
timerange: Optional[Tuple[Tuple, int, int]]) -> Tuple[
|
timerange: Optional[TimeRange]) -> Tuple[
|
||||||
List[Any],
|
List[Any],
|
||||||
Optional[int]]:
|
Optional[int]]:
|
||||||
"""
|
"""
|
||||||
@ -155,10 +156,10 @@ def load_cached_data_for_updating(filename: str,
|
|||||||
|
|
||||||
# user sets timerange, so find the start time
|
# user sets timerange, so find the start time
|
||||||
if timerange:
|
if timerange:
|
||||||
if timerange[0][0] == 'date':
|
if timerange.starttype == 'date':
|
||||||
since_ms = timerange[1] * 1000
|
since_ms = timerange.startts * 1000
|
||||||
elif timerange[0][1] == 'line':
|
elif timerange.stoptype == 'line':
|
||||||
num_minutes = timerange[2] * constants.TICKER_INTERVAL_MINUTES[tick_interval]
|
num_minutes = timerange.stopts * constants.TICKER_INTERVAL_MINUTES[tick_interval]
|
||||||
since_ms = arrow.utcnow().shift(minutes=num_minutes).timestamp * 1000
|
since_ms = arrow.utcnow().shift(minutes=num_minutes).timestamp * 1000
|
||||||
|
|
||||||
# read the cached file
|
# read the cached file
|
||||||
@ -188,7 +189,7 @@ def load_cached_data_for_updating(filename: str,
|
|||||||
def download_backtesting_testdata(datadir: str,
|
def download_backtesting_testdata(datadir: str,
|
||||||
pair: str,
|
pair: str,
|
||||||
tick_interval: str = '5m',
|
tick_interval: str = '5m',
|
||||||
timerange: Optional[Tuple[Tuple, int, int]] = None) -> None:
|
timerange: Optional[TimeRange] = None) -> None:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Download the latest ticker intervals from the exchange for the pairs passed in parameters
|
Download the latest ticker intervals from the exchange for the pairs passed in parameters
|
||||||
|
@ -221,7 +221,7 @@ class Backtesting(object):
|
|||||||
|
|
||||||
timerange = Arguments.parse_timerange(None if self.config.get(
|
timerange = Arguments.parse_timerange(None if self.config.get(
|
||||||
'timerange') is None else str(self.config.get('timerange')))
|
'timerange') is None else str(self.config.get('timerange')))
|
||||||
data = optimize.load_data( # type: ignore # timerange will be refactored
|
data = optimize.load_data(
|
||||||
self.config['datadir'],
|
self.config['datadir'],
|
||||||
pairs=pairs,
|
pairs=pairs,
|
||||||
ticker_interval=self.ticker_interval,
|
ticker_interval=self.ticker_interval,
|
||||||
|
@ -497,7 +497,7 @@ class Hyperopt(Backtesting):
|
|||||||
def start(self) -> None:
|
def start(self) -> None:
|
||||||
timerange = Arguments.parse_timerange(None if self.config.get(
|
timerange = Arguments.parse_timerange(None if self.config.get(
|
||||||
'timerange') is None else str(self.config.get('timerange')))
|
'timerange') is None else str(self.config.get('timerange')))
|
||||||
data = load_data( # type: ignore # timerange will be refactored
|
data = load_data(
|
||||||
datadir=str(self.config.get('datadir')),
|
datadir=str(self.config.get('datadir')),
|
||||||
pairs=self.config['exchange']['pair_whitelist'],
|
pairs=self.config['exchange']['pair_whitelist'],
|
||||||
ticker_interval=self.ticker_interval,
|
ticker_interval=self.ticker_interval,
|
||||||
|
@ -13,7 +13,7 @@ from arrow import Arrow
|
|||||||
|
|
||||||
from freqtrade import optimize
|
from freqtrade import optimize
|
||||||
from freqtrade.analyze import Analyze
|
from freqtrade.analyze import Analyze
|
||||||
from freqtrade.arguments import Arguments
|
from freqtrade.arguments import Arguments, TimeRange
|
||||||
from freqtrade.optimize.backtesting import Backtesting, start, setup_configuration
|
from freqtrade.optimize.backtesting import Backtesting, start, setup_configuration
|
||||||
from freqtrade.tests.conftest import log_has
|
from freqtrade.tests.conftest import log_has
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ def trim_dictlist(dict_list, num):
|
|||||||
|
|
||||||
|
|
||||||
def load_data_test(what):
|
def load_data_test(what):
|
||||||
timerange = ((None, 'line'), None, -100)
|
timerange = TimeRange(None, 'line', 0, -100)
|
||||||
data = optimize.load_data(None, ticker_interval='1m',
|
data = optimize.load_data(None, ticker_interval='1m',
|
||||||
pairs=['UNITTEST/BTC'], timerange=timerange)
|
pairs=['UNITTEST/BTC'], timerange=timerange)
|
||||||
pair = data['UNITTEST/BTC']
|
pair = data['UNITTEST/BTC']
|
||||||
@ -311,7 +311,7 @@ def test_tickerdata_to_dataframe(default_conf, mocker) -> None:
|
|||||||
Test Backtesting.tickerdata_to_dataframe() method
|
Test Backtesting.tickerdata_to_dataframe() method
|
||||||
"""
|
"""
|
||||||
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
|
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
|
||||||
timerange = ((None, 'line'), None, -100)
|
timerange = TimeRange(None, 'line', 0, -100)
|
||||||
tick = optimize.load_tickerdata_file(None, 'UNITTEST/BTC', '1m', timerange=timerange)
|
tick = optimize.load_tickerdata_file(None, 'UNITTEST/BTC', '1m', timerange=timerange)
|
||||||
tickerlist = {'UNITTEST/BTC': tick}
|
tickerlist = {'UNITTEST/BTC': tick}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ from freqtrade.misc import file_dump_json
|
|||||||
from freqtrade.optimize.__init__ import make_testdata_path, download_pairs, \
|
from freqtrade.optimize.__init__ import make_testdata_path, download_pairs, \
|
||||||
download_backtesting_testdata, load_tickerdata_file, trim_tickerlist, \
|
download_backtesting_testdata, load_tickerdata_file, trim_tickerlist, \
|
||||||
load_cached_data_for_updating
|
load_cached_data_for_updating
|
||||||
|
from freqtrade.arguments import TimeRange
|
||||||
from freqtrade.tests.conftest import log_has
|
from freqtrade.tests.conftest import log_has
|
||||||
|
|
||||||
# Change this if modifying UNITTEST/BTC testdatafile
|
# Change this if modifying UNITTEST/BTC testdatafile
|
||||||
@ -176,7 +177,7 @@ def test_load_cached_data_for_updating(mocker) -> None:
|
|||||||
|
|
||||||
# timeframe starts earlier than the cached data
|
# timeframe starts earlier than the cached data
|
||||||
# should fully update data
|
# should fully update data
|
||||||
timerange = (('date', None), test_data[0][0] / 1000 - 1, None)
|
timerange = TimeRange('date', None, test_data[0][0] / 1000 - 1, 0)
|
||||||
data, start_ts = load_cached_data_for_updating(test_filename,
|
data, start_ts = load_cached_data_for_updating(test_filename,
|
||||||
'1m',
|
'1m',
|
||||||
timerange)
|
timerange)
|
||||||
@ -187,13 +188,13 @@ def test_load_cached_data_for_updating(mocker) -> None:
|
|||||||
num_lines = (test_data[-1][0] - test_data[1][0]) / 1000 / 60 + 120
|
num_lines = (test_data[-1][0] - test_data[1][0]) / 1000 / 60 + 120
|
||||||
data, start_ts = load_cached_data_for_updating(test_filename,
|
data, start_ts = load_cached_data_for_updating(test_filename,
|
||||||
'1m',
|
'1m',
|
||||||
((None, 'line'), None, -num_lines))
|
TimeRange(None, 'line', 0, -num_lines))
|
||||||
assert data == []
|
assert data == []
|
||||||
assert start_ts < test_data[0][0] - 1
|
assert start_ts < test_data[0][0] - 1
|
||||||
|
|
||||||
# timeframe starts in the center of the cached data
|
# timeframe starts in the center of the cached data
|
||||||
# should return the chached data w/o the last item
|
# should return the chached data w/o the last item
|
||||||
timerange = (('date', None), test_data[0][0] / 1000 + 1, None)
|
timerange = TimeRange('date', None, test_data[0][0] / 1000 + 1, 0)
|
||||||
data, start_ts = load_cached_data_for_updating(test_filename,
|
data, start_ts = load_cached_data_for_updating(test_filename,
|
||||||
'1m',
|
'1m',
|
||||||
timerange)
|
timerange)
|
||||||
@ -202,7 +203,7 @@ def test_load_cached_data_for_updating(mocker) -> None:
|
|||||||
|
|
||||||
# same with 'line' timeframe
|
# same with 'line' timeframe
|
||||||
num_lines = (test_data[-1][0] - test_data[1][0]) / 1000 / 60 + 30
|
num_lines = (test_data[-1][0] - test_data[1][0]) / 1000 / 60 + 30
|
||||||
timerange = ((None, 'line'), None, -num_lines)
|
timerange = TimeRange(None, 'line', 0, -num_lines)
|
||||||
data, start_ts = load_cached_data_for_updating(test_filename,
|
data, start_ts = load_cached_data_for_updating(test_filename,
|
||||||
'1m',
|
'1m',
|
||||||
timerange)
|
timerange)
|
||||||
@ -211,7 +212,7 @@ def test_load_cached_data_for_updating(mocker) -> None:
|
|||||||
|
|
||||||
# timeframe starts after the chached data
|
# timeframe starts after the chached data
|
||||||
# should return the chached data w/o the last item
|
# should return the chached data w/o the last item
|
||||||
timerange = (('date', None), test_data[-1][0] / 1000 + 1, None)
|
timerange = TimeRange('date', None, test_data[-1][0] / 1000 + 1, 0)
|
||||||
data, start_ts = load_cached_data_for_updating(test_filename,
|
data, start_ts = load_cached_data_for_updating(test_filename,
|
||||||
'1m',
|
'1m',
|
||||||
timerange)
|
timerange)
|
||||||
@ -220,7 +221,7 @@ def test_load_cached_data_for_updating(mocker) -> None:
|
|||||||
|
|
||||||
# same with 'line' timeframe
|
# same with 'line' timeframe
|
||||||
num_lines = 30
|
num_lines = 30
|
||||||
timerange = ((None, 'line'), None, -num_lines)
|
timerange = TimeRange(None, 'line', 0, -num_lines)
|
||||||
data, start_ts = load_cached_data_for_updating(test_filename,
|
data, start_ts = load_cached_data_for_updating(test_filename,
|
||||||
'1m',
|
'1m',
|
||||||
timerange)
|
timerange)
|
||||||
@ -230,7 +231,7 @@ def test_load_cached_data_for_updating(mocker) -> None:
|
|||||||
# no timeframe is set
|
# no timeframe is set
|
||||||
# should return the chached data w/o the last item
|
# should return the chached data w/o the last item
|
||||||
num_lines = 30
|
num_lines = 30
|
||||||
timerange = ((None, 'line'), None, -num_lines)
|
timerange = TimeRange(None, 'line', 0, -num_lines)
|
||||||
data, start_ts = load_cached_data_for_updating(test_filename,
|
data, start_ts = load_cached_data_for_updating(test_filename,
|
||||||
'1m',
|
'1m',
|
||||||
timerange)
|
timerange)
|
||||||
@ -239,7 +240,7 @@ def test_load_cached_data_for_updating(mocker) -> None:
|
|||||||
|
|
||||||
# no datafile exist
|
# no datafile exist
|
||||||
# should return timestamp start time
|
# should return timestamp start time
|
||||||
timerange = (('date', None), now_ts - 10000, None)
|
timerange = TimeRange('date', None, now_ts - 10000, 0)
|
||||||
data, start_ts = load_cached_data_for_updating(test_filename + 'unexist',
|
data, start_ts = load_cached_data_for_updating(test_filename + 'unexist',
|
||||||
'1m',
|
'1m',
|
||||||
timerange)
|
timerange)
|
||||||
@ -248,7 +249,7 @@ def test_load_cached_data_for_updating(mocker) -> None:
|
|||||||
|
|
||||||
# same with 'line' timeframe
|
# same with 'line' timeframe
|
||||||
num_lines = 30
|
num_lines = 30
|
||||||
timerange = ((None, 'line'), None, -num_lines)
|
timerange = TimeRange(None, 'line', 0, -num_lines)
|
||||||
data, start_ts = load_cached_data_for_updating(test_filename + 'unexist',
|
data, start_ts = load_cached_data_for_updating(test_filename + 'unexist',
|
||||||
'1m',
|
'1m',
|
||||||
timerange)
|
timerange)
|
||||||
@ -343,7 +344,7 @@ def test_trim_tickerlist() -> None:
|
|||||||
|
|
||||||
# Test the pattern ^(-\d+)$
|
# Test the pattern ^(-\d+)$
|
||||||
# This pattern uses the latest N elements
|
# This pattern uses the latest N elements
|
||||||
timerange = ((None, 'line'), None, -5)
|
timerange = TimeRange(None, 'line', 0, -5)
|
||||||
ticker = trim_tickerlist(ticker_list, timerange)
|
ticker = trim_tickerlist(ticker_list, timerange)
|
||||||
ticker_len = len(ticker)
|
ticker_len = len(ticker)
|
||||||
|
|
||||||
@ -353,7 +354,7 @@ def test_trim_tickerlist() -> None:
|
|||||||
|
|
||||||
# Test the pattern ^(\d+)-$
|
# Test the pattern ^(\d+)-$
|
||||||
# This pattern keep X element from the end
|
# This pattern keep X element from the end
|
||||||
timerange = (('line', None), 5, None)
|
timerange = TimeRange('line', None, 5, 0)
|
||||||
ticker = trim_tickerlist(ticker_list, timerange)
|
ticker = trim_tickerlist(ticker_list, timerange)
|
||||||
ticker_len = len(ticker)
|
ticker_len = len(ticker)
|
||||||
|
|
||||||
@ -363,7 +364,7 @@ def test_trim_tickerlist() -> None:
|
|||||||
|
|
||||||
# Test the pattern ^(\d+)-(\d+)$
|
# Test the pattern ^(\d+)-(\d+)$
|
||||||
# This pattern extract a window
|
# This pattern extract a window
|
||||||
timerange = (('index', 'index'), 5, 10)
|
timerange = TimeRange('index', 'index', 5, 10)
|
||||||
ticker = trim_tickerlist(ticker_list, timerange)
|
ticker = trim_tickerlist(ticker_list, timerange)
|
||||||
ticker_len = len(ticker)
|
ticker_len = len(ticker)
|
||||||
|
|
||||||
@ -374,7 +375,7 @@ def test_trim_tickerlist() -> None:
|
|||||||
|
|
||||||
# Test the pattern ^(\d{8})-(\d{8})$
|
# Test the pattern ^(\d{8})-(\d{8})$
|
||||||
# This pattern extract a window between the dates
|
# This pattern extract a window between the dates
|
||||||
timerange = (('date', 'date'), ticker_list[5][0] / 1000, ticker_list[10][0] / 1000 - 1)
|
timerange = TimeRange('date', 'date', ticker_list[5][0] / 1000, ticker_list[10][0] / 1000 - 1)
|
||||||
ticker = trim_tickerlist(ticker_list, timerange)
|
ticker = trim_tickerlist(ticker_list, timerange)
|
||||||
ticker_len = len(ticker)
|
ticker_len = len(ticker)
|
||||||
|
|
||||||
@ -385,7 +386,7 @@ def test_trim_tickerlist() -> None:
|
|||||||
|
|
||||||
# Test the pattern ^-(\d{8})$
|
# Test the pattern ^-(\d{8})$
|
||||||
# This pattern extracts elements from the start to the date
|
# This pattern extracts elements from the start to the date
|
||||||
timerange = ((None, 'date'), None, ticker_list[10][0] / 1000 - 1)
|
timerange = TimeRange(None, 'date', 0, ticker_list[10][0] / 1000 - 1)
|
||||||
ticker = trim_tickerlist(ticker_list, timerange)
|
ticker = trim_tickerlist(ticker_list, timerange)
|
||||||
ticker_len = len(ticker)
|
ticker_len = len(ticker)
|
||||||
|
|
||||||
@ -395,7 +396,7 @@ def test_trim_tickerlist() -> None:
|
|||||||
|
|
||||||
# Test the pattern ^(\d{8})-$
|
# Test the pattern ^(\d{8})-$
|
||||||
# This pattern extracts elements from the date to now
|
# This pattern extracts elements from the date to now
|
||||||
timerange = (('date', None), ticker_list[10][0] / 1000 - 1, None)
|
timerange = TimeRange('date', None, ticker_list[10][0] / 1000 - 1, None)
|
||||||
ticker = trim_tickerlist(ticker_list, timerange)
|
ticker = trim_tickerlist(ticker_list, timerange)
|
||||||
ticker_len = len(ticker)
|
ticker_len = len(ticker)
|
||||||
|
|
||||||
@ -405,7 +406,7 @@ def test_trim_tickerlist() -> None:
|
|||||||
|
|
||||||
# Test a wrong pattern
|
# Test a wrong pattern
|
||||||
# This pattern must return the list unchanged
|
# This pattern must return the list unchanged
|
||||||
timerange = ((None, None), None, 5)
|
timerange = TimeRange(None, None, None, 5)
|
||||||
ticker = trim_tickerlist(ticker_list, timerange)
|
ticker = trim_tickerlist(ticker_list, timerange)
|
||||||
ticker_len = len(ticker)
|
ticker_len = len(ticker)
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ from pandas import DataFrame
|
|||||||
|
|
||||||
from freqtrade.analyze import Analyze, SignalType
|
from freqtrade.analyze import Analyze, SignalType
|
||||||
from freqtrade.optimize.__init__ import load_tickerdata_file
|
from freqtrade.optimize.__init__ import load_tickerdata_file
|
||||||
|
from freqtrade.arguments import TimeRange
|
||||||
from freqtrade.tests.conftest import log_has
|
from freqtrade.tests.conftest import log_has
|
||||||
|
|
||||||
# Avoid to reinit the same object again and again
|
# Avoid to reinit the same object again and again
|
||||||
@ -183,7 +184,7 @@ def test_tickerdata_to_dataframe(default_conf) -> None:
|
|||||||
"""
|
"""
|
||||||
analyze = Analyze(default_conf)
|
analyze = Analyze(default_conf)
|
||||||
|
|
||||||
timerange = ((None, 'line'), None, -100)
|
timerange = TimeRange(None, 'line', 0, -100)
|
||||||
tick = load_tickerdata_file(None, 'UNITTEST/BTC', '1m', timerange=timerange)
|
tick = load_tickerdata_file(None, 'UNITTEST/BTC', '1m', timerange=timerange)
|
||||||
tickerlist = {'UNITTEST/BTC': tick}
|
tickerlist = {'UNITTEST/BTC': tick}
|
||||||
data = analyze.tickerdata_to_dataframe(tickerlist)
|
data = analyze.tickerdata_to_dataframe(tickerlist)
|
||||||
|
@ -9,7 +9,7 @@ import logging
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from freqtrade.arguments import Arguments
|
from freqtrade.arguments import Arguments, TimeRange
|
||||||
|
|
||||||
|
|
||||||
def test_arguments_object() -> None:
|
def test_arguments_object() -> None:
|
||||||
@ -107,20 +107,24 @@ def test_parse_args_dynamic_whitelist_invalid_values() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_parse_timerange_incorrect() -> None:
|
def test_parse_timerange_incorrect() -> None:
|
||||||
assert ((None, 'line'), None, -200) == Arguments.parse_timerange('-200')
|
assert TimeRange(None, 'line', 0, -200) == Arguments.parse_timerange('-200')
|
||||||
assert (('line', None), 200, None) == Arguments.parse_timerange('200-')
|
assert TimeRange('line', None, 200, 0) == Arguments.parse_timerange('200-')
|
||||||
assert (('index', 'index'), 200, 500) == Arguments.parse_timerange('200-500')
|
assert TimeRange('index', 'index', 200, 500) == Arguments.parse_timerange('200-500')
|
||||||
|
|
||||||
assert (('date', None), 1274486400, None) == Arguments.parse_timerange('20100522-')
|
assert TimeRange('date', None, 1274486400, 0) == Arguments.parse_timerange('20100522-')
|
||||||
assert ((None, 'date'), None, 1274486400) == Arguments.parse_timerange('-20100522')
|
assert TimeRange(None, 'date', 0, 1274486400) == Arguments.parse_timerange('-20100522')
|
||||||
timerange = Arguments.parse_timerange('20100522-20150730')
|
timerange = Arguments.parse_timerange('20100522-20150730')
|
||||||
assert timerange == (('date', 'date'), 1274486400, 1438214400)
|
assert timerange == TimeRange('date', 'date', 1274486400, 1438214400)
|
||||||
|
|
||||||
# Added test for unix timestamp - BTC genesis date
|
# Added test for unix timestamp - BTC genesis date
|
||||||
assert (('date', None), 1231006505, None) == Arguments.parse_timerange('1231006505-')
|
assert TimeRange('date', None, 1231006505, 0) == Arguments.parse_timerange('1231006505-')
|
||||||
assert ((None, 'date'), None, 1233360000) == Arguments.parse_timerange('-1233360000')
|
assert TimeRange(None, 'date', 0, 1233360000) == Arguments.parse_timerange('-1233360000')
|
||||||
timerange = Arguments.parse_timerange('1231006505-1233360000')
|
timerange = Arguments.parse_timerange('1231006505-1233360000')
|
||||||
assert timerange == (('date', 'date'), 1231006505, 1233360000)
|
assert TimeRange('date', 'date', 1231006505, 1233360000) == timerange
|
||||||
|
|
||||||
|
# TODO: Find solution for the following case (passing timestamp in ms)
|
||||||
|
timerange = Arguments.parse_timerange('1231006505000-1233360000000')
|
||||||
|
assert TimeRange('date', 'date', 1231006505, 1233360000) != timerange
|
||||||
|
|
||||||
with pytest.raises(Exception, match=r'Incorrect syntax.*'):
|
with pytest.raises(Exception, match=r'Incorrect syntax.*'):
|
||||||
Arguments.parse_timerange('-')
|
Arguments.parse_timerange('-')
|
||||||
|
Loading…
Reference in New Issue
Block a user