博弈分析按合约分类展示,新增合约下拉选择器

This commit is contained in:
2026-07-24 22:58:44 +08:00
parent de62f0779b
commit 492ca9d82e
5 changed files with 66 additions and 29 deletions
+39 -16
View File
@@ -2,7 +2,7 @@ from fastapi import APIRouter, Depends, Request
from fastapi.responses import HTMLResponse
from sqlalchemy.orm import Session
from app.database import get_db
from app.models import PositionSnapshot
from app.models import PositionSnapshot, Contract, DailyBar
from app.engine.game_theory import net_position, net_pnl, format_pnl
router = APIRouter(prefix="/analysis", tags=["analysis"])
@@ -12,8 +12,28 @@ INSTITUTIONS = ["中信期货", "高盛期货", "国泰君安期货", "华泰期
@router.get("/", response_class=HTMLResponse)
def analysis_page(request: Request, db: Session = Depends(get_db)):
# Get active contracts for selector
active_contracts = (
db.query(Contract.code)
.filter(Contract.is_active == True)
.order_by(Contract.code)
.all()
)
contract_list = [c[0] for c in active_contracts]
# Default to first contract, or use query param
selected = request.query_params.get("contract", contract_list[0] if contract_list else None)
if not selected:
template = request.app.state.templates.get_template("analysis.html")
return HTMLResponse(
template.render(request=request, active_nav="analysis", rows=[], latest_date=None)
)
# Get latest date for selected contract
latest_snap = (
db.query(PositionSnapshot.date)
.filter(PositionSnapshot.contract_code == selected)
.order_by(PositionSnapshot.date.desc())
.first()
)
@@ -21,14 +41,24 @@ def analysis_page(request: Request, db: Session = Depends(get_db)):
if not latest_snap:
template = request.app.state.templates.get_template("analysis.html")
return HTMLResponse(
template.render(request=request, active_nav="analysis", rows=[], latest_date=None)
template.render(
request=request, active_nav="analysis",
rows=[], latest_date=None, contracts=contract_list, selected=selected,
)
)
latest_date = latest_snap[0]
current_price = 913 # TODO: fetch from daily_bars or akshare
# Get latest close for current_price reference
latest_bar = (
db.query(DailyBar)
.filter(DailyBar.contract == selected)
.order_by(DailyBar.date.desc())
.first()
)
current_price = int(latest_bar.close) if latest_bar else 0
rows = []
totals = {"long_pos": 0, "short_pos": 0, "net_pos": 0, "pnl": 0.0}
total_net_short = 0
pnl_sum = 0.0
@@ -36,6 +66,7 @@ def analysis_page(request: Request, db: Session = Depends(get_db)):
long = (
db.query(PositionSnapshot)
.filter(
PositionSnapshot.contract_code == selected,
PositionSnapshot.institution == inst,
PositionSnapshot.direction == "long",
PositionSnapshot.date == latest_date,
@@ -45,6 +76,7 @@ def analysis_page(request: Request, db: Session = Depends(get_db)):
short = (
db.query(PositionSnapshot)
.filter(
PositionSnapshot.contract_code == selected,
PositionSnapshot.institution == inst,
PositionSnapshot.direction == "short",
PositionSnapshot.date == latest_date,
@@ -64,19 +96,14 @@ def analysis_page(request: Request, db: Session = Depends(get_db)):
elif np > 0:
pnl = net_pnl(np, long_cost, current_price)
totals["long_pos"] += long_pos
totals["short_pos"] += short_pos
totals["net_pos"] += np
pnl_sum += pnl
if np < 0:
total_net_short += abs(np)
pnl_sum += pnl
rows.append({
"institution": inst,
"long_pos": f"{long_pos / 10000:.1f}" if long_pos else "",
"short_pos": f"{short_pos / 10000:.1f}" if short_pos else "",
"long_cost": f"{long_cost:.2f}" if long_cost else "",
"short_cost": f"{short_cost:.2f}" if short_cost else "",
"net_pos": f"{'' if np > 0 else ''} {abs(np) / 10000:.1f}",
"pnl": format_pnl(pnl),
"pnl_raw": pnl,
@@ -88,15 +115,11 @@ def analysis_page(request: Request, db: Session = Depends(get_db)):
request=request,
active_nav="analysis",
rows=rows,
totals={
"long_pos": f"{totals['long_pos'] / 10000:.1f}",
"short_pos": f"{totals['short_pos'] / 10000:.1f}",
"net_pos": f"{'' if totals['net_pos'] > 0 else ''} {abs(totals['net_pos']) / 10000:.1f}",
"pnl": format_pnl(pnl_sum),
},
latest_date=latest_date.strftime("%Y-%m-%d"),
current_price=current_price,
total_net_short=f"{total_net_short / 10000:.1f}",
total_pnl=format_pnl(pnl_sum),
contracts=contract_list,
selected=selected,
)
)