logo

CYBOS Plus로 종목 주가 불러오는 법 CpSysDib.StockChart 📂데이터확보

CYBOS Plus로 종목 주가 불러오는 법 CpSysDib.StockChart

가이드 1

CpSysDib.StockChart는 주식, 업종, ELW의 차트데이터를 수신한다. API를 사용하는 것에 익숙하지 않다면 이 체계를 이해하기가 대단히 어려울 수 있다. 주식회사 씨젠의 주가를 불러오는 파이썬 예제를 실행해보고 그 작동방식을 파악해보자.

  • SetInputValue(): 어떤 데이터를 원하는지를 구체적으로 지정한다.
  • BlockRequest(): 지정된 데이터 수신을 요청한다.
  • GetHeaderValue(): 수신된 헤드 데이터를 리턴한다.
  • GetDataValue(): 수신된 데이터를 리턴한다.

이렇게 기괴한 함수들을 이상하게 사용하는 이유는 CYBOS Plus가 딱히 파이썬 라이브러리가 아니기 때문이다. 설명에서 더 자세히 다루겠다.

하이라이트

>>> days = 10
>>> instStockChart = win32com.client.Dispatch("CpSysDib.StockChart")
>>> instStockChart.SetInputValue(0, seegene)
>>> instStockChart.SetInputValue(1, ord('2'))
>>> instStockChart.SetInputValue(4, days)
>>> instStockChart.SetInputValue(5, 5)
>>> instStockChart.SetInputValue(6, ord('D'))
>>> instStockChart.SetInputValue(9, ord('1'))
>>> instStockChart.BlockRequest()
0
>>> numData = instStockChart.GetHeaderValue(3)
>>> for i in range(numData):
...     print(instStockChart.GetDataValue(0, i), end = ', ')
...
80700, 80100, 77400, 77200, 82600, 85800, 83800, 88000, 88000, 90500, >>>

20210721_100212.png

2021년 7월 21일 오전 10시경을 기준으로 주가데이터를 잘 불러온 것을 확인할 수 있다.

설명

instStockChart = win32com.client.Dispatch("CpSysDib.StockChart")
instStockChart.SetInputValue(0, 'A096530')

앞서 언급했듯 CYBOS Plus는 딱히 파이썬을 위해서만 개발되지 않았다. Windows 시스템 COM Object 라이브러리를 사용할 수 있는 개발 환경이라면 어디서든 사용할 수 있고, 비주얼 스튜디오나 파이썬, MS 오피스 등에서도 사용된다. 오브젝트 instStockChartwin32com.client.Dispatch()를 통해 CpSysDib.StockChart를 불러와 만들어졌지만, 그 내부가 딱히 파이써닉pythonic해야할 이유가 하등 없다. 따라서 퓨어 파이썬pure Python과 다른 인터페이스interface를 사용하게 되는 것이다.

object.SetInputValue(0, code)object 의 종목을 code 로 지정해주는데, 사실 파이썬스러운 문법으로 상상해보면 instStockChart.code = 'A096530' 와 같이 instStockChart의 프로퍼티propertycode 에 직접 접근해서 값을 주는 게 자연스럽지만, 파이썬이 아니기 때문에 CYBOS Plus의 방식을 따르게 되는 것이다.

다음은 데이터를 기간으로 요청할지, 갯수로 요청할지에 대한 지정이다.

  • 1 - 요청구분(char)
    • ‘1’: 기간으로 요청
    • ‘2’: 갯수로 요청
instStockChart.SetInputValue(1, ord('2'))

그런데 지정하는 방식이 조금 이상하다. 그냥 2가 아니라 ord() 함수로 감싼 ord('2') 를 넘겨주고 있다. ord() 는 유니코드 문자를 나타내는 문자열을 정수인 유니코드 포인트로 리턴하는 함수로, 구체적으로 ord('2') 는 정수 50을 리턴한다. 위와 같이 문자열 '2' 를 그대로 넘기는 게 아니라 굳이 유니코드로 넘겨야 하는 것도 앞에서 설명한 이유와 맥락을 함께한다.

그런데 다음은 어떤 값을 요청할지에 대한 지정이다.

  • 5 - 필드(long array)
    • 5: 종가
    • 8: 거래량
    • 20: 기관순매수
instStockChart.SetInputValue(5, 5)

