AUTO TRADE/[대신증권] CYBOS PLUS

대신증권 CYBOS PLUS 프로그램 구현 (11) - 일봉 차트 조회 : 연속 조회 사용하기 ②

프로그램 구현 목표

  • 두 번보다도 많은 횟수의 데이터를 요청해보자
  • 요청한 데이터 개수만큼만 결과값을 전달받아보자

 

두 번보다도 많은 횟수의 데이터를 요청해보자

현재까지 구현한 코드는 단순하게 2,856개의 데이터를 두 번 요청하는 기능밖에 수행하지 못한다. 왜냐하면 동일한 작업을 계속해서 처리하도록 하는 기능이 구현되어 있지 않기 때문이다. 이해가 가지 않는다면, 3번을 요청해야만 회신받을 수 있는 데이터 개수인 6,000개를 요청해보면 된다. 아래의 결과값만 봐도 어렵지 않게 이해할 수 있는데, 정확히 5712개의 데이터만 반환되고 있다. 이는 10,000개를 요청하나 13,000개를 요청하나 똑같은 결과값만을 반환해줄 뿐이다.

6,000개를 요청했을 때의 결과값

더보기
더보기

self.object:CpCybos
[통신결과:1] 서버와의 연결에 성공했습니다.
로그인되어 있습니다.
self.object:_cont_len_chart
필드 개수:7(('날짜', '시가', '고가', '저가', '종가', '거래량', '거래대금')), 데이터 개수:2856
1
회신받은 개수:2856, 요청한 개수:6000
self.object:_cont_len_chart
필드 개수:7(('날짜', '시가', '고가', '저가', '종가', '거래량', '거래대금')), 데이터 개수:2856
          date    open    high     low   close       vol           tvol
0     20240906   69100   69700   68000   69000  12769516   878911000000
1     20240905   70100   71200   69000   69000  25686769  1795890000000
2     20240904   69800   71100   69800   70000  27366563  1923751000000
3     20240903   74100   74300   72500   72500  16314599  1195017000000
4     20240902   74500   74700   73500   74400  12641376   938130000000
...        ...     ...     ...     ...     ...       ...            ...
5707  20010802  201000  202000  194000  195500    635840   125604000000
5708  20010801  191500  199500  190500  198000   1157583   227329000000
5709  20010731  187000  190500  186000  189500    444664    84178000000
5710  20010730  188000  189000  184500  185500    401109    74832000000
5711  20010727  186500  189500  184500  185500    576045   107796000000
[5712 rows x 7 columns]

