class ExchangePersonalData(Initializable): # note: symbol keys are without / def __init__(self, exchange_manager): super().__init__() self.logger = get_logger(self.__class__.__name__) self.exchange_manager = exchange_manager self.config = exchange_manager.config self.trader = None self.exchange = None self.portfolio_manager = None self.trades_manager = None self.orders_manager = None self.positions_manager = None async def initialize_impl(self): self.trader = self.exchange_manager.trader self.exchange = self.exchange_manager.exchange if self.trader.is_enabled: try: self.portfolio_manager = PortfolioManager( self.config, self.trader, self.exchange_manager) self.trades_manager = TradesManager(self.config, self.trader, self.exchange_manager) self.orders_manager = OrdersManager(self.config, self.trader, self.exchange_manager) self.positions_manager = PositionsManager( self.config, self.trader, self.exchange_manager) await self.portfolio_manager.initialize() await self.trades_manager.initialize() await self.orders_manager.initialize() await self.positions_manager.initialize() except Exception as e: self.logger.error( f"Error when initializing : {e}. " f"{self.exchange.name} personal data disabled.") self.logger.exception(e) # updates async def handle_portfolio_update(self, balance, should_notify: bool = True) -> bool: try: changed: bool = await self.portfolio_manager.handle_balance_update( balance) if should_notify: await get_chan( BALANCE_CHANNEL, self.exchange.name).get_internal_producer().send(balance) return changed except AttributeError as e: self.logger.exception(f"Failed to update balance : {e}") return False async def handle_portfolio_update_from_order(self, order, should_notify: bool = True ) -> bool: try: changed: bool = await self.portfolio_manager.handle_balance_update_from_order( order) if should_notify: await get_chan(BALANCE_CHANNEL, self.exchange.name). \ get_internal_producer().send(self.portfolio_manager.portfolio.portfolio) return changed except AttributeError as e: self.logger.exception(f"Failed to update balance : {e}") return False async def handle_portfolio_profitability_update(self, balance, ticker, symbol, should_notify: bool = True ): try: portfolio_profitability = self.portfolio_manager.portfolio_profitability if balance is not None: await portfolio_profitability.handle_balance_update(balance) if ticker is not None and symbol is not None: await portfolio_profitability.handle_ticker_update( symbol, ticker) if should_notify: await get_chan(BALANCE_PROFITABILITY_CHANNEL, self.exchange.name).get_internal_producer() \ .send(profitability=portfolio_profitability.profitability, profitability_percent=portfolio_profitability.profitability_percent, market_profitability_percent=portfolio_profitability.market_profitability_percent, initial_portfolio_current_profitability=portfolio_profitability.initial_portfolio_current_profitability) except Exception as e: self.logger.exception( f"Failed to update portfolio profitability : {e}") async def handle_order_update(self, symbol, order_id, order, should_notify: bool = True) -> (bool, bool): try: changed: bool = self.orders_manager.upsert_order(order_id, order) if should_notify: await get_chan(ORDERS_CHANNEL, self.exchange.name).get_internal_producer() \ .send_(symbol=symbol, order=order, is_from_bot=True, is_closed=False, is_updated=changed) return changed except Exception as e: self.logger.exception(f"Failed to update order : {e}") return False async def handle_order_instance_update(self, order, should_notify: bool = True): try: changed: bool = self.orders_manager.upsert_order_instance(order) if should_notify: await get_chan(ORDERS_CHANNEL, self.exchange.name).get_internal_producer() \ .send(symbol=order.symbol, order=order, is_from_bot=True, is_closed=False, is_updated=changed) return changed except Exception as e: self.logger.exception(f"Failed to update order instance : {e}") return False async def handle_closed_order_update(self, symbol, order_id, order, should_notify: bool = True) -> bool: try: changed: bool = self.orders_manager.upsert_order_close( order_id, order) if should_notify: await get_chan(ORDERS_CHANNEL, self.exchange.name).get_internal_producer() \ .send(symbol=symbol, order=order, is_from_bot=True, is_closed=True, is_updated=changed) return changed except Exception as e: self.logger.exception(f"Failed to update order : {e}") return False async def handle_trade_update(self, symbol, trade_id, trade, should_notify: bool = True): try: changed: bool = self.trades_manager.upsert_trade(trade_id, trade) if should_notify: await get_chan(TRADES_CHANNEL, self.exchange.name).get_internal_producer() \ .send(symbol=symbol, trade=trade, old_trade=False) return changed except Exception as e: self.logger.exception(f"Failed to update trade : {e}") return False async def handle_trade_instance_update(self, trade, should_notify: bool = True): try: changed: bool = self.trades_manager.upsert_trade_instance(trade) if should_notify: await get_chan(TRADES_CHANNEL, self.exchange.name).get_internal_producer() \ .send(symbol=trade.symbol, trade=trade, old_trade=False) return changed except Exception as e: self.logger.exception(f"Failed to update trade instance : {e}") return False async def handle_position_update(self, symbol, position_id, position, should_notify: bool = True): try: changed: bool = self.positions_manager.upsert_position( position_id, position) if should_notify: await get_chan(POSITIONS_CHANNEL, self.exchange.name).get_internal_producer() \ .send(symbol=symbol, position=position, is_closed=False, is_updated=changed, is_from_bot=True) return changed except Exception as e: self.logger.exception(f"Failed to update position : {e}") return False async def handle_position_instance_update(self, position, should_notify: bool = True): try: changed: bool = self.positions_manager.upsert_position_instance( position) if should_notify: await get_chan(POSITIONS_CHANNEL, self.exchange.name).get_internal_producer() \ .send(symbol=position.symbol, position=position, is_closed=False, is_updated=changed, is_from_bot=True) return changed except Exception as e: self.logger.exception(f"Failed to update position instance : {e}") return False def get_order_portfolio(self, order): return order.linked_portfolio if order.linked_portfolio is not None else self.portfolio_manager.portfolio
class ExchangePersonalData(Initializable): # note: symbol keys are without / def __init__(self, exchange_manager): super().__init__() self.logger = get_logger(self.__class__.__name__) self.exchange_manager = exchange_manager self.config = exchange_manager.config self.trader = None self.exchange = None self.portfolio_manager = None self.trades_manager = None self.orders_manager = None self.positions_manager = None async def initialize_impl(self): self.trader = self.exchange_manager.trader self.exchange = self.exchange_manager.exchange if self.trader.is_enabled: try: self.portfolio_manager = PortfolioManager( self.config, self.trader, self.exchange_manager) self.trades_manager = TradesManager(self.config, self.trader, self.exchange_manager) self.orders_manager = OrdersManager(self.config, self.trader, self.exchange_manager) self.positions_manager = PositionsManager( self.config, self.trader, self.exchange_manager) await self.portfolio_manager.initialize() await self.trades_manager.initialize() await self.orders_manager.initialize() await self.positions_manager.initialize() except Exception as e: self.logger.exception( e, True, f"Error when initializing : {e}. " f"{self.exchange.name} personal data disabled.") # updates async def handle_portfolio_update(self, balance, should_notify: bool = True) -> bool: try: changed: bool = self.portfolio_manager.handle_balance_update( balance) if should_notify: await get_chan(BALANCE_CHANNEL, self.exchange_manager.id ).get_internal_producer().send(balance) return changed except AttributeError as e: self.logger.exception(e, True, f"Failed to update balance : {e}") return False async def handle_portfolio_update_from_order(self, order, should_notify: bool = True ) -> bool: try: changed: bool = self.portfolio_manager.handle_balance_update_from_order( order) if should_notify: await get_chan(BALANCE_CHANNEL, self.exchange_manager.id). \ get_internal_producer().send(self.portfolio_manager.portfolio.portfolio) return changed except AttributeError as e: self.logger.exception(e, True, f"Failed to update balance : {e}") return False async def handle_portfolio_profitability_update(self, balance, mark_price, symbol, should_notify: bool = True ): try: portfolio_profitability = self.portfolio_manager.portfolio_profitability if balance is not None: await portfolio_profitability.handle_balance_update(balance) if mark_price is not None and symbol is not None: await portfolio_profitability.handle_mark_price_update( symbol=symbol, mark_price=mark_price) if should_notify: await get_chan(BALANCE_PROFITABILITY_CHANNEL, self.exchange_manager.id).get_internal_producer() \ .send(profitability=portfolio_profitability.profitability, profitability_percent=portfolio_profitability.profitability_percent, market_profitability_percent=portfolio_profitability.market_profitability_percent, initial_portfolio_current_profitability=portfolio_profitability.initial_portfolio_current_profitability) except Exception as e: self.logger.exception( e, True, f"Failed to update portfolio profitability : {e}") async def handle_order_update_from_raw(self, symbol, order_id, raw_order, should_notify: bool = True) -> bool: try: changed: bool = self.orders_manager.upsert_order_from_raw( order_id, raw_order) if should_notify: await get_chan(ORDERS_CHANNEL, self.exchange_manager.id).get_internal_producer() \ .send(cryptocurrency=self.exchange_manager.exchange.get_pair_cryptocurrency(symbol), symbol=symbol, order=raw_order, is_from_bot=True, is_closed=False, is_updated=changed) return changed except Exception as e: self.logger.exception(e, True, f"Failed to update order : {e}") return False async def handle_order_instance_update(self, order, should_notify: bool = True): try: changed: bool = self.orders_manager.upsert_order_instance(order) if should_notify: await get_chan(ORDERS_CHANNEL, self.exchange_manager.id).get_internal_producer() \ .send(cryptocurrency=self.exchange_manager.exchange.get_pair_cryptocurrency(order.symbol), symbol=order.symbol, order=order.to_dict(), is_from_bot=True, is_closed=False, is_updated=changed) return changed except Exception as e: self.logger.exception(e, True, f"Failed to update order instance : {e}") return False async def handle_closed_order_update(self, symbol, order_id, raw_order, should_notify: bool = True) -> bool: try: existing_order = self.orders_manager.upsert_order_close_from_raw( order_id, raw_order) if existing_order is not None: if existing_order.status is OrderStatus.CANCELED: await self.trader.cancel_order(existing_order) elif existing_order.status is OrderStatus.FILLED: await self.trader.close_filled_order(existing_order) else: self.logger.error( f"Unknown closed order status: {existing_order.status} for order: {raw_order}" ) if should_notify: await get_chan(ORDERS_CHANNEL, self.exchange_manager.id).get_internal_producer() \ .send(cryptocurrency=self.exchange_manager.exchange.get_pair_cryptocurrency(symbol), symbol=symbol, order=existing_order.to_dict(), is_from_bot=True, is_closed=True, is_updated=True) return True return False except Exception as e: self.logger.exception(e, True, f"Failed to update order : {e}") return False async def handle_trade_update(self, symbol, trade_id, trade, should_notify: bool = True): try: changed: bool = self.trades_manager.upsert_trade(trade_id, trade) if should_notify: await get_chan(TRADES_CHANNEL, self.exchange_manager.id).get_internal_producer() \ .send(cryptocurrency=self.exchange_manager.exchange.get_pair_cryptocurrency(symbol), symbol=symbol, trade=trade.to_dict(), old_trade=False) return changed except Exception as e: self.logger.exception(e, True, f"Failed to update trade : {e}") return False async def handle_trade_instance_update(self, trade, should_notify: bool = True): try: changed: bool = self.trades_manager.upsert_trade_instance(trade) if should_notify: await get_chan(TRADES_CHANNEL, self.exchange_manager.id).get_internal_producer() \ .send(cryptocurrency=self.exchange_manager.exchange.get_pair_cryptocurrency(trade.symbol), symbol=trade.symbol, trade=trade.to_dict(), old_trade=False) return changed except Exception as e: self.logger.exception(e, True, f"Failed to update trade instance : {e}") return False async def handle_position_update(self, symbol, position_id, position, should_notify: bool = True): try: changed: bool = self.positions_manager.upsert_position( position_id, position) if should_notify: position_instance = self.positions_manager[position_id] await get_chan(POSITIONS_CHANNEL, self.exchange_manager.id).get_internal_producer() \ .send(cryptocurrency=self.exchange_manager.exchange.get_pair_cryptocurrency(symbol), symbol=symbol, position=position_instance.to_dict(), is_closed=False, is_updated=changed, is_from_bot=True, is_liquidated=position_instance.is_liquidated()) return changed except Exception as e: self.logger.exception(e, True, f"Failed to update position : {e}") return False async def handle_position_instance_update(self, position, should_notify: bool = True): try: changed: bool = self.positions_manager.upsert_position_instance( position) if should_notify: await get_chan(POSITIONS_CHANNEL, self.exchange_manager.id).get_internal_producer() \ .send(cryptocurrency=self.exchange_manager.exchange.get_pair_cryptocurrency(position.symbol), symbol=position.symbol, position=position, is_closed=False, is_updated=changed, is_from_bot=True, is_liquidated=position.is_liquidated()) return changed except Exception as e: self.logger.exception(e, True, f"Failed to update position instance : {e}") return False def get_order_portfolio(self, order): return order.linked_portfolio if order.linked_portfolio is not None else self.portfolio_manager.portfolio def clear(self): if self.portfolio_manager is not None: self.portfolio_manager.portfolio_profitability = None if self.orders_manager is not None: self.orders_manager.clear() if self.trades_manager is not None: self.trades_manager.clear()