Skip to main content

Pure Python wrapper for Korea Investment Securities OpenAPI

Project description

๐Ÿš€ Korea Investment Stock

PyPI version Python Versions License: MIT

Pure Python wrapper for Korea Investment Securities OpenAPI

๐ŸŽฏ Purpose

A simple, transparent wrapper around the Korea Investment Securities OpenAPI. This library handles API authentication and request formatting, giving you direct access to the API responses without abstraction layers.

Philosophy: Keep It Simple

  • Pure wrapper: Direct API access without magic
  • Minimal dependencies: Only requests and pandas
  • No abstraction: You get exactly what the API returns
  • Implement your way: Add rate limiting, caching, retries as you need them

๐ŸŒŸ Features

Core API Support

  • โœ… Stock Price Queries: Domestic (KR) and US stocks
  • โœ… Stock Information: Company details and market data
  • โœ… IPO Schedule: Public offering information and schedules
  • โœ… Unified Interface: Query KR/US stocks with fetch_price(symbol, market)
  • โœ… Search Functions: Stock search and lookup

Technical Features

  • ๐Ÿ”ง Context Manager: Automatic resource cleanup
  • ๐Ÿ”ง Thread Pool: Basic concurrent execution support
  • ๐Ÿ”ง Environment Variables: API credentials via env vars

๐Ÿ“ฆ Installation

pip install korea-investment-stock

Requirements

  • Python 3.11 or higher
  • Korea Investment Securities API account

๐Ÿš€ Quick Start

1. Set Up Credentials

# Add to your ~/.zshrc or ~/.bashrc
export KOREA_INVESTMENT_API_KEY="your-api-key"
export KOREA_INVESTMENT_API_SECRET="your-api-secret"
export KOREA_INVESTMENT_ACCOUNT_NO="12345678-01"

2. Basic Usage

from korea_investment_stock import KoreaInvestment
import os

# Create client (using environment variables)
with KoreaInvestment(
    api_key=os.getenv('KOREA_INVESTMENT_API_KEY'),
    api_secret=os.getenv('KOREA_INVESTMENT_API_SECRET'),
    acc_no=os.getenv('KOREA_INVESTMENT_ACCOUNT_NO')
) as broker:
    # Query Samsung Electronics
    result = broker.fetch_price("005930", "KR")

    if result['rt_cd'] == '0':
        price = result['output1']['stck_prpr']
        print(f"Price: {price}์›")

๐Ÿ“– API Methods

Stock Price Queries

# Domestic stock price
result = broker.fetch_price("005930", "KR")  # Samsung Electronics

# US stock price (requires real account)
result = broker.fetch_price("AAPL", "US")   # Apple

# Direct methods
result = broker.fetch_domestic_price("J", "005930")
result = broker.fetch_etf_domestic_price("J", "069500")  # KODEX 200
result = broker.fetch_price_detail_oversea("AAPL", "US")

Stock Information

# Stock info
result = broker.fetch_stock_info("005930", "KR")

# Search stock
result = broker.fetch_search_stock_info("005930", "KR")

IPO Schedule

# All IPOs (today + 30 days)
result = broker.fetch_ipo_schedule()

# Specific period
result = broker.fetch_ipo_schedule(
    from_date="20250101",
    to_date="20250131"
)

# Specific symbol
result = broker.fetch_ipo_schedule(symbol="123456")

# Helper methods
status = broker.get_ipo_status(ipo['subscr_dt'])  # "์˜ˆ์ •", "์ง„ํ–‰์ค‘", "๋งˆ๊ฐ"
d_day = broker.calculate_ipo_d_day(ipo['subscr_dt'])  # Days until subscription

Symbol Lists

# KOSPI symbols
result = broker.fetch_kospi_symbols()

# KOSDAQ symbols
result = broker.fetch_kosdaq_symbols()

๐Ÿ”ง Advanced Usage

Multiple Stock Queries

# Query multiple stocks
stocks = [
    ("005930", "KR"),  # Samsung
    ("000660", "KR"),  # SK Hynix
    ("035720", "KR"),  # Kakao
]

results = []
for symbol, market in stocks:
    result = broker.fetch_price(symbol, market)
    results.append(result)
    # Add your own rate limiting here if needed

Mixed KR/US Portfolio

