Пример #1
0
 def __init__(self,
              bot_id=None,
              bot_token=None,
              chat_id=None,
              message_handler={},
              expire_time=60,
              expired_handler=None):
     if bot_token is None:
         logger.debug("Telegram Bot Disabled.")
         self.enabled = True
         return
     if bot_id is None or bot_id == "":
         self.bot_id = str(
             random.randint(random.randint(1, 99),
                            random.randint(100, 9999)))
     else:
         self.bot_id = bot_id
     logger.debug("Telegram Bot ID. %s", self.bot_id)
     self.bot_token = bot_token
     self._bot = Bot(bot_token)
     self.chat_id = chat_id
     self.message_handler = message_handler
     if expired_handler is not None:
         self.question_tmp = expiredict(expired_handler)
     else:
         self.question_tmp = expiredict(
             expire_time=expire_time,
             expired_callback=self.expired_question)
     self.enabled = False
Пример #2
0
    def load(self):
        # 미리 history 크기의 df 를 만들고.
        # history 만큼 캔들 데이터를 채워넣는다.
        # 초기화. 데이터는 비어있음.

        # 최신것부터 limit 개를 가져온다.
        # new_data = await
        new_data = self.api.fetch_ohlcv(symbol=self.symbol,
                                        timeframe=self.period,
                                        since=self.since,
                                        limit=self.history)
        # 오래된순 정렬로 바꿈.
        # new_data = new_data[::-1]
        index_list = []
        data_list = []
        for row in new_data:
            logger.debug('>>> row>>> %s', row)

            index = row[0]
            index_list.append(index)
            data_list.append({
                'Open': row[1],
                'High': row[2],
                'Low': row[3],
                'Close': row[4],
                'Volume': row[5],
            })

        freq = utils.period_to_freq(self.period)
        self.candle = BarList(self.symbol, self.history, freq)
        self.candle.init(index_list, data_list)
Пример #3
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)
Пример #4
0
 def init(self, index_list, data_list):
     logger.debug('>> index_list >> %s', index_list)
     # dates = pd.DatetimeIndex(index_list, dtype='datetime64[ns]', freq=self.freq)
     self.df = pd.DataFrame(
         data=data_list,
         index=index_list,
         columns=['Open', 'High', 'Low', 'Close', 'Volume'])
Пример #5
0
    def update_position(self, position):
        logger.debug('update_position > %s', position)
        self.s['current_qty'] = position['currentQty']
        current_qty = self.s['current_qty']

        if current_qty == 0:
            # 포지션이 닫힌 경우.
            if 'isOpen' in position and not position['isOpen']:
                prevPnl = position['prevRealisedPnl']
                logger.info('Position Closed. pnl[%s%s]', prevPnl, position['currency'])
                self.send_telegram('Position Closed. pnl[{} {}]'.format(prevPnl, position['currency']))

            # stop모두 취소.
            for order in self.data['order']:
                if order['ordType'] == 'Stop':
                    order_id = order['orderID']
                    self.api.cancel_order(id=order_id, symbol=symbol)
            return

        if 'avgEntryPrice' in position:
            if position['avgEntryPrice']:
                ## entry_price가 대부분 안들어온다. 포지션이 수정될때만 들어옴. 봇을 리스타트시 안들어옴.
                self.s['entry_price'] = position['avgEntryPrice']
                if current_qty > 0:
                    # 롱 포지션은 아래쪽에 Sell을 예약한다.
                    stop_price = round(self.s['entry_price'] - self.stoploss)
                    found = False
                    for order in self.data['order']:
                        # limit 주문만 수정. stop은 손절주문이므로 수정하지 않으며, update_position에서 수정함.
                        if order['ordType'] == 'Stop' and order['side'] == 'Sell':
                            if order['stopPx'] != stop_price:
                                order_id = order['orderID']
                                self.api.edit_order(id=order_id, symbol=symbol, type='Stop', side='Buy',
                                                    amount=abs(current_qty),
                                                    params={'execInst': 'Close,LastPrice', 'stopPx': stop_price})
                            found = True
                            break
                    if not found:
                        self.api.create_order(symbol, type='Stop', side='Sell',
                                              amount=abs(current_qty),
                                              params={'execInst': 'Close,LastPrice', 'stopPx': stop_price})
                elif current_qty < 0:
                    # 숏 포지션은 위쪽에 Buy를 예약한다.
                    stop_price = round(self.s['entry_price'] + self.stoploss)
                    found = False
                    for order in self.data['order']:
                        # limit 주문만 수정. stop은 손절주문이므로 수정하지 않으며, update_position에서 수정함.
                        if order['ordType'] == 'Stop' and order['side'] == 'Buy':
                            if order['stopPx'] != stop_price:
                                order_id = order['orderID']
                                self.api.edit_order(id=order_id, symbol=symbol, type='Stop', side='Sell',
                                                    amount=abs(current_qty),
                                                    params={'execInst': 'Close,LastPrice', 'stopPx': stop_price})
                            found = True
                            break
                    if not found:
                        self.api.create_order(symbol, type='Stop', side='Buy',
                                              amount=abs(current_qty),
                                              params={'execInst': 'Close,LastPrice', 'stopPx': stop_price})
