Files
KisStock/한국투자증권(API)/examples_user/domestic_futureoption/domestic_futureoption_functions.py
2026-01-31 22:34:57 +09:00

2166 lines
87 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import logging
import time
import sys
from typing import Optional, Tuple
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__)
##############################################################################################
# [국내선물옵션] 기본시세 > 국내옵션전광판_콜풋[국내선물-022]
##############################################################################################
def display_board_callput(
fid_cond_mrkt_div_code: str, # [필수] 조건 시장 분류 코드 (ex. O: 옵션)
fid_cond_scr_div_code: str, # [필수] 조건 화면 분류 코드 (ex. 20503)
fid_mrkt_cls_code: str, # [필수] 시장 구분 코드 (ex. CO: 콜옵션)
fid_mtrt_cnt: str, # [필수] 만기 수 (ex. 202508)
fid_mrkt_cls_code1: str, # [필수] 시장 구분 코드 (ex. PO: 풋옵션)
fid_cond_mrkt_cls_code: str = "" # 조건 시장 구분 코드
) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""
국내옵션전광판_콜풋 API입니다.
한국투자 HTS(eFriend Plus) > [0503] 선물옵션 종합시세() 화면의 "중앙" 기능을 API로 개발한 사항으로, 해당 화면을 참고하시면 기능을 이해하기 쉽습니다.
※ output1, output2 각각 100건까지만 확인이 가능합니다. (FY25년도 서비스 개선 예정)
※ 조회시간이 긴 API인 점 참고 부탁드리며, 잦은 호출을 삼가해주시기 바랍니다. (1초당 최대 1건 권장)
Args:
fid_cond_mrkt_div_code (str): [필수] 조건 시장 분류 코드 (ex. O: 옵션)
fid_cond_scr_div_code (str): [필수] 조건 화면 분류 코드 (ex. 20503)
fid_mrkt_cls_code (str): [필수] 시장 구분 코드 (ex. CO: 콜옵션)
fid_mtrt_cnt (str): [필수] 만기 수 (ex. 202508)
fid_mrkt_cls_code1 (str): [필수] 시장 구분 코드 (ex. PO: 풋옵션)
fid_cond_mrkt_cls_code (str): 조건 시장 구분 코드
Returns:
Tuple[pd.DataFrame, pd.DataFrame]: (output1 DataFrame, output2 DataFrame)
Example:
>>> df1, df2 = display_board_callput("O", "20503", "CO", "202508", "PO")
>>> print(df1)
>>> print(df2)
"""
# 필수 파라미터 검증
if fid_cond_mrkt_div_code == "":
raise ValueError("fid_cond_mrkt_div_code is required (e.g. 'O')")
if fid_cond_scr_div_code == "":
raise ValueError("fid_cond_scr_div_code is required (e.g. '20503')")
if fid_mrkt_cls_code == "":
raise ValueError("fid_mrkt_cls_code is required (e.g. 'CO')")
if fid_mtrt_cnt == "":
raise ValueError("fid_mtrt_cnt is required (e.g. '202508')")
if fid_mrkt_cls_code1 == "":
raise ValueError("fid_mrkt_cls_code1 is required (e.g. 'PO')")
tr_id = "FHPIF05030100"
api_url = "/uapi/domestic-futureoption/v1/quotations/display-board-callput"
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_MTRT_CNT": fid_mtrt_cnt,
"FID_MRKT_CLS_CODE1": fid_mrkt_cls_code1,
"FID_COND_MRKT_CLS_CODE": fid_cond_mrkt_cls_code
}
res = ka._url_fetch(api_url, tr_id, "", params)
if res.isOK():
output1_df = pd.DataFrame(res.getBody().output1)
output2_df = pd.DataFrame(res.getBody().output2)
return output1_df, output2_df
else:
res.printError(url=api_url)
return pd.DataFrame(), pd.DataFrame()
##############################################################################################
# [국내선물옵션] 기본시세 > 국내옵션전광판_선물[국내선물-023]
##############################################################################################
def display_board_futures(
fid_cond_mrkt_div_code: str, # 조건 시장 분류 코드
fid_cond_scr_div_code: str, # 조건 화면 분류 코드
fid_cond_mrkt_cls_code: str # 조건 시장 구분 코드
) -> pd.DataFrame:
"""
국내옵션전광판_선물 API입니다.
한국투자 HTS(eFriend Plus) > [0503] 선물옵션 종합시세() 화면의 "하단" 기능을 API로 개발한 사항입니다.
Args:
fid_cond_mrkt_div_code (str): [필수] 조건 시장 분류 코드 (ex. F)
fid_cond_scr_div_code (str): [필수] 조건 화면 분류 코드 (ex. 20503)
fid_cond_mrkt_cls_code (str): [필수] 조건 시장 구분 코드 (ex. MKI)
Returns:
pd.DataFrame: 국내선물옵션 선물전광판 데이터
Example:
>>> df = display_board_futures("F", "20503", "MKI")
>>> print(df)
"""
# 필수 파라미터 검증
if fid_cond_mrkt_div_code == "":
raise ValueError("fid_cond_mrkt_div_code is required (e.g. 'F')")
if fid_cond_scr_div_code == "":
raise ValueError("fid_cond_scr_div_code is required (e.g. '20503')")
if fid_cond_mrkt_cls_code == "":
raise ValueError("fid_cond_mrkt_cls_code is required (e.g. 'MKI')")
tr_id = "FHPIF05030200"
api_url = "/uapi/domestic-futureoption/v1/quotations/display-board-futures"
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_COND_SCR_DIV_CODE": fid_cond_scr_div_code,
"FID_COND_MRKT_CLS_CODE": fid_cond_mrkt_cls_code
}
res = ka._url_fetch(api_url, tr_id, "", params)
if res.isOK():
return pd.DataFrame(res.getBody().output)
else:
res.printError(url=api_url)
return pd.DataFrame()
##############################################################################################
# [국내선물옵션] 기본시세 > 국내옵션전광판_옵션월물리스트[국내선물-020]
##############################################################################################
def display_board_option_list(
fid_cond_scr_div_code: str,
fid_cond_mrkt_div_code: str = "",
fid_cond_mrkt_cls_code: str = ""
) -> pd.DataFrame:
"""
국내옵션전광판_옵션월물리스트 API입니다.
한국투자 HTS(eFriend Plus) > [0503] 선물옵션 종합시세() 화면의 "월물리스트 목록 확인" 기능을 API로 개발한 사항입니다.
Args:
fid_cond_scr_div_code (str): [필수] 조건 화면 분류 코드 (ex. 509)
fid_cond_mrkt_div_code (str): 조건 시장 분류 코드
fid_cond_mrkt_cls_code (str): 조건 시장 구분 코드
Returns:
pd.DataFrame: 국내옵션전광판_옵션월물리스트 데이터
Example:
>>> df = display_board_option_list(fid_cond_scr_div_code="509")
>>> print(df)
"""
if fid_cond_scr_div_code == "":
raise ValueError("fid_cond_scr_div_code is required (e.g. '509')")
tr_id = "FHPIO056104C0"
api_url = "/uapi/domestic-futureoption/v1/quotations/display-board-option-list"
params = {
"FID_COND_SCR_DIV_CODE": fid_cond_scr_div_code,
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_COND_MRKT_CLS_CODE": fid_cond_mrkt_cls_code
}
res = ka._url_fetch(api_url, tr_id, "", params)
if res.isOK():
current_data = pd.DataFrame(res.getBody().output)
return current_data
else:
res.printError(url=api_url)
return pd.DataFrame()
##############################################################################################
# [국내선물옵션] 기본시세 > 국내선물 기초자산 시세[국내선물-021]
##############################################################################################
def display_board_top(
fid_cond_mrkt_div_code: str, # [필수] 조건 시장 분류 코드 (ex. F)
fid_input_iscd: str, # [필수] 입력 종목코드 (ex. 101V06)
fid_cond_mrkt_div_code1: str = "", # 조건 시장 분류 코드
fid_cond_scr_div_code: str = "", # 조건 화면 분류 코드
fid_mtrt_cnt: str = "", # 만기 수
fid_cond_mrkt_cls_code: str = "" # 조건 시장 구분 코드
) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""
국내선물 기초자산 시세 API입니다.
한국투자 HTS(eFriend Plus) > [0503] 선물옵션 종합시세() 화면의 "상단 바" 기능을 API로 개발한 사항입니다.
Args:
fid_cond_mrkt_div_code (str): [필수] 조건 시장 분류 코드 (ex. F)
fid_input_iscd (str): [필수] 입력 종목코드 (ex. 101V06)
fid_cond_mrkt_div_code1 (str): 조건 시장 분류 코드
fid_cond_scr_div_code (str): 조건 화면 분류 코드
fid_mtrt_cnt (str): 만기 수
fid_cond_mrkt_cls_code (str): 조건 시장 구분 코드
Returns:
Tuple[pd.DataFrame, pd.DataFrame]: (output1, output2) 데이터프레임 튜플
Example:
>>> output1, output2 = display_board_top(fid_cond_mrkt_div_code="F", fid_input_iscd="101W09")
>>> print(output1)
>>> print(output2)
"""
if fid_cond_mrkt_div_code == "":
raise ValueError("fid_cond_mrkt_div_code is required (e.g. 'F')")
if fid_input_iscd == "":
raise ValueError("fid_input_iscd is required (e.g. '101V06')")
tr_id = "FHPIF05030000"
api_url = "/uapi/domestic-futureoption/v1/quotations/display-board-top"
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_INPUT_ISCD": fid_input_iscd,
"FID_COND_MRKT_DIV_CODE1": fid_cond_mrkt_div_code1,
"FID_COND_SCR_DIV_CODE": fid_cond_scr_div_code,
"FID_MTRT_CNT": fid_mtrt_cnt,
"FID_COND_MRKT_CLS_CODE": fid_cond_mrkt_cls_code
}
res = ka._url_fetch(api_url, tr_id, "", params)
if res.isOK():
output1 = pd.DataFrame(res.getBody().output1, index=[0])
output2 = pd.DataFrame(res.getBody().output2)
return output1, output2
else:
res.printError(url=api_url)
return pd.DataFrame(), pd.DataFrame()
##############################################################################################
# [국내선물옵션] 기본시세 > 선물옵션 일중예상체결추이[국내선물-018]
##############################################################################################
def exp_price_trend(
fid_input_iscd: str, # [필수] 입력 종목코드 (ex. 101V06)
fid_cond_mrkt_div_code: str # [필수] 조건 시장 분류 코드 (ex. F)
) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""
선물옵션 일중예상체결추이 API입니다.
한국투자 HTS(eFriend Plus) > [0548] 선물옵션 예상체결추이 화면의 기능을 API로 개발한 사항입니다.
Args:
fid_input_iscd (str): [필수] 입력 종목코드 (ex. 101V06)
fid_cond_mrkt_div_code (str): [필수] 조건 시장 분류 코드 (ex. F)
Returns:
Tuple[pd.DataFrame, pd.DataFrame]: (output1, output2) 데이터프레임 튜플
Example:
>>> df1, df2 = exp_price_trend(fid_input_iscd="101W09", fid_cond_mrkt_div_code="F")
>>> print(df1)
>>> print(df2)
"""
if fid_input_iscd == "":
raise ValueError("fid_input_iscd is required (e.g. '101V06')")
if fid_cond_mrkt_div_code == "":
raise ValueError("fid_cond_mrkt_div_code is required (e.g. 'F')")
tr_id = "FHPIF05110100" # 선물옵션 일중예상체결추이
api_url = "/uapi/domestic-futureoption/v1/quotations/exp-price-trend"
params = {
"FID_INPUT_ISCD": fid_input_iscd, # 입력 종목코드
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code # 조건 시장 분류 코드
}
res = ka._url_fetch(api_url, tr_id, "", params)
if res.isOK():
# output1은 object 타입이므로 단일 행 DataFrame
output1_data = pd.DataFrame([res.getBody().output1])
# output2는 array 타입이므로 여러 행 DataFrame
output2_data = pd.DataFrame(res.getBody().output2)
return output1_data, output2_data
else:
res.printError(url=api_url)
return pd.DataFrame(), pd.DataFrame()
##############################################################################################
# [국내선물옵션] 기본시세 > 선물옵션 시세호가[v1_국내선물-007]
##############################################################################################
def inquire_asking_price(
fid_cond_mrkt_div_code: str, # [필수] FID 조건 시장 분류 코드 (ex. F: 지수선물, JF: 주식선물)
fid_input_iscd: str, # [필수] FID 입력 종목코드 (ex. 101W09)
env_dv: str # [필수] 실전모의구분 (ex. real:실전, demo:모의)
) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""
선물옵션 시세호가 API입니다.
Args:
fid_cond_mrkt_div_code (str): [필수] FID 조건 시장 분류 코드 (ex. F: 지수선물, JF: 주식선물)
fid_input_iscd (str): [필수] FID 입력 종목코드 (ex. 101W09)
env_dv (str): [필수] 실전모의구분 (ex. real:실전, demo:모의)
Returns:
Tuple[pd.DataFrame, pd.DataFrame]: (output1 데이터, output2 데이터)
Example:
>>> df1, df2 = inquire_asking_price("F", "101W09", "real")
>>> print(df1)
>>> print(df2)
"""
# 필수 파라미터 검증
if fid_cond_mrkt_div_code == "":
raise ValueError("fid_cond_mrkt_div_code is required (e.g. 'F', 'JF')")
if fid_input_iscd == "":
raise ValueError("fid_input_iscd is required (e.g. '101W09')")
if env_dv == "":
raise ValueError("env_dv is required (e.g. 'real', 'demo')")
# TR_ID 설정
if env_dv == "real":
tr_id = "FHMIF10010000"
elif env_dv == "demo":
tr_id = "FHMIF10010000"
else:
raise ValueError("env_dv can only be 'real' or 'demo'")
api_url = "/uapi/domestic-futureoption/v1/quotations/inquire-asking-price"
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, "", params)
if res.isOK():
# output1 (object) -> DataFrame
output1_data = pd.DataFrame([res.getBody().output1])
# output2 (object) -> DataFrame
output2_data = pd.DataFrame([res.getBody().output2])
return output1_data, output2_data
else:
res.printError(url=api_url)
return pd.DataFrame(), pd.DataFrame()
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 잔고현황[v1_국내선물-004]
##############################################################################################
def inquire_balance(
env_dv: str, # [필수] 실전모의구분 (ex. real:실전, demo:모의)
cano: str, # [필수] 종합계좌번호
acnt_prdt_cd: str, # [필수] 계좌상품코드 (ex. 03)
mgna_dvsn: str, # [필수] 증거금 구분 (ex. 01:게시,02:유지)
excc_stat_cd: str, # [필수] 정산상태코드 (ex. 1:정산,2:본정산)
FK200: str = "", # 연속조회검색조건200
NK200: str = "", # 연속조회키200
tr_cont: str = "", # 연속거래여부
dataframe1: Optional[pd.DataFrame] = None, # 누적 데이터프레임1
dataframe2: Optional[pd.DataFrame] = None, # 누적 데이터프레임2
depth: int = 0, # 내부 재귀 깊이 (자동 관리)
max_depth: int = 10 # 최대 재귀 횟수 제한
) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""
선물옵션 잔고현황 API입니다. 한 번의 호출에 최대 20건까지 확인 가능하며, 이후의 값은 연속조회를 통해 확인하실 수 있습니다.
Args:
env_dv (str): [필수] 실전모의구분 (ex. real:실전, demo:모의)
cano (str): [필수] 종합계좌번호
acnt_prdt_cd (str): [필수] 계좌상품코드 (ex. 03)
mgna_dvsn (str): [필수] 증거금 구분 (ex. 01:게시,02:유지)
excc_stat_cd (str): [필수] 정산상태코드 (ex. 1:정산,2:본정산)
FK200 (str): 연속조회검색조건200
NK200 (str): 연속조회키200
tr_cont (str): 연속거래여부
dataframe1 (Optional[pd.DataFrame]): 누적 데이터프레임1
dataframe2 (Optional[pd.DataFrame]): 누적 데이터프레임2
depth (int): 내부 재귀 깊이 (자동 관리)
max_depth (int): 최대 재귀 횟수 제한
Returns:
Tuple[pd.DataFrame, pd.DataFrame]: (output1, output2) 선물옵션 잔고현황 데이터
Example:
>>> df1, df2 = inquire_balance(env_dv="real", cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, mgna_dvsn="01", excc_stat_cd="1")
>>> print(df1)
>>> print(df2)
"""
if env_dv == "":
raise ValueError("env_dv is required (e.g. 'real' or 'demo')")
if cano == "":
raise ValueError("cano is required")
if acnt_prdt_cd == "":
raise ValueError("acnt_prdt_cd is required (e.g. '03')")
if mgna_dvsn == "":
raise ValueError("mgna_dvsn is required (e.g. '01' or '02')")
if excc_stat_cd == "":
raise ValueError("excc_stat_cd is required (e.g. '1' or '2')")
if depth > max_depth:
logging.warning("Max recursive depth reached.")
if dataframe1 is None:
dataframe1 = pd.DataFrame()
if dataframe2 is None:
dataframe2 = pd.DataFrame()
return dataframe1, dataframe2
# tr_id 설정
if env_dv == "real":
tr_id = "CTFO6118R"
elif env_dv == "demo":
tr_id = "VTFO6118R"
else:
raise ValueError("env_dv can only be 'real' or 'demo'")
api_url = "/uapi/domestic-futureoption/v1/trading/inquire-balance"
params = {
"CANO": cano,
"ACNT_PRDT_CD": acnt_prdt_cd,
"MGNA_DVSN": mgna_dvsn,
"EXCC_STAT_CD": excc_stat_cd,
"CTX_AREA_FK200": FK200,
"CTX_AREA_NK200": NK200
}
res = ka._url_fetch(api_url, tr_id, tr_cont, params)
if res.isOK():
# output1 처리 (array)
current_data1 = pd.DataFrame(res.getBody().output1)
if dataframe1 is not None:
dataframe1 = pd.concat([dataframe1, current_data1], ignore_index=True)
else:
dataframe1 = current_data1
# output2 처리 (object)
current_data2 = pd.DataFrame(res.getBody().output2, index=[0])
if dataframe2 is not None:
dataframe2 = pd.concat([dataframe2, current_data2], ignore_index=True)
else:
dataframe2 = current_data2
tr_cont = res.getHeader().tr_cont
FK200 = res.getBody().ctx_area_fk200
NK200 = res.getBody().ctx_area_nk200
if tr_cont in ["M", "F"]: # 다음 페이지 존재
logging.info("Call Next page...")
ka.smart_sleep() # 시스템 안정적 운영을 위한 지연
return inquire_balance(
env_dv, cano, acnt_prdt_cd, mgna_dvsn, excc_stat_cd,
FK200, NK200, "N", dataframe1, dataframe2, depth + 1, max_depth
)
else:
logging.info("Data fetch complete.")
return dataframe1, dataframe2
else:
res.printError(url=api_url)
return pd.DataFrame(), pd.DataFrame()
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 잔고정산손익내역[v1_국내선물-013]
##############################################################################################
def inquire_balance_settlement_pl(
cano: str, # 종합계좌번호
acnt_prdt_cd: str, # 계좌상품코드 (ex. 03)
inqr_dt: str, # 조회일자
FK200: str = "", # 연속조회검색조건200
NK200: str = "", # 연속조회키200
tr_cont: str = "", # 연속거래여부
dataframe1: Optional[pd.DataFrame] = None, # 누적 데이터프레임1
dataframe2: Optional[pd.DataFrame] = None, # 누적 데이터프레임2
depth: int = 0, # 내부 재귀깊이 (자동관리)
max_depth: int = 10 # 최대 재귀 횟수 제한
) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""
선물옵션 잔고정산손익내역 API입니다.
Args:
cano (str): [필수] 종합계좌번호
acnt_prdt_cd (str): [필수] 계좌상품코드 (ex. 03)
inqr_dt (str): [필수] 조회일자
FK200 (str): 연속조회검색조건200
NK200 (str): 연속조회키200
tr_cont (str): 연속거래여부
dataframe1 (Optional[pd.DataFrame]): 누적 데이터프레임1
dataframe2 (Optional[pd.DataFrame]): 누적 데이터프레임2
depth (int): 내부 재귀깊이 (자동관리)
max_depth (int): 최대 재귀 횟수 제한
Returns:
Tuple[pd.DataFrame, pd.DataFrame]: (output1 데이터, output2 데이터)
Example:
>>> df1, df2 = inquire_balance_settlement_pl(cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, inqr_dt="20230906")
>>> print(df1)
>>> print(df2)
"""
if cano == "":
raise ValueError("cano is required")
if acnt_prdt_cd == "":
raise ValueError("acnt_prdt_cd is required")
if inqr_dt == "":
raise ValueError("inqr_dt is required")
if depth > max_depth:
logging.warning("Max recursive depth reached.")
if dataframe1 is None:
dataframe1 = pd.DataFrame()
if dataframe2 is None:
dataframe2 = pd.DataFrame()
return dataframe1, dataframe2
tr_id = "CTFO6117R"
api_url = "/uapi/domestic-futureoption/v1/trading/inquire-balance-settlement-pl"
params = {
"CANO": cano,
"ACNT_PRDT_CD": acnt_prdt_cd,
"INQR_DT": inqr_dt,
"CTX_AREA_FK200": FK200,
"CTX_AREA_NK200": NK200
}
res = ka._url_fetch(api_url, tr_id, tr_cont, params)
if res.isOK():
# output1 처리 (array)
current_data1 = pd.DataFrame(res.getBody().output1)
if dataframe1 is not None:
dataframe1 = pd.concat([dataframe1, current_data1], ignore_index=True)
else:
dataframe1 = current_data1
# output2 처리 (object)
current_data2 = pd.DataFrame([res.getBody().output2])
if dataframe2 is not None:
dataframe2 = pd.concat([dataframe2, current_data2], ignore_index=True)
else:
dataframe2 = current_data2
tr_cont = res.getHeader().tr_cont
FK200 = res.getBody().ctx_area_fk200
NK200 = res.getBody().ctx_area_nk200
if tr_cont in ["M", "F"]: # 다음 페이지 존재
logging.info("Call Next page...")
ka.smart_sleep() # 시스템 안정적 운영을 위한 지연
return inquire_balance_settlement_pl(
cano, acnt_prdt_cd, inqr_dt, FK200, NK200, "N", dataframe1, dataframe2, depth + 1, max_depth
)
else:
logging.info("Data fetch complete.")
return dataframe1, dataframe2
else:
res.printError(url=api_url)
return pd.DataFrame(), pd.DataFrame()
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 잔고평가손익내역[v1_국내선물-015]
##############################################################################################
def inquire_balance_valuation_pl(
cano: str, # [필수] 종합계좌번호 (ex. 계좌번호 체계(8-2)의 앞 8자리)
acnt_prdt_cd: str, # [필수] 계좌상품코드 (ex. 계좌번호 체계(8-2)의 뒤 2자리)
mgna_dvsn: str, # [필수] 증거금구분 (ex. 01:개시, 02:유지)
excc_stat_cd: str, # [필수] 정산상태코드 (ex. 1:정산, 2:본정산)
FK200: str = "", # 연속조회검색조건200 (ex. 연속조회검색조건200)
NK200: str = "", # 연속조회키200 (ex. 연속조회키200)
tr_cont: str = "", # 연속거래여부
dataframe1: Optional[pd.DataFrame] = None, # 누적 데이터프레임 (output1)
dataframe2: Optional[pd.DataFrame] = None, # 누적 데이터프레임 (output2)
depth: int = 0, # 내부 재귀깊이 (자동관리)
max_depth: int = 10 # 최대 재귀 횟수 제한
) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""
시장별 투자자매매동향(일별) API입니다.
한국투자 HTS(eFriend Plus) > [0404] 시장별 일별동향 화면의 기능을 API로 개발한 사항으로, 해당 화면을 참고하시면 기능을 이해하기 쉽습니다.
Args:
cano (str): [필수] 종합계좌번호 (ex. 계좌번호 체계(8-2)의 앞 8자리)
acnt_prdt_cd (str): [필수] 계좌상품코드 (ex. 계좌번호 체계(8-2)의 뒤 2자리)
mgna_dvsn (str): [필수] 증거금구분 (ex. 01:개시, 02:유지)
excc_stat_cd (str): [필수] 정산상태코드 (ex. 1:정산, 2:본정산)
FK200 (str): 연속조회검색조건200 (ex. 연속조회검색조건200)
NK200 (str): 연속조회키200 (ex. 연속조회키200)
tr_cont (str): 연속거래여부
dataframe1 (Optional[pd.DataFrame]): 누적 데이터프레임 (output1)
dataframe2 (Optional[pd.DataFrame]): 누적 데이터프레임 (output2)
depth (int): 내부 재귀깊이 (자동관리)
max_depth (int): 최대 재귀 횟수 제한
Returns:
Tuple[pd.DataFrame, pd.DataFrame]: (output1 데이터프레임, output2 데이터프레임)
Example:
>>> df1, df2 = inquire_balance_valuation_pl(cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, mgna_dvsn="01", excc_stat_cd="1")
>>> print(df1)
>>> print(df2)
"""
if cano == "":
raise ValueError("cano is required (e.g. '계좌번호 체계(8-2)의 앞 8자리')")
if acnt_prdt_cd == "":
raise ValueError("acnt_prdt_cd is required (e.g. '계좌번호 체계(8-2)의 뒤 2자리')")
if mgna_dvsn == "":
raise ValueError("mgna_dvsn is required (e.g. '01:개시, 02:유지')")
if excc_stat_cd == "":
raise ValueError("excc_stat_cd is required (e.g. '1:정산, 2:본정산')")
if depth > max_depth:
logging.warning("Max recursive depth reached.")
if dataframe1 is None:
dataframe1 = pd.DataFrame()
if dataframe2 is None:
dataframe2 = pd.DataFrame()
return dataframe1, dataframe2
tr_id = "CTFO6159R" # 선물옵션 잔고평가손익내역
api_url = "/uapi/domestic-futureoption/v1/trading/inquire-balance-valuation-pl"
params = {
"CANO": cano,
"ACNT_PRDT_CD": acnt_prdt_cd,
"MGNA_DVSN": mgna_dvsn,
"EXCC_STAT_CD": excc_stat_cd,
"CTX_AREA_FK200": FK200,
"CTX_AREA_NK200": NK200
}
res = ka._url_fetch(api_url, tr_id, tr_cont, params)
if res.isOK():
# output1 처리 (array)
current_data1 = pd.DataFrame(res.getBody().output1)
if dataframe1 is not None:
dataframe1 = pd.concat([dataframe1, current_data1], ignore_index=True)
else:
dataframe1 = current_data1
# output2 처리 (object)
current_data2 = pd.DataFrame([res.getBody().output2])
if dataframe2 is not None:
dataframe2 = pd.concat([dataframe2, current_data2], ignore_index=True)
else:
dataframe2 = current_data2
tr_cont = res.getHeader().tr_cont
FK200 = res.getBody().ctx_area_fk200
NK200 = res.getBody().ctx_area_nk200
if tr_cont in ["M", "F"]: # 다음 페이지 존재
logging.info("Call Next page...")
ka.smart_sleep() # 시스템 안정적 운영을 위한 지연
return inquire_balance_valuation_pl(
cano, acnt_prdt_cd, mgna_dvsn, excc_stat_cd, FK200, NK200, "N", dataframe1, dataframe2, depth + 1,
max_depth
)
else:
logging.info("Data fetch complete.")
return dataframe1, dataframe2
else:
res.printError(url=api_url)
return pd.DataFrame(), pd.DataFrame()
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 주문체결내역조회[v1_국내선물-003]
##############################################################################################
def inquire_ccnl(
env_dv: str, # [필수] 실전모의구분 (ex. real:실전, demo:모의)
cano: str, # [필수] 종합계좌번호
acnt_prdt_cd: str, # [필수] 계좌상품코드 (ex. 03)
strt_ord_dt: str, # [필수] 시작주문일자 (ex. 주문내역 조회 시작 일자, YYYYMMDD)
end_ord_dt: str, # [필수] 종료주문일자 (ex. 주문내역 조회 마지막 일자, YYYYMMDD)
sll_buy_dvsn_cd: str, # [필수] 매도매수구분코드 (ex. 00:전체, 01:매도, 02:매수)
ccld_nccs_dvsn: str, # [필수] 체결미체결구분 (ex. 00:전체, 01:체결, 02:미체결)
sort_sqn: str, # [필수] 정렬순서 (ex. AS:정순, DS:역순)
pdno: str = "", # 상품번호
strt_odno: str = "", # 시작주문번호
mket_id_cd: str = "", # 시장ID코드
FK200: str = "", # 연속조회검색조건200
NK200: str = "", # 연속조회키200
tr_cont: str = "", # 연속거래여부
dataframe1: Optional[pd.DataFrame] = None, # 누적 데이터프레임1
dataframe2: Optional[pd.DataFrame] = None, # 누적 데이터프레임2
depth: int = 0, # 내부 재귀깊이 (자동관리)
max_depth: int = 10 # 최대 재귀 횟수 제한
) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""
선물옵션 주문체결내역조회 API입니다. 한 번의 호출에 최대 100건까지 확인 가능하며, 이후의 값은 연속조회를 통해 확인하실 수 있습니다.
Args:
env_dv (str): [필수] 실전모의구분 (ex. real:실전, demo:모의)
cano (str): [필수] 종합계좌번호
acnt_prdt_cd (str): [필수] 계좌상품코드 (ex. 03)
strt_ord_dt (str): [필수] 시작주문일자 (ex. 주문내역 조회 시작 일자, YYYYMMDD)
end_ord_dt (str): [필수] 종료주문일자 (ex. 주문내역 조회 마지막 일자, YYYYMMDD)
sll_buy_dvsn_cd (str): [필수] 매도매수구분코드 (ex. 00:전체, 01:매도, 02:매수)
ccld_nccs_dvsn (str): [필수] 체결미체결구분 (ex. 00:전체, 01:체결, 02:미체결)
sort_sqn (str): [필수] 정렬순서 (ex. AS:정순, DS:역순)
pdno (str, optional): 상품번호. Defaults to "".
strt_odno (str, optional): 시작주문번호. Defaults to "".
mket_id_cd (str, optional): 시장ID코드. Defaults to "".
FK200 (str, optional): 연속조회검색조건200. Defaults to "".
NK200 (str, optional): 연속조회키200. Defaults to "".
tr_cont (str, optional): 연속거래여부. Defaults to "".
dataframe1 (Optional[pd.DataFrame], optional): 누적 데이터프레임1. Defaults to None.
dataframe2 (Optional[pd.DataFrame], optional): 누적 데이터프레임2. Defaults to None.
depth (int, optional): 내부 재귀깊이 (자동관리). Defaults to 0.
max_depth (int, optional): 최대 재귀 횟수 제한. Defaults to 10.
Returns:
Tuple[pd.DataFrame, pd.DataFrame]: 주문체결내역 데이터 (output1, output2)
Example:
>>> df1, df2 = inquire_ccnl(env_dv="real", cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, strt_ord_dt="20220730", end_ord_dt="20220830", sll_buy_dvsn_cd="00", ccld_nccs_dvsn="00", sort_sqn="DS")
>>> print(df1)
>>> print(df2)
"""
# 필수 파라미터 검증
if not env_dv:
raise ValueError("env_dv is required (e.g. 'real' or 'demo')")
if not cano:
raise ValueError("cano is required")
if not acnt_prdt_cd:
raise ValueError("acnt_prdt_cd is required (e.g. '03')")
if not strt_ord_dt:
raise ValueError("strt_ord_dt is required (e.g. '20220730')")
if not end_ord_dt:
raise ValueError("end_ord_dt is required (e.g. '20220830')")
if not sll_buy_dvsn_cd:
raise ValueError("sll_buy_dvsn_cd is required (e.g. '00')")
if not ccld_nccs_dvsn:
raise ValueError("ccld_nccs_dvsn is required (e.g. '00')")
if not sort_sqn:
raise ValueError("sort_sqn is required (e.g. 'AS' or 'DS')")
# 재귀 깊이 제한 확인
if depth > max_depth:
logging.warning("Max recursive depth reached.")
if dataframe1 is None:
dataframe1 = pd.DataFrame()
if dataframe2 is None:
dataframe2 = pd.DataFrame()
return dataframe1, dataframe2
# tr_id 설정
if env_dv == "real":
tr_id = "TTTO5201R"
elif env_dv == "demo":
tr_id = "VTTO5201R"
else:
raise ValueError("env_dv can only be 'real' or 'demo'")
# 파라미터 설정
api_url = "/uapi/domestic-futureoption/v1/trading/inquire-ccnl"
params = {
"CANO": cano,
"ACNT_PRDT_CD": acnt_prdt_cd,
"STRT_ORD_DT": strt_ord_dt,
"END_ORD_DT": end_ord_dt,
"SLL_BUY_DVSN_CD": sll_buy_dvsn_cd,
"CCLD_NCCS_DVSN": ccld_nccs_dvsn,
"SORT_SQN": sort_sqn,
"PDNO": pdno,
"STRT_ODNO": strt_odno,
"MKET_ID_CD": mket_id_cd,
"CTX_AREA_FK200": FK200,
"CTX_AREA_NK200": NK200
}
res = ka._url_fetch(api_url, tr_id, tr_cont, params)
if res.isOK():
# output1 데이터 처리
current_data1 = pd.DataFrame(res.getBody().output1)
if dataframe1 is not None:
dataframe1 = pd.concat([dataframe1, current_data1], ignore_index=True)
else:
dataframe1 = current_data1
# output2 데이터 처리 (단일 객체)
current_data2 = pd.DataFrame(res.getBody().output2, index=[0])
if dataframe2 is not None:
dataframe2 = pd.concat([dataframe2, current_data2], ignore_index=True)
else:
dataframe2 = current_data2
# 연속조회 정보 업데이트
tr_cont = res.getHeader().tr_cont
FK200 = res.getBody().ctx_area_fk200
NK200 = res.getBody().ctx_area_nk200
if tr_cont in ["M", "F"]: # 다음 페이지 존재
logging.info("Call Next page...")
ka.smart_sleep() # 시스템 안정적 운영을 위한 지연
return inquire_ccnl(
env_dv, cano, acnt_prdt_cd, strt_ord_dt, end_ord_dt,
sll_buy_dvsn_cd, ccld_nccs_dvsn, sort_sqn, pdno, strt_odno,
mket_id_cd, FK200, NK200, "N", dataframe1, dataframe2,
depth + 1, max_depth
)
else:
logging.info("Data fetch complete.")
return dataframe1, dataframe2
else:
res.printError(url=api_url)
return pd.DataFrame(), pd.DataFrame()
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 기준일체결내역[v1_국내선물-016]
##############################################################################################
def inquire_ccnl_bstime(
cano: str, # [필수] 종합계좌번호
acnt_prdt_cd: str, # [필수] 계좌상품코드 (ex. 03)
ord_dt: str, # [필수] 주문일자 (ex. 20250101)
fuop_tr_strt_tmd: str, # [필수] 선물옵션거래시작시각 (ex. HHMMSS)
fuop_tr_end_tmd: str, # [필수] 선물옵션거래종료시각 (ex. HHMMSS)
FK200: str = "", # 연속조회검색조건200
NK200: str = "", # 연속조회키200
tr_cont: str = "", # 연속거래여부
dataframe1: Optional[pd.DataFrame] = None, # 누적 데이터프레임1
dataframe2: Optional[pd.DataFrame] = None, # 누적 데이터프레임2
depth: int = 0, # 내부 재귀깊이 (자동관리)
max_depth: int = 10 # 최대 재귀 횟수 제한
) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""
선물옵션 기준일체결내역 API입니다.
Args:
cano (str): [필수] 종합계좌번호
acnt_prdt_cd (str): [필수] 계좌상품코드 (ex. 03)
ord_dt (str): [필수] 주문일자 (ex. 20250101)
fuop_tr_strt_tmd (str): [필수] 선물옵션거래시작시각 (ex. HHMMSS)
fuop_tr_end_tmd (str): [필수] 선물옵션거래종료시각 (ex. HHMMSS)
FK200 (str): 연속조회검색조건200
NK200 (str): 연속조회키200
tr_cont (str): 연속거래여부
dataframe1 (Optional[pd.DataFrame]): 누적 데이터프레임1
dataframe2 (Optional[pd.DataFrame]): 누적 데이터프레임2
depth (int): 내부 재귀깊이 (자동관리)
max_depth (int): 최대 재귀 횟수 제한
Returns:
Tuple[pd.DataFrame, pd.DataFrame]: 선물옵션 기준일체결내역 데이터 (output1, output2)
Example:
>>> df1, df2 = inquire_ccnl_bstime(cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, ord_dt="20230920", fuop_tr_strt_tmd="000000", fuop_tr_end_tmd="240000")
>>> print(df1)
>>> print(df2)
"""
if cano == "":
raise ValueError("cano is required")
if acnt_prdt_cd == "":
raise ValueError("acnt_prdt_cd is required (e.g. '03')")
if ord_dt == "":
raise ValueError("ord_dt is required (e.g. '20250101')")
if fuop_tr_strt_tmd == "":
raise ValueError("fuop_tr_strt_tmd is required (e.g. 'HHMMSS')")
if fuop_tr_end_tmd == "":
raise ValueError("fuop_tr_end_tmd is required (e.g. 'HHMMSS')")
if depth > max_depth:
logging.warning("Max recursive depth reached.")
if dataframe1 is None:
dataframe1 = pd.DataFrame()
if dataframe2 is None:
dataframe2 = pd.DataFrame()
return dataframe1, dataframe2
tr_id = "CTFO5139R"
api_url = "/uapi/domestic-futureoption/v1/trading/inquire-ccnl-bstime"
params = {
"CANO": cano, # 종합계좌번호
"ACNT_PRDT_CD": acnt_prdt_cd, # 계좌상품코드
"ORD_DT": ord_dt, # 주문일자
"FUOP_TR_STRT_TMD": fuop_tr_strt_tmd, # 선물옵션거래시작시각
"FUOP_TR_END_TMD": fuop_tr_end_tmd, # 선물옵션거래종료시각
"CTX_AREA_FK200": FK200, # 연속조회검색조건200
"CTX_AREA_NK200": NK200 # 연속조회키200
}
res = ka._url_fetch(api_url, tr_id, tr_cont, params)
if res.isOK():
# output1 처리 (array)
current_data1 = pd.DataFrame(res.getBody().output1)
if dataframe1 is not None:
dataframe1 = pd.concat([dataframe1, current_data1], ignore_index=True)
else:
dataframe1 = current_data1
# output2 처리 (object)
current_data2 = pd.DataFrame([res.getBody().output2])
if dataframe2 is not None:
dataframe2 = pd.concat([dataframe2, current_data2], ignore_index=True)
else:
dataframe2 = current_data2
tr_cont = res.getHeader().tr_cont
FK200 = res.getBody().ctx_area_fk200
NK200 = res.getBody().ctx_area_nk200
if tr_cont in ["M", "F"]: # 다음 페이지 존재
logging.info("Call Next page...")
ka.smart_sleep() # 시스템 안정적 운영을 위한 지연
return inquire_ccnl_bstime(
cano, acnt_prdt_cd, ord_dt, fuop_tr_strt_tmd, fuop_tr_end_tmd,
FK200, NK200, "N", dataframe1, dataframe2, depth + 1, max_depth
)
else:
logging.info("Data fetch complete.")
return dataframe1, dataframe2
else:
res.printError(url=api_url)
return pd.DataFrame(), pd.DataFrame()
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션기간약정수수료일별[v1_국내선물-017]
##############################################################################################
def inquire_daily_amount_fee(
cano: str, # [필수] 종합계좌번호
acnt_prdt_cd: str, # [필수] 계좌상품코드 (ex. 03)
inqr_strt_day: str, # [필수] 조회시작일 (ex. 20240401)
inqr_end_day: str, # [필수] 조회종료일 (ex. 20240625)
FK200: str = "", # 연속조회검색조건200
NK200: str = "", # 연속조회키200
tr_cont: str = "", # 연속거래여부
dataframe1: Optional[pd.DataFrame] = None, # 누적 데이터프레임1
dataframe2: Optional[pd.DataFrame] = None, # 누적 데이터프레임2
depth: int = 0, # 내부 재귀깊이 (자동관리)
max_depth: int = 10 # 최대 재귀 횟수 제한
) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""
선물옵션기간약정수수료일별 API입니다.
Args:
cano (str): [필수] 종합계좌번호
acnt_prdt_cd (str): [필수] 계좌상품코드 (ex. 03)
inqr_strt_day (str): [필수] 조회시작일 (ex. 20240401)
inqr_end_day (str): [필수] 조회종료일 (ex. 20240625)
FK200 (str): 연속조회검색조건200
NK200 (str): 연속조회키200
tr_cont (str): 연속거래여부
dataframe1 (Optional[pd.DataFrame]): 누적 데이터프레임1
dataframe2 (Optional[pd.DataFrame]): 누적 데이터프레임2
depth (int): 내부 재귀깊이 (자동관리)
max_depth (int): 최대 재귀 횟수 제한
Returns:
Tuple[pd.DataFrame, pd.DataFrame]: 선물옵션기간약정수수료일별 데이터 (output1, output2)
Example:
>>> df1, df2 = inquire_daily_amount_fee(cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, inqr_strt_day="20240401", inqr_end_day="20240625")
>>> print(df1)
>>> print(df2)
"""
if cano == "":
raise ValueError("cano is required")
if acnt_prdt_cd == "":
raise ValueError("acnt_prdt_cd is required")
if inqr_strt_day == "":
raise ValueError("inqr_strt_day is required")
if inqr_end_day == "":
raise ValueError("inqr_end_day is required")
if depth > max_depth:
logging.warning("Max recursive depth reached.")
if dataframe1 is None:
dataframe1 = pd.DataFrame()
if dataframe2 is None:
dataframe2 = pd.DataFrame()
return dataframe1, dataframe2
tr_id = "CTFO6119R" # 선물옵션기간약정수수료일별
api_url = "/uapi/domestic-futureoption/v1/trading/inquire-daily-amount-fee"
params = {
"CANO": cano, # 종합계좌번호
"ACNT_PRDT_CD": acnt_prdt_cd, # 계좌상품코드
"INQR_STRT_DAY": inqr_strt_day, # 조회시작일
"INQR_END_DAY": inqr_end_day, # 조회종료일
"CTX_AREA_FK200": FK200, # 연속조회검색조건200
"CTX_AREA_NK200": NK200 # 연속조회키200
}
res = ka._url_fetch(api_url, tr_id, tr_cont, params)
if res.isOK():
# output1 (array) 처리
current_data1 = pd.DataFrame(res.getBody().output1)
if dataframe1 is not None:
dataframe1 = pd.concat([dataframe1, current_data1], ignore_index=True)
else:
dataframe1 = current_data1
# output2 (object) 처리
current_data2 = pd.DataFrame([res.getBody().output2])
if dataframe2 is not None:
dataframe2 = pd.concat([dataframe2, current_data2], ignore_index=True)
else:
dataframe2 = current_data2
tr_cont = res.getHeader().tr_cont
FK200 = res.getBody().ctx_area_fk200
NK200 = res.getBody().ctx_area_nk200
if tr_cont in ["M", "F"]: # 다음 페이지 존재
logging.info("Call Next page...")
ka.smart_sleep() # 시스템 안정적 운영을 위한 지연
return inquire_daily_amount_fee(
cano, acnt_prdt_cd, inqr_strt_day, inqr_end_day, FK200, NK200, "N", dataframe1, dataframe2, depth + 1, max_depth
)
else:
logging.info("Data fetch complete.")
return dataframe1, dataframe2
else:
res.printError(url=api_url)
return pd.DataFrame(), pd.DataFrame()
##############################################################################################
# [국내선물옵션] 기본시세 > 선물옵션기간별시세(일/주/월/년)[v1_국내선물-008]
##############################################################################################
def inquire_daily_fuopchartprice(
fid_cond_mrkt_div_code: str, # FID 조건 시장 분류 코드
fid_input_iscd: str, # 종목코드
fid_input_date_1: str, # 조회 시작일자
fid_input_date_2: str, # 조회 종료일자
fid_period_div_code: str, # 기간분류코드
env_dv: str # 실전모의구분
) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""
(지수)선물옵션 기간별시세 데이터(일/주/월/년) 조회 (최대 100건 조회)
실전계좌의 경우, 한 번의 호출에 최대 100건까지 확인 가능하며, 이후의 값은 연속조회를 통해 확인하실 수 있습니다.
모의계좌의 경우, 한 번의 호출에 최대 100건까지 확인 가능하며, 이후의 값은 연속조회를 통해 확인하실 수 있습니다.
Args:
fid_cond_mrkt_div_code (str): [필수] FID 조건 시장 분류 코드 (ex. F: 지수선물, O: 지수옵션)
fid_input_iscd (str): [필수] 종목코드 (ex. 101W09)
fid_input_date_1 (str): [필수] 조회 시작일자 (ex. 20250301)
fid_input_date_2 (str): [필수] 조회 종료일자 (ex. 20250810)
fid_period_div_code (str): [필수] 기간분류코드 (ex. D: 일봉, W: 주봉)
env_dv (str): [필수] 실전모의구분 (ex. real:실전, demo:모의)
Returns:
Tuple[pd.DataFrame, pd.DataFrame]: (기본정보, 차트데이터) 튜플
Example:
>>> output1, output2 = inquire_daily_fuopchartprice(
... fid_cond_mrkt_div_code="F",
... fid_input_iscd="101W09",
... fid_input_date_1="20250301",
... fid_input_date_2="20250810",
... fid_period_div_code="D",
... env_dv="real"
... )
>>> print(output1)
>>> print(output2)
"""
# 필수 파라미터 검증
if fid_cond_mrkt_div_code == "":
raise ValueError("fid_cond_mrkt_div_code is required (e.g. 'F: 지수선물, O: 지수옵션')")
if fid_input_iscd == "":
raise ValueError("fid_input_iscd is required (e.g. '101W09')")
if fid_input_date_1 == "":
raise ValueError("fid_input_date_1 is required (e.g. '20250301')")
if fid_input_date_2 == "":
raise ValueError("fid_input_date_2 is required (e.g. '20250810')")
if fid_period_div_code == "":
raise ValueError("fid_period_div_code is required (e.g. 'D: 일봉, W: 주봉')")
if env_dv == "":
raise ValueError("env_dv is required (e.g. 'real:실전, demo:모의')")
# tr_id 설정
if env_dv == "real":
tr_id = "FHKIF03020100"
elif env_dv == "demo":
tr_id = "FHKIF03020100"
else:
raise ValueError("env_dv can only be 'real' or 'demo'")
api_url = "/uapi/domestic-futureoption/v1/quotations/inquire-daily-fuopchartprice"
params = {
"FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
"FID_INPUT_ISCD": fid_input_iscd,
"FID_INPUT_DATE_1": fid_input_date_1,
"FID_INPUT_DATE_2": fid_input_date_2,
"FID_PERIOD_DIV_CODE": fid_period_div_code
}
res = ka._url_fetch(api_url, tr_id, "", params)
if res.isOK():
# output1: object -> DataFrame (1행)
output1_data = pd.DataFrame([res.getBody().output1])
# output2: array -> DataFrame (여러행)
output2_data = pd.DataFrame(res.getBody().output2)
return output1_data, output2_data
else:
res.printError(url=api_url)
return pd.DataFrame(), pd.DataFrame()
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 총자산현황[v1_국내선물-014]
##############################################################################################
def inquire_deposit(
cano: str, # [필수] 종합계좌번호
acnt_prdt_cd: str # [필수] 계좌상품코드 (ex. 03)
) -> pd.DataFrame:
"""
선물옵션 총자산현황 API 입니다.
Args:
cano (str): [필수] 종합계좌번호
acnt_prdt_cd (str): [필수] 계좌상품코드 (ex. 03)
Returns:
pd.DataFrame: 선물옵션 총자산현황 데이터
Example:
>>> df = inquire_deposit(cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod)
>>> print(df)
"""
if cano == "":
raise ValueError("cano is required")
if acnt_prdt_cd == "":
raise ValueError("acnt_prdt_cd is required")
tr_id = "CTRP6550R" # 선물옵션 총자산현황
api_url = "/uapi/domestic-futureoption/v1/trading/inquire-deposit"
params = {
"CANO": cano, # 종합계좌번호
"ACNT_PRDT_CD": acnt_prdt_cd # 계좌상품코드
}
res = ka._url_fetch(api_url, tr_id, "", params)
if res.isOK():
current_data = pd.DataFrame([res.getBody().output])
logging.info("Data fetch complete.")
return current_data
else:
res.printError(url=api_url)
return pd.DataFrame()
##############################################################################################
# [국내선물옵션] 주문/계좌 > (야간)선물옵션 잔고현황 [국내선물-010]
##############################################################################################
def inquire_ngt_balance(
cano: str, # 종합계좌번호
acnt_prdt_cd: str, # 계좌상품코드
mgna_dvsn: str, # 증거금구분
excc_stat_cd: str, # 정산상태코드
acnt_pwd: str = "", # 계좌비밀번호
FK200: str = "", # 연속조회검색조건200
NK200: str = "", # 연속조회키200
tr_cont: str = "", # 연속거래여부
dataframe1: Optional[pd.DataFrame] = None, # 누적 데이터프레임1
dataframe2: Optional[pd.DataFrame] = None, # 누적 데이터프레임2
depth: int = 0, # 내부 재귀깊이 (자동관리)
max_depth: int = 10 # 최대 재귀 횟수 제한
) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""
(야간)선물옵션 잔고현황 API입니다.
Args:
cano (str): [필수] 종합계좌번호 (ex. 계좌번호 체계(8-2)의 앞 8자리)
acnt_prdt_cd (str): [필수] 계좌상품코드 (ex. 계좌번호 체계(8-2)의 뒤 2자리)
mgna_dvsn (str): [필수] 증거금구분 (ex. 01:개시, 02:유지)
excc_stat_cd (str): [필수] 정산상태코드 (ex. 1:정산, 2:본정산)
acnt_pwd (str): 계좌비밀번호
FK200 (str): 연속조회검색조건200
NK200 (str): 연속조회키200
tr_cont (str): 연속거래여부
dataframe1 (Optional[pd.DataFrame]): 누적 데이터프레임1
dataframe2 (Optional[pd.DataFrame]): 누적 데이터프레임2
depth (int): 내부 재귀깊이 (자동관리)
max_depth (int): 최대 재귀 횟수 제한
Returns:
Tuple[pd.DataFrame, pd.DataFrame]: (output1 데이터, output2 데이터)
Example:
>>> df1, df2 = inquire_ngt_balance("12345678", "01", "01", "1")
>>> print(df1, df2)
"""
# 필수 파라미터 검증
if cano == "":
raise ValueError("cano is required (e.g. '계좌번호 체계(8-2)의 앞 8자리')")
if acnt_prdt_cd == "":
raise ValueError("acnt_prdt_cd is required (e.g. '계좌번호 체계(8-2)의 뒤 2자리')")
if mgna_dvsn == "":
raise ValueError("mgna_dvsn is required (e.g. '01:개시, 02:유지')")
if excc_stat_cd == "":
raise ValueError("excc_stat_cd is required (e.g. '1:정산, 2:본정산')")
# 재귀 깊이 제한 확인
if depth > max_depth:
logging.warning("Max recursive depth reached.")
return (
dataframe1 if dataframe1 is not None else pd.DataFrame(),
dataframe2 if dataframe2 is not None else pd.DataFrame()
)
tr_id = "CTFN6118R"
api_url = "/uapi/domestic-futureoption/v1/trading/inquire-ngt-balance"
params = {
"CANO": cano,
"ACNT_PRDT_CD": acnt_prdt_cd,
"MGNA_DVSN": mgna_dvsn,
"EXCC_STAT_CD": excc_stat_cd,
"ACNT_PWD": acnt_pwd,
"CTX_AREA_FK200": FK200,
"CTX_AREA_NK200": NK200
}
res = ka._url_fetch(api_url, tr_id, tr_cont, params)
if res.isOK():
# output1 처리 (array)
current_data1 = pd.DataFrame(res.getBody().output1)
if dataframe1 is not None:
dataframe1 = pd.concat([dataframe1, current_data1], ignore_index=True)
else:
dataframe1 = current_data1
# output2 처리 (object)
current_data2 = pd.DataFrame(res.getBody().output2, index=[0])
if dataframe2 is not None:
dataframe2 = pd.concat([dataframe2, current_data2], ignore_index=True)
else:
dataframe2 = current_data2
tr_cont = res.getHeader().tr_cont
FK200 = res.getBody().ctx_area_fk200
NK200 = res.getBody().ctx_area_nk200
if tr_cont in ["M", "F"]: # 다음 페이지 존재
logging.info("Call Next page...")
ka.smart_sleep() # 시스템 안정적 운영을 위한 지연
return inquire_ngt_balance(
cano, acnt_prdt_cd, mgna_dvsn, excc_stat_cd, acnt_pwd,
FK200, NK200, "N", dataframe1, dataframe2, depth + 1, max_depth
)
else:
logging.info("Data fetch complete.")
return (dataframe1, dataframe2)
else:
res.printError(url=api_url)
return (pd.DataFrame(), pd.DataFrame())
##############################################################################################
# [국내선물옵션] 주문/계좌 > (야간)선물옵션 주문체결 내역조회 [국내선물-009]
##############################################################################################
def inquire_ngt_ccnl(
cano: str, # 종합계좌번호
acnt_prdt_cd: str, # 계좌상품코드
strt_ord_dt: str, # 시작주문일자
end_ord_dt: str, # 종료주문일자
sll_buy_dvsn_cd: str, # 매도매수구분코드
ccld_nccs_dvsn: str, # 체결미체결구분
sort_sqn: str = "", # 정렬순서
strt_odno: str = "", # 시작주문번호
pdno: str = "", # 상품번호
mket_id_cd: str = "", # 시장ID코드
fuop_dvsn_cd: str = "", # 선물옵션구분코드
scrn_dvsn: str = "", # 화면구분
FK200: str = "", # 연속조회검색조건200
NK200: str = "", # 연속조회키200
tr_cont: str = "", # 연속거래여부
dataframe1: Optional[pd.DataFrame] = None, # 누적 데이터프레임1
dataframe2: Optional[pd.DataFrame] = None, # 누적 데이터프레임2
depth: int = 0, # 내부 재귀깊이 (자동관리)
max_depth: int = 10 # 최대 재귀 횟수 제한
) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""
(야간)선물옵션 주문체결 내역조회 API입니다.
Args:
cano (str): [필수] 종합계좌번호 (ex. 계좌번호 체계(8-2)의 앞 8자리)
acnt_prdt_cd (str): [필수] 계좌상품코드 (ex. 계좌번호 체계(8-2)의 뒤 2자리)
strt_ord_dt (str): [필수] 시작주문일자
end_ord_dt (str): [필수] 종료주문일자 (ex. 조회하려는 마지막 일자 다음일자로 조회 (ex. 20221011 까지의 내역을 조회하고자 할 경우, 20221012로 종료주문일자 설정))
sll_buy_dvsn_cd (str): [필수] 매도매수구분코드 (ex. 공란:default, 00:전체, 01:매도, 02:매수)
ccld_nccs_dvsn (str): [필수] 체결미체결구분 (ex. 00:전체, 01:체결, 02:미체결)
sort_sqn (str): 정렬순서 (ex. 공란:default(DS:정순, 그외:역순))
strt_odno (str): 시작주문번호 (ex. 공란:default)
pdno (str): 상품번호 (ex. 공란:default)
mket_id_cd (str): 시장ID코드 (ex. 공란:default)
fuop_dvsn_cd (str): 선물옵션구분코드 (ex. 공란:전체, 01:선물, 02:옵션)
scrn_dvsn (str): 화면구분 (ex. 02(Default))
FK200 (str): 연속조회검색조건200 (ex. 공란:최초 조회시, 이전 조회 Output CTX_AREA_FK200값:다음페이지 조회시(2번째부터))
NK200 (str): 연속조회키200 (ex. 공란:최초 조회시, 이전 조회 Output CTX_AREA_NK200값:다음페이지 조회시(2번째부터))
tr_cont (str): 연속거래여부
dataframe1 (Optional[pd.DataFrame]): 누적 데이터프레임1
dataframe2 (Optional[pd.DataFrame]): 누적 데이터프레임2
depth (int): 내부 재귀깊이 (자동관리)
max_depth (int): 최대 재귀 횟수 제한
Returns:
Tuple[pd.DataFrame, pd.DataFrame]: (output1 데이터, output2 데이터)
Example:
>>> df1, df2 = inquire_ngt_ccnl(cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, strt_ord_dt="20231201", end_ord_dt="20231214", sll_buy_dvsn_cd="00", ccld_nccs_dvsn="00")
>>> print(df1)
>>> print(df2)
"""
# 필수 파라미터 검증
if cano == "" or cano is None:
raise ValueError("cano is required (e.g. '계좌번호 체계(8-2)의 앞 8자리')")
if acnt_prdt_cd == "" or acnt_prdt_cd is None:
raise ValueError("acnt_prdt_cd is required (e.g. '계좌번호 체계(8-2)의 뒤 2자리')")
if strt_ord_dt == "" or strt_ord_dt is None:
raise ValueError("strt_ord_dt is required")
if end_ord_dt == "" or end_ord_dt is None:
raise ValueError("end_ord_dt is required (e.g. '조회하려는 마지막 일자 다음일자로 조회 (ex. 20221011 까지의 내역을 조회하고자 할 경우, 20221012로 종료주문일자 설정)')")
if sll_buy_dvsn_cd == "" or sll_buy_dvsn_cd is None:
raise ValueError("sll_buy_dvsn_cd is required (e.g. '공란:default, 00:전체, 01:매도, 02:매수')")
if ccld_nccs_dvsn == "" or ccld_nccs_dvsn is None:
raise ValueError("ccld_nccs_dvsn is required (e.g. '00:전체, 01:체결, 02:미체결')")
if depth > max_depth:
logging.warning("Max recursive depth reached.")
if dataframe1 is None:
dataframe1 = pd.DataFrame()
if dataframe2 is None:
dataframe2 = pd.DataFrame()
return dataframe1, dataframe2
tr_id = "STTN5201R"
api_url = "/uapi/domestic-futureoption/v1/trading/inquire-ngt-ccnl"
params = {
"CANO": cano,
"ACNT_PRDT_CD": acnt_prdt_cd,
"STRT_ORD_DT": strt_ord_dt,
"END_ORD_DT": end_ord_dt,
"SLL_BUY_DVSN_CD": sll_buy_dvsn_cd,
"CCLD_NCCS_DVSN": ccld_nccs_dvsn,
"SORT_SQN": sort_sqn,
"STRT_ODNO": strt_odno,
"PDNO": pdno,
"MKET_ID_CD": mket_id_cd,
"FUOP_DVSN_CD": fuop_dvsn_cd,
"SCRN_DVSN": scrn_dvsn,
"CTX_AREA_FK200": FK200,
"CTX_AREA_NK200": NK200
}
res = ka._url_fetch(api_url, tr_id, tr_cont, params)
print(res.getBody())
if res.isOK():
# output1 (array) 처리
current_data1 = pd.DataFrame(res.getBody().output1)
# output2 (object) 처리
current_data2 = pd.DataFrame([res.getBody().output2])
if dataframe1 is not None:
dataframe1 = pd.concat([dataframe1, current_data1], ignore_index=True)
else:
dataframe1 = current_data1
if dataframe2 is not None:
dataframe2 = pd.concat([dataframe2, current_data2], ignore_index=True)
else:
dataframe2 = current_data2
tr_cont = res.getHeader().tr_cont
FK200 = res.getBody().ctx_area_fk200
NK200 = res.getBody().ctx_area_nk200
if tr_cont in ["M", "F"]: # 다음 페이지 존재
logging.info("Call Next page...")
ka.smart_sleep() # 시스템 안정적 운영을 위한 지연
return inquire_ngt_ccnl(
cano, acnt_prdt_cd, strt_ord_dt, end_ord_dt, sll_buy_dvsn_cd, ccld_nccs_dvsn,
sort_sqn, strt_odno, pdno, mket_id_cd, fuop_dvsn_cd, scrn_dvsn,
FK200, NK200, "N", dataframe1, dataframe2, depth + 1, max_depth
)
else:
logging.info("Data fetch complete.")
return dataframe1, dataframe2
else:
res.printError(url=api_url)
return pd.DataFrame(), pd.DataFrame()
##############################################################################################
# [국내선물옵션] 기본시세 > 선물옵션 시세[v1_국내선물-006]
##############################################################################################
def inquire_price(
fid_cond_mrkt_div_code: str, # [필수] FID 조건 시장 분류 코드 (ex. F: 지수선물, O: 지수옵션)
fid_input_iscd: str, # [필수] FID 입력 종목코드 (ex. 101W09)
env_dv: str # [필수] 실전모의구분 (ex. real:실전, demo:모의)
) -> Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:
"""
선물옵션 시세 API입니다.
※ 종목코드 마스터파일 정제코드는 한국투자증권 Github 참고:
https://github.com/koreainvestment/open-trading-api/tree/main/stocks_info
Args:
fid_cond_mrkt_div_code (str): [필수] FID 조건 시장 분류 코드 (ex. F: 지수선물, O: 지수옵션)
fid_input_iscd (str): [필수] FID 입력 종목코드 (ex. 101W09)
env_dv (str): [필수] 실전모의구분 (ex. real:실전, demo:모의)
Returns:
Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]: 선물옵션 시세 데이터 (output1, output2, output3)
Example:
>>> result1, result2, result3 = inquire_price(
... fid_cond_mrkt_div_code="F",
... fid_input_iscd="101W09",
... env_dv="real"
... )
>>> print(result1)
"""
# 필수 파라미터 검증
if fid_cond_mrkt_div_code == "":
raise ValueError("fid_cond_mrkt_div_code is required (e.g. 'F', 'O')")
if fid_input_iscd == "":
raise ValueError("fid_input_iscd is required (e.g. '101W09')")
if env_dv == "":
raise ValueError("env_dv is required (e.g. 'real', 'demo')")
# tr_id 설정
if env_dv == "real":
tr_id = "FHMIF10000000"
elif env_dv == "demo":
tr_id = "FHMIF10000000"
else:
raise ValueError("env_dv can only be real or demo")
api_url = "/uapi/domestic-futureoption/v1/quotations/inquire-price"
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, "", params)
if res.isOK():
# output1 처리
output1 = pd.DataFrame(res.getBody().output1, index=[0])
# output2 처리
output2 = pd.DataFrame(res.getBody().output2, index=[0])
# output3 처리
output3 = pd.DataFrame(res.getBody().output3, index=[0])
return output1, output2, output3
else:
res.printError(url=api_url)
return pd.DataFrame(), pd.DataFrame(), pd.DataFrame()
##############################################################################################
# [국내선물옵션] 주문/계좌 > (야간)선물옵션 주문가능 조회 [국내선물-011]
##############################################################################################
def inquire_psbl_ngt_order(
cano: str, # 종합계좌번호
acnt_prdt_cd: str, # 계좌상품코드
pdno: str, # 상품번호
prdt_type_cd: str, # 상품유형코드
sll_buy_dvsn_cd: str, # 매도매수구분코드
unit_price: str, # 주문가격1
ord_dvsn_cd: str # 주문구분코드
) -> pd.DataFrame:
"""
(야간)선물옵션 주문가능 조회 API입니다.
Args:
cano (str): [필수] 종합계좌번호
acnt_prdt_cd (str): [필수] 계좌상품코드
pdno (str): [필수] 상품번호
prdt_type_cd (str): [필수] 상품유형코드 (ex. 301:선물옵션)
sll_buy_dvsn_cd (str): [필수] 매도매수구분코드 (ex. 01:매도, 02:매수)
unit_price (str): [필수] 주문가격1
ord_dvsn_cd (str): [필수] 주문구분코드 (ex. 01:지정가, 02:시장가, 03:조건부, 04:최유리, 10:지정가(IOC), 11:지정가(FOK), 12:시장가(IOC), 13:시장가(FOK), 14:최유리(IOC), 15:최유리(FOK))
Returns:
pd.DataFrame: (야간)선물옵션 주문가능 데이터
Example:
>>> df = inquire_psbl_ngt_order(cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, pdno="101W09", prdt_type_cd="301", sll_buy_dvsn_cd="02", unit_price="322", ord_dvsn_cd="01")
>>> print(df)
"""
# 필수 파라미터 검증
if cano == "" or cano is None:
raise ValueError("cano is required")
if acnt_prdt_cd == "" or acnt_prdt_cd is None:
raise ValueError("acnt_prdt_cd is required")
if pdno == "" or pdno is None:
raise ValueError("pdno is required")
if prdt_type_cd == "" or prdt_type_cd is None:
raise ValueError("prdt_type_cd is required (e.g. '301')")
if sll_buy_dvsn_cd == "" or sll_buy_dvsn_cd is None:
raise ValueError("sll_buy_dvsn_cd is required (e.g. '01', '02')")
if unit_price == "" or unit_price is None:
raise ValueError("unit_price is required")
if ord_dvsn_cd == "" or ord_dvsn_cd is None:
raise ValueError("ord_dvsn_cd is required (e.g. '01', '02', '03', '04', '10', '11', '12', '13', '14', '15')")
tr_id = "STTN5105R"
api_url = "/uapi/domestic-futureoption/v1/trading/inquire-psbl-ngt-order"
params = {
"CANO": cano,
"ACNT_PRDT_CD": acnt_prdt_cd,
"PDNO": pdno,
"PRDT_TYPE_CD": prdt_type_cd,
"SLL_BUY_DVSN_CD": sll_buy_dvsn_cd,
"UNIT_PRICE": unit_price,
"ORD_DVSN_CD": ord_dvsn_cd
}
res = ka._url_fetch(api_url, tr_id, "", params)
if res.isOK():
current_data = pd.DataFrame([res.getBody().output])
return current_data
else:
res.printError(url=api_url)
return pd.DataFrame()
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 주문가능[v1_국내선물-005]
##############################################################################################
def inquire_psbl_order(
env_dv: str, # [필수] 실전모의구분 (ex. real:실전, demo:모의)
cano: str, # [필수] 종합계좌번호
acnt_prdt_cd: str, # [필수] 계좌상품코드 (ex. 03)
pdno: str, # [필수] 상품번호 (ex. 선물 6자리, 옵션 9자리)
sll_buy_dvsn_cd: str, # [필수] 매도매수구분코드 (ex. 01:매도,02:매수)
unit_price: str, # [필수] 주문가격1
ord_dvsn_cd: str # [필수] 주문구분코드
) -> pd.DataFrame:
"""
선물옵션 주문가능 API입니다. 주문가능 내역과 수량을 확인하실 수 있습니다.
Args:
env_dv (str): [필수] 실전모의구분 (ex. real:실전, demo:모의)
cano (str): [필수] 종합계좌번호
acnt_prdt_cd (str): [필수] 계좌상품코드 (ex. 03)
pdno (str): [필수] 상품번호 (ex. 선물 6자리, 옵션 9자리)
sll_buy_dvsn_cd (str): [필수] 매도매수구분코드 (ex. 01:매도,02:매수)
unit_price (str): [필수] 주문가격1
ord_dvsn_cd (str): [필수] 주문구분코드
Returns:
pd.DataFrame: 선물옵션 주문가능 데이터
Example:
>>> df = inquire_psbl_order(env_dv="real", cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod,
... pdno="101W09", sll_buy_dvsn_cd="02", unit_price="1", ord_dvsn_cd="01")
>>> print(df)
"""
# 필수 파라미터 검증
if env_dv == "":
raise ValueError("env_dv is required (e.g. 'real' or 'demo')")
if cano == "":
raise ValueError("cano is required")
if acnt_prdt_cd == "":
raise ValueError("acnt_prdt_cd is required (e.g. '03')")
if pdno == "":
raise ValueError("pdno is required (e.g. '101W09')")
if sll_buy_dvsn_cd == "":
raise ValueError("sll_buy_dvsn_cd is required (e.g. '01' or '02')")
if unit_price == "":
raise ValueError("unit_price is required")
if ord_dvsn_cd == "":
raise ValueError("ord_dvsn_cd is required")
# tr_id 설정
if env_dv == "real":
tr_id = "TTTO5105R"
elif env_dv == "demo":
tr_id = "VTTO5105R"
else:
raise ValueError("env_dv can only be 'real' or 'demo'")
api_url = "/uapi/domestic-futureoption/v1/trading/inquire-psbl-order"
params = {
"CANO": cano,
"ACNT_PRDT_CD": acnt_prdt_cd,
"PDNO": pdno,
"SLL_BUY_DVSN_CD": sll_buy_dvsn_cd,
"UNIT_PRICE": unit_price,
"ORD_DVSN_CD": ord_dvsn_cd
}
res = ka._url_fetch(api_url, tr_id, "", params)
if res.isOK():
current_data = pd.DataFrame([res.getBody().output])
logging.info("Data fetch complete.")
return current_data
else:
res.printError(url=api_url)
return pd.DataFrame()
##############################################################################################
# [국내선물옵션] 기본시세 > 선물옵션 분봉조회[v1_국내선물-012]
##############################################################################################
def inquire_time_fuopchartprice(
fid_cond_mrkt_div_code: str, # FID 조건 시장 분류 코드 (F: 지수선물, O: 지수옵션)
fid_input_iscd: str, # FID 입력 종목코드 (101T12)
fid_hour_cls_code: str, # FID 시간 구분 코드 (30: 30초, 60: 1분)
fid_pw_data_incu_yn: str, # FID 과거 데이터 포함 여부 (Y:과거, N: 당일)
fid_fake_tick_incu_yn: str, # FID 허봉 포함 여부 (N)
fid_input_date_1: str, # FID 입력 날짜1 (20230901)
fid_input_hour_1: str # FID 입력 시간1 (100000)
) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""
선물옵션 분봉조회 API입니다.
실전계좌의 경우, 한 번의 호출에 최대 102건까지 확인 가능하며,
FID_INPUT_DATE_1(입력날짜), FID_INPUT_HOUR_1(입력시간)을 이용하여 다음 조회 가능합니다.
Args:
fid_cond_mrkt_div_code (str): [필수] FID 조건 시장 분류 코드 (ex. F: 지수선물, O: 지수옵션)
fid_input_iscd (str): [필수] FID 입력 종목코드 (ex. 101T12)
fid_hour_cls_code (str): [필수] FID 시간 구분 코드 (ex. 30: 30초, 60: 1분)
fid_pw_data_incu_yn (str): [필수] FID 과거 데이터 포함 여부 (ex. Y:과거, N: 당일)
fid_fake_tick_incu_yn (str): [필수] FID 허봉 포함 여부 (ex. N)
fid_input_date_1 (str): [필수] FID 입력 날짜1 (ex. 20230901)
fid_input_hour_1 (str): [필수] FID 입력 시간1 (ex. 100000)
Returns:
Tuple[pd.DataFrame, pd.DataFrame]: 선물옵션 분봉 데이터 (output1, output2)
Example:
>>> df1, df2 = inquire_time_fuopchartprice("F", "101T12", "60", "Y", "N", "20230901", "100000")
>>> print(df1)
>>> print(df2)
"""
# 필수 파라미터 검증
if fid_cond_mrkt_div_code == "":
raise ValueError("fid_cond_mrkt_div_code is required (e.g. 'F: 지수선물, O: 지수옵션')")
if fid_input_iscd == "":
raise ValueError("fid_input_iscd is required (e.g. '101T12')")
if fid_hour_cls_code == "":
raise ValueError("fid_hour_cls_code is required (e.g. '30: 30초, 60: 1분')")
if fid_pw_data_incu_yn == "":
raise ValueError("fid_pw_data_incu_yn is required (e.g. 'Y:과거, N: 당일')")
if fid_fake_tick_incu_yn == "":
raise ValueError("fid_fake_tick_incu_yn is required (e.g. 'N')")
if fid_input_date_1 == "":
raise ValueError("fid_input_date_1 is required (e.g. '20230901')")
if fid_input_hour_1 == "":
raise ValueError("fid_input_hour_1 is required (e.g. '100000')")
tr_id = "FHKIF03020200" # 선물옵션 분봉조회
api_url = "/uapi/domestic-futureoption/v1/quotations/inquire-time-fuopchartprice"
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,
"FID_INPUT_HOUR_1": fid_input_hour_1
}
res = ka._url_fetch(api_url, tr_id, "", params)
if res.isOK():
# output1: object array -> DataFrame
output1_data = pd.DataFrame(res.getBody().output1, index=[0])
# output2: array -> DataFrame
output2_data = pd.DataFrame(res.getBody().output2)
logging.info("Data fetch complete.")
return output1_data, output2_data
else:
res.printError(url=api_url)
return pd.DataFrame(), pd.DataFrame()
##############################################################################################
# [국내선물옵션] 주문/계좌 > (야간)선물옵션 증거금 상세 [국내선물-024]
##############################################################################################
def ngt_margin_detail(
cano: str, # 종합계좌번호
acnt_prdt_cd: str, # 계좌상품코드
mgna_dvsn_cd: str # 증거금 구분코드
) -> Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:
"""
(야간)선물옵션 증거금상세 API입니다.
한국투자 HTS(eFriend Force) > [2537] 야간선물옵션 증거금상세 화면 의 기능을 API로 개발한 사항으로, 해당 화면을 참고하시면 기능을 이해하기 쉽습니다.
Args:
cano (str): [필수] 종합계좌번호
acnt_prdt_cd (str): [필수] 계좌상품코드 (ex. 03)
mgna_dvsn_cd (str): [필수] 증거금 구분코드 (ex. 01:위탁, 02:유지)
Returns:
Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]: (output1, output2, output3) 데이터프레임
Example:
>>> df1, df2, df3 = ngt_margin_detail(cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, mgna_dvsn_cd="01")
>>> print(df1)
"""
if cano == "":
raise ValueError("cano is required")
if acnt_prdt_cd == "":
raise ValueError("acnt_prdt_cd is required (e.g. '03')")
if mgna_dvsn_cd == "":
raise ValueError("mgna_dvsn_cd is required (e.g. '01:위탁, 02:유지')")
tr_id = "CTFN7107R" # (야간)선물옵션 증거금 상세
api_url = "/uapi/domestic-futureoption/v1/trading/ngt-margin-detail"
params = {
"CANO": cano,
"ACNT_PRDT_CD": acnt_prdt_cd,
"MGNA_DVSN_CD": mgna_dvsn_cd
}
res = ka._url_fetch(api_url, tr_id, "", params)
if res.isOK():
output1_data = pd.DataFrame(res.getBody().output1)
output2_data = pd.DataFrame(res.getBody().output2)
output3_data = pd.DataFrame([res.getBody().output3])
return output1_data, output2_data, output3_data
else:
res.printError(url=api_url)
return pd.DataFrame(), pd.DataFrame(), pd.DataFrame()
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 주문[v1_국내선물-001]
##############################################################################################
def order(
env_dv: str, # 실전모의구분
ord_dv: str, # 매도매수구분
ord_prcs_dvsn_cd: str, # 주문처리구분코드
cano: str, # 종합계좌번호
acnt_prdt_cd: str, # 계좌상품코드
sll_buy_dvsn_cd: str, # 매도매수구분코드
shtn_pdno: str, # 단축상품번호
ord_qty: str, # 주문수량
unit_price: str, # 주문가격1
nmpr_type_cd: str, # 호가유형코드
krx_nmpr_cndt_cd: str, # 한국거래소호가조건코드
ord_dvsn_cd: str, # 주문구분코드
ctac_tlno: str = "", # 연락전화번호
fuop_item_dvsn_cd: str = "" # 선물옵션종목구분코드
) -> pd.DataFrame:
"""
[국내선물옵션] 주문/계좌 > 선물옵션 주문[v1_국내선물-001]
선물옵션 주문 API입니다.
* 선물옵션 운영시간 외 API 호출 시 애러가 발생하오니 운영시간을 확인해주세요.
※ POST API의 경우 BODY값의 key값들을 대문자로 작성하셔야 합니다.
(EX. "CANO" : "12345678", "ACNT_PRDT_CD": "01",...)
※ 종목코드 마스터파일 파이썬 정제코드는 한국투자증권 Github 참고 부탁드립니다.
https://github.com/koreainvestment/open-trading-api/tree/main/stocks_info
Args:
env_dv (str): [필수] 실전모의구분 (ex. real:실전, demo:모의)
ord_dv (str): [필수] 매도매수구분 (ex. day:주간, night:야간)
ord_prcs_dvsn_cd (str): [필수] 주문처리구분코드 (ex. 02:주문전송)
cano (str): [필수] 종합계좌번호 (ex. 계좌번호 체계(8-2)의 앞 8자리)
acnt_prdt_cd (str): [필수] 계좌상품코드 (ex. 계좌번호 체계(8-2)의 뒤 2자리)
sll_buy_dvsn_cd (str): [필수] 매도매수구분코드 (ex. 01:매도, 02:매수)
shtn_pdno (str): [필수] 단축상품번호 (ex. 종목번호, 선물 6자리 (예: 101W09), 옵션 9자리 (예: 201S03370))
ord_qty (str): [필수] 주문수량
unit_price (str): [필수] 주문가격1 (ex. 시장가나 최유리 지정가인 경우 0으로 입력)
nmpr_type_cd (str): [필수] 호가유형코드 (ex. 01:지정가, 02:시장가, 03:조건부, 04:최유리)
krx_nmpr_cndt_cd (str): [필수] 한국거래소호가조건코드 (ex. 0:없음, 3:IOC, 4:FOK)
ord_dvsn_cd (str): [필수] 주문구분코드 (ex. 01:지정가, 02:시장가, 03:조건부, 04:최유리, 10:지정가(IOC), 11:지정가(FOK), 12:시장가(IOC), 13:시장가(FOK), 14:최유리(IOC), 15:최유리(FOK))
ctac_tlno (str): 연락전화번호 (ex. 고객의 연락 가능한 전화번호)
fuop_item_dvsn_cd (str): 선물옵션종목구분코드 (ex. 공란(Default))
Returns:
pd.DataFrame: 선물옵션 주문 결과 데이터
Example:
>>> df = order(env_dv="real", ord_dv="day", ord_prcs_dvsn_cd="02", cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, sll_buy_dvsn_cd="02", shtn_pdno="101W09", ord_qty="1", unit_price="0", nmpr_type_cd="02", krx_nmpr_cndt_cd="0", ord_dvsn_cd="02")
>>> print(df)
"""
# 필수 파라미터 검증
if env_dv == "":
raise ValueError("env_dv is required (e.g. 'real', 'demo')")
if ord_dv == "":
raise ValueError("ord_dv is required (e.g. 'day', 'night')")
if ord_prcs_dvsn_cd == "":
raise ValueError("ord_prcs_dvsn_cd is required (e.g. '02')")
if cano == "":
raise ValueError("cano is required (e.g. '계좌번호 체계(8-2)의 앞 8자리')")
if acnt_prdt_cd == "":
raise ValueError("acnt_prdt_cd is required (e.g. '계좌번호 체계(8-2)의 뒤 2자리')")
if sll_buy_dvsn_cd == "":
raise ValueError("sll_buy_dvsn_cd is required (e.g. '01', '02')")
if shtn_pdno == "":
raise ValueError("shtn_pdno is required (e.g. '101W09', '201S03370')")
if ord_qty == "":
raise ValueError("ord_qty is required")
if unit_price == "":
raise ValueError("unit_price is required (e.g. '0')")
if nmpr_type_cd == "":
raise ValueError("nmpr_type_cd is required (e.g. '01', '02', '03', '04')")
if krx_nmpr_cndt_cd == "":
raise ValueError("krx_nmpr_cndt_cd is required (e.g. '0', '3', '4')")
if ord_dvsn_cd == "":
raise ValueError("ord_dvsn_cd is required (e.g. '01', '02', '03', '04', '10', '11', '12', '13', '14', '15')")
# tr_id 설정
if env_dv == "real":
if ord_dv == "day":
tr_id = "TTTO1101U"
elif ord_dv == "night":
tr_id = "STTN1101U"
else:
raise ValueError("ord_dv can only be 'day' or 'night'")
elif env_dv == "demo":
if ord_dv == "day":
tr_id = "VTTO1101U"
else:
raise ValueError("ord_dv can only be 'day' for demo environment")
else:
raise ValueError("env_dv can only be 'real' or 'demo'")
api_url = "/uapi/domestic-futureoption/v1/trading/order"
params = {
"ORD_PRCS_DVSN_CD": ord_prcs_dvsn_cd,
"CANO": cano,
"ACNT_PRDT_CD": acnt_prdt_cd,
"SLL_BUY_DVSN_CD": sll_buy_dvsn_cd,
"SHTN_PDNO": shtn_pdno,
"ORD_QTY": ord_qty,
"UNIT_PRICE": unit_price,
"NMPR_TYPE_CD": nmpr_type_cd,
"KRX_NMPR_CNDT_CD": krx_nmpr_cndt_cd,
"ORD_DVSN_CD": ord_dvsn_cd,
"CTAC_TLNO": ctac_tlno,
"FUOP_ITEM_DVSN_CD": fuop_item_dvsn_cd
}
res = ka._url_fetch(api_url, tr_id, "", params, postFlag=True)
if res.isOK():
return pd.DataFrame(res.getBody().output, index=[0])
else:
res.printError(url=api_url)
return pd.DataFrame()
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 정정취소주문[v1_국내선물-002]
##############################################################################################
def order_rvsecncl(
env_dv: str, # [필수] 실전모의구분 (ex. real:실전, demo:모의)
day_dv: str, # [필수] 주야간구분 (ex. day:주간, night:야간)
ord_prcs_dvsn_cd: str, # [필수] 주문처리구분코드 (ex. 02)
cano: str, # [필수] 종합계좌번호
acnt_prdt_cd: str, # [필수] 계좌상품코드
rvse_cncl_dvsn_cd: str, # [필수] 정정취소구분코드 (ex. 01:정정, 02:취소)
orgn_odno: str, # [필수] 원주문번호
ord_qty: str, # [필수] 주문수량 (ex. 0:전량, 그 외는 수량)
unit_price: str, # [필수] 주문가격1 (ex 0:시장가/최유리, 그 외 가격)
nmpr_type_cd: str, # [필수] 호가유형코드 (ex. 01:지정가, 02:시장가, 03:조건부, 04:최유리)
krx_nmpr_cndt_cd: str, # [필수] 한국거래소호가조건코드 (ex. 0:취소/없음, 3:IOC, 4:FOK)
rmn_qty_yn: str, # [필수] 잔여수량여부 (ex. Y:전량, N:일부)
ord_dvsn_cd: str, # [필수] 주문구분코드
fuop_item_dvsn_cd: str = "" # 선물옵션종목구분코드
) -> pd.DataFrame:
"""
선물옵션 주문 건에 대하여 정정 및 취소하는 API입니다. 단, 이미 체결된 건은 정정 및 취소가 불가합니다.
※ POST API의 경우 BODY값의 key값들을 대문자로 작성하셔야 합니다.
(EX. "CANO" : "12345678", "ACNT_PRDT_CD": "01",...)
Args:
env_dv (str): [필수] 실전모의구분 (ex. real:실전, demo:모의)
day_dv (str): [필수] 주야간구분 (ex. day:주간, night:야간)
ord_prcs_dvsn_cd (str): [필수] 주문처리구분코드 (ex. 02)
cano (str): [필수] 종합계좌번호
acnt_prdt_cd (str): [필수] 계좌상품코드
rvse_cncl_dvsn_cd (str): [필수] 정정취소구분코드 (ex. 01:정정, 02:취소)
orgn_odno (str): [필수] 원주문번호
ord_qty (str): [필수] 주문수량 (ex. 0:전량, 그 외는 수량)
unit_price (str): [필수] 주문가격1 (ex 0:시장가/최유리, 그 외 가격)
nmpr_type_cd (str): [필수] 호가유형코드 (ex. 01:지정가, 02:시장가, 03:조건부, 04:최유리)
krx_nmpr_cndt_cd (str): [필수] 한국거래소호가조건코드 (ex. 0:취소/없음, 3:IOC, 4:FOK)
rmn_qty_yn (str): [필수] 잔여수량여부 (ex. Y:전량, N:일부)
ord_dvsn_cd (str): [필수] 주문구분코드
fuop_item_dvsn_cd (str): 선물옵션종목구분코드
Returns:
pd.DataFrame: 선물옵션 정정취소주문 결과 데이터
Example:
>>> df = order_rvsecncl(
... env_dv="real", day_dv="day", ord_prcs_dvsn_cd="02",
... cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, rvse_cncl_dvsn_cd="02",
... orgn_odno="0000004018", ord_qty="0", unit_price="0",
... nmpr_type_cd="02", krx_nmpr_cndt_cd="0", rmn_qty_yn="Y",
... ord_dvsn_cd="01"
... )
>>> print(df)
"""
# tr_id 설정
if env_dv == "real":
if day_dv == "day":
tr_id = "TTTO1103U"
elif day_dv == "night":
tr_id = "TTTN1103U"
else:
raise ValueError("day_dv can only be 'day' or 'night'")
elif env_dv == "demo":
if day_dv == "day":
tr_id = "VTTO1103U"
else:
raise ValueError("day_dv can only be 'day' for demo environment")
else:
raise ValueError("env_dv is required (e.g. 'real' or 'demo')")
api_url = "/uapi/domestic-futureoption/v1/trading/order-rvsecncl"
params = {
"ORD_PRCS_DVSN_CD": ord_prcs_dvsn_cd,
"CANO": cano,
"ACNT_PRDT_CD": acnt_prdt_cd,
"RVSE_CNCL_DVSN_CD": rvse_cncl_dvsn_cd,
"ORGN_ODNO": orgn_odno,
"ORD_QTY": ord_qty,
"UNIT_PRICE": unit_price,
"NMPR_TYPE_CD": nmpr_type_cd,
"KRX_NMPR_CNDT_CD": krx_nmpr_cndt_cd,
"RMN_QTY_YN": rmn_qty_yn,
"ORD_DVSN_CD": ord_dvsn_cd,
"FUOP_ITEM_DVSN_CD": fuop_item_dvsn_cd
}
res = ka._url_fetch(api_url, tr_id, "", params, postFlag=True)
if res.isOK():
return pd.DataFrame(res.getBody().output)
else:
res.printError(url=api_url)
return pd.DataFrame()