Skip to main content

python wrapper for korea broker's REST API services

Project description

๐Ÿš€ Korea Investment Stock

PyPI version Python Versions License: MIT

ํ•œ๊ตญํˆฌ์ž์ฆ๊ถŒ OpenAPI๋ฅผ ์œ„ํ•œ ํŒŒ์ด์ฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. Rate Limiting, ์ž๋™ ์žฌ์‹œ๋„, ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ ๋“ฑ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์— ํ•„์š”ํ•œ ๊ธฐ๋Šฅ๋“ค์„ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๐ŸŒŸ ์ฃผ์š” ํŠน์ง•

โœจ ํ•ต์‹ฌ ๊ธฐ๋Šฅ

  • ํ•œ๊ตญํˆฌ์ž์ฆ๊ถŒ API ์‹œ์„ธ ์กฐํšŒ: ๊ตญ๋‚ด/ํ•ด์™ธ ์ฃผ์‹ ์‹œ์„ธ ๋ฐ ์ข…๋ชฉ ์ •๋ณด ์กฐํšŒ
  • ๊ณต๋ชจ์ฃผ ์ฒญ์•ฝ ์ผ์ • ์กฐํšŒ: ๊ณต๋ชจ์ฃผ ์ •๋ณด, ์ฒญ์•ฝ ์ผ์ •, ์ƒํƒœ ํ™•์ธ
  • ์ž๋™ Rate Limiting: API ํ˜ธ์ถœ ์ œํ•œ(์ดˆ๋‹น 20ํšŒ)์„ ์ž๋™์œผ๋กœ ๊ด€๋ฆฌ
  • ์Šค๋งˆํŠธ ์žฌ์‹œ๋„: Exponential Backoff์™€ Circuit Breaker ํŒจํ„ด ๊ตฌํ˜„
  • ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ: ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ์กฐํšŒ๋ฅผ ์œ„ํ•œ ์ตœ์ ํ™”๋œ ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ
  • ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง: ์ƒ์„ธํ•œ ํ†ต๊ณ„ ๋ฐ ์„ฑ๋Šฅ ์ถ”์ 
  • TTL ์บ์‹ฑ: ์ž๋™ ๋งŒ๋ฃŒ๋˜๋Š” ์บ์‹œ๋กœ API ํ˜ธ์ถœ ์ตœ์†Œํ™”

๐Ÿ›ก๏ธ ์•ˆ์ •์„ฑ

  • ์—๋Ÿฌ์œจ 0%: ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ ๊ฒ€์ฆ๋œ ์•ˆ์ •์„ฑ
  • ์ž๋™ ์—๋Ÿฌ ๋ณต๊ตฌ: ์ผ์‹œ์  ์˜ค๋ฅ˜ ์ž๋™ ์ฒ˜๋ฆฌ
  • Thread-Safe: ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ ์ง€์›

๐Ÿ“ฆ ์„ค์น˜

pip install korea-investment-stock

์š”๊ตฌ์‚ฌํ•ญ

  • Python 3.9 ์ด์ƒ
  • ํ•œ๊ตญํˆฌ์ž์ฆ๊ถŒ API ๊ณ„์ •

๐Ÿš€ ๋น ๋ฅธ ์‹œ์ž‘

๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

from korea_investment_stock import KoreaInvestment

# API ์ธ์ฆ ์ •๋ณด
api_key = "YOUR_API_KEY"
api_secret = "YOUR_API_SECRET"
account_no = "12345678-01"

# ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ
broker = KoreaInvestment(
    api_key=api_key,
    api_secret=api_secret,
    acc_no=account_no,
    mock=False  # ์‹ค๊ฑฐ๋ž˜: False, ๋ชจ์˜ํˆฌ์ž: True
)

# ํ˜„์žฌ๊ฐ€ ์กฐํšŒ
price_info = broker.fetch_price("005930")  # ์‚ผ์„ฑ์ „์ž
print(f"ํ˜„์žฌ๊ฐ€: {price_info['output']['stck_prpr']}์›")

# ์ข…๋ชฉ ์ •๋ณด ์กฐํšŒ
stock_info = broker.fetch_stock_info_list([("005930", "KR")])
print(stock_info)

Context Manager ์‚ฌ์šฉ (๊ถŒ์žฅ)

from korea_investment_stock import KoreaInvestment

