AUTO TRADE/[대신증권] CYBOS PLUS

대신증권 CYBOS PLUS 프로그램 구현 (12) - 분봉 차트 조회하기

프로그램 구현 목표

  • 최대로 회신 가능한 데이터 확인하기
  • 분봉 차트 조회 함수 제작하기
  • 연속 조회 기능 구현하기
  • 15분봉 말고 다른 분봉도 조회해보죠 ① GUI로 기능 구현하기
  • 15분봉 말고 다른 분봉도 조회해보죠 ② 함수의 인자로 전달받기

 

최대로 회신 가능한 데이터 확인하기

여기서 살펴볼 회신 가능한 데이터라는 개념은 일봉 차트를 구현할 때 확인했던 2,856개(분봉은 2,499개임)라는 개념과는 달리, 분봉 차트 데이터의 경우에만 적용되는 조회 가능한 범위의 한계가 있다. 대신증권 운영진 측의 답변에 따르면 아래와 같이 정리된다.

  1. 1분봉: 2년
  2. 5분봉: 5년
  3. 틱봉: 20일

 

 

분봉 차트 조회 함수 제작하기

분봉 차트는 기존에 살펴봤던 내용과 같이 데이터의 개수로만 조회가 가능하다. 그 전에 앞서 이전에 제작해두었던 일봉·주봉·월봉 차트 조회 함수인 `def _cont_len_chart():`의 이름을 `def chart_DWM():`으로 바꾸어준 후, 이번에 새롭게 만들 함수인 분봉·틱봉 차트 조회 함수의 이름을 `def chart_MT():`로 하여 새롭게 만들어주도록 하자.
※ Line: 10, 81, 82

## CpSysDib.py ##
import win32com.client
import pandas as pd

class StockChart:
    def __init__(self):
        self.stockchart = win32com.client.Dispatch("CpSysDib.StockChart")  ## COM 인스턴스 생성
        self.handlers = win32com.client.WithEvents(self.stockchart, event_handler_CpSysDib)

    def chart_DWM(self, item_code, request, quantity):
        _df = {'date':[], 'open':[], 'high':[], 'low':[], 'close':[], 'vol':[], 'tvol':[]}
        self.stockchart.SetInputValue(0, item_code)
        self.stockchart.SetInputValue(1, ord("2"))
        self.stockchart.SetInputValue(4, quantity)
        self.stockchart.SetInputValue(5, [0, 2, 3, 4, 5, 8, 9])
        self.stockchart.SetInputValue(6, ord(f"{request}"))  ## 차트 구분("D", "W", "M:)
        self.stockchart.SetInputValue(8, ord("0"))  ## 갭 보정 여부(0: 보정 X, 1: 보정 O)
        self.stockchart.SetInputValue(9, ord("0"))  ## 수정주가 여부(0: 수정 X, 1: 수정 O)
        self.stockchart.SetInputValue(10, ord("1"))  ## 거래량 구분
        self.stockchart.SetInputValue(11, ord("N"))  ## 조기 적용 여부
        self.handlers.set_instance(self.stockchart, "_cont_len_chart")
        self.stockchart.BlockRequest()  ## 데이터 요청

        len_fild = self.stockchart.GetHeaderValue(1)  ## 요청한 필드 개수
        array_fild = self.stockchart.GetHeaderValue(2)  ## 팔드 배열
        len_data = self.stockchart.GetHeaderValue(3)  ## 데이터 개수 확인
        # print(f"필드 개수:{len_fild}({array_fild}), 데이터 개수:{len_data}")

        for index in range(len_data):
            date = self.stockchart.GetDataValue(0, index)  ## 0: 날짜,    index: 인덱스 번호
            open = self.stockchart.GetDataValue(1, index)  ## 2: 시가,    index: 인덱스 번호
            high = self.stockchart.GetDataValue(2, index)  ## 3: 고가,    index: 인덱스 번호
            low = self.stockchart.GetDataValue(3, index)  ## 4: 저가,    index: 인덱스 번호
            close = self.stockchart.GetDataValue(4, index)  ## 5: 종가,    index: 인덱스 번호
            vol = self.stockchart.GetDataValue(5, index)  ## 8: 거래량,   index: 인덱스 번호
            tvol = self.stockchart.GetDataValue(6, index)  ## 9: 거래대금, index: 인덱스 번호
            _df['date'].append(str(date))
            _df['open'].append(open)
            _df['high'].append(high)
            _df['low'].append(low)
            _df['close'].append(close)
            _df['vol'].append(vol)
            _df['tvol'].append(tvol)

        # print(self.stockchart.Continue)
        # print(f"회신받은 개수:{len(_df['date'])}, 요청한 개수:{quantity}")

        while True:
            if len(_df['date']) <= quantity:        ## 아직 다 회신받지 못한 경우
                if self.stockchart.Continue == 1:   ## 추가 작업 수행
                    self.handlers.set_instance(self.stockchart, "_cont_len_chart")
                    self.stockchart.BlockRequest()  ## 데이터 요청

                    len_fild = self.stockchart.GetHeaderValue(1)  ## 요청한 필드 개수
                    array_fild = self.stockchart.GetHeaderValue(2)  ## 팔드 배열
                    len_data = self.stockchart.GetHeaderValue(3)  ## 데이터 개수 확인
                    # print(f"필드 개수:{len_fild}({array_fild}), 데이터 개수:{len_data}")

                    for index in range(len_data):
                        date = self.stockchart.GetDataValue(0, index)  ## 0: 날짜,    index: 인덱스 번호
                        open = self.stockchart.GetDataValue(1, index)  ## 2: 시가,    index: 인덱스 번호
                        high = self.stockchart.GetDataValue(2, index)  ## 3: 고가,    index: 인덱스 번호
                        low = self.stockchart.GetDataValue(3, index)  ## 4: 저가,    index: 인덱스 번호
                        close = self.stockchart.GetDataValue(4, index)  ## 5: 종가,    index: 인덱스 번호
                        vol = self.stockchart.GetDataValue(5, index)  ## 8: 거래량,   index: 인덱스 번호
                        tvol = self.stockchart.GetDataValue(6, index)  ## 9: 거래대금, index: 인덱스 번호
                        _df['date'].append(str(date))
                        _df['open'].append(open)
                        _df['high'].append(high)
                        _df['low'].append(low)
                        _df['close'].append(close)
                        _df['vol'].append(vol)
                        _df['tvol'].append(tvol)
                else:                               ## 데이터 조회 종료
                    break
            else:                                   ## 데이터 조회 종료(모두 회신받음)
                break
        chart_data = pd.DataFrame(_df, columns=['date', 'open', 'high', 'low', 'close', 'vol', 'tvol']).iloc[:quantity]
        print(chart_data)

    def chart_MT(self, item_code, request, quantity):
        pass

