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,120 @@
# [인증] OAuth 접근토큰 발급
# Generated by KIS API Generator (Single API Mode)
# -*- coding: utf-8 -*-
"""
Created on 2025-06-19
"""
import json
import logging
import sys
import pandas as pd
import requests
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [인증] OAuth 접근토큰 발급
##############################################################################################
# 상수 정의
API_URL = "/oauth2/tokenP"
def auth_token(
grant_type: str,
appkey: str,
appsecret: str,
env_dv: str
) -> pd.DataFrame:
"""
OAuth 접근토큰 발급 API를 호출하여 DataFrame으로 반환합니다.
Args:
grant_type (str): [필수] 권한부여 Type (client_credentials)
appkey (str): [필수] 앱키 (한국투자증권 홈페이지에서 발급받은 appkey)
appsecret (str): [필수] 앱시크릿키 (한국투자증권 홈페이지에서 발급받은 appsecret)
env_dv (str): [필수] 환경구분 (real: 실전, demo: 모의)
Returns:
pd.DataFrame: OAuth 토큰 발급 결과
Example:
>>> df = auth_token(
... grant_type="client_credentials",
... appkey=trenv.my_app,
... appsecret=trenv.my_sec,
... env_dv="real"
... )
>>> print(df)
"""
# 필수 파라미터 검증
if not grant_type:
logger.error("grant_type is required. (e.g. 'client_credentials')")
raise ValueError("grant_type is required. (e.g. 'client_credentials')")
if not appkey:
logger.error("appkey is required. (한국투자증권 홈페이지에서 발급받은 appkey)")
raise ValueError("appkey is required. (한국투자증권 홈페이지에서 발급받은 appkey)")
if not appsecret:
logger.error("appsecret is required. (한국투자증권 홈페이지에서 발급받은 appsecret)")
raise ValueError("appsecret is required. (한국투자증권 홈페이지에서 발급받은 appsecret)")
if not env_dv:
logger.error("env_dv is required. (real: 실전, demo: 모의)")
raise ValueError("env_dv is required. (real: 실전, demo: 모의)")
# 환경 구분에 따른 서버 URL 설정
config = ka.getEnv()
if env_dv == "real":
base_url = config.get("prod", "")
elif env_dv == "demo":
base_url = config.get("vps", "")
else:
logger.error("env_dv must be 'real' or 'demo'")
raise ValueError("env_dv must be 'real' or 'demo'")
url = f"{base_url}{API_URL}"
# 헤더 설정
headers = {
"Content-Type": "application/json",
"Accept": "text/plain",
"charset": "UTF-8"
}
# 요청 데이터
data = {
"grant_type": grant_type,
"appkey": appkey,
"appsecret": appsecret,
}
try:
# POST 방식으로 직접 API 호출
response = requests.post(url, data=json.dumps(data), headers=headers)
if response.status_code == 200:
# 응답 데이터를 DataFrame으로 반환 (1개 row)
response_data = response.json()
current_data = pd.DataFrame([response_data])
logger.info("OAuth 토큰 발급 성공")
return current_data
else:
logger.error("API call failed: %s - %s", response.status_code, response.text)
return pd.DataFrame()
except requests.RequestException as e:
logger.error("Request failed: %s", str(e))
return pd.DataFrame()
except json.JSONDecodeError as e:
logger.error("JSON decode failed: %s", str(e))
return pd.DataFrame()

View File

