Skip to main content

Python client for Toss Securities (토스증권) Open API

Project description

토스증권 Open API Python SDK (tossinvest-core)

토스증권 Open API를 파이썬 환경에서 쉽고 안전하게 연동할 수 있도록 돕는 서비스 지향 컴포지션 패턴(Service Composition Pattern) 기반의 Python SDK입니다.

자동 토큰 만료 관리, 429 Rate Limit 자동 재시도, 다중 계좌 컨텍스트 지원, 세밀한 타입 힌팅 등 프로덕션 환경에 즉시 적용 가능한 완성도 높은 기능들을 제공합니다.


주요 특징

  • 서비스 도메인 격리 (Service Composition): API 명세에 맞춰 시세(market), 계좌(account), 주문(order) 기능이 독립된 서비스 레이어로 설계되어 있어 자동완성과 가독성이 매우 뛰어납니다.
  • OAuth2 토큰 자동 수명 관리: 인증 및 토큰 갱신 로직이 TossInvestClient 내부에서 자동으로 수행됩니다. 만료 60초 전 감지하여 자동으로 토큰을 재발급하므로 개발자가 수동으로 발급 상태를 걱정할 필요가 없습니다.
  • 자동 429 재시도 (Retry-After 대응): API 호출 시 429 Too Many Requests 제한이 발생하면 헤더 및 응답 본문의 대기 시간을 자동으로 추출해 대기(sleep) 후 다시 시도합니다.
  • 계좌 컨텍스트 제어: 기본 계좌(account_seq)를 지정하여 번거로운 파라미터 지정을 생략할 수 있으며, 호출 시 특정 계좌 번호를 전달해 덮어쓰는 다중 계좌 환경도 완벽히 지원합니다.
  • 명확한 예외 및 타입 힌트: TypedDictEnum을 활용한 상세한 타입 정의(models.py) 및 전용 커스텀 예외들을 제공하여 버그 예방과 디버깅을 돕습니다.

설치 방법

PyPI를 통한 간편 설치:

pip install tossinvest-core

로컬 소스 코드로 빌드 및 설치 시:

# 기본 설치
pip install .

# 개발용 모드 설치 (실시간 코드 수정 반영)
pip install -e .

Quick Start

1. 클라이언트 초기화 및 인증

클라이언트 생성 시 토스증권에서 발급받은 client_idclient_secret을 제공해야 합니다. 기본 계좌 번호(account_seq)와 429 발생 시 최대 재시도 횟수(max_retries)도 설정 가능합니다.

import os
from tossinvest import TossInvestClient

# 토스증권 API 클라이언트 초기화
# 내부적으로 base_url("https://openapi.tossinvest.com")과 HTTP Session이 자동 생성 및 관리됩니다.
client = TossInvestClient(
    client_id=os.getenv("TOSS_CLIENT_ID", "your-client-id"),
    client_secret=os.getenv("TOSS_CLIENT_SECRET", "your-client-secret"),
    account_seq=1,       # API 요청 시 X-Tossinvest-Account 헤더로 전달될 기본 계좌 번호
    max_retries=3        # 429 Rate Limit 도달 시 자동 대기 후 재시도할 횟수
)

# 별도의 인증 함수 호출 없이, API 요청 시 내부에서 자동으로 OAuth2 토큰을 발급받아 캐싱 및 갱신합니다.

2. 시세 및 종목 정보 조회 (market 서비스)

국내/해외 주식의 현재가, 호가, 체결, 차트 정보, 환율 및 거래소 휴장일 일정을 조회할 수 있습니다.

# A. 현재가 조회 (최대 200개 종목 다건 조회 가능)
prices = client.market.get_prices(["005930", "AAPL"])
for p in prices:
    print(f"종목: {p['symbol']}, 현재가: {p['lastPrice']} {p['currency']}")

# B. 호가 조회
orderbook = client.market.get_orderbook("005930")
print(f"매도1호가: {orderbook['ask'][0]['price']}, 매수1호가: {orderbook['bid'][0]['price']}")

# C. 최근 체결 내역 조회 (당일 최근 체결 내역을 최대 50개까지 조회)
trades = client.market.get_trades("005930", count=5)
for t in trades:
    print(f"시간: {t['timestamp']}, 체결가: {t['price']}, 체결량: {t['quantity']}")

# D. 당일 상한가 및 하한가 조회
limits = client.market.get_price_limits("005930")
print(f"상한가: {limits['upper']}, 하한가: {limits['lower']}")

# E. 캔들 차트 조회 (interval: '1m' 또는 '1d', 최대 200개 봉)
candles_res = client.market.get_candles("005930", interval="1d", count=10, adjusted=True)
for c in candles_res.get("candles", []):
    print(f"날짜: {c['timestamp']}, 시가: {c['openPrice']}, 종가: {c['closePrice']}")

