[2026-05-18] DRY_RUN 가격=0 버그 수정 / 종목명 캐시 / ETF 유니버스 제외

This commit is contained in:
2026-05-18 13:14:26 +09:00
parent f2ce17ba48
commit a3832dd5a8
2 changed files with 35 additions and 14 deletions
+8 -4
View File
@@ -226,8 +226,10 @@ class KISClient:
dry_run = os.getenv("DRY_RUN", "true").lower() == "true"
if dry_run:
logger.info(f"[DRY_RUN] 매수 {ticker} {qty}주 @ {price or '시장가'}")
return {"dry_run": True, "ticker": ticker, "qty": qty}
price_info = await self.get_price(ticker)
current = price_info["current"]
logger.info(f"[DRY_RUN] 매수 {ticker} {qty}주 @ {current:,}")
return {"dry_run": True, "ticker": ticker, "qty": qty, "entry_price": current}
# 모의/실거래 TR 구분
tr_id = "VTTC0802U" if self.is_mock else "TTTC0802U"
@@ -259,8 +261,10 @@ class KISClient:
dry_run = os.getenv("DRY_RUN", "true").lower() == "true"
if dry_run:
logger.info(f"[DRY_RUN] 매도 {ticker} {qty}주 @ {price or '시장가'}")
return {"dry_run": True, "ticker": ticker, "qty": qty}
price_info = await self.get_price(ticker)
current = price_info["current"]
logger.info(f"[DRY_RUN] 매도 {ticker} {qty}주 @ {current:,}")
return {"dry_run": True, "ticker": ticker, "qty": qty, "exit_price": current}
tr_id = "VTTC0801U" if self.is_mock else "TTTC0801U"
+27 -10
View File
@@ -77,12 +77,13 @@ from app.config import (
class StockBot:
def __init__(self):
self.kis = KISClient()
self.executor = OrderExecutor(self.kis)
self.strategy = VolatilityBreakout()
self.positions = {} # ticker → {name, entry, qty, tp1_done, entry_time}
self.universe = [] # 감시 종목 리스트
self.risk = None # RiskManager (잔고 확인 후 초기화)
self.running = False
self.executor = OrderExecutor(self.kis)
self.strategy = VolatilityBreakout()
self.positions = {} # ticker → {name, entry, qty, tp1_done, entry_time}
self.universe = [] # 감시 종목 리스트
self.ticker_names = {} # ticker → 종목명 캐시
self.risk = None # RiskManager (잔고 확인 후 초기화)
self.running = False
mode = "모의투자" if self.kis.is_mock else "실거래"
dry = " [DRY_RUN]" if os.getenv("DRY_RUN","true")=="true" else ""
@@ -109,12 +110,28 @@ class StockBot:
# 유니버스 갱신 (08:30)
# ─────────────────────────────────────────
# ETF/ETN/인버스/레버리지 종목 필터
_ETF_KEYWORDS = ('인버스', '레버리지', '선물', 'KODEX', 'TIGER', 'KBSTAR',
'HANARO', 'ARIRANG', 'KOSEF', 'SOL', 'ACE', 'RISE', 'PLUS')
@staticmethod
def _is_etf(ticker: str, name: str) -> bool:
if ticker.startswith('Q') or len(ticker) != 6: # ETN or 비정상 코드
return True
return any(kw in name for kw in StockBot._ETF_KEYWORDS)
async def update_universe(self):
"""종목 풀 갱신 + 전일 데이터 수집"""
logger.info("유니버스 갱신 시작")
try:
rank = await self.kis.get_volume_rank(top_n=MAX_UNIVERSE)
tickers = [r["ticker"] for r in rank]
# ETF 필터 후 MAX_UNIVERSE 확보 위해 여유분 요청
rank = await self.kis.get_volume_rank(top_n=MAX_UNIVERSE + 20)
# 종목명 캐시 갱신 + ETF 필터
for r in rank:
self.ticker_names[r["ticker"]] = r["name"]
tickers = [r["ticker"] for r in rank
if not self._is_etf(r["ticker"], r["name"])]
ctx = self.strategy.context
blacklist = ctx.get("blacklist_tickers", [])
@@ -127,7 +144,7 @@ class StockBot:
)[:MAX_UNIVERSE]
self.universe = tickers
logger.info(f"유니버스: {len(tickers)}종목")
logger.info(f"유니버스: {len(tickers)}종목 (ETF 제외)")
# 전일 날짜 계산
from datetime import timedelta
@@ -246,7 +263,7 @@ class StockBot:
try:
price_info = await self.kis.get_price(ticker) # rate limiter가 자동 throttle
current = price_info["current"]
name = price_info.get("name", ticker)
name = self.ticker_names.get(ticker, ticker)
signal = self.strategy.check_entry(
ticker=ticker,