logo

CYBOS Plus로 기관, 외국인 매매량 불러오는 법 📂데이터확보

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

20210725151736274

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

20210725153928000

특이한 바깥 반복문에 대해 설명할 필요가 있겠다. 이유는 알 수 없지만 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 은 전체 데이터를 받아왔고, firmforeigner 는 각각 기관과 외국인의 데이터를 받아왔으므로 똑같아보이는 메소드임에도 용법이 다르다.

  • 전체데이터 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