이는 씨젠의 종가 데이터를 받아오겠다는 말이다. 이러한 필드의 종류는 0번부터 37번까지로 총 38가지가 있고, 각자의 상세한 용법은 공식 도움말을 참조하자. 그런데 이 입력데이터에서처럼 정수를 사용하지 않는 것도 아닌데 왜 요청구분(1)은 굳이 캐릭터를 받는지, 받는건 둘째 치더라도 헷갈리게 ‘1’과 ‘2’인 이유가 무엇인지는 알 수 없다. 그러려니 하고 넘어가야한다.

이제 종합적으로 위 코드가 어떤 데이터를 요구하는지에 대해 알아보자.

days = 10
instStockChart = win32com.client.Dispatch("CpSysDib.StockChart")
instStockChart.SetInputValue(0, seegene)
instStockChart.SetInputValue(1, ord('2'))
instStockChart.SetInputValue(4, days)
instStockChart.SetInputValue(5, 5)
instStockChart.SetInputValue(6, ord('D'))
instStockChart.SetInputValue(9, ord('1'))

위에서부터 다음과 같다.

  • 0 - 종목코드
    • 씨젠 (A096530)
  • 1 - 요청구분
    • ‘2’: 개수
  • 4 - 요청개수
    • days (10). 열흘간의 데이터를 요청할 것이다.
  • 5 - 필드
    • 5: 종가. 장을 마감할 때의 가격이다.
  • 6 - 차트구분
    • ‘D’: 일간 데이터
  • 9 - 수정주가
    • ‘1’: 수정주가. 증자, 액분 등 어떤 사유에서든 주가의 단위가 바뀌었더라도 현재 가격에 맞는 비율로 주가를 수정해주는지에 대한 여부다. 씨젠은 21년 전반기에 무상증자를 한 바 있으니 수정주가로 요청하는 것이 바람직할 것이다.

이에 따라 instStockChart 오브젝트는 데이터를 요청했을 때 ‘씨젠의 일일 종가를 수정주가로 최근 10일치만큼’ 받아온다. 이 오브젝트의 프로퍼티를 세팅해준것과 마찬가지다.

instStockChart.BlockRequest()

이제 object.BlockRequest() 메소드를 실행시키면 지정한대로의 데이터를 받아온다. 사실 이런 부분을 보면 사고방식 자체는 파이썬다운것을 알 수 있다.

numData = instStockChart.GetHeaderValue(3)
for i in range(numData):
    print(instStockChart.GetDataValue(0, i), end = ', ')

GetHeaderValue(): 수신된 헤더 데이터를 리턴한다. 데이터와의 차이는 약간 메타데이터인지 아닌지 정도인 것 같은데, 모듈마다도 조금씩 다르니 직접 공식 도움말을 보고 이해하는 게 빠를 것이다.

  • 3: 받아온 데이터의 갯수를 요청한다. 이 예제에선 애초에 10일치를 요청했으니 numData 는 정확히 10일 것이다. 기간으로 요청할 경우 거래일 기준으로 받아오기 때문에 이 값이 얼마든지 달라질 수 있다.

GetDataValue(Type,index): 수신된 데이터를 리턴한다.

  • Type 번째로 요청한 타입의 index 번째 값을 리턴한다. 이 예제에선 종가 하나만을 요청했으니 0번째 타입인 종가의 i번째 값을 리턴하는 게 될 것이다.

전체 코드

import win32com.client
instCpCybos = win32com.client.Dispatch("CpUtil.CpCybos")
if instCpCybos.IsConnect:
    print("Cybos Plus Connected...")

instCpStockCode = win32com.client.Dispatch("CpUtil.CpStockCode")
seegene = instCpStockCode.NameToCode("씨젠")

days = 10
instStockChart = win32com.client.Dispatch("CpSysDib.StockChart")
instStockChart.SetInputValue(0, seegene)
instStockChart.SetInputValue(1, ord('2'))
instStockChart.SetInputValue(4, days)
instStockChart.SetInputValue(5, 5)
instStockChart.SetInputValue(6, ord('D'))
instStockChart.SetInputValue(9, ord('1'))

instStockChart.BlockRequest()
numData = instStockChart.GetHeaderValue(3)
for i in range(numData):
    print(instStockChart.GetDataValue(0, i), end = ', ')