@@ -0,0 +1,104 @@
# -*- 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 auth_token import auth_token
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [인증] OAuth 접근토큰 발급 테스트
##############################################################################################
# 통합 컬럼 매핑
COLUMN_MAPPING = {
'access_token': '접근토큰',
'token_type': '접근토큰유형',
'expires_in': '접근토큰유효기간_초',
'access_token_token_expired': '접근토큰유효기간_일시표시'
}
def main():
"""
OAuth 접근토큰 발급 테스트 함수
Parameters:
- grant_type (str): 권한부여 Type (client_credentials)
- appkey (str): 앱키 (한국투자증권 홈페이지에서 발급받은 appkey)
- appsecret (str): 앱시크릿키 (한국투자증권 홈페이지에서 발급받은 appsecret)
- env_dv (str): 환경구분 (real: 실전, demo: 모의)
Returns:
- pd.DataFrame: OAuth 토큰 발급 결과
Response Fields:
- access_token: 접근토큰 (OAuth 토큰이 필요한 API 경우 발급한 Access token)
- token_type: 접근토큰유형 ("Bearer")
- expires_in: 접근토큰 유효기간(초)
- access_token_token_expired: 접근토큰 유효기간(일시표시)
Example:
>>> df = auth_token(grant_type="client_credentials", appkey=trenv.my_app, appsecret=trenv.my_sec, env_dv="real")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 환경 설정에서 앱키와 앱시크릿 가져오기
config = ka.getEnv()
# 실전투자용 앱키/앱시크릿 사용 (모의투자의 경우 paper_app, paper_sec 사용)
appkey = config.get("my_app", "")
appsecret = config.get("my_sec", "")
# 앱키와 앱시크릿이 설정되어 있는지 확인
if not appkey or not appsecret:
logger.error("앱키 또는 앱시크릿이 설정되지 않았습니다. kis_devlp.yaml 파일을 확인해주세요.")
logger.info("필요한 설정: my_app (앱키), my_sec (앱시크릿)")
return
# API 호출
logger.info("OAuth 접근토큰 발급 API 호출 시작")
result = auth_token(
grant_type="client_credentials",
appkey=appkey,
appsecret=appsecret,
env_dv="real" # 실전 환경으로 설정 (필요시 "demo"로 변경)
)
# 결과 확인
if result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 결과 처리
logger.info("=== OAuth 접근토큰 발급 결과 ===")
logger.info("사용 가능한 컬럼: %s", result.columns.tolist())
# 통합 컬럼명 한글 변환 (필요한 컬럼만 자동 매핑됨)
result = result.rename(columns=COLUMN_MAPPING)
logger.info("결과:")
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,127 @@
# [인증] WebSocket 웹소켓 접속키 발급
# Generated by KIS API Generator (Single API Mode)
# -*- coding: utf-8 -*-
"""
Created on 2025-06-19
"""
import json
import logging
import sys
from typing import Optional
import pandas as pd
import requests
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [인증] WebSocket 웹소켓 접속키 발급
##############################################################################################
# 상수 정의
API_URL = "/oauth2/Approval"
def auth_ws_token(
grant_type: str,
appkey: str,
appsecret: str,
env_dv: str,
token: Optional[str] = ""
) -> pd.DataFrame:
"""
WebSocket 웹소켓 접속키 발급 API를 호출하여 DataFrame으로 반환합니다.
Args:
grant_type (str): [필수] 권한부여 Type (client_credentials)
appkey (str): [필수] 고객 앱Key (한국투자증권 홈페이지에서 발급받은 appkey)
appsecret (str): [필수] 고객 앱Secret (한국투자증권 홈페이지에서 발급받은 appsecret)
env_dv (str): [필수] 환경구분 (real: 실전, demo: 모의)
token (Optional[str]): 접근토큰 (OAuth 토큰이 필요한 API 경우 발급한 Access token)
Returns:
pd.DataFrame: WebSocket 접속키 발급 결과
Example:
>>> df = auth_ws_token(
... grant_type="client_credentials",
... appkey=trenv.my_app,
... appsecret=trenv.my_sec,
... env_dv="real"
... )
>>> print(df)
"""
# 필수 파라미터 검증
if not grant_type:
logger.error("grant_type is required. (e.g. 'client_credentials')")
raise ValueError("grant_type is required. (e.g. 'client_credentials')")
if not appkey:
logger.error("appkey is required. (한국투자증권 홈페이지에서 발급받은 appkey)")
raise ValueError("appkey is required. (한국투자증권 홈페이지에서 발급받은 appkey)")
if not appsecret:
logger.error("appsecret is required. (한국투자증권 홈페이지에서 발급받은 appsecret)")
raise ValueError("appsecret is required. (한국투자증권 홈페이지에서 발급받은 appsecret)")
if not env_dv:
logger.error("env_dv is required. (real: 실전, demo: 모의)")
raise ValueError("env_dv is required. (real: 실전, demo: 모의)")
# 환경 구분에 따른 서버 URL 설정
config = ka.getEnv()
if env_dv == "real":
base_url = config.get("prod", "")
elif env_dv == "demo":
base_url = config.get("vps", "")
else:
logger.error("env_dv must be 'real' or 'demo'")
raise ValueError("env_dv must be 'real' or 'demo'")
url = f"{base_url}{API_URL}"
# 헤더 설정
headers = {
"Content-Type": "application/json",
"Accept": "text/plain",
"charset": "UTF-8"
}
# 요청 데이터
data = {
"grant_type": grant_type,
"appkey": appkey,
"secretkey": appsecret,
}
# token이 있는 경우에만 data에 추가
if token:
data["token"] = token
try:
# POST 방식으로 직접 API 호출
response = requests.post(url, data=json.dumps(data), headers=headers)
if response.status_code == 200:
# 응답 데이터를 DataFrame으로 반환 (1개 row)
response_data = response.json()
current_data = pd.DataFrame([response_data])
logger.info("WebSocket 접속키 발급 성공")
return current_data
else:
logger.error("API call failed: %s - %s", response.status_code, response.text)
return pd.DataFrame()
except requests.RequestException as e:
logger.error("Request failed: %s", str(e))
return pd.DataFrame()
except json.JSONDecodeError as e:
logger.error("JSON decode failed: %s", str(e))
return pd.DataFrame()

View File

@@ -0,0 +1,104 @@
# -*- 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 auth_ws_token import auth_ws_token
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [인증] WebSocket 웹소켓 접속키 발급 테스트
##############################################################################################
# 통합 컬럼 매핑
COLUMN_MAPPING = {
'code': '응답코드',
'message': '응답메세지',
'approval_key': '웹소켓접속키'
}
def main():
"""
WebSocket 웹소켓 접속키 발급 테스트 함수
Parameters:
- grant_type (str): 권한부여 Type (client_credentials)
- appkey (str): 고객 앱Key (한국투자증권 홈페이지에서 발급받은 appkey)
- appsecret (str): 고객 앱Secret (한국투자증권 홈페이지에서 발급받은 appsecret)
- env_dv (str): 환경구분 (real: 실전, demo: 모의)
- token (str): 접근토큰 (OAuth 토큰이 필요한 API 경우 발급한 Access token)
Returns:
- pd.DataFrame: WebSocket 접속키 발급 결과
Response Fields:
- code: 응답코드 (HTTP 응답코드)
- message: 응답메세지
Example:
>>> df = auth_ws_token(grant_type="client_credentials", appkey=trenv.my_app, appsecret=trenv.my_sec, env_dv="real")
"""
try:
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# OAuth 토큰 발급 (WebSocket 접속키 발급에 필요)
logger.info("OAuth 토큰 발급 중...")
ka.auth() # 토큰 발급
logger.info("OAuth 토큰 발급 완료")
# 환경 설정에서 토큰, 앱키, 앱시크릿 가져오기
trenv = ka.getTREnv()
appkey = trenv.my_app
appsecret = trenv.my_sec
# 토큰 및 앱키가 설정되어 있는지 확인
if not appkey or not appsecret:
logger.error("앱키 또는 앱시크릿이 설정되지 않았습니다.")
return
# API 호출
logger.info("WebSocket 웹소켓 접속키 발급 API 호출 시작")
result = auth_ws_token(
grant_type="client_credentials",
appkey=appkey,
appsecret=appsecret,
env_dv="real", # 실전 환경으로 설정 (필요시 "demo"로 변경)
)
# 결과 확인
if result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 결과 처리
logger.info("=== WebSocket 웹소켓 접속키 발급 결과 ===")
logger.info("사용 가능한 컬럼: %s", result.columns.tolist())
# 통합 컬럼명 한글 변환 (필요한 컬럼만 자동 매핑됨)
result = result.rename(columns=COLUMN_MAPPING)
logger.info("결과:")
print(result)
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,171 @@
# [장내채권] 기본시세 - 장내채권 평균단가조회
# Generated by KIS API Generator (Single API Mode)
# -*- coding: utf-8 -*-
"""
Created on 2025-06-19
"""
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__)
##############################################################################################
# [장내채권] 기본시세 > 장내채권 평균단가조회 [국내채권-158]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-bond/v1/quotations/avg-unit"
def avg_unit(
inqr_strt_dt: str, # 조회시작일자
inqr_end_dt: str, # 조회종료일자
pdno: str, # 상품번호
prdt_type_cd: str, # 상품유형코드
vrfc_kind_cd: str, # 검증종류코드
NK30: str = "", # 연속조회키30
FK100: str = "", # 연속조회검색조건100
dataframe1: Optional[pd.DataFrame] = None, # 누적 데이터프레임 (output1)
dataframe2: Optional[pd.DataFrame] = None, # 누적 데이터프레임 (output2)
dataframe3: Optional[pd.DataFrame] = None, # 누적 데이터프레임 (output3)
tr_cont: str = "",
depth: int = 0,
max_depth: int = 10
) -> Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:
"""
[장내채권] 기본시세
장내채권 평균단가조회[국내주식-158]
장내채권 평균단가조회 API를 호출하여 DataFrame으로 반환합니다.
Args:
inqr_strt_dt (str): 조회 시작 일자 (예: '20230101')
inqr_end_dt (str): 조회 종료 일자 (예: '20230131')
pdno (str): 상품번호, 공백: 전체, 특정종목 조회시 : 종목코드
prdt_type_cd (str): 상품유형코드 (예: '302')
vrfc_kind_cd (str): 검증종류코드 (예: '00')
NK30 (str): 연속조회키30, 공백 허용
FK100 (str): 연속조회검색조건100, 공백 허용
dataframe1 (Optional[pd.DataFrame]): 누적 데이터프레임 (output1)
dataframe2 (Optional[pd.DataFrame]): 누적 데이터프레임 (output2)
dataframe3 (Optional[pd.DataFrame]): 누적 데이터프레임 (output3)
tr_cont (str): 연속 거래 여부
depth (int): 현재 재귀 깊이
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]: 장내채권 평균단가조회 데이터
Example:
>>> df1, df2, df3 = avg_unit(
... inqr_strt_dt='20230101',
... inqr_end_dt='20230131',
... pdno='KR2033022D33',
... prdt_type_cd='302',
... vrfc_kind_cd='00',
... )
>>> print(df1)
>>> print(df2)
>>> print(df3)
"""
# 필수 파라미터 검증
if not inqr_strt_dt:
logger.error("inqr_strt_dt is required. (e.g. '20230101')")
raise ValueError("inqr_strt_dt is required. (e.g. '20230101')")
if not inqr_end_dt:
logger.error("inqr_end_dt is required. (e.g. '20230131')")
raise ValueError("inqr_end_dt is required. (e.g. '20230131')")
if not prdt_type_cd:
logger.error("prdt_type_cd is required. (e.g. '302')")
raise ValueError("prdt_type_cd is required. (e.g. '302')")
if not vrfc_kind_cd:
logger.error("vrfc_kind_cd is required. (e.g. '00')")
raise ValueError("vrfc_kind_cd is required. (e.g. '00')")
# 최대 재귀 깊이 체크
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(),
dataframe3 if dataframe3 is not None else pd.DataFrame()
)
tr_id = "CTPF2005R"
params = {
"INQR_STRT_DT": inqr_strt_dt,
"INQR_END_DT": inqr_end_dt,
"PDNO": pdno,
"PRDT_TYPE_CD": prdt_type_cd,
"VRFC_KIND_CD": vrfc_kind_cd,
"CTX_AREA_NK30": NK30,
"CTX_AREA_FK100": FK100,
}
res = ka._url_fetch(API_URL, tr_id, tr_cont, params)
if res.isOK():
# 연속조회 정보 업데이트
tr_cont = res.getHeader().tr_cont
NK30 = res.getBody().ctx_area_nk30
FK100 = res.getBody().ctx_area_fk100
# 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)
if dataframe2 is not None:
dataframe2 = pd.concat([dataframe2, current_data2], ignore_index=True)
else:
dataframe2 = current_data2
# output3 데이터 처리
current_data3 = pd.DataFrame(res.getBody().output3)
if dataframe3 is not None:
dataframe3 = pd.concat([dataframe3, current_data3], ignore_index=True)
else:
dataframe3 = current_data3
if tr_cont in ["M", "F"]: # 다음 페이지 존재
logger.info("Call Next page...")
ka.smart_sleep() # 시스템 안정적 운영을 위한 지연
return avg_unit(
inqr_strt_dt,
inqr_end_dt,
pdno,
prdt_type_cd,
vrfc_kind_cd,
NK30,
FK100,
dataframe1,
dataframe2,
dataframe3,
"N",
depth + 1,
max_depth
)
else:
logger.info("Data fetch complete.")
return dataframe1, dataframe2, dataframe3
else:
logger.error("API call failed: %s - %s", res.getErrorCode(), res.getErrorMessage())
res.printError(API_URL)
return pd.DataFrame(), pd.DataFrame(), pd.DataFrame()

View File

@@ -0,0 +1,184 @@
# -*- 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 avg_unit import avg_unit
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [장내채권] 기본시세 > 장내채권 평균단가조회 [국내채권-158]
##############################################################################################
# 통합 컬럼 매핑 (모든 output에서 공통 사용)
COLUMN_MAPPING = {
'evlu_dt': '평가일자',
'pdno': '상품번호',
'prdt_type_cd': '상품유형코드',
'kis_unpr': '한국신용평가단가',
'kbp_unpr': '한국채권평가단가',
'nice_evlu_unpr': '한국신용정보평가단가',
'fnp_unpr': '에프앤자산평가단가',
'avg_evlu_unpr': '평균평가단가',
'kis_crdt_grad_text': '한국신용평가신용등급내용',
'kbp_crdt_grad_text': '한국채권평가신용등급내용',
'nice_crdt_grad_text': '한국신용정보신용등급내용',
'fnp_crdt_grad_text': '에프앤자산평가신용등급내용',
'chng_yn': '변경여부',
'kis_erng_rt': '한국신용평가수익율',
'kbp_erng_rt': '한국채권평가수익율',
'nice_evlu_erng_rt': '한국신용정보평가수익율',
'fnp_erng_rt': '에프앤자산평가수익율',
'avg_evlu_erng_rt': '평균평가수익율',
'kis_rf_unpr': '한국신용평가RF단가',
'kbp_rf_unpr': '한국채권평가RF단가',
'nice_evlu_rf_unpr': '한국신용정보평가RF단가',
'avg_evlu_rf_unpr': '평균평가RF단가',
'evlu_dt': '평가일자',
'pdno': '상품번호',
'prdt_type_cd': '상품유형코드',
'kis_evlu_amt': '한국신용평가평가금액',
'kbp_evlu_amt': '한국채권평가평가금액',
'nice_evlu_amt': '한국신용정보평가금액',
'fnp_evlu_amt': '에프앤자산평가평가금액',
'avg_evlu_amt': '평균평가금액',
'chng_yn': '변경여부',
'output3': '응답상세',
'evlu_dt': '평가일자',
'pdno': '상품번호',
'prdt_type_cd': '상품유형코드',
'kis_crcy_cd': '한국신용평가통화코드',
'kis_evlu_unit_pric': '한국신용평가평가단위가격',
'kis_evlu_pric': '한국신용평가평가가격',
'kbp_crcy_cd': '한국채권평가통화코드',
'kbp_evlu_unit_pric': '한국채권평가평가단위가격',
'kbp_evlu_pric': '한국채권평가평가가격',
'nice_crcy_cd': '한국신용정보통화코드',
'nice_evlu_unit_pric': '한국신용정보평가단위가격',
'nice_evlu_pric': '한국신용정보평가가격',
'avg_evlu_unit_pric': '평균평가단위가격',
'avg_evlu_pric': '평균평가가격',
'chng_yn': '변경여부'
}
NUMERIC_COLUMNS = []
def main():
"""
[장내채권] 기본시세
장내채권 평균단가조회[국내주식-158]
장내채권 평균단가조회 테스트 함수`
Parameters:
- inqr_strt_dt (str): 조회시작일자 (일자 ~)
- inqr_end_dt (str): 조회종료일자 (~ 일자)
- pdno (str): 상품번호 (공백: 전체, 특정종목 조회시 : 종목코드)
- prdt_type_cd (str): 상품유형코드 (Unique key(302))
- vrfc_kind_cd (str): 검증종류코드 (Unique key(00))
Returns:
- Tuple[DataFrame, ...]: 장내채권 평균단가조회 결과
Example:
>>> df1, df2, df3 = avg_unit(inqr_strt_dt="20250101", inqr_end_dt="20250131", pdno="KR2033022D33", prdt_type_cd="302", vrfc_kind_cd="00")
"""
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, result3 = avg_unit(
inqr_strt_dt="20240101", # 조회시작일자
inqr_end_dt="20250630", # 조회종료일자
pdno="KR103502GA34", # 상품번호
prdt_type_cd="302", # 상품유형코드
vrfc_kind_cd="00", # 검증종류코드
)
# 결과 확인
results = [result1, result2, result3]
if all(result is None or result.empty for result in results):
logger.warning("조회된 데이터가 없습니다.")
return
# output1 결과 처리
logger.info("=== output1 조회 ===")
if not result1.empty:
logger.info("사용 가능한 컬럼: %s", 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)
logger.info("output1 결과:")
print(result1)
else:
logger.info("output1 데이터가 없습니다.")
# output2 결과 처리
logger.info("=== output2 조회 ===")
if not result2.empty:
logger.info("사용 가능한 컬럼: %s", 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)
logger.info("output2 결과:")
print(result2)
else:
logger.info("output2 데이터가 없습니다.")
# output3 결과 처리
logger.info("=== output3 조회 ===")
if not result3.empty:
logger.info("사용 가능한 컬럼: %s", result3.columns.tolist())
# 통합 컬럼명 한글 변환 (필요한 컬럼만 자동 매핑됨)
result3 = result3.rename(columns=COLUMN_MAPPING)
for col in NUMERIC_COLUMNS:
if col in result3.columns:
result3[col] = pd.to_numeric(result3[col], errors='coerce').round(2)
logger.info("output3 결과:")
print(result3)
else:
logger.info("output3 데이터가 없습니다.")
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,97 @@
"""
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__)
##############################################################################################
# [장내채권] 실시간시세 > 일반채권 실시간호가 [실시간-053]
##############################################################################################
def bond_asking_price(
tr_type: str,
tr_key: str,
) -> tuple[dict, list[str]]:
"""
일반채권 실시간호가[H0BJASP0]
일반채권 실시간호가 API를 통해 실시간 데이터를 구독합니다.
Args:
tr_type (str): [필수] 구독 등록("1") 또는 해제("0") 여부를 나타냅니다.
tr_key (str): [필수] 종목코드. 빈 문자열일 수 없습니다.
Returns:
message (dict): 실시간 데이터 메시지.
columns (list[str]): 응답 데이터의 컬럼 정보.
Raises:
ValueError: tr_key가 빈 문자열인 경우 발생합니다.
Example:
>>> msg, columns = bond_asking_price("1", "005930")
>>> print(msg, columns)
[참고자료]
채권 종목코드 마스터파일은 "KIS포털 - API문서 - 종목정보파일 - 장내채권 - 채권코드" 참고 부탁드립니다.
"""
# 필수 파라미터 검증
if not tr_key:
raise ValueError("tr_key is required and cannot be an empty string")
tr_id = "H0BJASP0"
params = {
"tr_key": tr_key,
}
# 데이터 요청
msg = ka.data_fetch(tr_id, tr_type, params)
# 응답 데이터 컬럼 정보
columns = [
"stnd_iscd",
"stck_cntg_hour",
"askp_ert1",
"bidp_ert1",
"askp1",
"bidp1",
"askp_rsqn1",
"bidp_rsqn1",
"askp_ert2",
"bidp_ert2",
"askp2",
"bidp2",
"askp_rsqn2",
"bidp_rsqn2",
"askp_ert3",
"bidp_ert3",
"askp3",
"bidp3",
"askp_rsqn3",
"bidp_rsqn3",
"askp_ert4",
"bidp_ert4",
"askp4",
"bidp4",
"askp_rsqn4",
"bidp_rsqn4",
"askp_ert5",
"bidp_ert5",
"askp5",
"bidp5",
"askp_rsqn52",
"bidp_rsqn53",
"total_askp_rsqn",
"total_bidp_rsqn",
]
return msg, columns

View File

@@ -0,0 +1,133 @@
"""
Created on 2025-07-09
"""
import logging
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from bond_asking_price import bond_asking_price
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [장내채권] 실시간시세 > 일반채권 실시간호가 [실시간-053]
##############################################################################################
COLUMN_MAPPING = {
"stnd_iscd": "표준종목코드",
"stck_cntg_hour": "주식체결시간",
"askp_ert1": "매도호가수익률1",
"bidp_ert1": "매수호가수익률1",
"askp1": "매도호가1",
"bidp1": "매수호가1",
"askp_rsqn1": "매도호가잔량1",
"bidp_rsqn1": "매수호가잔량1",
"askp_ert2": "매도호가수익률2",
"bidp_ert2": "매수호가수익률2",
"askp2": "매도호가2",
"bidp2": "매수호가2",
"askp_rsqn2": "매도호가잔량2",
"bidp_rsqn2": "매수호가잔량2",
"askp_ert3": "매도호가수익률3",
"bidp_ert3": "매수호가수익률3",
"askp3": "매도호가3",
"bidp3": "매수호가3",
"askp_rsqn3": "매도호가잔량3",
"bidp_rsqn3": "매수호가잔량3",
"askp_ert4": "매도호가수익률4",
"bidp_ert4": "매수호가수익률4",
"askp4": "매도호가4",
"bidp4": "매수호가4",
"askp_rsqn4": "매도호가잔량4",
"bidp_rsqn4": "매수호가잔량4",
"askp_ert5": "매도호가수익률5",
"bidp_ert5": "매수호가수익률5",
"askp5": "매도호가5",
"bidp5": "매수호가5",
"askp_rsqn52": "매도호가잔량5",
"bidp_rsqn53": "매수호가잔량5",
"total_askp_rsqn": "총매도호가잔량",
"total_bidp_rsqn": "총매수호가잔량"
}
NUMERIC_COLUMNS = [
"매도호가수익률1", "매수호가수익률1", "매도호가1", "매수호가1", "매도호가잔량1", "매수호가잔량1",
"매도호가수익률2", "매수호가수익률2", "매도호가2", "매수호가2", "매도호가잔량2", "매수호가잔량2",
"매도호가수익률3", "매수호가수익률3", "매도호가3", "매수호가3", "매도호가잔량3", "매수호가잔량3",
"매도호가수익률4", "매수호가수익률4", "매도호가4", "매수호가4", "매도호가잔량4", "매수호가잔량4",
"매도호가수익률5", "매수호가수익률5", "매도호가5", "매수호가5", "매도호가잔량5", "매수호가잔량5",
"총매도호가잔량", "총매수호가잔량"
]
def main():
"""
일반채권 실시간호가
일반채권 실시간호가 API입니다.
[참고자료]
채권 종목코드 마스터파일은 "KIS포털 - API문서 - 종목정보파일 - 장내채권 - 채권코드" 참고 부탁드립니다.
[호출 데이터]
헤더와 바디 값을 합쳐 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")
# 조회
kws.subscribe(request=bond_asking_price, data=["KR103502GA34", "KR6095572D81"])
# 결과 표시
def on_result(ws, tr_id: str, result: pd.DataFrame, data_map: dict):
try:
# 컬럼 매핑
result.rename(columns=COLUMN_MAPPING, inplace=True)
# 숫자형 컬럼 변환
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce')
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,85 @@
"""
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__)
##############################################################################################
# [장내채권] 실시간시세 > 일반채권 실시간체결가 [실시간-052]
##############################################################################################
def bond_ccnl(
tr_type: str,
tr_key: str,
) -> tuple[dict, list[str]]:
"""
일반채권 실시간체결가[H0BJCNT0] 구독 함수
한국투자증권 웹소켓 API를 통해 일반채권의 실시간 체결가 데이터를 구독합니다.
[참고자료]
채권 종목코드 마스터파일은 "KIS포털 - API문서 - 종목정보파일 - 장내채권 - 채권코드" 참고 부탁드립니다.
Args:
tr_type (str): [필수] 구독 등록("1") 또는 해제("0") 여부
tr_key (str): [필수] 종목코드 (빈 문자열 불가)
Returns:
message (dict): 실시간 데이터 구독 결과 메시지
columns (list[str]): 응답 데이터의 컬럼 정보
Raises:
ValueError: tr_key가 빈 문자열인 경우 발생
Example:
>>> msg, columns = bond_ccnl("1", "005930")
>>> print(msg, columns)
"""
# 필수 파라미터 검증
if not tr_key:
raise ValueError("tr_key는 빈 문자열일 수 없습니다.")
tr_id = "H0BJCNT0"
params = {
"tr_key": tr_key,
}
# 데이터 구독 요청
msg = ka.data_fetch(tr_id, tr_type, params)
# 응답 데이터 컬럼 정보
columns = [
"stnd_iscd", # 표준종목코드
"bond_isnm", # 채권종목명
"stck_cntg_hour", # 주식체결시간
"prdy_vrss_sign", # 전일대비부호
"prdy_vrss", # 전일대비
"prdy_ctrt", # 전일대비율
"stck_prpr", # 현재가
"cntg_vol", # 체결거래량
"stck_oprc", # 시가
"stck_hgpr", # 고가
"stck_lwpr", # 저가
"stck_prdy_clpr", # 전일종가
"bond_cntg_ert", # 현재수익률
"oprc_ert", # 시가수익률
"hgpr_ert", # 고가수익률
"lwpr_ert", # 저가수익률
"acml_vol", # 누적거래량
"prdy_vol", # 전일거래량
"cntg_type_cls_code", # 체결유형코드
]
return msg, columns

View File

@@ -0,0 +1,112 @@
"""
Created on 2025-07-09
"""
import logging
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from bond_ccnl import bond_ccnl
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [장내채권] 실시간시세 > 일반채권 실시간체결가 [실시간-052]
##############################################################################################
COLUMN_MAPPING = {
"stnd_iscd": "표준종목코드",
"bond_isnm": "채권종목명",
"stck_cntg_hour": "주식체결시간",
"prdy_vrss_sign": "전일대비부호",
"prdy_vrss": "전일대비",
"prdy_ctrt": "전일대비율",
"stck_prpr": "현재가",
"cntg_vol": "체결거래량",
"stck_oprc": "시가",
"stck_hgpr": "고가",
"stck_lwpr": "저가",
"stck_prdy_clpr": "전일종가",
"bond_cntg_ert": "현재수익률",
"oprc_ert": "시가수익률",
"hgpr_ert": "고가수익률",
"lwpr_ert": "저가수익률",
"acml_vol": "누적거래량",
"prdy_vol": "전일거래량",
"cntg_type_cls_code": "체결유형코드"
}
NUMERIC_COLUMNS = [
"전일대비", "전일대비율", "현재가", "체결거래량", "시가", "고가", "저가", "전일종가",
"현재수익률", "시가수익률", "고가수익률", "저가수익률", "누적거래량", "전일거래량"
]
def main():
"""
일반채권 실시간체결가
일반채권 실시간체결가 API입니다.
[호출 데이터]
헤더와 바디 값을 합쳐 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 데이터 참조 ( ^로 구분됨)
[참고자료]
채권 종목코드 마스터파일은 "KIS포털 - API문서 - 종목정보파일 - 장내채권 - 채권코드" 참고 부탁드립니다.
"""
# 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")
# 조회
kws.subscribe(request=bond_ccnl, data=["KR103502GA34", "KR6095572D81"])
# 결과 표시
def on_result(ws, tr_id: str, result: pd.DataFrame, data_map: dict):
try:
# 컬럼 매핑
result.rename(columns=COLUMN_MAPPING, inplace=True)
# 숫자형 컬럼 변환
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce')
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,84 @@
"""
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__)
##############################################################################################
# [장내채권] 실시간시세 > 채권지수 실시간체결가 [실시간-060]
##############################################################################################
def bond_index_ccnl(
tr_type: str,
tr_key: str,
) -> tuple[dict, list[str]]:
"""
채권지수 실시간체결가[H0BICNT0]
채권지수 실시간체결가 API를 통해 실시간 데이터를 구독합니다.
Args:
tr_type (str): [필수] 구독 등록("1") 또는 해제("0") 여부를 나타냅니다.
tr_key (str): [필수] 구독할 종목코드. 빈 문자열이 아니어야 합니다.
Returns:
message (dict): 구독 요청에 대한 응답 메시지.
columns (list[str]): 실시간 데이터의 컬럼 정보.
Raises:
ValueError: tr_key가 빈 문자열인 경우 발생합니다.
Example:
>>> msg, columns = bond_index_ccnl("1", "005930")
>>> print(msg, columns)
[참고자료]
채권 종목코드 마스터파일은 "KIS포털 - API문서 - 종목정보파일 - 장내채권 - 채권코드" 참고 부탁드립니다.
"""
# 필수 파라미터 검증
if not tr_key:
raise ValueError("tr_key is required and cannot be an empty string")
tr_id = "H0BICNT0"
params = {
"tr_key": tr_key,
}
# 데이터 구독 요청
msg = ka.data_fetch(tr_id, tr_type, params)
# 응답 데이터 컬럼 정보
columns = [
"nmix_id", # 지수ID
"stnd_date1", # 기준일자1
"trnm_hour", # 전송시간
"totl_ernn_nmix_oprc", # 총수익지수시가지수
"totl_ernn_nmix_hgpr", # 총수익지수최고가
"totl_ernn_nmix_lwpr", # 총수익지수최저가
"totl_ernn_nmix", # 총수익지수
"prdy_totl_ernn_nmix", # 전일총수익지수
"totl_ernn_nmix_prdy_vrss", # 총수익지수전일대비
"totl_ernn_nmix_prdy_vrss_sign", # 총수익지수전일대비부호
"totl_ernn_nmix_prdy_ctrt", # 총수익지수전일대비율
"clen_prc_nmix", # 순가격지수
"mrkt_prc_nmix", # 시장가격지수
"bond_call_rnvs_nmix", # Call재투자지수
"bond_zero_rnvs_nmix", # Zero재투자지수
"bond_futs_thpr", # 선물이론가격
"bond_avrg_drtn_val", # 평균듀레이션
"bond_avrg_cnvx_val", # 평균컨벡서티
"bond_avrg_ytm_val", # 평균YTM
"bond_avrg_frdl_ytm_val", # 평균선도YTM
]
return msg, columns

View File

@@ -0,0 +1,124 @@
"""
Created on 2025-07-09
"""
import logging
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from bond_index_ccnl import bond_index_ccnl
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [장내채권] 실시간시세 > 채권지수 실시간체결가 [실시간-060]
##############################################################################################
COLUMN_MAPPING = {
"nmix_id": "지수ID",
"stnd_date1": "기준일자1",
"trnm_hour": "전송시간",
"totl_ernn_nmix_oprc": "총수익지수시가지수",
"totl_ernn_nmix_hgpr": "총수익지수최고가",
"totl_ernn_nmix_lwpr": "총수익지수최저가",
"totl_ernn_nmix": "총수익지수",
"prdy_totl_ernn_nmix": "전일총수익지수",
"totl_ernn_nmix_prdy_vrss": "총수익지수전일대비",
"totl_ernn_nmix_prdy_vrss_sign": "총수익지수전일대비부호",
"totl_ernn_nmix_prdy_ctrt": "총수익지수전일대비율",
"clen_prc_nmix": "순가격지수",
"mrkt_prc_nmix": "시장가격지수",
"bond_call_rnvs_nmix": "Call재투자지수",
"bond_zero_rnvs_nmix": "Zero재투자지수",
"bond_futs_thpr": "선물이론가격",
"bond_avrg_drtn_val": "평균듀레이션",
"bond_avrg_cnvx_val": "평균컨벡서티",
"bond_avrg_ytm_val": "평균YTM",
"bond_avrg_frdl_ytm_val": "평균선도YTM"
}
NUMERIC_COLUMNS = [
"총수익지수시가지수", "총수익지수최고가", "총수익지수최저가", "총수익지수",
"전일총수익지수", "총수익지수전일대비", "총수익지수전일대비율", "순가격지수",
"시장가격지수", "Call재투자지수", "Zero재투자지수", "선물이론가격"]
def main():
"""
채권지수 실시간체결가
채권지수 실시간체결가 API입니다.
[참고자료]
채권 종목코드 마스터파일은 "KIS포털 - API문서 - 종목정보파일 - 장내채권 - 채권코드" 참고 부탁드립니다.
[호출 데이터]
헤더와 바디 값을 합쳐 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")
# 조회
# 한경채권지수: KBPR01, KBPR02, KBPR03, KBPR04
# KIS채권지수: KISR01, MSBI07, KTBL10, MSBI09, MSBI10, CDIX01
# 매경채권지수: MKFR01, MSBI01, MSBI03, MSBI10, CORP01
kws.subscribe(request=bond_index_ccnl, data=[
# 한경채권지수
"KBPR01", "KBPR02", "KBPR03", "KBPR04",
# KIS채권지수
"KISR01", "MSBI07", "KTBL10", "MSBI09", "MSBI10", "CDIX01",
# 매경채권지수
"MKFR01", "MSBI01", "MSBI03", "MSBI10", "CORP01"
])
# 결과 표시
def on_result(ws, tr_id: str, result: pd.DataFrame, data_map: dict):
try:
# 컬럼 매핑
result.rename(columns=COLUMN_MAPPING, inplace=True)
# 숫자형 컬럼 변환
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce')
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,112 @@
# [장내채권] 주문/계좌 - 장내채권 매수주문
# Generated by KIS API Generator (Single API Mode)
# -*- coding: utf-8 -*-
"""
Created on 2025-06-20
"""
import logging
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__)
##############################################################################################
# [장내채권] 주문/계좌 > 장내채권 매수주문 [국내주식-124]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-bond/v1/trading/buy"
def buy(
cano: str,
acnt_prdt_cd: str,
pdno: str,
ord_qty2: str,
bond_ord_unpr: str,
samt_mket_ptci_yn: str,
bond_rtl_mket_yn: str,
idcr_stfno: str = "",
mgco_aptm_odno: str = "",
ord_svr_dvsn_cd: str = "",
ctac_tlno: str = ""
) -> Optional[pd.DataFrame]:
"""
[장내채권] 주문/계좌
장내채권 매수주문[국내주식-124]
장내채권 매수주문 API를 호출하여 DataFrame으로 반환합니다.
Args:
cano (str): 종합계좌번호 (8자리)
acnt_prdt_cd (str): 계좌상품코드 (2자리)
pdno (str): 상품번호 (12자리)
ord_qty2 (str): 주문수량2 (19자리)
bond_ord_unpr (str): 채권주문단가 (182자리)
samt_mket_ptci_yn (str): 소액시장참여여부 ('Y' or 'N')
bond_rtl_mket_yn (str): 채권소매시장여부 ('Y' or 'N')
idcr_stfno (str, optional): 유치자직원번호 (6자리). Defaults to "".
mgco_aptm_odno (str, optional): 운용사지정주문번호 (12자리). Defaults to "".
ord_svr_dvsn_cd (str, optional): 주문서버구분코드. Defaults to "".
ctac_tlno (str, optional): 연락전화번호. Defaults to "".
Returns:
Optional[pd.DataFrame]: 장내채권 매수주문 데이터
Example:
>>> df = buy(
... cano=trenv.my_acct,
... acnt_prdt_cd=trenv.my_prod,
... pdno="KR1234567890",
... ord_qty2="10",
... bond_ord_unpr="10000",
... samt_mket_ptci_yn="N",
... bond_rtl_mket_yn="Y"
... )
>>> print(df)
"""
tr_id = "TTTC0952U"
params = {
"CANO": cano,
"ACNT_PRDT_CD": acnt_prdt_cd,
"PDNO": pdno,
"ORD_QTY2": ord_qty2,
"BOND_ORD_UNPR": bond_ord_unpr,
"SAMT_MKET_PTCI_YN": samt_mket_ptci_yn,
"BOND_RTL_MKET_YN": bond_rtl_mket_yn,
"IDCR_STFNO": idcr_stfno,
"MGCO_APTM_ODNO": mgco_aptm_odno,
"ORD_SVR_DVSN_CD": ord_svr_dvsn_cd,
"CTAC_TLNO": ctac_tlno,
}
res = ka._url_fetch(api_url=API_URL,
ptr_id=tr_id,
tr_cont="",
params=params,
postFlag=True
)
if res.isOK():
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
dataframe = pd.DataFrame(output_data)
else:
dataframe = pd.DataFrame()
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,114 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-20
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from buy import buy
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [장내채권] 주문/계좌 > 장내채권 매수주문 [국내주식-124]
##############################################################################################
COLUMN_MAPPING = {
'KRX_FWDG_ORD_ORGNO': '한국거래소전송주문조직번호',
'ODNO': '주문번호',
'ORD_TMD': '주문시각'
}
NUMERIC_COLUMNS = []
def main():
"""
[장내채권] 주문/계좌`
장내채권 매수주문[국내주식-124]
장내채권 매수주문 테스트 함수
Parameters:
cano (str): 종합계좌번호 (8자리)
acnt_prdt_cd (str): 계좌상품코드 (2자리)
pdno (str): 상품번호 (12자리)
ord_qty2 (str): 주문수량2 (19자리)
bond_ord_unpr (str): 채권주문단가 (182자리)
samt_mket_ptci_yn (str): 소액시장참여여부 ('Y' or 'N')
bond_rtl_mket_yn (str): 채권소매시장여부 ('Y' or 'N')
idcr_stfno (str, optional): 유치자직원번호 (6자리). Defaults to "".
mgco_aptm_odno (str, optional): 운용사지정주문번호 (12자리). Defaults to "".
Returns:
- DataFrame: 장내채권 매수주문 결과
Example:
>>> df = main()
>>> print(df)
"""
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("토큰 발급 완료")
# kis_auth 모듈에서 계좌 정보 가져오기
trenv = ka.getTREnv()
# API 호출
logger.info("API 호출 시작: 장내채권 매수주문")
result = buy(
cano=trenv.my_acct, # 종합계좌번호
acnt_prdt_cd=trenv.my_prod, # 계좌상품코드
pdno="KR6095572D81", # 상품번호
ord_qty2="10", # 주문수량
bond_ord_unpr="9900", # 채권주문단가
samt_mket_ptci_yn="N", # 소액시장참여여부
bond_rtl_mket_yn="N", # 채권소매시장여부
idcr_stfno="", # 유치자직원번호
mgco_aptm_odno="", # 운용사지정주문번호
ord_svr_dvsn_cd="0", # 주문서버구분코드
ctac_tlno="", # 연락전화번호
)
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')
# 결과 출력
logger.info("=== 장내채권 매수주문 결과 ===")
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,123 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-19
"""
import logging
import sys
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from inquire_asking_price import inquire_asking_price
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [장내채권] 기본시세 > 장내채권현재가(호가) [국내주식-132]
##############################################################################################
COLUMN_MAPPING = {
'aspr_acpt_hour': '호가 접수 시간',
'bond_askp1': '채권 매도호가1',
'bond_askp2': '채권 매도호가2',
'bond_askp3': '채권 매도호가3',
'bond_askp4': '채권 매도호가4',
'bond_askp5': '채권 매도호가5',
'bond_bidp1': '채권 매수호가1',
'bond_bidp2': '채권 매수호가2',
'bond_bidp3': '채권 매수호가3',
'bond_bidp4': '채권 매수호가4',
'bond_bidp5': '채권 매수호가5',
'askp_rsqn1': '매도호가 잔량1',
'askp_rsqn2': '매도호가 잔량2',
'askp_rsqn3': '매도호가 잔량3',
'askp_rsqn4': '매도호가 잔량4',
'askp_rsqn5': '매도호가 잔량5',
'bidp_rsqn1': '매수호가 잔량1',
'bidp_rsqn2': '매수호가 잔량2',
'bidp_rsqn3': '매수호가 잔량3',
'bidp_rsqn4': '매수호가 잔량4',
'bidp_rsqn5': '매수호가 잔량5',
'total_askp_rsqn': '총 매도호가 잔량',
'total_bidp_rsqn': '총 매수호가 잔량',
'ntby_aspr_rsqn': '순매수 호가 잔량',
'seln_ernn_rate1': '매도 수익 비율1',
'seln_ernn_rate2': '매도 수익 비율2',
'seln_ernn_rate3': '매도 수익 비율3',
'seln_ernn_rate4': '매도 수익 비율4',
'seln_ernn_rate5': '매도 수익 비율5',
'shnu_ernn_rate1': '매수2 수익 비율1',
'shnu_ernn_rate2': '매수2 수익 비율2',
'shnu_ernn_rate3': '매수2 수익 비율3',
'shnu_ernn_rate4': '매수2 수익 비율4',
'shnu_ernn_rate5': '매수2 수익 비율5'
}
NUMERIC_COLUMNS = []
def main():
"""
[장내채권] 기본시세
장내채권현재가(호가)[국내주식-132]
장내채권현재가(호가) 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 시장 분류 코드 (B 입력)
- fid_input_iscd (str): 채권종목코드
Returns:
- DataFrame: 장내채권현재가(호가) 결과
Example:
>>> df = inquire_asking_price(fid_cond_mrkt_div_code="B", fid_input_iscd="KR2033022D33")
"""
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 = inquire_asking_price(
fid_cond_mrkt_div_code="B", # 시장 분류 코드
fid_input_iscd="KR2033022D33", # 채권종목코드
)
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')
# 결과 출력
logger.info("=== 장내채권현재가(호가) 결과 ===")
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,116 @@
# [장내채권] 기본시세 - 장내채권현재가(호가)
# Generated by KIS API Generator (Single API Mode)
# -*- coding: utf-8 -*-
"""
Created on 2025-06-19
"""
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__)
##############################################################################################
# [장내채권] 기본시세 > 장내채권현재가(호가) [국내주식-132]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-bond/v1/quotations/inquire-asking-price"
def inquire_asking_price(
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]:
"""
[장내채권] 기본시세
장내채권현재가(호가)[국내주식-132]
장내채권현재가(호가) API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 시장 분류 코드 (B 입력)
fid_input_iscd (str): 채권종목코드 (ex KR2033022D33)
tr_cont (str): 연속 거래 여부 (기본값: "")
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임 (기본값: None)
depth (int): 현재 재귀 깊이 (기본값: 0)
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: 장내채권현재가(호가) 데이터
Example:
>>> df = inquire_asking_price(fid_cond_mrkt_div_code="B", fid_input_iscd="KR2033022D33")
>>> print(df)
"""
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'B')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'B')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. 'KR2033022D33')")
raise ValueError("fid_input_iscd is required. (e.g. 'KR2033022D33')")
# 최대 재귀 깊이 체크
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 = "FHKBJ773401C0"
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 inquire_asking_price(
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,111 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-20
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from inquire_balance import inquire_balance
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [장내채권] 주문/계좌 > 장내채권 잔고조회 [국내주식-198]
##############################################################################################
COLUMN_MAPPING = {
'pdno': '상품번호',
'buy_dt': '매수일자',
'buy_sqno': '매수일련번호',
'cblc_qty': '잔고수량',
'agrx_qty': '종합과세수량',
'sprx_qty': '분리과세수량',
'exdt': '만기일',
'buy_erng_rt': '매수수익율',
'buy_unpr': '매수단가',
'buy_amt': '매수금액',
'ord_psbl_qty': '주문가능수량'
}
NUMERIC_COLUMNS = []
def main():
"""
[장내채권] 주문/계좌
장내채권 잔고조회[국내주식-198]
장내채권 잔고조회 테스트 함수
Parameters:
- cano (str): 종합계좌번호 ()
- acnt_prdt_cd (str): 계좌상품코드 ()
- inqr_cndt (str): 조회조건 (00: 전체, 01: 상품번호단위)
- pdno (str): 상품번호 (공백)
- buy_dt (str): 매수일자 (공백)
Returns:
- DataFrame: 장내채권 잔고조회 결과
Example:
>>> df = inquire_balance(cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, inqr_cndt="00", pdno="", buy_dt="")
"""
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("토큰 발급 완료")
# kis_auth 모듈에서 계좌 정보 가져오기
trenv = ka.getTREnv()
# API 호출
logger.info("API 호출 시작: 장내채권 잔고조회")
result = inquire_balance(
cano=trenv.my_acct, # 종합계좌번호
acnt_prdt_cd=trenv.my_prod, # 계좌상품코드
inqr_cndt="00", # 조회조건
pdno="", # 상품번호
buy_dt="", # 매수일자
)
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')
# 결과 출력
logger.info("=== 장내채권 잔고조회 결과 ===")
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,147 @@
# [장내채권] 주문/계좌 - 장내채권 잔고조회
# Generated by KIS API Generator (Single API Mode)
# -*- coding: utf-8 -*-
"""
Created on 2025-06-20
"""
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__)
##############################################################################################
# [장내채권] 주문/계좌 > 장내채권 잔고조회 [국내주식-198]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-bond/v1/trading/inquire-balance"
def inquire_balance(
cano: str, # 종합계좌번호
acnt_prdt_cd: str, # 계좌상품코드
inqr_cndt: str, # 조회조건
pdno: str, # 상품번호
buy_dt: str, # 매수일자
FK200: str = "", # 연속조회검색조건200
NK200: str = "", # 연속조회키200
tr_cont: str = "", # 연속 거래 여부
dataframe: Optional[pd.DataFrame] = None, # 누적 데이터프레임
depth: int = 0, # 현재 재귀 깊이
max_depth: int = 10 # 최대 재귀 깊이
) -> Optional[pd.DataFrame]:
"""
[장내채권] 주문/계좌
장내채권 잔고조회[국내주식-198]
장내채권 잔고조회 API를 호출하여 DataFrame으로 반환합니다.
Args:
cano (str): 종합계좌번호
acnt_prdt_cd (str): 계좌상품코드
inqr_cndt (str): 조회조건 (00: 전체, 01: 상품번호단위)
pdno (str): 상품번호 (공백 허용)
buy_dt (str): 매수일자 (공백 허용)
FK200 (str): 연속조회검색조건200
NK200 (str): 연속조회키200
tr_cont (str): 연속 거래 여부 (기본값: "")
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임
depth (int): 현재 재귀 깊이
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: 장내채권 잔고조회 데이터
Example:
>>> df = inquire_balance(
... cano=trenv.my_acct,
... acnt_prdt_cd=trenv.my_prod,
... inqr_cndt='00',
... pdno='',
... buy_dt='',
... )
>>> print(df)
"""
# 로깅 설정
logger = logging.getLogger(__name__)
# 필수 파라미터 검증
if not cano:
logger.error("cano is required. (e.g. '12345678')")
raise ValueError("cano is required. (e.g. '12345678')")
if not acnt_prdt_cd:
logger.error("acnt_prdt_cd is required. (e.g. '01')")
raise ValueError("acnt_prdt_cd is required. (e.g. '01')")
if not inqr_cndt:
logger.error("inqr_cndt is required. (e.g. '00')")
raise ValueError("inqr_cndt is required. (e.g. '00')")
# 최대 재귀 깊이 체크
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 = "CTSC8407R"
params = {
"CANO": cano,
"ACNT_PRDT_CD": acnt_prdt_cd,
"INQR_CNDT": inqr_cndt,
"PDNO": pdno,
"BUY_DT": buy_dt,
"CTX_AREA_FK200": FK200,
"CTX_AREA_NK200": NK200,
}
# 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
NK200 = res.getBody().ctx_area_nk200
FK200 = res.getBody().ctx_area_fk200
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return inquire_balance(
cano,
acnt_prdt_cd,
inqr_cndt,
pdno,
buy_dt,
FK200,
NK200,
"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 inquire_ccnl import inquire_ccnl
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [장내채권] 기본시세 > 장내채권현재가(체결) [국내주식-201]
##############################################################################################
COLUMN_MAPPING = {
'output1': '응답상세',
'stck_cntg_hour': '주식 체결 시간',
'bond_prpr': '채권 현재가',
'bond_prdy_vrss': '채권 전일 대비',
'prdy_vrss_sign': '전일 대비 부호',
'prdy_ctrt': '전일 대비율',
'cntg_vol': '체결 거래량',
'acml_vol': '누적 거래량'
}
NUMERIC_COLUMNS = []
def main():
"""
[장내채권] 기본시세
장내채권현재가(체결)[국내주식-201]
장내채권현재가(체결) 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (B (업종코드))
- fid_input_iscd (str): 입력종목코드 (채권종목코드(ex KR2033022D33))
Returns:
- DataFrame: 장내채권현재가(체결) 결과
Example:
>>> df = inquire_ccnl(fid_cond_mrkt_div_code="B", fid_input_iscd="KR2033022D33")
"""
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 = inquire_ccnl(
fid_cond_mrkt_div_code="B", # 조건시장분류코드
fid_input_iscd="KR103502GA34", # 입력종목코드
)
if result is None or result.empty:
logger.warning("조회된 데이터가 없습니다.")
return
# 컬럼명 출력
logger.info("사용 가능한 컬럼 목록:")
logger.info(result.columns.tolist())
# 한글 컬럼명으로 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 변환s
for col in NUMERIC_COLUMNS:
if col in result.columns:
result[col] = pd.to_numeric(result[col], errors='coerce')
# 결과 출력
logger.info("=== 장내채권현재가(체결) 결과 ===")
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 @@
# [장내채권] 기본시세 - 장내채권현재가(체결)
# Generated by KIS API Generator (Single API Mode)
# -*- coding: utf-8 -*-
"""
Created on 2025-06-19
"""
import logging
import sys
import time
from typing import Optional
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__)
##############################################################################################
# [장내채권] 기본시세 > 장내채권현재가(체결) [국내주식-201]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-bond/v1/quotations/inquire-ccnl"
def inquire_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]:
"""
[장내채권] 기본시세
장내채권현재가(체결)[국내주식-201]
장내채권현재가(체결) API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 조건시장분류코드 (예: 'B')
fid_input_iscd (str): 입력종목코드 (예: 'KR2033022D33')
tr_cont (str): 연속 거래 여부 (기본값: "")
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임 (기본값: None)
depth (int): 현재 재귀 깊이 (기본값: 0)
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: 장내채권현재가(체결) 데이터
Example:
>>> df = inquire_ccnl('B', 'KR2033022D33')
>>> print(df)
"""
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'B')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'B')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. 'KR2033022D33')")
raise ValueError("fid_input_iscd is required. (e.g. 'KR2033022D33')")
# 최대 재귀 깊이 체크
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 = "FHKBJ773403C0"
# API 요청 파라미터 설정
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 inquire_ccnl(
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,156 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-20
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from inquire_daily_ccld import inquire_daily_ccld
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [장내채권] 주문/계좌 > 장내채권 일별체결조회 [국내주식-127]
##############################################################################################
# 통합 컬럼 매핑 (모든 output에서 공통 사용)
COLUMN_MAPPING = {
'tot_ord_qty': '총주문수량',
'tot_ccld_qty_smtl': '총체결수량합계',
'tot_bond_ccld_avg_unpr': '총채권체결평균단가',
'tot_ccld_amt_smtl': '총체결금액합계',
'ord_dt': '주문일자',
'odno': '주문번호',
'orgn_odno': '원주문번호',
'ord_dvsn_name': '주문구분명',
'sll_buy_dvsn_cd_name': '매도매수구분코드명',
'shtn_pdno': '단축상품번호',
'prdt_abrv_name': '상품약어명',
'ord_qty': '주문수량',
'bond_ord_unpr': '채권주문단가',
'ord_tmd': '주문시각',
'tot_ccld_qty': '총체결수량',
'bond_avg_unpr': '채권평균단가',
'tot_ccld_amt': '총체결금액',
'loan_dt': '대출일자',
'buy_dt': '매수일자',
'samt_mket_ptci_yn_name': '소액시장참여여부명',
'sprx_psbl_yn_ifom': '분리과세가능여부알림',
'ord_mdia_dvsn_name': '주문매체구분묭',
'sll_buy_dvsn_cd': '매도매수구분코드',
'nccs_qty': '미체결수량',
'ord_gno_brno': '주문채번지점번호'
}
NUMERIC_COLUMNS = []
def main():
"""
[장내채권] 주문/계좌
장내채권 주문체결내역[국내주식-127]
장내채권 주문체결내역 테스트 함수
Parameters:
- cano (str): 종합계좌번호 (종합계좌번호)
- acnt_prdt_cd (str): 계좌상품코드 (계좌상품코드)
- inqr_strt_dt (str): 조회시작일자 (일자 ~ (1주일 이내))
- inqr_end_dt (str): 조회종료일자 (~ 일자 (조회 당일))
- sll_buy_dvsn_cd (str): 매도매수구분코드 (%(전체), 01(매도), 02(매수))
- sort_sqn_dvsn (str): 정렬순서구분 (01(주문순서), 02(주문역순))
- pdno (str): 상품번호 ()
- nccs_yn (str): 미체결여부 (N(전체), C(체결), Y(미체결))
Returns:
- Tuple[DataFrame, ...]: 장내채권 주문체결내역 결과
Example:
>>> df1, df2 = inquire_daily_ccld(cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, inqr_strt_dt="20250601", inqr_end_dt="20250630", sll_buy_dvsn_cd="%", sort_sqn_dvsn="01", pdno="", nccs_yn="N", ctx_area_nk200="", ctx_area_fk200="")
"""
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("토큰 발급 완료")
# kis_auth 모듈에서 계좌 정보 가져오기
trenv = ka.getTREnv()
# API 호출
logger.info("API 호출 시작: 장내채권 주문체결내역")
result1, result2 = inquire_daily_ccld(
cano=trenv.my_acct, # 종합계좌번호
acnt_prdt_cd=trenv.my_prod, # 계좌상품코드
inqr_strt_dt="20250601", # 조회시작일자
inqr_end_dt="20250630", # 조회종료일자
sll_buy_dvsn_cd="%", # 매도매수구분코드
sort_sqn_dvsn="01", # 정렬순서구분
pdno="", # 상품번호
nccs_yn="N", # 미체결여부
ctx_area_nk200="", # 연속조회키200
ctx_area_fk200="", # 연속조회검색조건200
)
# 결과 확인
results = [result1, result2]
if all(result is None or result.empty for result in results):
logger.warning("조회된 데이터가 없습니다.")
return
# output1 결과 처리
logger.info("=== output1 조회 ===")
if not result1.empty:
logger.info("사용 가능한 컬럼: %s", result1.columns.tolist())
# 통합 컬럼명 한글 변환 (필요한 컬럼만 자동 매핑됨)
result1 = result1.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 변환s
for col in NUMERIC_COLUMNS:
if col in result1.columns:
result1[col] = pd.to_numeric(result1[col], errors='coerce')
logger.info("output1 결과:")
print(result1)
else:
logger.info("output1 데이터가 없습니다.")
# output2 결과 처리
logger.info("=== output2 조회 ===")
if not result2.empty:
logger.info("사용 가능한 컬럼: %s", result2.columns.tolist())
# 통합 컬럼명 한글 변환 (필요한 컬럼만 자동 매핑됨)
result2 = result2.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 변환s
for col in NUMERIC_COLUMNS:
if col in result2.columns:
result2[col] = pd.to_numeric(result2[col], errors='coerce')
logger.info("output2 결과:")
print(result2)
else:
logger.info("output2 데이터가 없습니다.")
except Exception as e:
logger.error("에러 발생: %s", str(e))
raise
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,202 @@
# [장내채권] 주문/계좌 - 장내채권 주문체결내역
# Generated by KIS API Generator (Single API Mode)
# -*- coding: utf-8 -*-
"""
Created on 2025-06-20
"""
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__)
##############################################################################################
# [장내채권] 주문/계좌 > 장내채권 일별체결조회 [국내주식-127]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-bond/v1/trading/inquire-daily-ccld"
def inquire_daily_ccld(
cano: str, # 종합계좌번호
acnt_prdt_cd: str, # 계좌상품코드
inqr_strt_dt: str, # 조회시작일자
inqr_end_dt: str, # 조회종료일자
sll_buy_dvsn_cd: str, # 매도매수구분코드
sort_sqn_dvsn: str, # 정렬순서구분
pdno: str, # 상품번호
nccs_yn: str, # 미체결여부
ctx_area_nk200: str, # 연속조회키200
ctx_area_fk200: str, # 연속조회검색조건200
dataframe1: Optional[pd.DataFrame] = None, # 누적 데이터프레임 (output1)
dataframe2: Optional[pd.DataFrame] = None, # 누적 데이터프레임 (output2)
tr_cont: str = "",
depth: int = 0,
max_depth: int = 10
) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""
[장내채권] 주문/계좌
장내채권 주문체결내역[국내주식-127]
장내채권 주문체결내역 API를 호출하여 DataFrame으로 반환합니다.
Args:
cano (str): 종합계좌번호
acnt_prdt_cd (str): 계좌상품코드
inqr_strt_dt (str): 조회시작일자 (1주일 이내)
inqr_end_dt (str): 조회종료일자 (조회 당일)
sll_buy_dvsn_cd (str): 매도매수구분코드 (%(전체), 01(매도), 02(매수))
sort_sqn_dvsn (str): 정렬순서구분 (01(주문순서), 02(주문역순))
pdno (str): 상품번호
nccs_yn (str): 미체결여부 (N(전체), C(체결), Y(미체결))
ctx_area_nk200 (str): 연속조회키200
ctx_area_fk200 (str): 연속조회검색조건200
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]: 장내채권 주문체결내역 데이터
Example:
>>> df1, df2 = inquire_daily_ccld(
... cano=trenv.my_acct,
... acnt_prdt_cd=trenv.my_prod,
... inqr_strt_dt='20230101',
... inqr_end_dt='20230107',
... sll_buy_dvsn_cd='01',
... sort_sqn_dvsn='01',
... pdno='000000000001',
... nccs_yn='N',
... ctx_area_nk200='',
... ctx_area_fk200=''
... )
>>> print(df1)
>>> print(df2)
"""
# 필수 파라미터 검증
if not cano:
logger.error("cano is required. (e.g. '12345678')")
raise ValueError("cano is required. (e.g. '12345678')")
if not acnt_prdt_cd:
logger.error("acnt_prdt_cd is required. (e.g. '01')")
raise ValueError("acnt_prdt_cd is required. (e.g. '01')")
if not inqr_strt_dt:
logger.error("inqr_strt_dt is required. (e.g. '20230101')")
raise ValueError("inqr_strt_dt is required. (e.g. '20230101')")
if not inqr_end_dt:
logger.error("inqr_end_dt is required. (e.g. '20230107')")
raise ValueError("inqr_end_dt is required. (e.g. '20230107')")
if not sll_buy_dvsn_cd in ["%", "01", "02"]:
logger.error("sll_buy_dvsn_cd is required. (e.g. '01')")
raise ValueError("sll_buy_dvsn_cd is required. (e.g. '01')")
if not sort_sqn_dvsn in ["01", "02"]:
logger.error("sort_sqn_dvsn is required. (e.g. '01')")
raise ValueError("sort_sqn_dvsn is required. (e.g. '01')")
if not nccs_yn in ["N", "C", "Y"]:
logger.error("nccs_yn is required. (e.g. 'N')")
raise ValueError("nccs_yn is required. (e.g. 'N')")
# 최대 재귀 깊이 체크
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 = "CTSC8013R"
params = {
"CANO": cano,
"ACNT_PRDT_CD": acnt_prdt_cd,
"INQR_STRT_DT": inqr_strt_dt,
"INQR_END_DT": inqr_end_dt,
"SLL_BUY_DVSN_CD": sll_buy_dvsn_cd,
"SORT_SQN_DVSN": sort_sqn_dvsn,
"PDNO": pdno,
"NCCS_YN": nccs_yn,
"CTX_AREA_NK200": ctx_area_nk200,
"CTX_AREA_FK200": ctx_area_fk200,
}
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:
# output1은 단일 객체, output2는 배열일 수 있음
if isinstance(output_data, list):
current_data1 = pd.DataFrame(output_data)
else:
# 단일 객체인 경우 리스트로 감싸서 DataFrame 생성
current_data1 = pd.DataFrame([output_data])
if dataframe1 is not None:
dataframe1 = pd.concat([dataframe1, current_data1], ignore_index=True)
else:
dataframe1 = current_data1
else:
if dataframe1 is None:
dataframe1 = pd.DataFrame()
else:
if dataframe1 is None:
dataframe1 = pd.DataFrame()
# output2 처리
if hasattr(res.getBody(), 'output2'):
output_data = res.getBody().output2
if output_data:
# output1은 단일 객체, output2는 배열일 수 있음
if isinstance(output_data, list):
current_data2 = pd.DataFrame(output_data)
else:
# 단일 객체인 경우 리스트로 감싸서 DataFrame 생성
current_data2 = pd.DataFrame([output_data])
if dataframe2 is not None:
dataframe2 = pd.concat([dataframe2, current_data2], ignore_index=True)
else:
dataframe2 = current_data2
else:
if dataframe2 is None:
dataframe2 = pd.DataFrame()
else:
if dataframe2 is None:
dataframe2 = pd.DataFrame()
tr_cont = res.getHeader().tr_cont
ctx_area_nk200 = res.getBody().ctx_area_nk200
ctx_area_fk200 = res.getBody().ctx_area_fk200
if tr_cont in ["M", "F"]:
logger.info("Calling next page...")
ka.smart_sleep()
return inquire_daily_ccld(
cano,
acnt_prdt_cd,
inqr_strt_dt,
inqr_end_dt,
sll_buy_dvsn_cd,
sort_sqn_dvsn,
pdno,
nccs_yn,
ctx_area_nk200,
ctx_area_fk200,
"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,95 @@
# -*- 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 inquire_daily_itemchartprice import inquire_daily_itemchartprice
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [장내채권] 기본시세 > 장내채권 기간별시세(일) [국내주식-159]
##############################################################################################
COLUMN_MAPPING = {
'stck_bsop_date': '주식영업일자',
'bond_oprc': '채권시가2',
'bond_hgpr': '채권고가',
'bond_lwpr': '채권저가',
'bond_prpr': '채권현재가',
'acml_vol': '누적거래량'
}
NUMERIC_COLUMNS = []
def main():
"""
[장내채권] 기본시세
장내채권 기간별시세(일)[국내주식-159]
장내채권 기간별시세(일) 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건 시장 구분 코드 (Unique key(B))
- fid_input_iscd (str): 입력 종목코드 (채권종목코드)
Returns:
- DataFrame: 장내채권 기간별시세(일) 결과
Example:
>>> df = inquire_daily_itemchartprice(fid_cond_mrkt_div_code="B", fid_input_iscd="KR2033022D33")
"""
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 = inquire_daily_itemchartprice(
fid_cond_mrkt_div_code="B", # 조건 시장 구분 코드
fid_input_iscd="KR103502GA34", # 입력 종목코드
)
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')
# 결과 출력
logger.info("=== 장내채권 기간별시세(일) 결과 ===")
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 @@
# [장내채권] 기본시세 - 장내채권 기간별시세(일)
# Generated by KIS API Generator (Single API Mode)
# -*- coding: utf-8 -*-
"""
Created on 2025-06-19
"""
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__)
##############################################################################################
# [장내채권] 기본시세 > 장내채권 기간별시세(일) [국내주식-159]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-bond/v1/quotations/inquire-daily-itemchartprice"
def inquire_daily_itemchartprice(
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]:
"""
[장내채권] 기본시세
장내채권 기간별시세(일)[국내주식-159]
장내채권 기간별시세(일) 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]: 장내채권 기간별시세(일) 데이터
Example:
>>> df = inquire_daily_itemchartprice("B", "KR2033022D33")
>>> print(df)
"""
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'B')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'B')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. 'KR2033022D33')")
raise ValueError("fid_input_iscd is required. (e.g. 'KR2033022D33')")
# 최대 재귀 깊이 체크
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 = "FHKBJ773701C0"
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 inquire_daily_itemchartprice(
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 inquire_daily_price import inquire_daily_price
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [장내채권] 기본시세 > 장내채권현재가(일별) [국내주식-202]
##############################################################################################
COLUMN_MAPPING = {
'output1': '응답상세',
'stck_bsop_date': '주식영업일자',
'bond_prpr': '채권현재가',
'bond_prdy_vrss': '채권전일대비',
'prdy_vrss_sign': '전일대비부호',
'prdy_ctrt': '전일대비율',
'acml_vol': '누적거래량',
'bond_oprc': '채권시가2',
'bond_hgpr': '채권고가',
'bond_lwpr': '채권저가'
}
NUMERIC_COLUMNS = []
def main():
"""
[장내채권] 기본시세
장내채권현재가(일별)[국내주식-202]
장내채권현재가(일별) 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (B (업종코드))
- fid_input_iscd (str): 입력종목코드 (채권종목코드(ex KR2033022D33))
Returns:
- DataFrame: 장내채권현재가(일별) 결과
Example:
>>> df = inquire_daily_price(fid_cond_mrkt_div_code="B", fid_input_iscd="KR2033022D33")
"""
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 = inquire_daily_price(
fid_cond_mrkt_div_code="B", # 조건시장분류코드
fid_input_iscd="KR6095572D81", # 입력종목코드
)
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')
# 결과 출력
logger.info("=== 장내채권현재가(일별) 결과 ===")
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 @@
# [장내채권] 기본시세 - 장내채권현재가(일별)
# Generated by KIS API Generator (Single API Mode)
# -*- coding: utf-8 -*-
"""
Created on 2025-06-19
"""
import logging
import sys
import time
from typing import Optional
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__)
##############################################################################################
# [장내채권] 기본시세 > 장내채권현재가(일별) [국내주식-202]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-bond/v1/quotations/inquire-daily-price"
def inquire_daily_price(
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]:
"""
[장내채권] 기본시세
장내채권현재가(일별)[국내주식-202]
장내채권현재가(일별) API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 조건시장분류코드 (예: 'B')
fid_input_iscd (str): 입력종목코드 (예: 'KR2033022D33')
tr_cont (str): 연속 거래 여부 (기본값: "")
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임 (기본값: None)
depth (int): 현재 재귀 깊이 (기본값: 0)
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: 장내채권현재가(일별) 데이터
Example:
>>> df = inquire_daily_price('B', 'KR2033022D33')
>>> print(df)
"""
# 로깅 설정
logger = logging.getLogger(__name__)
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'B')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'B')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. 'KR2033022D33')")
raise ValueError("fid_input_iscd is required. (e.g. 'KR2033022D33')")
# 최대 재귀 깊이 체크
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 = "FHKBJ773404C0"
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 inquire_daily_price(
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-19
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from inquire_price import inquire_price
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [장내채권] 기본시세 > 장내채권현재가(시세) [국내주식-200]
##############################################################################################
COLUMN_MAPPING = {
'stnd_iscd': '표준종목코드',
'hts_kor_isnm': 'HTS한글종목명',
'bond_prpr': '채권현재가',
'prdy_vrss_sign': '전일대비부호',
'bond_prdy_vrss': '채권전일대비',
'prdy_ctrt': '전일대비율',
'acml_vol': '누적거래량',
'bond_prdy_clpr': '채권전일종가',
'bond_oprc': '채권시가2',
'bond_hgpr': '채권고가',
'bond_lwpr': '채권저가',
'ernn_rate': '수익비율',
'oprc_ert': '시가2수익률',
'hgpr_ert': '최고가수익률',
'lwpr_ert': '최저가수익률',
'bond_mxpr': '채권상한가',
'bond_llam': '채권하한가'
}
NUMERIC_COLUMNS = []
def main():
"""
[장내채권] 기본시세
장내채권현재가(시세)[국내주식-200]
장내채권현재가(시세) 테스트 함수
Parameters:
- fid_cond_mrkt_div_code (str): 조건시장분류코드 (B (업종코드))
- fid_input_iscd (str): 입력종목코드 (채권종목코드(ex KR2033022D33))
Returns:
- DataFrame: 장내채권현재가(시세) 결과
Example:
>>> df = inquire_price(fid_cond_mrkt_div_code="B", fid_input_iscd="KR2033022D33")
"""
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 = inquire_price(
fid_cond_mrkt_div_code="B", # 조건시장분류코드
fid_input_iscd="KR2033022D33", # 입력종목코드
)
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')
# 결과 출력
logger.info("=== 장내채권현재가(시세) 결과 ===")
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 @@
# [장내채권] 기본시세 - 장내채권현재가(시세)
# Generated by KIS API Generator (Single API Mode)
# -*- coding: utf-8 -*-
"""
Created on 2025-06-19
"""
import logging
import sys
import time
from typing import Optional
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__)
##############################################################################################
# [장내채권] 기본시세 > 장내채권현재가(시세) [국내주식-200]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-bond/v1/quotations/inquire-price"
def inquire_price(
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]:
"""
[장내채권] 기본시세
장내채권현재가(시세)[국내주식-200]
장내채권현재가(시세) API를 호출하여 DataFrame으로 반환합니다.
Args:
fid_cond_mrkt_div_code (str): 조건시장분류코드 (예: 'B')
fid_input_iscd (str): 입력종목코드 (예: 'KR2033022D33')
tr_cont (str): 연속 거래 여부 (기본값: "")
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임 (기본값: None)
depth (int): 현재 재귀 깊이 (기본값: 0)
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: 장내채권현재가(시세) 데이터
Example:
>>> df = inquire_price('B', 'KR2033022D33')
>>> print(df)
"""
# 필수 파라미터 검증
if not fid_cond_mrkt_div_code:
logger.error("fid_cond_mrkt_div_code is required. (e.g. 'B')")
raise ValueError("fid_cond_mrkt_div_code is required. (e.g. 'B')")
if not fid_input_iscd:
logger.error("fid_input_iscd is required. (e.g. 'KR2033022D33')")
raise ValueError("fid_input_iscd is required. (e.g. 'KR2033022D33')")
# 최대 재귀 깊이 체크
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 = "FHKBJ773400C0"
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 inquire_price(
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,104 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-20
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from inquire_psbl_order import inquire_psbl_order
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [장내채권] 주문/계좌 > 장내채권 매수가능조회 [국내주식-199]
##############################################################################################
COLUMN_MAPPING = {
'ord_psbl_cash': '주문가능현금',
'ord_psbl_sbst': '주문가능대용',
'ruse_psbl_amt': '재사용가능금액',
'bond_ord_unpr2': '채권주문단가2',
'buy_psbl_amt': '매수가능금액',
'buy_psbl_qty': '매수가능수량',
'cma_evlu_amt': 'CMA평가금액'
}
NUMERIC_COLUMNS = []
def main():
"""
[장내채권] 주문/계좌
장내채권 매수가능조회[국내주식-199]
장내채권 매수가능조회 테스트 함수
Parameters:
- cano (str): 종합계좌번호
- acnt_prdt_cd (str): 계좌상품코드
- pdno (str): 채권종목코드(ex KR2033022D33)
- bond_ord_unpr (str): 채권주문단가
Returns:
- DataFrame: 장내채권 매수가능조회 결과
Example:
>>> df = inquire_psbl_order(cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, pdno="KR2033022D33", bond_ord_unpr="1000")
"""
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("토큰 발급 완료")
# kis_auth 모듈에서 계좌 정보 가져오기
trenv = ka.getTREnv()
# API 호출
logger.info("API 호출 시작: 장내채권 매수가능조회")
result = inquire_psbl_order(
cano=trenv.my_acct, # 종합계좌번호
acnt_prdt_cd=trenv.my_prod, # 계좌상품코드
pdno="KR2033022D33", # 채권종목코드(ex KR2033022D33)
bond_ord_unpr="1000", # 채권주문단가
)
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')
# 결과 출력
logger.info("=== 장내채권 매수가능조회 결과 ===")
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,132 @@
# [장내채권] 주문/계좌 - 장내채권 매수가능조회
# Generated by KIS API Generator (Single API Mode)
# -*- coding: utf-8 -*-
"""
Created on 2025-06-20
"""
import logging
import sys
import time
from typing import Optional
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__)
##############################################################################################
# [장내채권] 주문/계좌 > 장내채권 매수가능조회 [국내주식-199]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-bond/v1/trading/inquire-psbl-order"
def inquire_psbl_order(
cano: str, # 종합계좌번호
acnt_prdt_cd: str, # 계좌상품코드
pdno: str, # 상품번호
bond_ord_unpr: str, # 채권주문단가
tr_cont: str = "", # 연속 거래 여부
dataframe: Optional[pd.DataFrame] = None, # 누적 데이터프레임
depth: int = 0, # 현재 재귀 깊이
max_depth: int = 10 # 최대 재귀 깊이
) -> Optional[pd.DataFrame]:
"""
[장내채권] 주문/계좌
장내채권 매수가능조회[국내주식-199]
장내채권 매수가능조회 API를 호출하여 DataFrame으로 반환합니다.
Args:
cano (str): 종합계좌번호 (필수)
acnt_prdt_cd (str): 계좌상품코드 (필수)
pdno (str): 채권종목코드(ex KR2033022D33)
bond_ord_unpr (str): 채권주문단가 (필수)
tr_cont (str): 연속 거래 여부 (기본값: "")
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임
depth (int): 현재 재귀 깊이
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: 장내채권 매수가능조회 데이터
Example:
>>> df = inquire_psbl_order("12345678", "01", "KR2033022D33", "1000")
>>> print(df)
"""
# 필수 파라미터 검증
if not cano:
logger.error("cano is required. (e.g. '1234567890')")
raise ValueError("cano is required. (e.g. '1234567890')")
if not acnt_prdt_cd:
logger.error("acnt_prdt_cd is required. (e.g. '01')")
raise ValueError("acnt_prdt_cd is required. (e.g. '01')")
if not pdno:
logger.error("pdno is required. (e.g. 'KR2033022D33')")
raise ValueError("pdno is required. (e.g. 'KR2033022D33')")
if not bond_ord_unpr:
logger.error("bond_ord_unpr is required. (e.g. '1000')")
raise ValueError("bond_ord_unpr is required. (e.g. '1000')")
# 최대 재귀 깊이 체크
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 = "TTTC8910R"
params = {
"CANO": cano,
"ACNT_PRDT_CD": acnt_prdt_cd,
"PDNO": pdno,
"BOND_ORD_UNPR": bond_ord_unpr,
}
# 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 inquire_psbl_order(
cano,
acnt_prdt_cd,
pdno,
bond_ord_unpr,
"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,114 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-20
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from inquire_psbl_rvsecncl import inquire_psbl_rvsecncl
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [장내채권] 주문/계좌 > 채권정정취소가능주문조회 [국내주식-126]
##############################################################################################
COLUMN_MAPPING = {
'odno': '주문번호',
'pdno': '상품번호',
'rvse_cncl_dvsn_name': '정정취소구분명',
'ord_qty': '주문수량',
'bond_ord_unpr': '채권주문단가',
'ord_tmd': '주문시각',
'tot_ccld_qty': '총체결수량',
'tot_ccld_amt': '총체결금액',
'ord_psbl_qty': '주문가능수량',
'orgn_odno': '원주문번호',
'sll_buy_dvsn_cd': '매도매수구분코드',
'ord_dvsn_cd': '주문구분코드',
'mgco_aptm_odno': '운용사지정주문번호',
'samt_mket_ptci_yn': '소액시장참여여부'
}
NUMERIC_COLUMNS = []
def main():
"""
[장내채권] 주문/계좌
채권정정취소가능주문조회[국내주식-126]
채권정정취소가능주문조회 테스트 함수
Parameters:
- cano (str): 종합계좌번호 ()
- acnt_prdt_cd (str): 계좌상품코드 ()
- ord_dt (str): 주문일자 ()
- odno (str): 주문번호 ()
- ctx_area_fk200 (str): 연속조회검색조건200 ()
- ctx_area_nk200 (str): 연속조회키200 ()
Returns:
- DataFrame: 채권정정취소가능주문조회 결과
Example:
>>> df = inquire_psbl_rvsecncl(cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, ord_dt="20250601", odno="", ctx_area_fk200="", ctx_area_nk200="")
"""
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("토큰 발급 완료")
# kis_auth 모듈에서 계좌 정보 가져오기
trenv = ka.getTREnv()
# API 호출
logger.info("API 호출 시작: 채권정정취소가능주문조회")
result = inquire_psbl_rvsecncl(
cano=trenv.my_acct, # 종합계좌번호
acnt_prdt_cd=trenv.my_prod, # 계좌상품코드
ord_dt="", # 주문일자
odno="", # 주문번호
ctx_area_fk200="", # 연속조회검색조건200
ctx_area_nk200="", # 연속조회키200
)
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')
# 결과 출력
logger.info("=== 채권정정취소가능주문조회 결과 ===")
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,136 @@
# [장내채권] 주문/계좌 - 채권정정취소가능주문조회
# Generated by KIS API Generator (Single API Mode)
# -*- coding: utf-8 -*-
"""
Created on 2025-06-20
"""
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__)
##############################################################################################
# [장내채권] 주문/계좌 > 채권정정취소가능주문조회 [국내주식-126]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-bond/v1/trading/inquire-psbl-rvsecncl"
def inquire_psbl_rvsecncl(
cano: str, # 종합계좌번호
acnt_prdt_cd: str, # 계좌상품코드
ord_dt: str, # 주문일자
odno: str, # 주문번호
ctx_area_fk200: str, # 연속조회검색조건200
ctx_area_nk200: str, # 연속조회키200
tr_cont: str = "", # 연속 거래 여부
dataframe: Optional[pd.DataFrame] = None, # 누적 데이터프레임
depth: int = 0, # 현재 재귀 깊이
max_depth: int = 10 # 최대 재귀 깊이
) -> Optional[pd.DataFrame]:
"""
[장내채권] 주문/계좌
채권정정취소가능주문조회[국내주식-126]
채권정정취소가능주문조회 API를 호출하여 DataFrame으로 반환합니다.
Args:
cano (str): 종합계좌번호 (예: '12345678')
acnt_prdt_cd (str): 계좌상품코드 (예: '01')
ord_dt (str): 주문일자 (예: '20230101')
odno (str): 주문번호 (예: '0000000001')
ctx_area_fk200 (str): 연속조회검색조건200 (예: '조건값')
ctx_area_nk200 (str): 연속조회키200 (예: '키값')
tr_cont (str): 연속 거래 여부 (기본값: "")
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임
depth (int): 현재 재귀 깊이
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: 채권정정취소가능주문조회 데이터
Example:
>>> df = inquire_psbl_rvsecncl(
... cano=trenv.my_acct,
... acnt_prdt_cd=trenv.my_prod,
... ord_dt='20230101',
... odno='0000000001',
... ctx_area_fk200='조건값',
... ctx_area_nk200='키값'
... )
>>> print(df)
"""
# 필수 파라미터 검증
if not cano:
logger.error("cano is required. (e.g. '12345678')")
raise ValueError("cano is required. (e.g. '12345678')")
if not acnt_prdt_cd:
logger.error("acnt_prdt_cd is required. (e.g. '01')")
raise ValueError("acnt_prdt_cd is required. (e.g. '01')")
# 최대 재귀 깊이 체크
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 = "CTSC8035R"
params = {
"CANO": cano,
"ACNT_PRDT_CD": acnt_prdt_cd,
"ORD_DT": ord_dt,
"ODNO": odno,
"CTX_AREA_FK200": ctx_area_fk200,
"CTX_AREA_NK200": ctx_area_nk200,
}
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
ctx_area_nk200 = res.getBody().ctx_area_nk200
ctx_area_fk200 = res.getBody().ctx_area_fk200
if tr_cont == "M":
logger.info("Calling next page...")
ka.smart_sleep()
return inquire_psbl_rvsecncl(
cano,
acnt_prdt_cd,
ord_dt,
odno,
ctx_area_fk200,
ctx_area_nk200,
"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,176 @@
# -*- 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 issue_info import issue_info
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [장내채권] 기본시세 > 장내채권 발행정보 [국내주식-156]
##############################################################################################
COLUMN_MAPPING = {
'pdno': '상품번호',
'prdt_type_cd': '상품유형코드',
'prdt_name': '상품명',
'prdt_eng_name': '상품영문명',
'ivst_heed_prdt_yn': '투자유의상품여부',
'exts_yn': '연장여부',
'bond_clsf_cd': '채권분류코드',
'bond_clsf_kor_name': '채권분류한글명',
'papr': '액면가',
'int_mned_dvsn_cd': '이자월말구분코드',
'rvnu_shap_cd': '매출형태코드',
'issu_amt': '발행금액',
'lstg_rmnd': '상장잔액',
'int_dfrm_mcnt': '이자지급개월수',
'bond_int_dfrm_mthd_cd': '채권이자지급방법코드',
'splt_rdpt_rcnt': '분할상환횟수',
'prca_dfmt_term_mcnt': '원금거치기간개월수',
'int_anap_dvsn_cd': '이자선후급구분코드',
'bond_rght_dvsn_cd': '채권권리구분코드',
'prdt_pclc_text': '상품특성내용',
'prdt_abrv_name': '상품약어명',
'prdt_eng_abrv_name': '상품영문약어명',
'sprx_psbl_yn': '분리과세가능여부',
'pbff_pplc_ofrg_mthd_cd': '공모사모모집방법코드',
'cmco_cd': '주간사코드',
'issu_istt_cd': '발행기관코드',
'issu_istt_name': '발행기관명',
'pnia_dfrm_agcy_istt_cd': '원리금지급대행기관코드',
'dsct_ec_rt': '할인할증율',
'srfc_inrt': '표면이율',
'expd_rdpt_rt': '만기상환율',
'expd_asrc_erng_rt': '만기보장수익율',
'bond_grte_istt_name': '채권보증기관명',
'int_dfrm_day_type_cd': '이자지급일유형코드',
'ksd_int_calc_unit_cd': '증권예탁결제원이자계산단위코드',
'int_wunt_uder_prcs_dvsn_cd': '이자원화단위미만처리구분코드',
'rvnu_dt': '매출일자',
'issu_dt': '발행일자',
'lstg_dt': '상장일자',
'expd_dt': '만기일자',
'rdpt_dt': '상환일자',
'sbst_pric': '대용가격',
'rgbf_int_dfrm_dt': '직전이자지급일자',
'nxtm_int_dfrm_dt': '차기이자지급일자',
'frst_int_dfrm_dt': '최초이자지급일자',
'ecis_pric': '행사가격',
'rght_stck_std_pdno': '권리주식표준상품번호',
'ecis_opng_dt': '행사개시일자',
'ecis_end_dt': '행사종료일자',
'bond_rvnu_mthd_cd': '채권매출방법코드',
'oprt_stfno': '조작직원번호',
'oprt_stff_name': '조작직원명',
'rgbf_int_dfrm_wday': '직전이자지급요일',
'nxtm_int_dfrm_wday': '차기이자지급요일',
'kis_crdt_grad_text': '한국신용평가신용등급내용',
'kbp_crdt_grad_text': '한국채권평가신용등급내용',
'nice_crdt_grad_text': '한국신용정보신용등급내용',
'fnp_crdt_grad_text': '에프앤자산평가신용등급내용',
'dpsi_psbl_yn': '예탁가능여부',
'pnia_int_calc_unpr': '원리금이자계산단가',
'prcm_idx_bond_yn': '물가지수채권여부',
'expd_exts_srdp_rcnt': '만기연장분할상환횟수',
'expd_exts_srdp_rt': '만기연장분할상환율',
'loan_psbl_yn': '대출가능여부',
'grte_dvsn_cd': '보증구분코드',
'fnrr_rank_dvsn_cd': '선후순위구분코드',
'krx_lstg_abol_dvsn_cd': '한국거래소상장폐지구분코드',
'asst_rqdi_dvsn_cd': '자산유동화구분코드',
'opcb_dvsn_cd': '옵션부사채구분코드',
'crfd_item_yn': '크라우드펀딩종목여부',
'crfd_item_rstc_cclc_dt': '크라우드펀딩종목제한해지일자',
'bond_nmpr_unit_pric': '채권호가단위가격',
'ivst_heed_bond_dvsn_name': '투자유의채권구분명',
'add_erng_rt': '추가수익율',
'add_erng_rt_aply_dt': '추가수익율적용일자',
'bond_tr_stop_dvsn_cd': '채권거래정지구분코드',
'ivst_heed_bond_dvsn_cd': '투자유의채권구분코드',
'pclr_cndt_text': '특이조건내용',
'hbbd_yn': '하이브리드채권여부',
'cdtl_cptl_scty_type_cd': '조건부자본증권유형코드',
'elec_scty_yn': '전자증권여부',
'sq1_clop_ecis_opng_dt': '1차콜옵션행사개시일자',
'frst_erlm_stfno': '최초등록직원번호',
'frst_erlm_dt': '최초등록일자',
'frst_erlm_tmd': '최초등록시각',
'tlg_rcvg_dtl_dtime': '전문수신상세일시'
}
NUMERIC_COLUMNS = []
def main():
"""
[장내채권] 기본시세
장내채권 발행정보[국내주식-156]
장내채권 발행정보 테스트 함수
Parameters:
- pdno (str): 사용자권한정보 (채권 종목번호(ex. KR6449111CB8))
- prdt_type_cd (str): 거래소코드 (Unique key(302))
Returns:
- DataFrame: 장내채권 발행정보 결과
Example:
>>> df = issue_info(pdno="KR6449111CB8", prdt_type_cd="302")
"""
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 = issue_info(
pdno="KR6449111CB8", # 사용자권한정보
prdt_type_cd="302", # 거래소코드
)
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')
# 결과 출력
logger.info("=== 장내채권 발행정보 결과 ===")
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 @@
# [장내채권] 기본시세 - 장내채권 발행정보
# Generated by KIS API Generator (Single API Mode)
# -*- 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__)
##############################################################################################
# [장내채권] 기본시세 > 장내채권 발행정보 [국내주식-156]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-bond/v1/quotations/issue-info"
def issue_info(
pdno: str, # 사용자권한정보
prdt_type_cd: str, # 거래소코드
tr_cont: str = "", # 연속 거래 여부
dataframe: Optional[pd.DataFrame] = None, # 누적 데이터프레임
depth: int = 0, # 현재 재귀 깊이
max_depth: int = 10 # 최대 재귀 깊이
) -> Optional[pd.DataFrame]:
"""
[장내채권] 기본시세
장내채권 발행정보[국내주식-156]
장내채권 발행정보 API를 호출하여 DataFrame으로 반환합니다.
Args:
pdno (str): 채권 종목번호(ex. KR6449111CB8)
prdt_type_cd (str): Unique key(302)
tr_cont (str): 연속 거래 여부
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임
depth (int): 현재 재귀 깊이
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: 장내채권 발행정보 데이터
Example:
>>> df = issue_info("KR6449111CB8", "302")
>>> print(df)
"""
# 로깅 설정
logger = logging.getLogger(__name__)
# 필수 파라미터 검증
if not pdno:
logger.error("pdno is required. (e.g. 'KR6449111CB8')")
raise ValueError("pdno is required. (e.g. 'KR6449111CB8')")
if not prdt_type_cd:
logger.error("prdt_type_cd is required. (e.g. '302')")
raise ValueError("prdt_type_cd is required. (e.g. '302')")
# 최대 재귀 깊이 체크
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 = "CTPF1101R"
# 요청 파라미터 설정
params = {
"PDNO": pdno,
"PRDT_TYPE_CD": prdt_type_cd,
}
# 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 issue_info(
pdno,
prdt_type_cd,
"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,115 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-20
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from order_rvsecncl import order_rvsecncl
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [장내채권] 주문/계좌 > 장내채권 정정취소주문 [국내주식-125]
##############################################################################################
COLUMN_MAPPING = {
'KRX_FWDG_ORD_ORGNO': '한국거래소전송주문조직번호',
'ODNO': '주문번호',
'ORD_TMD': '주문시각'
}
NUMERIC_COLUMNS = []
def main():
"""
[장내채권] 주문/계좌
장내채권 정정취소주문[국내주식-125]
장내채권 정정취소주문 테스트 함수
Parameters:
cano (str): 종합계좌번호
acnt_prdt_cd (str): 계좌상품코드
pdno (str): 상품번호
orgn_odno (str): 원주문번호
ord_qty2 (str): 주문수량2
bond_ord_unpr (str): 채권주문단가
qty_all_ord_yn (str): 잔량전부주문여부
rvse_cncl_dvsn_cd (str): 정정취소구분코드
mgco_aptm_odno (str): 운용사지정주문번호
ord_svr_dvsn_cd (str): 주문서버구분코드
ctac_tlno (str): 연락전화번호
Returns:
- DataFrame: 장내채권 정정취소주문 결과
Example:
>>> df = main()
>>> print(df)
"""
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("토큰 발급 완료")
# kis_auth 모듈에서 계좌 정보 가져오기
trenv = ka.getTREnv()
# API 호출
logger.info("API 호출 시작: 장내채권 정정취소주문")
result = order_rvsecncl(
cano=trenv.my_acct,
acnt_prdt_cd=trenv.my_prod,
pdno="KR6095572D81",
orgn_odno="0004357900", # 실제 테스트 시 유효한 원주문번호로 변경해야 합니다.
ord_qty2="1", # 정정/취소 수량
bond_ord_unpr="10470", # 정정 단가
qty_all_ord_yn="Y", # 잔량 전부 주문 여부
rvse_cncl_dvsn_cd="01", # 01: 정정, 02: 취소
mgco_aptm_odno="",
ord_svr_dvsn_cd="0",
ctac_tlno="",
)
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')
# 결과 출력
logger.info("=== 장내채권 정정취소주문 결과 ===")
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,113 @@
# [장내채권] 주문/계좌 - 장내채권 정정취소주문
# Generated by KIS API Generator (Single API Mode)
# -*- coding: utf-8 -*-
"""
Created on 2025-06-20
"""
import logging
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__)
##############################################################################################
# [장내채권] 주문/계좌 > 장내채권 정정취소주문 [국내주식-125]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-bond/v1/trading/order-rvsecncl"
def order_rvsecncl(
cano: str,
acnt_prdt_cd: str,
pdno: str,
orgn_odno: str,
ord_qty2: str,
bond_ord_unpr: str,
qty_all_ord_yn: str,
rvse_cncl_dvsn_cd: str,
mgco_aptm_odno: str = "",
ord_svr_dvsn_cd: str = "0",
ctac_tlno: str = ""
) -> Optional[pd.DataFrame]:
"""
[장내채권] 주문/계좌
장내채권 정정취소주문[국내주식-125]
장내채권 정정취소주문 API를 호출하여 DataFrame으로 반환합니다.
Args:
cano (str): 종합계좌번호
acnt_prdt_cd (str): 계좌상품코드
pdno (str): 상품번호
orgn_odno (str): 원주문번호
ord_qty2 (str): 주문수량2
bond_ord_unpr (str): 채권주문단가
qty_all_ord_yn (str): 잔량전부주문여부
rvse_cncl_dvsn_cd (str): 정정취소구분코드
mgco_aptm_odno (str, optional): 운용사지정주문번호. Defaults to "".
ord_svr_dvsn_cd (str, optional): 주문서버구분코드. Defaults to "0".
ctac_tlno (str, optional): 연락전화번호. Defaults to "".
Returns:
Optional[pd.DataFrame]: 장내채권 정정취소주문 데이터
Example:
>>> df = order_rvsecncl(
... cano=trenv.my_acct,
... acnt_prdt_cd=trenv.my_prod,
... pdno="KR6095572D81",
... orgn_odno="0000015402",
... ord_qty2="2",
... bond_ord_unpr="10460",
... qty_all_ord_yn="Y",
... rvse_cncl_dvsn_cd="01"
... )
>>> print(df)
"""
tr_id = "TTTC0953U"
params = {
"CANO": cano,
"ACNT_PRDT_CD": acnt_prdt_cd,
"PDNO": pdno,
"ORGN_ODNO": orgn_odno,
"ORD_QTY2": ord_qty2,
"BOND_ORD_UNPR": bond_ord_unpr,
"QTY_ALL_ORD_YN": qty_all_ord_yn,
"RVSE_CNCL_DVSN_CD": rvse_cncl_dvsn_cd,
"MGCO_APTM_ODNO": mgco_aptm_odno,
"ORD_SVR_DVSN_CD": ord_svr_dvsn_cd,
"CTAC_TLNO": ctac_tlno
}
res = ka._url_fetch(api_url=API_URL,
ptr_id=tr_id,
tr_cont="",
params=params,
postFlag=True
)
if res.isOK():
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
dataframe = pd.DataFrame(output_data)
else:
dataframe = pd.DataFrame()
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,171 @@
# -*- 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 search_bond_info import search_bond_info
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [장내채권] 기본시세 > 장내채권 기본조회 [국내주식-129]
##############################################################################################
COLUMN_MAPPING = {
'pdno': '상품번호',
'prdt_type_cd': '상품유형코드',
'ksd_bond_item_name': '증권예탁결제원채권종목명',
'ksd_bond_item_eng_name': '증권예탁결제원채권종목영문명',
'ksd_bond_lstg_type_cd': '증권예탁결제원채권상장유형코드',
'ksd_ofrg_dvsn_cd': '증권예탁결제원모집구분코드',
'ksd_bond_int_dfrm_dvsn_cd': '증권예탁결제원채권이자지급구분',
'issu_dt': '발행일자',
'rdpt_dt': '상환일자',
'rvnu_dt': '매출일자',
'iso_crcy_cd': '통화코드',
'mdwy_rdpt_dt': '중도상환일자',
'ksd_rcvg_bond_dsct_rt': '증권예탁결제원수신채권할인율',
'ksd_rcvg_bond_srfc_inrt': '증권예탁결제원수신채권표면이율',
'bond_expd_rdpt_rt': '채권만기상환율',
'ksd_prca_rdpt_mthd_cd': '증권예탁결제원원금상환방법코드',
'int_caltm_mcnt': '이자계산기간개월수',
'ksd_int_calc_unit_cd': '증권예탁결제원이자계산단위코드',
'uval_cut_dvsn_cd': '절상절사구분코드',
'uval_cut_dcpt_dgit': '절상절사소수점자릿수',
'ksd_dydv_caltm_aply_dvsn_cd': '증권예탁결제원일할계산기간적용',
'dydv_calc_dcnt': '일할계산일수',
'bond_expd_asrc_erng_rt': '채권만기보장수익율',
'padf_plac_hdof_name': '원리금지급장소본점명',
'lstg_dt': '상장일자',
'lstg_abol_dt': '상장폐지일자',
'ksd_bond_issu_mthd_cd': '증권예탁결제원채권발행방법코드',
'laps_indf_yn': '경과이자지급여부',
'ksd_lhdy_pnia_dfrm_mthd_cd': '증권예탁결제원공휴일원리금지급',
'frst_int_dfrm_dt': '최초이자지급일자',
'ksd_prcm_lnkg_gvbd_yn': '증권예탁결제원물가연동국고채여',
'dpsi_end_dt': '예탁종료일자',
'dpsi_strt_dt': '예탁시작일자',
'dpsi_psbl_yn': '예탁가능여부',
'atyp_rdpt_bond_erlm_yn': '비정형상환채권등록여부',
'dshn_occr_yn': '부도발생여부',
'expd_exts_yn': '만기연장여부',
'pclr_ptcr_text': '특이사항내용',
'dpsi_psbl_excp_stat_cd': '예탁가능예외상태코드',
'expd_exts_srdp_rcnt': '만기연장분할상환횟수',
'expd_exts_srdp_rt': '만기연장분할상환율',
'expd_rdpt_rt': '만기상환율',
'expd_asrc_erng_rt': '만기보장수익율',
'bond_int_dfrm_mthd_cd': '채권이자지급방법코드',
'int_dfrm_day_type_cd': '이자지급일유형코드',
'prca_dfmt_term_mcnt': '원금거치기간개월수',
'splt_rdpt_rcnt': '분할상환횟수',
'rgbf_int_dfrm_dt': '직전이자지급일자',
'nxtm_int_dfrm_dt': '차기이자지급일자',
'sprx_psbl_yn': '분리과세가능여부',
'ictx_rt_dvsn_cd': '소득세율구분코드',
'bond_clsf_cd': '채권분류코드',
'bond_clsf_kor_name': '채권분류한글명',
'int_mned_dvsn_cd': '이자월말구분코드',
'pnia_int_calc_unpr': '원리금이자계산단가',
'frn_intr': 'FRN금리',
'aply_day_prcm_idx_lnkg_cefc': '적용일물가지수연동계수',
'ksd_expd_dydv_calc_bass_cd': '증권예탁결제원만기일할계산기준',
'expd_dydv_calc_dcnt': '만기일할계산일수',
'ksd_cbbw_dvsn_cd': '증권예탁결제원신종사채구분코드',
'crfd_item_yn': '크라우드펀딩종목여부',
'pnia_bank_ofdy_dfrm_mthd_cd': '원리금은행휴무일지급방법코드',
'qib_yn': 'QIB여부',
'qib_cclc_dt': 'QIB해지일자',
'csbd_yn': '영구채여부',
'csbd_cclc_dt': '영구채해지일자',
'ksd_opcb_yn': '증권예탁결제원옵션부사채여부',
'ksd_sodn_yn': '증권예탁결제원후순위채권여부',
'ksd_rqdi_scty_yn': '증권예탁결제원유동화증권여부',
'elec_scty_yn': '전자증권여부',
'rght_ecis_mbdy_dvsn_cd': '권리행사주체구분코드',
'int_rkng_mthd_dvsn_cd': '이자산정방법구분코드',
'ofrg_dvsn_cd': '모집구분코드',
'ksd_tot_issu_amt': '증권예탁결제원총발행금액',
'next_indf_chk_ecls_yn': '다음이자지급체크제외여부',
'ksd_bond_intr_dvsn_cd': '증권예탁결제원채권금리구분코드',
'ksd_inrt_aply_dvsn_cd': '증권예탁결제원이율적용구분코드',
'krx_issu_istt_cd': 'KRX발행기관코드',
'ksd_indf_frqc_uder_calc_cd': '증권예탁결제원이자지급주기미만',
'ksd_indf_frqc_uder_calc_dcnt': '증권예탁결제원이자지급주기미만',
'tlg_rcvg_dtl_dtime': '전문수신상세일시'
}
NUMERIC_COLUMNS = []
def main():
"""
[장내채권] 기본시세
장내채권 기본조회[국내주식-129]
장내채권 기본조회 테스트 함수
Parameters:
- pdno (str): 상품번호 (상품번호)
- prdt_type_cd (str): 상품유형코드 (Unique key(302))
Returns:
- DataFrame: 장내채권 기본조회 결과
Example:
>>> df = search_bond_info(pdno="", prdt_type_cd="302")
"""
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 = search_bond_info(
pdno="KR103502GA34", # 상품번호
prdt_type_cd="302", # 상품유형코드
)
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')
# 결과 출력
logger.info("=== 장내채권 기본조회 결과 ===")
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,115 @@
# [장내채권] 기본시세 - 장내채권 기본조회
# Generated by KIS API Generator (Single API Mode)
# -*- 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__)
##############################################################################################
# [장내채권] 기본시세 > 장내채권 기본조회 [국내주식-129]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-bond/v1/quotations/search-bond-info"
def search_bond_info(
pdno: str, # 상품번호
prdt_type_cd: str, # 상품유형코드
tr_cont: str = "", # 연속 거래 여부
dataframe: Optional[pd.DataFrame] = None, # 누적 데이터프레임
depth: int = 0, # 현재 재귀 깊이
max_depth: int = 10 # 최대 재귀 깊이
) -> Optional[pd.DataFrame]:
"""
[장내채권] 기본시세
장내채권 기본조회[국내주식-129]
장내채권 기본조회 API를 호출하여 DataFrame으로 반환합니다.
Args:
pdno (str): 상품번호 (필수)
prdt_type_cd (str): 상품유형코드 (필수)
tr_cont (str): 연속 거래 여부 (기본값: "")
dataframe (Optional[pd.DataFrame]): 누적 데이터프레임
depth (int): 현재 재귀 깊이
max_depth (int): 최대 재귀 깊이 (기본값: 10)
Returns:
Optional[pd.DataFrame]: 장내채권 기본조회 데이터
Example:
>>> df = search_bond_info("KR2033022D33", "302")
>>> print(df)
"""
# 로깅 설정
logger = logging.getLogger(__name__)
# 필수 파라미터 검증
if not pdno:
logger.error("pdno is required. (e.g. 'KR2033022D33')")
raise ValueError("pdno is required. (e.g. 'KR2033022D33')")
if not prdt_type_cd:
logger.error("prdt_type_cd is required. (e.g. '302')")
raise ValueError("prdt_type_cd is required. (e.g. '302')")
# 최대 재귀 깊이 체크
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 = "CTPF1114R"
params = {
"PDNO": pdno,
"PRDT_TYPE_CD": prdt_type_cd,
}
# 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 search_bond_info(
pdno,
prdt_type_cd,
"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,124 @@
# -*- coding: utf-8 -*-
"""
Created on 2025-06-20
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.']) # kis_auth 파일 경로 추가
import kis_auth as ka
from sell import sell
# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
##############################################################################################
# [장내채권] 주문/계좌 > 장내채권 매도주문 [국내주식-123]
##############################################################################################
COLUMN_MAPPING = {
'KRX_FWDG_ORD_ORGNO': '한국거래소전송주문조직번호',
'ODNO': '주문번호',
'ORD_TMD': '주문시각'
}
NUMERIC_COLUMNS = []
def main():
"""
[장내채권] 주문/계좌
장내채권 매도주문[국내주식-123]
장내채권 매도주문 테스트 함수
Parameters:
cano (str): 종합계좌번호
acnt_prdt_cd (str): 계좌상품코드
ord_dvsn (str): 주문구분
pdno (str): 상품번호
ord_qty2 (str): 주문수량2
bond_ord_unpr (str): 채권주문단가
sprx_yn (str): 분리과세여부
buy_dt (str): 매수일자
buy_seq (str): 매수순번
samt_mket_ptci_yn (str): 소액시장참여여부
sll_agco_opps_sll_yn (str): 매도대행사반대매도여부
bond_rtl_mket_yn (str): 채권소매시장여부
mgco_aptm_odno (str): 운용사지정주문번호
ord_svr_dvsn_cd (str): 주문서버구분코드
ctac_tlno (str): 연락전화번호
Returns:
- DataFrame: 장내채권 매도주문 결과
Example:
>>> df = main()
>>> print(df)
"""
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("토큰 발급 완료")
# kis_auth 모듈에서 계좌 정보 가져오기
trenv = ka.getTREnv()
# API 호출
logger.info("API 호출 시작: 장내채권 매도주문")
result = sell(
cano=trenv.my_acct, # 종합계좌번호
acnt_prdt_cd=trenv.my_prod, # 계좌상품코드
ord_dvsn="01", # 주문구분
pdno="KR6095572D81", # 상품번호
ord_qty2="1", # 주문수량
bond_ord_unpr="10000.0", # 채권주문단가
sprx_yn="N", # 분리과세여부
buy_dt="", # 매수일자
buy_seq="", # 매수순번
samt_mket_ptci_yn="N", # 소액시장참여여부
sll_agco_opps_sll_yn="N", # 매도대행사반대매도여부
bond_rtl_mket_yn="N", # 채권소매시장여부
mgco_aptm_odno="", # 운용사지정주문번호
ord_svr_dvsn_cd="0", # 주문서버구분코드
ctac_tlno="", # 연락전화번호
)
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')
# 결과 출력
logger.info("=== 장내채권 매도주문 결과 ===")
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,127 @@
# [장내채권] 주문/계좌 - 장내채권 매도주문
# Generated by KIS API Generator (Single API Mode)
# -*- coding: utf-8 -*-
"""
Created on 2025-06-20
"""
import logging
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__)
##############################################################################################
# [장내채권] 주문/계좌 > 장내채권 매도주문 [국내주식-123]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-bond/v1/trading/sell"
def sell(
cano: str,
acnt_prdt_cd: str,
ord_dvsn: str,
pdno: str,
ord_qty2: str,
bond_ord_unpr: str,
sprx_yn: str,
samt_mket_ptci_yn: str,
sll_agco_opps_sll_yn: str,
bond_rtl_mket_yn: str,
buy_dt: str = "",
buy_seq: str = "",
mgco_aptm_odno: str = "",
ord_svr_dvsn_cd: str = "0",
ctac_tlno: str = ""
) -> Optional[pd.DataFrame]:
"""
[장내채권] 주문/계좌
장내채권 매도주문[국내주식-123]
장내채권 매도주문 API를 호출하여 DataFrame으로 반환합니다.
Args:
cano (str): 종합계좌번호
acnt_prdt_cd (str): 계좌상품코드
ord_dvsn (str): 주문구분
pdno (str): 상품번호
ord_qty2 (str): 주문수량2
bond_ord_unpr (str): 채권주문단가
sprx_yn (str): 분리과세여부
samt_mket_ptci_yn (str): 소액시장참여여부
sll_agco_opps_sll_yn (str): 매도대행사반대매도여부
bond_rtl_mket_yn (str): 채권소매시장여부
buy_dt (str, optional): 매수일자. Defaults to "".
buy_seq (str, optional): 매수순번. Defaults to "".
mgco_aptm_odno (str, optional): 운용사지정주문번호. Defaults to "".
ord_svr_dvsn_cd (str, optional): 주문서버구분코드. Defaults to "0".
ctac_tlno (str, optional): 연락전화번호. Defaults to "".
Returns:
Optional[pd.DataFrame]: 장내채권 매도주문 데이터
Example:
>>> df = sell(
... cano=trenv.my_acct,
... acnt_prdt_cd=trenv.my_prod,
... ord_dvsn="01",
... pdno="KR6095572D81",
... ord_qty2="1",
... bond_ord_unpr="10000.0",
... sprx_yn="N",
... samt_mket_ptci_yn="N",
... sll_agco_opps_sll_yn="N",
... bond_rtl_mket_yn="N"
... )
>>> print(df)
"""
tr_id = "TTTC0958U"
params = {
"CANO": cano,
"ACNT_PRDT_CD": acnt_prdt_cd,
"ORD_DVSN": ord_dvsn,
"PDNO": pdno,
"ORD_QTY2": ord_qty2,
"BOND_ORD_UNPR": bond_ord_unpr,
"SPRX_YN": sprx_yn,
"BUY_DT": buy_dt,
"BUY_SEQ": buy_seq,
"SAMT_MKET_PTCI_YN": samt_mket_ptci_yn,
"SLL_AGCO_OPPS_SLL_YN": sll_agco_opps_sll_yn,
"BOND_RTL_MKET_YN": bond_rtl_mket_yn,
"MGCO_APTM_ODNO": mgco_aptm_odno,
"ORD_SVR_DVSN_CD": ord_svr_dvsn_cd,
"CTAC_TLNO": ctac_tlno
}
res = ka._url_fetch(api_url=API_URL,
ptr_id=tr_id,
tr_cont="",
params=params,
postFlag=True
)
if res.isOK():
if hasattr(res.getBody(), 'output'):
output_data = res.getBody().output
if not isinstance(output_data, list):
output_data = [output_data]
dataframe = pd.DataFrame(output_data)
else:
dataframe = pd.DataFrame()
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,116 @@
"""
Created on 20250601
"""
import logging
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from commodity_futures_realtime_conclusion import commodity_futures_realtime_conclusion
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > 상품선물 실시간체결가[실시간-022]
##############################################################################################
COLUMN_MAPPING = {
"futs_shrn_iscd": "선물 단축 종목코드",
"bsop_hour": "영업 시간",
"futs_prdy_vrss": "선물 전일 대비",
"prdy_vrss_sign": "전일 대비 부호",
"futs_prdy_ctrt": "선물 전일 대비율",
"futs_prpr": "선물 현재가",
"futs_oprc": "선물 시가2",
"futs_hgpr": "선물 최고가",
"futs_lwpr": "선물 최저가",
"last_cnqn": "최종 거래량",
"acml_vol": "누적 거래량",
"acml_tr_pbmn": "누적 거래 대금",
"hts_thpr": "HTS 이론가",
"mrkt_basis": "시장 베이시스",
"dprt": "괴리율",
"nmsc_fctn_stpl_prc": "근월물 약정가",
"fmsc_fctn_stpl_prc": "원월물 약정가",
"spead_prc": "스프레드1",
"hts_otst_stpl_qty": "HTS 미결제 약정 수량",
"otst_stpl_qty_icdc": "미결제 약정 수량 증감",
"oprc_hour": "시가 시간",
"oprc_vrss_prpr_sign": "시가2 대비 현재가 부호",
"oprc_vrss_nmix_prpr": "시가 대비 지수 현재가",
"hgpr_hour": "최고가 시간",
"hgpr_vrss_prpr_sign": "최고가 대비 현재가 부호",
"hgpr_vrss_nmix_prpr": "최고가 대비 지수 현재가",
"lwpr_hour": "최저가 시간",
"lwpr_vrss_prpr_sign": "최저가 대비 현재가 부호",
"lwpr_vrss_nmix_prpr": "최저가 대비 지수 현재가",
"shnu_rate": "매수2 비율",
"cttr": "체결강도",
"esdg": "괴리도",
"otst_stpl_rgbf_qty_icdc": "미결제 약정 직전 수량 증감",
"thpr_basis": "이론 베이시스",
"futs_askp1": "선물 매도호가1",
"futs_bidp1": "선물 매수호가1",
"askp_rsqn1": "매도호가 잔량1",
"bidp_rsqn1": "매수호가 잔량1",
"seln_cntg_csnu": "매도 체결 건수",
"shnu_cntg_csnu": "매수 체결 건수",
"ntby_cntg_csnu": "순매수 체결 건수",
"seln_cntg_smtn": "총 매도 수량",
"shnu_cntg_smtn": "총 매수 수량",
"total_askp_rsqn": "총 매도호가 잔량",
"total_bidp_rsqn": "총 매수호가 잔량",
"prdy_vol_vrss_acml_vol_rate": "전일 거래량 대비 등락율",
"dscs_bltr_acml_qty": "협의 대량 거래량",
"dynm_mxpr": "실시간상한가",
"dynm_llam": "실시간하한가",
"dynm_prc_limt_yn": "실시간가격제한구분"
}
NUMERIC_COLUMNS = []
def main():
"""
상품선물 실시간체결가
Returns:
None
"""
# 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")
# 조회
kws.subscribe(request=commodity_futures_realtime_conclusion, data=["165W09"])
# 결과 표시
def on_result(ws, tr_id: str, result: pd.DataFrame, data_map: dict):
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)
kws.start(on_result=on_result)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,108 @@
"""
Created on 20250601
"""
import logging
import sys
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > 상품선물 실시간체결가[실시간-022]
##############################################################################################
def commodity_futures_realtime_conclusion(
tr_type: str,
tr_key: str,
) -> (dict, list[str]):
"""
상품선물 실시간체결가 API입니다.
실시간 웹소켓 연결을 통해 상품선물의 실시간 체결가 정보를 수신할 수 있습니다.
현재가, 시고저가, 체결량, 누적거래량, 이론가, 베이시스, 괴리율 등의 상세 정보를 제공합니다.
매도/매수 호가, 체결 건수, 미결제 약정 수량 등의 선물거래 필수 정보를 포함합니다.
Args:
tr_type (str): [필수] 구독 등록/해제 여부 (ex. "1": 구독, "2": 해제)
tr_key (str): [필수] 종목코드 (ex. 101S12)
Returns:
message (str): 메시지 데이터
Example:
>>> msg, columns = commodity_futures_realtime_conclusion("1", "101S12")
>>> print(msg, columns)
"""
# 필수 파라미터 검증
if tr_type == "":
raise ValueError("tr_type is empty")
if tr_key == "":
raise ValueError("tr_key is required")
tr_id = "H0CFCNT0"
params = {
"tr_key": tr_key,
}
msg = ka.data_fetch(tr_id, tr_type, params)
columns = [
"futs_shrn_iscd",
"bsop_hour",
"futs_prdy_vrss",
"prdy_vrss_sign",
"futs_prdy_ctrt",
"futs_prpr",
"futs_oprc",
"futs_hgpr",
"futs_lwpr",
"last_cnqn",
"acml_vol",
"acml_tr_pbmn",
"hts_thpr",
"mrkt_basis",
"dprt",
"nmsc_fctn_stpl_prc",
"fmsc_fctn_stpl_prc",
"spead_prc",
"hts_otst_stpl_qty",
"otst_stpl_qty_icdc",
"oprc_hour",
"oprc_vrss_prpr_sign",
"oprc_vrss_nmix_prpr",
"hgpr_hour",
"hgpr_vrss_prpr_sign",
"hgpr_vrss_nmix_prpr",
"lwpr_hour",
"lwpr_vrss_prpr_sign",
"lwpr_vrss_nmix_prpr",
"shnu_rate",
"cttr",
"esdg",
"otst_stpl_rgbf_qty_icdc",
"thpr_basis",
"futs_askp1",
"futs_bidp1",
"askp_rsqn1",
"bidp_rsqn1",
"seln_cntg_csnu",
"shnu_cntg_csnu",
"ntby_cntg_csnu",
"seln_cntg_smtn",
"shnu_cntg_smtn",
"total_askp_rsqn",
"total_bidp_rsqn",
"prdy_vol_vrss_acml_vol_rate",
"dscs_bltr_acml_qty",
"dynm_mxpr",
"dynm_llam",
"dynm_prc_limt_yn"
]
return msg, columns

