Merge branch 'develop' into timeframe

This commit is contained in:
Matthias
2020-06-15 06:35:55 +02:00
47 changed files with 893 additions and 367 deletions

View File

@@ -1590,6 +1590,7 @@ def buy_order_fee():
'datetime': str(arrow.utcnow().shift(minutes=-601).datetime),
'price': 0.245441,
'amount': 8.0,
'cost': 1.963528,
'remaining': 90.99181073,
'status': 'closed',
'fee': None

View File

@@ -47,7 +47,7 @@ def test_load_trades_from_db(default_conf, fee, mocker):
assert isinstance(trades, DataFrame)
assert "pair" in trades.columns
assert "open_time" in trades.columns
assert "profitperc" in trades.columns
assert "profit_percent" in trades.columns
for col in BT_DATA_COLUMNS:
if col not in ['index', 'open_at_end']:

View File

@@ -25,7 +25,7 @@ from freqtrade.resolvers.exchange_resolver import ExchangeResolver
from tests.conftest import get_patched_exchange, log_has, log_has_re
# Make sure to always keep one exchange here which is NOT subclassed!!
EXCHANGES = ['bittrex', 'binance', 'kraken', ]
EXCHANGES = ['bittrex', 'binance', 'kraken', 'ftx']
# Source: https://stackoverflow.com/questions/29881236/how-to-mock-asyncio-coroutines
@@ -352,7 +352,7 @@ def test__load_markets(default_conf, mocker, caplog):
assert ex.markets == expected_return
def test__reload_markets(default_conf, mocker, caplog):
def test_reload_markets(default_conf, mocker, caplog):
caplog.set_level(logging.DEBUG)
initial_markets = {'ETH/BTC': {}}
@@ -371,17 +371,17 @@ def test__reload_markets(default_conf, mocker, caplog):
assert exchange.markets == initial_markets
# less than 10 minutes have passed, no reload
exchange._reload_markets()
exchange.reload_markets()
assert exchange.markets == initial_markets
# more than 10 minutes have passed, reload is executed
exchange._last_markets_refresh = arrow.utcnow().timestamp - 15 * 60
exchange._reload_markets()
exchange.reload_markets()
assert exchange.markets == updated_markets
assert log_has('Performing scheduled market reload..', caplog)
def test__reload_markets_exception(default_conf, mocker, caplog):
def test_reload_markets_exception(default_conf, mocker, caplog):
caplog.set_level(logging.DEBUG)
api_mock = MagicMock()
@@ -390,7 +390,7 @@ def test__reload_markets_exception(default_conf, mocker, caplog):
exchange = get_patched_exchange(mocker, default_conf, api_mock, id="binance")
# less than 10 minutes have passed, no reload
exchange._reload_markets()
exchange.reload_markets()
assert exchange._last_markets_refresh == 0
assert log_has_re(r"Could not reload markets.*", caplog)
@@ -1258,7 +1258,8 @@ def test_get_historic_ohlcv(default_conf, mocker, caplog, exchange_name):
exchange._async_get_candle_history = Mock(wraps=mock_candle_hist)
# one_call calculation * 1.8 should do 2 calls
since = 5 * 60 * 500 * 1.8
since = 5 * 60 * exchange._ft_has['ohlcv_candle_limit'] * 1.8
ret = exchange.get_historic_ohlcv(pair, "5m", int((arrow.utcnow().timestamp - since) * 1000))
assert exchange._async_get_candle_history.call_count == 2
@@ -1733,6 +1734,7 @@ def test_cancel_order_dry_run(default_conf, mocker, exchange_name):
default_conf['dry_run'] = True
exchange = get_patched_exchange(mocker, default_conf, id=exchange_name)
assert exchange.cancel_order(order_id='123', pair='TKN/BTC') == {}
assert exchange.cancel_stoploss_order(order_id='123', pair='TKN/BTC') == {}
@pytest.mark.parametrize("exchange_name", EXCHANGES)
@@ -1817,6 +1819,25 @@ def test_cancel_order(default_conf, mocker, exchange_name):
order_id='_', pair='TKN/BTC')
@pytest.mark.parametrize("exchange_name", EXCHANGES)
def test_cancel_stoploss_order(default_conf, mocker, exchange_name):
default_conf['dry_run'] = False
api_mock = MagicMock()
api_mock.cancel_order = MagicMock(return_value=123)
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
assert exchange.cancel_stoploss_order(order_id='_', pair='TKN/BTC') == 123
with pytest.raises(InvalidOrderException):
api_mock.cancel_order = MagicMock(side_effect=ccxt.InvalidOrder("Did not find order"))
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
exchange.cancel_stoploss_order(order_id='_', pair='TKN/BTC')
assert api_mock.cancel_order.call_count == 1
ccxt_exceptionhandlers(mocker, default_conf, api_mock, exchange_name,
"cancel_stoploss_order", "cancel_order",
order_id='_', pair='TKN/BTC')
@pytest.mark.parametrize("exchange_name", EXCHANGES)
def test_get_order(default_conf, mocker, exchange_name):
default_conf['dry_run'] = True
@@ -1846,6 +1867,38 @@ def test_get_order(default_conf, mocker, exchange_name):
order_id='_', pair='TKN/BTC')
@pytest.mark.parametrize("exchange_name", EXCHANGES)
def test_get_stoploss_order(default_conf, mocker, exchange_name):
# Don't test FTX here - that needs a seperate test
if exchange_name == 'ftx':
return
default_conf['dry_run'] = True
order = MagicMock()
order.myid = 123
exchange = get_patched_exchange(mocker, default_conf, id=exchange_name)
exchange._dry_run_open_orders['X'] = order
assert exchange.get_stoploss_order('X', 'TKN/BTC').myid == 123
with pytest.raises(InvalidOrderException, match=r'Tried to get an invalid dry-run-order.*'):
exchange.get_stoploss_order('Y', 'TKN/BTC')
default_conf['dry_run'] = False
api_mock = MagicMock()
api_mock.fetch_order = MagicMock(return_value=456)
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
assert exchange.get_stoploss_order('X', 'TKN/BTC') == 456
with pytest.raises(InvalidOrderException):
api_mock.fetch_order = MagicMock(side_effect=ccxt.InvalidOrder("Order not found"))
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
exchange.get_stoploss_order(order_id='_', pair='TKN/BTC')
assert api_mock.fetch_order.call_count == 1
ccxt_exceptionhandlers(mocker, default_conf, api_mock, exchange_name,
'get_stoploss_order', 'fetch_order',
order_id='_', pair='TKN/BTC')
@pytest.mark.parametrize("exchange_name", EXCHANGES)
def test_name(default_conf, mocker, exchange_name):
exchange = get_patched_exchange(mocker, default_conf, id=exchange_name)
@@ -2192,12 +2245,18 @@ def test_extract_cost_curr_rate(mocker, default_conf, order, expected) -> None:
'fee': {'currency': 'NEO', 'cost': 0.0012}}, 0.001944),
({'symbol': 'ETH/BTC', 'amount': 2.21, 'cost': 0.02992561,
'fee': {'currency': 'NEO', 'cost': 0.00027452}}, 0.00074305),
# TODO: More tests here!
# Rate included in return - return as is
({'symbol': 'ETH/BTC', 'amount': 0.04, 'cost': 0.05,
'fee': {'currency': 'USDT', 'cost': 0.34, 'rate': 0.01}}, 0.01),
({'symbol': 'ETH/BTC', 'amount': 0.04, 'cost': 0.05,
'fee': {'currency': 'USDT', 'cost': 0.34, 'rate': 0.005}}, 0.005),
# 0.1% filled - no costs (kraken - #3431)
({'symbol': 'ETH/BTC', 'amount': 0.04, 'cost': 0.0,
'fee': {'currency': 'BTC', 'cost': 0.0, 'rate': None}}, None),
({'symbol': 'ETH/BTC', 'amount': 0.04, 'cost': 0.0,
'fee': {'currency': 'ETH', 'cost': 0.0, 'rate': None}}, 0.0),
({'symbol': 'ETH/BTC', 'amount': 0.04, 'cost': 0.0,
'fee': {'currency': 'NEO', 'cost': 0.0, 'rate': None}}, None),
])
def test_calculate_fee_rate(mocker, default_conf, order, expected) -> None:
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', return_value={'last': 0.081})

