> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.6mm.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.6mm.com/_mcp/server.

# 合约查询与分页

本文对应 **Agent Java SDK `v0.3.0`**、Java 8+ 与该标签的公开契约。示例在合作方后端运行；先按[快速开始](/zh-CN/sdk/agent-sdk/java/quick-start)初始化 `client`。

## 示例前提

Java 示例共用以下导入。按快速开始初始化 `client`，从已保存的绑定取得 `platformUserId`。示例用户和订单 ID 必须替换为实际持久化值。

```java
import com.sixmm.agent.*;
import com.sixmm.agent.model.*;
import java.util.*;
```

## 查询永续合约数据

### 六类接口与 Java 方法

全部使用签名 POST 请求，公共前缀为 `/v1/agent/perpetual`。

| 路径后缀                 | Java 方法 / 请求类型                                                    | 玩家范围                            |
| -------------------- | ----------------------------------------------------------------- | ------------------------------- |
| `/orders/current`    | `listCurrentPerpetualOrders(CurrentPerpetualOrdersRequest)`       | NORMAL 可省略玩家；CONDITIONAL 必须指定玩家 |
| `/orders/history`    | `listPerpetualOrderHistory(PerpetualOrderHistoryRequest)`         | 同上                              |
| `/trades`            | `listPerpetualTrades(PerpetualTradesRequest)`                     | 必须指定玩家                          |
| `/positions/current` | `listCurrentPerpetualPositions(CurrentPerpetualPositionsRequest)` | 可省略玩家                           |
| `/positions/history` | `listPerpetualPositionHistory(PerpetualPositionHistoryRequest)`   | 可省略玩家                           |
| `/account/ledger`    | `listPerpetualLedger(PerpetualLedgerRequest)`                     | 可省略玩家                           |

`platformUserIds` 是公开平台 ID 的字符串数组，指定时需 1～100 个不重复且有权访问的玩家；对于允许省略的接口，省略时仅查询当前商户有权访问的直属玩家范围。成交查询始终必须传入该数组，条件委托查询也必须明确指定玩家 ID。省略与 `[]` 不等价，空数组非法。范围由签名商户确定，不能传其他商户 ID 扩大范围。

数组值参与签名前先序列化为紧凑 JSON。例如，`platformUserIds` 使用 `["1188041528"]`，签名原文中的键值片段为 `platformUserIds=["1188041528"]`。保留数组元素顺序、双引号和字符串 ID，不插入格式化空格，不使用 Java `List.toString()`（例如 `[1188041528]`）。SDK 自动完成该序列化。

委托查询必传 `orderCategory=NORMAL` 或 `CONDITIONAL`。普通委托使用 `orderId`，条件委托使用 `conditionId`，不能跨类别混用。条件单与其触发生成的普通委托分别按实体处理。

### 过滤条件

| 查询   | 可用业务筛选                                                                                                 |
| ---- | ------------------------------------------------------------------------------------------------------ |
| 当前委托 | `orderCategory`、`symbol`                                                                               |
| 历史委托 | `orderCategory`、`symbol`、`startTime`、`endTime`、`orderId`、`conditionId`、`clientOrderId`、`side`、`status` |
| 成交   | `symbol`、`startTime`、`endTime`、`orderId`                                                               |
| 当前持仓 | `symbol`                                                                                               |
| 历史持仓 | `symbol`、`startTime`、`endTime`、`positionSide`                                                          |
| 合约账变 | `startTime`、`endTime`、`assetType`、`changeType`                                                         |

历史查询的时间为 Unix **毫秒**，区间为 `[startTime, endTime)`；请求签名的 `timestamp` 为 Unix **秒**。建议固定 UTC 时间窗口并分段查询；日对账采用 UTC 日切。状态和类型使用平台契约枚举，不自行翻译成中文字符串。

`limit` 默认 500，范围 1～1000；页大小不保证每次返回相同数量。六接口当前共享每商户 2 次/秒、突发 4 次的查询额度，实例内每商户并发上限 2。商户侧使用统一队列，建议从顺序分页和较小历史窗口开始。

### Java 查询示例

查询一个玩家的当前普通委托：

```java
CurrentPerpetualOrdersRequest current = new CurrentPerpetualOrdersRequest();
current.orderCategory = "NORMAL";
current.platformUserIds = Collections.singletonList(platformUserId);
current.symbol = "BTCUSDT";
current.limit = 100;
PerpetualResponse currentPage = client.listCurrentPerpetualOrders(current);
```

查询最近一小时合约账变，并处理游标。下面示例不自动重试；实际应用遇限流或暂时故障时按相关指南恢复同一页。

