Merge remote-tracking branch 'upstream/develop' into hyperopt-trailing-space
This commit is contained in:
@@ -325,7 +325,7 @@ def get_markets():
|
||||
},
|
||||
'price': 500000,
|
||||
'cost': {
|
||||
'min': 1,
|
||||
'min': 0.0001,
|
||||
'max': 500000,
|
||||
},
|
||||
},
|
||||
@@ -351,7 +351,7 @@ def get_markets():
|
||||
},
|
||||
'price': 500000,
|
||||
'cost': {
|
||||
'min': 1,
|
||||
'min': 0.0001,
|
||||
'max': 500000,
|
||||
},
|
||||
},
|
||||
@@ -376,7 +376,7 @@ def get_markets():
|
||||
},
|
||||
'price': 500000,
|
||||
'cost': {
|
||||
'min': 1,
|
||||
'min': 0.0001,
|
||||
'max': 500000,
|
||||
},
|
||||
},
|
||||
@@ -401,7 +401,7 @@ def get_markets():
|
||||
},
|
||||
'price': 500000,
|
||||
'cost': {
|
||||
'min': 1,
|
||||
'min': 0.0001,
|
||||
'max': 500000,
|
||||
},
|
||||
},
|
||||
@@ -426,7 +426,7 @@ def get_markets():
|
||||
},
|
||||
'price': 500000,
|
||||
'cost': {
|
||||
'min': 1,
|
||||
'min': 0.0001,
|
||||
'max': 500000,
|
||||
},
|
||||
},
|
||||
@@ -451,7 +451,7 @@ def get_markets():
|
||||
},
|
||||
'price': 500000,
|
||||
'cost': {
|
||||
'min': 1,
|
||||
'min': 0.0001,
|
||||
'max': 500000,
|
||||
},
|
||||
},
|
||||
@@ -479,7 +479,7 @@ def get_markets():
|
||||
'max': None
|
||||
},
|
||||
'cost': {
|
||||
'min': 0.001,
|
||||
'min': 0.0001,
|
||||
'max': None
|
||||
}
|
||||
},
|
||||
@@ -980,6 +980,28 @@ def tickers():
|
||||
'quoteVolume': 62.68220262,
|
||||
'info': {}
|
||||
},
|
||||
'BTC/USDT': {
|
||||
'symbol': 'BTC/USDT',
|
||||
'timestamp': 1573758371399,
|
||||
'datetime': '2019-11-14T19:06:11.399Z',
|
||||
'high': 8800.0,
|
||||
'low': 8582.6,
|
||||
'bid': 8648.16,
|
||||
'bidVolume': 0.238771,
|
||||
'ask': 8648.72,
|
||||
'askVolume': 0.016253,
|
||||
'vwap': 8683.13647806,
|
||||
'open': 8759.7,
|
||||
'close': 8648.72,
|
||||
'last': 8648.72,
|
||||
'previousClose': 8759.67,
|
||||
'change': -110.98,
|
||||
'percentage': -1.267,
|
||||
'average': None,
|
||||
'baseVolume': 35025.943355,
|
||||
'quoteVolume': 304135046.4242901,
|
||||
'info': {}
|
||||
},
|
||||
'ETH/USDT': {
|
||||
'symbol': 'ETH/USDT',
|
||||
'timestamp': 1522014804118,
|
||||
@@ -1067,7 +1089,29 @@ def tickers():
|
||||
'baseVolume': 59698.79897,
|
||||
'quoteVolume': 29132399.743954,
|
||||
'info': {}
|
||||
}
|
||||
},
|
||||
'XRP/BTC': {
|
||||
'symbol': 'XRP/BTC',
|
||||
'timestamp': 1573758257534,
|
||||
'datetime': '2019-11-14T19:04:17.534Z',
|
||||
'high': 3.126e-05,
|
||||
'low': 3.061e-05,
|
||||
'bid': 3.093e-05,
|
||||
'bidVolume': 27901.0,
|
||||
'ask': 3.095e-05,
|
||||
'askVolume': 10551.0,
|
||||
'vwap': 3.091e-05,
|
||||
'open': 3.119e-05,
|
||||
'close': 3.094e-05,
|
||||
'last': 3.094e-05,
|
||||
'previousClose': 3.117e-05,
|
||||
'change': -2.5e-07,
|
||||
'percentage': -0.802,
|
||||
'average': None,
|
||||
'baseVolume': 37334921.0,
|
||||
'quoteVolume': 1154.19266394,
|
||||
'info': {}
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -1317,8 +1361,8 @@ def rpc_balance():
|
||||
'used': 0.0
|
||||
},
|
||||
'XRP': {
|
||||
'total': 1.0,
|
||||
'free': 1.0,
|
||||
'total': 0.1,
|
||||
'free': 0.01,
|
||||
'used': 0.0
|
||||
},
|
||||
'EUR': {
|
||||
|
@@ -869,6 +869,7 @@ def test_backtest_start_multi_strat(default_conf, mocker, caplog, testdatadir):
|
||||
'backtesting',
|
||||
'--config', 'config.json',
|
||||
'--datadir', str(testdatadir),
|
||||
'--strategy-path', str(Path(__file__).parents[2] / 'freqtrade/templates'),
|
||||
'--ticker-interval', '1m',
|
||||
'--timerange', '1510694220-1510700340',
|
||||
'--enable-position-stacking',
|
||||
|
@@ -360,7 +360,7 @@ def test_log_results_if_loss_improves(hyperopt, capsys) -> None:
|
||||
hyperopt.log_results(
|
||||
{
|
||||
'loss': 1,
|
||||
'current_epoch': 1,
|
||||
'current_epoch': 2, # This starts from 1 (in a human-friendly manner)
|
||||
'results_explanation': 'foo.',
|
||||
'is_initial_point': False
|
||||
}
|
||||
@@ -374,6 +374,7 @@ def test_no_log_if_loss_does_not_improve(hyperopt, caplog) -> None:
|
||||
hyperopt.log_results(
|
||||
{
|
||||
'loss': 3,
|
||||
'current_epoch': 1,
|
||||
}
|
||||
)
|
||||
assert caplog.record_tuples == []
|
||||
@@ -382,13 +383,19 @@ def test_no_log_if_loss_does_not_improve(hyperopt, caplog) -> None:
|
||||
def test_save_trials_saves_trials(mocker, hyperopt, testdatadir, caplog) -> None:
|
||||
trials = create_trials(mocker, hyperopt, testdatadir)
|
||||
mock_dump = mocker.patch('freqtrade.optimize.hyperopt.dump', return_value=None)
|
||||
hyperopt.trials = trials
|
||||
hyperopt.save_trials()
|
||||
|
||||
trials_file = testdatadir / 'optimize' / 'ut_trials.pickle'
|
||||
assert log_has(f"Saving 1 evaluations to '{trials_file}'", caplog)
|
||||
|
||||
hyperopt.trials = trials
|
||||
hyperopt.save_trials(final=True)
|
||||
assert log_has("Saving 1 epoch.", caplog)
|
||||
assert log_has(f"1 epoch saved to '{trials_file}'.", caplog)
|
||||
mock_dump.assert_called_once()
|
||||
|
||||
hyperopt.trials = trials + trials
|
||||
hyperopt.save_trials(final=True)
|
||||
assert log_has("Saving 2 epochs.", caplog)
|
||||
assert log_has(f"2 epochs saved to '{trials_file}'.", caplog)
|
||||
|
||||
|
||||
def test_read_trials_returns_trials_file(mocker, hyperopt, testdatadir, caplog) -> None:
|
||||
trials = create_trials(mocker, hyperopt, testdatadir)
|
||||
|
@@ -100,7 +100,7 @@ def test_refresh_pairlist_dynamic(mocker, shitcoinmarkets, tickers, whitelist_co
|
||||
markets=PropertyMock(return_value=shitcoinmarkets),
|
||||
)
|
||||
# argument: use the whitelist dynamically by exchange-volume
|
||||
whitelist = ['ETH/BTC', 'TKN/BTC', 'LTC/BTC', 'HOT/BTC', 'FUEL/BTC']
|
||||
whitelist = ['ETH/BTC', 'TKN/BTC', 'LTC/BTC', 'XRP/BTC', 'HOT/BTC']
|
||||
bot.pairlists.refresh_pairlist()
|
||||
|
||||
assert whitelist == bot.pairlists.whitelist
|
||||
@@ -135,10 +135,10 @@ def test_VolumePairList_refresh_empty(mocker, markets_empty, whitelist_conf):
|
||||
|
||||
@pytest.mark.parametrize("pairlists,base_currency,whitelist_result", [
|
||||
([{"method": "VolumePairList", "number_assets": 5, "sort_key": "quoteVolume"}],
|
||||
"BTC", ['ETH/BTC', 'TKN/BTC', 'LTC/BTC', 'HOT/BTC', 'FUEL/BTC']),
|
||||
"BTC", ['ETH/BTC', 'TKN/BTC', 'LTC/BTC', 'XRP/BTC', 'HOT/BTC']),
|
||||
# Different sorting depending on quote or bid volume
|
||||
([{"method": "VolumePairList", "number_assets": 5, "sort_key": "bidVolume"}],
|
||||
"BTC", ['HOT/BTC', 'FUEL/BTC', 'LTC/BTC', 'TKN/BTC', 'ETH/BTC']),
|
||||
"BTC", ['HOT/BTC', 'FUEL/BTC', 'XRP/BTC', 'LTC/BTC', 'TKN/BTC']),
|
||||
([{"method": "VolumePairList", "number_assets": 5, "sort_key": "quoteVolume"}],
|
||||
"USDT", ['ETH/USDT']),
|
||||
# No pair for ETH ...
|
||||
@@ -146,19 +146,19 @@ def test_VolumePairList_refresh_empty(mocker, markets_empty, whitelist_conf):
|
||||
"ETH", []),
|
||||
# Precisionfilter and quote volume
|
||||
([{"method": "VolumePairList", "number_assets": 5, "sort_key": "quoteVolume"},
|
||||
{"method": "PrecisionFilter"}], "BTC", ['ETH/BTC', 'TKN/BTC', 'LTC/BTC', 'FUEL/BTC']),
|
||||
{"method": "PrecisionFilter"}], "BTC", ['ETH/BTC', 'TKN/BTC', 'LTC/BTC', 'XRP/BTC']),
|
||||
# Precisionfilter bid
|
||||
([{"method": "VolumePairList", "number_assets": 5, "sort_key": "bidVolume"},
|
||||
{"method": "PrecisionFilter"}], "BTC", ['FUEL/BTC', 'LTC/BTC', 'TKN/BTC', 'ETH/BTC']),
|
||||
{"method": "PrecisionFilter"}], "BTC", ['FUEL/BTC', 'XRP/BTC', 'LTC/BTC', 'TKN/BTC']),
|
||||
# PriceFilter and VolumePairList
|
||||
([{"method": "VolumePairList", "number_assets": 5, "sort_key": "quoteVolume"},
|
||||
{"method": "PriceFilter", "low_price_ratio": 0.03}],
|
||||
"BTC", ['ETH/BTC', 'TKN/BTC', 'LTC/BTC', 'FUEL/BTC']),
|
||||
"BTC", ['ETH/BTC', 'TKN/BTC', 'LTC/BTC', 'XRP/BTC']),
|
||||
# Hot is removed by precision_filter, Fuel by low_price_filter.
|
||||
([{"method": "VolumePairList", "number_assets": 5, "sort_key": "quoteVolume"},
|
||||
([{"method": "VolumePairList", "number_assets": 6, "sort_key": "quoteVolume"},
|
||||
{"method": "PrecisionFilter"},
|
||||
{"method": "PriceFilter", "low_price_ratio": 0.02}
|
||||
], "BTC", ['ETH/BTC', 'TKN/BTC', 'LTC/BTC']),
|
||||
], "BTC", ['ETH/BTC', 'TKN/BTC', 'LTC/BTC', 'XRP/BTC']),
|
||||
# StaticPairlist Only
|
||||
([{"method": "StaticPairList"},
|
||||
], "BTC", ['ETH/BTC', 'TKN/BTC']),
|
||||
@@ -285,12 +285,7 @@ def test_volumepairlist_caching(mocker, markets, whitelist_conf, tickers):
|
||||
|
||||
|
||||
def test_pairlistmanager_no_pairlist(mocker, markets, whitelist_conf, caplog):
|
||||
del whitelist_conf['pairlists'][0]['method']
|
||||
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
|
||||
with pytest.raises(OperationalException,
|
||||
match=r"No Pairlist defined!"):
|
||||
get_patched_freqtradebot(mocker, whitelist_conf)
|
||||
assert log_has_re("No method in .*", caplog)
|
||||
|
||||
whitelist_conf['pairlists'] = []
|
||||
|
||||
|
@@ -355,29 +355,18 @@ def test_rpc_balance_handle_error(default_conf, mocker):
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
get_balances=MagicMock(return_value=mock_balance),
|
||||
get_ticker=MagicMock(side_effect=TemporaryError('Could not load ticker due to xxx'))
|
||||
get_tickers=MagicMock(side_effect=TemporaryError('Could not load ticker due to xxx'))
|
||||
)
|
||||
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||
patch_get_signal(freqtradebot, (True, False))
|
||||
rpc = RPC(freqtradebot)
|
||||
rpc._fiat_converter = CryptoToFiatConverter()
|
||||
|
||||
result = rpc._rpc_balance(default_conf['fiat_display_currency'])
|
||||
assert prec_satoshi(result['total'], 12)
|
||||
assert prec_satoshi(result['value'], 180000)
|
||||
assert 'USD' == result['symbol']
|
||||
assert result['currencies'] == [{
|
||||
'currency': 'BTC',
|
||||
'free': 10.0,
|
||||
'balance': 12.0,
|
||||
'used': 2.0,
|
||||
'est_btc': 12.0,
|
||||
}]
|
||||
assert result['total'] == 12.0
|
||||
with pytest.raises(RPCException, match="Error getting current tickers."):
|
||||
rpc._rpc_balance(default_conf['stake_currency'], default_conf['fiat_display_currency'])
|
||||
|
||||
|
||||
def test_rpc_balance_handle(default_conf, mocker):
|
||||
def test_rpc_balance_handle(default_conf, mocker, tickers):
|
||||
mock_balance = {
|
||||
'BTC': {
|
||||
'free': 10.0,
|
||||
@@ -389,7 +378,7 @@ def test_rpc_balance_handle(default_conf, mocker):
|
||||
'total': 5.0,
|
||||
'used': 4.0,
|
||||
},
|
||||
'PAX': {
|
||||
'USDT': {
|
||||
'free': 5.0,
|
||||
'total': 10.0,
|
||||
'used': 5.0,
|
||||
@@ -405,10 +394,9 @@ def test_rpc_balance_handle(default_conf, mocker):
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
get_balances=MagicMock(return_value=mock_balance),
|
||||
get_ticker=MagicMock(
|
||||
side_effect=lambda p, r: {'bid': 100} if p == "BTC/PAX" else {'bid': 0.01}),
|
||||
get_tickers=tickers,
|
||||
get_valid_pair_combination=MagicMock(
|
||||
side_effect=lambda a, b: f"{b}/{a}" if a == "PAX" else f"{a}/{b}")
|
||||
side_effect=lambda a, b: f"{b}/{a}" if a == "USDT" else f"{a}/{b}")
|
||||
)
|
||||
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||
@@ -416,30 +404,35 @@ def test_rpc_balance_handle(default_conf, mocker):
|
||||
rpc = RPC(freqtradebot)
|
||||
rpc._fiat_converter = CryptoToFiatConverter()
|
||||
|
||||
result = rpc._rpc_balance(default_conf['fiat_display_currency'])
|
||||
assert prec_satoshi(result['total'], 12.15)
|
||||
assert prec_satoshi(result['value'], 182250)
|
||||
result = rpc._rpc_balance(default_conf['stake_currency'], default_conf['fiat_display_currency'])
|
||||
assert prec_satoshi(result['total'], 12.309096315)
|
||||
assert prec_satoshi(result['value'], 184636.44472997)
|
||||
assert 'USD' == result['symbol']
|
||||
assert result['currencies'] == [
|
||||
{'currency': 'BTC',
|
||||
'free': 10.0,
|
||||
'balance': 12.0,
|
||||
'used': 2.0,
|
||||
'est_btc': 12.0,
|
||||
'free': 10.0,
|
||||
'balance': 12.0,
|
||||
'used': 2.0,
|
||||
'est_stake': 12.0,
|
||||
'stake': 'BTC',
|
||||
},
|
||||
{'free': 1.0,
|
||||
'balance': 5.0,
|
||||
'currency': 'ETH',
|
||||
'est_btc': 0.05,
|
||||
'used': 4.0
|
||||
'est_stake': 0.30794,
|
||||
'used': 4.0,
|
||||
'stake': 'BTC',
|
||||
|
||||
},
|
||||
{'free': 5.0,
|
||||
'balance': 10.0,
|
||||
'currency': 'PAX',
|
||||
'est_btc': 0.1,
|
||||
'used': 5.0}
|
||||
'currency': 'USDT',
|
||||
'est_stake': 0.0011563153318162476,
|
||||
'used': 5.0,
|
||||
'stake': 'BTC',
|
||||
}
|
||||
]
|
||||
assert result['total'] == 12.15
|
||||
assert result['total'] == 12.309096315331816
|
||||
|
||||
|
||||
def test_rpc_start(mocker, default_conf) -> None:
|
||||
@@ -697,8 +690,8 @@ def test_rpcforcebuy(mocker, default_conf, ticker, fee, limit_buy_order) -> None
|
||||
pair = 'XRP/BTC'
|
||||
|
||||
# Test not buying
|
||||
default_conf['stake_amount'] = 0.0000001
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||
freqtradebot.config['stake_amount'] = 0.0000001
|
||||
patch_get_signal(freqtradebot, (True, False))
|
||||
rpc = RPC(freqtradebot)
|
||||
pair = 'TKN/BTC'
|
||||
|
@@ -23,7 +23,7 @@ _TEST_PASS = "SuperSecurePassword1!"
|
||||
def botclient(default_conf, mocker):
|
||||
default_conf.update({"api_server": {"enabled": True,
|
||||
"listen_ip_address": "127.0.0.1",
|
||||
"listen_port": "8080",
|
||||
"listen_port": 8080,
|
||||
"username": _TEST_USER,
|
||||
"password": _TEST_PASS,
|
||||
}})
|
||||
@@ -133,7 +133,10 @@ def test_api__init__(default_conf, mocker):
|
||||
def test_api_run(default_conf, mocker, caplog):
|
||||
default_conf.update({"api_server": {"enabled": True,
|
||||
"listen_ip_address": "127.0.0.1",
|
||||
"listen_port": "8080"}})
|
||||
"listen_port": 8080,
|
||||
"username": "TestUser",
|
||||
"password": "testPass",
|
||||
}})
|
||||
mocker.patch('freqtrade.rpc.telegram.Updater', MagicMock())
|
||||
mocker.patch('freqtrade.rpc.api_server.threading.Thread', MagicMock())
|
||||
|
||||
@@ -146,7 +149,7 @@ def test_api_run(default_conf, mocker, caplog):
|
||||
apiserver.run()
|
||||
assert server_mock.call_count == 1
|
||||
assert server_mock.call_args_list[0][0][0] == "127.0.0.1"
|
||||
assert server_mock.call_args_list[0][0][1] == "8080"
|
||||
assert server_mock.call_args_list[0][0][1] == 8080
|
||||
assert isinstance(server_mock.call_args_list[0][0][2], Flask)
|
||||
assert hasattr(apiserver, "srv")
|
||||
|
||||
@@ -158,14 +161,14 @@ def test_api_run(default_conf, mocker, caplog):
|
||||
server_mock.reset_mock()
|
||||
apiserver._config.update({"api_server": {"enabled": True,
|
||||
"listen_ip_address": "0.0.0.0",
|
||||
"listen_port": "8089",
|
||||
"listen_port": 8089,
|
||||
"password": "",
|
||||
}})
|
||||
apiserver.run()
|
||||
|
||||
assert server_mock.call_count == 1
|
||||
assert server_mock.call_args_list[0][0][0] == "0.0.0.0"
|
||||
assert server_mock.call_args_list[0][0][1] == "8089"
|
||||
assert server_mock.call_args_list[0][0][1] == 8089
|
||||
assert isinstance(server_mock.call_args_list[0][0][2], Flask)
|
||||
assert log_has("Starting HTTP Server at 0.0.0.0:8089", caplog)
|
||||
assert log_has("Starting Local Rest Server.", caplog)
|
||||
@@ -186,7 +189,10 @@ def test_api_run(default_conf, mocker, caplog):
|
||||
def test_api_cleanup(default_conf, mocker, caplog):
|
||||
default_conf.update({"api_server": {"enabled": True,
|
||||
"listen_ip_address": "127.0.0.1",
|
||||
"listen_port": "8080"}})
|
||||
"listen_port": 8080,
|
||||
"username": "TestUser",
|
||||
"password": "testPass",
|
||||
}})
|
||||
mocker.patch('freqtrade.rpc.telegram.Updater', MagicMock())
|
||||
mocker.patch('freqtrade.rpc.api_server.threading.Thread', MagicMock())
|
||||
mocker.patch('freqtrade.rpc.api_server.make_server', MagicMock())
|
||||
@@ -224,28 +230,10 @@ def test_api_stopbuy(botclient):
|
||||
def test_api_balance(botclient, mocker, rpc_balance):
|
||||
ftbot, client = botclient
|
||||
|
||||
def mock_ticker(symbol, refresh):
|
||||
if symbol == 'BTC/USDT':
|
||||
return {
|
||||
'bid': 10000.00,
|
||||
'ask': 10000.00,
|
||||
'last': 10000.00,
|
||||
}
|
||||
elif symbol == 'XRP/BTC':
|
||||
return {
|
||||
'bid': 0.00001,
|
||||
'ask': 0.00001,
|
||||
'last': 0.00001,
|
||||
}
|
||||
return {
|
||||
'bid': 0.1,
|
||||
'ask': 0.1,
|
||||
'last': 0.1,
|
||||
}
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_balances', return_value=rpc_balance)
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_ticker', side_effect=mock_ticker)
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_valid_pair_combination',
|
||||
side_effect=lambda a, b: f"{a}/{b}")
|
||||
ftbot.wallets.update()
|
||||
|
||||
rc = client_get(client, f"{BASE_URI}/balance")
|
||||
assert_response(rc)
|
||||
@@ -256,7 +244,8 @@ def test_api_balance(botclient, mocker, rpc_balance):
|
||||
'free': 12.0,
|
||||
'balance': 12.0,
|
||||
'used': 0.0,
|
||||
'est_btc': 12.0,
|
||||
'est_stake': 12.0,
|
||||
'stake': 'BTC',
|
||||
}
|
||||
|
||||
|
||||
|
@@ -173,7 +173,10 @@ def test_init_apiserver_enabled(mocker, default_conf, caplog) -> None:
|
||||
default_conf["telegram"]["enabled"] = False
|
||||
default_conf["api_server"] = {"enabled": True,
|
||||
"listen_ip_address": "127.0.0.1",
|
||||
"listen_port": "8080"}
|
||||
"listen_port": 8080,
|
||||
"username": "TestUser",
|
||||
"password": "TestPass",
|
||||
}
|
||||
rpc_manager = RPCManager(get_patched_freqtradebot(mocker, default_conf))
|
||||
|
||||
# Sleep to allow the thread to start
|
||||
|
@@ -144,9 +144,9 @@ def test_authorized_only_exception(default_conf, mocker, caplog) -> None:
|
||||
|
||||
|
||||
def test_status(default_conf, update, mocker, fee, ticker,) -> None:
|
||||
update.message.chat.id = 123
|
||||
update.message.chat.id = "123"
|
||||
default_conf['telegram']['enabled'] = False
|
||||
default_conf['telegram']['chat_id'] = 123
|
||||
default_conf['telegram']['chat_id'] = "123"
|
||||
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
@@ -461,29 +461,10 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
|
||||
assert '*Best Performing:* `ETH/BTC: 6.20%`' in msg_mock.call_args_list[-1][0][0]
|
||||
|
||||
|
||||
def test_telegram_balance_handle(default_conf, update, mocker, rpc_balance) -> None:
|
||||
|
||||
def mock_ticker(symbol, refresh):
|
||||
if symbol == 'BTC/USDT':
|
||||
return {
|
||||
'bid': 10000.00,
|
||||
'ask': 10000.00,
|
||||
'last': 10000.00,
|
||||
}
|
||||
elif symbol == 'XRP/BTC':
|
||||
return {
|
||||
'bid': 0.00001,
|
||||
'ask': 0.00001,
|
||||
'last': 0.00001,
|
||||
}
|
||||
return {
|
||||
'bid': 0.1,
|
||||
'ask': 0.1,
|
||||
'last': 0.1,
|
||||
}
|
||||
def test_telegram_balance_handle(default_conf, update, mocker, rpc_balance, tickers) -> None:
|
||||
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_balances', return_value=rpc_balance)
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_ticker', side_effect=mock_ticker)
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_tickers', tickers)
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_valid_pair_combination',
|
||||
side_effect=lambda a, b: f"{a}/{b}")
|
||||
|
||||
@@ -564,7 +545,8 @@ def test_balance_handle_too_large_response(default_conf, update, mocker) -> None
|
||||
'free': 1.0,
|
||||
'used': 0.5,
|
||||
'balance': i,
|
||||
'est_btc': 1
|
||||
'est_stake': 1,
|
||||
'stake': 'BTC',
|
||||
})
|
||||
mocker.patch('freqtrade.rpc.rpc.RPC._rpc_balance', return_value={
|
||||
'currencies': balances,
|
||||
|
@@ -113,7 +113,7 @@ def test_send_msg(default_conf, mocker):
|
||||
|
||||
def test_exception_send_msg(default_conf, mocker, caplog):
|
||||
default_conf["webhook"] = get_webhook_dict()
|
||||
default_conf["webhook"]["webhookbuy"] = None
|
||||
del default_conf["webhook"]["webhookbuy"]
|
||||
|
||||
webhook = Webhook(get_patched_freqtradebot(mocker, default_conf))
|
||||
webhook.send_msg({'type': RPCMessageType.BUY_NOTIFICATION})
|
||||
|
@@ -36,13 +36,15 @@ def test_search_strategy():
|
||||
|
||||
|
||||
def test_load_strategy(default_conf, result):
|
||||
default_conf.update({'strategy': 'SampleStrategy'})
|
||||
default_conf.update({'strategy': 'SampleStrategy',
|
||||
'strategy_path': str(Path(__file__).parents[2] / 'freqtrade/templates')
|
||||
})
|
||||
resolver = StrategyResolver(default_conf)
|
||||
assert 'rsi' in resolver.strategy.advise_indicators(result, {'pair': 'ETH/BTC'})
|
||||
|
||||
|
||||
def test_load_strategy_base64(result, caplog, default_conf):
|
||||
with open("user_data/strategies/sample_strategy.py", "rb") as file:
|
||||
with (Path(__file__).parents[2] / 'freqtrade/templates/sample_strategy.py').open("rb") as file:
|
||||
encoded_string = urlsafe_b64encode(file.read()).decode("utf-8")
|
||||
default_conf.update({'strategy': 'SampleStrategy:{}'.format(encoded_string)})
|
||||
|
||||
@@ -54,10 +56,10 @@ def test_load_strategy_base64(result, caplog, default_conf):
|
||||
|
||||
|
||||
def test_load_strategy_invalid_directory(result, caplog, default_conf):
|
||||
default_conf['strategy'] = 'SampleStrategy'
|
||||
default_conf['strategy'] = 'DefaultStrategy'
|
||||
resolver = StrategyResolver(default_conf)
|
||||
extra_dir = Path.cwd() / 'some/path'
|
||||
resolver._load_strategy('SampleStrategy', config=default_conf, extra_dir=extra_dir)
|
||||
resolver._load_strategy('DefaultStrategy', config=default_conf, extra_dir=extra_dir)
|
||||
|
||||
assert log_has_re(r'Path .*' + r'some.*path.*' + r'.* does not exist', caplog)
|
||||
|
||||
|
@@ -17,8 +17,6 @@ from freqtrade.configuration.config_validation import validate_config_schema
|
||||
from freqtrade.configuration.deprecated_settings import (
|
||||
check_conflicting_settings, process_deprecated_setting,
|
||||
process_temporary_deprecated_settings)
|
||||
from freqtrade.configuration.directory_operations import (create_datadir,
|
||||
create_userdata_dir)
|
||||
from freqtrade.configuration.load_config import load_config_file
|
||||
from freqtrade.constants import DEFAULT_DB_DRYRUN_URL, DEFAULT_DB_PROD_URL
|
||||
from freqtrade.loggers import _set_loggers
|
||||
@@ -42,10 +40,16 @@ def test_load_config_invalid_pair(default_conf) -> None:
|
||||
|
||||
|
||||
def test_load_config_missing_attributes(default_conf) -> None:
|
||||
default_conf.pop('exchange')
|
||||
conf = deepcopy(default_conf)
|
||||
conf.pop('exchange')
|
||||
|
||||
with pytest.raises(ValidationError, match=r".*'exchange' is a required property.*"):
|
||||
validate_config_schema(default_conf)
|
||||
validate_config_schema(conf)
|
||||
|
||||
conf = deepcopy(default_conf)
|
||||
conf.pop('stake_currency')
|
||||
with pytest.raises(ValidationError, match=r".*'stake_currency' is a required property.*"):
|
||||
validate_config_schema(conf)
|
||||
|
||||
|
||||
def test_load_config_incorrect_stake_amount(default_conf) -> None:
|
||||
@@ -102,7 +106,6 @@ def test_load_config_max_open_trades_zero(default_conf, mocker, caplog) -> None:
|
||||
|
||||
assert validated_conf['max_open_trades'] == 0
|
||||
assert 'internals' in validated_conf
|
||||
assert log_has('Validating configuration ...', caplog)
|
||||
|
||||
|
||||
def test_load_config_combine_dicts(default_conf, mocker, caplog) -> None:
|
||||
@@ -134,7 +137,6 @@ def test_load_config_combine_dicts(default_conf, mocker, caplog) -> None:
|
||||
assert validated_conf['exchange']['pair_whitelist'] == conf2['exchange']['pair_whitelist']
|
||||
|
||||
assert 'internals' in validated_conf
|
||||
assert log_has('Validating configuration ...', caplog)
|
||||
|
||||
|
||||
def test_from_config(default_conf, mocker, caplog) -> None:
|
||||
@@ -161,7 +163,6 @@ def test_from_config(default_conf, mocker, caplog) -> None:
|
||||
assert validated_conf['exchange']['pair_whitelist'] == conf2['exchange']['pair_whitelist']
|
||||
assert validated_conf['fiat_display_currency'] == "EUR"
|
||||
assert 'internals' in validated_conf
|
||||
assert log_has('Validating configuration ...', caplog)
|
||||
assert isinstance(validated_conf['user_data_dir'], Path)
|
||||
|
||||
|
||||
@@ -193,7 +194,6 @@ def test_load_config_max_open_trades_minus_one(default_conf, mocker, caplog) ->
|
||||
|
||||
assert validated_conf['max_open_trades'] > 999999999
|
||||
assert validated_conf['max_open_trades'] == float('inf')
|
||||
assert log_has('Validating configuration ...', caplog)
|
||||
assert "runmode" in validated_conf
|
||||
assert validated_conf['runmode'] == RunMode.DRY_RUN
|
||||
|
||||
@@ -670,45 +670,6 @@ def test_validate_default_conf(default_conf) -> None:
|
||||
validate(default_conf, constants.CONF_SCHEMA, Draft4Validator)
|
||||
|
||||
|
||||
def test_create_datadir(mocker, default_conf, caplog) -> None:
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(return_value=False))
|
||||
md = mocker.patch.object(Path, 'mkdir', MagicMock())
|
||||
|
||||
create_datadir(default_conf, '/foo/bar')
|
||||
assert md.call_args[1]['parents'] is True
|
||||
assert log_has('Created data directory: /foo/bar', caplog)
|
||||
|
||||
|
||||
def test_create_userdata_dir(mocker, default_conf, caplog) -> None:
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(return_value=False))
|
||||
md = mocker.patch.object(Path, 'mkdir', MagicMock())
|
||||
|
||||
x = create_userdata_dir('/tmp/bar', create_dir=True)
|
||||
assert md.call_count == 7
|
||||
assert md.call_args[1]['parents'] is False
|
||||
assert log_has(f'Created user-data directory: {Path("/tmp/bar")}', caplog)
|
||||
assert isinstance(x, Path)
|
||||
assert str(x) == str(Path("/tmp/bar"))
|
||||
|
||||
|
||||
def test_create_userdata_dir_exists(mocker, default_conf, caplog) -> None:
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(return_value=True))
|
||||
md = mocker.patch.object(Path, 'mkdir', MagicMock())
|
||||
|
||||
create_userdata_dir('/tmp/bar')
|
||||
assert md.call_count == 0
|
||||
|
||||
|
||||
def test_create_userdata_dir_exists_exception(mocker, default_conf, caplog) -> None:
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(return_value=False))
|
||||
md = mocker.patch.object(Path, 'mkdir', MagicMock())
|
||||
|
||||
with pytest.raises(OperationalException,
|
||||
match=r'Directory `.{1,2}tmp.{1,2}bar` does not exist.*'):
|
||||
create_userdata_dir('/tmp/bar', create_dir=False)
|
||||
assert md.call_count == 0
|
||||
|
||||
|
||||
def test_validate_tsl(default_conf):
|
||||
default_conf['stoploss'] = 0.0
|
||||
with pytest.raises(OperationalException, match='The config stoploss needs to be different '
|
||||
|
91
tests/test_directory_operations.py
Normal file
91
tests/test_directory_operations.py
Normal file
@@ -0,0 +1,91 @@
|
||||
# pragma pylint: disable=missing-docstring, protected-access, invalid-name
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from freqtrade import OperationalException
|
||||
from freqtrade.configuration.directory_operations import (copy_sample_files,
|
||||
create_datadir,
|
||||
create_userdata_dir)
|
||||
from tests.conftest import log_has, log_has_re
|
||||
|
||||
|
||||
def test_create_datadir(mocker, default_conf, caplog) -> None:
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(return_value=False))
|
||||
md = mocker.patch.object(Path, 'mkdir', MagicMock())
|
||||
|
||||
create_datadir(default_conf, '/foo/bar')
|
||||
assert md.call_args[1]['parents'] is True
|
||||
assert log_has('Created data directory: /foo/bar', caplog)
|
||||
|
||||
|
||||
def test_create_userdata_dir(mocker, default_conf, caplog) -> None:
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(return_value=False))
|
||||
md = mocker.patch.object(Path, 'mkdir', MagicMock())
|
||||
|
||||
x = create_userdata_dir('/tmp/bar', create_dir=True)
|
||||
assert md.call_count == 8
|
||||
assert md.call_args[1]['parents'] is False
|
||||
assert log_has(f'Created user-data directory: {Path("/tmp/bar")}', caplog)
|
||||
assert isinstance(x, Path)
|
||||
assert str(x) == str(Path("/tmp/bar"))
|
||||
|
||||
|
||||
def test_create_userdata_dir_exists(mocker, default_conf, caplog) -> None:
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(return_value=True))
|
||||
md = mocker.patch.object(Path, 'mkdir', MagicMock())
|
||||
|
||||
create_userdata_dir('/tmp/bar')
|
||||
assert md.call_count == 0
|
||||
|
||||
|
||||
def test_create_userdata_dir_exists_exception(mocker, default_conf, caplog) -> None:
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(return_value=False))
|
||||
md = mocker.patch.object(Path, 'mkdir', MagicMock())
|
||||
|
||||
with pytest.raises(OperationalException,
|
||||
match=r'Directory `.{1,2}tmp.{1,2}bar` does not exist.*'):
|
||||
create_userdata_dir('/tmp/bar', create_dir=False)
|
||||
assert md.call_count == 0
|
||||
|
||||
|
||||
def test_copy_sample_files(mocker, default_conf, caplog) -> None:
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(return_value=True))
|
||||
mocker.patch.object(Path, "exists", MagicMock(return_value=False))
|
||||
copymock = mocker.patch('shutil.copy', MagicMock())
|
||||
|
||||
copy_sample_files(Path('/tmp/bar'))
|
||||
assert copymock.call_count == 5
|
||||
assert copymock.call_args_list[0][0][1] == str(
|
||||
Path('/tmp/bar') / 'strategies/sample_strategy.py')
|
||||
assert copymock.call_args_list[1][0][1] == str(
|
||||
Path('/tmp/bar') / 'hyperopts/sample_hyperopt_advanced.py')
|
||||
assert copymock.call_args_list[2][0][1] == str(
|
||||
Path('/tmp/bar') / 'hyperopts/sample_hyperopt_loss.py')
|
||||
assert copymock.call_args_list[3][0][1] == str(
|
||||
Path('/tmp/bar') / 'hyperopts/sample_hyperopt.py')
|
||||
assert copymock.call_args_list[4][0][1] == str(
|
||||
Path('/tmp/bar') / 'notebooks/strategy_analysis_example.ipynb')
|
||||
|
||||
|
||||
def test_copy_sample_files_errors(mocker, default_conf, caplog) -> None:
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(return_value=False))
|
||||
mocker.patch.object(Path, "exists", MagicMock(return_value=False))
|
||||
mocker.patch('shutil.copy', MagicMock())
|
||||
with pytest.raises(OperationalException,
|
||||
match=r"Directory `.{1,2}tmp.{1,2}bar` does not exist\."):
|
||||
copy_sample_files(Path('/tmp/bar'))
|
||||
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(side_effect=[True, False]))
|
||||
|
||||
with pytest.raises(OperationalException,
|
||||
match=r"Directory `.{1,2}tmp.{1,2}bar.{1,2}strategies` does not exist\."):
|
||||
copy_sample_files(Path('/tmp/bar'))
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(return_value=True))
|
||||
mocker.patch.object(Path, "exists", MagicMock(return_value=True))
|
||||
copy_sample_files(Path('/tmp/bar'))
|
||||
assert log_has_re(r"File `.*` exists already, not deploying sample file\.", caplog)
|
||||
caplog.clear()
|
||||
copy_sample_files(Path('/tmp/bar'), overwrite=True)
|
||||
assert log_has_re(r"File `.*` exists already, overwriting\.", caplog)
|
@@ -299,7 +299,7 @@ def test_total_open_trades_stakes(mocker, default_conf, ticker,
|
||||
limit_buy_order, fee) -> None:
|
||||
patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
default_conf['stake_amount'] = 0.0000098751
|
||||
default_conf['stake_amount'] = 0.00098751
|
||||
default_conf['max_open_trades'] = 2
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
@@ -313,7 +313,7 @@ def test_total_open_trades_stakes(mocker, default_conf, ticker,
|
||||
trade = Trade.query.first()
|
||||
|
||||
assert trade is not None
|
||||
assert trade.stake_amount == 0.0000098751
|
||||
assert trade.stake_amount == 0.00098751
|
||||
assert trade.is_open
|
||||
assert trade.open_date is not None
|
||||
|
||||
@@ -321,11 +321,11 @@ def test_total_open_trades_stakes(mocker, default_conf, ticker,
|
||||
trade = Trade.query.order_by(Trade.id.desc()).first()
|
||||
|
||||
assert trade is not None
|
||||
assert trade.stake_amount == 0.0000098751
|
||||
assert trade.stake_amount == 0.00098751
|
||||
assert trade.is_open
|
||||
assert trade.open_date is not None
|
||||
|
||||
assert Trade.total_open_trades_stakes() == 1.97502e-05
|
||||
assert Trade.total_open_trades_stakes() == 1.97502e-03
|
||||
|
||||
|
||||
def test_get_min_pair_stake_amount(mocker, default_conf) -> None:
|
||||
@@ -334,6 +334,7 @@ def test_get_min_pair_stake_amount(mocker, default_conf) -> None:
|
||||
freqtrade = FreqtradeBot(default_conf)
|
||||
freqtrade.strategy.stoploss = -0.05
|
||||
markets = {'ETH/BTC': {'symbol': 'ETH/BTC'}}
|
||||
|
||||
# no pair found
|
||||
mocker.patch(
|
||||
'freqtrade.exchange.Exchange.markets',
|
||||
@@ -425,7 +426,7 @@ def test_get_min_pair_stake_amount(mocker, default_conf) -> None:
|
||||
PropertyMock(return_value=markets)
|
||||
)
|
||||
result = freqtrade._get_min_pair_stake_amount('ETH/BTC', 2)
|
||||
assert result == min(2, 2 * 2) / 0.9
|
||||
assert result == max(2, 2 * 2) / 0.9
|
||||
|
||||
# min amount and cost are set (amount is minial)
|
||||
markets["ETH/BTC"]["limits"] = {
|
||||
@@ -437,7 +438,27 @@ def test_get_min_pair_stake_amount(mocker, default_conf) -> None:
|
||||
PropertyMock(return_value=markets)
|
||||
)
|
||||
result = freqtrade._get_min_pair_stake_amount('ETH/BTC', 2)
|
||||
assert result == min(8, 2 * 2) / 0.9
|
||||
assert result == max(8, 2 * 2) / 0.9
|
||||
|
||||
|
||||
def test_get_min_pair_stake_amount_real_data(mocker, default_conf) -> None:
|
||||
patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
freqtrade = FreqtradeBot(default_conf)
|
||||
freqtrade.strategy.stoploss = -0.05
|
||||
markets = {'ETH/BTC': {'symbol': 'ETH/BTC'}}
|
||||
|
||||
# Real Binance data
|
||||
markets["ETH/BTC"]["limits"] = {
|
||||
'cost': {'min': 0.0001},
|
||||
'amount': {'min': 0.001}
|
||||
}
|
||||
mocker.patch(
|
||||
'freqtrade.exchange.Exchange.markets',
|
||||
PropertyMock(return_value=markets)
|
||||
)
|
||||
result = freqtrade._get_min_pair_stake_amount('ETH/BTC', 0.020405)
|
||||
assert round(result, 8) == round(max(0.0001, 0.001 * 0.020405) / 0.9, 8)
|
||||
|
||||
|
||||
def test_create_trades(default_conf, ticker, limit_buy_order, fee, mocker) -> None:
|
||||
@@ -522,8 +543,9 @@ def test_create_trades_too_small_stake_amount(default_conf, ticker, limit_buy_or
|
||||
get_fee=fee,
|
||||
)
|
||||
|
||||
default_conf['stake_amount'] = 0.000000005
|
||||
freqtrade = FreqtradeBot(default_conf)
|
||||
freqtrade.config['stake_amount'] = 0.000000005
|
||||
|
||||
patch_get_signal(freqtrade)
|
||||
|
||||
assert not freqtrade.create_trades()
|
||||
|
@@ -212,9 +212,9 @@ def test_generate_plot_file(mocker, caplog):
|
||||
fig = generate_empty_figure()
|
||||
plot_mock = mocker.patch("freqtrade.plot.plotting.plot", MagicMock())
|
||||
store_plot_file(fig, filename="freqtrade-plot-UNITTEST_BTC-5m.html",
|
||||
directory=Path("user_data/plots"))
|
||||
directory=Path("user_data/plot"))
|
||||
|
||||
expected_fn = str(Path("user_data/plots/freqtrade-plot-UNITTEST_BTC-5m.html"))
|
||||
expected_fn = str(Path("user_data/plot/freqtrade-plot-UNITTEST_BTC-5m.html"))
|
||||
assert plot_mock.call_count == 1
|
||||
assert plot_mock.call_args[0][0] == fig
|
||||
assert (plot_mock.call_args_list[0][1]['filename']
|
||||
|
@@ -9,8 +9,9 @@ from freqtrade.state import RunMode
|
||||
from freqtrade.utils import (setup_utils_configuration, start_create_userdir,
|
||||
start_download_data, start_list_exchanges,
|
||||
start_list_markets, start_list_timeframes,
|
||||
start_new_hyperopt, start_new_strategy,
|
||||
start_trading)
|
||||
from tests.conftest import get_args, log_has, patch_exchange
|
||||
from tests.conftest import get_args, log_has, log_has_re, patch_exchange
|
||||
|
||||
|
||||
def test_setup_utils_configuration():
|
||||
@@ -442,6 +443,7 @@ def test_create_datadir_failed(caplog):
|
||||
|
||||
def test_create_datadir(caplog, mocker):
|
||||
cud = mocker.patch("freqtrade.utils.create_userdata_dir", MagicMock())
|
||||
csf = mocker.patch("freqtrade.utils.copy_sample_files", MagicMock())
|
||||
args = [
|
||||
"create-userdir",
|
||||
"--userdir",
|
||||
@@ -450,9 +452,82 @@ def test_create_datadir(caplog, mocker):
|
||||
start_create_userdir(get_args(args))
|
||||
|
||||
assert cud.call_count == 1
|
||||
assert csf.call_count == 1
|
||||
assert len(caplog.record_tuples) == 0
|
||||
|
||||
|
||||
def test_start_new_strategy(mocker, caplog):
|
||||
wt_mock = mocker.patch.object(Path, "write_text", MagicMock())
|
||||
mocker.patch.object(Path, "exists", MagicMock(return_value=False))
|
||||
|
||||
args = [
|
||||
"new-strategy",
|
||||
"--strategy",
|
||||
"CoolNewStrategy"
|
||||
]
|
||||
start_new_strategy(get_args(args))
|
||||
|
||||
assert wt_mock.call_count == 1
|
||||
assert "CoolNewStrategy" in wt_mock.call_args_list[0][0][0]
|
||||
assert log_has_re("Writing strategy to .*", caplog)
|
||||
|
||||
|
||||
def test_start_new_strategy_DefaultStrat(mocker, caplog):
|
||||
args = [
|
||||
"new-strategy",
|
||||
"--strategy",
|
||||
"DefaultStrategy"
|
||||
]
|
||||
with pytest.raises(OperationalException,
|
||||
match=r"DefaultStrategy is not allowed as name\."):
|
||||
start_new_strategy(get_args(args))
|
||||
|
||||
|
||||
def test_start_new_strategy_no_arg(mocker, caplog):
|
||||
args = [
|
||||
"new-strategy",
|
||||
]
|
||||
with pytest.raises(OperationalException,
|
||||
match="`new-strategy` requires --strategy to be set."):
|
||||
start_new_strategy(get_args(args))
|
||||
|
||||
|
||||
def test_start_new_hyperopt(mocker, caplog):
|
||||
wt_mock = mocker.patch.object(Path, "write_text", MagicMock())
|
||||
mocker.patch.object(Path, "exists", MagicMock(return_value=False))
|
||||
|
||||
args = [
|
||||
"new-hyperopt",
|
||||
"--hyperopt",
|
||||
"CoolNewhyperopt"
|
||||
]
|
||||
start_new_hyperopt(get_args(args))
|
||||
|
||||
assert wt_mock.call_count == 1
|
||||
assert "CoolNewhyperopt" in wt_mock.call_args_list[0][0][0]
|
||||
assert log_has_re("Writing hyperopt to .*", caplog)
|
||||
|
||||
|
||||
def test_start_new_hyperopt_DefaultHyperopt(mocker, caplog):
|
||||
args = [
|
||||
"new-hyperopt",
|
||||
"--hyperopt",
|
||||
"DefaultHyperopt"
|
||||
]
|
||||
with pytest.raises(OperationalException,
|
||||
match=r"DefaultHyperopt is not allowed as name\."):
|
||||
start_new_hyperopt(get_args(args))
|
||||
|
||||
|
||||
def test_start_new_hyperopt_no_arg(mocker, caplog):
|
||||
args = [
|
||||
"new-hyperopt",
|
||||
]
|
||||
with pytest.raises(OperationalException,
|
||||
match="`new-hyperopt` requires --hyperopt to be set."):
|
||||
start_new_hyperopt(get_args(args))
|
||||
|
||||
|
||||
def test_download_data_keyboardInterrupt(mocker, caplog, markets):
|
||||
dl_mock = mocker.patch('freqtrade.utils.refresh_backtest_ohlcv_data',
|
||||
MagicMock(side_effect=KeyboardInterrupt))
|
||||
|
Reference in New Issue
Block a user