대신증권 CYBOS PLUS 프로그램 구현 (5) - 전종목 종목코드 조회하기 ①
프로그램 구현 목표
- 종목코드 조회 함수 제작하기
- GUI 내부에서 종목코드 조회 버튼 생성하기
- 파이썬 내부에서 종목코드 조회 버튼과 함수 연결하기
- 종목코드 조회 함수 캡슐화
종목코드 조회 함수 제작하기
대신증권 CYBOS PLUS에서 종목코드를 조회하는 함수는 `CpUtil.CpCodeMgr` 모듈의 `GetStockListByMarket` 함수를 통해 제공되고 있다. 이 함수는 아래의 사진에서 확인할 수 있듯이, 전달된 시장 구분 값에 따라 해당 시장에 소속된 주식 종목코드들을 반환하는 기능을 갖고 있다.
- 1: 거래소(코스피)
- 2: 코스닥
- 3: K-OTC (금투협에서 운영하는 장외주식시장)
- 4: KRX
- 5: KONEX
그렇다면 이제 해당 함수에 각각의 데이터를 전달하고 그 결과 데이터를 반환받아보도록 하자.
## CpUtil.py ##
class CpCodeMgr:
def __init__(self):
self.codemgr = win32com.client.Dispatch("CpUtil.CpCodeMgr") ## COM 연결
def _GetStockListByMarket(self, market_kind_code):
"""
:param market_kind_code: GetStockMarketKind 함수의 인자값 참조
1: 거래소, 2: 코스닥, 3: K-OTC, 4: KRX, 5: KONEX
:return : 시장 구분에 따른 주식 종목 배열
"""
value = self.codemgr.GetStockListByMarket(market_kind_code)
print(f"[인자값:{market_kind_code}] 종목코드 목록:{value}")
## Boss.py ##
import win32com.client
from pywinauto import application
from COM import CpSysDib
from COM import CpUtil
from COM import CpTrade
from COM import DsCbo1
import time
## GUI ##
import sys
from PyQt5 import uic
from PyQt5.QtWidgets import *
main_ui = uic.loadUiType("main.ui")[0]
class cybos(QMainWindow, main_ui):
def __init__(self):
super().__init__()
self.cybos = CpUtil.CpCybos()
self.stockchart = CpUtil.CpStockCode()
self.trade = CpTrade.CpTdUtil()
self.codemgr = CpUtil.CpCodeMgr()
self.stockmst = DsCbo1.StockMst()
self.stockchart = CpSysDib.StockChart()
self._open_cybosplus()
self.codemgr._GetStockListByMarket(1)
def _open_cybosplus(self):
if self.cybos._IsConnect() == True: ## 연결되어 있는 경우
print(f"로그인되어 있습니다.")
elif self.cybos._IsConnect() == False:
print(f"로그인되어 있지 않습니다. 로그인을 시도합니다.")
login()
while True:
if self.cybos._IsConnect() == False:
time.sleep(1)
elif self.cybos._IsConnect() == True:
print(f"로그인되었습니다. 반복문에서 나갑니다.")
break
class login:
"""CYBOS PLUS 실행 함수"""
def __init__(self):
self.Id = ""
self.Password = ""
self.Cert = "*"
self.run()
def run(self):
app = application.Application()
executable_path = "C:\\DAISHIN\\STARTER\\ncStarter.exe"
args = f" /prj:cp /id:{self.Id} /pwd:{self.Password} /pwdcert:{self.Cert} /autostart"
app.start(f"{executable_path}{args}")
if __name__ == "__main__":
app = QApplication(sys.argv)
myWindow = cybos()
myWindow.show()
app.exec_()
▶ 실행 결과 확인하기
[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:0] 서버와의 연결에 실패했습니다.
[통신결과:1] 서버와의 연결에 성공했습니다.
[통신결과:1] 서버와의 연결에 성공했습니다.
로그인되었습니다. 반복문에서 나갑니다.
[인자값:1] 종목코드 목록:('A000020', 'A000040', 'A000050', 'A000070', 'A000075', · · · (중략) · · · 'Q760013')
여기까지의 내용에 따르면, 실질적으로 우리는 1번과 2번 데이터를 주로 사용하게 될 것이지만 경우에 따라서는 3번, 4번, 5번 데이터를 전달하여 결과값을 확인할 수도 있기 때문에 어떠한 데이터를 전달할지에 대해서는 재량이 있어야 한다. 이 때 우리가 떠올려야 할 부분은 바로 '캡슐화'이다. 즉, 이 경우에는 1에서 5까지 다섯 가지의 데이터 유형이 전달될 수 있기 때문에 캡슐화를 통해 어떠한 데이터가 인자로 전달되든지 간에 그 인자를 가지고 올바르게 처리할 수 있도록 하는 것이다. 다만 캡슐화와 관련해서는 조금 더 나중에 구현하도록 하고, 일단 GUI를 먼저 만들어주도록 하자.
GUI 내부에서 종목코드 조회 버튼 생성하기
다시 이전에 만들어두었던 main.ui 파일을 열어서 좌측의 PushButton 하나를 드래그해서 화면에 넣어주도록 하자. 그 후에 해당 버튼을 더블클릭해서 이름을 "종목코드 조회"로 바꿔준 후에, 그 버튼을 클릭(활성화)한 상태로 Qt Designer의 우측을 보면 해당 버튼의 객체 이름이 `pushButton`라고 적혀 있는 것을 확인할 수 있다. 여기서의 `pushButton`, 즉 객체 이름이 우리의 코드에 필요한 이름이니 기억해두도록 하자.
파이썬 내부에서 종목코드 조회 버튼과 함수 연결하기
앞서 살펴봤던 `pushButton`은 단순한 하나의 객체 이름에 해당할 뿐, 이 `pushButton`이 어떠한 기능을 수행할 수 있는지에 대해서는 우측의 클래스 행에 표기되어 있는 `QPushButton`을 살펴보아야 한다. 다만 여기서 클래스라고 적혀 있는 부분에서 우리는 '아. 이 클래스가 갖고 있는 여러 가지 함수를 사용할 수 있겠구나.'하는 생각을 할 수 있어야 한다. 이 클래스를 대표하는 함수는 `clicked`라는 함수인데, 이는 말 그대로 '클릭됐을 때'를 의미한다. 그렇다면 `pushButton`이 클릭됐을 때를 코드로 표현할 때에는 어떻게 표현할 수 있을까 ? 아래와 같이 표현할 수 있다.
## clicked ##
self.pushButton.clicked
물론 이 역시도 깊게 알아보자면, 사실 `QPushButton`이라는 클래스는 `clicked`라는 이벤트를 발생시킨다. 즉, 우리가 이전에 이벤트 처리기를 생성하여 해당 이벤트가 발생했을 때 그 이벤트를 처리할 함수를 별도로 지정해주었듯이 이 경우에도 그 이벤트를 처리할 함수와 연결해주어야 한다. 따라서 이제 이 버튼이 클릭됐을 때(=이벤트가 발생했을 때) 수행할 작업과 연결하는 작업이 필요한데, 그 기능은 `connect`가 수행하게 된다.
## connect ##
self.pushButton.clicked.connect(수행할 함수)
위의 코드를 해석하자면, `self.pushButton` 객체에서 `clicked`라는 이벤트가 발생했을 때, `수행할 함수`를 `connect`하라는 내용으로 볼 수 있다. 여기서 우리가 아직 `수행할 함수`를 정확하게 지정해주지는 않았지만, 대충 어떠한 구조의 함수가 들어가야 할지는 어렵지 않게 예측할 수 있을 것이다. 일단 Boss.py 파일 내부에서 `self.pushButton`의 이벤트를 처리하는 코드를 넣어주도록 하자.
이와 더불어, QPushButton 등과 같은 클래스를 사용하기 위해서는 반드시 `self.setupUi(self)`라는 구문을 추가해주어야 한다. 만약 이 구문 없이 코드를 실행하게 되면 `AttributeError: 'cybos' object has no attribute 'pushButton'`라는 에러가 발생하게 되는데, 이는 간단하게 설명하자면 현재 `pushButton`을 사용할 수 없기 때문에 발생하는 오류이다. 즉, `setupUi` 함수를 사용하지 않으면 GUI 내에서 제공되는 버튼을 사용할 수 없다는 것이다.
※ Line: 19, 28
## Boss.py ##
import win32com.client
from pywinauto import application
from COM import CpSysDib
from COM import CpUtil
from COM import CpTrade
from COM import DsCbo1
import time
## GUI ##
import sys
from PyQt5 import uic
from PyQt5.QtWidgets import *
main_ui = uic.loadUiType("main.ui")[0]
class cybos(QMainWindow, main_ui):
def __init__(self):
super().__init__()
self.setupUi(self)
self.cybos = CpUtil.CpCybos()
self.stockchart = CpUtil.CpStockCode()
self.trade = CpTrade.CpTdUtil()
self.codemgr = CpUtil.CpCodeMgr()
self.stockmst = DsCbo1.StockMst()
self.stockchart = CpSysDib.StockChart()
self._open_cybosplus()
self.pushButton.clicked.connect()
▶ 실행 결과 확인하기
self.pushButton.clicked.connect()
TypeError: Required argument 'slot' (pos 1) not found
실행 결과를 보면 알겠지만, 에러가 발생한다. 뭔가가 잘못된 것 같지만 사실 잘못되지 않았다. 왜냐하면 우리가 아직 `수행할 함수`를 지정해주지 않았기 때문이다. 이제 앞에서 작업하다가 멈춘 '캡슐화' 작업을 수행해주도록 하자.
종목코드 조회 함수 캡슐화
함수를 하나의 캡슐로 만든다는 것은 이전 게시글에서부터 수도 없이 살펴봤던 내용이기 때문에, 여기서는 간단하게 CpUtil.py 파일 내부에 있는 `class CpCodeMgr`의 `def _GetStockListByMarket(self, market_kind_code):` 함수의 캡슐화 작업을 진행하도록 하자.
하지만 아래의 코드를 보기 전에 앞서, `self.pushButton.clicked.connect()`와 같은 코드를 통해 `수행할 함수`를 지정하여 실행되도록 할 때에는 인자를 함께 전달할 수 없다. 그렇기 때문에 Boss.py 파일 내부의 `def _GetStockListByMarket(self):` 함수 내부에서 `market_kind=1`이라는 내용을 추가하여 인자를 함께 전달해줄 수밖에 없다. 이 부분과 관련하여, 우리가 아래에서 구현한 반쪽짜리 캡슐화가 아니라 온전한 캡슐화를 통해 이 함수의 인자로 데이터를 전달할 수 있도록 하는 기능은 다음 게시글에서 구현해보록 하자.
※ Line: 30, 31, 32
## Boss.py ##
import win32com.client
from pywinauto import application
from COM import CpSysDib
from COM import CpUtil
from COM import CpTrade
from COM import DsCbo1
import time
## GUI ##
import sys
from PyQt5 import uic
from PyQt5.QtWidgets import *
main_ui = uic.loadUiType("main.ui")[0]
class cybos(QMainWindow, main_ui):
def __init__(self):
super().__init__()
self.setupUi(self)
self.cybos = CpUtil.CpCybos()
self.stockchart = CpUtil.CpStockCode()
self.trade = CpTrade.CpTdUtil()
self.codemgr = CpUtil.CpCodeMgr()
self.stockmst = DsCbo1.StockMst()
self.stockchart = CpSysDib.StockChart()
self._open_cybosplus()
self.pushButton.clicked.connect()
def _GetStockListByMarket(self):
market_kind = 1
self.codemgr._GetStockListByMarket(market_kind_code=market_kind)
def _open_cybosplus(self):
if self.cybos._IsConnect() == True: ## 연결되어 있는 경우
print(f"로그인되어 있습니다.")
elif self.cybos._IsConnect() == False:
print(f"로그인되어 있지 않습니다. 로그인을 시도합니다.")
login()
while True:
if self.cybos._IsConnect() == False:
time.sleep(1)
elif self.cybos._IsConnect() == True:
print(f"로그인되었습니다. 반복문에서 나갑니다.")
break
▶ 실행 결과 확인하기
## 버튼 클릭 전
[통신결과:1] 서버와의 연결에 성공했습니다.
로그인되어 있습니다.
## 버튼 클릭 후
[통신결과:1] 서버와의 연결에 성공했습니다.
로그인되어 있습니다.
[인자값:1] 종목코드 목록:('A000020', 'A000040', · · · (중략) · · · 'Q760013')
## 버튼 클릭할 때마다
[인자값:1] 종목코드 목록:('A000020', 'A000040', · · · (중략) · · · 'Q760013')
[인자값:1] 종목코드 목록:('A000020', 'A000040', · · · (중략) · · · 'Q760013')
[인자값:1] 종목코드 목록:('A000020', 'A000040', · · · (중략) · · · 'Q760013')
'AUTO TRADE > [대신증권] CYBOS PLUS' 카테고리의 다른 글
대신증권 CYBOS PLUS 프로그램 구현 (7) - 일봉 차트 조회 : 일자 범위 (0) | 2024.08.27 |
---|---|
대신증권 CYBOS PLUS 프로그램 구현 (6) - 전종목 종목코드 조회하기 ② (0) | 2024.08.26 |
대신증권 CYBOS PLUS 프로그램 구현 (4) - 이벤트 처리 함수 보완하기 (0) | 2024.08.25 |
대신증권 CYBOS PLUS 프로그램 구현 (3) - GUI와 연결하기 (0) | 2024.08.18 |
대신증권 CYBOS PLUS 프로그램 구현 (2) - 자동로그인 구현하기 ② (0) | 2024.08.18 |
소중한 공감 감사합니다