Add trade stats board: win rate, hold buckets, by machine/side.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-17 22:31:17 +08:00
parent 6b705a60ca
commit ae1b91fcc5
5 changed files with 375 additions and 7 deletions
+26 -5
View File
@@ -621,21 +621,26 @@ def register_routes(app: Flask) -> None:
bars = database.get_bars(conn, symbol, timeframe, start_ts, end_ts)
return jsonify({"ok": True, "bars": bars})
def _resolve_machine_filter(u: dict, machine_raw: str):
machine_id = int(machine_raw) if machine_raw.isdigit() else None
with database.get_db() as conn:
machines = database.list_machines_for_user(conn, u)
allowed_ids = {int(m["id"]) for m in machines}
if machine_id is not None and machine_id not in allowed_ids:
machine_id = None
return machines, machine_id
@app.get("/records")
@login_required
def records_page():
u = current_user()
machine_raw = (request.args.get("machine_id") or "").strip()
machine_id = int(machine_raw) if machine_raw.isdigit() else None
page_raw = (request.args.get("page") or "1").strip()
page = int(page_raw) if page_raw.isdigit() and int(page_raw) >= 1 else 1
per_page = 10
account_id = None if u["role"] == "admin" else u.get("account_id")
machines, machine_id = _resolve_machine_filter(u, machine_raw)
with database.get_db() as conn:
machines = database.list_machines_for_user(conn, u)
allowed_ids = {int(m["id"]) for m in machines}
if machine_id is not None and machine_id not in allowed_ids:
machine_id = None
total = database.count_trades(conn, account_id=account_id, machine_id=machine_id)
total_pages = max(1, (total + per_page - 1) // per_page)
if page > total_pages:
@@ -661,6 +666,22 @@ def register_routes(app: Flask) -> None:
total_pages=total_pages,
)
@app.get("/records/stats")
@login_required
def records_stats_page():
u = current_user()
machine_raw = (request.args.get("machine_id") or "").strip()
account_id = None if u["role"] == "admin" else u.get("account_id")
machines, machine_id = _resolve_machine_filter(u, machine_raw)
with database.get_db() as conn:
stats = database.trade_stats(conn, account_id=account_id, machine_id=machine_id)
return render_template(
"records_stats.html",
stats=stats,
machines=machines,
selected_machine_id=machine_id,
)
@app.get("/records/<int:tid>")
@login_required
def record_detail(tid: int):