rebasing against develop

This commit is contained in:
Jean-Baptiste LE STANG
2018-01-07 21:34:42 +01:00
13 changed files with 454 additions and 177 deletions

View File

@@ -77,3 +77,40 @@ def test_no_log_if_loss_does_not_improve(mocker):
})
assert not logger.called
def test_fmin_best_results(mocker, caplog):
fmin_result = {
"adx": 1,
"adx-value": 15.0,
"fastd": 1,
"fastd-value": 40.0,
"green_candle": 1,
"mfi": 0,
"over_sar": 0,
"rsi": 1,
"rsi-value": 37.0,
"trigger": 2,
"uptrend_long_ema": 1,
"uptrend_short_ema": 0,
"uptrend_sma": 0
}
mocker.patch('freqtrade.optimize.hyperopt.MongoTrials', return_value=create_trials(mocker))
mocker.patch('freqtrade.optimize.preprocess')
mocker.patch('freqtrade.optimize.load_data')
mocker.patch('freqtrade.optimize.hyperopt.fmin', return_value=fmin_result)
args = mocker.Mock(epochs=1, config='config.json.example')
start(args)
exists = [
'Best parameters',
'"adx": {\n "enabled": true,\n "value": 15.0\n },',
'"green_candle": {\n "enabled": true\n },',
'"mfi": {\n "enabled": false\n },',
'"trigger": {\n "type": "ao_cross_zero"\n },'
]
for line in exists:
assert line in caplog.text

View File

@@ -167,6 +167,7 @@ def test_profit_handle(
mocker.patch.multiple('freqtrade.fiat_convert.Pymarketcap',
ticker=MagicMock(return_value={'price_usd': 15000.0}),
_cache_symbols=MagicMock(return_value={'BTC': 1}))
mocker.patch('freqtrade.fiat_convert.CryptoToFiatConverter._find_price', return_value=15000.0)
init(default_conf, create_engine('sqlite://'))
_profit(bot=MagicMock(), update=update)
@@ -422,6 +423,7 @@ def test_daily_handle(
mocker.patch.multiple('freqtrade.fiat_convert.Pymarketcap',
ticker=MagicMock(return_value={'price_usd': 15000.0}),
_cache_symbols=MagicMock(return_value={'BTC': 1}))
mocker.patch('freqtrade.fiat_convert.CryptoToFiatConverter._find_price', return_value=15000.0)
init(default_conf, create_engine('sqlite://'))
# Create some test data

View File

@@ -72,8 +72,11 @@ def test_fiat_convert_find_price(mocker):
with pytest.raises(ValueError, match=r'The fiat ABC is not supported.'):
fiat_convert._find_price(crypto_symbol='BTC', fiat_symbol='ABC')
mocker.patch('freqtrade.fiat_convert.CryptoToFiatConverter._find_price', return_value=12345.0)
assert fiat_convert.get_price(crypto_symbol='BTC', fiat_symbol='USD') == 12345.0
assert fiat_convert.get_price(crypto_symbol='btc', fiat_symbol='usd') == 12345.0
mocker.patch('freqtrade.fiat_convert.CryptoToFiatConverter._find_price', return_value=13000.2)
assert fiat_convert.get_price(crypto_symbol='BTC', fiat_symbol='EUR') == 13000.2
@@ -83,6 +86,7 @@ def test_fiat_convert_get_price(mocker):
'price_eur': 15000.0
})
mocker.patch('freqtrade.fiat_convert.Pymarketcap.ticker', api_mock)
mocker.patch('freqtrade.fiat_convert.CryptoToFiatConverter._find_price', return_value=28000.0)
fiat_convert = CryptoToFiatConverter()
@@ -109,3 +113,12 @@ def test_fiat_convert_get_price(mocker):
fiat_convert._pairs[0]._expiration = expiration
assert fiat_convert.get_price(crypto_symbol='BTC', fiat_symbol='USD') == 28000.0
assert fiat_convert._pairs[0]._expiration is not expiration
def test_fiat_convert_without_network(mocker):
Pymarketcap = MagicMock(side_effect=ImportError('Oh boy, you have no network!'))
mocker.patch('freqtrade.fiat_convert.Pymarketcap', Pymarketcap)
fiat_convert = CryptoToFiatConverter()
assert fiat_convert._coinmarketcap is None
assert fiat_convert._find_price(crypto_symbol='BTC', fiat_symbol='USD') == 0.0

