feat: initial upbit auto-trader implementation

Strategy C: volatility breakout (Larry Williams K=0.5) AND momentum
(MA20 + 2x volume surge) must both trigger for a buy signal.

Hard rules:
- Trailing stop: sell when price drops -10% from peak
- Max budget: 1,000,000 KRW total, up to 3 positions (333,333 KRW each)
- Scan top 20 KRW tickers by 24h trading volume every 60s
- Monitor positions every 10s

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
joungmin
2026-02-28 10:20:02 +09:00
commit 83bd51117f
11 changed files with 404 additions and 0 deletions

46
daemon/runner.py Normal file
View File

@@ -0,0 +1,46 @@
"""매수 기회 스캔 루프 - 60초마다 전체 시장 스캔."""
import logging
import time
from core import trader
from core.market import get_top_tickers
from core.strategy import should_buy
logger = logging.getLogger(__name__)
SCAN_INTERVAL = 60 # 초
def run_scanner() -> None:
"""메인 스캔 루프."""
logger.info(f"스캐너 시작 (주기={SCAN_INTERVAL}초)")
while True:
try:
# 포지션 꽉 찼으면 스캔 스킵
if len(trader.get_positions()) >= trader.MAX_POSITIONS:
logger.info("포지션 최대치 도달, 스캔 스킵")
time.sleep(SCAN_INTERVAL)
continue
tickers = get_top_tickers()
logger.info(f"스캔 시작: {len(tickers)}개 종목")
for ticker in tickers:
# 이미 보유 중인 종목 제외
if ticker in trader.get_positions():
continue
try:
if should_buy(ticker):
logger.info(f"매수 신호: {ticker}")
trader.buy(ticker)
time.sleep(0.15) # API rate limit 방지
except Exception as e:
logger.error(f"스캔 오류 {ticker}: {e}")
time.sleep(0.3)
except Exception as e:
logger.error(f"스캐너 루프 오류: {e}")
time.sleep(SCAN_INTERVAL)