From 30fbe0c79c65d8875dafbef8593e86390acd5c8d Mon Sep 17 00:00:00 2001 From: "aezo.teo" Date: Sun, 14 Nov 2021 16:51:03 +0800 Subject: [PATCH 1/8] added is_short and short_trades to schema --- freqtrade/rpc/api_server/api_schemas.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/freqtrade/rpc/api_server/api_schemas.py b/freqtrade/rpc/api_server/api_schemas.py index ff1915fca..1cb596451 100644 --- a/freqtrade/rpc/api_server/api_schemas.py +++ b/freqtrade/rpc/api_server/api_schemas.py @@ -95,6 +95,7 @@ class Profit(BaseModel): avg_duration: str best_pair: str best_rate: float + short_trades: int winning_trades: int losing_trades: int @@ -154,6 +155,7 @@ class TradeSchema(BaseModel): trade_id: int pair: str is_open: bool + is_short: bool exchange: str amount: float amount_requested: float From 8df334515fcf2f897a6ac8e68d9005a48be1b22a Mon Sep 17 00:00:00 2001 From: "aezo.teo" Date: Sun, 14 Nov 2021 16:52:38 +0800 Subject: [PATCH 2/8] added logic for is_short and tests --- freqtrade/rpc/rpc.py | 8 ++++- tests/conftest_trades.py | 1 + tests/rpc/test_rpc_apiserver.py | 55 +++++++++++++++++---------------- 3 files changed, 37 insertions(+), 27 deletions(-) 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, } From 92997c85f934bba4a03193956bf3d3ee8381ef52 Mon Sep 17 00:00:00 2001 From: "aezo.teo" Date: Sun, 14 Nov 2021 17:37:31 +0800 Subject: [PATCH 3/8] adding sides for rate and 1 more test case --- freqtrade/rpc/rpc.py | 9 ++++++--- tests/rpc/test_rpc_apiserver.py | 16 +++++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 91f379430..950d67dd5 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -156,8 +156,9 @@ class RPC: # calculate profit and send message to user if trade.is_open: 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 (ExchangeError, PricingError): current_rate = NAN else: @@ -216,8 +217,9 @@ class RPC: for trade in trades: # calculate profit and send message to user 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 trade_percent = (100 * trade.calc_profit_ratio(current_rate)) @@ -578,8 +580,9 @@ class RPC: if not fully_canceled: # Get current rate and execute sell + 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) sell_reason = SellCheckTuple(sell_type=SellType.FORCE_SELL) self._freqtrade.execute_trade_exit(trade, current_rate, sell_reason) # ---- EOF def _exec_forcesell ---- diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 40580f1c9..162fb048a 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -829,11 +829,8 @@ def test_api_performance(botclient, fee): 'profit_ratio': -0.05570419, 'profit_abs': -0.1150375}] -# TODO-lev: @pytest.mark.parametrize('is_short,side', [ -# (True, "short"), -# (False, "long") -# ]) -def test_api_status(botclient, mocker, ticker, fee, markets): +@pytest.mark.parametrize('is_short', [True, False]) +def test_api_status(botclient, mocker, ticker, fee, markets, is_short): ftbot, client = botclient patch_get_signal(ftbot) mocker.patch.multiple( @@ -848,7 +845,7 @@ def test_api_status(botclient, mocker, ticker, fee, markets): rc = client_get(client, f"{BASE_URI}/status") assert_response(rc, 200) assert rc.json() == [] - create_mock_trades(fee, False) + create_mock_trades(fee, is_short) rc = client_get(client, f"{BASE_URI}/status") assert_response(rc) @@ -869,7 +866,7 @@ def test_api_status(botclient, mocker, ticker, fee, markets): 'profit_pct': ANY, 'profit_abs': ANY, 'profit_fiat': ANY, - 'current_rate': 1.099e-05, + 'current_rate': 1.098e-05 if is_short else 1.099e-05, 'open_date': ANY, 'open_timestamp': ANY, 'open_order': None, @@ -899,11 +896,12 @@ def test_api_status(botclient, mocker, ticker, fee, markets): 'fee_open_cost': None, 'fee_open_currency': None, 'is_open': True, + "is_short": is_short, 'max_rate': ANY, 'min_rate': ANY, - 'open_order_id': 'dry_run_buy_long_12345', + 'open_order_id': 'dry_run_buy_short_12345' if is_short else 'dry_run_buy_long_12345', 'open_rate_requested': ANY, - 'open_trade_value': 15.1668225, + 'open_trade_value': 15.0911775 if is_short else 15.1668225, 'sell_reason': None, 'sell_order_status': None, 'strategy': CURRENT_TEST_STRATEGY, From 22f7c0fdc6ac3568fea4fd6f88d776eca328d647 Mon Sep 17 00:00:00 2001 From: "aezo.teo" Date: Sun, 14 Nov 2021 21:04:24 +0800 Subject: [PATCH 4/8] updated test cases --- tests/rpc/test_rpc_apiserver.py | 16 ++++++++++------ tests/rpc/test_rpc_telegram.py | 11 ++++++----- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 162fb048a..1d07ab6b8 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -735,14 +735,16 @@ def test_api_profit(botclient, mocker, ticker, fee, markets, is_short): '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_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_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, @@ -896,7 +898,7 @@ def test_api_status(botclient, mocker, ticker, fee, markets, is_short): 'fee_open_cost': None, 'fee_open_currency': None, 'is_open': True, - "is_short": is_short, + "is_short": is_short, 'max_rate': ANY, 'min_rate': ANY, 'open_order_id': 'dry_run_buy_short_12345' if is_short else 'dry_run_buy_long_12345', @@ -974,8 +976,8 @@ def test_api_whitelist(botclient): "method": ["StaticPairList"] } - -def test_api_forcebuy(botclient, mocker, fee): +@pytest.mark.parametrize('is_short', [True, False]) +def test_api_forcebuy(botclient, mocker, fee, is_short): ftbot, client = botclient rc = client_post(client, f"{BASE_URI}/forcebuy", @@ -1004,6 +1006,7 @@ def test_api_forcebuy(botclient, mocker, fee): open_order_id="123456", open_date=datetime.utcnow(), is_open=False, + is_short=is_short, fee_close=fee.return_value, fee_open=fee.return_value, close_rate=0.265441, @@ -1052,11 +1055,12 @@ def test_api_forcebuy(botclient, mocker, fee): 'fee_open_cost': None, 'fee_open_currency': None, 'is_open': False, + 'is_short': is_short, 'max_rate': None, 'min_rate': None, 'open_order_id': '123456', 'open_rate_requested': None, - 'open_trade_value': 0.24605460, + 'open_trade_value': 0.2448274 if is_short else 0.24605460, 'sell_reason': None, 'sell_order_status': None, 'strategy': CURRENT_TEST_STRATEGY, diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 323eddd4d..620a6e92d 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -1261,8 +1261,8 @@ def test_edge_enabled(edge_conf, update, mocker) -> None: assert 'Winrate' not in msg_mock.call_args_list[0][0][0] -# TODO-lev: @pytest.mark.parametrize('is_short', [True, False]) -def test_telegram_trades(mocker, update, default_conf, fee): +@pytest.mark.parametrize('is_short', [True, False]) +def test_telegram_trades(mocker, update, default_conf, fee, is_short): telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf) @@ -1280,7 +1280,7 @@ def test_telegram_trades(mocker, update, default_conf, fee): assert "
" not in msg_mock.call_args_list[0][0][0]
     msg_mock.reset_mock()
 
