Merge pull request #2624 from freqtrade/backtest_refactor

handle and document ROI=-1
This commit is contained in:
hroff-1902
2019-12-14 23:11:36 +03:00
committed by GitHub
5 changed files with 118 additions and 25 deletions

View File

@@ -261,6 +261,45 @@ class Backtesting:
ticker[pair] = [x for x in ticker_data.itertuples()]
return ticker
def _get_close_rate(self, sell_row, trade: Trade, sell, trade_dur) -> float:
"""
Get close rate for backtesting result
"""
# Special handling if high or low hit STOP_LOSS or ROI
if sell.sell_type in (SellType.STOP_LOSS, SellType.TRAILING_STOP_LOSS):
# Set close_rate to stoploss
return trade.stop_loss
elif sell.sell_type == (SellType.ROI):
roi_entry, roi = self.strategy.min_roi_reached_entry(trade_dur)
if roi is not None:
if roi == -1 and roi_entry % self.timeframe_mins == 0:
# When forceselling with ROI=-1, the roi time will always be equal to trade_dur.
# If that entry is a multiple of the timeframe (so on candle open)
# - we'll use open instead of close
return sell_row.open
# - (Expected abs profit + open_rate + open_fee) / (fee_close -1)
close_rate = - (trade.open_rate * roi + trade.open_rate *
(1 + trade.fee_open)) / (trade.fee_close - 1)
if (trade_dur > 0 and trade_dur == roi_entry
and roi_entry % self.timeframe_mins == 0
and sell_row.open > close_rate):
# new ROI entry came into effect.
# use Open rate if open_rate > calculated sell rate
return sell_row.open
# Use the maximum between close_rate and low as we
# cannot sell outside of a candle.
# Applies when a new ROI setting comes in place and the whole candle is above that.
return max(close_rate, sell_row.low)
else:
# This should not be reached...
return sell_row.open
else:
return sell_row.open
def _get_sell_trade_entry(
self, pair: str, buy_row: DataFrame,
partial_ticker: List, trade_count_lock: Dict,
@@ -287,26 +326,7 @@ class Backtesting:
sell_row.sell, low=sell_row.low, high=sell_row.high)
if sell.sell_flag:
trade_dur = int((sell_row.date - buy_row.date).total_seconds() // 60)
# Special handling if high or low hit STOP_LOSS or ROI
if sell.sell_type in (SellType.STOP_LOSS, SellType.TRAILING_STOP_LOSS):
# Set close_rate to stoploss
closerate = trade.stop_loss
elif sell.sell_type == (SellType.ROI):
roi = self.strategy.min_roi_reached_entry(trade_dur)
if roi is not None:
# - (Expected abs profit + open_rate + open_fee) / (fee_close -1)
closerate = - (trade.open_rate * roi + trade.open_rate *
(1 + trade.fee_open)) / (trade.fee_close - 1)
# Use the maximum between closerate and low as we
# cannot sell outside of a candle.
# Applies when using {"xx": -1} as roi to force sells after xx minutes
closerate = max(closerate, sell_row.low)
else:
# This should not be reached...
closerate = sell_row.open
else:
closerate = sell_row.open
closerate = self._get_close_rate(sell_row, trade, sell, trade_dur)
return BacktestResult(pair=pair,
profit_percent=trade.calc_profit_percent(rate=closerate),