with KoreaInvestment(api_key, api_secret, account_no) as broker:
    # ์ž๋™์œผ๋กœ ๋ฆฌ์†Œ์Šค ์ •๋ฆฌ
    price = broker.fetch_price("005930")
    # ... ์ž‘์—… ์ˆ˜ํ–‰
# ์ž๋™์œผ๋กœ broker.shutdown() ํ˜ธ์ถœ๋จ

๐Ÿ“Š ์ฃผ์š” ๊ธฐ๋Šฅ

1. ์ฃผ์‹ ์ •๋ณด ์กฐํšŒ

# ๊ตญ๋‚ด ์ฃผ์‹ ํ˜„์žฌ๊ฐ€
price = broker.fetch_domestic_price("J", "005930")

# ETF ํ˜„์žฌ๊ฐ€
etf_price = broker.fetch_etf_domestic_price("J", "069500")  # KODEX 200

# ์ข…๋ชฉ ์ •๋ณด ์กฐํšŒ
stock_info = broker.fetch_stock_info_list([("005930", "KR")])

# ์—ฌ๋Ÿฌ ์ข…๋ชฉ ๋™์‹œ ์กฐํšŒ
stock_list = [("005930", "KR"), ("000660", "KR"), ("035720", "KR")]
prices = broker.fetch_price_list(stock_list)

# ์ฝ”์Šคํ”ผ/์ฝ”์Šค๋‹ฅ ์ „์ฒด ์ข…๋ชฉ ์กฐํšŒ
kospi_symbols = broker.fetch_kospi_symbols()
kosdaq_symbols = broker.fetch_kosdaq_symbols()

2. ๊ณต๋ชจ์ฃผ ์ฒญ์•ฝ ์ผ์ • ์กฐํšŒ

# ์ „์ฒด ๊ณต๋ชจ์ฃผ ์ผ์ • ์กฐํšŒ (์˜ค๋Š˜๋ถ€ํ„ฐ 30์ผ)
ipo_schedule = broker.fetch_ipo_schedule()
if ipo_schedule['rt_cd'] == '0':
    for ipo in ipo_schedule['output1']:
        print(f"{ipo['isin_name']} - ์ฒญ์•ฝ๊ธฐ๊ฐ„: {ipo['subscr_dt']}")
        print(f"๊ณต๋ชจ๊ฐ€: {broker.format_number(ipo['fix_subscr_pri'])}์›")
        print(f"์ฃผ๊ฐ„์‚ฌ: {ipo['lead_mgr']}")

# ํŠน์ • ๊ธฐ๊ฐ„ ๊ณต๋ชจ์ฃผ ์กฐํšŒ
ipos = broker.fetch_ipo_schedule(
    from_date="20240101",
    to_date="20240131"
)

# ํŠน์ • ์ข…๋ชฉ ๊ณต๋ชจ์ฃผ ์ •๋ณด ์กฐํšŒ
ipo_info = broker.fetch_ipo_schedule(symbol="123456")

# ๊ณต๋ชจ์ฃผ ์ƒํƒœ ํ™•์ธ (์˜ˆ์ •/์ง„ํ–‰์ค‘/๋งˆ๊ฐ)
for ipo in ipo_schedule['output1']:
    status = broker.get_ipo_status(ipo['subscr_dt'])
    d_day = broker.calculate_ipo_d_day(ipo['subscr_dt'])
    print(f"{ipo['isin_name']}: {status}, D-{d_day}")

# ์ฃผ์˜: ๋ชจ์˜ํˆฌ์ž๋Š” ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค
# ์˜ˆํƒ์› ์ œ๊ณต ์ •๋ณด์ด๋ฏ€๋กœ ์ฐธ๊ณ ์šฉ์œผ๋กœ๋งŒ ์‚ฌ์šฉํ•˜์„ธ์š”

3. ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ (๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ)

# 100๊ฐœ ์ข…๋ชฉ ์กฐํšŒ
large_stock_list = [(f"{i:06d}", "KR") for i in range(1, 101)]

# ๊ณ ์ • ํฌ๊ธฐ ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ
results = broker.fetch_price_list_with_batch(
    large_stock_list,
    batch_size=20,       # 20๊ฐœ์”ฉ ์ฒ˜๋ฆฌ
    batch_delay=1.0,     # ๋ฐฐ์น˜ ๊ฐ„ 1์ดˆ ๋Œ€๊ธฐ
    progress_interval=10 # ์ง„ํ–‰์ƒํ™ฉ ์ถœ๋ ฅ
)