이제 분봉 차트를 조회하는 시점에서 `SetInputValue()` 함수를 통해 서버에 전달해주어야 하는 데이터는 일봉 차트를 조회할 때 사용했던 것과 크게 다르지 않고 특별히 다른 점이 있다면 필드 배열의 차이와 입력 데이터가 한 개 추가된다는 정도로 볼 수 있다. 필드 배열의 차이는 천천히 살펴보도록 하고, 입력 데이터가 한 개 늘어난다는 것은 차트 주기를 의미한다. 다시 말해, 일봉이나 주봉이나 월봉같은 경우에는 서버에서 자동적으로 입력받아 처리하기 때문에 상관은 없지만 분봉이나 틱봉같은 경우에는 정확히 몇분봉을 의미하는지를 함께 전달해주어야 한다는 것이다. 이 때 사용하는 입력 데이터의 번호는 7번이다. 일단 현재는 간단하게 15분봉을 조회한다고 가정하고 코드를 만들어보자.
※ Line: 7

    def chart_MT(self, item_code, request, quantity):
        self.stockchart.SetInputValue(0, item_code)
        self.stockchart.SetInputValue(1, ord("2"))
        self.stockchart.SetInputValue(4, quantity)
        self.stockchart.SetInputValue(5, [0, 1, 2, 3, 4, 5, 8, 9])
        self.stockchart.SetInputValue(6, ord(f"{request}"))  ## 차트 구분("m", "T")
        self.stockchart.SetInputValue(7, 15)  ## 분틱 주기(1, 3, 5, 10, 15 등등)
        self.stockchart.SetInputValue(8, ord("0"))  ## 갭 보정 여부(0: 보정 X, 1: 보정 O)
        self.stockchart.SetInputValue(9, ord("0"))  ## 수정주가 여부(0: 수정 X, 1: 수정 O)
        self.stockchart.SetInputValue(10, ord("1"))  ## 거래량 구분
        self.stockchart.SetInputValue(11, ord("N"))  ## 조기 적용 여부
        self.handlers.set_instance(self.stockchart, "_cont_len_chart")
        self.stockchart.BlockRequest()  ## 데이터 요청