View File

@@ -0,0 +1,104 @@
"""
Created on 20250601
"""
import logging
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from commodity_futures_realtime_quote import commodity_futures_realtime_quote
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > 상품선물 실시간호가[실시간-023]
##############################################################################################
COLUMN_MAPPING = {
"futs_shrn_iscd": "선물 단축 종목코드",
"bsop_hour": "영업 시간",
"futs_askp1": "선물 매도호가1",
"futs_askp2": "선물 매도호가2",
"futs_askp3": "선물 매도호가3",
"futs_askp4": "선물 매도호가4",
"futs_askp5": "선물 매도호가5",
"futs_bidp1": "선물 매수호가1",
"futs_bidp2": "선물 매수호가2",
"futs_bidp3": "선물 매수호가3",
"futs_bidp4": "선물 매수호가4",
"futs_bidp5": "선물 매수호가5",
"askp_csnu1": "매도호가 건수1",
"askp_csnu2": "매도호가 건수2",
"askp_csnu3": "매도호가 건수3",
"askp_csnu4": "매도호가 건수4",
"askp_csnu5": "매도호가 건수5",
"bidp_csnu1": "매수호가 건수1",
"bidp_csnu2": "매수호가 건수2",
"bidp_csnu3": "매수호가 건수3",
"bidp_csnu4": "매수호가 건수4",
"bidp_csnu5": "매수호가 건수5",
"askp_rsqn1": "매도호가 잔량1",
"askp_rsqn2": "매도호가 잔량2",
"askp_rsqn3": "매도호가 잔량3",
"askp_rsqn4": "매도호가 잔량4",
"askp_rsqn5": "매도호가 잔량5",
"bidp_rsqn1": "매수호가 잔량1",
"bidp_rsqn2": "매수호가 잔량2",
"bidp_rsqn3": "매수호가 잔량3",
"bidp_rsqn4": "매수호가 잔량4",
"bidp_rsqn5": "매수호가 잔량5",
"total_askp_csnu": "총 매도호가 건수",
"total_bidp_csnu": "총 매수호가 건수",
"total_askp_rsqn": "총 매도호가 잔량",
"total_bidp_rsqn": "총 매수호가 잔량",
"total_askp_rsqn_icdc": "총 매도호가 잔량 증감",
"total_bidp_rsqn_icdc": "총 매수호가 잔량 증감"
}
NUMERIC_COLUMNS = []
def main():
"""
상품선물 실시간호가
Returns:
None
"""
# 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")
# 조회
kws.subscribe(request=commodity_futures_realtime_quote, data=["165W09"])
# 결과 표시
def on_result(ws, tr_id: str, result: pd.DataFrame, data_map: dict):
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)
kws.start(on_result=on_result)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,96 @@
"""
Created on 20250601
"""
import logging
import sys
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > 상품선물 실시간호가[실시간-023]
##############################################################################################
def commodity_futures_realtime_quote(
tr_type: str,
tr_key: str,
) -> (dict, list[str]):
"""
상품선물 실시간호가 API입니다.
실시간 웹소켓 연결을 통해 상품선물 매도/매수 호가 정보를 실시간으로 수신할 수 있습니다.
실전계좌만 지원되며, 모의투자는 지원하지 않습니다.
선물옵션 호가 데이터는 0.2초 필터링 옵션이 적용됩니다.
Args:
tr_type (str): [필수] 구독 등록/해제 여부 (ex. "1": 구독, "2": 해제)
tr_key (str): [필수] 종목코드 (ex. 101S12)
Returns:
message (str): 메시지 데이터
Example:
>>> msg, columns = commodity_futures_realtime_quote("1", "101S12")
>>> print(msg, columns)
"""
# 필수 파라미터 검증
if tr_type == "":
raise ValueError("tr_type is required")
if tr_key == "":
raise ValueError("tr_key is required")
tr_id = "H0CFASP0"
params = {
"tr_key": tr_key,
}
msg = ka.data_fetch(tr_id, tr_type, params)
columns = [
"futs_shrn_iscd",
"bsop_hour",
"futs_askp1",
"futs_askp2",
"futs_askp3",
"futs_askp4",
"futs_askp5",
"futs_bidp1",
"futs_bidp2",
"futs_bidp3",
"futs_bidp4",
"futs_bidp5",
"askp_csnu1",
"askp_csnu2",
"askp_csnu3",
"askp_csnu4",
"askp_csnu5",
"bidp_csnu1",
"bidp_csnu2",
"bidp_csnu3",
"bidp_csnu4",
"bidp_csnu5",
"askp_rsqn1",
"askp_rsqn2",
"askp_rsqn3",
"askp_rsqn4",
"askp_rsqn5",
"bidp_rsqn1",
"bidp_rsqn2",
"bidp_rsqn3",
"bidp_rsqn4",
"bidp_rsqn5",
"total_askp_csnu",
"total_bidp_csnu",
"total_askp_rsqn",
"total_bidp_rsqn",
"total_askp_rsqn_icdc",
"total_bidp_rsqn_icdc"
]
return msg, columns

