Repository: freqtrade/freqtrade

Issue:
Is there a way to have /forcebuy or /forcesell execute the order at the market price, but have all other orders generated by a signal executed at the limit price?


## Describe the enhancement

An enhancement to consider would be to add a feature where the bot can perform market orders on /forcebuy and /forcesell, and limit orders on all other regular trades where a signal is generated.  You could add a command like /forcebuy market or /forcesell market.  This would allow you to enter or exit a trade if you see the price start to move rapidly while still allowing the bot to use limit orders for regular trades where a signal is generated.   





Discussion:
Why not start 2 bots? One for strategy based trading, and one for the "trade management" where you start trades manually.

That'll also give you possibilities to better compare your buys with strategy buys.


That's a great idea.  Thank you for the feedback.  
citing from Slack:

"my idea was to add "forcebuy", "forcesell" to the order_types dict in the strategy/configuration, if not set -- "buy" and "sell" entries from order_types should be used respectively

that's another option: to control it in the rpc command
"

both approaches (in addition to running 2 instances of the bot, as @xmatthias proposed above) can be useful and could be implemented as enhancements, in my opinion

Thanks hroff-1902, I agree both would be useful.  I'm in the process of setting up the other bot now as xmatthias suggested.  Thank you. 
at Slack @xmatthias said:
> the problem with `/forcebuy limit price` is that the command is already `/forcebuy <pair> [<price>]` ... now if i want market but no price ... that'll be difficult to detect and to be clear what is the desired way

in my opinion, `/forcebuy <pair> [<price>]` should buy using order type set in `order_types`, while `/forcebuy limit <pair> [<price>]` and `/forcebuy market <pair>` could forcibly buy with limit/market orders respectively (same for sell)

To be honest, I don't like this as enhancement (definitely not for telegram).

it'll complicate the telegram interface unnecessarily - and will "clog"  great strategy results in the database with poor human decisions (at least that's how my strategy would most likely look like).


The request itself (want to forcebuy with market order if price raises fast, but use limit if the strategy decides) comes from a FOMO approach - you see it raising, so you want in fast ... the probability of that trade going south with the next dip is higher than when using a strategy (which hopefully uses an analytical approach).

From a user perspective, you'll want to have a way to seperate these trades to know if the strategy or you performed better - so running 2 bots should be the way to go for this.

It's must have feature. At the current moment there's no ability to get rid of falling positions.

@xmatthias I understand what you don't want to complicated telegram interface. What about 
`/forcesell <trade_id>|all limit|market` with `limit` value as default?



that may work for `/forcesell`- but `/forcebuy <pair> [price]` already has an optional "price" argument, and i think the 2 commands should be very similar to use.

In the end, you can use `/forcebuy` with a price higher than current to get a marketable limit order (limit orders will always execute at the limit price *or better*).

For `/forcesell` i can think of 2 options...
either use a seperate ordertype for forcesell (which falls back to sell type if not configured) - or allow adding price to `/forcesell` as well (so the interface is aligned).

I guess the 2nd option (using price and the marketable limit order option) is the more flexible option as you can also get out "controlled" - without risking 100% loss.
Market orders are dependent on the orderbook - and if it's very thin on the bid side, you may "eat" your way all the way to 0.
If you're in strongly falling position (which suggests a weak buy side already) - you're risking 100% by using a market order to sell.


In theory, we can even try to convert the price parameter to float - or check if it's "market" and then act accordingly 
(possible commands would then be `/forcesell 33 20.2`, or `/forcesell 33 market`  (market is a price in theory) - but i'm not certain that's very easy to understand.

---

However, I still don't see why this would be a must have, so expect a very low priority from my side. 

Use proper stoploss and trust in your strategy.
You only have to get rid of a "falling" position if you set your stoploss wrongly / too wide.

Resolving patch:
diff --git a/freqtrade/constants.py b/freqtrade/constants.py
--- a/freqtrade/constants.py
+++ b/freqtrade/constants.py
@@ -179,6 +179,8 @@
             '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
--- a/freqtrade/freqtradebot.py
+++ b/freqtrade/freqtradebot.py
@@ -520,7 +520,8 @@ def _check_depth_of_market_buy(self, pair: str, conf: Dict) -> bool:
             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 @@ def execute_buy(self, pair: str, stake_amount: float, price: Optional[float] = N
 
         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
--- a/freqtrade/rpc/rpc.py
+++ b/freqtrade/rpc/rpc.py
@@ -593,7 +593,7 @@ def _rpc_forcebuy(self, pair: str, price: Optional[float]) -> Optional[Trade]:
             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:


Test patch: