분할 매수/매도 코딩하기(6), 종목명/종목코드 및 현재가 테이블 위젯(TableWidget)에 업데이트 하기
본문 바로가기

주식 자동매매 강의/중급반(시황 및 차트 구현)

분할 매수/매도 코딩하기(6), 종목명/종목코드 및 현재가 테이블 위젯(TableWidget)에 업데이트 하기

반응형

 저번 강의에서는 종목명/종목 코드를 가져왔었죠. 이번 강의에서는 종목의 현재가까지 가져와 우리가 테이블 위젯에 업데이트해 보겠습니다. 기초반에서 했던 거지만(아래 링크 참조) 복습한다 생각하시고 따라오세요.

 

 1. 현재가 가져오기

 종목명/종목코들 가져왔으니 이번에는 현재가를 가져오겠습니다. 현재가는 다양한 방면으로 응용될 수 있습니다. 혹시 잘 모르겠으면 이전 강의 또는 기초반 강의를 참고하세요.

 

[기초반 무료 강의 : 54강 링크]

 

 우선 현재가를 가져오기 위해 아래와 같이 코딩을 합니다.

반응형

현재가 가져오는 함수
현재가 가져오는 함수

 - self.getItemInfo(self.new_code) : 이전 강의에서 self.new_code에 우리가 확인하고자 하는 종목의 코드를 입력하였죠. self. getItemInfo()라는 함수를 만들어 코드를 넣어 줍니다.

현재가 요청 및 받아오기
현재가 요청 및 받아오기

 (1) 현재가 요청하기 : KOA Studio opt10001 주식기본정보요청

KOA Studio opt10001 주식 기본정보 요청하기를 사용할 것입니다. 이 함수를 사용하면 원하는 종목의 현재가뿐만 아니라 액면가/자본금/상장주식/신용비율/PER/EPS 등등의 상당히 많은 데이터를 받아 올 수 있는데 우리는 현재가만 뽑아내겠습니다.