# F. 종목 기본 정보 조회 (종목명, 시장구분, 결제통화, 상장상태, 거래정지 여부 등)
stocks_info = client.market.get_stocks(["005930", "AAPL"])
for s in stocks_info:
    print(f"종목명: {s['name']}, 시장: {s['market']}, 거래가능여부: {s['tradable']}")

# G. 매수 유의사항 및 VI 발동 정보 조회
warnings = client.market.get_stock_warnings("005930")
for w in warnings:
    print(f"유의타입: {w['type']}, 메시지: {w['message']}")

# H. 실시간 환율 조회 (기준통화 ↔ 상대통화)
exchange = client.market.get_exchange_rate(base_currency="USD", quote_currency="KRW")
print(f"기준환율: {exchange['basePrice']} (고시시간: {exchange['timestamp']})")

# I. 국내/해외 거래소 장 운영 정보 및 휴장일 조회 (country: 'KR' 또는 'US')
calendar = client.market.get_market_calendar(country="KR", date="2026-06-25")
print(f"영업여부: {calendar['businessDay']}, 장 구분: {calendar['status']}")

3. 계좌 및 자산 조회 (account 서비스)

등록된 계좌 목록과 각 계좌의 주식 보유 현황을 조회합니다.

# A. 사용자 등록 계좌 목록 조회 (종합매매 계좌 등 정보 반환)
accounts = client.account.get_accounts()
for acc in accounts:
    print(f"계좌명: {acc['name']}, 계좌번호: {acc['accountNo']}, 순번: {acc['accountSeq']}")

# B. 보유 주식 현황 조회 (평가금액, 매입금액, 수익률, 각 종목별 평균매입가/보유수량 등)
# account_seq를 생략하면 초기화 시 설정한 기본값이 사용되며, 특정 계좌를 조회하려면 파라미터로 넘겨줍니다.
holdings = client.account.get_holdings(account_seq=1)
print(f"총 매입금액: {holdings['purchaseValue']['total']['krw']} KRW")
print(f"총 평가금액: {holdings['marketValue']['total']['krw']} KRW")
for item in holdings.get("items", []):
    print(f" - {item['name']}({item['symbol']}): {item['quantity']}주 (수익률: {item['profitRate']})")

4. 주식 주문 거래 (order 서비스)

주식의 신규 주문 제출, 정정 및 취소, 주문 상세/목록 조회, 매매 가능 수량/수수료 조회가 가능합니다.

# A. 신규 주문 제출 (지정가 LIMIT 또는 시장가 MARKET)
# side: 'BUY' 또는 'SELL', quantity: 수량(주 단위), price: 지정가격(지정가 시 필수)
order_res = client.order.create_order(
    symbol="005930",
    side="BUY",
    order_type="LIMIT",
    quantity="10",
    price="60000",
    client_order_id="my-custom-uuid-001"  # 멱등성 보장을 위한 식별자 (선택)
)
order_id = order_res["orderId"]
print(f"매수 주문 완료: {order_id}")

# * 미국 주식의 경우 소수점 금액 주문(order_amount, 달러 단위)도 지원합니다.
# order_res = client.order.create_order(symbol="AAPL", side="BUY", order_type="MARKET", order_amount="100.50")

# B. 주문 정정
# 국내 주식은 가격과 수량 정정이 모두 가능하나, 미국 주식은 가격 정정만 가능합니다.
modified_res = client.order.modify_order(
    order_id=order_id,
    order_type="LIMIT",
    quantity="5",    # 정정할 수량
    price="60500"     # 정정할 가격
)
print(f"주문 정정 완료, 새 주문 ID: {modified_res['orderId']}")

# C. 주문 취소
cancelled_res = client.order.cancel_order(order_id=modified_res['orderId'])
print(f"주문 취소 접수완료: {cancelled_res['orderId']}")

# D. 주문 목록 조회 (status: 'OPEN' 미체결 또는 'CLOSED' 체결/취소완료)
orders_page = client.order.get_orders(status="CLOSED", symbol="005930", limit=10)
for ord in orders_page.get("orders", []):
    print(f"주문번호: {ord['orderId']}, 상태: {ord['status']}, 체결수량: {ord['filledQuantity']}")

# E. 단건 주문 상세 조회
order_detail = client.order.get_order_detail(order_id=order_id)
print(f"주문시간: {order_detail['orderedAt']}, 평균체결가: {order_detail['executionAveragePrice']}")

# F. 매수 가능 금액 조회 (currency: 'KRW' 또는 'USD')
buying_power = client.order.get_buying_power(currency="KRW")
print(f"현금 매수가능금액: {buying_power['buyingPower']} KRW")

