Merge branch 'develop_current' into backslap_develop

This commit is contained in:
Gert 2018-07-31 17:07:30 -07:00
commit 3428b6666b
19 changed files with 204 additions and 607 deletions

View File

@ -15,7 +15,8 @@ WORKDIR /freqtrade
# Install dependencies # Install dependencies
COPY requirements.txt /freqtrade/ COPY requirements.txt /freqtrade/
RUN pip install -r requirements.txt RUN pip install numpy \
&& pip install -r requirements.txt
# Install and execute # Install and execute
COPY . /freqtrade/ COPY . /freqtrade/

View File

@ -17,6 +17,7 @@
"name": "bittrex", "name": "bittrex",
"key": "your_exchange_key", "key": "your_exchange_key",
"secret": "your_exchange_secret", "secret": "your_exchange_secret",
"ccxt_rate_limit": true,
"pair_whitelist": [ "pair_whitelist": [
"ETH/BTC", "ETH/BTC",
"LTC/BTC", "LTC/BTC",

View File

@ -26,6 +26,7 @@
"name": "bittrex", "name": "bittrex",
"key": "your_exchange_key", "key": "your_exchange_key",
"secret": "your_exchange_secret", "secret": "your_exchange_secret",
"ccxt_rate_limit": true,
"pair_whitelist": [ "pair_whitelist": [
"ETH/BTC", "ETH/BTC",
"LTC/BTC", "LTC/BTC",

View File

@ -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`. 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 ## Manual installation - Linux/MacOS
The following steps are made for Linux/MacOS environment The following steps are made for Linux/MacOS environment
**1. Clone the repo** ### 1. Clone the repo
```bash ```bash
git clone git@github.com:freqtrade/freqtrade.git git clone git@github.com:freqtrade/freqtrade.git
git checkout develop git checkout develop
cd freqtrade cd freqtrade
``` ```
**2. Create the config file**
### 2. Create the config file
Switch `"dry_run": true,` Switch `"dry_run": true,`
```bash ```bash
cp config.json.example config.json cp config.json.example config.json
vi config.json vi config.json
``` ```
**3. Build your docker image and run it**
### 3. Build your docker image and run it
```bash ```bash
docker build -t freqtrade . docker build -t freqtrade .
docker run --rm -v /etc/localtime:/etc/localtime:ro -v `pwd`/config.json:/freqtrade/config.json -it freqtrade docker run --rm -v /etc/localtime:/etc/localtime:ro -v `pwd`/config.json:/freqtrade/config.json -it freqtrade

View File

@ -91,7 +91,7 @@ class Exchange(object):
'secret': exchange_config.get('secret'), 'secret': exchange_config.get('secret'),
'password': exchange_config.get('password'), 'password': exchange_config.get('password'),
'uid': exchange_config.get('uid', ''), 'uid': exchange_config.get('uid', ''),
'enableRateLimit': True, 'enableRateLimit': exchange_config.get('ccxt_rate_limit', True),
}) })
except (KeyError, AttributeError): except (KeyError, AttributeError):
raise OperationalException(f'Exchange {name} is not supported') raise OperationalException(f'Exchange {name} is not supported')

View File

@ -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

View File

@ -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):

View File

@ -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()

View File

@ -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 patch_exchange(mocker)
if not _HYPEROPT_INITIALIZED: return Hyperopt(default_conf)
patch_exchange(mocker)
_HYPEROPT = 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

View File

@ -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,

View File

@ -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 == []

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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://'

View File

@ -1,4 +1,4 @@
ccxt==1.17.49 ccxt==1.17.56
SQLAlchemy==1.2.10 SQLAlchemy==1.2.10
python-telegram-bot==10.1.0 python-telegram-bot==10.1.0
arrow==0.12.1 arrow==0.12.1
@ -12,7 +12,7 @@ scipy==1.1.0
jsonschema==2.6.0 jsonschema==2.6.0
numpy==1.15.0 numpy==1.15.0
TA-Lib==0.4.17 TA-Lib==0.4.17
pytest==3.6.4 pytest==3.7.0
pytest-mock==1.10.0 pytest-mock==1.10.0
pytest-cov==2.5.1 pytest-cov==2.5.1
tabulate==0.8.2 tabulate==0.8.2

View File

@ -18,7 +18,7 @@ setup(name='freqtrade',
license='GPLv3', license='GPLv3',
packages=['freqtrade'], packages=['freqtrade'],
scripts=['bin/freqtrade'], scripts=['bin/freqtrade'],
setup_requires=['pytest-runner'], setup_requires=['pytest-runner', 'numpy'],
tests_require=['pytest', 'pytest-mock', 'pytest-cov'], tests_require=['pytest', 'pytest-mock', 'pytest-cov'],
install_requires=[ install_requires=[
'ccxt', 'ccxt',