diff --git a/config_full.json.example b/config_full.json.example index 9a613c0a1..8366774c4 100644 --- a/config_full.json.example +++ b/config_full.json.example @@ -50,6 +50,7 @@ "sell": "limit", "emergencysell": "market", "forcesell": "market", + "forcebuy": "market", "stoploss": "market", "stoploss_on_exchange": false, "stoploss_on_exchange_interval": 60 diff --git a/docs/configuration.md b/docs/configuration.md index 99a5fea04..83ffbbff9 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -278,7 +278,7 @@ For example, if your strategy is using a 1h timeframe, and you only want to buy ### Understand order_types -The `order_types` configuration parameter maps actions (`buy`, `sell`, `stoploss`, `emergencysell`, `forcesell`) to order-types (`market`, `limit`, ...) as well as configures stoploss to be on the exchange and defines stoploss on exchange update interval in seconds. +The `order_types` configuration parameter maps actions (`buy`, `sell`, `stoploss`, `emergencysell`, `forcesell`, `forcebuy`) to order-types (`market`, `limit`, ...) as well as configures stoploss to be on the exchange and defines stoploss on exchange update interval in seconds. This allows to buy using limit orders, sell using limit-orders, and create stoplosses using market orders. It also allows to set the @@ -290,7 +290,7 @@ the buy order is fulfilled. If this is configured, the following 4 values (`buy`, `sell`, `stoploss` and `stoploss_on_exchange`) need to be present, otherwise the bot will fail to start. -For information on (`emergencysell`,`forcesell`, `stoploss_on_exchange`,`stoploss_on_exchange_interval`,`stoploss_on_exchange_limit_ratio`) please see stop loss documentation [stop loss on exchange](stoploss.md) +For information on (`emergencysell`,`forcesell`, `forcebuy`, `stoploss_on_exchange`,`stoploss_on_exchange_interval`,`stoploss_on_exchange_limit_ratio`) please see stop loss documentation [stop loss on exchange](stoploss.md) Syntax for Strategy: @@ -299,6 +299,7 @@ order_types = { "buy": "limit", "sell": "limit", "emergencysell": "market", + "forcebuy": "market", "forcesell": "market", "stoploss": "market", "stoploss_on_exchange": False, @@ -314,6 +315,7 @@ Configuration: "buy": "limit", "sell": "limit", "emergencysell": "market", + "forcebuy": "market", "forcesell": "market", "stoploss": "market", "stoploss_on_exchange": false, diff --git a/docs/stoploss.md b/docs/stoploss.md index 4a4391655..ae191f639 100644 --- a/docs/stoploss.md +++ b/docs/stoploss.md @@ -55,6 +55,10 @@ This same logic will reapply a stoploss order on the exchange should you cancel `forcesell` is an optional value, which defaults to the same value as `sell` and is used when sending a `/forcesell` command from Telegram or from the Rest API. +### forcebuy + +`forcebuy` is an optional value, which defaults to the same value as `buy` and is used when sending a `/forcebuy` command from Telegram or from the Rest API. + ### emergencysell `emergencysell` is an optional value, which defaults to `market` and is used when creating stop loss on exchange orders fails. diff --git a/freqtrade/constants.py b/freqtrade/constants.py index c03bff0ad..06eaad4f9 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -179,6 +179,8 @@ CONF_SCHEMA = { 'properties': { 'buy': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES}, 'sell': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES}, + 'forcesell': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES}, + 'forcebuy': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES}, 'emergencysell': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES}, 'stoploss': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES}, 'stoploss_on_exchange': {'type': 'boolean'}, diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 2f64f3dac..f605d61c4 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -520,7 +520,8 @@ class FreqtradeBot(LoggingMixin): logger.info(f"Bids to asks delta for {pair} does not satisfy condition.") return False - def execute_buy(self, pair: str, stake_amount: float, price: Optional[float] = None) -> bool: + def execute_buy(self, pair: str, stake_amount: float, price: Optional[float] = None, + forcebuy: bool = False) -> bool: """ Executes a limit buy for the given pair :param pair: pair for which we want to create a LIMIT_BUY @@ -548,6 +549,10 @@ class FreqtradeBot(LoggingMixin): amount = stake_amount / buy_limit_requested order_type = self.strategy.order_types['buy'] + if forcebuy: + # Forcebuy can define a different ordertype + order_type = self.strategy.order_types.get('forcebuy', order_type) + if not strategy_safe_wrapper(self.strategy.confirm_trade_entry, default_retval=True)( pair=pair, order_type=order_type, amount=amount, rate=buy_limit_requested, time_in_force=time_in_force): diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index fa830486e..61e22234d 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -593,7 +593,7 @@ class RPC: pair, self._freqtrade.get_free_open_trades()) # execute buy - if self._freqtrade.execute_buy(pair, stakeamount, price): + if self._freqtrade.execute_buy(pair, stakeamount, price, forcebuy=True): trade = Trade.get_trades([Trade.is_open.is_(True), Trade.pair == pair]).first() return trade else: