2065122777
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
118 lines
3.4 KiB
Python
118 lines
3.4 KiB
Python
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 Round, Position, Contract
|
|
|
|
router = APIRouter(prefix="/positions", tags=["positions"])
|
|
|
|
|
|
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]
|
|
|
|
|
|
@router.get("/", response_class=HTMLResponse)
|
|
def positions_page(request: Request, db: Session = Depends(get_db)):
|
|
active_round = (
|
|
db.query(Round)
|
|
.filter(Round.status == "active")
|
|
.order_by(Round.started_at.desc())
|
|
.first()
|
|
)
|
|
|
|
template = request.app.state.templates.get_template("positions.html")
|
|
return HTMLResponse(
|
|
template.render(
|
|
request=request,
|
|
active_nav="positions",
|
|
contracts=get_active_contracts(db),
|
|
active_round=active_round,
|
|
)
|
|
)
|
|
|
|
|
|
@router.post("/round")
|
|
def create_round(
|
|
request: Request,
|
|
contract_code: str = Form(...),
|
|
daily_hands: int = Form(1),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
existing = db.query(Round).filter(Round.status == "active").first()
|
|
if existing:
|
|
return RedirectResponse("/positions/?error=已有活跃轮次", status_code=303)
|
|
|
|
r = Round(
|
|
contract_code=contract_code.upper(),
|
|
daily_hands=daily_hands,
|
|
status="active",
|
|
started_at=date.today(),
|
|
)
|
|
db.add(r)
|
|
db.commit()
|
|
return RedirectResponse("/positions/", status_code=303)
|
|
|
|
|
|
@router.post("/add")
|
|
def add_position(
|
|
request: Request,
|
|
open_price: int = Form(...),
|
|
amp_threshold: int = Form(...),
|
|
hands: int = Form(1),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
active_round = db.query(Round).filter(Round.status == "active").first()
|
|
if not active_round:
|
|
return RedirectResponse("/positions/?error=无活跃轮次", status_code=303)
|
|
|
|
lock_price = open_price + amp_threshold
|
|
p = Position(
|
|
round_id=active_round.id,
|
|
open_price=open_price,
|
|
amp_threshold=amp_threshold,
|
|
lock_price=lock_price,
|
|
hands=hands,
|
|
opened_at=date.today(),
|
|
)
|
|
db.add(p)
|
|
db.commit()
|
|
return RedirectResponse("/positions/", status_code=303)
|
|
|
|
|
|
@router.post("/{position_id}/lock")
|
|
def lock_position(position_id: int, db: Session = Depends(get_db)):
|
|
p = db.query(Position).filter(Position.id == position_id).first()
|
|
if p and p.locked_count < p.hands:
|
|
p.locked_count += 1
|
|
db.commit()
|
|
return RedirectResponse("/positions/", status_code=303)
|
|
|
|
|
|
@router.post("/{position_id}/unlock")
|
|
def unlock_position(position_id: int, db: Session = Depends(get_db)):
|
|
p = db.query(Position).filter(Position.id == position_id).first()
|
|
if p and p.locked_count > 0:
|
|
p.locked_count -= 1
|
|
db.commit()
|
|
return RedirectResponse("/positions/", status_code=303)
|
|
|
|
|
|
@router.post("/close")
|
|
def close_round(
|
|
request: Request,
|
|
result: str = Form(...),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
active_round = db.query(Round).filter(Round.status == "active").first()
|
|
if active_round:
|
|
active_round.status = result
|
|
db.commit()
|
|
return RedirectResponse("/positions/", status_code=303)
|