Adjust backtest so sell uses stop-loss or roi value as closerate
This commit is contained in:
parent
a0e8bfbd77
commit
233c442af9
@ -206,12 +206,20 @@ class Backtesting(object):
|
|||||||
|
|
||||||
buy_signal = sell_row.buy
|
buy_signal = sell_row.buy
|
||||||
sell = self.strategy.should_sell(trade, sell_row.open, sell_row.date, buy_signal,
|
sell = self.strategy.should_sell(trade, sell_row.open, sell_row.date, buy_signal,
|
||||||
sell_row.sell)
|
sell_row.sell, low=sell_row.low, high=sell_row.high)
|
||||||
if sell.sell_flag:
|
if sell.sell_flag:
|
||||||
|
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):
|
||||||
|
# set close-rate to min-roi
|
||||||
|
closerate = trade.open_rate + trade.open_rate * self.strategy.minimal_roi[0]
|
||||||
|
else:
|
||||||
|
closerate = sell_row.open
|
||||||
|
|
||||||
return BacktestResult(pair=pair,
|
return BacktestResult(pair=pair,
|
||||||
profit_percent=trade.calc_profit_percent(rate=sell_row.open),
|
profit_percent=trade.calc_profit_percent(rate=closerate),
|
||||||
profit_abs=trade.calc_profit(rate=sell_row.open),
|
profit_abs=trade.calc_profit(rate=closerate),
|
||||||
open_time=buy_row.date,
|
open_time=buy_row.date,
|
||||||
close_time=sell_row.date,
|
close_time=sell_row.date,
|
||||||
trade_duration=int((
|
trade_duration=int((
|
||||||
@ -220,7 +228,7 @@ class Backtesting(object):
|
|||||||
close_index=sell_row.Index,
|
close_index=sell_row.Index,
|
||||||
open_at_end=False,
|
open_at_end=False,
|
||||||
open_rate=buy_row.open,
|
open_rate=buy_row.open,
|
||||||
close_rate=sell_row.open,
|
close_rate=closerate,
|
||||||
sell_reason=sell.sell_type
|
sell_reason=sell.sell_type
|
||||||
)
|
)
|
||||||
if partial_ticker:
|
if partial_ticker:
|
||||||
@ -260,7 +268,7 @@ class Backtesting(object):
|
|||||||
position_stacking: do we allow position stacking? (default: False)
|
position_stacking: do we allow position stacking? (default: False)
|
||||||
:return: DataFrame
|
:return: DataFrame
|
||||||
"""
|
"""
|
||||||
headers = ['date', 'buy', 'open', 'close', 'sell']
|
headers = ['date', 'buy', 'open', 'close', 'sell', 'low', 'high']
|
||||||
processed = args['processed']
|
processed = args['processed']
|
||||||
max_open_trades = args.get('max_open_trades', 0)
|
max_open_trades = args.get('max_open_trades', 0)
|
||||||
position_stacking = args.get('position_stacking', False)
|
position_stacking = args.get('position_stacking', False)
|
||||||
|
@ -203,18 +203,22 @@ class IStrategy(ABC):
|
|||||||
return buy, sell
|
return buy, sell
|
||||||
|
|
||||||
def should_sell(self, trade: Trade, rate: float, date: datetime, buy: bool,
|
def should_sell(self, trade: Trade, rate: float, date: datetime, buy: bool,
|
||||||
sell: bool) -> SellCheckTuple:
|
sell: bool, low: float=None, high: float=None) -> SellCheckTuple:
|
||||||
"""
|
"""
|
||||||
This function evaluate if on the condition required to trigger a sell has been reached
|
This function evaluate if on the condition required to trigger a sell has been reached
|
||||||
if the threshold is reached and updates the trade record.
|
if the threshold is reached and updates the trade record.
|
||||||
:return: True if trade should be sold, False otherwise
|
:return: True if trade should be sold, False otherwise
|
||||||
"""
|
"""
|
||||||
current_profit = trade.calc_profit_percent(rate)
|
# Set current rate to low for backtesting sell
|
||||||
stoplossflag = self.stop_loss_reached(current_rate=rate, trade=trade, current_time=date,
|
current_rate = rate if not low else low
|
||||||
|
current_profit = trade.calc_profit_percent(current_rate)
|
||||||
|
stoplossflag = self.stop_loss_reached(current_rate=current_rate, trade=trade, current_time=date,
|
||||||
current_profit=current_profit)
|
current_profit=current_profit)
|
||||||
if stoplossflag.sell_flag:
|
if stoplossflag.sell_flag:
|
||||||
return stoplossflag
|
return stoplossflag
|
||||||
|
# Set current rate to low for backtesting sell
|
||||||
|
current_rate = rate if not high else high
|
||||||
|
current_profit = trade.calc_profit_percent(current_rate)
|
||||||
experimental = self.config.get('experimental', {})
|
experimental = self.config.get('experimental', {})
|
||||||
|
|
||||||
if buy and experimental.get('ignore_roi_if_buy_signal', False):
|
if buy and experimental.get('ignore_roi_if_buy_signal', False):
|
||||||
|
@ -72,8 +72,8 @@ tc1 = BTContainer(data=DataFrame([
|
|||||||
[getdate('2018-06-10 11:00:00').datetime, 9955, 9975, 9955, 9990, 12345, 0, 0],
|
[getdate('2018-06-10 11:00:00').datetime, 9955, 9975, 9955, 9990, 12345, 0, 0],
|
||||||
[getdate('2018-06-10 12:00:00').datetime, 9990, 9990, 9990, 9900, 12345, 0, 0]
|
[getdate('2018-06-10 12:00:00').datetime, 9990, 9990, 9990, 9900, 12345, 0, 0]
|
||||||
], columns=columns),
|
], columns=columns),
|
||||||
# stop_loss=-0.01, roi=1, trades=1, profit_perc=-0.01, sell_r=SellType.STOP_LOSS) # should be
|
stop_loss=-0.01, roi=1, trades=1, profit_perc=-0.01, sell_r=SellType.STOP_LOSS) # should be
|
||||||
stop_loss=-0.01, roi=1, trades=1, profit_perc=-0.003, sell_r=SellType.FORCE_SELL) #
|
# stop_loss=-0.01, roi=1, trades=1, profit_perc=-0.003, sell_r=SellType.FORCE_SELL) #
|
||||||
|
|
||||||
|
|
||||||
# Test 2 Minus 4% Low, minus 1% close
|
# Test 2 Minus 4% Low, minus 1% close
|
||||||
@ -88,8 +88,8 @@ tc2 = BTContainer(data=DataFrame([
|
|||||||
[getdate('2018-06-10 11:00:00').datetime, 9925, 9975, 9875, 9900, 12345, 0, 0],
|
[getdate('2018-06-10 11:00:00').datetime, 9925, 9975, 9875, 9900, 12345, 0, 0],
|
||||||
[getdate('2018-06-10 12:00:00').datetime, 9900, 9950, 9850, 9900, 12345, 0, 0]
|
[getdate('2018-06-10 12:00:00').datetime, 9900, 9950, 9850, 9900, 12345, 0, 0]
|
||||||
], columns=columns),
|
], columns=columns),
|
||||||
# stop_loss=-0.03, roi=1, trades=1, profit_perc=-0.03, sell_r=SellType.STOP_LOSS) #should be
|
stop_loss=-0.03, roi=1, trades=1, profit_perc=-0.03, sell_r=SellType.STOP_LOSS) #should be
|
||||||
stop_loss=-0.03, roi=1, trades=1, profit_perc=-0.012, sell_r=SellType.FORCE_SELL) #
|
# stop_loss=-0.03, roi=1, trades=1, profit_perc=-0.007, sell_r=SellType.FORCE_SELL) #
|
||||||
|
|
||||||
|
|
||||||
# Test 3 Candle drops 4%, Recovers 1%.
|
# Test 3 Candle drops 4%, Recovers 1%.
|
||||||
@ -108,8 +108,9 @@ tc3 = BTContainer(data=DataFrame([
|
|||||||
[getdate('2018-06-10 12:00:00').datetime, 9925, 9975, 8000, 8000, 12345, 0, 0],
|
[getdate('2018-06-10 12:00:00').datetime, 9925, 9975, 8000, 8000, 12345, 0, 0],
|
||||||
[getdate('2018-06-10 13:00:00').datetime, 9900, 9950, 9950, 9900, 12345, 0, 0]
|
[getdate('2018-06-10 13:00:00').datetime, 9900, 9950, 9950, 9900, 12345, 0, 0]
|
||||||
], columns=columns),
|
], columns=columns),
|
||||||
# stop_loss=-0.02, roi=1, trades=2, profit_perc=-0.4, sell_r=SellType.STOP_LOSS) #should be
|
stop_loss=-0.02, roi=1, trades=2, profit_perc=-0.04, sell_r=SellType.STOP_LOSS) #should be
|
||||||
stop_loss=-0.02, roi=1, trades=1, profit_perc=-0.012, sell_r=SellType.FORCE_SELL) #
|
# stop_loss=-0.02, roi=1, trades=1, profit_perc=-0.02, sell_r=SellType.STOP_LOSS) #should be
|
||||||
|
# stop_loss=-0.02, roi=1, trades=1, profit_perc=-0.012, sell_r=SellType.FORCE_SELL) #
|
||||||
|
|
||||||
|
|
||||||
# Test 4 Minus 3% / recovery +15%
|
# Test 4 Minus 3% / recovery +15%
|
||||||
@ -124,8 +125,8 @@ tc4 = BTContainer(data=DataFrame([
|
|||||||
[getdate('2018-06-10 11:00:00').datetime, 9925, 9975, 9875, 9900, 12345, 0, 0],
|
[getdate('2018-06-10 11:00:00').datetime, 9925, 9975, 9875, 9900, 12345, 0, 0],
|
||||||
[getdate('2018-06-10 12:00:00').datetime, 9900, 9950, 9850, 9900, 12345, 0, 0]
|
[getdate('2018-06-10 12:00:00').datetime, 9900, 9950, 9850, 9900, 12345, 0, 0]
|
||||||
], columns=columns),
|
], columns=columns),
|
||||||
# stop_loss=-0.02, roi=0.06, trades=1, profit_perc=-0.02, sell_r=SellType.STOP_LOSS) #should be
|
stop_loss=-0.02, roi=0.06, trades=1, profit_perc=-0.02, sell_r=SellType.STOP_LOSS) #should be
|
||||||
stop_loss=-0.02, roi=0.06, trades=1, profit_perc=-0.012, sell_r=SellType.FORCE_SELL)
|
# stop_loss=-0.02, roi=0.06, trades=1, profit_perc=-0.012, sell_r=SellType.FORCE_SELL)
|
||||||
|
|
||||||
# Test 5 / Drops 0.5% Closes +20%
|
# Test 5 / Drops 0.5% Closes +20%
|
||||||
# Candle Data for test 5
|
# Candle Data for test 5
|
||||||
@ -139,8 +140,8 @@ tc5 = BTContainer(data=DataFrame([
|
|||||||
[getdate('2018-06-10 11:00:00').datetime, 9925, 9975, 9945, 9900, 12345, 0, 0],
|
[getdate('2018-06-10 11:00:00').datetime, 9925, 9975, 9945, 9900, 12345, 0, 0],
|
||||||
[getdate('2018-06-10 12:00:00').datetime, 9900, 9950, 9850, 9900, 12345, 0, 0]
|
[getdate('2018-06-10 12:00:00').datetime, 9900, 9950, 9850, 9900, 12345, 0, 0]
|
||||||
], columns=columns),
|
], columns=columns),
|
||||||
# stop_loss=-0.01, roi=0.03, trades=1, profit_perc=0.03, sell_r=SellType.ROI) #should be
|
stop_loss=-0.01, roi=0.03, trades=1, profit_perc=0.03, sell_r=SellType.ROI) #should be
|
||||||
stop_loss=-0.01, roi=0.03, trades=1, profit_perc=-0.012, sell_r=SellType.FORCE_SELL)
|
# stop_loss=-0.01, roi=0.03, trades=1, profit_perc=-0.012, sell_r=SellType.FORCE_SELL)
|
||||||
|
|
||||||
# Test 6 / Drops 3% / Recovers 6% Positive / Closes 1% positve
|
# Test 6 / Drops 3% / Recovers 6% Positive / Closes 1% positve
|
||||||
# Candle Data for test 6
|
# Candle Data for test 6
|
||||||
@ -154,8 +155,8 @@ tc6 = BTContainer(data=DataFrame([
|
|||||||
[getdate('2018-06-10 11:00:00').datetime, 9925, 9975, 9945, 9900, 12345, 0, 0],
|
[getdate('2018-06-10 11:00:00').datetime, 9925, 9975, 9945, 9900, 12345, 0, 0],
|
||||||
[getdate('2018-06-10 12:00:00').datetime, 9900, 9950, 9850, 9900, 12345, 0, 0]
|
[getdate('2018-06-10 12:00:00').datetime, 9900, 9950, 9850, 9900, 12345, 0, 0]
|
||||||
], columns=columns),
|
], columns=columns),
|
||||||
# stop_loss=-0.02, roi=0.05, trades=1, profit_perc=-0.02, sell_r=SellType.STOP_LOSS) #should be
|
stop_loss=-0.02, roi=0.05, trades=1, profit_perc=-0.02, sell_r=SellType.STOP_LOSS) #should be
|
||||||
stop_loss=-0.02, roi=0.05, trades=1, profit_perc=-0.012, sell_r=SellType.FORCE_SELL) #
|
# stop_loss=-0.02, roi=0.05, trades=1, profit_perc=-0.012, sell_r=SellType.FORCE_SELL) #
|
||||||
|
|
||||||
# Test 7 - 6% Positive / 1% Negative / Close 1% Positve
|
# Test 7 - 6% Positive / 1% Negative / Close 1% Positve
|
||||||
# Candle Data for test 7
|
# Candle Data for test 7
|
||||||
@ -169,8 +170,8 @@ tc7 = BTContainer(data=DataFrame([
|
|||||||
[getdate('2018-06-10 11:00:00').datetime, 9925, 9975, 9945, 9900, 12345, 0, 0],
|
[getdate('2018-06-10 11:00:00').datetime, 9925, 9975, 9945, 9900, 12345, 0, 0],
|
||||||
[getdate('2018-06-10 12:00:00').datetime, 9900, 9950, 9850, 9900, 12345, 0, 0]
|
[getdate('2018-06-10 12:00:00').datetime, 9900, 9950, 9850, 9900, 12345, 0, 0]
|
||||||
], columns=columns),
|
], columns=columns),
|
||||||
# stop_loss=-0.02, roi=0.03, trades=1, profit_perc=0.03, sell_r=SellType.ROI) #should be
|
stop_loss=-0.02, roi=0.03, trades=1, profit_perc=0.03, sell_r=SellType.ROI) #should be
|
||||||
stop_loss=-0.02, roi=0.03, trades=1, profit_perc=-0.012, sell_r=SellType.FORCE_SELL) #
|
# stop_loss=-0.02, roi=0.03, trades=1, profit_perc=-0.012, sell_r=SellType.FORCE_SELL) #
|
||||||
|
|
||||||
TESTS = [
|
TESTS = [
|
||||||
# tc_profit1,
|
# tc_profit1,
|
||||||
@ -193,7 +194,9 @@ def test_backtest_results(default_conf, fee, mocker, caplog, data) -> None:
|
|||||||
"""
|
"""
|
||||||
default_conf["stoploss"] = data.stop_loss
|
default_conf["stoploss"] = data.stop_loss
|
||||||
default_conf["minimal_roi"] = {"0": data.roi}
|
default_conf["minimal_roi"] = {"0": data.roi}
|
||||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
# mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||||
|
# TODO: don't Mock fee to for now
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange.get_fee', MagicMock(return_value=0.0))
|
||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
|
|
||||||
backtesting = Backtesting(default_conf)
|
backtesting = Backtesting(default_conf)
|
||||||
|
Loading…
Reference in New Issue
Block a user