# G. 판매 가능 수량 조회
sellable = client.order.get_sellable_quantity(symbol="005930")
print(f"매도 가능 잔량: {sellable['sellableQuantity']}주")

# H. 계좌별 시장별 수수료율 조회
commissions = client.order.get_commissions()
for comm in commissions:
    print(f"시장: {comm['market']}, 매수수수료: {comm['buyCommissionRate']}, 매도수수료: {comm['sellCommissionRate']}")

에러 핸들링

SDK는 예외 발생 시 예외의 종류에 따라 세분화된 커스텀 Exception 클래스를 발생시킵니다.

  • TossInvestError: SDK에서 발생하는 모든 오류의 기본 클래스입니다.
  • TossInvestAuthError: OAuth2 토큰 발급에 실패한 경우 발생합니다.
  • TossInvestAPIError: 토스증권 API가 에러 상태 코드를 응답한 경우 발생합니다.
    • status_code: HTTP 상태 코드
    • code: 토스증권 API 에러 코드 (예: invalid-request)
    • message: 에러 메시지
    • data: 에러 관련 힌트/상세 데이터 구조
    • request_id: 문제 추적을 위한 API Request ID (X-Request-Id)
  • TossInvestRateLimitError: 429 Too Many Requests 발생 후 최대 재시도(max_retries)에 도달했거나 재시도할 수 없을 때 발생합니다.
    • retry_after_seconds: API 서버가 지시한 대기 시간(초)
from tossinvest import TossInvestClient
from tossinvest.exceptions import (
    TossInvestAuthError,
    TossInvestAPIError,
    TossInvestRateLimitError,
    TossInvestError
)

client = TossInvestClient(client_id="id", client_secret="secret")

try:
    prices = client.market.get_prices(["005930"])
except TossInvestAuthError as e:
    print(f"인증 오류 발생: {e}")
except TossInvestRateLimitError as e:
    print(f"API 호출 한도 초과 (대기필요시간: {e.retry_after_seconds}초): {e}")
except TossInvestAPIError as e:
    print(f"API 호출 실패 [{e.status_code}] (Request ID: {e.request_id})")
    print(f"코드: {e.code}, 메시지: {e.message}")
except TossInvestError as e:
    print(f"기타 SDK 내부 오류: {e}")

타입 힌트 및 모델

모든 API 응답 스키마는 TypedDictEnum을 기반으로 설계되었습니다. 이에 따라 개발자는 pydantic 같은 별도 유효성 검사 라이브러리 사용 부담 없이 정적 타입 검사(mypy, pyright)와 IDE 자동 완성 기능을 100% 누릴 수 있습니다.

from tossinvest.models import PriceResponse, StockInfo, Order

# 타입 명시적 힌팅 활용 예시
def process_price(price: PriceResponse):
    symbol: str = price['symbol']
    last_price: str = price['lastPrice']
    # IDE에서 'symbol', 'lastPrice', 'currency' 등이 자동 완성됩니다.

라이선스

이 프로젝트는 MIT 라이선스에 따라 라이선스가 부여됩니다. 자세한 내용은 LICENSE 파일을 참조하세요.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tossinvest_core-0.1.0.tar.gz (18.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tossinvest_core-0.1.0-py3-none-any.whl (18.8 kB view details)

Uploaded Python 3

File details

Details for the file tossinvest_core-0.1.0.tar.gz.

File metadata

  • Download URL: tossinvest_core-0.1.0.tar.gz
  • Upload date:
  • Size: 18.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tossinvest_core-0.1.0.tar.gz
Algorithm Hash digest
SHA256 bc0aba106d59f5f4c467d9ac250a18adb79e967fcfc9dc017ccdbe3049642f28
MD5 23cd36386c17c52585cdd70bf718d3e8
BLAKE2b-256 9806bbefe80791d0fbb43f4ab3a972718e233e1c4fa12719395a8846bf0d44d4

See more details on using hashes here.

Provenance

The following attestation bundles were made for tossinvest_core-0.1.0.tar.gz:

Publisher: release.yml on gunhoon/tossinvest-core

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tossinvest_core-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: tossinvest_core-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 18.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tossinvest_core-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 413cc09c211e30842a4319ccfbdb085f91f9e611067ce35ac97a443d7b99bb92
MD5 864f756faec6c8af349f1ab73c1d8db6
BLAKE2b-256 6a2b839433a87e6e1560876572123e67d5fb43f0aedd940c31c19661b79eaac2

See more details on using hashes here.

Provenance

The following attestation bundles were made for tossinvest_core-0.1.0-py3-none-any.whl:

Publisher: release.yml on gunhoon/tossinvest-core

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page