fix: _get_strategy_trade_stats 兼容旧数据(strategy文本)和新数据(strategy_id),修复open_positions计算(含tp1_hit),current_balance实时计算

This commit is contained in:
root 2026-03-11 16:02:04 +00:00
parent d3784aaf79
commit 06f900b89b

View File

@ -2456,22 +2456,39 @@ def _strategy_row_to_detail(row: dict) -> dict:
async def _get_strategy_trade_stats(strategy_id: str) -> dict:
"""Fetch trade statistics for a strategy by strategy_id"""
"""Fetch trade statistics for a strategy by strategy_id.
兼容新数据strategy_id列和旧数据strategy文本列
"""
# 固定 UUID → legacy strategy文本名映射迁移时写死的三条策略
LEGACY_NAME_MAP = {
"00000000-0000-0000-0000-000000000053": "v53",
"00000000-0000-0000-0000-000000000054": "v53_middle",
"00000000-0000-0000-0000-000000000055": "v53_fast",
}
legacy_name = LEGACY_NAME_MAP.get(strategy_id)
# 查已关闭的交易记录(同时兼容新旧两种匹配方式)
if legacy_name:
rows = await async_fetch(
"""SELECT status, pnl_r, tp1_hit, entry_ts, exit_ts
FROM paper_trades
WHERE strategy_id=$1 AND status != 'active'
WHERE status NOT IN ('active', 'tp1_hit')
AND (strategy_id=$1 OR (strategy_id IS NULL AND strategy=$2))
ORDER BY entry_ts DESC""",
strategy_id, legacy_name
)
else:
rows = await async_fetch(
"""SELECT status, pnl_r, tp1_hit, entry_ts, exit_ts
FROM paper_trades
WHERE strategy_id=$1 AND status NOT IN ('active', 'tp1_hit')
ORDER BY entry_ts DESC""",
strategy_id
)
if not rows:
return {
"trade_count": 0, "win_rate": 0.0,
"avg_win_r": 0.0, "avg_loss_r": 0.0,
"open_positions": 0,
"pnl_usdt_24h": 0.0, "pnl_r_24h": 0.0,
"last_trade_at": None,
}
# 即使没有历史记录也要查持仓
pass
total = len(rows)
wins = [r for r in rows if (r["pnl_r"] or 0) > 0]
@ -2487,12 +2504,21 @@ async def _get_strategy_trade_stats(strategy_id: str) -> dict:
pnl_r_24h = round(sum(r["pnl_r"] or 0 for r in rows_24h), 3)
pnl_usdt_24h = round(pnl_r_24h * 200, 2)
# Open positions
# Open positions — status IN ('active','tp1_hit'),同时兼容新旧记录
if legacy_name:
open_rows = await async_fetch(
"SELECT COUNT(*) as cnt FROM paper_trades WHERE strategy_id=$1 AND status='active'",
"""SELECT COUNT(*) as cnt FROM paper_trades
WHERE status IN ('active','tp1_hit')
AND (strategy_id=$1 OR (strategy_id IS NULL AND strategy=$2))""",
strategy_id, legacy_name
)
else:
open_rows = await async_fetch(
"""SELECT COUNT(*) as cnt FROM paper_trades
WHERE strategy_id=$1 AND status IN ('active','tp1_hit')""",
strategy_id
)
open_positions = open_rows[0]["cnt"] if open_rows else 0
open_positions = int(open_rows[0]["cnt"]) if open_rows else 0
return {
"trade_count": total,
@ -2503,6 +2529,8 @@ async def _get_strategy_trade_stats(strategy_id: str) -> dict:
"pnl_usdt_24h": pnl_usdt_24h,
"pnl_r_24h": pnl_r_24h,
"last_trade_at": last_trade_at,
"net_r": round(sum(r["pnl_r"] or 0 for r in rows), 3),
"net_usdt": round(sum(r["pnl_r"] or 0 for r in rows) * 200, 2),
}
@ -2569,6 +2597,8 @@ async def list_strategies(
d = _strategy_row_to_card(dict(row))
stats = await _get_strategy_trade_stats(str(row["strategy_id"]))
d.update(stats)
# 用实时计算的 net_usdt 覆盖 DB 静态的 current_balance
d["current_balance"] = round(row["initial_balance"] + d["net_usdt"], 2)
result.append(d)
return {"strategies": result}
@ -2580,6 +2610,7 @@ async def get_strategy(sid: str, user: dict = Depends(get_current_user)):
detail = _strategy_row_to_detail(row)
stats = await _get_strategy_trade_stats(sid)
detail.update(stats)
detail["current_balance"] = round(row["initial_balance"] + detail["net_usdt"], 2)
return {"strategy": detail}