주식자동매매 22강. 계좌평가잔고내역요청(10), 멀티데이터 GUI에 삽입하기
본문 바로가기

주식 자동매매 강의/기초반(모든 코딩의 뿌리)

주식자동매매 22강. 계좌평가잔고내역요청(10), 멀티데이터 GUI에 삽입하기

반응형

이번 강의는 계좌평가 잔고내역 요청 마지막 강의입니다. 요청에 대한 멀티 데이터를 가져오고(종목마다의 수익률 등) 가져온 값을 19강에서 설명한 QTable Widget에 삽입하도록 하겠습니다. 잘모르겠으면 요약만 보세요.

 

[유튜브 강의, 링크]와 같이 보시면 많은 도움이 되실 겁니다.

1. 잠깐 복습하기

 아래 코드와 같이 stocklistTableWidget이라는 테이블 위젯 GUI에 행과 열 그리고 열의 이름을 할당하였습니다.

    def trdata_slot(self, sScrNo, sRQName, sTrCode, sRecordName, sPrevNext):

        if sRQName == "계좌평가잔고내역요청":

            column_head = ["종목번호", "종목명", "보유수량", "매입가", "현재가", "평가손익", "수익률(%)"]
            colCount = len(column_head)
            rowCount = self.k.kiwoom.dynamicCall("GetRepeatCnt(QString, QString)", sTrCode, sRQName)
            self.parent.stocklistTableWidget_2.setColumnCount(colCount)                 # 행 갯수
            self.parent.stocklistTableWidget_2.setRowCount(rowCount)                    # 열 갯수 (종목 수)
            self.parent.stocklistTableWidget_2.setHorizontalHeaderLabels(column_head)   # 행의 이름 삽입

 

2. 멀티데이터 받아오기

 (1) KOA Studio : 종목마다 아래 23가지의 값을 가져올 수 있습니다.

 

KOA Studio 멀티 데이터
KOA Studio 멀티 데이터

 (2) 멀티데이터 받아오는 코딩

  - self.k.kiwoom.dynamicCall()을 이용해 키움 서버에 특정 명령어를 전송합니다.

  - GetCommData() 함수를 이용하여 KOA Studio 값을 받아옵니다.

  - 이때, sTrCode는 opw00018이며, sRQName은 계좌평가잔고내역요청 입니다. 그리고 index는 아래에서 다시 설명드리고 "종목번호", "종목명" 등의 데이터를 받아옵니다. 

  - "종목번호"의 경우 strip을 이용해 띄어쓰기를 제거하고, 번호앞에 붙은 "A"도 제거합니다(키움 서버에서 띄어쓰기와 A를 붙여서 정보를 보내줍니다.)

  - 보유수량, 현재가 등은 int로 감싸줘서 문자로 넘어오는 값을 정수로 치환합니다.

  - 수익률은 소수점까지 확인해야 하므로 float을 사용합니다.

멀티데이터 받아오기
멀티데이터 받아오기

 - 자 그럼 index에 대하여 알아보겠습니다. 인덱스는 순서라고 생각하시면 되고 rowCount에는 행의 개수가 들어갑니다. 예로 10 종목의 주식을 계좌에 보유하고 있다면 (A, B, C, D, E, F, G, H, I, J) rowCount는 10이 됩니다. 그리고 1번 index에는 A가 2번 index에는 B가 들어가게 됩니다.

 - range는 10을 1:10까지 만들어주는 함수입니다.

 - for 문을 사용하여 1부터 10까지를 넣는 것입니다.

 - 우선 1번 index와 등가의 A종목의 "종목번호" 부터 " "매매 가능 수량"까지 9가지의 정보를 받아옵니다.

 - 이런식으로 10번 index와 등가인 J종목의 "종목번호"부터 " "매매 가능 수량"까지 9가지의 정보를 받아옵니다.

 

 (3) 멀티데이터 테이블 위젯 GUI에 삽입

 - self.parent를 이용하여 부모 GUI를 사용할 준비를 합니다.

 - stocklistTableWidget_2라는 테이블 위젯에 setItem 함수를 사용하여 행과 열에 특정 값을 삽입합니다.

 - 행과 열에 QTableWidgetItem이라는 함수를 사용해 앞서 받아온 멀티 데이터를 삽입합니다.

 - index는 행을 나타내고 0~6은 열을 나타냅니다.

   즉 1행 0열에는 itemcode를, 1행 1열에는 itemName을... 이런 식으로 하나하나 대입하여 삽입하는 것입니다. 

 - 그리고 만약 sPrevNext 가 "2"일때 (0이면 더 이상 조회할 값이 없는 것, 2면 조회할 값이 남아 있는 것, 일반적으로 종목이 30개가 넘어가면 2라는 숫자가 반환됩니다.) 계좌 잔고를 조회하는 함수 detail_acount_mystock 함수를 다시 실행시키는 것입니다.

  - 만약 0일경우에는 이벤트 루프를 종료합니다.

멀티데이터 삽입
멀티데이터 삽입

  - 멀티데이터 삽입 결과는 아래와 같습니다. 종목 명부터 평가손익까지 들어간 것이 보이시죠?