-    create_mock_trades(fee, False)
+    create_mock_trades(fee, is_short)
 
     context = MagicMock()
     context.args = [5]
@@ -1290,8 +1290,9 @@ def test_telegram_trades(mocker, update, default_conf, fee):
     assert "Profit (" in msg_mock.call_args_list[0][0][0]
     assert "Close Date" in msg_mock.call_args_list[0][0][0]
     assert "
" in msg_mock.call_args_list[0][0][0]
-    assert bool(re.search(r"just now[ ]*XRP\/BTC \(#3\)  1.00% \(",
-                msg_mock.call_args_list[0][0][0]))
+    regex_pattern = r"just now[ ]*XRP\/BTC \(#3\)  -1.00% \(" if is_short else \
+                    r"just now[ ]*XRP\/BTC \(#3\)  1.00% \("
+    assert bool(re.search(regex_pattern, msg_mock.call_args_list[0][0][0]))
 
 
 @pytest.mark.parametrize('is_short', [True, False])

From 910259036508b08eedb2721061187d90965319aa Mon Sep 17 00:00:00 2001
From: Matthias 
Date: Sun, 14 Nov 2021 19:22:12 +0100
Subject: [PATCH 5/8] Improve tests by also having a "Mixed" case

---
 tests/conftest.py               | 18 +++++----
 tests/rpc/test_rpc_apiserver.py | 72 ++++++++++++++++++---------------
 tests/test_freqtradebot.py      |  2 +-
 3 files changed, 51 insertions(+), 41 deletions(-)