163
tests/exchange/test_ftx.py Normal file
View File

@@ -0,0 +1,163 @@
# pragma pylint: disable=missing-docstring, C0103, bad-continuation, global-statement
# pragma pylint: disable=protected-access
from random import randint
from unittest.mock import MagicMock
import ccxt
import pytest
from freqtrade.exceptions import (DependencyException, InvalidOrderException,
OperationalException, TemporaryError)
from tests.conftest import get_patched_exchange
from .test_exchange import ccxt_exceptionhandlers
STOPLOSS_ORDERTYPE = 'stop'
def test_stoploss_order_ftx(default_conf, mocker):
api_mock = MagicMock()
order_id = 'test_prod_buy_{}'.format(randint(0, 10 ** 6))
api_mock.create_order = MagicMock(return_value={
'id': order_id,
'info': {
'foo': 'bar'
}
})
default_conf['dry_run'] = False
mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y)
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'ftx')
# stoploss_on_exchange_limit_ratio is irrelevant for ftx market orders
order = exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=190,
order_types={'stoploss_on_exchange_limit_ratio': 1.05})
assert api_mock.create_order.call_args_list[0][1]['symbol'] == 'ETH/BTC'
assert api_mock.create_order.call_args_list[0][1]['type'] == STOPLOSS_ORDERTYPE
assert api_mock.create_order.call_args_list[0][1]['side'] == 'sell'
assert api_mock.create_order.call_args_list[0][1]['amount'] == 1
assert api_mock.create_order.call_args_list[0][1]['price'] == 190
assert 'orderPrice' not in api_mock.create_order.call_args_list[0][1]['params']
assert api_mock.create_order.call_count == 1
api_mock.create_order.reset_mock()
order = exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
assert 'id' in order
assert 'info' in order
assert order['id'] == order_id
assert api_mock.create_order.call_args_list[0][1]['symbol'] == 'ETH/BTC'
assert api_mock.create_order.call_args_list[0][1]['type'] == STOPLOSS_ORDERTYPE
assert api_mock.create_order.call_args_list[0][1]['side'] == 'sell'
assert api_mock.create_order.call_args_list[0][1]['amount'] == 1
assert api_mock.create_order.call_args_list[0][1]['price'] == 220
assert 'orderPrice' not in api_mock.create_order.call_args_list[0][1]['params']
api_mock.create_order.reset_mock()
order = exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220,
order_types={'stoploss': 'limit'})
assert 'id' in order
assert 'info' in order
assert order['id'] == order_id
assert api_mock.create_order.call_args_list[0][1]['symbol'] == 'ETH/BTC'
assert api_mock.create_order.call_args_list[0][1]['type'] == STOPLOSS_ORDERTYPE
assert api_mock.create_order.call_args_list[0][1]['side'] == 'sell'
assert api_mock.create_order.call_args_list[0][1]['amount'] == 1
assert api_mock.create_order.call_args_list[0][1]['price'] == 220
assert 'orderPrice' in api_mock.create_order.call_args_list[0][1]['params']
assert api_mock.create_order.call_args_list[0][1]['params']['orderPrice'] == 217.8
# test exception handling
with pytest.raises(DependencyException):
api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds("0 balance"))
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'ftx')
exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
with pytest.raises(InvalidOrderException):
api_mock.create_order = MagicMock(
side_effect=ccxt.InvalidOrder("ftx Order would trigger immediately."))
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'ftx')
exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
with pytest.raises(TemporaryError):
api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError("No connection"))
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'ftx')
exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
with pytest.raises(OperationalException, match=r".*DeadBeef.*"):
api_mock.create_order = MagicMock(side_effect=ccxt.BaseError("DeadBeef"))
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'ftx')
exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
def test_stoploss_order_dry_run_ftx(default_conf, mocker):
api_mock = MagicMock()
default_conf['dry_run'] = True
mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y)
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'ftx')
api_mock.create_order.reset_mock()
order = exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
assert 'id' in order
assert 'info' in order
assert 'type' in order
assert order['type'] == STOPLOSS_ORDERTYPE
assert order['price'] == 220
assert order['amount'] == 1
def test_stoploss_adjust_ftx(mocker, default_conf):
exchange = get_patched_exchange(mocker, default_conf, id='ftx')
order = {
'type': STOPLOSS_ORDERTYPE,
'price': 1500,
}
assert exchange.stoploss_adjust(1501, order)
assert not exchange.stoploss_adjust(1499, order)
# Test with invalid order case ...
order['type'] = 'stop_loss_limit'
assert not exchange.stoploss_adjust(1501, order)
def test_get_stoploss_order(default_conf, mocker):
default_conf['dry_run'] = True
order = MagicMock()
order.myid = 123
exchange = get_patched_exchange(mocker, default_conf, id='ftx')
exchange._dry_run_open_orders['X'] = order
assert exchange.get_stoploss_order('X', 'TKN/BTC').myid == 123
with pytest.raises(InvalidOrderException, match=r'Tried to get an invalid dry-run-order.*'):
exchange.get_stoploss_order('Y', 'TKN/BTC')
default_conf['dry_run'] = False
api_mock = MagicMock()
api_mock.fetch_orders = MagicMock(return_value=[{'id': 'X', 'status': '456'}])
exchange = get_patched_exchange(mocker, default_conf, api_mock, id='ftx')
assert exchange.get_stoploss_order('X', 'TKN/BTC')['status'] == '456'
api_mock.fetch_orders = MagicMock(return_value=[{'id': 'Y', 'status': '456'}])
exchange = get_patched_exchange(mocker, default_conf, api_mock, id='ftx')
with pytest.raises(InvalidOrderException, match=r"Could not get stoploss order for id X"):
exchange.get_stoploss_order('X', 'TKN/BTC')['status']
with pytest.raises(InvalidOrderException):
api_mock.fetch_orders = MagicMock(side_effect=ccxt.InvalidOrder("Order not found"))
exchange = get_patched_exchange(mocker, default_conf, api_mock, id='ftx')
exchange.get_stoploss_order(order_id='_', pair='TKN/BTC')
assert api_mock.fetch_orders.call_count == 1
ccxt_exceptionhandlers(mocker, default_conf, api_mock, 'ftx',
'get_stoploss_order', 'fetch_orders',
order_id='_', pair='TKN/BTC')

