카테고리 없음

[Python] 키움증권 API를 활용한 잔고조회 코드 설명

indigenthuman 2024. 9. 7. 15:01

키움증권 API를 활용한 잔고조회 코드 설명

키움증권 API를 사용하면 사용자의 계좌 잔고, 거래 내역, 주식 가격 등을 조회할 수 있습니다. 이 블로그에서는 PyQt5와 키움증권의 Open API를 이용하여 잔고를 조회하는 코드를 단계별로 설명하겠습니다. 코드는 PyQt5를 사용해 GUI를 구현하고 키움증권 API와 상호작용하여 실시간 데이터를 받아 처리합니다.

1. 라이브러리 및 클래스 초기화

from PyQt5.QAxContainer import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import time
import pandas as pd
from util.const import *

PyQt5는 GUI 애플리케이션 개발을 위한 도구이며, QAxContainer는 ActiveX 컨트롤을 쉽게 사용할 수 있게 도와줍니다. 또한, time과 pandas 라이브러리는 요청 대기 및 데이터 처리를 위한 도구입니다.

class Kiwoom(QAxWidget):
    # 초기설정 함수
    def __init__(self):
        super().__init__()
        self._make_kiwoom_instance()
        self._set_signal_slots()
        self._comm_connect()

        self.account_number = self.get_account_number()

        self.tr_event_loop = QEventLoop()
        self.order = {}
        self.balance = {}
        self.universe_realtime_transaction_info = {}

Kiwoom 클래스는 QAxWidget을 상속받아 키움증권의 API와 연동됩니다. 생성자에서 초기 설정을 하고, 로그인, 계좌번호 조회 등을 처리하는 여러 메서드를 호출합니다.


2. Kiwoom API 인스턴스 생성 및 로그인

# kiwoom API와 연동함수
def _make_kiwoom_instance(self):
    self.setControl("KHOPENAPI.KHOpenAPICtrl.1")

여기서는 QAxWidget의 setControl 메서드를 사용해 키움증권 Open API 컨트롤을 초기화합니다.

# 로그인 요청함수
def _comm_connect(self):
    self.dynamicCall("CommConnect")
    self.login_event_loop = QEventLoop()
    self.login_event_loop.exec_()

CommConnect 메서드를 통해 로그인 요청을 보냅니다. 로그인 완료 여부는 QEventLoop 객체를 통해 확인됩니다.


3. 계좌번호 조회

# 계좌번호 요청함수
def get_account_number(self, tag="ACCNO"):
    acount_list = self.dynamicCall("GetLoginInfo(QString)", tag)
    acount_number = acount_list.split(';')[0]
    return acount_number

로그인 후 계좌번호를 요청하는 부분입니다. GetLoginInfo 메서드를 통해 계좌번호를 받아옵니다.


4. 잔고 조회 함수 구현

이제 본격적으로 잔고를 조회하는 코드를 살펴보겠습니다. 이 코드는 특정 계좌의 잔고와 보유한 종목들의 정보를 조회하여 출력합니다.

# 잔고요청 함수
def get_balance(self):
    self.dynamicCall("SetInputValue(QString, QString)", "계좌번호", self.account_number)
    self.dynamicCall("SetInputValue(QString, QString)", "비밀번호입력매체구분", "00")
    self.dynamicCall("SetInputValue(QString, Qstring)", "조회구분", "1")
    self.dynamicCall("CommRqData(QString, QString, int, QString)", "opw00018_req", "opw00018", 0, "0002")

    self.tr_event_loop.exec_()
    return self.tr_data
  • SetInputValue는 요청 시 필요한 파라미터를 설정하는 함수입니다.
    • 계좌번호: 조회할 계좌의 번호
    • 비밀번호입력매체구분: 로그인된 상태에서는 '00'으로 설정
    • 조회구분: '1'은 잔고조회
  • CommRqData는 데이터를 요청하는 함수입니다.
    • "opw00018_req": 잔고조회 요청명령
    • "opw00018": 요청코드
    • 화면번호는 "0002"로 임의 설정

tr_event_loop는 요청이 완료될 때까지 대기하는 역할을 하며, 요청이 완료되면 잔고 데이터를 반환합니다.


5. TR 데이터 처리 함수

잔고조회 요청 후 받은 데이터를 처리하는 함수는 _on_receive_tr_data입니다.

# tr data 처리함수
def _on_receive_tr_data(self, screen_no, rqname, trcode, record_name, next, unused1, unused2, unused3, unused4):
    tr_data_cnt = self.dynamicCall("GetRepeatCnt(QString, QString)", trcode, rqname)
    
    # 잔고조회
    if rqname == "opw00018_req":
        for i in range(tr_data_cnt):
            code = self.dynamicCall("GetCommData(QString, QString, int, QString)", trcode, rqname, i, "종목번호")
            code_name = self.dynamicCall("GetCommData(QString, QString, int, QString)", trcode, rqname, i, "종목명")
            quantity = self.dynamicCall("GetCommData(QString, QString, int, QString)", trcode, rqname, i, "보유수량")
            purchase_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", trcode, rqname, i, "매입가")
            return_rate = self.dynamicCall("GetCommData(QString, QString, int, QString)", trcode, rqname, i, "수익률(%)")
            current_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", trcode, rqname, i, "현재가")
            total_purchase_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", trcode, rqname, i, "매입금액")
            available_quantity = self.dynamicCall("GetCommData(QString, QString, int, QString)", trcode, rqname, i, "매매가능수량")

            code = code.strip()[1:]
            code_name = code_name.strip()
            quantity = int(quantity)
            purchase_price = int(purchase_price)
            return_rate = float(return_rate)
            current_price = int(current_price)
            total_purchase_price = int(total_purchase_price)
            available_quantity = int(available_quantity)

            self.balance[code] = {
                '종목명': code_name,
                '보유수량': quantity,
                '매입가': purchase_price,
                '수익률': return_rate,
                '현재가': current_price,
                '매입금액': total_purchase_price,
                '매매가능수량': available_quantity
            }

    self.tr_event_loop.exit()
    time.sleep(0.5)
  • GetRepeatCnt: 반복 데이터를 가져오기 위한 함수로, 보유 종목의 개수를 의미합니다.
  • GetCommData: 종목번호, 보유수량, 매입가, 현재가 등의 정보를 받아옵니다.
  • 데이터를 각각 받아와서 self.balance 딕셔너리에 저장합니다.

6. 잔고 데이터 출력

print(self.balance)

잔고 데이터를 조회한 후에는 이를 출력하거나 필요한 형태로 가공할 수 있습니다. 예를 들어, self.balance는 각 종목의 정보를 포함하는 딕셔너리로, 보유한 주식의 상태를 확인할 수 있습니다.

 

7. 결론

이 코드 예제에서는 키움증권 API를 이용하여 계좌 잔고와 보유 종목의 정보를 조회하는 방법을 설명했습니다. 키움증권의 OpenAPI와 PyQt5를 사용하면 다양한 트레이딩 도구를 개발할 수 있습니다.