diff --git a/Dockerfile b/Dockerfile index d2c2b1b22..309763d2a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,8 @@ WORKDIR /freqtrade # Install dependencies COPY requirements.txt /freqtrade/ -RUN pip install -r requirements.txt +RUN pip install numpy \ + && pip install -r requirements.txt # Install and execute COPY . /freqtrade/ diff --git a/config.json.example b/config.json.example index e8473e919..8bd3942e6 100644 --- a/config.json.example +++ b/config.json.example @@ -17,6 +17,7 @@ "name": "bittrex", "key": "your_exchange_key", "secret": "your_exchange_secret", + "ccxt_rate_limit": true, "pair_whitelist": [ "ETH/BTC", "LTC/BTC", diff --git a/config_full.json.example b/config_full.json.example index b0714535f..cc3b3d630 100644 --- a/config_full.json.example +++ b/config_full.json.example @@ -26,6 +26,7 @@ "name": "bittrex", "key": "your_exchange_key", "secret": "your_exchange_secret", + "ccxt_rate_limit": true, "pair_whitelist": [ "ETH/BTC", "LTC/BTC", diff --git a/docs/installation.md b/docs/installation.md index e5724a7dc..7a7719fc0 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -56,23 +56,29 @@ Reset parameter will hard reset your branch (only if you are on `master` or `dev Config parameter is a `config.json` configurator. This script will ask you questions to setup your bot and create your `config.json`. - ## Manual installation - Linux/MacOS + The following steps are made for Linux/MacOS environment -**1. Clone the repo** +### 1. Clone the repo + ```bash git clone git@github.com:freqtrade/freqtrade.git git checkout develop cd freqtrade ``` -**2. Create the config file** + +### 2. Create the config file + Switch `"dry_run": true,` + ```bash cp config.json.example config.json vi config.json ``` -**3. Build your docker image and run it** + +### 3. Build your docker image and run it + ```bash docker build -t freqtrade . docker run --rm -v /etc/localtime:/etc/localtime:ro -v `pwd`/config.json:/freqtrade/config.json -it freqtrade diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py index 423e38246..810957902 100644 --- a/freqtrade/exchange/__init__.py +++ b/freqtrade/exchange/__init__.py @@ -91,7 +91,7 @@ class Exchange(object): 'secret': exchange_config.get('secret'), 'password': exchange_config.get('password'), 'uid': exchange_config.get('uid', ''), - 'enableRateLimit': True, + 'enableRateLimit': exchange_config.get('ccxt_rate_limit', True), }) except (KeyError, AttributeError): raise OperationalException(f'Exchange {name} is not supported') diff --git a/freqtrade/tests/conftest.py b/freqtrade/tests/conftest.py index 8d0809367..d18016e16 100644 --- a/freqtrade/tests/conftest.py +++ b/freqtrade/tests/conftest.py @@ -8,10 +8,8 @@ from unittest.mock import MagicMock import arrow import pytest -from jsonschema import validate from telegram import Chat, Message, Update -from freqtrade import constants from freqtrade.exchange.exchange_helpers import parse_ticker_dataframe from freqtrade.exchange import Exchange from freqtrade.freqtradebot import FreqtradeBot @@ -127,7 +125,6 @@ def default_conf(): "db_url": "sqlite://", "loglevel": logging.DEBUG, } - validate(configuration, constants.CONF_SCHEMA) return configuration diff --git a/freqtrade/tests/exchange/test_exchange.py b/freqtrade/tests/exchange/test_exchange.py index f149ac82f..d327b97c7 100644 --- a/freqtrade/tests/exchange/test_exchange.py +++ b/freqtrade/tests/exchange/test_exchange.py @@ -1,7 +1,6 @@ # pragma pylint: disable=missing-docstring, C0103, bad-continuation, global-statement # pragma pylint: disable=protected-access import logging -from copy import deepcopy from datetime import datetime from random import randint 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): - """Function to test ccxt exception handling """ - with pytest.raises(TemporaryError): api_mock.__dict__[mock_ccxt_fun] = MagicMock(side_effect=ccxt.NetworkError) 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={ 'ETH/BTC': '', 'TKN/BTC': '', 'TRST/BTC': '', 'SWT/BTC': '', 'BCC/BTC': '' }) - conf = deepcopy(default_conf) - conf['stake_currency'] = 'ETH' + default_conf['stake_currency'] = 'ETH' mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock)) mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock()) with pytest.raises(OperationalException, match=r'not compatible'): - Exchange(conf) + Exchange(default_conf) 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): caplog.set_level(logging.INFO) - conf = deepcopy(default_conf) - conf['stake_currency'] = 'ETH' + default_conf['stake_currency'] = 'ETH' api_mock = MagicMock() api_mock.name = MagicMock(return_value='binance') mocker.patch('freqtrade.exchange.Exchange._init_ccxt', api_mock) @@ -208,7 +203,7 @@ def test_validate_pairs_stake_exception(default_conf, mocker, caplog): OperationalException, match=r'Pair ETH/BTC not compatible with stake_currency: ETH' ): - Exchange(conf) + Exchange(default_conf) def test_validate_timeframes(default_conf, mocker): diff --git a/freqtrade/tests/optimize/test_backtesting.py b/freqtrade/tests/optimize/test_backtesting.py index e4177eab5..5d121d27c 100644 --- a/freqtrade/tests/optimize/test_backtesting.py +++ b/freqtrade/tests/optimize/test_backtesting.py @@ -3,7 +3,6 @@ import json import math import random -from copy import deepcopy from typing import List from unittest.mock import MagicMock @@ -164,9 +163,6 @@ def _trend_alternate(dataframe=None, metadata=None): # Unit tests def test_setup_configuration_without_arguments(mocker, default_conf, caplog) -> None: - """ - Test setup_configuration() function - """ mocker.patch('freqtrade.configuration.open', mocker.mock_open( 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: - """ - Test setup_configuration() function - """ mocker.patch('freqtrade.configuration.open', mocker.mock_open( 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: - """ - Test setup_configuration() function - """ - - conf = deepcopy(default_conf) - conf['stake_amount'] = constants.UNLIMITED_STAKE_AMOUNT + default_conf['stake_amount'] = constants.UNLIMITED_STAKE_AMOUNT mocker.patch('freqtrade.configuration.open', mocker.mock_open( - read_data=json.dumps(conf) + read_data=json.dumps(default_conf) )) 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: - """ - Test start() function - """ start_mock = MagicMock() mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) patch_exchange(mocker) @@ -323,9 +308,6 @@ def test_start(mocker, fee, default_conf, caplog) -> None: def test_backtesting_init(mocker, default_conf) -> None: - """ - Test Backtesting._init() method - """ patch_exchange(mocker) get_fee = mocker.patch('freqtrade.exchange.Exchange.get_fee', MagicMock(return_value=0.5)) 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: - """ - Test Backtesting.tickerdata_to_dataframe() method - """ patch_exchange(mocker) timerange = TimeRange(None, 'line', 0, -100) 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: - """ - Test Backtesting.get_timeframe() method - """ patch_exchange(mocker) backtesting = Backtesting(default_conf) @@ -377,9 +353,6 @@ def test_get_timeframe(default_conf, mocker) -> None: def test_generate_text_table(default_conf, mocker): - """ - Test Backtesting.generate_text_table() method - """ patch_exchange(mocker) 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): - """ - Test Backtesting.generate_text_table_sell_reason() method - """ patch_exchange(mocker) 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: - """ - Test Backtesting.start() method - """ - def get_timeframe(input1, input2): 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, ) - conf = deepcopy(default_conf) - conf['exchange']['pair_whitelist'] = ['UNITTEST/BTC'] - conf['ticker_interval'] = 1 - conf['live'] = False - conf['datadir'] = None - conf['export'] = None - conf['timerange'] = '-100' + default_conf['exchange']['pair_whitelist'] = ['UNITTEST/BTC'] + default_conf['ticker_interval'] = 1 + default_conf['live'] = False + default_conf['datadir'] = None + default_conf['export'] = None + default_conf['timerange'] = '-100' - backtesting = Backtesting(conf) + backtesting = Backtesting(default_conf) backtesting.start() # check the logs, that will contain the backtest result 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: - """ - Test Backtesting.start() method if no data is found - """ - def get_timeframe(input1, input2): 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, ) - conf = deepcopy(default_conf) - conf['exchange']['pair_whitelist'] = ['UNITTEST/BTC'] - conf['ticker_interval'] = "1m" - conf['live'] = False - conf['datadir'] = None - conf['export'] = None - conf['timerange'] = '20180101-20180102' + default_conf['exchange']['pair_whitelist'] = ['UNITTEST/BTC'] + default_conf['ticker_interval'] = "1m" + default_conf['live'] = False + default_conf['datadir'] = None + default_conf['export'] = None + default_conf['timerange'] = '20180101-20180102' - backtesting = Backtesting(conf) + backtesting = Backtesting(default_conf) backtesting.start() # 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: - """ - Test Backtesting.backtest() method - """ mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) patch_exchange(mocker) 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: - """ - Test Backtesting.backtest() method with 1 min ticker - """ mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) patch_exchange(mocker) 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: - """ - Test Backtesting.backtest() method with offline data - """ patch_exchange(mocker) 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): - conf = deepcopy(default_conf) - conf['exchange']['pair_whitelist'] = ['UNITTEST/BTC'] + default_conf['exchange']['pair_whitelist'] = ['UNITTEST/BTC'] mocker.patch('freqtrade.exchange.Exchange.get_ticker_history', new=lambda s, n, i: _load_pair_as_ticks(n, i)) patch_exchange(mocker) mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest', MagicMock()) mocker.patch('freqtrade.optimize.backtesting.Backtesting._generate_text_table', MagicMock()) mocker.patch('freqtrade.configuration.open', mocker.mock_open( - read_data=json.dumps(conf) + read_data=json.dumps(default_conf) )) args = MagicMock() diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index f1e7ad1d7..65a3c2fdb 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -1,6 +1,5 @@ # pragma pylint: disable=missing-docstring,W0212,C0103 import os -from copy import deepcopy from unittest.mock import MagicMock 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.optimize.test_backtesting import get_args -# Avoid to reinit the same object again and again -_HYPEROPT_INITIALIZED = False -_HYPEROPT = None - @pytest.fixture(scope='function') -def init_hyperopt(default_conf, mocker): - global _HYPEROPT_INITIALIZED, _HYPEROPT - if not _HYPEROPT_INITIALIZED: - patch_exchange(mocker) - _HYPEROPT = Hyperopt(default_conf) - _HYPEROPT_INITIALIZED = True +def hyperopt(default_conf, mocker): + patch_exchange(mocker) + return Hyperopt(default_conf) # 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* - we don't create any pickle'd files in the filesystem - we might have a pickle'd file so make sure that we return 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.getsize', return_value=1) @@ -45,9 +37,6 @@ def create_trials(mocker) -> None: def test_start(mocker, default_conf, caplog) -> None: - """ - Test start() function - """ start_mock = MagicMock() mocker.patch( 'freqtrade.configuration.Configuration._load_config_file', @@ -76,8 +65,7 @@ def test_start(mocker, default_conf, caplog) -> None: assert start_mock.call_count == 1 -def test_loss_calculation_prefer_correct_trade_count(init_hyperopt) -> None: - hyperopt = _HYPEROPT +def test_loss_calculation_prefer_correct_trade_count(hyperopt) -> None: StrategyResolver({'strategy': 'DefaultStrategy'}) 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 -def test_loss_calculation_prefer_shorter_trades(init_hyperopt) -> None: - hyperopt = _HYPEROPT - +def test_loss_calculation_prefer_shorter_trades(hyperopt) -> None: shorter = hyperopt.calculate_loss(1, 100, 20) longer = hyperopt.calculate_loss(1, 100, 30) assert shorter < longer -def test_loss_calculation_has_limited_profit(init_hyperopt) -> None: - hyperopt = _HYPEROPT - +def test_loss_calculation_has_limited_profit(hyperopt) -> None: 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) 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 -def test_log_results_if_loss_improves(init_hyperopt, capsys) -> None: - hyperopt = _HYPEROPT +def test_log_results_if_loss_improves(hyperopt, capsys) -> None: hyperopt.current_best_loss = 2 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 -def test_no_log_if_loss_does_not_improve(init_hyperopt, caplog) -> None: - hyperopt = _HYPEROPT +def test_no_log_if_loss_does_not_improve(hyperopt, caplog) -> None: hyperopt.current_best_loss = 2 hyperopt.log_results( { @@ -131,13 +113,10 @@ def test_no_log_if_loss_does_not_improve(init_hyperopt, caplog) -> None: assert caplog.record_tuples == [] -def test_save_trials_saves_trials(mocker, init_hyperopt, caplog) -> None: - trials = create_trials(mocker) +def test_save_trials_saves_trials(mocker, hyperopt, caplog) -> None: + trials = create_trials(mocker, hyperopt) mock_dump = mocker.patch('freqtrade.optimize.hyperopt.dump', return_value=None) - - hyperopt = _HYPEROPT - _HYPEROPT.trials = trials - + hyperopt.trials = trials hyperopt.save_trials() 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() -def test_read_trials_returns_trials_file(mocker, init_hyperopt, caplog) -> None: - trials = create_trials(mocker) +def test_read_trials_returns_trials_file(mocker, hyperopt, caplog) -> None: + trials = create_trials(mocker, hyperopt) mock_load = mocker.patch('freqtrade.optimize.hyperopt.load', return_value=trials) - - hyperopt = _HYPEROPT hyperopt_trial = hyperopt.read_trials() trials_file = os.path.join('freqtrade', 'tests', 'optimize', 'ut_trials.pickle') assert log_has( @@ -163,7 +140,7 @@ def test_read_trials_returns_trials_file(mocker, init_hyperopt, caplog) -> None: mock_load.assert_called_once() -def test_roi_table_generation(init_hyperopt) -> None: +def test_roi_table_generation(hyperopt) -> None: params = { 'roi_t1': 5, 'roi_t2': 10, @@ -173,11 +150,10 @@ def test_roi_table_generation(init_hyperopt) -> None: 'roi_p3': 3, } - hyperopt = _HYPEROPT 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()) mocker.patch('freqtrade.optimize.hyperopt.load_data', MagicMock()) 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) - conf = deepcopy(default_conf) - conf.update({'config': 'config.json.example'}) - conf.update({'epochs': 1}) - conf.update({'timerange': None}) - conf.update({'spaces': 'all'}) + default_conf.update({'config': 'config.json.example'}) + default_conf.update({'epochs': 1}) + default_conf.update({'timerange': None}) + default_conf.update({'spaces': 'all'}) - hyperopt = Hyperopt(conf) + hyperopt = Hyperopt(default_conf) hyperopt.tickerdata_to_dataframe = MagicMock() hyperopt.start() @@ -203,11 +178,7 @@ def test_start_calls_optimizer(mocker, init_hyperopt, default_conf, caplog) -> N assert dumper.called -def test_format_results(init_hyperopt): - """ - Test Hyperopt.format_results() - """ - +def test_format_results(hyperopt): # Test with BTC as stake_currency trades = [ ('ETH/BTC', 2, 2, 123), @@ -217,7 +188,7 @@ def test_format_results(init_hyperopt): labels = ['currency', 'profit_percent', 'profit_abs', 'trade_duration'] 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('Total profit 1.00000000 BTC') assert result.find('2.0000Σ %') @@ -229,25 +200,25 @@ def test_format_results(init_hyperopt): ('XPR/EUR', -1, -2, -246) ] 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') -def test_has_space(init_hyperopt): - _HYPEROPT.config.update({'spaces': ['buy', 'roi']}) - assert _HYPEROPT.has_space('roi') - assert _HYPEROPT.has_space('buy') - assert not _HYPEROPT.has_space('stoploss') +def test_has_space(hyperopt): + hyperopt.config.update({'spaces': ['buy', 'roi']}) + assert hyperopt.has_space('roi') + assert hyperopt.has_space('buy') + assert not hyperopt.has_space('stoploss') - _HYPEROPT.config.update({'spaces': ['all']}) - assert _HYPEROPT.has_space('buy') + hyperopt.config.update({'spaces': ['all']}) + 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') tickerlist = {'UNITTEST/BTC': tick} - dataframes = _HYPEROPT.tickerdata_to_dataframe(tickerlist) - dataframe = _HYPEROPT.populate_indicators(dataframes['UNITTEST/BTC'], {'pair': 'UNITTEST/BTC'}) + dataframes = hyperopt.tickerdata_to_dataframe(tickerlist) + dataframe = hyperopt.populate_indicators(dataframes['UNITTEST/BTC'], {'pair': 'UNITTEST/BTC'}) # Check if some indicators are generated. We will not test all of them assert 'adx' in dataframe @@ -255,13 +226,13 @@ def test_populate_indicators(init_hyperopt) -> None: 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') tickerlist = {'UNITTEST/BTC': tick} - dataframes = _HYPEROPT.tickerdata_to_dataframe(tickerlist) - dataframe = _HYPEROPT.populate_indicators(dataframes['UNITTEST/BTC'], {'pair': 'UNITTEST/BTC'}) + dataframes = hyperopt.tickerdata_to_dataframe(tickerlist) + 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, 'fastd-value': 20, @@ -280,11 +251,10 @@ def test_buy_strategy_generator(init_hyperopt) -> None: assert 1 in result['buy'] -def test_generate_optimizer(mocker, init_hyperopt, default_conf) -> None: - conf = deepcopy(default_conf) - conf.update({'config': 'config.json.example'}) - conf.update({'timerange': None}) - conf.update({'spaces': 'all'}) +def test_generate_optimizer(mocker, default_conf) -> None: + default_conf.update({'config': 'config.json.example'}) + default_conf.update({'timerange': None}) + default_conf.update({'spaces': 'all'}) trades = [ ('POWR/BTC', 0.023117, 0.000233, 100) @@ -324,6 +294,6 @@ def test_generate_optimizer(mocker, init_hyperopt, default_conf) -> None: 'params': optimizer_param } - hyperopt = Hyperopt(conf) + hyperopt = Hyperopt(default_conf) generate_optimizer_value = hyperopt.generate_optimizer(list(optimizer_param.values())) assert generate_optimizer_value == response_expected diff --git a/freqtrade/tests/rpc/test_rpc.py b/freqtrade/tests/rpc/test_rpc.py index 63624db85..70b7dcfd9 100644 --- a/freqtrade/tests/rpc/test_rpc.py +++ b/freqtrade/tests/rpc/test_rpc.py @@ -11,8 +11,8 @@ from freqtrade.freqtradebot import FreqtradeBot from freqtrade.persistence import Trade from freqtrade.rpc import RPC, RPCException from freqtrade.state import State -from freqtrade.tests.test_freqtradebot import (patch_coinmarketcap, - patch_get_signal) +from freqtrade.tests.test_freqtradebot import patch_get_signal +from freqtrade.tests.conftest import patch_coinmarketcap # 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): - """ - Test rpc_balance() method - """ mock_balance = { 'BTC': { 'free': 10.0, diff --git a/freqtrade/tests/rpc/test_rpc_manager.py b/freqtrade/tests/rpc/test_rpc_manager.py index c4f27787b..90c693830 100644 --- a/freqtrade/tests/rpc/test_rpc_manager.py +++ b/freqtrade/tests/rpc/test_rpc_manager.py @@ -1,7 +1,6 @@ # pragma pylint: disable=missing-docstring, C0103 import logging -from copy import deepcopy from unittest.mock import MagicMock 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: - conf = deepcopy(default_conf) - conf['telegram']['enabled'] = False + default_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 == [] def test_init_telegram_disabled(mocker, default_conf, caplog) -> None: caplog.set_level(logging.DEBUG) - conf = deepcopy(default_conf) - conf['telegram']['enabled'] = False - rpc_manager = RPCManager(get_patched_freqtradebot(mocker, conf)) + default_conf['telegram']['enabled'] = False + rpc_manager = RPCManager(get_patched_freqtradebot(mocker, default_conf)) assert not log_has('Enabling rpc.telegram ...', caplog.record_tuples) 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: caplog.set_level(logging.DEBUG) telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.cleanup', MagicMock()) - conf = deepcopy(default_conf) - conf['telegram']['enabled'] = False + default_conf['telegram']['enabled'] = False - freqtradebot = get_patched_freqtradebot(mocker, conf) + freqtradebot = get_patched_freqtradebot(mocker, default_conf) rpc_manager = RPCManager(freqtradebot) 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: telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg', MagicMock()) - conf = deepcopy(default_conf) - conf['telegram']['enabled'] = False + default_conf['telegram']['enabled'] = False - freqtradebot = get_patched_freqtradebot(mocker, conf) + freqtradebot = get_patched_freqtradebot(mocker, default_conf) rpc_manager = RPCManager(freqtradebot) rpc_manager.send_msg({ '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: caplog.set_level(logging.DEBUG) - conf = deepcopy(default_conf) - conf['telegram']['enabled'] = False - conf['webhook'] = {'enabled': False} - rpc_manager = RPCManager(get_patched_freqtradebot(mocker, conf)) + default_conf['telegram']['enabled'] = False + default_conf['webhook'] = {'enabled': False} + rpc_manager = RPCManager(get_patched_freqtradebot(mocker, default_conf)) assert not log_has('Enabling rpc.webhook ...', caplog.record_tuples) assert rpc_manager.registered_modules == [] diff --git a/freqtrade/tests/rpc/test_rpc_telegram.py b/freqtrade/tests/rpc/test_rpc_telegram.py index ceb8a7808..4b2fe4cf5 100644 --- a/freqtrade/tests/rpc/test_rpc_telegram.py +++ b/freqtrade/tests/rpc/test_rpc_telegram.py @@ -3,7 +3,6 @@ # pragma pylint: disable=too-many-lines, too-many-arguments import re -from copy import deepcopy from datetime import datetime from random import randint 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.tests.conftest import (get_patched_freqtradebot, log_has, patch_exchange) -from freqtrade.tests.test_freqtradebot import (patch_coinmarketcap, - patch_get_signal) +from freqtrade.tests.test_freqtradebot import patch_get_signal +from freqtrade.tests.conftest import patch_coinmarketcap class DummyCls(Telegram): @@ -96,9 +95,8 @@ def test_authorized_only(default_conf, mocker, caplog) -> None: update = Update(randint(1, 100)) update.message = Message(randint(1, 100), 0, datetime.utcnow(), chat) - conf = deepcopy(default_conf) - conf['telegram']['enabled'] = False - bot = FreqtradeBot(conf) + default_conf['telegram']['enabled'] = False + bot = FreqtradeBot(default_conf) patch_get_signal(bot, (True, False)) dummy = DummyCls(bot) 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.message = Message(randint(1, 100), 0, datetime.utcnow(), chat) - conf = deepcopy(default_conf) - conf['telegram']['enabled'] = False - bot = FreqtradeBot(conf) + default_conf['telegram']['enabled'] = False + bot = FreqtradeBot(default_conf) patch_get_signal(bot, (True, False)) dummy = DummyCls(bot) 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.message = Message(randint(1, 100), 0, datetime.utcnow(), Chat(0, 0)) - conf = deepcopy(default_conf) - conf['telegram']['enabled'] = False + default_conf['telegram']['enabled'] = False - bot = FreqtradeBot(conf) + bot = FreqtradeBot(default_conf) patch_get_signal(bot, (True, False)) 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: update.message.chat.id = 123 - conf = deepcopy(default_conf) - conf['telegram']['enabled'] = False - conf['telegram']['chat_id'] = 123 + default_conf['telegram']['enabled'] = False + default_conf['telegram']['chat_id'] = 123 patch_coinmarketcap(mocker) @@ -214,7 +209,7 @@ def test_status(default_conf, update, mocker, fee, ticker, markets) -> None: ) mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock()) - freqtradebot = FreqtradeBot(conf) + freqtradebot = FreqtradeBot(default_conf) patch_get_signal(freqtradebot, (True, False)) 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()) - conf = deepcopy(default_conf) - conf['stake_amount'] = 15.0 - freqtradebot = FreqtradeBot(conf) + default_conf['stake_amount'] = 15.0 + freqtradebot = FreqtradeBot(default_conf) patch_get_signal(freqtradebot, (True, False)) 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: patch_coinmarketcap(mocker) mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock()) - conf = deepcopy(default_conf) bot = MagicMock() - freqtradebot = get_patched_freqtradebot(mocker, conf) + freqtradebot = get_patched_freqtradebot(mocker, default_conf) telegram = Telegram(freqtradebot) 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: patch_coinmarketcap(mocker) mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock()) - conf = deepcopy(default_conf) bot = MagicMock() 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._config['telegram']['enabled'] = True diff --git a/freqtrade/tests/strategy/test_interface.py b/freqtrade/tests/strategy/test_interface.py index 1099f4b5f..2c056870f 100644 --- a/freqtrade/tests/strategy/test_interface.py +++ b/freqtrade/tests/strategy/test_interface.py @@ -98,9 +98,6 @@ def test_get_signal_handles_exceptions(mocker, default_conf): def test_tickerdata_to_dataframe(default_conf) -> None: - """ - Test Analyze.tickerdata_to_dataframe() method - """ strategy = DefaultStrategy(default_conf) timerange = TimeRange(None, 'line', 0, -100) diff --git a/freqtrade/tests/test_arguments.py b/freqtrade/tests/test_arguments.py index c7740ce47..79bd0254b 100644 --- a/freqtrade/tests/test_arguments.py +++ b/freqtrade/tests/test_arguments.py @@ -1,9 +1,5 @@ # pragma pylint: disable=missing-docstring, C0103 -""" -Unit test file for arguments.py -""" - import argparse import pytest diff --git a/freqtrade/tests/test_configuration.py b/freqtrade/tests/test_configuration.py index d4f9f46e1..e48553bdf 100644 --- a/freqtrade/tests/test_configuration.py +++ b/freqtrade/tests/test_configuration.py @@ -2,13 +2,13 @@ import json from argparse import Namespace -from copy import deepcopy import logging from unittest.mock import MagicMock import pytest -from jsonschema import ValidationError +from jsonschema import validate, ValidationError +from freqtrade import constants from freqtrade import OperationalException from freqtrade.arguments import Arguments 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: - conf = deepcopy(default_conf) - conf['exchange']['pair_whitelist'].append('ETH-BTC') + default_conf['exchange']['pair_whitelist'].append('ETH-BTC') with pytest.raises(ValidationError, match=r'.*does not match.*'): configuration = Configuration(Namespace()) - configuration._validate_config(conf) + configuration._validate_config(default_conf) def test_load_config_missing_attributes(default_conf) -> None: - conf = deepcopy(default_conf) - conf.pop('exchange') + default_conf.pop('exchange') with pytest.raises(ValidationError, match=r'.*\'exchange\' is a required property.*'): configuration = Configuration(Namespace()) - configuration._validate_config(conf) + configuration._validate_config(default_conf) def test_load_config_incorrect_stake_amount(default_conf) -> None: - conf = deepcopy(default_conf) - conf['stake_amount'] = 'fake' + default_conf['stake_amount'] = 'fake' with pytest.raises(ValidationError, match=r'.*\'fake\' does not match \'unlimited\'.*'): configuration = Configuration(Namespace()) - configuration._validate_config(conf) + configuration._validate_config(default_conf) 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: - conf = deepcopy(default_conf) - conf['max_open_trades'] = 0 + default_conf['max_open_trades'] = 0 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') @@ -151,13 +147,12 @@ def test_load_config_with_params(default_conf, mocker) -> None: def test_load_custom_strategy(default_conf, mocker) -> None: - custom_conf = deepcopy(default_conf) - custom_conf.update({ + default_conf.update({ 'strategy': 'CustomStrategy', 'strategy_path': '/tmp/strategies', }) 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() @@ -322,29 +317,25 @@ def test_hyperopt_with_arguments(mocker, default_conf, caplog) -> None: def test_check_exchange(default_conf) -> None: - """ - Test the configuration validator with a missing attribute - """ - conf = deepcopy(default_conf) configuration = Configuration(Namespace()) # Test a valid exchange - conf.get('exchange').update({'name': 'BITTREX'}) - assert configuration.check_exchange(conf) + default_conf.get('exchange').update({'name': 'BITTREX'}) + assert configuration.check_exchange(default_conf) # Test a valid exchange - conf.get('exchange').update({'name': 'binance'}) - assert configuration.check_exchange(conf) + default_conf.get('exchange').update({'name': 'binance'}) + assert configuration.check_exchange(default_conf) # Test a invalid exchange - conf.get('exchange').update({'name': 'unknown_exchange'}) - configuration.config = conf + default_conf.get('exchange').update({'name': 'unknown_exchange'}) + configuration.config = default_conf with pytest.raises( OperationalException, 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: @@ -398,3 +389,7 @@ def test_set_loggers() -> None: assert logging.getLogger('requests').level is logging.DEBUG assert logging.getLogger('ccxt.base.exchange').level is logging.DEBUG assert logging.getLogger('telegram').level is logging.INFO + + +def test_validate_default_conf(default_conf) -> None: + validate(default_conf, constants.CONF_SCHEMA) diff --git a/freqtrade/tests/test_freqtradebot.py b/freqtrade/tests/test_freqtradebot.py index b1e08383b..69f349107 100644 --- a/freqtrade/tests/test_freqtradebot.py +++ b/freqtrade/tests/test_freqtradebot.py @@ -1,9 +1,6 @@ +# pragma pylint: disable=missing-docstring, C0103 # pragma pylint: disable=protected-access, too-many-lines, invalid-name, too-many-arguments -""" -Unit test file for freqtradebot.py -""" - import logging import re import time @@ -21,7 +18,7 @@ from freqtrade.persistence import Trade from freqtrade.rpc import RPCMessageType from freqtrade.state import State from freqtrade.strategy.interface import SellType, SellCheckTuple -from freqtrade.tests.conftest import log_has, patch_coinmarketcap, patch_exchange +from freqtrade.tests.conftest import log_has, patch_exchange # Functions for recurrent object patching @@ -35,7 +32,6 @@ def get_patched_freqtradebot(mocker, config) -> FreqtradeBot: mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock()) mocker.patch('freqtrade.freqtradebot.persistence.init', MagicMock()) patch_exchange(mocker) - patch_coinmarketcap(mocker) return FreqtradeBot(config) @@ -64,22 +60,15 @@ def patch_RPCManager(mocker) -> MagicMock: # Unit tests def test_freqtradebot(mocker, default_conf) -> None: - """ - Test __init__, _init_modules, update_state, and get_state methods - """ freqtrade = get_patched_freqtradebot(mocker, default_conf) assert freqtrade.state is State.RUNNING - conf = deepcopy(default_conf) - conf.pop('initial_state') - freqtrade = FreqtradeBot(conf) + default_conf.pop('initial_state') + freqtrade = FreqtradeBot(default_conf) assert freqtrade.state is State.STOPPED def test_cleanup(mocker, default_conf, caplog) -> None: - """ - Test clean() method - """ mock_cleanup = MagicMock() mocker.patch('freqtrade.persistence.cleanup', mock_cleanup) @@ -90,9 +79,6 @@ def test_cleanup(mocker, default_conf, caplog) -> None: def test_worker_running(mocker, default_conf, caplog) -> None: - """ - Test worker() method. Test when we start the bot - """ mock_throttle = MagicMock() mocker.patch('freqtrade.freqtradebot.FreqtradeBot._throttle', mock_throttle) @@ -105,9 +91,6 @@ def test_worker_running(mocker, default_conf, caplog) -> None: def test_worker_stopped(mocker, default_conf, caplog) -> None: - """ - Test worker() method. Test when we stop the bot - """ mock_throttle = MagicMock() mocker.patch('freqtrade.freqtradebot.FreqtradeBot._throttle', mock_throttle) mock_sleep = mocker.patch('time.sleep', return_value=None) @@ -122,53 +105,38 @@ def test_worker_stopped(mocker, default_conf, caplog) -> None: def test_throttle(mocker, default_conf, caplog) -> None: - """ - Test _throttle() method - """ - def func(): - """ - Test function to throttle - """ + def throttled_func(): return 42 caplog.set_level(logging.DEBUG) freqtrade = get_patched_freqtradebot(mocker, default_conf) start = time.time() - result = freqtrade._throttle(func, min_secs=0.1) + result = freqtrade._throttle(throttled_func, min_secs=0.1) end = time.time() assert result == 42 assert end - start > 0.1 - assert log_has('Throttling func for 0.10 seconds', caplog.record_tuples) + assert log_has('Throttling throttled_func for 0.10 seconds', caplog.record_tuples) - result = freqtrade._throttle(func, min_secs=-1) + result = freqtrade._throttle(throttled_func, min_secs=-1) assert result == 42 def test_throttle_with_assets(mocker, default_conf) -> None: - """ - Test _throttle() method when the function passed can have parameters - """ - def func(nb_assets=-1): - """ - Test function to throttle - """ + def throttled_func(nb_assets=-1): return nb_assets freqtrade = get_patched_freqtradebot(mocker, default_conf) - result = freqtrade._throttle(func, min_secs=0.1, nb_assets=666) + result = freqtrade._throttle(throttled_func, min_secs=0.1, nb_assets=666) assert result == 666 - result = freqtrade._throttle(func, min_secs=0.1) + result = freqtrade._throttle(throttled_func, min_secs=0.1) assert result == -1 def test_gen_pair_whitelist(mocker, default_conf, tickers) -> None: - """ - Test _gen_pair_whitelist() method - """ freqtrade = get_patched_freqtradebot(mocker, default_conf) mocker.patch('freqtrade.exchange.Exchange.get_tickers', tickers) mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True)) @@ -193,17 +161,10 @@ def test_gen_pair_whitelist(mocker, default_conf, tickers) -> None: @pytest.mark.skip(reason="Test not implemented") def test_refresh_whitelist() -> None: - """ - Test _refresh_whitelist() method - """ pass def test_get_trade_stake_amount(default_conf, ticker, limit_buy_order, fee, mocker) -> None: - """ - Test get_trade_stake_amount() method - """ - patch_RPCManager(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', @@ -214,7 +175,7 @@ def test_get_trade_stake_amount(default_conf, ticker, limit_buy_order, fee, mock freqtrade = FreqtradeBot(default_conf) result = freqtrade._get_trade_stake_amount() - assert(result == default_conf['stake_amount']) + assert result == default_conf['stake_amount'] def test_get_trade_stake_amount_no_stake_amount(default_conf, @@ -222,17 +183,12 @@ def test_get_trade_stake_amount_no_stake_amount(default_conf, limit_buy_order, fee, mocker) -> None: - """ - Test get_trade_stake_amount() method - """ patch_RPCManager(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), get_balance=MagicMock(return_value=default_conf['stake_amount'] * 0.5) ) - - # test defined stake amount freqtrade = FreqtradeBot(default_conf) with pytest.raises(DependencyException, match=r'.*stake amount.*'): @@ -245,11 +201,7 @@ def test_get_trade_stake_amount_unlimited_amount(default_conf, fee, markets, mocker) -> None: - """ - Test get_trade_stake_amount() method - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -291,10 +243,6 @@ def test_get_trade_stake_amount_unlimited_amount(default_conf, def test_get_min_pair_stake_amount(mocker, default_conf) -> None: - """ - Test get_trade_stake_amount() method - """ - patch_RPCManager(mocker) mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock()) freqtrade = FreqtradeBot(default_conf) @@ -430,11 +378,7 @@ def test_get_min_pair_stake_amount(mocker, default_conf) -> None: def test_create_trade(default_conf, ticker, limit_buy_order, fee, markets, mocker) -> None: - """ - Test create_trade() method - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -468,11 +412,7 @@ def test_create_trade(default_conf, ticker, limit_buy_order, fee, markets, mocke def test_create_trade_no_stake_amount(default_conf, ticker, limit_buy_order, fee, markets, mocker) -> None: - """ - Test create_trade() method - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -491,11 +431,7 @@ def test_create_trade_no_stake_amount(default_conf, ticker, limit_buy_order, def test_create_trade_minimal_amount(default_conf, ticker, limit_buy_order, fee, markets, mocker) -> None: - """ - Test create_trade() method - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker) buy_mock = MagicMock(return_value={'id': limit_buy_order['id']}) mocker.patch.multiple( 'freqtrade.exchange.Exchange', @@ -505,24 +441,18 @@ def test_create_trade_minimal_amount(default_conf, ticker, limit_buy_order, get_fee=fee, get_markets=markets ) - - conf = deepcopy(default_conf) - conf['stake_amount'] = 0.0005 - freqtrade = FreqtradeBot(conf) + default_conf['stake_amount'] = 0.0005 + freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade) freqtrade.create_trade() rate, amount = buy_mock.call_args[0][1], buy_mock.call_args[0][2] - assert rate * amount >= conf['stake_amount'] + assert rate * amount >= default_conf['stake_amount'] def test_create_trade_too_small_stake_amount(default_conf, ticker, limit_buy_order, fee, markets, mocker) -> None: - """ - Test create_trade() method - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker) buy_mock = MagicMock(return_value={'id': limit_buy_order['id']}) mocker.patch.multiple( 'freqtrade.exchange.Exchange', @@ -533,9 +463,8 @@ def test_create_trade_too_small_stake_amount(default_conf, ticker, limit_buy_ord get_markets=markets ) - conf = deepcopy(default_conf) - conf['stake_amount'] = 0.000000005 - freqtrade = FreqtradeBot(conf) + default_conf['stake_amount'] = 0.000000005 + freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade) result = freqtrade.create_trade() @@ -544,11 +473,7 @@ def test_create_trade_too_small_stake_amount(default_conf, ticker, limit_buy_ord def test_create_trade_limit_reached(default_conf, ticker, limit_buy_order, fee, markets, mocker) -> None: - """ - Test create_trade() method - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -558,11 +483,10 @@ def test_create_trade_limit_reached(default_conf, ticker, limit_buy_order, get_fee=fee, get_markets=markets ) - conf = deepcopy(default_conf) - conf['max_open_trades'] = 0 - conf['stake_amount'] = constants.UNLIMITED_STAKE_AMOUNT + default_conf['max_open_trades'] = 0 + default_conf['stake_amount'] = constants.UNLIMITED_STAKE_AMOUNT - freqtrade = FreqtradeBot(conf) + freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade) assert freqtrade.create_trade() is False @@ -570,11 +494,7 @@ def test_create_trade_limit_reached(default_conf, ticker, limit_buy_order, def test_create_trade_no_pairs(default_conf, ticker, limit_buy_order, fee, markets, mocker) -> None: - """ - Test create_trade() method - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -584,10 +504,9 @@ def test_create_trade_no_pairs(default_conf, ticker, limit_buy_order, fee, marke get_markets=markets ) - conf = deepcopy(default_conf) - conf['exchange']['pair_whitelist'] = ["ETH/BTC"] - conf['exchange']['pair_blacklist'] = ["ETH/BTC"] - freqtrade = FreqtradeBot(conf) + default_conf['exchange']['pair_whitelist'] = ["ETH/BTC"] + default_conf['exchange']['pair_blacklist'] = ["ETH/BTC"] + freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade) freqtrade.create_trade() @@ -598,11 +517,7 @@ def test_create_trade_no_pairs(default_conf, ticker, limit_buy_order, fee, marke def test_create_trade_no_pairs_after_blacklist(default_conf, ticker, limit_buy_order, fee, markets, mocker) -> None: - """ - Test create_trade() method - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -611,11 +526,9 @@ def test_create_trade_no_pairs_after_blacklist(default_conf, ticker, get_fee=fee, get_markets=markets ) - - conf = deepcopy(default_conf) - conf['exchange']['pair_whitelist'] = ["ETH/BTC"] - conf['exchange']['pair_blacklist'] = ["ETH/BTC"] - freqtrade = FreqtradeBot(conf) + default_conf['exchange']['pair_whitelist'] = ["ETH/BTC"] + default_conf['exchange']['pair_blacklist'] = ["ETH/BTC"] + freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade) freqtrade.create_trade() @@ -625,14 +538,9 @@ def test_create_trade_no_pairs_after_blacklist(default_conf, ticker, def test_create_trade_no_signal(default_conf, fee, mocker) -> None: - """ - Test create_trade() method - """ - conf = deepcopy(default_conf) - conf['dry_run'] = True + default_conf['dry_run'] = True patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -640,10 +548,8 @@ def test_create_trade_no_signal(default_conf, fee, mocker) -> None: get_balance=MagicMock(return_value=20), get_fee=fee, ) - - conf = deepcopy(default_conf) - conf['stake_amount'] = 10 - freqtrade = FreqtradeBot(conf) + default_conf['stake_amount'] = 10 + freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade, value=(False, False)) Trade.query = MagicMock() @@ -653,11 +559,7 @@ def test_create_trade_no_signal(default_conf, fee, mocker) -> None: def test_process_trade_creation(default_conf, ticker, limit_buy_order, markets, fee, mocker, caplog) -> None: - """ - Test the trade creation in _process() method - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker, value={'price_usd': 12345.0}) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -694,11 +596,7 @@ def test_process_trade_creation(default_conf, ticker, limit_buy_order, def test_process_exchange_failures(default_conf, ticker, markets, mocker) -> None: - """ - Test _process() method when a RequestException happens - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker, value={'price_usd': 12345.0}) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -717,11 +615,7 @@ def test_process_exchange_failures(default_conf, ticker, markets, mocker) -> Non def test_process_operational_exception(default_conf, ticker, markets, mocker) -> None: - """ - Test _process() method when an OperationalException happens - """ msg_mock = patch_RPCManager(mocker) - patch_coinmarketcap(mocker, value={'price_usd': 12345.0}) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -742,11 +636,7 @@ def test_process_operational_exception(default_conf, ticker, markets, mocker) -> def test_process_trade_handling( default_conf, ticker, limit_buy_order, markets, fee, mocker) -> None: - """ - Test _process() - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker, value={'price_usd': 12345.0}) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -771,9 +661,6 @@ def test_process_trade_handling( def test_balance_fully_ask_side(mocker, default_conf) -> None: - """ - Test get_target_bid() method - """ default_conf['bid_strategy']['ask_last_balance'] = 0.0 freqtrade = get_patched_freqtradebot(mocker, default_conf) @@ -781,9 +668,6 @@ def test_balance_fully_ask_side(mocker, default_conf) -> None: def test_balance_fully_last_side(mocker, default_conf) -> None: - """ - Test get_target_bid() method - """ default_conf['bid_strategy']['ask_last_balance'] = 1.0 freqtrade = get_patched_freqtradebot(mocker, default_conf) @@ -791,9 +675,6 @@ def test_balance_fully_last_side(mocker, default_conf) -> None: def test_balance_bigger_last_ask(mocker, default_conf) -> None: - """ - Test get_target_bid() method - """ default_conf['bid_strategy']['ask_last_balance'] = 1.0 freqtrade = get_patched_freqtradebot(mocker, default_conf) @@ -801,9 +682,6 @@ def test_balance_bigger_last_ask(mocker, default_conf) -> None: def test_process_maybe_execute_buy(mocker, default_conf) -> None: - """ - Test process_maybe_execute_buy() method - """ freqtrade = get_patched_freqtradebot(mocker, default_conf) mocker.patch('freqtrade.freqtradebot.FreqtradeBot.create_trade', MagicMock(return_value=True)) @@ -814,9 +692,6 @@ def test_process_maybe_execute_buy(mocker, default_conf) -> None: def test_process_maybe_execute_buy_exception(mocker, default_conf, caplog) -> None: - """ - Test exception on process_maybe_execute_buy() method - """ freqtrade = get_patched_freqtradebot(mocker, default_conf) mocker.patch( @@ -828,9 +703,6 @@ def test_process_maybe_execute_buy_exception(mocker, default_conf, caplog) -> No def test_process_maybe_execute_sell(mocker, default_conf, limit_buy_order, caplog) -> None: - """ - Test process_maybe_execute_sell() method - """ freqtrade = get_patched_freqtradebot(mocker, default_conf) mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_trade', MagicMock(return_value=True)) @@ -864,9 +736,6 @@ def test_process_maybe_execute_sell(mocker, default_conf, limit_buy_order, caplo def test_process_maybe_execute_sell_exception(mocker, default_conf, limit_buy_order, caplog) -> None: - """ - Test the exceptions in process_maybe_execute_sell() - """ freqtrade = get_patched_freqtradebot(mocker, default_conf) mocker.patch('freqtrade.exchange.Exchange.get_order', return_value=limit_buy_order) @@ -893,9 +762,6 @@ def test_process_maybe_execute_sell_exception(mocker, default_conf, def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, fee, markets, mocker) -> None: - """ - Test check_handle() method - """ patch_RPCManager(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', @@ -910,8 +776,6 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, get_fee=fee, get_markets=markets ) - patch_coinmarketcap(mocker, value={'price_usd': 15000.0}) - freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade) @@ -939,14 +803,9 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, def test_handle_overlpapping_signals(default_conf, ticker, limit_buy_order, fee, markets, mocker) -> None: - """ - Test check_handle() method - """ - conf = deepcopy(default_conf) - conf.update({'experimental': {'use_sell_signal': True}}) + default_conf.update({'experimental': {'use_sell_signal': True}}) patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -956,7 +815,7 @@ def test_handle_overlpapping_signals(default_conf, ticker, limit_buy_order, get_markets=markets ) - freqtrade = FreqtradeBot(conf) + freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade, value=(True, True)) freqtrade.strategy.min_roi_reached = lambda trade, current_profit, current_time: False @@ -999,15 +858,10 @@ def test_handle_overlpapping_signals(default_conf, ticker, limit_buy_order, def test_handle_trade_roi(default_conf, ticker, limit_buy_order, fee, mocker, markets, caplog) -> None: - """ - Test check_handle() method - """ caplog.set_level(logging.DEBUG) - conf = deepcopy(default_conf) - conf.update({'experimental': {'use_sell_signal': True}}) + default_conf.update({'experimental': {'use_sell_signal': True}}) patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -1017,7 +871,7 @@ def test_handle_trade_roi(default_conf, ticker, limit_buy_order, get_markets=markets ) - freqtrade = FreqtradeBot(conf) + freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade, value=(True, False)) freqtrade.strategy.min_roi_reached = lambda trade, current_profit, current_time: True @@ -1038,15 +892,9 @@ def test_handle_trade_roi(default_conf, ticker, limit_buy_order, def test_handle_trade_experimental( default_conf, ticker, limit_buy_order, fee, mocker, markets, caplog) -> None: - """ - Test check_handle() method - """ caplog.set_level(logging.DEBUG) - conf = deepcopy(default_conf) - conf.update({'experimental': {'use_sell_signal': True}}) - + default_conf.update({'experimental': {'use_sell_signal': True}}) patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -1056,7 +904,7 @@ def test_handle_trade_experimental( get_markets=markets ) - freqtrade = FreqtradeBot(conf) + freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade) freqtrade.strategy.min_roi_reached = lambda trade, current_profit, current_time: False freqtrade.create_trade() @@ -1074,11 +922,7 @@ def test_handle_trade_experimental( def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order, fee, markets, mocker) -> None: - """ - Test check_handle() method - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -1105,12 +949,8 @@ def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order, def test_check_handle_timedout_buy(default_conf, ticker, limit_buy_order_old, fee, mocker) -> None: - """ - Test check_handle_timedout() method - """ rpc_mock = patch_RPCManager(mocker) cancel_order_mock = MagicMock() - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -1146,11 +986,7 @@ def test_check_handle_timedout_buy(default_conf, ticker, limit_buy_order_old, fe def test_check_handle_timedout_sell(default_conf, ticker, limit_sell_order_old, mocker) -> None: - """ - Test check_handle_timedout() method - """ rpc_mock = patch_RPCManager(mocker) - patch_coinmarketcap(mocker) cancel_order_mock = MagicMock() mocker.patch.multiple( 'freqtrade.exchange.Exchange', @@ -1186,11 +1022,7 @@ def test_check_handle_timedout_sell(default_conf, ticker, limit_sell_order_old, def test_check_handle_timedout_partial(default_conf, ticker, limit_buy_order_old_partial, mocker) -> None: - """ - Test check_handle_timedout() method - """ rpc_mock = patch_RPCManager(mocker) - patch_coinmarketcap(mocker) cancel_order_mock = MagicMock() mocker.patch.multiple( 'freqtrade.exchange.Exchange', @@ -1228,12 +1060,8 @@ def test_check_handle_timedout_partial(default_conf, ticker, limit_buy_order_old def test_check_handle_timedout_exception(default_conf, ticker, mocker, caplog) -> None: - """ - Test check_handle_timedout() method when get_order throw an exception - """ patch_RPCManager(mocker) cancel_order_mock = MagicMock() - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.freqtradebot.FreqtradeBot', @@ -1274,11 +1102,7 @@ def test_check_handle_timedout_exception(default_conf, ticker, mocker, caplog) - def test_handle_timedout_limit_buy(mocker, default_conf) -> None: - """ - Test handle_timedout_limit_buy() method - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker) cancel_order_mock = MagicMock() mocker.patch.multiple( 'freqtrade.exchange.Exchange', @@ -1300,12 +1124,8 @@ def test_handle_timedout_limit_buy(mocker, default_conf) -> None: def test_handle_timedout_limit_sell(mocker, default_conf) -> None: - """ - Test handle_timedout_limit_sell() method - """ patch_RPCManager(mocker) cancel_order_mock = MagicMock() - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -1326,11 +1146,7 @@ def test_handle_timedout_limit_sell(mocker, default_conf) -> None: def test_execute_sell_up(default_conf, ticker, fee, ticker_sell_up, markets, mocker) -> None: - """ - Test execute_sell() method with a ticker going UP - """ rpc_mock = patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -1376,11 +1192,7 @@ def test_execute_sell_up(default_conf, ticker, fee, ticker_sell_up, markets, moc def test_execute_sell_down(default_conf, ticker, fee, ticker_sell_down, markets, mocker) -> None: - """ - Test execute_sell() method with a ticker going DOWN - """ rpc_mock = patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -1428,11 +1240,7 @@ def test_execute_sell_down(default_conf, ticker, fee, ticker_sell_down, markets, def test_execute_sell_without_conf_sell_up(default_conf, ticker, fee, ticker_sell_up, markets, mocker) -> None: - """ - Test execute_sell() method with a ticker going DOWN and with a bot config empty - """ rpc_mock = patch_RPCManager(mocker) - patch_coinmarketcap(mocker, value={'price_usd': 12345.0}) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -1478,11 +1286,7 @@ def test_execute_sell_without_conf_sell_up(default_conf, ticker, fee, def test_execute_sell_without_conf_sell_down(default_conf, ticker, fee, ticker_sell_down, markets, mocker) -> None: - """ - Test execute_sell() method with a ticker going DOWN and with a bot config empty - """ rpc_mock = patch_RPCManager(mocker) - patch_coinmarketcap(mocker, value={'price_usd': 12345.0}) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -1529,11 +1333,7 @@ def test_execute_sell_without_conf_sell_down(default_conf, ticker, fee, def test_sell_profit_only_enable_profit(default_conf, limit_buy_order, fee, markets, mocker) -> None: - """ - Test sell_profit_only feature when enabled - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -1546,12 +1346,11 @@ def test_sell_profit_only_enable_profit(default_conf, limit_buy_order, get_fee=fee, get_markets=markets ) - conf = deepcopy(default_conf) - conf['experimental'] = { + default_conf['experimental'] = { 'use_sell_signal': True, 'sell_profit_only': True, } - freqtrade = FreqtradeBot(conf) + freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade) freqtrade.strategy.min_roi_reached = lambda trade, current_profit, current_time: False @@ -1566,11 +1365,7 @@ def test_sell_profit_only_enable_profit(default_conf, limit_buy_order, def test_sell_profit_only_disable_profit(default_conf, limit_buy_order, fee, markets, mocker) -> None: - """ - Test sell_profit_only feature when disabled - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -1583,12 +1378,11 @@ def test_sell_profit_only_disable_profit(default_conf, limit_buy_order, get_fee=fee, get_markets=markets ) - conf = deepcopy(default_conf) - conf['experimental'] = { + default_conf['experimental'] = { 'use_sell_signal': True, 'sell_profit_only': False, } - freqtrade = FreqtradeBot(conf) + freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade) freqtrade.strategy.min_roi_reached = lambda trade, current_profit, current_time: False freqtrade.create_trade() @@ -1601,11 +1395,7 @@ def test_sell_profit_only_disable_profit(default_conf, limit_buy_order, def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, fee, markets, mocker) -> None: - """ - Test sell_profit_only feature when enabled and we have a loss - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -1618,12 +1408,11 @@ def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, fee, market get_fee=fee, get_markets=markets ) - conf = deepcopy(default_conf) - conf['experimental'] = { + default_conf['experimental'] = { 'use_sell_signal': True, 'sell_profit_only': True, } - freqtrade = FreqtradeBot(conf) + freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade) freqtrade.strategy.stop_loss_reached = \ lambda current_rate, trade, current_time, current_profit: SellCheckTuple( @@ -1637,11 +1426,7 @@ def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, fee, market def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, fee, markets, mocker) -> None: - """ - Test sell_profit_only feature when enabled and we have a loss - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -1654,14 +1439,12 @@ def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, fee, marke get_fee=fee, get_markets=markets ) - - conf = deepcopy(default_conf) - conf['experimental'] = { + default_conf['experimental'] = { 'use_sell_signal': True, 'sell_profit_only': False, } - freqtrade = FreqtradeBot(conf) + freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade) freqtrade.strategy.min_roi_reached = lambda trade, current_profit, current_time: False @@ -1675,11 +1458,7 @@ def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, fee, marke def test_ignore_roi_if_buy_signal(default_conf, limit_buy_order, fee, markets, mocker) -> None: - """ - Test sell_profit_only feature when enabled and we have a loss - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -1692,13 +1471,10 @@ def test_ignore_roi_if_buy_signal(default_conf, limit_buy_order, fee, markets, m get_fee=fee, get_markets=markets ) - - conf = deepcopy(default_conf) - conf['experimental'] = { + default_conf['experimental'] = { 'ignore_roi_if_buy_signal': True } - - freqtrade = FreqtradeBot(conf) + freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade) freqtrade.strategy.min_roi_reached = lambda trade, current_profit, current_time: True @@ -1716,11 +1492,7 @@ def test_ignore_roi_if_buy_signal(default_conf, limit_buy_order, fee, markets, m def test_trailing_stop_loss(default_conf, limit_buy_order, fee, markets, caplog, mocker) -> None: - """ - Test sell_profit_only feature when enabled and we have a loss - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -1733,11 +1505,8 @@ def test_trailing_stop_loss(default_conf, limit_buy_order, fee, markets, caplog, get_fee=fee, get_markets=markets, ) - - conf = deepcopy(default_conf) - conf['trailing_stop'] = True - print(limit_buy_order) - freqtrade = FreqtradeBot(conf) + default_conf['trailing_stop'] = True + freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade) freqtrade.strategy.min_roi_reached = lambda trade, current_profit, current_time: False @@ -1756,12 +1525,8 @@ def test_trailing_stop_loss(default_conf, limit_buy_order, fee, markets, caplog, def test_trailing_stop_loss_positive(default_conf, limit_buy_order, fee, markets, caplog, mocker) -> None: - """ - Test sell_profit_only feature when enabled and we have a loss - """ buy_price = limit_buy_order['price'] patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -1774,11 +1539,9 @@ def test_trailing_stop_loss_positive(default_conf, limit_buy_order, fee, markets get_fee=fee, get_markets=markets, ) - - conf = deepcopy(default_conf) - conf['trailing_stop'] = True - conf['trailing_stop_positive'] = 0.01 - freqtrade = FreqtradeBot(conf) + default_conf['trailing_stop'] = True + default_conf['trailing_stop_positive'] = 0.01 + freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade) freqtrade.strategy.min_roi_reached = lambda trade, current_profit, current_time: False freqtrade.create_trade() @@ -1818,13 +1581,10 @@ def test_trailing_stop_loss_positive(default_conf, limit_buy_order, fee, markets f'initial stop loss was at 0.000010, trade opened at 0.000011', caplog.record_tuples) -def test_trailing_stop_loss_offset(default_conf, limit_buy_order, fee, caplog, mocker) -> None: - """ - Test sell_profit_only feature when enabled and we have a loss - """ +def test_trailing_stop_loss_offset(default_conf, limit_buy_order, fee, + caplog, mocker, markets) -> None: buy_price = limit_buy_order['price'] patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -1835,13 +1595,13 @@ def test_trailing_stop_loss_offset(default_conf, limit_buy_order, fee, caplog, m }), buy=MagicMock(return_value={'id': limit_buy_order['id']}), get_fee=fee, + get_markets=markets, ) - conf = deepcopy(default_conf) - conf['trailing_stop'] = True - conf['trailing_stop_positive'] = 0.01 - conf['trailing_stop_positive_offset'] = 0.011 - freqtrade = FreqtradeBot(conf) + default_conf['trailing_stop'] = True + default_conf['trailing_stop_positive'] = 0.01 + default_conf['trailing_stop_positive_offset'] = 0.011 + freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade) freqtrade.strategy.min_roi_reached = lambda trade, current_profit, current_time: False freqtrade.create_trade() @@ -1884,11 +1644,7 @@ def test_trailing_stop_loss_offset(default_conf, limit_buy_order, fee, caplog, m def test_disable_ignore_roi_if_buy_signal(default_conf, limit_buy_order, fee, markets, mocker) -> None: - """ - Test sell_profit_only feature when enabled and we have a loss - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', validate_pairs=MagicMock(), @@ -1901,13 +1657,10 @@ def test_disable_ignore_roi_if_buy_signal(default_conf, limit_buy_order, get_fee=fee, get_markets=markets ) - - conf = deepcopy(default_conf) - conf['experimental'] = { + default_conf['experimental'] = { 'ignore_roi_if_buy_signal': False } - - freqtrade = FreqtradeBot(conf) + freqtrade = FreqtradeBot(default_conf) patch_get_signal(freqtrade) freqtrade.strategy.min_roi_reached = lambda trade, current_profit, current_time: True @@ -1926,14 +1679,8 @@ def test_disable_ignore_roi_if_buy_signal(default_conf, limit_buy_order, def test_get_real_amount_quote(default_conf, trades_for_order, buy_order_fee, caplog, mocker): - """ - Test get_real_amount - fee in quote currency - """ - mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=trades_for_order) - patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock(return_value=True)) amount = sum(x['amount'] for x in trades_for_order) trade = Trade( @@ -1954,14 +1701,9 @@ def test_get_real_amount_quote(default_conf, trades_for_order, buy_order_fee, ca def test_get_real_amount_no_trade(default_conf, buy_order_fee, caplog, mocker): - """ - Test get_real_amount - fee in quote currency - """ - mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=[]) patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock(return_value=True)) amount = buy_order_fee['amount'] trade = Trade( @@ -1982,13 +1724,9 @@ def test_get_real_amount_no_trade(default_conf, buy_order_fee, caplog, mocker): def test_get_real_amount_stake(default_conf, trades_for_order, buy_order_fee, mocker): - """ - Test get_real_amount - fees in Stake currency - """ trades_for_order[0]['fee']['currency'] = 'ETH' patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock(return_value=True)) mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=trades_for_order) amount = sum(x['amount'] for x in trades_for_order) @@ -2007,15 +1745,10 @@ def test_get_real_amount_stake(default_conf, trades_for_order, buy_order_fee, mo def test_get_real_amount_BNB(default_conf, trades_for_order, buy_order_fee, mocker): - """ - Test get_real_amount - Fees in BNB - """ - trades_for_order[0]['fee']['currency'] = 'BNB' trades_for_order[0]['fee']['cost'] = 0.00094518 patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock(return_value=True)) mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=trades_for_order) amount = sum(x['amount'] for x in trades_for_order) @@ -2034,12 +1767,7 @@ def test_get_real_amount_BNB(default_conf, trades_for_order, buy_order_fee, mock def test_get_real_amount_multi(default_conf, trades_for_order2, buy_order_fee, caplog, mocker): - """ - Test get_real_amount with split trades (multiple trades for this order) - """ - patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock(return_value=True)) mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=trades_for_order2) amount = float(sum(x['amount'] for x in trades_for_order2)) @@ -2061,14 +1789,10 @@ def test_get_real_amount_multi(default_conf, trades_for_order2, buy_order_fee, c def test_get_real_amount_fromorder(default_conf, trades_for_order, buy_order_fee, caplog, mocker): - """ - Test get_real_amount with split trades (multiple trades for this order) - """ limit_buy_order = deepcopy(buy_order_fee) limit_buy_order['fee'] = {'cost': 0.004, 'currency': 'LTC'} patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock(return_value=True)) mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=[trades_for_order]) @@ -2091,14 +1815,10 @@ def test_get_real_amount_fromorder(default_conf, trades_for_order, buy_order_fee def test_get_real_amount_invalid_order(default_conf, trades_for_order, buy_order_fee, mocker): - """ - Test get_real_amount with split trades (multiple trades for this order) - """ limit_buy_order = deepcopy(buy_order_fee) limit_buy_order['fee'] = {'cost': 0.004} patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock(return_value=True)) mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=[]) amount = float(sum(x['amount'] for x in trades_for_order)) @@ -2117,14 +1837,10 @@ def test_get_real_amount_invalid_order(default_conf, trades_for_order, buy_order def test_get_real_amount_invalid(default_conf, trades_for_order, buy_order_fee, mocker): - """ - Test get_real_amount - fees in Stake currency - """ # Remove "Currency" from fee dict trades_for_order[0]['fee'] = {'cost': 0.008} patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock(return_value=True)) mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=trades_for_order) amount = sum(x['amount'] for x in trades_for_order) @@ -2142,11 +1858,7 @@ def test_get_real_amount_invalid(default_conf, trades_for_order, buy_order_fee, def test_get_real_amount_open_trade(default_conf, mocker): - """ - Test get_real_amount condition trade.fee_open == 0 or order['status'] == 'open' - """ patch_RPCManager(mocker) - patch_coinmarketcap(mocker) mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock(return_value=True)) amount = 12345 trade = Trade( diff --git a/freqtrade/tests/test_persistence.py b/freqtrade/tests/test_persistence.py index 7baddf60a..26932136a 100644 --- a/freqtrade/tests/test_persistence.py +++ b/freqtrade/tests/test_persistence.py @@ -1,5 +1,4 @@ # pragma pylint: disable=missing-docstring, C0103 -from copy import deepcopy from unittest.mock import MagicMock import pytest @@ -23,46 +22,40 @@ def test_init_create_session(default_conf): 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 - 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()) - init(conf) + init(default_conf) assert create_engine_mock.call_count == 1 assert create_engine_mock.mock_calls[0][1][0] == 'sqlite:///tmp/freqtrade2_test.sqlite' def test_init_invalid_db_url(default_conf): - conf = deepcopy(default_conf) - # 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*'): - init(conf) + init(default_conf) def test_init_prod_db(default_conf, mocker): - conf = deepcopy(default_conf) - conf.update({'dry_run': False}) - conf.update({'db_url': constants.DEFAULT_DB_PROD_URL}) + default_conf.update({'dry_run': False}) + default_conf.update({'db_url': constants.DEFAULT_DB_PROD_URL}) 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.mock_calls[0][1][0] == 'sqlite:///tradesv3.sqlite' def test_init_dryrun_db(default_conf, mocker): - conf = deepcopy(default_conf) - conf.update({'dry_run': True}) - conf.update({'db_url': constants.DEFAULT_DB_DRYRUN_URL}) + default_conf.update({'dry_run': True}) + default_conf.update({'db_url': constants.DEFAULT_DB_DRYRUN_URL}) 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.mock_calls[0][1][0] == 'sqlite://' diff --git a/requirements.txt b/requirements.txt index 77cda0f4f..bfc5bc6c6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -ccxt==1.17.49 +ccxt==1.17.56 SQLAlchemy==1.2.10 python-telegram-bot==10.1.0 arrow==0.12.1 @@ -12,7 +12,7 @@ scipy==1.1.0 jsonschema==2.6.0 numpy==1.15.0 TA-Lib==0.4.17 -pytest==3.6.4 +pytest==3.7.0 pytest-mock==1.10.0 pytest-cov==2.5.1 tabulate==0.8.2 diff --git a/setup.py b/setup.py index bfe01e6fe..c5f61c34d 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ setup(name='freqtrade', license='GPLv3', packages=['freqtrade'], scripts=['bin/freqtrade'], - setup_requires=['pytest-runner'], + setup_requires=['pytest-runner', 'numpy'], tests_require=['pytest', 'pytest-mock', 'pytest-cov'], install_requires=[ 'ccxt',