Merge pull request #1096 from freqtrade/cleaner-tests
Cleaning unit tests, first set
This commit is contained in:
commit
1044d15b17
@ -8,10 +8,8 @@ from unittest.mock import MagicMock
|
|||||||
|
|
||||||
import arrow
|
import arrow
|
||||||
import pytest
|
import pytest
|
||||||
from jsonschema import validate
|
|
||||||
from telegram import Chat, Message, Update
|
from telegram import Chat, Message, Update
|
||||||
|
|
||||||
from freqtrade import constants
|
|
||||||
from freqtrade.exchange.exchange_helpers import parse_ticker_dataframe
|
from freqtrade.exchange.exchange_helpers import parse_ticker_dataframe
|
||||||
from freqtrade.exchange import Exchange
|
from freqtrade.exchange import Exchange
|
||||||
from freqtrade.freqtradebot import FreqtradeBot
|
from freqtrade.freqtradebot import FreqtradeBot
|
||||||
@ -127,7 +125,6 @@ def default_conf():
|
|||||||
"db_url": "sqlite://",
|
"db_url": "sqlite://",
|
||||||
"loglevel": logging.DEBUG,
|
"loglevel": logging.DEBUG,
|
||||||
}
|
}
|
||||||
validate(configuration, constants.CONF_SCHEMA)
|
|
||||||
return configuration
|
return configuration
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
# pragma pylint: disable=missing-docstring, C0103, bad-continuation, global-statement
|
# pragma pylint: disable=missing-docstring, C0103, bad-continuation, global-statement
|
||||||
# pragma pylint: disable=protected-access
|
# pragma pylint: disable=protected-access
|
||||||
import logging
|
import logging
|
||||||
from copy import deepcopy
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from random import randint
|
from random import randint
|
||||||
from unittest.mock import MagicMock, PropertyMock
|
from unittest.mock import MagicMock, PropertyMock
|
||||||
@ -15,8 +14,6 @@ from freqtrade.tests.conftest import get_patched_exchange, log_has
|
|||||||
|
|
||||||
|
|
||||||
def ccxt_exceptionhandlers(mocker, default_conf, api_mock, fun, mock_ccxt_fun, **kwargs):
|
def ccxt_exceptionhandlers(mocker, default_conf, api_mock, fun, mock_ccxt_fun, **kwargs):
|
||||||
"""Function to test ccxt exception handling """
|
|
||||||
|
|
||||||
with pytest.raises(TemporaryError):
|
with pytest.raises(TemporaryError):
|
||||||
api_mock.__dict__[mock_ccxt_fun] = MagicMock(side_effect=ccxt.NetworkError)
|
api_mock.__dict__[mock_ccxt_fun] = MagicMock(side_effect=ccxt.NetworkError)
|
||||||
exchange = get_patched_exchange(mocker, default_conf, api_mock)
|
exchange = get_patched_exchange(mocker, default_conf, api_mock)
|
||||||
@ -167,12 +164,11 @@ def test_validate_pairs_not_compatible(default_conf, mocker):
|
|||||||
api_mock.load_markets = MagicMock(return_value={
|
api_mock.load_markets = MagicMock(return_value={
|
||||||
'ETH/BTC': '', 'TKN/BTC': '', 'TRST/BTC': '', 'SWT/BTC': '', 'BCC/BTC': ''
|
'ETH/BTC': '', 'TKN/BTC': '', 'TRST/BTC': '', 'SWT/BTC': '', 'BCC/BTC': ''
|
||||||
})
|
})
|
||||||
conf = deepcopy(default_conf)
|
default_conf['stake_currency'] = 'ETH'
|
||||||
conf['stake_currency'] = 'ETH'
|
|
||||||
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
|
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
|
||||||
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
|
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
|
||||||
with pytest.raises(OperationalException, match=r'not compatible'):
|
with pytest.raises(OperationalException, match=r'not compatible'):
|
||||||
Exchange(conf)
|
Exchange(default_conf)
|
||||||
|
|
||||||
|
|
||||||
def test_validate_pairs_exception(default_conf, mocker, caplog):
|
def test_validate_pairs_exception(default_conf, mocker, caplog):
|
||||||
@ -197,8 +193,7 @@ def test_validate_pairs_exception(default_conf, mocker, caplog):
|
|||||||
|
|
||||||
def test_validate_pairs_stake_exception(default_conf, mocker, caplog):
|
def test_validate_pairs_stake_exception(default_conf, mocker, caplog):
|
||||||
caplog.set_level(logging.INFO)
|
caplog.set_level(logging.INFO)
|
||||||
conf = deepcopy(default_conf)
|
default_conf['stake_currency'] = 'ETH'
|
||||||
conf['stake_currency'] = 'ETH'
|
|
||||||
api_mock = MagicMock()
|
api_mock = MagicMock()
|
||||||
api_mock.name = MagicMock(return_value='binance')
|
api_mock.name = MagicMock(return_value='binance')
|
||||||
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', api_mock)
|
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', api_mock)
|
||||||
@ -208,7 +203,7 @@ def test_validate_pairs_stake_exception(default_conf, mocker, caplog):
|
|||||||
OperationalException,
|
OperationalException,
|
||||||
match=r'Pair ETH/BTC not compatible with stake_currency: ETH'
|
match=r'Pair ETH/BTC not compatible with stake_currency: ETH'
|
||||||
):
|
):
|
||||||
Exchange(conf)
|
Exchange(default_conf)
|
||||||
|
|
||||||
|
|
||||||
def test_validate_timeframes(default_conf, mocker):
|
def test_validate_timeframes(default_conf, mocker):
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
import json
|
import json
|
||||||
import math
|
import math
|
||||||
import random
|
import random
|
||||||
from copy import deepcopy
|
|
||||||
from typing import List
|
from typing import List
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
@ -164,9 +163,6 @@ def _trend_alternate(dataframe=None, metadata=None):
|
|||||||
|
|
||||||
# Unit tests
|
# Unit tests
|
||||||
def test_setup_configuration_without_arguments(mocker, default_conf, caplog) -> None:
|
def test_setup_configuration_without_arguments(mocker, default_conf, caplog) -> None:
|
||||||
"""
|
|
||||||
Test setup_configuration() function
|
|
||||||
"""
|
|
||||||
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
|
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
|
||||||
read_data=json.dumps(default_conf)
|
read_data=json.dumps(default_conf)
|
||||||
))
|
))
|
||||||
@ -205,9 +201,6 @@ def test_setup_configuration_without_arguments(mocker, default_conf, caplog) ->
|
|||||||
|
|
||||||
|
|
||||||
def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> None:
|
def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> None:
|
||||||
"""
|
|
||||||
Test setup_configuration() function
|
|
||||||
"""
|
|
||||||
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
|
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
|
||||||
read_data=json.dumps(default_conf)
|
read_data=json.dumps(default_conf)
|
||||||
))
|
))
|
||||||
@ -276,15 +269,10 @@ def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> Non
|
|||||||
|
|
||||||
|
|
||||||
def test_setup_configuration_unlimited_stake_amount(mocker, default_conf, caplog) -> None:
|
def test_setup_configuration_unlimited_stake_amount(mocker, default_conf, caplog) -> None:
|
||||||
"""
|
default_conf['stake_amount'] = constants.UNLIMITED_STAKE_AMOUNT
|
||||||
Test setup_configuration() function
|
|
||||||
"""
|
|
||||||
|
|
||||||
conf = deepcopy(default_conf)
|
|
||||||
conf['stake_amount'] = constants.UNLIMITED_STAKE_AMOUNT
|
|
||||||
|
|
||||||
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
|
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
|
||||||
read_data=json.dumps(conf)
|
read_data=json.dumps(default_conf)
|
||||||
))
|
))
|
||||||
|
|
||||||
args = [
|
args = [
|
||||||
@ -298,9 +286,6 @@ def test_setup_configuration_unlimited_stake_amount(mocker, default_conf, caplog
|
|||||||
|
|
||||||
|
|
||||||
def test_start(mocker, fee, default_conf, caplog) -> None:
|
def test_start(mocker, fee, default_conf, caplog) -> None:
|
||||||
"""
|
|
||||||
Test start() function
|
|
||||||
"""
|
|
||||||
start_mock = MagicMock()
|
start_mock = MagicMock()
|
||||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
@ -323,9 +308,6 @@ def test_start(mocker, fee, default_conf, caplog) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_backtesting_init(mocker, default_conf) -> None:
|
def test_backtesting_init(mocker, default_conf) -> None:
|
||||||
"""
|
|
||||||
Test Backtesting._init() method
|
|
||||||
"""
|
|
||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
get_fee = mocker.patch('freqtrade.exchange.Exchange.get_fee', MagicMock(return_value=0.5))
|
get_fee = mocker.patch('freqtrade.exchange.Exchange.get_fee', MagicMock(return_value=0.5))
|
||||||
backtesting = Backtesting(default_conf)
|
backtesting = Backtesting(default_conf)
|
||||||
@ -339,9 +321,6 @@ def test_backtesting_init(mocker, default_conf) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_tickerdata_to_dataframe(default_conf, mocker) -> None:
|
def test_tickerdata_to_dataframe(default_conf, mocker) -> None:
|
||||||
"""
|
|
||||||
Test Backtesting.tickerdata_to_dataframe() method
|
|
||||||
"""
|
|
||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
timerange = TimeRange(None, 'line', 0, -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)
|
||||||
@ -358,9 +337,6 @@ def test_tickerdata_to_dataframe(default_conf, mocker) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_get_timeframe(default_conf, mocker) -> None:
|
def test_get_timeframe(default_conf, mocker) -> None:
|
||||||
"""
|
|
||||||
Test Backtesting.get_timeframe() method
|
|
||||||
"""
|
|
||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
backtesting = Backtesting(default_conf)
|
backtesting = Backtesting(default_conf)
|
||||||
|
|
||||||
@ -377,9 +353,6 @@ def test_get_timeframe(default_conf, mocker) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_generate_text_table(default_conf, mocker):
|
def test_generate_text_table(default_conf, mocker):
|
||||||
"""
|
|
||||||
Test Backtesting.generate_text_table() method
|
|
||||||
"""
|
|
||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
backtesting = Backtesting(default_conf)
|
backtesting = Backtesting(default_conf)
|
||||||
|
|
||||||
@ -408,9 +381,6 @@ def test_generate_text_table(default_conf, mocker):
|
|||||||
|
|
||||||
|
|
||||||
def test_generate_text_table_sell_reason(default_conf, mocker):
|
def test_generate_text_table_sell_reason(default_conf, mocker):
|
||||||
"""
|
|
||||||
Test Backtesting.generate_text_table_sell_reason() method
|
|
||||||
"""
|
|
||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
backtesting = Backtesting(default_conf)
|
backtesting = Backtesting(default_conf)
|
||||||
|
|
||||||
@ -437,10 +407,6 @@ def test_generate_text_table_sell_reason(default_conf, mocker):
|
|||||||
|
|
||||||
|
|
||||||
def test_backtesting_start(default_conf, mocker, caplog) -> None:
|
def test_backtesting_start(default_conf, mocker, caplog) -> None:
|
||||||
"""
|
|
||||||
Test Backtesting.start() method
|
|
||||||
"""
|
|
||||||
|
|
||||||
def get_timeframe(input1, input2):
|
def get_timeframe(input1, input2):
|
||||||
return Arrow(2017, 11, 14, 21, 17), Arrow(2017, 11, 14, 22, 59)
|
return Arrow(2017, 11, 14, 21, 17), Arrow(2017, 11, 14, 22, 59)
|
||||||
|
|
||||||
@ -454,15 +420,14 @@ def test_backtesting_start(default_conf, mocker, caplog) -> None:
|
|||||||
get_timeframe=get_timeframe,
|
get_timeframe=get_timeframe,
|
||||||
)
|
)
|
||||||
|
|
||||||
conf = deepcopy(default_conf)
|
default_conf['exchange']['pair_whitelist'] = ['UNITTEST/BTC']
|
||||||
conf['exchange']['pair_whitelist'] = ['UNITTEST/BTC']
|
default_conf['ticker_interval'] = 1
|
||||||
conf['ticker_interval'] = 1
|
default_conf['live'] = False
|
||||||
conf['live'] = False
|
default_conf['datadir'] = None
|
||||||
conf['datadir'] = None
|
default_conf['export'] = None
|
||||||
conf['export'] = None
|
default_conf['timerange'] = '-100'
|
||||||
conf['timerange'] = '-100'
|
|
||||||
|
|
||||||
backtesting = Backtesting(conf)
|
backtesting = Backtesting(default_conf)
|
||||||
backtesting.start()
|
backtesting.start()
|
||||||
# check the logs, that will contain the backtest result
|
# check the logs, that will contain the backtest result
|
||||||
exists = [
|
exists = [
|
||||||
@ -477,10 +442,6 @@ def test_backtesting_start(default_conf, mocker, caplog) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_backtesting_start_no_data(default_conf, mocker, caplog) -> None:
|
def test_backtesting_start_no_data(default_conf, mocker, caplog) -> None:
|
||||||
"""
|
|
||||||
Test Backtesting.start() method if no data is found
|
|
||||||
"""
|
|
||||||
|
|
||||||
def get_timeframe(input1, input2):
|
def get_timeframe(input1, input2):
|
||||||
return Arrow(2017, 11, 14, 21, 17), Arrow(2017, 11, 14, 22, 59)
|
return Arrow(2017, 11, 14, 21, 17), Arrow(2017, 11, 14, 22, 59)
|
||||||
|
|
||||||
@ -494,15 +455,14 @@ def test_backtesting_start_no_data(default_conf, mocker, caplog) -> None:
|
|||||||
get_timeframe=get_timeframe,
|
get_timeframe=get_timeframe,
|
||||||
)
|
)
|
||||||
|
|
||||||
conf = deepcopy(default_conf)
|
default_conf['exchange']['pair_whitelist'] = ['UNITTEST/BTC']
|
||||||
conf['exchange']['pair_whitelist'] = ['UNITTEST/BTC']
|
default_conf['ticker_interval'] = "1m"
|
||||||
conf['ticker_interval'] = "1m"
|
default_conf['live'] = False
|
||||||
conf['live'] = False
|
default_conf['datadir'] = None
|
||||||
conf['datadir'] = None
|
default_conf['export'] = None
|
||||||
conf['export'] = None
|
default_conf['timerange'] = '20180101-20180102'
|
||||||
conf['timerange'] = '20180101-20180102'
|
|
||||||
|
|
||||||
backtesting = Backtesting(conf)
|
backtesting = Backtesting(default_conf)
|
||||||
backtesting.start()
|
backtesting.start()
|
||||||
# check the logs, that will contain the backtest result
|
# check the logs, that will contain the backtest result
|
||||||
|
|
||||||
@ -510,9 +470,6 @@ def test_backtesting_start_no_data(default_conf, mocker, caplog) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_backtest(default_conf, fee, mocker) -> None:
|
def test_backtest(default_conf, fee, mocker) -> None:
|
||||||
"""
|
|
||||||
Test Backtesting.backtest() method
|
|
||||||
"""
|
|
||||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
backtesting = Backtesting(default_conf)
|
backtesting = Backtesting(default_conf)
|
||||||
@ -560,9 +517,6 @@ def test_backtest(default_conf, fee, mocker) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_backtest_1min_ticker_interval(default_conf, fee, mocker) -> None:
|
def test_backtest_1min_ticker_interval(default_conf, fee, mocker) -> None:
|
||||||
"""
|
|
||||||
Test Backtesting.backtest() method with 1 min ticker
|
|
||||||
"""
|
|
||||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
backtesting = Backtesting(default_conf)
|
backtesting = Backtesting(default_conf)
|
||||||
@ -583,9 +537,6 @@ def test_backtest_1min_ticker_interval(default_conf, fee, mocker) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_processed(default_conf, mocker) -> None:
|
def test_processed(default_conf, mocker) -> None:
|
||||||
"""
|
|
||||||
Test Backtesting.backtest() method with offline data
|
|
||||||
"""
|
|
||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
backtesting = Backtesting(default_conf)
|
backtesting = Backtesting(default_conf)
|
||||||
|
|
||||||
@ -725,15 +676,14 @@ def test_backtest_record(default_conf, fee, mocker):
|
|||||||
|
|
||||||
|
|
||||||
def test_backtest_start_live(default_conf, mocker, caplog):
|
def test_backtest_start_live(default_conf, mocker, caplog):
|
||||||
conf = deepcopy(default_conf)
|
default_conf['exchange']['pair_whitelist'] = ['UNITTEST/BTC']
|
||||||
conf['exchange']['pair_whitelist'] = ['UNITTEST/BTC']
|
|
||||||
mocker.patch('freqtrade.exchange.Exchange.get_ticker_history',
|
mocker.patch('freqtrade.exchange.Exchange.get_ticker_history',
|
||||||
new=lambda s, n, i: _load_pair_as_ticks(n, i))
|
new=lambda s, n, i: _load_pair_as_ticks(n, i))
|
||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest', MagicMock())
|
mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest', MagicMock())
|
||||||
mocker.patch('freqtrade.optimize.backtesting.Backtesting._generate_text_table', MagicMock())
|
mocker.patch('freqtrade.optimize.backtesting.Backtesting._generate_text_table', MagicMock())
|
||||||
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
|
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
|
||||||
read_data=json.dumps(conf)
|
read_data=json.dumps(default_conf)
|
||||||
))
|
))
|
||||||
|
|
||||||
args = MagicMock()
|
args = MagicMock()
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
# pragma pylint: disable=missing-docstring,W0212,C0103
|
# pragma pylint: disable=missing-docstring,W0212,C0103
|
||||||
import os
|
import os
|
||||||
from copy import deepcopy
|
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
@ -12,29 +11,22 @@ from freqtrade.strategy.resolver import StrategyResolver
|
|||||||
from freqtrade.tests.conftest import log_has, patch_exchange
|
from freqtrade.tests.conftest import log_has, patch_exchange
|
||||||
from freqtrade.tests.optimize.test_backtesting import get_args
|
from freqtrade.tests.optimize.test_backtesting import get_args
|
||||||
|
|
||||||
# Avoid to reinit the same object again and again
|
|
||||||
_HYPEROPT_INITIALIZED = False
|
|
||||||
_HYPEROPT = None
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='function')
|
@pytest.fixture(scope='function')
|
||||||
def init_hyperopt(default_conf, mocker):
|
def hyperopt(default_conf, mocker):
|
||||||
global _HYPEROPT_INITIALIZED, _HYPEROPT
|
|
||||||
if not _HYPEROPT_INITIALIZED:
|
|
||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
_HYPEROPT = Hyperopt(default_conf)
|
return Hyperopt(default_conf)
|
||||||
_HYPEROPT_INITIALIZED = True
|
|
||||||
|
|
||||||
|
|
||||||
# Functions for recurrent object patching
|
# Functions for recurrent object patching
|
||||||
def create_trials(mocker) -> None:
|
def create_trials(mocker, hyperopt) -> None:
|
||||||
"""
|
"""
|
||||||
When creating trials, mock the hyperopt Trials so that *by default*
|
When creating trials, mock the hyperopt Trials so that *by default*
|
||||||
- we don't create any pickle'd files in the filesystem
|
- we don't create any pickle'd files in the filesystem
|
||||||
- we might have a pickle'd file so make sure that we return
|
- we might have a pickle'd file so make sure that we return
|
||||||
false when looking for it
|
false when looking for it
|
||||||
"""
|
"""
|
||||||
_HYPEROPT.trials_file = os.path.join('freqtrade', 'tests', 'optimize', 'ut_trials.pickle')
|
hyperopt.trials_file = os.path.join('freqtrade', 'tests', 'optimize', 'ut_trials.pickle')
|
||||||
|
|
||||||
mocker.patch('freqtrade.optimize.hyperopt.os.path.exists', return_value=False)
|
mocker.patch('freqtrade.optimize.hyperopt.os.path.exists', return_value=False)
|
||||||
mocker.patch('freqtrade.optimize.hyperopt.os.path.getsize', return_value=1)
|
mocker.patch('freqtrade.optimize.hyperopt.os.path.getsize', return_value=1)
|
||||||
@ -45,9 +37,6 @@ def create_trials(mocker) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_start(mocker, default_conf, caplog) -> None:
|
def test_start(mocker, default_conf, caplog) -> None:
|
||||||
"""
|
|
||||||
Test start() function
|
|
||||||
"""
|
|
||||||
start_mock = MagicMock()
|
start_mock = MagicMock()
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
'freqtrade.configuration.Configuration._load_config_file',
|
'freqtrade.configuration.Configuration._load_config_file',
|
||||||
@ -76,8 +65,7 @@ def test_start(mocker, default_conf, caplog) -> None:
|
|||||||
assert start_mock.call_count == 1
|
assert start_mock.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
def test_loss_calculation_prefer_correct_trade_count(init_hyperopt) -> None:
|
def test_loss_calculation_prefer_correct_trade_count(hyperopt) -> None:
|
||||||
hyperopt = _HYPEROPT
|
|
||||||
StrategyResolver({'strategy': 'DefaultStrategy'})
|
StrategyResolver({'strategy': 'DefaultStrategy'})
|
||||||
|
|
||||||
correct = hyperopt.calculate_loss(1, hyperopt.target_trades, 20)
|
correct = hyperopt.calculate_loss(1, hyperopt.target_trades, 20)
|
||||||
@ -87,17 +75,13 @@ def test_loss_calculation_prefer_correct_trade_count(init_hyperopt) -> None:
|
|||||||
assert under > correct
|
assert under > correct
|
||||||
|
|
||||||
|
|
||||||
def test_loss_calculation_prefer_shorter_trades(init_hyperopt) -> None:
|
def test_loss_calculation_prefer_shorter_trades(hyperopt) -> None:
|
||||||
hyperopt = _HYPEROPT
|
|
||||||
|
|
||||||
shorter = hyperopt.calculate_loss(1, 100, 20)
|
shorter = hyperopt.calculate_loss(1, 100, 20)
|
||||||
longer = hyperopt.calculate_loss(1, 100, 30)
|
longer = hyperopt.calculate_loss(1, 100, 30)
|
||||||
assert shorter < longer
|
assert shorter < longer
|
||||||
|
|
||||||
|
|
||||||
def test_loss_calculation_has_limited_profit(init_hyperopt) -> None:
|
def test_loss_calculation_has_limited_profit(hyperopt) -> None:
|
||||||
hyperopt = _HYPEROPT
|
|
||||||
|
|
||||||
correct = hyperopt.calculate_loss(hyperopt.expected_max_profit, hyperopt.target_trades, 20)
|
correct = hyperopt.calculate_loss(hyperopt.expected_max_profit, hyperopt.target_trades, 20)
|
||||||
over = hyperopt.calculate_loss(hyperopt.expected_max_profit * 2, hyperopt.target_trades, 20)
|
over = hyperopt.calculate_loss(hyperopt.expected_max_profit * 2, hyperopt.target_trades, 20)
|
||||||
under = hyperopt.calculate_loss(hyperopt.expected_max_profit / 2, hyperopt.target_trades, 20)
|
under = hyperopt.calculate_loss(hyperopt.expected_max_profit / 2, hyperopt.target_trades, 20)
|
||||||
@ -105,8 +89,7 @@ def test_loss_calculation_has_limited_profit(init_hyperopt) -> None:
|
|||||||
assert under > correct
|
assert under > correct
|
||||||
|
|
||||||
|
|
||||||
def test_log_results_if_loss_improves(init_hyperopt, capsys) -> None:
|
def test_log_results_if_loss_improves(hyperopt, capsys) -> None:
|
||||||
hyperopt = _HYPEROPT
|
|
||||||
hyperopt.current_best_loss = 2
|
hyperopt.current_best_loss = 2
|
||||||
hyperopt.log_results(
|
hyperopt.log_results(
|
||||||
{
|
{
|
||||||
@ -120,8 +103,7 @@ def test_log_results_if_loss_improves(init_hyperopt, capsys) -> None:
|
|||||||
assert ' 1/2: foo. Loss 1.00000' in out
|
assert ' 1/2: foo. Loss 1.00000' in out
|
||||||
|
|
||||||
|
|
||||||
def test_no_log_if_loss_does_not_improve(init_hyperopt, caplog) -> None:
|
def test_no_log_if_loss_does_not_improve(hyperopt, caplog) -> None:
|
||||||
hyperopt = _HYPEROPT
|
|
||||||
hyperopt.current_best_loss = 2
|
hyperopt.current_best_loss = 2
|
||||||
hyperopt.log_results(
|
hyperopt.log_results(
|
||||||
{
|
{
|
||||||
@ -131,13 +113,10 @@ def test_no_log_if_loss_does_not_improve(init_hyperopt, caplog) -> None:
|
|||||||
assert caplog.record_tuples == []
|
assert caplog.record_tuples == []
|
||||||
|
|
||||||
|
|
||||||
def test_save_trials_saves_trials(mocker, init_hyperopt, caplog) -> None:
|
def test_save_trials_saves_trials(mocker, hyperopt, caplog) -> None:
|
||||||
trials = create_trials(mocker)
|
trials = create_trials(mocker, hyperopt)
|
||||||
mock_dump = mocker.patch('freqtrade.optimize.hyperopt.dump', return_value=None)
|
mock_dump = mocker.patch('freqtrade.optimize.hyperopt.dump', return_value=None)
|
||||||
|
hyperopt.trials = trials
|
||||||
hyperopt = _HYPEROPT
|
|
||||||
_HYPEROPT.trials = trials
|
|
||||||
|
|
||||||
hyperopt.save_trials()
|
hyperopt.save_trials()
|
||||||
|
|
||||||
trials_file = os.path.join('freqtrade', 'tests', 'optimize', 'ut_trials.pickle')
|
trials_file = os.path.join('freqtrade', 'tests', 'optimize', 'ut_trials.pickle')
|
||||||
@ -148,11 +127,9 @@ def test_save_trials_saves_trials(mocker, init_hyperopt, caplog) -> None:
|
|||||||
mock_dump.assert_called_once()
|
mock_dump.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
def test_read_trials_returns_trials_file(mocker, init_hyperopt, caplog) -> None:
|
def test_read_trials_returns_trials_file(mocker, hyperopt, caplog) -> None:
|
||||||
trials = create_trials(mocker)
|
trials = create_trials(mocker, hyperopt)
|
||||||
mock_load = mocker.patch('freqtrade.optimize.hyperopt.load', return_value=trials)
|
mock_load = mocker.patch('freqtrade.optimize.hyperopt.load', return_value=trials)
|
||||||
|
|
||||||
hyperopt = _HYPEROPT
|
|
||||||
hyperopt_trial = hyperopt.read_trials()
|
hyperopt_trial = hyperopt.read_trials()
|
||||||
trials_file = os.path.join('freqtrade', 'tests', 'optimize', 'ut_trials.pickle')
|
trials_file = os.path.join('freqtrade', 'tests', 'optimize', 'ut_trials.pickle')
|
||||||
assert log_has(
|
assert log_has(
|
||||||
@ -163,7 +140,7 @@ def test_read_trials_returns_trials_file(mocker, init_hyperopt, caplog) -> None:
|
|||||||
mock_load.assert_called_once()
|
mock_load.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
def test_roi_table_generation(init_hyperopt) -> None:
|
def test_roi_table_generation(hyperopt) -> None:
|
||||||
params = {
|
params = {
|
||||||
'roi_t1': 5,
|
'roi_t1': 5,
|
||||||
'roi_t2': 10,
|
'roi_t2': 10,
|
||||||
@ -173,11 +150,10 @@ def test_roi_table_generation(init_hyperopt) -> None:
|
|||||||
'roi_p3': 3,
|
'roi_p3': 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
hyperopt = _HYPEROPT
|
|
||||||
assert hyperopt.generate_roi_table(params) == {0: 6, 15: 3, 25: 1, 30: 0}
|
assert hyperopt.generate_roi_table(params) == {0: 6, 15: 3, 25: 1, 30: 0}
|
||||||
|
|
||||||
|
|
||||||
def test_start_calls_optimizer(mocker, init_hyperopt, default_conf, caplog) -> None:
|
def test_start_calls_optimizer(mocker, default_conf, caplog) -> None:
|
||||||
dumper = mocker.patch('freqtrade.optimize.hyperopt.dump', MagicMock())
|
dumper = mocker.patch('freqtrade.optimize.hyperopt.dump', MagicMock())
|
||||||
mocker.patch('freqtrade.optimize.hyperopt.load_data', MagicMock())
|
mocker.patch('freqtrade.optimize.hyperopt.load_data', MagicMock())
|
||||||
mocker.patch('freqtrade.optimize.hyperopt.multiprocessing.cpu_count', MagicMock(return_value=1))
|
mocker.patch('freqtrade.optimize.hyperopt.multiprocessing.cpu_count', MagicMock(return_value=1))
|
||||||
@ -187,13 +163,12 @@ def test_start_calls_optimizer(mocker, init_hyperopt, default_conf, caplog) -> N
|
|||||||
)
|
)
|
||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
|
|
||||||
conf = deepcopy(default_conf)
|
default_conf.update({'config': 'config.json.example'})
|
||||||
conf.update({'config': 'config.json.example'})
|
default_conf.update({'epochs': 1})
|
||||||
conf.update({'epochs': 1})
|
default_conf.update({'timerange': None})
|
||||||
conf.update({'timerange': None})
|
default_conf.update({'spaces': 'all'})
|
||||||
conf.update({'spaces': 'all'})
|
|
||||||
|
|
||||||
hyperopt = Hyperopt(conf)
|
hyperopt = Hyperopt(default_conf)
|
||||||
hyperopt.tickerdata_to_dataframe = MagicMock()
|
hyperopt.tickerdata_to_dataframe = MagicMock()
|
||||||
|
|
||||||
hyperopt.start()
|
hyperopt.start()
|
||||||
@ -203,11 +178,7 @@ def test_start_calls_optimizer(mocker, init_hyperopt, default_conf, caplog) -> N
|
|||||||
assert dumper.called
|
assert dumper.called
|
||||||
|
|
||||||
|
|
||||||
def test_format_results(init_hyperopt):
|
def test_format_results(hyperopt):
|
||||||
"""
|
|
||||||
Test Hyperopt.format_results()
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Test with BTC as stake_currency
|
# Test with BTC as stake_currency
|
||||||
trades = [
|
trades = [
|
||||||
('ETH/BTC', 2, 2, 123),
|
('ETH/BTC', 2, 2, 123),
|
||||||
@ -217,7 +188,7 @@ def test_format_results(init_hyperopt):
|
|||||||
labels = ['currency', 'profit_percent', 'profit_abs', 'trade_duration']
|
labels = ['currency', 'profit_percent', 'profit_abs', 'trade_duration']
|
||||||
df = pd.DataFrame.from_records(trades, columns=labels)
|
df = pd.DataFrame.from_records(trades, columns=labels)
|
||||||
|
|
||||||
result = _HYPEROPT.format_results(df)
|
result = hyperopt.format_results(df)
|
||||||
assert result.find(' 66.67%')
|
assert result.find(' 66.67%')
|
||||||
assert result.find('Total profit 1.00000000 BTC')
|
assert result.find('Total profit 1.00000000 BTC')
|
||||||
assert result.find('2.0000Σ %')
|
assert result.find('2.0000Σ %')
|
||||||
@ -229,25 +200,25 @@ def test_format_results(init_hyperopt):
|
|||||||
('XPR/EUR', -1, -2, -246)
|
('XPR/EUR', -1, -2, -246)
|
||||||
]
|
]
|
||||||
df = pd.DataFrame.from_records(trades, columns=labels)
|
df = pd.DataFrame.from_records(trades, columns=labels)
|
||||||
result = _HYPEROPT.format_results(df)
|
result = hyperopt.format_results(df)
|
||||||
assert result.find('Total profit 1.00000000 EUR')
|
assert result.find('Total profit 1.00000000 EUR')
|
||||||
|
|
||||||
|
|
||||||
def test_has_space(init_hyperopt):
|
def test_has_space(hyperopt):
|
||||||
_HYPEROPT.config.update({'spaces': ['buy', 'roi']})
|
hyperopt.config.update({'spaces': ['buy', 'roi']})
|
||||||
assert _HYPEROPT.has_space('roi')
|
assert hyperopt.has_space('roi')
|
||||||
assert _HYPEROPT.has_space('buy')
|
assert hyperopt.has_space('buy')
|
||||||
assert not _HYPEROPT.has_space('stoploss')
|
assert not hyperopt.has_space('stoploss')
|
||||||
|
|
||||||
_HYPEROPT.config.update({'spaces': ['all']})
|
hyperopt.config.update({'spaces': ['all']})
|
||||||
assert _HYPEROPT.has_space('buy')
|
assert hyperopt.has_space('buy')
|
||||||
|
|
||||||
|
|
||||||
def test_populate_indicators(init_hyperopt) -> None:
|
def test_populate_indicators(hyperopt) -> None:
|
||||||
tick = load_tickerdata_file(None, 'UNITTEST/BTC', '1m')
|
tick = load_tickerdata_file(None, 'UNITTEST/BTC', '1m')
|
||||||
tickerlist = {'UNITTEST/BTC': tick}
|
tickerlist = {'UNITTEST/BTC': tick}
|
||||||
dataframes = _HYPEROPT.tickerdata_to_dataframe(tickerlist)
|
dataframes = hyperopt.tickerdata_to_dataframe(tickerlist)
|
||||||
dataframe = _HYPEROPT.populate_indicators(dataframes['UNITTEST/BTC'], {'pair': 'UNITTEST/BTC'})
|
dataframe = hyperopt.populate_indicators(dataframes['UNITTEST/BTC'], {'pair': 'UNITTEST/BTC'})
|
||||||
|
|
||||||
# Check if some indicators are generated. We will not test all of them
|
# Check if some indicators are generated. We will not test all of them
|
||||||
assert 'adx' in dataframe
|
assert 'adx' in dataframe
|
||||||
@ -255,13 +226,13 @@ def test_populate_indicators(init_hyperopt) -> None:
|
|||||||
assert 'rsi' in dataframe
|
assert 'rsi' in dataframe
|
||||||
|
|
||||||
|
|
||||||
def test_buy_strategy_generator(init_hyperopt) -> None:
|
def test_buy_strategy_generator(hyperopt) -> None:
|
||||||
tick = load_tickerdata_file(None, 'UNITTEST/BTC', '1m')
|
tick = load_tickerdata_file(None, 'UNITTEST/BTC', '1m')
|
||||||
tickerlist = {'UNITTEST/BTC': tick}
|
tickerlist = {'UNITTEST/BTC': tick}
|
||||||
dataframes = _HYPEROPT.tickerdata_to_dataframe(tickerlist)
|
dataframes = hyperopt.tickerdata_to_dataframe(tickerlist)
|
||||||
dataframe = _HYPEROPT.populate_indicators(dataframes['UNITTEST/BTC'], {'pair': 'UNITTEST/BTC'})
|
dataframe = hyperopt.populate_indicators(dataframes['UNITTEST/BTC'], {'pair': 'UNITTEST/BTC'})
|
||||||
|
|
||||||
populate_buy_trend = _HYPEROPT.buy_strategy_generator(
|
populate_buy_trend = hyperopt.buy_strategy_generator(
|
||||||
{
|
{
|
||||||
'adx-value': 20,
|
'adx-value': 20,
|
||||||
'fastd-value': 20,
|
'fastd-value': 20,
|
||||||
@ -280,11 +251,10 @@ def test_buy_strategy_generator(init_hyperopt) -> None:
|
|||||||
assert 1 in result['buy']
|
assert 1 in result['buy']
|
||||||
|
|
||||||
|
|
||||||
def test_generate_optimizer(mocker, init_hyperopt, default_conf) -> None:
|
def test_generate_optimizer(mocker, default_conf) -> None:
|
||||||
conf = deepcopy(default_conf)
|
default_conf.update({'config': 'config.json.example'})
|
||||||
conf.update({'config': 'config.json.example'})
|
default_conf.update({'timerange': None})
|
||||||
conf.update({'timerange': None})
|
default_conf.update({'spaces': 'all'})
|
||||||
conf.update({'spaces': 'all'})
|
|
||||||
|
|
||||||
trades = [
|
trades = [
|
||||||
('POWR/BTC', 0.023117, 0.000233, 100)
|
('POWR/BTC', 0.023117, 0.000233, 100)
|
||||||
@ -324,6 +294,6 @@ def test_generate_optimizer(mocker, init_hyperopt, default_conf) -> None:
|
|||||||
'params': optimizer_param
|
'params': optimizer_param
|
||||||
}
|
}
|
||||||
|
|
||||||
hyperopt = Hyperopt(conf)
|
hyperopt = Hyperopt(default_conf)
|
||||||
generate_optimizer_value = hyperopt.generate_optimizer(list(optimizer_param.values()))
|
generate_optimizer_value = hyperopt.generate_optimizer(list(optimizer_param.values()))
|
||||||
assert generate_optimizer_value == response_expected
|
assert generate_optimizer_value == response_expected
|
||||||
|
@ -11,8 +11,8 @@ from freqtrade.freqtradebot import FreqtradeBot
|
|||||||
from freqtrade.persistence import Trade
|
from freqtrade.persistence import Trade
|
||||||
from freqtrade.rpc import RPC, RPCException
|
from freqtrade.rpc import RPC, RPCException
|
||||||
from freqtrade.state import State
|
from freqtrade.state import State
|
||||||
from freqtrade.tests.test_freqtradebot import (patch_coinmarketcap,
|
from freqtrade.tests.test_freqtradebot import patch_get_signal
|
||||||
patch_get_signal)
|
from freqtrade.tests.conftest import patch_coinmarketcap
|
||||||
|
|
||||||
|
|
||||||
# Functions for recurrent object patching
|
# Functions for recurrent object patching
|
||||||
@ -278,9 +278,6 @@ def test_rpc_trade_statistics_closed(mocker, default_conf, ticker, fee, markets,
|
|||||||
|
|
||||||
|
|
||||||
def test_rpc_balance_handle(default_conf, mocker):
|
def test_rpc_balance_handle(default_conf, mocker):
|
||||||
"""
|
|
||||||
Test rpc_balance() method
|
|
||||||
"""
|
|
||||||
mock_balance = {
|
mock_balance = {
|
||||||
'BTC': {
|
'BTC': {
|
||||||
'free': 10.0,
|
'free': 10.0,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
# pragma pylint: disable=missing-docstring, C0103
|
# pragma pylint: disable=missing-docstring, C0103
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from copy import deepcopy
|
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
from freqtrade.rpc import RPCMessageType, RPCManager
|
from freqtrade.rpc import RPCMessageType, RPCManager
|
||||||
@ -9,18 +8,16 @@ from freqtrade.tests.conftest import log_has, get_patched_freqtradebot
|
|||||||
|
|
||||||
|
|
||||||
def test__init__(mocker, default_conf) -> None:
|
def test__init__(mocker, default_conf) -> None:
|
||||||
conf = deepcopy(default_conf)
|
default_conf['telegram']['enabled'] = False
|
||||||
conf['telegram']['enabled'] = False
|
|
||||||
|
|
||||||
rpc_manager = RPCManager(get_patched_freqtradebot(mocker, conf))
|
rpc_manager = RPCManager(get_patched_freqtradebot(mocker, default_conf))
|
||||||
assert rpc_manager.registered_modules == []
|
assert rpc_manager.registered_modules == []
|
||||||
|
|
||||||
|
|
||||||
def test_init_telegram_disabled(mocker, default_conf, caplog) -> None:
|
def test_init_telegram_disabled(mocker, default_conf, caplog) -> None:
|
||||||
caplog.set_level(logging.DEBUG)
|
caplog.set_level(logging.DEBUG)
|
||||||
conf = deepcopy(default_conf)
|
default_conf['telegram']['enabled'] = False
|
||||||
conf['telegram']['enabled'] = False
|
rpc_manager = RPCManager(get_patched_freqtradebot(mocker, default_conf))
|
||||||
rpc_manager = RPCManager(get_patched_freqtradebot(mocker, conf))
|
|
||||||
|
|
||||||
assert not log_has('Enabling rpc.telegram ...', caplog.record_tuples)
|
assert not log_has('Enabling rpc.telegram ...', caplog.record_tuples)
|
||||||
assert rpc_manager.registered_modules == []
|
assert rpc_manager.registered_modules == []
|
||||||
@ -40,10 +37,9 @@ def test_init_telegram_enabled(mocker, default_conf, caplog) -> None:
|
|||||||
def test_cleanup_telegram_disabled(mocker, default_conf, caplog) -> None:
|
def test_cleanup_telegram_disabled(mocker, default_conf, caplog) -> None:
|
||||||
caplog.set_level(logging.DEBUG)
|
caplog.set_level(logging.DEBUG)
|
||||||
telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.cleanup', MagicMock())
|
telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.cleanup', MagicMock())
|
||||||
conf = deepcopy(default_conf)
|
default_conf['telegram']['enabled'] = False
|
||||||
conf['telegram']['enabled'] = False
|
|
||||||
|
|
||||||
freqtradebot = get_patched_freqtradebot(mocker, conf)
|
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||||
rpc_manager = RPCManager(freqtradebot)
|
rpc_manager = RPCManager(freqtradebot)
|
||||||
rpc_manager.cleanup()
|
rpc_manager.cleanup()
|
||||||
|
|
||||||
@ -70,10 +66,9 @@ def test_cleanup_telegram_enabled(mocker, default_conf, caplog) -> None:
|
|||||||
|
|
||||||
def test_send_msg_telegram_disabled(mocker, default_conf, caplog) -> None:
|
def test_send_msg_telegram_disabled(mocker, default_conf, caplog) -> None:
|
||||||
telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg', MagicMock())
|
telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg', MagicMock())
|
||||||
conf = deepcopy(default_conf)
|
default_conf['telegram']['enabled'] = False
|
||||||
conf['telegram']['enabled'] = False
|
|
||||||
|
|
||||||
freqtradebot = get_patched_freqtradebot(mocker, conf)
|
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||||
rpc_manager = RPCManager(freqtradebot)
|
rpc_manager = RPCManager(freqtradebot)
|
||||||
rpc_manager.send_msg({
|
rpc_manager.send_msg({
|
||||||
'type': RPCMessageType.STATUS_NOTIFICATION,
|
'type': RPCMessageType.STATUS_NOTIFICATION,
|
||||||
@ -101,10 +96,9 @@ def test_send_msg_telegram_enabled(mocker, default_conf, caplog) -> None:
|
|||||||
|
|
||||||
def test_init_webhook_disabled(mocker, default_conf, caplog) -> None:
|
def test_init_webhook_disabled(mocker, default_conf, caplog) -> None:
|
||||||
caplog.set_level(logging.DEBUG)
|
caplog.set_level(logging.DEBUG)
|
||||||
conf = deepcopy(default_conf)
|
default_conf['telegram']['enabled'] = False
|
||||||
conf['telegram']['enabled'] = False
|
default_conf['webhook'] = {'enabled': False}
|
||||||
conf['webhook'] = {'enabled': False}
|
rpc_manager = RPCManager(get_patched_freqtradebot(mocker, default_conf))
|
||||||
rpc_manager = RPCManager(get_patched_freqtradebot(mocker, conf))
|
|
||||||
|
|
||||||
assert not log_has('Enabling rpc.webhook ...', caplog.record_tuples)
|
assert not log_has('Enabling rpc.webhook ...', caplog.record_tuples)
|
||||||
assert rpc_manager.registered_modules == []
|
assert rpc_manager.registered_modules == []
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
# pragma pylint: disable=too-many-lines, too-many-arguments
|
# pragma pylint: disable=too-many-lines, too-many-arguments
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from copy import deepcopy
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from random import randint
|
from random import randint
|
||||||
from unittest.mock import MagicMock, ANY
|
from unittest.mock import MagicMock, ANY
|
||||||
@ -21,8 +20,8 @@ from freqtrade.rpc.telegram import Telegram, authorized_only
|
|||||||
from freqtrade.state import State
|
from freqtrade.state import State
|
||||||
from freqtrade.tests.conftest import (get_patched_freqtradebot, log_has,
|
from freqtrade.tests.conftest import (get_patched_freqtradebot, log_has,
|
||||||
patch_exchange)
|
patch_exchange)
|
||||||
from freqtrade.tests.test_freqtradebot import (patch_coinmarketcap,
|
from freqtrade.tests.test_freqtradebot import patch_get_signal
|
||||||
patch_get_signal)
|
from freqtrade.tests.conftest import patch_coinmarketcap
|
||||||
|
|
||||||
|
|
||||||
class DummyCls(Telegram):
|
class DummyCls(Telegram):
|
||||||
@ -96,9 +95,8 @@ def test_authorized_only(default_conf, mocker, caplog) -> None:
|
|||||||
update = Update(randint(1, 100))
|
update = Update(randint(1, 100))
|
||||||
update.message = Message(randint(1, 100), 0, datetime.utcnow(), chat)
|
update.message = Message(randint(1, 100), 0, datetime.utcnow(), chat)
|
||||||
|
|
||||||
conf = deepcopy(default_conf)
|
default_conf['telegram']['enabled'] = False
|
||||||
conf['telegram']['enabled'] = False
|
bot = FreqtradeBot(default_conf)
|
||||||
bot = FreqtradeBot(conf)
|
|
||||||
patch_get_signal(bot, (True, False))
|
patch_get_signal(bot, (True, False))
|
||||||
dummy = DummyCls(bot)
|
dummy = DummyCls(bot)
|
||||||
dummy.dummy_handler(bot=MagicMock(), update=update)
|
dummy.dummy_handler(bot=MagicMock(), update=update)
|
||||||
@ -124,9 +122,8 @@ def test_authorized_only_unauthorized(default_conf, mocker, caplog) -> None:
|
|||||||
update = Update(randint(1, 100))
|
update = Update(randint(1, 100))
|
||||||
update.message = Message(randint(1, 100), 0, datetime.utcnow(), chat)
|
update.message = Message(randint(1, 100), 0, datetime.utcnow(), chat)
|
||||||
|
|
||||||
conf = deepcopy(default_conf)
|
default_conf['telegram']['enabled'] = False
|
||||||
conf['telegram']['enabled'] = False
|
bot = FreqtradeBot(default_conf)
|
||||||
bot = FreqtradeBot(conf)
|
|
||||||
patch_get_signal(bot, (True, False))
|
patch_get_signal(bot, (True, False))
|
||||||
dummy = DummyCls(bot)
|
dummy = DummyCls(bot)
|
||||||
dummy.dummy_handler(bot=MagicMock(), update=update)
|
dummy.dummy_handler(bot=MagicMock(), update=update)
|
||||||
@ -152,10 +149,9 @@ def test_authorized_only_exception(default_conf, mocker, caplog) -> None:
|
|||||||
update = Update(randint(1, 100))
|
update = Update(randint(1, 100))
|
||||||
update.message = Message(randint(1, 100), 0, datetime.utcnow(), Chat(0, 0))
|
update.message = Message(randint(1, 100), 0, datetime.utcnow(), Chat(0, 0))
|
||||||
|
|
||||||
conf = deepcopy(default_conf)
|
default_conf['telegram']['enabled'] = False
|
||||||
conf['telegram']['enabled'] = False
|
|
||||||
|
|
||||||
bot = FreqtradeBot(conf)
|
bot = FreqtradeBot(default_conf)
|
||||||
patch_get_signal(bot, (True, False))
|
patch_get_signal(bot, (True, False))
|
||||||
dummy = DummyCls(bot)
|
dummy = DummyCls(bot)
|
||||||
|
|
||||||
@ -177,9 +173,8 @@ def test_authorized_only_exception(default_conf, mocker, caplog) -> None:
|
|||||||
|
|
||||||
def test_status(default_conf, update, mocker, fee, ticker, markets) -> None:
|
def test_status(default_conf, update, mocker, fee, ticker, markets) -> None:
|
||||||
update.message.chat.id = 123
|
update.message.chat.id = 123
|
||||||
conf = deepcopy(default_conf)
|
default_conf['telegram']['enabled'] = False
|
||||||
conf['telegram']['enabled'] = False
|
default_conf['telegram']['chat_id'] = 123
|
||||||
conf['telegram']['chat_id'] = 123
|
|
||||||
|
|
||||||
patch_coinmarketcap(mocker)
|
patch_coinmarketcap(mocker)
|
||||||
|
|
||||||
@ -214,7 +209,7 @@ def test_status(default_conf, update, mocker, fee, ticker, markets) -> None:
|
|||||||
)
|
)
|
||||||
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
|
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
|
||||||
|
|
||||||
freqtradebot = FreqtradeBot(conf)
|
freqtradebot = FreqtradeBot(default_conf)
|
||||||
patch_get_signal(freqtradebot, (True, False))
|
patch_get_signal(freqtradebot, (True, False))
|
||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
@ -294,9 +289,8 @@ def test_status_table_handle(default_conf, update, ticker, fee, markets, mocker)
|
|||||||
)
|
)
|
||||||
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
|
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
|
||||||
|
|
||||||
conf = deepcopy(default_conf)
|
default_conf['stake_amount'] = 15.0
|
||||||
conf['stake_amount'] = 15.0
|
freqtradebot = FreqtradeBot(default_conf)
|
||||||
freqtradebot = FreqtradeBot(conf)
|
|
||||||
patch_get_signal(freqtradebot, (True, False))
|
patch_get_signal(freqtradebot, (True, False))
|
||||||
|
|
||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
@ -1181,9 +1175,8 @@ def test_send_msg_sell_notification_no_fiat(default_conf, mocker) -> None:
|
|||||||
def test__send_msg(default_conf, mocker) -> None:
|
def test__send_msg(default_conf, mocker) -> None:
|
||||||
patch_coinmarketcap(mocker)
|
patch_coinmarketcap(mocker)
|
||||||
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
|
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
|
||||||
conf = deepcopy(default_conf)
|
|
||||||
bot = MagicMock()
|
bot = MagicMock()
|
||||||
freqtradebot = get_patched_freqtradebot(mocker, conf)
|
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
telegram._config['telegram']['enabled'] = True
|
telegram._config['telegram']['enabled'] = True
|
||||||
@ -1194,10 +1187,9 @@ def test__send_msg(default_conf, mocker) -> None:
|
|||||||
def test__send_msg_network_error(default_conf, mocker, caplog) -> None:
|
def test__send_msg_network_error(default_conf, mocker, caplog) -> None:
|
||||||
patch_coinmarketcap(mocker)
|
patch_coinmarketcap(mocker)
|
||||||
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
|
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
|
||||||
conf = deepcopy(default_conf)
|
|
||||||
bot = MagicMock()
|
bot = MagicMock()
|
||||||
bot.send_message = MagicMock(side_effect=NetworkError('Oh snap'))
|
bot.send_message = MagicMock(side_effect=NetworkError('Oh snap'))
|
||||||
freqtradebot = get_patched_freqtradebot(mocker, conf)
|
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
telegram._config['telegram']['enabled'] = True
|
telegram._config['telegram']['enabled'] = True
|
||||||
|
@ -98,9 +98,6 @@ def test_get_signal_handles_exceptions(mocker, default_conf):
|
|||||||
|
|
||||||
|
|
||||||
def test_tickerdata_to_dataframe(default_conf) -> None:
|
def test_tickerdata_to_dataframe(default_conf) -> None:
|
||||||
"""
|
|
||||||
Test Analyze.tickerdata_to_dataframe() method
|
|
||||||
"""
|
|
||||||
strategy = DefaultStrategy(default_conf)
|
strategy = DefaultStrategy(default_conf)
|
||||||
|
|
||||||
timerange = TimeRange(None, 'line', 0, -100)
|
timerange = TimeRange(None, 'line', 0, -100)
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
# pragma pylint: disable=missing-docstring, C0103
|
# pragma pylint: disable=missing-docstring, C0103
|
||||||
|
|
||||||
"""
|
|
||||||
Unit test file for arguments.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
from argparse import Namespace
|
from argparse import Namespace
|
||||||
from copy import deepcopy
|
|
||||||
import logging
|
import logging
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from jsonschema import ValidationError
|
from jsonschema import validate, ValidationError
|
||||||
|
|
||||||
|
from freqtrade import constants
|
||||||
from freqtrade import OperationalException
|
from freqtrade import OperationalException
|
||||||
from freqtrade.arguments import Arguments
|
from freqtrade.arguments import Arguments
|
||||||
from freqtrade.configuration import Configuration, set_loggers
|
from freqtrade.configuration import Configuration, set_loggers
|
||||||
@ -17,30 +17,27 @@ from freqtrade.tests.conftest import log_has
|
|||||||
|
|
||||||
|
|
||||||
def test_load_config_invalid_pair(default_conf) -> None:
|
def test_load_config_invalid_pair(default_conf) -> None:
|
||||||
conf = deepcopy(default_conf)
|
default_conf['exchange']['pair_whitelist'].append('ETH-BTC')
|
||||||
conf['exchange']['pair_whitelist'].append('ETH-BTC')
|
|
||||||
|
|
||||||
with pytest.raises(ValidationError, match=r'.*does not match.*'):
|
with pytest.raises(ValidationError, match=r'.*does not match.*'):
|
||||||
configuration = Configuration(Namespace())
|
configuration = Configuration(Namespace())
|
||||||
configuration._validate_config(conf)
|
configuration._validate_config(default_conf)
|
||||||
|
|
||||||
|
|
||||||
def test_load_config_missing_attributes(default_conf) -> None:
|
def test_load_config_missing_attributes(default_conf) -> None:
|
||||||
conf = deepcopy(default_conf)
|
default_conf.pop('exchange')
|
||||||
conf.pop('exchange')
|
|
||||||
|
|
||||||
with pytest.raises(ValidationError, match=r'.*\'exchange\' is a required property.*'):
|
with pytest.raises(ValidationError, match=r'.*\'exchange\' is a required property.*'):
|
||||||
configuration = Configuration(Namespace())
|
configuration = Configuration(Namespace())
|
||||||
configuration._validate_config(conf)
|
configuration._validate_config(default_conf)
|
||||||
|
|
||||||
|
|
||||||
def test_load_config_incorrect_stake_amount(default_conf) -> None:
|
def test_load_config_incorrect_stake_amount(default_conf) -> None:
|
||||||
conf = deepcopy(default_conf)
|
default_conf['stake_amount'] = 'fake'
|
||||||
conf['stake_amount'] = 'fake'
|
|
||||||
|
|
||||||
with pytest.raises(ValidationError, match=r'.*\'fake\' does not match \'unlimited\'.*'):
|
with pytest.raises(ValidationError, match=r'.*\'fake\' does not match \'unlimited\'.*'):
|
||||||
configuration = Configuration(Namespace())
|
configuration = Configuration(Namespace())
|
||||||
configuration._validate_config(conf)
|
configuration._validate_config(default_conf)
|
||||||
|
|
||||||
|
|
||||||
def test_load_config_file(default_conf, mocker, caplog) -> None:
|
def test_load_config_file(default_conf, mocker, caplog) -> None:
|
||||||
@ -57,10 +54,9 @@ def test_load_config_file(default_conf, mocker, caplog) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_load_config_max_open_trades_zero(default_conf, mocker, caplog) -> None:
|
def test_load_config_max_open_trades_zero(default_conf, mocker, caplog) -> None:
|
||||||
conf = deepcopy(default_conf)
|
default_conf['max_open_trades'] = 0
|
||||||
conf['max_open_trades'] = 0
|
|
||||||
file_mock = mocker.patch('freqtrade.configuration.open', mocker.mock_open(
|
file_mock = mocker.patch('freqtrade.configuration.open', mocker.mock_open(
|
||||||
read_data=json.dumps(conf)
|
read_data=json.dumps(default_conf)
|
||||||
))
|
))
|
||||||
|
|
||||||
Configuration(Namespace())._load_config_file('somefile')
|
Configuration(Namespace())._load_config_file('somefile')
|
||||||
@ -151,13 +147,12 @@ def test_load_config_with_params(default_conf, mocker) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_load_custom_strategy(default_conf, mocker) -> None:
|
def test_load_custom_strategy(default_conf, mocker) -> None:
|
||||||
custom_conf = deepcopy(default_conf)
|
default_conf.update({
|
||||||
custom_conf.update({
|
|
||||||
'strategy': 'CustomStrategy',
|
'strategy': 'CustomStrategy',
|
||||||
'strategy_path': '/tmp/strategies',
|
'strategy_path': '/tmp/strategies',
|
||||||
})
|
})
|
||||||
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
|
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
|
||||||
read_data=json.dumps(custom_conf)
|
read_data=json.dumps(default_conf)
|
||||||
))
|
))
|
||||||
|
|
||||||
args = Arguments([], '').get_parsed_arg()
|
args = Arguments([], '').get_parsed_arg()
|
||||||
@ -322,29 +317,25 @@ def test_hyperopt_with_arguments(mocker, default_conf, caplog) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_check_exchange(default_conf) -> None:
|
def test_check_exchange(default_conf) -> None:
|
||||||
"""
|
|
||||||
Test the configuration validator with a missing attribute
|
|
||||||
"""
|
|
||||||
conf = deepcopy(default_conf)
|
|
||||||
configuration = Configuration(Namespace())
|
configuration = Configuration(Namespace())
|
||||||
|
|
||||||
# Test a valid exchange
|
# Test a valid exchange
|
||||||
conf.get('exchange').update({'name': 'BITTREX'})
|
default_conf.get('exchange').update({'name': 'BITTREX'})
|
||||||
assert configuration.check_exchange(conf)
|
assert configuration.check_exchange(default_conf)
|
||||||
|
|
||||||
# Test a valid exchange
|
# Test a valid exchange
|
||||||
conf.get('exchange').update({'name': 'binance'})
|
default_conf.get('exchange').update({'name': 'binance'})
|
||||||
assert configuration.check_exchange(conf)
|
assert configuration.check_exchange(default_conf)
|
||||||
|
|
||||||
# Test a invalid exchange
|
# Test a invalid exchange
|
||||||
conf.get('exchange').update({'name': 'unknown_exchange'})
|
default_conf.get('exchange').update({'name': 'unknown_exchange'})
|
||||||
configuration.config = conf
|
configuration.config = default_conf
|
||||||
|
|
||||||
with pytest.raises(
|
with pytest.raises(
|
||||||
OperationalException,
|
OperationalException,
|
||||||
match=r'.*Exchange "unknown_exchange" not supported.*'
|
match=r'.*Exchange "unknown_exchange" not supported.*'
|
||||||
):
|
):
|
||||||
configuration.check_exchange(conf)
|
configuration.check_exchange(default_conf)
|
||||||
|
|
||||||
|
|
||||||
def test_cli_verbose_with_params(default_conf, mocker, caplog) -> None:
|
def test_cli_verbose_with_params(default_conf, mocker, caplog) -> None:
|
||||||
@ -398,3 +389,7 @@ def test_set_loggers() -> None:
|
|||||||
assert logging.getLogger('requests').level is logging.DEBUG
|
assert logging.getLogger('requests').level is logging.DEBUG
|
||||||
assert logging.getLogger('ccxt.base.exchange').level is logging.DEBUG
|
assert logging.getLogger('ccxt.base.exchange').level is logging.DEBUG
|
||||||
assert logging.getLogger('telegram').level is logging.INFO
|
assert logging.getLogger('telegram').level is logging.INFO
|
||||||
|
|
||||||
|
|
||||||
|
def test_validate_default_conf(default_conf) -> None:
|
||||||
|
validate(default_conf, constants.CONF_SCHEMA)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,4 @@
|
|||||||
# pragma pylint: disable=missing-docstring, C0103
|
# pragma pylint: disable=missing-docstring, C0103
|
||||||
from copy import deepcopy
|
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@ -23,46 +22,40 @@ def test_init_create_session(default_conf):
|
|||||||
|
|
||||||
|
|
||||||
def test_init_custom_db_url(default_conf, mocker):
|
def test_init_custom_db_url(default_conf, mocker):
|
||||||
conf = deepcopy(default_conf)
|
|
||||||
|
|
||||||
# Update path to a value other than default, but still in-memory
|
# Update path to a value other than default, but still in-memory
|
||||||
conf.update({'db_url': 'sqlite:///tmp/freqtrade2_test.sqlite'})
|
default_conf.update({'db_url': 'sqlite:///tmp/freqtrade2_test.sqlite'})
|
||||||
create_engine_mock = mocker.patch('freqtrade.persistence.create_engine', MagicMock())
|
create_engine_mock = mocker.patch('freqtrade.persistence.create_engine', MagicMock())
|
||||||
|
|
||||||
init(conf)
|
init(default_conf)
|
||||||
assert create_engine_mock.call_count == 1
|
assert create_engine_mock.call_count == 1
|
||||||
assert create_engine_mock.mock_calls[0][1][0] == 'sqlite:///tmp/freqtrade2_test.sqlite'
|
assert create_engine_mock.mock_calls[0][1][0] == 'sqlite:///tmp/freqtrade2_test.sqlite'
|
||||||
|
|
||||||
|
|
||||||
def test_init_invalid_db_url(default_conf):
|
def test_init_invalid_db_url(default_conf):
|
||||||
conf = deepcopy(default_conf)
|
|
||||||
|
|
||||||
# Update path to a value other than default, but still in-memory
|
# Update path to a value other than default, but still in-memory
|
||||||
conf.update({'db_url': 'unknown:///some.url'})
|
default_conf.update({'db_url': 'unknown:///some.url'})
|
||||||
with pytest.raises(OperationalException, match=r'.*no valid database URL*'):
|
with pytest.raises(OperationalException, match=r'.*no valid database URL*'):
|
||||||
init(conf)
|
init(default_conf)
|
||||||
|
|
||||||
|
|
||||||
def test_init_prod_db(default_conf, mocker):
|
def test_init_prod_db(default_conf, mocker):
|
||||||
conf = deepcopy(default_conf)
|
default_conf.update({'dry_run': False})
|
||||||
conf.update({'dry_run': False})
|
default_conf.update({'db_url': constants.DEFAULT_DB_PROD_URL})
|
||||||
conf.update({'db_url': constants.DEFAULT_DB_PROD_URL})
|
|
||||||
|
|
||||||
create_engine_mock = mocker.patch('freqtrade.persistence.create_engine', MagicMock())
|
create_engine_mock = mocker.patch('freqtrade.persistence.create_engine', MagicMock())
|
||||||
|
|
||||||
init(conf)
|
init(default_conf)
|
||||||
assert create_engine_mock.call_count == 1
|
assert create_engine_mock.call_count == 1
|
||||||
assert create_engine_mock.mock_calls[0][1][0] == 'sqlite:///tradesv3.sqlite'
|
assert create_engine_mock.mock_calls[0][1][0] == 'sqlite:///tradesv3.sqlite'
|
||||||
|
|
||||||
|
|
||||||
def test_init_dryrun_db(default_conf, mocker):
|
def test_init_dryrun_db(default_conf, mocker):
|
||||||
conf = deepcopy(default_conf)
|
default_conf.update({'dry_run': True})
|
||||||
conf.update({'dry_run': True})
|
default_conf.update({'db_url': constants.DEFAULT_DB_DRYRUN_URL})
|
||||||
conf.update({'db_url': constants.DEFAULT_DB_DRYRUN_URL})
|
|
||||||
|
|
||||||
create_engine_mock = mocker.patch('freqtrade.persistence.create_engine', MagicMock())
|
create_engine_mock = mocker.patch('freqtrade.persistence.create_engine', MagicMock())
|
||||||
|
|
||||||
init(conf)
|
init(default_conf)
|
||||||
assert create_engine_mock.call_count == 1
|
assert create_engine_mock.call_count == 1
|
||||||
assert create_engine_mock.mock_calls[0][1][0] == 'sqlite://'
|
assert create_engine_mock.mock_calls[0][1][0] == 'sqlite://'
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user