프로젝트/비트코인 자동매매

잔고정보 조회하기(오류 수정) - 업비트 파이썬 비트코인 자동매매

Tech&Fin 2021. 10. 26. 17:58
반응형

업비트 잔고를 조회하는 로직을 과거에 포스팅을 했었는데 해당 로직 자체로는 아무 문제가 없지만 매도를 위한 목적등에 사용할 때는 원치 않는 결과를 초래하는 것 같아 로직을 조금 수정해 보았습니다.

 

 

목차 - 클릭하면 이동합니다.

     

    잔고정보 조회하기

    잔고 정보 조회하기는 보유하고 있는 원화 또는 코인들을 조회하는 로직인데요. 아래와 같은 목적으로 사용할 수 있습니다.

     

    ① 매수를 하기 위한 KRW 원화 금액을 조회

    ② 보유하고 있는 코인을 매도 하기 위해 조회

     

    마켓(Market)

    코인 거래는 기준 통화(?)를 무엇으로 할 것이냐에 따라 달라지는데요. 이것을 마켓이라고 합니다. 업비트에는 총 세 가지 마켓이 있으며 바로 KRW, BTC, USDT 마켓 입니다.

     

    KRW는 원화를 가지고 매수/매도를 하는 마켓이며 BTC는 비트코인을 가지고 매수/매도를 USDT는 USD테더를 가지고 매수 및 매도를 하는 마켓 입니다.

     

    어떤 코인이든지 해당 마켓에서 거래되고 있는 코인이라면 다른 마켓에서 구매한 코인도 매도할 수 있습니다. 그래서 잔고 정보에는 마켓 정보는 없이 단순히 코인 정보만 들어있게 됩니다.

     

    이전 로직의 문제점

    KRW 마켓에서 매도를 하기 위해 잔고 정보를 조회할 때 보유하고 있는 모든 코인 리스트가 조회 되는데 만약 KRW 마켓에서 거래되지 않는 종목이 조회되면 오류가 발생하는 현상이 있었습니다.

     

    예를 들어 아래와 같이 매수를 했었다고 한다면,

     

    ① KRW 마켓에서 DOGE(도지코인) 구매 

    ② BTC 마켓에서 DOGE(도지코인) 구매

    ③ BTC 마켓에서 SOLVE(솔브케어) 구매

     

    잔고 정보를 조회하면 아래와 같이 총 2개의 종목이 조회 됩니다.

     

    ① DOGE

    ② SOLVE

     

    KRW 마켓과 BTC마켓에서 구매한 도지코인은 수량이 합쳐져 하나로 나오게 되고 전체 보유 수량을 거래가 되고 있는 KRW 또는 BTC 마켓에서 매도가 가능합니다.

     

    하지만 BTC 마켓에서 구매한 솔브케어는 아직 원화 마켓에서는 거래가 되지 않기 때문에 원화 마켓에서는 거래를 할 수 없습니다.

     

    이전 로직에서는 무조건 매도 거래를 하고자 하는 마켓 코드를 앞에 붙였기 때문에 KRW-DOGE와 KRW-SOLVE를 조합하게 되는데 실제 KRW-SOLVE는 존재하지 않기 때문에 오류가 발생하는 현상이 발생하였습니다.

     

    수정된 로직

    반응형
    # -----------------------------------------------------------------------------
    # - Name : get_accounts
    # - Desc : 잔고정보 조회
    # - Input
    #   1) except_yn : KRW 및 소액 제외
    #   2) market_code : 마켓코드 추가(매도시 필요)
    # - Output
    #   1) 잔고 정보
    # -----------------------------------------------------------------------------
    # 계좌 조회
    def get_accounts(except_yn, market_code):
        try:
    
            rtn_data = []
    
            # 해당 마켓에 존재하는 종목 리스트만 추출
            market_item_list = get_items(market_code, '')
    
            # 소액 제외 기준
            min_price = 5000
    
            payload = {
                'access_key': access_key,
                'nonce': str(uuid.uuid4()),
            }
    
            jwt_token = jwt.encode(payload, secret_key)
            authorize_token = 'Bearer {}'.format(jwt_token)
            headers = {"Authorization": authorize_token}
    
            res = send_request("GET", server_url + "/v1/accounts", "", headers)
            account_data = res.json()
    
            for account_data_for in account_data:            
                for market_item_list_for in market_item_list:
                    
                    # 해당 마켓에 있는 종목만 조합
                    if market_code + '-' + account_data_for['currency'] == market_item_list_for['market']:
                        
                        # KRW 및 소액 제외
                        if except_yn == "Y" or except_yn == "y":
                            if account_data_for['currency'] != "KRW" and Decimal(str(account_data_for['avg_buy_price'])) * (
                                    Decimal(str(account_data_for['balance'])) + Decimal(
                                    str(account_data_for['locked']))) >= Decimal(str(min_price)):
                                rtn_data.append(
                                    {'market': market_code + '-' + account_data_for['currency'],
                                     'balance': account_data_for['balance'],
                                     'locked': account_data_for['locked'],
                                     'avg_buy_price': account_data_for['avg_buy_price'],
                                     'avg_buy_price_modified': account_data_for['avg_buy_price_modified']})
                        else:
                            if account_data_for['currency'] != "KRW":
                                rtn_data.append(
                                {'market': market_code + '-' + account_data_for['currency'], 'balance': account_data_for['balance'],
                                 'locked': account_data_for['locked'],
                                 'avg_buy_price': account_data_for['avg_buy_price'],
                                 'avg_buy_price_modified': account_data_for['avg_buy_price_modified']})
    
            return rtn_data
    
        # ----------------------------------------
        # Exception Raise
        # ----------------------------------------
        except Exception:
            raise

     

    해당 마켓에 존재하는 종목을 체크하기 위해 어쩔 수 없이 한번 더 API 호출이 필요했습니다.

    # 해당 마켓에 존재하는 종목 리스트만 추출
    market_item_list = get_items(market_code, '')

     

    그 다음에 for 문을 이용하여 잔고 정보를 조합할 때 실제 해당 마켓에 거래되는 코드만 조합할 수 있도록 로직을 추가 하였습니다.

    for account_data_for in account_data:
       for market_item_list_for in market_item_list:
          # 해당 마켓에 있는 종목만 조합
          if market_code + '-' + account_data_for['currency'] == market_item_list_for['market']:

     

    마치며

    블로그에 글이 조금씩 쌓여가면서 댓글로 많은 분들이 의견 및 질문을 주고 계신데요. 이번 내용도 어떤 분께서 댓글로 알려 주셔서 로직을 수정하고 포스팅하게 되었습니다.

     

    앞으로도 의견을 듣고 소통하며 조금씩 더 실수하지 않는 로직을 만들어 가도록 노력해 보겠습니다.

     

    블로그를 구독해 주시면 소식을 조금 더 빨리 받아보실 수 있습니다. 참고 부탁 드리며 궁금한 점은 댓글로 부탁 드리겠습니다.

    반응형