그 후에 데이터를 요청했으니 데이터를 회신받아야 하는데, 이 때 사용하는 함수도 일봉 차트 데이터를 조회할 때 사용했던 것과 거의 동일하다. 차이점이 있다면 필드 배열이 변경됨에 따라 날짜 데이터를 별도로 수신받아야 한다는 차이점만 있다. 코드를 아래와 같이 수정한 후에, 프로그램에서 차트구분을 분봉으로 놓고 6,000개의 분봉 차트 데이터를 조회해보도록 하자.
※ Line: 15 ~ 29

    def chart_MT(self, item_code, request, quantity):
        self.stockchart.SetInputValue(0, item_code)
        self.stockchart.SetInputValue(1, ord("2"))
        self.stockchart.SetInputValue(4, quantity)
        self.stockchart.SetInputValue(5, [0, 1, 2, 3, 4, 5, 8, 9])
        self.stockchart.SetInputValue(6, ord(f"{request}"))  ## 차트 구분("m", "T")
        self.stockchart.SetInputValue(7, 15)  ## 분틱 주기(1, 3, 5, 10, 15 등등)
        self.stockchart.SetInputValue(8, ord("0"))  ## 갭 보정 여부(0: 보정 X, 1: 보정 O)
        self.stockchart.SetInputValue(9, ord("0"))  ## 수정주가 여부(0: 수정 X, 1: 수정 O)
        self.stockchart.SetInputValue(10, ord("1"))  ## 거래량 구분
        self.stockchart.SetInputValue(11, ord("N"))  ## 조기 적용 여부
        self.handlers.set_instance(self.stockchart, "_cont_len_chart")
        self.stockchart.BlockRequest()  ## 데이터 요청
        
        len_fild = self.stockchart.GetHeaderValue(1)  ## 요청한 필드 개수
        array_fild = self.stockchart.GetHeaderValue(2)  ## 팔드 배열
        len_data = self.stockchart.GetHeaderValue(3)  ## 데이터 개수 확인
        print(f"필드 개수:{len_fild}({array_fild}), 데이터 개수:{len_data}")

        for index in range(len_data):
            date = self.stockchart.GetDataValue(0, index)  ## 0: 날짜,    index: 인덱스 번호
            hour = self.stockchart.GetDataValue(1, index)  ## 1: 시간,    index: 인덱스 번호
            open = self.stockchart.GetDataValue(2, index)  ## 2: 시가,    index: 인덱스 번호
            high = self.stockchart.GetDataValue(3, index)  ## 3: 고가,    index: 인덱스 번호
            low = self.stockchart.GetDataValue(4, index)  ## 4: 저가,    index: 인덱스 번호
            close = self.stockchart.GetDataValue(5, index)  ## 5: 종가,    index: 인덱스 번호
            vol = self.stockchart.GetDataValue(6, index)  ## 8: 거래량,   index: 인덱스 번호
            tvol = self.stockchart.GetDataValue(7, index)  ## 9: 거래대금, index: 인덱스 번호
            print(f"[{date} {hour}] 시:{open}, 고:{high}, 저:{low}, 종:{close}, 거래:{vol}, 대금:{tvol}")

 

프로그램 실행 전에 앞서, 일봉 차트를 조회하는 함수는 `def chart_DWM`으로 바꾸었고 분봉 차트를 조회하는 함수의 이름은 `def chart_MT`로 새롭게 생성한 만큼 Boss.py 파일에 있는 코드를 조금 수정해주어야 한다. 이전에 `comboBox_2`의 `currentIndex()`를 활용하여 콤보박스의 활성화되어 있는 데이터가 틱봉이면 "T", 분봉이면 "m", 일봉이면 "D"와 같은 데이터를 `request` 변수에 입력하도록 해주었다. 따라서 우리는 콤보박스의 `currentIndex()`값이 틱봉·분봉을 뜻하는 0과 1인 경우에는 `chart_MT`를 실행시키도록 하고 일봉·주봉·월봉을 뜻하는 2, 3, 4인 경우에는 `chart_DWM`을 실행시키도록 해주어야 한다.
※ Line: 34 ~ 48

## 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.stockcode = CpUtil.CpStockCode()
        self.trade = CpTrade.CpTdUtil()
        self.stockmst = DsCbo1.StockMst()

        self._open_cybosplus()

        self.pushButton.clicked.connect(self._GetStockListByMarket)
        self.pushButton_2.clicked.connect(self._day_range)
        self.pushButton_3.clicked.connect(self._len_chart)

    def _len_chart(self):
        item_code = self.lineEdit_4.text()
        data_len = int(self.lineEdit_5.text())
        cur_idx = self.comboBox_2.currentIndex()
        if cur_idx == 0:
            request = "T"
            CpSysDib.StockChart().chart_MT(item_code, request, data_len)
        elif cur_idx == 1:
            request = "m"
            CpSysDib.StockChart().chart_MT(item_code, request, data_len)
        elif cur_idx == 2:
            request = "D"
            CpSysDib.StockChart().chart_DWM(item_code, request, data_len)
        elif cur_idx == 3:
            request = "W"
            CpSysDib.StockChart().chart_DWM(item_code, request, data_len)
        elif cur_idx == 4:
            request = "M"
            CpSysDib.StockChart().chart_DWM(item_code, request, data_len)

▶ 실행 결과 확인하기

더보기

