투자/python과 주식

KRX 정보데이터시스템에서 자료 가지고 오기 (csv 파일 다운로드)

된다잘된다 2024. 7. 16. 18:10

참고: Henry's Quant University https://www.youtube.com/watch?v=HloktbVPGVA&list=PLkREQFGfPOZ3g1aWNVEHoJRaUWOga10pw&index=16

 

HTS에 없는 주식시장의 데이터들을 모아서 보고 싶은 경우들이 있다.

예를 들어, KRX 데이터 시스템에서 POSCO홀딩스의 공매도 거래대금과 수량의 추이를 알고 싶다고 하자.

이 정보는 통계 >  공매도 통계 > 공매도 거래 > 개별종목 공매도 거래 에서 POSCO홀딩스를 검색하면 자료가 나온다. 

 

 

이 자료를 화면으로만 보기엔 좀 불편하기 때문에 보통 Excel로 다운받아서 차트를 그려본다거나 하면서 분석할 것이다.

이것을 매번 이 사이트에 들어가서 다운받아서 보기도 그렇고.. 해서 자동화 해보았다.

 

위의 화면까지 들어갔으면, 오른쪽 부분에 다운로드를 표시하는 아이콘이 있고 이것을 클릭하면 파일형식을 물어본다.

 

python에서 읽어들이려면 csv 형식이 편하다. (물론 excel형식도 읽을 수 있다)

 

이 CSV를 클릭하기 전에 웹브라우저에서 개발자모드(F12)를 눌러서 network 탭을 선택하고 다운로드를 받아보자.

 

그러면 두가지 과정을 거쳐서 다운로드를 받게되는데 하나는 generate.cmd, download.cmd이다.

 

generate.cmd는 OTP code를 생성하는 명령이고, download.cmd는 실제 파일을 받는 명령이라는 것을 인식하고 천천히 살펴보자.

 

generate.cmd를 클릭하면, 인터넷 상에서 주고 받은 내용들을 볼 수 있다. 

여기서 잘 봐야 할 것은, Header탭에서 Request URL, Request Headers의 일부, 그리고 Payload 탭이다.

이 내용을 가지고 code로 구현해보자. 먼저 OPT code를 구한다.

 

OPT code를 구했으면 다운로드는 어떻게 동작하는지 download.cmd를 클릭해서 보자.

 

 

거의 비슷하게 Request URL, Request Header를 만들어주고, payload에 위에서 구한 OTP code를 전달하면 된다.

 

여기서 주의할 사항은 read_csv()에서 encoding을 EUC-KR로 해주어야 한다는 것이다.

그리고 아마도 header부분은 위에서 사용한 header를 그대로 사용해도 별 문제가 없을 것이다.

 

우리가 공매도 잔고의 추이를 보고 싶은 것이므로, 한번 그려보자.

 

또한, 여기서 이 데이터를 csv로 저장하고자 하면, to_csv()함수를 사용하면 된다. (여기서도 encoding에 유의하자)

 

 

 

참고하시라고 코드 전문도 붙여둔다.

import requests as rq
from io import BytesIO
import pandas as pd

bizDate = '20240716'
trdDt = str(int(bizDate)-1)
stDt = str(int(bizDate)-10002)
## data.krx.co.kr 통게 > 공매도 통계 > 공매도 거래 > 개별종목 공매도 거래 > 개별추이 선택 > 종목명 검색
site = 'http://data.krx.co.kr/contents/MDC/MDI/mdiLoader/index.cmd?menuId=MDC0201020201'        
## 그런데 막상 F12로 개발자모드를 켜고, network 탭에서 살펴보면 아래 주소에 요청을 해서 다운 받는다. 
otp_url= 'http://data.krx.co.kr/comm/fileDn/GenerateOTP/generate.cmd'
otp_payload = {
    'locale': 'ko_KR',
    'searchType': '2',    
    'mktId': 'STK',
    'secugrpId': 'BC',
    'inqCond': 'STMFRTSCIFDRFSSRSWBC',
    'trdDd': trdDt,
    'tboxisuCd_finder_srtisu1_16': '005490/POSCO홀딩스',
    'isuCd': 'KR7005490008',
    'isuCd2': '005490',
    'codeNmisuCd_finder_srtisu1_16': 'POSCO홀딩스',
    'param1isuCd_finder_srtisu1_16': '',
    'strtDd': stDt,
    'endDd': bizDate,
    'share': '1',
    'money': '1',
    'csvxls_isNo': 'false',
    'name': 'fileDown',
    'url': 'dbms/MDC/STAT/srt/MDCSTAT30102'
}
headers = {
    'Connection': 'keep-alive',
    'Content-Length': '411',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Cookie': '__smVisitorID=mU4_xsAGIdc; JSESSIONID=g2RxWashB4zdjNt4slyF8hIQTaLNv6aAOwLAkZwAOdBUwaS6zRxPpblFJuirnjh1.bWRjX2RvbWFpbi9tZGNvd2FwMS1tZGNhcHAxMQ==',
    'Host': 'data.krx.co.kr',
    'Origin': 'http://data.krx.co.kr',
    'Referer': 'http://data.krx.co.kr/contents/MDC/MDI/mdiLoader/index.cmd?menuId=MDC0201020201',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
}

otp_code = rq.post(otp_url, otp_payload, headers=headers).text

short_url = 'http://data.krx.co.kr/comm/fileDn/download_csv/download.cmd'
short_payload = {'code': otp_code}
headers = {
    'Connection': 'keep-alive',
    'Content-Length': '731',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Cookie': '__smVisitorID=mU4_xsAGIdc; JSESSIONID=g2RxWashB4zdjNt4slyF8hIQTaLNv6aAOwLAkZwAOdBUwaS6zRxPpblFJuirnjh1.bWRjX2RvbWFpbi9tZGNvd2FwMS1tZGNhcHAxMQ==',
    'Host': 'data.krx.co.kr',
    'Origin': 'http://data.krx.co.kr',
    'Referer': 'http://data.krx.co.kr/contents/MDC/MDI/mdiLoader/index.cmd?menuId=MDC0201020201',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
}

short_data = rq.post(short_url, short_payload, headers= headers)
short_df = pd.read_csv(BytesIO(short_data.content), encoding='EUC-KR')
print(short_df.head())

import matplotlib.pyplot as plt
from matplotlib import font_manager

font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()
plt.rc('font', family= font_name)
short_df.plot(x='일자', y='금액_공매도거래대금_전체', color='r')

short_df.to_csv('./short_posco.csv', header=True, index=True, sep=',', encoding='EUC-KR')