We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
stoploss_from_open has some ambiguous with leverage
<!-- 
Have you searched for similar issues before posting it?

If you have discovered a bug in the bot, please [search the issue tracker](https://github.com/freqtrade/freqtrade/issues?q=is%3Aissue). 
If it hasn't been reported, please create a new issue.

Please do not use bug reports to request new features.
-->

## Describe your environment

  * Operating system: ____ Linux
  * Python Version: _____ (`python -V`) 3.10
  * CCXT version: _____ (`pip freeze | grep ccxt`) 1.95
  * Freqtrade Version: ____ (`freqtrade -V` or `docker compose run --rm freqtrade -V` for Freqtrade running in docker)
  
Note: All issues other than enhancement requests will be closed without further comment if the above template is deleted or not filled out.

## Describe the problem:

In the doc explanation,  profit and stoploss is calculated with leverage.

And this function `stoploss_from_open` (in freqtrade/strategy/strategy_helper.py)  may wrong when enter short with leverage.  Because it's profit_rate may large than 1 , and  but open_relative_stop still less than 1, and stoploss be always negative, and function return 0.0. But in fact, it has positive profit.

*Explain the problem you have encountered*

### Steps to reproduce:

  1. _____
  2. _____
  3. _____
  
### Observed Results:

  * What happened?  
       stoploss_from_open may have  ambiguous  when used leverage
  * What did you expect to happen?
       In function dive leverage,  or argument explicitly explanates  without leverage
### Relevant code exceptions or logs
``` Python
              def stoploss_from_open(
                  open_relative_stop: float,
                  current_profit: float,
                  is_short: bool = False
                  ) -> float:
                  """
                  Given the current profit, and a desired stop loss value relative to the open price,
                  return a stop loss value that is relative to the current price, and which can be
                  returned from `custom_stoploss`.
              
                  The requested stop can be positive for a stop above the open price, or negative for
                  a stop below the open price. The return value is always >= 0.
              
                  Returns 0 if the resulting stop price would be above/below (longs/shorts) the current price
              
                  :param open_relative_stop: Desired stop loss percentage relative to open price
                  :param current_profit: The current profit percentage
                  :param is_short: When true, perform the calculation for short instead of long
                  :return: Stop loss value relative to current price
                  """
              
                  # formula is undefined for current_profit -1 (longs) or 1 (shorts), return maximum value
                  if (current_profit == -1 and not is_short) or (is_short and current_profit == 1):
                      return 1
              
                  if is_short is True:
                      stoploss = -1 + ((1 - open_relative_stop) / (1 - current_profit))
                  else:
                      stoploss = 1 - ((1 + open_relative_stop) / (1 + current_profit))
              
                  # negative stoploss values indicate the requested stop price is higher/lower
                  # (long/short) than the current price
                  return max(stoploss, 0.0)
```
Note: Please copy/paste text of the messages, no screenshots of logs please.

  ```
  // paste your log here
  ```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `freqtrade/strategy/strategy_helper.py`
Content:
```
1 from typing import Optional
2 
3 import pandas as pd
4 
5 from freqtrade.exchange import timeframe_to_minutes
6 
7 
8 def merge_informative_pair(dataframe: pd.DataFrame, informative: pd.DataFrame,
9                            timeframe: str, timeframe_inf: str, ffill: bool = True,
10                            append_timeframe: bool = True,
11                            date_column: str = 'date',
12                            suffix: Optional[str] = None) -> pd.DataFrame:
13     """
14     Correctly merge informative samples to the original dataframe, avoiding lookahead bias.
15 
16     Since dates are candle open dates, merging a 15m candle that starts at 15:00, and a
17     1h candle that starts at 15:00 will result in all candles to know the close at 16:00
18     which they should not know.
19 
20     Moves the date of the informative pair by 1 time interval forward.
21     This way, the 14:00 1h candle is merged to 15:00 15m candle, since the 14:00 1h candle is the
22     last candle that's closed at 15:00, 15:15, 15:30 or 15:45.
23 
24     Assuming inf_tf = '1d' - then the resulting columns will be:
25     date_1d, open_1d, high_1d, low_1d, close_1d, rsi_1d
26 
27     :param dataframe: Original dataframe
28     :param informative: Informative pair, most likely loaded via dp.get_pair_dataframe
29     :param timeframe: Timeframe of the original pair sample.
30     :param timeframe_inf: Timeframe of the informative pair sample.
31     :param ffill: Forwardfill missing values - optional but usually required
32     :param append_timeframe: Rename columns by appending timeframe.
33     :param date_column: A custom date column name.
34     :param suffix: A string suffix to add at the end of the informative columns. If specified,
35                    append_timeframe must be false.
36     :return: Merged dataframe
37     :raise: ValueError if the secondary timeframe is shorter than the dataframe timeframe
38     """
39 
40     minutes_inf = timeframe_to_minutes(timeframe_inf)
41     minutes = timeframe_to_minutes(timeframe)
42     if minutes == minutes_inf:
43         # No need to forwardshift if the timeframes are identical
44         informative['date_merge'] = informative[date_column]
45     elif minutes < minutes_inf:
46         # Subtract "small" timeframe so merging is not delayed by 1 small candle
47         # Detailed explanation in https://github.com/freqtrade/freqtrade/issues/4073
48         informative['date_merge'] = (
49             informative[date_column] + pd.to_timedelta(minutes_inf, 'm') -
50             pd.to_timedelta(minutes, 'm')
51         )
52     else:
53         raise ValueError("Tried to merge a faster timeframe to a slower timeframe."
54                          "This would create new rows, and can throw off your regular indicators.")
55 
56     # Rename columns to be unique
57     date_merge = 'date_merge'
58     if suffix and append_timeframe:
59         raise ValueError("You can not specify `append_timeframe` as True and a `suffix`.")
60     elif append_timeframe:
61         date_merge = f'date_merge_{timeframe_inf}'
62         informative.columns = [f"{col}_{timeframe_inf}" for col in informative.columns]
63 
64     elif suffix:
65         date_merge = f'date_merge_{suffix}'
66         informative.columns = [f"{col}_{suffix}" for col in informative.columns]
67 
68     # Combine the 2 dataframes
69     # all indicators on the informative sample MUST be calculated before this point
70     if ffill:
71         # https://pandas.pydata.org/docs/user_guide/merging.html#timeseries-friendly-merging
72         # merge_ordered - ffill method is 2.5x faster than seperate ffill()
73         dataframe = pd.merge_ordered(dataframe, informative, fill_method="ffill", left_on='date',
74                                      right_on=date_merge, how='left')
75     else:
76         dataframe = pd.merge(dataframe, informative, left_on='date',
77                              right_on=date_merge, how='left')
78     dataframe = dataframe.drop(date_merge, axis=1)
79 
80     # if ffill:
81     #     dataframe = dataframe.ffill()
82 
83     return dataframe
84 
85 
86 def stoploss_from_open(
87     open_relative_stop: float,
88     current_profit: float,
89     is_short: bool = False
90 ) -> float:
91     """
92 
93     Given the current profit, and a desired stop loss value relative to the open price,
94     return a stop loss value that is relative to the current price, and which can be
95     returned from `custom_stoploss`.
96 
97     The requested stop can be positive for a stop above the open price, or negative for
98     a stop below the open price. The return value is always >= 0.
99 
100     Returns 0 if the resulting stop price would be above/below (longs/shorts) the current price
101 
102     :param open_relative_stop: Desired stop loss percentage relative to open price
103     :param current_profit: The current profit percentage
104     :param is_short: When true, perform the calculation for short instead of long
105     :return: Stop loss value relative to current price
106     """
107 
108     # formula is undefined for current_profit -1 (longs) or 1 (shorts), return maximum value
109     if (current_profit == -1 and not is_short) or (is_short and current_profit == 1):
110         return 1
111 
112     if is_short is True:
113         stoploss = -1 + ((1 - open_relative_stop) / (1 - current_profit))
114     else:
115         stoploss = 1 - ((1 + open_relative_stop) / (1 + current_profit))
116 
117     # negative stoploss values indicate the requested stop price is higher/lower
118     # (long/short) than the current price
119     return max(stoploss, 0.0)
120 
121 
122 def stoploss_from_absolute(stop_rate: float, current_rate: float, is_short: bool = False) -> float:
123     """
124     Given current price and desired stop price, return a stop loss value that is relative to current
125     price.
126 
127     The requested stop can be positive for a stop above the open price, or negative for
128     a stop below the open price. The return value is always >= 0.
129 
130     Returns 0 if the resulting stop price would be above the current price.
131 
132     :param stop_rate: Stop loss price.
133     :param current_rate: Current asset price.
134     :param is_short: When true, perform the calculation for short instead of long
135     :return: Positive stop loss value relative to current price
136     """
137 
138     # formula is undefined for current_rate 0, return maximum value
139     if current_rate == 0:
140         return 1
141 
142     stoploss = 1 - (stop_rate / current_rate)
143     if is_short:
144         stoploss = -stoploss
145 
146     # negative stoploss values indicate the requested stop price is higher/lower
147     # (long/short) than the current price
148     # shorts can yield stoploss values higher than 1, so limit that as well
149     return max(min(stoploss, 1.0), 0.0)
150
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/freqtrade/strategy/strategy_helper.py b/freqtrade/strategy/strategy_helper.py
--- a/freqtrade/strategy/strategy_helper.py
+++ b/freqtrade/strategy/strategy_helper.py
@@ -86,37 +86,41 @@
 def stoploss_from_open(
     open_relative_stop: float,
     current_profit: float,
-    is_short: bool = False
+    is_short: bool = False,
+    leverage: float = 1.0
 ) -> float:
     """
-
-    Given the current profit, and a desired stop loss value relative to the open price,
+    Given the current profit, and a desired stop loss value relative to the trade entry price,
     return a stop loss value that is relative to the current price, and which can be
     returned from `custom_stoploss`.
 
     The requested stop can be positive for a stop above the open price, or negative for
     a stop below the open price. The return value is always >= 0.
+    `open_relative_stop` will be considered as adjusted for leverage if leverage is provided..
 
     Returns 0 if the resulting stop price would be above/below (longs/shorts) the current price
 
-    :param open_relative_stop: Desired stop loss percentage relative to open price
+    :param open_relative_stop: Desired stop loss percentage, relative to the open price,
+                               adjusted for leverage
     :param current_profit: The current profit percentage
     :param is_short: When true, perform the calculation for short instead of long
+    :param leverage: Leverage to use for the calculation
     :return: Stop loss value relative to current price
     """
 
     # formula is undefined for current_profit -1 (longs) or 1 (shorts), return maximum value
-    if (current_profit == -1 and not is_short) or (is_short and current_profit == 1):
+    _current_profit = current_profit / leverage
+    if (_current_profit == -1 and not is_short) or (is_short and _current_profit == 1):
         return 1
 
     if is_short is True:
-        stoploss = -1 + ((1 - open_relative_stop) / (1 - current_profit))
+        stoploss = -1 + ((1 - open_relative_stop / leverage) / (1 - _current_profit))
     else:
-        stoploss = 1 - ((1 + open_relative_stop) / (1 + current_profit))
+        stoploss = 1 - ((1 + open_relative_stop / leverage) / (1 + _current_profit))
 
     # negative stoploss values indicate the requested stop price is higher/lower
     # (long/short) than the current price
-    return max(stoploss, 0.0)
+    return max(stoploss * leverage, 0.0)
 
 
 def stoploss_from_absolute(stop_rate: float, current_rate: float, is_short: bool = False) -> float:

{"golden_diff": "diff --git a/freqtrade/strategy/strategy_helper.py b/freqtrade/strategy/strategy_helper.py\n--- a/freqtrade/strategy/strategy_helper.py\n+++ b/freqtrade/strategy/strategy_helper.py\n@@ -86,37 +86,41 @@\n def stoploss_from_open(\n     open_relative_stop: float,\n     current_profit: float,\n-    is_short: bool = False\n+    is_short: bool = False,\n+    leverage: float = 1.0\n ) -> float:\n     \"\"\"\n-\n-    Given the current profit, and a desired stop loss value relative to the open price,\n+    Given the current profit, and a desired stop loss value relative to the trade entry price,\n     return a stop loss value that is relative to the current price, and which can be\n     returned from `custom_stoploss`.\n \n     The requested stop can be positive for a stop above the open price, or negative for\n     a stop below the open price. The return value is always >= 0.\n+    `open_relative_stop` will be considered as adjusted for leverage if leverage is provided..\n \n     Returns 0 if the resulting stop price would be above/below (longs/shorts) the current price\n \n-    :param open_relative_stop: Desired stop loss percentage relative to open price\n+    :param open_relative_stop: Desired stop loss percentage, relative to the open price,\n+                               adjusted for leverage\n     :param current_profit: The current profit percentage\n     :param is_short: When true, perform the calculation for short instead of long\n+    :param leverage: Leverage to use for the calculation\n     :return: Stop loss value relative to current price\n     \"\"\"\n \n     # formula is undefined for current_profit -1 (longs) or 1 (shorts), return maximum value\n-    if (current_profit == -1 and not is_short) or (is_short and current_profit == 1):\n+    _current_profit = current_profit / leverage\n+    if (_current_profit == -1 and not is_short) or (is_short and _current_profit == 1):\n         return 1\n \n     if is_short is True:\n-        stoploss = -1 + ((1 - open_relative_stop) / (1 - current_profit))\n+        stoploss = -1 + ((1 - open_relative_stop / leverage) / (1 - _current_profit))\n     else:\n-        stoploss = 1 - ((1 + open_relative_stop) / (1 + current_profit))\n+        stoploss = 1 - ((1 + open_relative_stop / leverage) / (1 + _current_profit))\n \n     # negative stoploss values indicate the requested stop price is higher/lower\n     # (long/short) than the current price\n-    return max(stoploss, 0.0)\n+    return max(stoploss * leverage, 0.0)\n \n \n def stoploss_from_absolute(stop_rate: float, current_rate: float, is_short: bool = False) -> float:\n", "issue": "stoploss_from_open has some ambiguous with leverage\n<!-- \r\nHave you searched for similar issues before posting it?\r\n\r\nIf you have discovered a bug in the bot, please [search the issue tracker](https://github.com/freqtrade/freqtrade/issues?q=is%3Aissue). \r\nIf it hasn't been reported, please create a new issue.\r\n\r\nPlease do not use bug reports to request new features.\r\n-->\r\n\r\n## Describe your environment\r\n\r\n  * Operating system: ____ Linux\r\n  * Python Version: _____ (`python -V`) 3.10\r\n  * CCXT version: _____ (`pip freeze | grep ccxt`) 1.95\r\n  * Freqtrade Version: ____ (`freqtrade -V` or `docker compose run --rm freqtrade -V` for Freqtrade running in docker)\r\n  \r\nNote: All issues other than enhancement requests will be closed without further comment if the above template is deleted or not filled out.\r\n\r\n## Describe the problem:\r\n\r\nIn the doc explanation,  profit and stoploss is calculated with leverage.\r\n\r\nAnd this function `stoploss_from_open` (in freqtrade/strategy/strategy_helper.py)  may wrong when enter short with leverage.  Because it's profit_rate may large than 1 , and  but open_relative_stop still less than 1, and stoploss be always negative, and function return 0.0. But in fact, it has positive profit.\r\n\r\n*Explain the problem you have encountered*\r\n\r\n### Steps to reproduce:\r\n\r\n  1. _____\r\n  2. _____\r\n  3. _____\r\n  \r\n### Observed Results:\r\n\r\n  * What happened?  \r\n       stoploss_from_open may have  ambiguous  when used leverage\r\n  * What did you expect to happen?\r\n       In function dive leverage,  or argument explicitly explanates  without leverage\r\n### Relevant code exceptions or logs\r\n``` Python\r\n              def stoploss_from_open(\r\n                  open_relative_stop: float,\r\n                  current_profit: float,\r\n                  is_short: bool = False\r\n                  ) -> float:\r\n                  \"\"\"\r\n                  Given the current profit, and a desired stop loss value relative to the open price,\r\n                  return a stop loss value that is relative to the current price, and which can be\r\n                  returned from `custom_stoploss`.\r\n              \r\n                  The requested stop can be positive for a stop above the open price, or negative for\r\n                  a stop below the open price. The return value is always >= 0.\r\n              \r\n                  Returns 0 if the resulting stop price would be above/below (longs/shorts) the current price\r\n              \r\n                  :param open_relative_stop: Desired stop loss percentage relative to open price\r\n                  :param current_profit: The current profit percentage\r\n                  :param is_short: When true, perform the calculation for short instead of long\r\n                  :return: Stop loss value relative to current price\r\n                  \"\"\"\r\n              \r\n                  # formula is undefined for current_profit -1 (longs) or 1 (shorts), return maximum value\r\n                  if (current_profit == -1 and not is_short) or (is_short and current_profit == 1):\r\n                      return 1\r\n              \r\n                  if is_short is True:\r\n                      stoploss = -1 + ((1 - open_relative_stop) / (1 - current_profit))\r\n                  else:\r\n                      stoploss = 1 - ((1 + open_relative_stop) / (1 + current_profit))\r\n              \r\n                  # negative stoploss values indicate the requested stop price is higher/lower\r\n                  # (long/short) than the current price\r\n                  return max(stoploss, 0.0)\r\n```\r\nNote: Please copy/paste text of the messages, no screenshots of logs please.\r\n\r\n  ```\r\n  // paste your log here\r\n  ```\r\n\n", "before_files": [{"content": "from typing import Optional\n\nimport pandas as pd\n\nfrom freqtrade.exchange import timeframe_to_minutes\n\n\ndef merge_informative_pair(dataframe: pd.DataFrame, informative: pd.DataFrame,\n                           timeframe: str, timeframe_inf: str, ffill: bool = True,\n                           append_timeframe: bool = True,\n                           date_column: str = 'date',\n                           suffix: Optional[str] = None) -> pd.DataFrame:\n    \"\"\"\n    Correctly merge informative samples to the original dataframe, avoiding lookahead bias.\n\n    Since dates are candle open dates, merging a 15m candle that starts at 15:00, and a\n    1h candle that starts at 15:00 will result in all candles to know the close at 16:00\n    which they should not know.\n\n    Moves the date of the informative pair by 1 time interval forward.\n    This way, the 14:00 1h candle is merged to 15:00 15m candle, since the 14:00 1h candle is the\n    last candle that's closed at 15:00, 15:15, 15:30 or 15:45.\n\n    Assuming inf_tf = '1d' - then the resulting columns will be:\n    date_1d, open_1d, high_1d, low_1d, close_1d, rsi_1d\n\n    :param dataframe: Original dataframe\n    :param informative: Informative pair, most likely loaded via dp.get_pair_dataframe\n    :param timeframe: Timeframe of the original pair sample.\n    :param timeframe_inf: Timeframe of the informative pair sample.\n    :param ffill: Forwardfill missing values - optional but usually required\n    :param append_timeframe: Rename columns by appending timeframe.\n    :param date_column: A custom date column name.\n    :param suffix: A string suffix to add at the end of the informative columns. If specified,\n                   append_timeframe must be false.\n    :return: Merged dataframe\n    :raise: ValueError if the secondary timeframe is shorter than the dataframe timeframe\n    \"\"\"\n\n    minutes_inf = timeframe_to_minutes(timeframe_inf)\n    minutes = timeframe_to_minutes(timeframe)\n    if minutes == minutes_inf:\n        # No need to forwardshift if the timeframes are identical\n        informative['date_merge'] = informative[date_column]\n    elif minutes < minutes_inf:\n        # Subtract \"small\" timeframe so merging is not delayed by 1 small candle\n        # Detailed explanation in https://github.com/freqtrade/freqtrade/issues/4073\n        informative['date_merge'] = (\n            informative[date_column] + pd.to_timedelta(minutes_inf, 'm') -\n            pd.to_timedelta(minutes, 'm')\n        )\n    else:\n        raise ValueError(\"Tried to merge a faster timeframe to a slower timeframe.\"\n                         \"This would create new rows, and can throw off your regular indicators.\")\n\n    # Rename columns to be unique\n    date_merge = 'date_merge'\n    if suffix and append_timeframe:\n        raise ValueError(\"You can not specify `append_timeframe` as True and a `suffix`.\")\n    elif append_timeframe:\n        date_merge = f'date_merge_{timeframe_inf}'\n        informative.columns = [f\"{col}_{timeframe_inf}\" for col in informative.columns]\n\n    elif suffix:\n        date_merge = f'date_merge_{suffix}'\n        informative.columns = [f\"{col}_{suffix}\" for col in informative.columns]\n\n    # Combine the 2 dataframes\n    # all indicators on the informative sample MUST be calculated before this point\n    if ffill:\n        # https://pandas.pydata.org/docs/user_guide/merging.html#timeseries-friendly-merging\n        # merge_ordered - ffill method is 2.5x faster than seperate ffill()\n        dataframe = pd.merge_ordered(dataframe, informative, fill_method=\"ffill\", left_on='date',\n                                     right_on=date_merge, how='left')\n    else:\n        dataframe = pd.merge(dataframe, informative, left_on='date',\n                             right_on=date_merge, how='left')\n    dataframe = dataframe.drop(date_merge, axis=1)\n\n    # if ffill:\n    #     dataframe = dataframe.ffill()\n\n    return dataframe\n\n\ndef stoploss_from_open(\n    open_relative_stop: float,\n    current_profit: float,\n    is_short: bool = False\n) -> float:\n    \"\"\"\n\n    Given the current profit, and a desired stop loss value relative to the open price,\n    return a stop loss value that is relative to the current price, and which can be\n    returned from `custom_stoploss`.\n\n    The requested stop can be positive for a stop above the open price, or negative for\n    a stop below the open price. The return value is always >= 0.\n\n    Returns 0 if the resulting stop price would be above/below (longs/shorts) the current price\n\n    :param open_relative_stop: Desired stop loss percentage relative to open price\n    :param current_profit: The current profit percentage\n    :param is_short: When true, perform the calculation for short instead of long\n    :return: Stop loss value relative to current price\n    \"\"\"\n\n    # formula is undefined for current_profit -1 (longs) or 1 (shorts), return maximum value\n    if (current_profit == -1 and not is_short) or (is_short and current_profit == 1):\n        return 1\n\n    if is_short is True:\n        stoploss = -1 + ((1 - open_relative_stop) / (1 - current_profit))\n    else:\n        stoploss = 1 - ((1 + open_relative_stop) / (1 + current_profit))\n\n    # negative stoploss values indicate the requested stop price is higher/lower\n    # (long/short) than the current price\n    return max(stoploss, 0.0)\n\n\ndef stoploss_from_absolute(stop_rate: float, current_rate: float, is_short: bool = False) -> float:\n    \"\"\"\n    Given current price and desired stop price, return a stop loss value that is relative to current\n    price.\n\n    The requested stop can be positive for a stop above the open price, or negative for\n    a stop below the open price. The return value is always >= 0.\n\n    Returns 0 if the resulting stop price would be above the current price.\n\n    :param stop_rate: Stop loss price.\n    :param current_rate: Current asset price.\n    :param is_short: When true, perform the calculation for short instead of long\n    :return: Positive stop loss value relative to current price\n    \"\"\"\n\n    # formula is undefined for current_rate 0, return maximum value\n    if current_rate == 0:\n        return 1\n\n    stoploss = 1 - (stop_rate / current_rate)\n    if is_short:\n        stoploss = -stoploss\n\n    # negative stoploss values indicate the requested stop price is higher/lower\n    # (long/short) than the current price\n    # shorts can yield stoploss values higher than 1, so limit that as well\n    return max(min(stoploss, 1.0), 0.0)\n", "path": "freqtrade/strategy/strategy_helper.py"}], "after_files": [{"content": "from typing import Optional\n\nimport pandas as pd\n\nfrom freqtrade.exchange import timeframe_to_minutes\n\n\ndef merge_informative_pair(dataframe: pd.DataFrame, informative: pd.DataFrame,\n                           timeframe: str, timeframe_inf: str, ffill: bool = True,\n                           append_timeframe: bool = True,\n                           date_column: str = 'date',\n                           suffix: Optional[str] = None) -> pd.DataFrame:\n    \"\"\"\n    Correctly merge informative samples to the original dataframe, avoiding lookahead bias.\n\n    Since dates are candle open dates, merging a 15m candle that starts at 15:00, and a\n    1h candle that starts at 15:00 will result in all candles to know the close at 16:00\n    which they should not know.\n\n    Moves the date of the informative pair by 1 time interval forward.\n    This way, the 14:00 1h candle is merged to 15:00 15m candle, since the 14:00 1h candle is the\n    last candle that's closed at 15:00, 15:15, 15:30 or 15:45.\n\n    Assuming inf_tf = '1d' - then the resulting columns will be:\n    date_1d, open_1d, high_1d, low_1d, close_1d, rsi_1d\n\n    :param dataframe: Original dataframe\n    :param informative: Informative pair, most likely loaded via dp.get_pair_dataframe\n    :param timeframe: Timeframe of the original pair sample.\n    :param timeframe_inf: Timeframe of the informative pair sample.\n    :param ffill: Forwardfill missing values - optional but usually required\n    :param append_timeframe: Rename columns by appending timeframe.\n    :param date_column: A custom date column name.\n    :param suffix: A string suffix to add at the end of the informative columns. If specified,\n                   append_timeframe must be false.\n    :return: Merged dataframe\n    :raise: ValueError if the secondary timeframe is shorter than the dataframe timeframe\n    \"\"\"\n\n    minutes_inf = timeframe_to_minutes(timeframe_inf)\n    minutes = timeframe_to_minutes(timeframe)\n    if minutes == minutes_inf:\n        # No need to forwardshift if the timeframes are identical\n        informative['date_merge'] = informative[date_column]\n    elif minutes < minutes_inf:\n        # Subtract \"small\" timeframe so merging is not delayed by 1 small candle\n        # Detailed explanation in https://github.com/freqtrade/freqtrade/issues/4073\n        informative['date_merge'] = (\n            informative[date_column] + pd.to_timedelta(minutes_inf, 'm') -\n            pd.to_timedelta(minutes, 'm')\n        )\n    else:\n        raise ValueError(\"Tried to merge a faster timeframe to a slower timeframe.\"\n                         \"This would create new rows, and can throw off your regular indicators.\")\n\n    # Rename columns to be unique\n    date_merge = 'date_merge'\n    if suffix and append_timeframe:\n        raise ValueError(\"You can not specify `append_timeframe` as True and a `suffix`.\")\n    elif append_timeframe:\n        date_merge = f'date_merge_{timeframe_inf}'\n        informative.columns = [f\"{col}_{timeframe_inf}\" for col in informative.columns]\n\n    elif suffix:\n        date_merge = f'date_merge_{suffix}'\n        informative.columns = [f\"{col}_{suffix}\" for col in informative.columns]\n\n    # Combine the 2 dataframes\n    # all indicators on the informative sample MUST be calculated before this point\n    if ffill:\n        # https://pandas.pydata.org/docs/user_guide/merging.html#timeseries-friendly-merging\n        # merge_ordered - ffill method is 2.5x faster than seperate ffill()\n        dataframe = pd.merge_ordered(dataframe, informative, fill_method=\"ffill\", left_on='date',\n                                     right_on=date_merge, how='left')\n    else:\n        dataframe = pd.merge(dataframe, informative, left_on='date',\n                             right_on=date_merge, how='left')\n    dataframe = dataframe.drop(date_merge, axis=1)\n\n    # if ffill:\n    #     dataframe = dataframe.ffill()\n\n    return dataframe\n\n\ndef stoploss_from_open(\n    open_relative_stop: float,\n    current_profit: float,\n    is_short: bool = False,\n    leverage: float = 1.0\n) -> float:\n    \"\"\"\n    Given the current profit, and a desired stop loss value relative to the trade entry price,\n    return a stop loss value that is relative to the current price, and which can be\n    returned from `custom_stoploss`.\n\n    The requested stop can be positive for a stop above the open price, or negative for\n    a stop below the open price. The return value is always >= 0.\n    `open_relative_stop` will be considered as adjusted for leverage if leverage is provided..\n\n    Returns 0 if the resulting stop price would be above/below (longs/shorts) the current price\n\n    :param open_relative_stop: Desired stop loss percentage, relative to the open price,\n                               adjusted for leverage\n    :param current_profit: The current profit percentage\n    :param is_short: When true, perform the calculation for short instead of long\n    :param leverage: Leverage to use for the calculation\n    :return: Stop loss value relative to current price\n    \"\"\"\n\n    # formula is undefined for current_profit -1 (longs) or 1 (shorts), return maximum value\n    _current_profit = current_profit / leverage\n    if (_current_profit == -1 and not is_short) or (is_short and _current_profit == 1):\n        return 1\n\n    if is_short is True:\n        stoploss = -1 + ((1 - open_relative_stop / leverage) / (1 - _current_profit))\n    else:\n        stoploss = 1 - ((1 + open_relative_stop / leverage) / (1 + _current_profit))\n\n    # negative stoploss values indicate the requested stop price is higher/lower\n    # (long/short) than the current price\n    return max(stoploss * leverage, 0.0)\n\n\ndef stoploss_from_absolute(stop_rate: float, current_rate: float, is_short: bool = False) -> float:\n    \"\"\"\n    Given current price and desired stop price, return a stop loss value that is relative to current\n    price.\n\n    The requested stop can be positive for a stop above the open price, or negative for\n    a stop below the open price. The return value is always >= 0.\n\n    Returns 0 if the resulting stop price would be above the current price.\n\n    :param stop_rate: Stop loss price.\n    :param current_rate: Current asset price.\n    :param is_short: When true, perform the calculation for short instead of long\n    :return: Positive stop loss value relative to current price\n    \"\"\"\n\n    # formula is undefined for current_rate 0, return maximum value\n    if current_rate == 0:\n        return 1\n\n    stoploss = 1 - (stop_rate / current_rate)\n    if is_short:\n        stoploss = -stoploss\n\n    # negative stoploss values indicate the requested stop price is higher/lower\n    # (long/short) than the current price\n    # shorts can yield stoploss values higher than 1, so limit that as well\n    return max(min(stoploss, 1.0), 0.0)\n", "path": "freqtrade/strategy/strategy_helper.py"}]}