# ๋™์  ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ (์—๋Ÿฌ์œจ์— ๋”ฐ๋ผ ์ž๋™ ์กฐ์ •)
results = broker.fetch_price_list_with_dynamic_batch(large_stock_list)

4. Rate Limiting ๊ด€๋ฆฌ

# Rate Limiter ํ†ต๊ณ„ ํ™•์ธ
broker.rate_limiter.print_stats()

# ํ†ต๊ณ„ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ
stats = broker.rate_limiter.get_stats()
print(f"์ด ํ˜ธ์ถœ: {stats['total_calls']}")
print(f"์—๋Ÿฌ์œจ: {stats['error_rate']:.1%}")
print(f"ํ‰๊ท  ๋Œ€๊ธฐ์‹œ๊ฐ„: {stats['avg_wait_time']:.3f}์ดˆ")

# ํ†ต๊ณ„ ์ €์žฅ
broker.rate_limiter.save_stats()

5. ์บ์‹œ ๊ด€๋ฆฌ

# ์บ์‹œ ์ƒํƒœ ํ™•์ธ
cache_stats = broker.get_cache_stats()
print(f"์บ์‹œ ์ ์ค‘๋ฅ : {cache_stats['hit_rate']:.1%}")
print(f"๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰: {cache_stats['memory_usage']:.1f}MB")

# ์บ์‹œ ๋น„์šฐ๊ธฐ
broker.clear_cache()  # ์ „์ฒด ์บ์‹œ ์‚ญ์ œ
broker.clear_cache("fetch_domestic_price:J:005930")  # ํŠน์ • ํ•ญ๋ชฉ๋งŒ ์‚ญ์ œ

# ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ์ข…๋ชฉ ๋ฏธ๋ฆฌ ์บ์‹ฑ
popular_stocks = ["005930", "000660", "035720", "051910", "005380"]
broker.preload_cache(popular_stocks, market="KR")

6. ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ

# Circuit Breaker ์ƒํƒœ ํ™•์ธ
from korea_investment_stock.rate_limiting import get_backoff_strategy

backoff = get_backoff_strategy()
state = backoff.get_stats()['state']  # CLOSED, OPEN, HALF_OPEN

# ์—๋Ÿฌ ๋ณต๊ตฌ ์‹œ์Šคํ…œ
from korea_investment_stock.error_handling import get_error_recovery_system

recovery = get_error_recovery_system()
summary = recovery.get_error_summary(hours=1)
print(f"์ตœ๊ทผ 1์‹œ๊ฐ„ ์—๋Ÿฌ: {summary['total_errors']}๊ฑด")

# ํ†ต๊ณ„ ๋งค๋‹ˆ์ €
from korea_investment_stock.monitoring import get_stats_manager

stats_mgr = get_stats_manager()
stats_mgr.save_all_stats()  # ๋ชจ๋“  ํ†ต๊ณ„ ์ €์žฅ

7. ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ ์‹œ๊ฐํ™”

# ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง ๋Œ€์‹œ๋ณด๋“œ ์ƒ์„ฑ
dashboard = broker.create_monitoring_dashboard()
broker.save_monitoring_dashboard("monitoring.html")

# ์‹œ์Šคํ…œ ํ—ฌ์Šค ์ฒดํฌ
health_chart = broker.get_system_health_chart()

# API ์‚ฌ์šฉ๋Ÿ‰ ์ฐจํŠธ
usage_chart = broker.get_api_usage_chart(hours=24)

# ํ†ต๊ณ„ ๋ฆฌํฌํŠธ ์ƒ์„ฑ
report_files = broker.create_stats_report("weekly_report")

๐Ÿšง ๊ฐœ๋ฐœ ์ค‘์ธ ๊ธฐ๋Šฅ