멀티데이터 삽입결과
멀티데이터 삽입결과

 (3) 멀티데이터 별도의 절대 언어에 저장하기

  여기서 끝이 아닙니다. 손쉽게 다른 스레드에서도 계좌 관련 정보를 얻기 위해 16강에서 설명드린 kiwoom 스크립트에 별도의 절대언어(self.acc_portfoli)를 만들어 줍니다. self.acc_portfoli는 딕셔너리로 구성되어 있으며, 앞으로 어떤 스레드든 계좌 관련 정보를 얻으려면 self.acc_portfoli를 호출하면 됩니다.

kiwoom 스크립트에 절대 언어 입력
kiwoom 스크립트에 절대 언어 입력

  그리고 계좌 관련 정보에 멀티데이터인 itemCode가 있으면 pass 해서 넘어가고 그렇지 않으면 acc_portfoli에 update함수를 사용하여 itemCode를 저장합니다. 관련된 코드는 요약에 첨부하도록 하겠습니다.

 

계좌관련 정보 acc_protfolio에 저장
계좌관련 정보 acc_protfolio에 저장

3. 요약

  (1) 멀티데이터 받아오기 위해 for문을 사용하여 행에 대한 인덱스를 호출하였습니다. 그리고 각 인덱스에 등가인 종목 정보를 저장하였습니다.

  (2) 모든 스레드에서 관련 종목에 대한 정보에 접근하기 위해 16강에 설명드린 kiwoom 스크립트(매타클래스)에 self.acc_protfolio라는 절대 언어를 만들었습니다.

  (3) 관련된 코드 정보가 acc_portfoli에 있는지 확인 후 없으면 acc_portfoli에 관련 코드를 저장합니다.

  (4) 세부 정보(종목명 ~ 매매가능수량)는 다시 update함수를 이용해 acc_portfoli에 저장합니다.

  (5) GUI에 시각화를 위해 부모 GUI사용권한을 획득한 후 해당 테이블 위젯에 setItem 함수 및 QTableWidgetItem 함수를 사용하여 해당 행 과열에 원하는 값을 넣습니다.

  (6) 만약 멀티데이터가 30개 이상이면 이 과정을 한 번 더 해주고 그렇지 않으면 이벤트 루프를 종료합니다.

반응형
for index in range(rowCount):
    itemCode = self.k.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, index, "종목번호").strip(" ").strip("A")
    itemName = self.k.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, index, "종목명")
    amount = int(self.k.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, index, "보유수량"))
    buyingPrice = int(self.k.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, index, "매입가"))
    currentPrice = int(self.k.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, index, "현재가"))
    estimateProfit = int(self.k.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, index, "평가손익"))
    profitRate = float(self.k.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, index, "수익률(%)"))
    total_chegual_price = self.k.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, index, "매입금액")
    total_chegual_price = int(total_chegual_price.strip())
    possible_quantity = self.k.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, index, "매매가능수량")
    possible_quantity = int(possible_quantity.strip())

    if itemCode in self.k.acc_portfolio:
        pass
    else:
        self.k.acc_portfolio.update({itemCode:{}})      # self.account_stock_dict[code] = {}

    self.k.acc_portfolio[itemCode].update({"종목명": itemName.strip()})
    self.k.acc_portfolio[itemCode].update({"보유수량": amount})
    self.k.acc_portfolio[itemCode].update({"매입가": buyingPrice})
    self.k.acc_portfolio[itemCode].update({"수익률(%)": profitRate})
    self.k.acc_portfolio[itemCode].update({"현재가": currentPrice})
    self.k.acc_portfolio[itemCode].update({"매입금액": total_chegual_price})
    self.k.acc_portfolio[itemCode].update({"매매가능수량": possible_quantity})

    self.parent.stocklistTableWidget_2.setItem(index, 0, QTableWidgetItem(str(itemCode)))
    self.parent.stocklistTableWidget_2.setItem(index, 1, QTableWidgetItem(str(itemName)))
    self.parent.stocklistTableWidget_2.setItem(index, 2, QTableWidgetItem(str(amount)))
    self.parent.stocklistTableWidget_2.setItem(index, 3, QTableWidgetItem(str(buyingPrice)))
    self.parent.stocklistTableWidget_2.setItem(index, 4, QTableWidgetItem(str(currentPrice)))
    self.parent.stocklistTableWidget_2.setItem(index, 5, QTableWidgetItem(str(estimateProfit)))
    self.parent.stocklistTableWidget_2.setItem(index, 6, QTableWidgetItem(str(profitRate)))

if sPrevNext == "2":
    self.detail_acount_mystock(sPrevNext="2")  # 다음 페이지가 있으면 전부 검색한다.
else:
    self.detail_account_info_event_loop.exit()  # 끊어 준다.

여러분. 드디어 계좌평가잔고내역가져오기 강의가 종료되었습니다. 다음 강의에서는 앞서 한 모든 것들을 종합 정리해 드리겠습니다. 감사합니다.

 

23강 바로가기 : 모든 코드 정리

반응형

.link_tit