파이썬과 엑셀 xlwings 패키지를 활용해 퀀트투자를 위한 종목선정 툴을 만들었습니다.
mokeya.tistory.com/67?category=914399
이 작업은 크게 네 가지 과업으로 이루어지는데,
이 포스팅은 그 첫 번째 단계에 대한 내용을 담고 있습니다.
(아래 목차 클릭 시 해당 포스팅으로)
1. 대신증권API로 주식시장 전종목에 대한 정보 추출(현재 글)
2. Company Guide(Fn Guide) 웹을 크롤링해 전종목에 대한 재무정보 추출
3. 1과 2의 결과물을 종목코드를 기준으로 합친 후 투자지표 필드 추가
4. 3의 결과물을 가지고 xlwings 패키지 활용하여 엑셀툴 제작
코딩의 결과
결과물은 다음과 같은 정보를 가지고 있습니다.
아래 정보는 MarketEye를 통해 가져올 수 있는 정보 중 일부에 해당하는 것이므로,
Cybos의 도움말 페이지에서 API명세서를 살펴보시고 필요한 정보를 더 추가해보셔도 좋을 것 같습니다.
또한 일부 컬럼은 API로 받아온 값을 그대로 사용하지 않고 제가 가공한 것입니다.
가령 종목코드 앞에 붙어 있는 'A-'를 제거한다든가,
시가총액을 종목 현재가 기준으로 계산한다든가,
백분율 지표의 형태를 소수점 둘째 자리로 통일시킨 것 등입니다.
컬럼명 | 설명 혹은 값 예시 |
종목구분 | 1 (1은 주권을 의미. 투자회사, 리츠, ETF 등을 의미하는 0~17까지의 구분 코드가 존재) |
종목코드 | A005930 |
현재가 | 84,800 |
종목명 | 삼성전자 |
상장주식수 | 5,969,782,000 |
외국인보유비율(%) | 54.73% |
52주최고가 | 96,800 |
52주최저가 | 45,350 |
배당수익률(%) | 3.53% |
부채비율(%) | 37.07% |
자기자본이익률(%) | (ROE, Return On Equity) 9.99% |
매출증가율(%) | 2.78% |
순이익증가율(%) | 21.48% |
경상이익 | 36,345,117,000,000 |
분기매출액증가율(%) | 2.78% |
분기영업이익액증가율(%) | 29.62% |
분기순이익증가율(%) | 21.48% |
분기년월 | 202012 |
시가총액 | (현재 주가를 기준으로 계산된 시총) 506,237,513,600,000 |
정제코드 | (기존 종목코드 앞에 붙은 "A"를 제거한 코드) 005930 |
작업환경
1. 파이썬3.7(32bit) - 대신증권API는 64bit로 사용 불가
2. 파이썬IDE는 JetBrain의 Pycharm - 관리자 권한으로 실행
3. 대신증권 계좌를 보유하고 있어야 하고, CYOBS Plus(대신증권 API 서비스) ID 등록 필요
4. 코드를 정상 실행(RUN)하기 위해서는 CYBOS Plus 클라이언트가 (관리자 권한으로) 실행 중이어야 함
코드
기본적으로 API와 여러 클래스에 대한 명세서는 CybosPlus 도움말 페이지에서 확인할 수 있습니다.
이 중 퀀트 종목 선정 프로그램에서 주로 활용하게 되는 클래스는
'MarketEye' 클래스이고, 이 클래스는 여러 종목에 대한 각종 정보를 구하는 데 사용합니다.
COM은 Component object model의 약어로,
특정 프로그래밍 언어로 개발된 유용한 객체를 그 외 다른 언어로 사용할 수 있게 해줍니다.
이번 파이썬 코드에서도, 다른 프로그래밍 언어로 작성된 COM 객체를 생성하기 위해
win32com.client 모듈을 사용합니다.
# COM(Component Object Model)을 비롯, 필요한 모듈 불러오기
import win32com.client
import win32com
import time
필요한 정보의 종류(m_InfoList)와
정보 추출 대상 종목(m_CodeList)을 받아 값을 반환하는 함수(subMarketEye)를 작성합니다.
각 정보가 하나의 열(column)을, 종목 하나가 하나의 행(row)를 차지하는 테이블을 그려내는 함수입니다.
def subMarketEye(m_InfoList, m_CodeList):
## 대신 api 세팅
instMarketEye = win32com.client.Dispatch("cpsysdib.MarketEye")
instMarketEye.SetInputValue(0, m_InfoList) # SetInputValue(type, value) - type=0은 필드(재무정보) 혹은 필드 배열을 의미
instMarketEye.SetInputValue(1,
m_CodeList) # SetInputValue(type, value) - type=1은 종목코드 혹은 종목코드 배열을 의미. 최대 200개 종목까지 가능
instMarketEye.BlockRequest()
numField = instMarketEye.GetHeaderValue(0) # GetHeaderValue(type) - type=0은 필드 개수; 1은 필드명의 배열; 2는 종목 개수
numData = instMarketEye.GetHeaderValue(2)
data = []
for ixRow in range(numData):
tempdata = [instCpCodeMgr.GetStockSectionKind(m_CodeList[ixRow])]
for ixCol in range(numField):
# GetDataVale(type, index) - type은 요청한 필드의 인덱스, index는 요청한 종목의 인덱스
# 주당 가격이 큰 종목의 경우 천 단위로 표현이 되기 때문에 1,000을 곱해줌
if instCpCodeMgr.IsBigListingStock(instMarketEye.GetDataValue(0, ixRow)) and ixCol == 3:
tempdata.append(instMarketEye.GetDataValue(ixCol, ixRow) * 1000)
else :
tempdata.append(instMarketEye.GetDataValue(ixCol, ixRow))
data.append(tempdata)
return data
최종 결과물에 담을 정보의 종류(컬럼)를 지정하고,
코스피와 코스닥에 상장된 전 종목의 코드를 지정하여
최종 결과물을 .csv로 출력합니다.
이 때 주의할 점은 CybosPlus에서는 한 번에 요청할 수 있는 정보의 양을 한정해두었기 때문에,
for loop 구문을 통해 한 번에 200개 종목씩 끊어서 요청해야 한다는 것입니다.
그리고 몇몇 컬럼들은 형변환을 통하여 소수점 둘째자리의 백분율로 표시가 되도록 코드를 추가했습니다.
from pandas import DataFrame
if __name__ == "__main__":
m_InfoList = [0, 4, 17, 20, 21, 63, 64, 74, 75, 77
, 78, 80, 87, 97, 98, 99, 100, 111] # 요청 필드 - 이 부분을 수정해야 함
codeList = instCpCodeMgr.GetStockListByMarket(1) # 시장구분(CPE_MARKET_KIND)에 따른 주식종목배열을 반환
codeList2 = instCpCodeMgr.GetStockListByMarket(2) # CPE_MARKET_KIND=0은 구분없음, 1은 코스피, 2는 코스닥, 3은 프리보드, 4는 KRX
m_CodeList = codeList + codeList2
data = []
rqCodeList = []
# 한 번에 요청 가능한 양 내에서 끊어서 반복 요청
for i, code in enumerate(m_CodeList):
rqCodeList.append(code)
if len(rqCodeList) == 200:
data = data + subMarketEye(m_InfoList, rqCodeList)
rqCodeList = []
continue
if len(rqCodeList) > 0:
data = data + subMarketEye(m_InfoList, rqCodeList)
dfMarketEye = DataFrame(data, columns=['종목구분', '종목코드', '현재가', '종목명', '상장주식수', '외국인보유비율(%)', '52주최고가', '52주최저가', '배당수익률(%)', '부채비율(%)', '자기자본이익률(%)'
, '매출증가율(%)', '순이익증가율(%)', '경상이익', '분기매출액증가율(%)', '분기영업이익액증가율(%)', '분기경상이익증가율(%)', '분기순이익증가율(%)', '분기년월'])
# 시가총액 계산하여 컬럼 추가하기
dfMarketEye['시가총액'] = dfMarketEye['현재가'] * dfMarketEye['상장주식수']
# 종목코드에서 'A' 빼기
dfMarketEye['정제코드'] = dfMarketEye['종목코드'].str.extract('(\d+)')
# 백분율 지표 소수점 둘째 자리의 퍼센티지로 표현하기
dfMarketEye['외국인보유비율(%)'] = dfMarketEye['외국인보유비율(%)'].apply('{0:.2f}%'.format)
dfMarketEye['배당수익률(%)'] = dfMarketEye['배당수익률(%)'].apply('{0:.2f}%'.format)
dfMarketEye['부채비율(%)'] = dfMarketEye['부채비율(%)'].apply('{0:.2f}%'.format)
dfMarketEye['자기자본이익률(%)'] = dfMarketEye['자기자본이익률(%)'].apply('{0:.2f}%'.format)
dfMarketEye['매출증가율(%)'] = dfMarketEye['매출증가율(%)'].apply('{0:.2f}%'.format)
dfMarketEye['순이익증가율(%)'] = dfMarketEye['순이익증가율(%)'].apply('{0:.2f}%'.format)
dfMarketEye['분기매출액증가율(%)'] = dfMarketEye['분기매출액증가율(%)'].apply('{0:.2f}%'.format)
dfMarketEye['분기영업이익액증가율(%)'] = dfMarketEye['분기영업이익액증가율(%)'].apply('{0:.2f}%'.format)
dfMarketEye['분기경상이익증가율(%)'] = dfMarketEye['분기경상이익증가율(%)'].apply('{0:.2f}%'.format)
dfMarketEye['분기순이익증가율(%)'] = dfMarketEye['분기순이익증가율(%)'].apply('{0:.2f}%'.format)
# 스팩(SPAC) 종목 제외
# dfMarketEye = dfMarketEye[~dfMarketEye['종목명'].str.contains('스팩')]
# '분기년월' 정보가 없는 종목 제외
# dfMarketEye = dfMarketEye[dfMarketEye['분기년월']!= ""]
# 결과물 출력
print(dfMarketEye)
dfMarketEye.to_csv('subMarketEye.csv', encoding="cp949")
다음 포스팅에서는 대신증권API로는 커버하지 못 하는 투자지표를 보강하기 위하여
FnGuide의 지표를 가져오는 코드를 작성해보겠습니다.
'Programming > Quant' 카테고리의 다른 글
[미국주식] 퀀트투자를 위한 종목별 재무정보 및 투자지표 무료 데이터_21년11월29일 마감 기준 (0) | 2021.11.30 |
---|---|
[국내주식] 퀀트투자를 위한 종목별 재무정보 및 투자지표 무료 데이터_21년11월26일 마감 기준 (0) | 2021.11.28 |
[퀀트투자를 위한 툴 만들기 3] 대신증권API로 추출한 종목 정보와 Company Guide(Fn Guide)에서 추출한 재무 정보 합치기(Merging) (2) | 2021.08.04 |
[퀀트투자를 위한 툴 만들기 2] Company Guide(Fn Guide)에서 종목 재무정보 추출 (5) | 2021.05.19 |
[퀀트투자를 위한 툴 만들기 0] 파이썬과 엑셀을 활용한 종목 선정 프로그램 기획 (4) | 2021.01.09 |
댓글