diff --git a/config_full.json.example b/config_full.json.example
index db8debb2c..ef791d267 100644
--- a/config_full.json.example
+++ b/config_full.json.example
@@ -42,6 +42,7 @@
"order_book_max": 1,
"use_sell_signal": true,
"sell_profit_only": false,
+ "sell_profit_offset": 0.0,
"ignore_roi_if_buy_signal": false
},
"order_types": {
diff --git a/docs/configuration.md b/docs/configuration.md
index 13c7eb47b..926506f22 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -72,7 +72,8 @@ Mandatory parameters are marked as **Required**, which means that they are requi
| `ask_strategy.order_book_min` | Bot will scan from the top min to max Order Book Asks searching for a profitable rate.
*Defaults to `1`.*
**Datatype:** Positive Integer
| `ask_strategy.order_book_max` | Bot will scan from the top min to max Order Book Asks searching for a profitable rate.
*Defaults to `1`.*
**Datatype:** Positive Integer
| `ask_strategy.use_sell_signal` | Use sell signals produced by the strategy in addition to the `minimal_roi`. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `true`.*
**Datatype:** Boolean
-| `ask_strategy.sell_profit_only` | Wait until the bot makes a positive profit before taking a sell decision. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `false`.*
**Datatype:** Boolean
+| `ask_strategy.sell_profit_only` | Wait until the bot reaches `ask_strategy.sell_profit_offset` before taking a sell decision. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `false`.*
**Datatype:** Boolean
+| `ask_strategy.sell_profit_offset` | Sell-signal is only active above this value. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `0.0`.*
**Datatype:** Float (as ratio)
| `ask_strategy.ignore_roi_if_buy_signal` | Do not sell if the buy signal is still active. This setting takes preference over `minimal_roi` and `use_sell_signal`. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `false`.*
**Datatype:** Boolean
| `order_types` | Configure order-types depending on the action (`"buy"`, `"sell"`, `"stoploss"`, `"stoploss_on_exchange"`). [More information below](#understand-order_types). [Strategy Override](#parameters-in-the-strategy).
**Datatype:** Dict
| `order_time_in_force` | Configure time in force for buy and sell orders. [More information below](#understand-order_time_in_force). [Strategy Override](#parameters-in-the-strategy).
**Datatype:** Dict
diff --git a/freqtrade/constants.py b/freqtrade/constants.py
index e7d7e80f6..d48ab635e 100644
--- a/freqtrade/constants.py
+++ b/freqtrade/constants.py
@@ -154,6 +154,7 @@ CONF_SCHEMA = {
'order_book_max': {'type': 'integer', 'minimum': 1, 'maximum': 50},
'use_sell_signal': {'type': 'boolean'},
'sell_profit_only': {'type': 'boolean'},
+ 'sell_profit_offset': {'type': 'number', 'minimum': 0.0},
'ignore_roi_if_buy_signal': {'type': 'boolean'}
}
},
diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py
index d029ecd13..6c70b7c84 100644
--- a/freqtrade/optimize/optimize_reports.py
+++ b/freqtrade/optimize/optimize_reports.py
@@ -299,6 +299,7 @@ def generate_backtest_stats(btdata: Dict[str, DataFrame],
'minimal_roi': config['minimal_roi'],
'use_sell_signal': config['ask_strategy']['use_sell_signal'],
'sell_profit_only': config['ask_strategy']['sell_profit_only'],
+ 'sell_profit_offset': config['ask_strategy']['sell_profit_offset'],
'ignore_roi_if_buy_signal': config['ask_strategy']['ignore_roi_if_buy_signal'],
**daily_stats,
}
diff --git a/freqtrade/resolvers/strategy_resolver.py b/freqtrade/resolvers/strategy_resolver.py
index 2b7a4f0c2..825e6572a 100644
--- a/freqtrade/resolvers/strategy_resolver.py
+++ b/freqtrade/resolvers/strategy_resolver.py
@@ -79,6 +79,7 @@ class StrategyResolver(IResolver):
("use_sell_signal", True, 'ask_strategy'),
("sell_profit_only", False, 'ask_strategy'),
("ignore_roi_if_buy_signal", False, 'ask_strategy'),
+ ("sell_profit_offset", 0.0, 'ask_strategy'),
("disable_dataframe_checks", False, None),
]
for attribute, default, subkey in attributes:
diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py
index 348e6a446..8546b1eda 100644
--- a/freqtrade/strategy/interface.py
+++ b/freqtrade/strategy/interface.py
@@ -505,18 +505,19 @@ class IStrategy(ABC):
# Set current rate to high for backtesting sell
current_rate = high or rate
current_profit = trade.calc_profit_ratio(current_rate)
- config_ask_strategy = self.config.get('ask_strategy', {})
+ ask_strategy = self.config.get('ask_strategy', {})
# if buy signal and ignore_roi is set, we don't need to evaluate min_roi.
- roi_reached = (not (buy and config_ask_strategy.get('ignore_roi_if_buy_signal', False))
+ roi_reached = (not (buy and ask_strategy.get('ignore_roi_if_buy_signal', False))
and self.min_roi_reached(trade=trade, current_profit=current_profit,
current_time=date))
- if config_ask_strategy.get('sell_profit_only', False) and trade.calc_profit(rate=rate) <= 0:
+ if (ask_strategy.get('sell_profit_only', False)
+ and trade.calc_profit(rate=rate) <= ask_strategy.get('sell_profit_offset', 0)):
# Negative profits and sell_profit_only - ignore sell signal
sell_signal = False
else:
- sell_signal = sell and not buy and config_ask_strategy.get('use_sell_signal', True)
+ sell_signal = sell and not buy and ask_strategy.get('use_sell_signal', True)
# TODO: return here if sell-signal should be favored over ROI
# Start evaluations
diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py
index 5c5666788..e6aff3352 100644
--- a/tests/test_freqtradebot.py
+++ b/tests/test_freqtradebot.py
@@ -3065,6 +3065,7 @@ def test_sell_profit_only_enable_profit(default_conf, limit_buy_order, limit_buy
default_conf['ask_strategy'] = {
'use_sell_signal': True,
'sell_profit_only': True,
+ 'sell_profit_offset': 0.1,
}
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
@@ -3076,7 +3077,11 @@ def test_sell_profit_only_enable_profit(default_conf, limit_buy_order, limit_buy
trade.update(limit_buy_order)
freqtrade.wallets.update()
patch_get_signal(freqtrade, value=(False, True))
+ assert freqtrade.handle_trade(trade) is False
+
+ freqtrade.config['ask_strategy']['sell_profit_offset'] = 0.0
assert freqtrade.handle_trade(trade) is True
+
assert trade.sell_reason == SellType.SELL_SIGNAL.value