그렇다면 계속해서 차트 데이터를 조회하기 위해 추가해주어야 하는 코드는 무엇일까 ? 바로 `while`문이다. 이 구문은 간단하게 설명하자면 특정 조건이 충족되거나 했을 때 `break`라는 구문이 호출되기까지 계속해서 반복 작업을 수행하는 구문이다. 따라서 우리는 차트 데이터를 조회하면서 ①서버에서 회신해 줄 수 있는 데이터가 더 이상 없거나 ②요청한 데이터의 개수에 알맞는 데이터가 회신된 경우에는 `break` 구문을 호출하여 데이터 요청을 멈추면 된다. 
※ Line: 48, 75, 77

    def _cont_len_chart(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'])
        print(chart_data)

□ 6,000개 조회 시 실행 결과 확인하기 (데이터 요청 횟수: 3회)

더보기
더보기

self.object:CpCybos
[통신결과:1] 서버와의 연결에 성공했습니다.
로그인되어 있습니다.
self.object:_cont_len_chart
필드 개수:7(('날짜', '시가', '고가', '저가', '종가', '거래량', '거래대금')), 데이터 개수:2856
1
회신받은 개수:2856, 요청한 개수:6000
self.object:_cont_len_chart
필드 개수:7(('날짜', '시가', '고가', '저가', '종가', '거래량', '거래대금')), 데이터 개수:2856
self.object:_cont_len_chart
필드 개수:7(('날짜', '시가', '고가', '저가', '종가', '거래량', '거래대금')), 데이터 개수:2856
          date   open   high    low  close       vol           tvol
0     20240906  69100  69700  68000  69000  16989595  1169824000000
1     20240905  70100  71200  69000  69000  25686769  1795890000000
2     20240904  69800  71100  69800  70000  27366563  1923751000000
3     20240903  74100  74300  72500  72500  16314599  1195017000000
4     20240902  74500  74700  73500  74400  12641376   938130000000
...        ...    ...    ...    ...    ...       ...            ...
8563  19910608  33000  33000  32500  33000      2940       96000000
8564  19910607  33000  33100  32600  33000      8380      276000000
8565  19910605  32900  33200  32600  33200      4450      146000000
8566  19910604  33000  33000  32300  33000      5600      183000000
8567  19910603  33400  33400  32800  33000      3910      128000000

□ 10,000개 조회 시 실행 결과 확인하기 (데이터 요청 횟수: 4회)

더보기
더보기

self.object:CpCybos
[통신결과:1] 서버와의 연결에 성공했습니다.
로그인되어 있습니다.
self.object:_cont_len_chart
필드 개수:7(('날짜', '시가', '고가', '저가', '종가', '거래량', '거래대금')), 데이터 개수:2856
1
회신받은 개수:2856, 요청한 개수:10000
self.object:_cont_len_chart
필드 개수:7(('날짜', '시가', '고가', '저가', '종가', '거래량', '거래대금')), 데이터 개수:2856
self.object:_cont_len_chart
필드 개수:7(('날짜', '시가', '고가', '저가', '종가', '거래량', '거래대금')), 데이터 개수:2856
self.object:_cont_len_chart
필드 개수:7(('날짜', '시가', '고가', '저가', '종가', '거래량', '거래대금')), 데이터 개수:2856
           date   open   high    low  close       vol           tvol
0      20240906  69100  69700  68000  68900  17025487  1172298000000
1      20240905  70100  71200  69000  69000  25686769  1795890000000
2      20240904  69800  71100  69800  70000  27366563  1923751000000
3      20240903  74100  74300  72500  72500  16314599  1195017000000
4      20240902  74500  74700  73500  74400  12641376   938130000000
...         ...    ...    ...    ...    ...       ...            ...
11419  19810901   9700   9800   9650   9700     12070              0
11420  19810831   9750   9800   9700   9750      3100              0
11421  19810829  10050  10050   9900   9900       640              0
11422  19810828   9700  10000   9700  10000     11330              0
11423  19810827   9700   9800   9700   9700     11930              0

 

 

요청한 데이터 개수만큼만 결과값을 전달받아보자

우리가 데이터를 요청한 후에 서버로부터 회신받은 데이터는 모두 `_df` 변수(Dictionary 타입)에 입력되고 그 데이터를 기반으로 판다스의 `DataFrame` 함수를 활용하여 `chart_data`라는 변수로 만들어주고 있다. 여기서 우리가 필요한 개수의 데이터만 확인하기 위해서는 `DataFrame`의 인덱스 정보를 활용하면 된다. 데이터프레임 형식의 변수 내부에서 인덱스 정보만을 사용하여 데이터를 가공하기 위해서는 `iloc` 메서드를 사용하면 된다. 아래의 예제를 살펴보자.

## iloc 사용 방법
chart_data.iloc[0:6000]
chart_data.iloc[:6000]	## :의 좌측에 있는 데이터는 생략할 경우 0으로 인식됨

이렇게 사용하게 되면 인덱스 번호가 0인 자료부터 5999인 자료까지를 출력하게 된다. 여기서 6000이라는 데이터를 전달해주었음에도 5999까지만 반환해주는 이유는, 인덱싱 방법은 항상 입력된 숫자보다 1 적은 값까지만 확인하기 때문이다. 다시 본론으로 돌아와, 우리는 두 번째 줄에 있는 0을 생략한 `chart_data.iloc[:6000]`을 사용할 예정인데 여기서 6000이라는 데이터는 사전에 조회할 데이터의 개수를 전달한 `quantity` 변수에 입력되어 있다. 따라서 아래와 같이 사용할 수 있다.

## 우리가 사용할 방법
chart_data.iloc[:quantity]

이제 코드를 아래와 같이 변경해준 후 6000개의 데이터를 조회하여 결과값을 확인해보도록 하자.

## 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 _cont_len_chart(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'])
        print(chart_data)

        chart_data_2 = pd.DataFrame(_df, columns=['date', 'open', 'high', 'low', 'close', 'vol', 'tvol']).iloc[:quantity]
        print(chart_data_2)

▶ 실행 결과 확인하기

더보기
더보기

self.object:CpCybos
[통신결과:1] 서버와의 연결에 성공했습니다.
로그인되어 있습니다.
self.object:_cont_len_chart
필드 개수:7(('날짜', '시가', '고가', '저가', '종가', '거래량', '거래대금')), 데이터 개수:2856
1
회신받은 개수:2856, 요청한 개수:6000
self.object:_cont_len_chart
필드 개수:7(('날짜', '시가', '고가', '저가', '종가', '거래량', '거래대금')), 데이터 개수:2856
self.object:_cont_len_chart
필드 개수:7(('날짜', '시가', '고가', '저가', '종가', '거래량', '거래대금')), 데이터 개수:2856
          date   open   high    low  close       vol           tvol
0     20240906  69100  69700  68000  69000  17682522  1217561000000
1     20240905  70100  71200  69000  69000  25686769  1795890000000
2     20240904  69800  71100  69800  70000  27366563  1923751000000
3     20240903  74100  74300  72500  72500  16314599  1195017000000
4     20240902  74500  74700  73500  74400  12641376   938130000000
...        ...    ...    ...    ...    ...       ...            ...
8563  19910608  33000  33000  32500  33000      2940       96000000
8564  19910607  33000  33100  32600  33000      8380      276000000
8565  19910605  32900  33200  32600  33200      4450      146000000
8566  19910604  33000  33000  32300  33000      5600      183000000
8567  19910603  33400  33400  32800  33000      3910      128000000
[8568 rows x 7 columns]


          date    open    high     low   close       vol           tvol
0     20240906   69100   69700   68000   69000  17682522  1217561000000
1     20240905   70100   71200   69000   69000  25686769  1795890000000
2     20240904   69800   71100   69800   70000  27366563  1923751000000
3     20240903   74100   74300   72500   72500  16314599  1195017000000
4     20240902   74500   74700   73500   74400  12641376   938130000000
...        ...     ...     ...     ...     ...       ...            ...
5995  20000529  263000  284000  262000  273000   1342608   368331000000
5996  20000526  295000  299500  280000  280000   1342077   386580000000
5997  20000525  316500  319000  296500  300000   1719303   524805000000
5998  20000524  308000  318500  296000  310000   1443050   440266000000
5999  20000523  325000  335000  317500  319000    825886   268229000000
[6000 rows x 7 columns]

 

 


728x90
반응형
Contents

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

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