CYBOS Plus로 기관, 외국인 매매량 불러오는 법
가이드1
CpSysDib.CpSvr7254
는 투자주체별현황을 일별-기간별,순매수-매매비중, 수량-금액을 일자별로 확인한다. 주식회사 씨젠의 투자주체별 데이터를 불러우는 파이썬 예제로 사용법을 익혀보자. 만약 CYBOS API에 익숙하지 않다면 다음의 가이드를 먼저 참고하자.
하이라이트
>>> data7254
종가 등락률 거래량 기관계 외국인
0 76000 -0.26 873525 -31512 34478
1 76200 -3.18 1546826 -128698 19419
2 78700 -1.75 1406556 -62565 -111363
3 80100 3.49 2544337 73141 214885
4 77400 0.26 2012656 -24802 7375
.. ... ... ... ... ...
97 62066 0.49 522518 4608 -50814
98 61765 -2.77 279088 3672 -908
99 63524 -1.56 403473 -7307 -26027
100 64529 0.23 388193 -6985 -36055
101 64378 2.89 1060835 787 163109
2021년 7월 25일 오후 3시경을 기준으로 종가, 등락률, 거래량, 기관, 외국인의 순매매량을 잘 불러온 것을 확인할 수 있다.
설명
days = 100
yesterday = int((date.today() - timedelta(days=1)).strftime("%Y%m%d"))
firstday = int((date.today() - timedelta(days=(days + 1))).strftime("%Y%m%d"))
...
data7254 = None
data7254 = pd.DataFrame(columns=('종가', '등락률', '거래량', '기관계', '외국인'))
어제부터 100일 이전까지의 데이터를 불러오며, 데이터를 기록할 빈 pandas
데이터 프레임을 만들었다.
for j in range((days // 17) + 1):
time.sleep(0.1)
stock.BlockRequest()
foreigner.BlockRequest()
firm.BlockRequest()
numData = stock.GetHeaderValue(1)
for i in range(numData):
oneday = {}
...
if stock.Continue != True:
break
특이한 바깥 반복문에 대해 설명할 필요가 있겠다. 이유는 알 수 없지만 CpSysDib.CpSvr7254
를 디스패치한 객체는 지정일자가 몇일이든 최대 17일까지만 조회가 되며, 데이터 요청을 새로 할때마다 퓨어 파이썬의 이터레이터처럼 다음 데이터를 가져오게 된다.
range((days // 17) + 1)
를 통해 바깥 반복문은 전체 일자를 17로 나눈 몫에 1만큼만 더 돌고, 이렇게 돌 때마다BlockRequest()
로 다음 17일치 데이터를 가져온다. 이에 따르면 데이터의 길이는 항상 17이겠지만, 끝부분에서는 그렇지 않을 수 있기 때문에 정확히numData = stock.GetHeaderValue(1)
를 받아 일별 데이터의 갯수를 조회한다.stock.Continue
: 바운드 에러를 회피하기 위한 프로퍼티로, 데이터가 더 남았으면 참이고 마지막이면 거짓이다. 사실 위 코드는 이중for
문으로 정확하게 계산되어서 에러가 날 일이 없지만,while True
등을 사용한다면 이러한 체크가 필요하다.
이 과정을 공식 도움말에선 ‘연속 처리’라 부르고 있으니 그렇게 알아두도록 하자.
for i in range(numData):
oneday = {}
oneday['종가'] = stock.GetDataValue(14, i)
oneday['등락률'] = stock.GetDataValue(16, i)
oneday['거래량'] = stock.GetDataValue(17, i)
oneday['기관계'] = firm.GetDataValue(5, i) - firm.GetDataValue(1, i)
oneday['외국인'] = foreigner.GetDataValue(5, i) - foreigner.GetDataValue(1, i)
data7254.loc[len(data7254)] = oneday
안쪽 반복문은 위와 같다. 매번 oneday
라는 빈 딕셔너리를 만들어 값을 받아주고 마지막에 data7254.loc[len(data7254)] = oneday
를 통해 데이터프레임의 마지막 자리에 하나씩 넣어주고 있다.
object.GetDataValue
는 특정 투자자냐 전체 데이터를 받아오냐에 따라 다르게 사용된다. stock
은 전체 데이터를 받아왔고, firm
과 foreigner
는 각각 기관과 외국인의 데이터를 받아왔으므로 똑같아보이는 메소드임에도 용법이 다르다.
- 전체데이터
stock
- 14: 종가
- 16: 등락률
- 17: 거래량
- 개별데이터
firm
,foreigner
- 5: 매수수량
- 1: 매도수량
보다시피 매매량을 구하려면 매수수량에서 매도수량을 빼는 계산이 필요하다.
전체코드
from datetime import date, timedelta
import numpy as np
import time
import pandas as pd
days = 100
yesterday = int((date.today() - timedelta(days=1)).strftime("%Y%m%d"))
firstday = int((date.today() - timedelta(days=(days + 1))).strftime("%Y%m%d"))
import win32com.client
instCpCybos = win32com.client.Dispatch("CpUtil.CpCybos")
if instCpCybos.IsConnect:
print("Cybos Plus Connected...")
data7254 = None
data7254 = pd.DataFrame(columns=('종가', '등락률', '거래량', '기관계', '외국인'))
instCpStockCode = win32com.client.Dispatch("CpUtil.CpStockCode")
seegene = instCpStockCode.NameToCode("씨젠")
stock = win32com.client.Dispatch("CpSysDib.CpSvr7254")
stock.SetInputValue(0, seegene)
stock.SetInputValue(1, 6) # 기간선택구분 일별
stock.SetInputValue(2, firstday) # 시작일자
stock.SetInputValue(3, yesterday) # 끝일자
stock.SetInputValue(4, 0) # 매매비중구분 - 순매수
stock.SetInputValue(5, 0) # 투자자 전체
foreigner = win32com.client.Dispatch("CpSysDib.CpSvr7254")
foreigner.SetInputValue(0, seegene)
foreigner.SetInputValue(1, 6) # 기간선택구분 일별
foreigner.SetInputValue(2, firstday) # 시작일자
foreigner.SetInputValue(3, yesterday) # 끝일자
foreigner.SetInputValue(4, 0) # 매매비중구분 - 순매수
foreigner.SetInputValue(5, 2) # 투자자 외국인
firm = win32com.client.Dispatch("CpSysDib.CpSvr7254")
firm.SetInputValue(0, seegene)
firm.SetInputValue(1, 6) # 기간선택구분 일별
firm.SetInputValue(2, firstday) # 시작일자
firm.SetInputValue(3, yesterday) # 끝일자
firm.SetInputValue(4, 0) # 매매비중구분 - 순매수
firm.SetInputValue(5, 3) # 투자자 기관계
for j in range((days // 17) + 1):
time.sleep(0.1)
stock.BlockRequest()
foreigner.BlockRequest()
firm.BlockRequest()
numData = stock.GetHeaderValue(1)
for i in range(numData):
oneday = {}
oneday['종가'] = stock.GetDataValue(14, i)
oneday['등락률'] = stock.GetDataValue(16, i)
oneday['거래량'] = stock.GetDataValue(17, i)
oneday['기관계'] = firm.GetDataValue(5, i) - firm.GetDataValue(1, i)
oneday['외국인'] = foreigner.GetDataValue(5, i) - foreigner.GetDataValue(1, i)
data7254.loc[len(data7254)] = oneday
if stock.Continue != True:
break