from datetime import date from fastapi import APIRouter, Depends, Form, Request from fastapi.responses import HTMLResponse, RedirectResponse from sqlalchemy.orm import Session from app.database import get_db from app.models import Trade, Product, Contract router = APIRouter(prefix="/trades", tags=["trades"]) DIRECTIONS = [("short", "空"), ("long", "多")] def get_active_contracts(db: Session) -> list[str]: contracts = ( db.query(Contract.code) .filter(Contract.is_active == True) .order_by(Contract.code) .all() ) return [c[0] for c in contracts] def get_products(db: Session) -> list[str]: products = db.query(Product.code).order_by(Product.code).all() return [p[0] for p in products] def today_str() -> str: return date.today().isoformat() @router.get("/", response_class=HTMLResponse) def trades_page(request: Request, db: Session = Depends(get_db)): open_trades = ( db.query(Trade).filter(Trade.status == "open") .order_by(Trade.open_date.desc()).all() ) closed_trades = ( db.query(Trade).filter(Trade.status == "closed") .order_by(Trade.close_date.desc()).limit(50).all() ) template = request.app.state.templates.get_template("trades.html") return HTMLResponse( template.render( request=request, active_nav="trades", contracts=get_active_contracts(db), products=get_products(db), directions=DIRECTIONS, open_trades=open_trades, closed_trades=closed_trades, today=today_str(), ) ) @router.post("/open") def open_trade( request: Request, product_code: str = Form(...), contract_code: str = Form(...), direction: str = Form(...), open_date: str = Form(...), open_price: float = Form(...), open_fee: float = Form(0.0), db: Session = Depends(get_db), ): t = Trade( product_code=product_code.upper(), contract_code=contract_code.upper(), direction=direction, open_date=date.fromisoformat(open_date), open_price=open_price, open_fee=open_fee, status="open", ) db.add(t) db.commit() return RedirectResponse("/trades/", status_code=303) @router.post("/{trade_id}/close") def close_trade( request: Request, trade_id: int, close_date: str = Form(...), close_price: float = Form(...), close_fee: float = Form(0.0), db: Session = Depends(get_db), ): t = db.query(Trade).filter(Trade.id == trade_id).first() if t and t.status == "open": t.close_date = date.fromisoformat(close_date) t.close_price = close_price t.close_fee = close_fee t.status = "closed" db.commit() return RedirectResponse("/trades/", status_code=303) @router.post("/{trade_id}/delete") def delete_trade(trade_id: int, db: Session = Depends(get_db)): t = db.query(Trade).filter(Trade.id == trade_id).first() if t: db.delete(t) db.commit() return RedirectResponse("/trades/", status_code=303)