diff --git a/tests/conftest.py b/tests/conftest.py
index 60d620639..0fa7daf59 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -248,33 +248,35 @@ def patch_get_signal(
     freqtrade.exchange.refresh_latest_ohlcv = lambda p: None
 
 
-def create_mock_trades(fee, is_short: bool = False, use_db: bool = True):
+def create_mock_trades(fee, is_short: Optional[bool] = False, use_db: bool = True):
     """
     Create some fake trades ...
+    :param is_short: Optional bool, None creates a mix of long and short trades.
     """
     def add_trade(trade):
         if use_db:
             Trade.query.session.add(trade)
         else:
             LocalTrade.add_bt_trade(trade)
-
+    is_short1 = is_short if is_short is not None else True
+    is_short2 = is_short if is_short is not None else False
     # Simulate dry_run entries
-    trade = mock_trade_1(fee, is_short)
+    trade = mock_trade_1(fee, is_short1)
     add_trade(trade)
 
-    trade = mock_trade_2(fee, is_short)
+    trade = mock_trade_2(fee, is_short1)
     add_trade(trade)
 
-    trade = mock_trade_3(fee, is_short)
+    trade = mock_trade_3(fee, is_short2)
     add_trade(trade)
 
-    trade = mock_trade_4(fee, is_short)
+    trade = mock_trade_4(fee, is_short2)
     add_trade(trade)
 
-    trade = mock_trade_5(fee, is_short)
+    trade = mock_trade_5(fee, is_short2)
     add_trade(trade)
 
-    trade = mock_trade_6(fee, is_short)
+    trade = mock_trade_6(fee, is_short1)
     add_trade(trade)
 
     if use_db:
diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py
index 1d07ab6b8..597198458 100644
--- a/tests/rpc/test_rpc_apiserver.py
+++ b/tests/rpc/test_rpc_apiserver.py
@@ -699,7 +699,7 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):
     assert rc.json() == {"error": "Error querying /api/v1/edge: Edge is not enabled."}
 
 
-@pytest.mark.parametrize('is_short', [True, False])
+@pytest.mark.parametrize('is_short', [True, False, None])
 def test_api_profit(botclient, mocker, ticker, fee, markets, is_short):
     ftbot, client = botclient
     patch_get_signal(ftbot)
@@ -721,37 +721,44 @@ def test_api_profit(botclient, mocker, ticker, fee, markets, is_short):
     rc = client_get(client, f"{BASE_URI}/profit")
     assert_response(rc)
     # raise ValueError(rc.json())
-    assert rc.json() == {'avg_duration': ANY,
-                         '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': 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,
-                         'short_trades': 6 if is_short else 0,
-                         'winning_trades': 0 if is_short else 2,
-                         'losing_trades': 2 if is_short else 0,
-                         }
+    assert rc.json() == {
+        'avg_duration': ANY,
+        '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': 43.61269123 if is_short else -14.43790415
+        if is_short is None else -44.0631579,
+        'profit_all_fiat': 538398.67323435 if is_short else -178235.92673175
+        if is_short is None else -543959.6842755,
+        'profit_all_percent_mean': 66.41 if is_short else 0.08 if is_short is None else -66.41,
+        'profit_all_ratio_mean': 0.664109545 if is_short else 0.000835751666666662
+        if is_short is None else -0.6641100666666667,
+        'profit_all_percent_sum': 398.47 if is_short else 0.5 if is_short is None else -398.47,
+        'profit_all_ratio_sum': 3.98465727 if is_short else 0.005014509999999972
+        if is_short is None else -3.9846604,
+        'profit_all_percent': 4.36 if is_short else -1.44 if is_short is None else -4.41,
+        'profit_all_ratio': 0.043612222872799825 if is_short else -0.014437768014451796
+        if is_short is None else -0.044063014216106644,
+        'profit_closed_coin': -0.00673913 if is_short else -0.00542913
+        if is_short is None else 0.00073913,
+        'profit_closed_fiat': -83.19455985 if is_short else -67.02260985
+        if is_short is None else 9.124559849999999,
+        'profit_closed_ratio_mean': -0.0075 if is_short else 0.0025 if is_short is None else 0.0075,
+        'profit_closed_percent_mean': -0.75 if is_short else 0.25 if is_short is None else 0.75,
+        'profit_closed_ratio_sum': -0.015 if is_short else 0.005 if is_short is None else 0.015,
+        'profit_closed_percent_sum': -1.5 if is_short else 0.5 if is_short is None else 1.5,
+        'profit_closed_ratio': -6.739057628404269e-06 if is_short
+        else -5.429078808526421e-06 if is_short is None else 7.391275897987988e-07,
+        'profit_closed_percent': -0.0 if is_short else -0.0 if is_short is None else 0.0,
+        'trade_count': 6,
+        'closed_trade_count': 2,
+        'short_trades': 6 if is_short else 3 if is_short is None else 0,
+        'winning_trades': 0 if is_short else 1 if is_short is None else 2,
+        'losing_trades': 2 if is_short else 1 if is_short is None else 0,
+        }
 
 
 @pytest.mark.parametrize('is_short', [True, False])
@@ -976,6 +983,7 @@ def test_api_whitelist(botclient):
         "method": ["StaticPairList"]
     }
 
+
 @pytest.mark.parametrize('is_short', [True, False])
 def test_api_forcebuy(botclient, mocker, fee, is_short):
     ftbot, client = botclient
diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py
index e5a6195f3..019fa42c7 100644
--- a/tests/test_freqtradebot.py
+++ b/tests/test_freqtradebot.py
@@ -4317,7 +4317,7 @@ def test_sync_wallet_dry_run(mocker, default_conf_usdt, ticker_usdt, fee, limit_
 @pytest.mark.usefixtures("init_persistence")
 @pytest.mark.parametrize("is_short,buy_calls,sell_calls", [
     (False, 1, 2),
-    (True, 2, 1),
+    (True, 1, 2),
 ])
 def test_cancel_all_open_orders(mocker, default_conf_usdt, fee, limit_order, limit_order_open,
                                 is_short, buy_calls, sell_calls):

From ff6b1f442104d2bb6f346bea474d8d975617216d Mon Sep 17 00:00:00 2001
From: Sam Germain 
Date: Sun, 14 Nov 2021 21:01:08 -0600
Subject: [PATCH 6/8] Small changes

---
 tests/rpc/test_rpc_apiserver.py | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py
index 597198458..cf01c7221 100644
--- a/tests/rpc/test_rpc_apiserver.py
+++ b/tests/rpc/test_rpc_apiserver.py
@@ -602,6 +602,7 @@ 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
@@ -699,7 +700,11 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):
     assert rc.json() == {"error": "Error querying /api/v1/edge: Edge is not enabled."}
 
 
-@pytest.mark.parametrize('is_short', [True, False, None])
+@pytest.mark.parametrize('is_short', [
+    (True),
+    (False),
+    (None),
+])
 def test_api_profit(botclient, mocker, ticker, fee, markets, is_short):
     ftbot, client = botclient
     patch_get_signal(ftbot)
@@ -758,7 +763,7 @@ def test_api_profit(botclient, mocker, ticker, fee, markets, is_short):
         'short_trades': 6 if is_short else 3 if is_short is None else 0,
         'winning_trades': 0 if is_short else 1 if is_short is None else 2,
         'losing_trades': 2 if is_short else 1 if is_short is None else 0,
-        }
+    }
 
 
 @pytest.mark.parametrize('is_short', [True, False])

From c17c1611bd9a2fc145abfaa14de810e4597af6f3 Mon Sep 17 00:00:00 2001
From: "aezo.teo" 
Date: Tue, 16 Nov 2021 14:03:33 +0800
Subject: [PATCH 7/8] removed short_trades, updated schema, tests

---
 freqtrade/rpc/api_server/api_schemas.py |   1 -
 freqtrade/rpc/rpc.py                    |   5 -
 tests/rpc/test_rpc_apiserver.py         | 122 +++++++++++++++---------
 tests/rpc/test_rpc_telegram.py          |  14 +--
 4 files changed, 82 insertions(+), 60 deletions(-)

diff --git a/freqtrade/rpc/api_server/api_schemas.py b/freqtrade/rpc/api_server/api_schemas.py
index 1cb596451..113e93b5a 100644
--- a/freqtrade/rpc/api_server/api_schemas.py
+++ b/freqtrade/rpc/api_server/api_schemas.py
@@ -95,7 +95,6 @@ class Profit(BaseModel):
     avg_duration: str
     best_pair: str
     best_rate: float
-    short_trades: int
     winning_trades: int
     losing_trades: int
 
diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py
index 950d67dd5..4a44ebe77 100644
--- a/freqtrade/rpc/rpc.py
+++ b/freqtrade/rpc/rpc.py
@@ -358,7 +358,6 @@ class RPC:
         durations = []
         winning_trades = 0
         losing_trades = 0
-        short_trades = 0
 
         for trade in trades:
             current_rate: float = 0.0
@@ -391,9 +390,6 @@ 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
@@ -453,7 +449,6 @@ 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/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py
index cf01c7221..fa5e3a2bd 100644
--- a/tests/rpc/test_rpc_apiserver.py
+++ b/tests/rpc/test_rpc_apiserver.py
@@ -476,7 +476,7 @@ def test_api_count(botclient, mocker, ticker, fee, markets, is_short):
     assert rc.json()["max"] == 1
 
     # Create some test data
-    create_mock_trades(fee, is_short)
+    create_mock_trades(fee, is_short=is_short)
     rc = client_get(client, f"{BASE_URI}/count")
     assert_response(rc)
     assert rc.json()["current"] == 4
@@ -700,12 +700,45 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):
     assert rc.json() == {"error": "Error querying /api/v1/edge: Edge is not enabled."}
 
 
