from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from typing import List, Optional from datetime import datetime, timedelta from decimal import Decimal from app.core.database import get_db from app.models.models import TradeHistory from pydantic import BaseModel router = APIRouter() class TradeHistoryResponse(BaseModel): id: int rule_id: Optional[int] stock_code: str stock_name: Optional[str] order_type: str order_price: Optional[Decimal] order_quantity: int executed_price: Optional[Decimal] executed_quantity: Optional[int] status: str order_id: Optional[str] message: Optional[str] created_at: datetime executed_at: Optional[datetime] class Config: from_attributes = True @router.get("", response_model=List[TradeHistoryResponse]) async def get_trade_history( skip: int = 0, limit: int = 100, stock_code: Optional[str] = None, status: Optional[str] = None, order_type: Optional[str] = None, days: int = 30, db: AsyncSession = Depends(get_db) ): """거래 이력 조회""" query = select(TradeHistory) # 날짜 필터 since_date = datetime.utcnow() - timedelta(days=days) query = query.where(TradeHistory.created_at >= since_date) # 종목 코드 필터 if stock_code: query = query.where(TradeHistory.stock_code == stock_code) # 상태 필터 if status: query = query.where(TradeHistory.status == status) # 주문 유형 필터 if order_type: query = query.where(TradeHistory.order_type == order_type) query = query.order_by(TradeHistory.created_at.desc()) query = query.offset(skip).limit(limit) result = await db.execute(query) trades = result.scalars().all() return trades @router.get("/{trade_id}", response_model=TradeHistoryResponse) async def get_trade(trade_id: int, db: AsyncSession = Depends(get_db)): """특정 거래 조회""" result = await db.execute(select(TradeHistory).where(TradeHistory.id == trade_id)) trade = result.scalar_one_or_none() if not trade: raise HTTPException(status_code=404, detail="Trade not found") return trade @router.get("/stats/summary") async def get_trade_stats( days: int = 30, db: AsyncSession = Depends(get_db) ): """거래 통계 조회""" since_date = datetime.utcnow() - timedelta(days=days) result = await db.execute( select(TradeHistory).where(TradeHistory.created_at >= since_date) ) trades = result.scalars().all() total_trades = len(trades) buy_trades = len([t for t in trades if t.order_type == "BUY"]) sell_trades = len([t for t in trades if t.order_type == "SELL"]) executed_trades = len([t for t in trades if t.status == "EXECUTED"]) failed_trades = len([t for t in trades if t.status == "FAILED"]) # 총 거래 금액 계산 total_amount = sum( float(t.executed_price or 0) * (t.executed_quantity or 0) for t in trades if t.status == "EXECUTED" ) return { "period_days": days, "total_trades": total_trades, "buy_trades": buy_trades, "sell_trades": sell_trades, "executed_trades": executed_trades, "failed_trades": failed_trades, "success_rate": executed_trades / total_trades if total_trades > 0 else 0, "total_amount": total_amount }