self.object:CpCybos
[통신결과:1] 서버와의 연결에 성공했습니다.
로그인되어 있습니다.
self.object:_cont_len_chart
필드 개수:8(('날짜', '시간', '시가', '고가', '저가', '종가', '거래량', '거래대금')), 데이터 개수:2499
[20240906 1530] 시:68800, 고:69000, 저:68800, 종:68900, 거래:1343919, 대금:92591640000
[20240906 1515] 시:69000, 고:69200, 저:68800, 종:68900, 거래:812495, 대금:56032100000

( 중략 )
[20240418 1500] 시:79700, 고:79800, 저:79600, 종:79700, 거래:498107, 대금:39696840000
[20240418 1445] 시:79800, 고:79900, 저:79500, 종:79600, 거래:705055, 대금:56208310000

 

 

연속 조회 기능 구현하기

위의 실행 결과에서 확인할 수 있듯이, 분봉 차트 데이터의 경우에는 일봉과는 달리 최대 2,499개의 데이터만 회신해준다는 것을 확인할 수 있다. 하지만 요청 회당 최대 몇 개의 데이터를 회신해주는지와는 무관하게 우리는 연속 조회 기능을 구현해주어야만 한다. 연속 조회 기능은 일전에 일봉 차트 데이터에서 구현했던 것과 거의 동일한 로직으로 구현해주면 된다.
※ Line: 2, 31 ~ 76

    def chart_MT(self, item_code, request, quantity):
        _df = {'date':[], 'hour':[], 'dhour':[], 'open':[], 'high':[], 'low':[], 'close':[], 'vol':[], 'tvol':[]}
        self.stockchart.SetInputValue(0, item_code)
        self.stockchart.SetInputValue(1, ord("2"))
        self.stockchart.SetInputValue(4, quantity)
        self.stockchart.SetInputValue(5, [0, 1, 2, 3, 4, 5, 8, 9])
        self.stockchart.SetInputValue(6, ord(f"{request}"))  ## 차트 구분("m", "T")
        self.stockchart.SetInputValue(7, 15)  ## 분틱 주기(1, 3, 5, 10, 15 등등)
        self.stockchart.SetInputValue(8, ord("0"))  ## 갭 보정 여부(0: 보정 X, 1: 보정 O)
        self.stockchart.SetInputValue(9, ord("0"))  ## 수정주가 여부(0: 수정 X, 1: 수정 O)
        self.stockchart.SetInputValue(10, ord("1"))  ## 거래량 구분
        self.stockchart.SetInputValue(11, ord("N"))  ## 조기 적용 여부
        self.handlers.set_instance(self.stockchart, "_cont_len_chart")
        self.stockchart.BlockRequest()  ## 데이터 요청

        len_fild = self.stockchart.GetHeaderValue(1)  ## 요청한 필드 개수
        array_fild = self.stockchart.GetHeaderValue(2)  ## 팔드 배열
        len_data = self.stockchart.GetHeaderValue(3)  ## 데이터 개수 확인
        # print(f"필드 개수:{len_fild}({array_fild}), 데이터 개수:{len_data}")

        for index in range(len_data):
            date = self.stockchart.GetDataValue(0, index)  ## 0: 날짜,    index: 인덱스 번호
            hour = self.stockchart.GetDataValue(1, index)  ## 1: 시간,    index: 인덱스 번호
            open = self.stockchart.GetDataValue(2, index)  ## 2: 시가,    index: 인덱스 번호
            high = self.stockchart.GetDataValue(3, index)  ## 3: 고가,    index: 인덱스 번호
            low = self.stockchart.GetDataValue(4, index)  ## 4: 저가,    index: 인덱스 번호
            close = self.stockchart.GetDataValue(5, index)  ## 5: 종가,    index: 인덱스 번호
            vol = self.stockchart.GetDataValue(6, index)  ## 8: 거래량,   index: 인덱스 번호
            tvol = self.stockchart.GetDataValue(7, index)  ## 9: 거래대금, index: 인덱스 번호
            # print(f"[{date} {hour}] 시:{open}, 고:{high}, 저:{low}, 종:{close}, 거래:{vol}, 대금:{tvol}")
            _df['date'].append(str(date))
            _df['hour'].append(str(hour))
            _df['dhour'].append(f"{str(date)}{str(hour)}")
            _df['open'].append(open)
            _df['high'].append(high)
            _df['low'].append(low)
            _df['close'].append(close)
            _df['vol'].append(vol)
            _df['tvol'].append(tvol)

        while True:
            if len(_df['date']) <= quantity:        ## 아직 다 회신받지 못한 경우
                if self.stockchart.Continue == 1:   ## 추가 작업 수행
                    self.handlers.set_instance(self.stockchart, "_cont_len_chart")
                    self.stockchart.BlockRequest()  ## 데이터 요청

                    len_fild = self.stockchart.GetHeaderValue(1)  ## 요청한 필드 개수
                    array_fild = self.stockchart.GetHeaderValue(2)  ## 팔드 배열
                    len_data = self.stockchart.GetHeaderValue(3)  ## 데이터 개수 확인
                    # print(f"필드 개수:{len_fild}({array_fild}), 데이터 개수:{len_data}")

                    for index in range(len_data):
                        date = self.stockchart.GetDataValue(0, index)  ## 0: 날짜,    index: 인덱스 번호
                        hour = self.stockchart.GetDataValue(1, index)  ## 1: 시간,    index: 인덱스 번호
                        open = self.stockchart.GetDataValue(2, index)  ## 2: 시가,    index: 인덱스 번호
                        high = self.stockchart.GetDataValue(3, index)  ## 3: 고가,    index: 인덱스 번호
                        low = self.stockchart.GetDataValue(4, index)  ## 4: 저가,    index: 인덱스 번호
                        close = self.stockchart.GetDataValue(5, index)  ## 5: 종가,    index: 인덱스 번호
                        vol = self.stockchart.GetDataValue(6, index)  ## 8: 거래량,   index: 인덱스 번호
                        tvol = self.stockchart.GetDataValue(7, index)  ## 9: 거래대금, index: 인덱스 번호
                        # print(f"[{date} {hour}] 시:{open}, 고:{high}, 저:{low}, 종:{close}, 거래:{vol}, 대금:{tvol}")
                        _df['date'].append(str(date))
                        _df['hour'].append(str(hour))
                        _df['dhour'].append(f"{str(date)}{str(hour)}")
                        _df['open'].append(open)
                        _df['high'].append(high)
                        _df['low'].append(low)
                        _df['close'].append(close)
                        _df['vol'].append(vol)
                        _df['tvol'].append(tvol)
                else:                               ## 데이터 조회 종료
                    break
            else:                                   ## 데이터 조회 종료(모두 회신받음)
                break
        chart_data = pd.DataFrame(_df, columns=['date', 'hour', 'dhour', 'open', 'high', 'low', 'close', 'vol', 'tvol']).iloc[:quantity]
        print(chart_data)