portfolio = [
    ("005930", "KR"),  # Samsung Electronics
    ("AAPL", "US"),    # Apple
    ("035720", "KR"),  # Kakao
    ("MSFT", "US"),    # Microsoft
]

for symbol, market in portfolio:
    result = broker.fetch_price(symbol, market)

    if result['rt_cd'] == '0':
        if market == "KR":
            output = result['output1']
            price = output['stck_prpr']
            print(f"{symbol}: โ‚ฉ{int(price):,}")
        else:
            output = result['output']
            price = output['last']
            print(f"{symbol}: ${price}")

Error Handling

try:
    result = broker.fetch_price("INVALID", "US")

    if result['rt_cd'] != '0':
        # API returned error
        print(f"API Error: {result['msg1']}")
except ValueError as e:
    # Invalid parameters
    print(f"Invalid request: {e}")
except Exception as e:
    # Network or other errors
    print(f"Error: {e}")

Memory Caching (Optional)

Reduce API calls and improve response times with built-in memory caching:

from korea_investment_stock import KoreaInvestment, CachedKoreaInvestment

# Create base broker
broker = KoreaInvestment(api_key, api_secret, acc_no)

# Wrap with caching (opt-in)
cached_broker = CachedKoreaInvestment(broker, price_ttl=5)

# First call: API request (cache miss)
result1 = cached_broker.fetch_price("005930", "KR")  # ~200ms

# Second call: from cache (cache hit)
result2 = cached_broker.fetch_price("005930", "KR")  # <1ms

# Cache statistics
stats = cached_broker.get_cache_stats()
print(f"Hit rate: {stats['hit_rate']}")  # "50.00%"

TTL Configuration (in seconds):

cached_broker = CachedKoreaInvestment(
    broker,
    price_ttl=5,        # Real-time price: 5 seconds
    stock_info_ttl=300, # Stock info: 5 minutes
    symbols_ttl=3600,   # Symbol lists: 1 hour
    ipo_ttl=1800        # IPO schedule: 30 minutes
)

Performance Benefits:

  • ๐Ÿ“‰ API calls reduced by 30-50%
  • โšก Response time improved by 90%+ (cached queries)
  • ๐Ÿ”’ Thread-safe with automatic expiration
  • ๐Ÿ’พ No external dependencies (memory-only)

See: examples/cached_basic_example.py for comprehensive examples

๐Ÿ“Š Response Format

Domestic Stock (KR)

{
    'rt_cd': '0',               # Return code ('0' = success)
    'msg1': '์ •์ƒ์ฒ˜๋ฆฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค',   # Message
    'output1': {
        'stck_prpr': '62600',   # Current price
        'prdy_vrss': '1600',    # Change from previous day
        'prdy_ctrt': '2.62',    # Change rate (%)
        'stck_oprc': '61000',   # Opening price
        'stck_hgpr': '63000',   # High price
        'stck_lwpr': '60500',   # Low price
        'acml_vol': '15234567'  # Volume
        # ... more fields
    }
}

US Stock (US)

{
    'rt_cd': '0',
    'msg1': '์ •์ƒ์ฒ˜๋ฆฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค',
    'output': {
        'rsym': 'DNASAAPL',     # Exchange + Symbol
        'last': '211.16',       # Current price
        'open': '210.56',       # Opening price
        'high': '212.13',       # High price
        'low': '209.86',        # Low price
        'tvol': '39765812',     # Volume
        't_xdif': '1.72',       # Change
        't_xrat': '-0.59',      # Change rate (%)
        'perx': '32.95',        # PER
        'pbrx': '47.23',        # PBR
        'epsx': '6.41',         # EPS
        'bpsx': '4.47'          # BPS
        # ... more fields
    }
}

โš ๏ธ Important Notes

API Rate Limits

  • Korea Investment API: 20 requests/second
  • You are responsible for implementing rate limiting
  • Exceeding limits will cause API errors

US Stocks

  • Auto-detects exchange (NASDAQ โ†’ NYSE โ†’ AMEX)
  • Includes financial ratios (PER, PBR, EPS, BPS)

Context Manager

Always use context manager for proper resource cleanup:

# โœ… Good: Automatic cleanup
with KoreaInvestment(api_key, api_secret, acc_no) as broker:
    result = broker.fetch_price("005930", "KR")

