Files
upbit-trader/daemon/runner.py
joungmin 16b4c932a2 feat: bear block, trend-continuation entry, partial TP backtest
1. daemon/runner.py: skip scan entirely in bear regime
   - calls get_regime() at start of each scan loop
   - logs bear block with score before sleeping

2. core/strategy.py: trend-continuation entry filter
   - check_trend_6h(): 6h price trend >= 1% (rejects flash spikes)
   - 15-min confirmation watchlist (_watchlist dict)
   - should_buy() adds watchlist to existing 12h+regime+momentum logic
   - CONFIRM_SECONDS env var (default 900 = 15min)
   - TREND_6H_MIN_PCT env var (default 1.0%)

3. backtest.py: partial take-profit scenario comparison (--tp-cmp)
   - simulate(): partial_tp_pct / partial_tp_ratio params
   - blended pnl = ratio * partial_pnl + (1-ratio) * remaining_pnl
   - main_tp_cmp(): 3 scenarios A/B/C (none / +5% 50% / +3% 50%)
   - result: partial TP reduces cumulative return (-56% → -63%)
     big winners carry the strategy; trimming them hurts expected value

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 10:51:02 +09:00

58 lines
1.9 KiB
Python

"""매수 기회 스캔 루프 - 60초마다 전체 시장 스캔."""
import logging
import time
from core import trader
from core.market import get_top_tickers
from core.market_regime import get_regime
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
# Bear 레짐 시 신규 매수 완전 차단
regime = get_regime()
if regime["name"] == "bear":
logger.info(
f"[Bear차단] 레짐={regime['emoji']} BEAR "
f"(score={regime['score']:+.2f}%) — 신규 매수 스킵"
)
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)