[2026-06-02] 결산 중복과 모의투자 호출 안정화
This commit is contained in:
@@ -3,7 +3,7 @@ kis_client.py
|
||||
KIS Open API REST + WebSocket 래퍼
|
||||
- 토큰 자동 발급/갱신
|
||||
- 모의투자/실거래 모드 자동 전환
|
||||
- rate limit 제어 (초당 20건)
|
||||
- rate limit 제어 (모드별 요청 간격)
|
||||
"""
|
||||
|
||||
import os
|
||||
@@ -55,8 +55,9 @@ class KISClient:
|
||||
)
|
||||
self._load_token_from_file()
|
||||
|
||||
# rate limit: 모의투자 1건/초, 실거래 5건/초
|
||||
# rate limit: 모의투자 1건/초보다 보수적, 실거래 5건/초 이하
|
||||
self._rate_limit = 1 if self.is_mock else 5
|
||||
self._request_spacing = 1.2 if self.is_mock else 0.22
|
||||
self._semaphore = asyncio.Semaphore(1)
|
||||
self._req_times : list = []
|
||||
|
||||
@@ -158,7 +159,7 @@ class KISClient:
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
KIS REST API 공통 호출
|
||||
- rate limit 제어 (초당 20건)
|
||||
- rate limit 제어 (모드별 요청 간격)
|
||||
- 토큰 자동 첨부
|
||||
"""
|
||||
token = await self.get_access_token()
|
||||
@@ -174,11 +175,17 @@ class KISClient:
|
||||
|
||||
async with self._semaphore:
|
||||
now = time.monotonic()
|
||||
if self._req_times:
|
||||
wait = self._request_spacing - (now - self._req_times[-1])
|
||||
if wait > 0:
|
||||
await asyncio.sleep(wait)
|
||||
now = time.monotonic()
|
||||
self._req_times = [t for t in self._req_times if now - t < 1.0]
|
||||
if len(self._req_times) >= self._rate_limit:
|
||||
wait = 1.0 - (now - self._req_times[0])
|
||||
if wait > 0:
|
||||
await asyncio.sleep(wait)
|
||||
now = time.monotonic()
|
||||
self._req_times.append(time.monotonic())
|
||||
|
||||
_timeout = aiohttp.ClientTimeout(total=10)
|
||||
|
||||
@@ -31,10 +31,14 @@ class OrderExecutor:
|
||||
qty: int,
|
||||
reason: str = "",
|
||||
ai_boosted: bool = False,
|
||||
fill_price: float | None = None,
|
||||
) -> dict:
|
||||
"""Submit a market buy and save the opened trade."""
|
||||
try:
|
||||
result = await self.kis.order_buy(ticker, qty)
|
||||
if self.dry_run and fill_price:
|
||||
result = {"entry_price": fill_price}
|
||||
else:
|
||||
result = await self.kis.order_buy(ticker, qty)
|
||||
price = result.get("entry_price", 0)
|
||||
if not price:
|
||||
price = (await self.kis.get_price(ticker))["current"]
|
||||
@@ -64,10 +68,14 @@ class OrderExecutor:
|
||||
name: str,
|
||||
qty: int,
|
||||
reason: str = "",
|
||||
fill_price: float | None = None,
|
||||
) -> dict:
|
||||
"""Submit a market sell and save full or partial exit results."""
|
||||
try:
|
||||
result = await self.kis.order_sell(ticker, qty)
|
||||
if self.dry_run and fill_price:
|
||||
result = {"exit_price": fill_price}
|
||||
else:
|
||||
result = await self.kis.order_sell(ticker, qty)
|
||||
price = result.get("exit_price", 0)
|
||||
if not price:
|
||||
price = (await self.kis.get_price(ticker))["current"]
|
||||
|
||||
Reference in New Issue
Block a user