▶ 실행 결과 확인하기

더보기

self.object:CpCybos
[통신결과:1] 서버와의 연결에 성공했습니다.
로그인되어 있습니다.
self.object:chart_MT
self.object:chart_MT
self.object:chart_MT
          date  hour         dhour   open  ...    low  close      vol         tvol
0     20240906  1530  202409061530  68800  ...  68800  68900  1343919  92591640000
1     20240906  1515  202409061515  69000  ...  68800  68900   812495  56032100000
2     20240906  1500  202409061500  68700  ...  68600  69100   681327  46945020000
3     20240906  1445  202409061445  68700  ...  68600  68700   565439  38874400000
4     20240906  1430  202409061430  69000  ...  68700  68800   615722  42367610000
...        ...   ...           ...    ...  ...    ...    ...      ...          ...
5995  20230927  1030  202309271030  68700  ...  68600  68700   485409  33349120000
5996  20230927  1015  202309271015  68600  ...  68500  68800   569140  39104320000
5997  20230927  1000  202309271000  68800  ...  68500  68500   498518  34254920000
5998  20230927   945   20230927945  68900  ...  68800  68900   492186  33892640000
5999  20230927   930   20230927930  69000  ...  68800  68800   502016  34598440000
[6000 rows x 9 columns]

 

 


반응형
728x90

 

 

15분봉 말고 다른 분봉도 조회해보죠 ① GUI로 기능 구현하기

글의 제목에서 알 수 있듯이, 이번 목차에서는 GUI 상에서 분봉을 입력할 수 있는 기능을 넣어서 그 데이터에 해당하는 분봉을 조회해 볼 예정이다. 먼저, GUI와 관련된 이벤트들을 처리하는 qt_gui.py 파일을 생성해주고, `class etc:`라는 이름의 클래스를 먼저 생성해주자. 그 후에 초기화 함수에서는 Boss.py 파일의 클래스를 상속받은 후, 콤보박스 2에서 발생하는 데이터들을 처리하기 위해 `def comboBox_2_CIC()`라는 이름의 함수를 생성해주도록 하자.

## qt_gui.py ##
class etc:
    def __init__(self, boss):
        self.boss = boss

    def comboBox_2_CIC(self):
        pass

물론 Boss.py 파일의 초기화 함수에서 추가적인 코드가 구현되어야 하지만, 그 부분은 아래에서 구현해보도록 하고 일단 당장은 `def comboBox_2_CIC(self):` 함수 내부에서는 `self.boss`라는 내용을 통해 GUI에 접근할 수 있다고 가정하고 코드를 구현해보자. 일단 이 함수의 이름에 있는 CIC는 currentIndexChanged의 약자인데, 이는 `QComboBox` 객체가 지원하는 메서드인 `currentIndexChanged`를 따온 것이다. 이 메서드는 `comboBox_2`의 데이터가 변경될 때 발생하는 이벤트이다. 다시 말해, GUI의 comboBox_2가 틱봉으로 설정되어 있는 상태에서 분봉으로 변경되면 이 이벤트가 발생하고, 분봉에서 또 다른 것으로 변경될 때에도 이벤트가 발생한다. 아래와 같이 `def comboBox_2CIC(self):` 함수를 수정해주자.
※ Line: 7, 8, 9

