跳到主要内容

账户绩效汇总

按一组固定的时间窗口分桶返回用户的交易绩效。供账户仪表盘的综合绩效明细表格渲染 Today / Yesterday / Last 7d / Last 30d / This Year / All Time 各行。

GET /account/performance-summary
Authorization: Bearer <token>

请求参数

名称类型必需说明
symbolstring过滤到单个市场(如 BTC-USDT)。缺省时聚合全部市场。

没有日期参数:桶集合固定,由服务端按 UTC 解析。

分桶

所有桶边界均为 UTC。设 today_start = 当日 UTC 零点

bucket窗口(起点含,终点不含)
today[today_start, now)
yesterday[today_start − 1d, today_start)
week[today_start − 7d, now)
month[today_start − 30d, now)
year[当年 1 月 1 日 UTC, now)
all(−∞, now)

桶之间的重叠是有意为之:today 包含在 week 内,week 包含在 month 内,依此类推。每一行都独立地从底层表计算。

响应

{
"symbol": null,
"buckets": [
{
"bucket": "today",
"start_ts": 1778716800,
"end_ts": 1778740012,
"volume": "12500.00",
"trade_count": 18,
"realized_pnl": "42.10",
"unrealized_pnl": "-3.25",
"start_unrealized_pnl": "-3.25",
"pnl": "42.10",
"wins": 7,
"losses": 4,
"win_rate": "63.64",
"used_capital": "850.00",
"pnl_bps": 495
},
{ "bucket": "yesterday", "...": "..." },
{ "bucket": "week", "...": "..." },
{ "bucket": "month", "...": "..." },
{ "bucket": "year", "...": "..." },
{ "bucket": "all", "...": "..." }
]
}

buckets 始终是按上述顺序排列的 6 元素数组。没有任何活动的桶,其所有数值字段为 0win_rate0pnl_bps0

响应字段

顶层

字段类型说明
symbolstring | null回显 symbol 请求参数。
bucketsPerformanceBucket[]始终 6 个条目,顺序为:todayyesterdayweekmonthyearall

PerformanceBucket

字段类型说明
bucketstringtodayyesterdayweekmonthyearall 之一。
start_tsint64桶起点,UTC Unix 秒级时间戳。对 all,下界为 unix 纪元(0)。
end_tsint64桶终点,UTC Unix 秒级时间戳,不含。对开放端点的桶(todayweekmonthyearall)等于 "now"。
volumeDecimal[start_ts, end_ts) 内用户为 maker 或 taker 的 trades 上的 SUM(price × amount)
trade_countint64上述 trades 行数。
realized_pnlDecimal[start_ts, end_ts) 内的 SUM(realized_pnl_events.realized_pnl)
unrealized_pnlDecimal用户当前未平仓位按最新标记价格估值的浮动盈亏。与桶窗口无关;逐行提供仅为方便。
start_unrealized_pnlDecimal预期语义:用户带入 start_ts 时刻的浮动盈亏。v1 实际行为:除 all 外的每个桶,该值就是用户当前未平仓位按当前标记价格计算的未实现盈亏 —— 与 unrealized_pnl 字段完全相同,与 start_ts 时刻的持仓无关。对 all 恒为 0。见 v1 简化
pnlDecimalrealized_pnl + unrealized_pnl − start_unrealized_pnl。即表格中展示的"区间 PnL"。由于 v1 的 start_unrealized_pnl 行为,除 all 外的每个桶该值退化为 realized_pnlall 桶为 realized_pnl + unrealized_pnl)。
winsint64窗口内 realized_pnl > 0realized_pnl_events 行数。
lossesint64窗口内 realized_pnl ≤ 0realized_pnl_events 行数。
win_rateDecimalwins / (wins + losses) × 100。窗口内没有平仓时为 0
used_capitalDecimal窗口内使用的资金(USD)。见 used_capital 语义
pnl_bpsint64pnl / used_capital × 10000,四舍五入为整数基点。used_capital0 时为 0

used_capital 语义

预期定义是*"桶内观测到的 [未平仓抵押 + 未结算 PnL] 峰值"*,与目前 Subsquid 支撑的仪表盘渲染该列的口径一致。

v1 实现返回一个简化值:

used_capital = max(
sum_open_position_collateral_at_end_of_bucket
- realized_pnl_in_bucket
+ start_unrealized_pnl,
0
)

它由请求时刻已有的数据算得(当前未平仓位、该桶的已实现 PnL、该桶的期初未实现 PnL)。它不是桶内峰值;当仓位在桶中段大于桶末时,可能低估真实的资金占用。

用户没有未平仓位且桶内已实现 PnL 持平时,used_capital 可能为 0,此时 pnl_bps 也为 0

v1 简化

以下是明确的 v1 取舍,后续会在不改变响应结构的前提下收紧:

  • start_unrealized_pnl 完全考察 start_ts 时刻的持仓。v1 实现计算的是当前所有未平仓位按当前标记价格的未实现盈亏,并把这同一个值用作除 all 外每个桶的 start_unrealized_pnlall0)。后果:对 today/yesterday/week/month/year 各行,pnl = realized_pnl + unrealized_pnl − start_unrealized_pnl 抵消为纯 realized_pnl —— 未实现盈亏实际上只影响 all 行。这是已知的 v1 局限;忠实的"期初带入 PnL"需要一张历史 open_positions_snapshot 表,目前尚不存在。
  • used_capital 是时点值(桶末)而非桶内峰值;见上文。
  • 窗口内的 max_capital 属于本端点。若峰值抵押数据可用,将以新增字段的方式加入,不改动现有字段。

这些简化对 month/year/all 各行的影响大于 today/yesterday/week。客户端应把简化后的行当作方向性指标,而非精确审计。

错误

HTTPcode场景
500PERFORMANCE_SUMMARY_FAILED聚合六个桶中任一时数据库出错。

错误响应体:

{ "error": "...", "code": "..." }

注意事项

  • 所有金额均以十进制字符串返回。
  • v1 中响应在服务端不做缓存。调用方应自行限频(仪表盘每 60 秒轮询一次)。
  • 端点先通过 tokio::try_join! 计算两个与窗口无关的聚合值(当前未实现 PnL、未平仓抵押),再以派生任务并发执行各桶的聚合查询(tokio::spawn,每桶两个)。市场或用户增多不会成倍增加往返次数。