배치 수정
This commit is contained in:
@@ -246,10 +246,12 @@ class PortfolioCache:
|
||||
# D+2 정산액 및 기타 상세 정보 추출
|
||||
d2_settlement = 0.0
|
||||
stock_value_from_api = 0.0
|
||||
bfdy_total_assets = 0.0
|
||||
if balance_data and "output2" in balance_data:
|
||||
output2 = balance_data["output2"][0] if isinstance(balance_data["output2"], list) else balance_data["output2"]
|
||||
d2_settlement = pick_float(output2, ["nxdy_excc_amt", "d2_auto_rdpt_amt"])
|
||||
stock_value_from_api = pick_float(output2, ["scts_evlu_amt", "evlu_amt_smtl_amt"])
|
||||
bfdy_total_assets = pick_float(output2, ["bfdy_tot_asst_evlu_amt"])
|
||||
|
||||
# 해외 잔고 합산 (원화 환산 총자산에 포함)
|
||||
overseas_total_krw = 0.0
|
||||
@@ -263,6 +265,10 @@ class PortfolioCache:
|
||||
total_assets += overseas_total_krw
|
||||
logger.debug(f"💵 해외 잔고 합산: {overseas_total_krw:,.0f}원")
|
||||
|
||||
# 금일 평가손익 (전일 총자산 대비 오늘 변화)
|
||||
today_profit_loss = (total_assets - bfdy_total_assets) if bfdy_total_assets > 0 else 0.0
|
||||
today_profit_loss_rate = (today_profit_loss / bfdy_total_assets * 100) if bfdy_total_assets > 0 else 0.0
|
||||
|
||||
self.summary = {
|
||||
"total_stocks": total_stocks,
|
||||
"total_value": total_value,
|
||||
@@ -273,6 +279,9 @@ class PortfolioCache:
|
||||
"total_assets": total_assets,
|
||||
"d2_settlement": d2_settlement,
|
||||
"stock_value_from_api": stock_value_from_api,
|
||||
"bfdy_total_assets": bfdy_total_assets,
|
||||
"today_profit_loss": today_profit_loss,
|
||||
"today_profit_loss_rate": today_profit_loss_rate,
|
||||
# 해외 관련 추가 필드
|
||||
"overseas_value_usd": overseas_value_usd,
|
||||
"overseas_value_krw": overseas_value_krw if exchange_rate > 0 else overseas_total_krw,
|
||||
@@ -632,26 +641,36 @@ async def get_portfolio_summary(db: AsyncSession = Depends(get_db)):
|
||||
if portfolio_cache.summary and not portfolio_cache.should_sync():
|
||||
logger.debug("Portfolio cache hit (summary)")
|
||||
resp = dict(portfolio_cache.summary)
|
||||
resp.update({
|
||||
"sync_status": "ok" if portfolio_cache.last_error is None else "error",
|
||||
"last_synced": portfolio_cache.last_synced.isoformat() if portfolio_cache.last_synced else None,
|
||||
"last_error": portfolio_cache.last_error,
|
||||
else:
|
||||
try:
|
||||
await sync_portfolio(db, force=False)
|
||||
except HTTPException:
|
||||
logger.warning("get_portfolio_summary: sync failed, returning cached summary")
|
||||
resp = dict(portfolio_cache.summary or {
|
||||
"total_stocks": 0,
|
||||
"total_value": 0,
|
||||
"total_investment": 0,
|
||||
"total_profit_loss": 0,
|
||||
"total_profit_loss_rate": 0,
|
||||
"available_cash": 0,
|
||||
"total_assets": 0,
|
||||
})
|
||||
return resp
|
||||
|
||||
# 누적 실현 손익 (TradeHistory SELL 체결 기준)
|
||||
try:
|
||||
await sync_portfolio(db, force=False)
|
||||
except HTTPException:
|
||||
logger.warning("get_portfolio_summary: sync failed, returning cached summary")
|
||||
base = portfolio_cache.summary or {
|
||||
"total_stocks": 0,
|
||||
"total_value": 0,
|
||||
"total_investment": 0,
|
||||
"total_profit_loss": 0,
|
||||
"total_profit_loss_rate": 0,
|
||||
"available_cash": 0,
|
||||
"total_assets": 0
|
||||
}
|
||||
resp = dict(base)
|
||||
realized_result = await db.execute(
|
||||
select(func.sum(TradeHistory.net_profit_loss)).where(
|
||||
TradeHistory.order_type == "SELL",
|
||||
TradeHistory.status.in_(["EXECUTED", "COMPLETED"]),
|
||||
TradeHistory.net_profit_loss.isnot(None),
|
||||
)
|
||||
)
|
||||
cumulative_realized_pl = float(realized_result.scalar() or 0)
|
||||
except Exception as e:
|
||||
logger.warning(f"누적 실현손익 조회 실패: {e}")
|
||||
cumulative_realized_pl = 0.0
|
||||
|
||||
resp["cumulative_realized_pl"] = cumulative_realized_pl
|
||||
resp.update({
|
||||
"sync_status": "ok" if portfolio_cache.last_error is None else "error",
|
||||
"last_synced": portfolio_cache.last_synced.isoformat() if portfolio_cache.last_synced else None,
|
||||
|
||||
Reference in New Issue
Block a user