mcpField
B
bingx-coinm-trade

bingx-coinm-trade

github.com/bingx-api其他19174 次安装1 周前更新
代码仓库

关于 bingx-coinm-trade

面向处理订单和账户查询的 Agent,提供 BingX Coin-M 反向永续合约交易操作。它强调参数校验,并要求实时环境写操作先确认。

主要功能

  1. 01下达和取消期货订单
  2. 02查询订单、成交和持仓
  3. 03设置杠杆与保证金类型
  4. 04调整逐仓持仓保证金
  5. 05校验参数并要求实时操作确认

适用场景

  1. 01提交 Coin-M 市价或限价单
  2. 02查看未完成订单和交易历史
  3. 03更改杠杆或保证金设置
  4. 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/orderPOST下新订单是
/openApi/cswap/v1/trade/cancelOrderDELETE取消订单是
/openApi/cswap/v1/trade/allOpenOrdersPOST取消某交易对的所有未成交订单是
/openApi/cswap/v1/trade/closeAllPositionsPOST平掉所有仓位是
/openApi/cswap/v1/trade/openOrdersGET查询未成交订单是
/openApi/cswap/v1/trade/orderDetailGET按 ID 查询单个订单是
/openApi/cswap/v1/trade/orderHistoryGET查询历史订单是
/openApi/cswap/v1/trade/allFillOrdersGET查询成交记录是
/openApi/cswap/v1/trade/forceOrdersGET查询强平/ADL 订单是
/openApi/cswap/v1/trade/leverageGET查询当前杠杆是
/openApi/cswap/v1/trade/leveragePOST设置杠杆是
/openApi/cswap/v1/trade/marginTypeGET查询保证金类型是
/openApi/cswap/v1/trade/marginTypePOST设置保证金类型(ISOLATED/CROSSED)是
/openApi/cswap/v1/trade/positionMarginPOST调整逐仓仓位保证金是
/openApi/cswap/v1/user/commissionRateGET查询交易手续费率是
/openApi/cswap/v1/user/balanceGET查询账户资产是
/openApi/cswap/v1/user/positionsGET查询当前仓位是

参数

订单参数
  • 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 和 leverage SET)
  • 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)自定义环境的 BASE URL 条目;(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 和状态。


取消订单流程
  1. 如果未提供,请询问 orderId(或 clientOrderId)。
  2. 对于 prod-live:要求用户输入 CONFIRM。
  3. 执行 DELETE /openApi/cswap/v1/trade/cancelOrder。
杠杆设置流程
  1. 如果未提供,请询问交易对。
  2. 询问仓位方向(LONG / SHORT)。
  3. 询问杠杆值(例如 BTC-USD 的范围为 1–50)。
  4. 对于 prod-live:要求用户输入 CONFIRM。
  5. 执行 POST /openApi/cswap/v1/trade/leverage。
保证金类型流程
  1. 如果未提供,请询问交易对。
  2. 提供选项:ISOLATED 或 CROSSED。
  3. 对于 prod-live:要求用户输入 CONFIRM。
  4. 执行 POST /openApi/cswap/v1/trade/marginType。

评论

支持 Markdown