View File

@@ -0,0 +1,130 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from display_board_callput import display_board_callput
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 기본시세 > 국내옵션전광판_콜풋[국내선물-022]
##############################################################################################
# 컬럼명 한글 변환 및 데이터 출력
COLUMN_MAPPING = {
'acpr': '행사가',
'unch_prpr': '환산 현재가',
'optn_shrn_iscd': '옵션 단축 종목코드',
'optn_prpr': '옵션 현재가',
'optn_prdy_vrss': '옵션 전일 대비',
'prdy_vrss_sign': '전일 대비 부호',
'optn_prdy_ctrt': '옵션 전일 대비율',
'optn_bidp': '옵션 매수호가',
'optn_askp': '옵션 매도호가',
'tmvl_val': '시간가치 값',
'nmix_sdpr': '지수 기준가',
'acml_vol': '누적 거래량',
'seln_rsqn': '매도 잔량',
'shnu_rsqn': '매수2 잔량',
'acml_tr_pbmn': '누적 거래 대금',
'hts_otst_stpl_qty': 'HTS 미결제 약정 수량',
'otst_stpl_qty_icdc': '미결제 약정 수량 증감',
'delta_val': '델타 값',
'gama': '감마',
'vega': '베가',
'theta': '세타',
'rho': '로우',
'hts_ints_vltl': 'HTS 내재 변동성',
'invl_val': '내재가치 값',
'esdg': '괴리도',
'dprt': '괴리율',
'hist_vltl': '역사적 변동성',
'hts_thpr': 'HTS 이론가',
'optn_oprc': '옵션 시가2',
'optn_hgpr': '옵션 최고가',
'optn_lwpr': '옵션 최저가',
'optn_mxpr': '옵션 상한가',
'optn_llam': '옵션 하한가',
'atm_cls_name': 'ATM 구분 명',
'rgbf_vrss_icdc': '직전 대비 증감',
'total_askp_rsqn': '총 매도호가 잔량',
'total_bidp_rsqn': '총 매수호가 잔량',
'futs_antc_cnpr': '선물예상체결가',
'futs_antc_cntg_vrss': '선물예상체결대비',
'antc_cntg_vrss_sign': '예상 체결 대비 부호',
'antc_cntg_prdy_ctrt': '예상 체결 전일 대비율',
}
NUMERIC_COLUMNS = []
def main():
"""
국내옵션전광판_콜풋 조회 테스트 함수
이 함수는 국내옵션전광판_콜풋 API를 호출하여 결과를 출력합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
# Case1 테스트
logging.info("=== Case1 테스트 ===")
try:
result1, result2 = display_board_callput(
fid_cond_mrkt_div_code="O",
fid_cond_scr_div_code="20503",
fid_mrkt_cls_code="CO",
fid_mtrt_cnt="202508",
fid_mrkt_cls_code1="PO"
)
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
# Output1 처리
logging.info("=== Output1 결과 ===")
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result1)
# Output2 처리
logging.info("=== Output2 결과 ===")
logging.info("사용 가능한 컬럼: %s", result2.columns.tolist())
result2 = result2.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시 (메타데이터에 number 자료형 없음)
for col in NUMERIC_COLUMNS:
if col in result2.columns:
result2[col] = pd.to_numeric(result2[col], errors='coerce').round(2)
logging.info("결과:")
print(result2)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,91 @@
"""
Created on 20250601
"""
import sys
from typing import Tuple
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 기본시세 > 국내옵션전광판_콜풋[국내선물-022]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/quotations/display-board-callput"
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"
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()

View File

@@ -0,0 +1,91 @@
"""
Created on 20250112
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from display_board_futures import display_board_futures
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 기본시세 > 국내옵션전광판_선물[국내선물-023]
##############################################################################################
COLUMN_MAPPING = {
'futs_shrn_iscd': '선물 단축 종목코드',
'hts_kor_isnm': 'HTS 한글 종목명',
'futs_prpr': '선물 현재가',
'futs_prdy_vrss': '선물 전일 대비',
'prdy_vrss_sign': '전일 대비 부호',
'futs_prdy_ctrt': '선물 전일 대비율',
'hts_thpr': 'HTS 이론가',
'acml_vol': '누적 거래량',
'futs_askp': '선물 매도호가',
'futs_bidp': '선물 매수호가',
'hts_otst_stpl_qty': 'HTS 미결제 약정 수량',
'futs_hgpr': '선물 최고가',
'futs_lwpr': '선물 최저가',
'hts_rmnn_dynu': 'HTS 잔존 일수',
'total_askp_rsqn': '총 매도호가 잔량',
'total_bidp_rsqn': '총 매수호가 잔량',
'futs_antc_cnpr': '선물예상체결가',
'futs_antc_cntg_vrss': '선물예상체결대비',
'antc_cntg_vrss_sign': '예상 체결 대비 부호',
'antc_cntg_prdy_ctrt': '예상 체결 전일 대비율'
}
NUMERIC_COLUMNS = []
def main():
"""
국내선물옵션 선물전광판 조회 테스트 함수
이 함수는 국내선물옵션 선물전광판 API를 호출하여 결과를 출력합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
# case1 테스트
logging.info("=== case1 테스트 ===")
try:
result = display_board_futures(
fid_cond_mrkt_div_code="F",
fid_cond_scr_div_code="20503",
fid_cond_mrkt_cls_code="MKI"
)
except ValueError as e:
logging.error("에러 발생: %s", str(e))
return
logging.info("사용 가능한 컬럼: %s", result.columns.tolist())
# 컬럼명 한글 변환
result = result.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 표시 (메타데이터에 number 자료형이 명시된 컬럼 없음)
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)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,69 @@
"""
Created on 20250112
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 기본시세 > 국내옵션전광판_선물[국내선물-023]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/quotations/display-board-futures"
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"
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()

