Move parse_timerange to TimeRange class

This commit is contained in:
Matthias 2019-08-14 10:07:14 +02:00
parent 3b30aab8a7
commit 06fa07e73e
4 changed files with 95 additions and 82 deletions

View File

@ -2,10 +2,8 @@
This module contains the argument manager class This module contains the argument manager class
""" """
import argparse import argparse
import re from typing import List, Optional
from typing import List, NamedTuple, Optional
import arrow
from freqtrade.configuration.cli_options import AVAILABLE_CLI_OPTIONS from freqtrade.configuration.cli_options import AVAILABLE_CLI_OPTIONS
from freqtrade import constants from freqtrade import constants
@ -43,18 +41,6 @@ ARGS_PLOT_PROFIT = (ARGS_COMMON + ARGS_STRATEGY +
["pairs", "timerange", "export", "exportfilename", "db_url", "trade_source"]) ["pairs", "timerange", "export", "exportfilename", "db_url", "trade_source"])
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
@ -133,45 +119,3 @@ class Arguments(object):
) )
list_exchanges_cmd.set_defaults(func=start_list_exchanges) list_exchanges_cmd.set_defaults(func=start_list_exchanges)
self._build_args(optionlist=ARGS_LIST_EXCHANGES, parser=list_exchanges_cmd) self._build_args(optionlist=ARGS_LIST_EXCHANGES, parser=list_exchanges_cmd)
@staticmethod
def parse_timerange(text: Optional[str]) -> TimeRange:
"""
Parse the value of the argument --timerange to determine what is the range desired
:param text: value from --timerange
:return: Start and End range period
"""
if text is None:
return TimeRange(None, None, 0, 0)
syntax = [(r'^-(\d{8})$', (None, 'date')),
(r'^(\d{8})-$', ('date', None)),
(r'^(\d{8})-(\d{8})$', ('date', 'date')),
(r'^-(\d{10})$', (None, 'date')),
(r'^(\d{10})-$', ('date', None)),
(r'^(\d{10})-(\d{10})$', ('date', 'date')),
(r'^(-\d+)$', (None, 'line')),
(r'^(\d+)-$', ('line', None)),
(r'^(\d+)-(\d+)$', ('index', 'index'))]
for rex, stype in syntax:
# Apply the regular expression to text
match = re.match(rex, text)
if match: # Regex has matched
rvals = match.groups()
index = 0
start: int = 0
stop: int = 0
if stype[0]:
starts = rvals[index]
if stype[0] == 'date' and len(starts) == 8:
start = arrow.get(starts, 'YYYYMMDD').timestamp
else:
start = int(starts)
index += 1
if stype[1]:
stops = rvals[index]
if stype[1] == 'date' and len(stops) == 8:
stop = arrow.get(stops, 'YYYYMMDD').timestamp
else:
stop = int(stops)
return TimeRange(stype[0], stype[1], start, stop)
raise Exception('Incorrect syntax for timerange "%s"' % text)

View File

@ -0,0 +1,65 @@
"""
This module contains the argument manager class
"""
import re
from typing import Optional
import arrow
class TimeRange():
"""
object defining timerange inputs.
[start/stop]type defines if [start/stop]ts shall be used.
if *type is None, don't use corresponding startvalue.
"""
def __init__(self, starttype: Optional[str], stoptype: Optional[str],
startts: int, stopts: int):
self.starttype: Optional[str] = starttype
self.stoptype: Optional[str] = stoptype
self.startts: int = startts
self.stopts: int = stopts
@staticmethod
def parse_timerange(text: Optional[str]):
"""
Parse the value of the argument --timerange to determine what is the range desired
:param text: value from --timerange
:return: Start and End range period
"""
if text is None:
return TimeRange(None, None, 0, 0)
syntax = [(r'^-(\d{8})$', (None, 'date')),
(r'^(\d{8})-$', ('date', None)),
(r'^(\d{8})-(\d{8})$', ('date', 'date')),
(r'^-(\d{10})$', (None, 'date')),
(r'^(\d{10})-$', ('date', None)),
(r'^(\d{10})-(\d{10})$', ('date', 'date')),
(r'^(-\d+)$', (None, 'line')),
(r'^(\d+)-$', ('line', None)),
(r'^(\d+)-(\d+)$', ('index', 'index'))]
for rex, stype in syntax:
# Apply the regular expression to text
match = re.match(rex, text)
if match: # Regex has matched
rvals = match.groups()
index = 0
start: int = 0
stop: int = 0
if stype[0]:
starts = rvals[index]
if stype[0] == 'date' and len(starts) == 8:
start = arrow.get(starts, 'YYYYMMDD').timestamp
else:
start = int(starts)
index += 1
if stype[1]:
stops = rvals[index]
if stype[1] == 'date' and len(stops) == 8:
stop = arrow.get(stops, 'YYYYMMDD').timestamp
else:
stop = int(stops)
return TimeRange(stype[0], stype[1], start, stop)
raise Exception('Incorrect syntax for timerange "%s"' % text)

View File

@ -3,7 +3,7 @@ import argparse
import pytest import pytest
from freqtrade.configuration import Arguments, TimeRange from freqtrade.configuration import Arguments
from freqtrade.configuration.arguments import ARGS_DOWNLOADER, ARGS_PLOT_DATAFRAME from freqtrade.configuration.arguments import ARGS_DOWNLOADER, ARGS_PLOT_DATAFRAME
from freqtrade.configuration.cli_options import check_int_positive from freqtrade.configuration.cli_options import check_int_positive
@ -86,30 +86,6 @@ def test_parse_args_strategy_path_invalid() -> None:
Arguments(['--strategy-path'], '').get_parsed_arg() Arguments(['--strategy-path'], '').get_parsed_arg()
def test_parse_timerange_incorrect() -> None:
assert TimeRange(None, 'line', 0, -200) == Arguments.parse_timerange('-200')
assert TimeRange('line', None, 200, 0) == Arguments.parse_timerange('200-')
assert TimeRange('index', 'index', 200, 500) == Arguments.parse_timerange('200-500')
assert TimeRange('date', None, 1274486400, 0) == Arguments.parse_timerange('20100522-')
assert TimeRange(None, 'date', 0, 1274486400) == Arguments.parse_timerange('-20100522')
timerange = Arguments.parse_timerange('20100522-20150730')
assert timerange == TimeRange('date', 'date', 1274486400, 1438214400)
# Added test for unix timestamp - BTC genesis date
assert TimeRange('date', None, 1231006505, 0) == Arguments.parse_timerange('1231006505-')
assert TimeRange(None, 'date', 0, 1233360000) == Arguments.parse_timerange('-1233360000')
timerange = Arguments.parse_timerange('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.*'):
Arguments.parse_timerange('-')
def test_parse_args_backtesting_invalid() -> None: def test_parse_args_backtesting_invalid() -> None:
with pytest.raises(SystemExit, match=r'2'): with pytest.raises(SystemExit, match=r'2'):
Arguments(['backtesting --ticker-interval'], '').get_parsed_arg() Arguments(['backtesting --ticker-interval'], '').get_parsed_arg()

View File

@ -0,0 +1,28 @@
# pragma pylint: disable=missing-docstring, C0103
import pytest
from freqtrade.configuration import TimeRange
def test_parse_timerange_incorrect() -> None:
assert TimeRange(None, 'line', 0, -200) == TimeRange.parse_timerange('-200')
assert TimeRange('line', None, 200, 0) == TimeRange.parse_timerange('200-')
assert TimeRange('index', 'index', 200, 500) == TimeRange.parse_timerange('200-500')
assert TimeRange('date', None, 1274486400, 0) == TimeRange.parse_timerange('20100522-')
assert TimeRange(None, 'date', 0, 1274486400) == TimeRange.parse_timerange('-20100522')
timerange = TimeRange.parse_timerange('20100522-20150730')
assert timerange == TimeRange('date', 'date', 1274486400, 1438214400)
# Added test for unix timestamp - BTC genesis date
assert TimeRange('date', None, 1231006505, 0) == TimeRange.parse_timerange('1231006505-')
assert TimeRange(None, 'date', 0, 1233360000) == TimeRange.parse_timerange('-1233360000')
timerange = TimeRange.parse_timerange('1231006505-1233360000')
assert TimeRange('date', 'date', 1231006505, 1233360000) == timerange
# TODO: Find solution for the following case (passing timestamp in ms)
timerange = TimeRange.parse_timerange('1231006505000-1233360000000')
assert TimeRange('date', 'date', 1231006505, 1233360000) != timerange
with pytest.raises(Exception, match=r'Incorrect syntax.*'):
TimeRange.parse_timerange('-')