feat: 리스크 관리 강화 — 포트폴리오 락, MDD 단기전략 비활성화, 상관관계 필터
- portfolio.py: summary_lock으로 동시성 보호, apply_buy/apply_sell async화 - mdd_manager.py: MDD -10% 시 단기전략 비활성화 (is_short_term_strategy_paused) - loss_tracker.py: DB 직접 접근 → db_worker 큐 기반 전환 - db_worker.py: upsert_stock_ban 태스크 추가 - correlation_filter.py: 섹터 집중도 + 피어슨 상관관계 검증 (CLAUDE.md 5.4) - trade_executor.py: 상관관계 필터 통합, await 적용 - mean_reversion_strategy.py: config 값 타입 안전성 (float 변환) - main.py/day_trading.py: MDD 체크 후 자동매매/데이트레이딩 차단 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -230,8 +230,17 @@ async def auto_trade_scheduler():
|
||||
except Exception as e:
|
||||
logger.error(f"Exit trade check error: {e}", exc_info=True)
|
||||
|
||||
# 2. 자동매매: Redis 캐시 우선 → cache miss 시만 DB 조회
|
||||
if settings.AUTO_TRADE_ENABLED:
|
||||
# 2. MDD 체크 (CLAUDE.md 5.3) — 신규 진입 가능 여부
|
||||
from app.services.mdd_manager import mdd_manager
|
||||
can_open_new = await mdd_manager.can_open_new_position()
|
||||
if not can_open_new:
|
||||
logger.warning(
|
||||
"⚠️ [Auto-Trade] MDD -10% 이상 도달 — 신규 진입 차단. "
|
||||
"기존 포지션만 손절/익절 모니터링 중"
|
||||
)
|
||||
|
||||
# 3. 자동매매: Redis 캐시 우선 → cache miss 시만 DB 조회
|
||||
if settings.AUTO_TRADE_ENABLED and can_open_new:
|
||||
# ── Redis 캐시 확인 (10분 배치 결과, TTL 30분) ────────────────
|
||||
rec = await get_json("recommendations:latest")
|
||||
if rec:
|
||||
@@ -324,6 +333,8 @@ async def auto_trade_scheduler():
|
||||
await execute_auto_trade_background(rec, session)
|
||||
else:
|
||||
logger.info("⏭️ Auto-trade skipped: no recommendations")
|
||||
elif settings.AUTO_TRADE_ENABLED and not can_open_new:
|
||||
logger.info("⏸️ Auto-trade disabled (MDD protection) - only monitoring stop-loss/take-profit")
|
||||
else:
|
||||
logger.info("⏸️ Auto-trade disabled - only monitoring stop-loss/take-profit")
|
||||
except Exception as e:
|
||||
@@ -336,15 +347,19 @@ async def auto_trade_scheduler():
|
||||
|
||||
|
||||
async def day_trade_scheduler():
|
||||
"""30초 간격 데이트레이딩 스케줄러.
|
||||
"""30초 간격 데이트레이딩 스케줄러 (MDD 보호 기능 포함).
|
||||
|
||||
- Opening Range 수집 (09:00~09:30)
|
||||
- 진입 신호 스캔 + 주문 실행 (09:30~15:00)
|
||||
- 진입 신호 스캔 + 주문 실행 (09:30~15:00) — MDD -10% 이상이면 진입 중단
|
||||
- EOD 강제 청산 (15:20~15:30)
|
||||
- 장 외 시간: 30분 슬립
|
||||
|
||||
MDD 체크 (CLAUDE.md 섹션 5.3):
|
||||
- MDD -10% 도달 시: 데이트레이딩(단기전략) 일시 중단
|
||||
"""
|
||||
await asyncio.sleep(5)
|
||||
from app.api.endpoints.day_trading import run_day_trading_cycle
|
||||
from app.services.mdd_manager import mdd_manager
|
||||
|
||||
logger.info("📈 Day-trade scheduler started (every 30s)")
|
||||
try:
|
||||
@@ -355,6 +370,14 @@ async def day_trade_scheduler():
|
||||
if not settings.DAY_TRADE_ENABLED:
|
||||
await asyncio.sleep(60)
|
||||
continue
|
||||
|
||||
# MDD 체크: 단기 전략 활성화 여부 확인 (CLAUDE.md 5.3)
|
||||
short_term_enabled = await mdd_manager.is_short_term_strategy_enabled()
|
||||
if not short_term_enabled:
|
||||
logger.info("⏸️ [DayTrade] MDD -10% 이상 — 단기 전략(데이트레이딩) 중단 (신규 진입 불가)")
|
||||
await asyncio.sleep(60) # 1분 후 재확인
|
||||
continue
|
||||
|
||||
try:
|
||||
result = await run_day_trading_cycle()
|
||||
phase = result.get("phase", "")
|
||||
|
||||
Reference in New Issue
Block a user