diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index e2b655651..91f379430 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -356,6 +356,7 @@ class RPC: durations = [] winning_trades = 0 losing_trades = 0 + short_trades = 0 for trade in trades: current_rate: float = 0.0 @@ -376,8 +377,9 @@ class RPC: else: # Get current rate try: + closing_side = "buy" if trade.is_short else "sell" current_rate = self._freqtrade.exchange.get_rate( - trade.pair, refresh=False, side="sell") + trade.pair, refresh=False, side=closing_side) except (PricingError, ExchangeError): current_rate = NAN profit_ratio = trade.calc_profit_ratio(rate=current_rate) @@ -387,6 +389,9 @@ class RPC: ) profit_all_ratio.append(profit_ratio) + if trade.is_short: + short_trades += 1 + best_pair = Trade.get_best_pair(start_date) # Prepare data to display @@ -446,6 +451,7 @@ class RPC: 'avg_duration': str(timedelta(seconds=sum(durations) / num)).split('.')[0], 'best_pair': best_pair[0] if best_pair else '', 'best_rate': round(best_pair[1] * 100, 2) if best_pair else 0, + 'short_trades': short_trades, 'winning_trades': winning_trades, 'losing_trades': losing_trades, } diff --git a/tests/conftest_trades.py b/tests/conftest_trades.py index dcd5e70df..0ad01e72f 100644 --- a/tests/conftest_trades.py +++ b/tests/conftest_trades.py @@ -317,6 +317,7 @@ def mock_trade_6(fee, is_short: bool): buy_tag='TEST2', open_order_id=f"prod_sell_{direc(is_short)}_6", timeframe=5, + is_short=is_short ) o = Order.parse_from_ccxt_object(mock_order_6(is_short), 'LTC/BTC', enter_side(is_short)) trade.orders.append(o) diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index e0e73f6f1..40580f1c9 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -571,7 +571,7 @@ def test_api_trades(botclient, mocker, fee, markets, is_short): assert rc.json()['trades_count'] == 0 assert rc.json()['total_trades'] == 0 - create_mock_trades(fee, is_short) + create_mock_trades(fee, is_short=is_short) Trade.query.session.flush() rc = client_get(client, f"{BASE_URI}/trades") @@ -579,6 +579,7 @@ def test_api_trades(botclient, mocker, fee, markets, is_short): assert len(rc.json()['trades']) == 2 assert rc.json()['trades_count'] == 2 assert rc.json()['total_trades'] == 2 + assert rc.json()['trades'][0]['is_short'] == is_short rc = client_get(client, f"{BASE_URI}/trades?limit=1") assert_response(rc) assert len(rc.json()['trades']) == 1 @@ -601,10 +602,10 @@ def test_api_trade_single(botclient, mocker, fee, ticker, markets, is_short): create_mock_trades(fee, is_short=is_short) Trade.query.session.flush() - rc = client_get(client, f"{BASE_URI}/trade/3") assert_response(rc) assert rc.json()['trade_id'] == 3 + assert rc.json()['is_short'] == is_short @pytest.mark.parametrize('is_short', [True, False]) @@ -623,7 +624,7 @@ def test_api_delete_trade(botclient, mocker, fee, markets, is_short): # Error - trade won't exist yet. assert_response(rc, 502) - create_mock_trades(fee, False) + create_mock_trades(fee, is_short=is_short) ftbot.strategy.order_types['stoploss_on_exchange'] = True trades = Trade.query.all() @@ -698,8 +699,8 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets): assert rc.json() == {"error": "Error querying /api/v1/edge: Edge is not enabled."} -# TODO-lev: @pytest.mark.parametrize('is_short', [True, False]) -def test_api_profit(botclient, mocker, ticker, fee, markets): +@pytest.mark.parametrize('is_short', [True, False]) +def test_api_profit(botclient, mocker, ticker, fee, markets, is_short): ftbot, client = botclient patch_get_signal(ftbot) mocker.patch.multiple( @@ -714,38 +715,40 @@ def test_api_profit(botclient, mocker, ticker, fee, markets): assert_response(rc, 200) assert rc.json()['trade_count'] == 0 - create_mock_trades(fee, False) + create_mock_trades(fee, is_short=is_short) # Simulate fulfilled LIMIT_BUY order for trade rc = client_get(client, f"{BASE_URI}/profit") assert_response(rc) + # raise ValueError(rc.json()) assert rc.json() == {'avg_duration': ANY, - 'best_pair': 'XRP/BTC', - 'best_rate': 1.0, + 'best_pair': 'ETC/BTC' if is_short else 'XRP/BTC', + 'best_rate': -0.5 if is_short else 1.0, 'first_trade_date': ANY, 'first_trade_timestamp': ANY, 'latest_trade_date': '5 minutes ago', 'latest_trade_timestamp': ANY, - 'profit_all_coin': -44.0631579, - 'profit_all_fiat': -543959.6842755, - 'profit_all_percent_mean': -66.41, - 'profit_all_ratio_mean': -0.6641100666666667, - 'profit_all_percent_sum': -398.47, - 'profit_all_ratio_sum': -3.9846604, - 'profit_all_percent': -4.41, - 'profit_all_ratio': -0.044063014216106644, - 'profit_closed_coin': 0.00073913, - 'profit_closed_fiat': 9.124559849999999, - 'profit_closed_ratio_mean': 0.0075, - 'profit_closed_percent_mean': 0.75, - 'profit_closed_ratio_sum': 0.015, - 'profit_closed_percent_sum': 1.5, - 'profit_closed_ratio': 7.391275897987988e-07, - 'profit_closed_percent': 0.0, + 'profit_all_coin': 43.61269123 if is_short else -44.0631579, + 'profit_all_fiat': 538398.67323435 if is_short else -543959.6842755, + 'profit_all_percent_mean': 66.41 if is_short else -66.41, + 'profit_all_ratio_mean': 0.664109545 if is_short else -0.6641100666666667, + 'profit_all_percent_sum': 398.47 if is_short else -398.47, + 'profit_all_ratio_sum': 3.98465727 if is_short else -3.9846604, + 'profit_all_percent': 4.36 if is_short else -4.41, + 'profit_all_ratio': 0.043612222872799825 if is_short else -0.044063014216106644, + 'profit_closed_coin': -0.00673913 if is_short else 0.00073913, + 'profit_closed_fiat': -83.19455985 if is_short else 9.124559849999999, + 'profit_closed_ratio_mean': -0.0075 if is_short else 0.0075, + 'profit_closed_percent_mean': -0.75 if is_short else 0.75, + 'profit_closed_ratio_sum': -0.015 if is_short else 0.015, + 'profit_closed_percent_sum': -1.5 if is_short else 1.5, + 'profit_closed_ratio': -6.739057628404269e-06 if is_short else 7.391275897987988e-07, + 'profit_closed_percent': -0.0 if is_short else 0.0, 'trade_count': 6, 'closed_trade_count': 2, - 'winning_trades': 2, - 'losing_trades': 0, + 'short_trades': 6 if is_short else 0, + 'winning_trades': 0 if is_short else 2, + 'losing_trades': 2 if is_short else 0, }