Add support for fudging unavailable funding rates, allowing backtesting of timeranges where futures candles are available, but rates are not

This commit is contained in:
froggleston 2022-05-17 22:05:33 +01:00
parent 7b9439f2e4
commit bb758da940
4 changed files with 34 additions and 3 deletions

View File

@ -230,6 +230,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi
| `dataformat_trades` | Data format to use to store historical trades data. <br> *Defaults to `jsongz`*. <br> **Datatype:** String
| `position_adjustment_enable` | Enables the strategy to use position adjustments (additional buys or sells). [More information here](strategy-callbacks.md#adjust-trade-position). <br> [Strategy Override](#parameters-in-the-strategy). <br>*Defaults to `false`.*<br> **Datatype:** Boolean
| `max_entry_position_adjustment` | Maximum additional order(s) for each open trade on top of the first entry Order. Set it to `-1` for unlimited additional orders. [More information here](strategy-callbacks.md#adjust-trade-position). <br> [Strategy Override](#parameters-in-the-strategy). <br>*Defaults to `-1`.*<br> **Datatype:** Positive Integer or -1
| `futures_funding_rate` | User-specified funding rate to be used when historical funding rates are not available from the exchange. This does not overwrite real historical rates. It is recommended that this be set to 0 unless you are testing a specific coin and you understand how the funding rate will affect freqtrade's profit calculations. [More information here](configuration.md) <br>*Defaults to None.*<br> **Datatype:** Float
### Parameters in the strategy

View File

@ -101,6 +101,12 @@ Possible values are any floats between 0.0 and 0.99
!!! Danger "A `liquidation_buffer` of 0.0, or a low `liquidation_buffer` is likely to result in liquidations, and liquidation fees"
Currently Freqtrade is able to calculate liquidation prices, but does not calculate liquidation fees. Setting your `liquidation_buffer` to 0.0, or using a low `liquidation_buffer` could result in your positions being liquidated. Freqtrade does not track liquidation fees, so liquidations will result in inaccurate profit/loss results for your bot. If you use a low `liquidation_buffer`, it is recommended to use `stoploss_on_exchange` if your exchange supports this.
## Unavailable funding rates
For futures data, exchanges commonly provide the futures candles, the marks, and the funding rates. However, it is common that whilst candles and marks might be available, the funding rates are not. This can affect backtesting timeranges, i.e. you may only be able to test recent timeranges and not earlier, experiencing the `No data found. Terminating.` error. To get around this, add the `futures_funding_rate` config option as listed in [configuration.md](configuration.md), and it is recommended that you set this to `0`, unless you know a given specific funding rate for your pair, exchange and timerange. Setting this to anything other than `0` can have drastic effects on your profit calculations within strategy, e.g. within the `custom_exit`, `custom_stoploss`, etc functions.
!!! This will not overwrite funding rates that are available from the exchange.
### Developer
#### Margin mode

View File

@ -68,7 +68,8 @@ def load_data(datadir: Path,
startup_candles: int = 0,
fail_without_data: bool = False,
data_format: str = 'json',
candle_type: CandleType = CandleType.SPOT
candle_type: CandleType = CandleType.SPOT,
user_futures_funding_rate = None,
) -> Dict[str, DataFrame]:
"""
Load ohlcv history data for a list of pairs.
@ -100,6 +101,10 @@ def load_data(datadir: Path,
)
if not hist.empty:
result[pair] = hist
else:
if candle_type is CandleType.FUNDING_RATE and user_futures_funding_rate is not None:
logger.warn(f"{pair} using user specified [{user_futures_funding_rate}]")
result[pair] = DataFrame(columns=["open","close","high","low","volume"])
if fail_without_data and not result:
raise OperationalException("No data found. Terminating.")

View File

@ -275,8 +275,27 @@ class Backtesting:
if pair not in self.exchange._leverage_tiers:
unavailable_pairs.append(pair)
continue
self.futures_data[pair] = funding_rates_dict[pair].merge(
mark_rates_dict[pair], on='date', how="inner", suffixes=["_fund", "_mark"])
if (pair in mark_rates_dict
and len(funding_rates_dict[pair]) == 0
and "futures_funding_rate" in self.config):
mark_rates_dict[pair]["open_fund"] = self.config.get('futures_funding_rate')
mark_rates_dict[pair]["close_fund"] = 0.0
mark_rates_dict[pair]["high_fund"] = 0.0
mark_rates_dict[pair]["low_fund"] = 0.0
mark_rates_dict[pair]["volume_fund"] = 0.0
mark_rates_dict[pair].rename(
columns = {'open':'open_mark',
'close':'close_mark',
'high':'high_mark',
'low':'low_mark',
'volume':'volume_mark'},
inplace = True)
self.futures_data[pair] = mark_rates_dict[pair]
else:
self.futures_data[pair] = mark_rates_dict[pair].merge(
funding_rates_dict[pair], on='date', how="inner", suffixes=["_fund", "_mark"])
if unavailable_pairs:
raise OperationalException(