```java
PerpetualLedgerRequest ledger = new PerpetualLedgerRequest();
ledger.platformUserIds = Collections.singletonList(platformUserId);
ledger.endTime = System.currentTimeMillis();
ledger.startTime = ledger.endTime - 3_600_000L;
ledger.limit = 100;
Set<String> seenCursors = new HashSet<>();

while (true) {
    PerpetualResponse page = client.listPerpetualLedger(ledger);
    for (PerpetualRecord row : page.data.items) {
        // 在此按 platformUserId、entityType、entityId 幂等保存业务数据。
    }
    if (!page.data.hasMore) {
        break;
    }
    String next = page.data.nextCursor;
    if (next == null || next.isEmpty() || !seenCursors.add(next)) {
        throw new IllegalStateException("游标未推进，停止查询并排查");
    }
    ledger.cursor = next;
    Thread.sleep(650L); // 控制本查询频率；其他查询也需共享商户队列。
}
```

### 返回结构与保存规则

公共字段见[公共响应与分页](#common-response-and-pagination)。资源字段分别见[委托字段](/zh-CN/sdk/agent-sdk/java/perpetual-orders)、[成交字段](/zh-CN/sdk/agent-sdk/java/perpetual-trades)、[持仓字段](/zh-CN/sdk/agent-sdk/java/perpetual-positions)和[账变字段](/zh-CN/sdk/agent-sdk/java/perpetual-ledger)。

六接口统一返回 `PerpetualResponse`：

```json
{
  "code": 0,
  "message": "success",
  "data": {
    "items": [],
    "nextCursor": "",
    "hasMore": false
  }
}
```

每条 `items` 包含 `platformUserId`、`entityType`、`entityId`、`data`。实体类型包括 `ORDER`、`CONDITION_ORDER`、`TRADE_FILL`、`POSITION`、`ACCOUNT_LEDGER`。使用这三个身份字段构建幂等键；不要将条件单 ID、委托 ID 和成交 ID 当成同一编号。

`data` 按资源提供价格、数量、状态、费用、损益或余额变化等字段。金额、价格、数量及实体 ID 按字符串处理；业务时间使用毫秒。缺失字段不补造为 0，不从其他实体推断。

游标是一次查询的分页位置，不是可靠增量订阅，也不保证跨页原子快照。当前游标从首轮生成起有效 24 小时；后续分页保留相同商户、资源、玩家集合和过滤条件。历史拉取固定窗口，重复拉取时幂等覆盖；当前委托/持仓重新查询后刷新状态。需要实时界面时使用平台前端的数据机制，不能把轮询六接口当作高频行情接口。

### 错误与恢复

HTTP 成功不代表业务成功，必须检查 `code`。Java SDK 会以 `AgentApiException` 抛出业务错误。

| 业务码      | 典型含义              | 处理                      |
| -------- | ----------------- | ----------------------- |
| `102001` | 缺少必填参数，例如条件单查询缺玩家 | 补齐请求                    |
| `102002` | 参数非法、空数组、游标不匹配或过期 | 修正参数；过期游标清空后重查固定窗口并幂等保存 |
| `102003` | limit、玩家数或时间范围非法  | 缩小或修正范围                 |
| `6001`   | 签名错误              | 检查密钥、数组序列化及签名字段         |
| `6009`   | 商户接入方式或访问范围不允许    | 核对商户权限及玩家归属             |
| `6904`   | 服务暂不可用、并发或查询资源保护  | 降低并发、缩小窗口；持续出现联系平台      |
| `6905`   | 六类查询共享额度已耗尽       | 退避后重新调用原失败页             |

限流、超时或暂时故障后保留原失败页的 `cursor` 和所有筛选条件；每次重新调用 SDK 会生成新 `timestamp`、`nonce`、`sign`。不能直接跳到下一页，也不能把故障当作空结果。SDK 不负责自动重试资金业务。

## 公共响应与分页

| 字段                | JSON 类型 | 说明                                 |
| ----------------- | ------- | ---------------------------------- |
| `code`            | integer | 业务码，0 为成功；非 0 时按错误处理，不把失败当作空页      |
| `message`         | string  | 结果描述，不作为业务判断唯一依据                   |
| `data`            | object  | 成功时的分页结果                           |
| `data.items`      | array   | 本页记录；合法空页为 `[]`                    |
| `data.nextCursor` | string  | 下一页游标；没有后续页时通常为空字符串                |
| `data.hasMore`    | boolean | 是否存在后续页；true 时使用 nextCursor 继续相同查询 |

每条 `data.items[]` 的结构：

| 字段               | JSON 类型 | 说明                            |
| ---------------- | ------- | ----------------------------- |
| `platformUserId` | string  | 平台公开用户 ID，保存为字符串；不是内部数据库用户 ID |
| `entityType`     | string  | 记录所属实体类型，见下表                  |
| `entityId`       | string  | 当前实体的标识，与平台用户、实体类型组合构建本地幂等键   |
| `data`           | object  | 该实体的业务字段；不同资源字段不同             |

| 查询资源    | `entityType`      | `entityId` 对应关系               |
| ------- | ----------------- | ----------------------------- |
| 普通委托    | `ORDER`           | `data.orderId`                |
| 条件委托    | `CONDITION_ORDER` | `data.conditionId`            |
| 成交明细    | `TRADE_FILL`      | `data.fillId`，不是 tradeId      |
| 当前/历史持仓 | `POSITION`        | `data.positionId`             |
| 合约账变明细  | `ACCOUNT_LEDGER`  | 单条账变明细标识，**不是 data.ledgerId** |

同一个 `ledgerId` 可以拆出手续费、盈亏等多条明细；按 ledgerId 去重会丢数据。不同资源的 ID 不能混用。分页和字段保存规则见接入指南相关指南。

## 类型、单位与缺省行为

* 金额、价格、数量、实体 ID 使用 string；用十进制处理金额，不能使用浮点数或将长 ID 转为 JavaScript Number。金额币种和数量单位按交易对/合约规格解释。
* 业务时间使用 integer（int64），均为 Unix 毫秒；请求认证 timestamp 和入口凭据 expireAt 使用秒，不能混淆。
* 字符串业务字段为空时通常不输出，数值字段为 0 时有些会被省略。**字段缺失不代表业务值为 0**。
* 通用记录模型中的 `reduceOnly`、`closeOnly`、`makerOnly` 不省略 false，因此成交或持仓也可能出现这三个 false。只在委托资源中解释它们；不能据此认为成交/持仓执行了对应委托规则。
* `closePosition` 是可选 boolean：条件委托会提供，其他资源通常省略。缺失与 false 含义不同。
* 下表“当前提供”指读取逻辑具有字段来源；可选字段仍可能因没有值而省略。模型里存在的字段不保证每个接口都会填充。

## 状态与保证金模式的区别

| 资源                           | 当前返回值                                                                                 |
| ---------------------------- | ------------------------------------------------------------------------------------- |
| 当前普通委托 status                | NEW、PENDING、PARTIALLY_FILLED                                                          |
| 历史普通委托 status                | FILLED、CANCELED、REJECTED、PARTIAL_FILLED_CANCELED 或 PARTIALLY_FILLED_CANCELED；保持实际来源拼写 |
| 当前条件单 status / triggerStatus | PENDING_ACTIVATION、PENDING、TRIGGERING                                                 |
| 历史条件单 status / triggerStatus | TRIGGERED、CANCELLED、REJECTED、FIRED                                                    |
| 当前持仓 status                  | 数字字符串 "1" 持仓中、"3" 强平中                                                                 |
| 历史持仓 status                  | 数字字符串 "2" 已平仓、"4" 强平平仓                                                                |

普通委托的 CANCELED 与条件单的 CANCELLED 拼写不同；条件单已触发不等于生成的普通委托已成交。不要复用同一套 status 翻译表处理所有资源。

条件委托 marginMode 返回 CROSS / ISOLATED；历史普通委托及持仓目前返回 "1" / "2"，分别为全仓/逐仓。当前普通委托不提供 marginMode。商户可以在自己的展示层按资源归一化，原始值仍需保存。

## 模型中声明但本次查询不提供的字段

通用 RecordData / Java PerpetualData 模型还声明了下列字段，但当前六类正式读取逻辑不填充它们。**不应列为可用业务数据，也不能用字段默认值替代真实结果。**

| 字段               | 模型类型    | 当前边界                          |
| ---------------- | ------- | ----------------------------- |
| `closeReason`    | string  | 未提供历史持仓平仓原因                   |
| `walletDelta`    | string  | 账变接口不返回钱包 delta               |
| `frozenDelta`    | string  | 账变接口不返回冻结 delta               |
| `usedDelta`      | string  | 账变接口不返回已用保证金 delta            |
| `feeDelta`       | string  | 账变接口不返回费用 delta               |
| `pnlDelta`       | string  | 账变接口不返回损益 delta               |
| `accountVersion` | string  | 账变接口不返回账户版本，不能用其做可靠增量同步       |
| `occurredAt`     | integer | 账变接口使用 createdAt，不提供另一套事件发生时间 |

实际字段适用范围以上述各资源表为准；平台更新字段或枚举时，按新的接口说明和 SDK 版本适配。

## 来源与相关指南

* [官方 v0.3.0 源码](https://github.com/6mm-com/agent-java-sdk/tree/54aa3c1)
* [Funding 钱包](/zh-CN/sdk/agent-sdk/java/funding-wallet)
* [升级指南](/zh-CN/sdk/agent-sdk/java/upgrade)