mirror of
https://github.com/freqtrade/freqtrade.git
synced 2024-11-10 10:21:59 +00:00
Allow custom_stoploss to cooperate with stoploss on exchange
This commit is contained in:
parent
30e5c01cb1
commit
16dad8b6d4
|
@ -136,6 +136,7 @@ Values set in the configuration file always overwrite values set in the strategy
|
|||
* `trailing_stop_positive`
|
||||
* `trailing_stop_positive_offset`
|
||||
* `trailing_only_offset_is_reached`
|
||||
* `use_custom_stoploss`
|
||||
* `process_only_new_candles`
|
||||
* `order_types`
|
||||
* `order_time_in_force`
|
||||
|
|
|
@ -998,7 +998,8 @@ class FreqtradeBot(LoggingMixin):
|
|||
logger.warning('Stoploss order was cancelled, but unable to recreate one.')
|
||||
|
||||
# Finally we check if stoploss on exchange should be moved up because of trailing.
|
||||
if stoploss_order and self.config.get('trailing_stop', False):
|
||||
if stoploss_order and (self.config.get('trailing_stop', False)
|
||||
or self.config.get('use_custom_stoploss', False)):
|
||||
# if trailing stoploss is enabled we check if stoploss value has changed
|
||||
# in which case we cancel stoploss order and put another one with new
|
||||
# value immediately
|
||||
|
|
|
@ -68,6 +68,7 @@ class StrategyResolver(IResolver):
|
|||
("trailing_stop_positive", None, None),
|
||||
("trailing_stop_positive_offset", 0.0, None),
|
||||
("trailing_only_offset_is_reached", None, None),
|
||||
("use_custom_stoploss", None, None),
|
||||
("process_only_new_candles", None, None),
|
||||
("order_types", None, None),
|
||||
("order_time_in_force", None, None),
|
||||
|
|
|
@ -123,6 +123,7 @@ class ShowConfig(BaseModel):
|
|||
trailing_stop_positive: Optional[float]
|
||||
trailing_stop_positive_offset: Optional[float]
|
||||
trailing_only_offset_is_reached: Optional[bool]
|
||||
use_custom_stoploss: Optional[bool]
|
||||
timeframe: str
|
||||
timeframe_ms: int
|
||||
timeframe_min: int
|
||||
|
|
|
@ -129,6 +129,7 @@ class RPC:
|
|||
'trailing_stop_positive': config.get('trailing_stop_positive'),
|
||||
'trailing_stop_positive_offset': config.get('trailing_stop_positive_offset'),
|
||||
'trailing_only_offset_is_reached': config.get('trailing_only_offset_is_reached'),
|
||||
'use_custom_stoploss': config.get('use_custom_stoploss'),
|
||||
'bot_name': config.get('bot_name', 'freqtrade'),
|
||||
'timeframe': config.get('timeframe'),
|
||||
'timeframe_ms': timeframe_to_msecs(config['timeframe']
|
||||
|
|
|
@ -1570,6 +1570,109 @@ def test_handle_stoploss_on_exchange_trailing_error(mocker, default_conf, fee, c
|
|||
assert log_has_re(r"Could not create trailing stoploss order for pair ETH/BTC\..*", caplog)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("init_persistence")
|
||||
def test_handle_stoploss_on_exchange_custom_stop(mocker, default_conf, fee,
|
||||
limit_buy_order, limit_sell_order) -> None:
|
||||
# When trailing stoploss is set
|
||||
stoploss = MagicMock(return_value={'id': 13434334})
|
||||
patch_RPCManager(mocker)
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=MagicMock(return_value={
|
||||
'bid': 0.00001172,
|
||||
'ask': 0.00001173,
|
||||
'last': 0.00001172
|
||||
}),
|
||||
buy=MagicMock(return_value={'id': limit_buy_order['id']}),
|
||||
sell=MagicMock(return_value={'id': limit_sell_order['id']}),
|
||||
get_fee=fee,
|
||||
stoploss=stoploss,
|
||||
stoploss_adjust=MagicMock(return_value=True),
|
||||
)
|
||||
|
||||
# enabling TSL
|
||||
default_conf['use_custom_stoploss'] = True
|
||||
|
||||
# disabling ROI
|
||||
default_conf['minimal_roi']['0'] = 999999999
|
||||
|
||||
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
||||
|
||||
# enabling stoploss on exchange
|
||||
freqtrade.strategy.order_types['stoploss_on_exchange'] = True
|
||||
|
||||
# setting stoploss
|
||||
freqtrade.strategy.custom_stoploss = lambda *args, **kwargs: -0.04
|
||||
|
||||
# setting stoploss_on_exchange_interval to 60 seconds
|
||||
freqtrade.strategy.order_types['stoploss_on_exchange_interval'] = 60
|
||||
|
||||
patch_get_signal(freqtrade)
|
||||
|
||||
freqtrade.enter_positions()
|
||||
trade = Trade.query.first()
|
||||
trade.is_open = True
|
||||
trade.open_order_id = None
|
||||
trade.stoploss_order_id = 100
|
||||
|
||||
stoploss_order_hanging = MagicMock(return_value={
|
||||
'id': 100,
|
||||
'status': 'open',
|
||||
'type': 'stop_loss_limit',
|
||||
'price': 3,
|
||||
'average': 2,
|
||||
'info': {
|
||||
'stopPrice': '0.000011134'
|
||||
}
|
||||
})
|
||||
|
||||
mocker.patch('freqtrade.exchange.Exchange.fetch_stoploss_order', stoploss_order_hanging)
|
||||
|
||||
assert freqtrade.handle_trade(trade) is False
|
||||
assert freqtrade.handle_stoploss_on_exchange(trade) is False
|
||||
|
||||
# price jumped 2x
|
||||
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', MagicMock(return_value={
|
||||
'bid': 0.00002344,
|
||||
'ask': 0.00002346,
|
||||
'last': 0.00002344
|
||||
}))
|
||||
|
||||
cancel_order_mock = MagicMock()
|
||||
stoploss_order_mock = MagicMock(return_value={'id': 13434334})
|
||||
mocker.patch('freqtrade.exchange.Exchange.cancel_stoploss_order', cancel_order_mock)
|
||||
mocker.patch('freqtrade.exchange.Exchange.stoploss', stoploss_order_mock)
|
||||
|
||||
# stoploss should not be updated as the interval is 60 seconds
|
||||
assert freqtrade.handle_trade(trade) is False
|
||||
assert freqtrade.handle_stoploss_on_exchange(trade) is False
|
||||
cancel_order_mock.assert_not_called()
|
||||
stoploss_order_mock.assert_not_called()
|
||||
|
||||
assert freqtrade.handle_trade(trade) is False
|
||||
assert trade.stop_loss == 0.00002346 * 0.96
|
||||
assert trade.stop_loss_pct == -0.04
|
||||
|
||||
# setting stoploss_on_exchange_interval to 0 seconds
|
||||
freqtrade.strategy.order_types['stoploss_on_exchange_interval'] = 0
|
||||
|
||||
assert freqtrade.handle_stoploss_on_exchange(trade) is False
|
||||
|
||||
cancel_order_mock.assert_called_once_with(100, 'ETH/BTC')
|
||||
stoploss_order_mock.assert_called_once_with(amount=85.32423208,
|
||||
pair='ETH/BTC',
|
||||
order_types=freqtrade.strategy.order_types,
|
||||
stop_price=0.00002346 * 0.96)
|
||||
|
||||
# price fell below stoploss, so dry-run sells trade.
|
||||
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', MagicMock(return_value={
|
||||
'bid': 0.00002144,
|
||||
'ask': 0.00002146,
|
||||
'last': 0.00002144
|
||||
}))
|
||||
assert freqtrade.handle_trade(trade) is True
|
||||
|
||||
|
||||
def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, caplog,
|
||||
limit_buy_order, limit_sell_order) -> None:
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user