Пример #6
0
 def update_order(self, order):
     logger.debug('update_order > %s', order)
     # if 'side' in order:
     #     self.send_telegram(
     #         '{} {} {}XBT @{}'.format(order['ordType'], order['side'], order['orderQty'], order['price']))
     if 'ordStatus' in order:
         if order['ordStatus'] == 'Filled':
             self.send_telegram('Order filled {} {}@{}'.format(order['symbol'], order['cumQty'], order['avgPx']))
Пример #7
0
 def update_leverage(self, leverage):
     # update leverage
     self.leverage = leverage
     if not self.dry_run:
         result = self.client.Position.Position_updateLeverage(
             symbol=self.symbol, leverage=leverage).result()
         logger.debug('UPDATE LEVERAGE symbol[%s] leverage[%s] Result > %s',
                      self.symbol, self.leverage, result[0])
Пример #8
0
 def test_bitmex_data_ingest(self):
     exchange = utils.ccxt_exchange('bitmex', is_async=True)
     markets = asyncio.get_event_loop().run_until_complete(
         exchange.load_markets())
     #exchange, symbols, start_date, end_date, periods
     base_dir, filepath = asyncio.get_event_loop().run_until_complete(
         data_ingest.ingest_data(exchange, 'XBT/USD',
                                 datetime(2019, 1, 1, 0, 0, 0),
                                 datetime(2019, 1, 1, 12, 0, 0), '5m', 12))
     logger.debug('filepath > %s', filepath)
Пример #9
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)
Пример #10
0
        def handle_topic(topic, action, data):
            print(topic, action, data)
            if topic == 'margin':
                if action == 'partial':
                    self.margin = data
                elif action == 'update':
                    self.margin.update(data)
                    used_margin = self.margin['maintMargin']
                    avail_margin = self.margin['availableMargin']
                    logger.debug(
                        f'[Margin] used_margin[{used_margin}], avail_margin[{avail_margin}]'
                    )

            elif topic == 'order':
                # for order in data:

                if action == 'partial' or action == 'insert':
                    if data:
                        order_id = data['orderID']
                        self.orders[order_id] = data
                else:
                    if data and 'orderID' in data:
                        order_id = data['orderID']
                        working_indicator = data['workingIndicator']
                        if working_indicator:
                            self.orders[order_id].update(data)
                        else:
                            del self.orders[order_id]

                print(self.orders)
                print('--------------------')

            elif topic == 'position':
                if action == 'partial':
                    self.position = data
                else:
                    self.position.update(data)

                # 필수.
                currentQty = self.position['currentQty']
                currency = self.position['currency']
                markPrice = self.position['markPrice']
                timestamp = self.position['timestamp']
                liquidationPrice = self.position['liquidationPrice']

                logger.info('%s %s current_qty[%s]', topic, action, currentQty)
