프로그래밍/파이썬

2. 파이썬 - 키움API 활용한 예수금 얻어오기

가카리 2025. 6. 6. 09:32
반응형

 

1. 예수금 정보를 얻어오는 TR(opw00001)

  - 사실상 계좌번호만 전달하면됨

  - 계좌번호는 아래 get_account_number를 통해서 

def get_account_number(self, tag="ACCNO"):
    account_list = self.dynamicCall("GetLoginInfo(QString)", tag)
    account_number = account_list.split(';')[0] #계좌만 분리해서 가져옴 [1]은 공백임
    print(account_number)
    return account_number

 

  - 생성자부분에서 self.account_number에 저장해둠

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()#TR 요청에 대한 응답 대기를 위한 변수 데이터가 올 때까지 기다렸다가 처리해!" 하는 용도로 사용하는 이벤트 루프

 

  - 참고로 KOA에서 개발가이드 - 로그인 버전처리 - 관련함수 - GetLoginInfo를 보면 계좌번호를 얻어오는 관련함수를 볼 수 있음

 

  - 예수금을 얻어오는 함수인 get_deposit는 다음과 같음

 

 

def get_deposit(self):
    self.dynamicCall("SetInputValue(QString, QString","계좌번호", self.account_number)
    self.dynamicCall("SetInputValue(QString, QString", "비밀번호입력매체구분", "00")
    self.dynamicCall("SetInputValue(QString, QString",  "조회구분", "2")
    self.dynamicCall("CommRqData(QString, QString, int, QString","opw00001_req", "opw00001", 0, "0002")

    self.tr_event_loop.exec()#응답을 대기할 수 있는 상태로 만듬
    return self.tr_data

 

  - 계좌번호는 self.account_number를 넘겨주고 나머지는 파라미터를 강제로 줌

  - 그리고 self.tr_event_loop.exec()코드를 통해 응답을 대기할 수 있는 상태로 만듬

 

2. 예수금 정보를 받는 함수

  - 기존의 _on_receive_tr_data 함수에서 아래쪽 elif부분이 예수금을 바다오는 부분임

def _on_receive_tr_data(self, screen_no, rqname, trcode, record_name, next, unused1, unused2, unused3, unused4):
    print("[Kiwoon _on_receive_tr_data is called {} / {} / {}".format(screen_no, rqname, trcode))
    tr_data_cnt = self.dynamicCall("GetRepeatCnt(QString, QString", trcode, rqname) #가져온 TR의 응답갯수 즉 600일치면 600이 저장됨

    #만약 600일치가 넘은 일본데이터를 필요하면 next를 2로 설정해서 _on_receive_tr_data를 한번더 호출할 수 있게 함
    if next == '2':
        self.has_next_tr_data = True
    else:
        self.has_next_tr_data = False

    if rqname == "opt10081_req":
        ohlcv = {'date': [], 'open': [], 'high': [], 'low': [], 'close': [], 'volume': []}#ohlcv는 지역변수임

        for i in range(tr_data_cnt):
            date = self.dynamicCall("GetCommData(QString, QString, int, QString", trcode, rqname, i, "일자")
            open = self.dynamicCall("GetCommData(QString, QString, int, QString", trcode, rqname, i, "시가")
            high = self.dynamicCall("GetCommData(QString, QString, int, QString", trcode, rqname, i, "고가")
            low = self.dynamicCall("GetCommData(QString, QString, int, QString", trcode, rqname, i, "저가")
            close = self.dynamicCall("GetCommData(QString, QString, int, QString", trcode, rqname, i, "현재가")
            volume = self.dynamicCall("GetCommData(QString, QString, int, QString", trcode, rqname, i, "거래량")

            ohlcv['date'].append(date.strip())
            ohlcv['open'].append(int(open))
            ohlcv['high'].append(int(high))
            ohlcv['low'].append(int(low))
            ohlcv['close'].append(int(close))
            ohlcv['volume'].append(int(volume))

        self.tr_data = ohlcv#글로벌 변수로 편입시킴

    #예수금 얻어오기 받는 부분
    elif rqname == "opw00001_req":
        deposit = self.dynamicCall("GetCommData(QString, QString, int, QString", trcode, rqname, 0, "주문가능금액")
        self.tr_data = int(deposit)
        print(self.tr_data)

    self.tr_event_loop.exit()#tr 요청을 보내고 응답을 대기시키는데 사용하는 self.tr_event_loop 를 종료 시킴
    time.sleep(0.5)#0.5초만듬 쉼

 

  GetCommData함수를 통해서 받아옴

 

  - if문을 넣어서 rqname이 opw00001_req일때만 처리할 코드를 넣었다.(get_deposit에 보면 rqname을 opw00001_req를 넣어줬음)

 

  - 예수금을 얻어오는 TR(opw00001)은 단 한번 호출로 얻어 오므로 싱글데이터 응답으로 주문가능 금액 항목을 얻어와 변수 deposit에 담았다.

  - 왜 예수금을 안가져왔는지는 사실 예수금은 D+2에 처리가 되고 주문가능 금액은 주식을 팔고 바로 주문을 넣을 수 있는 금액이기 때문에 시스템 트레이딩을 하는 입장에서는 주문가능금액이 더 중요하기 때문이다.

 

 

  - 그리고 여기서 가져온 deposit 값을 int로 바꿔주는데 예수금이 100만원이면 00001000000 이런식으로 0000이 앞에 붙기때문에 0을 제거하기 위함이다.

self.tr_data = int(deposit)

 

 

3. 실행 결과

  - 현재 모의 투자 계좌에 99,997,590원이 있는데

 

  - 실제 실행해보면 99,938,490원이다!?

 

  - 곰곰히 생각해보니까 1억원 - 삼성전자1주 매수가격(61300원) = 99,938,700원이 맞다.

 

  - 위 모의투자계좌는 추정예탁자산이었다..

 

 

참고. 소스코드 깃헙

https://github.com/GaKaRi/python_trading/tree/main/SystemTrading

 

python_trading/SystemTrading at main · GaKaRi/python_trading

Contribute to GaKaRi/python_trading development by creating an account on GitHub.

github.com