View File

@@ -15,6 +15,39 @@ from freqtrade.main import create_trade, handle_trade, init, \
get_target_bid, _process, execute_sell, check_handle_timedout
from freqtrade.misc import get_state, State
from freqtrade.persistence import Trade
import freqtrade.main as main
# Test that main() can start backtesting or hyperopt.
# and also ensure we can pass some specific arguments
# argument parsing is done in test_misc.py
def test_parse_args_backtesting(mocker):
backtesting_mock = mocker.patch(
'freqtrade.optimize.backtesting.start', MagicMock())
with pytest.raises(SystemExit, match=r'0'):
main.main(['backtesting'])
assert backtesting_mock.call_count == 1
call_args = backtesting_mock.call_args[0][0]
assert call_args.config == 'config.json'
assert call_args.live is False
assert call_args.loglevel == 20
assert call_args.subparser == 'backtesting'
assert call_args.func is not None
assert call_args.ticker_interval == 5
def test_main_start_hyperopt(mocker):
hyperopt_mock = mocker.patch(
'freqtrade.optimize.hyperopt.start', MagicMock())
with pytest.raises(SystemExit, match=r'0'):
main.main(['hyperopt'])
assert hyperopt_mock.call_count == 1
call_args = hyperopt_mock.call_args[0][0]
assert call_args.config == 'config.json'
assert call_args.loglevel == 20
assert call_args.subparser == 'hyperopt'
assert call_args.func is not None
def test_process_trade_creation(default_conf, ticker, limit_buy_order, health, mocker):
@@ -331,7 +364,7 @@ def test_check_handle_timedout_buy(default_conf, ticker, health, limit_buy_order
cancel_order=cancel_order_mock)
init(default_conf, create_engine('sqlite://'))
tradeBuy = Trade(
trade_buy = Trade(
pair='BTC_ETH',
open_rate=0.00001099,
exchange='BITTREX',
@@ -343,12 +376,12 @@ def test_check_handle_timedout_buy(default_conf, ticker, health, limit_buy_order
is_open=True
)
Trade.session.add(tradeBuy)
Trade.session.add(trade_buy)
# check it does cancel buy orders over the time limit
check_handle_timedout(600)
assert cancel_order_mock.call_count == 1
trades = Trade.query.filter(Trade.open_order_id.is_(tradeBuy.open_order_id)).all()
trades = Trade.query.filter(Trade.open_order_id.is_(trade_buy.open_order_id)).all()
assert len(trades) == 0
@@ -363,7 +396,7 @@ def test_check_handle_timedout_sell(default_conf, ticker, health, limit_sell_ord
cancel_order=cancel_order_mock)
init(default_conf, create_engine('sqlite://'))
tradeSell = Trade(
trade_sell = Trade(
pair='BTC_ETH',
open_rate=0.00001099,
exchange='BITTREX',
@@ -376,12 +409,12 @@ def test_check_handle_timedout_sell(default_conf, ticker, health, limit_sell_ord
is_open=False
)
Trade.session.add(tradeSell)
Trade.session.add(trade_sell)
# check it does cancel sell orders over the time limit
check_handle_timedout(600)
assert cancel_order_mock.call_count == 1
assert tradeSell.is_open is True
assert trade_sell.is_open is True
def test_check_handle_timedout_partial(default_conf, ticker, limit_buy_order_old_partial,
@@ -396,7 +429,7 @@ def test_check_handle_timedout_partial(default_conf, ticker, limit_buy_order_old
cancel_order=cancel_order_mock)
init(default_conf, create_engine('sqlite://'))
tradeBuy = Trade(
trade_buy = Trade(
pair='BTC_ETH',
open_rate=0.00001099,
exchange='BITTREX',
@@ -408,16 +441,16 @@ def test_check_handle_timedout_partial(default_conf, ticker, limit_buy_order_old
is_open=True
)
Trade.session.add(tradeBuy)
Trade.session.add(trade_buy)
# check it does cancel buy orders over the time limit
# note this is for a partially-complete buy order
check_handle_timedout(600)
assert cancel_order_mock.call_count == 1
trades = Trade.query.filter(Trade.open_order_id.is_(tradeBuy.open_order_id)).all()
trades = Trade.query.filter(Trade.open_order_id.is_(trade_buy.open_order_id)).all()
assert len(trades) == 1
assert trades[0].amount == 23.0
assert trades[0].stake_amount == tradeBuy.open_rate * trades[0].amount
assert trades[0].stake_amount == trade_buy.open_rate * trades[0].amount
def test_balance_fully_ask_side(mocker):
@@ -537,10 +570,13 @@ def test_execute_sell_without_conf(default_conf, ticker, ticker_sell_up, mocker)
def test_sell_profit_only_enable_profit(default_conf, limit_buy_order, mocker):
default_conf['experimental'] = {}
default_conf['experimental']['sell_profit_only'] = True
default_conf['experimental'] = {
'use_sell_signal': True,
'sell_profit_only': True,
}
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.min_roi_reached', return_value=False)
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
mocker.patch.multiple('freqtrade.main.exchange',
@@ -561,10 +597,13 @@ def test_sell_profit_only_enable_profit(default_conf, limit_buy_order, mocker):
def test_sell_profit_only_disable_profit(default_conf, limit_buy_order, mocker):
default_conf['experimental'] = {}
default_conf['experimental']['sell_profit_only'] = False
default_conf['experimental'] = {
'use_sell_signal': True,
'sell_profit_only': False,
}
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.min_roi_reached', return_value=False)
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
mocker.patch.multiple('freqtrade.main.exchange',
@@ -585,10 +624,13 @@ def test_sell_profit_only_disable_profit(default_conf, limit_buy_order, mocker):
def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, mocker):
default_conf['experimental'] = {}
default_conf['experimental']['sell_profit_only'] = True
default_conf['experimental'] = {
'use_sell_signal': True,
'sell_profit_only': True,
}
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.min_roi_reached', return_value=False)
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
mocker.patch.multiple('freqtrade.main.exchange',
@@ -609,10 +651,13 @@ def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, mocker):
def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, mocker):
default_conf['experimental'] = {}
default_conf['experimental']['sell_profit_only'] = False
default_conf['experimental'] = {
'use_sell_signal': True,
'sell_profit_only': False,
}
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.min_roi_reached', return_value=False)
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
mocker.patch.multiple('freqtrade.main.exchange',

View File

@@ -1,13 +1,14 @@
# pragma pylint: disable=missing-docstring,C0103
import json
import time
import argparse
from copy import deepcopy
from unittest.mock import MagicMock
import pytest
from jsonschema import ValidationError
from freqtrade.misc import throttle, parse_args, load_config
from freqtrade.misc import throttle, parse_args, load_config,\
parse_args_common
def test_throttle():
@@ -38,89 +39,83 @@ def test_throttle_with_assets():
assert result == -1
# Parse common command-line-arguments
# used for all tools
def test_parse_args_none():
args = parse_args_common([], '')
assert isinstance(args, argparse.ArgumentParser)
def test_parse_args_defaults():
args = parse_args([])
assert args is not None
args = parse_args([], '')
assert args.config == 'config.json'
assert args.dynamic_whitelist is None
assert args.loglevel == 20
def test_parse_args_invalid():
with pytest.raises(SystemExit, match=r'2'):
parse_args(['-c'])
def test_parse_args_config():
args = parse_args(['-c', '/dev/null'])
assert args is not None
args = parse_args(['-c', '/dev/null'], '')
assert args.config == '/dev/null'
args = parse_args(['--config', '/dev/null'])
assert args is not None
args = parse_args(['--config', '/dev/null'], '')
assert args.config == '/dev/null'
def test_parse_args_verbose():
args = parse_args(['-v'])
assert args is not None
args = parse_args(['-v'], '')
assert args.loglevel == 10
args = parse_args(['--verbose'], '')
assert args.loglevel == 10
def test_parse_args_version():
with pytest.raises(SystemExit, match=r'0'):
parse_args(['--version'], '')
def test_parse_args_invalid():
with pytest.raises(SystemExit, match=r'2'):
parse_args(['-c'], '')
# Parse command-line-arguments
# used for main, backtesting and hyperopt
def test_parse_args_dynamic_whitelist():
args = parse_args(['--dynamic-whitelist'])
assert args is not None
args = parse_args(['--dynamic-whitelist'], '')
assert args.dynamic_whitelist is 20
def test_parse_args_dynamic_whitelist_10():
args = parse_args(['--dynamic-whitelist', '10'])
assert args is not None
args = parse_args(['--dynamic-whitelist', '10'], '')
assert args.dynamic_whitelist is 10
def test_parse_args_dynamic_whitelist_invalid_values():
with pytest.raises(SystemExit, match=r'2'):
parse_args(['--dynamic-whitelist', 'abc'])
def test_parse_args_backtesting(mocker):
backtesting_mock = mocker.patch(
'freqtrade.optimize.backtesting.start', MagicMock())
args = parse_args(['backtesting'])
assert args is None
assert backtesting_mock.call_count == 1
call_args = backtesting_mock.call_args[0][0]
assert call_args.config == 'config.json'
assert call_args.live is False
assert call_args.loglevel == 20
assert call_args.subparser == 'backtesting'
assert call_args.func is not None
assert call_args.ticker_interval == 5
parse_args(['--dynamic-whitelist', 'abc'], '')
def test_parse_args_backtesting_invalid():
with pytest.raises(SystemExit, match=r'2'):
parse_args(['backtesting --ticker-interval'])
parse_args(['backtesting --ticker-interval'], '')
with pytest.raises(SystemExit, match=r'2'):
parse_args(['backtesting --ticker-interval', 'abc'])
parse_args(['backtesting --ticker-interval', 'abc'], '')
def test_parse_args_backtesting_custom(mocker):
backtesting_mock = mocker.patch(
'freqtrade.optimize.backtesting.start', MagicMock())
args = parse_args([
def test_parse_args_backtesting_custom():
args = [
'-c', 'test_conf.json',
'backtesting',
'--live',
'--ticker-interval', '1',
'--refresh-pairs-cached'])
assert args is None
assert backtesting_mock.call_count == 1
call_args = backtesting_mock.call_args[0][0]
'--refresh-pairs-cached']
call_args = parse_args(args, '')
assert call_args.config == 'test_conf.json'
assert call_args.live is True
assert call_args.loglevel == 20
@@ -130,28 +125,9 @@ def test_parse_args_backtesting_custom(mocker):
assert call_args.refresh_pairs is True
def test_parse_args_hyperopt(mocker):
hyperopt_mock = mocker.patch(
'freqtrade.optimize.hyperopt.start', MagicMock())
args = parse_args(['hyperopt'])
assert args is None
assert hyperopt_mock.call_count == 1
call_args = hyperopt_mock.call_args[0][0]
assert call_args.config == 'config.json'
assert call_args.loglevel == 20
assert call_args.subparser == 'hyperopt'
assert call_args.func is not None
def test_parse_args_hyperopt_custom(mocker):
hyperopt_mock = mocker.patch(
'freqtrade.optimize.hyperopt.start', MagicMock())
args = parse_args(['-c', 'test_conf.json', 'hyperopt', '--epochs', '20'])
assert args is None
assert hyperopt_mock.call_count == 1
call_args = hyperopt_mock.call_args[0][0]
args = ['-c', 'test_conf.json', 'hyperopt', '--epochs', '20']
call_args = parse_args(args, '')
assert call_args.config == 'test_conf.json'
assert call_args.epochs == 20
assert call_args.loglevel == 20