Merge branch 'develop' into interface_ordertimeoutcallback
This commit is contained in:
@@ -761,8 +761,8 @@ def test_process_trade_creation(default_conf, ticker, limit_buy_order,
|
||||
assert trade.is_open
|
||||
assert trade.open_date is not None
|
||||
assert trade.exchange == 'bittrex'
|
||||
assert trade.open_rate == 0.00001099
|
||||
assert trade.amount == 90.99181073703367
|
||||
assert trade.open_rate == 0.00001098
|
||||
assert trade.amount == 91.07468123861567
|
||||
|
||||
assert log_has(
|
||||
'Buy signal found: about create a new trade with stake_amount: 0.001 ...', caplog
|
||||
@@ -782,7 +782,7 @@ def test_process_exchange_failures(default_conf, ticker, mocker) -> None:
|
||||
worker = Worker(args=None, config=default_conf)
|
||||
patch_get_signal(worker.freqtrade)
|
||||
|
||||
worker._process()
|
||||
worker._process_running()
|
||||
assert sleep_mock.has_calls()
|
||||
|
||||
|
||||
@@ -799,7 +799,7 @@ def test_process_operational_exception(default_conf, ticker, mocker) -> None:
|
||||
|
||||
assert worker.freqtrade.state == State.RUNNING
|
||||
|
||||
worker._process()
|
||||
worker._process_running()
|
||||
assert worker.freqtrade.state == State.STOPPED
|
||||
assert 'OperationalException' in msg_mock.call_args_list[-1][0][0]['status']
|
||||
|
||||
@@ -906,22 +906,47 @@ def test_process_informative_pairs_added(default_conf, ticker, mocker) -> None:
|
||||
assert ("ETH/BTC", default_conf["ticker_interval"]) in refresh_mock.call_args[0][0]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("ask,last,last_ab,expected", [
|
||||
(20, 10, 0.0, 20), # Full ask side
|
||||
(20, 10, 1.0, 10), # Full last side
|
||||
(20, 10, 0.5, 15), # Between ask and last
|
||||
(20, 10, 0.7, 13), # Between ask and last
|
||||
(20, 10, 0.3, 17), # Between ask and last
|
||||
(5, 10, 1.0, 5), # last bigger than ask
|
||||
(5, 10, 0.5, 5), # last bigger than ask
|
||||
@pytest.mark.parametrize("side,ask,bid,last,last_ab,expected", [
|
||||
('ask', 20, 19, 10, 0.0, 20), # Full ask side
|
||||
('ask', 20, 19, 10, 1.0, 10), # Full last side
|
||||
('ask', 20, 19, 10, 0.5, 15), # Between ask and last
|
||||
('ask', 20, 19, 10, 0.7, 13), # Between ask and last
|
||||
('ask', 20, 19, 10, 0.3, 17), # Between ask and last
|
||||
('ask', 5, 6, 10, 1.0, 5), # last bigger than ask
|
||||
('ask', 5, 6, 10, 0.5, 5), # last bigger than ask
|
||||
('ask', 10, 20, None, 0.5, 10), # last not available - uses ask
|
||||
('ask', 4, 5, None, 0.5, 4), # last not available - uses ask
|
||||
('ask', 4, 5, None, 1, 4), # last not available - uses ask
|
||||
('ask', 4, 5, None, 0, 4), # last not available - uses ask
|
||||
('bid', 10, 20, 10, 0.0, 20), # Full bid side
|
||||
('bid', 10, 20, 10, 1.0, 10), # Full last side
|
||||
('bid', 10, 20, 10, 0.5, 15), # Between bid and last
|
||||
('bid', 10, 20, 10, 0.7, 13), # Between bid and last
|
||||
('bid', 10, 20, 10, 0.3, 17), # Between bid and last
|
||||
('bid', 4, 5, 10, 1.0, 5), # last bigger than bid
|
||||
('bid', 4, 5, 10, 0.5, 5), # last bigger than bid
|
||||
('bid', 10, 20, None, 0.5, 20), # last not available - uses bid
|
||||
('bid', 4, 5, None, 0.5, 5), # last not available - uses bid
|
||||
('bid', 4, 5, None, 1, 5), # last not available - uses bid
|
||||
('bid', 4, 5, None, 0, 5), # last not available - uses bid
|
||||
])
|
||||
def test_get_buy_rate(mocker, default_conf, ask, last, last_ab, expected) -> None:
|
||||
def test_get_buy_rate(mocker, default_conf, caplog, side, ask, bid,
|
||||
last, last_ab, expected) -> None:
|
||||
default_conf['bid_strategy']['ask_last_balance'] = last_ab
|
||||
default_conf['bid_strategy']['price_side'] = side
|
||||
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
||||
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker',
|
||||
MagicMock(return_value={'ask': ask, 'last': last}))
|
||||
MagicMock(return_value={'ask': ask, 'last': last, 'bid': bid}))
|
||||
|
||||
assert freqtrade.get_buy_rate('ETH/BTC', True) == expected
|
||||
assert not log_has("Using cached buy rate for ETH/BTC.", caplog)
|
||||
|
||||
assert freqtrade.get_buy_rate('ETH/BTC', False) == expected
|
||||
assert log_has("Using cached buy rate for ETH/BTC.", caplog)
|
||||
# Running a 2nd time with Refresh on!
|
||||
caplog.clear()
|
||||
assert freqtrade.get_buy_rate('ETH/BTC', True) == expected
|
||||
assert not log_has("Using cached buy rate for ETH/BTC.", caplog)
|
||||
|
||||
|
||||
def test_execute_buy(mocker, default_conf, fee, limit_buy_order) -> None:
|
||||
@@ -1309,7 +1334,7 @@ def test_handle_stoploss_on_exchange_trailing(mocker, default_conf, fee, caplog,
|
||||
stoploss_order_mock.assert_not_called()
|
||||
|
||||
assert freqtrade.handle_trade(trade) is False
|
||||
assert trade.stop_loss == 0.00002344 * 0.95
|
||||
assert trade.stop_loss == 0.00002346 * 0.95
|
||||
|
||||
# setting stoploss_on_exchange_interval to 0 seconds
|
||||
freqtrade.strategy.order_types['stoploss_on_exchange_interval'] = 0
|
||||
@@ -1317,10 +1342,10 @@ def test_handle_stoploss_on_exchange_trailing(mocker, default_conf, fee, caplog,
|
||||
assert freqtrade.handle_stoploss_on_exchange(trade) is False
|
||||
|
||||
cancel_order_mock.assert_called_once_with(100, 'ETH/BTC')
|
||||
stoploss_order_mock.assert_called_once_with(amount=85.25149190110828,
|
||||
stoploss_order_mock.assert_called_once_with(amount=85.32423208191126,
|
||||
pair='ETH/BTC',
|
||||
order_types=freqtrade.strategy.order_types,
|
||||
stop_price=0.00002344 * 0.95)
|
||||
stop_price=0.00002346 * 0.95)
|
||||
|
||||
# price fell below stoploss, so dry-run sells trade.
|
||||
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', MagicMock(return_value={
|
||||
@@ -1502,12 +1527,12 @@ def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, caplog,
|
||||
assert freqtrade.handle_stoploss_on_exchange(trade) is False
|
||||
|
||||
# stoploss should be set to 1% as trailing is on
|
||||
assert trade.stop_loss == 0.00002344 * 0.99
|
||||
assert trade.stop_loss == 0.00002346 * 0.99
|
||||
cancel_order_mock.assert_called_once_with(100, 'NEO/BTC')
|
||||
stoploss_order_mock.assert_called_once_with(amount=2131074.168797954,
|
||||
stoploss_order_mock.assert_called_once_with(amount=2132892.491467577,
|
||||
pair='NEO/BTC',
|
||||
order_types=freqtrade.strategy.order_types,
|
||||
stop_price=0.00002344 * 0.99)
|
||||
stop_price=0.00002346 * 0.99)
|
||||
|
||||
|
||||
def test_enter_positions(mocker, default_conf, caplog) -> None:
|
||||
@@ -2290,6 +2315,7 @@ def test_handle_timedout_limit_buy(mocker, default_conf, limit_buy_order) -> Non
|
||||
|
||||
Trade.session = MagicMock()
|
||||
trade = MagicMock()
|
||||
trade.pair = 'LTC/ETH'
|
||||
limit_buy_order['remaining'] = limit_buy_order['amount']
|
||||
assert freqtrade.handle_timedout_limit_buy(trade, limit_buy_order)
|
||||
assert cancel_order_mock.call_count == 1
|
||||
@@ -2313,6 +2339,7 @@ def test_handle_timedout_limit_buy_corder_empty(mocker, default_conf, limit_buy_
|
||||
|
||||
Trade.session = MagicMock()
|
||||
trade = MagicMock()
|
||||
trade.pair = 'LTC/ETH'
|
||||
limit_buy_order['remaining'] = limit_buy_order['amount']
|
||||
assert freqtrade.handle_timedout_limit_buy(trade, limit_buy_order)
|
||||
assert cancel_order_mock.call_count == 1
|
||||
@@ -2380,12 +2407,12 @@ def test_execute_sell_up(default_conf, ticker, fee, ticker_sell_up, mocker) -> N
|
||||
'pair': 'ETH/BTC',
|
||||
'gain': 'profit',
|
||||
'limit': 1.172e-05,
|
||||
'amount': 90.99181073703367,
|
||||
'amount': 91.07468123861567,
|
||||
'order_type': 'limit',
|
||||
'open_rate': 1.099e-05,
|
||||
'current_rate': 1.172e-05,
|
||||
'profit_amount': 6.126e-05,
|
||||
'profit_percent': 0.0611052,
|
||||
'open_rate': 1.098e-05,
|
||||
'current_rate': 1.173e-05,
|
||||
'profit_amount': 6.223e-05,
|
||||
'profit_ratio': 0.0620716,
|
||||
'stake_currency': 'BTC',
|
||||
'fiat_currency': 'USD',
|
||||
'sell_reason': SellType.ROI.value,
|
||||
@@ -2429,12 +2456,12 @@ def test_execute_sell_down(default_conf, ticker, fee, ticker_sell_down, mocker)
|
||||
'pair': 'ETH/BTC',
|
||||
'gain': 'loss',
|
||||
'limit': 1.044e-05,
|
||||
'amount': 90.99181073703367,
|
||||
'amount': 91.07468123861567,
|
||||
'order_type': 'limit',
|
||||
'open_rate': 1.099e-05,
|
||||
'current_rate': 1.044e-05,
|
||||
'profit_amount': -5.492e-05,
|
||||
'profit_percent': -0.05478342,
|
||||
'open_rate': 1.098e-05,
|
||||
'current_rate': 1.043e-05,
|
||||
'profit_amount': -5.406e-05,
|
||||
'profit_ratio': -0.05392257,
|
||||
'stake_currency': 'BTC',
|
||||
'fiat_currency': 'USD',
|
||||
'sell_reason': SellType.STOP_LOSS.value,
|
||||
@@ -2485,12 +2512,12 @@ def test_execute_sell_down_stoploss_on_exchange_dry_run(default_conf, ticker, fe
|
||||
'pair': 'ETH/BTC',
|
||||
'gain': 'loss',
|
||||
'limit': 1.08801e-05,
|
||||
'amount': 90.99181073703367,
|
||||
'amount': 91.07468123861567,
|
||||
'order_type': 'limit',
|
||||
'open_rate': 1.099e-05,
|
||||
'current_rate': 1.044e-05,
|
||||
'profit_amount': -1.498e-05,
|
||||
'profit_percent': -0.01493766,
|
||||
'open_rate': 1.098e-05,
|
||||
'current_rate': 1.043e-05,
|
||||
'profit_amount': -1.408e-05,
|
||||
'profit_ratio': -0.01404051,
|
||||
'stake_currency': 'BTC',
|
||||
'fiat_currency': 'USD',
|
||||
'sell_reason': SellType.STOP_LOSS.value,
|
||||
@@ -2675,7 +2702,7 @@ def test_execute_sell_market_order(default_conf, ticker, fee,
|
||||
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'], sell_reason=SellType.ROI)
|
||||
|
||||
assert not trade.is_open
|
||||
assert trade.close_profit == 0.0611052
|
||||
assert trade.close_profit == 0.0620716
|
||||
|
||||
assert rpc_mock.call_count == 2
|
||||
last_msg = rpc_mock.call_args_list[-1][0][0]
|
||||
@@ -2685,12 +2712,12 @@ def test_execute_sell_market_order(default_conf, ticker, fee,
|
||||
'pair': 'ETH/BTC',
|
||||
'gain': 'profit',
|
||||
'limit': 1.172e-05,
|
||||
'amount': 90.99181073703367,
|
||||
'amount': 91.07468123861567,
|
||||
'order_type': 'market',
|
||||
'open_rate': 1.099e-05,
|
||||
'current_rate': 1.172e-05,
|
||||
'profit_amount': 6.126e-05,
|
||||
'profit_percent': 0.0611052,
|
||||
'open_rate': 1.098e-05,
|
||||
'current_rate': 1.173e-05,
|
||||
'profit_amount': 6.223e-05,
|
||||
'profit_ratio': 0.0620716,
|
||||
'stake_currency': 'BTC',
|
||||
'fiat_currency': 'USD',
|
||||
'sell_reason': SellType.ROI.value,
|
||||
@@ -3712,29 +3739,55 @@ def test_order_book_ask_strategy(default_conf, limit_buy_order, limit_sell_order
|
||||
assert freqtrade.handle_trade(trade) is True
|
||||
|
||||
|
||||
def test_get_sell_rate(default_conf, mocker, ticker, order_book_l2) -> None:
|
||||
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
get_order_book=order_book_l2,
|
||||
fetch_ticker=ticker,
|
||||
)
|
||||
@pytest.mark.parametrize('side,ask,bid,expected', [
|
||||
('bid', 10.0, 11.0, 11.0),
|
||||
('bid', 10.0, 11.2, 11.2),
|
||||
('bid', 10.0, 11.0, 11.0),
|
||||
('bid', 9.8, 11.0, 11.0),
|
||||
('bid', 0.0001, 0.002, 0.002),
|
||||
('ask', 10.0, 11.0, 10.0),
|
||||
('ask', 10.11, 11.2, 10.11),
|
||||
('ask', 0.001, 0.002, 0.001),
|
||||
('ask', 0.006, 1.0, 0.006),
|
||||
])
|
||||
def test_get_sell_rate(default_conf, mocker, caplog, side, bid, ask, expected) -> None:
|
||||
default_conf['ask_strategy']['price_side'] = side
|
||||
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', return_value={'ask': ask, 'bid': bid})
|
||||
pair = "ETH/BTC"
|
||||
|
||||
# Test regular mode
|
||||
ft = get_patched_freqtradebot(mocker, default_conf)
|
||||
rate = ft.get_sell_rate(pair, True)
|
||||
assert not log_has("Using cached sell rate for ETH/BTC.", caplog)
|
||||
assert isinstance(rate, float)
|
||||
assert rate == 0.00001098
|
||||
assert rate == expected
|
||||
# Use caching
|
||||
rate = ft.get_sell_rate(pair, False)
|
||||
assert rate == expected
|
||||
assert log_has("Using cached sell rate for ETH/BTC.", caplog)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('side,expected', [
|
||||
('bid', 0.043936), # Value from order_book_l2 fiture - bids side
|
||||
('ask', 0.043949), # Value from order_book_l2 fiture - asks side
|
||||
])
|
||||
def test_get_sell_rate_orderbook(default_conf, mocker, caplog, side, expected, order_book_l2):
|
||||
# Test orderbook mode
|
||||
default_conf['ask_strategy']['price_side'] = side
|
||||
default_conf['ask_strategy']['use_order_book'] = True
|
||||
default_conf['ask_strategy']['order_book_min'] = 1
|
||||
default_conf['ask_strategy']['order_book_max'] = 2
|
||||
# TODO: min/max is irrelevant for this test until refactoring
|
||||
pair = "ETH/BTC"
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_order_book', order_book_l2)
|
||||
ft = get_patched_freqtradebot(mocker, default_conf)
|
||||
rate = ft.get_sell_rate(pair, True)
|
||||
assert not log_has("Using cached sell rate for ETH/BTC.", caplog)
|
||||
assert isinstance(rate, float)
|
||||
assert rate == 0.043936
|
||||
assert rate == expected
|
||||
rate = ft.get_sell_rate(pair, False)
|
||||
assert rate == expected
|
||||
assert log_has("Using cached sell rate for ETH/BTC.", caplog)
|
||||
|
||||
|
||||
def test_startup_state(default_conf, mocker):
|
||||
@@ -3763,30 +3816,6 @@ def test_startup_trade_reinit(default_conf, edge_conf, mocker):
|
||||
assert reinit_mock.call_count == 0
|
||||
|
||||
|
||||
def test_process_i_am_alive(default_conf, mocker, caplog):
|
||||
patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
|
||||
|
||||
ftbot = get_patched_freqtradebot(mocker, default_conf)
|
||||
message = r"Bot heartbeat\. PID=.*"
|
||||
ftbot.process()
|
||||
assert log_has_re(message, caplog)
|
||||
assert ftbot._heartbeat_msg != 0
|
||||
|
||||
caplog.clear()
|
||||
# Message is not shown before interval is up
|
||||
ftbot.process()
|
||||
assert not log_has_re(message, caplog)
|
||||
|
||||
caplog.clear()
|
||||
# Set clock - 70 seconds
|
||||
ftbot._heartbeat_msg -= 70
|
||||
|
||||
ftbot.process()
|
||||
assert log_has_re(message, caplog)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("init_persistence")
|
||||
def test_sync_wallet_dry_run(mocker, default_conf, ticker, fee, limit_buy_order, caplog):
|
||||
default_conf['dry_run'] = True
|
||||
|
Reference in New Issue
Block a user