-@pytest.mark.parametrize('is_short', [
-    (True),
-    (False),
-    (None),
-])
-def test_api_profit(botclient, mocker, ticker, fee, markets, is_short):
+@pytest.mark.parametrize(
+        'is_short, best_pair, best_rate, profit_all_coin, profit_all_fiat,'
+        'profit_all_percent_mean, profit_all_ratio_mean, profit_all_percent_sum,'
+        'profit_all_ratio_sum, profit_all_percent, profit_all_ratio,'
+        'profit_closed_coin, profit_closed_fiat, profit_closed_ratio_mean,'
+        'profit_closed_percent_mean, profit_closed_ratio_sum,'
+        'profit_closed_percent_sum, profit_closed_ratio,'
+        'profit_closed_percent, winning_trades, losing_trades',
+        [
+            (True, 'ETC/BTC', -0.5, 43.61269123, 538398.67323435,
+             66.41, 0.664109545, 398.47,
+             3.98465727, 4.36, 0.043612222872799825,
+             -0.00673913, -83.19455985, -0.0075,
+             -0.75, -0.015,
+             -1.5, -6.739057628404269e-06,
+             -0.0, 0, 2),
+            (False, 'XRP/BTC', 1.0, -44.0631579, -543959.6842755,
+             -66.41, -0.6641100666666667, -398.47,
+             -3.9846604, -4.41, -0.044063014216106644,
+             0.00073913, 9.124559849999999, 0.0075,
+             0.75, 0.015,
+             1.5, 7.391275897987988e-07,
+             0.0, 2, 0),
+            (None, 'XRP/BTC', 1.0, -14.43790415, -178235.92673175,
+             0.08, 0.000835751666666662, 0.5,
+             0.005014509999999972, -1.44, -0.014437768014451796,
+             -0.00542913, -67.02260985, 0.0025,
+             0.25, 0.005,
+             0.5, -5.429078808526421e-06,
+             -0.0, 1, 1)
+        ])
+def test_api_profit(
+    botclient, mocker, ticker, fee, markets, is_short, best_pair, best_rate, profit_all_coin,
+    profit_all_fiat, profit_all_percent_mean, profit_all_ratio_mean, profit_all_percent_sum,
+    profit_all_ratio_sum, profit_all_percent, profit_all_ratio, profit_closed_coin,
+    profit_closed_fiat, profit_closed_ratio_mean, profit_closed_percent_mean,
+    profit_closed_ratio_sum, profit_closed_percent_sum, profit_closed_ratio,
+    profit_closed_percent, winning_trades, losing_trades
+):
     ftbot, client = botclient
     patch_get_signal(ftbot)
     mocker.patch.multiple(
@@ -728,41 +761,32 @@ def test_api_profit(botclient, mocker, ticker, fee, markets, is_short):
     # raise ValueError(rc.json())
     assert rc.json() == {
         'avg_duration': ANY,
-        'best_pair': 'ETC/BTC' if is_short else 'XRP/BTC',
-        'best_rate': -0.5 if is_short else 1.0,
+        'best_pair': best_pair,
+        'best_rate': best_rate,
         'first_trade_date': ANY,
         'first_trade_timestamp': ANY,
         'latest_trade_date': '5 minutes ago',
         'latest_trade_timestamp': ANY,
-        'profit_all_coin': 43.61269123 if is_short else -14.43790415
-        if is_short is None else -44.0631579,
-        'profit_all_fiat': 538398.67323435 if is_short else -178235.92673175
-        if is_short is None else -543959.6842755,
-        'profit_all_percent_mean': 66.41 if is_short else 0.08 if is_short is None else -66.41,
-        'profit_all_ratio_mean': 0.664109545 if is_short else 0.000835751666666662
-        if is_short is None else -0.6641100666666667,
-        'profit_all_percent_sum': 398.47 if is_short else 0.5 if is_short is None else -398.47,
-        'profit_all_ratio_sum': 3.98465727 if is_short else 0.005014509999999972
-        if is_short is None else -3.9846604,
-        'profit_all_percent': 4.36 if is_short else -1.44 if is_short is None else -4.41,
-        'profit_all_ratio': 0.043612222872799825 if is_short else -0.014437768014451796
-        if is_short is None else -0.044063014216106644,
-        'profit_closed_coin': -0.00673913 if is_short else -0.00542913
-        if is_short is None else 0.00073913,
-        'profit_closed_fiat': -83.19455985 if is_short else -67.02260985
-        if is_short is None else 9.124559849999999,
-        'profit_closed_ratio_mean': -0.0075 if is_short else 0.0025 if is_short is None else 0.0075,
-        'profit_closed_percent_mean': -0.75 if is_short else 0.25 if is_short is None else 0.75,
-        'profit_closed_ratio_sum': -0.015 if is_short else 0.005 if is_short is None else 0.015,
-        'profit_closed_percent_sum': -1.5 if is_short else 0.5 if is_short is None else 1.5,
-        'profit_closed_ratio': -6.739057628404269e-06 if is_short
-        else -5.429078808526421e-06 if is_short is None else 7.391275897987988e-07,
-        'profit_closed_percent': -0.0 if is_short else -0.0 if is_short is None else 0.0,
+        'profit_all_coin': profit_all_coin,
+        'profit_all_fiat': profit_all_fiat,
+        'profit_all_percent_mean': profit_all_percent_mean,
+        'profit_all_ratio_mean': profit_all_ratio_mean,
+        'profit_all_percent_sum': profit_all_percent_sum,
+        'profit_all_ratio_sum': profit_all_ratio_sum,
+        'profit_all_percent': profit_all_percent,
+        'profit_all_ratio': profit_all_ratio,
+        'profit_closed_coin': profit_closed_coin,
+        'profit_closed_fiat': profit_closed_fiat,
+        'profit_closed_ratio_mean': profit_closed_ratio_mean,
+        'profit_closed_percent_mean': profit_closed_percent_mean,
+        'profit_closed_ratio_sum': profit_closed_ratio_sum,
+        'profit_closed_percent_sum': profit_closed_percent_sum,
+        'profit_closed_ratio': profit_closed_ratio,
+        'profit_closed_percent': profit_closed_percent,
         'trade_count': 6,
         'closed_trade_count': 2,
-        'short_trades': 6 if is_short else 3 if is_short is None else 0,
-        'winning_trades': 0 if is_short else 1 if is_short is None else 2,
-        'losing_trades': 2 if is_short else 1 if is_short is None else 0,
+        'winning_trades': winning_trades,
+        'losing_trades': losing_trades,
     }
 
 
@@ -843,8 +867,12 @@ def test_api_performance(botclient, fee):
                           'profit_ratio': -0.05570419, 'profit_abs': -0.1150375}]
 
 