View File

@@ -0,0 +1,71 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from display_board_option_list import display_board_option_list
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 기본시세 > 국내옵션전광판_옵션월물리스트[국내선물-020]
##############################################################################################
COLUMN_MAPPING = {
'mtrt_yymm_code': '만기 년월 코드',
'mtrt_yymm': '만기 년월'
}
NUMERIC_COLUMNS = []
def main():
"""
국내옵션전광판_옵션월물리스트 조회 테스트 함수
이 함수는 국내옵션전광판_옵션월물리스트 API를 호출하여 결과를 출력합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
# case1 조회
logging.info("=== case1 조회 ===")
try:
result = display_board_option_list(fid_cond_scr_div_code="509")
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
logging.info("사용 가능한 컬럼: %s", result.columns.tolist())
# 컬럼명 한글 변환 및 데이터 출력
result = result.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시 (메타데이터에 number 자료형이 명시된 필드가 없음)
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)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,63 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 기본시세 > 국내옵션전광판_옵션월물리스트[국내선물-020]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/quotations/display-board-option-list"
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"
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()

View File

@@ -0,0 +1,96 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from display_board_top import display_board_top
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 기본시세 > 국내선물 기초자산 시세[국내선물-021]
##############################################################################################
COLUMN_MAPPING = {
'unas_prpr': '기초자산 현재가',
'unas_prdy_vrss': '기초자산 전일 대비',
'unas_prdy_vrss_sign': '기초자산 전일 대비 부호',
'unas_prdy_ctrt': '기초자산 전일 대비율',
'unas_acml_vol': '기초자산 누적 거래량',
'hts_kor_isnm': 'HTS 한글 종목명',
'futs_prpr': '선물 현재가',
'futs_prdy_vrss': '선물 전일 대비',
'prdy_vrss_sign': '전일 대비 부호',
'futs_prdy_ctrt': '선물 전일 대비율',
'hts_rmnn_dynu': 'HTS 잔존 일수'
}
NUMERIC_COLUMNS = []
def main():
"""
국내선물 기초자산 시세 조회 테스트 함수
이 함수는 국내선물 기초자산 시세 API를 호출하여 결과를 출력합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
logging.info("=== 국내선물 기초자산 시세 조회 ===")
try:
output1, output2 = display_board_top(fid_cond_mrkt_div_code="F", fid_input_iscd="101W09")
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
# output1 처리
logging.info("=== output1 결과 ===")
logging.info("사용 가능한 컬럼: %s", output1.columns.tolist())
# 컬럼명 한글 변환
output1 = output1.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시
for col in NUMERIC_COLUMNS:
if col in output1.columns:
output1[col] = pd.to_numeric(output1[col], errors='coerce').round(2)
logging.info("결과:")
print(output1)
# output2 처리
logging.info("=== output2 결과 ===")
logging.info("사용 가능한 컬럼: %s", output2.columns.tolist())
# 컬럼명 한글 변환
output2 = output2.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시
for col in NUMERIC_COLUMNS:
if col in output2.columns:
output2[col] = pd.to_numeric(output2[col], errors='coerce').round(2)
logging.info("결과:")
print(output2)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,79 @@
"""
Created on 20250601
"""
import sys
import logging
from typing import Tuple
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 기본시세 > 국내선물 기초자산 시세[국내선물-021]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/quotations/display-board-top"
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. '101W09')")
tr_id = "FHPIF05030000"
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()

View File

