대신증권 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]
'AUTO TRADE > [대신증권] CYBOS PLUS' 카테고리의 다른 글
대신증권 CYBOS PLUS 프로그램 구현 (13) - 로그인 시 계좌 조회하기 (0) | 2024.09.07 |
---|---|
대신증권 CYBOS PLUS 프로그램 구현 (12) - 분봉 차트 조회하기 (0) | 2024.09.06 |
대신증권 CYBOS PLUS 프로그램 구현 (10) - 일봉 차트 조회 : 연속 조회 사용하기 ① (0) | 2024.09.02 |
대신증권 CYBOS PLUS 프로그램 구현 (9) - 일봉 차트 조회 : 오류 개선 (1) | 2024.09.01 |
대신증권 CYBOS PLUS 프로그램 구현 (8) - 일봉 차트 조회 : 데이터 개수 (0) | 2024.09.01 |
소중한 공감 감사합니다