initial commit

This commit is contained in:
2026-02-04 00:16:34 +09:00
commit ae11528dd9
867 changed files with 209640 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
"""
Created on 2025-06-18
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from compare_stocks import compare_stocks
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 비교대상종목조회[국내주식-183]
##############################################################################################
COLUMN_MAPPING = {
'elw_shrn_iscd': 'ELW단축종목코드',
'elw_kor_isnm': 'ELW한글종목명'
}
NUMERIC_COLUMNS = []
def main():
"""
[국내주식] ELW시세
ELW 비교대상종목조회[국내주식-183]
ELW 비교대상종목조회 테스트 함수
Parameters:
- fid_cond_scr_div_code (str): 조건화면분류코드 (11517(Primary key))
- fid_input_iscd (str): 입력종목코드 (종목코드(ex)005930(삼성전자)))
Returns:
- DataFrame: ELW 비교대상종목조회 결과
Example:
>>> df = compare_stocks(fid_cond_scr_div_code="11517", fid_input_iscd="005930")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# 인라인 코드로 파라미터 직접 전달
logger.info("API 호출 ")
result = compare_stocks(fid_cond_scr_div_code="11517", fid_input_iscd="005930")
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 결과 출력
logger.info("=== ELW 비교대상종목조회 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,111 @@
"""
Created on 2025-06-18
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 비교대상종목조회[국내주식-183]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/quotations/compare-stocks"
def compare_stocks(
fid_cond_scr_div_code: str, # 조건화면분류코드
fid_input_iscd: str, # 입력종목코드
tr_cont: str = "", # 연속 거래 여부
dataframe: Optional[pd.DataFrame] = None, # 누적 데이터프레임
depth: int = 0, # 현재 재귀 깊이
max_depth: int = 10 # 최대 재귀 깊이
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 비교대상종목조회[국내주식-183]
ELW 비교대상종목조회 API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_scr_div_code (str): 조건화면분류코드 (예: '11517')
fid_input_iscd (str): 입력종목코드 (예: '005930')
tr_cont (str): 연속 거래 여부 (기본값: "")
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임 (기본값: None)
depth (int): 현재 재귀 깊이 (기본값: 0)
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 비교대상종목조회 데이터
Example:
>>> df = compare_stocks('11517', '005930')
>>> print(df)
"""
# 필수 파라미터 검증
if not fid_cond_scr_div_code:
logger.error("fid_cond_scr_div_code is required. (e.g. '11517')")
raise ValueError("fid_cond_scr_div_code is required. (e.g. '11517')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. '005930')")
raise ValueError("fid_input_iscd is required. (e.g. '005930')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
tr_id = "FHKEW151701C0"
params = {
"FID_COND_SCR_DIV_CODE": fid_cond_scr_div_code,
"FID_INPUT_ISCD": fid_input_iscd,
}
# API 호출
res = ka._url_fetch(API_URL, tr_id, tr_cont, params)
if res.isOK():
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
# 데이터프레임 병합
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
# 연속 거래 여부 확인
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return compare_stocks(
fid_cond_scr_div_code,
fid_input_iscd,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()

View File

@@ -0,0 +1,251 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-19
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from cond_search import cond_search
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 종목검색[국내주식-166]
##############################################################################################
COLUMN_MAPPING = {
'bond_shrn_iscd': '채권단축종목코드',
'hts_kor_isnm': 'HTS한글종목명',
'rght_type_name': '권리유형명',
'elw_prpr': 'ELW현재가',
'prdy_vrss': '전일대비',
'prdy_vrss_sign': '전일대비부호',
'prdy_ctrt': '전일대비율',
'acml_vol': '누적거래량',
'acpr': '행사가',
'stck_cnvr_rate': '주식전환비율',
'stck_lstn_date': '주식상장일자',
'stck_last_tr_date': '주식최종거래일자',
'hts_rmnn_dynu': 'HTS잔존일수',
'unas_isnm': '기초자산종목명',
'unas_prpr': '기초자산현재가',
'unas_prdy_vrss': '기초자산전일대비',
'unas_prdy_vrss_sign': '기초자산전일대비부호',
'unas_prdy_ctrt': '기초자산전일대비율',
'unas_acml_vol': '기초자산누적거래량',
'moneyness': 'MONEYNESS',
'atm_cls_name': 'ATM구분명',
'prit': '패리티',
'delta_val': '델타값',
'hts_ints_vltl': 'HTS내재변동성',
'tmvl_val': '시간가치값',
'gear': '기어링',
'lvrg_val': '레버리지값',
'prls_qryr_rate': '손익분기비율',
'cfp': '자본지지점',
'lstn_stcn': '상장주수',
'pblc_co_name': '발행회사명',
'lp_mbcr_name': 'LP회원사명',
'lp_hldn_rate': 'LP보유비율',
'elw_rght_form': 'ELW권리형태',
'elw_ko_barrier': '조기종료발생기준가격',
'apprch_rate': '접근도',
'unas_shrn_iscd': '기초자산단축종목코드',
'mtrt_date': '만기일자',
'prmm_val': '프리미엄값',
'stck_lp_fin_date': '주식LP종료일자',
'tick_conv_prc': '틱환산가',
'prls_qryr_stpr_prc': '손익분기주가가격',
'lp_hvol': 'LP보유량'
}
NUMERIC_COLUMNS = [
'elw_prpr', 'prdy_ctrt', 'acml_vol', 'acpr', 'stck_cnvr_rate',
'hts_rmnn_dynu', 'unas_prpr', 'unas_prdy_ctrt', 'unas_acml_vol',
'moneyness', 'prit', 'delta_val', 'hts_ints_vltl', 'tmvl_val',
'gear', 'lvrg_val', 'prls_qryr_rate', 'cfp', 'lstn_stcn', 'pblc_co_name', 'lp_mbcr_name', 'lp_hldn_rate', 'elw_rght_form', 'elw_ko_barrier', 'apprch_rate', 'unas_shrn_iscd', 'mtrt_date', 'prmm_val', 'stck_lp_fin_date', 'tick_conv_prc', 'prls_qryr_stpr_prc', 'lp_hvol'
]
def main():
"""
[국내주식] ELW시세
ELW 종목검색[국내주식-166]
ELW 종목검색 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (ELW(W))
- fid_cond_scr_div_code (str): 조건화면분류코드 (화면번호(11510))
- fid_rank_sort_cls_code (str): 순위정렬구분코드 ('정렬1정렬안함(0)종목코드(1)현재가(2)대비율(3)거래량(4)행사가격(5) 전환비율(6)상장일(7)만기일(8)잔존일수(9)레버리지(10)')
- fid_input_cnt_1 (str): 입력수1 (정렬1기준 - 상위(1)하위(2))
- fid_rank_sort_cls_code_2 (str): 순위정렬구분코드2 (정렬2)
- fid_input_cnt_2 (str): 입력수2 (정렬2기준 - 상위(1)하위(2))
- fid_rank_sort_cls_code_3 (str): 순위정렬구분코드3 (정렬3)
- fid_input_cnt_3 (str): 입력수3 (정렬3기준 - 상위(1)하위(2))
- fid_trgt_cls_code (str): 대상구분코드 (0:발행회사종목코드,1:기초자산종목코드,2:FID시장구분코드,3:FID입력날짜1(상장일), 4:FID입력날짜2(만기일),5:LP회원사종목코드,6:행사가기초자산비교>=(1) <=(2), 7:잔존일 이상 이하, 8:현재가, 9:전일대비율, 10:거래량, 11:최종거래일, 12:레버리지)
- fid_input_iscd (str): 입력종목코드 (발행사종목코드전체(00000))
- fid_unas_input_iscd (str): 기초자산입력종목코드 ()
- fid_mrkt_cls_code (str): 시장구분코드 (권리유형전체(A)콜(CO)풋(PO))
- fid_input_date_1 (str): 입력날짜1 (상장일전체(0)금일(1)7일이하(2)8~30일(3)31~90일(4))
- fid_input_date_2 (str): 입력날짜2 (만기일전체(0)1개월(1)1~2(2)2~3(3)3~6(4)6~9(5)9~12(6)12이상(7))
- fid_input_iscd_2 (str): 입력종목코드2 ()
- fid_etc_cls_code (str): 기타구분코드 (행사가전체(0)>=(1))
- fid_input_rmnn_dynu_1 (str): 입력잔존일수1 (잔존일이상)
- fid_input_rmnn_dynu_2 (str): 입력잔존일수2 (잔존일이하)
- fid_prpr_cnt1 (str): 현재가수1 (현재가이상)
- fid_prpr_cnt2 (str): 현재가수2 (현재가이하)
- fid_rsfl_rate1 (str): 등락비율1 (전일대비율이상)
- fid_rsfl_rate2 (str): 등락비율2 (전일대비율이하)
- fid_vol1 (str): 거래량1 (거래량이상)
- fid_vol2 (str): 거래량2 (거래량이하)
- fid_aply_rang_prc_1 (str): 적용범위가격1 (최종거래일from)
- fid_aply_rang_prc_2 (str): 적용범위가격2 (최종거래일to)
- fid_lvrg_val1 (str): 레버리지값1 ()
- fid_lvrg_val2 (str): 레버리지값2 ()
- fid_vol3 (str): 거래량3 (LP종료일from)
- fid_vol4 (str): 거래량4 (LP종료일to)
- fid_ints_vltl1 (str): 내재변동성1 (내재변동성이상)
- fid_ints_vltl2 (str): 내재변동성2 (내재변동성이하)
- fid_prmm_val1 (str): 프리미엄값1 (프리미엄이상)
- fid_prmm_val2 (str): 프리미엄값2 (프리미엄이하)
- fid_gear1 (str): 기어링1 (기어링이상)
- fid_gear2 (str): 기어링2 (기어링이하)
- fid_prls_qryr_rate1 (str): 손익분기비율1 (손익분기이상)
- fid_prls_qryr_rate2 (str): 손익분기비율2 (손익분기이하)
- fid_delta1 (str): 델타1 (델타이상)
- fid_delta2 (str): 델타2 (델타이하)
- fid_acpr1 (str): 행사가1 ()
- fid_acpr2 (str): 행사가2 ()
- fid_stck_cnvr_rate1 (str): 주식전환비율1 (전환비율이상)
- fid_stck_cnvr_rate2 (str): 주식전환비율2 (전환비율이하)
- fid_div_cls_code (str): 분류구분코드 (0:전체,1:일반,2:조기종료)
- fid_prit1 (str): 패리티1 (패리티이상)
- fid_prit2 (str): 패리티2 (패리티이하)
- fid_cfp1 (str): 자본지지점1 (배리어이상)
- fid_cfp2 (str): 자본지지점2 (배리어이하)
- fid_input_nmix_price_1 (str): 지수가격1 (LP보유비율이상)
- fid_input_nmix_price_2 (str): 지수가격2 (LP보유비율이하)
- fid_egea_val1 (str): E기어링값1 (접근도이상)
- fid_egea_val2 (str): E기어링값2 (접근도이하)
- fid_input_dvdn_ert (str): 배당수익율 (손익분기점이상)
- fid_input_hist_vltl (str): 역사적변동성 (손익분기점이하)
- fid_theta1 (str): 세타1 (MONEYNESS이상)
- fid_theta2 (str): 세타2 (MONEYNESS이하)
Returns:
- DataFrame: ELW 종목검색 결과
Example:
>>> df = cond_search(fid_cond_mrkt_div_code="W", fid_cond_scr_div_code="11510", fid_rank_sort_cls_code="0", fid_input_cnt_1="100")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# api 호출
logger.info("API 호출 ")
result = cond_search(
fid_cond_mrkt_div_code="W", # 조건시장분류코드
fid_cond_scr_div_code="11510", # 조건화면분류코드
fid_rank_sort_cls_code="0", # 순위정렬구분코드
fid_input_cnt_1="100", # 입력수1
fid_rank_sort_cls_code_2="", # 순위정렬구분코드2
fid_input_cnt_2="", # 입력수2
fid_rank_sort_cls_code_3="", # 순위정렬구분코드3
fid_input_cnt_3="", # 입력수3
fid_trgt_cls_code="", # 대상구분코드
fid_input_iscd="", # 입력종목코드
fid_unas_input_iscd="", # 기초자산입력종목코드
fid_mrkt_cls_code="", # 시장구분코드
fid_input_date_1="", # 입력날짜1
fid_input_date_2="", # 입력날짜2
fid_input_iscd_2="", # 입력종목코드2
fid_etc_cls_code="", # 기타구분코드
fid_input_rmnn_dynu_1="", # 입력잔존일수1
fid_input_rmnn_dynu_2="", # 입력잔존일수2
fid_prpr_cnt1="", # 현재가수1
fid_prpr_cnt2="", # 현재가수2
fid_rsfl_rate1="", # 등락비율1
fid_rsfl_rate2="", # 등락비율2
fid_vol1="", # 거래량1
fid_vol2="", # 거래량2
fid_aply_rang_prc_1="", # 적용범위가격1
fid_aply_rang_prc_2="", # 적용범위가격2
fid_lvrg_val1="", # 레버리지값1
fid_lvrg_val2="", # 레버리지값2
fid_vol3="", # 거래량3
fid_vol4="", # 거래량4
fid_ints_vltl1="", # 내재변동성1
fid_ints_vltl2="", # 내재변동성2
fid_prmm_val1="", # 프리미엄값1
fid_prmm_val2="", # 프리미엄값2
fid_gear1="", # 기어링1
fid_gear2="", # 기어링2
fid_prls_qryr_rate1="", # 손익분기비율1
fid_prls_qryr_rate2="", # 손익분기비율2
fid_delta1="", # 델타1
fid_delta2="", # 델타2
fid_acpr1="", # 행사가1
fid_acpr2="", # 행사가2
fid_stck_cnvr_rate1="", # 주식전환비율1
fid_stck_cnvr_rate2="", # 주식전환비율2
fid_div_cls_code="", # 분류구분코드
fid_prit1="", # 패리티1
fid_prit2="", # 패리티2
fid_cfp1="", # 자본지지점1
fid_cfp2="", # 자본지지점2
fid_input_nmix_price_1="", # 지수가격1
fid_input_nmix_price_2="", # 지수가격2
fid_egea_val1="", # E기어링값1
fid_egea_val2="", # E기어링값2
fid_input_dvdn_ert="", # 배당수익율
fid_input_hist_vltl="", # 역사적변동성
fid_theta1="", # 세타1
fid_theta2="", # 세타2
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 숫자형 컬럼 소수점 둘째자리까지 표시
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 결과 출력
logger.info("=== ELW 종목검색 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,349 @@
"""
Created on 2025-06-19
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 종목검색[국내주식-166]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/quotations/cond-search"
def cond_search(
fid_cond_mrkt_div_code: str, # 조건시장분류코드 (필수)
fid_cond_scr_div_code: str, # 조건화면분류코드 (필수)
fid_rank_sort_cls_code: str, # 순위정렬구분코드 (필수)
fid_input_cnt_1: str, # 입력수1 (필수)
fid_rank_sort_cls_code_2: Optional[str] = "", # 순위정렬구분코드2 (선택)
fid_input_cnt_2: Optional[str] = "", # 입력수2 (선택)
fid_rank_sort_cls_code_3: Optional[str] = "", # 순위정렬구분코드3 (선택)
fid_input_cnt_3: Optional[str] = "", # 입력수3 (선택)
fid_trgt_cls_code: Optional[str] = "", # 대상구분코드 (선택)
fid_input_iscd: Optional[str] = "", # 입력종목코드 (선택 - 전체 허용)
fid_unas_input_iscd: Optional[str] = "", # 기초자산입력종목코드 (선택)
fid_mrkt_cls_code: Optional[str] = "", # 시장구분코드 (선택 - 전체 허용)
fid_input_date_1: Optional[str] = "", # 입력날짜1 (선택 - 전체 허용)
fid_input_date_2: Optional[str] = "", # 입력날짜2 (선택 - 전체 허용)
fid_input_iscd_2: Optional[str] = "", # 입력종목코드2 (선택)
fid_etc_cls_code: Optional[str] = "", # 기타구분코드 (선택 - 전체 허용)
fid_input_rmnn_dynu_1: Optional[str] = "", # 입력잔존일수1 (선택 - 이상값)
fid_input_rmnn_dynu_2: Optional[str] = "", # 입력잔존일수2 (선택 - 이하값)
fid_prpr_cnt1: Optional[str] = "", # 현재가수1 (선택 - 이상값)
fid_prpr_cnt2: Optional[str] = "", # 현재가수2 (선택 - 이하값)
fid_rsfl_rate1: Optional[str] = "", # 등락비율1 (선택 - 이상값)
fid_rsfl_rate2: Optional[str] = "", # 등락비율2 (선택 - 이하값)
fid_vol1: Optional[str] = "", # 거래량1 (선택 - 이상값)
fid_vol2: Optional[str] = "", # 거래량2 (선택 - 이하값)
fid_aply_rang_prc_1: Optional[str] = "", # 적용범위가격1 (선택)
fid_aply_rang_prc_2: Optional[str] = "", # 적용범위가격2 (선택)
fid_lvrg_val1: Optional[str] = "", # 레버리지값1 (선택)
fid_lvrg_val2: Optional[str] = "", # 레버리지값2 (선택)
fid_vol3: Optional[str] = "", # 거래량3 (선택)
fid_vol4: Optional[str] = "", # 거래량4 (선택)
fid_ints_vltl1: Optional[str] = "", # 내재변동성1 (선택 - 이상값)
fid_ints_vltl2: Optional[str] = "", # 내재변동성2 (선택 - 이하값)
fid_prmm_val1: Optional[str] = "", # 프리미엄값1 (선택 - 이상값)
fid_prmm_val2: Optional[str] = "", # 프리미엄값2 (선택 - 이하값)
fid_gear1: Optional[str] = "", # 기어링1 (선택 - 이상값)
fid_gear2: Optional[str] = "", # 기어링2 (선택 - 이하값)
fid_prls_qryr_rate1: Optional[str] = "", # 손익분기비율1 (선택 - 이상값)
fid_prls_qryr_rate2: Optional[str] = "", # 손익분기비율2 (선택 - 이하값)
fid_delta1: Optional[str] = "", # 델타1 (선택 - 이상값)
fid_delta2: Optional[str] = "", # 델타2 (선택 - 이하값)
fid_acpr1: Optional[str] = "", # 행사가1 (선택)
fid_acpr2: Optional[str] = "", # 행사가2 (선택)
fid_stck_cnvr_rate1: Optional[str] = "", # 주식전환비율1 (선택 - 이상값)
fid_stck_cnvr_rate2: Optional[str] = "", # 주식전환비율2 (선택 - 이하값)
fid_div_cls_code: Optional[str] = "", # 분류구분코드 (선택)
fid_prit1: Optional[str] = "", # 패리티1 (선택 - 이상값)
fid_prit2: Optional[str] = "", # 패리티2 (선택 - 이하값)
fid_cfp1: Optional[str] = "", # 자본지지점1 (선택 - 이상값)
fid_cfp2: Optional[str] = "", # 자본지지점2 (선택 - 이하값)
fid_input_nmix_price_1: Optional[str] = "", # 지수가격1 (선택 - 이상값)
fid_input_nmix_price_2: Optional[str] = "", # 지수가격2 (선택 - 이하값)
fid_egea_val1: Optional[str] = "", # E기어링값1 (선택 - 이상값)
fid_egea_val2: Optional[str] = "", # E기어링값2 (선택 - 이하값)
fid_input_dvdn_ert: Optional[str] = "", # 배당수익율 (선택 - 이상값)
fid_input_hist_vltl: Optional[str] = "", # 역사적변동성 (선택 - 이하값)
fid_theta1: Optional[str] = "", # 세타1 (선택 - 이상값)
fid_theta2: Optional[str] = "", # 세타2 (선택 - 이하값)
tr_cont: str = "", # 연속 거래 여부
dataframe: Optional[pd.DataFrame] = None, # 누적 데이터프레임
depth: int = 0, # 현재 재귀 깊이
max_depth: int = 10 # 최대 재귀 깊이
) -> pd.DataFrame:
"""
ELW 종목검색 API를 호출하여 조건에 맞는 ELW 종목 정보를 조회합니다.
한국투자 HTS(eFriend Plus) > [0291] ELW 종목검색 화면의 기능을 API로 구현한 함수입니다.
다양한 조건을 설정하여 ELW 종목을 검색하고, 한 번의 호출에 최대 100건까지 조회 가능합니다.
연속 조회를 통해 전체 데이터를 수집할 수 있습니다.
Args:
fid_cond_mrkt_div_code (str): 조건시장분류코드 (ELW의 경우 "W" 입력)
fid_cond_scr_div_code (str): 조건화면분류코드 (화면번호 "11510" 입력)
fid_rank_sort_cls_code (str): 순위정렬구분코드
- 0: 정렬안함, 1: 종목코드, 2: 현재가, 3: 대비율, 4: 거래량
- 5: 행사가격, 6: 전환비율, 7: 상장일, 8: 만기일, 9: 잔존일수, 10: 레버리지
fid_input_cnt_1 (str): 정렬1기준 (1: 상위, 2: 하위)
나머지 파라미터들: 대부분 선택사항으로 빈 문자열("")로 설정 가능
tr_cont (str): 연속 거래 여부 (초기 조회시 공백, 연속 조회시 "N")
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임 (재귀 호출용)
depth (int): 현재 재귀 깊이 (재귀 호출 횟수 추적)
max_depth (int): 최대 재귀 깊이 (무한 재귀 방지, 기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 종목검색 결과 데이터프레임
- 성공시: ELW 종목 정보가 포함된 DataFrame 반환
- 실패시: 빈 DataFrame 반환
- API 오류시: None 반환
Raises:
ValueError: 필수 파라미터가 누락되거나 잘못된 값이 입력된 경우
Example:
>>> # 기본 ELW 검색 (전체 종목)
>>> df = cond_search(
... fid_cond_mrkt_div_code="W",
... fid_cond_scr_div_code="11510",
... fid_rank_sort_cls_code="0",
... fid_input_cnt_1="1",
... fid_rank_sort_cls_code_2="",
... fid_input_cnt_2="",
... fid_rank_sort_cls_code_3="",
... fid_input_cnt_3="",
... fid_trgt_cls_code="",
... fid_input_iscd="",
... fid_unas_input_iscd="",
... fid_mrkt_cls_code="",
... fid_input_date_1="",
... fid_input_date_2="",
... fid_input_iscd_2="",
... fid_etc_cls_code="",
... # 나머지 모든 파라미터는 빈 문자열
... **{param: "" for param in [
... "fid_input_rmnn_dynu_1", "fid_input_rmnn_dynu_2",
... "fid_prpr_cnt1", "fid_prpr_cnt2", "fid_rsfl_rate1", "fid_rsfl_rate2",
... "fid_vol1", "fid_vol2", "fid_aply_rang_prc_1", "fid_aply_rang_prc_2",
... "fid_lvrg_val1", "fid_lvrg_val2", "fid_vol3", "fid_vol4",
... "fid_ints_vltl1", "fid_ints_vltl2", "fid_prmm_val1", "fid_prmm_val2",
... "fid_gear1", "fid_gear2", "fid_prls_qryr_rate1", "fid_prls_qryr_rate2",
... "fid_delta1", "fid_delta2", "fid_acpr1", "fid_acpr2",
... "fid_stck_cnvr_rate1", "fid_stck_cnvr_rate2", "fid_div_cls_code",
... "fid_prit1", "fid_prit2", "fid_cfp1", "fid_cfp2",
... "fid_input_nmix_price_1", "fid_input_nmix_price_2",
... "fid_egea_val1", "fid_egea_val2", "fid_input_dvdn_ert",
... "fid_input_hist_vltl", "fid_theta1", "fid_theta2"
... ]}
... )
>>> print(df.head())
"""
# 필수 파라미터 검증 (최소한으로 축소)
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_cond_scr_div_code:
logger.error("fid_cond_scr_div_code is required. (e.g. '11510')")
raise ValueError("fid_cond_scr_div_code is required. (e.g. '11510')")
if fid_rank_sort_cls_code is None:
logger.error("fid_rank_sort_cls_code is required. (e.g. '0')")
raise ValueError("fid_rank_sort_cls_code is required. (e.g. '0')")
if not fid_input_cnt_1:
logger.error("fid_input_cnt_1 is required. (e.g. '1')")
raise ValueError("fid_input_cnt_1 is required. (e.g. '1')")
# 최대 재귀 깊이 체크 (무한 재귀 방지)
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
# API 호출 정보 설정
tr_id = "FHKEW15100000"
# 요청 파라미터 설정
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_COND_SCR_DIV_CODE": fid_cond_scr_div_code,
"FID_RANK_SORT_CLS_CODE": fid_rank_sort_cls_code,
"FID_INPUT_CNT_1": fid_input_cnt_1,
"FID_RANK_SORT_CLS_CODE_2": fid_rank_sort_cls_code_2,
"FID_INPUT_CNT_2": fid_input_cnt_2,
"FID_RANK_SORT_CLS_CODE_3": fid_rank_sort_cls_code_3,
"FID_INPUT_CNT_3": fid_input_cnt_3,
"FID_TRGT_CLS_CODE": fid_trgt_cls_code,
"FID_INPUT_ISCD": fid_input_iscd,
"FID_UNAS_INPUT_ISCD": fid_unas_input_iscd,
"FID_MRKT_CLS_CODE": fid_mrkt_cls_code,
"FID_INPUT_DATE_1": fid_input_date_1,
"FID_INPUT_DATE_2": fid_input_date_2,
"FID_INPUT_ISCD_2": fid_input_iscd_2,
"FID_ETC_CLS_CODE": fid_etc_cls_code,
"FID_INPUT_RMNN_DYNU_1": fid_input_rmnn_dynu_1,
"FID_INPUT_RMNN_DYNU_2": fid_input_rmnn_dynu_2,
"FID_PRPR_CNT1": fid_prpr_cnt1,
"FID_PRPR_CNT2": fid_prpr_cnt2,
"FID_RSFL_RATE1": fid_rsfl_rate1,
"FID_RSFL_RATE2": fid_rsfl_rate2,
"FID_VOL1": fid_vol1,
"FID_VOL2": fid_vol2,
"FID_APLY_RANG_PRC_1": fid_aply_rang_prc_1,
"FID_APLY_RANG_PRC_2": fid_aply_rang_prc_2,
"FID_LVRG_VAL1": fid_lvrg_val1,
"FID_LVRG_VAL2": fid_lvrg_val2,
"FID_VOL3": fid_vol3,
"FID_VOL4": fid_vol4,
"FID_INTS_VLTL1": fid_ints_vltl1,
"FID_INTS_VLTL2": fid_ints_vltl2,
"FID_PRMM_VAL1": fid_prmm_val1,
"FID_PRMM_VAL2": fid_prmm_val2,
"FID_GEAR1": fid_gear1,
"FID_GEAR2": fid_gear2,
"FID_PRLS_QRYR_RATE1": fid_prls_qryr_rate1,
"FID_PRLS_QRYR_RATE2": fid_prls_qryr_rate2,
"FID_DELTA1": fid_delta1,
"FID_DELTA2": fid_delta2,
"FID_ACPR1": fid_acpr1,
"FID_ACPR2": fid_acpr2,
"FID_STCK_CNVR_RATE1": fid_stck_cnvr_rate1,
"FID_STCK_CNVR_RATE2": fid_stck_cnvr_rate2,
"FID_DIV_CLS_CODE": fid_div_cls_code,
"FID_PRIT1": fid_prit1,
"FID_PRIT2": fid_prit2,
"FID_CFP1": fid_cfp1,
"FID_CFP2": fid_cfp2,
"FID_INPUT_NMIX_PRICE_1": fid_input_nmix_price_1,
"FID_INPUT_NMIX_PRICE_2": fid_input_nmix_price_2,
"FID_EGEA_VAL1": fid_egea_val1,
"FID_EGEA_VAL2": fid_egea_val2,
"FID_INPUT_DVDN_ERT": fid_input_dvdn_ert,
"FID_INPUT_HIST_VLTL": fid_input_hist_vltl,
"FID_THETA1": fid_theta1,
"FID_THETA2": fid_theta2,
}
# API 호출 정보 로그
logger.info("ELW 종목검색 API 호출 시작 (depth: %d)", depth)
# API 호출 실행
res = ka._url_fetch(API_URL, tr_id, tr_cont, params)
# API 응답 처리
if res.isOK():
# 응답 데이터 처리
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
# 단일 객체인 경우 리스트로 변환
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
logger.info("API 호출 성공: %d건의 데이터를 수신했습니다.", len(current_data))
else:
current_data = pd.DataFrame()
logger.warning("API 응답에서 output 데이터를 찾을 수 없습니다.")
# 데이터프레임 누적 처리
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
# 연속 조회 여부 확인
tr_cont = res.getHeader().tr_cont
# 연속 데이터가 있는 경우 재귀 호출
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep() # API 호출 간격 조절
return cond_search(
fid_cond_mrkt_div_code,
fid_cond_scr_div_code,
fid_rank_sort_cls_code,
fid_input_cnt_1,
fid_rank_sort_cls_code_2,
fid_input_cnt_2,
fid_rank_sort_cls_code_3,
fid_input_cnt_3,
fid_trgt_cls_code,
fid_input_iscd,
fid_unas_input_iscd,
fid_mrkt_cls_code,
fid_input_date_1,
fid_input_date_2,
fid_input_iscd_2,
fid_etc_cls_code,
fid_input_rmnn_dynu_1,
fid_input_rmnn_dynu_2,
fid_prpr_cnt1,
fid_prpr_cnt2,
fid_rsfl_rate1,
fid_rsfl_rate2,
fid_vol1,
fid_vol2,
fid_aply_rang_prc_1,
fid_aply_rang_prc_2,
fid_lvrg_val1,
fid_lvrg_val2,
fid_vol3,
fid_vol4,
fid_ints_vltl1,
fid_ints_vltl2,
fid_prmm_val1,
fid_prmm_val2,
fid_gear1,
fid_gear2,
fid_prls_qryr_rate1,
fid_prls_qryr_rate2,
fid_delta1,
fid_delta2,
fid_acpr1,
fid_acpr2,
fid_stck_cnvr_rate1,
fid_stck_cnvr_rate2,
fid_div_cls_code,
fid_prit1,
fid_prit2,
fid_cfp1,
fid_cfp2,
fid_input_nmix_price_1,
fid_input_nmix_price_2,
fid_egea_val1,
fid_egea_val2,
fid_input_dvdn_ert,
fid_input_hist_vltl,
fid_theta1,
fid_theta2,
"N", dataframe, depth + 1, max_depth
)
else:
# 데이터 수집 완료
logger.info("Data fetch complete.")
total_records = len(dataframe) if dataframe is not None else 0
logger.info("%d건의 ELW 종목 데이터를 수집했습니다.", total_records)
return dataframe
else:
# API 호출 실패 처리
error_code = res.getErrorCode()
error_message = res.getErrorMessage()
logger.error("API call failed: %s - %s", error_code, error_message)
res.printError(API_URL)
return pd.DataFrame() # 빈 데이터프레임 반환

View File

@@ -0,0 +1,193 @@
"""
Created on 2025-07-09
"""
import logging
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from elw_asking_price import elw_asking_price
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] 실시간시세 - ELW 실시간호가[실시간-062]
##############################################################################################
# 컬럼명 매핑
COLUMN_MAPPING = {
"mksc_shrn_iscd": "유가증권단축종목코드",
"bsop_hour": "영업시간",
"hour_cls_code": "시간구분코드",
"askp1": "매도호가1",
"askp2": "매도호가2",
"askp3": "매도호가3",
"askp4": "매도호가4",
"askp5": "매도호가5",
"askp6": "매도호가6",
"askp7": "매도호가7",
"askp8": "매도호가8",
"askp9": "매도호가9",
"askp10": "매도호가10",
"bidp1": "매수호가1",
"bidp2": "매수호가2",
"bidp3": "매수호가3",
"bidp4": "매수호가4",
"bidp5": "매수호가5",
"bidp6": "매수호가6",
"bidp7": "매수호가7",
"bidp8": "매수호가8",
"bidp9": "매수호가9",
"bidp10": "매수호가10",
"askp_rsqn1": "매도호가잔량1",
"askp_rsqn2": "매도호가잔량2",
"askp_rsqn3": "매도호가잔량3",
"askp_rsqn4": "매도호가잔량4",
"askp_rsqn5": "매도호가잔량5",
"askp_rsqn6": "매도호가잔량6",
"askp_rsqn7": "매도호가잔량7",
"askp_rsqn8": "매도호가잔량8",
"askp_rsqn9": "매도호가잔량9",
"askp_rsqn10": "매도호가잔량10",
"bidp_rsqn1": "매수호가잔량1",
"bidp_rsqn2": "매수호가잔량2",
"bidp_rsqn3": "매수호가잔량3",
"bidp_rsqn4": "매수호가잔량4",
"bidp_rsqn5": "매수호가잔량5",
"bidp_rsqn6": "매수호가잔량6",
"bidp_rsqn7": "매수호가잔량7",
"bidp_rsqn8": "매수호가잔량8",
"bidp_rsqn9": "매수호가잔량9",
"bidp_rsqn10": "매수호가잔량10",
"total_askp_rsqn": "총매도호가잔량",
"total_bidp_rsqn": "총매수호가잔량",
"antc_cnpr": "예상체결가",
"antc_cnqn": "예상체결량",
"antc_cntg_vrss_sign": "예상체결대비부호",
"antc_cntg_vrss": "예상체결대비",
"antc_cntg_prdy_ctrt": "예상체결전일대비율",
"lp_askp_rsqn1": "LP매도호가잔량1",
"lp_askp_rsqn2": "LP매도호가잔량2",
"lp_askp_rsqn3": "LP매도호가잔량3",
"lp_bidp_rsqn4": "LP매수호가잔량4",
"lp_askp_rsqn4": "LP매도호가잔량4",
"lp_bidp_rsqn5": "LP매수호가잔량5",
"lp_askp_rsqn5": "LP매도호가잔량5",
"lp_bidp_rsqn6": "LP매수호가잔량6",
"lp_askp_rsqn6": "LP매도호가잔량6",
"lp_bidp_rsqn7": "LP매수호가잔량7",
"lp_askp_rsqn7": "LP매도호가잔량7",
"lp_askp_rsqn8": "LP매도호가잔량8",
"lp_bidp_rsqn8": "LP매수호가잔량8",
"lp_askp_rsqn9": "LP매도호가잔량9",
"lp_bidp_rsqn9": "LP매수호가잔량9",
"lp_askp_rsqn10": "LP매도호가잔량10",
"lp_bidp_rsqn10": "LP매수호가잔량10",
"lp_bidp_rsqn1": "LP매수호가잔량1",
"lp_total_askp_rsqn": "LP총매도호가잔량",
"lp_bidp_rsqn2": "LP매수호가잔량2",
"lp_total_bidp_rsqn": "LP총매수호가잔량",
"lp_bidp_rsqn3": "LP매수호가잔량3",
"antc_vol": "예상거래량"
}
# 숫자형 컬럼 리스트 (문자열 컬럼 제외)
NUMERIC_COLUMNS = [
"매도호가1", "매도호가2", "매도호가3", "매도호가4", "매도호가5", "매도호가6", "매도호가7", "매도호가8", "매도호가9", "매도호가10",
"매수호가1", "매수호가2", "매수호가3", "매수호가4", "매수호가5", "매수호가6", "매수호가7", "매수호가8", "매수호가9", "매수호가10",
"매도호가잔량1", "매도호가잔량2", "매도호가잔량3", "매도호가잔량4", "매도호가잔량5",
"매도호가잔량6", "매도호가잔량7", "매도호가잔량8", "매도호가잔량9", "매도호가잔량10",
"매수호가잔량1", "매수호가잔량2", "매수호가잔량3", "매수호가잔량4", "매수호가잔량5",
"매수호가잔량6", "매수호가잔량7", "매수호가잔량8", "매수호가잔량9", "매수호가잔량10",
"총매도호가잔량", "총매수호가잔량", "예상체결가", "예상체결량", "예상체결대비", "예상체결전일대비율",
"LP매도호가잔량1", "LP매도호가잔량2", "LP매도호가잔량3", "LP매수호가잔량4", "LP매도호가잔량4",
"LP매수호가잔량5", "LP매도호가잔량5", "LP매수호가잔량6", "LP매도호가잔량6", "LP매수호가잔량7",
"LP매도호가잔량7", "LP매도호가잔량8", "LP매수호가잔량8", "LP매도호가잔량9", "LP매수호가잔량9",
"LP매도호가잔량10", "LP매수호가잔량10", "LP매수호가잔량1", "LP총매도호가잔량", "LP매수호가잔량2",
"LP총매수호가잔량", "LP매수호가잔량3", "예상거래량"
]
def main():
"""
[국내주식] ELW시세
ELW 실시간호가[H0EWASP0]
ELW 실시간 호가 정보를 실시간으로 구독하는 웹소켓 API입니다.
[참고자료]
종목코드 마스터파일 파이썬 정제코드는 한국투자증권 Github 참고 부탁드립니다.
https://github.com/koreainvestment/open-trading-api/tree/main/stocks_info
[호출 데이터]
헤더와 바디 값을 합쳐 JSON 형태로 전송합니다.
[응답 데이터]
1. 정상 등록 여부 (JSON)
- JSON["body"]["msg1"] - 정상 응답 시, SUBSCRIBE SUCCESS
- JSON["body"]["output"]["iv"] - 실시간 결과 복호화에 필요한 AES256 IV (Initialize Vector)
- JSON["body"]["output"]["key"] - 실시간 결과 복호화에 필요한 AES256 Key
2. 실시간 결과 응답 ( | 로 구분되는 값)
ex) 0|H0STCNT0|004|005930^123929^73100^5^...
- 암호화 유무 : 0 암호화 되지 않은 데이터 / 1 암호화된 데이터
- TR_ID : 등록한 tr_id (ex. H0STCNT0)
- 데이터 건수 : (ex. 001 인 경우 데이터 건수 1건, 004인 경우 데이터 건수 4건)
- 응답 데이터 : 아래 response 데이터 참조 ( ^로 구분됨)
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
ka.auth_ws()
logger.info("토큰 발급 완료")
# 인증(auth_ws()) 이후에 선언
kws = ka.KISWebSocket(api_url="/tryitout")
# API 호출
logger.info("API 호출 ")
kws.subscribe(request=elw_asking_price, data=["57LA24","57L739","57L650","57L966","52L181","57LB38"])
# 결과 표시
def on_result(ws, tr_id: str, result: pd.DataFrame, data_map: dict):
try:
# 안전한 컬럼명 매핑 (존재하는 컬럼에 대해서만 한글명 적용)
if not result.empty:
# 컬럼명 매핑
existing_columns = {col: COLUMN_MAPPING[col] for col in result.columns if col in COLUMN_MAPPING}
if existing_columns:
result = result.rename(columns=existing_columns)
logging.info(f"컬럼명 매핑 완료: {len(existing_columns)}개 컬럼")
# 숫자형 컬럼 소수점 둘째자리까지 표시
for col in NUMERIC_COLUMNS:
# 원본 컬럼명 확인
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 한글명으로 변환된 컬럼명 확인
elif COLUMN_MAPPING.get(col) in result.columns:
result[COLUMN_MAPPING[col]] = pd.to_numeric(result[COLUMN_MAPPING[col]], errors='coerce').round(2)
logger.info("=== ELW 실시간호가 결과 ===")
print(result)
except Exception as e:
logging.error(f"결과 처리 중 오류: {e}")
logging.error(f"받은 데이터: {result}")
kws.start(on_result=on_result)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,137 @@
"""
Created on 2025-07-09
"""
import logging
import sys
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] 실시간시세 - ELW 실시간호가[실시간-062]
##############################################################################################
def elw_asking_price(
tr_type: str,
tr_key: str,
) -> tuple[dict, list[str]]:
"""
ELW 실시간호가[H0EWASP0]
ELW 실시간 호가 정보를 실시간으로 구독하는 웹소켓 API입니다.
Args:
tr_type (str): [필수] 구독 등록("1") 또는 해제("0") 여부를 나타냅니다.
tr_key (str): [필수] 종목코드. 빈 문자열일 수 없습니다.
Returns:
message (dict): 실시간 데이터 구독에 대한 응답 메시지.
columns (list[str]): 실시간 데이터의 컬럼 정보.
Raises:
ValueError: tr_key가 빈 문자열인 경우 발생합니다.
Example:
>>> msg, columns = elw_asking_price("1", "005930")
>>> print(msg, columns)
[참고자료]
종목코드 마스터파일 파이썬 정제코드는 한국투자증권 Github 참고 부탁드립니다.
https://github.com/koreainvestment/open-trading-api/tree/main/stocks_info
"""
# 필수 파라미터 검증
if not tr_key:
raise ValueError("tr_key is required and cannot be an empty string")
tr_id = "H0EWASP0"
params = {
"tr_key": tr_key,
}
# 데이터 구독 요청
msg = ka.data_fetch(tr_id, tr_type, params)
# 응답 데이터 컬럼 정보
columns = [
"mksc_shrn_iscd",
"bsop_hour",
"hour_cls_code",
"askp1",
"askp2",
"askp3",
"askp4",
"askp5",
"askp6",
"askp7",
"askp8",
"askp9",
"askp10",
"bidp1",
"bidp2",
"bidp3",
"bidp4",
"bidp5",
"bidp6",
"bidp7",
"bidp8",
"bidp9",
"bidp10",
"askp_rsqn1",
"askp_rsqn2",
"askp_rsqn3",
"askp_rsqn4",
"askp_rsqn5",
"askp_rsqn6",
"askp_rsqn7",
"askp_rsqn8",
"askp_rsqn9",
"askp_rsqn10",
"bidp_rsqn1",
"bidp_rsqn2",
"bidp_rsqn3",
"bidp_rsqn4",
"bidp_rsqn5",
"bidp_rsqn6",
"bidp_rsqn7",
"bidp_rsqn8",
"bidp_rsqn9",
"bidp_rsqn10",
"total_askp_rsqn",
"total_bidp_rsqn",
"antc_cnpr",
"antc_cnqn",
"antc_cntg_vrss_sign",
"antc_cntg_vrss",
"antc_cntg_prdy_ctrt",
"lp_askp_rsqn1",
"lp_askp_rsqn2",
"lp_askp_rsqn3",
"lp_bidp_rsqn4",
"lp_askp_rsqn4",
"lp_bidp_rsqn5",
"lp_askp_rsqn5",
"lp_bidp_rsqn6",
"lp_askp_rsqn6",
"lp_bidp_rsqn7",
"lp_askp_rsqn7",
"lp_askp_rsqn8",
"lp_bidp_rsqn8",
"lp_askp_rsqn9",
"lp_bidp_rsqn9",
"lp_askp_rsqn10",
"lp_bidp_rsqn10",
"lp_bidp_rsqn1",
"lp_total_askp_rsqn",
"lp_bidp_rsqn2",
"lp_total_bidp_rsqn",
"lp_bidp_rsqn3",
"antc_vol",
]
return msg, columns

View File

@@ -0,0 +1,169 @@
"""
Created on 2025-07-09
"""
import logging
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from elw_ccnl import elw_ccnl
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] 실시간시세 - ELW 실시간체결가[실시간-061]
##############################################################################################
COLUMN_MAPPING = {
"mksc_shrn_iscd": "유가증권단축종목코드",
"stck_cntg_hour": "주식체결시간",
"stck_prpr": "주식현재가",
"prdy_vrss_sign": "전일대비부호",
"prdy_vrss": "전일대비",
"prdy_ctrt": "전일대비율",
"wghn_avrg_stck_prc": "가중평균주식가격",
"stck_oprc": "주식시가2",
"stck_hgpr": "주식최고가",
"stck_lwpr": "주식최저가",
"askp1": "매도호가1",
"bidp1": "매수호가1",
"cntg_vol": "체결거래량",
"acml_vol": "누적거래량",
"acml_tr_pbmn": "누적거래대금",
"seln_cntg_csnu": "매도체결건수",
"shnu_cntg_csnu": "매수체결건수",
"ntby_cntg_csnu": "순매수체결건수",
"cttr": "체결강도",
"seln_cntg_smtn": "총매도수량",
"shnu_cntg_smtn": "총매수수량",
"cntg_cls_code": "체결구분코드",
"shnu_rate": "매수2비율",
"prdy_vol_vrss_acml_vol_rate": "전일거래량대비등락율",
"oprc_hour": "시가시간",
"oprc_vrss_prpr_sign": "시가2대비현재가부호",
"oprc_vrss_prpr": "시가2대비현재가",
"hgpr_vrss_prpr_sign": "최고가대비현재가부호",
"hgpr_vrss_prpr": "최고가대비현재가",
"lwpr_vrss_prpr_sign": "최저가대비현재가부호",
"lwpr_vrss_prpr": "최저가대비현재가",
"bsop_date": "기준일자",
"new_mkop_cls_code": "신규시장분류코드",
"trht_yn": "거래정지여부",
"askp_rsqn1": "매도호가잔량1",
"bidp_rsqn1": "매수호가잔량1",
"total_askp_rsqn": "총매도호가잔량",
"total_bidp_rsqn": "총매수호가잔량",
"vol_rate": "거래량비율",
"prdy_vrss_vol_rate": "전일대비거래량비율",
"askp_rsqn_icdc": "매도호가잔량증감",
"bidp_rsqn_icdc": "매수호가잔량증감",
"hour_cls_code": "시간구분코드",
"mrkt_trtm_cls_code": "시장거래시간구분코드",
"vi_cls_code": "VI구분코드",
"timr_val": "시간가치값",
"parity": "패리티",
"prm_val": "프리미엄값",
"gear": "기어링",
"bep_rate": "손익분기비율",
"itmv_val": "내재가치값",
"prm_rate": "프리미엄비율",
"sppt_pnt": "자본지지점",
"lvrg_val": "레버리지값",
"delta": "델타",
"gamma": "감마",
"vega": "베가",
"theta": "세타",
"rho": "로우",
"hts_antc_vol": "HTS내재변동성",
"hts_theo_prc": "HTS이론가",
"vol_tnrt": "거래량회전율",
"prdy_smns_hour_acml_vol": "전일동시간누적거래량",
"prdy_smns_hour_acml_vol_rate": "전일동시간누적거래량비율",
"apprch_rate": "접근도",
"lp_hvol": "LP보유량",
"lp_hldn_rate": "LP보유비율",
"lp_ntby_qty": "LP순매도량"
}
NUMERIC_COLUMNS = [
"주식현재가", "전일대비", "전일대비율", "가중평균주식가격", "주식시가2", "주식최고가", "주식최저가",
"매도호가1", "매수호가1", "체결거래량", "누적거래량", "누적거래대금", "매도체결건수", "매수체결건수",
"순매수체결건수", "체결강도", "총매도수량", "총매수수량", "매수2비율", "전일거래량대비등락율",
"시가2대비현재가", "최고가대비현재가", "최저가대비현재가", "매도호가잔량1", "매수호가잔량1",
"총매도호가잔량", "총매수호가잔량", "시간가치값", "패리티", "프리미엄값", "기어링", "손익분기비율",
"내재가치값", "프리미엄비율", "자본지지점", "레버리지값", "델타", "감마", "베가", "세타", "로우",
"HTS내재변동성", "HTS이론가", "거래량회전율", "전일동시간누적거래량", "전일동시간누적거래량비율",
"접근도", "LP보유량", "LP보유비율", "LP순매도량"
]
def main():
"""
ELW 실시간체결가
ELW 실시간체결가 API입니다.
[참고자료]
종목코드 마스터파일 파이썬 정제코드는 한국투자증권 Github 참고 부탁드립니다.
https://github.com/koreainvestment/open-trading-api/tree/main/stocks_info
[호출 데이터]
헤더와 바디 값을 합쳐 JSON 형태로 전송합니다.
[응답 데이터]
1. 정상 등록 여부 (JSON)
- JSON["body"]["msg1"] - 정상 응답 시, SUBSCRIBE SUCCESS
- JSON["body"]["output"]["iv"] - 실시간 결과 복호화에 필요한 AES256 IV (Initialize Vector)
- JSON["body"]["output"]["key"] - 실시간 결과 복호화에 필요한 AES256 Key
2. 실시간 결과 응답 ( | 로 구분되는 값)
ex) 0|H0STCNT0|004|005930^123929^73100^5^...
- 암호화 유무 : 0 암호화 되지 않은 데이터 / 1 암호화된 데이터
- TR_ID : 등록한 tr_id (ex. H0STCNT0)
- 데이터 건수 : (ex. 001 인 경우 데이터 건수 1건, 004인 경우 데이터 건수 4건)
- 응답 데이터 : 아래 response 데이터 참조 ( ^로 구분됨)
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
ka.auth_ws()
# 인증(auth_ws()) 이후에 선언
kws = ka.KISWebSocket(api_url="/tryitout")
# API 호출
logger.info("API 호출")
kws.subscribe(request=elw_ccnl, data=["57LA24","57L739","57L650","57L966","52L181","57LB38"])
# 결과 표시
def on_result(ws, tr_id: str, result: pd.DataFrame, data_map: dict):
try:
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
logging.info("결과:")
print(result)
except Exception as e:
logging.error(f"결과 처리 중 오류: {e}")
logging.error(f"받은 데이터: {result}")
kws.start(on_result=on_result)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,77 @@
"""
Created on 2025-07-09
"""
import logging
import sys
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] 실시간시세 - ELW 실시간체결가[실시간-061]
##############################################################################################
def elw_ccnl(
tr_type: str,
tr_key: str,
) -> tuple[dict, list[str]]:
"""
ELW 실시간체결가[H0EWCNT0] 구독 함수
ELW 실시간체결가 API를 통해 실시간 데이터를 구독합니다.
Args:
tr_type (str): [필수] 구독 등록("1") 또는 해제("0") 여부를 나타냅니다.
tr_key (str): [필수] 종목코드를 입력합니다. 빈 문자열이 아니어야 합니다.
Returns:
message (dict): 메시지 데이터
columns (list[str]): 실시간 데이터의 컬럼 정보
Example:
>>> msg, columns = elw_ccnl("1", "005930")
>>> print(msg, columns)
[참고자료]
종목코드 마스터파일 파이썬 정제코드는 한국투자증권 Github 참고 부탁드립니다.
https://github.com/koreainvestment/open-trading-api/tree/main/stocks_info
"""
# 필수 파라미터 검증
if not tr_key:
raise ValueError("tr_key는 필수 입력값입니다.")
tr_id = "H0EWCNT0"
params = {
"tr_key": tr_key,
}
# 데이터 구독 요청
msg = ka.data_fetch(tr_id, tr_type, params)
# 응답 데이터 컬럼 정보
columns = [
"mksc_shrn_iscd", "stck_cntg_hour", "stck_prpr", "prdy_vrss_sign",
"prdy_vrss", "prdy_ctrt", "wghn_avrg_stck_prc", "stck_oprc",
"stck_hgpr", "stck_lwpr", "askp1", "bidp1", "cntg_vol", "acml_vol",
"acml_tr_pbmn", "seln_cntg_csnu", "shnu_cntg_csnu", "ntby_cntg_csnu",
"cttr", "seln_cntg_smtn", "shnu_cntg_smtn", "cntg_cls_code",
"shnu_rate", "prdy_vol_vrss_acml_vol_rate", "oprc_hour",
"oprc_vrss_prpr_sign", "oprc_vrss_prpr", "hgpr_hour",
"hgpr_vrss_prpr_sign", "hgpr_vrss_prpr", "lwpr_hour",
"lwpr_vrss_prpr_sign", "lwpr_vrss_prpr", "bsop_date",
"new_mkop_cls_code", "trht_yn", "askp_rsqn1", "bidp_rsqn1",
"total_askp_rsqn", "total_bidp_rsqn", "tmvl_val", "prit", "prmm_val",
"gear", "prls_qryr_rate", "invl_val", "prmm_rate", "cfp", "lvrg_val",
"delta", "gama", "vega", "theta", "rho", "hts_ints_vltl", "hts_thpr",
"vol_tnrt", "prdy_smns_hour_acml_vol", "prdy_smns_hour_acml_vol_rate",
"apprch_rate", "lp_hvol", "lp_hldn_rate", "lp_ntby_qty"
]
return msg, columns