@@ -0,0 +1,92 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from exp_price_trend import exp_price_trend
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 기본시세 > 선물옵션 일중예상체결추이[국내선물-018]
##############################################################################################
COLUMN_MAPPING = {
'hts_kor_isnm': '영업 시간',
'futs_antc_cnpr': '업종 지수 현재가',
'antc_cntg_vrss_sign': '업종 지수 전일 대비',
'futs_antc_cntg_vrss': '전일 대비 부호',
'antc_cntg_prdy_ctrt': '업종 지수 전일 대비율',
'futs_sdpr': '누적 거래 대금',
'stck_cntg_hour': '주식체결시간',
'futs_antc_cnpr': '선물예상체결가',
'antc_cntg_vrss_sign': '예상체결대비부호',
'futs_antc_cntg_vrss': '선물예상체결대비',
'antc_cntg_prdy_ctrt': '예상체결전일대비율'
}
NUMERIC_COLUMNS = []
def main():
"""
선물옵션 일중예상체결추이 조회 테스트 함수
이 함수는 선물옵션 일중예상체결추이 API를 호출하여 결과를 출력합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
# case1 조회
logging.info("=== case1 조회 ===")
try:
result1, result2 = exp_price_trend(fid_input_iscd="101W09", fid_cond_mrkt_div_code="F")
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
# output1 결과 처리
logging.info("사용 가능한 컬럼 (output1): %s", result1.columns.tolist())
# 컬럼명 한글 변환 및 데이터 출력 (output1)
result1 = result1.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시 (output1)
for col in NUMERIC_COLUMNS:
if col in result1.columns:
result1[col] = pd.to_numeric(result1[col], errors='coerce').round(2)
logging.info("결과 (output1):")
print(result1)
# output2 결과 처리
logging.info("사용 가능한 컬럼 (output2): %s", result2.columns.tolist())
# 컬럼명 한글 변환 및 데이터 출력 (output2)
result2 = result2.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시 (output2)
for col in NUMERIC_COLUMNS:
if col in result2.columns:
result2[col] = pd.to_numeric(result2[col], errors='coerce').round(2)
logging.info("결과 (output2):")
print(result2)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,70 @@
"""
Created on 20250601
"""
import sys
import logging
from typing import Tuple
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 기본시세 > 선물옵션 일중예상체결추이[국내선물-018]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/quotations/exp-price-trend"
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. '101W09')")
if fid_cond_mrkt_div_code == "":
raise ValueError("fid_cond_mrkt_div_code is required (e.g. 'F')")
tr_id = "FHPIF05110100" # 선물옵션 일중예상체결추이
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()

View File

@@ -0,0 +1,89 @@
"""
Created on 20250601
"""
import logging
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from fuopt_ccnl_notice import fuopt_ccnl_notice
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > 선물옵션 실시간체결통보[실시간-012]
##############################################################################################
COLUMN_MAPPING = {
"cust_id": "고객 ID",
"acnt_no": "계좌번호",
"oder_no": "주문번호",
"ooder_no": "원주문번호",
"seln_byov_cls": "매도매수구분",
"rctf_cls": "정정구분",
"oder_kind2": "주문종류2",
"stck_shrn_iscd": "주식 단축 종목코드",
"cntg_qty": "체결 수량",
"cntg_unpr": "체결단가",
"stck_cntg_hour": "주식 체결 시간",
"rfus_yn": "거부여부",
"cntg_yn": "체결여부",
"acpt_yn": "접수여부",
"brnc_no": "지점번호",
"oder_qty": "주문수량",
"acnt_name": "계좌명",
"cntg_isnm": "체결종목명",
"oder_cond": "주문조건",
"ord_grp": "주문그룹ID",
"ord_grpseq": "주문그룹SEQ",
"order_prc": "주문가격"
}
NUMERIC_COLUMNS = []
def main():
"""
선물옵션 실시간체결통보
Returns:
None
"""
# 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()
trenv = ka.getTREnv()
# 인증(auth_ws()) 이후에 선언
kws = ka.KISWebSocket(api_url="/tryitout")
# 조회
kws.subscribe(request=fuopt_ccnl_notice, data=[trenv.my_htsid])
# 결과 표시
def on_result(ws, tr_id: str, result: pd.DataFrame, data_map: dict):
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)
kws.start(on_result=on_result)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,81 @@
"""
Created on 20250601
"""
import logging
import sys
from typing import Optional, Tuple
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > 선물옵션 실시간체결통보[실시간-012]
##############################################################################################
def fuopt_ccnl_notice(
tr_type: str,
tr_key: str,
):
"""
선물옵션 실시간체결통보 API입니다.
실시간 웹소켓 연결을 통해 선물옵션 거래의 실시간 체결 통보를 수신할 수 있습니다.
주문접수, 체결, 정정, 취소 등의 거래 상태 변화를 실시간으로 통보받을 수 있습니다.
고객ID, 계좌번호, 주문번호, 체결수량, 체결단가 등의 상세 거래 정보를 포함합니다.
실전계좌와 모의투자 모두 지원됩니다.
Args:
tr_type (str): [필수] 구독 등록/해제 여부 (ex. "1": 구독, "2": 해제)
tr_key (str): [필수] 코드 (ex. dttest11)
Returns:
message (str): 메시지 데이터
Example:
>>> msg, columns = fuopt_ccnl_notice("1", trenv.my_htsid)
>>> print(msg, columns)
"""
# 필수 파라미터 검증
if tr_key == "":
raise ValueError("tr_key is required")
tr_id = "H0IFCNI0"
params = {
"tr_key": tr_key,
}
msg = ka.data_fetch(tr_id, tr_type, params)
columns = [
"cust_id",
"acnt_no",
"oder_no",
"ooder_no",
"seln_byov_cls",
"rctf_cls",
"oder_kind2",
"stck_shrn_iscd",
"cntg_qty",
"cntg_unpr",
"stck_cntg_hour",
"rfus_yn",
"cntg_yn",
"acpt_yn",
"brnc_no",
"oder_qty",
"acnt_name",
"cntg_isnm",
"oder_cond",
"ord_grp",
"ord_grpseq",
"order_prc"
]
return msg, columns

View File

@@ -0,0 +1,74 @@
"""
Created on 20250601
"""
import logging
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from futures_exp_ccnl import futures_exp_ccnl
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > 주식선물 실시간예상체결 [실시간-031]
##############################################################################################
COLUMN_MAPPING = {
"futs_shrn_iscd": "선물단축종목코드",
"bsop_hour": "영업시간",
"antc_cnpr": "예상체결가",
"antc_cntg_vrss": "예상체결대비",
"antc_cntg_vrss_sign": "예상체결대비부호",
"antc_cntg_prdy_ctrt": "예상체결전일대비율",
"antc_mkop_cls_code": "예상장운영구분코드",
"antc_cnqn": "예상체결수량"
}
NUMERIC_COLUMNS = []
def main():
"""
[국내선물옵션] 실시간시세 > 주식선물 실시간예상체결 [실시간-031]
Returns:
None
"""
# 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")
# 조회
kws.subscribe(request=futures_exp_ccnl, data=["111W07"])
# 결과 표시
def on_result(ws, tr_id: str, result: pd.DataFrame, data_map: dict):
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)
kws.start(on_result=on_result)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,64 @@
"""
Created on 20250601
"""
import logging
import sys
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > 주식선물 실시간예상체결 [실시간-031]
##############################################################################################
def futures_exp_ccnl(
tr_type: str,
tr_key: str,
) -> (dict, list[str]):
"""
[국내선물옵션] 실시간시세 > 주식선물 실시간예상체결 [실시간-031]
Args:
tr_type (str): [필수] 등록/해제
tr_key (str): [필수] 종목코드
Returns:
message (dict): 메시지 데이터
columns (list[str]): 컬럼 정보
Example:
>>> msg, columns = futures_exp_ccnl("1", "111W07")
>>> print(msg, columns)
"""
# 필수 파라미터 검증
if tr_type == "":
raise ValueError("tr_type is required")
if tr_key == "":
raise ValueError("tr_key is required")
tr_id = "H0ZFANC0"
params = {
"tr_key": tr_key,
}
msg = ka.data_fetch(tr_id, tr_type, params)
columns = [
"futs_shrn_iscd",
"bsop_hour",
"antc_cnpr",
"antc_cntg_vrss",
"antc_cntg_vrss_sign",
"antc_cntg_prdy_ctrt",
"antc_mkop_cls_code",
"antc_cnqn"
]
return msg, columns

View File

@@ -0,0 +1,116 @@
"""
Created on 20250601
"""
import logging
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from index_futures_realtime_conclusion import index_futures_realtime_conclusion
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > 지수선물 실시간체결가[실시간-010]
##############################################################################################
COLUMN_MAPPING = {
"futs_shrn_iscd": "선물 단축 종목코드",
"bsop_hour": "영업 시간",
"futs_prdy_vrss": "선물 전일 대비",
"prdy_vrss_sign": "전일 대비 부호",
"futs_prdy_ctrt": "선물 전일 대비율",
"futs_prpr": "선물 현재가",
"futs_oprc": "선물 시가2",
"futs_hgpr": "선물 최고가",
"futs_lwpr": "선물 최저가",
"last_cnqn": "최종 거래량",
"acml_vol": "누적 거래량",
"acml_tr_pbmn": "누적 거래 대금",
"hts_thpr": "HTS 이론가",
"mrkt_basis": "시장 베이시스",
"dprt": "괴리율",
"nmsc_fctn_stpl_prc": "근월물 약정가",
"fmsc_fctn_stpl_prc": "원월물 약정가",
"spead_prc": "스프레드1",
"hts_otst_stpl_qty": "HTS 미결제 약정 수량",
"otst_stpl_qty_icdc": "미결제 약정 수량 증감",
"oprc_hour": "시가 시간",
"oprc_vrss_prpr_sign": "시가2 대비 현재가 부호",
"oprc_vrss_nmix_prpr": "시가 대비 지수 현재가",
"hgpr_hour": "최고가 시간",
"hgpr_vrss_prpr_sign": "최고가 대비 현재가 부호",
"hgpr_vrss_nmix_prpr": "최고가 대비 지수 현재가",
"lwpr_hour": "최저가 시간",
"lwpr_vrss_prpr_sign": "최저가 대비 현재가 부호",
"lwpr_vrss_nmix_prpr": "최저가 대비 지수 현재가",
"shnu_rate": "매수2 비율",
"cttr": "체결강도",
"esdg": "괴리도",
"otst_stpl_rgbf_qty_icdc": "미결제 약정 직전 수량 증감",
"thpr_basis": "이론 베이시스",
"futs_askp1": "선물 매도호가1",
"futs_bidp1": "선물 매수호가1",
"askp_rsqn1": "매도호가 잔량1",
"bidp_rsqn1": "매수호가 잔량1",
"seln_cntg_csnu": "매도 체결 건수",
"shnu_cntg_csnu": "매수 체결 건수",
"ntby_cntg_csnu": "순매수 체결 건수",
"seln_cntg_smtn": "총 매도 수량",
"shnu_cntg_smtn": "총 매수 수량",
"total_askp_rsqn": "총 매도호가 잔량",
"total_bidp_rsqn": "총 매수호가 잔량",
"prdy_vol_vrss_acml_vol_rate": "전일 거래량 대비 등락율",
"dscs_bltr_acml_qty": "협의 대량 거래량",
"dynm_mxpr": "실시간상한가",
"dynm_llam": "실시간하한가",
"dynm_prc_limt_yn": "실시간가격제한구분"
}
NUMERIC_COLUMNS = []
def main():
"""
지수선물 실시간체결가
Returns:
None
"""
# 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")
# 조회
kws.subscribe(request=index_futures_realtime_conclusion, data=["101W09"])
# 결과 표시
def on_result(ws, tr_id: str, result: pd.DataFrame, data_map: dict):
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)
kws.start(on_result=on_result)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,109 @@
"""
Created on 20250601
"""
import logging
import sys
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > 지수선물 실시간체결가[실시간-010]
##############################################################################################
def index_futures_realtime_conclusion(
tr_type: str,
tr_key: str,
) -> (dict, list[str]):
"""
지수선물 실시간체결가 API입니다.
실시간 웹소켓 연결을 통해 지수선물의 실시간 체결가 정보를 수신할 수 있습니다.
현재가, 시고저가, 체결량, 누적거래량, 이론가, 베이시스, 괴리율 등의 상세 정보를 제공합니다.
매도/매수 호가, 체결 건수, 미결제 약정 수량 등의 선물거래 필수 정보를 포함합니다.
실전계좌만 지원되며 모의투자는 미지원됩니다.
Args:
tr_type (str): [필수] 구독 등록/해제 여부 (ex. "1": 구독, "2": 해제)
tr_key (str): [필수] 코드 (ex. 101S12)
Returns:
message (str): 메시지 데이터
Example:
>>> msg, columns = index_futures_realtime_conclusion("1", "101S12")
>>> print(msg, columns)
"""
# 필수 파라미터 검증
if tr_type == "":
raise ValueError("tr_type is required")
if tr_key == "":
raise ValueError("tr_key is required")
tr_id = "H0IFCNT0"
params = {
"tr_key": tr_key,
}
msg = ka.data_fetch(tr_id, tr_type, params)
columns = [
"futs_shrn_iscd",
"bsop_hour",
"futs_prdy_vrss",
"prdy_vrss_sign",
"futs_prdy_ctrt",
"futs_prpr",
"futs_oprc",
"futs_hgpr",
"futs_lwpr",
"last_cnqn",
"acml_vol",
"acml_tr_pbmn",
"hts_thpr",
"mrkt_basis",
"dprt",
"nmsc_fctn_stpl_prc",
"fmsc_fctn_stpl_prc",
"spead_prc",
"hts_otst_stpl_qty",
"otst_stpl_qty_icdc",
"oprc_hour",
"oprc_vrss_prpr_sign",
"oprc_vrss_nmix_prpr",
"hgpr_hour",
"hgpr_vrss_prpr_sign",
"hgpr_vrss_nmix_prpr",
"lwpr_hour",
"lwpr_vrss_prpr_sign",
"lwpr_vrss_nmix_prpr",
"shnu_rate",
"cttr",
"esdg",
"otst_stpl_rgbf_qty_icdc",
"thpr_basis",
"futs_askp1",
"futs_bidp1",
"askp_rsqn1",
"bidp_rsqn1",
"seln_cntg_csnu",
"shnu_cntg_csnu",
"ntby_cntg_csnu",
"seln_cntg_smtn",
"shnu_cntg_smtn",
"total_askp_rsqn",
"total_bidp_rsqn",
"prdy_vol_vrss_acml_vol_rate",
"dscs_bltr_acml_qty",
"dynm_mxpr",
"dynm_llam",
"dynm_prc_limt_yn"
]
return msg, columns

View File

@@ -0,0 +1,104 @@
"""
Created on 20250601
"""
import logging
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from index_futures_realtime_quote import index_futures_realtime_quote
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > 지수선물 실시간호가[실시간-011]
##############################################################################################
COLUMN_MAPPING = {
"futs_shrn_iscd": "선물 단축 종목코드",
"bsop_hour": "영업 시간",
"futs_askp1": "선물 매도호가1",
"futs_askp2": "선물 매도호가2",
"futs_askp3": "선물 매도호가3",
"futs_askp4": "선물 매도호가4",
"futs_askp5": "선물 매도호가5",
"futs_bidp1": "선물 매수호가1",
"futs_bidp2": "선물 매수호가2",
"futs_bidp3": "선물 매수호가3",
"futs_bidp4": "선물 매수호가4",
"futs_bidp5": "선물 매수호가5",
"askp_csnu1": "매도호가 건수1",
"askp_csnu2": "매도호가 건수2",
"askp_csnu3": "매도호가 건수3",
"askp_csnu4": "매도호가 건수4",
"askp_csnu5": "매도호가 건수5",
"bidp_csnu1": "매수호가 건수1",
"bidp_csnu2": "매수호가 건수2",
"bidp_csnu3": "매수호가 건수3",
"bidp_csnu4": "매수호가 건수4",
"bidp_csnu5": "매수호가 건수5",
"askp_rsqn1": "매도호가 잔량1",
"askp_rsqn2": "매도호가 잔량2",
"askp_rsqn3": "매도호가 잔량3",
"askp_rsqn4": "매도호가 잔량4",
"askp_rsqn5": "매도호가 잔량5",
"bidp_rsqn1": "매수호가 잔량1",
"bidp_rsqn2": "매수호가 잔량2",
"bidp_rsqn3": "매수호가 잔량3",
"bidp_rsqn4": "매수호가 잔량4",
"bidp_rsqn5": "매수호가 잔량5",
"total_askp_csnu": "총 매도호가 건수",
"total_bidp_csnu": "총 매수호가 건수",
"total_askp_rsqn": "총 매도호가 잔량",
"total_bidp_rsqn": "총 매수호가 잔량",
"total_askp_rsqn_icdc": "총 매도호가 잔량 증감",
"total_bidp_rsqn_icdc": "총 매수호가 잔량 증감"
}
NUMERIC_COLUMNS = []
def main():
"""
지수선물 실시간호가
Returns:
None
"""
# 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")
# 조회
kws.subscribe(request=index_futures_realtime_quote, data=["101W09"])
# 결과 표시
def on_result(ws, tr_id: str, result: pd.DataFrame, data_map: dict):
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)
kws.start(on_result=on_result)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,97 @@
"""
Created on 20250601
"""
import logging
import sys
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > 지수선물 실시간호가[실시간-011]
##############################################################################################
def index_futures_realtime_quote(
tr_type: str,
tr_key: str,
) -> (dict, list[str]):
"""
지수선물 실시간호가 API입니다.
실시간 웹소켓 연결을 통해 지수선물의 실시간 호가 정보를 수신할 수 있습니다.
매도/매수 호가 1~5단계, 호가 건수, 호가 잔량 등의 상세 정보를 제공합니다.
선물옵션 호가 데이터는 0.2초 필터링 옵션이 적용됩니다.
실전계좌만 지원되며 모의투자는 미지원됩니다.
Args:
tr_type (str): [필수] 구독 등록/해제 여부 (ex. "1": 구독, "2": 해제)
tr_key (str): [필수] 코드 (ex. 101S12)
Returns:
message (str): 메시지 데이터
Example:
>>> msg, columns = index_futures_realtime_quote("1", "101S12")
>>> print(msg, columns)
"""
# 필수 파라미터 검증
if tr_type == "":
raise ValueError("tr_type is required")
if tr_key == "":
raise ValueError("tr_key is required")
tr_id = "H0IFASP0"
params = {
"tr_key": tr_key,
}
msg = ka.data_fetch(tr_id, tr_type, params)
columns = [
"futs_shrn_iscd",
"bsop_hour",
"futs_askp1",
"futs_askp2",
"futs_askp3",
"futs_askp4",
"futs_askp5",
"futs_bidp1",
"futs_bidp2",
"futs_bidp3",
"futs_bidp4",
"futs_bidp5",
"askp_csnu1",
"askp_csnu2",
"askp_csnu3",
"askp_csnu4",
"askp_csnu5",
"bidp_csnu1",
"bidp_csnu2",
"bidp_csnu3",
"bidp_csnu4",
"bidp_csnu5",
"askp_rsqn1",
"askp_rsqn2",
"askp_rsqn3",
"askp_rsqn4",
"askp_rsqn5",
"bidp_rsqn1",
"bidp_rsqn2",
"bidp_rsqn3",
"bidp_rsqn4",
"bidp_rsqn5",
"total_askp_csnu",
"total_bidp_csnu",
"total_askp_rsqn",
"total_bidp_rsqn",
"total_askp_rsqn_icdc",
"total_bidp_rsqn_icdc"
]
return msg, columns

View File

@@ -0,0 +1,124 @@
"""
Created on 20250601
"""
import logging
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from index_option_realtime_conclusion import index_option_realtime_conclusion
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > 지수옵션 실시간체결가[실시간-014]
##############################################################################################
COLUMN_MAPPING = {
"optn_shrn_iscd": "옵션 단축 종목코드",
"bsop_hour": "영업 시간",
"optn_prpr": "옵션 현재가",
"prdy_vrss_sign": "전일 대비 부호",
"optn_prdy_vrss": "옵션 전일 대비",
"prdy_ctrt": "전일 대비율",
"optn_oprc": "옵션 시가2",
"optn_hgpr": "옵션 최고가",
"optn_lwpr": "옵션 최저가",
"last_cnqn": "최종 거래량",
"acml_vol": "누적 거래량",
"acml_tr_pbmn": "누적 거래 대금",
"hts_thpr": "HTS 이론가",
"hts_otst_stpl_qty": "HTS 미결제 약정 수량",
"otst_stpl_qty_icdc": "미결제 약정 수량 증감",
"oprc_hour": "시가 시간",
"oprc_vrss_prpr_sign": "시가2 대비 현재가 부호",
"oprc_vrss_nmix_prpr": "시가 대비 지수 현재가",
"hgpr_hour": "최고가 시간",
"hgpr_vrss_prpr_sign": "최고가 대비 현재가 부호",
"hgpr_vrss_nmix_prpr": "최고가 대비 지수 현재가",
"lwpr_hour": "최저가 시간",
"lwpr_vrss_prpr_sign": "최저가 대비 현재가 부호",
"lwpr_vrss_nmix_prpr": "최저가 대비 지수 현재가",
"shnu_rate": "매수2 비율",
"prmm_val": "프리미엄 값",
"invl_val": "내재가치 값",
"tmvl_val": "시간가치 값",
"delta": "델타",
"gama": "감마",
"vega": "베가",
"theta": "세타",
"rho": "로우",
"hts_ints_vltl": "HTS 내재 변동성",
"esdg": "괴리도",
"otst_stpl_rgbf_qty_icdc": "미결제 약정 직전 수량 증감",
"thpr_basis": "이론 베이시스",
"unas_hist_vltl": "역사적변동성",
"cttr": "체결강도",
"dprt": "괴리율",
"mrkt_basis": "시장 베이시스",
"optn_askp1": "옵션 매도호가1",
"optn_bidp1": "옵션 매수호가1",
"askp_rsqn1": "매도호가 잔량1",
"bidp_rsqn1": "매수호가 잔량1",
"seln_cntg_csnu": "매도 체결 건수",
"shnu_cntg_csnu": "매수 체결 건수",
"ntby_cntg_csnu": "순매수 체결 건수",
"seln_cntg_smtn": "총 매도 수량",
"shnu_cntg_smtn": "총 매수 수량",
"total_askp_rsqn": "총 매도호가 잔량",
"total_bidp_rsqn": "총 매수호가 잔량",
"prdy_vol_vrss_acml_vol_rate": "전일 거래량 대비 등락율",
"avrg_vltl": "평균 변동성",
"dscs_lrqn_vol": "협의대량누적 거래량",
"dynm_mxpr": "실시간상한가",
"dynm_llam": "실시간하한가",
"dynm_prc_limt_yn": "실시간가격제한구분"
}
NUMERIC_COLUMNS = []
def main():
"""
지수옵션 실시간체결가
Returns:
None
"""
# 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")
# 조회
kws.subscribe(request=index_option_realtime_conclusion, data=["201W08427"])
# 결과 표시
def on_result(ws, tr_id: str, result: pd.DataFrame, data_map: dict):
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)
kws.start(on_result=on_result)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,121 @@
"""
Created on 20250601
"""
import logging
import sys
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > 지수옵션 실시간체결가[실시간-014]
##############################################################################################
def index_option_realtime_conclusion(
tr_type: str,
tr_key: str,
) -> (dict, list[str]):
"""
지수옵션 실시간체결가 API입니다.
실시간 웹소켓 연결을 통해 지수옵션의 실시간 체결가 정보를 수신할 수 있습니다.
옵션 현재가, 시고저가, 체결량, 누적거래량, 이론가 등의 기본 정보와 함께
델타, 감마, 베가, 세타, 로우 등의 그리스 지표와 내재가치, 시간가치, 변동성 정보를 제공합니다.
옵션 거래에 필수적인 전문 지표들을 포함하는 확장된 체결가 정보입니다.
실전계좌만 지원되며 모의투자는 미지원됩니다.
Args:
tr_type (str): [필수] 구독 등록/해제 여부 (ex. "1": 구독, "2": 해제)
tr_key (str): [필수] 코드 (ex. 201S11305)
Returns:
message (str): 메시지 데이터
Example:
>>> msg, columns = index_option_realtime_conclusion("1", "101W09")
>>> print(msg, columns)
"""
# 필수 파라미터 검증
if tr_type == "":
raise ValueError("tr_type is required")
if tr_type == "":
raise ValueError("tr_type is required")
if tr_key == "":
raise ValueError("tr_key is required")
tr_id = "H0IOCNT0"
params = {
"tr_key": tr_key,
}
msg = ka.data_fetch(tr_id, tr_type, params)
columns = [
"optn_shrn_iscd",
"bsop_hour",
"optn_prpr",
"prdy_vrss_sign",
"optn_prdy_vrss",
"prdy_ctrt",
"optn_oprc",
"optn_hgpr",
"optn_lwpr",
"last_cnqn",
"acml_vol",
"acml_tr_pbmn",
"hts_thpr",
"hts_otst_stpl_qty",
"otst_stpl_qty_icdc",
"oprc_hour",
"oprc_vrss_prpr_sign",
"oprc_vrss_nmix_prpr",
"hgpr_hour",
"hgpr_vrss_prpr_sign",
"hgpr_vrss_nmix_prpr",
"lwpr_hour",
"lwpr_vrss_prpr_sign",
"lwpr_vrss_nmix_prpr",
"shnu_rate",
"prmm_val",
"invl_val",
"tmvl_val",
"delta",
"gama",
"vega",
"theta",
"rho",
"hts_ints_vltl",
"esdg",
"otst_stpl_rgbf_qty_icdc",
"thpr_basis",
"unas_hist_vltl",
"cttr",
"dprt",
"mrkt_basis",
"optn_askp1",
"optn_bidp1",
"askp_rsqn1",
"bidp_rsqn1",
"seln_cntg_csnu",
"shnu_cntg_csnu",
"ntby_cntg_csnu",
"seln_cntg_smtn",
"shnu_cntg_smtn",
"total_askp_rsqn",
"total_bidp_rsqn",
"prdy_vol_vrss_acml_vol_rate",
"avrg_vltl",
"dscs_lrqn_vol",
"dynm_mxpr",
"dynm_llam",
"dynm_prc_limt_yn"
]
return msg, columns

View File

@@ -0,0 +1,104 @@
"""
Created on 20250601
"""
import logging
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from index_option_realtime_quote import index_option_realtime_quote
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > 지수옵션 실시간호가[실시간-015]
##############################################################################################
COLUMN_MAPPING = {
"optn_shrn_iscd": "옵션 단축 종목코드",
"bsop_hour": "영업 시간",
"optn_askp1": "옵션 매도호가1",
"optn_askp2": "옵션 매도호가2",
"optn_askp3": "옵션 매도호가3",
"optn_askp4": "옵션 매도호가4",
"optn_askp5": "옵션 매도호가5",
"optn_bidp1": "옵션 매수호가1",
"optn_bidp2": "옵션 매수호가2",
"optn_bidp3": "옵션 매수호가3",
"optn_bidp4": "옵션 매수호가4",
"optn_bidp5": "옵션 매수호가5",
"askp_csnu1": "매도호가 건수1",
"askp_csnu2": "매도호가 건수2",
"askp_csnu3": "매도호가 건수3",
"askp_csnu4": "매도호가 건수4",
"askp_csnu5": "매도호가 건수5",
"bidp_csnu1": "매수호가 건수1",
"bidp_csnu2": "매수호가 건수2",
"bidp_csnu3": "매수호가 건수3",
"bidp_csnu4": "매수호가 건수4",
"bidp_csnu5": "매수호가 건수5",
"askp_rsqn1": "매도호가 잔량1",
"askp_rsqn2": "매도호가 잔량2",
"askp_rsqn3": "매도호가 잔량3",
"askp_rsqn4": "매도호가 잔량4",
"askp_rsqn5": "매도호가 잔량5",
"bidp_rsqn1": "매수호가 잔량1",
"bidp_rsqn2": "매수호가 잔량2",
"bidp_rsqn3": "매수호가 잔량3",
"bidp_rsqn4": "매수호가 잔량4",
"bidp_rsqn5": "매수호가 잔량5",
"total_askp_csnu": "총 매도호가 건수",
"total_bidp_csnu": "총 매수호가 건수",
"total_askp_rsqn": "총 매도호가 잔량",
"total_bidp_rsqn": "총 매수호가 잔량",
"total_askp_rsqn_icdc": "총 매도호가 잔량 증감",
"total_bidp_rsqn_icdc": "총 매수호가 잔량 증감"
}
NUMERIC_COLUMNS = []
def main():
"""
지수옵션 실시간호가
Returns:
None
"""
# 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")
# 조회
kws.subscribe(request=index_option_realtime_quote, data=["201W08427"])
# 결과 표시
def on_result(ws, tr_id: str, result: pd.DataFrame, data_map: dict):
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)
kws.start(on_result=on_result)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,95 @@
"""
Created on 20250601
"""
import logging
import sys
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > 지수옵션 실시간호가[실시간-015]
##############################################################################################
def index_option_realtime_quote(
tr_type: str,
tr_key: str,
) -> (dict, list[str]):
"""
지수옵션 실시간호가 API입니다.
실시간 웹소켓 연결을 통해 지수옵션 매도/매수 호가 정보를 실시간으로 수신할 수 있습니다.
실전계좌만 지원되며, 모의투자는 지원하지 않습니다.
Args:
tr_type (str): [필수] 구독 등록/해제 여부 (ex. "1": 구독, "2": 해제)
tr_key (str): [필수] 코드 (ex. 201S11305)
Returns:
message (str): 메시지 데이터
Example:
>>> msg, columns = index_option_realtime_quote("1", "201S11305")
>>> print(msg, columns)
"""
# 필수 파라미터 검증
if tr_type == "":
raise ValueError("tr_type is required")
if tr_key == "":
raise ValueError("tr_key is required")
tr_id = "H0IOASP0"
params = {
"tr_key": tr_key,
}
msg = ka.data_fetch(tr_id, tr_type, params)
columns = [
"optn_shrn_iscd",
"bsop_hour",
"optn_askp1",
"optn_askp2",
"optn_askp3",
"optn_askp4",
"optn_askp5",
"optn_bidp1",
"optn_bidp2",
"optn_bidp3",
"optn_bidp4",
"optn_bidp5",
"askp_csnu1",
"askp_csnu2",
"askp_csnu3",
"askp_csnu4",
"askp_csnu5",
"bidp_csnu1",
"bidp_csnu2",
"bidp_csnu3",
"bidp_csnu4",
"bidp_csnu5",
"askp_rsqn1",
"askp_rsqn2",
"askp_rsqn3",
"askp_rsqn4",
"askp_rsqn5",
"bidp_rsqn1",
"bidp_rsqn2",
"bidp_rsqn3",
"bidp_rsqn4",
"bidp_rsqn5",
"total_askp_csnu",
"total_bidp_csnu",
"total_askp_rsqn",
"total_bidp_rsqn",
"total_askp_rsqn_icdc",
"total_bidp_rsqn_icdc"
]
return msg, columns

View File

@@ -0,0 +1,129 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from inquire_asking_price import inquire_asking_price
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 기본시세 > 선물옵션 시세호가[v1_국내선물-007]
##############################################################################################
COLUMN_MAPPING = {
'hts_kor_isnm': 'HTS 한글 종목명',
'futs_prpr': '선물 현재가',
'prdy_vrss_sign': '전일 대비 부호',
'futs_prdy_vrss': '선물 전일 대비',
'futs_prdy_ctrt': '선물 전일 대비율',
'acml_vol': '누적 거래량',
'futs_prdy_clpr': '선물 전일 종가',
'futs_shrn_iscd': '선물 단축 종목코드',
'futs_askp1': '선물 매도호가1',
'futs_askp2': '선물 매도호가2',
'futs_askp3': '선물 매도호가3',
'futs_askp4': '선물 매도호가4',
'futs_askp5': '선물 매도호가5',
'futs_bidp1': '선물 매수호가1',
'futs_bidp2': '선물 매수호가2',
'futs_bidp3': '선물 매수호가3',
'futs_bidp4': '선물 매수호가4',
'futs_bidp5': '선물 매수호가5',
'askp_rsqn1': '매도호가 잔량1',
'askp_rsqn2': '매도호가 잔량2',
'askp_rsqn3': '매도호가 잔량3',
'askp_rsqn4': '매도호가 잔량4',
'askp_rsqn5': '매도호가 잔량5',
'bidp_rsqn1': '매수호가 잔량1',
'bidp_rsqn2': '매수호가 잔량2',
'bidp_rsqn3': '매수호가 잔량3',
'bidp_rsqn4': '매수호가 잔량4',
'bidp_rsqn5': '매수호가 잔량5',
'askp_csnu1': '매도호가 건수1',
'askp_csnu2': '매도호가 건수2',
'askp_csnu3': '매도호가 건수3',
'askp_csnu4': '매도호가 건수4',
'askp_csnu5': '매도호가 건수5',
'bidp_csnu1': '매수호가 건수1',
'bidp_csnu2': '매수호가 건수2',
'bidp_csnu3': '매수호가 건수3',
'bidp_csnu4': '매수호가 건수4',
'bidp_csnu5': '매수호가 건수5',
'total_askp_rsqn': '총 매도호가 잔량',
'total_bidp_rsqn': '총 매수호가 잔량',
'total_askp_csnu': '총 매도호가 건수',
'total_bidp_csnu': '총 매수호가 건수',
'aspr_acpt_hour': '호가 접수 시간'
}
NUMERIC_COLUMNS = []
def main():
"""
선물옵션 시세호가 조회 테스트 함수
이 함수는 선물옵션 시세호가 API를 호출하여 결과를 출력합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
# case1 조회
logging.info("=== case1 조회 ===")
try:
result1, result2 = inquire_asking_price(fid_cond_mrkt_div_code="F", fid_input_iscd="101W09", env_dv="real")
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
# output1 결과 처리
logging.info("=== output1 결과 ===")
logging.info("사용 가능한 컬럼: %s", result1.columns.tolist())
# 컬럼명 한글 변환
result1 = result1.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시 (메타데이터에 number 자료형이 명시된 필드 없음)
for col in NUMERIC_COLUMNS:
if col in result1.columns:
result1[col] = pd.to_numeric(result1[col], errors='coerce').round(2)
logging.info("결과:")
print(result1)
# output2 결과 처리
logging.info("=== output2 결과 ===")
logging.info("사용 가능한 컬럼: %s", result2.columns.tolist())
# 컬럼명 한글 변환
result2 = result2.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시 (메타데이터에 number 자료형이 명시된 필드 없음)
for col in NUMERIC_COLUMNS:
if col in result2.columns:
result2[col] = pd.to_numeric(result2[col], errors='coerce').round(2)
logging.info("결과:")
print(result2)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,81 @@
"""
Created on 20250601
"""
import sys
import logging
from typing import Tuple
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 기본시세 > 선물옵션 시세호가[v1_국내선물-007]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/quotations/inquire-asking-price"
def inquire_asking_price(
fid_cond_mrkt_div_code: str, # [필수] FID 조건 시장 분류 코드 (ex. F: 지수선물, JF: 주식선물)
fid_input_iscd: str, # [필수] FID 입력 종목코드 (ex. 101S03)
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'")
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()

View File

@@ -0,0 +1,136 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from inquire_balance import inquire_balance
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 잔고현황[v1_국내선물-004]
##############################################################################################
COLUMN_MAPPING = {
'cano': '종합계좌번호',
'acnt_prdt_cd': '계좌상품코드',
'pdno': '상품번호',
'prdt_type_cd': '상품유형코드',
'shtn_pdno': '단축상품번호',
'prdt_name': '상품명',
'sll_buy_dvsn_name': '매도매수구분명',
'cblc_qty': '잔고수량',
'excc_unpr': '정산단가',
'ccld_avg_unpr1': '체결평균단가1',
'idx_clpr': '지수종가',
'pchs_amt': '매입금액',
'evlu_amt': '평가금액',
'evlu_pfls_amt': '평가손익금액',
'trad_pfls_amt': '매매손익금액',
'lqd_psbl_qty': '청산가능수량',
'dnca_cash': '예수금현금',
'frcr_dncl_amt': '외화예수금액',
'dnca_sbst': '예수금대용',
'tot_dncl_amt': '총예수금액',
'tot_ccld_amt': '총체결금액',
'cash_mgna': '현금증거금',
'sbst_mgna': '대용증거금',
'mgna_tota': '증거금총액',
'opt_dfpa': '옵션차금',
'thdt_dfpa': '당일차금',
'rnwl_dfpa': '갱신차금',
'fee': '수수료',
'nxdy_dnca': '익일예수금',
'nxdy_dncl_amt': '익일예수금액',
'prsm_dpast': '추정예탁자산',
'prsm_dpast_amt': '추정예탁자산금액',
'pprt_ord_psbl_cash': '적정주문가능현금',
'add_mgna_cash': '추가증거금현금',
'add_mgna_tota': '추가증거금총액',
'futr_trad_pfls_amt': '선물매매손익금액',
'opt_trad_pfls_amt': '옵션매매손익금액',
'futr_evlu_pfls_amt': '선물평가손익금액',
'opt_evlu_pfls_amt': '옵션평가손익금액',
'trad_pfls_amt_smtl': '매매손익금액합계',
'evlu_pfls_amt_smtl': '평가손익금액합계',
'wdrw_psbl_tot_amt': '인출가능총금액',
'ord_psbl_cash': '주문가능현금',
'ord_psbl_sbst': '주문가능대용',
'ord_psbl_tota': '주문가능총액',
'pchs_amt_smtl': '매입금액합계',
'evlu_amt_smtl': '평가금액합계'
}
NUMERIC_COLUMNS = []
def main():
"""
선물옵션 잔고현황 조회 테스트 함수
이 함수는 선물옵션 잔고현황 API를 호출하여 결과를 출력합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
trenv = ka.getTREnv()
# case1 조회
logging.info("=== case1 조회 ===")
try:
result1, result2 = inquire_balance(env_dv="real", cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, mgna_dvsn="01",
excc_stat_cd="1")
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
# output1 결과 처리
logging.info("=== output1 결과 ===")
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result1)
# output2 결과 처리
logging.info("=== output2 결과 ===")
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result2)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,138 @@
"""
Created on 20250601
"""
import sys
import time
from typing import Optional, Tuple
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 잔고현황[v1_국내선물-004]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/trading/inquire-balance"
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'")
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()

View File

@@ -0,0 +1,109 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from inquire_balance_settlement_pl import inquire_balance_settlement_pl
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 잔고정산손익내역[v1_국내선물-013]
##############################################################################################
COLUMN_MAPPING = {
'pdno': '상품번호',
'prdt_name': '상품명',
'trad_dvsn_name': '매매구분명',
'bfdy_cblc_qty': '전일잔고수량',
'new_qty': '신규수량',
'mnpl_rpch_qty': '전매환매수량',
'cblc_qty': '잔고수량',
'cblc_amt': '잔고금액',
'trad_pfls_amt': '매매손익금액',
'evlu_amt': '평가금액',
'evlu_pfls_amt': '평가손익금액',
'nxdy_dnca': '익일예수금',
'mmga_cash': '유지증거금현금',
'brkg_mgna_cash': '위탁증거금현금',
'opt_buy_chgs': '옵션매수대금',
'opt_lqd_evlu_amt': '옵션청산평가금액',
'dnca_sbst': '예수금대용',
'mmga_tota': '유지증거금총액',
'brkg_mgna_tota': '위탁증거금총액',
'opt_sll_chgs': '옵션매도대금',
'fee': '수수료',
'thdt_dfpa': '당일차금',
'rnwl_dfpa': '갱신차금',
'dnca_cash': '예수금현금'
}
NUMERIC_COLUMNS = []
def main():
"""
선물옵션 잔고정산손익내역 조회 테스트 함수
이 함수는 선물옵션 잔고정산손익내역 API를 호출하여 결과를 출력합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
trenv = ka.getTREnv()
# Case 1
logging.info("=== Case 1 ===")
try:
result1, result2 = inquire_balance_settlement_pl(cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, inqr_dt="20230906")
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
logging.info("사용 가능한 컬럼 (output1): %s", result1.columns.tolist())
# 컬럼명 한글 변환 및 데이터 출력 (output1)
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)
logging.info("결과 (output1):")
print(result1)
logging.info("사용 가능한 컬럼 (output2): %s", result2.columns.tolist())
# 컬럼명 한글 변환 및 데이터 출력 (output2)
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)
logging.info("결과 (output2):")
print(result2)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,120 @@
"""
Created on 20250601
"""
import sys
import time
from typing import Optional, Tuple
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 잔고정산손익내역[v1_국내선물-013]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/trading/inquire-balance-settlement-pl"
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"
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()

