LS증권(구 이베스트증권) Open API를 파이썬에서 쉽게 사용할 수 있도록 만든 헬퍼 라이브러리입니다.
공식 카탈로그 페이지 https://openapi.ls-sec.co.kr/apiservice를 Playwright로 크롤링해 41개 API 그룹 · 364개 TR의 엔드포인트/요청·응답 예제를 specs/에 덤프해 두었고, 그 스펙을 런타임에 로드해 TR 코드만으로 호출이 가능합니다.
pip install requests websocket-client
# (최초 1회) 카탈로그 크롤링에 사용된 Playwright — 이미 specs/가 포함돼 있어 런타임에는 필요 없음
pip install playwright && python -m playwright install chromiumLS증권 OpenAPI 포털에서 발급받은 appkey / appsecret을 환경변수로 주입합니다.
set LS_APPKEY=your-app-key
set LS_APPSECRET=your-app-secret또는 코드에서 직접 전달:
from lsapi import LSClient
client = LSClient(appkey="...", appsecret="...")토큰은 ~/.lsapi/token-<appkey>.json에 캐시되며, 만료 30초 전부터 자동 갱신합니다.
from lsapi import LSClient
client = LSClient()
# 1) 주식 편의 래퍼 — 자주 쓰는 주식 TR만 도메인 언어로 노출
quote = client.stock.quote("078020") # t1101
print(quote.block("t1101OutBlock"))
# 2) 전체 카테고리 자동 래퍼 — 248개 REST TR을 TR 코드 그대로 메서드로 호출
client.api.stock_quote.t1102(shcode="078020")
client.api.futures_quote.t2101(focode="105V6000")
client.api.overseas_stock_quote.g3101(symbol="AAPL", exchcd="82", delaygb="R", keysymbol="AAPL.O")
client.api.stock_order.CSPAT00601(
IsuNo="078020", OrdQty=1, OrdPrc=4000, BnsTpCode="2",
OrdprcPtnCode="00", MgntrnCode="000", LoanDt="", OrdCndiTpCode="0", MbrNo="",
)
# 3) TR 코드로 범용 호출 — body를 직접 주거나 키워드만 주거나
client.call("t1102", shcode="078020")
client.call("t1102", {"t1102InBlock": {"shcode": "078020"}})
# 4) 페이지네이션 (tr_cont 자동 추적)
for page in client.paginate("t1301", shcode="078020", cvolume=0):
print(len(page.block("t1301OutBlock1") or []))
# 5) 실시간 체결 스트림
rt = client.realtime()
rt.subscribe("S3_", "078020", lambda msg: print(msg["body"]))
rt.run_forever()| 카테고리 | 메서드 | TR 코드 | 설명 |
|---|---|---|---|
| 시세 | quote(shcode) |
t1101 | 현재가 호가 |
| 시세 | current_price(shcode) |
t1102 | 현재가(시세) |
| 시세 | tick_history(shcode) |
t1104 | 체결 메모 |
| 시세 | time_ticks(shcode, …) |
t1301 | 시간대별 체결 |
| 시세 | period_prices(shcode, …) |
t1305 | 기간별 주가 |
| 시세 | multi_current_price(*codes) |
t8407 | 복수 현재가 |
| 차트 | daily_chart(shcode, …) |
t8410 | 일·주·월·연봉 |
| 차트 | tick_chart(shcode, …) |
t8411 | 틱/n틱 |
| 차트 | minute_chart(shcode, …) |
t8412 | 분봉 |
| 계좌 | balance(…) |
t0424 | 잔고 |
| 계좌 | orders_and_fills(…) |
t0425 | 체결/미체결 |
| 계좌 | available_cash(…) |
CSPAQ12200 | 주문가능금액 |
| 주문 | buy(shcode, qty, price) |
CSPAT00601 | 현금 매수 |
| 주문 | sell(shcode, qty, price) |
CSPAT00601 | 현금 매도 |
| 주문 | modify(…) |
CSPAT00701 | 정정 |
| 주문 | cancel(…) |
CSPAT00801 | 취소 |
| 검색 | master(gubun) |
t8430 | 종목 마스터 |
| 검색 | condition_search(…) |
t1809 | 조건검색 신호 |
위 client.stock 편의 메서드는 주식 쪽 자주 쓰는 19개를 손으로 감싼 것이고, 모든 REST TR은 client.api.<카테고리>.<TR코드>()로도 호출 가능합니다. 248개 메서드가 tools/gen_wrappers.py로 specs/에서 자동 생성됩니다.
client.api 네임스페이스에 34개 카테고리가 서브 속성으로 매달려 있습니다. 각 서브 속성은 해당 카테고리의 TR 코드를 그대로 Python 메서드로 노출합니다 — 파라미터는 LS 문서의 Element 이름을 그대로 키워드 인자로 받습니다.
| 네임스페이스 | 그룹 | TR 수 | 예시 |
|---|---|---|---|
client.api.stock_quote |
[주식] 시세 | 25 | t1101(shcode=...) |
client.api.stock_chart |
[주식] 차트 | 7 | t8410(...), t8411(...) |
client.api.stock_account |
[주식] 계좌 | 12 | t0424(...), CSPAQ12200(...) |
client.api.stock_order |
[주식] 주문 | 3 | CSPAT00601(...), CSPAT00701(...) |
client.api.stock_search |
[주식] 종목검색 | 8 | t1809(...), t1859(...) |
client.api.stock_info |
[주식] 투자정보 | 8 | t3102(...), t3202(...) |
client.api.stock_top |
[주식] 상위종목 | 9 | t1441(...), t1452(...) |
client.api.stock_program |
[주식] 프로그램 | 7 | t1631(...), t1632(...) |
client.api.stock_etf |
[주식] ETF | 5 | t1901(...), t1902(...) |
client.api.stock_elw |
[주식] ELW | 20 | t1950(...) |
client.api.stock_sector |
[주식] 섹터 | 5 | t1531(...), t1537(...) |
client.api.stock_investor |
[주식] 투자자 | 7 | t1601(...), t1615(...) |
client.api.stock_foreign |
[주식] 외인/기관 | 3 | t1702(...), t1717(...) |
client.api.stock_brokers |
[주식] 거래원 | 3 | t1752(...), t1764(...) |
client.api.stock_misc |
[주식] 기타 | 10 | t8430(...), t1921(...) |
client.api.futures_quote |
[선물/옵션] 시세 | 29 | t2101(...), t2105(...) |
client.api.futures_chart |
[선물/옵션] 차트 | 5 | t8414(...) |
client.api.futures_account |
[선물/옵션] 계좌 | 13 | t0434(...), CFOAQ00600(...) |
client.api.futures_order |
[선물/옵션] 주문 | 7 | CFOAT00100(...) |
client.api.futures_investor |
[선물/옵션] 투자자 | 4 | |
client.api.futures_misc |
[선물/옵션] 기타 | 1 | |
client.api.overseas_stock_quote |
[해외주식] 시세 | 5 | g3101(...) |
client.api.overseas_stock_chart |
[해외주식] 차트 | 4 | |
client.api.overseas_stock_account |
[해외주식] 계좌 | 4 | |
client.api.overseas_stock_order |
[해외주식] 주문 | 4 | |
client.api.overseas_futures_quote |
[해외선물] 시세 | 14 | o3101(...), o3103(...) |
client.api.overseas_futures_chart |
[해외선물] 차트 | 4 | |
client.api.overseas_futures_account |
[해외선물] 계좌 | 7 | |
client.api.overseas_futures_order |
[해외선물] 주문 | 3 | |
client.api.sector_quote |
[업종] 시세 | 5 | t1511(...) |
client.api.sector_chart |
[업종] 차트 | 4 | |
client.api.misc_time |
[기타] 시간조회 | 1 | t0167(id="") |
client.api.auth_token |
접근토큰 발급 | 1 | token() |
client.api.auth_revoke |
접근토큰 폐기 | 1 | revoke() |
REST TR 합계: 248개 (34개 그룹) — LS 문서 페이지에 나와있는 모든 REST TR을 전부 포함합니다.
모든 파라미터는 keyword-only이고 기본값은 빈 문자열 ""이므로, 필요한 필드만 채워 넣으면 됩니다. IDE 자동완성도 정상 동작합니다. 메서드명은 LS 문서의 TR 코드 그대로라 문서에서 찾아낸 코드를 바로 호출할 수 있습니다.
# 전체 그룹 요약
python samples/05_catalog_explore.py
# 특정 TR 상세
python samples/05_catalog_explore.py t1101
# 키워드 검색
python samples/05_catalog_explore.py --search 호가또는 파이썬에서:
from lsapi import Catalog
cat = Catalog.load()
spec = cat.tr("t1101")
print(spec.primary_in_block, spec.in_blocks, spec.out_blocks)
print(cat.find_by_group("[주식] 주문"))
print(cat.search("차트"))LS 문서의 실시간 시세 카테고리 116개 TR 전부가 lsapi.REALTIME_TOPICS에 한글 설명과 함께 등록돼 있습니다. 카테고리는 stock, futures, overseas_stock, overseas_futures, sector, etc, investinfo 7종.
| 대표 TR 코드 | 의미 |
|---|---|
S3_ |
KOSPI 체결 |
K3_ |
KOSDAQ 체결 |
H1_ |
KOSPI 호가 잔량 |
HA_ |
KOSDAQ 호가 잔량 |
SC0~SC4 |
주식 주문접수/체결/정정/취소/거부 |
FC0/OC0 |
KOSPI200 선물/옵션 체결 |
from lsapi import REALTIME_TOPICS, list_topics
rt = client.realtime()
rt.subscribe("S3_", "078020", on_tick)
rt.subscribe("H1_", "078020", on_hoga)
rt.run_forever()
# 카테고리별 TR 조회
print(rt.topics("stock")) # dict of tr_cd → 한글 이름
print(rt.topics("overseas_stock"))
print(len(list_topics())) # 116
# 배치 구독
rt.subscribe_many(
[("S3_", "078020"), ("H1_", "078020"), ("SC1", "")],
handler=lambda msg: print(msg),
)- 자동 재연결: 기본 ON (
LSRealtime(auto_reconnect=False)로 비활성) - 서버가 끊기면 기존 구독을 자동으로 재전송합니다
LS 측이 스펙을 갱신했을 때는 다음 두 단계를 순서대로 실행:
python tools/crawl_specs.py # specs/*.json 재생성
python tools/gen_wrappers.py # lsapi/generated/*.py + lsapi/realtime_topics.py 재생성크롤러는 specs/catalog.json, specs/apis/<api_id>.json, specs/index.json, specs/blocks.json을 덤프하고, 생성기는 카테고리별 파이썬 래퍼와 실시간 TR 상수 파일을 갱신합니다. 두 파일은 모두 커밋 대상 — 런타임 크롤링 없이도 lsapi가 바로 동작합니다.
lsapi/
__init__.py
config.py # 환경변수/설정
errors.py # LSError 계층
auth.py # TokenManager (OAuth2 client_credentials)
catalog.py # TRSpec, Catalog 로더
rest.py # LSClient, TRResponse (동기 REST)
realtime.py # LSRealtime (WebSocket + auto-reconnect)
realtime_topics.py # AUTOGEN: 실시간 TR 카테고리별 상수 (116개)
stock.py # StockAPI (수동 편의 메서드 19개)
generated/ # AUTOGEN: 34개 카테고리 래퍼 248개 메서드
__init__.py # - GeneratedAPI facade
stock_quote.py # - client.api.stock_quote.t1101(...)
...
specs/
catalog.json # 41개 API 그룹 메타
index.json # 364 TR → 엔드포인트 매핑
blocks.json # 364 TR → InBlock/OutBlock 필드 목록
apis/<api_id>.json
tools/
crawl_specs.py # Playwright/urllib 기반 카탈로그 덤프
gen_wrappers.py # specs → lsapi/generated/ 코드 생성기
explore*.py # 사이트 구조 탐색 (개발 히스토리용)
samples/
01_quote.py ~ 05_catalog_explore.py
samples/04_order.py는 실계좌 주문을 발생시킵니다. 반드시 모의투자 appkey로 먼저 검증하세요.- LS OpenAPI의 초당 전송 건수(TPS)는 TR마다 다릅니다.
spec.transaction_per_sec로 확인하거나catalog.json의extraParam.ThroughputQuotaRule을 참고하세요. - 응답 본문의
rsp_cd != "00000"는LSApiError로 자동 변환됩니다. HTTP 429는LSRateLimitError.