feat: 데이트레이딩 포지션 화면 표시 + 모든 매도 즉시 화면 반영

- portfolio_cache_bridge 신설: 매매 엔진 체결 시 Portfolio(db_worker 큐) + 인메모리 캐시 즉시 갱신.
  DT 매수는 strategy_type='daytrading'으로 태깅되어 보유 종목 패널의 '데이트레이딩' 그룹에 표시되고
  스윙 청산 로직(strategy_type='swing' 대상)에서 제외됨. (기존엔 KIS 동기화로 'swing'으로 유입돼
  DT 포지션이 안 보이고 스윙 엔진이 같이 관리하는 문제)
- DT 매도·스윙 자동 매도도 캐시에서 즉시 제거/차감 + 최근매도 기록(동기화 되살림 방지).
- 동기화 시 DT 엔진 보유 종목은 'daytrading'으로 태깅.
- 프론트: 수동 매도 성공 시 낙관적 갱신으로 서버 재조회 전 즉시 목록에서 제거.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-22 16:49:46 +09:00
parent 496529782b
commit a57c720559
7 changed files with 189 additions and 10 deletions

View File

@@ -335,15 +335,17 @@ async def check_and_execute_exit_v2(db: AsyncSession) -> list[dict]:
"strategy_type": "swing",
})
# 포트폴리오 화면 즉시 반영 (Portfolio 수량 차감 + 캐시)
from app.services.portfolio_cache_bridge import reflect_sell
await reflect_sell(stock_code, sell_qty, latest_price, remaining_qty=quantity - sell_qty)
# 전량 청산이면 ActiveTrade 종료, 분할 매도면 remaining_pct 갱신
if sell_qty >= quantity:
await enqueue_close_active_trade(stock_code, strategy_name=None)
else:
# 분할 매도 후 remaining_pct 갱신 (반복 트리거 방지)
new_remaining = max(0.0, remaining_pct - sell_pct)
from app.services.db_worker import (
enqueue_active_trade_upsert, enqueue_portfolio_upsert,
)
from app.services.db_worker import enqueue_active_trade_upsert
_at_data = {
"stock_code": stock_code,
"remaining_pct": new_remaining,
@@ -364,13 +366,6 @@ async def check_and_execute_exit_v2(db: AsyncSession) -> list[dict]:
"entry_reason": "동기화 유입 포지션 (부분매도 시 자동 생성)",
})
await enqueue_active_trade_upsert(_at_data)
# [FIX] 잔여 수량도 즉시 반영 — 다음 사이클이 동기화 전 원래 수량
# 기준으로 매도 수량을 계산하지 않도록 (18주→9주 재매도 방지)
await enqueue_portfolio_upsert({
"stock_code": stock_code,
"quantity": quantity - sell_qty,
"current_price": latest_price,
})
# LossTracker 업데이트 — 전량매도 시에만 (분할매도 이중 카운트 방지)
if sell_qty >= quantity: