Move parse_timerange to TimeRange class
This commit is contained in:
parent
3b30aab8a7
commit
06fa07e73e
@ -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)
|
|
||||||
|
65
freqtrade/configuration/timerange.py
Normal file
65
freqtrade/configuration/timerange.py
Normal 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)
|
@ -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()
|
||||||
|
28
freqtrade/tests/test_timerange.py
Normal file
28
freqtrade/tests/test_timerange.py
Normal 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('-')
|
Loading…
Reference in New Issue
Block a user