ํค์์ฆ๊ถ REST API๋ฅผ ํ์ด์ฌ์ผ๋ก ์ง๊ด์ ์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํ ํด๋ผ์ด์ธํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค.
๐ v0.3.3 ์๋ก์ด ๊ธฐ๋ฅ: ํฌ๊ด์ ์ธ ์์ ์์คํ , ์ค์๊ฐ WebSocket ์ง์, 163๊ฐ API ๋ฉ์๋ ์์ ๊ตฌํ
- ๐ฏ ํ ์ค ์ฐ๊ฒฐ:
pyheroapi.connect()ํ ๋ฒ์ผ๋ก ๋ชจ๋ ๊ธฐ๋ฅ ์ฌ์ฉ - ๐ ์๋ ํ ํฐ ๊ด๋ฆฌ: ํ ํฐ ๋ฐ๊ธ, ๊ฐฑ์ , ํ๊ธฐ ์์ ์๋ํ
- ๐ก๏ธ ์ฐ์ํ ์ค๋ฅ ์ฒ๋ฆฌ: ์์ธ ๋์ ์์ ํ ๊ธฐ๋ณธ๊ฐ ๋ฐํ
- โก ์ค๋งํธ ์บ์ฑ: ์ค๋ณต API ํธ์ถ ์๋ ์ต์ ํ
- โ ํฌ๊ด์ ์ธ ์ฃผ๋ฌธ ๊ด๋ฆฌ: ๋งค์/๋งค๋, ์ ์ /์ทจ์, ์กฐ๊ฑด๋ถ ์ฃผ๋ฌธ
- โ ์ ์ฉ๊ฑฐ๋ ์ง์: ์ ์ฉ ๋งค์/๋งค๋, ๋์ถ ๊ด๋ฆฌ
- โ ๋ค์ํ ์ฃผ๋ฌธ ์ ํ: ์ง์ ๊ฐ, ์์ฅ๊ฐ, ์ต์ ๋ฆฌ, IOC, FOK ๋ฑ
- โ ์ค์๊ฐ ์ฃผ๋ฌธ ์ถ์ : ๋ฏธ์ฒด๊ฒฐ/์ฒด๊ฒฐ ๋ด์ญ, ์ค์๊ฐ ์ํ ์ ๋ฐ์ดํธ
- ๐ WebSocket ์ค์๊ฐ ์์ธ: ์ฃผ๊ฐ, ํธ๊ฐ, ์ฒด๊ฒฐ ๋ฐ์ดํฐ
- ๐ ์ค์๊ฐ ๊ณ์ข ๋ชจ๋ํฐ๋ง: ์๊ณ , ํฌ์ง์ ๋ณํ ์ถ์
- โก ๋น๋๊ธฐ ์ฒ๋ฆฌ: async/await ํจํด ์์ ์ง์
- ๐ ์ด๋ฒคํธ ๊ธฐ๋ฐ ์ฝ๋ฐฑ: ์ค์๊ฐ ๋ฐ์ดํฐ ๋ณํ ์๋ฆผ
- ๐ ETF ์ฌํ ๋ถ์: NAV, ์ถ์ ์ค์ฐจ, ์์ต๋ฅ , ๊ตฌ์ฑ์ข ๋ชฉ
- โก ELW ์ ๋ฌธ ๋๊ตฌ: ๊ทธ๋ฆญ์ค(Delta, Gamma, Theta, Vega), ๋ฏผ๊ฐ๋ ์งํ
- ๐๏ธ ๊ธฐ๊ด/์ธ๊ตญ์ธ ๋งค๋งค: ์ค์๊ฐ ๋งค๋งค ๋ํฅ, ์๋งค์/์๋งค๋
- ๐ ์์ฅ ์์ ๋ถ์: ๊ฑฐ๋๋, ๋ฑ๋ฝ๋ฅ , ์๊ฐ์ด์ก ์์
- ๐ 7๊ฐ ํฌ๊ด์ ๋ชจ๋: ๊ธฐ์ด๋ถํฐ ๊ณ ๊ธ๊น์ง ๋จ๊ณ๋ณ ํ์ต
- ๐ก๏ธ ์์ ํ ์๋๋ฐ์ค: ๋ชจ์๊ฑฐ๋ ํ๊ฒฝ ์ ๊ณต๊ณต
- ๐ ์์ธํ ๋ฌธ์ํ: ๋ชจ๋ ๊ธฐ๋ฅ์ ๋ํ ์ค์ฉ์ ์์
- ๐ง ํ๋ก๋์ ์ค๋น: ์ค์ ๊ฑฐ๋๋ฅผ ์ํ ์์ ๊ฐ์ด๋
| ์นดํ ๊ณ ๋ฆฌ | ๊ตฌํ๋ ๊ธฐ๋ฅ | ์ปค๋ฒ๋ฆฌ์ง |
|---|---|---|
| ๐ ์ธ์ฆ & ํ ํฐ | ํ ํฐ ๋ฐ๊ธ/ํ๊ธฐ, ์๋ ๊ด๋ฆฌ | 100% |
| ๐ฐ ์ฃผ๋ฌธ & ๊ฑฐ๋ | ๋ชจ๋ ์ฃผ๋ฌธ ์ ํ, ์ ์ฉ๊ฑฐ๋ | 100% |
| ๐๏ธ ๊ณ์ข ๊ด๋ฆฌ | ์๊ณ , ํฌ์ง์ , ์์ต๋ถ์ | 100% |
| ๐ ์์ธ ๋ฐ์ดํฐ | ์ค์๊ฐ/๊ณผ๊ฑฐ ์์ธ, ํธ๊ฐ | 100% |
| ๐ ์ฐจํธ ๋ฐ์ดํฐ | ์ผ/์ฃผ/์/๋ถ๋ด, ๊ธฐ์ ์ ์งํ | 100% |
| ๐ ์ข ๋ชฉ ์ ๋ณด | ์ข ๋ชฉ ์์ธ์ ๋ณด, ์ฌ๋ฌด๋ฐ์ดํฐ | 95% |
| ๐น ETF ๋ถ์ | NAV, ์ถ์ ์ค์ฐจ, ๊ตฌ์ฑ์ข ๋ชฉ | 100% |
| โก ELW ๋๊ตฌ | ๊ทธ๋ฆญ์ค, ๋ฏผ๊ฐ๋, ์กฐ๊ฑด๊ฒ์ | 100% |
| ๐ ์์ ์ ๋ณด | ๊ฑฐ๋๋/๋ฑ๋ฝ๋ฅ /์์ด ์์ | 100% |
| ๐ข ๊ธฐ๊ด/์ธ๊ตญ์ธ | ๋งค๋งค ๋ํฅ, ๋ณด์ ํํฉ | 100% |
| ๐ ์ค์๊ฐ ๋ฐ์ดํฐ | WebSocket ์คํธ๋ฆฌ๋ฐ | 100% |
| ๐ฏ ์กฐ๊ฑด ๊ฒ์ | ์ค์๊ฐ ์กฐ๊ฑด๊ฒ์, ์กฐ๊ฑด๋ชฉ๋ก ๊ด๋ฆฌ | 100% |
# ๊ธฐ๋ณธ ์ค์น
pip install pyheroapi
# ์ค์๊ฐ ๊ธฐ๋ฅ ํฌํจ
pip install pyheroapi[realtime]
# ๋ชจ๋ ๊ธฐ๋ฅ ํฌํจ
pip install pyheroapi[all]# ~/.bashrc ๋๋ ~/.zshrc์ ์ถ๊ฐ
export KIWOOM_APPKEY="your_app_key_here"
export KIWOOM_SECRETKEY="your_secret_key_here"
export KIWOOM_ACCOUNT_NUMBER="your_account_number_here"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']:,}์ฃผ")01_authentication.py - ๐ ์ธ์ฆ ๊ธฐ์ด
# ํ ํฐ ๊ด๋ฆฌ์ ๋ชจ๋ ๊ฒ
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 - ๐ ์์ธ ๋ฐ์ดํฐ ๋ง์คํฐ
# ์ค์๊ฐ ์์ธ๋ถํฐ ๊ณผ๊ฑฐ ๋ฐ์ดํฐ๊น์ง
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 - ๐ฐ ๊ฑฐ๋ ์คํ ์์ ๊ฐ์ด๋
# ๋ชจ๋ ์ข
๋ฅ์ ์ฃผ๋ฌธ๊ณผ ๊ด๋ฆฌ
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 - ๐น ETF/ELW ์ ๋ฌธ ๋ถ์
# 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 - ๐ ์์ฅ ์์ ๋ถ์
# ์์ฅ์ ๋ชจ๋ ์์ ์ ๋ณด
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 - ๐ ์ฐจํธ & ๊ธฐ์ ์ ๋ถ์
# ๋ชจ๋ ์ฐจํธ ๋ฐ์ดํฐ์ ๊ธฐ์ ์ ๋ถ์
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 - ๐ ์ค์๊ฐ ์คํธ๋ฆฌ๋ฐ
# 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())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}")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}์ต")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))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
)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()01_authentication.py- ์ธ์ฆ๊ณผ ํ ํฐ ๊ด๋ฆฌ02_market_data.py- ๊ธฐ๋ณธ ์์ธ ์กฐํ
03_trading_orders.py- ์ฃผ๋ฌธ ์คํ๊ณผ ๊ด๋ฆฌ- ์๋๋ฐ์ค์์ ์ถฉ๋ถํ ์ฐ์ต
04_etf_elw.py- ETF/ELW ์ ๋ฌธ ๋ถ์05_rankings_analysis.py- ์์ฅ ์์ ๋ถ์06_charts_technical.py- ์ฐจํธ์ ๊ธฐ์ ์ ๋ถ์
07_realtime_websocket.py- ์ค์๊ฐ ์คํธ๋ฆฌ๋ฐ- ํฌํธํด๋ฆฌ์ค ๊ด๋ฆฌ ์์คํ ๊ตฌ์ถ
- ์๋ ๋งค๋งค ์์คํ ๊ฐ๋ฐ
- ํค์ OpenAPI ํํ์ด์ง์ง ๋ฐฉ๋ฌธ
- ๊ณ์ ์์ฑ ๋ฐ ๋ก๊ทธ์ธ
- REST API ์๋น์ค ์ ์ฒญ
- APP KEY์ SECRET KEY ๋ฐ๊ธ
# 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 ํค๋ ์ ๋ ๊ณต๊ฐํ์ง ๋ง์ธ์
- ๐ด ์ ์ฅ์ ํฌํฌ
- ๐ฟ ๊ธฐ๋ฅ ๋ธ๋์น ์์ฑ:
git checkout -b feature/amazing-feature - ๐ ๋ณ๊ฒฝ์ฌํญ ์ปค๋ฐ:
git commit -m 'Add amazing feature' - ๐ค ๋ธ๋์น ํธ์:
git push origin feature/amazing-feature - ๐ Pull Request ์์ฑ
- ๐ ๋ฌธ์: GitHub Wiki
- ๐ ๋ฒ๊ทธ ๋ฆฌํฌํธ: Issues
- ๐ก ๊ธฐ๋ฅ ์์ฒญ: Discussions
- ๐ง ์ด๋ฉ์ผ: dean_jin@icloud.com
MIT License - ์์ธํ ๋ด์ฉ์ LICENSE ํ์ผ ์ฐธ์กฐ
Happy Trading! ๐๐