Attempt to support limit orders for position adjustment.
This commit is contained in:
		| @@ -469,15 +469,14 @@ class FreqtradeBot(LoggingMixin): | |||||||
|     def adjust_trade_position(self, trade: Trade): |     def adjust_trade_position(self, trade: Trade): | ||||||
|         """ |         """ | ||||||
|         Check the implemented trading strategy for adjustment command. |         Check the implemented trading strategy for adjustment command. | ||||||
|         If the strategy triggers the adjustment a new buy/sell-order gets issued. |         If the strategy triggers the adjustment, a new order gets issued. | ||||||
|         Once that completes, the existing trade is modified to match new data. |         Once that completes, the existing trade is modified to match new data. | ||||||
|         """ |         """ | ||||||
|         logger.debug(f"adjust_trade_position for pair {trade.pair}") |  | ||||||
|         for order in trade.orders: |         for order in trade.orders: | ||||||
|             if order.ft_is_open: |             if order.ft_is_open: | ||||||
|                 logger.debug(f"Order {order} is still open, skipping pair.") |  | ||||||
|                 return |                 return | ||||||
|  |  | ||||||
|  |         logger.debug(f"adjust_trade_position for pair {trade.pair}") | ||||||
|         sell_rate = self.exchange.get_rate(trade.pair, refresh=True, side="sell") |         sell_rate = self.exchange.get_rate(trade.pair, refresh=True, side="sell") | ||||||
|         current_profit = trade.calc_profit_ratio(sell_rate) |         current_profit = trade.calc_profit_ratio(sell_rate) | ||||||
|         stake_to_adjust = strategy_safe_wrapper(self.strategy.adjust_trade_position, default_retval=None)( |         stake_to_adjust = strategy_safe_wrapper(self.strategy.adjust_trade_position, default_retval=None)( | ||||||
| @@ -491,6 +490,7 @@ class FreqtradeBot(LoggingMixin): | |||||||
|         if stake_to_adjust != None and stake_to_adjust < 0.0: |         if stake_to_adjust != None and stake_to_adjust < 0.0: | ||||||
|             # We should decrease our position |             # We should decrease our position | ||||||
|             # TODO: Selling part of the trade not implemented yet. |             # TODO: Selling part of the trade not implemented yet. | ||||||
|  |             logger.error(f"Unable to decrease trade position / sell partially for pair {trade.pair}, feature not implemented.") | ||||||
|             return |             return | ||||||
|  |  | ||||||
|         return |         return | ||||||
| @@ -528,7 +528,7 @@ class FreqtradeBot(LoggingMixin): | |||||||
|  |  | ||||||
|         logger.debug(f'Executing additional order: amount={amount}, stake={stake_amount}, price={enter_limit_requested}') |         logger.debug(f'Executing additional order: amount={amount}, stake={stake_amount}, price={enter_limit_requested}') | ||||||
|  |  | ||||||
|         order_type = 'market' |         order_type = self.strategy.order_types['buy'] | ||||||
|         order = self.exchange.create_order(pair=pair, ordertype=order_type, side="buy", |         order = self.exchange.create_order(pair=pair, ordertype=order_type, side="buy", | ||||||
|                                            amount=amount, rate=enter_limit_requested, |                                            amount=amount, rate=enter_limit_requested, | ||||||
|                                            time_in_force=time_in_force) |                                            time_in_force=time_in_force) | ||||||
| @@ -573,7 +573,7 @@ class FreqtradeBot(LoggingMixin): | |||||||
|         # Updating wallets |         # Updating wallets | ||||||
|         self.wallets.update() |         self.wallets.update() | ||||||
|  |  | ||||||
|         self._notify_enter(trade, order_type) |         self._notify_additional_buy(trade, order_obj, order_type) | ||||||
|  |  | ||||||
|         return True |         return True | ||||||
|  |  | ||||||
| @@ -729,6 +729,31 @@ class FreqtradeBot(LoggingMixin): | |||||||
|  |  | ||||||
|         return True |         return True | ||||||
|  |  | ||||||
|  |     def _notify_additional_buy(self, trade: Trade, order: Order, order_type: Optional[str] = None, | ||||||
|  |                       fill: bool = False) -> None: | ||||||
|  |         """ | ||||||
|  |         Sends rpc notification when a buy occurred. | ||||||
|  |         """ | ||||||
|  |         msg = { | ||||||
|  |             'trade_id': trade.id, | ||||||
|  |             'type': RPCMessageType.BUY_FILL if fill else RPCMessageType.BUY, | ||||||
|  |             'buy_tag': "adjust_trade_position", | ||||||
|  |             'exchange': self.exchange.name.capitalize(), | ||||||
|  |             'pair': trade.pair, | ||||||
|  |             'limit': order.price,  # Deprecated (?) | ||||||
|  |             'open_rate': order.price, | ||||||
|  |             'order_type': order_type, | ||||||
|  |             'stake_amount': order.cost, | ||||||
|  |             'stake_currency': self.config['stake_currency'], | ||||||
|  |             'fiat_currency': self.config.get('fiat_display_currency', None), | ||||||
|  |             'amount': order.amount, | ||||||
|  |             'open_date': order.order_filled_date or datetime.utcnow(), | ||||||
|  |             'current_rate': order.price, | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         # Send the message | ||||||
|  |         self.rpc.send_msg(msg) | ||||||
|  |  | ||||||
|     def _notify_enter(self, trade: Trade, order_type: Optional[str] = None, |     def _notify_enter(self, trade: Trade, order_type: Optional[str] = None, | ||||||
|                       fill: bool = False) -> None: |                       fill: bool = False) -> None: | ||||||
|         """ |         """ | ||||||
|   | |||||||
| @@ -568,8 +568,13 @@ class LocalTrade(): | |||||||
|         profit_ratio = (close_trade_value / self.open_trade_value) - 1 |         profit_ratio = (close_trade_value / self.open_trade_value) - 1 | ||||||
|         return float(f"{profit_ratio:.8f}") |         return float(f"{profit_ratio:.8f}") | ||||||
|  |  | ||||||
|  |  | ||||||
|     def recalc_trade_from_orders(self): |     def recalc_trade_from_orders(self): | ||||||
|  |         # We need at least 2 orders for averaging amounts and rates. | ||||||
|  |         if len(self.orders) < 2: | ||||||
|  |             # Just in case, still recalc open trade value | ||||||
|  |             self.recalc_open_trade_value() | ||||||
|  |             return | ||||||
|  |  | ||||||
|         total_amount = 0.0 |         total_amount = 0.0 | ||||||
|         total_stake = 0.0 |         total_stake = 0.0 | ||||||
|         for temp_order in self.orders: |         for temp_order in self.orders: | ||||||
| @@ -590,7 +595,6 @@ class LocalTrade(): | |||||||
|             if self.stop_loss_pct is not None and self.open_rate is not None: |             if self.stop_loss_pct is not None and self.open_rate is not None: | ||||||
|                 self.adjust_stop_loss(self.open_rate, self.stop_loss_pct) |                 self.adjust_stop_loss(self.open_rate, self.stop_loss_pct) | ||||||
|  |  | ||||||
|  |  | ||||||
|     def select_order(self, order_side: str, is_open: Optional[bool]) -> Optional[Order]: |     def select_order(self, order_side: str, is_open: Optional[bool]) -> Optional[Order]: | ||||||
|         """ |         """ | ||||||
|         Finds latest order for this orderside and status |         Finds latest order for this orderside and status | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user