## qt_gui.py ##
class etc:
    def __init__(self, boss):
        self.boss = boss

    def comboBox_2_CIC(self):
        """CIC: current Index Changed"""
        cur_index = self.boss.comboBox_2.currentIndex()
        print(f" 콤보박스 인덱스 변경됨:{cur_index}")

그 후에 다시 Boss.ui(GUI) 파일을 열어서 아래와 같이 lineEdit을 활용하여 주기 구분을 추가해주도록 하자. (해당 객체의 이름은 `lineEdit_6`이다.)

그 후 다시 Boss.py 파일로 돌아와 GUI와 관련된 내용을 호출하는 구간에서 `from gui import qt_gui`라는 구문을 통해 해당 파일을 임포트한 후, `class cybos`의 초기화 함수 부분에서 `lambda` 함수를 활용하여 `class etc`의 인자로 `self`를 전달해주도록 하자. 이제 qt_gui.py 파일 내부의 `class etc`에서는 `self.boss.comboBox_2`나 `self.boss.lineEdit_6`와 같은 구문을 통해 GUI에 접근할 수 있다.
※ Line: 30

## 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 *
from gui import qt_gui

main_ui = uic.loadUiType("main.ui")[0]
class cybos(QMainWindow, main_ui):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.stockcode = CpUtil.CpStockCode()
        self.trade = CpTrade.CpTdUtil()
        self.stockmst = DsCbo1.StockMst()

        self._open_cybosplus()

        self.pushButton.clicked.connect(self._GetStockListByMarket)
        self.pushButton_2.clicked.connect(self._day_range)
        self.pushButton_3.clicked.connect(self._len_chart)
        self.comboBox_2.currentIndexChanged.connect(lambda: qt_gui.etc(self).comboBox_2_CIC())

이제 다시 qt_gui.py 파일로 돌아와서 `def comboBox_2_CIC(self):` 함수 내부에서 `QLineEdit` 객체의 `setEnabled` 메서드를 활용하여 `lineEdit_6`를 활성화시키거나 비활성화시킬 수 있다. 즉, comboBox_2의 데이터를 바탕으로 그 아래에 있는 주기구분에 데이터를 입력할 수 있는지 없는지를 결정지을 수 있다는 것이다. 
※ Line: 10 ~ 13

(좌측) 활성화되어 있는 모습 / (우측) 비활성화된 모습

## qt_gui.py ##
class etc:
    def __init__(self, boss):
        self.boss = boss

    def comboBox_2_CIC(self):
        """CIC: current Index Changed"""
        cur_index = self.boss.comboBox_2.currentIndex()
        print(f" 콤보박스 인덱스 변경됨:{cur_index}")
        if cur_index == 0 or cur_index == 1:
            self.boss.lineEdit_6.setEnabled(True)
        else:
            self.boss.lineEdit_6.setEnabled(False)

□ 프로그램을 실행시켜서 차트구분 데이터를 변경해보자.

더보기

self.object:CpCybos
[통신결과:1] 서버와의 연결에 성공했습니다.
로그인되어 있습니다.
 콤보박스 인덱스 변경됨:2
 콤보박스 인덱스 변경됨:0
 콤보박스 인덱스 변경됨:1
 콤보박스 인덱스 변경됨:0

 

 

15분봉 말고 다른 분봉도 조회해보죠 ② 함수의 인자로 전달받기

