Merge pull request #2982 from freqtrade/rate_side_optional

Rate side configurable
This commit is contained in:
hroff-1902
2020-03-04 16:07:08 +03:00
committed by GitHub
9 changed files with 222 additions and 122 deletions

View File

@@ -51,13 +51,13 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'open_date_hum': ANY,
'close_date': None,
'close_date_hum': None,
'open_rate': 1.099e-05,
'open_rate': 1.098e-05,
'close_rate': None,
'current_rate': 1.098e-05,
'amount': 90.99181074,
'current_rate': 1.099e-05,
'amount': 91.07468124,
'stake_amount': 0.001,
'close_profit': None,
'current_profit': -0.59,
'current_profit': -0.41,
'stop_loss': 0.0,
'initial_stop_loss': 0.0,
'initial_stop_loss_pct': None,
@@ -78,10 +78,10 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'open_date_hum': ANY,
'close_date': None,
'close_date_hum': None,
'open_rate': 1.099e-05,
'open_rate': 1.098e-05,
'close_rate': None,
'current_rate': ANY,
'amount': 90.99181074,
'amount': 91.07468124,
'stake_amount': 0.001,
'close_profit': None,
'current_profit': ANY,
@@ -121,7 +121,7 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None:
assert "Pair" in headers
assert 'instantly' == result[0][2]
assert 'ETH/BTC' in result[0][1]
assert '-0.59%' == result[0][3]
assert '-0.41%' == result[0][3]
# Test with fiatconvert
rpc._fiat_converter = CryptoToFiatConverter()
@@ -130,7 +130,7 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None:
assert "Pair" in headers
assert 'instantly' == result[0][2]
assert 'ETH/BTC' in result[0][1]
assert '-0.59% (-0.09)' == result[0][3]
assert '-0.41% (-0.06)' == result[0][3]
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_sell_rate',
MagicMock(side_effect=DependencyException(f"Pair 'ETH/BTC' not available")))
@@ -245,9 +245,9 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
assert prec_satoshi(stats['profit_closed_coin'], 6.217e-05)
assert prec_satoshi(stats['profit_closed_percent'], 6.2)
assert prec_satoshi(stats['profit_closed_fiat'], 0.93255)
assert prec_satoshi(stats['profit_all_coin'], 5.632e-05)
assert prec_satoshi(stats['profit_all_percent'], 2.81)
assert prec_satoshi(stats['profit_all_fiat'], 0.8448)
assert prec_satoshi(stats['profit_all_coin'], 5.802e-05)
assert prec_satoshi(stats['profit_all_percent'], 2.89)
assert prec_satoshi(stats['profit_all_fiat'], 0.8703)
assert stats['trade_count'] == 2
assert stats['first_trade_date'] == 'just now'
assert stats['latest_trade_date'] == 'just now'
@@ -668,7 +668,7 @@ def test_rpcforcebuy(mocker, default_conf, ticker, fee, limit_buy_order) -> None
trade = rpc._rpc_forcebuy(pair, None)
assert isinstance(trade, Trade)
assert trade.pair == pair
assert trade.open_rate == ticker()['ask']
assert trade.open_rate == ticker()['bid']
# Test buy duplicate
with pytest.raises(RPCException, match=r'position for ETH/BTC already open - id: 1'):

View File

@@ -426,20 +426,20 @@ def test_api_status(botclient, mocker, ticker, fee, markets):
rc = client_get(client, f"{BASE_URI}/status")
assert_response(rc)
assert len(rc.json) == 1
assert rc.json == [{'amount': 90.99181074,
assert rc.json == [{'amount': 91.07468124,
'base_currency': 'BTC',
'close_date': None,
'close_date_hum': None,
'close_profit': None,
'close_rate': None,
'current_profit': -0.59,
'current_rate': 1.098e-05,
'current_profit': -0.41,
'current_rate': 1.099e-05,
'initial_stop_loss': 0.0,
'initial_stop_loss_pct': None,
'open_date': ANY,
'open_date_hum': 'just now',
'open_order': '(limit buy rem=0.00000000)',
'open_rate': 1.099e-05,
'open_rate': 1.098e-05,
'pair': 'ETH/BTC',
'stake_amount': 0.001,
'stop_loss': 0.0,

View File

@@ -720,13 +720,13 @@ def test_forcesell_handle(default_conf, update, ticker, fee,
'exchange': 'Bittrex',
'pair': 'ETH/BTC',
'gain': 'profit',
'limit': 1.172e-05,
'amount': 90.99181073703367,
'limit': 1.173e-05,
'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.314e-05,
'profit_percent': 0.0629778,
'stake_currency': 'BTC',
'fiat_currency': 'USD',
'sell_reason': SellType.FORCE_SELL.value,
@@ -779,13 +779,13 @@ def test_forcesell_down_handle(default_conf, update, ticker, fee,
'exchange': 'Bittrex',
'pair': 'ETH/BTC',
'gain': 'loss',
'limit': 1.044e-05,
'amount': 90.99181073703367,
'limit': 1.043e-05,
'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.497e-05,
'profit_percent': -0.05482878,
'stake_currency': 'BTC',
'fiat_currency': 'USD',
'sell_reason': SellType.FORCE_SELL.value,
@@ -827,13 +827,13 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, mocker) -> None
'exchange': 'Bittrex',
'pair': 'ETH/BTC',
'gain': 'loss',
'limit': 1.098e-05,
'amount': 90.99181073703367,
'limit': 1.099e-05,
'amount': 91.07468123861567,
'order_type': 'limit',
'open_rate': 1.099e-05,
'current_rate': 1.098e-05,
'profit_amount': -5.91e-06,
'profit_percent': -0.00589291,
'open_rate': 1.098e-05,
'current_rate': 1.099e-05,
'profit_amount': -4.09e-06,
'profit_percent': -0.00408133,
'stake_currency': 'BTC',
'fiat_currency': 'USD',
'sell_reason': SellType.FORCE_SELL.value,

View File

@@ -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
@@ -906,20 +906,37 @@ 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, caplog, 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)
@@ -1317,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
@@ -1325,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={
@@ -1510,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:
@@ -2292,12 +2309,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_percent': 0.0620716,
'stake_currency': 'BTC',
'fiat_currency': 'USD',
'sell_reason': SellType.ROI.value,
@@ -2341,12 +2358,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_percent': -0.05392257,
'stake_currency': 'BTC',
'fiat_currency': 'USD',
'sell_reason': SellType.STOP_LOSS.value,
@@ -2397,12 +2414,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_percent': -0.01404051,
'stake_currency': 'BTC',
'fiat_currency': 'USD',
'sell_reason': SellType.STOP_LOSS.value,
@@ -2587,7 +2604,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]
@@ -2597,12 +2614,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_percent': 0.0620716,
'stake_currency': 'BTC',
'fiat_currency': 'USD',
'sell_reason': SellType.ROI.value,
@@ -3624,13 +3641,20 @@ 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, caplog, 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
@@ -3638,25 +3662,33 @@ def test_get_sell_rate(default_conf, mocker, caplog, ticker, order_book_l2) -> N
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 == 0.00001098
assert rate == expected
assert log_has("Using cached sell rate for ETH/BTC.", caplog)
caplog.clear()
@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 == 0.043936
assert rate == expected
assert log_has("Using cached sell rate for ETH/BTC.", caplog)