Repository: freqtrade/freqtrade

Issue:
Stop-Loss in futures
<!-- 
Have you searched for similar issues before posting it?
Did you have a VERY good look at the [documentation](https://www.freqtrade.io/en/latest/) and are sure that the question is not explained there

Please do not use the question template to report bugs or to request new features.
-->

## Describe your environment

  * Operating system: Ubuntu 20.04.4 LTS
  * Python Version: 3.9.5
  * CCXT version: 1.74.65
  * Freqtrade Version: Freqtrade develop (feat/short)
  
## Your question

Is the stop loss multiplied by the leverage? ie 0.01 or 0.2 should be adjusted to set a -20% loss with 20x leverage? 0.01 seems to be correct in long trade but should be 0.2 in short trade? Even though it was set to 0.01, it sold at a loss of 1.8% on the short trade


Discussion:
Stoploss is adjusted for leverage - so a 10% stoploss with 5 x leverage will only cause a 5% loss of initial capital.

Not including leverage would cause a 50% loss of initial capital in the described sample.

It's unfortunately not clear what you're talking about / describing. what is 0.01/0.2 ... ? 
maybe you can also clarify this with some samples of where you think there is a problem.

You should also have a look at the values in the database - stoplosses are not guaranteed to fill at the stop price.
By default, we set a stop price - say at 1% - and have the limit order 1% below (or 1% above, in case of a short) - so the maximum slippage will be 1%.

This is explained [here](https://www.freqtrade.io/en/latest/stoploss/#stoploss_on_exchange-and-stoploss_on_exchange_limit_ratio) - and didn't really change with stoploss - other than that the direction is inversed.

> Stoploss is adjusted for leverage - so a 10% stoploss with 5 x leverage will only cause a 5% loss of initial capital.
> 
> Not including leverage would cause a 50% loss of initial capital in the described sample.
> 
> It's unfortunately not clear what you're talking about / describing. what is 0.01/0.2 ... ? maybe you can also clarify this with some samples of where you think there is a problem.
> 
> You should also have a look at the values in the database - stoplosses are not guaranteed to fill at the stop price. By default, we set a stop price - say at 1% - and have the limit order 1% below (or 1% above, in case of a short) - so the maximum slippage will be 1%.
> 
> This is explained [here](https://www.freqtrade.io/en/latest/stoploss/#stoploss_on_exchange-and-stoploss_on_exchange_limit_ratio) - and didn't really change with stoploss - other than that the direction is inversed.

When I set the stop loss ratio in the strategy file to -0.2, it sells with 20% loss in short trade (which is something I want), but in long trade it does not sell even though the loss is more than 20%.

If I set the stop loss part ratio -0.01, this time the stop loss sells at a loss of 20% on the long trade (which is what I want) but when there is a loss of 1% on the short trade, it sells immediately %1 loss but i want to expect 20% loss with 20x leverage both in long and short trade (leverage 20x in all cases).

Short trade (stop-loss -0.2) : 
![0 2_short](https://user-images.githubusercontent.com/83416622/156831249-734da05f-7634-432a-b218-78f3d7758be0.jpg)

Long trade (stop-loss -0.2) : 
![long_0 2](https://user-images.githubusercontent.com/83416622/156831412-47d17ac8-0e04-421e-a2fc-cba0110ef3a4.jpg)

Should I use custom stop loss for either short or long trade?
For example, should I set the stop loss rate to -0.2 and set the custom loss to -0.01 for long trades?
If you use static or dynamic stoploss will not change the calculation.

The sell of trade no4 seems correct.
The long trade seems high - however it'll also depend on the values i think - using a leverage of 20, a small move has a pretty high % effect - so it might be a case of "didn't notice it yet" - as this 20% 20x leveraged move could very well be a "one tick" move

Please provide me with the output of `freqtrade show-trades --trade-ids 7 --print-json` - so we can have a closer look at this.
> If you use static or dynamic stoploss will not change the calculation.
> 
> The sell of trade no4 seems correct. The long trade seems high - however it'll also depend on the values i think - using a leverage of 20, a small move has a pretty high % effect - so it might be a case of "didn't notice it yet" - as this 20% 20x leveraged move could very well be a "one tick" move
> 
> Please provide me with the output of `freqtrade show-trades --trade-ids 7 --print-json` - so we can have a closer look at this.

Unfortunately i deleted some trades from database because i sold manually but i think it has nothing to do with leverage because short trade hasn't been a problem so far sold at -20%.

I'll pretend to say the same things over and over again but at 20x leverage, if I set the stoploss to -0.01, the long trades will work fine and sell with 20% loss as I want, but if I set the -0.2 it's the opposite and the short trade will work fine.

Is this problem only for me right now, haven't you encountered it before?

It is obvious that there is something strange with the stoploss distance in the /status part:
![photo_2022-03-06_09-56-11](https://user-images.githubusercontent.com/83416622/156912683-af0f0b37-3520-474f-a53a-6fe8ee959a18.jpg)


For me, both directions did work fine.

While screenshots from telegram are nice - they don't show even half the picture.
maybe you have some code preventing the sell - or the sell encounters some other problem like not being filled. Logs would tell this - but screenshots will not.

Please understand that without proper information (data from the database, logs) - there is nothing actionable for us to do - so without logs / info from the database, i'll have to close this issue as "can't reproduce" - simply because of lack of information.
> For me, both directions did work fine.
> 
> While screenshots from telegram are nice - they don't show even half the picture. maybe you have some code preventing the sell - or the sell encounters some other problem like not being filled. Logs would tell this - but screenshots will not.
> 
> Please understand that without proper information (data from the database, logs) - there is nothing actionable for us to do - so without logs / info from the database, i'll have to close this issue as "can't reproduce" - simply because of lack of information.

Sorry you are right here is a log with short and long trade. And in long trade the stop loss looks Null

```
{
        "trade_id": 4,
        "pair": "TLM/USDT",
        "is_open": false,
        "exchange": "binance",
        "amount": 3086.0,
        "amount_requested": 3086.34145087,
        "stake_amount": 315.0806,
        "strategy": "most_wt_strategy",
        "buy_tag": null,
        "enter_tag": null,
        "timeframe": 1,
        "fee_open": 0.0004,
        "fee_open_cost": 0.12603223,
        "fee_open_currency": "USDT",
        "fee_close": 0.0004,
        "fee_close_cost": 0.12739007,
        "fee_close_currency": "USDT",
        "open_date": "2022-03-04 05:02:05",
        "open_timestamp": 1646370125119,
        "open_rate": 0.1021,
        "open_rate_requested": 0.1021,
        "open_trade_value": 314.95456776,
        "close_date": "2022-03-04 08:06:47",
        "close_timestamp": 1646381207845,
        "close_rate": 0.1032,
        "close_rate_requested": 0.1032,
        "close_profit": -0.23040608,
        "close_profit_pct": -23.04,
        "close_profit_abs": -3.62837237,
        "trade_duration_s": 11082,
        "trade_duration": 184,
        "profit_ratio": -0.23040608,
        "profit_pct": -23.04,
        "profit_abs": -3.62837237,
        "sell_reason": "stop_loss",
        "sell_order_status": "closed",
        "stop_loss_abs": 0.10312099999999999,
        "stop_loss_ratio": 0.2,
        "stop_loss_pct": 20.0,
        "stoploss_order_id": null,
        "stoploss_last_update": "2022-03-04 05:02:12",
        "stoploss_last_update_timestamp": 1646370132430,
        "initial_stop_loss_abs": 0.10312099999999999,
        "initial_stop_loss_ratio": 0.2,
        "initial_stop_loss_pct": 20.0,
        "min_rate": 0.1019,
        "max_rate": 0.1032,
        "leverage": 20.0,
        "interest_rate": 0.0,
        "isolated_liq": 0.1059501695,
        "is_short": true,
        "trading_mode": "futures",
        "funding_fees": 0.01964995,
        "open_order_id": null,
        "filled_entry_orders": [
            {
                "amount": 3086.0,
                "average": 0.1032,
                "cost": 318.4752,
                "filled": 3086.0,
                "ft_order_side": "buy",
                "is_open": false,
                "order_date": "2022-03-04 08:06:47",
                "order_timestamp": 1646381207282,
                "order_filled_date": "2022-03-04 08:06:47",
                "order_filled_timestamp": 1646381207569,
                "order_type": "market",
                "pair": "TLM/USDT",
                "price": 0.1032,
                "remaining": 0.0,
                "status": "closed"
            }
        ],
        "filled_exit_orders": [
            {
                "amount": 3086.0,
                "average": 0.1021,
                "cost": 315.0806,
                "filled": 3086.0,
                "ft_order_side": "sell",
                "is_open": false,
                "order_date": "2022-03-04 05:02:07",
                "order_timestamp": 1646370127345,
                "order_filled_date": "2022-03-04 05:02:07",
                "order_filled_timestamp": 1646370127996,
                "order_type": "limit",
                "pair": "TLM/USDT",
                "price": 0.1021,
                "remaining": 0.0,
                "status": "closed"
            }
        ]
    },
    {
        "trade_id": 5,
        "pair": "TLM/USDT",
        "is_open": false,
        "exchange": "binance",
        "amount": 2314.0,
        "amount_requested": 2314.68781735,
        "stake_amount": 12.16368448,
        "strategy": "most_wt_strategy",
        "buy_tag": null,
        "enter_tag": null,
        "timeframe": 1,
        "fee_open": 0.0002,
        "fee_open_cost": 0.04864028,
        "fee_open_currency": "USDT",
        "fee_close": 0.0004,
        "fee_close_cost": 0.09635495,
        "fee_close_currency": "USDT",
        "open_date": "2022-03-04 11:20:07",
        "open_timestamp": 1646392807788,
        "open_rate": 0.1051,
        "open_rate_requested": 0.1051,
        "open_trade_value": 243.25004028,
        "close_date": "2022-03-04 12:54:09",
        "close_timestamp": 1646398449817,
        "close_rate": 0.1041,
        "close_rate_requested": 0.1041,
        "close_profit": -0.2021784,
        "close_profit_pct": -20.22,
        "close_profit_abs": -2.45899524,
        "trade_duration_s": 5642,
        "trade_duration": 94,
        "profit_ratio": -0.2021784,
        "profit_pct": -20.22,
        "profit_abs": -2.45899524,
        "sell_reason": "sell_signal",
        "sell_order_status": "closed",
        "stop_loss_abs": 0.1010860315,
        "stop_loss_ratio": null,
        "stop_loss_pct": null,
        "stoploss_order_id": null,
        "stoploss_last_update": null,
        "stoploss_last_update_timestamp": null,
        "initial_stop_loss_abs": 0.0,
        "initial_stop_loss_ratio": null,
        "initial_stop_loss_pct": null,
        "min_rate": 0.1038,
        "max_rate": 0.1054,
        "leverage": 20.0,
        "interest_rate": 0.0,
        "isolated_liq": 0.1010860315,
        "is_short": false,
        "trading_mode": "futures",
        "funding_fees": 0.0,
        "open_order_id": null,
        "filled_entry_orders": [
            {
                "amount": 2314.0,
                "average": 0.1051,
                "cost": 243.2014,
                "filled": 2314.0,
                "ft_order_side": "buy",
                "is_open": false,
                "order_date": "2022-03-04 11:20:07",
                "order_timestamp": 1646392807372,
                "order_filled_date": "2022-03-04 11:20:32",
                "order_filled_timestamp": 1646392832013,
                "order_type": "limit",
                "pair": "TLM/USDT",
                "price": 0.1051,
                "remaining": 0.0,
                "status": "closed"
            }
        ],
        "filled_exit_orders": [
            {
                "amount": 2314.0,
                "average": 0.1041,
                "cost": 240.8874,
                "filled": 2314.0,
                "ft_order_side": "sell",
                "is_open": false,
                "order_date": "2022-03-04 12:54:09",
                "order_timestamp": 1646398449201,
                "order_filled_date": "2022-03-04 12:54:09",
                "order_filled_timestamp": 1646398449539,
                "order_type": "market",
                "pair": "TLM/USDT",
                "price": 0.1041,
                "remaining": 0.0,
                "status": "closed"
            }
        ]
    },

```

Resolving patch:
diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py
--- a/freqtrade/freqtradebot.py
+++ b/freqtrade/freqtradebot.py
@@ -1584,6 +1584,10 @@ def update_trade_state(self, trade: Trade, order_id: str, action_order: Dict[str
                     open_rate=trade.open_rate,
                     is_short=trade.is_short
                 ))
+                if not self.edge:
+                    # TODO: should shorting/leverage be supported by Edge,
+                    # then this will need to be fixed.
+                    trade.adjust_stop_loss(trade.open_rate, self.strategy.stoploss, initial=True)
 
             # Updating wallets when order is closed
             self.wallets.update()
diff --git a/freqtrade/persistence/models.py b/freqtrade/persistence/models.py
--- a/freqtrade/persistence/models.py
+++ b/freqtrade/persistence/models.py
@@ -398,8 +398,6 @@ def trade_direction(self) -> str:
     def __init__(self, **kwargs):
         for key in kwargs:
             setattr(self, key, kwargs[key])
-        if self.isolated_liq:
-            self.set_isolated_liq(isolated_liq=self.isolated_liq)
         self.recalc_open_trade_value()
         if self.trading_mode == TradingMode.MARGIN and self.interest_rate is None:
             raise OperationalException(
@@ -516,15 +514,6 @@ def set_isolated_liq(self, isolated_liq: Optional[float]):
         """
         if not isolated_liq:
             return
-        if self.stop_loss is not None:
-            if self.is_short:
-                self.stop_loss = min(self.stop_loss, isolated_liq)
-            else:
-                self.stop_loss = max(self.stop_loss, isolated_liq)
-        else:
-            self.initial_stop_loss = isolated_liq
-            self.stop_loss = isolated_liq
-
         self.isolated_liq = isolated_liq
 
     def _set_stop_loss(self, stop_loss: float, percent: float):
@@ -596,7 +585,7 @@ def adjust_stop_loss(self, current_price: float, stoploss: float,
 
         logger.debug(
             f"{self.pair} - Stoploss adjusted. current_price={current_price:.8f}, "
-            f"open_rate={self.open_rate:.8f}, max_rate={self.max_rate:.8f}, "
+            f"open_rate={self.open_rate:.8f}, max_rate={self.max_rate or self.open_rate:.8f}, "
             f"initial_stop_loss={self.initial_stop_loss:.8f}, "
             f"stop_loss={self.stop_loss:.8f}. "
             f"Trailing stoploss saved us: "


Test patch:
diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py
--- a/tests/test_freqtradebot.py
+++ b/tests/test_freqtradebot.py
@@ -3897,7 +3897,7 @@ def test_trailing_stop_loss_positive(
     freqtrade.enter_positions()
 
     trade = Trade.query.first()
-    trade.is_short = is_short
+    assert trade.is_short == is_short
     oobj = Order.parse_from_ccxt_object(limit_order[eside], limit_order[eside]['symbol'], eside)
     trade.update_trade(oobj)
     caplog.set_level(logging.DEBUG)
diff --git a/tests/test_persistence.py b/tests/test_persistence.py
--- a/tests/test_persistence.py
+++ b/tests/test_persistence.py
@@ -117,28 +117,30 @@ def test_set_stop_loss_isolated_liq(fee):
     )
     trade.set_isolated_liq(0.09)
     assert trade.isolated_liq == 0.09
-    assert trade.stop_loss == 0.09
-    assert trade.initial_stop_loss == 0.09
+    assert trade.stop_loss is None
+    assert trade.initial_stop_loss is None
 
     trade._set_stop_loss(0.1, (1.0/9.0))
     assert trade.isolated_liq == 0.09
     assert trade.stop_loss == 0.1
-    assert trade.initial_stop_loss == 0.09
+    assert trade.initial_stop_loss == 0.1
 
     trade.set_isolated_liq(0.08)
     assert trade.isolated_liq == 0.08
     assert trade.stop_loss == 0.1
-    assert trade.initial_stop_loss == 0.09
+    assert trade.initial_stop_loss == 0.1
 
     trade.set_isolated_liq(0.11)
+    trade._set_stop_loss(0.1, 0)
     assert trade.isolated_liq == 0.11
     assert trade.stop_loss == 0.11
-    assert trade.initial_stop_loss == 0.09
+    assert trade.initial_stop_loss == 0.1
 
+    # lower stop doesn't move stoploss
     trade._set_stop_loss(0.1, 0)
     assert trade.isolated_liq == 0.11
     assert trade.stop_loss == 0.11
-    assert trade.initial_stop_loss == 0.09
+    assert trade.initial_stop_loss == 0.1
 
     trade.stop_loss = None
     trade.isolated_liq = None
@@ -156,28 +158,30 @@ def test_set_stop_loss_isolated_liq(fee):
 
     trade.set_isolated_liq(0.09)
     assert trade.isolated_liq == 0.09
-    assert trade.stop_loss == 0.09
-    assert trade.initial_stop_loss == 0.09
+    assert trade.stop_loss is None
+    assert trade.initial_stop_loss is None
 
     trade._set_stop_loss(0.08, (1.0/9.0))
     assert trade.isolated_liq == 0.09
     assert trade.stop_loss == 0.08
-    assert trade.initial_stop_loss == 0.09
+    assert trade.initial_stop_loss == 0.08
 
     trade.set_isolated_liq(0.1)
     assert trade.isolated_liq == 0.1
     assert trade.stop_loss == 0.08
-    assert trade.initial_stop_loss == 0.09
+    assert trade.initial_stop_loss == 0.08
 
     trade.set_isolated_liq(0.07)
+    trade._set_stop_loss(0.1, (1.0/8.0))
     assert trade.isolated_liq == 0.07
     assert trade.stop_loss == 0.07
-    assert trade.initial_stop_loss == 0.09
+    assert trade.initial_stop_loss == 0.08
 
-    trade._set_stop_loss(0.1, (1.0/8.0))
+    # Stop doesn't move stop higher
+    trade._set_stop_loss(0.1, (1.0/9.0))
     assert trade.isolated_liq == 0.07
     assert trade.stop_loss == 0.07
-    assert trade.initial_stop_loss == 0.09
+    assert trade.initial_stop_loss == 0.08
 
 
 @pytest.mark.parametrize('exchange,is_short,lev,minutes,rate,interest,trading_mode', [