View File

@@ -0,0 +1,134 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from inquire_balance_valuation_pl import inquire_balance_valuation_pl
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 잔고평가손익내역[v1_국내선물-015]
##############################################################################################
COLUMN_MAPPING = {
'cano': '종합계좌번호',
'acnt_prdt_cd': '계좌상품코드',
'pdno': '상품번호',
'prdt_type_cd': '상품유형코드',
'shtn_pdno': '단축상품번호',
'prdt_name': '상품명',
'sll_buy_dvsn_name': '매도매수구분명',
'cblc_qty1': '잔고수량1',
'excc_unpr': '정산단가',
'ccld_avg_unpr1': '체결평균단가1',
'idx_clpr': '지수종가',
'pchs_amt': '매입금액',
'evlu_amt': '평가금액',
'evlu_pfls_amt': '평가손익금액',
'trad_pfls_amt': '매매손익금액',
'lqd_psbl_qty': '청산가능수량',
'dnca_cash': '예수금현금',
'frcr_dncl_amt': '외화예수금액',
'dnca_sbst': '예수금대용',
'tot_dncl_amt': '총예수금액',
'tot_ccld_amt': '총체결금액',
'cash_mgna': '현금증거금',
'sbst_mgna': '대용증거금',
'mgna_tota': '증거금총액',
'opt_dfpa': '옵션차금',
'thdt_dfpa': '당일차금',
'rnwl_dfpa': '갱신차금',
'fee': '수수료',
'nxdy_dnca': '익일예수금',
'nxdy_dncl_amt': '익일예수금액',
'prsm_dpast': '추정예탁자산',
'prsm_dpast_amt': '추정예탁자산금액',
'pprt_ord_psbl_cash': '적정주문가능현금',
'add_mgna_cash': '추가증거금현금',
'add_mgna_tota': '추가증거금총액',
'futr_trad_pfls_amt': '선물매매손익금액',
'opt_trad_pfls_amt': '옵션매매손익금액',
'futr_evlu_pfls_amt': '선물평가손익금액',
'opt_evlu_pfls_amt': '옵션평가손익금액',
'trad_pfls_amt_smtl': '매매손익금액합계',
'evlu_pfls_amt_smtl': '평가손익금액합계',
'wdrw_psbl_tot_amt': '인출가능총금액',
'ord_psbl_cash': '주문가능현금',
'ord_psbl_sbst': '주문가능대용',
'ord_psbl_tota': '주문가능총액'
}
NUMERIC_COLUMNS = []
def main():
"""
선물옵션 잔고평가손익내역 조회 테스트 함수
이 함수는 선물옵션 잔고평가손익내역 API를 호출하여 결과를 출력합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
trenv = ka.getTREnv()
# case1 조회
logging.info("=== case1 조회 ===")
try:
result1, result2 = inquire_balance_valuation_pl(cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, mgna_dvsn="01",
excc_stat_cd="1")
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
# output1 처리
logging.info("=== output1 결과 ===")
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result1)
# output2 처리
logging.info("=== output2 결과 ===")
logging.info("사용 가능한 컬럼: %s" % 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)
logging.info("결과:")
print(result2)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,129 @@
"""
Created on 20250601
"""
import sys
import time
from typing import Optional, Tuple
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 잔고평가손익내역[v1_국내선물-015]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/trading/inquire-balance-valuation-pl"
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" # 선물옵션 잔고평가손익내역
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()

View File

@@ -0,0 +1,128 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from inquire_ccnl import inquire_ccnl
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 주문체결내역조회[v1_국내선물-003]
##############################################################################################
COLUMN_MAPPING = {
'ord_gno_brno': '주문채번지점번호',
'cano': '종합계좌번호',
'csac_name': '종합계좌명',
'acnt_prdt_cd': '계좌상품코드',
'ord_dt': '주문일자',
'odno': '주문번호',
'orgn_odno': '원주문번호',
'sll_buy_dvsn_cd': '매도매수구분코드',
'trad_dvsn_name': '매매구분명',
'nmpr_type_cd': '호가유형코드',
'nmpr_type_name': '호가유형명',
'pdno': '상품번호',
'prdt_name': '상품명',
'prdt_type_cd': '상품유형코드',
'ord_qty': '주문수량',
'ord_idx': '주문지수',
'qty': '잔량',
'ord_tmd': '주문시각',
'tot_ccld_qty': '총체결수량',
'avg_idx': '평균지수',
'tot_ccld_amt': '총체결금액',
'rjct_qty': '거부수량',
'ingr_trad_rjct_rson_cd': '장내매매거부사유코드',
'ingr_trad_rjct_rson_name': '장내매매거부사유명',
'ord_stfno': '주문직원번호',
'sprd_item_yn': '스프레드종목여부',
'ord_ip_addr': '주문IP주소',
'tot_ord_qty': '총주문수량',
'tot_ccld_amt_smtl': '총체결금액합계',
'tot_ccld_qty_smtl': '총체결수량합계',
'fee_smtl': '수수료합계',
'ctac_tlno': '연락전화번호'
}
NUMERIC_COLUMNS = []
def main():
"""
선물옵션 주문체결내역조회 테스트 함수
이 함수는 선물옵션 주문체결내역조회 API를 호출하여 결과를 출력합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
trenv = ka.getTREnv()
# case1 조회
logging.info("=== case1 조회 ===")
try:
result1, result2 = 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"
)
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
# output1 결과 처리
logging.info("=== output1 결과 ===")
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result1)
# output2 결과 처리
logging.info("=== output2 결과 ===")
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result2)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,172 @@
"""
Created on 20250601
"""
import sys
import time
from typing import Optional, Tuple
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 주문체결내역조회[v1_국내선물-003]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/trading/inquire-ccnl"
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'")
# 파라미터 설정
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()

View File

@@ -0,0 +1,108 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from inquire_ccnl_bstime import inquire_ccnl_bstime
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 기준일체결내역[v1_국내선물-016]
##############################################################################################
COLUMN_MAPPING = {
'pdno': '상품번호',
'prdt_name': '상품명',
'odno': '주문번호',
'tr_type_name': '거래유형명',
'last_sttldt': '최종결제일',
'ccld_idx': '체결지수',
'ccld_qty': '체결량',
'trad_amt': '매매금액',
'fee': '수수료',
'ccld_btwn': '체결시간',
'tot_ccld_qty_smtl': '총체결수량합계',
'tot_ccld_amt_smtl': '총체결금액합계',
'fee_adjt': '수수료조정',
'fee_smtl': '수수료합계'
}
NUMERIC_COLUMNS = []
def main():
"""
선물옵션 기준일체결내역 조회 테스트 함수
이 함수는 선물옵션 기준일체결내역 API를 호출하여 결과를 출력합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
trenv = ka.getTREnv()
# case1 조회
logging.info("=== case1 조회 ===")
try:
result1, result2 = 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"
)
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
# output1 처리
logging.info("=== output1 결과 ===")
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result1)
# output2 처리
logging.info("=== output2 결과 ===")
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result2)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,134 @@
"""
Created on 20250601
"""
import sys
import time
from typing import Optional, Tuple
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 기준일체결내역[v1_국내선물-016]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/trading/inquire-ccnl-bstime"
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"
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()

View File

@@ -0,0 +1,127 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from inquire_daily_amount_fee import inquire_daily_amount_fee
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션기간약정수수료일별[v1_국내선물-017]
##############################################################################################
COLUMN_MAPPING = {
'ord_dt': '주문일자',
'pdno': '상품번호',
'item_name': '종목명',
'sll_agrm_amt': '매도약정금액',
'sll_fee': '매도수수료',
'buy_agrm_amt': '매수약정금액',
'buy_fee': '매수수수료',
'tot_fee_smtl': '총수수료합계',
'trad_pfls': '매매손익',
'futr_agrm': '선물약정',
'futr_agrm_amt': '선물약정금액',
'futr_agrm_amt_smtl': '선물약정금액합계',
'futr_sll_fee_smtl': '선물매도수수료합계',
'futr_buy_fee_smtl': '선물매수수수료합계',
'futr_fee_smtl': '선물수수료합계',
'opt_agrm': '옵션약정',
'opt_agrm_amt': '옵션약정금액',
'opt_agrm_amt_smtl': '옵션약정금액합계',
'opt_sll_fee_smtl': '옵션매도수수료합계',
'opt_buy_fee_smtl': '옵션매수수수료합계',
'opt_fee_smtl': '옵션수수료합계',
'prdt_futr_agrm': '상품선물약정',
'prdt_fuop': '상품선물옵션',
'prdt_futr_evlu_amt': '상품선물평가금액',
'futr_fee': '선물수수료',
'opt_fee': '옵션수수료',
'fee': '수수료',
'sll_agrm_amt': '매도약정금액',
'buy_agrm_amt': '매수약정금액',
'agrm_amt_smtl': '약정금액합계',
'sll_fee': '매도수수료',
'buy_fee': '매수수수료',
'fee_smtl': '수수료합계',
'trad_pfls_smtl': '매매손익합계'
}
NUMERIC_COLUMNS = []
def main():
"""
선물옵션기간약정수수료일별 조회 테스트 함수
이 함수는 선물옵션기간약정수수료일별 API를 호출하여 결과를 출력합니다.
테스트 데이터로 메타데이터에서 제공하는 case1 데이터를 사용합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
trenv = ka.getTREnv()
# case1 조회
logging.info("=== case1 조회 ===")
try:
result1, result2 = inquire_daily_amount_fee(
cano=trenv.my_acct,
acnt_prdt_cd=trenv.my_prod,
inqr_strt_day="20240401",
inqr_end_day="20240625"
)
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
# output1 블록
logging.info("=== output1 결과 ===")
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result1)
# output2 블록
logging.info("=== output2 결과 ===")
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result2)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,127 @@
"""
Created on 20250601
"""
import sys
import time
from typing import Optional, Tuple
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션기간약정수수료일별[v1_국내선물-017]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/trading/inquire-daily-amount-fee"
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" # 선물옵션기간약정수수료일별
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()

View File

@@ -0,0 +1,130 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from inquire_daily_fuopchartprice import inquire_daily_fuopchartprice
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 기본시세 > 선물옵션기간별시세(일/주/월/년)[v1_국내선물-008]
##############################################################################################
COLUMN_MAPPING = {
'futs_prdy_vrss': '전일 대비',
'prdy_vrss_sign': '전일 대비 부호',
'futs_prdy_ctrt': '선물 전일 대비율',
'futs_prdy_clpr': '선물 전일 종가',
'acml_vol': '누적 거래량',
'acml_tr_pbmn': '누적 거래 대금',
'hts_kor_isnm': 'HTS 한글 종목명',
'futs_prpr': '현재가',
'futs_shrn_iscd': '단축 종목코드',
'prdy_vol': '전일 거래량',
'futs_mxpr': '상한가',
'futs_llam': '하한가',
'futs_oprc': '시가',
'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': '전일 대비 부호',
'hts_otst_stpl_qty': 'HTS 미결제 약정 수량',
'otst_stpl_qty_icdc': '미결제 약정 수량 증감',
'tday_rltv': '당일 체결강도',
'hts_thpr': 'HTS 이론가',
'dprt': '괴리율',
'stck_bsop_date': '영업 일자',
'futs_prpr': '현재가',
'futs_oprc': '시가',
'futs_hgpr': '최고가',
'futs_lwpr': '최저가',
'acml_vol': '누적 거래량',
'acml_tr_pbmn': '누적 거래 대금',
'mod_yn': '변경 여부'
}
NUMERIC_COLUMNS = []
def main():
"""
선물옵션기간별시세 조회 테스트 함수
이 함수는 선물옵션기간별시세 API를 호출하여 결과를 출력합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
# case1 조회
logging.info("=== case1 조회 ===")
try:
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"
)
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
# output1 처리
logging.info("=== output1 결과 ===")
logging.info("사용 가능한 컬럼: %s", output1.columns.tolist())
# 컬럼명 한글 변환 및 데이터 출력
output1 = output1.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시
for col in NUMERIC_COLUMNS:
if col in output1.columns:
output1[col] = pd.to_numeric(output1[col], errors='coerce').round(2)
logging.info("결과:")
print(output1)
# output2 처리
logging.info("=== output2 결과 ===")
logging.info("사용 가능한 컬럼: %s" % output2.columns.tolist())
# 컬럼명 한글 변환 및 데이터 출력
output2 = output2.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시
for col in NUMERIC_COLUMNS:
if col in output2.columns:
output2[col] = pd.to_numeric(output2[col], errors='coerce').round(2)
logging.info("결과:")
print(output2)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,109 @@
"""
Created on 20250601
"""
import sys
from typing import Tuple
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 기본시세 > 선물옵션기간별시세(일/주/월/년)[v1_국내선물-008]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/quotations/inquire-daily-fuopchartprice"
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. 20220301)
fid_input_date_2 (str): [필수] 조회 종료일자 (ex. 20220810)
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'")
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()

View File

@@ -0,0 +1,102 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from inquire_deposit import inquire_deposit
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 총자산현황[v1_국내선물-014]
##############################################################################################
COLUMN_MAPPING = {
'dnca_tota': '예수금총액',
'bfdy_chck_amt': '전일수표금액',
'thdt_chck_amt': '당일수표금액',
'rlth_uwdl_dpos_amt': '실물인수도예치금액',
'brkg_mgna_cash': '위탁증거금현금',
'wdrw_psbl_tot_amt': '인출가능총금액',
'ord_psbl_cash': '주문가능현금',
'ord_psbl_tota': '주문가능총액',
'dnca_sbst': '예수금대용',
'scts_sbst_amt': '유가증권대용금액',
'frcr_evlu_amt': '외화평가금액',
'brkg_mgna_sbst': '위탁증거금대용',
'sbst_rlse_psbl_amt': '대용해제가능금액',
'mtnc_rt': '유지비율',
'add_mgna_tota': '추가증거금총액',
'add_mgna_cash': '추가증거금현금',
'rcva': '미수금',
'futr_trad_pfls': '선물매매손익',
'opt_trad_pfls_amt': '옵션매매손익금액',
'trad_pfls_smtl': '매매손익합계',
'futr_evlu_pfls_amt': '선물평가손익금액',
'opt_evlu_pfls_amt': '옵션평가손익금액',
'evlu_pfls_smtl': '평가손익합계',
'excc_dfpa': '정산차금',
'opt_dfpa': '옵션차금',
'brkg_fee': '위탁수수료',
'nxdy_dnca': '익일예수금',
'prsm_dpast_amt': '추정예탁자산금액',
'cash_mntn_amt': '현금유지금액',
'hack_acdt_acnt_move_amt': '해킹사고계좌이전금액'
}
NUMERIC_COLUMNS = []
def main():
"""
선물옵션 총자산현황 조회 테스트 함수
이 함수는 선물옵션 총자산현황 API를 호출하여 결과를 출력합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
trenv = ka.getTREnv()
# case1 조회
logging.info("=== case1 조회 ===")
try:
result = inquire_deposit(cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod)
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,64 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 총자산현황[v1_국내선물-014]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/trading/inquire-deposit"
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" # 선물옵션 총자산현황
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()

