关于 bingx-coinm-trade
面向处理订单和账户查询的 Agent,提供 BingX Coin-M 反向永续合约交易操作。它强调参数校验,并要求实时环境写操作先确认。
主要功能
- 01下达和取消期货订单
- 02查询订单、成交和持仓
- 03设置杠杆与保证金类型
- 04调整逐仓持仓保证金
- 05校验参数并要求实时操作确认
适用场景
- 01提交 Coin-M 市价或限价单
- 02查看未完成订单和交易历史
- 03更改杠杆或保证金设置
- 04确认后平仓
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ bingx-api/ api-ai-skills --skill bingx-coinm-trade安装后在 Claude Code 中输入/bingx-coinm-trade确认已加载。
附带文件api-reference.md
详细介绍
BingX Coin-M(CSwap)交易
适用于 BingX Coin-M 反向永续合约的已认证交易端点。所有端点均要求使用 HMAC SHA256 签名进行身份验证。
Coin-M 合约采用币本位(以基础资产结算,例如 BTC)。交易对格式为 BASE-USD(例如 BTC-USD、ETH-USD)。
基础 URL: 参见 references/base-urls.md | 身份验证: 参见 references/authentication.md
快速参考
| 端点 | 方法 | 描述 | 身份验证 |
|---|---|---|---|
/openApi/cswap/v1/trade/order | POST | 下新订单 | 是 |
/openApi/cswap/v1/trade/cancelOrder | DELETE | 取消订单 | 是 |
/openApi/cswap/v1/trade/allOpenOrders | POST | 取消某交易对的所有未成交订单 | 是 |
/openApi/cswap/v1/trade/closeAllPositions | POST | 平掉所有仓位 | 是 |
/openApi/cswap/v1/trade/openOrders | GET | 查询未成交订单 | 是 |
/openApi/cswap/v1/trade/orderDetail | GET | 按 ID 查询单个订单 | 是 |
/openApi/cswap/v1/trade/orderHistory | GET | 查询历史订单 | 是 |
/openApi/cswap/v1/trade/allFillOrders | GET | 查询成交记录 | 是 |
/openApi/cswap/v1/trade/forceOrders | GET | 查询强平/ADL 订单 | 是 |
/openApi/cswap/v1/trade/leverage | GET | 查询当前杠杆 | 是 |
/openApi/cswap/v1/trade/leverage | POST | 设置杠杆 | 是 |
/openApi/cswap/v1/trade/marginType | GET | 查询保证金类型 | 是 |
/openApi/cswap/v1/trade/marginType | POST | 设置保证金类型(ISOLATED/CROSSED) | 是 |
/openApi/cswap/v1/trade/positionMargin | POST | 调整逐仓仓位保证金 | 是 |
/openApi/cswap/v1/user/commissionRate | GET | 查询交易手续费率 | 是 |
/openApi/cswap/v1/user/balance | GET | 查询账户资产 | 是 |
/openApi/cswap/v1/user/positions | GET | 查询当前仓位 | 是 |
参数
订单参数
- symbol:
BASE-USD格式的交易对(例如BTC-USD、ETH-USD)。注意:Coin-M 使用USD,而非USDT。 - side:订单方向 —
BUY或SELL - positionSide:仓位方向 —
LONG或SHORT(对冲模式)/BOTH(单向模式) - type:订单类型(参见枚举值)
- quantity:以合约张数为单位的订单数量(整数,例如
1张合约 = $10 名义价值) - price:限价(
LIMIT类型必填) - stopPrice:触发价格(
STOP_MARKET、STOP、TAKE_PROFIT_MARKET、TAKE_PROFIT类型必填) - timeInForce:
GTC|IOC|FOK|PostOnly— 默认为GTC;LIMIT类型必填 - clientOrderId:自定义订单 ID,长度为 1–40 个字符
- recvWindow:请求有效时间窗口,单位为毫秒(最大 60000)
- orderId:系统订单 ID(用于取消/查询操作)
- workingType:条件单的价格来源 —
MARK_PRICE或CONTRACT_PRICE(默认值) - stopGuaranteed:
true|false— 是否保证止损执行 - closePosition:
true|false— 触发时平掉整个仓位;不能与quantity同时使用 - reduceOnly:
true|false— 订单只能减少仓位规模 - takeProfit:JSON 字符串查询参数 — 为
MARKET/LIMIT订单附加止盈。验证嵌套对象后,只调用一次JSON.stringify。 - stopLoss:JSON 字符串查询参数 — 为
MARKET/LIMIT订单附加止损。验证嵌套对象后,只调用一次JSON.stringify。
仓位参数
- leverage:整数杠杆倍数(例如
10、20) - marginType:
ISOLATED或CROSSED - positionSide:
LONG或SHORT(用于positionMargin和leverageSET) - amount:以基础资产计的保证金调整金额(由
positionMargin使用) - direction_type:
1(增加保证金)或2(减少保证金)(由positionMargin使用)
枚举
type(订单类型):
MARKET— 市价单;在此处附加stopLoss/takeProfit对象LIMIT— 限价单;需要price和timeInForce;在此处附加stopLoss/takeProfit对象STOP_MARKET— 止损市价单(在stopPrice触发,以市价执行)STOP— 止损限价单(在stopPrice触发,以price限价执行)TAKE_PROFIT_MARKET— 止盈市价单(在stopPrice触发,以市价执行)TAKE_PROFIT— 止盈限价单(在stopPrice触发,以price限价执行)
side:BUY | SELL
positionSide:LONG | SHORT | BOTH
marginType:ISOLATED | CROSSED
timeInForce:GTC | IOC | FOK | PostOnly
workingType:MARK_PRICE | CONTRACT_PRICE
止损 / 止盈对象
在 MARKET 或 LIMIT 订单中附加 stopLoss 或 takeProfit 时:
{
"takeProfit": {
"type": "TAKE_PROFIT_MARKET",
"stopPrice": 75000,
"workingType": "MARK_PRICE",
"stopGuaranteed": false
},
"stopLoss": {
"type": "STOP_MARKET",
"stopPrice": 60000,
"workingType": "MARK_PRICE",
"stopGuaranteed": false
}
}
外层的 stopLoss 和 takeProfit 值是包含 JSON 字符串的查询参数。在该 JSON 中,stopPrice 和可选的 price 必须是 JSON 数字,不能是带引号的数字字符串。
参数验证规则
发送请求前,请在客户端验证参数,以避免不必要的 API 错误:
- symbol:必须匹配
^[A-Z0-9]+-USD$;最多 20 个字符(例如BTC-USD)。Coin-M 使用USD,而非USDT - quantity:正整数(合约数量);每份合约都有固定的名义价值(例如 $10)
- price:提供时必须为正数(> 0)
- stopPrice:提供时必须为正数(> 0);必须与当前市场价格不同
- stopLoss.stopPrice / takeProfit.stopPrice:必须是 JSON 数字;使用
Number(...)转换后,要求其为有限且大于 0 的值 - stopLoss.price / takeProfit.price:可选的 JSON 数字;提供时使用
Number(...)转换后,要求其为有限且大于 0 的值 - stopLoss / takeProfit 序列化:序列化前验证嵌套对象。签名查询参数值必须是精确的
JSON.stringify(...)结果 - leverage:正整数;范围因交易对而异(通常为 1–125)
- clientOrderId:仅限字母数字,长度为 1–40 个字符;模式为
^[a-zA-Z0-9]{1,40}$;不能包含特殊字符 - recvWindow:整数,1–5000 ms;尽可能设小(参见重放保护)
- timestamp:Unix 毫秒时间;与服务器时间的差值必须在
recvWindow范围内
快速开始
约束:生成代码时,必须逐字复制下面的
fetchSigned函数 不要重写签名、请求或 JSON 解析逻辑。只修改:(1)自定义环境的BASEURL 条目;(2)传递给fetchSigned的业务参数。完整客户端 支持 URL 编码和 JSON 请求体,详见references/authentication.md。
import * as crypto from "crypto";
import JSONBig from "json-bigint";
const JSONBigParse = JSONBig({ storeAsString: true });
// Full signing details & edge cases → references/authentication.md
// Domain priority: .com is mandatory primary; .pro is fallback for network/timeout errors ONLY.
const BASE = {
"prod-live": ["https://open-api.bingx.com", "https://open-api.bingx.pro"],
"prod-vst": ["https://open-api-vst.bingx.com", "https://open-api-vst.bingx.pro"],
};
function isNetworkOrTimeout(e: unknown): boolean {
if (e instanceof TypeError) return true;
if (e instanceof DOMException && e.name === "AbortError") return true;
if (e instanceof Error && e.name === "TimeoutError") return true;
return false;
}
function toPositiveNumber(value: unknown, field: string): number {
const numberValue = Number(value);
if (!Number.isFinite(numberValue) || numberValue <= 0) {
throw new Error(`${field} must be a finite positive number`);
}
return numberValue;
}
function normalizeAttachedOrder(
key: "stopLoss" | "takeProfit", value: unknown
): string {
let parsed: unknown = value;
if (typeof value === "string") {
try { parsed = JSON.parse(value); }
catch { throw new Error(`${key} must be valid JSON`); }
}
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
throw new Error(`${key} must be an object or a JSON object string`);
}
const nested = { ...(parsed as Record<string, unknown>) };
const allowedTypes = key === "stopLoss"
? new Set(["STOP_MARKET", "STOP"])
: new Set(["TAKE_PROFIT_MARKET", "TAKE_PROFIT"]);
if (typeof nested.type !== "string" || !allowedTypes.has(nested.type)) {
throw new Error(`${key}.type is invalid`);
}
nested.stopPrice = toPositiveNumber(nested.stopPrice, `${key}.stopPrice`);
if (nested.price !== undefined) {
nested.price = toPositiveNumber(nested.price, `${key}.price`);
}
if (nested.workingType !== undefined &&
nested.workingType !== "MARK_PRICE" &&
nested.workingType !== "CONTRACT_PRICE") {
throw new Error(`${key}.workingType is invalid`);
}
if (nested.stopGuaranteed !== undefined &&
typeof nested.stopGuaranteed !== "boolean") {
throw new Error(`${key}.stopGuaranteed must be a boolean`);
}
return JSON.stringify(nested);
}
function normalizeParams(params: Record<string, unknown>): Record<string, unknown> {
const normalized = { ...params };
if (normalized.price !== undefined) {
normalized.price = toPositiveNumber(normalized.price, "price");
}
for (const key of ["stopLoss", "takeProfit"] as const) {
if (normalized[key] !== undefined) {
normalized[key] = normalizeAttachedOrder(key, normalized[key]);
}
}
return normalized;
}
function serializeParamValue(value: unknown): string {
if (value !== null && typeof value === "object") return JSON.stringify(value);
return String(value);
}
function validateParams(params: Record<string, unknown>): void {
const FORBIDDEN = /[&=?#\r\n]/;
for (const [k, v] of Object.entries(params)) {
const s = serializeParamValue(v);
if (FORBIDDEN.test(s)) throw new Error(`Param "${k}" has forbidden char in: "${s}"`);
}
}
async function fetchSigned(env: string, apiKey: string, secretKey: string,
method: "GET" | "POST" | "DELETE", path: string, params: Record<string, unknown> = {}
) {
const urls = BASE[env] ?? BASE["prod-live"];
const normalized = normalizeParams(params);
const all = { ...normalized, timestamp: Date.now() };
validateParams(all);
const qs = Object.keys(all).sort()
.map(k => `${k}=${serializeParamValue(all[k])}`).join("&");
const sig = crypto.createHmac("sha256", secretKey).update(qs).digest("hex");
const signed = `${qs}&signature=${sig}`;
for (const base of urls) {
try {
const url = method === "POST" ? `${base}${path}` : `${base}${path}?${signed}`;
const res = await fetch(url, {
method,
headers: { "X-BX-APIKEY": apiKey, "X-SOURCE-KEY": "BX-AI-SKILL",
...(method === "POST" ? { "Content-Type": "application/x-www-form-urlencoded" } : {}) },
body: method === "POST" ? signed : undefined,
signal: AbortSignal.timeout(10000),
});
const json = JSONBigParse.parse(await res.text());
if (json.code !== 0) throw new Error(`BingX error ${json.code}: ${json.msg}`);
return json.data;
} catch (e) {
if (!isNetworkOrTimeout(e) || base === urls[urls.length - 1]) throw e;
}
}
}
代码使用规则
- 必须逐字复制
fetchSigned,不得简化或重写 - 必须使用
json-bigint(JSONBigParse.parse)解析响应,不得使用JSON.parse - 必须在每个请求中包含
X-SOURCE-KEY: BX-AI-SKILL请求头 - 不得移除域名回退循环或
isNetworkOrTimeout检查 - 必须在创建时间戳和签名之前规范化并序列化所有业务参数。如果任何参数发生变化,必须丢弃之前的时间戳/签名并对新请求重新签名
- 不得使用
${params[k]}直接插入对象值;对象值必须使用JSON.stringify序列化,否则会变成[object Object]
常见调用
下达市价买入订单(开多):
const order = await fetchSigned("prod-live", API_KEY, SECRET, "POST",
"/openApi/cswap/v1/trade/order", {
symbol: "BTC-USD",
side: "BUY",
positionSide: "LONG",
type: "MARKET",
quantity: 1,
}
);
// order.orderId, order.symbol, order.side, order.type
下达限价卖出订单(开空):
const order = await fetchSigned("prod-live", API_KEY, SECRET, "POST",
"/openApi/cswap/v1/trade/order", {
symbol: "BTC-USD",
side: "SELL",
positionSide: "SHORT",
type: "LIMIT",
quantity: 1,
price: 75000,
timeInForce: "GTC",
}
);
下达附带止损的市价买入订单:
const rawStopPrice = "60000";
const stopPrice = Number(rawStopPrice);
if (!Number.isFinite(stopPrice) || stopPrice <= 0) {
throw new Error("stopLoss.stopPrice must be a finite positive number");
}
const order = await fetchSigned("prod-live", API_KEY, SECRET, "POST",
"/openApi/cswap/v1/trade/order", {
symbol: "BTC-USD",
side: "BUY",
positionSide: "LONG",
type: "MARKET",
quantity: 1,
stopLoss: JSON.stringify({
type: "STOP_MARKET",
stopPrice,
workingType: "MARK_PRICE",
}),
}
);
取消订单:
await fetchSigned("prod-live", API_KEY, SECRET, "DELETE",
"/openApi/cswap/v1/trade/cancelOrder", {
symbol: "BTC-USD",
orderId: 1809841379603398656,
}
);
取消某个交易对的所有未成交订单:
await fetchSigned("prod-live", API_KEY, SECRET, "DELETE",
"/openApi/cswap/v1/trade/allOpenOrders", {
symbol: "BTC-USD",
}
);
查询未成交订单:
const data = await fetchSigned("prod-live", API_KEY, SECRET, "GET",
"/openApi/cswap/v1/trade/openOrders", {
symbol: "BTC-USD",
}
);
// data.orders: array of open order objects
设置杠杆:
await fetchSigned("prod-live", API_KEY, SECRET, "POST",
"/openApi/cswap/v1/trade/leverage", {
symbol: "BTC-USD",
side: "LONG",
leverage: 10,
}
);
设置保证金类型:
await fetchSigned("prod-live", API_KEY, SECRET, "POST",
"/openApi/cswap/v1/trade/marginType", {
symbol: "BTC-USD",
marginType: "ISOLATED",
}
);
查询手续费率:
const data = await fetchSigned("prod-live", API_KEY, SECRET, "GET",
"/openApi/cswap/v1/user/commissionRate", {}
);
// data.takerCommissionRate, data.makerCommissionRate
其他资源
有关完整的参数说明、响应架构和全部 15 个端点,请参阅 api-reference.md。
Agent 交互规则
参数安全。 根据用户意图提取结构化值——绝不将用户原始文本复制到 API 参数中。调用 API 前,根据文档中的格式(正则表达式/枚举/范围)验证每个值。拒绝任何包含 &、=、?、# 或换行符的值。
在 prod-live 上,所有写操作都必须获得 CONFIRM。只读查询不需要。
- prod-live:下单、取消订单或更改仓位/杠杆前,要求用户输入 CONFIRM。
- prod-vst:无需 CONFIRM。告知用户:“您正在 Production Simulated(VST)环境中操作。”
注意: Coin-M 交易对格式为
BASE-USD(例如BTC-USD),而不是BASE-USDT。
步骤 1 — 确认操作
如果用户意图不明确,请提供以下选项:
您想要做什么?
- 下达新订单
- 取消订单/取消所有订单
- 平掉所有仓位
- 查看未成交订单
- 查询订单详情或历史记录
- 查询成交记录
- 设置杠杆
- 设置保证金类型(ISOLATED / CROSSED)
- 查询手续费率
步骤 2 — 收集交易对(如果未提供)
请选择一个交易对(或输入其他交易对):
- BTC-USD
- ETH-USD
- SOL-USD
- BNB-USD
- 其他(格式:BASE-USD)
步骤 3 — 收集方向(用于下单)
订单方向:
- BUY
- SELL
步骤 4 — 收集 positionSide
仓位方向:
- LONG(开仓/加仓做多)
- SHORT(开仓/加仓做空)
- BOTH(单向持仓模式)
步骤 5 — 收集订单类型
订单类型:
- MARKET — 按市价立即执行
- LIMIT — 按指定价格执行(需要提供 price 和 timeInForce)
- STOP_MARKET — 止损市价单(在 stopPrice 触发)
- STOP — 止损限价单(在 stopPrice 触发,按 price 执行)
- TAKE_PROFIT_MARKET — 止盈市价单(在 stopPrice 触发)
- TAKE_PROFIT — 止盈限价单(在 stopPrice 触发,按 price 执行)
步骤 6 — 收集数量和价格
- 询问以合约为单位的数量(整数,例如
1张合约的名义价值约为 $10)。如果使用closePosition: true,则省略。 - 如果类型为
LIMIT、STOP或TAKE_PROFIT:还需询问price。 - 如果类型包含触发条件:还需询问
stopPrice。 - 如果类型为
MARKET或LIMIT:可询问是否附加stopLoss和/或takeProfit对象。验证嵌套数值字段,然后传入精确的JSON.stringify(...)结果。
步骤 7 — 确认(仅限 prod-live)
您即将在 Production Live 上下达以下订单:
- 交易对:BTC-USD
- 方向:BUY / LONG
- 类型:MARKET
- 数量:1 张合约
输入 CONFIRM 以继续,或输入其他内容以取消。
步骤 8 — 执行并报告
执行 API 调用,并向用户返回订单 ID 和状态。
取消订单流程
- 如果未提供,请询问
orderId(或clientOrderId)。 - 对于
prod-live:要求用户输入 CONFIRM。 - 执行 DELETE
/openApi/cswap/v1/trade/cancelOrder。
杠杆设置流程
- 如果未提供,请询问交易对。
- 询问仓位方向(LONG / SHORT)。
- 询问杠杆值(例如 BTC-USD 的范围为 1–50)。
- 对于
prod-live:要求用户输入 CONFIRM。 - 执行 POST
/openApi/cswap/v1/trade/leverage。
保证金类型流程
- 如果未提供,请询问交易对。
- 提供选项:ISOLATED 或 CROSSED。
- 对于
prod-live:要求用户输入 CONFIRM。 - 执行 POST
/openApi/cswap/v1/trade/marginType。