KOA Stuido
KOA Stuido

 - def getItemInfo(self, new_code) : 앞서 전달해온 self.new_code의 코드번호를 new_code로 받습니다.

 - self.k.kiwoom.dynamicCall(~new_code) : 위의 KOA Studio에서 원하는 값을 입력하는데 SetInputValue를 통해 종목코드 번호를 우선 입력합니다.

 - self.k.kiwoom.dynamicCall("opt1001,0,"100") : 다음으로 sTrCode인 opt10001을 입력하고 스크린 넘버는 100을 입력 후 CommRqData를 통해 현재가를 요청합니다.

 - self.detail_account_info_event_loop.exec_() :  이벤트 루프를 동작하여 키움 서버로부터 원하는 값이 반환될 때까지 기다려 줍니다.

 

 (2) 현재가 수신하기

 이전 강의에서 반환되는 데이터는 OnReceiveTrData 함수를 통해 trdata_slot에 반환되게 끔 만들었었죠?

OnReceiveTrData
OnReceiveTrData

 그러면 코딩 설명드리겠습니다.

 - if sTrCdoe == "opt10001" : sTrCdoe가 opt10001일 경우 아래 코드를 실행합니다.

 - if sRQName == "주식 기본정보 요청" : 혹시 여러 군대서 opt10001을 요청할 수 있기 때문에(주식 프로그램이 너무 방대해질 경우) 반환되는 sRQName이 주식 기본정보 요청일 경우 아래 코드를 실행하게 한 번 더 필터링합니다.

 - GetCommData를 통해 우리가 원하는 종목의 현재가를 currentPrice에 받아 옵니다. 이때 int를 통해 문자를 정수로 치환하고 정수 앞에 붙어있는 기호를 제거하기 위해 abs(절댓값)을 취합니다.

 - row_count = self.buylast.rowCount() : 조금 후 설명드릴 텐데 우리가 저장할 테이블 위젯의 objectName이 buylast이고 rowCount() 함수를 통해 몇 개의 행이 있는지 확인합니다.

 - self.buytlast.setItem(row_count - 1, 2, QTableWidgetItem(str(format(int(currentPrice), ", ")))) : 이 부분이 조금 중요한데 우리가 만든 테이블 위젯의 첫 번째 행에는 행의 목차가 들어가 있고 두 번째 행부터 원하는 값이 들어가게 됩니다. 따라서, 첫 행이 비어 있을 지라도 목차로 인해 2행이라고 반환되어 마이너스 1을 해줌으로써 목차를 생략한 1행이다라고 재명 시해 주는 것입니다. 그리고 QTableWidgetItem을 이용하여 currentPrice를 넣을 것인데 3열에 넣기 위해 2를 넣습니다. 반복적으로 말씀드리지만 파이썬은 처음이 0 두 번째가 1로 시작합니다. 2는 3번째 열을 뜻합니다.

 

2. 종목명/종목코드/현재가/매수 가격/매수수량/매도 가격/매도수량 전부 QtableWidget에 입력하기

 아래 코드를 보시면 크게 (1) 표 세팅하기, (2) 원하는 값 입력하기가 있습니다.

테이블위젯 셋팅 및 원하는 값 입력하기
테이블위젯 셋팅 및 원하는 값 입력하기

 (1) QTableWidget 셋팅하기

 아래 그림은 우리가 만든 GUI ALBA2.ui이며 QTableWidget의 objectName은 buylast입니다.

GUI ALBA2.ui
GUI ALBA2.ui

 -column_head = ["종목코드", "종목명", "현재가", "매수가격_1", ....] : 우리가 만들 표의 목차를 만드는 것입니다. 목차는 종목코드/종목명/현재가 및 매수가격1/매수수량1/~매도가격4/매도수량4 까지 총 19개를 입력합니다.

 - colCount = len(column_head) :  열의 개수(목차의 개수)를 계산합니다.

 - row_count = self.buylast.rowCount() : 행의 개수를 계산합니다.

 - self.buylast.setColumnCount(colCount) : setColumnCount를 통해 표의 열 개수 만큼 생성합니다.

 - self.buylast.setRowCount(colCount) : setRowCount를 통해 표의 행 개수를 생성합니다.

 - setHorizontalHeaderLabels(colum_head) : 우리가 만든 목차를 표에 삽입합니다.

 

 (2) 표에 원하는 값 집어넣기

 지금부터는 간단합니다. 오로지 setItem을 통해 우리가 원하는 값을 집어넣기만 하면 됩니다.

 -self.buylast.setItem(row_count, 0, QTalbeWidgetItem(str(self.new_code))) : 종목코드번호를 setItem과 QTalbeWidgetItem함수를 이용해 0열에 집어넣습니다.

 -self.buylast.setItem(row_count, 0, QTalbeWidgetItem(str(self.itemNmae))) : 종목 이름을 setItem과 QTalbeWidgetItem함수를 이용해 1열에 집어넣습니다.

 -self.getItemInfo(self.new_code) : 원하는 종목의 현재가를 입력합니다. 위에서 함수 세팅하셨죠?

 

 나머지는 다 동일하니 생략하도록 하겠습니다.

 

3. GUI 정렬과 초기화

 이 부분도 기초반에서 열심히 설명한 부분이라 간단히 넘어가도록 하겠습니다. 부족하신 분들은 기초반 강의를 타고 넘어가 확인하시면 자세히 설명되어 있습니다.

 아래 그림을 보시면 setTextAligment를 이용해 GUI 들어가는 값의 좌/우/상/하 정렬을 조정할 수 있습니다.

GUI 정렬과 초기화
GUI 정렬과 초기화

 (1) GUI 입력값 정렬

 GUI의 디자인을 위해 입력값의 상/하/좌/우 정렬을 합니다. 

 - 원하는 QtableWidget의 objectName을 입력하고 itme함수와 setTextAlignment 함수를 통해 원하는 세팅을 실시합니다. Qt.AlignVCenter를 통해 상/중/하 중 중앙 정렬하시고 Qt.AlignRight를 통해 좌/중/우 중 우측 정렬을 하십시오.

 

 (2) 초기화

 우리가 원하는 종목의 이름/코드/현재가/매수매도 수량 등을 입력한 후 다음 종목 입력을 위해 setValue(0)을 통해 초기화합니다.

 

4. 결론 및 최종 코드

 아래 그림을 보시면 최종 GUI로 종목명을 입력하고 종목 추가를 누를 시 오른쪽 표에 우리가 매수/매도하고자 하는 종목의 모든 정보가 입력되는 것을 확인할 수 있습니다. 이로써 분할 매수/매도할 준비가 끝났습니다. 다음 강의에서는 사용자 편의성을 위해 DB에 관한 입력 사항을 알아보겠습니다.

최종 GUI
최종 GUI

 코드공유

 

import sys                        # system specific parameters and functions : 파이썬 스크립트 관리
from PyQt5.QtWidgets import *     # GUI의 그래픽적 요소를 제어       하단의 terminal 선택, activate py37_32,  pip install pyqt5,   전부다 y
from PyQt5 import uic             # ui 파일을 가져오기위한 함수
from PyQt5.QtCore import *         # 쓰레드 함수를 불러온다.

################# 부가 기능 수행(일꾼) #####################################
from kiwoom import Kiwoom          # 키움증권 함수/공용 방 (싱글턴)

from Qthread_1 import Thread1      # 계좌평가잔고내역 가져오기
from Qthread_2 import Thread2      # 계좌 관리
from Qthread_3 import Thread3      # 실시간 자동매매 시작



###################################################
form_thirdwindow = uic.loadUiType("ALBA3.ui")[0]

class Thirdwindow(QMainWindow, QWidget, form_thirdwindow):
    def __init__(self):
        super(Thirdwindow, self).__init__()
        self.initUi()
        self.show()

        ### 초기 셋팅 : 분할 매수/매도
        self.textEdit_1.setValue(0)      # 초기 매수 금액
        self.textEdit_2.setValue(0)      # 초기 매수 금액
        self.textEdit_3.setValue(0)      # 초기 매수 금액
        self.textEdit_4.setValue(0)      # 초기 매수 금액
        self.textEdit_5.setValue(0)      # 초기 매수 금액
        self.textEdit_6.setValue(0)      # 초기 매수 금액
        self.textEdit_7.setValue(0)      # 초기 매수 금액
        self.textEdit_8.setValue(0)      # 초기 매수 금액
        self.textEdit_9.setValue(0)      # 초기 매수 금액
        self.textEdit_10.setValue(0)      # 초기 매수 금액
        self.textEdit_11.setValue(0)      # 초기 매수 금액
        self.textEdit_12.setValue(0)      # 초기 매수 금액
        self.textEdit_13.setValue(0)      # 초기 매수 금액
        self.textEdit_14.setValue(0)      # 초기 매수 금액
        self.textEdit_15.setValue(0)      # 초기 매수 금액
        self.textEdit_16.setValue(0)      # 초기 매수 금액

        ########## 더블 스핀 박스 우측정렬 및 소수점 삭제
        self.textEdit_1.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.textEdit_1.setDecimals(0)
        self.textEdit_2.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.textEdit_2.setDecimals(0)
        self.textEdit_3.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.textEdit_3.setDecimals(0)
        self.textEdit_4.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.textEdit_4.setDecimals(0)
        self.textEdit_5.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.textEdit_5.setDecimals(0)
        self.textEdit_6.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.textEdit_6.setDecimals(0)
        self.textEdit_7.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.textEdit_7.setDecimals(0)
        self.textEdit_8.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.textEdit_8.setDecimals(0)
        self.textEdit_9.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.textEdit_9.setDecimals(0)
        self.textEdit_10.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.textEdit_10.setDecimals(0)
        self.textEdit_11.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.textEdit_11.setDecimals(0)
        self.textEdit_12.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.textEdit_12.setDecimals(0)
        self.textEdit_13.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.textEdit_13.setDecimals(0)
        self.textEdit_14.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.textEdit_14.setDecimals(0)
        self.textEdit_15.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.textEdit_15.setDecimals(0)
        self.textEdit_16.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.textEdit_16.setDecimals(0)


        ####키움증권에 멸령을 보낼 수 있는 싱글턴 가져오기
        self.k = Kiwoom()                     # Kiwoom()을 실행하며 상속 받는다. Kiwoom()은 전지적인 아이다.

        ###### EventLoop
        self.detail_account_info_event_loop = QEventLoop()  # 계좌 이벤트루프


        ################# 부가기능 1 : 종목선택하기 새로운 종목 추가 및 삭제
        self.k.kiwoom.OnReceiveTrData.connect(self.trdata_slot)           # 키움서버 데이터 받는 곳

        self.additmelast.clicked.connect(self.searchItem2)                # 종목 추가




    def searchItem2(self):            # 종목추가시 사용됨.
        self.itemName = self.searchItemTextEdit2.toPlainText()
        self.new_code = None
        if self.itemName != "":
            for code in self.k.All_Stock_Code.keys():  # 포트폴리오에 저장된 코드들을 실시간 등록
                # 주식체결 정보 가져오기(틱 데이터) : 현재가, 전일대비, 등락률, 매도호가, 매수호가, 거래량, 누적거래량, 고가, 시가, 저가
                if self.itemName == self.k.All_Stock_Code[code]['종목명']:
                    self.new_code = code

        if self.new_code != "" and self.itemName == "":
            self.new_code = self.searchItemTextEdit3.toPlainText().strip()

            for code in self.k.All_Stock_Code.keys():  # 포트폴리오에 저장된 코드들을 실시간 등록
                if self.new_code == code:
                    self.itemName = self.k.All_Stock_Code[code]['종목명']


        column_head = ["종목코드", "종목명", "현재가", "매수가격_1", "매수수량_1", "매수가격_2", "매수수량_2", "매수가격_3", "매수수량_3", "매수가격_4", "매수수량_4", "매도가격_1", "매도수량_1", "매도가격_2", "매도수량_2", "매도가격_3", "매도수량_3", "매도가격_4", "매도수량_4"]
        colCount = len(column_head)
        row_count = self.buylast.rowCount()

        self.buylast.setColumnCount(colCount)  # 행 갯수
        self.buylast.setRowCount(row_count+1)  # colum_haed가 한 행을 잡아 먹는다. 실제 입력 되는 값은 1행 부터이다.
        self.buylast.setHorizontalHeaderLabels(column_head)  # 행의 이름 삽입

        self.buylast.setItem(row_count, 0, QTableWidgetItem(str(self.new_code))) # 실제 입력값은 1행부터이나 0부터 들어가야 된다.
        self.buylast.setItem(row_count, 1, QTableWidgetItem(str(self.itemName)))

        self.getItemInfo(self.new_code)

        self.buylast.setItem(row_count, 3, QTableWidgetItem(str(format(int(self.textEdit_1.value()), ","))))
        self.buylast.setItem(row_count, 4, QTableWidgetItem(str(format(int(self.textEdit_2.value()), ","))))
        self.buylast.setItem(row_count, 5, QTableWidgetItem(str(format(int(self.textEdit_3.value()), ","))))
        self.buylast.setItem(row_count, 6, QTableWidgetItem(str(format(int(self.textEdit_4.value()), ","))))
        self.buylast.setItem(row_count, 7, QTableWidgetItem(str(format(int(self.textEdit_5.value()), ","))))
        self.buylast.setItem(row_count, 8, QTableWidgetItem(str(format(int(self.textEdit_6.value()), ","))))
        self.buylast.setItem(row_count, 9, QTableWidgetItem(str(format(int(self.textEdit_7.value()), ","))))
        self.buylast.setItem(row_count, 10, QTableWidgetItem(str(format(int(self.textEdit_8.value()), ","))))
        self.buylast.setItem(row_count, 11, QTableWidgetItem(str(format(int(self.textEdit_9.value()), ","))))
        self.buylast.setItem(row_count, 12, QTableWidgetItem(str(format(int(self.textEdit_10.value()), ","))))
        self.buylast.setItem(row_count, 13, QTableWidgetItem(str(format(int(self.textEdit_11.value()), ","))))
        self.buylast.setItem(row_count, 14, QTableWidgetItem(str(format(int(self.textEdit_12.value()), ","))))
        self.buylast.setItem(row_count, 15, QTableWidgetItem(str(format(int(self.textEdit_13.value()), ","))))
        self.buylast.setItem(row_count, 16, QTableWidgetItem(str(format(int(self.textEdit_14.value()), ","))))


        ############# 좌측 정렬을 우측 정렬로 교체
        self.buylast.item(row_count, 0).setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter | Qt.AlignCenter)
        self.buylast.item(row_count, 1).setTextAlignment(Qt.AlignVCenter | Qt.AlignLeft)
        self.buylast.item(row_count, 2).setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.buylast.item(row_count, 3).setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.buylast.item(row_count, 4).setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.buylast.item(row_count, 5).setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.buylast.item(row_count, 6).setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.buylast.item(row_count, 7).setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.buylast.item(row_count, 8).setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.buylast.item(row_count, 9).setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.buylast.item(row_count, 10).setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.buylast.item(row_count, 11).setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.buylast.item(row_count, 12).setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.buylast.item(row_count, 13).setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.buylast.item(row_count, 14).setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.buylast.item(row_count, 15).setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self.buylast.item(row_count, 16).setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)


        ############################ 초기화

        self.textEdit_1.setValue(0)      # 초기 매수 금액
        self.textEdit_2.setValue(0)      # 초기 매수 금액
        self.textEdit_3.setValue(0)      # 초기 매수 금액
        self.textEdit_4.setValue(0)      # 초기 매수 금액
        self.textEdit_5.setValue(0)      # 초기 매수 금액
        self.textEdit_6.setValue(0)      # 초기 매수 금액
        self.textEdit_7.setValue(0)      # 초기 매수 금액
        self.textEdit_8.setValue(0)      # 초기 매수 금액
        self.textEdit_9.setValue(0)      # 초기 매수 금액
        self.textEdit_10.setValue(0)      # 초기 매수 금액
        self.textEdit_11.setValue(0)      # 초기 매수 금액
        self.textEdit_12.setValue(0)      # 초기 매수 금액
        self.textEdit_13.setValue(0)      # 초기 매수 금액
        self.textEdit_14.setValue(0)      # 초기 매수 금액
        self.textEdit_15.setValue(0)      # 초기 매수 금액
        self.textEdit_16.setValue(0)      # 초기 매수 금액


    def initUi(self):
        self.setupUi(self)


    def getItemInfo(self, new_code):
        self.k.kiwoom.dynamicCall("SetInputValue(QString, QString)", "종목코드", new_code)
        self.k.kiwoom.dynamicCall("CommRqData(QString, QString, int, QString)", "주식기본정보요청", "opt10001", 0, "100")
        self.detail_account_info_event_loop.exec_()

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

        if sTrCode == "opt10001":
            if sRQName == "주식기본정보요청":
                currentPrice = abs(int(self.k.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "현재가")))
                #D_R = (self.k.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "신용비율")).strip()
                row_count = self.buylast.rowCount()

                self.buylast.setItem(row_count - 1, 2, QTableWidgetItem(str(format(int(currentPrice), ","))))

            self.detail_account_info_event_loop.exit()
반응형

.link_tit