fix: 최종 회의 CRITICAL 1건 + MEDIUM 2건 수정
1. swing/scheduler: mdd_manager.update() 매 사이클 호출 추가 — 새 스케줄러에서 MDD -10%/-20% 감지가 완전 무력화되어 있었음 2. mdd_manager: place_order() → safe_place_order() 변경 — 세마포어+분산락 보호로 이중 매도 방지 3. mdd_manager: 매도 후 ActiveTrade close/update 추가 — 전량 매도 시 enqueue_close_active_trade() — 부분 매도 시 remaining_pct 갱신 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -230,7 +230,8 @@ class MDDManager:
|
|||||||
sell_qty = min(sell_qty, quantity)
|
sell_qty = min(sell_qty, quantity)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
order_resp = await korea_investment_api.place_order(
|
from app.services.trade_executor import safe_place_order
|
||||||
|
order_resp = await safe_place_order(
|
||||||
stock_code=stock_code,
|
stock_code=stock_code,
|
||||||
order_type="SELL",
|
order_type="SELL",
|
||||||
quantity=sell_qty,
|
quantity=sell_qty,
|
||||||
@@ -269,6 +270,20 @@ class MDDManager:
|
|||||||
"strategy_type": "mdd_reduction",
|
"strategy_type": "mdd_reduction",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# [FIX] 전량 매도 시 ActiveTrade 닫기
|
||||||
|
remaining_qty = quantity - sell_qty
|
||||||
|
if remaining_qty <= 0:
|
||||||
|
from app.services.db_worker import enqueue_close_active_trade
|
||||||
|
await enqueue_close_active_trade(stock_code)
|
||||||
|
else:
|
||||||
|
# 부분 매도: remaining_pct 갱신
|
||||||
|
from app.services.db_worker import enqueue_active_trade_upsert
|
||||||
|
new_remaining = remaining_qty / quantity
|
||||||
|
await enqueue_active_trade_upsert({
|
||||||
|
"stock_code": stock_code,
|
||||||
|
"remaining_pct": new_remaining,
|
||||||
|
})
|
||||||
|
|
||||||
results.append({
|
results.append({
|
||||||
"stock_code": stock_code,
|
"stock_code": stock_code,
|
||||||
"stock_name": stock_name,
|
"stock_name": stock_name,
|
||||||
|
|||||||
@@ -93,7 +93,20 @@ async def swing_scheduler() -> None:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"[Swing] 청산 체크 오류: {e}", exc_info=True)
|
logger.error(f"[Swing] 청산 체크 오류: {e}", exc_info=True)
|
||||||
|
|
||||||
# ── Phase 2: MDD 체크 + 강제 축소 (세션 불필요) ──
|
# ── Phase 2: MDD 업데이트 + 체크 + 강제 축소 ──
|
||||||
|
# [FIX] mdd_manager.update()를 매 사이클 호출하여 MDD 감지 활성화
|
||||||
|
try:
|
||||||
|
from app.services.korea_investment_api import korea_investment_api
|
||||||
|
balance_resp = await korea_investment_api.get_balance()
|
||||||
|
if balance_resp:
|
||||||
|
_total = float(balance_resp.get("output2", [{}])[0].get("tot_evlu_amt", 0))
|
||||||
|
if _total > 0:
|
||||||
|
mdd_result = await mdd_manager.update(_total)
|
||||||
|
if mdd_result.get("action") != "NONE":
|
||||||
|
logger.warning(f"[Swing] MDD 상태 변경: {mdd_result}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug(f"[Swing] MDD update 조회 실패 (무시): {e}")
|
||||||
|
|
||||||
can_open_new = await mdd_manager.can_open_new_position()
|
can_open_new = await mdd_manager.can_open_new_position()
|
||||||
logger.info(f"[Swing] MDD 체크: can_open={can_open_new}")
|
logger.info(f"[Swing] MDD 체크: can_open={can_open_new}")
|
||||||
if not can_open_new:
|
if not can_open_new:
|
||||||
|
|||||||
Reference in New Issue
Block a user