-@pytest.mark.parametrize('is_short', [True, False])
-def test_api_status(botclient, mocker, ticker, fee, markets, is_short):
+@pytest.mark.parametrize(
+    'is_short,current_rate,open_order_id,open_trade_value',
+    [(True, 1.098e-05, 'dry_run_buy_short_12345', 15.0911775),
+     (False, 1.099e-05, 'dry_run_buy_long_12345', 15.1668225)])
+def test_api_status(botclient, mocker, ticker, fee, markets, is_short,
+                    current_rate, open_order_id, open_trade_value):
     ftbot, client = botclient
     patch_get_signal(ftbot)
     mocker.patch.multiple(
@@ -859,7 +887,7 @@ def test_api_status(botclient, mocker, ticker, fee, markets, is_short):
     rc = client_get(client, f"{BASE_URI}/status")
     assert_response(rc, 200)
     assert rc.json() == []
-    create_mock_trades(fee, is_short)
+    create_mock_trades(fee, is_short=is_short)
 
     rc = client_get(client, f"{BASE_URI}/status")
     assert_response(rc)
@@ -880,7 +908,7 @@ def test_api_status(botclient, mocker, ticker, fee, markets, is_short):
         'profit_pct': ANY,
         'profit_abs': ANY,
         'profit_fiat': ANY,
-        'current_rate': 1.098e-05 if is_short else 1.099e-05,
+        'current_rate': current_rate,
         'open_date': ANY,
         'open_timestamp': ANY,
         'open_order': None,
@@ -913,9 +941,9 @@ def test_api_status(botclient, mocker, ticker, fee, markets, is_short):
         "is_short": is_short,
         'max_rate': ANY,
         'min_rate': ANY,
-        'open_order_id': 'dry_run_buy_short_12345' if is_short else 'dry_run_buy_long_12345',
+        'open_order_id': open_order_id,
         'open_rate_requested': ANY,
-        'open_trade_value': 15.0911775 if is_short else 15.1668225,
+        'open_trade_value': open_trade_value,
         'sell_reason': None,
         'sell_order_status': None,
         'strategy': CURRENT_TEST_STRATEGY,
@@ -989,8 +1017,8 @@ def test_api_whitelist(botclient):
     }
 
 