View File

@@ -0,0 +1,144 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from inquire_ngt_balance import inquire_ngt_balance
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > (야간)선물옵션 잔고현황 [국내선물-010]
##############################################################################################
COLUMN_MAPPING = {
'cano': '종합계좌번호',
'acnt_prdt_cd': '계좌상품코드',
'pdno': '상품번호',
'prdt_type_cd': '상품유형코드',
'shtn_pdno': '단축상품번호',
'prdt_name': '상품명',
'sll_buy_dvsn_name': '매도매수구분명',
'sll_buy_dvsn_cd': '매도매수구분코드',
'trad_dvsn_name': '매매구분명',
'cblc_qty': '잔고수량',
'excc_unpr': '정산단가',
'ccld_avg_unpr1': '체결평균단가1',
'idx_clpr': '지수종가',
'pchs_amt': '매입금액',
'evlu_amt': '평가금액',
'evlu_pfls_amt': '평가손익금액',
'trad_pfls_amt': '매매손익금액',
'lqd_psbl_qty': '청산가능수량',
'dnca_cash': '예수금현금',
'frcr_dncl_amt': '외화예수금액',
'dnca_sbst': '예수금대용',
'tot_dncl_amt': '총예수금액',
'cash_mgna': '현금증거금',
'sbst_mgna': '대용증거금',
'mgna_tota': '증거금총액',
'opt_dfpa': '옵션차금',
'thdt_dfpa': '당일차금',
'rnwl_dfpa': '갱신차금',
'fee': '수수료',
'nxdy_dnca': '익일예수금',
'nxdy_dncl_amt': '익일예수금액',
'prsm_dpast': '추정예탁자산',
'pprt_ord_psbl_cash': '적정주문가능현금',
'add_mgna_cash': '추가증거금현금',
'add_mgna_tota': '추가증거금총액',
'futr_trad_pfls_amt': '선물매매손익금액',
'opt_trad_pfls_amt': '옵션매매손익금액',
'futr_evlu_pfls_amt': '선물평가손익금액',
'opt_evlu_pfls_amt': '옵션평가손익금액',
'trad_pfls_amt_smtl': '매매손익금액합계',
'evlu_pfls_amt_smtl': '평가손익금액합계',
'wdrw_psbl_tot_amt': '인출가능총금액',
'ord_psbl_cash': '주문가능현금',
'ord_psbl_sbst': '주문가능대용',
'ord_psbl_tota': '주문가능총액',
'mmga_tot_amt': '유지증거금총금액',
'mmga_cash_amt': '유지증거금현금금액',
'mtnc_rt': '유지비율',
'isfc_amt': '부족금액',
'pchs_amt_smtl': '매입금액합계',
'evlu_amt_smtl': '평가금액합계'
}
NUMERIC_COLUMNS = []
def main():
"""
(야간)선물옵션 잔고현황 조회 테스트 함수
이 함수는 (야간)선물옵션 잔고현황 API를 호출하여 결과를 출력합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
trenv = ka.getTREnv()
# Case 1 조회
logging.info("=== Case 1 조회 ===")
try:
result1, result2 = inquire_ngt_balance(
cano=trenv.my_acct,
acnt_prdt_cd=trenv.my_prod,
mgna_dvsn="01",
excc_stat_cd="1"
)
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
# output1 결과 처리
logging.info("=== output1 결과 ===")
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result1)
# output2 결과 처리
logging.info("=== output2 결과 ===")
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result2)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,131 @@
"""
Created on 20250601
"""
import sys
import time
from typing import Optional, Tuple
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > (야간)선물옵션 잔고현황 [국내선물-010]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/trading/inquire-ngt-balance"
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"
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())

View File

@@ -0,0 +1,122 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from inquire_ngt_ccnl import inquire_ngt_ccnl
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > (야간)선물옵션 주문체결 내역조회 [국내선물-009]
##############################################################################################
COLUMN_MAPPING = {
'ord_gno_brno': '주문채번지점번호',
'cano': '종합계좌번호',
'csac_name': '종합계좌명',
'acnt_prdt_cd': '계좌상품코드',
'ord_dt': '주문일자',
'odno': '주문번호',
'orgn_odno': '원주문번호',
'sll_buy_dvsn_cd': '매도매수구분코드',
'trad_dvsn_name': '매매구분명',
'nmpr_type_name': '호가유형명',
'pdno': '상품번호',
'prdt_name': '상품명',
'prdt_type_cd': '상품유형코드',
'ord_qty': '주문수량',
'ord_idx4': '주문지수',
'qty': '잔량',
'ord_tmd': '주문시각',
'tot_ccld_qty': '총체결수량',
'avg_idx': '평균지수',
'tot_ccld_amt': '총체결금액',
'rjct_qty': '거부수량',
'ingr_trad_rjct_rson_cd': '장내매매거부사유코드',
'ingr_trad_rjct_rson_name': '장내매매거부사유명',
'ord_stfno': '주문직원번호',
'sprd_item_yn': '스프레드종목여부',
'ord_ip_addr': '주문IP주소',
'tot_ord_qty': '총주문수량',
'tot_ccld_qty': '총체결수량',
'tot_ccld_qty_SMTL': '총체결수량',
'tot_ccld_amt': '총체결금액',
'tot_ccld_amt_SMTL': '총체결금액',
'fee': '수수료',
'ctac_tlno': '연락전화번호'
}
NUMERIC_COLUMNS = []
def main():
"""
(야간)선물옵션 주문체결 내역조회 테스트 함수
이 함수는 (야간)선물옵션 주문체결 내역조회 API를 호출하여 결과를 출력합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
trenv = ka.getTREnv()
# case1 조회
logging.info("=== case1 조회 ===")
try:
result1, result2 = inquire_ngt_ccnl(cano=trenv.my_acct, acnt_prdt_cd=trenv.my_prod, strt_ord_dt="20250610",
end_ord_dt="20250613", sll_buy_dvsn_cd="00", ccld_nccs_dvsn="00")
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
# output1 처리
logging.info("=== output1 결과 ===")
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result1)
# output2 처리
logging.info("=== output2 결과 ===")
logging.info("사용 가능한 컬럼: %s" % 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)
logging.info("결과:")
print(result2)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,164 @@
"""
Created on 20250601
"""
import sys
import time
from typing import Optional, Tuple
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > (야간)선물옵션 주문체결 내역조회 [국내선물-009]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/trading/inquire-ngt-ccnl"
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"
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()

View File

@@ -0,0 +1,145 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from inquire_price import inquire_price
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 기본시세 > 선물옵션 시세[v1_국내선물-006]
##############################################################################################
COLUMN_MAPPING = {
'hts_kor_isnm': 'HTS 한글 종목명',
'futs_prpr': '선물 현재가',
'futs_prdy_vrss': '선물 전일 대비',
'prdy_vrss_sign': '전일 대비 부호',
'futs_prdy_clpr': '선물 전일 종가',
'futs_prdy_ctrt': '선물 전일 대비율',
'acml_vol': '누적 거래량',
'acml_tr_pbmn': '누적 거래 대금',
'hts_otst_stpl_qty': 'HTS 미결제 약정 수량',
'otst_stpl_qty_icdc': '미결제 약정 수량 증감',
'futs_oprc': '선물 시가2',
'futs_hgpr': '선물 최고가',
'futs_lwpr': '선물 최저가',
'futs_mxpr': '선물 상한가',
'futs_llam': '선물 하한가',
'basis': '베이시스',
'futs_sdpr': '선물 기준가',
'hts_thpr': 'HTS 이론가',
'dprt': '괴리율',
'crbr_aply_mxpr': '서킷브레이커 적용 상한가',
'crbr_aply_llam': '서킷브레이커 적용 하한가',
'futs_last_tr_date': '선물 최종 거래 일자',
'hts_rmnn_dynu': 'HTS 잔존 일수',
'futs_lstn_medm_hgpr': '선물 상장 중 최고가',
'futs_lstn_medm_lwpr': '선물 상장 중 최저가',
'delta_val': '델타 값',
'gama': '감마',
'theta': '세타',
'vega': '베가',
'rho': '로우',
'hist_vltl': '역사적 변동성',
'hts_ints_vltl': 'HTS 내재 변동성',
'mrkt_basis': '시장 베이시스',
'acpr': '행사가',
'bstp_cls_code': '업종 구분 코드',
'hts_kor_isnm': 'HTS 한글 종목명',
'bstp_nmix_prpr': '업종 지수 현재가',
'prdy_vrss_sign': '전일 대비 부호',
'bstp_nmix_prdy_vrss': '업종 지수 전일 대비',
'bstp_nmix_prdy_ctrt': '업종 지수 전일 대비율'
}
NUMERIC_COLUMNS = []
def main():
"""
선물옵션 시세 조회 테스트 함수
이 함수는 선물옵션 시세 API를 호출하여 결과를 출력합니다.
테스트 데이터로 101S09 종목을 사용합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
# case1 조회
logging.info("=== case1 조회 ===")
try:
result1, result2, result3 = inquire_price(
fid_cond_mrkt_div_code="F",
fid_input_iscd="101W09",
env_dv="real"
)
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
# output1 처리
logging.info("=== output1 결과 ===")
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result1)
# output2 처리
logging.info("=== output2 결과 ===")
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result2)
# output3 처리
logging.info("=== output3 결과 ===")
logging.info("사용 가능한 컬럼: %s", result3.columns.tolist())
# 컬럼명 한글 변환
result3 = result3.rename(columns=COLUMN_MAPPING)
# 숫자형 컬럼 소수점 둘째자리까지 표시
for col in NUMERIC_COLUMNS:
if col in result3.columns:
result3[col] = pd.to_numeric(result3[col], errors='coerce').round(2)
logging.info("결과:")
print(result3)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,91 @@
"""
Created on 20250601
"""
import sys
import logging
from typing import Tuple
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 기본시세 > 선물옵션 시세[v1_국내선물-006]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/quotations/inquire-price"
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")
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()

View File

@@ -0,0 +1,84 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from inquire_psbl_ngt_order import inquire_psbl_ngt_order
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > (야간)선물옵션 주문가능 조회 [국내선물-011]
##############################################################################################
COLUMN_MAPPING = {
'max_ord_psbl_qty': '최대주문가능수량',
'tot_psbl_qty': '최대주문가능수량',
'lqd_psbl_qty': '청산가능수량',
'lqd_psbl_qty_1': '청산가능수량',
'ord_psbl_qty': '주문가능수량',
'bass_idx': '기준지수'
}
NUMERIC_COLUMNS = []
def main():
"""
(야간)선물옵션 주문가능 조회 테스트 함수
이 함수는 (야간)선물옵션 주문가능 조회 API를 호출하여 결과를 출력합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
trenv = ka.getTREnv()
# case1 조회
logging.info("=== case1 조회 ===")
try:
result = 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"
)
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,94 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > (야간)선물옵션 주문가능 조회 [국내선물-011]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/trading/inquire-psbl-ngt-order"
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"
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()

View File

@@ -0,0 +1,83 @@
"""
Created on 20250115
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from inquire_psbl_order import inquire_psbl_order
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 주문가능[v1_국내선물-005]
##############################################################################################
COLUMN_MAPPING = {
'tot_psbl_qty': '총가능수량',
'lqd_psbl_qty1': '청산가능수량1',
'ord_psbl_qty': '주문가능수량',
'bass_idx': '기준지수'
}
NUMERIC_COLUMNS = []
def main():
"""
선물옵션 주문가능 조회 테스트 함수
이 함수는 선물옵션 주문가능 API를 호출하여 결과를 출력합니다.
테스트 데이터로 실전 환경의 선물옵션 계좌를 사용합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
trenv = ka.getTREnv()
# case1 조회
logging.info("=== case1 조회 ===")
try:
result = 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"
)
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,101 @@
"""
Created on 20250115
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 주문/계좌 > 선물옵션 주문가능[v1_국내선물-005]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/trading/inquire-psbl-order"
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'")
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()

View File

@@ -0,0 +1,132 @@
"""
Created on 20250601
"""
import sys
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from inquire_time_fuopchartprice import inquire_time_fuopchartprice
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 기본시세 > 선물옵션 분봉조회[v1_국내선물-012]
##############################################################################################
COLUMN_MAPPING = {
'futs_prdy_vrss': '선물 전일 대비',
'prdy_vrss_sign': '전일 대비 부호',
'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': '괴리율',
'stck_bsop_date': '주식 영업 일자',
'stck_cntg_hour': '주식 체결 시간',
'futs_prpr': '선물 현재가',
'futs_oprc': '선물 시가2',
'futs_hgpr': '선물 최고가',
'futs_lwpr': '선물 최저가',
'cntg_vol': '체결 거래량',
'acml_tr_pbmn': '누적 거래 대금'
}
NUMERIC_COLUMNS = []
def main():
"""
선물옵션 분봉조회 테스트 함수
이 함수는 선물옵션 분봉조회 API를 호출하여 결과를 출력합니다.
Returns:
None
"""
# pandas 출력 옵션 설정
pd.set_option('display.max_columns', None) # 모든 컬럼 표시
pd.set_option('display.width', None) # 출력 너비 제한 해제
pd.set_option('display.max_rows', None) # 모든 행 표시
# 인증 토큰 발급
ka.auth()
# case1 조회
logging.info("=== case1 조회 ===")
try:
result1, result2 = inquire_time_fuopchartprice(
fid_cond_mrkt_div_code="F",
fid_input_iscd="101T12",
fid_hour_cls_code="60",
fid_pw_data_incu_yn="Y",
fid_fake_tick_incu_yn="N",
fid_input_date_1="20230901",
fid_input_hour_1="100000"
)
except ValueError as e:
logging.error("에러 발생: %s" % str(e))
return
# output1 처리
logging.info("=== output1 결과 ===")
logging.info("사용 가능한 컬럼: %s", 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)
logging.info("결과:")
print(result1)
# output2 처리
logging.info("=== output2 결과 ===")
logging.info("사용 가능한 컬럼: %s" % 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)
logging.info("결과:")
print(result2)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,104 @@
"""
Created on 20250601
"""
import sys
from typing import Tuple
import logging
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 기본시세 > 선물옵션 분봉조회[v1_국내선물-012]
##############################################################################################
# 상수 정의
API_URL = "/uapi/domestic-futureoption/v1/quotations/inquire-time-fuopchartprice"
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" # 선물옵션 분봉조회
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()

View File

@@ -0,0 +1,103 @@
"""
Created on 20250601
"""
import logging
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from krx_ngt_futures_asking_price import krx_ngt_futures_asking_price
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > KRX야간선물 실시간호가 [실시간-065]
##############################################################################################
COLUMN_MAPPING = {
"futs_shrn_iscd": "선물 단축 종목코드",
"bsop_hour": "영업 시간",
"futs_askp1": "선물 매도호가1",
"futs_askp2": "선물 매도호가2",
"futs_askp3": "선물 매도호가3",
"futs_askp4": "선물 매도호가4",
"futs_askp5": "선물 매도호가5",
"futs_bidp1": "선물 매수호가1",
"futs_bidp2": "선물 매수호가2",
"futs_bidp3": "선물 매수호가3",
"futs_bidp4": "선물 매수호가4",
"futs_bidp5": "선물 매수호가5",
"askp_csnu1": "매도호가 건수1",
"askp_csnu2": "매도호가 건수2",
"askp_csnu3": "매도호가 건수3",
"askp_csnu4": "매도호가 건수4",
"askp_csnu5": "매도호가 건수5",
"bidp_csnu1": "매수호가 건수1",
"bidp_csnu2": "매수호가 건수2",
"bidp_csnu3": "매수호가 건수3",
"bidp_csnu4": "매수호가 건수4",
"bidp_csnu5": "매수호가 건수5",
"askp_rsqn1": "매도호가 잔량1",
"askp_rsqn2": "매도호가 잔량2",
"askp_rsqn3": "매도호가 잔량3",
"askp_rsqn4": "매도호가 잔량4",
"askp_rsqn5": "매도호가 잔량5",
"bidp_rsqn1": "매수호가 잔량1",
"bidp_rsqn2": "매수호가 잔량2",
"bidp_rsqn3": "매수호가 잔량3",
"bidp_rsqn4": "매수호가 잔량4",
"bidp_rsqn5": "매수호가 잔량5",
"total_askp_csnu": "총 매도호가 건수",
"total_bidp_csnu": "총 매수호가 건수",
"total_askp_rsqn": "총 매도호가 잔량",
"total_bidp_rsqn": "총 매수호가 잔량",
"total_askp_rsqn_icdc": "총 매도호가 잔량 증감",
"total_bidp_rsqn_icdc": "총 매수호가 잔량 증감"
}
NUMERIC_COLUMNS = []
def main():
"""
KRX야간선물 실시간호가 조회 테스트 함수
Returns:
None
"""
# 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")
# 조회
kws.subscribe(request=krx_ngt_futures_asking_price, data=["101W09"])
# 결과 표시
def on_result(ws, tr_id: str, result: pd.DataFrame, data_map: dict):
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)
kws.start(on_result=on_result)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,99 @@
"""
Created on 20250601
"""
import logging
import sys
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > KRX야간선물 실시간호가 [실시간-065]
##############################################################################################
def krx_ngt_futures_asking_price(
tr_type: str,
tr_key: str,
) -> (dict, list[str]):
"""
※ 선물옵션 호가 데이터는 0.2초 필터링 옵션이 있습니다.
필터링 사유는 순간적으로 데이터가 폭증할 경우 서버 뿐만아니라 클라이언트 환경에도 부하를 줄 수 있어 적용된 사항인 점 양해 부탁드립니다.
[참고자료]
종목코드 마스터파일 파이썬 정제코드는 한국투자증권 Github 참고 부탁드립니다.
https://github.com/koreainvestment/open-trading-api/tree/main/stocks_info
Args:
tr_type (str): [필수] 등록/해제
tr_key (str): [필수] 종목코드
Returns:
message (dict): 메시지 데이터
columns (list[str]): 컬럼 정보
Example:
>>> msg, columns = krx_ngt_futures_asking_price("1", "101W9000")
>>> print(msg, columns)
"""
# 필수 파라미터 검증
if tr_type == "":
raise ValueError("tr_type is required")
if tr_key == "":
raise ValueError("tr_key is required")
tr_id = "H0MFASP0"
params = {
"tr_key": tr_key,
}
msg = ka.data_fetch(tr_id, tr_type, params)
columns = [
"futs_shrn_iscd",
"bsop_hour",
"futs_askp1",
"futs_askp2",
"futs_askp3",
"futs_askp4",
"futs_askp5",
"futs_bidp1",
"futs_bidp2",
"futs_bidp3",
"futs_bidp4",
"futs_bidp5",
"askp_csnu1",
"askp_csnu2",
"askp_csnu3",
"askp_csnu4",
"askp_csnu5",
"bidp_csnu1",
"bidp_csnu2",
"bidp_csnu3",
"bidp_csnu4",
"bidp_csnu5",
"askp_rsqn1",
"askp_rsqn2",
"askp_rsqn3",
"askp_rsqn4",
"askp_rsqn5",
"bidp_rsqn1",
"bidp_rsqn2",
"bidp_rsqn3",
"bidp_rsqn4",
"bidp_rsqn5",
"total_askp_csnu",
"total_bidp_csnu",
"total_askp_rsqn",
"total_bidp_rsqn",
"total_askp_rsqn_icdc",
"total_bidp_rsqn_icdc"
]
return msg, columns

View File

@@ -0,0 +1,115 @@
"""
Created on 20250601
"""
import logging
import sys
import pandas as pd
sys.path.extend(['../..', '.'])
import kis_auth as ka
from krx_ngt_futures_ccnl import krx_ngt_futures_ccnl
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > KRX야간선물 실시간종목체결 [실시간-064]
##############################################################################################
COLUMN_MAPPING = {
"futs_shrn_iscd": "선물 단축 종목코드",
"bsop_hour": "영업 시간",
"futs_prdy_vrss": "선물 전일 대비",
"prdy_vrss_sign": "전일 대비 부호",
"futs_prdy_ctrt": "선물 전일 대비율",
"futs_prpr": "선물 현재가",
"futs_oprc": "선물 시가2",
"futs_hgpr": "선물 최고가",
"futs_lwpr": "선물 최저가",
"last_cnqn": "최종 거래량",
"acml_vol": "누적 거래량",
"acml_tr_pbmn": "누적 거래 대금",
"hts_thpr": "HTS 이론가",
"mrkt_basis": "시장 베이시스",
"dprt": "괴리율",
"nmsc_fctn_stpl_prc": "근월물 약정가",
"fmsc_fctn_stpl_prc": "원월물 약정가",
"spead_prc": "스프레드1",
"hts_otst_stpl_qty": "HTS 미결제 약정 수량",
"otst_stpl_qty_icdc": "미결제 약정 수량 증감",
"oprc_hour": "시가 시간",
"oprc_vrss_prpr_sign": "시가2 대비 현재가 부호",
"oprc_vrss_nmix_prpr": "시가 대비 지수 현재가",
"hgpr_hour": "최고가 시간",
"hgpr_vrss_prpr_sign": "최고가 대비 현재가 부호",
"hgpr_vrss_nmix_prpr": "최고가 대비 지수 현재가",
"lwpr_hour": "최저가 시간",
"lwpr_vrss_prpr_sign": "최저가 대비 현재가 부호",
"lwpr_vrss_nmix_prpr": "최저가 대비 지수 현재가",
"shnu_rate": "매수2 비율",
"cttr": "체결강도",
"esdg": "괴리도",
"otst_stpl_rgbf_qty_icdc": "미결제 약정 직전 수량 증감",
"thpr_basis": "이론 베이시스",
"futs_askp1": "선물 매도호가1",
"futs_bidp1": "선물 매수호가1",
"askp_rsqn1": "매도호가 잔량1",
"bidp_rsqn1": "매수호가 잔량1",
"seln_cntg_csnu": "매도 체결 건수",
"shnu_cntg_csnu": "매수 체결 건수",
"ntby_cntg_csnu": "순매수 체결 건수",
"seln_cntg_smtn": "총 매도 수량",
"shnu_cntg_smtn": "총 매수 수량",
"total_askp_rsqn": "총 매도호가 잔량",
"total_bidp_rsqn": "총 매수호가 잔량",
"prdy_vol_vrss_acml_vol_rate": "전일 거래량 대비 등락율",
"dynm_mxpr": "실시간상한가",
"dynm_llam": "실시간하한가",
"dynm_prc_limt_yn": "실시간가격제한구분"
}
NUMERIC_COLUMNS = []
def main():
"""
[국내선물옵션] 실시간시세 > KRX야간선물 실시간종목체결
Returns:
None
"""
# 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")
# 조회
kws.subscribe(request=krx_ngt_futures_ccnl, data=["101W9000"])
# 결과 표시
def on_result(ws, tr_id: str, result: pd.DataFrame, data_map: dict):
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)
kws.start(on_result=on_result)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,108 @@
"""
Created on 20250601
"""
import logging
import sys
sys.path.extend(['../..', '.'])
import kis_auth as ka
# 로깅 설정
logging.basicConfig(level=logging.INFO)
##############################################################################################
# [국내선물옵션] 실시간시세 > KRX야간선물 실시간종목체결 [실시간-064]
##############################################################################################
def krx_ngt_futures_ccnl(
tr_type: str,
tr_key: str,
) -> (dict, list[str]):
"""
[참고자료]
종목코드 마스터파일 파이썬 정제코드는 한국투자증권 Github 참고 부탁드립니다.
https://github.com/koreainvestment/open-trading-api/tree/main/stocks_info
Args:
tr_type (str): [필수] 등록/해제
tr_key (str): [필수] 종목코드
Returns:
message (dict): 메시지 데이터
columns (list[str]): 컬럼 정보
Example:
>>> msg, columns = krx_ngt_futures_ccnl("1", "101W9000")
>>> print(msg, columns)
"""
# 필수 파라미터 검증
if tr_type == "":
raise ValueError("tr_type is required")
if tr_key == "":
raise ValueError("tr_key is required")
tr_id = "H0MFCNT0"
params = {
"tr_key": tr_key,
}
msg = ka.data_fetch(tr_id, tr_type, params)
columns = [
"futs_shrn_iscd",
"bsop_hour",
"futs_prdy_vrss",
"prdy_vrss_sign",
"futs_prdy_ctrt",
"futs_prpr",
"futs_oprc",
"futs_hgpr",
"futs_lwpr",
"last_cnqn",
"acml_vol",
"acml_tr_pbmn",
"hts_thpr",
"mrkt_basis",
"dprt",
"nmsc_fctn_stpl_prc",
"fmsc_fctn_stpl_prc",
"spead_prc",
"hts_otst_stpl_qty",
"otst_stpl_qty_icdc",
"oprc_hour",
"oprc_vrss_prpr_sign",
"oprc_vrss_nmix_prpr",
"hgpr_hour",
"hgpr_vrss_prpr_sign",
"hgpr_vrss_nmix_prpr",
"lwpr_hour",
"lwpr_vrss_prpr_sign",
"lwpr_vrss_nmix_prpr",
"shnu_rate",
"cttr",
"esdg",
"otst_stpl_rgbf_qty_icdc",
"thpr_basis",
"futs_askp1",
"futs_bidp1",
"askp_rsqn1",
"bidp_rsqn1",
"seln_cntg_csnu",
"shnu_cntg_csnu",
"ntby_cntg_csnu",
"seln_cntg_smtn",
"shnu_cntg_smtn",
"total_askp_rsqn",
"total_bidp_rsqn",
"prdy_vol_vrss_acml_vol_rate",
"dynm_mxpr",
"dynm_llam",
"dynm_prc_limt_yn"
]
return msg, columns

Some files were not shown because too many files have changed in this diff Show More