[2026-05-15] rate limit·전일데이터·TR ID 등 버그 수정

- main.py: sleep 0.05/0.1 → 1.1초 (KIS rate limit 준수)
- main.py: 전일 날짜 계산 수정 (월요일→금요일), 인라인 주석 env 파싱, 장 중 재시작 즉시 루프 진입
- strategy/volatility_breakout.py: has_prev_data() 추가, 중복 수집 skip
- db/repository.py, order_executor.py: UPDATE ORDER BY → 서브쿼리 수정 (SQLite 호환)
- kis_client.py: get_balance TR ID VTTC8001R → VTTC8434R
- test_connection.py: API 호출 간 sleep 추가

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-15 13:38:40 +09:00
parent 253867ef1c
commit a64a3f017b
7 changed files with 77 additions and 19 deletions
+36 -14
View File
@@ -31,12 +31,21 @@ def load_env():
continue
k, _, v = line.partition("=")
k = k.strip()
v = v.strip()
# 인라인 주석 제거 (예: true # 모의투자 → true)
if " #" in v:
v = v[:v.index(" #")]
v = v.strip().strip('"').strip("'")
if k and v and k not in os.environ:
os.environ[k] = v
load_env()
# 프로젝트 루트를 sys.path에 추가 (로컬 실행 시 필요)
ROOT = Path(__file__).parent.parent
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
# 로깅 설정
logging.basicConfig(
level=getattr(logging, os.getenv("LOG_LEVEL", "INFO")),
@@ -104,16 +113,13 @@ class StockBot:
"""종목 풀 갱신 + 전일 데이터 수집"""
logger.info("유니버스 갱신 시작")
try:
# 거래량 순위 상위 30종목
rank = await self.kis.get_volume_rank(top_n=MAX_UNIVERSE)
tickers = [r["ticker"] for r in rank]
# AI 블랙리스트 제거
ctx = self.strategy.context
blacklist = ctx.get("blacklist_tickers", [])
tickers = [t for t in tickers if t not in blacklist]
# boosted 종목 상단 배치
boosted = ctx.get("boosted_tickers", [])
tickers = (
[t for t in boosted if t in tickers] +
@@ -123,27 +129,35 @@ class StockBot:
self.universe = tickers
logger.info(f"유니버스: {len(tickers)}종목")
# 전일 OHLCV 수집 (목표가 계산용)
today = datetime.now().strftime("%Y%m%d")
# 전일 날짜 계산
from datetime import timedelta
today = datetime.now()
# 월요일이면 금요일로
offset = 3 if today.weekday() == 0 else 1
prev_date = (today - timedelta(days=offset)).strftime("%Y%m%d")
for ticker in self.universe:
# 이미 전일 데이터 있으면 skip
if self.strategy.has_prev_data(ticker):
continue
try:
ohlcv = await self.kis.get_ohlcv_daily(
ticker,
start=today,
end=today,
start=prev_date,
end=prev_date,
)
if len(ohlcv) >= 2:
prev = ohlcv[-2]
if ohlcv:
prev = ohlcv[-1]
self.strategy.set_prev_data(
ticker,
high = prev["high"],
low = prev["low"],
amount= prev.get("amount",
prev.get("volume",0) * prev.get("close",0))
prev.get("volume", 0) * prev.get("close", 0))
)
except Exception as e:
logger.warning(f"전일 데이터 실패 {ticker}: {e}")
await asyncio.sleep(0.1) # rate limit
await asyncio.sleep(1.1) # 초당 2.5건으로 제한
except Exception as e:
logger.error(f"유니버스 갱신 실패: {e}")
@@ -162,7 +176,7 @@ class StockBot:
target = self.strategy.get_target(ticker)
if target > 0:
logger.debug(f"{ticker} 목표가: {target:,.0f}")
await asyncio.sleep(0.05)
await asyncio.sleep(1.1)
except Exception as e:
logger.warning(f"시가 수집 실패 {ticker}: {e}")
@@ -279,7 +293,7 @@ class StockBot:
boosted=signal.get("boosted", False),
)
await asyncio.sleep(0.1)
await asyncio.sleep(1.1)
except Exception as e:
logger.error(f"진입 체크 오류 {ticker}: {e}")
@@ -319,7 +333,7 @@ class StockBot:
reason=signal["reason"],
)
await asyncio.sleep(0.05)
await asyncio.sleep(1.1)
except Exception as e:
logger.error(f"청산 체크 오류 {ticker}: {e}")
@@ -412,6 +426,14 @@ async def run():
bot = StockBot()
await bot.initialize()
now = datetime.now().strftime("%H:%M")
if "09:00" <= now <= "14:30":
logger.info("장 중 재시작 감지 → 유니버스/목표가 즉시 계산")
await bot.update_universe()
await bot.calc_targets()
await bot.trading_loop() # 바로 매매루프 진입
return
while True:
now = datetime.now().strftime("%H:%M")