docs: remove callback examples imports

This commit is contained in:
Matthias
2024-08-18 08:37:34 +02:00
parent 9408e858cd
commit b1ae09c003

View File

@@ -198,9 +198,7 @@ Of course, many more things are possible, and all examples can be combined at wi
To simulate a regular trailing stoploss of 4% (trailing 4% behind the maximum reached price) you would use the following very simple method: To simulate a regular trailing stoploss of 4% (trailing 4% behind the maximum reached price) you would use the following very simple method:
``` python ``` python
# additional imports required # Default imports
from datetime import datetime
from freqtrade.persistence import Trade
class AwesomeStrategy(IStrategy): class AwesomeStrategy(IStrategy):
@@ -208,7 +206,7 @@ class AwesomeStrategy(IStrategy):
use_custom_stoploss = True use_custom_stoploss = True
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime,
current_rate: float, current_profit: float, after_fill: bool, current_rate: float, current_profit: float, after_fill: bool,
**kwargs) -> Optional[float]: **kwargs) -> Optional[float]:
""" """
@@ -238,8 +236,7 @@ class AwesomeStrategy(IStrategy):
Use the initial stoploss for the first 60 minutes, after this change to 10% trailing stoploss, and after 2 hours (120 minutes) we use a 5% trailing stoploss. Use the initial stoploss for the first 60 minutes, after this change to 10% trailing stoploss, and after 2 hours (120 minutes) we use a 5% trailing stoploss.
``` python ``` python
from datetime import datetime, timedelta # Default imports
from freqtrade.persistence import Trade
class AwesomeStrategy(IStrategy): class AwesomeStrategy(IStrategy):
@@ -247,7 +244,7 @@ class AwesomeStrategy(IStrategy):
use_custom_stoploss = True use_custom_stoploss = True
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime,
current_rate: float, current_profit: float, after_fill: bool, current_rate: float, current_profit: float, after_fill: bool,
**kwargs) -> Optional[float]: **kwargs) -> Optional[float]:
@@ -265,8 +262,7 @@ Use the initial stoploss for the first 60 minutes, after this change to 10% trai
If an additional order fills, set stoploss to -10% below the new `open_rate` ([Averaged across all entries](#position-adjust-calculations)). If an additional order fills, set stoploss to -10% below the new `open_rate` ([Averaged across all entries](#position-adjust-calculations)).
``` python ``` python
from datetime import datetime, timedelta # Default imports
from freqtrade.persistence import Trade
class AwesomeStrategy(IStrategy): class AwesomeStrategy(IStrategy):
@@ -274,7 +270,7 @@ class AwesomeStrategy(IStrategy):
use_custom_stoploss = True use_custom_stoploss = True
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime,
current_rate: float, current_profit: float, after_fill: bool, current_rate: float, current_profit: float, after_fill: bool,
**kwargs) -> Optional[float]: **kwargs) -> Optional[float]:
@@ -295,8 +291,7 @@ Use a different stoploss depending on the pair.
In this example, we'll trail the highest price with 10% trailing stoploss for `ETH/BTC` and `XRP/BTC`, with 5% trailing stoploss for `LTC/BTC` and with 15% for all other pairs. In this example, we'll trail the highest price with 10% trailing stoploss for `ETH/BTC` and `XRP/BTC`, with 5% trailing stoploss for `LTC/BTC` and with 15% for all other pairs.
``` python ``` python
from datetime import datetime # Default imports
from freqtrade.persistence import Trade
class AwesomeStrategy(IStrategy): class AwesomeStrategy(IStrategy):
@@ -304,7 +299,7 @@ class AwesomeStrategy(IStrategy):
use_custom_stoploss = True use_custom_stoploss = True
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime,
current_rate: float, current_profit: float, after_fill: bool, current_rate: float, current_profit: float, after_fill: bool,
**kwargs) -> Optional[float]: **kwargs) -> Optional[float]:
@@ -322,8 +317,7 @@ Use the initial stoploss until the profit is above 4%, then use a trailing stopl
Please note that the stoploss can only increase, values lower than the current stoploss are ignored. Please note that the stoploss can only increase, values lower than the current stoploss are ignored.
``` python ``` python
from datetime import datetime, timedelta # Default imports
from freqtrade.persistence import Trade
class AwesomeStrategy(IStrategy): class AwesomeStrategy(IStrategy):
@@ -331,7 +325,7 @@ class AwesomeStrategy(IStrategy):
use_custom_stoploss = True use_custom_stoploss = True
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime,
current_rate: float, current_profit: float, after_fill: bool, current_rate: float, current_profit: float, after_fill: bool,
**kwargs) -> Optional[float]: **kwargs) -> Optional[float]:
@@ -355,9 +349,7 @@ Instead of continuously trailing behind the current price, this example sets fix
* Once profit is > 40% - set stoploss to 25% above open price. * Once profit is > 40% - set stoploss to 25% above open price.
``` python ``` python
from datetime import datetime # Default imports
from freqtrade.persistence import Trade
from freqtrade.strategy import stoploss_from_open
class AwesomeStrategy(IStrategy): class AwesomeStrategy(IStrategy):
@@ -365,7 +357,7 @@ class AwesomeStrategy(IStrategy):
use_custom_stoploss = True use_custom_stoploss = True
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime,
current_rate: float, current_profit: float, after_fill: bool, current_rate: float, current_profit: float, after_fill: bool,
**kwargs) -> Optional[float]: **kwargs) -> Optional[float]:
@@ -386,6 +378,8 @@ class AwesomeStrategy(IStrategy):
Absolute stoploss value may be derived from indicators stored in dataframe. Example uses parabolic SAR below the price as stoploss. Absolute stoploss value may be derived from indicators stored in dataframe. Example uses parabolic SAR below the price as stoploss.
``` python ``` python
# Default imports
class AwesomeStrategy(IStrategy): class AwesomeStrategy(IStrategy):
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
@@ -394,7 +388,7 @@ class AwesomeStrategy(IStrategy):
use_custom_stoploss = True use_custom_stoploss = True
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime,
current_rate: float, current_profit: float, after_fill: bool, current_rate: float, current_profit: float, after_fill: bool,
**kwargs) -> Optional[float]: **kwargs) -> Optional[float]:
@@ -431,10 +425,7 @@ Stoploss values returned from `custom_stoploss()` must specify a percentage rela
``` python ``` python
# Default imports
from datetime import datetime
from freqtrade.persistence import Trade
from freqtrade.strategy import IStrategy, stoploss_from_open
class AwesomeStrategy(IStrategy): class AwesomeStrategy(IStrategy):
@@ -442,7 +433,7 @@ Stoploss values returned from `custom_stoploss()` must specify a percentage rela
use_custom_stoploss = True use_custom_stoploss = True
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime,
current_rate: float, current_profit: float, after_fill: bool, current_rate: float, current_profit: float, after_fill: bool,
**kwargs) -> Optional[float]: **kwargs) -> Optional[float]:
@@ -475,10 +466,7 @@ The helper function `stoploss_from_absolute()` can be used to convert from an ab
For futures, we need to adjust the direction (up or down), as well as adjust for leverage, since the [`custom_stoploss`](strategy-callbacks.md#custom-stoploss) callback returns the ["risk for this trade"](stoploss.md#stoploss-and-leverage) - not the relative price movement. For futures, we need to adjust the direction (up or down), as well as adjust for leverage, since the [`custom_stoploss`](strategy-callbacks.md#custom-stoploss) callback returns the ["risk for this trade"](stoploss.md#stoploss-and-leverage) - not the relative price movement.
``` python ``` python
# Default imports
from datetime import datetime
from freqtrade.persistence import Trade
from freqtrade.strategy import IStrategy, stoploss_from_absolute, timeframe_to_prev_date
class AwesomeStrategy(IStrategy): class AwesomeStrategy(IStrategy):
@@ -488,7 +476,7 @@ The helper function `stoploss_from_absolute()` can be used to convert from an ab
dataframe['atr'] = ta.ATR(dataframe, timeperiod=14) dataframe['atr'] = ta.ATR(dataframe, timeperiod=14)
return dataframe return dataframe
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime,
current_rate: float, current_profit: float, after_fill: bool, current_rate: float, current_profit: float, after_fill: bool,
**kwargs) -> Optional[float]: **kwargs) -> Optional[float]:
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
@@ -502,7 +490,6 @@ The helper function `stoploss_from_absolute()` can be used to convert from an ab
``` ```
--- ---
## Custom order price rules ## Custom order price rules
@@ -522,19 +509,18 @@ Each of these methods are called right before placing an order on the exchange.
### Custom order entry and exit price example ### Custom order entry and exit price example
``` python ``` python
from datetime import datetime, timedelta, timezone # Default imports
from freqtrade.persistence import Trade
class AwesomeStrategy(IStrategy): class AwesomeStrategy(IStrategy):
# ... populate_* methods # ... populate_* methods
def custom_entry_price(self, pair: str, trade: Optional['Trade'], current_time: datetime, proposed_rate: float, def custom_entry_price(self, pair: str, trade: Optional[Trade], current_time: datetime, proposed_rate: float,
entry_tag: Optional[str], side: str, **kwargs) -> float: entry_tag: Optional[str], side: str, **kwargs) -> float:
dataframe, last_updated = self.dp.get_analyzed_dataframe(pair=pair, dataframe, last_updated = self.dp.get_analyzed_dataframe(pair=pair,
timeframe=self.timeframe) timeframe=self.timeframe)
new_entryprice = dataframe['bollinger_10_lowerband'].iat[-1] new_entryprice = dataframe["bollinger_10_lowerband"].iat[-1]
return new_entryprice return new_entryprice
@@ -544,7 +530,7 @@ class AwesomeStrategy(IStrategy):
dataframe, last_updated = self.dp.get_analyzed_dataframe(pair=pair, dataframe, last_updated = self.dp.get_analyzed_dataframe(pair=pair,
timeframe=self.timeframe) timeframe=self.timeframe)
new_exitprice = dataframe['bollinger_10_upperband'].iat[-1] new_exitprice = dataframe["bollinger_10_upperband"].iat[-1]
return new_exitprice return new_exitprice
@@ -581,8 +567,7 @@ It applies a tight timeout for higher priced assets, while allowing more time to
The function must return either `True` (cancel order) or `False` (keep order alive). The function must return either `True` (cancel order) or `False` (keep order alive).
``` python ``` python
from datetime import datetime, timedelta # Default imports
from freqtrade.persistence import Trade, Order
class AwesomeStrategy(IStrategy): class AwesomeStrategy(IStrategy):
@@ -594,7 +579,7 @@ class AwesomeStrategy(IStrategy):
'exit': 60 * 25 'exit': 60 * 25
} }
def check_entry_timeout(self, pair: str, trade: 'Trade', order: 'Order', def check_entry_timeout(self, pair: str, trade: Trade, order: Order,
current_time: datetime, **kwargs) -> bool: current_time: datetime, **kwargs) -> bool:
if trade.open_rate > 100 and trade.open_date_utc < current_time - timedelta(minutes=5): if trade.open_rate > 100 and trade.open_date_utc < current_time - timedelta(minutes=5):
return True return True
@@ -605,7 +590,7 @@ class AwesomeStrategy(IStrategy):
return False return False
def check_exit_timeout(self, pair: str, trade: Trade, order: 'Order', def check_exit_timeout(self, pair: str, trade: Trade, order: Order,
current_time: datetime, **kwargs) -> bool: current_time: datetime, **kwargs) -> bool:
if trade.open_rate > 100 and trade.open_date_utc < current_time - timedelta(minutes=5): if trade.open_rate > 100 and trade.open_date_utc < current_time - timedelta(minutes=5):
return True return True
@@ -622,8 +607,7 @@ class AwesomeStrategy(IStrategy):
### Custom order timeout example (using additional data) ### Custom order timeout example (using additional data)
``` python ``` python
from datetime import datetime # Default imports
from freqtrade.persistence import Trade, Order
class AwesomeStrategy(IStrategy): class AwesomeStrategy(IStrategy):
@@ -631,24 +615,24 @@ class AwesomeStrategy(IStrategy):
# Set unfilledtimeout to 25 hours, since the maximum timeout from below is 24 hours. # Set unfilledtimeout to 25 hours, since the maximum timeout from below is 24 hours.
unfilledtimeout = { unfilledtimeout = {
'entry': 60 * 25, "entry": 60 * 25,
'exit': 60 * 25 "exit": 60 * 25
} }
def check_entry_timeout(self, pair: str, trade: 'Trade', order: 'Order', def check_entry_timeout(self, pair: str, trade: Trade, order: Order,
current_time: datetime, **kwargs) -> bool: current_time: datetime, **kwargs) -> bool:
ob = self.dp.orderbook(pair, 1) ob = self.dp.orderbook(pair, 1)
current_price = ob['bids'][0][0] current_price = ob["bids"][0][0]
# Cancel buy order if price is more than 2% above the order. # Cancel buy order if price is more than 2% above the order.
if current_price > order.price * 1.02: if current_price > order.price * 1.02:
return True return True
return False return False
def check_exit_timeout(self, pair: str, trade: 'Trade', order: 'Order', def check_exit_timeout(self, pair: str, trade: Trade, order: Order,
current_time: datetime, **kwargs) -> bool: current_time: datetime, **kwargs) -> bool:
ob = self.dp.orderbook(pair, 1) ob = self.dp.orderbook(pair, 1)
current_price = ob['asks'][0][0] current_price = ob["asks"][0][0]
# Cancel sell order if price is more than 2% below the order. # Cancel sell order if price is more than 2% below the order.
if current_price < order.price * 0.98: if current_price < order.price * 0.98:
return True return True
@@ -667,6 +651,8 @@ This are the last methods that will be called before an order is placed.
`confirm_trade_entry()` can be used to abort a trade entry at the latest second (maybe because the price is not what we expect). `confirm_trade_entry()` can be used to abort a trade entry at the latest second (maybe because the price is not what we expect).
``` python ``` python
# Default imports
class AwesomeStrategy(IStrategy): class AwesomeStrategy(IStrategy):
# ... populate_* methods # ... populate_* methods
@@ -713,8 +699,7 @@ The exit-reasons (if applicable) will be in the following sequence:
* `trailing_stop_loss` * `trailing_stop_loss`
``` python ``` python
from freqtrade.persistence import Trade # Default imports
class AwesomeStrategy(IStrategy): class AwesomeStrategy(IStrategy):
@@ -747,7 +732,7 @@ class AwesomeStrategy(IStrategy):
:return bool: When True, then the exit-order is placed on the exchange. :return bool: When True, then the exit-order is placed on the exchange.
False aborts the process False aborts the process
""" """
if exit_reason == 'force_exit' and trade.calc_profit_ratio(rate) < 0: if exit_reason == "force_exit" and trade.calc_profit_ratio(rate) < 0:
# Reject force-sells with negative profit # Reject force-sells with negative profit
# This is just a sample, please adjust to your needs # This is just a sample, please adjust to your needs
# (this does not necessarily make sense, assuming you know when you're force-selling) # (this does not necessarily make sense, assuming you know when you're force-selling)
@@ -813,6 +798,7 @@ Returning a value more than the above (so remaining stake_amount would become ne
Trades with long duration and 10s or even 100ds of position adjustments are therefore not recommended, and should be closed at regular intervals to not affect performance. Trades with long duration and 10s or even 100ds of position adjustments are therefore not recommended, and should be closed at regular intervals to not affect performance.
``` python ``` python
# Default imports
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
from typing import Optional, Tuple, Union from typing import Optional, Tuple, Union
@@ -953,8 +939,7 @@ If the cancellation of the original order fails, then the order will not be repl
Entry Orders that are cancelled via the above methods will not have this callback called. Be sure to update timeout values to match your expectations. Entry Orders that are cancelled via the above methods will not have this callback called. Be sure to update timeout values to match your expectations.
```python ```python
from freqtrade.persistence import Trade # Default imports
from datetime import timedelta, datetime
class AwesomeStrategy(IStrategy): class AwesomeStrategy(IStrategy):
@@ -985,7 +970,12 @@ class AwesomeStrategy(IStrategy):
""" """
# Limit orders to use and follow SMA200 as price target for the first 10 minutes since entry trigger for BTC/USDT pair. # Limit orders to use and follow SMA200 as price target for the first 10 minutes since entry trigger for BTC/USDT pair.
if pair == 'BTC/USDT' and entry_tag == 'long_sma200' and side == 'long' and (current_time - timedelta(minutes=10)) > trade.open_date_utc: if (
pair == "BTC/USDT"
and entry_tag == "long_sma200"
and side == "long"
and (current_time - timedelta(minutes=10)) > trade.open_date_utc
):
# just cancel the order if it has been filled more than half of the amount # just cancel the order if it has been filled more than half of the amount
if order.filled > order.remaining: if order.filled > order.remaining:
return None return None
@@ -993,7 +983,7 @@ class AwesomeStrategy(IStrategy):
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe) dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
current_candle = dataframe.iloc[-1].squeeze() current_candle = dataframe.iloc[-1].squeeze()
# desired price # desired price
return current_candle['sma_200'] return current_candle["sma_200"]
# default: maintain existing order # default: maintain existing order
return current_order_rate return current_order_rate
``` ```
@@ -1008,6 +998,8 @@ Values that are above `max_leverage` will be adjusted to `max_leverage`.
For markets / exchanges that don't support leverage, this method is ignored. For markets / exchanges that don't support leverage, this method is ignored.
``` python ``` python
# Default imports
class AwesomeStrategy(IStrategy): class AwesomeStrategy(IStrategy):
def leverage(self, pair: str, current_time: datetime, current_rate: float, def leverage(self, pair: str, current_time: datetime, current_rate: float,
proposed_leverage: float, max_leverage: float, entry_tag: Optional[str], side: str, proposed_leverage: float, max_leverage: float, entry_tag: Optional[str], side: str,
@@ -1038,6 +1030,8 @@ It will be called independent of the order type (entry, exit, stoploss or positi
Assuming that your strategy needs to store the high value of the candle at trade entry, this is possible with this callback as the following example show. Assuming that your strategy needs to store the high value of the candle at trade entry, this is possible with this callback as the following example show.
``` python ``` python
# Default imports
class AwesomeStrategy(IStrategy): class AwesomeStrategy(IStrategy):
def order_filled(self, pair: str, trade: Trade, order: Order, current_time: datetime, **kwargs) -> None: def order_filled(self, pair: str, trade: Trade, order: Order, current_time: datetime, **kwargs) -> None:
""" """