def add_trades(self, trades: [Trade], start_listening=True): self.logInfo('Adding {} trades to the TradeHandler.'.format( len(trades))) # try: self.stop_listening() # if not ExchangeInfo().has_all_symbol(self.strategies_dict.keys()): ExchangeInfo().update(self.fx.get_exchange_info()) AccountBalances().update_balances(self.fx.get_all_balances_dict()) for trade in trades: new_strategy = TargetsAndStopLossStrategy( trade, self.fx, self.order_updated_handler, self.balances.get_balance(trade.asset)) if self.handle_completed_strategy(new_strategy): self.logInfo('Strategy is completed [{}]'.format( new_strategy.symbol())) continue self.add_new_strategy(new_strategy, listen_symbols=False) self.fx.listen_symbols([s.symbol() for s in self.strategies], self.listen_handler, self.user_data_handler) if start_listening: self.start_listening()
def add_new_strategy(self, strategy: TradingStrategy): self.strategies.append(strategy) sym = strategy.symbol() if sym in self.strategies_dict: self.strategies_dict[sym].append(strategy) else: self.strategies_dict[sym] = [strategy] self.tradeid_strategy_dict[strategy.trade.id] = strategy # self.balances.update_balances(self.fx.get_all_balances_dict()) if not ExchangeInfo().has_all_symbol(self.strategies_dict.keys()): ExchangeInfo().update(self.fx.get_exchange_info()) self.fx.listen_symbols([s.symbol() for s in self.strategies], self.listen_handler, self.user_data_handler) self.socket_message_rcvd = False
def __init__(self, trades: List[Trade], fx: FXConnector, trade_updated_handler=None): super().__init__() self.fx = fx self.balances = AccountBalances() self.order_updated_handler = trade_updated_handler ExchangeInfo().update(fx.get_exchange_info()) self.strategies = [] self.logInfo('Creating {} with {} trades.'.format( self.__class__.__name__, len(trades))) for t in trades: try: if t.symbol not in ExchangeInfo().symbols: self.logError('Exchange doesn\'t have market "{}"'.format( t.symbol)) continue self.strategies.append( TargetsAndStopLossStrategy( t, fx, trade_updated_handler, self.balances.get_balance(t.asset))) except Exception: self.logError(traceback.format_exc()) self.strategies_dict = {} self.tradeid_strategy_dict = {} self.trade_info_ticker_buf = {} self.process_delay = 500 self.last_ts = dt.now() self.first_processing = True self.socket_message_rcvd = False self.lock = RLock()
def init_strategies(self): # self.strategies_dict = {s.symbol(): s for s in self.strategies} self.strategies_dict = {} for strategy in self.strategies: sym = strategy.symbol() if sym in self.strategies_dict: self.strategies_dict[sym].append(strategy) else: self.strategies_dict[sym] = [strategy] self.tradeid_strategy_dict = {s.trade.id: s for s in self.strategies} self.balances.update_balances(self.fx.get_all_balances_dict()) if not ExchangeInfo().has_all_symbol(self.strategies_dict.keys()): ExchangeInfo().update(self.fx.get_exchange_info()) self.process_initial_prices() self.fx.listen_symbols([s.symbol() for s in self.strategies], self.listen_handler, self.user_data_handler) self.socket_message_rcvd = False
def __init__(self, trade: Trade, fx: FXConnector, trade_updated=None, nested=False, exchange_info=None, balance: Balance = None): self.trade: Trade = trade self.fx = fx self.balance: Balance = balance if balance else Balance() self.exchange_info = ExchangeInfo().symbol_info(self.symbol()) self.simulate = False self.trade_updated = trade_updated self.last_execution_price = 0 super().__init__() if nested: if balance: self.balance = balance else: self.init()
def get(self): return list(ExchangeInfo().get_all_symbols())
def exchange_info(self): if not self._exchange_info: self._exchange_info = ExchangeInfo().symbol_info(self.symbol()) return self._exchange_info
class TradingStrategy(Logger): def __init__(self, trade: Trade, fx: FXConnector, trade_updated=None, nested=False, exchange_info=None, balance: Balance = None): self.trade: Trade = trade self.fx = fx self.balance: Balance = balance if balance else Balance() self.exchange_info = ExchangeInfo().symbol_info(self.symbol()) self.simulate = False self.trade_updated = trade_updated self.last_execution_price = 0 super().__init__() if nested: if balance: self.balance = balance else: self.init() def _get_logger_name(self): return '{}({})'.format(self.__class__.__name__, self.symbol()) def update_trade(self, trade: Trade): self.trade = trade self.init(True) def init(self, force_cancel_open_orders=False): # #TODO: make one call for each symbols # if not force_cancel_open_orders: # self.exchange_info = self.fx.get_exchange_info(self.symbol()) # self.exchange_info = self.ExchangeInfo().symbol_info(self.symbol()) self.validate_target_orders(force_cancel_open_orders) def is_completed(self): return self.trade.is_completed() def trade_side(self): return self.trade.side def self_update_balances(self): AccountBalances().update_balances(self.fx.get_all_balances_dict()) def asset(self): return self.trade.asset.upper() def secondary_asset(self): return self.symbol().replace(self.asset(), '') def secondary_asset_balance(self): return AccountBalances().get_balance(self.secondary_asset()) def symbol(self): return self.trade.symbol def on_execution_rpt(self, data): self.logInfo('Execution Rpt: {}'.format(data)) orderId = data['orderId'] tgts = self.trade.get_all_active_placed_targets() for t in tgts: if t.id == orderId: if self._update_trade_target_status_change(t, data['status']): self.last_execution_price = 0 self.trigger_target_updated() self.on_order_status_changed(t, data) break def on_order_status_changed(self, t: Target, data): pass def validate_target_orders(self, force_cancel_open_orders=False): NEW_STATUSES = [ FXConnector.ORDER_STATUS_NEW, FXConnector.ORDER_STATUS_PARTIALLY_FILLED ] try: exchange_orders = self.fx.get_all_orders(self.symbol()) has_open_orders = any([ eo['status'] in NEW_STATUSES for eo in exchange_orders.values() ]) except BinanceAPIException as bae: self.logError(str(bae)) return active_trade_targets = self.trade.get_all_active_placed_targets() update_required = False if force_cancel_open_orders or (len(active_trade_targets) == 0 and has_open_orders): self.logInfo('Cancelling all Open orders') self.fx.cancel_open_orders(self.symbol()) else: for active_trade_target in active_trade_targets: if active_trade_target.id not in exchange_orders: active_trade_target.set_canceled() update_required = True else: s = exchange_orders[active_trade_target.id]['status'] if s in NEW_STATUSES: # check if price in file is the same as on the exchange trade_prices = { self.exchange_info.adjust_price( active_trade_target.price) } if active_trade_target.is_smart(): trade_prices.add( self.exchange_info.adjust_price( active_trade_target.best_price)) exchange_prices = { float(exchange_orders[active_trade_target.id] ['price']), float(exchange_orders[active_trade_target.id] ['stop_price']) } if not PriceHelper.is_float_price( active_trade_target.price) or len( trade_prices & exchange_prices) == 0: self.logInfo('Target price changed: {}'.format( active_trade_target)) self.fx.cancel_order(self.symbol(), active_trade_target.id) active_trade_target.set_canceled() update_required = True update_required |= self._update_trade_target_status_change( active_trade_target, s) if update_required: self.trigger_target_updated() def _update_trade_target_status_change(self, t: Target, status: str) -> bool: if status == FXConnector.ORDER_STATUS_FILLED: t.set_completed() return True if status in [ FXConnector.ORDER_STATUS_CANCELED, FXConnector.ORDER_STATUS_REJECTED, FXConnector.ORDER_STATUS_EXPIRED ]: t.set_canceled() return True return False def get_balance_for_side(self, is_sell=None): if not is_sell: is_sell = self.trade_side().is_sell() return self.balance if is_sell else self.secondary_asset_balance() def execute(self, new_price): pass # def update_asset_balance(self, avail, locked): # self.balance.avail = avail # self.balance.locked = locked # def validate_asset_balance(self): # self.balance.avail, self.balance.locked = self.fx.get_balance(self.trade.asset) def set_trade_completed(self): if not self.trade.is_completed(): self.trade.set_completed() self.trigger_target_updated() def trigger_target_updated(self, sync_cloud=True): if self.trade_updated: self.trade_updated(self.trade, sync_cloud) def get_bid_ask(self, price): return price['b'], price['a'] def get_single_price(self, price, selector=None): if not selector: selector = self.price_selector() return price[selector] def get_info(self): # return TradeInfo(self) pass def price_selector(self, side=None): if not side: side = self.trade_side() return 'b' if side.is_sell() else 'a' def __str__(self): return self.logger.name