-@pytest.mark.parametrize('is_short', [True, False])
-def test_api_forcebuy(botclient, mocker, fee, is_short):
+# TODO -lev: add test for forcebuy (short) when feature is supported
+def test_api_forcebuy(botclient, mocker, fee):
     ftbot, client = botclient
 
     rc = client_post(client, f"{BASE_URI}/forcebuy",
@@ -1019,7 +1047,7 @@ def test_api_forcebuy(botclient, mocker, fee, is_short):
         open_order_id="123456",
         open_date=datetime.utcnow(),
         is_open=False,
-        is_short=is_short,
+        is_short=False,
         fee_close=fee.return_value,
         fee_open=fee.return_value,
         close_rate=0.265441,
@@ -1068,12 +1096,12 @@ def test_api_forcebuy(botclient, mocker, fee, is_short):
         'fee_open_cost': None,
         'fee_open_currency': None,
         'is_open': False,
-        'is_short': is_short,
+        'is_short': False,
         'max_rate': None,
         'min_rate': None,
         'open_order_id': '123456',
         'open_rate_requested': None,
-        'open_trade_value': 0.2448274 if is_short else 0.24605460,
+        'open_trade_value': 0.24605460,
         'sell_reason': None,
         'sell_order_status': None,
         'strategy': CURRENT_TEST_STRATEGY,
diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py
index 620a6e92d..07407d7f0 100644
--- a/tests/rpc/test_rpc_telegram.py
+++ b/tests/rpc/test_rpc_telegram.py
@@ -499,7 +499,7 @@ def test_telegram_stats(default_conf, update, ticker, ticker_sell_up, fee,
     msg_mock.reset_mock()
 
     # Create some test data
-    create_mock_trades(fee, is_short)
+    create_mock_trades(fee, is_short=is_short)
 
     telegram._stats(update=update, context=MagicMock())
     assert msg_mock.call_count == 1
@@ -1261,8 +1261,10 @@ def test_edge_enabled(edge_conf, update, mocker) -> None:
     assert 'Winrate' not in msg_mock.call_args_list[0][0][0]
 
 
-@pytest.mark.parametrize('is_short', [True, False])
-def test_telegram_trades(mocker, update, default_conf, fee, is_short):
+@pytest.mark.parametrize('is_short,regex_pattern',
+                         [(True, r"just now[ ]*XRP\/BTC \(#3\)  -1.00% \("),
+                          (False, r"just now[ ]*XRP\/BTC \(#3\)  1.00% \(")])
+def test_telegram_trades(mocker, update, default_conf, fee, is_short, regex_pattern):
 
     telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf)
 
@@ -1280,7 +1282,7 @@ def test_telegram_trades(mocker, update, default_conf, fee, is_short):
     assert "
" not in msg_mock.call_args_list[0][0][0]
     msg_mock.reset_mock()
 
-    create_mock_trades(fee, is_short)
+    create_mock_trades(fee, is_short=is_short)
 
     context = MagicMock()
     context.args = [5]
@@ -1290,8 +1292,6 @@ def test_telegram_trades(mocker, update, default_conf, fee, is_short):
     assert "Profit (" in msg_mock.call_args_list[0][0][0]
     assert "Close Date" in msg_mock.call_args_list[0][0][0]
     assert "
" in msg_mock.call_args_list[0][0][0]
-    regex_pattern = r"just now[ ]*XRP\/BTC \(#3\)  -1.00% \(" if is_short else \
-                    r"just now[ ]*XRP\/BTC \(#3\)  1.00% \("
     assert bool(re.search(regex_pattern, msg_mock.call_args_list[0][0][0]))
 
 
@@ -1306,7 +1306,7 @@ def test_telegram_delete_trade(mocker, update, default_conf, fee, is_short):
     assert "Trade-id not set." in msg_mock.call_args_list[0][0][0]
 
     msg_mock.reset_mock()
-    create_mock_trades(fee, is_short)
+    create_mock_trades(fee, is_short=is_short)
 
     context = MagicMock()
     context.args = [1]

From 1ba2e275b80980fadccf1765c824c3bb4b9ecf1c Mon Sep 17 00:00:00 2001
From: "aezo.teo" 
Date: Tue, 16 Nov 2021 14:29:40 +0800
Subject: [PATCH 8/8] updated test param format

---
 tests/rpc/test_rpc_apiserver.py | 117 ++++++++++++++++----------------
 1 file changed, 59 insertions(+), 58 deletions(-)

diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py
index fa5e3a2bd..4fe2f8daa 100644
--- a/tests/rpc/test_rpc_apiserver.py
+++ b/tests/rpc/test_rpc_apiserver.py
@@ -701,44 +701,45 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):
 
 
 @pytest.mark.parametrize(
-        'is_short, best_pair, best_rate, profit_all_coin, profit_all_fiat,'
-        'profit_all_percent_mean, profit_all_ratio_mean, profit_all_percent_sum,'
-        'profit_all_ratio_sum, profit_all_percent, profit_all_ratio,'
-        'profit_closed_coin, profit_closed_fiat, profit_closed_ratio_mean,'
-        'profit_closed_percent_mean, profit_closed_ratio_sum,'
-        'profit_closed_percent_sum, profit_closed_ratio,'
-        'profit_closed_percent, winning_trades, losing_trades',
-        [
-            (True, 'ETC/BTC', -0.5, 43.61269123, 538398.67323435,
-             66.41, 0.664109545, 398.47,
-             3.98465727, 4.36, 0.043612222872799825,
-             -0.00673913, -83.19455985, -0.0075,
-             -0.75, -0.015,
-             -1.5, -6.739057628404269e-06,
-             -0.0, 0, 2),
-            (False, 'XRP/BTC', 1.0, -44.0631579, -543959.6842755,
-             -66.41, -0.6641100666666667, -398.47,
-             -3.9846604, -4.41, -0.044063014216106644,
-             0.00073913, 9.124559849999999, 0.0075,
-             0.75, 0.015,
-             1.5, 7.391275897987988e-07,
-             0.0, 2, 0),
-            (None, 'XRP/BTC', 1.0, -14.43790415, -178235.92673175,
-             0.08, 0.000835751666666662, 0.5,
-             0.005014509999999972, -1.44, -0.014437768014451796,
-             -0.00542913, -67.02260985, 0.0025,
-             0.25, 0.005,
-             0.5, -5.429078808526421e-06,
-             -0.0, 1, 1)
-        ])
-def test_api_profit(
-    botclient, mocker, ticker, fee, markets, is_short, best_pair, best_rate, profit_all_coin,
-    profit_all_fiat, profit_all_percent_mean, profit_all_ratio_mean, profit_all_percent_sum,
-    profit_all_ratio_sum, profit_all_percent, profit_all_ratio, profit_closed_coin,
-    profit_closed_fiat, profit_closed_ratio_mean, profit_closed_percent_mean,
-    profit_closed_ratio_sum, profit_closed_percent_sum, profit_closed_ratio,
-    profit_closed_percent, winning_trades, losing_trades
-):
+    'is_short,expected',
+    [(
+        True,
+        {'best_pair': 'ETC/BTC', 'best_rate': -0.5, 'profit_all_coin': 43.61269123,
+         'profit_all_fiat': 538398.67323435, 'profit_all_percent_mean': 66.41,
+         'profit_all_ratio_mean': 0.664109545, 'profit_all_percent_sum': 398.47,
+         'profit_all_ratio_sum': 3.98465727, 'profit_all_percent': 4.36,
+         'profit_all_ratio': 0.043612222872799825, 'profit_closed_coin': -0.00673913,
+         'profit_closed_fiat': -83.19455985, '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': -6.739057628404269e-06,
+         'profit_closed_percent': -0.0, 'winning_trades': 0, 'losing_trades': 2}
+     ),
+     (
+        False,
+        {'best_pair': 'XRP/BTC', 'best_rate': 1.0, '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, 'winning_trades': 2, 'losing_trades': 0}
+     ),
+     (
+        None,
+        {'best_pair': 'XRP/BTC', 'best_rate': 1.0, 'profit_all_coin': -14.43790415,
+         'profit_all_fiat': -178235.92673175, 'profit_all_percent_mean': 0.08,
+         'profit_all_ratio_mean': 0.000835751666666662, 'profit_all_percent_sum': 0.5,
+         'profit_all_ratio_sum': 0.005014509999999972, 'profit_all_percent': -1.44,
+         'profit_all_ratio': -0.014437768014451796, 'profit_closed_coin': -0.00542913,
+         'profit_closed_fiat': -67.02260985, 'profit_closed_ratio_mean': 0.0025,
+         'profit_closed_percent_mean': 0.25, 'profit_closed_ratio_sum': 0.005,
+         'profit_closed_percent_sum': 0.5, 'profit_closed_ratio': -5.429078808526421e-06,
+         'profit_closed_percent': -0.0, 'winning_trades': 1, 'losing_trades': 1}
+     )
+     ])
+def test_api_profit(botclient, mocker, ticker, fee, markets, is_short, expected):
     ftbot, client = botclient
     patch_get_signal(ftbot)
     mocker.patch.multiple(
@@ -761,32 +762,32 @@ def test_api_profit(
     # raise ValueError(rc.json())
     assert rc.json() == {
         'avg_duration': ANY,
-        'best_pair': best_pair,
-        'best_rate': best_rate,
+        'best_pair': expected['best_pair'],
+        'best_rate': expected['best_rate'],
         'first_trade_date': ANY,
         'first_trade_timestamp': ANY,
         'latest_trade_date': '5 minutes ago',
         'latest_trade_timestamp': ANY,
-        'profit_all_coin': profit_all_coin,
-        'profit_all_fiat': profit_all_fiat,
-        'profit_all_percent_mean': profit_all_percent_mean,
-        'profit_all_ratio_mean': profit_all_ratio_mean,
-        'profit_all_percent_sum': profit_all_percent_sum,
-        'profit_all_ratio_sum': profit_all_ratio_sum,
-        'profit_all_percent': profit_all_percent,
-        'profit_all_ratio': profit_all_ratio,
-        'profit_closed_coin': profit_closed_coin,
-        'profit_closed_fiat': profit_closed_fiat,
-        'profit_closed_ratio_mean': profit_closed_ratio_mean,
-        'profit_closed_percent_mean': profit_closed_percent_mean,
-        'profit_closed_ratio_sum': profit_closed_ratio_sum,
-        'profit_closed_percent_sum': profit_closed_percent_sum,
-        'profit_closed_ratio': profit_closed_ratio,
-        'profit_closed_percent': profit_closed_percent,
+        'profit_all_coin': expected['profit_all_coin'],
+        'profit_all_fiat': expected['profit_all_fiat'],
+        'profit_all_percent_mean': expected['profit_all_percent_mean'],
+        'profit_all_ratio_mean': expected['profit_all_ratio_mean'],
+        'profit_all_percent_sum': expected['profit_all_percent_sum'],
+        'profit_all_ratio_sum': expected['profit_all_ratio_sum'],
+        'profit_all_percent': expected['profit_all_percent'],
+        'profit_all_ratio': expected['profit_all_ratio'],
+        'profit_closed_coin': expected['profit_closed_coin'],
+        'profit_closed_fiat': expected['profit_closed_fiat'],
+        'profit_closed_ratio_mean': expected['profit_closed_ratio_mean'],
+        'profit_closed_percent_mean': expected['profit_closed_percent_mean'],
+        'profit_closed_ratio_sum': expected['profit_closed_ratio_sum'],
+        'profit_closed_percent_sum': expected['profit_closed_percent_sum'],
+        'profit_closed_ratio': expected['profit_closed_ratio'],
+        'profit_closed_percent': expected['profit_closed_percent'],
         'trade_count': 6,
         'closed_trade_count': 2,
-        'winning_trades': winning_trades,
-        'losing_trades': losing_trades,
+        'winning_trades': expected['winning_trades'],
+        'losing_trades': expected['losing_trades'],
     }