Metadata-Version: 2.5
Name: toss-openapi-client
Version: 0.1.0
Summary: 토스증권 OpenAPI의 조회와 실시간 수신만 제공하는 Python 클라이언트
Requires-Python: >=3.12
Requires-Dist: anyio<5,>=4
Requires-Dist: httpx<1,>=0.28
Requires-Dist: pydantic<3,>=2
Requires-Dist: websockets<17,>=15
Description-Content-Type: text/markdown

# toss-openapi-client

토스증권 OpenAPI의 조회 REST와 실시간 수신만 제공하는 Python 클라이언트입니다. 일반 거래나 조건 거래를 생성·정정·취소하는 기능은 범위에 넣지 않았습니다.

## 설치

Python 3.12 이상과 `uv`를 준비한 뒤 패키지를 설치합니다.

```bash
uv add toss-openapi-client
```

실행 의존성은 `httpx`, `websockets`, `anyio`, `pydantic`뿐입니다. 개발·검사 도구는 별도의 개발 그룹에 있습니다.

## 자격 증명과 관심 종목 가격

자격 증명은 호출자가 직접 `TossInvestCredentials`로 만듭니다. 클라이언트는 사용자 홈의 비밀번호 파일을 자동으로 읽지 않습니다.

```python
import anyio

from toss_api_client import AsyncTossInvestClient, TossInvestCredentials


async def main() -> None:
    credentials = TossInvestCredentials(
        client_id="발급받은_클라이언트_아이디",
        client_secret="발급받은_클라이언트_보안값",
    )
    async with AsyncTossInvestClient(credentials) as client:
        prices = await client.market_data.get_prices(["005930", "AAPL"])
        for price in prices:
            print(price.symbol, price.last_price, price.currency)


if __name__ == "__main__":
    anyio.run(main)
```

`get_prices()`는 한 번에 1~200개 종목을 받고 가격과 통화를 `Decimal` 기반 응답으로 돌려줍니다. 200개를 넘는 관심 종목은 `market_data.iter_prices()`로 유한한 묶음을 순서대로 받을 수 있습니다.

## 시장 전체 목록과 가격

먼저 `stocks.list_stocks()`로 시장별 상장 종목을 조회한 다음, 애플리케이션이 최대 200개씩 나누어 `get_prices()`를 호출합니다. 클라이언트가 결과를 파일이나 데이터베이스에 저장하지 않으므로 필요한 화면이나 분석 코드에서 바로 소비하십시오.

```python
stocks = await client.stocks.list_stocks(market="KOSPI")
symbols = [stock.symbol for stock in stocks]
async for prices in client.market_data.iter_prices(symbols, batch_size=200):
    print(prices)
```

## 동기 사용

`TossInvestClient`는 같은 조회 REST 서비스를 동기 메서드로 제공합니다. 내부 실행 문맥은 `anyio` 포털 하나를 재사용하며, 동기 클라이언트에는 실시간 세션이 없습니다.

```python
from toss_api_client import TossInvestClient, TossInvestCredentials

credentials = TossInvestCredentials(client_id="아이디", client_secret="보안값")
with TossInvestClient(credentials) as client:
    prices = client.market_data.get_prices(["005930"])
    print(prices)
```

## 실시간 수신

`AsyncTossInvestClient.realtime()`은 전체 교체 방식의 구독 선언과 순수 텍스트 `PING`만 애플리케이션 송신으로 사용합니다. 수신 이벤트는 `TradeEvent`, `OrderbookEvent` 등 형식 모델로 해석됩니다.

```python
from toss_api_client.models.realtime_subscriptions import Subscription, SubscriptionType

session = client.realtime()
async with session:
    await session.set_subscriptions(
        [Subscription(type=SubscriptionType.TRADE_KR, codes=("005930",))]
    )
    event = await session.receive()
    print(event)
```

연결이 끊기면 최근 구독 선언을 다시 보내고 데이터 공백을 별도 이벤트로 알립니다. 초기 스냅샷이나 완전한 틱 이력은 보장하지 않습니다.

## 제한과 지원 범위

요청 제한은 공식 그룹별로 적용하며 응답 헤더의 관측값을 반영합니다. 일시적인 연결 오류·제한 초과·서버 오류에 한해 제한된 횟수로 재시도하고, 다른 오류와 응답 형식 오류는 즉시 돌려줍니다.

공개 REST는 공식 조회 29개와 조회 반복 도우미만 포함합니다. 계좌 문맥이 필요한 조회는 `account_seq`를 명시하거나 클라이언트 기본값을 설정해야 하며 임의로 첫 계좌를 선택하지 않습니다. 거래를 발생시키는 작업, Kafka, 저장소, 수집 일정, 투자 전략은 제공하지 않습니다.

가격·수량·금액은 `Decimal`, 날짜는 `date`, 시각은 시간대가 있는 `datetime`으로 다룹니다. API의 미래 응답 필드는 보존하지만 요청 필드는 엄격하게 검사합니다.

## 개발 명령

저장소를 내려받은 뒤 다음 명령으로 잠금 파일 기준 환경을 만들고 검사합니다.

```bash
uv sync --frozen
uv run ruff format --check .
uv run ruff check .
uv run basedpyright
uv run pytest
uv run python scripts/check_python_size.py
uv run python scripts/check_korean_markdown.py
uv build
```

실사용 읽기 전용 시험은 별도 선택을 명시한 경우에만 실행하며, 자격 증명을 출력하거나 기록하지 않습니다. 이 프로젝트는 PyPI에 게시하지 않고 실제 거래도 수행하지 않습니다.
