import datetime as dtm
from decimal import Decimal
from pyqqq.brokerage.kis.oauth import KISAuth
from pyqqq.brokerage.kis.tr_client import KISTRClient
[docs]
class KISDomesticFutureOption:
"""
한국투자증권 국내선물옵션 API
"""
[docs]
def __init__(self, auth: KISAuth, corp_data: dict = None):
self.auth = auth
self.corp_data = corp_data
self.tr_client = KISTRClient(auth, corp_data)
def _tr_request(self, *args, **kwargs):
return self.tr_client.request(*args, **kwargs)
[docs]
def inquire_time_fuopchartprice(
self,
fid_input_iscd: str,
fid_input_date_1: dtm.date,
fid_input_hour_1: dtm.time | str,
fid_cond_mrkt_div_code: str = "F",
fid_hour_cls_code: str = "60",
fid_pw_data_incu_yn: str = "Y",
fid_fake_tick_incu_yn: str = "N",
):
"""
(국내선물옵션시세) 선물옵션 분봉조회[v1_국내선물-012]
선물옵션 분봉조회 API입니다.
실전계좌의 경우, 한 번의 호출에 최대 102건까지 확인 가능하며, FID_INPUT_DATE_1(입력날짜), FID_INPUT_HOUR_1(입력시간)을 이용하여 다음조회 가능합니다.
tr_cont를 이용한 다음조회는 불가능한 API입니다.
CM(야간선물), EU(야간옵션)의 경우 자정 이후 시간은 +24시간으로 입력/표시됩니다. (ex. "253000" = 새벽 1시 30분)
자정 이후 봉은 stck_bsop_date(영업일자)와 실제 달력상 일자가 다릅니다.
Args:
fid_input_iscd (str): 종목번호 (지수선물 6자리, 지수옵션 9자리. ex. A01609 - KOSPI200 선물 2026년 9월물)
fid_input_date_1 (dtm.date): 조회 기준일자 - 입력 날짜 기준으로 이전 기간 역순 조회
fid_input_hour_1 (dtm.time | str): 조회 기준시간 - 입력 시간 기준으로 역순 조회. 야간시장(CM/EU)의 자정 이후 시간은 +24시간 HHMMSS 문자열로 입력 (ex. "253000")
fid_cond_mrkt_div_code (str): FID 조건시장분류코드 - F:지수선물 O:지수옵션 JF:주식선물 JO:주식옵션 CF:상품선물(금),금리선물(국채),통화선물(달러) CM:야간선물 EU:야간옵션
fid_hour_cls_code (str): FID 시간구분코드 - 30:30초 60:1분 3600:1시간
fid_pw_data_incu_yn (str): 과거 데이터 포함 여부 - Y:과거 N:당일
fid_fake_tick_incu_yn (str): 허봉 포함 여부 - N으로 입력
Returns:
dict:
- rt_cd (str): 응답코드
- msg_cd (str): 메시지코드
- msg1 (str): 메시지1
- tr_cont (str): 연속거래여부
- output1 (dict): 응답상세1
- futs_prdy_vrss: 선물 전일 대비
- prdy_vrss_sign: 전일 대비 부호 - 1:상한 2:상승 3:보합 4:하한 5:하락
- futs_prdy_ctrt: 선물 전일 대비율
- futs_prdy_clpr: 선물 전일 종가
- prdy_nmix: 전일 지수
- acml_vol: 누적 거래량
- acml_tr_pbmn: 누적 거래 대금
- hts_kor_isnm: HTS 한글 종목명
- futs_prpr: 선물 현재가
- futs_shrn_iscd: 선물 단축 종목코드
- prdy_vol: 전일 거래량
- futs_mxpr: 선물 상한가
- futs_llam: 선물 하한가
- futs_oprc: 선물 시가2
- futs_hgpr: 선물 최고가
- futs_lwpr: 선물 최저가
- futs_prdy_oprc: 선물 전일 시가
- futs_prdy_hgpr: 선물 전일 최고가
- futs_prdy_lwpr: 선물 전일 최저가
- futs_askp: 선물 매도호가
- futs_bidp: 선물 매수호가
- basis: 베이시스
- kospi200_nmix: KOSPI200 지수
- kospi200_prdy_vrss: KOSPI200 전일 대비
- kospi200_prdy_ctrt: KOSPI200 전일 대비율
- kospi200_prdy_vrss_sign: KOSPI200 전일 대비 부호
- hts_otst_stpl_qty: HTS 미결제 약정 수량
- otst_stpl_qty_icdc: 미결제 약정 수량 증감
- tday_rltv: 당일 체결강도
- hts_thpr: HTS 이론가
- dprt: 괴리율
- output2 (list): 응답상세2
- stck_bsop_date: 주식 영업 일자
- stck_cntg_hour: 주식 체결 시간 - 야간시장(CM/EU)의 자정 이후 시간은 +24시간에서 24시간을 뺀 시간으로 변환됨
- futs_prpr: 선물 현재가
- futs_oprc: 선물 시가2
- futs_hgpr: 선물 최고가
- futs_lwpr: 선물 최저가
- cntg_vol: 체결 거래량
- acml_tr_pbmn: 누적 거래 대금
Raise:
ValueError: API 에러 발생시
"""
assert not self.auth.paper_trading, "실전계좌에서만 사용 가능한 API입니다."
assert fid_cond_mrkt_div_code in ["F", "O", "JF", "JO", "CF", "CM", "EU"], 'fid_cond_mrkt_div_code must be one of "F", "O", "JF", "JO", "CF", "CM", or "EU"'
assert fid_hour_cls_code in ["30", "60", "3600"], 'fid_hour_cls_code must be one of "30", "60", or "3600"'
assert fid_pw_data_incu_yn in ["Y", "N"], 'fid_pw_data_incu_yn must be "Y" or "N"'
assert fid_fake_tick_incu_yn in ["Y", "N"], 'fid_fake_tick_incu_yn must be "Y" or "N"'
url_path = "/uapi/domestic-futureoption/v1/quotations/inquire-time-fuopchartprice"
tr_id = "FHKIF03020200"
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,
"FID_FAKE_TICK_INCU_YN": fid_fake_tick_incu_yn,
"FID_INPUT_DATE_1": fid_input_date_1.strftime("%Y%m%d"),
"FID_INPUT_HOUR_1": fid_input_hour_1.strftime("%H%M%S") if isinstance(fid_input_hour_1, dtm.time) else fid_input_hour_1,
}
res_body, res_headers = self._tr_request(url_path, tr_id, params=params)
if res_body["rt_cd"] != "0":
raise ValueError(f"Error: ({res_body['msg_cd']}) {res_body['msg1']}")
output1 = res_body["output1"]
for k in output1.keys():
if k in ["hts_kor_isnm", "futs_shrn_iscd"]:
pass
elif k in ["prdy_vrss_sign", "kospi200_prdy_vrss_sign", "acml_vol", "prdy_vol", "acml_tr_pbmn", "hts_otst_stpl_qty", "otst_stpl_qty_icdc"]:
output1[k] = int(output1[k])
else:
output1[k] = Decimal(output1[k])
output2 = []
for el in res_body["output2"]:
for k in el.keys():
if k == "stck_bsop_date":
el[k] = dtm.datetime.strptime(el[k], "%Y%m%d").date()
elif k == "stck_cntg_hour":
hour = int(el[k][:2])
if hour >= 24:
el[k] = dtm.time(hour - 24, int(el[k][2:4]), int(el[k][4:6]))
else:
el[k] = dtm.datetime.strptime(el[k], "%H%M%S").time()
elif k in ["cntg_vol", "acml_tr_pbmn"]:
el[k] = int(el[k])
else:
el[k] = Decimal(el[k])
output2.append(el)
result = {
"rt_cd": res_body["rt_cd"],
"msg_cd": res_body["msg_cd"],
"msg1": res_body["msg1"],
"tr_cont": res_headers["tr_cont"],
"output1": output1,
"output2": output2,
}
return result