[2026-05-19] KIS API TR_ID 수정 — 외국인/기관 수급·업종 지수 API 교체
- get_foreign_institution_rank: FHKST04430000(없는 서비스) → FHPTJ04400000(foreign-institution-total) - get_sector_trend: FHKST03010100(일봉 오용) → FHPUP02100000(inquire-index-price) 15개 업종 다중 호출 - 두 함수 모두 실거래 API 테스트 통과 확인 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+59
-34
@@ -413,61 +413,86 @@ class KISClient:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
async def get_foreign_institution_rank(self, top_n: int = 30) -> Dict:
|
async def get_foreign_institution_rank(self, top_n: int = 30) -> Dict:
|
||||||
"""외국인/기관 순매수 상위 (AI 판단용)"""
|
"""외국인/기관 순매수 상위 (AI 판단용) — FHPTJ04400000"""
|
||||||
data = await self._request(
|
data = await self._request(
|
||||||
method = "GET",
|
method = "GET",
|
||||||
path = "/uapi/domestic-stock/v1/quotations/inquire-investor",
|
path = "/uapi/domestic-stock/v1/quotations/foreign-institution-total",
|
||||||
tr_id = "FHKST04430000",
|
tr_id = "FHPTJ04400000",
|
||||||
params = {
|
params = {
|
||||||
"FID_COND_MRKT_DIV_CODE": "J",
|
"FID_COND_MRKT_DIV_CODE" : "J",
|
||||||
|
"FID_COND_SCR_DIV_CODE" : "20171",
|
||||||
"FID_INPUT_ISCD" : "0000",
|
"FID_INPUT_ISCD" : "0000",
|
||||||
|
"FID_DIV_CLS_CODE" : "0",
|
||||||
|
"FID_BLNG_CLS_CODE" : "0",
|
||||||
|
"FID_TRGT_CLS_CODE" : "111111111",
|
||||||
|
"FID_TRGT_EXLS_CLS_CODE" : "000000",
|
||||||
|
"FID_INPUT_PRICE_1" : "",
|
||||||
|
"FID_INPUT_PRICE_2" : "",
|
||||||
|
"FID_VOL_CNT" : "",
|
||||||
"FID_INPUT_DATE_1" : "",
|
"FID_INPUT_DATE_1" : "",
|
||||||
"FID_INPUT_DATE_2" : "",
|
"FID_RANK_SORT_CLS_CODE" : "1", # 순매수량 기준 정렬
|
||||||
"FID_PERIOD_DIV_CODE" : "D",
|
"FID_ETC_CLS_CODE" : "0",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
foreign = []
|
foreign = []
|
||||||
institution = []
|
institution = []
|
||||||
for row in data.get("output", [])[:top_n]:
|
for row in data.get("output", []):
|
||||||
entry = {
|
ticker = row.get("mksc_shrn_iscd", "")
|
||||||
"ticker": row.get("mksc_shrn_iscd", ""),
|
name = row.get("hts_kor_isnm", "")
|
||||||
"name" : row.get("hts_kor_isnm", ""),
|
try:
|
||||||
"amount": int(row.get("frgn_ntby_qty", "0")),
|
frgn_qty = int(row.get("frgn_ntby_qty") or 0)
|
||||||
}
|
except (ValueError, TypeError):
|
||||||
foreign.append(entry)
|
frgn_qty = 0
|
||||||
entry2 = {
|
try:
|
||||||
"ticker": row.get("mksc_shrn_iscd", ""),
|
orgn_qty = int(row.get("orgn_ntby_qty") or 0)
|
||||||
"name" : row.get("hts_kor_isnm", ""),
|
except (ValueError, TypeError):
|
||||||
"amount": int(row.get("orgn_ntby_qty", "0")),
|
orgn_qty = 0
|
||||||
}
|
foreign.append({"ticker": ticker, "name": name, "amount": frgn_qty})
|
||||||
institution.append(entry2)
|
institution.append({"ticker": ticker, "name": name, "amount": orgn_qty})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"foreign" : sorted(foreign, key=lambda x: x["amount"], reverse=True)[:top_n],
|
"foreign" : sorted(foreign, key=lambda x: x["amount"], reverse=True)[:top_n],
|
||||||
"institution": sorted(institution, key=lambda x: x["amount"], reverse=True)[:top_n],
|
"institution": sorted(institution, key=lambda x: x["amount"], reverse=True)[:top_n],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 업종코드 → 업종명 (KOSPI 주요 업종)
|
||||||
|
_SECTOR_CODES = [
|
||||||
|
("0001", "KOSPI"),
|
||||||
|
("0028", "반도체"),
|
||||||
|
("0150", "2차전지"),
|
||||||
|
("0018", "전기전자"),
|
||||||
|
("0011", "의약품"),
|
||||||
|
("0010", "화학"),
|
||||||
|
("0016", "철강금속"),
|
||||||
|
("0017", "기계"),
|
||||||
|
("0006", "건설업"),
|
||||||
|
("0027", "금융업"),
|
||||||
|
("0026", "통신업"),
|
||||||
|
("0020", "운수창고"),
|
||||||
|
("0021", "유통업"),
|
||||||
|
("0009", "음식료품"),
|
||||||
|
("0024", "전기가스업"),
|
||||||
|
]
|
||||||
|
|
||||||
async def get_sector_trend(self) -> list:
|
async def get_sector_trend(self) -> list:
|
||||||
"""업종별 등락률 (AI 판단용)"""
|
"""업종별 등락률 (AI 판단용) — FHPUP02100000 다중 호출"""
|
||||||
|
result = []
|
||||||
|
for code, name in self._SECTOR_CODES:
|
||||||
|
try:
|
||||||
data = await self._request(
|
data = await self._request(
|
||||||
method = "GET",
|
method = "GET",
|
||||||
path = "/uapi/domestic-stock/v1/quotations/inquire-daily-itemchartprice",
|
path = "/uapi/domestic-stock/v1/quotations/inquire-index-price",
|
||||||
tr_id = "FHKST03010100",
|
tr_id = "FHPUP02100000",
|
||||||
params = {
|
params = {
|
||||||
"FID_COND_MRKT_DIV_CODE": "U", # 업종
|
"FID_COND_MRKT_DIV_CODE": "U",
|
||||||
"FID_INPUT_ISCD" : "0001",
|
"FID_INPUT_ISCD" : code,
|
||||||
"FID_INPUT_DATE_1" : "",
|
|
||||||
"FID_INPUT_DATE_2" : "",
|
|
||||||
"FID_PERIOD_DIV_CODE" : "D",
|
|
||||||
"FID_ORG_ADJ_PRC" : "0",
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
result = []
|
o = data.get("output", {})
|
||||||
for row in data.get("output1", []):
|
change_pct = float(o.get("bstp_nmix_prdy_ctrt") or 0)
|
||||||
result.append({
|
result.append({"sector": name, "change_pct": change_pct})
|
||||||
"sector" : row.get("hts_kor_isnm", ""),
|
except Exception as e:
|
||||||
"change_pct": float(row.get("prdy_ctrt", "0")),
|
logger.warning(f"업종 지수 조회 실패 [{name}/{code}]: {e}")
|
||||||
})
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user