Пример #11
0
 async def run():
     logger.debug('ws > %s', ws)
     await ws.connect()
     """
     "affiliate",   // Affiliate status, such as total referred users & payout %
     "execution",   // Individual executions; can be multiple per order
     "order",       // Live updates on your orders
     "margin",      // Updates on your current account balance and margin requirements
     "position",    // Updates on your positions
     "privateNotifications", // Individual notifications - currently not used
     "transact"     // Deposit/Withdrawal updates
     "wallet"       // Bitcoin address balance data, including total deposits & withdrawals
     """
     # req = {'op': 'subscribe', 'args': ['tradeBin1m:XBTUSD', 'order', 'margin', 'position', 'wallet']}
     # req = {'op': 'subscribe', 'args': ['margin', 'position:XBTUSD', 'quote:XBTUSD', 'orderBook10:XBTUSD']}
     # req = {'op': 'subscribe', 'args': ['order:XBTUSD', 'position:XBTUSD', 'wallet']}
     req = {'op': 'subscribe', 'args': ['orderBook10:XBTUSD']}
     ws.update_orderbook = lambda x: print(x)
     await ws.listen()
Пример #12
0
    def start(self):
        new_data = self.api.bulk_klines(symbol=self.symbol,
                                        timeframe=self.period,
                                        since=self.since)
        index_list = []
        data_list = []
        for row in new_data:
            logger.debug('>>> row>>> %s', row)

            index = pd.to_datetime(row[0], unit='ms')
            index_list.append(index)
            data_list.append({
                'open': float(row[1]),
                'high': float(row[2]),
                'low': float(row[3]),
                'close': float(row[4]),
                'volume': float(row[5]),
            })

        freq = utils.period_to_freq(self.period)
        self.candle = BarList(self.symbol, self.history, freq)
        self.candle.init(index_list, data_list)
        # websocket
        self.api.start_websocket(self.symbol, self.period, self.__update)
Пример #13
0
    def update_position(self, position):
        logger.info('update_position > %s', position)
        try:
            price = position["avgEntryPrice"]
            self.avg_entry_price = position["avgEntryPrice"]
        except KeyError:
            logger.debug("시정 평균가가 변동이 없습니다.")
            price = self.avg_entry_price

        current_qty = 0 if position["currentQty"] is None else position["currentQty"] * -1

        if position['currentQty'] > 0:
            self.position = "BOT"
            price = price + self.limit_tick
        elif position['currentQty'] < 0:
            self.position = "SLD"
            price = price - self.limit_tick
        else:
            self.position = "NTL"

        logger.info(f"규모: {current_qty}, 시장평균가: {price}")
        if position["currentQty"] != 0:
            # 포지션을 가지고 있을 경우
            if self.limit_order is None:
                # 익절 주문.
                self.limit_order = self.nexus.api.put_order(order_qty=current_qty,
                                                            price=price,
                                                            stop_price=price,
                                                            type="LimitIfTouched")

            elif self.limit_order is not None \
                    and self.is_order_request \
                    and self.limit_order["orderQty"] != current_qty:
                # 기존 주문 가격, 규모 수정.
                self.limit_order = self.nexus.api.amend_order(order=self.limit_order,
                                                              order_qty=current_qty,
                                                              price=price,
                                                              stop_price=price,
                                                              type="LimitIfTouched")

            self.is_order_request = False
        else:
            # 포지션이 없을때.
            pass

        if self.count % 2 == 0:
            return

        try:
            last_price = position["lastPrice"]
        except KeyError:
            return

        order_list = self.nexus.api.get_order()
        cancel_orders = []
        remove_orders = []
        for pare_order in self.pare_orders:
            high_price = abs(pare_order["price"]) + (0.5 * 10)
            low_price = abs(pare_order["price"]) - (0.5 * 10)

            # 가격 범위가 넘은 경우
            if last_price > high_price or low_price > last_price:
                cancel_orders.append(pare_order)

            # 대기 중이 아닌경우
            is_deplay = False
            for order in order_list:
                if pare_order["limit_order"]["orderID"] == order["orderID"]:
                    is_deplay = True
                    break
            if not is_deplay:
                remove_orders.append(pare_order)

            # 취소처리
            for cancel_order in cancel_orders:
                remove_orders.append(cancel_order)
                try:
                    self.nexus.api.cancel_order(cancel_order["limit_order"])
                except ExchangeError:
                    pass
                try:
                    self.nexus.api.cancel_order(cancel_order["stop_limit_order"])
                except ExchangeError:
                    pass

            # 저장된 데이터 제거
            for remove_order in remove_orders:
                for pare_order in self.pare_orders:
                    if remove_order["limit_order"]["orderID"] == pare_order["limit_order"]["orderID"]:
                        self.pare_orders.remove(pare_order)
                        break