View File

@@ -11,6 +11,8 @@ from freqtrade.exceptions import (DependencyException, InvalidOrderException,
from tests.conftest import get_patched_exchange
from tests.exchange.test_exchange import ccxt_exceptionhandlers
STOPLOSS_ORDERTYPE = 'stop-loss'
def test_buy_kraken_trading_agreement(default_conf, mocker):
api_mock = MagicMock()
@@ -159,7 +161,6 @@ def test_get_balances_prod(default_conf, mocker):
def test_stoploss_order_kraken(default_conf, mocker):
api_mock = MagicMock()
order_id = 'test_prod_buy_{}'.format(randint(0, 10 ** 6))
order_type = 'stop-loss'
api_mock.create_order = MagicMock(return_value={
'id': order_id,
@@ -187,7 +188,7 @@ def test_stoploss_order_kraken(default_conf, mocker):
assert 'info' in order
assert order['id'] == order_id
assert api_mock.create_order.call_args_list[0][1]['symbol'] == 'ETH/BTC'
assert api_mock.create_order.call_args_list[0][1]['type'] == order_type
assert api_mock.create_order.call_args_list[0][1]['type'] == STOPLOSS_ORDERTYPE
assert api_mock.create_order.call_args_list[0][1]['side'] == 'sell'
assert api_mock.create_order.call_args_list[0][1]['amount'] == 1
assert api_mock.create_order.call_args_list[0][1]['price'] == 220
@@ -218,7 +219,6 @@ def test_stoploss_order_kraken(default_conf, mocker):
def test_stoploss_order_dry_run_kraken(default_conf, mocker):
api_mock = MagicMock()
order_type = 'stop-loss'
default_conf['dry_run'] = True
mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y)
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
@@ -233,7 +233,7 @@ def test_stoploss_order_dry_run_kraken(default_conf, mocker):
assert 'info' in order
assert 'type' in order
assert order['type'] == order_type
assert order['type'] == STOPLOSS_ORDERTYPE
assert order['price'] == 220
assert order['amount'] == 1
@@ -241,7 +241,7 @@ def test_stoploss_order_dry_run_kraken(default_conf, mocker):
def test_stoploss_adjust_kraken(mocker, default_conf):
exchange = get_patched_exchange(mocker, default_conf, id='kraken')
order = {
'type': 'stop-loss',
'type': STOPLOSS_ORDERTYPE,
'price': 1500,
}
assert exchange.stoploss_adjust(1501, order)

View File

@@ -659,17 +659,17 @@ def test_backtest_start_multi_strat(default_conf, mocker, caplog, testdatadir):
mocker.patch('freqtrade.pairlist.pairlistmanager.PairListManager.whitelist',
PropertyMock(return_value=['UNITTEST/BTC']))
mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest', backtestmock)
gen_table_mock = MagicMock()
text_table_mock = MagicMock()
sell_reason_mock = MagicMock()
gen_strattable_mock = MagicMock()
gen_strat_summary = MagicMock()
strattable_mock = MagicMock()
strat_summary = MagicMock()
mocker.patch.multiple('freqtrade.optimize.optimize_reports',
generate_text_table=gen_table_mock,
generate_text_table_strategy=gen_strattable_mock,
text_table_bt_results=text_table_mock,
text_table_strategy=strattable_mock,
generate_pair_metrics=MagicMock(),
generate_sell_reason_stats=sell_reason_mock,
generate_strategy_metrics=gen_strat_summary,
generate_strategy_metrics=strat_summary,
)
patched_configuration_load_config_file(mocker, default_conf)
@@ -690,10 +690,10 @@ def test_backtest_start_multi_strat(default_conf, mocker, caplog, testdatadir):
start_backtesting(args)
# 2 backtests, 4 tables
assert backtestmock.call_count == 2
assert gen_table_mock.call_count == 4
assert gen_strattable_mock.call_count == 1
assert text_table_mock.call_count == 4
assert strattable_mock.call_count == 1
assert sell_reason_mock.call_count == 2
assert gen_strat_summary.call_count == 1
assert strat_summary.call_count == 1
# check the logs, that will contain the backtest result
exists = [

View File

@@ -7,13 +7,13 @@ from arrow import Arrow
from freqtrade.edge import PairInfo
from freqtrade.optimize.optimize_reports import (
generate_pair_metrics, generate_edge_table, generate_sell_reason_stats,
generate_text_table, generate_text_table_sell_reason, generate_strategy_metrics,
generate_text_table_strategy, store_backtest_result)
text_table_bt_results, text_table_sell_reason, generate_strategy_metrics,
text_table_strategy, store_backtest_result)
from freqtrade.strategy.interface import SellType
from tests.conftest import patch_exchange
def test_generate_text_table(default_conf, mocker):
def test_text_table_bt_results(default_conf, mocker):
results = pd.DataFrame(
{
@@ -40,8 +40,7 @@ def test_generate_text_table(default_conf, mocker):
pair_results = generate_pair_metrics(data={'ETH/BTC': {}}, stake_currency='BTC',
max_open_trades=2, results=results)
assert generate_text_table(pair_results,
stake_currency='BTC') == result_str
assert text_table_bt_results(pair_results, stake_currency='BTC') == result_str
def test_generate_pair_metrics(default_conf, mocker):
@@ -69,7 +68,7 @@ def test_generate_pair_metrics(default_conf, mocker):
pytest.approx(pair_results[-1]['profit_sum_pct']) == pair_results[-1]['profit_sum'] * 100)
def test_generate_text_table_sell_reason(default_conf):
def test_text_table_sell_reason(default_conf):
results = pd.DataFrame(
{
@@ -97,8 +96,8 @@ def test_generate_text_table_sell_reason(default_conf):
sell_reason_stats = generate_sell_reason_stats(max_open_trades=2,
results=results)
assert generate_text_table_sell_reason(sell_reason_stats=sell_reason_stats,
stake_currency='BTC') == result_str
assert text_table_sell_reason(sell_reason_stats=sell_reason_stats,
stake_currency='BTC') == result_str
def test_generate_sell_reason_stats(default_conf):
@@ -136,7 +135,7 @@ def test_generate_sell_reason_stats(default_conf):
assert stop_result['profit_mean_pct'] == round(stop_result['profit_mean'] * 100, 2)
def test_generate_text_table_strategy(default_conf, mocker):
def test_text_table_strategy(default_conf, mocker):
results = {}
results['TestStrategy1'] = pd.DataFrame(
{
@@ -178,7 +177,7 @@ def test_generate_text_table_strategy(default_conf, mocker):
max_open_trades=2,
all_results=results)
assert generate_text_table_strategy(strategy_results, 'BTC') == result_str
assert text_table_strategy(strategy_results, 'BTC') == result_str
def test_generate_edge_table(edge_conf, mocker):

View File

@@ -421,6 +421,23 @@ def test__whitelist_for_active_markets(mocker, whitelist_conf, markets, pairlist
assert log_message in caplog.text
@pytest.mark.parametrize("pairlist", AVAILABLE_PAIRLISTS)
def test__whitelist_for_active_markets_empty(mocker, whitelist_conf, markets, pairlist, tickers):
whitelist_conf['pairlists'][0]['method'] = pairlist
mocker.patch('freqtrade.exchange.Exchange.exchange_has', return_value=True)
freqtrade = get_patched_freqtradebot(mocker, whitelist_conf)
mocker.patch.multiple('freqtrade.exchange.Exchange',
markets=PropertyMock(return_value=None),
get_tickers=tickers
)
# Assign starting whitelist
pairlist_handler = freqtrade.pairlists._pairlist_handlers[0]
with pytest.raises(OperationalException, match=r'Markets not loaded.*'):
pairlist_handler._whitelist_for_active_markets(['ETH/BTC'])
def test_volumepairlist_invalid_sortvalue(mocker, markets, whitelist_conf):
whitelist_conf['pairlists'][0].update({"sort_key": "asdf"})

View File

@@ -42,8 +42,12 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
rpc._rpc_trade_status()
freqtradebot.enter_positions()
trades = Trade.get_open_trades()
trades[0].open_order_id = None
freqtradebot.exit_positions(trades)
results = rpc._rpc_trade_status()
assert {
assert results[0] == {
'trade_id': 1,
'pair': 'ETH/BTC',
'base_currency': 'BTC',
@@ -54,11 +58,11 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'fee_open': ANY,
'fee_open_cost': ANY,
'fee_open_currency': ANY,
'fee_close': ANY,
'fee_close': fee.return_value,
'fee_close_cost': ANY,
'fee_close_currency': ANY,
'open_rate_requested': ANY,
'open_trade_price': ANY,
'open_trade_price': 0.0010025,
'close_rate_requested': ANY,
'sell_reason': ANY,
'sell_order_status': ANY,
@@ -81,28 +85,32 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'close_profit_abs': None,
'current_profit': -0.00408133,
'current_profit_pct': -0.41,
'stop_loss': 0.0,
'stop_loss_abs': 0.0,
'stop_loss_pct': None,
'stop_loss_ratio': None,
'current_profit_abs': -4.09e-06,
'stop_loss': 9.882e-06,
'stop_loss_abs': 9.882e-06,
'stop_loss_pct': -10.0,
'stop_loss_ratio': -0.1,
'stoploss_order_id': None,
'stoploss_last_update': None,
'stoploss_last_update_timestamp': None,
'initial_stop_loss': 0.0,
'initial_stop_loss_abs': 0.0,
'initial_stop_loss_pct': None,
'initial_stop_loss_ratio': None,
'open_order': '(limit buy rem=0.00000000)',
'stoploss_last_update': ANY,
'stoploss_last_update_timestamp': ANY,
'initial_stop_loss': 9.882e-06,
'initial_stop_loss_abs': 9.882e-06,
'initial_stop_loss_pct': -10.0,
'initial_stop_loss_ratio': -0.1,
'stoploss_current_dist': -1.1080000000000002e-06,
'stoploss_current_dist_ratio': -0.10081893,
'stoploss_entry_dist': -0.00010475,
'stoploss_entry_dist_ratio': -0.10448878,
'open_order': None,
'exchange': 'bittrex',
} == results[0]
}
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_sell_rate',
MagicMock(side_effect=DependencyException("Pair 'ETH/BTC' not available")))
results = rpc._rpc_trade_status()
assert isnan(results[0]['current_profit'])
assert isnan(results[0]['current_rate'])
assert {
assert results[0] == {
'trade_id': 1,
'pair': 'ETH/BTC',
'base_currency': 'BTC',
@@ -113,7 +121,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'fee_open': ANY,
'fee_open_cost': ANY,
'fee_open_currency': ANY,
'fee_close': ANY,
'fee_close': fee.return_value,
'fee_close_cost': ANY,
'fee_close_currency': ANY,
'open_rate_requested': ANY,
@@ -140,20 +148,25 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'close_profit_abs': None,
'current_profit': ANY,
'current_profit_pct': ANY,
'stop_loss': 0.0,
'stop_loss_abs': 0.0,
'stop_loss_pct': None,
'stop_loss_ratio': None,
'current_profit_abs': ANY,
'stop_loss': 9.882e-06,
'stop_loss_abs': 9.882e-06,
'stop_loss_pct': -10.0,
'stop_loss_ratio': -0.1,
'stoploss_order_id': None,
'stoploss_last_update': None,
'stoploss_last_update_timestamp': None,
'initial_stop_loss': 0.0,
'initial_stop_loss_abs': 0.0,
'initial_stop_loss_pct': None,
'initial_stop_loss_ratio': None,
'open_order': '(limit buy rem=0.00000000)',
'stoploss_last_update': ANY,
'stoploss_last_update_timestamp': ANY,
'initial_stop_loss': 9.882e-06,
'initial_stop_loss_abs': 9.882e-06,
'initial_stop_loss_pct': -10.0,
'initial_stop_loss_ratio': -0.1,
'stoploss_current_dist': ANY,
'stoploss_current_dist_ratio': ANY,
'stoploss_entry_dist': -0.00010475,
'stoploss_entry_dist_ratio': -0.10448878,
'open_order': None,
'exchange': 'bittrex',
} == results[0]
}
def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None:
@@ -581,7 +594,7 @@ def test_rpc_stopbuy(mocker, default_conf) -> None:
assert freqtradebot.config['max_open_trades'] != 0
result = rpc._rpc_stopbuy()
assert {'status': 'No more buy will occur from now. Run /reload_conf to reset.'} == result
assert {'status': 'No more buy will occur from now. Run /reload_config to reset.'} == result
assert freqtradebot.config['max_open_trades'] == 0

View File

@@ -251,10 +251,10 @@ def test_api_cleanup(default_conf, mocker, caplog):
def test_api_reloadconf(botclient):
ftbot, client = botclient
rc = client_post(client, f"{BASE_URI}/reload_conf")
rc = client_post(client, f"{BASE_URI}/reload_config")
assert_response(rc)
assert rc.json == {'status': 'reloading config ...'}
assert ftbot.state == State.RELOAD_CONF
assert ftbot.state == State.RELOAD_CONFIG
def test_api_stopbuy(botclient):
@@ -263,7 +263,7 @@ def test_api_stopbuy(botclient):
rc = client_post(client, f"{BASE_URI}/stopbuy")
assert_response(rc)
assert rc.json == {'status': 'No more buy will occur from now. Run /reload_conf to reset.'}
assert rc.json == {'status': 'No more buy will occur from now. Run /reload_config to reset.'}
assert ftbot.config['max_open_trades'] == 0
@@ -326,6 +326,8 @@ def test_api_show_config(botclient, mocker):
assert rc.json['timeframe'] == '5m'
assert rc.json['state'] == 'running'
assert not rc.json['trailing_stop']
assert 'bid_strategy' in rc.json
assert 'ask_strategy' in rc.json
def test_api_daily(botclient, mocker, ticker, fee, markets):
@@ -429,9 +431,17 @@ def test_api_profit(botclient, mocker, ticker, fee, markets, limit_buy_order, li
'profit_all_coin': 6.217e-05,
'profit_all_fiat': 0,
'profit_all_percent': 6.2,
'profit_all_percent_mean': 6.2,
'profit_all_ratio_mean': 0.06201058,
'profit_all_percent_sum': 6.2,
'profit_all_ratio_sum': 0.06201058,
'profit_closed_coin': 6.217e-05,
'profit_closed_fiat': 0,
'profit_closed_percent': 6.2,
'profit_closed_ratio_mean': 0.06201058,
'profit_closed_percent_mean': 6.2,
'profit_closed_ratio_sum': 0.06201058,
'profit_closed_percent_sum': 6.2,
'trade_count': 1,
'closed_trade_count': 1,
}
@@ -496,6 +506,10 @@ def test_api_status(botclient, mocker, ticker, fee, markets):
assert rc.json == []
ftbot.enter_positions()
trades = Trade.get_open_trades()
trades[0].open_order_id = None
ftbot.exit_positions(trades)
rc = client_get(client, f"{BASE_URI}/status")
assert_response(rc)
assert len(rc.json) == 1
@@ -510,25 +524,30 @@ def test_api_status(botclient, mocker, ticker, fee, markets):
'close_rate': None,
'current_profit': -0.00408133,
'current_profit_pct': -0.41,
'current_profit_abs': -4.09e-06,
'current_rate': 1.099e-05,
'open_date': ANY,
'open_date_hum': 'just now',
'open_timestamp': ANY,
'open_order': '(limit buy rem=0.00000000)',
'open_order': None,
'open_rate': 1.098e-05,
'pair': 'ETH/BTC',
'stake_amount': 0.001,
'stop_loss': 0.0,
'stop_loss_abs': 0.0,
'stop_loss_pct': None,
'stop_loss_ratio': None,
'stop_loss': 9.882e-06,
'stop_loss_abs': 9.882e-06,
'stop_loss_pct': -10.0,
'stop_loss_ratio': -0.1,
'stoploss_order_id': None,
'stoploss_last_update': None,
'stoploss_last_update_timestamp': None,
'initial_stop_loss': 0.0,
'initial_stop_loss_abs': 0.0,
'initial_stop_loss_pct': None,
'initial_stop_loss_ratio': None,
'stoploss_last_update': ANY,
'stoploss_last_update_timestamp': ANY,
'initial_stop_loss': 9.882e-06,
'initial_stop_loss_abs': 9.882e-06,
'initial_stop_loss_pct': -10.0,
'initial_stop_loss_ratio': -0.1,
'stoploss_current_dist': -1.1080000000000002e-06,
'stoploss_current_dist_ratio': -0.10081893,
'stoploss_entry_dist': -0.00010475,
'stoploss_entry_dist_ratio': -0.10448878,
'trade_id': 1,
'close_rate_requested': None,
'current_rate': 1.099e-05,
@@ -540,9 +559,9 @@ def test_api_status(botclient, mocker, ticker, fee, markets):
'fee_open_currency': None,
'open_date': ANY,
'is_open': True,
'max_rate': 0.0,
'min_rate': None,
'open_order_id': ANY,
'max_rate': 1.099e-05,
'min_rate': 1.098e-05,
'open_order_id': None,
'open_rate_requested': 1.098e-05,
'open_trade_price': 0.0010025,
'sell_reason': None,

View File

@@ -71,10 +71,11 @@ def test_init(default_conf, mocker, caplog) -> None:
assert start_polling.dispatcher.add_handler.call_count > 0
assert start_polling.start_polling.call_count == 1
message_str = "rpc.telegram is listening for following commands: [['status'], ['profit'], " \
"['balance'], ['start'], ['stop'], ['forcesell'], ['forcebuy'], " \
"['performance'], ['daily'], ['count'], ['reload_conf'], ['show_config'], " \
"['stopbuy'], ['whitelist'], ['blacklist'], ['edge'], ['help'], ['version']]"
message_str = ("rpc.telegram is listening for following commands: [['status'], ['profit'], "
"['balance'], ['start'], ['stop'], ['forcesell'], ['forcebuy'], "
"['performance'], ['daily'], ['count'], ['reload_config', 'reload_conf'], "
"['show_config', 'show_conf'], ['stopbuy'], ['whitelist'], ['blacklist'], "
"['edge'], ['help'], ['version']]")
assert log_has(message_str, caplog)
@@ -434,7 +435,8 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
assert msg_mock.call_count == 1
assert 'No closed trade' in msg_mock.call_args_list[-1][0][0]
assert '*ROI:* All trades' in msg_mock.call_args_list[-1][0][0]
assert '∙ `-0.00000500 BTC (-0.50%)`' in msg_mock.call_args_list[-1][0][0]
assert ('∙ `-0.00000500 BTC (-0.50%) (-0.5 \N{GREEK CAPITAL LETTER SIGMA}%)`'
in msg_mock.call_args_list[-1][0][0])
msg_mock.reset_mock()
# Update the ticker with a market going up
@@ -447,10 +449,12 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
telegram._profit(update=update, context=MagicMock())
assert msg_mock.call_count == 1
assert '*ROI:* Closed trades' in msg_mock.call_args_list[-1][0][0]
assert '∙ `0.00006217 BTC (6.20%)`' in msg_mock.call_args_list[-1][0][0]
assert ('∙ `0.00006217 BTC (6.20%) (6.2 \N{GREEK CAPITAL LETTER SIGMA}%)`'
in msg_mock.call_args_list[-1][0][0])
assert '∙ `0.933 USD`' in msg_mock.call_args_list[-1][0][0]
assert '*ROI:* All trades' in msg_mock.call_args_list[-1][0][0]
assert '∙ `0.00006217 BTC (6.20%)`' in msg_mock.call_args_list[-1][0][0]
assert ('∙ `0.00006217 BTC (6.20%) (6.2 \N{GREEK CAPITAL LETTER SIGMA}%)`'
in msg_mock.call_args_list[-1][0][0])
assert '∙ `0.933 USD`' in msg_mock.call_args_list[-1][0][0]
assert '*Best Performing:* `ETH/BTC: 6.20%`' in msg_mock.call_args_list[-1][0][0]
@@ -663,11 +667,11 @@ def test_stopbuy_handle(default_conf, update, mocker) -> None:
telegram._stopbuy(update=update, context=MagicMock())
assert freqtradebot.config['max_open_trades'] == 0
assert msg_mock.call_count == 1
assert 'No more buy will occur from now. Run /reload_conf to reset.' \
assert 'No more buy will occur from now. Run /reload_config to reset.' \
in msg_mock.call_args_list[0][0][0]
def test_reload_conf_handle(default_conf, update, mocker) -> None:
def test_reload_config_handle(default_conf, update, mocker) -> None:
msg_mock = MagicMock()
mocker.patch.multiple(
'freqtrade.rpc.telegram.Telegram',
@@ -680,8 +684,8 @@ def test_reload_conf_handle(default_conf, update, mocker) -> None:
freqtradebot.state = State.RUNNING
assert freqtradebot.state == State.RUNNING
telegram._reload_conf(update=update, context=MagicMock())
assert freqtradebot.state == State.RELOAD_CONF
telegram._reload_config(update=update, context=MagicMock())
assert freqtradebot.state == State.RELOAD_CONFIG
assert msg_mock.call_count == 1
assert 'reloading config' in msg_mock.call_args_list[0][0][0]
@@ -1013,9 +1017,8 @@ def test_count_handle(default_conf, update, ticker, fee, mocker) -> None:
msg_mock.reset_mock()
telegram._count(update=update, context=MagicMock())
msg = '<pre> current max total stake\n--------- ----- -------------\n' \
' 1 {} {}</pre>'\
.format(
msg = ('<pre> current max total stake\n--------- ----- -------------\n'
' 1 {} {}</pre>').format(
default_conf['max_open_trades'],
default_conf['stake_amount']
)
@@ -1222,7 +1225,7 @@ def test_send_msg_buy_notification(default_conf, mocker) -> None:
'open_date': arrow.utcnow().shift(hours=-1)
})
assert msg_mock.call_args[0][0] \
== '*Bittrex:* Buying ETH/BTC\n' \
== '\N{LARGE BLUE CIRCLE} *Bittrex:* Buying ETH/BTC\n' \
'*Amount:* `1333.33333333`\n' \
'*Open Rate:* `0.00001099`\n' \
'*Current Rate:* `0.00001099`\n' \
@@ -1244,7 +1247,7 @@ def test_send_msg_buy_cancel_notification(default_conf, mocker) -> None:
'pair': 'ETH/BTC',
})
assert msg_mock.call_args[0][0] \
== ('*Bittrex:* Cancelling Open Buy Order for ETH/BTC')
== ('\N{WARNING SIGN} *Bittrex:* Cancelling Open Buy Order for ETH/BTC')
def test_send_msg_sell_notification(default_conf, mocker) -> None:
@@ -1277,7 +1280,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None:
'close_date': arrow.utcnow(),
})
assert msg_mock.call_args[0][0] \
== ('*Binance:* Selling KEY/ETH\n'
== ('\N{WARNING SIGN} *Binance:* Selling KEY/ETH\n'
'*Amount:* `1333.33333333`\n'
'*Open Rate:* `0.00007500`\n'
'*Current Rate:* `0.00003201`\n'
@@ -1305,7 +1308,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None:
'close_date': arrow.utcnow(),
})
assert msg_mock.call_args[0][0] \
== ('*Binance:* Selling KEY/ETH\n'
== ('\N{WARNING SIGN} *Binance:* Selling KEY/ETH\n'
'*Amount:* `1333.33333333`\n'
'*Open Rate:* `0.00007500`\n'
'*Current Rate:* `0.00003201`\n'
@@ -1335,7 +1338,8 @@ def test_send_msg_sell_cancel_notification(default_conf, mocker) -> None:
'reason': 'Cancelled on exchange'
})
assert msg_mock.call_args[0][0] \
== ('*Binance:* Cancelling Open Sell Order for KEY/ETH. Reason: Cancelled on exchange')
== ('\N{WARNING SIGN} *Binance:* Cancelling Open Sell Order for KEY/ETH. '
'Reason: Cancelled on exchange')
msg_mock.reset_mock()
telegram.send_msg({
@@ -1345,7 +1349,7 @@ def test_send_msg_sell_cancel_notification(default_conf, mocker) -> None:
'reason': 'timeout'
})
assert msg_mock.call_args[0][0] \
== ('*Binance:* Cancelling Open Sell Order for KEY/ETH. Reason: timeout')
== ('\N{WARNING SIGN} *Binance:* Cancelling Open Sell Order for KEY/ETH. Reason: timeout')
# Reset singleton function to avoid random breaks
telegram._fiat_converter.convert_amount = old_convamount
@@ -1379,7 +1383,7 @@ def test_warning_notification(default_conf, mocker) -> None:
'type': RPCMessageType.WARNING_NOTIFICATION,
'status': 'message'
})
assert msg_mock.call_args[0][0] == '*Warning:* `message`'
assert msg_mock.call_args[0][0] == '\N{WARNING SIGN} *Warning:* `message`'
def test_custom_notification(default_conf, mocker) -> None:
@@ -1437,12 +1441,11 @@ def test_send_msg_buy_notification_no_fiat(default_conf, mocker) -> None:
'amount': 1333.3333333333335,
'open_date': arrow.utcnow().shift(hours=-1)
})
assert msg_mock.call_args[0][0] \
== '*Bittrex:* Buying ETH/BTC\n' \
'*Amount:* `1333.33333333`\n' \
'*Open Rate:* `0.00001099`\n' \
'*Current Rate:* `0.00001099`\n' \
'*Total:* `(0.001000 BTC)`'
assert msg_mock.call_args[0][0] == ('\N{LARGE BLUE CIRCLE} *Bittrex:* Buying ETH/BTC\n'
'*Amount:* `1333.33333333`\n'
'*Open Rate:* `0.00001099`\n'
'*Current Rate:* `0.00001099`\n'
'*Total:* `(0.001000 BTC)`')
def test_send_msg_sell_notification_no_fiat(default_conf, mocker) -> None:
@@ -1473,15 +1476,37 @@ def test_send_msg_sell_notification_no_fiat(default_conf, mocker) -> None:
'open_date': arrow.utcnow().shift(hours=-2, minutes=-35, seconds=-3),
'close_date': arrow.utcnow(),
})
assert msg_mock.call_args[0][0] \
== '*Binance:* Selling KEY/ETH\n' \
'*Amount:* `1333.33333333`\n' \
'*Open Rate:* `0.00007500`\n' \
'*Current Rate:* `0.00003201`\n' \
'*Close Rate:* `0.00003201`\n' \
'*Sell Reason:* `stop_loss`\n' \
'*Duration:* `2:35:03 (155.1 min)`\n' \
'*Profit:* `-57.41%`'
assert msg_mock.call_args[0][0] == ('\N{WARNING SIGN} *Binance:* Selling KEY/ETH\n'
'*Amount:* `1333.33333333`\n'
'*Open Rate:* `0.00007500`\n'
'*Current Rate:* `0.00003201`\n'
'*Close Rate:* `0.00003201`\n'
'*Sell Reason:* `stop_loss`\n'
'*Duration:* `2:35:03 (155.1 min)`\n'
'*Profit:* `-57.41%`')
@pytest.mark.parametrize('msg,expected', [
({'profit_percent': 20.1, 'sell_reason': 'roi'}, "\N{ROCKET}"),
({'profit_percent': 5.1, 'sell_reason': 'roi'}, "\N{ROCKET}"),
({'profit_percent': 2.56, 'sell_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"),
({'profit_percent': 1.0, 'sell_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"),
({'profit_percent': 0.0, 'sell_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"),
({'profit_percent': -5.0, 'sell_reason': 'stop_loss'}, "\N{WARNING SIGN}"),
({'profit_percent': -2.0, 'sell_reason': 'sell_signal'}, "\N{CROSS MARK}"),
])
def test__sell_emoji(default_conf, mocker, msg, expected):
del default_conf['fiat_display_currency']
msg_mock = MagicMock()
mocker.patch.multiple(
'freqtrade.rpc.telegram.Telegram',
_init=MagicMock(),
_send_msg=msg_mock
)
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
telegram = Telegram(freqtradebot)
assert telegram._get_sell_emoji(msg) == expected
def test__send_msg(default_conf, mocker) -> None:

View File

@@ -1126,7 +1126,7 @@ def test_handle_stoploss_on_exchange(mocker, default_conf, fee, caplog,
trade.stoploss_order_id = 100
hanging_stoploss_order = MagicMock(return_value={'status': 'open'})
mocker.patch('freqtrade.exchange.Exchange.get_order', hanging_stoploss_order)
mocker.patch('freqtrade.exchange.Exchange.get_stoploss_order', hanging_stoploss_order)
assert freqtrade.handle_stoploss_on_exchange(trade) is False
assert trade.stoploss_order_id == 100
@@ -1139,7 +1139,7 @@ def test_handle_stoploss_on_exchange(mocker, default_conf, fee, caplog,
trade.stoploss_order_id = 100
canceled_stoploss_order = MagicMock(return_value={'status': 'canceled'})
mocker.patch('freqtrade.exchange.Exchange.get_order', canceled_stoploss_order)
mocker.patch('freqtrade.exchange.Exchange.get_stoploss_order', canceled_stoploss_order)
stoploss.reset_mock()
assert freqtrade.handle_stoploss_on_exchange(trade) is False
@@ -1164,7 +1164,7 @@ def test_handle_stoploss_on_exchange(mocker, default_conf, fee, caplog,
'average': 2,
'amount': limit_buy_order['amount'],
})
mocker.patch('freqtrade.exchange.Exchange.get_order', stoploss_order_hit)
mocker.patch('freqtrade.exchange.Exchange.get_stoploss_order', stoploss_order_hit)
assert freqtrade.handle_stoploss_on_exchange(trade) is True
assert log_has('STOP_LOSS_LIMIT is hit for {}.'.format(trade), caplog)
assert trade.stoploss_order_id is None
@@ -1183,7 +1183,8 @@ def test_handle_stoploss_on_exchange(mocker, default_conf, fee, caplog,
# It should try to add stoploss order
trade.stoploss_order_id = 100
stoploss.reset_mock()
mocker.patch('freqtrade.exchange.Exchange.get_order', side_effect=InvalidOrderException())
mocker.patch('freqtrade.exchange.Exchange.get_stoploss_order',
side_effect=InvalidOrderException())
mocker.patch('freqtrade.exchange.Exchange.stoploss', stoploss)
freqtrade.handle_stoploss_on_exchange(trade)
assert stoploss.call_count == 1
@@ -1214,7 +1215,7 @@ def test_handle_sle_cancel_cant_recreate(mocker, default_conf, fee, caplog,
buy=MagicMock(return_value={'id': limit_buy_order['id']}),
sell=MagicMock(return_value={'id': limit_sell_order['id']}),
get_fee=fee,
get_order=MagicMock(return_value={'status': 'canceled'}),
get_stoploss_order=MagicMock(return_value={'status': 'canceled'}),
stoploss=MagicMock(side_effect=DependencyException()),
)
freqtrade = FreqtradeBot(default_conf)
@@ -1331,7 +1332,7 @@ def test_handle_stoploss_on_exchange_trailing(mocker, default_conf, fee, caplog,
}
})
mocker.patch('freqtrade.exchange.Exchange.get_order', stoploss_order_hanging)
mocker.patch('freqtrade.exchange.Exchange.get_stoploss_order', stoploss_order_hanging)
# stoploss initially at 5%
assert freqtrade.handle_trade(trade) is False
@@ -1346,7 +1347,7 @@ def test_handle_stoploss_on_exchange_trailing(mocker, default_conf, fee, caplog,
cancel_order_mock = MagicMock()
stoploss_order_mock = MagicMock()
mocker.patch('freqtrade.exchange.Exchange.cancel_order', cancel_order_mock)
mocker.patch('freqtrade.exchange.Exchange.cancel_stoploss_order', cancel_order_mock)
mocker.patch('freqtrade.exchange.Exchange.stoploss', stoploss_order_mock)
# stoploss should not be updated as the interval is 60 seconds
@@ -1429,8 +1430,9 @@ def test_handle_stoploss_on_exchange_trailing_error(mocker, default_conf, fee, c
'stopPrice': '0.1'
}
}
mocker.patch('freqtrade.exchange.Exchange.cancel_order', side_effect=InvalidOrderException())
mocker.patch('freqtrade.exchange.Exchange.get_order', stoploss_order_hanging)
mocker.patch('freqtrade.exchange.Exchange.cancel_stoploss_order',
side_effect=InvalidOrderException())
mocker.patch('freqtrade.exchange.Exchange.get_stoploss_order', stoploss_order_hanging)
freqtrade.handle_trailing_stoploss_on_exchange(trade, stoploss_order_hanging)
assert log_has_re(r"Could not cancel stoploss order abcd for pair ETH/BTC.*", caplog)
@@ -1439,7 +1441,7 @@ def test_handle_stoploss_on_exchange_trailing_error(mocker, default_conf, fee, c
# Fail creating stoploss order
caplog.clear()
cancel_mock = mocker.patch("freqtrade.exchange.Exchange.cancel_order", MagicMock())
cancel_mock = mocker.patch("freqtrade.exchange.Exchange.cancel_stoploss_order", MagicMock())
mocker.patch("freqtrade.exchange.Exchange.stoploss", side_effect=DependencyException())
freqtrade.handle_trailing_stoploss_on_exchange(trade, stoploss_order_hanging)
assert cancel_mock.call_count == 1
@@ -1510,7 +1512,7 @@ def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, caplog,
}
})
mocker.patch('freqtrade.exchange.Exchange.get_order', stoploss_order_hanging)
mocker.patch('freqtrade.exchange.Exchange.get_stoploss_order', stoploss_order_hanging)
# stoploss initially at 20% as edge dictated it.
assert freqtrade.handle_trade(trade) is False
@@ -1519,7 +1521,7 @@ def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, caplog,
cancel_order_mock = MagicMock()
stoploss_order_mock = MagicMock()
mocker.patch('freqtrade.exchange.Exchange.cancel_order', cancel_order_mock)
mocker.patch('freqtrade.exchange.Exchange.cancel_stoploss_order', cancel_order_mock)
mocker.patch('freqtrade.exchange.Binance.stoploss', stoploss_order_mock)
# price goes down 5%
@@ -2632,7 +2634,8 @@ def test_execute_sell_down_stoploss_on_exchange_dry_run(default_conf, ticker, fe
def test_execute_sell_sloe_cancel_exception(mocker, default_conf, ticker, fee, caplog) -> None:
freqtrade = get_patched_freqtradebot(mocker, default_conf)
mocker.patch('freqtrade.exchange.Exchange.cancel_order', side_effect=InvalidOrderException())
mocker.patch('freqtrade.exchange.Exchange.cancel_stoploss_order',
side_effect=InvalidOrderException())
mocker.patch('freqtrade.wallets.Wallets.get_free', MagicMock(return_value=300))
sellmock = MagicMock()
patch_exchange(mocker)
@@ -2680,7 +2683,7 @@ def test_execute_sell_with_stoploss_on_exchange(default_conf, ticker, fee, ticke
amount_to_precision=lambda s, x, y: y,
price_to_precision=lambda s, x, y: y,
stoploss=stoploss,
cancel_order=cancel_order,
cancel_stoploss_order=cancel_order,
)
freqtrade = FreqtradeBot(default_conf)
@@ -2771,7 +2774,7 @@ def test_may_execute_sell_after_stoploss_on_exchange_hit(default_conf, ticker, f
"fee": None,
"trades": None
})
mocker.patch('freqtrade.exchange.Exchange.get_order', stoploss_executed)
mocker.patch('freqtrade.exchange.Exchange.get_stoploss_order', stoploss_executed)
freqtrade.exit_positions(trades)
assert trade.stoploss_order_id is None

View File

@@ -62,8 +62,8 @@ def test_may_execute_sell_stoploss_on_exchange_multi(default_conf, ticker, fee,
get_fee=fee,
amount_to_precision=lambda s, x, y: y,
price_to_precision=lambda s, x, y: y,
get_order=stoploss_order_mock,
cancel_order=cancel_order_mock,
get_stoploss_order=stoploss_order_mock,
cancel_stoploss_order=cancel_order_mock,
)
mocker.patch.multiple(

View File

@@ -141,12 +141,12 @@ def test_main_operational_exception1(mocker, default_conf, caplog) -> None:
assert log_has_re(r'SIGINT.*', caplog)
def test_main_reload_conf(mocker, default_conf, caplog) -> None:
def test_main_reload_config(mocker, default_conf, caplog) -> None:
patch_exchange(mocker)
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.cleanup', MagicMock())
# Simulate Running, reload, running workflow
worker_mock = MagicMock(side_effect=[State.RUNNING,
State.RELOAD_CONF,
State.RELOAD_CONFIG,
State.RUNNING,
OperationalException("Oh snap!")])
mocker.patch('freqtrade.worker.Worker._worker', worker_mock)

View File

@@ -298,7 +298,7 @@ def test_calc_profit(limit_buy_order, limit_sell_order, fee):
fee_close=fee.return_value,
exchange='bittrex',
)
trade.open_order_id = 'profit_percent'
trade.open_order_id = 'something'
trade.update(limit_buy_order) # Buy @ 0.00001099
# Custom closing rate and regular fee rate
@@ -332,7 +332,7 @@ def test_calc_profit_ratio(limit_buy_order, limit_sell_order, fee):
fee_close=fee.return_value,
exchange='bittrex',
)
trade.open_order_id = 'profit_percent'
trade.open_order_id = 'something'
trade.update(limit_buy_order) # Buy @ 0.00001099
# Get percent of profit with a custom rate (Higher than open rate)

View File

@@ -124,7 +124,7 @@ def test_plot_trades(testdatadir, caplog):
trade_sell = find_trace_in_fig_data(figure.data, 'Sell - Profit')
assert isinstance(trade_sell, go.Scatter)
assert trade_sell.yaxis == 'y'
assert len(trades.loc[trades['profitperc'] > 0]) == len(trade_sell.x)
assert len(trades.loc[trades['profit_percent'] > 0]) == len(trade_sell.x)
assert trade_sell.marker.color == 'green'
assert trade_sell.marker.symbol == 'square-open'
assert trade_sell.text[0] == '4.0%, roi, 15 min'
@@ -132,7 +132,7 @@ def test_plot_trades(testdatadir, caplog):
trade_sell_loss = find_trace_in_fig_data(figure.data, 'Sell - Loss')
assert isinstance(trade_sell_loss, go.Scatter)
assert trade_sell_loss.yaxis == 'y'
assert len(trades.loc[trades['profitperc'] <= 0]) == len(trade_sell_loss.x)
assert len(trades.loc[trades['profit_percent'] <= 0]) == len(trade_sell_loss.x)
assert trade_sell_loss.marker.color == 'red'
assert trade_sell_loss.marker.symbol == 'square-open'
assert trade_sell_loss.text[5] == '-10.4%, stop_loss, 720 min'