# โŒ Bad: Manual cleanup required
broker = KoreaInvestment(api_key, api_secret, acc_no)
result = broker.fetch_price("005930", "KR")
broker.shutdown()  # Must call manually

๐Ÿ”จ Implementing Your Own Features

Rate Limiting Example

import time

class RateLimiter:
    def __init__(self, calls_per_second=15):
        self.min_interval = 1.0 / calls_per_second
        self.last_call = 0

    def wait(self):
        elapsed = time.time() - self.last_call
        if elapsed < self.min_interval:
            time.sleep(self.min_interval - elapsed)
        self.last_call = time.time()

# Usage
limiter = RateLimiter(calls_per_second=15)

for symbol, market in stocks:
    limiter.wait()
    result = broker.fetch_price(symbol, market)

Caching Example

from functools import lru_cache
from datetime import datetime, timedelta

class CachedBroker:
    def __init__(self, broker):
        self.broker = broker
        self.cache = {}
        self.ttl = timedelta(minutes=5)

    def fetch_price_cached(self, symbol, market):
        key = f"{symbol}:{market}"
        now = datetime.now()

        if key in self.cache:
            cached_time, cached_result = self.cache[key]
            if now - cached_time < self.ttl:
                return cached_result

        result = self.broker.fetch_price(symbol, market)
        self.cache[key] = (now, result)
        return result

Retry Example

import time

def fetch_with_retry(broker, symbol, market, max_retries=3):
    for attempt in range(max_retries):
        try:
            result = broker.fetch_price(symbol, market)
            if result['rt_cd'] == '0':
                return result
        except Exception as e:
            if attempt == max_retries - 1:
                raise
            time.sleep(2 ** attempt)  # Exponential backoff

๐Ÿ“š Examples

See the examples/ directory:

  • basic_example.py: Simple usage patterns
  • ipo_schedule_example.py: IPO queries and helpers
  • us_stock_price_example.py: US stock queries

๐Ÿ”„ Migration from v0.5.0

Breaking Changes in v0.6.0

Removed features (~6,000 lines of code):

  • Rate limiting system
  • TTL caching
  • Batch processing methods
  • Monitoring and statistics
  • Visualization tools
  • Automatic retry decorators

API changes:

# v0.5.0 (Old)
results = broker.fetch_price_list([("005930", "KR"), ("AAPL", "US")])

# v0.6.0 (New)
results = []
for symbol, market in [("005930", "KR"), ("AAPL", "US")]:
    result = broker.fetch_price(symbol, market)
    results.append(result)

See CHANGELOG.md for complete migration guide.

๐Ÿ“– Documentation

๐Ÿค Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Submit a pull request

๐Ÿ“ License

MIT License - see LICENSE file

โšก Performance Tips

  1. Implement rate limiting: Prevent API errors
  2. Use caching: Reduce redundant API calls
  3. Batch requests wisely: Don't overwhelm the API
  4. Handle errors gracefully: Check rt_cd and msg1
  5. Use context manager: Ensure proper cleanup

๐Ÿ™ Credits

  • Korea Investment Securities for providing the OpenAPI
  • Original contributors: Jonghun Yoo, Brayden Jo, Frank Oh

Remember: This is a pure wrapper. You control rate limiting, caching, error handling, and monitoring according to your needs.

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.6.0.tar.gz (117.2 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.6.0-py3-none-any.whl (40.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: korea_investment_stock-0.6.0.tar.gz
  • Upload date:
  • Size: 117.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for korea_investment_stock-0.6.0.tar.gz
Algorithm Hash digest
SHA256 6c46214d0accd5134654fac517e8af4b4257c311a7a131f3f910fe79d71d7d2f
MD5 38ed298c8af22dfb7c9ffc3bf658be2a
BLAKE2b-256 c9323a2877d5d7e24943571fbd4a317f0445fbbd45696c24653cfafa77501fc2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for korea_investment_stock-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5e624e46067427429c0beb1b03092ab2c881a87227a3c423d43cc803719b0064
MD5 9be7a9b305cf231498429332ff3fbc02
BLAKE2b-256 c8fa1b58acdcabfae56a0a203bfd96fcd9c2580644212b5699d004c7153f2031

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