Пример #14
0
def ingest_data(api,
                symbol,
                start_date,
                end_date,
                interval,
                history=0,
                reload=False):
    """
    데이터를 받아서 csv파일로 저장한다.
    만약 파일이 존재한다면 스킵한다.
    :return: 해당 파일이 존재하는 디렉토리 경로.
    """
    dir = tempfile.gettempdir()
    timer_start = timeit.default_timer()
    tz = start_date.tzinfo

    # 값, 단위 분리
    interval_num, interval_unit = split_interval(interval)

    interval = interval.lower()
    interval_unit = interval_unit.lower()

    base_dir, filepath = ingest_filepath(dir, api, symbol, start_date,
                                         end_date, interval, history)

    logger.debug('file_path=%s', filepath)
    # 강제 리로드 요청이 없고, 파일이 존재하고, 사이즈도 0보다 크면, 그냥 사용.
    if not reload and os.path.exists(
            filepath) and os.path.getsize(filepath) > 0:
        logger.debug('# [{}] CandleFile Download Passed. {}'.format(
            symbol, filepath))
        return base_dir, filepath

    prepare_date = get_prepare_date(start_date, interval, history)
    delta = (end_date - prepare_date)
    # 나누어 받을때 다음번 루프의 시작시점이 된다.
    next_delta = 0
    if interval_unit == 'm':
        length = (delta.days * 24 * 60 + delta.seconds // 60) // interval_num
        next_delta = timedelta(minutes=interval_num).total_seconds()
    elif interval_unit == 'h':
        length = (delta.days * 24 + delta.seconds // 3600) // interval_num
        next_delta = timedelta(hours=interval_num).total_seconds()
    elif interval_unit == 'd':
        length = (delta.days) // interval_num
        next_delta = timedelta(days=interval_num).total_seconds()

    since = int(prepare_date.timestamp()) * 1000
    logger.info('Ingest time range: %s ~ %s', prepare_date, end_date)
    logger.info('Ingest candle length[%s] of [%s] since[%s]', length,
                interval_unit, since)

    params = {}
    if api.id == 'bitmex':
        max_limit = 750
        # params = { 'partial': 'true' }
    elif api.id == 'binance':
        max_limit = 1000

    with open(filepath, 'w', encoding='utf-8', newline='') as f:

        wr = csv.writer(f)
        wr.writerow(
            ['Datetime', 'Index', 'Open', 'High', 'Low', 'Close', 'Volume'])

        seq = 0
        while length > 0:
            if seq > 0:
                time.sleep(api.rateLimit / 1000)  # time.sleep wants seconds

            limit = min(length, max_limit)
            logger.debug('#### fetch_ohlcv request [%s / %s]', limit, length)
            # candles = await
            candles = fetch_ohlcv(api, symbol, interval, since, limit, params)
            # 읽은 갯수만큼 빼준다.
            length -= limit
            logger.debug('#### fetch_ohlcv remnant [%s]', length)
            logger.debug('#### fetch_ohlcv response [%s] >> \n%s',
                         len(candles), candles)

            if len(candles) == 0:
                logger.warn('candle data rows are empty!')
                break

            last_candle = None
            for candle in candles:
                wr.writerow([
                    datetime.fromtimestamp(
                        int(candle[0] / 1000),
                        tz=tz).strftime('%Y-%m-%d %H:%M:%S'),
                    int(candle[0]),
                    '{:.8f}'.format(candle[1]),
                    '{:.8f}'.format(candle[2]),
                    '{:.8f}'.format(candle[3]),
                    '{:.8f}'.format(candle[4]),
                    '{:.2f}'.format(candle[5]),
                ])
                last_candle = candle

            # 다음번 루프는 마지막 캔들부터 이어서 내려받는다.
            logger.debug('>>> last_candle >>> %s', last_candle)
            since = last_candle[0] + next_delta
            seq += 1

    timer_end = timeit.default_timer()
    logger.debug('# {} Downloaded CandleFile. elapsed: {}'.format(
        symbol, str(timer_end - timer_start)))
    return base_dir, filepath
Пример #15
0
    def update_candle(self, df, candle):
        logger.info(f"시장가격: {df.Close[-1]}")
        if self.count < 5:
            self.count += 1
            return
        self.count = 0

        diff_sum = sum(df.Close - df.Open)
        add_qty = 0
        logger.info(f"포지션: {self.position}, 차이가격: {diff_sum}")
        if diff_sum > 0:

            if self.position == "SLD":
                # SLD 포지션이면 정리.
                for pare_order in self.pare_orders:
                    try:
                        self.nexus.api.cancel_order(pare_order["limit_order"])
                    except ExchangeError:
                        logger.debug("<ignore> 없어진 요청.")
                    try:
                        self.nexus.api.cancel_order(pare_order["stop_limit_order"])
                    except ExchangeError:
                        logger.debug("<ignore> 없어진 요청.")

                add_qty = self.limit_order["orderQty"]
                self.limit_order = None
                self.pare_orders = []

            # 매수
            order = self.nexus.api.put_order(order_qty=(self.order_qty + add_qty),
                                             # side="Buy",
                                             price=df.Close[-1] - 0.5
                                             )
            if order["ordStatus"] == "New":
                stop_limit_order = self.nexus.api.put_order(order_qty=-(self.order_qty + add_qty),
                                                            # side="Sell",
                                                            price=df.Close[-1] - 0.5 - self.stop_limit_tick,
                                                            stop_price=df.Close[-1] - 0.5 - self.stop_limit_tick,
                                                            type="StopLimit")
                self.pare_orders.append({
                    "price": df.Close[-1],
                    "position": "BOT",
                    "limit_order": order,
                    "stop_limit_order": stop_limit_order
                })
                self.is_order_request = True

        elif diff_sum < 0:

            if self.position == "BOT":
                # BOT 포지션이면 정리.
                for pare_order in self.pare_orders:
                    try:
                        self.nexus.api.cancel_order(pare_order["limit_order"])
                    except ExchangeError:
                        logger.debug("<ignore> 없어진 요청.")
                    try:
                        self.nexus.api.cancel_order(pare_order["stop_limit_order"])
                    except ExchangeError:
                        logger.debug("<ignore> 없어진 요청.")

                add_qty = self.limit_order["orderQty"]
                self.limit_order = None
                self.pare_orders = []

            # 매도
            order = self.nexus.api.put_order(order_qty=-(self.order_qty + add_qty),
                                             # side="Sell",
                                             price=df.Close[-1] + 0.5)
            if order["ordStatus"] == "New":
                stop_limit_order = self.nexus.api.put_order(order_qty=(self.order_qty + add_qty),
                                                            # side="Buy",
                                                            price=df.Close[-1] + 0.5 + self.stop_limit_tick,
                                                            stop_price=df.Close[-1] + 0.5 + self.stop_limit_tick,
                                                            type="StopLimit")
                self.pare_orders.append({
                    "price": df.Close[-1],
                    "position": "SLD",
                    "limit_order": order,
                    "stop_limit_order": stop_limit_order
                })
                self.is_order_request = True
Пример #16
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

                # 임시저장된 내용 가져온수 삭제처리.
                self.question_tmp.lock()
                question = self.question_tmp.get(message_id)
                del self.question_tmp[message_id]
                self.question_tmp.unlock()

                # 버튼을 지운다.
                self._bot.edit_message_text(chat_id=question["message"]["chat_id"],
                                            message_id=question["message"]["message_id"],
                                            text=f"{question['message']['text']}",
                                            parse_mode="HTML")
                # 선택에 따라서 함수 호출한다.
                result = None
                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'])

                # 결과를 전송한다.
                if result is None:
                    result = "No Data"
                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:
            # ignore 요청의 두번 답을 말할경우.
            pass
Пример #17
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)
Пример #18
0
 def cancel_order(self, order):
     order_id = order['orderID']
     if not self.dry_run:
         result = self.client.Order.Order_cancel(orderID=order_id).result()
         logger.debug('CANCEL ORDER > order_id[%s] symbol[%s] Result > %s',
                      order_id, self.symbol, result[0])
Пример #19
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())