pyheroapi


Namepyheroapi JSON
Version 0.4.3 PyPI version JSON
download
home_pageNone
SummaryEasy-to-use Python client for Kiwoom Securities REST API with intuitive interface
upload_time2025-08-25 05:04:30
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseNone
keywords api kiwoom korea securities stock trading
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # PyHero API - AI와 만들어본 키움증권 REST API Python 클라이언트 v0.3.3

[![PyPI version](https://badge.fury.io/py/pyheroapi.svg)](https://badge.fury.io/py/pyheroapi)
[![Python versions](https://img.shields.io/pypi/pyversions/pyheroapi.svg)](https://pypi.org/project/pyheroapi/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Documentation](https://img.shields.io/badge/docs-latest-brightgreen.svg)](https://github.com/gejyn14/pyheroapi#readme)

키움증권 REST API를 파이썬으로 직관적으로 사용하기 위한 클라이언트 라이브러리입니다.

🚀 **v0.3.3 새로운 기능**: 포괄적인 예제 시스템, 실시간 WebSocket 지원, 163개 API 메소드 완전 구현

---

## 🌟 주요 특징

### 💡 **직관적이고 강력한 API**
- 🎯 **한 줄 연결**: `pyheroapi.connect()` 한 번으로 모든 기능 사용
- 🔄 **자동 토큰 관리**: 토큰 발급, 갱신, 폐기 완전 자동화
- 🛡️ **우아한 오류 처리**: 예외 대신 안전한 기본값 반환
- ⚡ **스마트 캐싱**: 중복 API 호출 자동 최적화

### 📊 **완전한 거래 시스템**
- ✅ **포괄적인 주문 관리**: 매수/매도, 정정/취소, 조건부 주문
- ✅ **신용거래 지원**: 신용 매수/매도, 대출 관리
- ✅ **다양한 주문 유형**: 지정가, 시장가, 최유리, IOC, FOK 등
- ✅ **실시간 주문 추적**: 미체결/체결 내역, 실시간 상태 업데이트

### 🔥 **실시간 데이터 스트리밍**
- 🌐 **WebSocket 실시간 시세**: 주가, 호가, 체결 데이터
- 📈 **실시간 계좌 모니터링**: 잔고, 포지션 변화 추적
- ⚡ **비동기 처리**: async/await 패턴 완전 지원
- 🔔 **이벤트 기반 콜백**: 실시간 데이터 변화 알림

### 💰 **고급 금융 데이터 분석**
- 📊 **ETF 심화 분석**: NAV, 추적오차, 수익률, 구성종목
- ⚡ **ELW 전문 도구**: 그릭스(Delta, Gamma, Theta, Vega), 민감도 지표
- 🏛️ **기관/외국인 매매**: 실시간 매매 동향, 순매수/순매도
- 📈 **시장 순위 분석**: 거래량, 등락률, 시가총액 순위

### 🎓 **교육적 예제 시스템**
- 📚 **7개 포괄적 모듈**: 기초부터 고급까지 단계별 학습
- 🛡️ **안전한 샌드박스**: 모의거래 환경 제공공
- 📖 **상세한 문서화**: 모든 기능에 대한 실용적 예제
- 🔧 **프로덕션 준비**: 실제 거래를 위한 안전 가이드

---

## 🎯 완전한 API 커버리지

### **✅ 163개 API 메소드 구현 완료**

| 카테고리 | 구현된 기능 | 커버리지 |
|---------|------------|---------|
| 🔐 **인증 & 토큰** | 토큰 발급/폐기, 자동 관리 | **100%** |
| 💰 **주문 & 거래** | 모든 주문 유형, 신용거래 | **100%** |
| 🏛️ **계좌 관리** | 잔고, 포지션, 손익분석 | **100%** |
| 📊 **시세 데이터** | 실시간/과거 시세, 호가 | **100%** |
| 📈 **차트 데이터** | 일/주/월/분봉, 기술적 지표 | **100%** |
| 🔍 **종목 정보** | 종목 상세정보, 재무데이터 | **95%** |
| 💹 **ETF 분석** | NAV, 추적오차, 구성종목 | **100%** |
| ⚡ **ELW 도구** | 그릭스, 민감도, 조건검색 | **100%** |
| 📊 **순위 정보** | 거래량/등락률/시총 순위 | **100%** |
| 🏢 **기관/외국인** | 매매 동향, 보유 현황 | **100%** |
| 🔄 **실시간 데이터** | WebSocket 스트리밍 | **100%** |
| 🎯 **조건 검색** | 실시간 조건검색, 조건목록 관리 | **100%** |

---

## 🚀 빠른 시작

### 설치

```bash
# 기본 설치
pip install pyheroapi

# 실시간 기능 포함
pip install pyheroapi[realtime]

# 모든 기능 포함
pip install pyheroapi[all]
```

### 환경 변수 설정

```bash
# ~/.bashrc 또는 ~/.zshrc에 추가
export KIWOOM_APPKEY="your_app_key_here"
export KIWOOM_SECRETKEY="your_secret_key_here"  
export KIWOOM_ACCOUNT_NUMBER="your_account_number_here"
```

### 🎯 30초 시작하기

```python
import pyheroapi

# 1. 간단한 연결 (샌드박스 모드)
with pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly
    # 2. 주식 가격 조회
    samsung = api.stock("005930")
    price = samsung.current_price
    print(f"삼성전자: ₩{price:,.0f}")
    
    # 3. 계좌 정보
    account = api.account()
    balance = account.balance["available_balance"] 
    print(f"주문가능금액: ₩{balance:,.0f}")
    
    # 4. 시장 순위 (상위 10개)
    rankings = api.rankings.volume_leaders(limit=10)
    for rank, stock in enumerate(rankings, 1):
        print(f"{rank}. {stock['name']}: {stock['volume']:,}주")
```

---

## 📚 포괄적인 예제 시스템

### 🎓 **7개 교육 모듈 - 초급부터 전문가까지**

#### [`01_authentication.py`](examples/01_authentication.py) - 🔐 인증 기초
```python
# 토큰 관리의 모든 것
from pyheroapi import KiwoomClient

# 환경변수에서 자동 로드
client = KiwoomClient.create_with_credentials()

# 토큰 수동 관리
token = client.issue_token()
print(f"발급된 토큰: {token.token[:20]}...")

# 토큰 검증 및 폐기
is_valid = client.validate_token()
client.revoke_token()
```

#### [`02_market_data.py`](examples/02_market_data.py) - 📊 시세 데이터 마스터
```python
# 실시간 시세부터 과거 데이터까지
with pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly
    # 실시간 시세
    samsung = api.stock("005930")
    quote = samsung.quote
    print(f"현재가: {quote['current_price']}")
    print(f"매수호가: {quote['best_bid']}")
    print(f"매도호가: {quote['best_ask']}")
    
    # OHLCV 과거 데이터
    history = samsung.get_daily_data(period="1Y")
    
    # 분봉 데이터 
    minute_data = samsung.get_minute_data(interval="1", period="1D")
    
    # 시장 성과 지표
    performance = samsung.market_performance()
    print(f"거래강도: {performance['trading_intensity']}")
```

#### [`03_trading_orders.py`](examples/03_trading_orders.py) - 💰 거래 실행 완전 가이드
```python
# 모든 종류의 주문과 관리
with pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly
    # 계좌 상태 확인
    account = api.account()
    balance = account.balance
    print(f"주문가능금액: ₩{balance['available']:,.0f}")
    
    # 다양한 주문 유형
    # 지정가 매수
    result = api.trading.buy("005930", quantity=10, price=75000, order_type="limit")
    
    # 시장가 매도  
    result = api.trading.sell("005930", quantity=5, order_type="market")
    
    # 조건부 지정가
    result = api.trading.buy("005930", quantity=10, price=75000, 
                           order_type="conditional_limit", condition_price=74000)
    
    # 주문 수정/취소
    if result["success"]:
        order_no = result["order_number"]
        
        # 주문 수정
        api.trading.modify_order(order_no, "005930", new_quantity=8, new_price=74500)
        
        # 주문 취소
        api.trading.cancel_order(order_no, "005930", cancel_quantity=8)
    
    # 신용거래
    credit_result = api.trading.credit_buy("005930", quantity=100, price=75000)
```

#### [`04_etf_elw.py`](examples/04_etf_elw.py) - 💹 ETF/ELW 전문 분석
```python
# ETF와 ELW의 모든 것
with pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly
    # ETF 심화 분석
    kodex = api.etf("069500")
    
    # NAV 분석
    nav_data = kodex.get_nav_analysis()
    print(f"NAV: ₩{nav_data['nav']:,.2f}")
    print(f"괴리율: {nav_data['premium_discount']:.2f}%")
    print(f"추적오차: {nav_data['tracking_error']:.4f}")
    
    # ETF 구성종목
    holdings = kodex.get_holdings()
    for holding in holdings[:10]:
        print(f"{holding['symbol']}: {holding['weight']:.2f}%")
    
    # ELW 그릭스 분석
    elw = api.elw("5XXXXX")  # ELW 종목코드
    
    # 실시간 그릭스
    greeks = elw.get_greeks()
    print(f"Delta: {greeks['delta']:.4f}")
    print(f"Gamma: {greeks['gamma']:.4f}")
    print(f"Theta: {greeks['theta']:.4f}")
    print(f"Vega: {greeks['vega']:.4f}")
    
    # 민감도 지표
    sensitivity = elw.get_sensitivity_indicators()
    
    # ELW 조건 검색 (REST API)
    elw_search = client.get_elw_condition_search(
        underlying_asset_code="201",  # KOSPI200
        right_type="1",  # 콜옵션
        sort_type="1"    # 상승율순
    )
    
    # 실시간 조건검색 (WebSocket)
    async def on_condition_result(data):
        print(f"조건검색 결과: {data['symbol']} - {data['name']}")
    
    # 조건검색 목록 조회
    await client.realtime.get_conditional_search_list()
    
    # 조건검색 실행 (일반)
    await client.realtime.execute_conditional_search("1", "0")
    
    # 조건검색 실시간 모니터링
    await client.realtime.execute_conditional_search_realtime("1")
    
    # 실시간 조건검색 해제
    await client.realtime.cancel_conditional_search_realtime("1")
```

#### [`05_rankings_analysis.py`](examples/05_rankings_analysis.py) - 📈 시장 순위 분석
```python
# 시장의 모든 순위 정보
with pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly
    # 거래량 순위
    volume_leaders = api.rankings.volume_leaders(limit=20)
    print("🔥 거래량 TOP 20")
    for i, stock in enumerate(volume_leaders, 1):
        print(f"{i:2d}. {stock['name']:10s} {stock['volume']:>10,}주")
    
    # 상승률 순위
    gainers = api.rankings.price_gainers(limit=10)
    print("\n📈 상승률 TOP 10")
    for stock in gainers:
        print(f"{stock['name']}: +{stock['change_rate']:.2f}%")
    
    # 외국인 순매수 순위
    foreign_net_buy = api.rankings.foreign_net_buying(limit=15)
    print("\n🌍 외국인 순매수 TOP 15")
    
    # 기관 순매수 순위  
    institutional_buy = api.rankings.institutional_net_buying(limit=15)
    
    # 프로그램 매매 분석
    program_trading = api.rankings.program_trading_activity()
    
    # 섹터별 분석
    sector_performance = api.rankings.sector_performance()
    print("\n🏭 섹터 성과")
    for sector in sector_performance:
        print(f"{sector['name']}: {sector['change_rate']:+.2f}%")
```

#### [`06_charts_technical.py`](examples/06_charts_technical.py) - 📊 차트 & 기술적 분석
```python
# 모든 차트 데이터와 기술적 분석
with pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly
    samsung = api.stock("005930")
    
    # 다양한 시간프레임 차트
    daily_chart = samsung.get_chart_data("daily", period="6M")
    weekly_chart = samsung.get_chart_data("weekly", period="2Y") 
    monthly_chart = samsung.get_chart_data("monthly", period="5Y")
    
    # 분봉 차트 (1분, 5분, 15분, 30분, 60분)
    minute_1 = samsung.get_chart_data("1min", period="1D")
    minute_5 = samsung.get_chart_data("5min", period="5D")
    minute_30 = samsung.get_chart_data("30min", period="1M")
    
    # 기술적 지표 계산
    def calculate_sma(data, period=20):
        """단순이동평균 계산"""
        prices = [float(d['close']) for d in data]
        sma = []
        for i in range(len(prices)):
            if i >= period - 1:
                avg = sum(prices[i-period+1:i+1]) / period
                sma.append(avg)
            else:
                sma.append(None)
        return sma
    
    # 20일 이동평균
    sma_20 = calculate_sma(daily_chart, 20)
    
    # 거래량 분석
    volume_analysis = samsung.volume_analysis(period="3M")
    
    # 업종 차트 분석
    sector_chart = api.get_sector_chart("전기전자", period="1Y")
```

#### [`07_realtime_websocket.py`](examples/07_realtime_websocket.py) - 🌐 실시간 스트리밍
```python
# WebSocket을 통한 실시간 데이터 스트리밍
import asyncio
from pyheroapi import RealtimeClient

async def main():
    # 실시간 클라이언트 생성
    realtime = RealtimeClient()
    await realtime.connect()
    
    # 실시간 시세 콜백
    def on_price_update(data):
        print(f"[{data['symbol']}] ₩{data['price']:,} ({data['change']:+.2f}%)")
    
    # 실시간 호가 콜백  
    def on_orderbook_update(data):
        print(f"매수호가: ₩{data['best_bid']:,} / 매도호가: ₩{data['best_ask']:,}")
    
    # 실시간 체결 콜백
    def on_trade_update(data):
        print(f"체결: {data['quantity']:,}주 @ ₩{data['price']:,}")
    
    # 실시간 계좌 콜백
    def on_account_update(data):
        print(f"계좌변화: 잔고 ₩{data['balance']:,}")
    
    # 실시간 조건검색 콜백
    def on_conditional_search_result(data):
        print(f"🎯 조건검색 편입: {data['symbol']} - 시간: {data['time']}")
    
    def on_conditional_search_list(data):
        print(f"📋 조건검색 목록: {len(data)}개 조건식 확인")
    
    # 구독 설정
    await realtime.subscribe_price("005930", on_price_update)
    await realtime.subscribe_orderbook("005930", on_orderbook_update)  
    await realtime.subscribe_trades("005930", on_trade_update)
    await realtime.subscribe_account("your_account", on_account_update)
    
    # 조건검색 콜백 등록
    realtime.register_callback('conditional_search_realtime', on_conditional_search_result)
    realtime.register_callback('conditional_search_list', on_conditional_search_list)
    
    # 조건검색 목록 조회
    await realtime.get_conditional_search_list()
    
    # 실시간 조건검색 시작 (조건식 번호 "1")
    await realtime.execute_conditional_search_realtime("1")
    
    # 다중 종목 구독
    symbols = ["005930", "000660", "035420", "005380", "068270"]
    for symbol in symbols:
        await realtime.subscribe_price(symbol, on_price_update)
    
    # 실시간 데이터 수신 대기
    print("🔴 실시간 데이터 수신 중... (Ctrl+C로 중단)")
    try:
        await realtime.listen()
    except KeyboardInterrupt:
        print("\n⏹️ 실시간 데이터 수신 중단")
        await realtime.disconnect()

# 실행
if __name__ == "__main__":
    asyncio.run(main())
```

---

## 🔥 고급 기능

### 🎯 **스마트 포트폴리오 관리**

```python
with pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly
    account = api.account()
    
    # 전체 포트폴리오 분석
    portfolio = account.get_portfolio_analysis()
    print(f"총 평가금액: ₩{portfolio['total_value']:,.0f}")
    print(f"실현손익: ₩{portfolio['realized_pnl']:,.0f}")
    print(f"평가손익: ₩{portfolio['unrealized_pnl']:,.0f}")
    print(f"총 수익률: {portfolio['total_return']:.2f}%")
    
    # 종목별 포지션
    positions = account.positions
    for pos in positions:
        print(f"{pos['name']}: {pos['quantity']:,}주")
        print(f"  평균단가: ₩{pos['avg_price']:,}")
        print(f"  현재가: ₩{pos['current_price']:,}")
        print(f"  수익률: {pos['return_rate']:+.2f}%")
        print(f"  평가손익: ₩{pos['unrealized_pnl']:+,.0f}")
    
    # 일별 손익 내역
    daily_pnl = account.get_daily_pnl(days=30)
    total_trades = sum(day['trade_count'] for day in daily_pnl)
    total_pnl = sum(day['realized_pnl'] for day in daily_pnl)
    
    print(f"\n📊 30일 거래 통계")
    print(f"총 거래 횟수: {total_trades:,}회")
    print(f"실현손익 합계: ₩{total_pnl:+,.0f}")
```

### 📊 **고급 시장 분석**

```python
with pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly
    # 시장 전체 현황
    market_summary = api.get_market_summary()
    print(f"KOSPI: {market_summary['kospi']['value']:.2f} ({market_summary['kospi']['change']:+.2f}%)")
    print(f"KOSDAQ: {market_summary['kosdaq']['value']:.2f} ({market_summary['kosdaq']['change']:+.2f}%)")
    
    # 외국인/기관 매매 동향
    institutional_flow = api.get_institutional_trading()
    print(f"\n💰 외국인 순매매: ₩{institutional_flow['foreign_net']:+,.0f}억")
    print(f"💰 기관 순매매: ₩{institutional_flow['institution_net']:+,.0f}억")
    
    # 프로그램 매매 현황
    program_trading = api.get_program_trading()
    print(f"📈 프로그램 매수: ₩{program_trading['buy_amount']:,.0f}억")
    print(f"📉 프로그램 매도: ₩{program_trading['sell_amount']:,.0f}억")
    
    # 신용거래 현황
    credit_info = api.get_credit_balance()
    print(f"🏦 신용잔고: ₩{credit_info['credit_balance']:,.0f}억")
    print(f"🏦 대주잔고: ₩{credit_info['lending_balance']:,.0f}억")
```

### ⚡ **고성능 일괄 처리**

```python
import asyncio
from concurrent.futures import ThreadPoolExecutor

async def analyze_multiple_stocks(symbols):
    """여러 종목 동시 분석"""
    with pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly
        with ThreadPoolExecutor(max_workers=10) as executor:
            # 동시에 여러 종목 데이터 수집
            futures = []
            for symbol in symbols:
                future = executor.submit(api.stock(symbol).get_complete_data)
                futures.append((symbol, future))
            
            results = {}
            for symbol, future in futures:
                try:
                    data = future.result(timeout=30)
                    results[symbol] = data
                    print(f"✅ {symbol}: 데이터 수집 완료")
                except Exception as e:
                    print(f"❌ {symbol}: 오류 - {e}")
            
            return results

# 대형주 TOP 20 동시 분석
large_caps = ["005930", "000660", "035420", "005380", "068270", 
              "207940", "005490", "035720", "000270", "006400"]

results = asyncio.run(analyze_multiple_stocks(large_caps))
```

---

## 🛡️ 안전 가이드

### 🔒 **보안 모범 사례**

```python
import os
from pyheroapi import KiwoomClient

# ✅ 환경변수 사용 (권장)
appkey = os.getenv("KIWOOM_APPKEY")
secretkey = os.getenv("KIWOOM_SECRETKEY")

# ❌ 하드코딩 금지
# appkey = "PAKXXXXXXXX"  # 절대 금지!

# 안전한 클라이언트 생성
client = KiwoomClient.create_with_credentials(
    appkey=appkey,
    secretkey=secretkey,
    is_production=False,  # SANDBOX MODE: set is_production=False explicitly
    timeout=30,
    retry_attempts=3
)
```

### 🎯 **거래 안전 점검**

```python
def safe_trading_example():
    """안전한 거래 프로세스"""
    with pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly
        account = api.account()
        
        # 1. 계좌 상태 확인
        balance = account.balance
        available = balance["available_balance"]
        print(f"주문가능금액: ₩{available:,.0f}")
        
        # 2. 종목 분석
        samsung = api.stock("005930")
        current_price = samsung.current_price
        quote = samsung.quote
        
        # 3. 안전 점검
        order_amount = current_price * 100  # 100주 주문금액
        
        if available < order_amount:
            print("❌ 주문가능금액 부족")
            return
        
        if quote["volume"] < 1000:  # 최소 거래량 점검
            print("❌ 거래량 부족 - 주문 취소")
            return
        
        # 4. 주문 실행 (샌드박스에서만!)
        result = api.trading.buy("005930", quantity=100, price=current_price)
        
        if result["success"]:
            print(f"✅ 주문 성공: {result['order_number']}")
            
            # 5. 주문 상태 모니터링
            order_status = api.trading.get_order_status(result["order_number"])
            print(f"주문 상태: {order_status['status']}")
        else:
            print(f"❌ 주문 실패: {result['message']}")

# 실행
safe_trading_example()
```

---

## 🎓 단계별 학습 가이드

### **1단계: 기초 (1-2일)**
- [`01_authentication.py`](examples/01_authentication.py) - 인증과 토큰 관리
- [`02_market_data.py`](examples/02_market_data.py) - 기본 시세 조회

### **2단계: 거래 (3-5일)**  
- [`03_trading_orders.py`](examples/03_trading_orders.py) - 주문 실행과 관리
- 샌드박스에서 충분한 연습

### **3단계: 분석 (1주)**
- [`04_etf_elw.py`](examples/04_etf_elw.py) - ETF/ELW 전문 분석
- [`05_rankings_analysis.py`](examples/05_rankings_analysis.py) - 시장 순위 분석
- [`06_charts_technical.py`](examples/06_charts_technical.py) - 차트와 기술적 분석

### **4단계: 고급 (2주)**
- [`07_realtime_websocket.py`](examples/07_realtime_websocket.py) - 실시간 스트리밍
- 포트폴리오 관리 시스템 구축
- 자동 매매 시스템 개발

---

## 🔧 환경 설정

### **API 키 발급**
1. [키움 OpenAPI 홈페이지지](https://openapi.kiwoom.com/) 방문
2. 계정 생성 및 로그인
3. REST API 서비스 신청
4. APP KEY와 SECRET KEY 발급

### **개발 환경 설정**

```bash
# 1. 프로젝트 폴더 생성
mkdir my_trading_bot
cd my_trading_bot

# 2. 가상환경 생성
python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate

# 3. PyHeroAPI 설치
pip install pyheroapi[all]

# 4. 환경변수 설정
echo 'export KIWOOM_APPKEY="키움 REST API APPKEY' >> ~/.bashrc
echo 'export KIWOOM_SECRETKEY="키움 REST API SECRETKEY"' >> ~/.bashrc
source ~/.bashrc

# 5. 첫 번째 테스트
python -c "
import pyheroapi
with pyheroapi.connect(is_production=False) as api:
    print('✅ 연결 성공!')
    print(f'삼성전자: ₩{api.stock(\"005930\").current_price:,.0f}')
"
```

---

## 📋 시스템 요구사항

- **Python**: 3.8 이상
- **운영체제**: Windows, macOS, Linux
- **메모리**: 최소 512MB (실시간 스트리밍 시 1GB 권장)
- **네트워크**: 안정적인 인터넷 연결

### **의존성 패키지**
```
requests>=2.25.0        # HTTP 클라이언트
pydantic>=2.0.0         # 데이터 검증
typing-extensions>=4.0.0 # 타입 힌트
websockets>=11.0.0      # 실시간 스트리밍 (선택사항)
```

---

## ⚠️ 중요 공지사항

### **면책조항**
- 📖 **교육 목적**: 이 라이브러리는 교육 및 개발 목적으로 제공됩니다
- 💰 **투자 책임**: 실제 거래로 인한 손실에 대해 책임지지 않습니다
- 🧪 **충분한 테스트**: 실거래 전 반드시 샌드박스에서 충분히 테스트하세요
- 📊 **시장 리스크**: 주식 투자에는 원금 손실 위험이 있습니다

### **사용 제한사항**
- 🕐 **API 호출 제한**: 초당 요청 수 제한 (자동 관리됨)
- 🏛️ **장 시간 제한**: 일부 기능은 개장 시간에만 작동
- 📱 **실시간 데이터**: 약간의 지연이 있을 수 있음
- 🔒 **보안**: API 키는 절대 공개하지 마세요

---

## 🤝 커뮤니티

### **기여하기**
1. 🍴 [저장소 포크](https://github.com/gejyn14/pyheroapi/fork)
2. 🌿 기능 브랜치 생성: `git checkout -b feature/amazing-feature`
3. 📝 변경사항 커밋: `git commit -m 'Add amazing feature'`
4. 📤 브랜치 푸시: `git push origin feature/amazing-feature`
5. 🔄 Pull Request 생성

### **지원 채널**
- 📖 **문서**: [GitHub Wiki](https://github.com/gejyn14/pyheroapi/wiki)
- 🐛 **버그 리포트**: [Issues](https://github.com/gejyn14/pyheroapi/issues)
- 💡 **기능 요청**: [Discussions](https://github.com/gejyn14/pyheroapi/discussions)
- 📧 **이메일**: dean_jin@icloud.com

### **라이선스**
MIT License - 자세한 내용은 [LICENSE](LICENSE) 파일 참조

---

<div align="center">

### ⭐ 이 프로젝트가 도움이 되셨다면 별표를 눌러주세요!

[![GitHub stars](https://img.shields.io/github/stars/gejyn14/pyheroapi.svg?style=social&label=Star)](https://github.com/gejyn14/pyheroapi)
[![GitHub forks](https://img.shields.io/github/forks/gejyn14/pyheroapi.svg?style=social&label=Fork)](https://github.com/gejyn14/pyheroapi/fork)

**Happy Trading! 📈🚀**

**⚠️ 면책조항**: 이 라이브러리는 교육 및 개발 목적으로 제공됩니다. 실제 거래에서 발생하는 손실에 대해서는 책임지지 않습니다. 거래 시 주의하시기 바랍니다.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "pyheroapi",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "api, kiwoom, korea, securities, stock, trading",
    "author": null,
    "author_email": "Kiwoom API Client <contact@example.com>",
    "download_url": "https://files.pythonhosted.org/packages/e1/43/721c73e54753e2390876365a98bff0ff75c8a10a7c6b2dcc6b20262838c8/pyheroapi-0.4.3.tar.gz",
    "platform": null,
    "description": "# PyHero API - AI\uc640 \ub9cc\ub4e4\uc5b4\ubcf8 \ud0a4\uc6c0\uc99d\uad8c REST API Python \ud074\ub77c\uc774\uc5b8\ud2b8 v0.3.3\n\n[![PyPI version](https://badge.fury.io/py/pyheroapi.svg)](https://badge.fury.io/py/pyheroapi)\n[![Python versions](https://img.shields.io/pypi/pyversions/pyheroapi.svg)](https://pypi.org/project/pyheroapi/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Documentation](https://img.shields.io/badge/docs-latest-brightgreen.svg)](https://github.com/gejyn14/pyheroapi#readme)\n\n\ud0a4\uc6c0\uc99d\uad8c REST API\ub97c \ud30c\uc774\uc36c\uc73c\ub85c \uc9c1\uad00\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\uae30 \uc704\ud55c \ud074\ub77c\uc774\uc5b8\ud2b8 \ub77c\uc774\ube0c\ub7ec\ub9ac\uc785\ub2c8\ub2e4.\n\n\ud83d\ude80 **v0.3.3 \uc0c8\ub85c\uc6b4 \uae30\ub2a5**: \ud3ec\uad04\uc801\uc778 \uc608\uc81c \uc2dc\uc2a4\ud15c, \uc2e4\uc2dc\uac04 WebSocket \uc9c0\uc6d0, 163\uac1c API \uba54\uc18c\ub4dc \uc644\uc804 \uad6c\ud604\n\n---\n\n## \ud83c\udf1f \uc8fc\uc694 \ud2b9\uc9d5\n\n### \ud83d\udca1 **\uc9c1\uad00\uc801\uc774\uace0 \uac15\ub825\ud55c API**\n- \ud83c\udfaf **\ud55c \uc904 \uc5f0\uacb0**: `pyheroapi.connect()` \ud55c \ubc88\uc73c\ub85c \ubaa8\ub4e0 \uae30\ub2a5 \uc0ac\uc6a9\n- \ud83d\udd04 **\uc790\ub3d9 \ud1a0\ud070 \uad00\ub9ac**: \ud1a0\ud070 \ubc1c\uae09, \uac31\uc2e0, \ud3d0\uae30 \uc644\uc804 \uc790\ub3d9\ud654\n- \ud83d\udee1\ufe0f **\uc6b0\uc544\ud55c \uc624\ub958 \ucc98\ub9ac**: \uc608\uc678 \ub300\uc2e0 \uc548\uc804\ud55c \uae30\ubcf8\uac12 \ubc18\ud658\n- \u26a1 **\uc2a4\ub9c8\ud2b8 \uce90\uc2f1**: \uc911\ubcf5 API \ud638\ucd9c \uc790\ub3d9 \ucd5c\uc801\ud654\n\n### \ud83d\udcca **\uc644\uc804\ud55c \uac70\ub798 \uc2dc\uc2a4\ud15c**\n- \u2705 **\ud3ec\uad04\uc801\uc778 \uc8fc\ubb38 \uad00\ub9ac**: \ub9e4\uc218/\ub9e4\ub3c4, \uc815\uc815/\ucde8\uc18c, \uc870\uac74\ubd80 \uc8fc\ubb38\n- \u2705 **\uc2e0\uc6a9\uac70\ub798 \uc9c0\uc6d0**: \uc2e0\uc6a9 \ub9e4\uc218/\ub9e4\ub3c4, \ub300\ucd9c \uad00\ub9ac\n- \u2705 **\ub2e4\uc591\ud55c \uc8fc\ubb38 \uc720\ud615**: \uc9c0\uc815\uac00, \uc2dc\uc7a5\uac00, \ucd5c\uc720\ub9ac, IOC, FOK \ub4f1\n- \u2705 **\uc2e4\uc2dc\uac04 \uc8fc\ubb38 \ucd94\uc801**: \ubbf8\uccb4\uacb0/\uccb4\uacb0 \ub0b4\uc5ed, \uc2e4\uc2dc\uac04 \uc0c1\ud0dc \uc5c5\ub370\uc774\ud2b8\n\n### \ud83d\udd25 **\uc2e4\uc2dc\uac04 \ub370\uc774\ud130 \uc2a4\ud2b8\ub9ac\ubc0d**\n- \ud83c\udf10 **WebSocket \uc2e4\uc2dc\uac04 \uc2dc\uc138**: \uc8fc\uac00, \ud638\uac00, \uccb4\uacb0 \ub370\uc774\ud130\n- \ud83d\udcc8 **\uc2e4\uc2dc\uac04 \uacc4\uc88c \ubaa8\ub2c8\ud130\ub9c1**: \uc794\uace0, \ud3ec\uc9c0\uc158 \ubcc0\ud654 \ucd94\uc801\n- \u26a1 **\ube44\ub3d9\uae30 \ucc98\ub9ac**: async/await \ud328\ud134 \uc644\uc804 \uc9c0\uc6d0\n- \ud83d\udd14 **\uc774\ubca4\ud2b8 \uae30\ubc18 \ucf5c\ubc31**: \uc2e4\uc2dc\uac04 \ub370\uc774\ud130 \ubcc0\ud654 \uc54c\ub9bc\n\n### \ud83d\udcb0 **\uace0\uae09 \uae08\uc735 \ub370\uc774\ud130 \ubd84\uc11d**\n- \ud83d\udcca **ETF \uc2ec\ud654 \ubd84\uc11d**: NAV, \ucd94\uc801\uc624\ucc28, \uc218\uc775\ub960, \uad6c\uc131\uc885\ubaa9\n- \u26a1 **ELW \uc804\ubb38 \ub3c4\uad6c**: \uadf8\ub9ad\uc2a4(Delta, Gamma, Theta, Vega), \ubbfc\uac10\ub3c4 \uc9c0\ud45c\n- \ud83c\udfdb\ufe0f **\uae30\uad00/\uc678\uad6d\uc778 \ub9e4\ub9e4**: \uc2e4\uc2dc\uac04 \ub9e4\ub9e4 \ub3d9\ud5a5, \uc21c\ub9e4\uc218/\uc21c\ub9e4\ub3c4\n- \ud83d\udcc8 **\uc2dc\uc7a5 \uc21c\uc704 \ubd84\uc11d**: \uac70\ub798\ub7c9, \ub4f1\ub77d\ub960, \uc2dc\uac00\ucd1d\uc561 \uc21c\uc704\n\n### \ud83c\udf93 **\uad50\uc721\uc801 \uc608\uc81c \uc2dc\uc2a4\ud15c**\n- \ud83d\udcda **7\uac1c \ud3ec\uad04\uc801 \ubaa8\ub4c8**: \uae30\ucd08\ubd80\ud130 \uace0\uae09\uae4c\uc9c0 \ub2e8\uacc4\ubcc4 \ud559\uc2b5\n- \ud83d\udee1\ufe0f **\uc548\uc804\ud55c \uc0cc\ub4dc\ubc15\uc2a4**: \ubaa8\uc758\uac70\ub798 \ud658\uacbd \uc81c\uacf5\uacf5\n- \ud83d\udcd6 **\uc0c1\uc138\ud55c \ubb38\uc11c\ud654**: \ubaa8\ub4e0 \uae30\ub2a5\uc5d0 \ub300\ud55c \uc2e4\uc6a9\uc801 \uc608\uc81c\n- \ud83d\udd27 **\ud504\ub85c\ub355\uc158 \uc900\ube44**: \uc2e4\uc81c \uac70\ub798\ub97c \uc704\ud55c \uc548\uc804 \uac00\uc774\ub4dc\n\n---\n\n## \ud83c\udfaf \uc644\uc804\ud55c API \ucee4\ubc84\ub9ac\uc9c0\n\n### **\u2705 163\uac1c API \uba54\uc18c\ub4dc \uad6c\ud604 \uc644\ub8cc**\n\n| \uce74\ud14c\uace0\ub9ac | \uad6c\ud604\ub41c \uae30\ub2a5 | \ucee4\ubc84\ub9ac\uc9c0 |\n|---------|------------|---------|\n| \ud83d\udd10 **\uc778\uc99d & \ud1a0\ud070** | \ud1a0\ud070 \ubc1c\uae09/\ud3d0\uae30, \uc790\ub3d9 \uad00\ub9ac | **100%** |\n| \ud83d\udcb0 **\uc8fc\ubb38 & \uac70\ub798** | \ubaa8\ub4e0 \uc8fc\ubb38 \uc720\ud615, \uc2e0\uc6a9\uac70\ub798 | **100%** |\n| \ud83c\udfdb\ufe0f **\uacc4\uc88c \uad00\ub9ac** | \uc794\uace0, \ud3ec\uc9c0\uc158, \uc190\uc775\ubd84\uc11d | **100%** |\n| \ud83d\udcca **\uc2dc\uc138 \ub370\uc774\ud130** | \uc2e4\uc2dc\uac04/\uacfc\uac70 \uc2dc\uc138, \ud638\uac00 | **100%** |\n| \ud83d\udcc8 **\ucc28\ud2b8 \ub370\uc774\ud130** | \uc77c/\uc8fc/\uc6d4/\ubd84\ubd09, \uae30\uc220\uc801 \uc9c0\ud45c | **100%** |\n| \ud83d\udd0d **\uc885\ubaa9 \uc815\ubcf4** | \uc885\ubaa9 \uc0c1\uc138\uc815\ubcf4, \uc7ac\ubb34\ub370\uc774\ud130 | **95%** |\n| \ud83d\udcb9 **ETF \ubd84\uc11d** | NAV, \ucd94\uc801\uc624\ucc28, \uad6c\uc131\uc885\ubaa9 | **100%** |\n| \u26a1 **ELW \ub3c4\uad6c** | \uadf8\ub9ad\uc2a4, \ubbfc\uac10\ub3c4, \uc870\uac74\uac80\uc0c9 | **100%** |\n| \ud83d\udcca **\uc21c\uc704 \uc815\ubcf4** | \uac70\ub798\ub7c9/\ub4f1\ub77d\ub960/\uc2dc\ucd1d \uc21c\uc704 | **100%** |\n| \ud83c\udfe2 **\uae30\uad00/\uc678\uad6d\uc778** | \ub9e4\ub9e4 \ub3d9\ud5a5, \ubcf4\uc720 \ud604\ud669 | **100%** |\n| \ud83d\udd04 **\uc2e4\uc2dc\uac04 \ub370\uc774\ud130** | WebSocket \uc2a4\ud2b8\ub9ac\ubc0d | **100%** |\n| \ud83c\udfaf **\uc870\uac74 \uac80\uc0c9** | \uc2e4\uc2dc\uac04 \uc870\uac74\uac80\uc0c9, \uc870\uac74\ubaa9\ub85d \uad00\ub9ac | **100%** |\n\n---\n\n## \ud83d\ude80 \ube60\ub978 \uc2dc\uc791\n\n### \uc124\uce58\n\n```bash\n# \uae30\ubcf8 \uc124\uce58\npip install pyheroapi\n\n# \uc2e4\uc2dc\uac04 \uae30\ub2a5 \ud3ec\ud568\npip install pyheroapi[realtime]\n\n# \ubaa8\ub4e0 \uae30\ub2a5 \ud3ec\ud568\npip install pyheroapi[all]\n```\n\n### \ud658\uacbd \ubcc0\uc218 \uc124\uc815\n\n```bash\n# ~/.bashrc \ub610\ub294 ~/.zshrc\uc5d0 \ucd94\uac00\nexport KIWOOM_APPKEY=\"your_app_key_here\"\nexport KIWOOM_SECRETKEY=\"your_secret_key_here\"  \nexport KIWOOM_ACCOUNT_NUMBER=\"your_account_number_here\"\n```\n\n### \ud83c\udfaf 30\ucd08 \uc2dc\uc791\ud558\uae30\n\n```python\nimport pyheroapi\n\n# 1. \uac04\ub2e8\ud55c \uc5f0\uacb0 (\uc0cc\ub4dc\ubc15\uc2a4 \ubaa8\ub4dc)\nwith pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly\n    # 2. \uc8fc\uc2dd \uac00\uaca9 \uc870\ud68c\n    samsung = api.stock(\"005930\")\n    price = samsung.current_price\n    print(f\"\uc0bc\uc131\uc804\uc790: \u20a9{price:,.0f}\")\n    \n    # 3. \uacc4\uc88c \uc815\ubcf4\n    account = api.account()\n    balance = account.balance[\"available_balance\"] \n    print(f\"\uc8fc\ubb38\uac00\ub2a5\uae08\uc561: \u20a9{balance:,.0f}\")\n    \n    # 4. \uc2dc\uc7a5 \uc21c\uc704 (\uc0c1\uc704 10\uac1c)\n    rankings = api.rankings.volume_leaders(limit=10)\n    for rank, stock in enumerate(rankings, 1):\n        print(f\"{rank}. {stock['name']}: {stock['volume']:,}\uc8fc\")\n```\n\n---\n\n## \ud83d\udcda \ud3ec\uad04\uc801\uc778 \uc608\uc81c \uc2dc\uc2a4\ud15c\n\n### \ud83c\udf93 **7\uac1c \uad50\uc721 \ubaa8\ub4c8 - \ucd08\uae09\ubd80\ud130 \uc804\ubb38\uac00\uae4c\uc9c0**\n\n#### [`01_authentication.py`](examples/01_authentication.py) - \ud83d\udd10 \uc778\uc99d \uae30\ucd08\n```python\n# \ud1a0\ud070 \uad00\ub9ac\uc758 \ubaa8\ub4e0 \uac83\nfrom pyheroapi import KiwoomClient\n\n# \ud658\uacbd\ubcc0\uc218\uc5d0\uc11c \uc790\ub3d9 \ub85c\ub4dc\nclient = KiwoomClient.create_with_credentials()\n\n# \ud1a0\ud070 \uc218\ub3d9 \uad00\ub9ac\ntoken = client.issue_token()\nprint(f\"\ubc1c\uae09\ub41c \ud1a0\ud070: {token.token[:20]}...\")\n\n# \ud1a0\ud070 \uac80\uc99d \ubc0f \ud3d0\uae30\nis_valid = client.validate_token()\nclient.revoke_token()\n```\n\n#### [`02_market_data.py`](examples/02_market_data.py) - \ud83d\udcca \uc2dc\uc138 \ub370\uc774\ud130 \ub9c8\uc2a4\ud130\n```python\n# \uc2e4\uc2dc\uac04 \uc2dc\uc138\ubd80\ud130 \uacfc\uac70 \ub370\uc774\ud130\uae4c\uc9c0\nwith pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly\n    # \uc2e4\uc2dc\uac04 \uc2dc\uc138\n    samsung = api.stock(\"005930\")\n    quote = samsung.quote\n    print(f\"\ud604\uc7ac\uac00: {quote['current_price']}\")\n    print(f\"\ub9e4\uc218\ud638\uac00: {quote['best_bid']}\")\n    print(f\"\ub9e4\ub3c4\ud638\uac00: {quote['best_ask']}\")\n    \n    # OHLCV \uacfc\uac70 \ub370\uc774\ud130\n    history = samsung.get_daily_data(period=\"1Y\")\n    \n    # \ubd84\ubd09 \ub370\uc774\ud130 \n    minute_data = samsung.get_minute_data(interval=\"1\", period=\"1D\")\n    \n    # \uc2dc\uc7a5 \uc131\uacfc \uc9c0\ud45c\n    performance = samsung.market_performance()\n    print(f\"\uac70\ub798\uac15\ub3c4: {performance['trading_intensity']}\")\n```\n\n#### [`03_trading_orders.py`](examples/03_trading_orders.py) - \ud83d\udcb0 \uac70\ub798 \uc2e4\ud589 \uc644\uc804 \uac00\uc774\ub4dc\n```python\n# \ubaa8\ub4e0 \uc885\ub958\uc758 \uc8fc\ubb38\uacfc \uad00\ub9ac\nwith pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly\n    # \uacc4\uc88c \uc0c1\ud0dc \ud655\uc778\n    account = api.account()\n    balance = account.balance\n    print(f\"\uc8fc\ubb38\uac00\ub2a5\uae08\uc561: \u20a9{balance['available']:,.0f}\")\n    \n    # \ub2e4\uc591\ud55c \uc8fc\ubb38 \uc720\ud615\n    # \uc9c0\uc815\uac00 \ub9e4\uc218\n    result = api.trading.buy(\"005930\", quantity=10, price=75000, order_type=\"limit\")\n    \n    # \uc2dc\uc7a5\uac00 \ub9e4\ub3c4  \n    result = api.trading.sell(\"005930\", quantity=5, order_type=\"market\")\n    \n    # \uc870\uac74\ubd80 \uc9c0\uc815\uac00\n    result = api.trading.buy(\"005930\", quantity=10, price=75000, \n                           order_type=\"conditional_limit\", condition_price=74000)\n    \n    # \uc8fc\ubb38 \uc218\uc815/\ucde8\uc18c\n    if result[\"success\"]:\n        order_no = result[\"order_number\"]\n        \n        # \uc8fc\ubb38 \uc218\uc815\n        api.trading.modify_order(order_no, \"005930\", new_quantity=8, new_price=74500)\n        \n        # \uc8fc\ubb38 \ucde8\uc18c\n        api.trading.cancel_order(order_no, \"005930\", cancel_quantity=8)\n    \n    # \uc2e0\uc6a9\uac70\ub798\n    credit_result = api.trading.credit_buy(\"005930\", quantity=100, price=75000)\n```\n\n#### [`04_etf_elw.py`](examples/04_etf_elw.py) - \ud83d\udcb9 ETF/ELW \uc804\ubb38 \ubd84\uc11d\n```python\n# ETF\uc640 ELW\uc758 \ubaa8\ub4e0 \uac83\nwith pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly\n    # ETF \uc2ec\ud654 \ubd84\uc11d\n    kodex = api.etf(\"069500\")\n    \n    # NAV \ubd84\uc11d\n    nav_data = kodex.get_nav_analysis()\n    print(f\"NAV: \u20a9{nav_data['nav']:,.2f}\")\n    print(f\"\uad34\ub9ac\uc728: {nav_data['premium_discount']:.2f}%\")\n    print(f\"\ucd94\uc801\uc624\ucc28: {nav_data['tracking_error']:.4f}\")\n    \n    # ETF \uad6c\uc131\uc885\ubaa9\n    holdings = kodex.get_holdings()\n    for holding in holdings[:10]:\n        print(f\"{holding['symbol']}: {holding['weight']:.2f}%\")\n    \n    # ELW \uadf8\ub9ad\uc2a4 \ubd84\uc11d\n    elw = api.elw(\"5XXXXX\")  # ELW \uc885\ubaa9\ucf54\ub4dc\n    \n    # \uc2e4\uc2dc\uac04 \uadf8\ub9ad\uc2a4\n    greeks = elw.get_greeks()\n    print(f\"Delta: {greeks['delta']:.4f}\")\n    print(f\"Gamma: {greeks['gamma']:.4f}\")\n    print(f\"Theta: {greeks['theta']:.4f}\")\n    print(f\"Vega: {greeks['vega']:.4f}\")\n    \n    # \ubbfc\uac10\ub3c4 \uc9c0\ud45c\n    sensitivity = elw.get_sensitivity_indicators()\n    \n    # ELW \uc870\uac74 \uac80\uc0c9 (REST API)\n    elw_search = client.get_elw_condition_search(\n        underlying_asset_code=\"201\",  # KOSPI200\n        right_type=\"1\",  # \ucf5c\uc635\uc158\n        sort_type=\"1\"    # \uc0c1\uc2b9\uc728\uc21c\n    )\n    \n    # \uc2e4\uc2dc\uac04 \uc870\uac74\uac80\uc0c9 (WebSocket)\n    async def on_condition_result(data):\n        print(f\"\uc870\uac74\uac80\uc0c9 \uacb0\uacfc: {data['symbol']} - {data['name']}\")\n    \n    # \uc870\uac74\uac80\uc0c9 \ubaa9\ub85d \uc870\ud68c\n    await client.realtime.get_conditional_search_list()\n    \n    # \uc870\uac74\uac80\uc0c9 \uc2e4\ud589 (\uc77c\ubc18)\n    await client.realtime.execute_conditional_search(\"1\", \"0\")\n    \n    # \uc870\uac74\uac80\uc0c9 \uc2e4\uc2dc\uac04 \ubaa8\ub2c8\ud130\ub9c1\n    await client.realtime.execute_conditional_search_realtime(\"1\")\n    \n    # \uc2e4\uc2dc\uac04 \uc870\uac74\uac80\uc0c9 \ud574\uc81c\n    await client.realtime.cancel_conditional_search_realtime(\"1\")\n```\n\n#### [`05_rankings_analysis.py`](examples/05_rankings_analysis.py) - \ud83d\udcc8 \uc2dc\uc7a5 \uc21c\uc704 \ubd84\uc11d\n```python\n# \uc2dc\uc7a5\uc758 \ubaa8\ub4e0 \uc21c\uc704 \uc815\ubcf4\nwith pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly\n    # \uac70\ub798\ub7c9 \uc21c\uc704\n    volume_leaders = api.rankings.volume_leaders(limit=20)\n    print(\"\ud83d\udd25 \uac70\ub798\ub7c9 TOP 20\")\n    for i, stock in enumerate(volume_leaders, 1):\n        print(f\"{i:2d}. {stock['name']:10s} {stock['volume']:>10,}\uc8fc\")\n    \n    # \uc0c1\uc2b9\ub960 \uc21c\uc704\n    gainers = api.rankings.price_gainers(limit=10)\n    print(\"\\n\ud83d\udcc8 \uc0c1\uc2b9\ub960 TOP 10\")\n    for stock in gainers:\n        print(f\"{stock['name']}: +{stock['change_rate']:.2f}%\")\n    \n    # \uc678\uad6d\uc778 \uc21c\ub9e4\uc218 \uc21c\uc704\n    foreign_net_buy = api.rankings.foreign_net_buying(limit=15)\n    print(\"\\n\ud83c\udf0d \uc678\uad6d\uc778 \uc21c\ub9e4\uc218 TOP 15\")\n    \n    # \uae30\uad00 \uc21c\ub9e4\uc218 \uc21c\uc704  \n    institutional_buy = api.rankings.institutional_net_buying(limit=15)\n    \n    # \ud504\ub85c\uadf8\ub7a8 \ub9e4\ub9e4 \ubd84\uc11d\n    program_trading = api.rankings.program_trading_activity()\n    \n    # \uc139\ud130\ubcc4 \ubd84\uc11d\n    sector_performance = api.rankings.sector_performance()\n    print(\"\\n\ud83c\udfed \uc139\ud130 \uc131\uacfc\")\n    for sector in sector_performance:\n        print(f\"{sector['name']}: {sector['change_rate']:+.2f}%\")\n```\n\n#### [`06_charts_technical.py`](examples/06_charts_technical.py) - \ud83d\udcca \ucc28\ud2b8 & \uae30\uc220\uc801 \ubd84\uc11d\n```python\n# \ubaa8\ub4e0 \ucc28\ud2b8 \ub370\uc774\ud130\uc640 \uae30\uc220\uc801 \ubd84\uc11d\nwith pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly\n    samsung = api.stock(\"005930\")\n    \n    # \ub2e4\uc591\ud55c \uc2dc\uac04\ud504\ub808\uc784 \ucc28\ud2b8\n    daily_chart = samsung.get_chart_data(\"daily\", period=\"6M\")\n    weekly_chart = samsung.get_chart_data(\"weekly\", period=\"2Y\") \n    monthly_chart = samsung.get_chart_data(\"monthly\", period=\"5Y\")\n    \n    # \ubd84\ubd09 \ucc28\ud2b8 (1\ubd84, 5\ubd84, 15\ubd84, 30\ubd84, 60\ubd84)\n    minute_1 = samsung.get_chart_data(\"1min\", period=\"1D\")\n    minute_5 = samsung.get_chart_data(\"5min\", period=\"5D\")\n    minute_30 = samsung.get_chart_data(\"30min\", period=\"1M\")\n    \n    # \uae30\uc220\uc801 \uc9c0\ud45c \uacc4\uc0b0\n    def calculate_sma(data, period=20):\n        \"\"\"\ub2e8\uc21c\uc774\ub3d9\ud3c9\uade0 \uacc4\uc0b0\"\"\"\n        prices = [float(d['close']) for d in data]\n        sma = []\n        for i in range(len(prices)):\n            if i >= period - 1:\n                avg = sum(prices[i-period+1:i+1]) / period\n                sma.append(avg)\n            else:\n                sma.append(None)\n        return sma\n    \n    # 20\uc77c \uc774\ub3d9\ud3c9\uade0\n    sma_20 = calculate_sma(daily_chart, 20)\n    \n    # \uac70\ub798\ub7c9 \ubd84\uc11d\n    volume_analysis = samsung.volume_analysis(period=\"3M\")\n    \n    # \uc5c5\uc885 \ucc28\ud2b8 \ubd84\uc11d\n    sector_chart = api.get_sector_chart(\"\uc804\uae30\uc804\uc790\", period=\"1Y\")\n```\n\n#### [`07_realtime_websocket.py`](examples/07_realtime_websocket.py) - \ud83c\udf10 \uc2e4\uc2dc\uac04 \uc2a4\ud2b8\ub9ac\ubc0d\n```python\n# WebSocket\uc744 \ud1b5\ud55c \uc2e4\uc2dc\uac04 \ub370\uc774\ud130 \uc2a4\ud2b8\ub9ac\ubc0d\nimport asyncio\nfrom pyheroapi import RealtimeClient\n\nasync def main():\n    # \uc2e4\uc2dc\uac04 \ud074\ub77c\uc774\uc5b8\ud2b8 \uc0dd\uc131\n    realtime = RealtimeClient()\n    await realtime.connect()\n    \n    # \uc2e4\uc2dc\uac04 \uc2dc\uc138 \ucf5c\ubc31\n    def on_price_update(data):\n        print(f\"[{data['symbol']}] \u20a9{data['price']:,} ({data['change']:+.2f}%)\")\n    \n    # \uc2e4\uc2dc\uac04 \ud638\uac00 \ucf5c\ubc31  \n    def on_orderbook_update(data):\n        print(f\"\ub9e4\uc218\ud638\uac00: \u20a9{data['best_bid']:,} / \ub9e4\ub3c4\ud638\uac00: \u20a9{data['best_ask']:,}\")\n    \n    # \uc2e4\uc2dc\uac04 \uccb4\uacb0 \ucf5c\ubc31\n    def on_trade_update(data):\n        print(f\"\uccb4\uacb0: {data['quantity']:,}\uc8fc @ \u20a9{data['price']:,}\")\n    \n    # \uc2e4\uc2dc\uac04 \uacc4\uc88c \ucf5c\ubc31\n    def on_account_update(data):\n        print(f\"\uacc4\uc88c\ubcc0\ud654: \uc794\uace0 \u20a9{data['balance']:,}\")\n    \n    # \uc2e4\uc2dc\uac04 \uc870\uac74\uac80\uc0c9 \ucf5c\ubc31\n    def on_conditional_search_result(data):\n        print(f\"\ud83c\udfaf \uc870\uac74\uac80\uc0c9 \ud3b8\uc785: {data['symbol']} - \uc2dc\uac04: {data['time']}\")\n    \n    def on_conditional_search_list(data):\n        print(f\"\ud83d\udccb \uc870\uac74\uac80\uc0c9 \ubaa9\ub85d: {len(data)}\uac1c \uc870\uac74\uc2dd \ud655\uc778\")\n    \n    # \uad6c\ub3c5 \uc124\uc815\n    await realtime.subscribe_price(\"005930\", on_price_update)\n    await realtime.subscribe_orderbook(\"005930\", on_orderbook_update)  \n    await realtime.subscribe_trades(\"005930\", on_trade_update)\n    await realtime.subscribe_account(\"your_account\", on_account_update)\n    \n    # \uc870\uac74\uac80\uc0c9 \ucf5c\ubc31 \ub4f1\ub85d\n    realtime.register_callback('conditional_search_realtime', on_conditional_search_result)\n    realtime.register_callback('conditional_search_list', on_conditional_search_list)\n    \n    # \uc870\uac74\uac80\uc0c9 \ubaa9\ub85d \uc870\ud68c\n    await realtime.get_conditional_search_list()\n    \n    # \uc2e4\uc2dc\uac04 \uc870\uac74\uac80\uc0c9 \uc2dc\uc791 (\uc870\uac74\uc2dd \ubc88\ud638 \"1\")\n    await realtime.execute_conditional_search_realtime(\"1\")\n    \n    # \ub2e4\uc911 \uc885\ubaa9 \uad6c\ub3c5\n    symbols = [\"005930\", \"000660\", \"035420\", \"005380\", \"068270\"]\n    for symbol in symbols:\n        await realtime.subscribe_price(symbol, on_price_update)\n    \n    # \uc2e4\uc2dc\uac04 \ub370\uc774\ud130 \uc218\uc2e0 \ub300\uae30\n    print(\"\ud83d\udd34 \uc2e4\uc2dc\uac04 \ub370\uc774\ud130 \uc218\uc2e0 \uc911... (Ctrl+C\ub85c \uc911\ub2e8)\")\n    try:\n        await realtime.listen()\n    except KeyboardInterrupt:\n        print(\"\\n\u23f9\ufe0f \uc2e4\uc2dc\uac04 \ub370\uc774\ud130 \uc218\uc2e0 \uc911\ub2e8\")\n        await realtime.disconnect()\n\n# \uc2e4\ud589\nif __name__ == \"__main__\":\n    asyncio.run(main())\n```\n\n---\n\n## \ud83d\udd25 \uace0\uae09 \uae30\ub2a5\n\n### \ud83c\udfaf **\uc2a4\ub9c8\ud2b8 \ud3ec\ud2b8\ud3f4\ub9ac\uc624 \uad00\ub9ac**\n\n```python\nwith pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly\n    account = api.account()\n    \n    # \uc804\uccb4 \ud3ec\ud2b8\ud3f4\ub9ac\uc624 \ubd84\uc11d\n    portfolio = account.get_portfolio_analysis()\n    print(f\"\ucd1d \ud3c9\uac00\uae08\uc561: \u20a9{portfolio['total_value']:,.0f}\")\n    print(f\"\uc2e4\ud604\uc190\uc775: \u20a9{portfolio['realized_pnl']:,.0f}\")\n    print(f\"\ud3c9\uac00\uc190\uc775: \u20a9{portfolio['unrealized_pnl']:,.0f}\")\n    print(f\"\ucd1d \uc218\uc775\ub960: {portfolio['total_return']:.2f}%\")\n    \n    # \uc885\ubaa9\ubcc4 \ud3ec\uc9c0\uc158\n    positions = account.positions\n    for pos in positions:\n        print(f\"{pos['name']}: {pos['quantity']:,}\uc8fc\")\n        print(f\"  \ud3c9\uade0\ub2e8\uac00: \u20a9{pos['avg_price']:,}\")\n        print(f\"  \ud604\uc7ac\uac00: \u20a9{pos['current_price']:,}\")\n        print(f\"  \uc218\uc775\ub960: {pos['return_rate']:+.2f}%\")\n        print(f\"  \ud3c9\uac00\uc190\uc775: \u20a9{pos['unrealized_pnl']:+,.0f}\")\n    \n    # \uc77c\ubcc4 \uc190\uc775 \ub0b4\uc5ed\n    daily_pnl = account.get_daily_pnl(days=30)\n    total_trades = sum(day['trade_count'] for day in daily_pnl)\n    total_pnl = sum(day['realized_pnl'] for day in daily_pnl)\n    \n    print(f\"\\n\ud83d\udcca 30\uc77c \uac70\ub798 \ud1b5\uacc4\")\n    print(f\"\ucd1d \uac70\ub798 \ud69f\uc218: {total_trades:,}\ud68c\")\n    print(f\"\uc2e4\ud604\uc190\uc775 \ud569\uacc4: \u20a9{total_pnl:+,.0f}\")\n```\n\n### \ud83d\udcca **\uace0\uae09 \uc2dc\uc7a5 \ubd84\uc11d**\n\n```python\nwith pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly\n    # \uc2dc\uc7a5 \uc804\uccb4 \ud604\ud669\n    market_summary = api.get_market_summary()\n    print(f\"KOSPI: {market_summary['kospi']['value']:.2f} ({market_summary['kospi']['change']:+.2f}%)\")\n    print(f\"KOSDAQ: {market_summary['kosdaq']['value']:.2f} ({market_summary['kosdaq']['change']:+.2f}%)\")\n    \n    # \uc678\uad6d\uc778/\uae30\uad00 \ub9e4\ub9e4 \ub3d9\ud5a5\n    institutional_flow = api.get_institutional_trading()\n    print(f\"\\n\ud83d\udcb0 \uc678\uad6d\uc778 \uc21c\ub9e4\ub9e4: \u20a9{institutional_flow['foreign_net']:+,.0f}\uc5b5\")\n    print(f\"\ud83d\udcb0 \uae30\uad00 \uc21c\ub9e4\ub9e4: \u20a9{institutional_flow['institution_net']:+,.0f}\uc5b5\")\n    \n    # \ud504\ub85c\uadf8\ub7a8 \ub9e4\ub9e4 \ud604\ud669\n    program_trading = api.get_program_trading()\n    print(f\"\ud83d\udcc8 \ud504\ub85c\uadf8\ub7a8 \ub9e4\uc218: \u20a9{program_trading['buy_amount']:,.0f}\uc5b5\")\n    print(f\"\ud83d\udcc9 \ud504\ub85c\uadf8\ub7a8 \ub9e4\ub3c4: \u20a9{program_trading['sell_amount']:,.0f}\uc5b5\")\n    \n    # \uc2e0\uc6a9\uac70\ub798 \ud604\ud669\n    credit_info = api.get_credit_balance()\n    print(f\"\ud83c\udfe6 \uc2e0\uc6a9\uc794\uace0: \u20a9{credit_info['credit_balance']:,.0f}\uc5b5\")\n    print(f\"\ud83c\udfe6 \ub300\uc8fc\uc794\uace0: \u20a9{credit_info['lending_balance']:,.0f}\uc5b5\")\n```\n\n### \u26a1 **\uace0\uc131\ub2a5 \uc77c\uad04 \ucc98\ub9ac**\n\n```python\nimport asyncio\nfrom concurrent.futures import ThreadPoolExecutor\n\nasync def analyze_multiple_stocks(symbols):\n    \"\"\"\uc5ec\ub7ec \uc885\ubaa9 \ub3d9\uc2dc \ubd84\uc11d\"\"\"\n    with pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly\n        with ThreadPoolExecutor(max_workers=10) as executor:\n            # \ub3d9\uc2dc\uc5d0 \uc5ec\ub7ec \uc885\ubaa9 \ub370\uc774\ud130 \uc218\uc9d1\n            futures = []\n            for symbol in symbols:\n                future = executor.submit(api.stock(symbol).get_complete_data)\n                futures.append((symbol, future))\n            \n            results = {}\n            for symbol, future in futures:\n                try:\n                    data = future.result(timeout=30)\n                    results[symbol] = data\n                    print(f\"\u2705 {symbol}: \ub370\uc774\ud130 \uc218\uc9d1 \uc644\ub8cc\")\n                except Exception as e:\n                    print(f\"\u274c {symbol}: \uc624\ub958 - {e}\")\n            \n            return results\n\n# \ub300\ud615\uc8fc TOP 20 \ub3d9\uc2dc \ubd84\uc11d\nlarge_caps = [\"005930\", \"000660\", \"035420\", \"005380\", \"068270\", \n              \"207940\", \"005490\", \"035720\", \"000270\", \"006400\"]\n\nresults = asyncio.run(analyze_multiple_stocks(large_caps))\n```\n\n---\n\n## \ud83d\udee1\ufe0f \uc548\uc804 \uac00\uc774\ub4dc\n\n### \ud83d\udd12 **\ubcf4\uc548 \ubaa8\ubc94 \uc0ac\ub840**\n\n```python\nimport os\nfrom pyheroapi import KiwoomClient\n\n# \u2705 \ud658\uacbd\ubcc0\uc218 \uc0ac\uc6a9 (\uad8c\uc7a5)\nappkey = os.getenv(\"KIWOOM_APPKEY\")\nsecretkey = os.getenv(\"KIWOOM_SECRETKEY\")\n\n# \u274c \ud558\ub4dc\ucf54\ub529 \uae08\uc9c0\n# appkey = \"PAKXXXXXXXX\"  # \uc808\ub300 \uae08\uc9c0!\n\n# \uc548\uc804\ud55c \ud074\ub77c\uc774\uc5b8\ud2b8 \uc0dd\uc131\nclient = KiwoomClient.create_with_credentials(\n    appkey=appkey,\n    secretkey=secretkey,\n    is_production=False,  # SANDBOX MODE: set is_production=False explicitly\n    timeout=30,\n    retry_attempts=3\n)\n```\n\n### \ud83c\udfaf **\uac70\ub798 \uc548\uc804 \uc810\uac80**\n\n```python\ndef safe_trading_example():\n    \"\"\"\uc548\uc804\ud55c \uac70\ub798 \ud504\ub85c\uc138\uc2a4\"\"\"\n    with pyheroapi.connect(is_production=False) as api:  # SANDBOX MODE: set is_production=False explicitly\n        account = api.account()\n        \n        # 1. \uacc4\uc88c \uc0c1\ud0dc \ud655\uc778\n        balance = account.balance\n        available = balance[\"available_balance\"]\n        print(f\"\uc8fc\ubb38\uac00\ub2a5\uae08\uc561: \u20a9{available:,.0f}\")\n        \n        # 2. \uc885\ubaa9 \ubd84\uc11d\n        samsung = api.stock(\"005930\")\n        current_price = samsung.current_price\n        quote = samsung.quote\n        \n        # 3. \uc548\uc804 \uc810\uac80\n        order_amount = current_price * 100  # 100\uc8fc \uc8fc\ubb38\uae08\uc561\n        \n        if available < order_amount:\n            print(\"\u274c \uc8fc\ubb38\uac00\ub2a5\uae08\uc561 \ubd80\uc871\")\n            return\n        \n        if quote[\"volume\"] < 1000:  # \ucd5c\uc18c \uac70\ub798\ub7c9 \uc810\uac80\n            print(\"\u274c \uac70\ub798\ub7c9 \ubd80\uc871 - \uc8fc\ubb38 \ucde8\uc18c\")\n            return\n        \n        # 4. \uc8fc\ubb38 \uc2e4\ud589 (\uc0cc\ub4dc\ubc15\uc2a4\uc5d0\uc11c\ub9cc!)\n        result = api.trading.buy(\"005930\", quantity=100, price=current_price)\n        \n        if result[\"success\"]:\n            print(f\"\u2705 \uc8fc\ubb38 \uc131\uacf5: {result['order_number']}\")\n            \n            # 5. \uc8fc\ubb38 \uc0c1\ud0dc \ubaa8\ub2c8\ud130\ub9c1\n            order_status = api.trading.get_order_status(result[\"order_number\"])\n            print(f\"\uc8fc\ubb38 \uc0c1\ud0dc: {order_status['status']}\")\n        else:\n            print(f\"\u274c \uc8fc\ubb38 \uc2e4\ud328: {result['message']}\")\n\n# \uc2e4\ud589\nsafe_trading_example()\n```\n\n---\n\n## \ud83c\udf93 \ub2e8\uacc4\ubcc4 \ud559\uc2b5 \uac00\uc774\ub4dc\n\n### **1\ub2e8\uacc4: \uae30\ucd08 (1-2\uc77c)**\n- [`01_authentication.py`](examples/01_authentication.py) - \uc778\uc99d\uacfc \ud1a0\ud070 \uad00\ub9ac\n- [`02_market_data.py`](examples/02_market_data.py) - \uae30\ubcf8 \uc2dc\uc138 \uc870\ud68c\n\n### **2\ub2e8\uacc4: \uac70\ub798 (3-5\uc77c)**  \n- [`03_trading_orders.py`](examples/03_trading_orders.py) - \uc8fc\ubb38 \uc2e4\ud589\uacfc \uad00\ub9ac\n- \uc0cc\ub4dc\ubc15\uc2a4\uc5d0\uc11c \ucda9\ubd84\ud55c \uc5f0\uc2b5\n\n### **3\ub2e8\uacc4: \ubd84\uc11d (1\uc8fc)**\n- [`04_etf_elw.py`](examples/04_etf_elw.py) - ETF/ELW \uc804\ubb38 \ubd84\uc11d\n- [`05_rankings_analysis.py`](examples/05_rankings_analysis.py) - \uc2dc\uc7a5 \uc21c\uc704 \ubd84\uc11d\n- [`06_charts_technical.py`](examples/06_charts_technical.py) - \ucc28\ud2b8\uc640 \uae30\uc220\uc801 \ubd84\uc11d\n\n### **4\ub2e8\uacc4: \uace0\uae09 (2\uc8fc)**\n- [`07_realtime_websocket.py`](examples/07_realtime_websocket.py) - \uc2e4\uc2dc\uac04 \uc2a4\ud2b8\ub9ac\ubc0d\n- \ud3ec\ud2b8\ud3f4\ub9ac\uc624 \uad00\ub9ac \uc2dc\uc2a4\ud15c \uad6c\ucd95\n- \uc790\ub3d9 \ub9e4\ub9e4 \uc2dc\uc2a4\ud15c \uac1c\ubc1c\n\n---\n\n## \ud83d\udd27 \ud658\uacbd \uc124\uc815\n\n### **API \ud0a4 \ubc1c\uae09**\n1. [\ud0a4\uc6c0 OpenAPI \ud648\ud398\uc774\uc9c0\uc9c0](https://openapi.kiwoom.com/) \ubc29\ubb38\n2. \uacc4\uc815 \uc0dd\uc131 \ubc0f \ub85c\uadf8\uc778\n3. REST API \uc11c\ube44\uc2a4 \uc2e0\uccad\n4. APP KEY\uc640 SECRET KEY \ubc1c\uae09\n\n### **\uac1c\ubc1c \ud658\uacbd \uc124\uc815**\n\n```bash\n# 1. \ud504\ub85c\uc81d\ud2b8 \ud3f4\ub354 \uc0dd\uc131\nmkdir my_trading_bot\ncd my_trading_bot\n\n# 2. \uac00\uc0c1\ud658\uacbd \uc0dd\uc131\npython -m venv venv\nsource venv/bin/activate  # Windows: venv\\Scripts\\activate\n\n# 3. PyHeroAPI \uc124\uce58\npip install pyheroapi[all]\n\n# 4. \ud658\uacbd\ubcc0\uc218 \uc124\uc815\necho 'export KIWOOM_APPKEY=\"\ud0a4\uc6c0 REST API APPKEY' >> ~/.bashrc\necho 'export KIWOOM_SECRETKEY=\"\ud0a4\uc6c0 REST API SECRETKEY\"' >> ~/.bashrc\nsource ~/.bashrc\n\n# 5. \uccab \ubc88\uc9f8 \ud14c\uc2a4\ud2b8\npython -c \"\nimport pyheroapi\nwith pyheroapi.connect(is_production=False) as api:\n    print('\u2705 \uc5f0\uacb0 \uc131\uacf5!')\n    print(f'\uc0bc\uc131\uc804\uc790: \u20a9{api.stock(\\\"005930\\\").current_price:,.0f}')\n\"\n```\n\n---\n\n## \ud83d\udccb \uc2dc\uc2a4\ud15c \uc694\uad6c\uc0ac\ud56d\n\n- **Python**: 3.8 \uc774\uc0c1\n- **\uc6b4\uc601\uccb4\uc81c**: Windows, macOS, Linux\n- **\uba54\ubaa8\ub9ac**: \ucd5c\uc18c 512MB (\uc2e4\uc2dc\uac04 \uc2a4\ud2b8\ub9ac\ubc0d \uc2dc 1GB \uad8c\uc7a5)\n- **\ub124\ud2b8\uc6cc\ud06c**: \uc548\uc815\uc801\uc778 \uc778\ud130\ub137 \uc5f0\uacb0\n\n### **\uc758\uc874\uc131 \ud328\ud0a4\uc9c0**\n```\nrequests>=2.25.0        # HTTP \ud074\ub77c\uc774\uc5b8\ud2b8\npydantic>=2.0.0         # \ub370\uc774\ud130 \uac80\uc99d\ntyping-extensions>=4.0.0 # \ud0c0\uc785 \ud78c\ud2b8\nwebsockets>=11.0.0      # \uc2e4\uc2dc\uac04 \uc2a4\ud2b8\ub9ac\ubc0d (\uc120\ud0dd\uc0ac\ud56d)\n```\n\n---\n\n## \u26a0\ufe0f \uc911\uc694 \uacf5\uc9c0\uc0ac\ud56d\n\n### **\uba74\ucc45\uc870\ud56d**\n- \ud83d\udcd6 **\uad50\uc721 \ubaa9\uc801**: \uc774 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub294 \uad50\uc721 \ubc0f \uac1c\ubc1c \ubaa9\uc801\uc73c\ub85c \uc81c\uacf5\ub429\ub2c8\ub2e4\n- \ud83d\udcb0 **\ud22c\uc790 \ucc45\uc784**: \uc2e4\uc81c \uac70\ub798\ub85c \uc778\ud55c \uc190\uc2e4\uc5d0 \ub300\ud574 \ucc45\uc784\uc9c0\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4\n- \ud83e\uddea **\ucda9\ubd84\ud55c \ud14c\uc2a4\ud2b8**: \uc2e4\uac70\ub798 \uc804 \ubc18\ub4dc\uc2dc \uc0cc\ub4dc\ubc15\uc2a4\uc5d0\uc11c \ucda9\ubd84\ud788 \ud14c\uc2a4\ud2b8\ud558\uc138\uc694\n- \ud83d\udcca **\uc2dc\uc7a5 \ub9ac\uc2a4\ud06c**: \uc8fc\uc2dd \ud22c\uc790\uc5d0\ub294 \uc6d0\uae08 \uc190\uc2e4 \uc704\ud5d8\uc774 \uc788\uc2b5\ub2c8\ub2e4\n\n### **\uc0ac\uc6a9 \uc81c\ud55c\uc0ac\ud56d**\n- \ud83d\udd50 **API \ud638\ucd9c \uc81c\ud55c**: \ucd08\ub2f9 \uc694\uccad \uc218 \uc81c\ud55c (\uc790\ub3d9 \uad00\ub9ac\ub428)\n- \ud83c\udfdb\ufe0f **\uc7a5 \uc2dc\uac04 \uc81c\ud55c**: \uc77c\ubd80 \uae30\ub2a5\uc740 \uac1c\uc7a5 \uc2dc\uac04\uc5d0\ub9cc \uc791\ub3d9\n- \ud83d\udcf1 **\uc2e4\uc2dc\uac04 \ub370\uc774\ud130**: \uc57d\uac04\uc758 \uc9c0\uc5f0\uc774 \uc788\uc744 \uc218 \uc788\uc74c\n- \ud83d\udd12 **\ubcf4\uc548**: API \ud0a4\ub294 \uc808\ub300 \uacf5\uac1c\ud558\uc9c0 \ub9c8\uc138\uc694\n\n---\n\n## \ud83e\udd1d \ucee4\ubba4\ub2c8\ud2f0\n\n### **\uae30\uc5ec\ud558\uae30**\n1. \ud83c\udf74 [\uc800\uc7a5\uc18c \ud3ec\ud06c](https://github.com/gejyn14/pyheroapi/fork)\n2. \ud83c\udf3f \uae30\ub2a5 \ube0c\ub79c\uce58 \uc0dd\uc131: `git checkout -b feature/amazing-feature`\n3. \ud83d\udcdd \ubcc0\uacbd\uc0ac\ud56d \ucee4\ubc0b: `git commit -m 'Add amazing feature'`\n4. \ud83d\udce4 \ube0c\ub79c\uce58 \ud478\uc2dc: `git push origin feature/amazing-feature`\n5. \ud83d\udd04 Pull Request \uc0dd\uc131\n\n### **\uc9c0\uc6d0 \ucc44\ub110**\n- \ud83d\udcd6 **\ubb38\uc11c**: [GitHub Wiki](https://github.com/gejyn14/pyheroapi/wiki)\n- \ud83d\udc1b **\ubc84\uadf8 \ub9ac\ud3ec\ud2b8**: [Issues](https://github.com/gejyn14/pyheroapi/issues)\n- \ud83d\udca1 **\uae30\ub2a5 \uc694\uccad**: [Discussions](https://github.com/gejyn14/pyheroapi/discussions)\n- \ud83d\udce7 **\uc774\uba54\uc77c**: dean_jin@icloud.com\n\n### **\ub77c\uc774\uc120\uc2a4**\nMIT License - \uc790\uc138\ud55c \ub0b4\uc6a9\uc740 [LICENSE](LICENSE) \ud30c\uc77c \ucc38\uc870\n\n---\n\n<div align=\"center\">\n\n### \u2b50 \uc774 \ud504\ub85c\uc81d\ud2b8\uac00 \ub3c4\uc6c0\uc774 \ub418\uc168\ub2e4\uba74 \ubcc4\ud45c\ub97c \ub20c\ub7ec\uc8fc\uc138\uc694!\n\n[![GitHub stars](https://img.shields.io/github/stars/gejyn14/pyheroapi.svg?style=social&label=Star)](https://github.com/gejyn14/pyheroapi)\n[![GitHub forks](https://img.shields.io/github/forks/gejyn14/pyheroapi.svg?style=social&label=Fork)](https://github.com/gejyn14/pyheroapi/fork)\n\n**Happy Trading! \ud83d\udcc8\ud83d\ude80**\n\n**\u26a0\ufe0f \uba74\ucc45\uc870\ud56d**: \uc774 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub294 \uad50\uc721 \ubc0f \uac1c\ubc1c \ubaa9\uc801\uc73c\ub85c \uc81c\uacf5\ub429\ub2c8\ub2e4. \uc2e4\uc81c \uac70\ub798\uc5d0\uc11c \ubc1c\uc0dd\ud558\ub294 \uc190\uc2e4\uc5d0 \ub300\ud574\uc11c\ub294 \ucc45\uc784\uc9c0\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \uac70\ub798 \uc2dc \uc8fc\uc758\ud558\uc2dc\uae30 \ubc14\ub78d\ub2c8\ub2e4.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Easy-to-use Python client for Kiwoom Securities REST API with intuitive interface",
    "version": "0.4.3",
    "project_urls": {
        "Documentation": "https://github.com/gejyn14/pyheroapi#readme",
        "Homepage": "https://github.com/gejyn14/pyheroapi",
        "Issues": "https://github.com/gejyn14/pyheroapi/issues",
        "Repository": "https://github.com/gejyn14/pyheroapi.git"
    },
    "split_keywords": [
        "api",
        " kiwoom",
        " korea",
        " securities",
        " stock",
        " trading"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "1abf08dabad731df38b222b0637e8b5eda7fce2648d1aa65f8fe0b90aa1e5f27",
                "md5": "72a0b6f89dc0266cc844b41522a95437",
                "sha256": "4756d5de8ab02b91f73825721b46e84123e95e5be0fca4bc787e58f8667ea261"
            },
            "downloads": -1,
            "filename": "pyheroapi-0.4.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "72a0b6f89dc0266cc844b41522a95437",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 47807,
            "upload_time": "2025-08-25T05:04:28",
            "upload_time_iso_8601": "2025-08-25T05:04:28.604968Z",
            "url": "https://files.pythonhosted.org/packages/1a/bf/08dabad731df38b222b0637e8b5eda7fce2648d1aa65f8fe0b90aa1e5f27/pyheroapi-0.4.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e143721c73e54753e2390876365a98bff0ff75c8a10a7c6b2dcc6b20262838c8",
                "md5": "fbd7ddc40b57349bc667035cab4c7c43",
                "sha256": "de8da6bfad30f5b84dbbb07682237dbcdade6ea2eabad50325273085b5cdbc81"
            },
            "downloads": -1,
            "filename": "pyheroapi-0.4.3.tar.gz",
            "has_sig": false,
            "md5_digest": "fbd7ddc40b57349bc667035cab4c7c43",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 216398,
            "upload_time": "2025-08-25T05:04:30",
            "upload_time_iso_8601": "2025-08-25T05:04:30.490221Z",
            "url": "https://files.pythonhosted.org/packages/e1/43/721c73e54753e2390876365a98bff0ff75c8a10a7c6b2dcc6b20262838c8/pyheroapi-0.4.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-25 05:04:30",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "gejyn14",
    "github_project": "pyheroapi#readme",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "pyheroapi"
}
        
Elapsed time: 1.47899s