๋‹ค์Œ ๊ธฐ๋Šฅ๋“ค์€ ํ–ฅํ›„ ๋ฒ„์ „์—์„œ ์ถ”๊ฐ€๋  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค:

  • ์ฃผ๋ฌธ ๊ธฐ๋Šฅ: ์‹œ์žฅ๊ฐ€/์ง€์ •๊ฐ€ ์ฃผ๋ฌธ, ์ฃผ๋ฌธ ์ทจ์†Œ
  • ์ž”๊ณ  ์กฐํšŒ: ๋ณด์œ  ์ข…๋ชฉ ๋ฐ ์˜ˆ์ˆ˜๊ธˆ ์กฐํšŒ
  • ์ฐจํŠธ ๋ฐ์ดํ„ฐ: ์ผ๋ด‰, ๋ถ„๋ด‰ ๋“ฑ OHLCV ๋ฐ์ดํ„ฐ
  • ํ•ด์™ธ ์ฃผ์‹: ๋ฏธ๊ตญ ์ฃผ์‹ ์‹œ์„ธ ์กฐํšŒ ๊ธฐ๋Šฅ ํ™•๋Œ€

๐Ÿ“ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

korea_investment_stock/
โ”œโ”€โ”€ __init__.py
โ”œโ”€โ”€ korea_investment_stock.py      # ๋ฉ”์ธ ํด๋ž˜์Šค
โ”œโ”€โ”€ rate_limiting/                 # Rate Limiting ๋ชจ๋“ˆ
โ”‚   โ”œโ”€โ”€ enhanced_rate_limiter.py
โ”‚   โ”œโ”€โ”€ enhanced_backoff_strategy.py
โ”‚   โ””โ”€โ”€ enhanced_retry_decorator.py
โ”œโ”€โ”€ error_handling/                # ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ชจ๋“ˆ
โ”‚   โ””โ”€โ”€ error_recovery_system.py
โ”œโ”€โ”€ batch_processing/              # ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ ๋ชจ๋“ˆ
โ”‚   โ””โ”€โ”€ dynamic_batch_controller.py
โ”œโ”€โ”€ caching/                       # ์บ์‹ฑ ๋ชจ๋“ˆ
โ”‚   โ”œโ”€โ”€ ttl_cache.py
โ”‚   โ””โ”€โ”€ market_hours.py
โ”œโ”€โ”€ monitoring/                    # ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ ํ†ต๊ณ„
โ”‚   โ””โ”€โ”€ stats_manager.py
โ”œโ”€โ”€ visualization/                 # ์‹œ๊ฐํ™” ๋ชจ๋“ˆ
โ”‚   โ”œโ”€โ”€ charts.py
โ”‚   โ”œโ”€โ”€ dashboard.py
โ”‚   โ””โ”€โ”€ plotly_visualizer.py
โ””โ”€โ”€ utils/                        # ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜

๐Ÿ”ง ํ™˜๊ฒฝ ์„ค์ •

ํ™˜๊ฒฝ ๋ณ€์ˆ˜

# Rate Limiting ์„ค์ •
export RATE_LIMIT_MAX_CALLS=15        # ์ตœ๋Œ€ ํ˜ธ์ถœ ์ˆ˜ (๊ธฐ๋ณธ: 15)
export RATE_LIMIT_SAFETY_MARGIN=0.8   # ์•ˆ์ „ ๋งˆ์ง„ (๊ธฐ๋ณธ: 0.8)

# Backoff ์ „๋žต ์„ค์ •
export BACKOFF_BASE_DELAY=1.0         # ๊ธฐ๋ณธ ๋Œ€๊ธฐ ์‹œ๊ฐ„
export BACKOFF_MAX_DELAY=60.0         # ์ตœ๋Œ€ ๋Œ€๊ธฐ ์‹œ๊ฐ„
export CIRCUIT_FAILURE_THRESHOLD=5    # Circuit Breaker ์ž„๊ณ„๊ฐ’

# ์บ์‹œ ์„ค์ •
export CACHE_DEFAULT_TTL=300          # ๊ธฐ๋ณธ ์บ์‹œ TTL (์ดˆ)
export CACHE_MAX_SIZE=10000          # ์ตœ๋Œ€ ์บ์‹œ ํฌ๊ธฐ

๐Ÿ“ˆ ์„ฑ๋Šฅ ์ง€ํ‘œ

  • ์ฒ˜๋ฆฌ๋Ÿ‰: 10-12 TPS (์•ˆ์ •์ )
  • ์—๋Ÿฌ์œจ: < 0.1%
  • 100์ข…๋ชฉ ์กฐํšŒ: ~8.5์ดˆ
  • ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ: < 100MB
  • CPU ์‚ฌ์šฉ๋ฅ : < 5%
  • ์บ์‹œ ์ ์ค‘๋ฅ : > 80% (์ผ๋ฐ˜์ ์ธ ์‚ฌ์šฉ ํŒจํ„ด)

