Merge branch 'develop' into db_keep_orders

This commit is contained in:
Matthias
2020-09-06 15:22:13 +02:00
26 changed files with 547 additions and 420 deletions

View File

@@ -1760,6 +1760,14 @@ def test_cancel_order_dry_run(default_conf, mocker, exchange_name):
assert exchange.cancel_order(order_id='123', pair='TKN/BTC') == {}
assert exchange.cancel_stoploss_order(order_id='123', pair='TKN/BTC') == {}
order = exchange.buy('ETH/BTC', 'limit', 5, 0.55, 'gtc')
cancel_order = exchange.cancel_order(order_id=order['id'], pair='ETH/BTC')
assert order['id'] == cancel_order['id']
assert order['amount'] == cancel_order['amount']
assert order['pair'] == cancel_order['pair']
assert cancel_order['status'] == 'canceled'
@pytest.mark.parametrize("exchange_name", EXCHANGES)
@pytest.mark.parametrize("order,result", [

View File

@@ -231,9 +231,6 @@ def test_VolumePairList_refresh_empty(mocker, markets_empty, whitelist_conf):
# VolumePairList only
([{"method": "VolumePairList", "number_assets": 5, "sort_key": "quoteVolume"}],
"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', 'XRP/BTC', 'LTC/BTC', 'TKN/BTC']),
([{"method": "VolumePairList", "number_assets": 5, "sort_key": "quoteVolume"}],
"USDT", ['ETH/USDT', 'NANO/USDT', 'ADAHALF/USDT', 'ADADOUBLE/USDT']),
# No pair for ETH, VolumePairList
@@ -263,10 +260,6 @@ def test_VolumePairList_refresh_empty(mocker, markets_empty, whitelist_conf):
([{"method": "VolumePairList", "number_assets": 5, "sort_key": "quoteVolume"},
{"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', 'XRP/BTC', 'LTC/BTC', 'TKN/BTC']),
# PriceFilter and VolumePairList
([{"method": "VolumePairList", "number_assets": 5, "sort_key": "quoteVolume"},
{"method": "PriceFilter", "low_price_ratio": 0.03}],
@@ -293,9 +286,6 @@ def test_VolumePairList_refresh_empty(mocker, markets_empty, whitelist_conf):
([{"method": "StaticPairList"}],
"BTC", ['ETH/BTC', 'TKN/BTC', 'HOT/BTC']),
# Static Pairlist before VolumePairList - sorting changes
([{"method": "StaticPairList"},
{"method": "VolumePairList", "number_assets": 5, "sort_key": "bidVolume"}],
"BTC", ['HOT/BTC', 'TKN/BTC', 'ETH/BTC']),
# SpreadFilter
([{"method": "VolumePairList", "number_assets": 5, "sort_key": "quoteVolume"},
{"method": "SpreadFilter", "max_spread_ratio": 0.005}],
@@ -344,9 +334,9 @@ def test_VolumePairList_refresh_empty(mocker, markets_empty, whitelist_conf):
([{"method": "SpreadFilter", "max_spread_ratio": 0.005}],
"BTC", 'filter_at_the_beginning'), # OperationalException expected
# Static Pairlist after VolumePairList, on a non-first position
([{"method": "VolumePairList", "number_assets": 5, "sort_key": "bidVolume"},
([{"method": "VolumePairList", "number_assets": 5, "sort_key": "quoteVolume"},
{"method": "StaticPairList"}],
"BTC", 'static_in_the_middle'),
"BTC", 'static_in_the_middle'),
([{"method": "VolumePairList", "number_assets": 20, "sort_key": "quoteVolume"},
{"method": "PriceFilter", "low_price_ratio": 0.02}],
"USDT", ['ETH/USDT', 'NANO/USDT']),

View File

@@ -668,7 +668,8 @@ def test_rpc_forcesell(default_conf, ticker, fee, mocker) -> None:
return_value={
'status': 'closed',
'type': 'limit',
'side': 'buy'
'side': 'buy',
'filled': 0.0,
}
),
get_fee=fee,
@@ -694,6 +695,7 @@ def test_rpc_forcesell(default_conf, ticker, fee, mocker) -> None:
msg = rpc._rpc_forcesell('all')
assert msg == {'result': 'Created sell orders for all open trades.'}
freqtradebot.enter_positions()
msg = rpc._rpc_forcesell('1')
assert msg == {'result': 'Created sell order for trade 1.'}
@@ -706,17 +708,24 @@ def test_rpc_forcesell(default_conf, ticker, fee, mocker) -> None:
freqtradebot.state = State.RUNNING
assert cancel_order_mock.call_count == 0
freqtradebot.enter_positions()
# make an limit-buy open trade
trade = Trade.query.filter(Trade.id == '1').first()
filled_amount = trade.amount / 2
# Fetch order - it's open first, and closed after cancel_order is called.
mocker.patch(
'freqtrade.exchange.Exchange.fetch_order',
return_value={
side_effect=[{
'status': 'open',
'type': 'limit',
'side': 'buy',
'filled': filled_amount
}
}, {
'status': 'closed',
'type': 'limit',
'side': 'buy',
'filled': filled_amount
}]
)
# check that the trade is called, which is done by ensuring exchange.cancel_order is called
# and trade amount is updated
@@ -724,6 +733,16 @@ def test_rpc_forcesell(default_conf, ticker, fee, mocker) -> None:
assert cancel_order_mock.call_count == 1
assert trade.amount == filled_amount
mocker.patch(
'freqtrade.exchange.Exchange.fetch_order',
return_value={
'status': 'open',
'type': 'limit',
'side': 'buy',
'filled': filled_amount
})
freqtradebot.config['max_open_trades'] = 3
freqtradebot.enter_positions()
trade = Trade.query.filter(Trade.id == '2').first()
amount = trade.amount
@@ -743,20 +762,22 @@ def test_rpc_forcesell(default_conf, ticker, fee, mocker) -> None:
assert cancel_order_mock.call_count == 2
assert trade.amount == amount
freqtradebot.enter_positions()
# make an limit-sell open trade
mocker.patch(
'freqtrade.exchange.Exchange.fetch_order',
return_value={
'status': 'open',
'type': 'limit',
'side': 'sell'
'side': 'sell',
'amount': amount,
'remaining': amount,
'filled': 0.0
}
)
msg = rpc._rpc_forcesell('3')
assert msg == {'result': 'Created sell order for trade 3.'}
# status quo, no exchange calls
assert cancel_order_mock.call_count == 2
assert cancel_order_mock.call_count == 3
def test_performance_handle(default_conf, ticker, limit_buy_order, fee,

View File

@@ -266,7 +266,7 @@ def test_api_reloadconf(botclient):
rc = client_post(client, f"{BASE_URI}/reload_config")
assert_response(rc)
assert rc.json == {'status': 'reloading config ...'}
assert rc.json == {'status': 'Reloading config ...'}
assert ftbot.state == State.RELOAD_CONFIG

View File

@@ -14,6 +14,7 @@ from telegram import Chat, Message, Update
from telegram.error import NetworkError
from freqtrade import __version__
from freqtrade.constants import CANCEL_REASON
from freqtrade.edge import PairInfo
from freqtrade.freqtradebot import FreqtradeBot
from freqtrade.loggers import setup_logging
@@ -690,7 +691,7 @@ def test_reload_config_handle(default_conf, update, mocker) -> None:
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]
assert 'Reloading config' in msg_mock.call_args_list[0][0][0]
def test_telegram_forcesell_handle(default_conf, update, ticker, fee,
@@ -724,7 +725,7 @@ def test_telegram_forcesell_handle(default_conf, update, ticker, fee,
context.args = ["1"]
telegram._forcesell(update=update, context=context)
assert rpc_mock.call_count == 2
assert rpc_mock.call_count == 3
last_msg = rpc_mock.call_args_list[-1][0][0]
assert {
'type': RPCMessageType.SELL_NOTIFICATION,
@@ -783,7 +784,7 @@ def test_telegram_forcesell_down_handle(default_conf, update, ticker, fee,
context.args = ["1"]
telegram._forcesell(update=update, context=context)
assert rpc_mock.call_count == 2
assert rpc_mock.call_count == 3
last_msg = rpc_mock.call_args_list[-1][0][0]
assert {
@@ -833,8 +834,9 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, mocker) -> None
context.args = ["all"]
telegram._forcesell(update=update, context=context)
assert rpc_mock.call_count == 4
msg = rpc_mock.call_args_list[0][0][0]
# Called for each trade 3 times
assert rpc_mock.call_count == 8
msg = rpc_mock.call_args_list[1][0][0]
assert {
'type': RPCMessageType.SELL_NOTIFICATION,
'trade_id': 1,
@@ -1341,9 +1343,10 @@ def test_send_msg_buy_cancel_notification(default_conf, mocker) -> None:
'type': RPCMessageType.BUY_CANCEL_NOTIFICATION,
'exchange': 'Bittrex',
'pair': 'ETH/BTC',
'reason': CANCEL_REASON['TIMEOUT']
})
assert msg_mock.call_args[0][0] \
== ('\N{WARNING SIGN} *Bittrex:* Cancelling Open Buy Order for ETH/BTC')
assert (msg_mock.call_args[0][0] == '\N{WARNING SIGN} *Bittrex:* '
'Cancelling open buy Order for ETH/BTC. Reason: cancelled due to timeout.')
def test_send_msg_sell_notification(default_conf, mocker) -> None:

View File

@@ -2,8 +2,7 @@
# Test Documentation boxes -
# !!! <TYPE>: is not allowed!
# !!! <TYPE> "title" - Title needs to be quoted!
# !!! <TYPE> Spaces at the beginning are not allowed
grep -Er '^!{3}\s\S+:|^!{3}\s\S+\s[^"]|^\s+!{3}\s\S+' docs/*
grep -Er '^!{3}\s\S+:|^!{3}\s\S+\s[^"]' docs/*
if [ $? -ne 0 ]; then
echo "Docs test success."

View File

@@ -2345,7 +2345,7 @@ def test_check_handle_timedout_partial(default_conf, ticker, limit_buy_order_old
# note this is for a partially-complete buy order
freqtrade.check_handle_timedout()
assert cancel_order_mock.call_count == 1
assert rpc_mock.call_count == 2
assert rpc_mock.call_count == 1
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
assert len(trades) == 1
assert trades[0].amount == 23.0
@@ -2380,7 +2380,7 @@ def test_check_handle_timedout_partial_fee(default_conf, ticker, open_trade, cap
assert log_has_re(r"Applying fee on amount for Trade.*", caplog)
assert cancel_order_mock.call_count == 1
assert rpc_mock.call_count == 2
assert rpc_mock.call_count == 1
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
assert len(trades) == 1
# Verify that trade has been updated
@@ -2420,7 +2420,7 @@ def test_check_handle_timedout_partial_except(default_conf, ticker, open_trade,
assert log_has_re(r"Could not update trade amount: .*", caplog)
assert cancel_order_mock.call_count == 1
assert rpc_mock.call_count == 2
assert rpc_mock.call_count == 1
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
assert len(trades) == 1
# Verify that trade has been updated
@@ -2583,13 +2583,15 @@ def test_handle_cancel_sell_limit(mocker, default_conf, fee) -> None:
send_msg_mock.reset_mock()
order['amount'] = 2
assert freqtrade.handle_cancel_sell(trade, order, reason) == CANCEL_REASON['PARTIALLY_FILLED']
assert freqtrade.handle_cancel_sell(trade, order, reason
) == CANCEL_REASON['PARTIALLY_FILLED_KEEP_OPEN']
# Assert cancel_order was not called (callcount remains unchanged)
assert cancel_order_mock.call_count == 1
assert send_msg_mock.call_count == 1
assert freqtrade.handle_cancel_sell(trade, order, reason) == CANCEL_REASON['PARTIALLY_FILLED']
assert freqtrade.handle_cancel_sell(trade, order, reason
) == CANCEL_REASON['PARTIALLY_FILLED_KEEP_OPEN']
# Message should not be iterated again
assert trade.sell_order_status == CANCEL_REASON['PARTIALLY_FILLED']
assert trade.sell_order_status == CANCEL_REASON['PARTIALLY_FILLED_KEEP_OPEN']
assert send_msg_mock.call_count == 1