From da5be9fbd0ea132a9490ecca007d2e8adf568c34 Mon Sep 17 00:00:00 2001 From: xmatthias Date: Tue, 26 Jun 2018 23:06:27 +0200 Subject: [PATCH] add stop_loss based on work from @berlinguyinca --- config.json.example | 4 +--- config_full.json.example | 3 ++- docs/stoploss.md | 6 ++---- freqtrade/analyze.py | 42 ++++++++++++++++++++++++++++++++++++---- freqtrade/constants.py | 2 ++ 5 files changed, 45 insertions(+), 12 deletions(-) diff --git a/config.json.example b/config.json.example index 7b53ffa99..f92849ec9 100644 --- a/config.json.example +++ b/config.json.example @@ -5,9 +5,7 @@ "fiat_display_currency": "USD", "ticker_interval" : "5m", "dry_run": false, - "trailing_stop": { - "positive" : 0.005 - }, + "trailing_stop": false, "unfilledtimeout": 600, "bid_strategy": { "ask_last_balance": 0.0 diff --git a/config_full.json.example b/config_full.json.example index d7d8f7369..244daabac 100644 --- a/config_full.json.example +++ b/config_full.json.example @@ -5,7 +5,8 @@ "fiat_display_currency": "USD", "dry_run": false, "ticker_interval": "5m", - "trailing_stop": true, + "trailing_stop": false, + "trailing_stop_positive": 0.005, "minimal_roi": { "40": 0.0, "30": 0.01, diff --git a/docs/stoploss.md b/docs/stoploss.md index cf6a2bcab..db4433a02 100644 --- a/docs/stoploss.md +++ b/docs/stoploss.md @@ -39,12 +39,10 @@ Due to demand, it is possible to have a default stop loss, when you are in the r 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 -this can be configured in the main configuration file, the following way: +This 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": 0.01, ``` The 0.01 would translate to a 1% stop loss, once you hit profit. diff --git a/freqtrade/analyze.py b/freqtrade/analyze.py index 36e00dd0e..b283e3ae9 100644 --- a/freqtrade/analyze.py +++ b/freqtrade/analyze.py @@ -180,7 +180,7 @@ class Analyze(object): :return: True if trade should be sold, False otherwise """ current_profit = trade.calc_profit_percent(rate) - if self.stop_loss_reached(current_profit=current_profit): + if self.stop_loss_reached(current_rate=rate, trade=trade, current_time=date): return True experimental = self.config.get('experimental', {}) @@ -204,12 +204,46 @@ class Analyze(object): return False - def stop_loss_reached(self, current_profit: float) -> bool: - """Based on current profit of the trade and configured stoploss, decides to sell or not""" + def stop_loss_reached(self, current_rate: float, trade: Trade, current_time: datetime) -> bool: + """ + Based on current profit of the trade and configured (trailing) stoploss, + decides to sell or not + """ + + current_profit = trade.calc_profit_percent(current_rate) + trailing_stop = self.config.get('trailing_stop', False) + if trade.stop_loss is None: + # initially adjust the stop loss to the base value + trade.adjust_stop_loss(trade.open_rate, self.strategy.stoploss) + + # evaluate if the stoploss was hit + if self.strategy.stoploss is not None and trade.stop_loss >= current_rate: + + if trailing_stop: + logger.debug( + f"HIT STOP: current price at {current_rate:.6f}, " + f"stop loss is {trade.stop_loss:.6f}, " + f"initial stop loss was at {trade.initial_stop_loss:.6f}, " + f"trade opened at {trade.open_rate:.6f}") + logger.debug(f"trailing stop saved {trade.stop_loss - trade.initial_stop_loss:.6f}") - if self.strategy.stoploss is not None and current_profit < self.strategy.stoploss: logger.debug('Stop loss hit.') return True + + # update the stop loss afterwards, after all by definition it's supposed to be hanging + if trailing_stop: + + # check if we have a special stop loss for positive condition + # and if profit is positive + stop_loss_value = self.strategy.stoploss + if 'trailing_stop_positive' in self.config and current_profit > 0: + + stop_loss_value = self.config.get('trailing_stop_positive') + logger.debug(f"using positive stop loss mode: {stop_loss_value} " + f"since we have profit {current_profit}") + + trade.adjust_stop_loss(current_rate, stop_loss_value) + return False def min_roi_reached(self, trade: Trade, current_profit: float, current_time: datetime) -> bool: diff --git a/freqtrade/constants.py b/freqtrade/constants.py index 0f12905e3..4ba1a7094 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -61,6 +61,8 @@ CONF_SCHEMA = { 'minProperties': 1 }, 'stoploss': {'type': 'number', 'maximum': 0, 'exclusiveMaximum': True}, + 'trailing_stop': {'type': 'boolean'}, + 'trailing_stop_positive': {'type': 'number', 'minimum': 0}, 'unfilledtimeout': {'type': 'integer', 'minimum': 0}, 'bid_strategy': { 'type': 'object',