def distribute(self, update_type, message_id, text, choice=None): try: logger.debug("==============================================") logger.debug("새로운 메시지가 도착했습니다.") logger.debug(f"[{update_type}] message_id: {message_id}, choice: {choice}") logger.debug(f"{text}") logger.debug("==============================================") if update_type == "message": # TODO 메시지로 도착했을때 명령어 기능 추가하면 좋을듯.. logger.debug("[미개발..] %s", text) elif update_type == "callback_query": bot_id = text.split("\n")[0].split(":")[1].strip() if self.bot_id != bot_id: logger.debug("다른 봇 메시지는 무시합니다.") return question = self.question_tmp.get(message_id) del self.question_tmp[message_id] if choice == "YES": logger.debug("selected: YES") if question['yes_func'] is not None: result = question['yes_func'](question['yes_param']) else: logger.debug("selected: No") if question['no_func'] is not None: result = question['no_func'](question['no_param']) self.bot.edit_message_text(chat_id=question["message"]["chat_id"], message_id=question["message"]["message_id"], text=f"{question['message']['text']}\n결과 >> {result}", parse_mode="HTML") except KeyError: logger.error(KeyError)
def put_order(self, order_qty, price=None, stop_price=None, post_only=True, close_position=True, type='Limit'): order_logger.info( 'NEW ORDER > symbol[%s] type[%s] order_qty[%s] price[%s] stop_price[%s]', self.symbol, type, order_qty, price, stop_price) if self.dry_run: return try: if type == 'Limit': result = self.client.Order.Order_new( symbol=self.symbol, ordType=type, orderQty=order_qty, price=price, side='Buy' if order_qty > 0 else 'Sell', execInst='ParticipateDoNotInitiate' if post_only else '').result() elif type == 'Stop': if close_position: result = self.client.Order.Order_new( symbol=self.symbol, ordType=type, stopPx=stop_price, execInst='Close,LastPrice', side='Buy' if order_qty > 0 else 'Sell').result() else: result = self.client.Order.Order_new( symbol=self.symbol, ordType=type, orderQty=order_qty, stopPx=stop_price).result() elif type == 'LimitIfTouched' or type == "StopLimit": result = self.client.Order.Order_new( symbol=self.symbol, ordType=type, orderQty=order_qty, price=price, stopPx=stop_price, execInst='ParticipateDoNotInitiate').result() elif type == 'Market': result = self.client.Order.Order_new(symbol=self.symbol, ordType=type, orderQty=order_qty, price=price).result() logger.debug('NEW ORDER > symbol[%s] Result > %s', self.symbol, result[0]) order = result[0] status = order['ordStatus'] if status != 'Rejected': return order except Exception as e: logger.error('put order error %s', e)
async def init(self): """ 이 부분을 호출하여 넥서스를 초기화한다. :return: """ try: await self.nexus.wait_ready() except Exception as e: logger.error('init error > %s', e) utils.print_traceback()
async def start(self): if not self.candle_handler: logger.error('Nexus mock is not loaded yet!') return logger.info('Backtest start timer!') while True: df = await self._update_candle() if df is None: break
def amend_order(self, order, order_qty, price=None, stop_price=None, type='Limit'): """ 기존 주문 수정. :param key: :param order_qty: :param price: :return: """ if not self.dry_run: try: order_id = order['orderID'] if type == 'Limit': result = self.client.Order.Order_amend( orderID=order_id, orderQty=order_qty, price=price).result() elif type == 'Stop': result = self.client.Order.Order_amend( orderID=order_id, orderQty=order_qty, stopPx=stop_price).result() elif type == 'LimitIfTouched' or type == "StopLimit": result = self.client.Order.Order_amend( orderID=order_id, orderQty=order_qty, price=price, stopPx=stop_price).result() elif type == 'Market': result = self.client.Order.Order_new(symbol=self.symbol, ordType=type, orderQty=order_qty, price=price).result() logger.debug( 'AMEND ORDER > order_id[%s] symbol[%s] Result > %s', order_id, self.symbol, result[0]) order = result[0] status = order['ordStatus'] order_logger.info( 'AMEND ORDER (%s) > order_id[%s] symbol[%s] type[%s] order_qty[%s] price[%s] stop_price[%s]', status, order_id, self.symbol, type, order_qty, price, stop_price) if status != 'Rejected': return order except Exception as e: if 'Invalid ordStatus' in e.response.text: raise OrderNotFoundException() logger.error('amend order error %s', e)
async def _run_server(self): try: app = web.Application() app.add_routes([ web.get('/', self._handle_info), ]) runner = web.AppRunner(app) await runner.setup() site = web.TCPSite(runner, '0.0.0.0', self.http_port) await site.start() logger.info('HTTP server bind port %s', self.http_port) except Exception as e: logger.error('_run_server error %s', e)
async def get_update(): async with aiohttp.ClientSession() as session: offset = 0 limit = 50 current_ts = int(time.time()) while True: url = f"https://api.telegram.org/bot{self.bot_token}/getUpdates?offset={offset + 1}&limit={limit}" async with session.get(url) as response: data = json.loads(await response.text()) if data["ok"]: results = data["result"] for result in results: for update_type in result.keys(): try: date = None text = None choice = None message_id = None if update_type == "message": date = result["message"]["date"] text = result["message"]["text"] message_id = result["message"][ "message_id"] elif update_type == "callback_query": date = result["callback_query"][ "message"]["date"] text = result["callback_query"][ "message"]["text"] message_id = result[ "callback_query"]["message"][ "message_id"] choice = result["callback_query"][ "data"] if update_type == "update_id" or current_ts >= date: # 이전 메시지 무시.. offset = result["update_id"] continue self.distribute( update_type, str(message_id), text, choice) except KeyError: logger.error("key error", KeyError) # 한번씩 쉬면서 대화 내용 조회하기. time.sleep(1)
async def listen(self): if self.websocket: while True: try: message = await self.websocket.recv() self.__on_message(message) except Exception as e: logger.error('listen error', e) self.connected = False logger.error('########################################') logger.error('########################################') logger.error('########################################') logger.error('Websocket closed. %s', e) logger.error('########################################') logger.error('########################################') logger.error('########################################') logger.error('Try websocket reconnect in 5 seconds...') # 5초후 웹소켓 접속 재시도. await asyncio.sleep(5) await self.connect() else: raise Exception('Websocket disconnected.')
def __on_message(self, message): '''Handler for parsing WS messages.''' message = json.loads(message) logger.debug(json.dumps(message)) table = message['table'] if 'table' in message else None action = message['action'] if 'action' in message else None try: if 'subscribe' in message: logger.debug("Subscribed to %s." % message['subscribe']) elif action: if table not in self.data: self.data[table] = [] # There are four possible actions from the WS: # 'partial' - full table image # 'insert' - new row # 'update' - update row # 'delete' - delete row value = message['data'] if action == 'partial': logger.debug("%s: partial" % table) self.data[table] += value # Keys are communicated on partials to let you know how to uniquely identify # an item. We use it for updates. self.keys[table] = message['keys'] elif action == 'insert': logger.debug('%s: inserting %s' % (table, value)) self.data[table] += value # Limit the max length of the table to avoid excessive memory usage. # Don't trim orders because we'll lose valuable state if we do. if table not in [ 'order', 'orderBookL2' ] and len(self.data[table]) > BitmexWS.MAX_TABLE_LEN: self.data[table] = self.data[table][int(BitmexWS. MAX_TABLE_LEN / 2):] elif action == 'update': logger.debug('%s: updating %s' % (table, value)) # Locate the item in the collection and update it. for updateData in value: item = findItemByKeys(self.keys[table], self.data[table], updateData) if not item: return # No item found to update. Could happen before push item.update(updateData) # Remove cancelled / filled orders if table == 'order' and item['leavesQty'] <= 0: self.data[table].remove(item) elif action == 'delete': logger.debug('%s: deleting %s' % (table, value)) # Locate the item in the collection and remove it. for deleteData in value: item = findItemByKeys(self.keys[table], self.data[table], deleteData) self.data[table].remove(item) else: raise Exception("Unknown action: %s" % action) # 업데이트 콜백을 호출한다. for item in value: if self.is_ready: if table.startswith('tradeBin'): if self.update_candle and item: self.update_candle(item) elif table == 'orderBook10': if self.update_orderbook and item: self.update_orderbook(item) elif table == 'order': if self.update_order and item: self.update_order(item) if table == 'position': if self.update_position and item: self.update_position(item) except: logger.error(traceback.format_exc())