sharebook-kr / pykrx

KRX 주식 정보 스크래핑
693 stars 240 forks source link

일자별 공매도 잔고를 확인하는 get_shorting_status_by_date 함수에 이슈가 있습니다. #37

Closed woongbinni closed 3 years ago

woongbinni commented 3 years ago

README에 따르면 (T+2)일자의 정보를 제공한다 하였으니 2영업일전일의 공매도 정보는 수집이 가능한걸로 이해하였는데요. 금일 테스트 도중 2영업일전의 공매도 잔고를 잘 가져오다가 자정 12시를 지난 시점부터 empty_dataframe이 나옵니다.

# 테스트한 시각 1/9 01:20
df = stock.get_shorting_status_by_date("20210106", "20210106", '005930')
print(df)

# 결과 : 
Empty DataFrame
Columns: [공매도, 잔고, 공매도금액, 잔고금액]
Index: []

3영업일 전으로 설정하면 값이 나옵니다.

# 테스트한 시각 1/9 01:20
df = stock.get_shorting_status_by_date("20210105", "20210105", '005930')
print(df)

# 결과 : 
            공매도       잔고     공매도금액          잔고금액
날짜                                              
2021-01-05  169  2676924  14011100  224593923600

자정을 넘어가는 시점에 오류가 발생할만한 코너케이스가 있는건지, 아니면 제가 사용법을 이해를 잘못 이해한 것인지 확인 부탁드립니다.

woongbinni commented 3 years ago

내부 소스를 훓어봤는데 https://github.com/sharebook-kr/pykrx/blob/master/pykrx/website/krx/market/wrap.py 해당 파일에서 date_offset을 계산해주는 부분에서 코너케이스가 있는 것 같습니다.

import datetime
today = datetime.datetime.now()
# - today.isocalendar()[2] : 월(1)/화(2)/수(3)/목(4)/금(5)/토(6)/일(7) 반환
# - base에는 최근 영업일이 저장
base = today - datetime.timedelta(max(today.isocalendar()[2] - 5, 0))
elapsedTime = base - datetime.datetime.strptime("20210106" + "0900",
                                                '%Y%m%d%H%M')
day_offset = 2 - min(int(elapsedTime.total_seconds() / 3600 / 24), 2)
print(day_offset) 

이 결과가 1이 나와서 빈값이 있는 dataframe의 첫줄이 들어가는게 아닌가 싶습니다.

mr-yoo commented 3 years ago

최근 KRX 웹사이트가 완전히 변경돼서 공매도 기능을 새롭게 연결하고 있습니다. 다른 기능도 다음 주에는 정상 동작 할 것으로 예상 됩니다. 모듈의 업데이트 또한 다음 주에 진행될 예정입니다.

우선 언급하신 이슈를 해결하기 위해 https://github.com/sharebook-kr/pykrx/commit/a625df992f39b814c6c636b69acb5bd72172ffd2#diff-c9f53bcefd27f65047161295dafac4fbe5778048b2d1e4f2e16789f45d4f8aa6 에서 복잡만 차지하는 시간 연산을 제거하고, 데이터에 따라 슬라이싱 해서 최근 데이터를 제거하도록 수정했습니다.


웹 서버는 집계되지 않은 최근 데이터에는 -로 표기합니다. image

서버에서 전송된 최근 영업일의 데이터에서 -가 하나라도 있는 행의 개수를 카운팅 해서 슬라이싱으로 제거합니다.

idx = (df.iloc[:2] == '-').any(axis=1).sum()
df = df.iloc[idx:]
mr-yoo commented 3 years ago

@woongbinni 모든 내용을 반영해서 모듈 업데이트 했습니다. 이슈가 몰려서 수정에 시간이 다소 오래걸렸네요.

모듈 업데이트 하시면 최신 기능을 모두 사용하실 수 있습니다.