comment updates, formatting, TODOs
This commit is contained in:
		| @@ -66,6 +66,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|  | ||||
|         init_db(self.config.get('db_url', None), clean_open_orders=self.config['dry_run']) | ||||
|  | ||||
|         # TODO-lev: Do anything with this? | ||||
|         self.wallets = Wallets(self.config, self.exchange) | ||||
|  | ||||
|         PairLocks.timeframe = self.config['timeframe'] | ||||
| @@ -77,6 +78,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|         # so anything in the Freqtradebot instance should be ready (initialized), including | ||||
|         # the initial state of the bot. | ||||
|         # Keep this at the end of this initialization method. | ||||
|         # TODO-lev: Do I need to consider the rpc, pairlists or dataprovider? | ||||
|         self.rpc: RPCManager = RPCManager(self) | ||||
|  | ||||
|         self.pairlists = PairListManager(self.exchange, self.config) | ||||
| @@ -98,7 +100,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|         initial_state = self.config.get('initial_state') | ||||
|         self.state = State[initial_state.upper()] if initial_state else State.STOPPED | ||||
|  | ||||
|         # Protect sell-logic from forcesell and vice versa | ||||
|         # Protect exit-logic from forcesell and vice versa | ||||
|         self._exit_lock = Lock() | ||||
|         LoggingMixin.__init__(self, logger, timeframe_to_seconds(self.strategy.timeframe)) | ||||
|  | ||||
| @@ -170,9 +172,9 @@ class FreqtradeBot(LoggingMixin): | ||||
|             # Check and handle any timed out open orders | ||||
|             self.check_handle_timedout() | ||||
|  | ||||
|         # Protect from collisions with forcesell. | ||||
|         # Protect from collisions with forceexit. | ||||
|         # Without this, freqtrade my try to recreate stoploss_on_exchange orders | ||||
|         # while selling is in process, since telegram messages arrive in an different thread. | ||||
|         # while exiting is in process, since telegram messages arrive in an different thread. | ||||
|         with self._exit_lock: | ||||
|             trades = Trade.get_open_trades() | ||||
|             # First process current opened trades (positions) | ||||
| @@ -289,8 +291,8 @@ class FreqtradeBot(LoggingMixin): | ||||
|  | ||||
|     def handle_insufficient_funds(self, trade: Trade): | ||||
|         """ | ||||
|         Determine if we ever opened a sell order for this trade. | ||||
|         If not, try update buy fees - otherwise "refind" the open order we obviously lost. | ||||
|         Determine if we ever opened a exiting order for this trade. | ||||
|         If not, try update entering fees - otherwise "refind" the open order we obviously lost. | ||||
|         """ | ||||
|         sell_order = trade.select_order('sell', None) | ||||
|         if sell_order: | ||||
| @@ -312,7 +314,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|     def refind_lost_order(self, trade): | ||||
|         """ | ||||
|         Try refinding a lost trade. | ||||
|         Only used when InsufficientFunds appears on sell orders (stoploss or sell). | ||||
|         Only used when InsufficientFunds appears on exit orders (stoploss or long sell/short buy). | ||||
|         Tries to walk the stored orders and sell them off eventually. | ||||
|         """ | ||||
|         logger.info(f"Trying to refind lost order for {trade}") | ||||
| @@ -323,7 +325,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|                 logger.debug(f"Order {order} is no longer open.") | ||||
|                 continue | ||||
|             if order.ft_order_side == 'buy': | ||||
|                 # Skip buy side - this is handled by reupdate_buy_order_fees | ||||
|                 # Skip buy side - this is handled by reupdate_enter_order_fees | ||||
|                 continue | ||||
|             try: | ||||
|                 fo = self.exchange.fetch_order_or_stoploss_order(order.order_id, order.ft_pair, | ||||
| @@ -350,7 +352,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|  | ||||
|     def enter_positions(self) -> int: | ||||
|         """ | ||||
|         Tries to execute buy orders for new trades (positions) | ||||
|         Tries to execute long buy/short sell orders for new trades (positions) | ||||
|         """ | ||||
|         trades_created = 0 | ||||
|  | ||||
| @@ -366,7 +368,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|  | ||||
|         if not whitelist: | ||||
|             logger.info("No currency pair in active pair whitelist, " | ||||
|                         "but checking to sell open trades.") | ||||
|                         "but checking to exit open trades.") | ||||
|             return trades_created | ||||
|         if PairLocks.is_global_lock(): | ||||
|             lock = PairLocks.get_pair_longest_lock('*') | ||||
| @@ -621,7 +623,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|  | ||||
|     def _notify_enter_cancel(self, trade: Trade, order_type: str, reason: str) -> None: | ||||
|         """ | ||||
|         Sends rpc notification when a buy cancel occurred. | ||||
|         Sends rpc notification when a buy/short cancel occurred. | ||||
|         """ | ||||
|         current_rate = self.exchange.get_rate(trade.pair, refresh=False, side="buy") | ||||
|  | ||||
| @@ -667,7 +669,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|  | ||||
|     def exit_positions(self, trades: List[Any]) -> int: | ||||
|         """ | ||||
|         Tries to execute sell orders for open trades (positions) | ||||
|         Tries to execute sell/exit_short orders for open trades (positions) | ||||
|         """ | ||||
|         trades_closed = 0 | ||||
|         for trade in trades: | ||||
| @@ -693,8 +695,8 @@ class FreqtradeBot(LoggingMixin): | ||||
|  | ||||
|     def handle_trade(self, trade: Trade) -> bool: | ||||
|         """ | ||||
|         Sells the current pair if the threshold is reached and updates the trade record. | ||||
|         :return: True if trade has been sold, False otherwise | ||||
|         Sells/exits_short the current pair if the threshold is reached and updates the trade record. | ||||
|         :return: True if trade has been sold/exited_short, False otherwise | ||||
|         """ | ||||
|         if not trade.is_open: | ||||
|             raise DependencyException(f'Attempt to handle closed trade: {trade}') | ||||
| @@ -702,7 +704,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|         logger.debug('Handling %s ...', trade) | ||||
|  | ||||
|         (enter, exit_) = (False, False) | ||||
|  | ||||
|         # TODO-lev: change to use_exit_signal, ignore_roi_if_enter_signal | ||||
|         if (self.config.get('use_sell_signal', True) or | ||||
|                 self.config.get('ignore_roi_if_buy_signal', False)): | ||||
|             analyzed_df, _ = self.dataprovider.get_analyzed_dataframe(trade.pair, | ||||
| @@ -764,6 +766,8 @@ class FreqtradeBot(LoggingMixin): | ||||
|         Check if trade is fulfilled in which case the stoploss | ||||
|         on exchange should be added immediately if stoploss on exchange | ||||
|         is enabled. | ||||
|         # TODO-mg: liquidation price will always be on exchange, even though | ||||
|         # TODO-mg: stoploss_on_exchange might not be enabled | ||||
|         """ | ||||
|  | ||||
|         logger.debug('Handling stoploss on exchange %s ...', trade) | ||||
| @@ -782,6 +786,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|  | ||||
|         # We check if stoploss order is fulfilled | ||||
|         if stoploss_order and stoploss_order['status'] in ('closed', 'triggered'): | ||||
|             # TODO-lev: Update to exit reason | ||||
|             trade.sell_reason = SellType.STOPLOSS_ON_EXCHANGE.value | ||||
|             self.update_trade_state(trade, trade.stoploss_order_id, stoploss_order, | ||||
|                                     stoploss_order=True) | ||||
| @@ -797,7 +802,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|             # The trade can be closed already (sell-order fill confirmation came in this iteration) | ||||
|             return False | ||||
|  | ||||
|         # If buy order is fulfilled but there is no stoploss, we add a stoploss on exchange | ||||
|         # If enter order is fulfilled but there is no stoploss, we add a stoploss on exchange | ||||
|         if not stoploss_order: | ||||
|             stoploss = self.edge.stoploss(pair=trade.pair) if self.edge else self.strategy.stoploss | ||||
|             stop_price = trade.open_rate * (1 + stoploss) | ||||
| @@ -948,6 +953,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|         Buy cancel - cancel order | ||||
|         :return: True if order was fully cancelled | ||||
|         """ | ||||
|         # TODO-lev: Pay back borrowed/interest and transfer back on margin trades | ||||
|         was_trade_fully_canceled = False | ||||
|  | ||||
|         # Cancelled orders may have the status of 'canceled' or 'closed' | ||||
| @@ -992,6 +998,8 @@ class FreqtradeBot(LoggingMixin): | ||||
|             # to the order dict acquired before cancelling. | ||||
|             # we need to fall back to the values from order if corder does not contain these keys. | ||||
|             trade.amount = filled_amount | ||||
|             # TODO-lev: Check edge cases, we don't want to make leverage > 1.0 if we don't have to | ||||
|  | ||||
|             trade.stake_amount = trade.amount * trade.open_rate | ||||
|             self.update_trade_state(trade, trade.open_order_id, corder) | ||||
|  | ||||
| @@ -1000,13 +1008,15 @@ class FreqtradeBot(LoggingMixin): | ||||
|             reason += f", {constants.CANCEL_REASON['PARTIALLY_FILLED']}" | ||||
|  | ||||
|         self.wallets.update() | ||||
|         # TODO-lev: Should short and exit_short be an order type? | ||||
|  | ||||
|         self._notify_enter_cancel(trade, order_type=self.strategy.order_types['buy'], | ||||
|                                   reason=reason) | ||||
|         return was_trade_fully_canceled | ||||
|  | ||||
|     def handle_cancel_exit(self, trade: Trade, order: Dict, reason: str) -> str: | ||||
|         """ | ||||
|         Sell cancel - cancel order and update trade | ||||
|         Sell/exit_short cancel - cancel order and update trade | ||||
|         :return: Reason for cancel | ||||
|         """ | ||||
|         # if trade is not partially completed, just cancel the order | ||||
| @@ -1056,6 +1066,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|         :return: amount to sell | ||||
|         :raise: DependencyException: if available balance is not within 2% of the available amount. | ||||
|         """ | ||||
|         # TODO-lev Maybe update? | ||||
|         # Update wallets to ensure amounts tied up in a stoploss is now free! | ||||
|         self.wallets.update() | ||||
|         trade_base_currency = self.exchange.get_pair_base_currency(pair) | ||||
| @@ -1078,7 +1089,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|         :param sell_reason: Reason the sell was triggered | ||||
|         :return: True if it succeeds (supported) False (not supported) | ||||
|         """ | ||||
|         sell_type = 'sell' | ||||
|         sell_type = 'sell'  # TODO-lev: Update to exit | ||||
|         if sell_reason.sell_type in (SellType.STOP_LOSS, SellType.TRAILING_STOP_LOSS): | ||||
|             sell_type = 'stoploss' | ||||
|  | ||||
| @@ -1118,22 +1129,25 @@ class FreqtradeBot(LoggingMixin): | ||||
|             order_type = self.strategy.order_types.get("forcesell", order_type) | ||||
|  | ||||
|         amount = self._safe_sell_amount(trade.pair, trade.amount) | ||||
|         time_in_force = self.strategy.order_time_in_force['sell'] | ||||
|         time_in_force = self.strategy.order_time_in_force['sell']  # TODO-lev update to exit | ||||
|  | ||||
|         if not strategy_safe_wrapper(self.strategy.confirm_trade_exit, default_retval=True)( | ||||
|                 pair=trade.pair, trade=trade, order_type=order_type, amount=amount, rate=limit, | ||||
|                 time_in_force=time_in_force, sell_reason=sell_reason.sell_reason, | ||||
|                 current_time=datetime.now(timezone.utc)): | ||||
|             logger.info(f"User requested abortion of selling {trade.pair}") | ||||
|                 current_time=datetime.now(timezone.utc)):  # TODO-lev: Update to exit | ||||
|             logger.info(f"User requested abortion of exiting {trade.pair}") | ||||
|             return False | ||||
|  | ||||
|         try: | ||||
|             # Execute sell and update trade record | ||||
|             order = self.exchange.create_order(pair=trade.pair, | ||||
|                                                ordertype=order_type, side="sell", | ||||
|                                                amount=amount, rate=limit, | ||||
|                                                time_in_force=time_in_force | ||||
|                                                ) | ||||
|             order = self.exchange.create_order( | ||||
|                 pair=trade.pair, | ||||
|                 ordertype=order_type, | ||||
|                 side="sell", | ||||
|                 amount=amount, | ||||
|                 rate=limit, | ||||
|                 time_in_force=time_in_force | ||||
|             ) | ||||
|         except InsufficientFundsError as e: | ||||
|             logger.warning(f"Unable to place order {e}.") | ||||
|             # Try to figure out what went wrong | ||||
| @@ -1144,15 +1158,15 @@ class FreqtradeBot(LoggingMixin): | ||||
|         trade.orders.append(order_obj) | ||||
|  | ||||
|         trade.open_order_id = order['id'] | ||||
|         trade.sell_order_status = '' | ||||
|         trade.sell_order_status = ''  # TODO-lev: Update to exit_order_status | ||||
|         trade.close_rate_requested = limit | ||||
|         trade.sell_reason = sell_reason.sell_reason | ||||
|         trade.sell_reason = sell_reason.sell_reason  # TODO-lev: Update to exit_reason | ||||
|         # In case of market sell orders the order can be closed immediately | ||||
|         if order.get('status', 'unknown') in ('closed', 'expired'): | ||||
|             self.update_trade_state(trade, trade.open_order_id, order) | ||||
|         Trade.commit() | ||||
|  | ||||
|         # Lock pair for one candle to prevent immediate re-buys | ||||
|         # Lock pair for one candle to prevent immediate re-trading | ||||
|         self.strategy.lock_pair(trade.pair, datetime.now(timezone.utc), | ||||
|                                 reason='Auto lock') | ||||
|  | ||||
| @@ -1187,7 +1201,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|             'current_rate': current_rate, | ||||
|             'profit_amount': profit_trade, | ||||
|             'profit_ratio': profit_ratio, | ||||
|             'sell_reason': trade.sell_reason, | ||||
|             'sell_reason': trade.sell_reason,  # TODO-lev: change to exit_reason | ||||
|             'open_date': trade.open_date, | ||||
|             'close_date': trade.close_date or datetime.utcnow(), | ||||
|             'stake_currency': self.config['stake_currency'], | ||||
| @@ -1206,10 +1220,10 @@ class FreqtradeBot(LoggingMixin): | ||||
|         """ | ||||
|         Sends rpc notification when a sell cancel occurred. | ||||
|         """ | ||||
|         if trade.sell_order_status == reason: | ||||
|         if trade.sell_order_status == reason:  # TODO-lev: Update to exit_order_status | ||||
|             return | ||||
|         else: | ||||
|             trade.sell_order_status = reason | ||||
|             trade.sell_order_status = reason  # TODO-lev: Update to exit_order_status | ||||
|  | ||||
|         profit_rate = trade.close_rate if trade.close_rate else trade.close_rate_requested | ||||
|         profit_trade = trade.calc_profit(rate=profit_rate) | ||||
| @@ -1230,7 +1244,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|             'current_rate': current_rate, | ||||
|             'profit_amount': profit_trade, | ||||
|             'profit_ratio': profit_ratio, | ||||
|             'sell_reason': trade.sell_reason, | ||||
|             'sell_reason': trade.sell_reason,  # TODO-lev: trade to exit_reason | ||||
|             'open_date': trade.open_date, | ||||
|             'close_date': trade.close_date, | ||||
|             'stake_currency': self.config['stake_currency'], | ||||
| @@ -1316,6 +1330,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|         self.wallets.update() | ||||
|         if fee_abs != 0 and self.wallets.get_free(trade_base_currency) >= amount: | ||||
|             # Eat into dust if we own more than base currency | ||||
|             # TODO-lev: won't be in "base"(quote) currency for shorts | ||||
|             logger.info(f"Fee amount for {trade} was in base currency - " | ||||
|                         f"Eating Fee {fee_abs} into dust.") | ||||
|         elif fee_abs != 0: | ||||
| @@ -1392,6 +1407,7 @@ class FreqtradeBot(LoggingMixin): | ||||
|                 trade.update_fee(fee_cost, fee_currency, fee_rate, order.get('side', '')) | ||||
|  | ||||
|         if not isclose(amount, order_amount, abs_tol=constants.MATH_CLOSE_PREC): | ||||
|             # TODO-lev: leverage? | ||||
|             logger.warning(f"Amount {amount} does not match amount {trade.amount}") | ||||
|             raise DependencyException("Half bought? Amounts don't match") | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user