Add preliminary backtesting test
This commit is contained in:
parent
5c82cce06c
commit
b2f33944ec
@ -40,6 +40,8 @@ class BTContainer(NamedTuple):
|
|||||||
custom_entry_price: Optional[float] = None
|
custom_entry_price: Optional[float] = None
|
||||||
custom_exit_price: Optional[float] = None
|
custom_exit_price: Optional[float] = None
|
||||||
leverage: float = 1.0
|
leverage: float = 1.0
|
||||||
|
timeout: Optional[int] = None
|
||||||
|
adjust_entry_price: Optional[float] = None
|
||||||
|
|
||||||
|
|
||||||
def _get_frame_time_from_offset(offset):
|
def _get_frame_time_from_offset(offset):
|
||||||
|
@ -754,6 +754,21 @@ tc47 = BTContainer(data=[
|
|||||||
trades=[]
|
trades=[]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Test 48: Custom-entry-price below all candles - readjust order
|
||||||
|
tc48 = BTContainer(data=[
|
||||||
|
# D O H L C V EL XL ES Xs BT
|
||||||
|
[0, 5000, 5050, 4950, 5000, 6172, 1, 0],
|
||||||
|
[1, 5000, 5500, 4951, 5000, 6172, 0, 0], # timeout
|
||||||
|
[2, 4900, 5250, 4500, 5100, 6172, 0, 0], # Order readjust
|
||||||
|
[3, 5100, 5100, 4650, 4750, 6172, 0, 0],
|
||||||
|
[4, 4750, 4950, 4350, 4750, 6172, 0, 0]],
|
||||||
|
stop_loss=-0.01, roi={"0": 0.10}, profit_perc=0.1,
|
||||||
|
timeout=1000,
|
||||||
|
custom_entry_price=4200,
|
||||||
|
adjust_entry_price=5200,
|
||||||
|
trades=[BTrade(exit_reason=ExitType.ROI, open_tick=1, close_tick=2, is_short=False)]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
TESTS = [
|
TESTS = [
|
||||||
tc0,
|
tc0,
|
||||||
@ -804,6 +819,7 @@ TESTS = [
|
|||||||
tc45,
|
tc45,
|
||||||
tc46,
|
tc46,
|
||||||
tc47,
|
tc47,
|
||||||
|
tc48,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -817,6 +833,11 @@ def test_backtest_results(default_conf, fee, mocker, caplog, data: BTContainer)
|
|||||||
default_conf["timeframe"] = tests_timeframe
|
default_conf["timeframe"] = tests_timeframe
|
||||||
default_conf["trailing_stop"] = data.trailing_stop
|
default_conf["trailing_stop"] = data.trailing_stop
|
||||||
default_conf["trailing_only_offset_is_reached"] = data.trailing_only_offset_is_reached
|
default_conf["trailing_only_offset_is_reached"] = data.trailing_only_offset_is_reached
|
||||||
|
if data.timeout:
|
||||||
|
default_conf['unfilledtimeout'].update({
|
||||||
|
'entry': data.timeout,
|
||||||
|
'exit': data.timeout,
|
||||||
|
})
|
||||||
# Only add this to configuration If it's necessary
|
# Only add this to configuration If it's necessary
|
||||||
if data.trailing_stop_positive is not None:
|
if data.trailing_stop_positive is not None:
|
||||||
default_conf["trailing_stop_positive"] = data.trailing_stop_positive
|
default_conf["trailing_stop_positive"] = data.trailing_stop_positive
|
||||||
@ -840,6 +861,9 @@ def test_backtest_results(default_conf, fee, mocker, caplog, data: BTContainer)
|
|||||||
backtesting.strategy.custom_entry_price = MagicMock(return_value=data.custom_entry_price)
|
backtesting.strategy.custom_entry_price = MagicMock(return_value=data.custom_entry_price)
|
||||||
if data.custom_exit_price:
|
if data.custom_exit_price:
|
||||||
backtesting.strategy.custom_exit_price = MagicMock(return_value=data.custom_exit_price)
|
backtesting.strategy.custom_exit_price = MagicMock(return_value=data.custom_exit_price)
|
||||||
|
if data.adjust_entry_price:
|
||||||
|
backtesting.strategy.adjust_entry_price = MagicMock(return_value=data.adjust_entry_price)
|
||||||
|
|
||||||
backtesting.strategy.use_custom_stoploss = data.use_custom_stoploss
|
backtesting.strategy.use_custom_stoploss = data.use_custom_stoploss
|
||||||
backtesting.strategy.leverage = lambda **kwargs: data.leverage
|
backtesting.strategy.leverage = lambda **kwargs: data.leverage
|
||||||
caplog.set_level(logging.DEBUG)
|
caplog.set_level(logging.DEBUG)
|
||||||
|
@ -2493,10 +2493,8 @@ def test_adjust_entry_cancel(
|
|||||||
freqtrade.strategy.adjust_entry_price = MagicMock(return_value=None)
|
freqtrade.strategy.adjust_entry_price = MagicMock(return_value=None)
|
||||||
freqtrade.manage_open_orders()
|
freqtrade.manage_open_orders()
|
||||||
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
|
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
|
||||||
nb_trades = len(trades)
|
assert len(trades) == 0
|
||||||
assert nb_trades == 0
|
assert len(Order.query.all()) == 0
|
||||||
nb_all_orders = len(Order.query.all())
|
|
||||||
assert nb_all_orders == 0
|
|
||||||
assert log_has_re(
|
assert log_has_re(
|
||||||
f"{'Sell' if is_short else 'Buy'} order user requested order cancel*", caplog)
|
f"{'Sell' if is_short else 'Buy'} order user requested order cancel*", caplog)
|
||||||
assert log_has_re(
|
assert log_has_re(
|
||||||
@ -2535,10 +2533,8 @@ def test_adjust_entry_maintain_replace(
|
|||||||
freqtrade.strategy.adjust_entry_price = MagicMock(return_value=old_order['price'])
|
freqtrade.strategy.adjust_entry_price = MagicMock(return_value=old_order['price'])
|
||||||
freqtrade.manage_open_orders()
|
freqtrade.manage_open_orders()
|
||||||
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
|
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
|
||||||
nb_trades = len(trades)
|
assert len(trades) == 1
|
||||||
assert nb_trades == 1
|
assert len(Order.get_open_orders()) == 1
|
||||||
nb_orders = len(Order.get_open_orders())
|
|
||||||
assert nb_orders == 1
|
|
||||||
# Entry adjustment is called
|
# Entry adjustment is called
|
||||||
assert freqtrade.strategy.adjust_entry_price.call_count == 1
|
assert freqtrade.strategy.adjust_entry_price.call_count == 1
|
||||||
|
|
||||||
@ -2547,10 +2543,8 @@ def test_adjust_entry_maintain_replace(
|
|||||||
freqtrade.strategy.adjust_entry_price = MagicMock(return_value=1234)
|
freqtrade.strategy.adjust_entry_price = MagicMock(return_value=1234)
|
||||||
freqtrade.manage_open_orders()
|
freqtrade.manage_open_orders()
|
||||||
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
|
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
|
||||||
nb_trades = len(trades)
|
assert len(trades) == 1
|
||||||
assert nb_trades == 1
|
|
||||||
nb_all_orders = len(Order.query.all())
|
nb_all_orders = len(Order.query.all())
|
||||||
freqtrade.logger.warning(Order.query.all())
|
|
||||||
assert nb_all_orders == 2
|
assert nb_all_orders == 2
|
||||||
# New order seems to be in closed status?
|
# New order seems to be in closed status?
|
||||||
# nb_open_orders = len(Order.get_open_orders())
|
# nb_open_orders = len(Order.get_open_orders())
|
||||||
@ -2588,8 +2582,7 @@ def test_check_handle_cancelled_buy(
|
|||||||
assert cancel_order_mock.call_count == 0
|
assert cancel_order_mock.call_count == 0
|
||||||
assert rpc_mock.call_count == 1
|
assert rpc_mock.call_count == 1
|
||||||
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
|
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
|
||||||
nb_trades = len(trades)
|
assert len(trades) == 0
|
||||||
assert nb_trades == 0
|
|
||||||
assert log_has_re(
|
assert log_has_re(
|
||||||
f"{'Sell' if is_short else 'Buy'} order cancelled on exchange for Trade.*", caplog)
|
f"{'Sell' if is_short else 'Buy'} order cancelled on exchange for Trade.*", caplog)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user