fix: _get_strategy_trade_stats 兼容旧数据(strategy文本)和新数据(strategy_id),修复open_positions计算(含tp1_hit),current_balance实时计算
This commit is contained in:
parent
d3784aaf79
commit
06f900b89b
@ -2456,22 +2456,39 @@ def _strategy_row_to_detail(row: dict) -> dict:
|
|||||||
|
|
||||||
|
|
||||||
async def _get_strategy_trade_stats(strategy_id: str) -> 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.
|
||||||
rows = await async_fetch(
|
兼容新数据(strategy_id列)和旧数据(strategy文本列)。
|
||||||
"""SELECT status, pnl_r, tp1_hit, entry_ts, exit_ts
|
"""
|
||||||
FROM paper_trades
|
# 固定 UUID → legacy strategy文本名映射(迁移时写死的三条策略)
|
||||||
WHERE strategy_id=$1 AND status != 'active'
|
LEGACY_NAME_MAP = {
|
||||||
ORDER BY entry_ts DESC""",
|
"00000000-0000-0000-0000-000000000053": "v53",
|
||||||
strategy_id
|
"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 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:
|
if not rows:
|
||||||
return {
|
# 即使没有历史记录也要查持仓
|
||||||
"trade_count": 0, "win_rate": 0.0,
|
pass
|
||||||
"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,
|
|
||||||
}
|
|
||||||
|
|
||||||
total = len(rows)
|
total = len(rows)
|
||||||
wins = [r for r in rows if (r["pnl_r"] or 0) > 0]
|
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_r_24h = round(sum(r["pnl_r"] or 0 for r in rows_24h), 3)
|
||||||
pnl_usdt_24h = round(pnl_r_24h * 200, 2)
|
pnl_usdt_24h = round(pnl_r_24h * 200, 2)
|
||||||
|
|
||||||
# Open positions
|
# Open positions — status IN ('active','tp1_hit'),同时兼容新旧记录
|
||||||
open_rows = await async_fetch(
|
if legacy_name:
|
||||||
"SELECT COUNT(*) as cnt FROM paper_trades WHERE strategy_id=$1 AND status='active'",
|
open_rows = await async_fetch(
|
||||||
strategy_id
|
"""SELECT COUNT(*) as cnt FROM paper_trades
|
||||||
)
|
WHERE status IN ('active','tp1_hit')
|
||||||
open_positions = open_rows[0]["cnt"] if open_rows else 0
|
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 = int(open_rows[0]["cnt"]) if open_rows else 0
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"trade_count": total,
|
"trade_count": total,
|
||||||
@ -2503,6 +2529,8 @@ async def _get_strategy_trade_stats(strategy_id: str) -> dict:
|
|||||||
"pnl_usdt_24h": pnl_usdt_24h,
|
"pnl_usdt_24h": pnl_usdt_24h,
|
||||||
"pnl_r_24h": pnl_r_24h,
|
"pnl_r_24h": pnl_r_24h,
|
||||||
"last_trade_at": last_trade_at,
|
"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))
|
d = _strategy_row_to_card(dict(row))
|
||||||
stats = await _get_strategy_trade_stats(str(row["strategy_id"]))
|
stats = await _get_strategy_trade_stats(str(row["strategy_id"]))
|
||||||
d.update(stats)
|
d.update(stats)
|
||||||
|
# 用实时计算的 net_usdt 覆盖 DB 静态的 current_balance
|
||||||
|
d["current_balance"] = round(row["initial_balance"] + d["net_usdt"], 2)
|
||||||
result.append(d)
|
result.append(d)
|
||||||
return {"strategies": result}
|
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)
|
detail = _strategy_row_to_detail(row)
|
||||||
stats = await _get_strategy_trade_stats(sid)
|
stats = await _get_strategy_trade_stats(sid)
|
||||||
detail.update(stats)
|
detail.update(stats)
|
||||||
|
detail["current_balance"] = round(row["initial_balance"] + detail["net_usdt"], 2)
|
||||||
return {"strategy": detail}
|
return {"strategy": detail}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user