[λΉμ¬μμ μ 곡νλ μνμ½λμ λν μ μμ¬ν]
- μν μ½λλ νκ΅ν¬μμ¦κΆ Open API(KIS Developers)λ₯Ό μ°λνλ μμμ λλ€. κ³ κ°λμ κ°λ° λΆλ΄μ μ€μ΄κ³ μ μ°Έκ³ μ©μΌλ‘ μ 곡λκ³ μμ΅λλ€.
- μν μ½λλ λ³λμ κ³΅μ§ μμ΄ μ§μμ μΌλ‘ μ λ°μ΄νΈλ μ μμ΅λλ€.
- μν μ½λλ₯Ό νμ©νμ¬ μ μν κ³ κ°λμ νλ‘κ·Έλ¨μΌλ‘ μΈν μν΄μ λν΄μλ λΉμ¬μμ μ± μμ§μ§ μμ΅λλ€.
μ΄ μ μ₯μλ ChatGPT, Claude λ± LLM(Large Language Model) κΈ°λ° μλν νκ²½κ³Ό Python κ°λ°μ λͺ¨λκ° νκ΅ν¬μμ¦κΆ(Korea Investment & Securities) Open APIλ₯Ό μ½κ² μ΄ν΄νκ³ νμ©ν μ μλλ‘ κ΅¬μ±λ μν μ½λ λͺ¨μμ λλ€.
examples_llm/: LLMμ΄ λ¨μΌ API κΈ°λ₯μ μ½κ² νμνκ³ νΈμΆν μ μλλ‘ κ΅¬μ±λ κΈ°λ₯ λ¨μ μν μ½λexamples_user/: μ¬μ©μκ° μ€μ ν¬μ λ° μλλ§€λ§€ ꡬνμ νμ©ν μ μλλ‘ μνλ³λ‘ ν΅ν©λ API νΈμΆ μμ μ½λ
AIμ μ¬λμ΄ λͺ¨λ νμ©νκΈ° μ¬μ΄ ꡬ쑰λ₯Ό μ§ν₯ν©λλ€.
νκ΅ν¬μμ¦κΆ Open API ν¬νΈ λ°λ‘κ°κΈ°
- νκ΅ν¬μμ¦κΆ Open APIλ₯Ό μ²μ μ¬μ©νλ Python κ°λ°μ
- κΈ°μ‘΄ Open API μ¬μ©μ μ€ μ½λ κ°μ λ° κ΅¬μ‘° νμ΅μ΄ νμν μ¬μ©μ
- LLM κΈ°λ° μ½λ μμ΄μ νΈλ₯Ό νμ©ν΄ μ’ λͺ© κ²μ, μμΈ λΆμ, μλλ§€λ§€ λ±μ ꡬννκ³ μ νλ μ¬μ©μ
# νλ‘μ νΈ κ΅¬μ‘°
.
βββ README.md # νλ‘μ νΈ μ€λͺ
μ
βββ docs/
β βββ convention.md # μ½λ© 컨벀μ
κ°μ΄λ
βββ examples_llm/ # LLMμ© μν μ½λ
β βββ kis_auth.py # μΈμ¦ κ³΅ν΅ ν¨μ
β βββ domestic_bond # κ΅λ΄μ±κΆ
β β βββ inquire_price # API λ¨μΌ κΈ°λ₯λ³ ν΄λ
β β βββ inquire_price.py # νμ€ νΈμΆ νμΌ (μ: μ±κΆ κ°κ²© μ‘°ν)
β β βββ chk_inquire_price.py # ν
μ€νΈ νμΌ (μ: μ±κΆ κ°κ²© μ‘°ν κ²°κ³Ό κ²μ¦)
β βββ domestic_futureoption # κ΅λ΄μ λ¬Όμ΅μ
β βββ domestic_stock # κ΅λ΄μ£Όμ
β βββ elw # ELW
β βββ etfetn # ETF/ETN
β βββ overseas_futureoption # ν΄μΈμ λ¬Όμ΅μ
β βββ overseas_price # ν΄μΈμμΈ
β βββ overseas_stock # ν΄μΈμ£Όμ
βββ examples_user/ # userμ© μ€μ μ¬μ© μμ
β βββ kis_auth.py # μΈμ¦ κ³΅ν΅ ν¨μ
β βββ domestic_bond # κ΅λ΄μ±κΆ
β β βββ domestic_bond_functions.py # (REST) ν΅ν© ν¨μ νμΌ (λͺ¨λ API ν¨μ λͺ¨μ)
β β βββ domestic_bond_examples.py # (REST) μ€ν μμ νμΌ (ν¨μ μ¬μ©λ²)
β β βββ domestic_bond_functions_ws.py # (Websocket) ν΅ν© ν¨μ νμΌ
β β βββ domestic_bond_examples_ws.py # (Websocket) μ€ν μμ νμΌ
β βββ domestic_futureoption # κ΅λ΄μ λ¬Όμ΅μ
β βββ domestic_stock # κ΅λ΄μ£Όμ
β βββ elw # ELW
β βββ etfetn # ETF/ETN
β βββ overseas_futureoption # ν΄μΈμ λ¬Όμ΅μ
β βββ overseas_price # ν΄μΈμμΈ
β βββ overseas_stock # ν΄μΈμ£Όμ
βββ legacy/ # ꡬ μνμ½λ 보κ΄
βββ stock_info/ # μ’
λͺ©μ 보νμΌ μ°Έκ³ λ°μ΄ν°
βββ kis_devlp.yaml # API μ€μ νμΌ (κ°μΈμ 보 μ
λ ₯ νμ)
βββ pyproject.toml # (uv)νλ‘μ νΈ μμ‘΄μ± κ΄λ¦¬
βββ uv.lock # (uv)μμ‘΄μ± λ½ νμΌ
- μλ μΉ΄ν κ³ λ¦¬ λ° ν΄λ ꡬ쑰λ examples_llm/, examples_user/ ν΄λ λͺ¨λ λμΌνκ² μ μ©λ©λλ€.
| μΉ΄ν κ³ λ¦¬ | μ€λͺ | ν΄λλͺ |
|---|---|---|
| κ΅λ΄μ£Όμ | κ΅λ΄ μ£Όμ μμΈ, μ£Όλ¬Έ, μκ³ λ± | domestic_stock |
| κ΅λ΄μ±κΆ | κ΅λ΄ μ±κΆ μμΈ, μ£Όλ¬Έ λ± | domestic_bond |
| κ΅λ΄μ λ¬Όμ΅μ | κ΅λ΄ νμμν κ΄λ ¨ | domestic_futureoption |
| ν΄μΈμ£Όμ | ν΄μΈ μ£Όμ μμΈ, μ£Όλ¬Έ λ± | overseas_stock |
| ν΄μΈμ λ¬Όμ΅μ | ν΄μΈ νμμν κ΄λ ¨ | overseas_futureoption |
| ELW | ELW μμΈ API | elw |
| ETF/ETN | ETF, ETN μμΈ API | etfetn |
APIλ³ κ°λ³ ν΄λ ꡬ쑰: λ¨μΌ API κΈ°λ₯μ λ 립 ν΄λλ‘ λΆλ¦¬νμ¬, LLMμ΄ κ΄λ ¨ μ½λλ₯Ό μ½κ² νμν μ μλλ‘ κ΅¬μ±
- νμ€ νΈμΆ νμΌ:
[ν¨μλͺ ].pyβ λ¨μΌ κΈ°λ₯μ νΈμΆνλ μ΅μ λ¨μ μ½λ (μ:inquire_price.py) - ν
μ€νΈ νμΌ:
chk_[ν¨μλͺ ].pyβ νΈμΆ κ²°κ³Όλ₯Ό κ²μ¦νλ ν μ€νΈ μ€ν μ½λ (μ:chk_inquire_price.py)
μΉ΄ν κ³ λ¦¬λ³ κ°λ³ ν΄λ ꡬ쑰: μΉ΄ν κ³ λ¦¬(μν)λ³λ‘ λͺ¨λ κΈ°λ₯μ ν΅ν©νμ¬, μ¬μ©μκ° μ½κ² μν μ½λλ₯Ό νμνκ³ μ€νν μ μλλ‘ κ΅¬μ±
- ν΅ν© ν¨μ νμΌ:
[μΉ΄ν κ³ λ¦¬]_functions.py- ν΄λΉ μΉ΄ν κ³ λ¦¬μ λͺ¨λ API κΈ°λ₯μ΄ ν΅ν©λ ν¨μ λͺ¨μ - μ€ν μμ νμΌ:
[μΉ΄ν κ³ λ¦¬]_examples.py- μ€μ μ¬μ© μμ λ₯Ό κΈ°λ°μΌλ‘ ν μ€ν μ½λ - μΉμμΌ ν΅ν© ν¨μ νμΌ λ° μ€ν μμ νμΌ:
[μΉ΄ν κ³ λ¦¬]_functions_ws.py,[μΉ΄ν κ³ λ¦¬]_examples_ws.py
- μ κ·Όν ν° λ°κΈ λ° κ΄λ¦¬
- API νΈμΆ κ³΅ν΅ ν¨μ
- μ€μ ν¬μ/λͺ¨μν¬μ νκ²½ μ ν μ§μ
- μΉμμΌ μ°κ²° μ€μ κΈ°λ₯ μ 곡
- Python 3.9 μ΄μ νμ
- uv ν¨ν€μ§ λ§€λμ μ¬μ© κΆμ₯ (λΉ λ₯΄κ³ κ°νΈν μμ‘΄μ± κ΄λ¦¬)
- κ°νΈ μ€μ μ μν΄ uvλ₯Ό κΆμ₯ν©λλ€
# Windows (PowerShell)
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# μ€μΉ νμΈ
uv --version
# uv 0.x.x ... -> μ€μΉ μλ£# μ μ₯μ ν΄λ‘
git clone https://github.com/koreainvestment/open-trading-api
cd open-trading-api/kis_github
# uvλ₯Ό μ¬μ©ν μμ‘΄μ± μ€μΉ - νμ€λ‘ λ
uv syncπ μλΉμ€ μ μ² μλ΄ λ°λ‘κ°κΈ°
- νκ΅ν¬μμ¦κΆ κ³μ’ κ°μ€ λ° ID μ°κ²°
- νκ΅ν¬μμ¦κΆ ννμ΄μ§ or μ±μμ Open API μλΉμ€ μ μ²
- μ±ν€(App Key), μ±μν¬λ¦Ώ(App Secret) λ°κΈ
- λͺ¨μν¬μ λ° μ€μ ν¬μ μ±ν€ κ°κ° μ€λΉ
- λ³ΈμΈμ κ³μ μ€μ μ μν΄
kis_devlp.yamlνμΌμ μ΄μ΄ λ€μκ³Ό κ°μ΄ μμ ν©λλ€.
- νλ‘μ νΈ λ£¨νΈμ μμΉν
kis_devlp.yamlνμΌ μ΄κΈ° - μ±ν€μ μ±μν¬λ¦Ώ μ 보 μ λ ₯
- HTS ID μ 보 μ λ ₯
- κ³μ’λ²νΈ μ 보 μ λ ₯ (μ 8μ리μ λ€ 2μ리 ꡬλΆ)
- μ μ₯ ν λ«κΈ°
# μ€μ ν¬μ
my_app: "μ¬κΈ°μ μ€μ ν¬μ μ±ν€ μ
λ ₯"
my_sec: "μ¬κΈ°μ μ€μ ν¬μ μ±μν¬λ¦Ώ μ
λ ₯"
# λͺ¨μν¬μ
paper_app: "μ¬κΈ°μ λͺ¨μν¬μ μ±ν€ μ
λ ₯"
paper_sec: "μ¬κΈ°μ λͺ¨μν¬μ μ±μν¬λ¦Ώ μ
λ ₯"
# HTS ID(KIS Developers κ³ κ° ID) - 체결ν΅λ³΄, λμ 쑰건 λͺ©λ‘ νμΈ λ±μ μ¬μ©λ©λλ€.
my_htsid: "μ¬μ©μ HTS ID"
# κ³μ’λ²νΈ μ 8μ리
my_acct_stock: "μ¦κΆκ³μ’ 8μ리"
my_acct_future: "μ λ¬Όμ΅μ
κ³μ’ 8μ리"
my_paper_stock: "λͺ¨μν¬μ μ¦κΆκ³μ’ 8μ리"
my_paper_future: "λͺ¨μν¬μ μ λ¬Όμ΅μ
κ³μ’ 8μ리"
# κ³μ’λ²νΈ λ€ 2μ리
my_prod: "01" # μ’
ν©κ³μ’
# my_prod: "03" # κ΅λ΄μ λ¬Όμ΅μ
κ³μ’
# my_prod: "08" # ν΄μΈμ λ¬Όμ΅μ
κ³μ’
# my_prod: "22" # μ°κΈμ μΆ κ³μ’
# my_prod: "29" # ν΄μ§μ°κΈ κ³μ’
# User-Agent(κΈ°λ³Έκ° μ¬μ© κΆμ₯, λ³κ²½ λΆνμ)
my_agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"kis_auth.pyμ config_root κ²½λ‘λ₯Ό λ³ΈμΈ νκ²½μ λ§κ² μμ ν΄μ€λλ€. λ°κΈλ ν ν° νμΌμ΄ μ μ₯λ κ²½λ‘λ‘, μ 3μκ° μ°ΎκΈ° μ΄λ ΅λλ‘ μ€μ νλκ²μ κΆμ₯ν©λλ€.
# kis_auth.py 39λ²μ§Έ μ€
# windows - C:\Users\μ¬μ©μμ΄λ¦\KIS\config
# Linux/macOS - /home/μ¬μ©μμ΄λ¦/KIS/config
# config_root = os.path.join(os.path.expanduser("~"), "KIS", "config")
config_root = os.path.join(os.path.expanduser("~"), "ν΄λ κ²½λ‘", "config")- μ€ννλ €λ νμΌμμ μΈμ¦ κ΄λ ¨ μ€μ μ κ²ν νΉμ λ³κ²½ν΄μ€λλ€. κ΅λ΄μ£Όμ κΈ°λ₯ μ 체λ₯Ό μ΄μ©νμλ €λ©΄,
domestic_stock/domestic_stock_examples.pyνμΌμ νμΈν΄μ£ΌμΈμ. ka.auth() ν¨μμ svr, product λ§€κ°λ³μλ₯Ό μλμ κ°μ΄ μμ νλ©΄ μ€μ νκ²½(prod)μμ μνκ³μ’(-01)λ‘ λ§€λ§€ ν μ€νΈκ° κ°λ₯ν©λλ€.
import kis_auth as ka
# μ€μ ν¬μ μΈμ¦
ka.auth(svr="prod", product="01") # λͺ¨μν¬μ: svr="vps"- examples_user κΈ°μ€
# κ΅λ΄μ£Όμ μν μ½λ μ€ν (examples_user/domestic_stock/)
python domestic_stock_examples.py # REST λ°©μ
python domestic_stock_examples_ws.py # Websocket λ°©μ domestic_stock_examples.pyμλ μ¬λ¬ ν¨μκ° ν¬ν¨λμ΄ μμΌλ―λ‘, μ¬μ©νλ €λ ν¨μλ§ λ¨κΈ°κ³ λλ¨Έμ§λ μ£Όμ μ²λ¦¬ν ν, μ λ ₯κ°μ μμ νμ¬ νΈμΆν΄ μ£ΌμΈμ.
- examples_llm κΈ°μ€
# κ΅λ΄μ£Όμ > μ£Όμνμ¬κ° μμΈ μν μ½λ μ€ν (examples_llm/domestic_stock/inquire_price/)
python chk_inquire_price.pyexamples_llm μ κ° κΈ°λ₯λ³λ‘ κ°λ³ μ€ν νμΌ(chk_*.py)μ΄ λΆλ¦¬λμ΄ μμ΄, νΉμ κΈ°λ₯λ§ ν μ€νΈνκ³ μ ν λ μ μ©ν©λλ€.
# REST API νΈμΆ μμ - domestic_stock_examples.py
import sys
import logging
import pandas as pd
sys.path.extend(['..', '.'])
import kis_auth as ka
from domestic_stock_functions import *
# λ‘κΉ
μ€μ
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
# μΈμ¦
ka.auth()
trenv = ka.getTREnv()
# μΌμ±μ μ νμ¬κ° μμΈ μ‘°ν
result = inquire_price(env_dv="real", fid_cond_mrkt_div_code="J", fid_input_iscd="005930")
print(result)# μΉμμΌ νΈμΆ μμ - domestic_stock_examples_ws.py
import sys
import logging
import pandas as pd
sys.path.extend(['..', '.'])
import kis_auth as ka
from domestic_stock_functions_ws import *
# λ‘κΉ
μ€μ
logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
# μΈμ¦
ka.auth()
ka.auth_ws()
trenv = ka.getTREnv()
# μΉμμΌ μ μΈ
kws = ka.KISWebSocket(api_url="/tryitout")
# μΌμ±μ μ, skνμ΄λμ€ μ€μκ° νΈκ° ꡬλ
kws.subscribe(request=asking_price_krx, data=["005930", "000660"])import kis_auth as ka
# ν ν° μ¬λ°κΈ - 1λΆλΉ 1ν λ°κΈλ©λλ€.
ka.auth(svr="prod") # λλ "vps"kis_devlp.yamlνμΌμ μ±ν€, μ±μν¬λ¦Ώμ΄ μ¬λ°λ₯Έμ§ νμΈ- κ³μ’λ²νΈ νμμ΄ λ§λμ§ νμΈ (μ 8μ리 + λ€ 2μ리)
- μ€μκ° μμΈ(WebSocket) μ΄μ© μ€ βNo close frame receivedβ μ€λ₯κ° λ°μνλ κ²½μ°,
kis_devlp.yamlμ μ λ ₯νμ HTS IDκ° μ ννμ§ νμΈ
# μμ‘΄μ± μ¬μ€μΉ
uv sync --reinstall- π¬ νκ΅ν¬μμ¦κΆ Open API μ±λ΄μ μΈμ λ κΆκΈν μ μ λ¬Όμ΄λ³΄μΈμ.