Merge pull request #1034 from freqtrade/feat/positive_sl_limit

add offset for positive trailing stop loss
This commit is contained in:
Samuel Husso 2018-07-29 08:30:29 +03:00 committed by GitHub
commit 187e039a58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 82 additions and 8 deletions

View File

@ -7,6 +7,7 @@
"ticker_interval": "5m",
"trailing_stop": false,
"trailing_stop_positive": 0.005,
"trailing_stop_positive_offset": 0.0051,
"minimal_roi": {
"40": 0.0,
"30": 0.01,

View File

@ -27,6 +27,7 @@ The table below will list all configuration parameters.
| `stoploss` | -0.10 | No | Value of the stoploss in percent used by the bot. More information below. If set, this parameter will override `stoploss` from your strategy file.
| `trailing_stoploss` | false | No | Enables trailing stop-loss (based on `stoploss` in either configuration or strategy file).
| `trailing_stoploss_positve` | 0 | No | Changes stop-loss once profit has been reached.
| `trailing_stoploss_positve_offset` | 0 | No | Offset on when to apply `trailing_stoploss_positive`. Percentage value which should be positive.
| `unfilledtimeout.buy` | 10 | Yes | How long (in minutes) the bot will wait for an unfilled buy order to complete, after which the order will be cancelled.
| `unfilledtimeout.sell` | 10 | Yes | How long (in minutes) the bot will wait for an unfilled sell order to complete, after which the order will be cancelled.
| `bid_strategy.ask_last_balance` | 0.0 | Yes | Set the bidding price. More information below.

View File

@ -35,14 +35,17 @@ basically what this means is that your stop loss will be adjusted to be always b
### Custom positive loss
Due to demand, it is possible to have a default stop loss, when you are in the red with your buy, but once your buy turns positive,
the system will utilize a new stop loss, which can be a different value. For example your default stop loss is 5%, but once you are in the
black, it will be changed to be only a 1% stop loss
Due to demand, it is possible to have a default stop loss, when you are in the red with your buy, but once your profit surpasses a certain percentage,
the system will utilize a new stop loss, which can be a different value. For example your default stop loss is 5%, but once you have 1.1% profit,
it will be changed to be only a 1% stop loss, which trails the green candles until it goes below them.
This can be configured in the main configuration file and requires `"trailing_stop": true` to be set to true.
Both values can be configured in the main configuration file and requires `"trailing_stop": true` to be set to true.
``` json
"trailing_stop_positive": 0.01,
"trailing_stop_positive_offset": 0.011,
```
The 0.01 would translate to a 1% stop loss, once you hit profit.
The 0.01 would translate to a 1% stop loss, once you hit 1.1% profit.
You should also make sure to have this value higher than your minimal ROI, otherwise minimal ROI will apply first and sell your trade.

View File

@ -63,6 +63,7 @@ CONF_SCHEMA = {
'stoploss': {'type': 'number', 'maximum': 0, 'exclusiveMaximum': True},
'trailing_stop': {'type': 'boolean'},
'trailing_stop_positive': {'type': 'number', 'minimum': 0, 'maximum': 1},
'trailing_stop_positive_offset': {'type': 'number', 'minimum': 0, 'maximum': 1},
'unfilledtimeout': {
'type': 'object',
'properties': {

View File

@ -200,6 +200,7 @@ class IStrategy(ABC):
"""
Based on current profit of the trade and configured (trailing) stoploss,
decides to sell or not
:param current_profit: current profit in percent
"""
trailing_stop = self.config.get('trailing_stop', False)
@ -227,12 +228,15 @@ class IStrategy(ABC):
# check if we have a special stop loss for positive condition
# and if profit is positive
stop_loss_value = self.stoploss
if 'trailing_stop_positive' in self.config and current_profit > 0:
sl_offset = self.config.get('trailing_stop_positive_offset', 0.0)
if 'trailing_stop_positive' in self.config and current_profit > sl_offset:
# Ignore mypy error check in configuration that this is a float
stop_loss_value = self.config.get('trailing_stop_positive') # type: ignore
logger.debug(f"using positive stop loss mode: {stop_loss_value} "
f"since we have profit {current_profit}")
f"with offset {sl_offset:.4g} "
f"since we have profit {current_profit:.4f}%")
trade.adjust_stop_loss(current_rate, stop_loss_value)

View File

@ -1814,7 +1814,71 @@ def test_trailing_stop_loss_positive(default_conf, limit_buy_order, fee, markets
}))
# stop-loss not reached, adjusted stoploss
assert freqtrade.handle_trade(trade) is False
assert log_has(f'using positive stop loss mode: 0.01 since we have profit 0.26662643',
assert log_has(f'using positive stop loss mode: 0.01 with offset 0 '
f'since we have profit 0.2666%',
caplog.record_tuples)
assert log_has(f'adjusted stop loss', caplog.record_tuples)
assert trade.stop_loss == 0.0000138501
mocker.patch('freqtrade.exchange.Exchange.get_ticker',
MagicMock(return_value={
'bid': buy_price + 0.000002,
'ask': buy_price + 0.000002,
'last': buy_price + 0.000002
}))
# Lower price again (but still positive)
assert freqtrade.handle_trade(trade) is True
assert log_has(
f'HIT STOP: current price at {buy_price + 0.000002:.6f}, '
f'stop loss is {trade.stop_loss:.6f}, '
f'initial stop loss was at 0.000010, trade opened at 0.000011', caplog.record_tuples)
def test_trailing_stop_loss_offset(default_conf, limit_buy_order, fee, caplog, mocker) -> None:
"""
Test sell_profit_only feature when enabled and we have a loss
"""
buy_price = limit_buy_order['price']
patch_RPCManager(mocker)
patch_coinmarketcap(mocker)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
validate_pairs=MagicMock(),
get_ticker=MagicMock(return_value={
'bid': buy_price - 0.000001,
'ask': buy_price - 0.000001,
'last': buy_price - 0.000001
}),
buy=MagicMock(return_value={'id': limit_buy_order['id']}),
get_fee=fee,
)
conf = deepcopy(default_conf)
conf['trailing_stop'] = True
conf['trailing_stop_positive'] = 0.01
conf['trailing_stop_positive_offset'] = 0.011
freqtrade = FreqtradeBot(conf)
patch_get_signal(freqtrade)
freqtrade.strategy.min_roi_reached = lambda trade, current_profit, current_time: False
freqtrade.create_trade()
trade = Trade.query.first()
trade.update(limit_buy_order)
caplog.set_level(logging.DEBUG)
# stop-loss not reached
assert freqtrade.handle_trade(trade) is False
# Raise ticker above buy price
mocker.patch('freqtrade.exchange.Exchange.get_ticker',
MagicMock(return_value={
'bid': buy_price + 0.000003,
'ask': buy_price + 0.000003,
'last': buy_price + 0.000003
}))
# stop-loss not reached, adjusted stoploss
assert freqtrade.handle_trade(trade) is False
assert log_has(f'using positive stop loss mode: 0.01 with offset 0.011 '
f'since we have profit 0.2666%',
caplog.record_tuples)
assert log_has(f'adjusted stop loss', caplog.record_tuples)
assert trade.stop_loss == 0.0000138501