View File

@@ -0,0 +1,159 @@
"""
Created on 2025-07-09
"""
import logging
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from elw_exp_ccnl import elw_exp_ccnl
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] 실시간시세 - ELW 실시간예상체결[실시간-063]
##############################################################################################
COLUMN_MAPPING = {
"mksc_shrn_iscd": "유가증권단축종목코드",
"stck_cntg_hour": "주식체결시간",
"stck_prpr": "주식현재가",
"prdy_vrss_sign": "전일대비부호",
"prdy_vrss": "전일대비",
"prdy_ctrt": "전일대비율",
"wghn_avrg_stck_prc": "가중평균주식가격",
"stck_oprc": "주식시가2",
"stck_hgpr": "주식최고가",
"stck_lwpr": "주식최저가",
"askp1": "매도호가1",
"bidp1": "매수호가1",
"cntg_vol": "체결거래량",
"acml_vol": "누적거래량",
"acml_tr_pbmn": "누적거래대금",
"seln_cntg_csnu": "매도체결건수",
"shnu_cntg_csnu": "매수체결건수",
"ntby_cntg_csnu": "순매수체결건수",
"cttr": "체결강도",
"seln_cntg_smtn": "총매도수량",
"shnu_cntg_smtn": "총매수수량",
"cntg_cls_code": "체결구분코드",
"shnu_rate": "매수2비율",
"prdy_vol_vrss_acml_vol_rate": "전일거래량대비등락율",
"oprc_hour": "시가시간",
"oprc_vrss_prpr_sign": "시가2대비현재가부호",
"oprc_vrss_prpr": "시가2대비현재가",
"hgpr_hour": "최고가시간",
"hgpr_vrss_prpr_sign": "최고가대비현재가부호",
"hgpr_vrss_prpr": "최고가대비현재가",
"lwpr_hour": "최저가시간",
"lwpr_vrss_prpr_sign": "최저가대비현재가부호",
"lwpr_vrss_prpr": "최저가대비현재가",
"bsop_date": "영업일자",
"new_mkop_cls_code": "신장운영구분코드",
"trht_yn": "거래정지여부",
"askp_rsqn1": "매도호가잔량1",
"bidp_rsqn1": "매수호가잔량1",
"total_askp_rsqn": "총매도호가잔량",
"total_bidp_rsqn": "총매수호가잔량",
"tmvl_val": "시간가치값",
"prit": "패리티",
"prmm_val": "프리미엄값",
"gear": "기어링",
"prls_qryr_rate": "손익분기비율",
"invl_val": "내재가치값",
"prmm_rate": "프리미엄비율",
"cfp": "자본지지점",
"lvrg_val": "레버리지값",
"delta": "델타",
"gama": "감마",
"vega": "베가",
"theta": "세타",
"rho": "로우",
"hts_ints_vltl": "HTS내재변동성",
"hts_thpr": "HTS이론가",
"vol_tnrt": "거래량회전율",
"lp_hvol": "LP보유량",
"lp_hldn_rate": "LP보유비율"
}
NUMERIC_COLUMNS = [
"주식현재가", "전일대비", "전일대비율", "가중평균주식가격", "주식시가2", "주식최고가", "주식최저가",
"매도호가1", "매수호가1", "체결거래량", "누적거래량", "누적거래대금", "매도체결건수", "매수체결건수",
"순매수체결건수", "체결강도", "총매도수량", "총매수수량", "매수2비율", "전일거래량대비등락율",
"시가2대비현재가", "최고가대비현재가", "최저가대비현재가", "매도호가잔량1", "매수호가잔량1",
"총매도호가잔량", "총매수호가잔량", "시간가치값", "패리티", "프리미엄값", "기어링", "손익분기비율",
"내재가치값", "프리미엄비율", "자본지지점", "레버리지값", "델타", "감마", "베가", "세타", "로우",
"HTS내재변동성", "HTS이론가", "거래량회전율", "LP보유량", "LP보유비율"
]
def main():
"""
ELW 실시간예상체결
ELW 실시간예상체결 API입니다.
[참고자료]
종목코드 마스터파일 파이썬 정제코드는 한국투자증권 Github 참고 부탁드립니다.
https://github.com/koreainvestment/open-trading-api/tree/main/stocks_info
[호출 데이터]
헤더와 바디 값을 합쳐 JSON 형태로 전송합니다.
[응답 데이터]
1. 정상 등록 여부 (JSON)
- JSON["body"]["msg1"] - 정상 응답 시, SUBSCRIBE SUCCESS
- JSON["body"]["output"]["iv"] - 실시간 결과 복호화에 필요한 AES256 IV (Initialize Vector)
- JSON["body"]["output"]["key"] - 실시간 결과 복호화에 필요한 AES256 Key
2. 실시간 결과 응답 ( | 로 구분되는 값)
ex) 0|H0STCNT0|004|005930^123929^73100^5^...
- 암호화 유무 : 0 암호화 되지 않은 데이터 / 1 암호화된 데이터
- TR_ID : 등록한 tr_id (ex. H0STCNT0)
- 데이터 건수 : (ex. 001 인 경우 데이터 건수 1건, 004인 경우 데이터 건수 4건)
- 응답 데이터 : 아래 response 데이터 참조 ( ^로 구분됨)
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
ka.auth_ws()
# 인증(auth_ws()) 이후에 선언
kws = ka.KISWebSocket(api_url="/tryitout")
# API 호출
logger.info("API 호출")
kws.subscribe(request=elw_exp_ccnl, data=["57LA24","57L739","57L650","57L966","52L181","57LB38"])
# 결과 표시
def on_result(ws, tr_id: str, result: pd.DataFrame, data_map: dict):
try:
# 숫자형 컬럼 소수점 둘째자리까지 표시
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
logging.info("결과:")
print(result)
except Exception as e:
logging.error(f"결과 처리 중 오류: {e}")
logging.error(f"받은 데이터: {result}")
kws.start(on_result=on_result)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,121 @@
"""
Created on 2025-07-09
"""
import logging
import sys
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] 실시간시세 - ELW 실시간예상체결[실시간-063]
##############################################################################################
def elw_exp_ccnl(
tr_type: str,
tr_key: str,
) -> tuple[dict, list[str]]:
"""
ELW 실시간예상체결[H0EWANC0]
ELW 실시간예상체결 API입니다. 이 함수는 웹소켓을 통해 실시간 데이터를 구독합니다.
Args:
tr_type (str): [필수] 구독 등록("1") 또는 해제("0") 여부를 나타냅니다.
tr_key (str): [필수] 종목코드. 빈 문자열일 수 없습니다.
Returns:
message (dict): 메시지 데이터
columns (list[str]): 응답 데이터의 컬럼 정보
Raises:
ValueError: tr_key가 빈 문자열인 경우 발생합니다.
Example:
>>> msg, columns = elw_exp_ccnl("1", "005930")
>>> print(msg, columns)
"""
# 필수 파라미터 검증
if not tr_key:
raise ValueError("tr_key is required and cannot be an empty string")
tr_id = "H0EWANC0"
params = {
"tr_key": tr_key,
}
# 데이터 구독 요청
msg = ka.data_fetch(tr_id, tr_type, params)
# 응답 데이터의 컬럼 정보
columns = [
"mksc_shrn_iscd",
"stck_cntg_hour",
"stck_prpr",
"prdy_vrss_sign",
"prdy_vrss",
"prdy_ctrt",
"wghn_avrg_stck_prc",
"stck_oprc",
"stck_hgpr",
"stck_lwpr",
"askp1",
"bidp1",
"cntg_vol",
"acml_vol",
"acml_tr_pbmn",
"seln_cntg_csnu",
"shnu_cntg_csnu",
"ntby_cntg_csnu",
"cttr",
"seln_cntg_smtn",
"shnu_cntg_smtn",
"cntg_cls_code",
"shnu_rate",
"prdy_vol_vrss_acml_vol_rate",
"oprc_hour",
"oprc_vrss_prpr_sign",
"oprc_vrss_prpr",
"hgpr_hour",
"hgpr_vrss_prpr_sign",
"hgpr_vrss_prpr",
"lwpr_hour",
"lwpr_vrss_prpr_sign",
"lwpr_vrss_prpr",
"bsop_date",
"new_mkop_cls_code",
"trht_yn",
"askp_rsqn1",
"bidp_rsqn1",
"total_askp_rsqn",
"total_bidp_rsqn",
"tmvl_val",
"prit",
"prmm_val",
"gear",
"prls_qryr_rate",
"invl_val",
"prmm_rate",
"cfp",
"lvrg_val",
"delta",
"gama",
"vega",
"theta",
"rho",
"hts_ints_vltl",
"hts_thpr",
"vol_tnrt",
"lp_hvol",
"lp_hldn_rate",
]
return msg, columns

View File

@@ -0,0 +1,128 @@
"""
Created on 2025-06-19
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from expiration_stocks import expiration_stocks
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 만기예정/만기종목[국내주식-184]
##############################################################################################
COLUMN_MAPPING = {
'elw_shrn_iscd': 'ELW단축종목코드',
'elw_kor_isnm': 'ELW한글종목명',
'unas_isnm': '기초자산종목명',
'unas_prpr': '기초자산현재가',
'acpr': '행사가',
'stck_cnvr_rate': '주식전환비율',
'elw_prpr': 'ELW현재가',
'stck_lstn_date': '주식상장일자',
'stck_last_tr_date': '주식최종거래일자',
'total_rdmp_amt': '총상환금액',
'rdmp_amt': '상환금액',
'lstn_stcn': '상장주수',
'lp_hvol': 'LP보유량',
'ccls_paym_prc': '확정지급2가격',
'mtrt_vltn_amt': '만기평가금액',
'evnt_prd_fin_date': '행사2기간종료일자',
'stlm_date': '결제일자',
'pblc_prc': '발행가격',
'unas_shrn_iscd': '기초자산단축종목코드',
'stnd_iscd': '표준종목코드',
'rdmp_ask_amt': '상환청구금액'
}
NUMERIC_COLUMNS = [
'기초자산현재가', '행사가', '주식전환비율', 'ELW현재가', '총상환금액', '상환금액',
'상장주수', 'LP보유량', '확정지급2가격', '만기평가금액', '발행가격', '상환청구금액'
]
def main():
"""
[국내주식] ELW시세
ELW 만기예정_만기종목[국내주식-184]
ELW 만기예정_만기종목 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (W 입력)
- fid_cond_scr_div_code (str): 조건화면분류코드 (11547 입력)
- fid_input_date_1 (str): 입력날짜1 (입력날짜 ~ (ex) 20240402))
- fid_input_date_2 (str): 입력날짜2 (~입력날짜 (ex) 20240408))
- fid_div_cls_code (str): 분류구분코드 (0(콜),1(풋),2(전체))
- fid_etc_cls_code (str): 기타구분코드 (공백 입력)
- fid_unas_input_iscd (str): 기초자산입력종목코드 (000000(전체), 2001(KOSPI 200), 기초자산코드(종목코드 ex. 삼성전자-005930))
- fid_input_iscd_2 (str): 발행회사코드 (00000(전체), 00003(한국투자증권), 00017(KB증권), 00005(미래에셋증권))
- fid_blng_cls_code (str): 결제방법 (0(전체),1(일반),2(조기종료))
- fid_input_option_1 (str): 입력옵션1 (공백 입력)
Returns:
- DataFrame: ELW 만기예정_만기종목 결과
Example:
>>> df = expiration_stocks(fid_cond_mrkt_div_code="W", fid_cond_scr_div_code="11547", fid_input_date_1="20240402", fid_input_date_2="20240408", fid_div_cls_code="2", fid_etc_cls_code="", fid_unas_input_iscd="000000", fid_input_iscd_2="00000", fid_blng_cls_code="0", fid_input_option_1="")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result = expiration_stocks(
fid_cond_mrkt_div_code="W", # 조건시장분류코드
fid_cond_scr_div_code="11547", # 조건화면분류코드
fid_input_date_1="20250101", # 입력날짜1
fid_input_date_2="20250930", # 입력날짜2
fid_div_cls_code="2", # 분류구분코드
fid_etc_cls_code="", # 기타구분코드
fid_unas_input_iscd="000000", # 기초자산입력종목코드
fid_input_iscd_2="00000", # 발행회사코드
fid_blng_cls_code="0", # 결제방법
fid_input_option_1="", # 입력옵션1
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 결과 출력
logger.info("=== ELW 만기예정_만기종목 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,179 @@
"""
Created on 2025-06-19
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 만기예정/만기종목[국내주식-184]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/quotations/expiration-stocks"
def expiration_stocks(
fid_cond_mrkt_div_code: str, # 조건시장분류코드
fid_cond_scr_div_code: str, # 조건화면분류코드
fid_input_date_1: str, # 입력날짜1
fid_input_date_2: str, # 입력날짜2
fid_div_cls_code: str, # 분류구분코드
fid_etc_cls_code: str, # 기타구분코드
fid_unas_input_iscd: str, # 기초자산입력종목코드
fid_input_iscd_2: str, # 발행회사코드
fid_blng_cls_code: str, # 결제방법
fid_input_option_1: str, # 입력옵션1
tr_cont: str = "",
dataframe: Optional[pd.DataFrame] = None,
depth: int = 0,
max_depth: int = 10
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 만기예정_만기종목[국내주식-184]
ELW 만기예정_만기종목 API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): W 입력
fid_cond_scr_div_code (str): 11547 입력
fid_input_date_1 (str): 입력날짜 ~ (ex) 20240402)
fid_input_date_2 (str): ~입력날짜 (ex) 20240408)
fid_div_cls_code (str): 0(콜),1(풋),2(전체)
fid_etc_cls_code (str): 공백 입력
fid_unas_input_iscd (str): 000000(전체), 2001(KOSPI 200), 기초자산코드(종목코드 ex. 삼성전자-005930)
fid_input_iscd_2 (str): 00000(전체), 00003(한국투자증권), 00017(KB증권), 00005(미래에셋증권)
fid_blng_cls_code (str): 0(전체),1(일반),2(조기종료)
fid_input_option_1 (str): 공백 입력
tr_cont (str): 연속 거래 여부
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임
depth (int): 현재 재귀 깊이
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 만기예정_만기종목 데이터
Example:
>>> df = expiration_stocks(
... fid_cond_mrkt_div_code='W',
... fid_cond_scr_div_code='11547',
... fid_input_date_1='20240402',
... fid_input_date_2='20240408',
... fid_div_cls_code='0',
... fid_etc_cls_code='',
... fid_unas_input_iscd='000000',
... fid_input_iscd_2='00000',
... fid_blng_cls_code='0',
... fid_input_option_1='',
... )
>>> print(df)
"""
# 로깅 설정
logger = logging.getLogger(__name__)
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_cond_scr_div_code:
logger.error("fid_cond_scr_div_code is required. (e.g. '11547')")
raise ValueError("fid_cond_scr_div_code is required. (e.g. '11547')")
if not fid_input_date_1:
logger.error("fid_input_date_1 is required. (e.g. '20240402')")
raise ValueError("fid_input_date_1 is required. (e.g. '20240402')")
if not fid_input_date_2:
logger.error("fid_input_date_2 is required. (e.g. '20240408')")
raise ValueError("fid_input_date_2 is required. (e.g. '20240408')")
if not fid_div_cls_code:
logger.error("fid_div_cls_code is required. (e.g. '0')")
raise ValueError("fid_div_cls_code is required. (e.g. '0')")
if not fid_unas_input_iscd:
logger.error("fid_unas_input_iscd is required. (e.g. '000000')")
raise ValueError("fid_unas_input_iscd is required. (e.g. '000000')")
if not fid_input_iscd_2:
logger.error("fid_input_iscd_2 is required. (e.g. '00000')")
raise ValueError("fid_input_iscd_2 is required. (e.g. '00000')")
if not fid_blng_cls_code:
logger.error("fid_blng_cls_code is required. (e.g. '0')")
raise ValueError("fid_blng_cls_code is required. (e.g. '0')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
tr_id = "FHKEW154700C0"
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_COND_SCR_DIV_CODE": fid_cond_scr_div_code,
"FID_INPUT_DATE_1": fid_input_date_1,
"FID_INPUT_DATE_2": fid_input_date_2,
"FID_DIV_CLS_CODE": fid_div_cls_code,
"FID_ETC_CLS_CODE": fid_etc_cls_code,
"FID_UNAS_INPUT_ISCD": fid_unas_input_iscd,
"FID_INPUT_ISCD_2": fid_input_iscd_2,
"FID_BLNG_CLS_CODE": fid_blng_cls_code,
"FID_INPUT_OPTION_1": fid_input_option_1,
}
# API 호출
res = ka._url_fetch(API_URL, tr_id, tr_cont, params)
if res.isOK():
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return expiration_stocks(
fid_cond_mrkt_div_code,
fid_cond_scr_div_code,
fid_input_date_1,
fid_input_date_2,
fid_div_cls_code,
fid_etc_cls_code,
fid_unas_input_iscd,
fid_input_iscd_2,
fid_blng_cls_code,
fid_input_option_1,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()

View File

@@ -0,0 +1,123 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from indicator import indicator
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 지표순위[국내주식-169]
##############################################################################################
COLUMN_MAPPING = {
'elw_shrn_iscd': 'ELW단축종목코드',
'elw_kor_isnm': 'ELW한글종목명',
'elw_prpr': 'ELW현재가',
'prdy_vrss': '전일대비',
'prdy_vrss_sign': '전일대비부호',
'prdy_ctrt': '전일대비율',
'acml_vol': '누적거래량',
'stck_cnvr_rate': '주식전환비율',
'lvrg_val': '레버리지값',
'acpr': '행사가',
'tmvl_val': '시간가치값',
'invl_val': '내재가치값',
'elw_ko_barrier': '조기종료발생기준가격'
}
NUMERIC_COLUMNS = [
'ELW현재가', '전일대비', '전일대비율', '누적거래량', '주식전환비율',
'레버리지값', '행사가', '시간가치값', '내재가치값', '조기종료발생기준가격'
]
def main():
"""
[국내주식] ELW시세
ELW 지표순위[국내주식-169]
ELW 지표순위 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (시장구분코드 (W))
- fid_cond_scr_div_code (str): 조건화면분류코드 (Unique key(20279))
- fid_unas_input_iscd (str): 기초자산입력종목코드 ('000000(전체), 2001(코스피200) , 3003(코스닥150), 005930(삼성전자) ')
- fid_input_iscd (str): 발행사 ('00000(전체), 00003(한국투자증권) , 00017(KB증권), 00005(미래에셋주식회사)')
- fid_div_cls_code (str): 콜풋구분코드 (0(전체), 1(콜), 2(풋))
- fid_input_price_1 (str): 가격(이상) ()
- fid_input_price_2 (str): 가격(이하) ()
- fid_input_vol_1 (str): 거래량(이상) ()
- fid_input_vol_2 (str): 거래량(이하) ()
- fid_rank_sort_cls_code (str): 순위정렬구분코드 (0(전환비율), 1(레버리지), 2(행사가 ), 3(내재가치), 4(시간가치))
- fid_blng_cls_code (str): 결재방법 (0(전체), 1(일반), 2(조기종료))
Returns:
- DataFrame: ELW 지표순위 결과
Example:
>>> df = indicator(fid_cond_mrkt_div_code="W", fid_cond_scr_div_code="20279", fid_unas_input_iscd="000000", fid_input_iscd="00000", fid_div_cls_code="0", fid_input_price_1="", fid_input_price_2="", fid_input_vol_1="", fid_input_vol_2="", fid_rank_sort_cls_code="0", fid_blng_cls_code="0")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result = indicator(
fid_cond_mrkt_div_code="W", # 조건시장분류코드
fid_cond_scr_div_code="20279", # 조건화면분류코드
fid_unas_input_iscd="000000", # 기초자산입력종목코드
fid_input_iscd="00000", # 발행사
fid_div_cls_code="0", # 콜풋구분코드
fid_input_price_1="", # 가격(이상)
fid_input_price_2="", # 가격(이하)
fid_input_vol_1="", # 거래량(이상)
fid_input_vol_2="", # 거래량(이하)
fid_rank_sort_cls_code="0", # 순위정렬구분코드
fid_blng_cls_code="0", # 결재방법
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 결과 출력
logger.info("=== ELW 지표순위 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,180 @@
"""
Created on 2025-06-18
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 지표순위[국내주식-169]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/ranking/indicator"
def indicator(
fid_cond_mrkt_div_code: str, # 조건시장분류코드
fid_cond_scr_div_code: str, # 조건화면분류코드
fid_unas_input_iscd: str, # 기초자산입력종목코드
fid_input_iscd: str, # 발행사
fid_div_cls_code: str, # 콜풋구분코드
fid_input_price_1: str, # 가격(이상)
fid_input_price_2: str, # 가격(이하)
fid_input_vol_1: str, # 거래량(이상)
fid_input_vol_2: str, # 거래량(이하)
fid_rank_sort_cls_code: str, # 순위정렬구분코드
fid_blng_cls_code: str, # 결재방법
tr_cont: str = "", # 연속 거래 여부
dataframe: Optional[pd.DataFrame] = None, # 누적 데이터프레임
depth: int = 0, # 현재 재귀 깊이
max_depth: int = 10 # 최대 재귀 깊이
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 지표순위[국내주식-169]
ELW 지표순위 API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 조건시장분류코드 (필수)
fid_cond_scr_div_code (str): 조건화면분류코드 (필수)
fid_unas_input_iscd (str): 기초자산입력종목코드 (필수)
fid_input_iscd (str): 발행사 (필수)
fid_div_cls_code (str): 콜풋구분코드 (필수)
fid_input_price_1 (str): 가격(이상) (필수)
fid_input_price_2 (str): 가격(이하) (필수)
fid_input_vol_1 (str): 거래량(이상) (필수)
fid_input_vol_2 (str): 거래량(이하) (필수)
fid_rank_sort_cls_code (str): 순위정렬구분코드 (필수)
fid_blng_cls_code (str): 결재방법 (필수)
tr_cont (str): 연속 거래 여부 (옵션)
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임 (옵션)
depth (int): 현재 재귀 깊이 (옵션)
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 지표순위 데이터
Example:
>>> df = indicator(
... fid_cond_mrkt_div_code='W',
... fid_cond_scr_div_code='20279',
... fid_unas_input_iscd='000000',
... fid_input_iscd='00000',
... fid_div_cls_code='0',
... fid_input_price_1='1000',
... fid_input_price_2='5000',
... fid_input_vol_1='100',
... fid_input_vol_2='1000',
... fid_rank_sort_cls_code='0',
... fid_blng_cls_code='0'
... )
>>> print(df)
"""
# 로깅 설정
logger = logging.getLogger(__name__)
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_cond_scr_div_code:
logger.error("fid_cond_scr_div_code is required. (e.g. '20279')")
raise ValueError("fid_cond_scr_div_code is required. (e.g. '20279')")
if not fid_unas_input_iscd:
logger.error("fid_unas_input_iscd is required. (e.g. '000000')")
raise ValueError("fid_unas_input_iscd is required. (e.g. '000000')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. '00000')")
raise ValueError("fid_input_iscd is required. (e.g. '00000')")
if not fid_div_cls_code:
logger.error("fid_div_cls_code is required. (e.g. '0')")
raise ValueError("fid_div_cls_code is required. (e.g. '0')")
if not fid_rank_sort_cls_code:
logger.error("fid_rank_sort_cls_code is required. (e.g. '0')")
raise ValueError("fid_rank_sort_cls_code is required. (e.g. '0')")
if not fid_blng_cls_code:
logger.error("fid_blng_cls_code is required. (e.g. '0')")
raise ValueError("fid_blng_cls_code is required. (e.g. '0')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
tr_id = "FHPEW02790000"
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_COND_SCR_DIV_CODE": fid_cond_scr_div_code,
"FID_UNAS_INPUT_ISCD": fid_unas_input_iscd,
"FID_INPUT_ISCD": fid_input_iscd,
"FID_DIV_CLS_CODE": fid_div_cls_code,
"FID_INPUT_PRICE_1": fid_input_price_1,
"FID_INPUT_PRICE_2": fid_input_price_2,
"FID_INPUT_VOL_1": fid_input_vol_1,
"FID_INPUT_VOL_2": fid_input_vol_2,
"FID_RANK_SORT_CLS_CODE": fid_rank_sort_cls_code,
"FID_BLNG_CLS_CODE": fid_blng_cls_code,
}
# API 호출
res = ka._url_fetch(API_URL, tr_id, tr_cont, params)
if res.isOK():
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return indicator(
fid_cond_mrkt_div_code,
fid_cond_scr_div_code,
fid_unas_input_iscd,
fid_input_iscd,
fid_div_cls_code,
fid_input_price_1,
fid_input_price_2,
fid_input_vol_1,
fid_input_vol_2,
fid_rank_sort_cls_code,
fid_blng_cls_code,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()

View File

@@ -0,0 +1,104 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from indicator_trend_ccnl import indicator_trend_ccnl
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 투자지표추이(체결)[국내주식-172]
##############################################################################################
COLUMN_MAPPING = {
'stck_cntg_hour': '주식체결시간',
'elw_prpr': 'ELW현재가',
'prdy_vrss_sign': '전일대비부호',
'prdy_vrss': '전일대비',
'prdy_ctrt': '전일대비율',
'acml_vol': '누적거래량',
'lvrg_val': '레버리지값',
'gear': '기어링',
'tmvl_val': '시간가치값',
'invl_val': '내재가치값',
'prit': '패리티',
'apprch_rate': '접근도'
}
NUMERIC_COLUMNS = [
'ELW현재가', '전일대비', '전일대비율', '누적거래량', '레버리지값',
'기어링', '시간가치값', '내재가치값', '패리티', '접근도'
]
def main():
"""
[국내주식] ELW시세
ELW 투자지표추이(체결)[국내주식-172]
ELW 투자지표추이(체결) 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (시장구분코드 (W))
- fid_input_iscd (str): 입력종목코드 (ex) 58J297(KBJ297삼성전자콜))
Returns:
- DataFrame: ELW 투자지표추이(체결) 결과
Example:
>>> df = indicator_trend_ccnl(fid_cond_mrkt_div_code="W", fid_input_iscd="58J297")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result = indicator_trend_ccnl(
fid_cond_mrkt_div_code="W", # 조건시장분류코드
fid_input_iscd="57LA50", # 입력종목코드
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 결과 출력
logger.info("=== ELW 투자지표추이(체결) 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,114 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 투자지표추이(체결)[국내주식-172]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/quotations/indicator-trend-ccnl"
def indicator_trend_ccnl(
fid_cond_mrkt_div_code: str, # 조건시장분류코드
fid_input_iscd: str, # 입력종목코드
tr_cont: str = "",
dataframe: Optional[pd.DataFrame] = None,
depth: int = 0,
max_depth: int = 10
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 투자지표추이(체결)[국내주식-172]
ELW 투자지표추이(체결) API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 조건시장분류코드 (필수)
fid_input_iscd (str): 입력종목코드 (필수)
tr_cont (str): 연속 거래 여부 (기본값: "")
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임 (기본값: None)
depth (int): 현재 재귀 깊이 (기본값: 0)
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 투자지표추이(체결) 데이터
Example:
>>> df = indicator_trend_ccnl("W", "58J297")
>>> print(df)
"""
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. '58J297')")
raise ValueError("fid_input_iscd is required. (e.g. '58J297')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
tr_id = "FHPEW02740100"
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_INPUT_ISCD": fid_input_iscd,
}
# API 호출
res = ka._url_fetch(API_URL, tr_id, tr_cont, params)
if res.isOK():
# 응답 데이터 처리
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
# 데이터프레임 병합
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
# 연속 거래 여부 확인
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return indicator_trend_ccnl(
fid_cond_mrkt_div_code,
fid_input_iscd,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
# API 에러 처리
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()

View File

@@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from indicator_trend_daily import indicator_trend_daily
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 투자지표추이(일별)[국내주식-173]
##############################################################################################
COLUMN_MAPPING = {
'stck_bsop_date': '주식영업일자',
'elw_prpr': 'ELW현재가',
'prdy_vrss_sign': '전일대비부호',
'prdy_vrss': '전일대비',
'prdy_ctrt': '전일대비율',
'acml_vol': '누적거래량',
'lvrg_val': '레버리지값',
'gear': '기어링',
'tmvl_val': '시간가치값',
'invl_val': '내재가치값',
'prit': '패리티',
'elw_oprc': 'ELW시가2',
'elw_hgpr': 'ELW최고가',
'elw_lwpr': 'ELW최저가',
'apprch_rate': '접근도'
}
NUMERIC_COLUMNS = [
'ELW현재가', '전일대비', '전일대비율', '누적거래량', '레버리지값', '기어링',
'시간가치값', '내재가치값', '패리티', 'ELW시가2', 'ELW최고가', 'ELW최저가', '접근도'
]
def main():
"""
[국내주식] ELW시세
ELW 투자지표추이(일별)[국내주식-173]
ELW 투자지표추이(일별) 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 시장 분류 코드 (예: 'W')
- fid_input_iscd (str): 종목코드 (6자리, 예: '57K281')
Returns:
- DataFrame: ELW 투자지표추이(일별) 결과
Example:
>>> df = indicator_trend_daily(fid_cond_mrkt_div_code="W", fid_input_iscd="57K281")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result = indicator_trend_daily(
fid_cond_mrkt_div_code="W", # 시장 분류 코드
fid_input_iscd="57K281", # 종목코드
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 숫자형 컬럼 소수점 둘째자리까지 표시
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 결과 출력
logger.info("=== ELW 투자지표추이(일별) 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,109 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 투자지표추이(일별)[국내주식-173]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/quotations/indicator-trend-daily"
def indicator_trend_daily(
fid_cond_mrkt_div_code: str, # 시장 분류 코드 (예: 'W')
fid_input_iscd: str, # 종목코드 (6자리)
tr_cont: str = "",
dataframe: Optional[pd.DataFrame] = None,
depth: int = 0,
max_depth: int = 10
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 투자지표추이(일별)[국내주식-173]
ELW 투자지표추이(일별) API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 시장 분류 코드 (예: 'W')
fid_input_iscd (str): 종목코드 (6자리, 예: '57K281')
tr_cont (str): 연속 거래 여부
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임
depth (int): 현재 재귀 깊이
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 투자지표추이(일별) 데이터
Example:
>>> df = indicator_trend_daily('W', '57K281')
"""
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. '57K281')")
raise ValueError("fid_input_iscd is required. (e.g. '57K281')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
tr_id = "FHPEW02740200"
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_INPUT_ISCD": fid_input_iscd,
}
# API 호출
res = ka._url_fetch(API_URL, tr_id, tr_cont, params)
if res.isOK():
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return indicator_trend_daily(
fid_cond_mrkt_div_code,
fid_input_iscd,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()

View File

@@ -0,0 +1,109 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from indicator_trend_minute import indicator_trend_minute
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 투자지표추이(분별)[국내주식-174]
##############################################################################################
COLUMN_MAPPING = {
'stck_bsop_date': '주식영업일자',
'stck_cntg_hour': '주식체결시간',
'elw_prpr': 'ELW현재가',
'elw_oprc': 'ELW시가2',
'elw_hgpr': 'ELW최고가',
'elw_lwpr': 'ELW최저가',
'lvrg_val': '레버리지값',
'gear': '기어링',
'prmm_val': '프리미엄값',
'invl_val': '내재가치값',
'prit': '패리티',
'acml_vol': '누적거래량',
'cntg_vol': '체결거래량'
}
NUMERIC_COLUMNS = [
'ELW현재가', 'ELW시가2', 'ELW최고가', 'ELW최저가', '레버리지값', '기어링',
'프리미엄값', '내재가치값', '패리티', '누적거래량', '체결거래량'
]
def main():
"""
[국내주식] ELW시세
ELW 투자지표추이(분별)[국내주식-174]
ELW 투자지표추이(분별) 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (시장구분코드 (W))
- fid_input_iscd (str): 입력종목코드 (ex) 58J297(KBJ297삼성전자콜))
- fid_hour_cls_code (str): 시간구분코드 ('60(1분), 180(3분), 300(5분), 600(10분), 1800(30분), 3600(60분), 7200(60분) ')
- fid_pw_data_incu_yn (str): 과거데이터 포함 여부 (N(과거데이터포함X),Y(과거데이터포함O))
Returns:
- DataFrame: ELW 투자지표추이(분별) 결과
Example:
>>> df = indicator_trend_minute(fid_cond_mrkt_div_code="W", fid_input_iscd="58J297", fid_hour_cls_code="60", fid_pw_data_incu_yn="N")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result = indicator_trend_minute(
fid_cond_mrkt_div_code="W", # 조건시장분류코드
fid_input_iscd="57LA50", # 입력종목코드
fid_hour_cls_code="60", # 시간구분코드
fid_pw_data_incu_yn="N", # 과거데이터 포함 여부
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 결과 출력
logger.info("=== ELW 투자지표추이(분별) 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,141 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 투자지표추이(분별)[국내주식-174]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/quotations/indicator-trend-minute"
def indicator_trend_minute(
fid_cond_mrkt_div_code: str, # 조건시장분류코드
fid_input_iscd: str, # 입력종목코드
fid_hour_cls_code: str, # 시간구분코드
fid_pw_data_incu_yn: str, # 과거데이터 포함 여부
tr_cont: str = "", # 연속 거래 여부
dataframe: Optional[pd.DataFrame] = None, # 누적 데이터프레임
depth: int = 0, # 현재 재귀 깊이
max_depth: int = 10 # 최대 재귀 깊이
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 투자지표추이(분별)[국내주식-174]
ELW 투자지표추이(분별) API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 시장구분코드 (W)
fid_input_iscd (str): 입력종목코드 예시: 58J297(KBJ297삼성전자콜)
fid_hour_cls_code (str): 시간구분코드 예시: '60(1분), 180(3분), 300(5분), 600(10분), 1800(30분), 3600(60분), 7200(60분)'
fid_pw_data_incu_yn (str): 과거데이터 포함 여부 예시: N(과거데이터포함X), Y(과거데이터포함O)
tr_cont (str): 연속 거래 여부
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임
depth (int): 현재 재귀 깊이
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 투자지표추이(분별) 데이터
Example:
>>> df = indicator_trend_minute(
... fid_cond_mrkt_div_code='W',
... fid_input_iscd='58J297',
... fid_hour_cls_code='60',
... fid_pw_data_incu_yn='N'
... )
>>> print(df)
"""
# 로깅 설정
logger = logging.getLogger(__name__)
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. '58J297')")
raise ValueError("fid_input_iscd is required. (e.g. '58J297')")
if not fid_hour_cls_code:
logger.error("fid_hour_cls_code is required. (e.g. '60')")
raise ValueError("fid_hour_cls_code is required. (e.g. '60')")
if not fid_pw_data_incu_yn:
logger.error("fid_pw_data_incu_yn is required. (e.g. 'N')")
raise ValueError("fid_pw_data_incu_yn is required. (e.g. 'N')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
# API 호출 URL 및 거래 ID 설정
url = API_URL
tr_id = "FHPEW02740300"
# 요청 파라미터 설정
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_INPUT_ISCD": fid_input_iscd,
"FID_HOUR_CLS_CODE": fid_hour_cls_code,
"FID_PW_DATA_INCU_YN": fid_pw_data_incu_yn,
}
# API 호출
res = ka._url_fetch(url, tr_id, tr_cont, params)
# API 호출 성공 여부 확인
if res.isOK():
# 응답 데이터 처리
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
# 데이터프레임 병합
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
# 연속 거래 여부 확인
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return indicator_trend_minute(
fid_cond_mrkt_div_code,
fid_input_iscd,
fid_hour_cls_code,
fid_pw_data_incu_yn,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
# API 호출 실패 시 에러 로그 출력
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()

View File

@@ -0,0 +1,132 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
import lp_trade_trend
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW LP매매추이[국내주식-182]
##############################################################################################
COLUMN_MAPPING = {
'cntg_hour': '체결시간',
'elw_prpr': 'ELW현재가',
'prdy_vrss_sign': '전일대비부호',
'prdy_vrss': '전일대비',
'prdy_ctrt': '전일대비율',
'acml_vol': '누적거래량',
'acml_tr_pbmn': '누적거래대금',
'lp_buy_qty': 'LP매수수량',
'lp_sell_qty': 'LP매도수량',
'lp_ntby_qty': 'LP순매수수량',
'lp_buy_amt': 'LP매수금액',
'lp_sell_amt': 'LP매도금액',
'lp_ntby_amt': 'LP순매수금액',
'inst_deal_qty': '기관매매수량',
'frgn_deal_qty': '외국인매매수량',
'prsn_deal_qty': '개인매매수량',
'apprch_rate': '접근도'
}
NUMERIC_COLUMNS = [
'ELW현재가', '전일대비', '전일대비율', '누적거래량', '누적거래대금',
'LP매수수량', 'LP매도수량', 'LP순매수수량', 'LP매수금액', 'LP매도금액',
'LP순매수금액', '기관매매수량', '외국인매매수량', '개인매매수량', '접근도'
]
def main():
"""
[국내주식] ELW시세
ELW LP매매추이[국내주식-182]
ELW LP매매추이 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (시장구분(W))
- fid_input_iscd (str): 입력종목코드 (입력종목코드(ex 52K577(미래 K577KOSDAQ150콜))
Returns:
- Tuple[DataFrame, ...]: ELW LP매매추이 결과
Example:
>>> df1, df2 = lp_trade_trend(fid_cond_mrkt_div_code="W", fid_input_iscd="52K577")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result1, result2 = lp_trade_trend.lp_trade_trend(
fid_cond_mrkt_div_code="W", # 조건시장분류코드
fid_input_iscd="52K577", # 입력종목코드
)
# 첫 번째 결과 처리
if result1 is None or result1.empty:
logger.warning("첫 번째 조회된 데이터가 없습니다.")
else:
# 컬럼명 출력
logger.info("첫 번째 결과 사용 가능한 컬럼 목록:")
logger.info(result1.columns.tolist())
# 한글 컬럼명으로 변환
result1 = result1.rename(columns=COLUMN_MAPPING)
# 숫자 컬럼 처리
for col in NUMERIC_COLUMNS:
if col in result1.columns:
result1[col] = pd.to_numeric(result1[col], errors='coerce').round(2)
# 결과 출력 (output1)
logger.info("=== output1 ===")
logger.info("조회된 데이터 건수: %d", len(result1))
print("output1:")
print(result1)
# 두 번째 결과 처리
if result2 is None or result2.empty:
logger.warning("두 번째 조회된 데이터가 없습니다.")
else:
# 컬럼명 출력
logger.info("두 번째 결과 사용 가능한 컬럼 목록:")
logger.info(result2.columns.tolist())
# 한글 컬럼명으로 변환
result2 = result2.rename(columns=COLUMN_MAPPING)
# 숫자 컬럼 처리
for col in NUMERIC_COLUMNS:
if col in result2.columns:
result2[col] = pd.to_numeric(result2[col], errors='coerce').round(2)
# 결과 출력 (output2)
logger.info("=== output2 ===")
logger.info("조회된 데이터 건수: %d", len(result2))
print("output2:")
print(result2)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,124 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import logging
import time
from typing import Optional, Tuple
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW LP매매추이[국내주식-182]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/quotations/lp-trade-trend"
def lp_trade_trend(
fid_cond_mrkt_div_code: str, # 조건시장분류코드
fid_input_iscd: str, # 입력종목코드
dataframe1: Optional[pd.DataFrame] = None, # 누적 데이터프레임 (output1)
dataframe2: Optional[pd.DataFrame] = None, # 누적 데이터프레임 (output2)
tr_cont: str = "",
depth: int = 0,
max_depth: int = 10
) -> Tuple[Optional[pd.DataFrame], Optional[pd.DataFrame]]:
"""
[국내주식] ELW시세
ELW LP매매추이[국내주식-182]
ELW LP매매추이 API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 시장구분(W)
fid_input_iscd (str): 입력종목코드(ex 52K577(미래 K577KOSDAQ150콜)
dataframe1 (Optional[pd.DataFrame]): 누적 데이터프레임 (output1)
dataframe2 (Optional[pd.DataFrame]): 누적 데이터프레임 (output2)
tr_cont (str): 연속 거래 여부
depth (int): 현재 재귀 깊이
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Tuple[pd.DataFrame, pd.DataFrame]: ELW LP매매추이 데이터
Example:
>>> df1, df2 = lp_trade_trend("W", "52K577")
>>> print(df1)
>>> print(df2)
"""
# 로깅 설정
logger = logging.getLogger(__name__)
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. '52K577')")
raise ValueError("fid_input_iscd is required. (e.g. '52K577')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe1 if dataframe1 is not None else pd.DataFrame(), dataframe2 if dataframe2 is not None else pd.DataFrame()
tr_id = "FHPEW03760000"
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_INPUT_ISCD": fid_input_iscd,
}
res = ka._url_fetch(API_URL, tr_id, tr_cont, params)
if res.isOK():
# output1 처리
if hasattr(res.getBody(), 'output1'):
output_data = res.getBody().output1
if output_data:
current_data1 = pd.DataFrame(output_data if isinstance(output_data, list) else [output_data])
dataframe1 = pd.concat([dataframe1, current_data1], ignore_index=True) if dataframe1 is not None else current_data1
else:
dataframe1 = dataframe1 if dataframe1 is not None else pd.DataFrame()
else:
dataframe1 = dataframe1 if dataframe1 is not None else pd.DataFrame()
# output2 처리
if hasattr(res.getBody(), 'output2'):
output_data = res.getBody().output2
if output_data:
current_data2 = pd.DataFrame(output_data if isinstance(output_data, list) else [output_data])
dataframe2 = pd.concat([dataframe2, current_data2], ignore_index=True) if dataframe2 is not None else current_data2
else:
dataframe2 = dataframe2 if dataframe2 is not None else pd.DataFrame()
else:
dataframe2 = dataframe2 if dataframe2 is not None else pd.DataFrame()
tr_cont = res.getHeader().tr_cont
if tr_cont in ["M", "F"]:
logger.info("Calling next page...")
ka.smart_sleep()
return lp_trade_trend(
fid_cond_mrkt_div_code,
fid_input_iscd,
"N", dataframe1, dataframe2, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe1, dataframe2
else:
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame(), pd.DataFrame()

View File

@@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from newly_listed import newly_listed
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 신규상장종목[국내주식-181]
##############################################################################################
COLUMN_MAPPING = {
'elw_shrn_iscd': 'ELW단축종목코드',
'unas_isnm': '기초자산종목명',
'lstn_stcn': '상장주수',
'acpr': '행사가',
'stck_last_tr_date': '주식최종거래일자',
'elw_ko_barrier': '조기종료발생기준가격'
}
NUMERIC_COLUMNS = [
'상장주수', '행사가'
]
def main():
"""
[국내주식] ELW시세
ELW 신규상장종목[국내주식-181]
ELW 신규상장종목 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (시장구분코드 (W))
- fid_cond_scr_div_code (str): 조건화면분류코드 (Unique key(11548))
- fid_div_cls_code (str): 분류구분코드 (전체(02), 콜(00), 풋(01))
- fid_unas_input_iscd (str): 기초자산입력종목코드 ('ex) 000000(전체), 2001(코스피200) , 3003(코스닥150), 005930(삼성전자) ')
- fid_input_iscd_2 (str): 입력종목코드2 ('00003(한국투자증권), 00017(KB증권), 00005(미래에셋증권)')
- fid_input_date_1 (str): 입력날짜1 (날짜 (ex) 20240402))
- fid_blng_cls_code (str): 결재방법 (0(전체), 1(일반), 2(조기종료))
Returns:
- DataFrame: ELW 신규상장종목 결과
Example:
>>> df = newly_listed(fid_cond_mrkt_div_code="W", fid_cond_scr_div_code="11548", fid_div_cls_code="02", fid_unas_input_iscd="000000", fid_input_iscd_2="00003", fid_input_date_1="20240402", fid_blng_cls_code="0")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result = newly_listed(
fid_cond_mrkt_div_code="W", # 조건시장분류코드
fid_cond_scr_div_code="11548", # 조건화면분류코드
fid_div_cls_code="02", # 분류구분코드
fid_unas_input_iscd="000000", # 기초자산입력종목코드
fid_input_iscd_2="00003", # 입력종목코드2
fid_input_date_1="20250601", # 입력날짜1
fid_blng_cls_code="0", # 결제방법
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 결과 출력
logger.info("=== ELW 신규상장종목 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,160 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 신규상장종목[국내주식-181]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/quotations/newly-listed"
def newly_listed(
fid_cond_mrkt_div_code: str, # 조건시장분류코드
fid_cond_scr_div_code: str, # 조건화면분류코드
fid_div_cls_code: str, # 분류구분코드
fid_unas_input_iscd: str, # 기초자산입력종목코드
fid_input_iscd_2: str, # 입력종목코드2
fid_input_date_1: str, # 입력날짜1
fid_blng_cls_code: str, # 결재방법
tr_cont: str = "", # 연속 거래 여부
dataframe: Optional[pd.DataFrame] = None, # 누적 데이터프레임
depth: int = 0, # 현재 재귀 깊이
max_depth: int = 10 # 최대 재귀 깊이
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 신규상장종목[국내주식-181]
ELW 신규상장종목 API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 시장구분코드 (W)
fid_cond_scr_div_code (str): Unique key(11548)
fid_div_cls_code (str): 전체(02), 콜(00), 풋(01)
fid_unas_input_iscd (str): 'ex) 000000(전체), 2001(코스피200) , 3003(코스닥150), 005930(삼성전자) '
fid_input_iscd_2 (str): '00003(한국투자증권), 00017(KB증권), 00005(미래에셋증권)'
fid_input_date_1 (str): 날짜 (ex) 20240402)
fid_blng_cls_code (str): 0(전체), 1(일반), 2(조기종료)
tr_cont (str): 연속 거래 여부
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임
depth (int): 현재 재귀 깊이
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 신규상장종목 데이터
Example:
>>> df = newly_listed(
... fid_cond_mrkt_div_code='W',
... fid_cond_scr_div_code='11548',
... fid_div_cls_code='02',
... fid_unas_input_iscd='000000',
... fid_input_iscd_2='00003',
... fid_input_date_1='20240402',
... fid_blng_cls_code='0'
... )
>>> print(df)
"""
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_cond_scr_div_code:
logger.error("fid_cond_scr_div_code is required. (e.g. '11548')")
raise ValueError("fid_cond_scr_div_code is required. (e.g. '11548')")
if not fid_div_cls_code:
logger.error("fid_div_cls_code is required. (e.g. '02')")
raise ValueError("fid_div_cls_code is required. (e.g. '02')")
if not fid_unas_input_iscd:
logger.error("fid_unas_input_iscd is required. (e.g. '000000')")
raise ValueError("fid_unas_input_iscd is required. (e.g. '000000')")
if not fid_input_iscd_2:
logger.error("fid_input_iscd_2 is required. (e.g. '00003')")
raise ValueError("fid_input_iscd_2 is required. (e.g. '00003')")
if not fid_input_date_1:
logger.error("fid_input_date_1 is required. (e.g. '20240402')")
raise ValueError("fid_input_date_1 is required. (e.g. '20240402')")
if not fid_blng_cls_code:
logger.error("fid_blng_cls_code is required. (e.g. '0')")
raise ValueError("fid_blng_cls_code is required. (e.g. '0')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
tr_id = "FHKEW154800C0"
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_COND_SCR_DIV_CODE": fid_cond_scr_div_code,
"FID_DIV_CLS_CODE": fid_div_cls_code,
"FID_UNAS_INPUT_ISCD": fid_unas_input_iscd,
"FID_INPUT_ISCD_2": fid_input_iscd_2,
"FID_INPUT_DATE_1": fid_input_date_1,
"FID_BLNG_CLS_CODE": fid_blng_cls_code,
}
# API 호출
res = ka._url_fetch(API_URL, tr_id, tr_cont, params)
if res.isOK():
# 응답 데이터 처리
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return newly_listed(
fid_cond_mrkt_div_code,
fid_cond_scr_div_code,
fid_div_cls_code,
fid_unas_input_iscd,
fid_input_iscd_2,
fid_input_date_1,
fid_blng_cls_code,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
# API 에러 처리
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()

View File

@@ -0,0 +1,130 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from quick_change import quick_change
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 당일급변종목[국내주식-171]
##############################################################################################
COLUMN_MAPPING = {
'elw_shrn_iscd': 'ELW단축종목코드',
'elw_kor_isnm': 'ELW한글종목명',
'elw_prpr': 'ELW현재가',
'prdy_vrss_sign': '전일대비부호',
'prdy_vrss': '전일대비',
'prdy_ctrt': '전일대비율',
'askp': '매도호가',
'bidp': '매수호가',
'total_askp_rsqn': '총매도호가잔량',
'total_bidp_rsqn': '총매수호가잔량',
'acml_vol': '누적거래량',
'stnd_val': '기준값',
'stnd_val_vrss': '기준값대비',
'stnd_val_ctrt': '기준값대비율'
}
NUMERIC_COLUMNS = [
'ELW현재가', '전일대비', '전일대비율', '누적거래량', '누적거래대금',
'기준값', '기준값대비', '기준값대비율'
]
def main():
"""
[국내주식] ELW시세
ELW 당일급변종목[국내주식-171]
ELW 당일급변종목 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (시장구분코드 (W))
- fid_cond_scr_div_code (str): 조건화면분류코드 (Unique key(20287))
- fid_unas_input_iscd (str): 기초자산입력종목코드 ('000000(전체), 2001(코스피200) , 3003(코스닥150), 005930(삼성전자) ')
- fid_input_iscd (str): 발행사 ('00000(전체), 00003(한국투자증권) , 00017(KB증권), 00005(미래에셋주식회사)')
- fid_mrkt_cls_code (str): 시장구분코드 (Unique key(A))
- fid_input_price_1 (str): 가격(이상) ()
- fid_input_price_2 (str): 가격(이하) ()
- fid_input_vol_1 (str): 거래량(이상) ()
- fid_input_vol_2 (str): 거래량(이하) ()
- fid_hour_cls_code (str): 시간구분코드 (1(분), 2(일))
- fid_input_hour_1 (str): 입력 일 또는 분 ()
- fid_input_hour_2 (str): 기준시간(분 선택 시) ()
- fid_rank_sort_cls_code (str): 순위정렬구분코드 ('1(가격급등), 2(가격급락), 3(거래량급증) , 4(매수잔량급증), 5(매도잔량급증)')
- fid_blng_cls_code (str): 결재방법 (0(전체), 1(일반), 2(조기종료))
Returns:
- DataFrame: ELW 당일급변종목 결과
Example:
>>> df = quick_change(fid_cond_mrkt_div_code="W", fid_cond_scr_div_code="20287", fid_unas_input_iscd="000000", fid_input_iscd="00000", fid_mrkt_cls_code="A", fid_input_price_1="", fid_input_price_2="", fid_input_vol_1="", fid_input_vol_2="", fid_hour_cls_code="1", fid_input_hour_1="", fid_input_hour_2="", fid_rank_sort_cls_code="1", fid_blng_cls_code="0")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result = quick_change(
fid_cond_mrkt_div_code="W", # 조건시장분류코드
fid_cond_scr_div_code="20287", # 조건화면분류코드
fid_unas_input_iscd="000000", # 기초자산입력종목코드
fid_input_iscd="00000", # 발행사
fid_mrkt_cls_code="A", # 시장구분코드
fid_input_price_1="", # 가격(이상)
fid_input_price_2="", # 가격(이하)
fid_input_vol_1="", # 거래량(이상)
fid_input_vol_2="", # 거래량(이하)
fid_hour_cls_code="1", # 시간구분코드
fid_input_hour_1="0", # 입력 일 또는 분
fid_input_hour_2="", # 기준시간(분 선택 시)
fid_rank_sort_cls_code="1", # 순위정렬구분코드
fid_blng_cls_code="0" # 결재방법
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 결과 출력
logger.info("=== ELW 당일급변종목 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,193 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 당일급변종목[국내주식-171]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/ranking/quick-change"
def quick_change(
fid_cond_mrkt_div_code: str, # 조건시장분류코드
fid_cond_scr_div_code: str, # 조건화면분류코드
fid_unas_input_iscd: str, # 기초자산입력종목코드
fid_input_iscd: str, # 발행사
fid_mrkt_cls_code: str, # 시장구분코드
fid_input_price_1: str, # 가격(이상)
fid_input_price_2: str, # 가격(이하)
fid_input_vol_1: str, # 거래량(이상)
fid_input_vol_2: str, # 거래량(이하)
fid_hour_cls_code: str, # 시간구분코드
fid_input_hour_1: str, # 입력 일 또는 분
fid_input_hour_2: str, # 기준시간(분 선택 시)
fid_rank_sort_cls_code: str, # 순위정렬구분코드
fid_blng_cls_code: str, # 결재방법
tr_cont: str = "",
dataframe: Optional[pd.DataFrame] = None,
depth: int = 0,
max_depth: int = 10
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 당일급변종목[국내주식-171]
ELW 당일급변종목 API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 조건시장분류코드 (필수)
fid_cond_scr_div_code (str): 조건화면분류코드 (필수)
fid_unas_input_iscd (str): 기초자산입력종목코드 (필수)
fid_input_iscd (str): 발행사 (필수)
fid_mrkt_cls_code (str): 시장구분코드 (필수)
fid_input_price_1 (str): 가격(이상) (필수)
fid_input_price_2 (str): 가격(이하) (필수)
fid_input_vol_1 (str): 거래량(이상) (필수)
fid_input_vol_2 (str): 거래량(이하) (필수)
fid_hour_cls_code (str): 시간구분코드 (필수)
fid_input_hour_1 (str): 입력 일 또는 분 (필수)
fid_input_hour_2 (str): 기준시간(분 선택 시) (필수)
fid_rank_sort_cls_code (str): 순위정렬구분코드 (필수)
fid_blng_cls_code (str): 결재방법 (필수)
tr_cont (str): 연속 거래 여부 (옵션)
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임 (옵션)
depth (int): 현재 재귀 깊이 (옵션)
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 당일급변종목 데이터
Example:
>>> df = quick_change(
... fid_cond_mrkt_div_code='W',
... fid_cond_scr_div_code='20287',
... fid_unas_input_iscd='000000',
... fid_input_iscd='00000',
... fid_mrkt_cls_code='A',
... fid_input_price_1='1000',
... fid_input_price_2='5000',
... fid_input_vol_1='10000',
... fid_input_vol_2='50000',
... fid_hour_cls_code='1',
... fid_input_hour_1='10',
... fid_input_hour_2='30',
... fid_rank_sort_cls_code='1',
... fid_blng_cls_code='0'
... )
>>> print(df)
"""
# 로깅 설정
logger = logging.getLogger(__name__)
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_cond_scr_div_code:
logger.error("fid_cond_scr_div_code is required. (e.g. '20287')")
raise ValueError("fid_cond_scr_div_code is required. (e.g. '20287')")
if not fid_unas_input_iscd:
logger.error("fid_unas_input_iscd is required. (e.g. '000000')")
raise ValueError("fid_unas_input_iscd is required. (e.g. '000000')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. '00000')")
raise ValueError("fid_input_iscd is required. (e.g. '00000')")
if not fid_mrkt_cls_code:
logger.error("fid_mrkt_cls_code is required. (e.g. 'A')")
raise ValueError("fid_mrkt_cls_code is required. (e.g. 'A')")
if not fid_hour_cls_code:
logger.error("fid_hour_cls_code is required. (e.g. '1')")
raise ValueError("fid_hour_cls_code is required. (e.g. '1')")
if not fid_rank_sort_cls_code:
logger.error("fid_rank_sort_cls_code is required. (e.g. '1')")
raise ValueError("fid_rank_sort_cls_code is required. (e.g. '1')")
if not fid_blng_cls_code:
logger.error("fid_blng_cls_code is required. (e.g. '0')")
raise ValueError("fid_blng_cls_code is required. (e.g. '0')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
tr_id = "FHPEW02870000"
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_COND_SCR_DIV_CODE": fid_cond_scr_div_code,
"FID_UNAS_INPUT_ISCD": fid_unas_input_iscd,
"FID_INPUT_ISCD": fid_input_iscd,
"FID_MRKT_CLS_CODE": fid_mrkt_cls_code,
"FID_INPUT_PRICE_1": fid_input_price_1,
"FID_INPUT_PRICE_2": fid_input_price_2,
"FID_INPUT_VOL_1": fid_input_vol_1,
"FID_INPUT_VOL_2": fid_input_vol_2,
"FID_HOUR_CLS_CODE": fid_hour_cls_code,
"FID_INPUT_HOUR_1": fid_input_hour_1,
"FID_INPUT_HOUR_2": fid_input_hour_2,
"FID_RANK_SORT_CLS_CODE": fid_rank_sort_cls_code,
"FID_BLNG_CLS_CODE": fid_blng_cls_code,
}
# API 호출
res = ka._url_fetch(API_URL, tr_id, tr_cont, params)
if res.isOK():
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return quick_change(
fid_cond_mrkt_div_code,
fid_cond_scr_div_code,
fid_unas_input_iscd,
fid_input_iscd,
fid_mrkt_cls_code,
fid_input_price_1,
fid_input_price_2,
fid_input_vol_1,
fid_input_vol_2,
fid_hour_cls_code,
fid_input_hour_1,
fid_input_hour_2,
fid_rank_sort_cls_code,
fid_blng_cls_code,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()

View File

@@ -0,0 +1,129 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from sensitivity import sensitivity
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 민감도 순위[국내주식-170]
##############################################################################################
COLUMN_MAPPING = {
'elw_shrn_iscd': 'ELW단축종목코드',
'elw_kor_isnm': 'ELW한글종목명',
'elw_prpr': 'ELW현재가',
'prdy_vrss': '전일대비',
'prdy_vrss_sign': '전일대비부호',
'prdy_ctrt': '전일대비율',
'acml_vol': '누적거래량',
'hts_thpr': 'HTS이론가',
'delta_val': '델타값',
'gama': '감마',
'theta': '세타',
'vega': '베가',
'rho': '로우',
'hts_ints_vltl': 'HTS내재변동성',
'd90_hist_vltl': '90일역사적변동성'
}
NUMERIC_COLUMNS = [
'ELW현재가', '전일대비', '전일대비율', '누적거래량', 'HTS이론가',
'델타값', '감마', '세타', '베가', '로우', 'HTS내재변동성', '90일역사적변동성'
]
def main():
"""
[국내주식] ELW시세
ELW 민감도 순위[국내주식-170]
ELW 민감도 순위 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (시장구분코드 (W))
- fid_cond_scr_div_code (str): 조건화면분류코드 (Unique key(20285))
- fid_unas_input_iscd (str): 기초자산입력종목코드 ('000000(전체), 2001(코스피200) , 3003(코스닥150), 005930(삼성전자) ')
- fid_input_iscd (str): 입력종목코드 ('00000(전체), 00003(한국투자증권) , 00017(KB증권), 00005(미래에셋주식회사)')
- fid_div_cls_code (str): 콜풋구분코드 (0(전체), 1(콜), 2(풋))
- fid_input_price_1 (str): 가격(이상) ()
- fid_input_price_2 (str): 가격(이하) ()
- fid_input_vol_1 (str): 거래량(이상) ()
- fid_input_vol_2 (str): 거래량(이하) ()
- fid_rank_sort_cls_code (str): 순위정렬구분코드 ('0(이론가), 1(델타), 2(감마), 3(로), 4(베가) , 5(로) , 6(내재변동성), 7(90일변동성)')
- fid_input_rmnn_dynu_1 (str): 잔존일수(이상) ()
- fid_input_date_1 (str): 조회기준일 ()
- fid_blng_cls_code (str): 결재방법 (0(전체), 1(일반), 2(조기종료))
Returns:
- DataFrame: ELW 민감도 순위 결과
Example:
>>> df = sensitivity(fid_cond_mrkt_div_code="W", fid_cond_scr_div_code="20285", fid_unas_input_iscd="000000", fid_input_iscd="00000", fid_div_cls_code="0", fid_input_price_1="", fid_input_price_2="", fid_input_vol_1="", fid_input_vol_2="", fid_rank_sort_cls_code="0", fid_input_rmnn_dynu_1="", fid_input_date_1="", fid_blng_cls_code="0")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result = sensitivity(
fid_cond_mrkt_div_code="W", # 조건시장분류코드
fid_cond_scr_div_code="20285", # 조건화면분류코드
fid_unas_input_iscd="000000", # 기초자산입력종목코드
fid_input_iscd="00000", # 입력종목코드
fid_div_cls_code="0", # 콜풋구분코드
fid_input_price_1="", # 가격(이상)
fid_input_price_2="", # 가격(이하)
fid_input_vol_1="", # 거래량(이상)
fid_input_vol_2="", # 거래량(이하)
fid_rank_sort_cls_code="0", # 순위정렬구분코드
fid_input_rmnn_dynu_1="", # 잔존일수(이상)
fid_input_date_1="", # 조회기준일
fid_blng_cls_code="0" # 결재방법
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 결과 출력
logger.info("=== ELW 민감도 순위 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,188 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 민감도 순위[국내주식-170]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/ranking/sensitivity"
def sensitivity(
fid_cond_mrkt_div_code: str, # 조건시장분류코드
fid_cond_scr_div_code: str, # 조건화면분류코드
fid_unas_input_iscd: str, # 기초자산입력종목코드
fid_input_iscd: str, # 입력종목코드
fid_div_cls_code: str, # 콜풋구분코드
fid_input_price_1: str, # 가격(이상)
fid_input_price_2: str, # 가격(이하)
fid_input_vol_1: str, # 거래량(이상)
fid_input_vol_2: str, # 거래량(이하)
fid_rank_sort_cls_code: str, # 순위정렬구분코드
fid_input_rmnn_dynu_1: str, # 잔존일수(이상)
fid_input_date_1: str, # 조회기준일
fid_blng_cls_code: str, # 결재방법
tr_cont: str = "", # 연속 거래 여부
dataframe: Optional[pd.DataFrame] = None, # 누적 데이터프레임
depth: int = 0, # 현재 재귀 깊이
max_depth: int = 10 # 최대 재귀 깊이
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 민감도 순위[국내주식-170]
ELW 민감도 순위 API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 조건시장분류코드
fid_cond_scr_div_code (str): 조건화면분류코드
fid_unas_input_iscd (str): 기초자산입력종목코드
fid_input_iscd (str): 입력종목코드
fid_div_cls_code (str): 콜풋구분코드
fid_input_price_1 (str): 가격(이상)
fid_input_price_2 (str): 가격(이하)
fid_input_vol_1 (str): 거래량(이상)
fid_input_vol_2 (str): 거래량(이하)
fid_rank_sort_cls_code (str): 순위정렬구분코드
fid_input_rmnn_dynu_1 (str): 잔존일수(이상)
fid_input_date_1 (str): 조회기준일
fid_blng_cls_code (str): 결재방법
tr_cont (str): 연속 거래 여부
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임
depth (int): 현재 재귀 깊이
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 민감도 순위 데이터
Example:
>>> df = sensitivity(
fid_cond_mrkt_div_code='W',
fid_cond_scr_div_code='20285',
fid_unas_input_iscd='000000',
fid_input_iscd='00000',
fid_div_cls_code='0',
fid_input_price_1='0',
fid_input_price_2='100000',
fid_input_vol_1='0',
fid_input_vol_2='1000000',
fid_rank_sort_cls_code='0',
fid_input_rmnn_dynu_1='0',
fid_input_date_1='20230101',
fid_blng_cls_code='0'
)
>>> print(df)
"""
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_cond_scr_div_code:
logger.error("fid_cond_scr_div_code is required. (e.g. '20285')")
raise ValueError("fid_cond_scr_div_code is required. (e.g. '20285')")
if not fid_unas_input_iscd:
logger.error("fid_unas_input_iscd is required. (e.g. '000000')")
raise ValueError("fid_unas_input_iscd is required. (e.g. '000000')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. '00000')")
raise ValueError("fid_input_iscd is required. (e.g. '00000')")
if not fid_div_cls_code:
logger.error("fid_div_cls_code is required. (e.g. '0')")
raise ValueError("fid_div_cls_code is required. (e.g. '0')")
if not fid_rank_sort_cls_code:
logger.error("fid_rank_sort_cls_code is required. (e.g. '0')")
raise ValueError("fid_rank_sort_cls_code is required. (e.g. '0')")
if not fid_blng_cls_code:
logger.error("fid_blng_cls_code is required. (e.g. '0')")
raise ValueError("fid_blng_cls_code is required. (e.g. '0')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
tr_id = "FHPEW02850000"
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_COND_SCR_DIV_CODE": fid_cond_scr_div_code,
"FID_UNAS_INPUT_ISCD": fid_unas_input_iscd,
"FID_INPUT_ISCD": fid_input_iscd,
"FID_DIV_CLS_CODE": fid_div_cls_code,
"FID_INPUT_PRICE_1": fid_input_price_1,
"FID_INPUT_PRICE_2": fid_input_price_2,
"FID_INPUT_VOL_1": fid_input_vol_1,
"FID_INPUT_VOL_2": fid_input_vol_2,
"FID_RANK_SORT_CLS_CODE": fid_rank_sort_cls_code,
"FID_INPUT_RMNN_DYNU_1": fid_input_rmnn_dynu_1,
"FID_INPUT_DATE_1": fid_input_date_1,
"FID_BLNG_CLS_CODE": fid_blng_cls_code,
}
# API 호출
res = ka._url_fetch(API_URL, tr_id, tr_cont, params)
if res.isOK():
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return sensitivity(
fid_cond_mrkt_div_code,
fid_cond_scr_div_code,
fid_unas_input_iscd,
fid_input_iscd,
fid_div_cls_code,
fid_input_price_1,
fid_input_price_2,
fid_input_vol_1,
fid_input_vol_2,
fid_rank_sort_cls_code,
fid_input_rmnn_dynu_1,
fid_input_date_1,
fid_blng_cls_code,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()

View File

@@ -0,0 +1,103 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from sensitivity_trend_ccnl import sensitivity_trend_ccnl
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 민감도 추이(체결)[국내주식-175]
##############################################################################################
COLUMN_MAPPING = {
'stck_cntg_hour': '주식체결시간',
'elw_prpr': 'ELW현재가',
'prdy_vrss': '전일대비',
'prdy_vrss_sign': '전일대비부호',
'prdy_ctrt': '전일대비율',
'hts_thpr': 'hts 이론가',
'delta_val': '델타 값',
'gama': '감마',
'theta': '세타',
'vega': '베가',
'rho': '로우'
}
NUMERIC_COLUMNS = [
'ELW현재가', '전일대비', '전일대비율', 'hts 이론가', '델타 값',
'감마', '세타', '베가', '로우'
]
def main():
"""
[국내주식] ELW시세
ELW 민감도 추이(체결)[국내주식-175]
ELW 민감도 추이(체결) 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (시장구분코드 (W))
- fid_input_iscd (str): 입력종목코드 (ex) 58J297(KBJ297삼성전자콜))
Returns:
- DataFrame: ELW 민감도 추이(체결) 결과
Example:
>>> df = sensitivity_trend_ccnl(fid_cond_mrkt_div_code="W", fid_input_iscd="58J297")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result = sensitivity_trend_ccnl(
fid_cond_mrkt_div_code="W", # 조건시장분류코드
fid_input_iscd="57LA50", # 입력종목코드
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자 컬럼 처리
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 결과 출력
logger.info("=== ELW 민감도 추이(체결) 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,114 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 민감도 추이(체결)[국내주식-175]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/quotations/sensitivity-trend-ccnl"
def sensitivity_trend_ccnl(
fid_cond_mrkt_div_code: str, # 조건시장분류코드
fid_input_iscd: str, # 입력종목코드
tr_cont: str = "", # 연속 거래 여부
dataframe: Optional[pd.DataFrame] = None, # 누적 데이터프레임
depth: int = 0, # 현재 재귀 깊이
max_depth: int = 10 # 최대 재귀 깊이
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 민감도 추이(체결)[국내주식-175]
ELW 민감도 추이(체결) API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 조건시장분류코드 (필수)
fid_input_iscd (str): 입력종목코드 (필수)
tr_cont (str): 연속 거래 여부 (기본값: "")
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임 (기본값: None)
depth (int): 현재 재귀 깊이 (기본값: 0)
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 민감도 추이(체결) 데이터
Example:
>>> df = sensitivity_trend_ccnl('W', '58J297')
>>> print(df)
"""
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. '58J297')")
raise ValueError("fid_input_iscd is required. (e.g. '58J297')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
tr_id = "FHPEW02830100"
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_INPUT_ISCD": fid_input_iscd,
}
# API 호출
res = ka._url_fetch(API_URL, tr_id, tr_cont, params)
if res.isOK():
# 응답 데이터 처리
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
# 데이터프레임 병합
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
# 연속 거래 여부 확인
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return sensitivity_trend_ccnl(
fid_cond_mrkt_div_code,
fid_input_iscd,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
# API 에러 처리
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()

View File

@@ -0,0 +1,103 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from sensitivity_trend_daily import sensitivity_trend_daily
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 민감도 추이(일별)[국내주식-176]
##############################################################################################
COLUMN_MAPPING = {
'stck_bsop_date': '주식영업일자',
'elw_prpr': 'ELW현재가',
'prdy_vrss': '전일대비',
'prdy_vrss_sign': '전일대비부호',
'prdy_ctrt': '전일대비율',
'hts_thpr': 'HTS이론가',
'delta_val': '델타값',
'gama': '감마',
'theta': '세타',
'vega': '베가',
'rho': '로우'
}
NUMERIC_COLUMNS = [
'ELW현재가', '전일대비', '전일대비율', 'HTS이론가', '델타값',
'감마', '세타', '베가', '로우'
]
def main():
"""
[국내주식] ELW시세
ELW 민감도 추이(일별)[국내주식-176]
ELW 민감도 추이(일별) 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (시장구분코드 (W))
- fid_input_iscd (str): 입력종목코드 (ex)(58J438(KBJ438삼성전자풋))
Returns:
- DataFrame: ELW 민감도 추이(일별) 결과
Example:
>>> df = sensitivity_trend_daily(fid_cond_mrkt_div_code="W", fid_input_iscd="58J438")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result = sensitivity_trend_daily(
fid_cond_mrkt_div_code="W", # 조건시장분류코드
fid_input_iscd="58J438", # 입력종목코드
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자 컬럼 처리
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 결과 출력
logger.info("=== ELW 민감도 추이(일별) 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 민감도 추이(일별)[국내주식-176]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/quotations/sensitivity-trend-daily"
def sensitivity_trend_daily(
fid_cond_mrkt_div_code: str, # 조건시장분류코드
fid_input_iscd: str, # 입력종목코드
tr_cont: str = "", # 연속 거래 여부
dataframe: Optional[pd.DataFrame] = None, # 누적 데이터프레임
depth: int = 0, # 현재 재귀 깊이
max_depth: int = 10 # 최대 재귀 깊이
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 민감도 추이(일별)[국내주식-176]
ELW 민감도 추이(일별) API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 조건시장분류코드 (필수)
fid_input_iscd (str): 입력종목코드 (필수)
tr_cont (str): 연속 거래 여부 (기본값: "")
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임 (기본값: None)
depth (int): 현재 재귀 깊이 (기본값: 0)
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 민감도 추이(일별) 데이터
Example:
>>> df = sensitivity_trend_daily("W", "58J438")
>>> print(df)
"""
# 로깅 설정
logger = logging.getLogger(__name__)
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. '58J438')")
raise ValueError("fid_input_iscd is required. (e.g. '58J438')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
# API 호출 URL 및 거래 ID 설정
tr_id = "FHPEW02830200"
# 요청 파라미터 설정
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_INPUT_ISCD": fid_input_iscd,
}
# API 호출
res = ka._url_fetch(API_URL, tr_id, tr_cont, params)
# API 응답 처리
if res.isOK():
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
# 데이터프레임 병합
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
# 연속 거래 여부 확인
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return sensitivity_trend_daily(
fid_cond_mrkt_div_code,
fid_input_iscd,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()

View File

@@ -0,0 +1,99 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-19
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from udrl_asset_list import udrl_asset_list
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 기초자산 목록조회[국내주식-185]
##############################################################################################
COLUMN_MAPPING = {
'unas_shrn_iscd': '기초자산단축종목코드',
'unas_isnm': '기초자산종목명',
'unas_prpr': '기초자산현재가',
'unas_prdy_vrss': '기초자산전일대비',
'unas_prdy_vrss_sign': '기초자산전일대비부호',
'unas_prdy_ctrt': '기초자산전일대비율'
}
NUMERIC_COLUMNS = [
'기초자산현재가', '기초자산전일대비', '기초자산전일대비율'
]
def main():
"""
[국내주식] ELW시세
ELW 기초자산 목록조회[국내주식-185]
ELW 기초자산 목록조회 테스트 함수
Parameters:
- fid_cond_scr_div_code (str): 조건화면분류코드 (11541(Primary key))
- fid_rank_sort_cls_code (str): 순위정렬구분코드 (0(종목명순), 1(콜발행종목순), 2(풋발행종목순), 3(전일대비 상승율순), 4(전일대비 하락율순), 5(현재가 크기순), 6(종목코드순))
- fid_input_iscd (str): 입력종목코드 (00000(전체), 00003(한국투자증권), 00017(KB증권), 00005(미래에셋))
Returns:
- DataFrame: ELW 기초자산 목록조회 결과
Example:
>>> df = udrl_asset_list(fid_cond_scr_div_code="11541", fid_rank_sort_cls_code="0", fid_input_iscd="00000")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result = udrl_asset_list(
fid_cond_scr_div_code="11541", # 조건화면분류코드
fid_rank_sort_cls_code="0", # 순위정렬구분코드
fid_input_iscd="00000", # 입력종목코드
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자 컬럼 처리
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 결과 출력
logger.info("=== ELW 기초자산 목록조회 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,121 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-19
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 기초자산 목록조회[국내주식-185]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/quotations/udrl-asset-list"
def udrl_asset_list(
fid_cond_scr_div_code: str, # 조건화면분류코드
fid_rank_sort_cls_code: str, # 순위정렬구분코드
fid_input_iscd: str, # 입력종목코드
tr_cont: str = "", # 연속 거래 여부
dataframe: Optional[pd.DataFrame] = None, # 누적 데이터프레임
depth: int = 0, # 현재 재귀 깊이
max_depth: int = 10 # 최대 재귀 깊이
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 기초자산 목록조회[국내주식-185]
ELW 기초자산 목록조회 API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_scr_div_code (str): 조건화면분류코드, 예: '11541'
fid_rank_sort_cls_code (str): 순위정렬구분코드, 예: '0', '1', '2', '3', '4', '5', '6'
fid_input_iscd (str): 입력종목코드, 예: '00000', '00003', '00017', '00005'
tr_cont (str): 연속 거래 여부, 기본값은 공백
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임
depth (int): 현재 재귀 깊이
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 기초자산 목록조회 데이터
Example:
>>> df = udrl_asset_list('11541', '0', '00000')
>>> print(df)
"""
# 로깅 설정
logger = logging.getLogger(__name__)
# 필수 파라미터 검증
if not fid_cond_scr_div_code:
logger.error("fid_cond_scr_div_code is required. (e.g. '11541')")
raise ValueError("fid_cond_scr_div_code is required. (e.g. '11541')")
if not fid_rank_sort_cls_code:
logger.error("fid_rank_sort_cls_code is required. (e.g. '0')")
raise ValueError("fid_rank_sort_cls_code is required. (e.g. '0')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. '00000')")
raise ValueError("fid_input_iscd is required. (e.g. '00000')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
tr_id = "FHKEW154100C0"
params = {
"FID_COND_SCR_DIV_CODE": fid_cond_scr_div_code,
"FID_RANK_SORT_CLS_CODE": fid_rank_sort_cls_code,
"FID_INPUT_ISCD": fid_input_iscd,
}
# API 호출
res = ka._url_fetch(API_URL, tr_id, tr_cont, params)
if res.isOK():
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return udrl_asset_list(
fid_cond_scr_div_code,
fid_rank_sort_cls_code,
fid_input_iscd,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()

View File

@@ -0,0 +1,151 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from udrl_asset_price import udrl_asset_price
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 기초자산별 종목시세[국내주식-186]
##############################################################################################
COLUMN_MAPPING = {
'elw_shrn_iscd': 'ELW단축종목코드',
'hts_kor_isnm': 'HTS한글종목명',
'elw_prpr': 'ELW현재가',
'prdy_vrss': '전일대비',
'prdy_vrss_sign': '전일대비부호',
'prdy_ctrt': '전일대비율',
'acml_vol': '누적거래량',
'acpr': '행사가',
'prls_qryr_stpr_prc': '손익분기주가가격',
'hts_rmnn_dynu': 'HTS잔존일수',
'hts_ints_vltl': 'HTS내재변동성',
'stck_cnvr_rate': '주식전환비율',
'lp_hvol': 'LP보유량',
'lp_rlim': 'LP비중',
'lvrg_val': '레버리지값',
'gear': '기어링',
'delta_val': '델타값',
'gama': '감마',
'vega': '베가',
'theta': '세타',
'prls_qryr_rate': '손익분기비율',
'cfp': '자본지지점',
'prit': '패리티',
'invl_val': '내재가치값',
'tmvl_val': '시간가치값',
'hts_thpr': 'HTS이론가',
'stck_lstn_date': '주식상장일자',
'stck_last_tr_date': '주식최종거래일자',
'lp_ntby_qty': 'LP순매도량'
}
NUMERIC_COLUMNS = [
'ELW현재가', '전일대비', '전일대비율', '누적거래량', '행사가', '손익분기주가가격',
'HTS잔존일수', 'HTS내재변동성', '주식전환비율', 'LP보유량', 'LP비중', '레버리지값',
'기어링', '델타값', '감마', '베가', '세타', '손익분기비율', '자본지지점', '패리티',
'내재가치값', '시간가치값', 'HTS이론가', 'LP순매도량'
]
def main():
"""
[국내주식] ELW시세
ELW 기초자산별 종목시세[국내주식-186]
ELW 기초자산별 종목시세 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (시장구분(W))
- fid_cond_scr_div_code (str): 조건화면분류코드 (Uniquekey(11541))
- fid_mrkt_cls_code (str): 시장구분코드 (전체(A),콜(C),풋(P))
- fid_input_iscd (str): 입력종목코드 ('00000(전체), 00003(한국투자증권) , 00017(KB증권), 00005(미래에셋주식회사)')
- fid_unas_input_iscd (str): 기초자산입력종목코드 ()
- fid_vol_cnt (str): 거래량수 (전일거래량(정수량미만))
- fid_trgt_exls_cls_code (str): 대상제외구분코드 (거래불가종목제외(0:미체크,1:체크))
- fid_input_price_1 (str): 입력가격1 (가격~원이상)
- fid_input_price_2 (str): 입력가격2 (가격~월이하)
- fid_input_vol_1 (str): 입력거래량1 (거래량~계약이상)
- fid_input_vol_2 (str): 입력거래량2 (거래량~계약이하)
- fid_input_rmnn_dynu_1 (str): 입력잔존일수1 (잔존일(~일이상))
- fid_input_rmnn_dynu_2 (str): 입력잔존일수2 (잔존일(~일이하))
- fid_option (str): 옵션 (옵션상태(0:없음,1:ATM,2:ITM,3:OTM))
- fid_input_option_1 (str): 입력옵션1 ()
- fid_input_option_2 (str): 입력옵션2 ()
Returns:
- DataFrame: ELW 기초자산별 종목시세 결과
Example:
>>> df = udrl_asset_price(fid_cond_mrkt_div_code="W", fid_cond_scr_div_code="11541", fid_mrkt_cls_code="A", fid_input_iscd="00000", fid_unas_input_iscd="005930", fid_vol_cnt="1000", fid_trgt_exls_cls_code="0", fid_input_price_1="1000", fid_input_price_2="5000", fid_input_vol_1="100", fid_input_vol_2="1000", fid_input_rmnn_dynu_1="30", fid_input_rmnn_dynu_2="90", fid_option="0", fid_input_option_1="", fid_input_option_2="")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result = udrl_asset_price(
fid_cond_mrkt_div_code="W", # 조건시장분류코드
fid_cond_scr_div_code="11541", # 조건화면분류코드
fid_mrkt_cls_code="A", # 시장구분코드
fid_input_iscd="00000", # 입력종목코드
fid_unas_input_iscd="005930", # 기초자산입력종목코드
fid_vol_cnt="", # 거래량수
fid_trgt_exls_cls_code="0", # 대상제외구분코드
fid_input_price_1="", # 입력가격1
fid_input_price_2="", # 입력가격2
fid_input_vol_1="", # 입력거래량1
fid_input_vol_2="", # 입력거래량2
fid_input_rmnn_dynu_1="", # 입력잔존일수1
fid_input_rmnn_dynu_2="", # 입력잔존일수2
fid_option="0", # 옵션
fid_input_option_1="", # 입력옵션1
fid_input_option_2="", # 입력옵션2
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자 컬럼 처리
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 결과 출력
logger.info("=== ELW 기초자산별 종목시세 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,209 @@
# [국내주식] ELW시세 - ELW 기초자산별 종목시세
# Generated by KIS API Generator (Single API Mode)
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 기초자산별 종목시세[국내주식-186]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/quotations/udrl-asset-price"
def udrl_asset_price(
fid_cond_mrkt_div_code: str, # 조건시장분류코드
fid_cond_scr_div_code: str, # 조건화면분류코드
fid_mrkt_cls_code: str, # 시장구분코드
fid_input_iscd: str, # 입력종목코드
fid_unas_input_iscd: str, # 기초자산입력종목코드
fid_vol_cnt: str, # 거래량수
fid_trgt_exls_cls_code: str, # 대상제외구분코드
fid_input_price_1: str, # 입력가격1
fid_input_price_2: str, # 입력가격2
fid_input_vol_1: str, # 입력거래량1
fid_input_vol_2: str, # 입력거래량2
fid_input_rmnn_dynu_1: str, # 입력잔존일수1
fid_input_rmnn_dynu_2: str, # 입력잔존일수2
fid_option: str, # 옵션
fid_input_option_1: str, # 입력옵션1
fid_input_option_2: str, # 입력옵션2
tr_cont: str = "",
dataframe: Optional[pd.DataFrame] = None,
depth: int = 0,
max_depth: int = 10
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 기초자산별 종목시세[국내주식-186]
ELW 기초자산별 종목시세 API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 시장구분(W)
fid_cond_scr_div_code (str): Uniquekey(11541)
fid_mrkt_cls_code (str): 전체(A),콜(C),풋(P)
fid_input_iscd (str): '00000(전체), 00003(한국투자증권) , 00017(KB증권), 00005(미래에셋주식회사)'
fid_unas_input_iscd (str): 기초자산입력종목코드
fid_vol_cnt (str): 전일거래량(정수량미만)
fid_trgt_exls_cls_code (str): 거래불가종목제외(0:미체크,1:체크)
fid_input_price_1 (str): 가격~원이상
fid_input_price_2 (str): 가격~월이하
fid_input_vol_1 (str): 거래량~계약이상
fid_input_vol_2 (str): 거래량~계약이하
fid_input_rmnn_dynu_1 (str): 잔존일(~일이상)
fid_input_rmnn_dynu_2 (str): 잔존일(~일이하)
fid_option (str): 옵션상태(0:없음,1:ATM,2:ITM,3:OTM)
fid_input_option_1 (str): 입력옵션1
fid_input_option_2 (str): 입력옵션2
tr_cont (str): 연속 거래 여부
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임
depth (int): 현재 재귀 깊이
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 기초자산별 종목시세 데이터
Example:
>>> df = udrl_asset_price(
... fid_cond_mrkt_div_code='W',
... fid_cond_scr_div_code='11541',
... fid_mrkt_cls_code='A',
... fid_input_iscd='00000',
... fid_unas_input_iscd='005930',
... fid_vol_cnt='1000',
... fid_trgt_exls_cls_code='0',
... fid_input_price_1='1000',
... fid_input_price_2='5000',
... fid_input_vol_1='100',
... fid_input_vol_2='500',
... fid_input_rmnn_dynu_1='10',
... fid_input_rmnn_dynu_2='20',
... fid_option='0',
... fid_input_option_1='',
... fid_input_option_2=''
... )
>>> print(df)
"""
# 로깅 설정
logger = logging.getLogger(__name__)
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_cond_scr_div_code:
logger.error("fid_cond_scr_div_code is required. (e.g. '11541')")
raise ValueError("fid_cond_scr_div_code is required. (e.g. '11541')")
if not fid_mrkt_cls_code:
logger.error("fid_mrkt_cls_code is required. (e.g. 'A')")
raise ValueError("fid_mrkt_cls_code is required. (e.g. 'A')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. '00000')")
raise ValueError("fid_input_iscd is required. (e.g. '00000')")
if not fid_unas_input_iscd:
logger.error("fid_unas_input_iscd is required. (e.g. '00001')")
raise ValueError("fid_unas_input_iscd is required. (e.g. '00001')")
if not fid_trgt_exls_cls_code:
logger.error("fid_trgt_exls_cls_code is required. (e.g. '0')")
raise ValueError("fid_trgt_exls_cls_code is required. (e.g. '0')")
if not fid_option:
logger.error("fid_option is required. (e.g. '0')")
raise ValueError("fid_option is required. (e.g. '0')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
tr_id = "FHKEW154101C0"
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_COND_SCR_DIV_CODE": fid_cond_scr_div_code,
"FID_MRKT_CLS_CODE": fid_mrkt_cls_code,
"FID_INPUT_ISCD": fid_input_iscd,
"FID_UNAS_INPUT_ISCD": fid_unas_input_iscd,
"FID_VOL_CNT": fid_vol_cnt,
"FID_TRGT_EXLS_CLS_CODE": fid_trgt_exls_cls_code,
"FID_INPUT_PRICE_1": fid_input_price_1,
"FID_INPUT_PRICE_2": fid_input_price_2,
"FID_INPUT_VOL_1": fid_input_vol_1,
"FID_INPUT_VOL_2": fid_input_vol_2,
"FID_INPUT_RMNN_DYNU_1": fid_input_rmnn_dynu_1,
"FID_INPUT_RMNN_DYNU_2": fid_input_rmnn_dynu_2,
"FID_OPTION": fid_option,
"FID_INPUT_OPTION_1": fid_input_option_1,
"FID_INPUT_OPTION_2": fid_input_option_2,
}
# API 호출
res = ka._url_fetch(API_URL, tr_id, tr_cont, params)
if res.isOK():
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return udrl_asset_price(
fid_cond_mrkt_div_code,
fid_cond_scr_div_code,
fid_mrkt_cls_code,
fid_input_iscd,
fid_unas_input_iscd,
fid_vol_cnt,
fid_trgt_exls_cls_code,
fid_input_price_1,
fid_input_price_2,
fid_input_vol_1,
fid_input_vol_2,
fid_input_rmnn_dynu_1,
fid_input_rmnn_dynu_2,
fid_option,
fid_input_option_1,
fid_input_option_2,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()

View File

@@ -0,0 +1,153 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from updown_rate import updown_rate
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 상승률순위[국내주식-167]
##############################################################################################
COLUMN_MAPPING = {
'hts_kor_isnm': 'HTS한글종목명',
'elw_shrn_iscd': 'ELW단축종목코드',
'elw_prpr': 'ELW현재가',
'prdy_vrss': '전일대비',
'prdy_vrss_sign': '전일대비부호',
'prdy_ctrt': '전일대비율',
'acml_vol': '누적거래량',
'stck_sdpr': '주식기준가',
'sdpr_vrss_prpr_sign': '기준가대비현재가부호',
'sdpr_vrss_prpr': '기준가대비현재가',
'sdpr_vrss_prpr_rate': '기준가대비현재가비율',
'stck_oprc': '주식시가2',
'oprc_vrss_prpr_sign': '시가2대비현재가부호',
'oprc_vrss_prpr': '시가2대비현재가',
'oprc_vrss_prpr_rate': '시가2대비현재가비율',
'stck_hgpr': '주식최고가',
'stck_lwpr': '주식최저가',
'prd_rsfl_sign': '기간등락부호',
'prd_rsfl': '기간등락',
'prd_rsfl_rate': '기간등락비율',
'stck_cnvr_rate': '주식전환비율',
'hts_rmnn_dynu': 'HTS잔존일수',
'acpr': '행사가',
'unas_isnm': '기초자산명',
'unas_shrn_iscd': '기초자산코드',
'lp_hldn_rate': 'LP보유비율',
'prit': '패리티',
'prls_qryr_stpr_prc': '손익분기주가가격',
'delta_val': '델타값',
'theta': '세타',
'prls_qryr_rate': '손익분기비율',
'stck_lstn_date': '주식상장일자',
'stck_last_tr_date': '주식최종거래일자',
'hts_ints_vltl': 'HTS내재변동성',
'lvrg_val': '레버리지값'
}
NUMERIC_COLUMNS = [
'ELW현재가', '전일대비', '전일대비율', '누적거래량', '주식기준가', '기준가대비현재가', '기준가대비현재가비율',
'주식시가2', '시가2대비현재가', '시가2대비현재가비율', '주식최고가', '주식최저가', '기간등락', '기간등락비율',
'주식전환비율', 'HTS잔존일수', '행사가', 'LP보유비율', '패리티', '손익분기주가가격', '델타값', '세타', '손익분기비율',
'HTS내재변동성', '레버리지값'
]
def main():
"""
[국내주식] ELW시세
ELW 상승률순위[국내주식-167]
ELW 상승률순위 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 사용자권한정보 (시장구분코드 (W))
- fid_cond_scr_div_code (str): 거래소코드 (Unique key(20277))
- fid_unas_input_iscd (str): 상승율/하락율 구분 ('000000(전체), 2001(코스피200) , 3003(코스닥150), 005930(삼성전자) ')
- fid_input_iscd (str): N일자값 ('00000(전체), 00003(한국투자증권) , 00017(KB증권), 00005(미래에셋주식회사)')
- fid_input_rmnn_dynu_1 (str): 거래량조건 ('0(전체), 1(1개월이하), 2(1개월~2개월), 3(2개월~3개월), 4(3개월~6개월), 5(6개월~9개월),6(9개월~12개월), 7(12개월이상)')
- fid_div_cls_code (str): NEXT KEY BUFF (0(전체), 1(콜), 2(풋))
- fid_input_price_1 (str): 사용자권한정보 ()
- fid_input_price_2 (str): 거래소코드 ()
- fid_input_vol_1 (str): 상승율/하락율 구분 ()
- fid_input_vol_2 (str): N일자값 ()
- fid_input_date_1 (str): 거래량조건 ()
- fid_rank_sort_cls_code (str): NEXT KEY BUFF ('0(상승율), 1(하락율), 2(시가대비상승율) , 3(시가대비하락율), 4(변동율)')
- fid_blng_cls_code (str): 사용자권한정보 (0(전체))
- fid_input_date_2 (str): 거래소코드 ()
Returns:
- DataFrame: ELW 상승률순위 결과
Example:
>>> df = updown_rate(fid_cond_mrkt_div_code="W", fid_cond_scr_div_code="20277", fid_unas_input_iscd="000000", fid_input_iscd="00000", fid_input_rmnn_dynu_1="0", fid_div_cls_code="0", fid_input_price_1="", fid_input_price_2="", fid_input_vol_1="", fid_input_vol_2="", fid_input_date_1="", fid_rank_sort_cls_code="0", fid_blng_cls_code="0", fid_input_date_2="")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result = updown_rate(
fid_cond_mrkt_div_code="W", # 사용자권한정보
fid_cond_scr_div_code="20277", # 거래소코드
fid_unas_input_iscd="000000", # 상승율/하락율 구분
fid_input_iscd="00000", # N일자값
fid_input_rmnn_dynu_1="0", # 거래량조건
fid_div_cls_code="0", # NEXT KEY BUFF
fid_input_price_1="", # 사용자권한정보
fid_input_price_2="", # 거래소코드
fid_input_vol_1="", # 상승율/하락율 구분
fid_input_vol_2="", # N일자값
fid_input_date_1="1", # 거래량조건
fid_rank_sort_cls_code="0", # NEXT KEY BUFF
fid_blng_cls_code="0", # 사용자권한정보
fid_input_date_2="", # 거래소코드
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자 컬럼 처리
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 결과 출력
logger.info("=== ELW 상승률순위 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,200 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 상승률순위[국내주식-167]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/ranking/updown-rate"
def updown_rate(
fid_cond_mrkt_div_code: str, # 사용자권한정보
fid_cond_scr_div_code: str, # 거래소코드
fid_unas_input_iscd: str, # 상승율/하락율 구분
fid_input_iscd: str, # N일자값
fid_input_rmnn_dynu_1: str, # 거래량조건
fid_div_cls_code: str, # NEXT KEY BUFF
fid_input_price_1: str, # 사용자권한정보
fid_input_price_2: str, # 거래소코드
fid_input_vol_1: str, # 상승율/하락율 구분
fid_input_vol_2: str, # N일자값
fid_input_date_1: str, # 거래량조건
fid_rank_sort_cls_code: str, # NEXT KEY BUFF
fid_blng_cls_code: str, # 사용자권한정보
fid_input_date_2: str, # 거래소코드
tr_cont: str = "",
dataframe: Optional[pd.DataFrame] = None,
depth: int = 0,
max_depth: int = 10
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 상승률순위[국내주식-167]
ELW 상승률순위 API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 시장구분코드 (W)
fid_cond_scr_div_code (str): Unique key(20277)
fid_unas_input_iscd (str): '000000(전체), 2001(코스피200) , 3003(코스닥150), 005930(삼성전자) '
fid_input_iscd (str): '00000(전체), 00003(한국투자증권) , 00017(KB증권), 00005(미래에셋주식회사)'
fid_input_rmnn_dynu_1 (str): '0(전체), 1(1개월이하), 2(1개월~2개월), 3(2개월~3개월), 4(3개월~6개월), 5(6개월~9개월),6(9개월~12개월), 7(12개월이상)'
fid_div_cls_code (str): 0(전체), 1(콜), 2(풋)
fid_input_price_1 (str):
fid_input_price_2 (str):
fid_input_vol_1 (str):
fid_input_vol_2 (str):
fid_input_date_1 (str):
fid_rank_sort_cls_code (str): '0(상승율), 1(하락율), 2(시가대비상승율) , 3(시가대비하락율), 4(변동율)'
fid_blng_cls_code (str): 0(전체)
fid_input_date_2 (str):
tr_cont (str): 연속 거래 여부
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임
depth (int): 현재 재귀 깊이
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 상승률순위 데이터
Example:
>>> df = updown_rate(
... fid_cond_mrkt_div_code='W',
... fid_cond_scr_div_code='20277',
... fid_unas_input_iscd='000000',
... fid_input_iscd='00000',
... fid_input_rmnn_dynu_1='0',
... fid_div_cls_code='0',
... fid_input_price_1='',
... fid_input_price_2='',
... fid_input_vol_1='',
... fid_input_vol_2='',
... fid_input_date_1='1',
... fid_rank_sort_cls_code='0',
... fid_blng_cls_code='0',
... fid_input_date_2=''
... )
>>> print(df)
"""
# 로깅 설정
logger = logging.getLogger(__name__)
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_cond_scr_div_code:
logger.error("fid_cond_scr_div_code is required. (e.g. '20277')")
raise ValueError("fid_cond_scr_div_code is required. (e.g. '20277')")
if not fid_unas_input_iscd:
logger.error("fid_unas_input_iscd is required. (e.g. '000000')")
raise ValueError("fid_unas_input_iscd is required. (e.g. '000000')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. '00000')")
raise ValueError("fid_input_iscd is required. (e.g. '00000')")
if not fid_input_rmnn_dynu_1:
logger.error("fid_input_rmnn_dynu_1 is required. (e.g. '0')")
raise ValueError("fid_input_rmnn_dynu_1 is required. (e.g. '0')")
if not fid_div_cls_code:
logger.error("fid_div_cls_code is required. (e.g. '0')")
raise ValueError("fid_div_cls_code is required. (e.g. '0')")
if not fid_rank_sort_cls_code:
logger.error("fid_rank_sort_cls_code is required. (e.g. '0')")
raise ValueError("fid_rank_sort_cls_code is required. (e.g. '0')")
if not fid_blng_cls_code:
logger.error("fid_blng_cls_code is required. (e.g. '0')")
raise ValueError("fid_blng_cls_code is required. (e.g. '0')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
tr_id = "FHPEW02770000"
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_COND_SCR_DIV_CODE": fid_cond_scr_div_code,
"FID_UNAS_INPUT_ISCD": fid_unas_input_iscd,
"FID_INPUT_ISCD": fid_input_iscd,
"FID_INPUT_RMNN_DYNU_1": fid_input_rmnn_dynu_1,
"FID_DIV_CLS_CODE": fid_div_cls_code,
"FID_INPUT_PRICE_1": fid_input_price_1,
"FID_INPUT_PRICE_2": fid_input_price_2,
"FID_INPUT_VOL_1": fid_input_vol_1,
"FID_INPUT_VOL_2": fid_input_vol_2,
"FID_INPUT_DATE_1": fid_input_date_1,
"FID_RANK_SORT_CLS_CODE": fid_rank_sort_cls_code,
"FID_BLNG_CLS_CODE": fid_blng_cls_code,
"FID_INPUT_DATE_2": fid_input_date_2,
}
# API 호출
res = ka._url_fetch(API_URL, tr_id, tr_cont, params)
if res.isOK():
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return updown_rate(
fid_cond_mrkt_div_code,
fid_cond_scr_div_code,
fid_unas_input_iscd,
fid_input_iscd,
fid_input_rmnn_dynu_1,
fid_div_cls_code,
fid_input_price_1,
fid_input_price_2,
fid_input_vol_1,
fid_input_vol_2,
fid_input_date_1,
fid_rank_sort_cls_code,
fid_blng_cls_code,
fid_input_date_2,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()

View File

@@ -0,0 +1,100 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from volatility_trend_ccnl import volatility_trend_ccnl
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 변동성추이(체결)[국내주식-177]
##############################################################################################
COLUMN_MAPPING = {
'stck_cntg_hour': '주식체결시간',
'elw_prpr': 'ELW현재가',
'prdy_vrss': '전일대비',
'prdy_vrss_sign': '전일대비부호',
'prdy_ctrt': '전일대비율',
'bidp': '매수호가',
'askp': '매도호가',
'acml_vol': '누적거래량',
'hts_ints_vltl': 'HTS내재변동성'
}
NUMERIC_COLUMNS = [
'ELW현재가', '전일대비', '전일대비율', '매수호가', '매도호가', '누적거래량', 'HTS내재변동성'
]
def main():
"""
[국내주식] ELW시세
ELW 변동성추이(체결)[국내주식-177]
ELW 변동성추이(체결) 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (W(Unique key))
- fid_input_iscd (str): 입력종목코드 (ex) 58J297(KBJ297삼성전자콜))
Returns:
- DataFrame: ELW 변동성추이(체결) 결과
Example:
>>> df = volatility_trend_ccnl(fid_cond_mrkt_div_code="W", fid_input_iscd="58J297")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result = volatility_trend_ccnl(
fid_cond_mrkt_div_code="W", # 조건시장분류코드
fid_input_iscd="57LA50", # 입력종목코드
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자 컬럼 처리
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 결과 출력
logger.info("=== ELW 변동성추이(체결) 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,119 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 변동성추이(체결)[국내주식-177]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/quotations/volatility-trend-ccnl"
def volatility_trend_ccnl(
fid_cond_mrkt_div_code: str, # 조건시장분류코드
fid_input_iscd: str, # 입력종목코드
tr_cont: str = "", # 연속 거래 여부
dataframe: Optional[pd.DataFrame] = None, # 누적 데이터프레임
depth: int = 0, # 현재 재귀 깊이
max_depth: int = 10 # 최대 재귀 깊이
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 변동성추이(체결)[국내주식-177]
ELW 변동성추이(체결) API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 조건시장분류코드 (필수)
fid_input_iscd (str): 입력종목코드 (필수)
tr_cont (str): 연속 거래 여부 (기본값: "")
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임 (기본값: None)
depth (int): 현재 재귀 깊이 (기본값: 0)
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 변동성추이(체결) 데이터
Example:
>>> df = volatility_trend_ccnl("W", "58J297")
>>> print(df)
"""
# 로깅 설정
logger = logging.getLogger(__name__)
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. '58J297')")
raise ValueError("fid_input_iscd is required. (e.g. '58J297')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
# API 호출 URL 및 거래 ID 설정
url = API_URL
tr_id = "FHPEW02840100"
# 요청 파라미터 설정
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_INPUT_ISCD": fid_input_iscd,
}
# API 호출
res = ka._url_fetch(url, tr_id, tr_cont, params)
# API 응답 처리
if res.isOK():
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
# 데이터프레임 병합
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
# 연속 거래 여부 확인
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return volatility_trend_ccnl(
fid_cond_mrkt_div_code,
fid_input_iscd,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
# API 에러 처리
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()

View File

@@ -0,0 +1,108 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from volatility_trend_daily import volatility_trend_daily
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 변동성 추이(일별)[국내주식-178]
##############################################################################################
COLUMN_MAPPING = {
'stck_bsop_date': '주식 영업 일자',
'elw_prpr': 'ELW 현재가',
'prdy_vrss': '전일대비',
'prdy_vrss_sign': '전일대비부호',
'prdy_ctrt': '전일대비율',
'elw_oprc': 'elw 시가2',
'elw_hgpr': 'elw 최고가',
'elw_lwpr': 'elw 최저가',
'acml_vol': '누적 거래량',
'd10_hist_vltl': '10일 역사적 변동성',
'd20_hist_vltl': '20일 역사적 변동성',
'd30_hist_vltl': '30일 역사적 변동성',
'd60_hist_vltl': '60일 역사적 변동성',
'd90_hist_vltl': '90일 역사적 변동성',
'hts_ints_vltl': 'HTS 내재 변동성'
}
NUMERIC_COLUMNS = [
'ELW 현재가', '전일대비', '전일대비율', 'elw 시가2', 'elw 최고가', 'elw 최저가', '누적 거래량',
'10일 역사적 변동성', '20일 역사적 변동성', '30일 역사적 변동성', '60일 역사적 변동성',
'90일 역사적 변동성', 'HTS 내재 변동성'
]
def main():
"""
[국내주식] ELW시세
ELW 변동성 추이(일별)[국내주식-178]
ELW 변동성 추이(일별) 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (시장구분코드 (W))
- fid_input_iscd (str): 입력종목코드 (ex) 58J297(KBJ297삼성전자콜))
Returns:
- DataFrame: ELW 변동성 추이(일별) 결과
Example:
>>> df = volatility_trend_daily(fid_cond_mrkt_div_code="W", fid_input_iscd="58J297")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result = volatility_trend_daily(
fid_cond_mrkt_div_code="W", # 조건시장분류코드
fid_input_iscd="58J297", # 입력종목코드
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자 컬럼 처리
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 결과 출력
logger.info("=== ELW 변동성 추이(일별) 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,117 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 변동성추이(일별)[국내주식-178]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/quotations/volatility-trend-daily"
def volatility_trend_daily(
fid_cond_mrkt_div_code: str, # 조건시장분류코드
fid_input_iscd: str, # 입력종목코드
tr_cont: str = "", # 연속 거래 여부
dataframe: Optional[pd.DataFrame] = None, # 누적 데이터프레임
depth: int = 0, # 현재 재귀 깊이
max_depth: int = 10 # 최대 재귀 깊이
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 변동성 추이(일별)[국내주식-178]
ELW 변동성 추이(일별) API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 조건시장분류코드 (예: 'W')
fid_input_iscd (str): 입력종목코드 (예: '58J297')
tr_cont (str): 연속 거래 여부 (기본값: "")
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임 (기본값: None)
depth (int): 현재 재귀 깊이 (기본값: 0)
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 변동성 추이(일별) 데이터
Example:
>>> df = volatility_trend_daily('W', '58J297')
>>> print(df)
"""
# 로깅 설정
logger = logging.getLogger(__name__)
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. '58J297')")
raise ValueError("fid_input_iscd is required. (e.g. '58J297')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
tr_id = "FHPEW02840200"
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_INPUT_ISCD": fid_input_iscd,
}
# API 호출
res = ka._url_fetch(API_URL, tr_id, tr_cont, params)
if res.isOK():
# 응답 데이터 처리
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
# 데이터프레임 병합
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
# 연속 거래 여부 확인
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return volatility_trend_daily(
fid_cond_mrkt_div_code,
fid_input_iscd,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
# API 에러 처리
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()

View File

@@ -0,0 +1,103 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from volatility_trend_minute import volatility_trend_minute
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 변동성 추이(분별)[국내주식-179]
##############################################################################################
COLUMN_MAPPING = {
'stck_bsop_date': '주식 영업 일자',
'stck_cntg_hour': '주식 체결 시간',
'stck_prpr': '주식 현재가',
'elw_oprc': 'ELW 시가2',
'elw_hgpr': 'ELW 최고가',
'elw_lwpr': 'ELW 최저가',
'hts_ints_vltl': 'HTS 내재 변동성',
'hist_vltl': '역사적 변동성'
}
NUMERIC_COLUMNS = [
'주식 현재가', 'ELW 시가2', 'ELW 최고가', 'ELW 최저가', 'HTS 내재 변동성', '역사적 변동성'
]
def main():
"""
[국내주식] ELW시세
ELW 변동성 추이(분별)[국내주식-179]
ELW 변동성 추이(분별) 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (W(Unique key))
- fid_input_iscd (str): 입력종목코드 (ex) 58J297(KBJ297삼성전자콜))
- fid_hour_cls_code (str): 시간구분코드 ('60(1분), 180(3분), 300(5분), 600(10분), 1800(30분), 3600(60분) ')
- fid_pw_data_incu_yn (str): 과거데이터 포함 여부 (N(과거데이터포함X),Y(과거데이터포함O))
Returns:
- DataFrame: ELW 변동성 추이(분별) 결과
Example:
>>> df = volatility_trend_minute(fid_cond_mrkt_div_code="W", fid_input_iscd="58J297", fid_hour_cls_code="60", fid_pw_data_incu_yn="N")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result = volatility_trend_minute(
fid_cond_mrkt_div_code="W", # 조건시장분류코드
fid_input_iscd="57LA50", # 입력종목코드
fid_hour_cls_code="60", # 시간구분코드
fid_pw_data_incu_yn="N", # 과거데이터 포함 여부
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자 컬럼 처리
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 결과 출력
logger.info("=== ELW 변동성 추이(분별) 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,142 @@
# [국내주식] ELW시세 - ELW 변동성 추이(분별)
# Generated by KIS API Generator (Single API Mode)
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import logging
import time
from typing import Optional, Tuple
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 변동성추이(분별)[국내주식-179]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/quotations/volatility-trend-minute"
def volatility_trend_minute(
fid_cond_mrkt_div_code: str, # 조건시장분류코드
fid_input_iscd: str, # 입력종목코드
fid_hour_cls_code: str, # 시간구분코드
fid_pw_data_incu_yn: str, # 과거데이터 포함 여부
tr_cont: str = "", # 연속 거래 여부
dataframe: Optional[pd.DataFrame] = None, # 누적 데이터프레임
depth: int = 0, # 현재 재귀 깊이
max_depth: int = 10 # 최대 재귀 깊이
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 변동성 추이(분별)[국내주식-179]
ELW 변동성 추이(분별) API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 조건시장분류코드 (예: 'W')
fid_input_iscd (str): 입력종목코드 (예: '58J297')
fid_hour_cls_code (str): 시간구분코드 (예: '60', '180', '300', '600', '1800', '3600')
fid_pw_data_incu_yn (str): 과거데이터 포함 여부 ('N' 또는 'Y')
tr_cont (str): 연속 거래 여부 (기본값: "")
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임
depth (int): 현재 재귀 깊이
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 변동성 추이(분별) 데이터
Example:
>>> df = volatility_trend_minute(
... fid_cond_mrkt_div_code='W',
... fid_input_iscd='58J297',
... fid_hour_cls_code='60',
... fid_pw_data_incu_yn='N'
... )
>>> print(df)
"""
# 로깅 설정
logger = logging.getLogger(__name__)
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. '58J297')")
raise ValueError("fid_input_iscd is required. (e.g. '58J297')")
if not fid_hour_cls_code:
logger.error("fid_hour_cls_code is required. (e.g. '60')")
raise ValueError("fid_hour_cls_code is required. (e.g. '60')")
if not fid_pw_data_incu_yn:
logger.error("fid_pw_data_incu_yn is required. (e.g. 'N')")
raise ValueError("fid_pw_data_incu_yn is required. (e.g. 'N')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
# API 호출 URL 및 거래 ID 설정
url = API_URL
tr_id = "FHPEW02840300"
# 요청 파라미터 설정
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_INPUT_ISCD": fid_input_iscd,
"FID_HOUR_CLS_CODE": fid_hour_cls_code,
"FID_PW_DATA_INCU_YN": fid_pw_data_incu_yn,
}
# API 호출
res = ka._url_fetch(url, tr_id, tr_cont, params)
# API 응답 처리
if res.isOK():
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
# 데이터프레임 병합
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
# 연속 거래 여부 확인
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return volatility_trend_minute(
fid_cond_mrkt_div_code,
fid_input_iscd,
fid_hour_cls_code,
fid_pw_data_incu_yn,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()

View File

@@ -0,0 +1,95 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from volatility_trend_tick import volatility_trend_tick
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 변동성 추이(틱)[국내주식-180]
##############################################################################################
COLUMN_MAPPING = {
'bsop_date': '주식영업일자',
'stck_cntg_hour': 'ELW현재가',
'elw_prpr': '전일대비',
'hts_ints_vltl': '전일대비부호'
}
NUMERIC_COLUMNS = [
'ELW현재가', '전일대비'
]
def main():
"""
[국내주식] ELW시세
ELW 변동성 추이(틱)[국내주식-180]
ELW 변동성 추이(틱) 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (W(Unique key))
- fid_input_iscd (str): 입력종목코드 (ex) 58J297(KBJ297삼성전자콜))
Returns:
- DataFrame: ELW 변동성 추이(틱) 결과
Example:
>>> df = volatility_trend_tick(fid_cond_mrkt_div_code="W", fid_input_iscd="58J297")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result = volatility_trend_tick(
fid_cond_mrkt_div_code="W", # 조건시장분류코드
fid_input_iscd="57LA50", # 입력종목코드
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자 컬럼 처리
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 결과 출력
logger.info("=== ELW 변동성 추이(틱) 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,119 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 변동성추이(틱)[국내주식-180]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/quotations/volatility-trend-tick"
def volatility_trend_tick(
fid_cond_mrkt_div_code: str, # 조건시장분류코드
fid_input_iscd: str, # 입력종목코드
tr_cont: str = "", # 연속 거래 여부
dataframe: Optional[pd.DataFrame] = None, # 누적 데이터프레임
depth: int = 0, # 현재 재귀 깊이
max_depth: int = 10 # 최대 재귀 깊이
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 변동성 추이(틱)[국내주식-180]
ELW 변동성 추이(틱) API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 조건시장분류코드 (예: 'W')
fid_input_iscd (str): 입력종목코드 (예: '58J297')
tr_cont (str): 연속 거래 여부 (기본값: "")
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임
depth (int): 현재 재귀 깊이
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 변동성 추이(틱) 데이터
Example:
>>> df = volatility_trend_tick('W', '58J297')
>>> print(df)
"""
# 로깅 설정
logger = logging.getLogger(__name__)
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. '58J297')")
raise ValueError("fid_input_iscd is required. (e.g. '58J297')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
# API 호출 URL 및 거래 ID 설정
url = API_URL
tr_id = "FHPEW02840400"
# 요청 파라미터 설정
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_INPUT_ISCD": fid_input_iscd,
}
# API 호출
res = ka._url_fetch(url, tr_id, tr_cont, params)
# API 응답 처리
if res.isOK():
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
# 데이터프레임 병합
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
# 연속 거래 여부 확인
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return volatility_trend_tick(
fid_cond_mrkt_div_code,
fid_input_iscd,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()

View File

@@ -0,0 +1,162 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from volume_rank import volume_rank
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 거래량순위[국내주식-168]
##############################################################################################
COLUMN_MAPPING = {
'elw_kor_isnm': 'ELW한글종목명',
'elw_shrn_iscd': 'ELW단축종목코드',
'elw_prpr': 'ELW현재가',
'prdy_vrss': '전일대비',
'prdy_vrss_sign': '전일대비부호',
'prdy_ctrt': '전일대비율',
'lstn_stcn': '상장주수',
'acml_vol': '누적거래량',
'n_prdy_vol': 'N전일거래량',
'n_prdy_vol_vrss': 'N전일거래량대비',
'vol_inrt': '거래량증가율',
'vol_tnrt': '거래량회전율',
'nday_vol_tnrt': 'N일거래량회전율',
'acml_tr_pbmn': '누적거래대금',
'n_prdy_tr_pbmn': 'N전일거래대금',
'n_prdy_tr_pbmn_vrss': 'N전일거래대금대비',
'total_askp_rsqn': '총매도호가잔량',
'total_bidp_rsqn': '총매수호가잔량',
'ntsl_rsqn': '순매도잔량',
'ntby_rsqn': '순매수잔량',
'seln_rsqn_rate': '매도잔량비율',
'shnu_rsqn_rate': '매수2잔량비율',
'stck_cnvr_rate': '주식전환비율',
'hts_rmnn_dynu': 'HTS잔존일수',
'invl_val': '내재가치값',
'tmvl_val': '시간가치값',
'acpr': '행사가',
'unas_isnm': '기초자산명',
'stck_last_tr_date': '최종거래일',
'unas_shrn_iscd': '기초자산코드',
'prdy_vol': '전일거래량',
'lp_hldn_rate': 'LP보유비율',
'prit': '패리티',
'prls_qryr_stpr_prc': '손익분기주가가격',
'delta_val': '델타값',
'theta': '세타',
'prls_qryr_rate': '손익분기비율',
'stck_lstn_date': '주식상장일자',
'hts_ints_vltl': 'HTS내재변동성',
'lvrg_val': '레버리지값',
'lp_ntby_qty': 'LP순매도량'
}
NUMERIC_COLUMNS = [
'ELW현재가', '전일대비', '전일대비율', '상장주수', '누적거래량', 'N전일거래량', 'N전일거래량대비',
'거래량증가율', '거래량회전율', 'N일거래량회전율', '누적거래대금', 'N전일거래대금', 'N전일거래대금대비',
'총매도호가잔량', '총매수호가잔량', '순매도잔량', '순매수잔량', '매도잔량비율', '매수2잔량비율',
'주식전환비율', 'HTS잔존일수', '내재가치값', '시간가치값', '행사가', '전일거래량', 'LP보유비율',
'패리티', '손익분기주가가격', '델타값', '세타', '손익분기비율', 'HTS내재변동성', '레버리지값', 'LP순매도량'
]
def main():
"""
[국내주식] ELW시세
ELW 거래량순위[국내주식-168]
ELW 거래량순위 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (W)
- fid_cond_scr_div_code (str): 조건화면분류코드 (20278)
- fid_unas_input_iscd (str): 기초자산입력종목코드 (000000)
- fid_input_iscd (str): 발행사 (00000(전체), 00003(한국투자증권) , 00017(KB증권), 00005(미래에셋주식회사)')
- fid_input_rmnn_dynu_1 (str): 입력잔존일수 ()
- fid_div_cls_code (str): 콜풋구분코드 (0(전체), 1(콜), 2(풋))
- fid_input_price_1 (str): 가격(이상) (거래가격1(이상))
- fid_input_price_2 (str): 가격(이하) (거래가격1(이하))
- fid_input_vol_1 (str): 거래량(이상) (거래량1(이상))
- fid_input_vol_2 (str): 거래량(이하) (거래량1(이하))
- fid_input_date_1 (str): 조회기준일 (입력날짜(기준가 조회기준))
- fid_rank_sort_cls_code (str): 순위정렬구분코드 (0: 거래량순 1: 평균거래증가율 2: 평균거래회전율 3:거래금액순 4: 순매수잔량순 5: 순매도잔량순)
- fid_blng_cls_code (str): 소속구분코드 (0: 전체)
- fid_input_iscd_2 (str): LP발행사 (0000)
- fid_input_date_2 (str): 만기일-최종거래일조회 (공백)
Returns:
- DataFrame: ELW 거래량순위 결과
Example:
>>> df = volume_rank(fid_cond_mrkt_div_code="W", fid_cond_scr_div_code="20278", fid_unas_input_iscd="000000", fid_input_iscd="00000", fid_input_rmnn_dynu_1="", fid_div_cls_code="0", fid_input_price_1="0", fid_input_price_2="100000", fid_input_vol_1="0", fid_input_vol_2="1000000", fid_input_date_1="20250101", fid_rank_sort_cls_code="0", fid_blng_cls_code="0", fid_input_iscd_2="0000", fid_input_date_2="")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 토큰 발급
logger.info("토큰 발급 중...")
ka.auth()
logger.info("토큰 발급 완료")
# API 호출
logger.info("API 호출")
result = volume_rank(
fid_cond_mrkt_div_code="W", # 조건시장분류코드
fid_cond_scr_div_code="20278", # 조건화면분류코드
fid_unas_input_iscd="000000", # 기초자산입력종목코드
fid_input_iscd="00000", # 발행사
fid_input_rmnn_dynu_1="0", # 입력잔존일수
fid_div_cls_code="0", # 콜풋구분코드
fid_input_price_1="", # 가격(이상)
fid_input_price_2="", # 가격(이하)
fid_input_vol_1="", # 거래량(이상)
fid_input_vol_2="", # 거래량(이하)
fid_input_date_1="", # 조회기준일
fid_rank_sort_cls_code="0", # 순위정렬구분코드
fid_blng_cls_code="0", # 소속구분코드
fid_input_iscd_2="0000", # LP발행사
fid_input_date_2="", # 만기일-최종거래일조회
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자 컬럼 처리
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce').round(2)
# 결과 출력
logger.info("=== ELW 거래량순위 결과 ===")
logger.info("조회된 데이터 건수: %d", len(result))
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,203 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-18
"""
import logging
import time
from typing import Optional
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [국내주식] ELW시세 - ELW 거래량순위[국내주식-168]
##############################################################################################
# 상수 정의
API_URL = "/uapi/elw/v1/ranking/volume-rank"
def volume_rank(
fid_cond_mrkt_div_code: str, # 조건시장분류코드
fid_cond_scr_div_code: str, # 조건화면분류코드
fid_unas_input_iscd: str, # 기초자산입력종목코드
fid_input_iscd: str, # 발행사
fid_input_rmnn_dynu_1: str, # 입력잔존일수
fid_div_cls_code: str, # 콜풋구분코드
fid_input_price_1: str, # 가격(이상)
fid_input_price_2: str, # 가격(이하)
fid_input_vol_1: str, # 거래량(이상)
fid_input_vol_2: str, # 거래량(이하)
fid_input_date_1: str, # 조회기준일
fid_rank_sort_cls_code: str, # 순위정렬구분코드
fid_blng_cls_code: str, # 소속구분코드
fid_input_iscd_2: str, # LP발행사
fid_input_date_2: str, # 만기일-최종거래일조회
tr_cont: str = "",
dataframe: Optional[pd.DataFrame] = None,
depth: int = 0,
max_depth: int = 10
) -> Optional[pd.DataFrame]:
"""
[국내주식] ELW시세
ELW 거래량순위[국내주식-168]
ELW 거래량순위 API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 조건시장분류코드 (예: 'W')
fid_cond_scr_div_code (str): 조건화면분류코드 (예: '20278')
fid_unas_input_iscd (str): 기초자산입력종목코드 (예: '000000')
fid_input_iscd (str): 발행사 (예: '00000')
fid_input_rmnn_dynu_1 (str): 입력잔존일수
fid_div_cls_code (str): 콜풋구분코드 (예: '0')
fid_input_price_1 (str): 가격(이상)
fid_input_price_2 (str): 가격(이하)
fid_input_vol_1 (str): 거래량(이상)
fid_input_vol_2 (str): 거래량(이하)
fid_input_date_1 (str): 조회기준일
fid_rank_sort_cls_code (str): 순위정렬구분코드 (예: '0')
fid_blng_cls_code (str): 소속구분코드 (예: '0')
fid_input_iscd_2 (str): LP발행사 (예: '0000')
fid_input_date_2 (str): 만기일-최종거래일조회
tr_cont (str): 연속 거래 여부
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임
depth (int): 현재 재귀 깊이
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: ELW 거래량순위 데이터
Example:
>>> df = volume_rank(
... fid_cond_mrkt_div_code='W',
... fid_cond_scr_div_code='20278',
... fid_unas_input_iscd='000000',
... fid_input_iscd='00000',
... fid_input_rmnn_dynu_1='',
... fid_div_cls_code='0',
... fid_input_price_1='1000',
... fid_input_price_2='5000',
... fid_input_vol_1='100',
... fid_input_vol_2='1000',
... fid_input_date_1='20230101',
... fid_rank_sort_cls_code='0',
... fid_blng_cls_code='0',
... fid_input_iscd_2='0000',
... fid_input_date_2=''
... )
>>> print(df)
"""
# 로깅 설정
logger = logging.getLogger(__name__)
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'W')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'W')")
if not fid_cond_scr_div_code:
logger.error("fid_cond_scr_div_code is required. (e.g. '20278')")
raise ValueError("fid_cond_scr_div_code is required. (e.g. '20278')")
if not fid_unas_input_iscd:
logger.error("fid_unas_input_iscd is required. (e.g. '000000')")
raise ValueError("fid_unas_input_iscd is required. (e.g. '000000')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. '00000')")
raise ValueError("fid_input_iscd is required. (e.g. '00000')")
if not fid_div_cls_code:
logger.error("fid_div_cls_code is required. (e.g. '0')")
raise ValueError("fid_div_cls_code is required. (e.g. '0')")
if not fid_rank_sort_cls_code:
logger.error("fid_rank_sort_cls_code is required. (e.g. '0')")
raise ValueError("fid_rank_sort_cls_code is required. (e.g. '0')")
if not fid_blng_cls_code:
logger.error("fid_blng_cls_code is required. (e.g. '0')")
raise ValueError("fid_blng_cls_code is required. (e.g. '0')")
if not fid_input_iscd_2:
logger.error("fid_input_iscd_2 is required. (e.g. '0000')")
raise ValueError("fid_input_iscd_2 is required. (e.g. '0000')")
# 최대 재귀 깊이 체크
if depth >= max_depth:
logger.warning("Maximum recursion depth (%d) reached. Stopping further requests.", max_depth)
return dataframe if dataframe is not None else pd.DataFrame()
url = API_URL
tr_id = "FHPEW02780000"
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_COND_SCR_DIV_CODE": fid_cond_scr_div_code,
"FID_UNAS_INPUT_ISCD": fid_unas_input_iscd,
"FID_INPUT_ISCD": fid_input_iscd,
"FID_INPUT_RMNN_DYNU_1": fid_input_rmnn_dynu_1,
"FID_DIV_CLS_CODE": fid_div_cls_code,
"FID_INPUT_PRICE_1": fid_input_price_1,
"FID_INPUT_PRICE_2": fid_input_price_2,
"FID_INPUT_VOL_1": fid_input_vol_1,
"FID_INPUT_VOL_2": fid_input_vol_2,
"FID_INPUT_DATE_1": fid_input_date_1,
"FID_RANK_SORT_CLS_CODE": fid_rank_sort_cls_code,
"FID_BLNG_CLS_CODE": fid_blng_cls_code,
"FID_INPUT_ISCD_2": fid_input_iscd_2,
"FID_INPUT_DATE_2": fid_input_date_2,
}
# API 호출
res = ka._url_fetch(url, tr_id, tr_cont, params)
if res.isOK():
# 응답 데이터 처리
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
current_data = pd.DataFrame(output_data)
else:
current_data = pd.DataFrame()
# 데이터프레임 병합
if dataframe is not None:
dataframe = pd.concat([dataframe, current_data], ignore_index=True)
else:
dataframe = current_data
# 연속 거래 여부 확인
tr_cont = res.getHeader().tr_cont
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return volume_rank(
fid_cond_mrkt_div_code,
fid_cond_scr_div_code,
fid_unas_input_iscd,
fid_input_iscd,
fid_input_rmnn_dynu_1,
fid_div_cls_code,
fid_input_price_1,
fid_input_price_2,
fid_input_vol_1,
fid_input_vol_2,
fid_input_date_1,
fid_rank_sort_cls_code,
fid_blng_cls_code,
fid_input_iscd_2,
fid_input_date_2,
"N", dataframe, depth + 1, max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe
else:
# API 에러 처리
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame()