2017-11-18 07:45:01 +00:00
|
|
|
# pragma pylint: disable=missing-docstring,C0103
|
2017-12-11 07:56:03 +00:00
|
|
|
|
2018-02-04 07:33:54 +00:00
|
|
|
import datetime
|
2019-08-16 11:04:07 +00:00
|
|
|
from pathlib import Path
|
2018-02-04 07:33:54 +00:00
|
|
|
from unittest.mock import MagicMock
|
2018-03-17 21:44:47 +00:00
|
|
|
|
2020-01-05 09:36:08 +00:00
|
|
|
import pytest
|
|
|
|
|
2020-03-08 10:35:31 +00:00
|
|
|
from freqtrade.data.converter import ohlcv_to_dataframe
|
2019-06-30 11:15:41 +00:00
|
|
|
from freqtrade.misc import (datesarray_to_datetimearray, file_dump_json,
|
2020-01-05 09:36:08 +00:00
|
|
|
file_load_json, format_ms_time, pair_to_filename,
|
2020-03-01 08:34:42 +00:00
|
|
|
plural, render_template,
|
2020-04-19 04:58:44 +00:00
|
|
|
render_template_with_fallback, safe_value_fallback,
|
2020-07-15 17:49:51 +00:00
|
|
|
safe_value_fallback2, shorten_date)
|
2017-11-20 18:37:25 +00:00
|
|
|
|
|
|
|
|
2018-02-04 07:33:54 +00:00
|
|
|
def test_shorten_date() -> None:
|
|
|
|
str_data = '1 day, 2 hours, 3 minutes, 4 seconds ago'
|
|
|
|
str_shorten_data = '1 d, 2 h, 3 min, 4 sec ago'
|
|
|
|
assert shorten_date(str_data) == str_shorten_data
|
2018-01-29 00:25:15 +00:00
|
|
|
|
|
|
|
|
2020-03-08 10:35:31 +00:00
|
|
|
def test_datesarray_to_datetimearray(ohlcv_history_list):
|
|
|
|
dataframes = ohlcv_to_dataframe(ohlcv_history_list, "5m", pair="UNITTEST/BTC",
|
|
|
|
fill_missing=True)
|
2018-01-29 00:25:15 +00:00
|
|
|
dates = datesarray_to_datetimearray(dataframes['date'])
|
|
|
|
|
|
|
|
assert isinstance(dates[0], datetime.datetime)
|
|
|
|
assert dates[0].year == 2017
|
|
|
|
assert dates[0].month == 11
|
|
|
|
assert dates[0].day == 26
|
|
|
|
assert dates[0].hour == 8
|
|
|
|
assert dates[0].minute == 50
|
|
|
|
|
|
|
|
date_len = len(dates)
|
2018-06-07 09:56:39 +00:00
|
|
|
assert date_len == 2
|
2018-02-04 07:33:54 +00:00
|
|
|
|
|
|
|
|
2018-02-04 09:21:16 +00:00
|
|
|
def test_file_dump_json(mocker) -> None:
|
2018-02-04 07:33:54 +00:00
|
|
|
file_open = mocker.patch('freqtrade.misc.open', MagicMock())
|
2018-12-28 09:01:16 +00:00
|
|
|
json_dump = mocker.patch('rapidjson.dump', MagicMock())
|
2019-08-16 11:04:07 +00:00
|
|
|
file_dump_json(Path('somefile'), [1, 2, 3])
|
2018-02-04 07:33:54 +00:00
|
|
|
assert file_open.call_count == 1
|
|
|
|
assert json_dump.call_count == 1
|
2018-03-30 21:30:23 +00:00
|
|
|
file_open = mocker.patch('freqtrade.misc.gzip.open', MagicMock())
|
2018-12-28 09:01:16 +00:00
|
|
|
json_dump = mocker.patch('rapidjson.dump', MagicMock())
|
2019-08-16 11:04:07 +00:00
|
|
|
file_dump_json(Path('somefile'), [1, 2, 3], True)
|
2018-03-30 21:30:23 +00:00
|
|
|
assert file_open.call_count == 1
|
|
|
|
assert json_dump.call_count == 1
|
2018-04-10 18:09:14 +00:00
|
|
|
|
|
|
|
|
2019-09-07 18:56:03 +00:00
|
|
|
def test_file_load_json(mocker, testdatadir) -> None:
|
2018-12-28 09:25:12 +00:00
|
|
|
|
|
|
|
# 7m .json does not exist
|
2019-12-27 09:49:01 +00:00
|
|
|
ret = file_load_json(testdatadir / 'UNITTEST_BTC-7m.json')
|
2018-12-28 09:25:12 +00:00
|
|
|
assert not ret
|
|
|
|
# 1m json exists (but no .gz exists)
|
2019-12-27 09:49:01 +00:00
|
|
|
ret = file_load_json(testdatadir / 'UNITTEST_BTC-1m.json')
|
2018-12-28 09:25:12 +00:00
|
|
|
assert ret
|
|
|
|
# 8 .json is empty and will fail if it's loaded. .json.gz is a copy of 1.json
|
2019-12-27 09:49:01 +00:00
|
|
|
ret = file_load_json(testdatadir / 'UNITTEST_BTC-8m.json')
|
2018-12-28 09:25:12 +00:00
|
|
|
assert ret
|
|
|
|
|
|
|
|
|
2020-01-05 09:36:08 +00:00
|
|
|
@pytest.mark.parametrize("pair,expected_result", [
|
|
|
|
("ETH/BTC", 'ETH_BTC'),
|
|
|
|
("Fabric Token/ETH", 'Fabric_Token_ETH'),
|
|
|
|
("ETHH20", 'ETHH20'),
|
|
|
|
(".XBTBON2H", '_XBTBON2H'),
|
|
|
|
("ETHUSD.d", 'ETHUSD_d'),
|
|
|
|
("ADA-0327", 'ADA_0327'),
|
|
|
|
("BTC-USD-200110", 'BTC_USD_200110'),
|
|
|
|
("F-AKRO/USDT", 'F_AKRO_USDT'),
|
|
|
|
("LC+/ETH", 'LC__ETH'),
|
|
|
|
("CMT@18/ETH", 'CMT_18_ETH'),
|
|
|
|
("LBTC:1022/SAI", 'LBTC_1022_SAI'),
|
|
|
|
("$PAC/BTC", '_PAC_BTC'),
|
|
|
|
("ACC_OLD/BTC", 'ACC_OLD_BTC'),
|
|
|
|
])
|
|
|
|
def test_pair_to_filename(pair, expected_result):
|
|
|
|
pair_s = pair_to_filename(pair)
|
|
|
|
assert pair_s == expected_result
|
|
|
|
|
|
|
|
|
2018-04-10 18:09:14 +00:00
|
|
|
def test_format_ms_time() -> None:
|
2018-04-12 17:32:14 +00:00
|
|
|
# Date 2018-04-10 18:02:01
|
|
|
|
date_in_epoch_ms = 1523383321000
|
|
|
|
date = format_ms_time(date_in_epoch_ms)
|
2018-04-10 18:09:14 +00:00
|
|
|
assert type(date) is str
|
2018-04-11 18:19:13 +00:00
|
|
|
res = datetime.datetime(2018, 4, 10, 18, 2, 1, tzinfo=datetime.timezone.utc)
|
|
|
|
assert date == res.astimezone(None).strftime('%Y-%m-%dT%H:%M:%S')
|
|
|
|
res = datetime.datetime(2017, 12, 13, 8, 2, 1, tzinfo=datetime.timezone.utc)
|
2018-04-12 17:32:14 +00:00
|
|
|
# Date 2017-12-13 08:02:01
|
|
|
|
date_in_epoch_ms = 1513152121000
|
|
|
|
assert format_ms_time(date_in_epoch_ms) == res.astimezone(None).strftime('%Y-%m-%dT%H:%M:%S')
|
2019-10-17 14:52:33 +00:00
|
|
|
|
|
|
|
|
2020-04-09 17:34:48 +00:00
|
|
|
def test_safe_value_fallback():
|
2020-07-15 17:49:51 +00:00
|
|
|
dict1 = {'keya': None, 'keyb': 2, 'keyc': 5, 'keyd': None}
|
|
|
|
assert safe_value_fallback(dict1, 'keya', 'keyb') == 2
|
|
|
|
assert safe_value_fallback(dict1, 'keyb', 'keya') == 2
|
|
|
|
|
|
|
|
assert safe_value_fallback(dict1, 'keyb', 'keyc') == 2
|
|
|
|
assert safe_value_fallback(dict1, 'keya', 'keyc') == 5
|
|
|
|
|
|
|
|
assert safe_value_fallback(dict1, 'keyc', 'keyb') == 5
|
|
|
|
|
|
|
|
assert safe_value_fallback(dict1, 'keya', 'keyd') is None
|
|
|
|
|
|
|
|
assert safe_value_fallback(dict1, 'keyNo', 'keyNo') is None
|
|
|
|
assert safe_value_fallback(dict1, 'keyNo', 'keyNo', 55) == 55
|
|
|
|
|
|
|
|
|
|
|
|
def test_safe_value_fallback2():
|
2020-04-09 17:40:04 +00:00
|
|
|
dict1 = {'keya': None, 'keyb': 2, 'keyc': 5, 'keyd': None}
|
|
|
|
dict2 = {'keya': 20, 'keyb': None, 'keyc': 6, 'keyd': None}
|
2020-07-15 17:49:51 +00:00
|
|
|
assert safe_value_fallback2(dict1, dict2, 'keya', 'keya') == 20
|
|
|
|
assert safe_value_fallback2(dict2, dict1, 'keya', 'keya') == 20
|
2020-04-09 17:34:48 +00:00
|
|
|
|
2020-07-15 17:49:51 +00:00
|
|
|
assert safe_value_fallback2(dict1, dict2, 'keyb', 'keyb') == 2
|
|
|
|
assert safe_value_fallback2(dict2, dict1, 'keyb', 'keyb') == 2
|
2020-04-09 17:34:48 +00:00
|
|
|
|
2020-07-15 17:49:51 +00:00
|
|
|
assert safe_value_fallback2(dict1, dict2, 'keyc', 'keyc') == 5
|
|
|
|
assert safe_value_fallback2(dict2, dict1, 'keyc', 'keyc') == 6
|
2020-04-09 17:34:48 +00:00
|
|
|
|
2020-07-15 17:49:51 +00:00
|
|
|
assert safe_value_fallback2(dict1, dict2, 'keyd', 'keyd') is None
|
|
|
|
assert safe_value_fallback2(dict2, dict1, 'keyd', 'keyd') is None
|
|
|
|
assert safe_value_fallback2(dict2, dict1, 'keyd', 'keyd', 1234) == 1234
|
2020-04-09 17:40:04 +00:00
|
|
|
|
2020-07-15 17:49:51 +00:00
|
|
|
assert safe_value_fallback2(dict1, dict2, 'keyNo', 'keyNo') is None
|
|
|
|
assert safe_value_fallback2(dict2, dict1, 'keyNo', 'keyNo') is None
|
|
|
|
assert safe_value_fallback2(dict2, dict1, 'keyNo', 'keyNo', 1234) == 1234
|
2020-04-09 17:40:04 +00:00
|
|
|
|
2020-04-09 17:34:48 +00:00
|
|
|
|
2019-10-17 14:52:33 +00:00
|
|
|
def test_plural() -> None:
|
|
|
|
assert plural(0, "page") == "pages"
|
|
|
|
assert plural(0.0, "page") == "pages"
|
|
|
|
assert plural(1, "page") == "page"
|
|
|
|
assert plural(1.0, "page") == "page"
|
|
|
|
assert plural(2, "page") == "pages"
|
|
|
|
assert plural(2.0, "page") == "pages"
|
|
|
|
assert plural(-1, "page") == "page"
|
|
|
|
assert plural(-1.0, "page") == "page"
|
|
|
|
assert plural(-2, "page") == "pages"
|
|
|
|
assert plural(-2.0, "page") == "pages"
|
|
|
|
assert plural(0.5, "page") == "pages"
|
|
|
|
assert plural(1.5, "page") == "pages"
|
|
|
|
assert plural(-0.5, "page") == "pages"
|
|
|
|
assert plural(-1.5, "page") == "pages"
|
|
|
|
|
|
|
|
assert plural(0, "ox", "oxen") == "oxen"
|
|
|
|
assert plural(0.0, "ox", "oxen") == "oxen"
|
|
|
|
assert plural(1, "ox", "oxen") == "ox"
|
|
|
|
assert plural(1.0, "ox", "oxen") == "ox"
|
|
|
|
assert plural(2, "ox", "oxen") == "oxen"
|
|
|
|
assert plural(2.0, "ox", "oxen") == "oxen"
|
|
|
|
assert plural(-1, "ox", "oxen") == "ox"
|
|
|
|
assert plural(-1.0, "ox", "oxen") == "ox"
|
|
|
|
assert plural(-2, "ox", "oxen") == "oxen"
|
|
|
|
assert plural(-2.0, "ox", "oxen") == "oxen"
|
|
|
|
assert plural(0.5, "ox", "oxen") == "oxen"
|
|
|
|
assert plural(1.5, "ox", "oxen") == "oxen"
|
|
|
|
assert plural(-0.5, "ox", "oxen") == "oxen"
|
|
|
|
assert plural(-1.5, "ox", "oxen") == "oxen"
|
2020-03-01 08:34:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_render_template_fallback(mocker):
|
|
|
|
from jinja2.exceptions import TemplateNotFound
|
|
|
|
with pytest.raises(TemplateNotFound):
|
|
|
|
val = render_template(
|
|
|
|
templatefile='subtemplates/indicators_does-not-exist.j2',)
|
|
|
|
|
|
|
|
val = render_template_with_fallback(
|
|
|
|
templatefile='subtemplates/indicators_does-not-exist.j2',
|
|
|
|
templatefallbackfile='subtemplates/indicators_minimal.j2',
|
|
|
|
)
|
|
|
|
assert isinstance(val, str)
|
|
|
|
assert 'if self.dp' in val
|