일단 함수의 인자로 전달받기 위해서는 CpSysDib.py 파일 내부의 `def chart_MT()` 함수의 인자를 변경해주면 된다. 기존에는 종목코드(`item_code`)와 요청구분(`request`), 요청개수(`quantity`)까지만 구현되어 있었지만 마지막 자리에 `cycle`이라는 주기구분을 추가해주면 된다.
※ Line: 1, 8

    def chart_MT(self, item_code, request, quantity, cycle):
        _df = {'date':[], 'hour':[], 'dhour':[], 'open':[], 'high':[], 'low':[], 'close':[], 'vol':[], 'tvol':[]}
        self.stockchart.SetInputValue(0, item_code)
        self.stockchart.SetInputValue(1, ord("2"))
        self.stockchart.SetInputValue(4, quantity)
        self.stockchart.SetInputValue(5, [0, 1, 2, 3, 4, 5, 8, 9])
        self.stockchart.SetInputValue(6, ord(f"{request}"))  ## 차트 구분("m", "T")
        self.stockchart.SetInputValue(7, cycle)  ## 분틱 주기(1, 3, 5, 10, 15 등등)
        self.stockchart.SetInputValue(8, ord("0"))  ## 갭 보정 여부(0: 보정 X, 1: 보정 O)
        self.stockchart.SetInputValue(9, ord("0"))  ## 수정주가 여부(0: 수정 X, 1: 수정 O)
        self.stockchart.SetInputValue(10, ord("1"))  ## 거래량 구분
        self.stockchart.SetInputValue(11, ord("N"))  ## 조기 적용 여부
        self.handlers.set_instance(self.stockchart, "chart_MT")
        self.stockchart.BlockRequest()  ## 데이터 요청

        len_fild = self.stockchart.GetHeaderValue(1)  ## 요청한 필드 개수
        array_fild = self.stockchart.GetHeaderValue(2)  ## 팔드 배열
        len_data = self.stockchart.GetHeaderValue(3)  ## 데이터 개수 확인
        # print(f"필드 개수:{len_fild}({array_fild}), 데이터 개수:{len_data}")

        for index in range(len_data):
            date = self.stockchart.GetDataValue(0, index)  ## 0: 날짜,    index: 인덱스 번호
            hour = self.stockchart.GetDataValue(1, index)  ## 1: 시간,    index: 인덱스 번호
            open = self.stockchart.GetDataValue(2, index)  ## 2: 시가,    index: 인덱스 번호
            high = self.stockchart.GetDataValue(3, index)  ## 3: 고가,    index: 인덱스 번호
            low = self.stockchart.GetDataValue(4, index)  ## 4: 저가,    index: 인덱스 번호
            close = self.stockchart.GetDataValue(5, index)  ## 5: 종가,    index: 인덱스 번호
            vol = self.stockchart.GetDataValue(6, index)  ## 8: 거래량,   index: 인덱스 번호
            tvol = self.stockchart.GetDataValue(7, index)  ## 9: 거래대금, index: 인덱스 번호
            # print(f"[{date} {hour}] 시:{open}, 고:{high}, 저:{low}, 종:{close}, 거래:{vol}, 대금:{tvol}")
            _df['date'].append(str(date))
            _df['hour'].append(str(hour))
            _df['dhour'].append(f"{str(date)}{str(hour)}")
            _df['open'].append(open)
            _df['high'].append(high)
            _df['low'].append(low)
            _df['close'].append(close)
            _df['vol'].append(vol)
            _df['tvol'].append(tvol)

        while True:
            if len(_df['date']) <= quantity:        ## 아직 다 회신받지 못한 경우
                if self.stockchart.Continue == 1:   ## 추가 작업 수행
                    self.handlers.set_instance(self.stockchart, "chart_MT")
                    self.stockchart.BlockRequest()  ## 데이터 요청

                    len_fild = self.stockchart.GetHeaderValue(1)  ## 요청한 필드 개수
                    array_fild = self.stockchart.GetHeaderValue(2)  ## 팔드 배열
                    len_data = self.stockchart.GetHeaderValue(3)  ## 데이터 개수 확인
                    # print(f"필드 개수:{len_fild}({array_fild}), 데이터 개수:{len_data}")

                    for index in range(len_data):
                        date = self.stockchart.GetDataValue(0, index)  ## 0: 날짜,    index: 인덱스 번호
                        hour = self.stockchart.GetDataValue(1, index)  ## 1: 시간,    index: 인덱스 번호
                        open = self.stockchart.GetDataValue(2, index)  ## 2: 시가,    index: 인덱스 번호
                        high = self.stockchart.GetDataValue(3, index)  ## 3: 고가,    index: 인덱스 번호
                        low = self.stockchart.GetDataValue(4, index)  ## 4: 저가,    index: 인덱스 번호
                        close = self.stockchart.GetDataValue(5, index)  ## 5: 종가,    index: 인덱스 번호
                        vol = self.stockchart.GetDataValue(6, index)  ## 8: 거래량,   index: 인덱스 번호
                        tvol = self.stockchart.GetDataValue(7, index)  ## 9: 거래대금, index: 인덱스 번호
                        # print(f"[{date} {hour}] 시:{open}, 고:{high}, 저:{low}, 종:{close}, 거래:{vol}, 대금:{tvol}")
                        _df['date'].append(str(date))
                        _df['hour'].append(str(hour))
                        _df['dhour'].append(f"{str(date)}{str(hour)}")
                        _df['open'].append(open)
                        _df['high'].append(high)
                        _df['low'].append(low)
                        _df['close'].append(close)
                        _df['vol'].append(vol)
                        _df['tvol'].append(tvol)
                else:                               ## 데이터 조회 종료
                    break
            else:                                   ## 데이터 조회 종료(모두 회신받음)
                break
        chart_data = pd.DataFrame(_df, columns=['date', 'hour', 'dhour', 'open', 'high', 'low', 'close', 'vol', 'tvol']).iloc[:quantity]
        print(chart_data)

