< 주가 일봉 데이터 저장 프로그램 개발 - 프로그램 GUI 구현>


1. "프로그램 개발 개요"

2. "프로그램 DB 설계 및 구현"

3. "키움 OPEN API 구현"

4. "프로그램 기능 구현"


해당 포스트를 읽기 전에 이전 포스트를 읽기 바란다.


"주가 일봉 데이터 저장 프로그램 개발" 포스트 시리즈의 마지막 포스트다. 이번 포스트에서 프로그램 GUI를 구현하고 다음 포스트에 실행 프로그램 파일을 올릴 예정이다. 구현할 GUI는 다음과 같다.


위 GUI는 "Qt Designer"라는 툴을 이용해 구현했다. "Qt Designer"에 대해서 잘 모른다면 아래에 링크된 사이트에서 배울 수 있다. 

"파이썬으로 배우는 알고리즘 트레이딩"


"Qt Designer"를 몰라도 된다. ui 구성은 아래 첨부파일에 있다. 다운 받아서 바로 사용하면 된다.


stock_regist.ui


전체 GUI 구현 코드는 다음과 같다. 이전 포스트에서 구현한 MainFunctions 클래스를 이용하고 모든 예외 처리를 하지 않았기에 간단하다.

import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
import MainFunctions as mf

form_class = uic.loadUiType("stock_regist.ui")[0]

class MainWindow(QMainWindow, form_class):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.setFixedSize(355,400)
        self.loginBtn.clicked.connect(self.loginBtn_clicked)
        self.dbBtn.clicked.connect(self.dbBtn_clicked)
        self.excelBtn.clicked.connect(self.excelBtn_clicked)

        self.mainFucntions = mf.MainFunctions()

    def loginBtn_clicked(self):
        pwd = self.pwdEdit.toPlainText()
        if pwd == "":
            QMessageBox.about(self, "로그인 실패", "패스워드를 입력하세요")
            self.listWidget.addItem(QListWidgetItem("패스워드를 입력하세요"))
            return
        if self.mainFucntions.db_login(pwd):
            QMessageBox.about(self, "로그인 성공", "로그인 성공")
            self.pwdEdit.setEnabled(False)
            self.loginBtn.setEnabled(False)
            self.dbBtn.setEnabled(True)
            self.listWidget.addItem(QListWidgetItem("로그인 성공"))
        else:
            QMessageBox.about(self, "로그인 실패", "패스워드를 다시 입력하세요")
            self.listWidget.addItem(QListWidgetItem("비밀번호가 틀렸습니다. 다시 입력하세요"))

    def dbBtn_clicked(self):
        code = self.codeEdit.toPlainText()
        if code == '':
            QMessageBox.about(self, "실패", "종목 코드를 입력하세요")
            self.listWidget.addItem(QListWidgetItem("종목 코드를 입력하세요"))
            return

        if self.mainFucntions.is_stock(code):
            QMessageBox.about(self, "입력 시작", "종목 데이터 전송을 시작하겠습니다.  OK를 눌러주세요")
            self.mainFucntions.db_insert_stock(code)
            QMessageBox.about(self, "입력 성공", "종목 데이터를 DB에 저장했습니다.")
            self.listWidget.addItem(QListWidgetItem("종목 데이터 전송 성공. DB에 데이터가 저장되었습니다."))

        else:
            QMessageBox.about(self, "실패", "종목 코드를 다시 입력하세요")
            self.listWidget.addItem(QListWidgetItem("종목 코드를 다시 입력하세요. 코드에 해당하는 종목이 없습니다."))

    def excelBtn_clicked(self):
        code = self.codeEdit.toPlainText()
        if code == '':
            QMessageBox.about(self, "실패", "종목 코드를 입력하세요")
            self.listWidget.addItem(QListWidgetItem("종목 코드를 입력하세요"))
            return
        if self.mainFucntions.is_stock(code):
            QMessageBox.about(self, "입력 시작", "종목 데이터 전송 시작을 시작하겠습니다.. OK를 눌러주세요")
            self.mainFucntions.data_to_excel(code)
            QMessageBox.about(self, "입력 성공", "종목 데이터 엑셀 파일을 다운로드했습니다.")
            self.listWidget.addItem(QListWidgetItem("종목 데이터 전송 성공. 엑셀에 데이터가 저장되었습니다."))
            self.listWidget.addItem(QListWidgetItem("이 프로그램 설치 위치에 엑셀 파일이 있습니다."))
        else:
            QMessageBox.about(self, "실패", "종목 코드를 다시 입력하세요")
            self.listWidget.addItem(QListWidgetItem("종목 코드를 다시 입력하세요. 코드에 해당하는 종목이 없습니다."))


if __name__ == "__main__":
    app = QApplication(sys.argv)
    mainWindow = MainWindow()
    mainWindow.show()
    app.exec_()


초기화 부분을 보자. 'uic.loadUiType"을 이용해 "Qt Designer"에서 만든 UI 파일을 로드하고 'setupUi"를 통해 부착한다. ~Btn.clicked.connect 를 이용해 버튼을 눌렀을 때 호출되는 메서드를 연결한다. "loginBtn", "dbBtn", "excelBtn"은 각각 "로그인", "DB 저장", "엑셀 저장" 버튼 ID 값이다. 해당 ID 값은 "Qt Designer" 툴에서 설정한다. 마지막으로 프로그램 기능 역할을 하는 MainFunctions()을 생성한다. MainFunctions 클래스 코드는 이전 포스트에 있다.  

form_class = uic.loadUiType("stock_regist.ui")[0]

class MainWindow(QMainWindow, form_class):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.setFixedSize(355,400)
        self.loginBtn.clicked.connect(self.loginBtn_clicked)
        self.dbBtn.clicked.connect(self.dbBtn_clicked)
        self.excelBtn.clicked.connect(self.excelBtn_clicked)

        self.mainFucntions = mf.MainFunctions()

로그인 버튼을 눌렀을 때 호출되는 메서드를 보자. 'pwdEdit.toPlainText()'를 통해 로그인 버튼 옆 에디트 박스에 입력된 값을 얻는다. 조건문을 통해 입력 값이 비어있는 지 확인하고 그렇다면 'QMessageBox.about'을 이용해 "로그인 실패" 팝업창을 띄우고 리스트 박스에 "패스워드를 입력하세요"라고 출력한다. 만약 입력 값이 비어있지 않다면 "mainFunctions.db_login(pwd)" 를 통해 로그인한다. 이전 포스트에서 배웠듯이 결과값이 True를 리턴하면 로그인을 성공한다. False를 리턴하면 로그인을 실패한다. 로그인에 성공했다면 로그인 버튼과 옆에 에디트 박스를 'setEnabled(False)'를 통해 비활성화 시키고 "DB 저장" 버튼을 활성화 시킨다. 

    def loginBtn_clicked(self):
        pwd = self.pwdEdit.toPlainText()
        if pwd == "":
            QMessageBox.about(self, "로그인 실패", "패스워드를 입력하세요")
            self.listWidget.addItem(QListWidgetItem("패스워드를 입력하세요"))
            return
        if self.mainFucntions.db_login(pwd):
            QMessageBox.about(self, "로그인 성공", "로그인 성공")
            self.pwdEdit.setEnabled(False)
            self.loginBtn.setEnabled(False)
            self.dbBtn.setEnabled(True)
            self.listWidget.addItem(QListWidgetItem("로그인 성공"))
        else:
            QMessageBox.about(self, "로그인 실패", "패스워드를 다시 입력하세요")
            self.listWidget.addItem(QListWidgetItem("비밀번호가 틀렸습니다. 다시 입력하세요"))


"DB 저장" 버튼을 눌렀을 때 호출되는 소스는 다음과 같다. 사용자가 입력한 코드 값을 읽는다. 비어있는 지 확인하고 "mainFuctions.is_stock()" 메서드를 이용해 사용자 입력 값이 올바른 지 확인한다. 오라르다면 'mainFuctions.db_insert_stock()" 을 호출해 DB에 데이터를 저장한다. 

   def dbBtn_clicked(self):
        code = self.codeEdit.toPlainText()
        if code == '':
            QMessageBox.about(self, "실패", "종목 코드를 입력하세요")
            self.listWidget.addItem(QListWidgetItem("종목 코드를 입력하세요"))
            return

        if self.mainFucntions.is_stock(code):
            QMessageBox.about(self, "입력 시작", "종목 데이터 전송을 시작하겠습니다.  OK를 눌러주세요")
            self.mainFucntions.db_insert_stock(code)
            QMessageBox.about(self, "입력 성공", "종목 데이터를 DB에 저장했습니다.")
            self.listWidget.addItem(QListWidgetItem("종목 데이터 전송 성공. DB에 데이터가 저장되었습니다."))

        else:
            QMessageBox.about(self, "실패", "종목 코드를 다시 입력하세요")
            self.listWidget.addItem(QListWidgetItem("종목 코드를 다시 입력하세요. 코드에 해당하는 종목이 없습니다."))


"엑셀 저장" 버튼을 눌렀을 때 호출되는 소스는 위에서 본 "dbBtn_clicked()" 메서드와 로직이 동일하다. 차이점이라면 'db_insert_stock()' 부분이 엑셀 저장을 위해 'data_to_excel()' 메서드로 바뀐 것 밖에 없다. 

    def excelBtn_clicked(self):
        code = self.codeEdit.toPlainText()
        if code == '':
            QMessageBox.about(self, "실패", "종목 코드를 입력하세요")
            self.listWidget.addItem(QListWidgetItem("종목 코드를 입력하세요"))
            return
        if self.mainFucntions.is_stock(code):
            QMessageBox.about(self, "입력 시작", "종목 데이터 전송 시작을 시작하겠습니다.. OK를 눌러주세요")
            self.mainFucntions.data_to_excel(code)
            QMessageBox.about(self, "입력 성공", "종목 데이터 엑셀 파일을 다운로드했습니다.")
            self.listWidget.addItem(QListWidgetItem("종목 데이터 전송 성공. 엑셀에 데이터가 저장되었습니다."))
            self.listWidget.addItem(QListWidgetItem("이 프로그램 설치 위치에 엑셀 파일이 있습니다."))
        else:
            QMessageBox.about(self, "실패", "종목 코드를 다시 입력하세요")
            self.listWidget.addItem(QListWidgetItem("종목 코드를 다시 입력하세요. 코드에 해당하는 종목이 없습니다."))



이것으로 GUI 구현을 마쳤다. 주요 기능들을 이전 포스트들에서 다 구현했기에 쉽게 구현 가능했다. 해당 전체 소스파일은 아래 첨부 파일에 있다. 


MainWindow.py


여기까지 해서 "주가 일봉 데이터 저장 프로그램" 개발을 마쳤다. 



필자는 파이썬을 전문으로 하는 현업 프로그래머가 아니라 평범한 컴퓨터 공학과 대학생입니다. 따라서 코드의 효율성, 최적화 측면에서 부족한 면이 있습니다. 잘못된 부분이나 좀 더 효율적으로 수정해야할 부분이 있다면 댓글 부탁드립니다.

해당 프로그램의 최종 결과 파일 및 소스 코드는 다음 포스트에 첨부할 예정입니다. 

+ Recent posts