예제 #1
0
    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)
예제 #2
0
    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)
예제 #3
0
 async def init(self):
     """
     이 부분을 호출하여 넥서스를 초기화한다.
     :return:
     """
     try:
         await self.nexus.wait_ready()
     except Exception as e:
         logger.error('init error > %s', e)
         utils.print_traceback()
예제 #4
0
    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
예제 #5
0
    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)
예제 #6
0
 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)
예제 #7
0
        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)
예제 #8
0
 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.')
예제 #9
0
    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())