资产组合与账户状态
跨 SDK 和 CLI 的汇总账户状态、可提现余额、费率表、增强仓位字段以及资产组合时间序列。
资产组合端点回答关于账户的四个问题:它现在值多少、可以提现多少、被收取多少费用,以及它随时间的表现如何。它们是一小组需要认证的 REST 端点,外加增强的逐仓位风险字段。每个接口(Rust、TypeScript 和 Python SDK 以及 CLI)访问的都是网关上的同一组路由,详见 API 与速率限制。
如果您正在构建资产组合视图,请在渲染任何内容之前先阅读安全读取这些值。有几个字段有意设计为可空,有一个符号约定很容易弄反,而一个简单的两次调用实现在生产环境中会遇到竞态条件。
获取方式
npm install @nexus-xyz/exchange-ts # TypeScript
cargo add nexus-exchange # Rust
pip install nexus-exchange # PythonCLI 通过 nexus-exchange-cli 的发布版本分发。全部客户端请参见SDK 与工具。
身份验证
本页的每个路由都限定在账户范围内,并且需要 HMAC API 密钥。没有公开或无需认证的版本。请求需携带 X-API-Key、X-Timestamp 和 X-Signature,并且时间戳必须与服务器时间相差不超过30秒。SDK 和 CLI 会替您签名。完整流程以及可运行的 cURL 示例请参见快速入门。
请不要把 API secret 写进源代码或留在 shell 历史中。它只在创建时显示一次,之后无法再次获取。下面的示例从环境变量中读取它。
选择网络
交易所目前运行在 Nexus Testnet 上,主网随后推出。请在构造客户端时选择网络。各接口如何选择网络以及 API 密钥如何绑定到网络,请参见网络;当前的基础 URL 请参见 API 与速率限制。这些路由所需的 HMAC 密钥仅限于创建它的网络。
参考
GET
/account/state
HMAC
资产组合摘要以及所有未平仓仓位,来自同一次一致的读取
GET
/account/summary
HMAC
仅资产组合摘要,与 /account/state 中内嵌的对象相同
GET
/account/fees
HMAC
账户的实际费率表
GET
/account/portfolio-history?window=&limit=
HMAC
权益、累计盈亏和累计成交额的时间序列
各 SDK 的入口:
Rust
fetch_account_state()
fetch_account_fees()
fetch_portfolio_history(window, limit)
Python
fetch_account_state()
fetch_account_fees()
fetch_portfolio_history(window, limit)
TypeScript
getAccountState()
getAccountFees()
getPortfolioHistory({ window, limit })
CLI
nexus account state
nexus account fees
nexus account portfolio-history --window --limit
汇总账户状态
GET /account/state 返回资产组合汇总数据以及所有未平仓仓位,二者都来自服务器端的同一次读取。由于两部分来自同一个快照,summary.open_positions_count 始终等于 positions 的长度。
摘要包含 collateral、total_equity、total_unrealized_pnl、total_realized_pnl_24h、total_volume_24h、open_positions_count、open_orders_count、margin_used、available_margin 和 withdrawable。
withdrawable 是可以转出账户的余额:以引擎为准的可用保证金,下限为零,即 max(0, available_margin)。可用保证金已经从权益中扣除了每个仓位的初始保证金和每笔下单前的订单保证金占用,因此这就是提现可以动用的金额。它不是 total_equity,也不是 collateral。资不抵债的账户会被截断为 "0",永远不会报告为负数。该值来自权威的保证金视图,因此当该视图不可用时,端点会以 502 故障关闭,而不是返回一个本地估算的数字。
费率表
GET /account/fees 报告交易所当前向该账户收取的费用。这是面向未来的费率表费率,而不是过去成交的实际平均费率。
maker_fee_bps
顶层费率,以基点表示。可以为负;当 schedule=unknown 时,零是哨兵值
taker_fee_bps
顶层费率,以基点表示;当 schedule=unknown 时,零是哨兵值
tier
目前始终为 base;尚无按账户划分的等级
schedule
per_market、reference 或 unknown;请按开放字符串处理
markets
保留的成交缓冲区内各市场的费率;按 market_id 排序
volume_30d
滚动30天的成交名义价值,十进制字符串。尽力而为,参见下面的标志
volume_30d_estimated
当 volume_30d 可能少计(源成交缓冲区已满)时为 true
discounts
生效中的折扣。目前始终为空
当 schedule 为 per_market 时,请以返回的 markets 行作为权威费率。顶层的那一对费率只是它们确定性的众数摘要。有上限的内存成交缓冲区可能会重置或淘汰旧市场,因此某一行缺失并不能证明该账户从未交易过该市场。reference 表示保留的缓冲区中没有任何市场带有镜像的费率表,此时顶层的那一对费率是所有已镜像交易所市场中确定性的众数费率。两种众数计算都以出现次数最多的那一对为准,出现平局时取字典序最小的 (maker_fee_bps, taker_fee_bps) 组合。unknown 表示市场参数不可用。此时 markets 为空,两个顶层基点值都是零哨兵值,并不代表免手续费。目前不存在按账户划分的等级或折扣计划。请把 schedule 视为开放取值,也不要针对并不存在的折扣结构编写分支。
资产组合时间序列
GET /account/portfolio-history 返回某个窗口内的权益、累计交易盈亏和累计成交名义价值,并在服务器端降采样。数据点按时间从旧到新排列。
window
间隔
最大数据点数
跨度
day
5分钟
288
24小时
week
1小时
168
7天
month
6小时
120
30天
all
1天
366
约1年
省略 window 时默认为 day。不在该集合中的值会以 400(invalid_window)被拒绝。如果该参数重复出现,则使用第一个值。limit 必须在 1 到 366 之间。在此范围内,它会缩小结果,并被截断到窗口的容量,而不是被拒绝,因此请求 day 的366个数据点会返回288个,而不是报错。超出该范围时,请求会以 400 被拒绝。
响应会回显实际提供的 window 和 cadence_ms。请读取回显的值,而不要假定就是您发送的值,这样您的图表坐标轴使用的才是实际提供的值。
每个数据点都包含 timestamp_ms、equity、pnl 和 volume。pnl 和 volume 是截至该采样点的累计值,而不是每个区间的值。如果要绘制每个区间的活动,请自行计算相邻数据点之差。
增强仓位字段
/account/state(以及 /positions)返回的仓位,除了 symbol、side、size、entryPrice、unrealizedPnl 和 realizedPnl 之外,还带有逐仓位的风险详情:
notional
abs(size) × mark price
initialMargin
按全仓保证金模型为该仓位占用的初始保证金
roe
初始保证金回报率:unrealizedPnl / initialMargin
max_leverage
该市场允许的最大杠杆,来自其风险参数
leverage
该账户在此仓位上的杠杆倍数
funding_paid
该仓位的累计资金费。符号约定见下文
这些名称采用 CCXT 的统一词汇,因此 ccxt.nexus() 客户端可以直接读取这一结构。CCXT 中没有对应项的字段保留交易所自己的写法:size、roe、max_leverage、funding_paid。GET /account 不是这种结构。它由撮合引擎转发,返回的是一个范围更窄、使用引擎自有命名的对象。
服务器在低延迟读取路径上计算这些字段,而不是往返撮合引擎,从而保持端点的速度。代价是,当某个输入在该路径上不可用时,该字段为 null,并由配套的 <field>_error 给出机器可读的原因,而不是编造一个数字。
leverage 目前始终为 null,并且 leverage_error 被设为 margin_state_not_mirrored。推导它需要账户的杠杆设置或其分配的保证金,而这两者在读取路径上都不可用。不要根据 initialMargin 反推它。那个表达式会简化为 1 / initial_margin_rate,这是一个按市场设定的常数,而不是仓位的真实杠杆,因此对该市场中的每个仓位都是错误的。
funding_paid 以支付为正。 正值表示该仓位支付了资金费,负值表示它收取了资金费。该字段始终存在,在产生任何资金费之前为 "0",并受交易所保留的资金费历史限制。把这个符号弄反,会在盈亏界面上把成本变成收入,所以请为它编写测试。
安全读取这些值
金额是十进制字符串,而不是数字。equity、pnl、volume、withdrawable、notional 等都是以字符串序列化的任意精度十进制数,从而保证无损。请使用十进制类型解析它们。如果经过浮点数(parseFloat、float()、as f64)转换,就会重新引入字符串编码本来要避免的舍入误差。杠杆字段(leverage、max_leverage)则是真正的 JSON 数字。
派生字段有三种状态,而不是两种。五个计算得出的仓位字段(notional、initialMargin、roe、leverage 和 max_leverage)中的每一个都可能是:
一个值:已计算且具有权威性;
null:已报告但无法计算,配套的<field>_error会说明原因;缺失:服务器版本早于该字段。
把其中任何一种情况折算成 0 都是在捏造数据。当用户询问其仓位价值多少时,“未报告”、“无法计算”和“零”是三种不同的答案,而其中只有一种是数字。请把缺失的情况显示为明确的空缺(CLI 会打印 -),并在有 <field>_error 时将其展示出来。withdrawable 也是如此。它在 Schema 中是可选的,因此较旧的部署可能省略它;如果将其默认为 "0",就等于告诉用户他们没有任何可用余额,而服务器实际上从未报告过该值。
恰好只有这五个字段带有配套的 <field>_error。funding_paid 不在其中。它始终存在,因此没有可供分支判断的 funding_paid_error。
优先使用 /account/state,而不是两次调用。 分别获取 /account/summary 和 /positions,是对一个活跃账户发出的两个独立请求。如果两次请求之间有一笔成交落地,返回的汇总数据就会与仓位列表不一致(open_positions_count 显示三个,数组里却有四个),而这在任何真实负载下都会发生。汇总端点用同一次一致的读取支撑这两部分。
分别处理各个失败状态码。401 是凭证或时钟问题。在认定密钥错误之前,请先检查 X-Timestamp 是否与服务器时间相差不超过30秒。429 表示您超出了速率预算;请参见速率限制,并进行退避,而不是立即重试。本页有三个路由(/account/summary、/fills 和 /account/portfolio-history)每次消耗该预算的五个单位,而不是一个,所以在紧密循环中轮询它们,会以比请求次数所显示的快五倍的速度耗尽 Pro 调用方每秒20次的额度。/account/state 只消耗一个单位,并同时返回摘要和仓位,是读取两者更省的方式。/account/state 和 /account/summary 返回 502,表示权威的保证金视图无法访问,服务器拒绝猜测。请重试,并且不要回退到本地计算的 withdrawable。
示例
上面的数字彼此一致。在标记价格为 86000 时,notional 为 0.25 × 86000,unrealizedPnl 为 0.25 × (86000 − 84000),initialMargin 为 notional × 1/max_leverage,roe 为 unrealizedPnl / initialMargin,而 withdrawable 等于摘要中的 total_equity − margin_used,因为没有占用保证金的挂单。请注意最后一句中的两种写法:SUMMARY 对象上的 margin_used 是账户汇总值,保留其名称;仓位上的 initialMargin 则是逐仓位的要求。
可运行的端到端示例位于 SDK 仓库中:examples/portfolio.ts 和 examples/portfolio.rs。
相关内容
状态:测试网上的开发预览版。这些路由随 OpenAPI 规范 v0.7.2 发布,并在 v0.9.90 中仍为最新。在生产环境中请固定到某个规范版本,并在升级前查看各 SDK 的发布说明。
/account/fees目前没有按账户划分的等级或折扣计划,并且在其所需的保证金状态被镜像之前,leverage报告为null。测试网凭证和余额没有现实价值。
最后更新于