그 후에 다시 Boss.py 파일로 돌아와서 차트 데이터를 요청하는 지점의 조건문 하단을 아래와 같이 수정해주면 된다.
※ Line: 7, 8, 11, 12

    def _len_chart(self):
        item_code = self.lineEdit_4.text()
        data_len = int(self.lineEdit_5.text())
        cur_idx = self.comboBox_2.currentIndex()
        if cur_idx == 0:
            request = "T"
            cycle = int(self.lineEdit_6.text())
            CpSysDib.StockChart().chart_MT(item_code, request, data_len, cycle)
        elif cur_idx == 1:
            request = "m"
            cycle = int(self.lineEdit_6.text())
            CpSysDib.StockChart().chart_MT(item_code, request, data_len, cycle)
        elif cur_idx == 2:
            request = "D"
            CpSysDib.StockChart().chart_DWM(item_code, request, data_len)
        elif cur_idx == 3:
            request = "W"
            CpSysDib.StockChart().chart_DWM(item_code, request, data_len)
        elif cur_idx == 4:
            request = "M"
            CpSysDib.StockChart().chart_DWM(item_code, request, data_len)

□ 삼성전자(A005930) 5분봉 차트 5,000개를 조회했을 때의 결과 데이터 확인

더보기

          date  hour         dhour   open  ...    low  close      vol          tvol
0     20240906  1530  202409061530  68900  ...  68900  68900  1028428   70858680000
1     20240906  1520  202409061520  68800  ...  68800  69000   315491   21732960000
2     20240906  1515  202409061515  68900  ...  68800  68900   372529   25666710000
3     20240906  1510  202409061510  69000  ...  68900  68900   324893   22415900000
4     20240906  1505  202409061505  69000  ...  69000  69000   115073    7949490000
...        ...   ...           ...    ...  ...    ...    ...      ...           ...
4995  20240607   925   20240607925  78000  ...  77800  77800   482247   37601560000
4996  20240607   920   20240607920  78000  ...  77800  78100   713218   55588130000
4997  20240607   915   20240607915  78400  ...  78000  78100   928028   72729810000
4998  20240607   910   20240607910  78100  ...  78100  78300   488149   38189320000
4999  20240607   905   20240607905  78400  ...  78000  78100  2502156  195973050000
[5000 rows x 9 columns]

□ 삼성전자(A005930) 10분봉 차트 데이터 5,000개를 조회했을 때의 결과 데이터 확인

더보기

          date  hour         dhour   open  ...    low  close      vol         tvol
0     20240906  1530  202409061530  68900  ...  68900  68900  1028428  70858680000
1     20240906  1520  202409061520  68900  ...  68800  69000   688020  47399670000
2     20240906  1510  202409061510  69000  ...  68900  68900   439966  30365390000
3     20240906  1500  202409061500  68900  ...  68800  69100   429750  29658980000
4     20240906  1450  202409061450  68800  ...  68600  68900   480089  32983000000
...        ...   ...           ...    ...  ...    ...    ...      ...          ...
4995  20240304  1440  202403041440  74900  ...  74700  74700   653767  48906200000
4996  20240304  1430  202403041430  74900  ...  74800  74800   202991  15194780000
4997  20240304  1420  202403041420  74800  ...  74700  74800   221277  16561570000
4998  20240304  1410  202403041410  74800  ...  74700  74700   587372  43932510000
4999  20240304  1400  202403041400  74700  ...  74600  74800   430371  32154100000
[5000 rows x 9 columns]

□ 삼성전자(A005930) 30분봉 차트 데이터 5,000개를 조회했을 때의 결과 데이터 확인

더보기

          date  hour         dhour   open  ...    low  close      vol          tvol
0     20240906  1530  202409061530  69000  ...  68800  68900  2156414  148623740000
1     20240906  1500  202409061500  68700  ...  68600  69100  1246766   85819420000
2     20240906  1430  202409061430  69100  ...  68700  68800   875163   60264220000
3     20240906  1400  202409061400  68900  ...  68900  69000  1023127   70690760000
4     20240906  1330  202409061330  69100  ...  68800  69000   654774   45133180000
...        ...   ...           ...    ...  ...    ...    ...      ...           ...
4995  20230215  1300  202302151300  62300  ...  62100  62300   325506   20249150000
4996  20230215  1230  202302151230  62200  ...  62100  62300   683753   42533210000
4997  20230215  1200  202302151200  62300  ...  62000  62200   827141   51410100000
4998  20230215  1130  202302151130  62400  ...  62100  62300   802252   49940830000
4999  20230215  1100  202302151100  62600  ...  62200  62300  1116184   69657400000
[5000 rows x 9 columns]

 

 


728x90
반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.