๐Ÿค ๊ธฐ์—ฌํ•˜๊ธฐ

ํ”„๋กœ์ ํŠธ์— ๊ธฐ์—ฌ๋ฅผ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์„ค์ •

# ์ €์žฅ์†Œ ํด๋ก 
git clone https://github.com/softyoungha/korea-investment-stock.git
cd korea-investment-stock

# ๊ฐ€์ƒํ™˜๊ฒฝ ์ƒ์„ฑ ๋ฐ ํ™œ์„ฑํ™”
python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate

# ๊ฐœ๋ฐœ ์˜์กด์„ฑ ์„ค์น˜
pip install -e ".[dev]"

# ํ…Œ์ŠคํŠธ ์‹คํ–‰
pytest

๐Ÿ“š ๋ฌธ์„œ

โš ๏ธ ์ฃผ์˜์‚ฌํ•ญ

  • ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ํ•œ๊ตญํˆฌ์ž์ฆ๊ถŒ OpenAPI์˜ ๊ณต์‹ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค
  • ์‹ค๊ฑฐ๋ž˜ ์‚ฌ์šฉ ์‹œ ์ถฉ๋ถ„ํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ๊ฑฐ์ณ ์‚ฌ์šฉํ•˜์„ธ์š”
  • API ํ˜ธ์ถœ ์ œํ•œ์„ ์ค€์ˆ˜ํ•˜์—ฌ ์‚ฌ์šฉํ•˜์„ธ์š”
  • ํ˜„์žฌ๋Š” ์‹œ์„ธ ์กฐํšŒ ๊ธฐ๋Šฅ๋งŒ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค

๐Ÿ“„ ๋ผ์ด์„ ์Šค

์ด ํ”„๋กœ์ ํŠธ๋Š” MIT ๋ผ์ด์„ ์Šค ํ•˜์— ๋ฐฐํฌ๋ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ LICENSE ํŒŒ์ผ์„ ์ฐธ์กฐํ•˜์„ธ์š”.

๐Ÿ™ ๊ฐ์‚ฌ์˜ ๊ธ€

  • ํ•œ๊ตญํˆฌ์ž์ฆ๊ถŒ OpenAPI ํŒ€
  • ๋ชจ๋“  ๊ธฐ์—ฌ์ž๋“ค
  • ์ด์Šˆ ๋ฆฌํฌํŠธ์™€ ํ”ผ๋“œ๋ฐฑ์„ ์ฃผ์‹  ์‚ฌ์šฉ์ž๋ถ„๋“ค

๐Ÿ“ž ์ง€์›


Made with โค๏ธ by the Korea Investment Stock community

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

korea_investment_stock-0.4.1.tar.gz (98.6 kB view details)

Uploaded Source

Built Distribution

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

korea_investment_stock-0.4.1-py3-none-any.whl (120.2 kB view details)

Uploaded Python 3

File details

Details for the file korea_investment_stock-0.4.1.tar.gz.

File metadata

  • Download URL: korea_investment_stock-0.4.1.tar.gz
  • Upload date:
  • Size: 98.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.6

File hashes

Hashes for korea_investment_stock-0.4.1.tar.gz
Algorithm Hash digest
SHA256 9bd18fde401363ba281c28d1fce395b77dcc154b5e4cc459f6627b1bdaa895f4
MD5 e07d1c83e43013d3db19a4315def9496
BLAKE2b-256 4e410af2fec3e94d6f3932b553fb294afb88119955ef670aeb88c77600c68a4a

See more details on using hashes here.

File details

Details for the file korea_investment_stock-0.4.1-py3-none-any.whl.

File metadata

File hashes

Hashes for korea_investment_stock-0.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9dfa6359a14193aa73899e1f86e7042f03ad27241c154edb857851aeb5a8675b
MD5 be4b5796fa3d0c5b0777f94297ff24fd
BLAKE2b-256 5c18ea9430bcf65dfcc16771be1c10f7cff0eff38d86d972c401431c4e672325

See more details on using hashes here.

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