@okx_ai/okx-trade-cli 1.2.4-beta.3 → 1.2.4-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1367,6 +1367,14 @@ function normalizeResponse(response) {
1367
1367
  data: response.data
1368
1368
  };
1369
1369
  }
1370
+ function buildAttachAlgoOrds(source) {
1371
+ const tpTriggerPx = readString(source, "tpTriggerPx");
1372
+ const tpOrdPx = readString(source, "tpOrdPx");
1373
+ const slTriggerPx = readString(source, "slTriggerPx");
1374
+ const slOrdPx = readString(source, "slOrdPx");
1375
+ const entry = compactObject({ tpTriggerPx, tpOrdPx, slTriggerPx, slOrdPx });
1376
+ return Object.keys(entry).length > 0 ? [entry] : void 0;
1377
+ }
1370
1378
  var OKX_CANDLE_BARS = [
1371
1379
  "1m",
1372
1380
  "3m",
@@ -1414,19 +1422,12 @@ function assertNotDemo(config, endpoint) {
1414
1422
  );
1415
1423
  }
1416
1424
  }
1417
- function normalize(response) {
1418
- return {
1419
- endpoint: response.endpoint,
1420
- requestTime: response.requestTime,
1421
- data: response.data
1422
- };
1423
- }
1424
1425
  function registerAccountTools() {
1425
1426
  return [
1426
1427
  {
1427
1428
  name: "account_get_balance",
1428
1429
  module: "account",
1429
- description: "Get account balance for trading account. Returns balances for all currencies or a specific one. Private endpoint. Rate limit: 10 req/s.",
1430
+ description: "Get account balance for trading account. Returns balances for all currencies or a specific one.",
1430
1431
  isWrite: false,
1431
1432
  inputSchema: {
1432
1433
  type: "object",
@@ -1444,13 +1445,13 @@ function registerAccountTools() {
1444
1445
  compactObject({ ccy: readString(args, "ccy") }),
1445
1446
  privateRateLimit("account_get_balance", 10)
1446
1447
  );
1447
- return normalize(response);
1448
+ return normalizeResponse(response);
1448
1449
  }
1449
1450
  },
1450
1451
  {
1451
1452
  name: "account_transfer",
1452
1453
  module: "account",
1453
- description: "Transfer funds between accounts (trading, funding, etc.). [CAUTION] Moves real funds. Private endpoint. Rate limit: 2 req/s.",
1454
+ description: "Transfer funds between accounts (trading, funding, etc.). [CAUTION] Moves real funds.",
1454
1455
  isWrite: true,
1455
1456
  inputSchema: {
1456
1457
  type: "object",
@@ -1501,13 +1502,13 @@ function registerAccountTools() {
1501
1502
  }),
1502
1503
  privateRateLimit("account_transfer", 2)
1503
1504
  );
1504
- return normalize(response);
1505
+ return normalizeResponse(response);
1505
1506
  }
1506
1507
  },
1507
1508
  {
1508
1509
  name: "account_get_max_size",
1509
1510
  module: "account",
1510
- description: "Get max buy/sell order size for a SWAP/FUTURES instrument given current balance and leverage. Useful before placing orders. Private. Rate limit: 20 req/s.",
1511
+ description: "Get max buy/sell order size for a SWAP/FUTURES instrument given current balance and leverage. Useful before placing orders.",
1511
1512
  isWrite: false,
1512
1513
  inputSchema: {
1513
1514
  type: "object",
@@ -1548,13 +1549,13 @@ function registerAccountTools() {
1548
1549
  }),
1549
1550
  privateRateLimit("account_get_max_size", 20)
1550
1551
  );
1551
- return normalize(response);
1552
+ return normalizeResponse(response);
1552
1553
  }
1553
1554
  },
1554
1555
  {
1555
1556
  name: "account_get_asset_balance",
1556
1557
  module: "account",
1557
- description: "Get funding account balance (asset account). Different from account_get_balance which queries the trading account. Private. Rate limit: 6 req/s.",
1558
+ description: "Get funding account balance (asset account). Different from account_get_balance which queries the trading account.",
1558
1559
  isWrite: false,
1559
1560
  inputSchema: {
1560
1561
  type: "object",
@@ -1572,13 +1573,13 @@ function registerAccountTools() {
1572
1573
  compactObject({ ccy: readString(args, "ccy") }),
1573
1574
  privateRateLimit("account_get_asset_balance", 6)
1574
1575
  );
1575
- return normalize(response);
1576
+ return normalizeResponse(response);
1576
1577
  }
1577
1578
  },
1578
1579
  {
1579
1580
  name: "account_get_bills",
1580
1581
  module: "account",
1581
- description: "Get account ledger: fees paid, funding charges, realized PnL, transfers, etc. Default 20 records (last 7 days), max 100. Private endpoint. Rate limit: 6 req/s.",
1582
+ description: "Get account ledger: fees paid, funding charges, realized PnL, transfers, etc. Default 20 records (last 7 days), max 100.",
1582
1583
  isWrite: false,
1583
1584
  inputSchema: {
1584
1585
  type: "object",
@@ -1638,13 +1639,13 @@ function registerAccountTools() {
1638
1639
  }),
1639
1640
  privateRateLimit("account_get_bills", 6)
1640
1641
  );
1641
- return normalize(response);
1642
+ return normalizeResponse(response);
1642
1643
  }
1643
1644
  },
1644
1645
  {
1645
1646
  name: "account_get_positions_history",
1646
1647
  module: "account",
1647
- description: "Get closed position history for SWAP or FUTURES. Default 20 records, max 100. Private endpoint. Rate limit: 1 req/s.",
1648
+ description: "Get closed position history for SWAP or FUTURES. Default 20 records, max 100.",
1648
1649
  isWrite: false,
1649
1650
  inputSchema: {
1650
1651
  type: "object",
@@ -1699,13 +1700,13 @@ function registerAccountTools() {
1699
1700
  }),
1700
1701
  privateRateLimit("account_get_positions_history", 1)
1701
1702
  );
1702
- return normalize(response);
1703
+ return normalizeResponse(response);
1703
1704
  }
1704
1705
  },
1705
1706
  {
1706
1707
  name: "account_get_trade_fee",
1707
1708
  module: "account",
1708
- description: "Get maker/taker fee rates for the account. Useful to understand your fee tier before trading. Private endpoint. Rate limit: 5 req/s.",
1709
+ description: "Get maker/taker fee rates for the account. Useful to understand your fee tier before trading.",
1709
1710
  isWrite: false,
1710
1711
  inputSchema: {
1711
1712
  type: "object",
@@ -1731,13 +1732,13 @@ function registerAccountTools() {
1731
1732
  }),
1732
1733
  privateRateLimit("account_get_trade_fee", 5)
1733
1734
  );
1734
- return normalize(response);
1735
+ return normalizeResponse(response);
1735
1736
  }
1736
1737
  },
1737
1738
  {
1738
1739
  name: "account_get_config",
1739
1740
  module: "account",
1740
- description: "Get account configuration: position mode (net vs hedge), account level, auto-loan settings, etc. Private endpoint. Rate limit: 5 req/s.",
1741
+ description: "Get account configuration: position mode (net vs hedge), account level, auto-loan settings, etc.",
1741
1742
  isWrite: false,
1742
1743
  inputSchema: {
1743
1744
  type: "object",
@@ -1749,13 +1750,13 @@ function registerAccountTools() {
1749
1750
  {},
1750
1751
  privateRateLimit("account_get_config", 5)
1751
1752
  );
1752
- return normalize(response);
1753
+ return normalizeResponse(response);
1753
1754
  }
1754
1755
  },
1755
1756
  {
1756
1757
  name: "account_get_max_withdrawal",
1757
1758
  module: "account",
1758
- description: "Get maximum withdrawable amount for a currency from the trading account. Useful before initiating a transfer or withdrawal. Private endpoint. Rate limit: 20 req/s.",
1759
+ description: "Get maximum withdrawable amount for a currency from the trading account. Useful before initiating a transfer or withdrawal.",
1759
1760
  isWrite: false,
1760
1761
  inputSchema: {
1761
1762
  type: "object",
@@ -1773,13 +1774,13 @@ function registerAccountTools() {
1773
1774
  compactObject({ ccy: readString(args, "ccy") }),
1774
1775
  privateRateLimit("account_get_max_withdrawal", 20)
1775
1776
  );
1776
- return normalize(response);
1777
+ return normalizeResponse(response);
1777
1778
  }
1778
1779
  },
1779
1780
  {
1780
1781
  name: "account_get_max_avail_size",
1781
1782
  module: "account",
1782
- description: "Get maximum available size for opening or reducing a position. Different from account_get_max_size which calculates new order size. Private endpoint. Rate limit: 20 req/s.",
1783
+ description: "Get maximum available size for opening or reducing a position. Different from account_get_max_size which calculates new order size.",
1783
1784
  isWrite: false,
1784
1785
  inputSchema: {
1785
1786
  type: "object",
@@ -1817,13 +1818,13 @@ function registerAccountTools() {
1817
1818
  }),
1818
1819
  privateRateLimit("account_get_max_avail_size", 20)
1819
1820
  );
1820
- return normalize(response);
1821
+ return normalizeResponse(response);
1821
1822
  }
1822
1823
  },
1823
1824
  {
1824
1825
  name: "account_get_positions",
1825
1826
  module: "account",
1826
- description: "Get current open positions across all instrument types (MARGIN, SWAP, FUTURES, OPTION). Use swap_get_positions for SWAP/FUTURES-only queries when the swap module is loaded. Private endpoint. Rate limit: 10 req/s.",
1827
+ description: "Get current open positions across all instrument types (MARGIN, SWAP, FUTURES, OPTION). Use swap_get_positions for SWAP/FUTURES-only queries.",
1827
1828
  isWrite: false,
1828
1829
  inputSchema: {
1829
1830
  type: "object",
@@ -1852,13 +1853,13 @@ function registerAccountTools() {
1852
1853
  }),
1853
1854
  privateRateLimit("account_get_positions", 10)
1854
1855
  );
1855
- return normalize(response);
1856
+ return normalizeResponse(response);
1856
1857
  }
1857
1858
  },
1858
1859
  {
1859
1860
  name: "account_get_bills_archive",
1860
1861
  module: "account",
1861
- description: "Get archived account ledger (bills older than 7 days, up to 3 months). Use account_get_bills for recent 7-day records. Default 20 records, max 100. Private endpoint. Rate limit: 6 req/s.",
1862
+ description: "Get archived account ledger (bills older than 7 days, up to 3 months). Use account_get_bills for recent 7-day records. Default 20 records, max 100.",
1862
1863
  isWrite: false,
1863
1864
  inputSchema: {
1864
1865
  type: "object",
@@ -1918,13 +1919,13 @@ function registerAccountTools() {
1918
1919
  }),
1919
1920
  privateRateLimit("account_get_bills_archive", 6)
1920
1921
  );
1921
- return normalize(response);
1922
+ return normalizeResponse(response);
1922
1923
  }
1923
1924
  },
1924
1925
  {
1925
1926
  name: "account_set_position_mode",
1926
1927
  module: "account",
1927
- description: "Switch between net position mode and long/short hedge mode. net: one position per instrument (default for most accounts). long_short_mode: separate long and short positions. [CAUTION] Requires no open positions or pending orders. Private endpoint. Rate limit: 5 req/s.",
1928
+ description: "Switch between net position mode and long/short hedge mode. net: one position per instrument (default). long_short_mode: separate long and short positions. [CAUTION] Requires no open positions or pending orders.",
1928
1929
  isWrite: true,
1929
1930
  inputSchema: {
1930
1931
  type: "object",
@@ -1944,24 +1945,17 @@ function registerAccountTools() {
1944
1945
  { posMode: requireString(args, "posMode") },
1945
1946
  privateRateLimit("account_set_position_mode", 5)
1946
1947
  );
1947
- return normalize(response);
1948
+ return normalizeResponse(response);
1948
1949
  }
1949
1950
  }
1950
1951
  ];
1951
1952
  }
1952
- function normalize2(response) {
1953
- return {
1954
- endpoint: response.endpoint,
1955
- requestTime: response.requestTime,
1956
- data: response.data
1957
- };
1958
- }
1959
1953
  function registerAlgoTradeTools() {
1960
1954
  return [
1961
1955
  {
1962
1956
  name: "swap_place_algo_order",
1963
1957
  module: "swap",
1964
- description: "Place a SWAP/FUTURES take-profit or stop-loss algo order. [CAUTION] Executes real trades. Use ordType='conditional' for a single TP, single SL, or combined TP+SL on one order. Use ordType='oco' (one-cancels-other) to place TP and SL simultaneously \u2014 whichever triggers first cancels the other. Set tpOrdPx='-1' or slOrdPx='-1' to execute the closing leg as a market order. Private endpoint. Rate limit: 20 req/s per UID.",
1958
+ description: "Place a SWAP/FUTURES algo order: TP/SL (conditional/oco) or trailing stop (move_order_stop). [CAUTION] Executes real trades. conditional: single TP, single SL, or both on one order. oco: TP+SL simultaneously \u2014 first trigger cancels the other. move_order_stop: provide callbackRatio (e.g. '0.01'=1%) OR callbackSpread, and optionally activePx. Set tpOrdPx='-1' or slOrdPx='-1' for market execution.",
1965
1959
  isWrite: true,
1966
1960
  inputSchema: {
1967
1961
  type: "object",
@@ -1987,8 +1981,8 @@ function registerAlgoTradeTools() {
1987
1981
  },
1988
1982
  ordType: {
1989
1983
  type: "string",
1990
- enum: ["conditional", "oco"],
1991
- description: "conditional=single TP/SL or both; oco=TP+SL pair (first trigger cancels other)"
1984
+ enum: ["conditional", "oco", "move_order_stop"],
1985
+ description: "conditional=single TP/SL or both; oco=TP+SL pair (first trigger cancels other); move_order_stop=trailing stop"
1992
1986
  },
1993
1987
  sz: {
1994
1988
  type: "string",
@@ -1996,29 +1990,41 @@ function registerAlgoTradeTools() {
1996
1990
  },
1997
1991
  tpTriggerPx: {
1998
1992
  type: "string",
1999
- description: "TP trigger price"
1993
+ description: "TP trigger price (conditional/oco only)"
2000
1994
  },
2001
1995
  tpOrdPx: {
2002
1996
  type: "string",
2003
- description: "TP order price; -1=market"
1997
+ description: "TP order price; -1=market (conditional/oco only)"
2004
1998
  },
2005
1999
  tpTriggerPxType: {
2006
2000
  type: "string",
2007
2001
  enum: ["last", "index", "mark"],
2008
- description: "last(default)|index|mark"
2002
+ description: "last(default)|index|mark (conditional/oco only)"
2009
2003
  },
2010
2004
  slTriggerPx: {
2011
2005
  type: "string",
2012
- description: "SL trigger price"
2006
+ description: "SL trigger price (conditional/oco only)"
2013
2007
  },
2014
2008
  slOrdPx: {
2015
2009
  type: "string",
2016
- description: "SL order price; -1=market (recommended)"
2010
+ description: "SL order price; -1=market (recommended) (conditional/oco only)"
2017
2011
  },
2018
2012
  slTriggerPxType: {
2019
2013
  type: "string",
2020
2014
  enum: ["last", "index", "mark"],
2021
- description: "last(default)|index|mark"
2015
+ description: "last(default)|index|mark (conditional/oco only)"
2016
+ },
2017
+ callbackRatio: {
2018
+ type: "string",
2019
+ description: "Callback ratio (e.g. '0.01'=1%); provide either ratio or spread (move_order_stop only)"
2020
+ },
2021
+ callbackSpread: {
2022
+ type: "string",
2023
+ description: "Callback spread in price units; provide either ratio or spread (move_order_stop only)"
2024
+ },
2025
+ activePx: {
2026
+ type: "string",
2027
+ description: "Activation price; tracking starts after market reaches this level (move_order_stop only)"
2022
2028
  },
2023
2029
  reduceOnly: {
2024
2030
  type: "boolean",
@@ -2049,19 +2055,22 @@ function registerAlgoTradeTools() {
2049
2055
  slTriggerPx: readString(args, "slTriggerPx"),
2050
2056
  slOrdPx: readString(args, "slOrdPx"),
2051
2057
  slTriggerPxType: readString(args, "slTriggerPxType"),
2058
+ callBackRatio: readString(args, "callbackRatio"),
2059
+ callBackSpread: readString(args, "callbackSpread"),
2060
+ activePx: readString(args, "activePx"),
2052
2061
  reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
2053
2062
  clOrdId: readString(args, "clOrdId"),
2054
2063
  tag: context.config.sourceTag
2055
2064
  }),
2056
2065
  privateRateLimit("swap_place_algo_order", 20)
2057
2066
  );
2058
- return normalize2(response);
2067
+ return normalizeResponse(response);
2059
2068
  }
2060
2069
  },
2061
2070
  {
2062
2071
  name: "swap_place_move_stop_order",
2063
2072
  module: "swap",
2064
- description: "Place a SWAP/FUTURES trailing stop order (move_order_stop). [CAUTION] Executes real trades. The order tracks the market price and triggers when the price reverses by the callback amount. Specify either callbackRatio (e.g. '0.01' for 1%) or callbackSpread (fixed price distance), not both. Optionally set activePx so tracking only starts once the market reaches that price. Private endpoint. Rate limit: 20 req/s per UID.",
2073
+ description: "[DEPRECATED] Use swap_place_algo_order with ordType='move_order_stop' instead. Place a SWAP/FUTURES trailing stop order. [CAUTION] Executes real trades. Specify callbackRatio (e.g. '0.01'=1%) or callbackSpread (fixed price distance), not both. Optionally set activePx so tracking starts once market reaches that price.",
2065
2074
  isWrite: true,
2066
2075
  inputSchema: {
2067
2076
  type: "object",
@@ -2124,21 +2133,21 @@ function registerAlgoTradeTools() {
2124
2133
  posSide: readString(args, "posSide"),
2125
2134
  ordType: "move_order_stop",
2126
2135
  sz: requireString(args, "sz"),
2127
- callbackRatio: readString(args, "callbackRatio"),
2128
- callbackSpread: readString(args, "callbackSpread"),
2136
+ callBackRatio: readString(args, "callbackRatio"),
2137
+ callBackSpread: readString(args, "callbackSpread"),
2129
2138
  activePx: readString(args, "activePx"),
2130
2139
  reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
2131
2140
  clOrdId: readString(args, "clOrdId")
2132
2141
  }),
2133
2142
  privateRateLimit("swap_place_move_stop_order", 20)
2134
2143
  );
2135
- return normalize2(response);
2144
+ return normalizeResponse(response);
2136
2145
  }
2137
2146
  },
2138
2147
  {
2139
2148
  name: "swap_cancel_algo_orders",
2140
2149
  module: "swap",
2141
- description: "Cancel one or more pending SWAP/FUTURES algo orders (TP/SL). Accepts a list of {algoId, instId} objects. Private endpoint. Rate limit: 20 req/s per UID.",
2150
+ description: "Cancel one or more pending SWAP/FUTURES algo orders (TP/SL). Accepts a list of {algoId, instId} objects.",
2142
2151
  isWrite: true,
2143
2152
  inputSchema: {
2144
2153
  type: "object",
@@ -2175,13 +2184,13 @@ function registerAlgoTradeTools() {
2175
2184
  orders,
2176
2185
  privateRateLimit("swap_cancel_algo_orders", 20)
2177
2186
  );
2178
- return normalize2(response);
2187
+ return normalizeResponse(response);
2179
2188
  }
2180
2189
  },
2181
2190
  {
2182
2191
  name: "swap_get_algo_orders",
2183
2192
  module: "swap",
2184
- description: "Query pending or completed SWAP/FUTURES algo orders (TP/SL, OCO, trailing stop). Private endpoint. Rate limit: 20 req/s.",
2193
+ description: "Query pending or completed SWAP/FUTURES algo orders (TP/SL, OCO, trailing stop).",
2185
2194
  isWrite: false,
2186
2195
  inputSchema: {
2187
2196
  type: "object",
@@ -2191,6 +2200,11 @@ function registerAlgoTradeTools() {
2191
2200
  enum: ["pending", "history"],
2192
2201
  description: "pending=active (default); history=completed"
2193
2202
  },
2203
+ instType: {
2204
+ type: "string",
2205
+ enum: ["SWAP", "FUTURES"],
2206
+ description: "SWAP (default) or FUTURES"
2207
+ },
2194
2208
  ordType: {
2195
2209
  type: "string",
2196
2210
  enum: ["conditional", "oco", "move_order_stop"],
@@ -2230,8 +2244,9 @@ function registerAlgoTradeTools() {
2230
2244
  const path4 = isHistory ? "/api/v5/trade/orders-algo-history" : "/api/v5/trade/orders-algo-pending";
2231
2245
  const ordType = readString(args, "ordType");
2232
2246
  const state = isHistory ? readString(args, "state") ?? "effective" : void 0;
2247
+ const instType = readString(args, "instType") ?? "SWAP";
2233
2248
  const baseParams = compactObject({
2234
- instType: "SWAP",
2249
+ instType,
2235
2250
  instId: readString(args, "instId"),
2236
2251
  algoId: readString(args, "algoId"),
2237
2252
  after: readString(args, "after"),
@@ -2245,7 +2260,7 @@ function registerAlgoTradeTools() {
2245
2260
  { ...baseParams, ordType },
2246
2261
  privateRateLimit("swap_get_algo_orders", 20)
2247
2262
  );
2248
- return normalize2(response);
2263
+ return normalizeResponse(response);
2249
2264
  }
2250
2265
  const [r1, r2, r3] = await Promise.all([
2251
2266
  context.client.privateGet(path4, { ...baseParams, ordType: "conditional" }, privateRateLimit("swap_get_algo_orders", 20)),
@@ -2262,193 +2277,537 @@ function registerAlgoTradeTools() {
2262
2277
  }
2263
2278
  ];
2264
2279
  }
2265
- var DEFAULT_LOG_DIR = path.join(os.homedir(), ".okx", "logs");
2266
- function getLogPaths(logDir, days = 7) {
2267
- const paths = [];
2268
- const now = /* @__PURE__ */ new Date();
2269
- for (let i = 0; i < days; i++) {
2270
- const d = new Date(now);
2271
- d.setUTCDate(now.getUTCDate() - i);
2272
- const yyyy = d.getUTCFullYear();
2273
- const mm = String(d.getUTCMonth() + 1).padStart(2, "0");
2274
- const dd = String(d.getUTCDate()).padStart(2, "0");
2275
- paths.push(path.join(logDir, `trade-${yyyy}-${mm}-${dd}.log`));
2276
- }
2277
- return paths;
2278
- }
2279
- function readEntries(logDir) {
2280
- const entries = [];
2281
- for (const filePath of getLogPaths(logDir)) {
2282
- let content;
2283
- try {
2284
- content = fs.readFileSync(filePath, "utf8");
2285
- } catch {
2286
- continue;
2287
- }
2288
- for (const line of content.split("\n")) {
2289
- const trimmed = line.trim();
2290
- if (!trimmed) continue;
2291
- try {
2292
- entries.push(JSON.parse(trimmed));
2293
- } catch {
2294
- }
2295
- }
2296
- }
2297
- return entries;
2298
- }
2299
- function registerAuditTools() {
2280
+ function registerFuturesAlgoTools() {
2300
2281
  return [
2301
2282
  {
2302
- name: "trade_get_history",
2303
- module: "account",
2304
- description: "Query local audit log of tool calls made through this MCP server. Returns recent operations with timestamps, duration, params, and results. Use to review what trades or queries were executed in this session or past sessions.",
2305
- isWrite: false,
2283
+ name: "futures_place_algo_order",
2284
+ module: "futures",
2285
+ description: "Place a FUTURES delivery algo order: TP/SL (conditional/oco) or trailing stop (move_order_stop). [CAUTION] Executes real trades. conditional: single TP, single SL, or both on one order. oco: TP+SL simultaneously \u2014 first trigger cancels the other. move_order_stop: provide callbackRatio (e.g. '0.01'=1%) OR callbackSpread, and optionally activePx. Set tpOrdPx='-1' or slOrdPx='-1' for market execution.",
2286
+ isWrite: true,
2306
2287
  inputSchema: {
2307
2288
  type: "object",
2308
2289
  properties: {
2309
- limit: {
2310
- type: "number",
2311
- description: "Max results (default 20)"
2290
+ instId: {
2291
+ type: "string",
2292
+ description: "e.g. BTC-USDT-240329"
2312
2293
  },
2313
- tool: {
2294
+ tdMode: {
2314
2295
  type: "string",
2315
- description: "e.g. swap_place_order"
2296
+ enum: ["cross", "isolated"],
2297
+ description: "cross|isolated margin"
2316
2298
  },
2317
- level: {
2299
+ side: {
2318
2300
  type: "string",
2319
- enum: ["INFO", "WARN", "ERROR", "DEBUG"]
2301
+ enum: ["buy", "sell"],
2302
+ description: "sell=close long, buy=close short"
2320
2303
  },
2321
- since: {
2304
+ posSide: {
2322
2305
  type: "string",
2323
- description: "ISO 8601 timestamp lower bound"
2324
- }
2325
- }
2326
- },
2327
- handler: async (rawArgs) => {
2328
- const args = asRecord(rawArgs);
2329
- const limit = Math.min(readNumber(args, "limit") ?? 20, 100);
2330
- const toolFilter = readString(args, "tool");
2331
- const levelFilter = readString(args, "level")?.toUpperCase();
2332
- const since = readString(args, "since");
2333
- const sinceTime = since ? new Date(since).getTime() : void 0;
2334
- let entries = readEntries(DEFAULT_LOG_DIR);
2335
- if (toolFilter) {
2336
- entries = entries.filter((e) => e.tool === toolFilter);
2337
- }
2338
- if (levelFilter) {
2339
- entries = entries.filter((e) => e.level === levelFilter);
2340
- }
2341
- if (sinceTime !== void 0) {
2342
- entries = entries.filter((e) => new Date(e.timestamp).getTime() >= sinceTime);
2343
- }
2344
- entries.sort(
2345
- (a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
2346
- );
2347
- entries = entries.slice(0, limit);
2348
- return { entries, total: entries.length };
2349
- }
2350
- }
2351
- ];
2352
- }
2353
- function normalize3(response) {
2354
- return {
2355
- endpoint: response.endpoint,
2356
- requestTime: response.requestTime,
2357
- data: response.data
2358
- };
2359
- }
2360
- function normalizeWrite(response) {
2361
- const data = response.data;
2362
- if (Array.isArray(data) && data.length > 0) {
2363
- const failed = data.filter(
2364
- (item) => item !== null && typeof item === "object" && "sCode" in item && item["sCode"] !== "0"
2365
- );
2366
- if (failed.length > 0) {
2367
- const messages2 = failed.map(
2368
- (item) => `[${item["sCode"]}] ${item["sMsg"] ?? "Operation failed"}`
2369
- );
2370
- throw new OkxApiError(messages2.join("; "), {
2371
- code: String(failed[0]["sCode"] ?? ""),
2372
- endpoint: response.endpoint
2373
- });
2374
- }
2375
- }
2376
- return {
2377
- endpoint: response.endpoint,
2378
- requestTime: response.requestTime,
2379
- data
2380
- };
2381
- }
2382
- function registerGridTools() {
2383
- return [
2384
- {
2385
- name: "grid_get_orders",
2386
- module: "bot.grid",
2387
- description: "Query grid trading bot list. Use status='active' for running bots, status='history' for completed/stopped bots. Covers Spot Grid, Contract Grid, and Moon Grid. Private endpoint. Rate limit: 20 req/2s per UID.",
2388
- isWrite: false,
2389
- inputSchema: {
2390
- type: "object",
2391
- properties: {
2392
- algoOrdType: {
2306
+ enum: ["long", "short", "net"],
2307
+ description: "net=one-way (default); long/short=hedge mode"
2308
+ },
2309
+ ordType: {
2393
2310
  type: "string",
2394
- enum: ["grid", "contract_grid", "moon_grid"],
2395
- description: "Grid bot type. grid=Spot, contract_grid=Contract, moon_grid=Moon. Must match the bot's actual type when filtering by algoId."
2311
+ enum: ["conditional", "oco", "move_order_stop"],
2312
+ description: "conditional=single TP/SL or both; oco=TP+SL pair; move_order_stop=trailing stop"
2396
2313
  },
2397
- status: {
2314
+ sz: {
2398
2315
  type: "string",
2399
- enum: ["active", "history"],
2400
- description: "active=running (default); history=stopped"
2316
+ description: "Number of contracts (NOT USDT amount)."
2401
2317
  },
2402
- instId: {
2318
+ tpTriggerPx: {
2403
2319
  type: "string",
2404
- description: "e.g. BTC-USDT"
2320
+ description: "TP trigger price (conditional/oco only)"
2405
2321
  },
2406
- algoId: {
2322
+ tpOrdPx: {
2407
2323
  type: "string",
2408
- description: "Grid bot algo order ID (returned by grid_create_order or grid_get_orders). This is NOT a normal trade order ID."
2324
+ description: "TP order price; -1=market (conditional/oco only)"
2409
2325
  },
2410
- after: {
2326
+ tpTriggerPxType: {
2411
2327
  type: "string",
2412
- description: "Pagination: before this algo ID"
2328
+ enum: ["last", "index", "mark"],
2329
+ description: "last(default)|index|mark (conditional/oco only)"
2413
2330
  },
2414
- before: {
2331
+ slTriggerPx: {
2415
2332
  type: "string",
2416
- description: "Pagination: after this algo ID"
2333
+ description: "SL trigger price (conditional/oco only)"
2417
2334
  },
2418
- limit: {
2419
- type: "number",
2420
- description: "Max results (default 100)"
2335
+ slOrdPx: {
2336
+ type: "string",
2337
+ description: "SL order price; -1=market (conditional/oco only)"
2338
+ },
2339
+ slTriggerPxType: {
2340
+ type: "string",
2341
+ enum: ["last", "index", "mark"],
2342
+ description: "last(default)|index|mark (conditional/oco only)"
2343
+ },
2344
+ callbackRatio: {
2345
+ type: "string",
2346
+ description: "Callback ratio (e.g. '0.01'=1%); provide either ratio or spread (move_order_stop only)"
2347
+ },
2348
+ callbackSpread: {
2349
+ type: "string",
2350
+ description: "Callback spread in price units (move_order_stop only)"
2351
+ },
2352
+ activePx: {
2353
+ type: "string",
2354
+ description: "Activation price; tracking starts after market reaches this level (move_order_stop only)"
2355
+ },
2356
+ reduceOnly: {
2357
+ type: "boolean",
2358
+ description: "Ensure order only reduces position"
2359
+ },
2360
+ clOrdId: {
2361
+ type: "string",
2362
+ description: "Client order ID (max 32 chars)"
2421
2363
  }
2422
2364
  },
2423
- required: ["algoOrdType"]
2365
+ required: ["instId", "tdMode", "side", "ordType", "sz"]
2424
2366
  },
2425
2367
  handler: async (rawArgs, context) => {
2426
2368
  const args = asRecord(rawArgs);
2427
- const algoOrdType = requireString(args, "algoOrdType");
2428
- const status = readString(args, "status") ?? "active";
2429
- const path4 = status === "history" ? "/api/v5/tradingBot/grid/orders-algo-history" : "/api/v5/tradingBot/grid/orders-algo-pending";
2430
- const response = await context.client.privateGet(
2431
- path4,
2369
+ const reduceOnly = args.reduceOnly;
2370
+ const response = await context.client.privatePost(
2371
+ "/api/v5/trade/order-algo",
2432
2372
  compactObject({
2433
- algoOrdType,
2434
- instId: readString(args, "instId"),
2435
- algoId: readString(args, "algoId"),
2436
- after: readString(args, "after"),
2437
- before: readString(args, "before"),
2438
- limit: readNumber(args, "limit")
2439
- }),
2440
- privateRateLimit("grid_get_orders", 20)
2441
- );
2442
- return normalize3(response);
2443
- }
2444
- },
2445
- {
2446
- name: "grid_get_order_details",
2447
- module: "bot.grid",
2448
- description: "Query details of a single grid trading bot by its algo ID. Returns configuration, current status, PnL, and position info. Private endpoint. Rate limit: 20 req/2s per UID.",
2449
- isWrite: false,
2450
- inputSchema: {
2451
- type: "object",
2373
+ instId: requireString(args, "instId"),
2374
+ tdMode: requireString(args, "tdMode"),
2375
+ side: requireString(args, "side"),
2376
+ posSide: readString(args, "posSide"),
2377
+ ordType: requireString(args, "ordType"),
2378
+ sz: requireString(args, "sz"),
2379
+ tpTriggerPx: readString(args, "tpTriggerPx"),
2380
+ tpOrdPx: readString(args, "tpOrdPx"),
2381
+ tpTriggerPxType: readString(args, "tpTriggerPxType"),
2382
+ slTriggerPx: readString(args, "slTriggerPx"),
2383
+ slOrdPx: readString(args, "slOrdPx"),
2384
+ slTriggerPxType: readString(args, "slTriggerPxType"),
2385
+ callBackRatio: readString(args, "callbackRatio"),
2386
+ callBackSpread: readString(args, "callbackSpread"),
2387
+ activePx: readString(args, "activePx"),
2388
+ reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
2389
+ clOrdId: readString(args, "clOrdId"),
2390
+ tag: context.config.sourceTag
2391
+ }),
2392
+ privateRateLimit("futures_place_algo_order", 20)
2393
+ );
2394
+ return normalizeResponse(response);
2395
+ }
2396
+ },
2397
+ {
2398
+ name: "futures_place_move_stop_order",
2399
+ module: "futures",
2400
+ description: "[DEPRECATED] Use futures_place_algo_order with ordType='move_order_stop' instead. Place a FUTURES delivery trailing stop order. [CAUTION] Executes real trades.",
2401
+ isWrite: true,
2402
+ inputSchema: {
2403
+ type: "object",
2404
+ properties: {
2405
+ instId: {
2406
+ type: "string",
2407
+ description: "e.g. BTC-USDT-240329"
2408
+ },
2409
+ tdMode: {
2410
+ type: "string",
2411
+ enum: ["cross", "isolated"],
2412
+ description: "cross|isolated margin"
2413
+ },
2414
+ side: {
2415
+ type: "string",
2416
+ enum: ["buy", "sell"],
2417
+ description: "sell=close long, buy=close short"
2418
+ },
2419
+ posSide: {
2420
+ type: "string",
2421
+ enum: ["long", "short", "net"],
2422
+ description: "net=one-way (default); long/short=hedge mode"
2423
+ },
2424
+ sz: {
2425
+ type: "string",
2426
+ description: "Number of contracts (NOT USDT amount)."
2427
+ },
2428
+ callbackRatio: {
2429
+ type: "string",
2430
+ description: "Callback ratio (e.g. '0.01'=1%); provide either ratio or spread"
2431
+ },
2432
+ callbackSpread: {
2433
+ type: "string",
2434
+ description: "Callback spread in price units; provide either ratio or spread"
2435
+ },
2436
+ activePx: {
2437
+ type: "string",
2438
+ description: "Activation price"
2439
+ },
2440
+ reduceOnly: {
2441
+ type: "boolean",
2442
+ description: "Ensure order only reduces position"
2443
+ },
2444
+ clOrdId: {
2445
+ type: "string",
2446
+ description: "Client order ID (max 32 chars)"
2447
+ }
2448
+ },
2449
+ required: ["instId", "tdMode", "side", "sz"]
2450
+ },
2451
+ handler: async (rawArgs, context) => {
2452
+ const args = asRecord(rawArgs);
2453
+ const reduceOnly = args.reduceOnly;
2454
+ const response = await context.client.privatePost(
2455
+ "/api/v5/trade/order-algo",
2456
+ compactObject({
2457
+ instId: requireString(args, "instId"),
2458
+ tdMode: requireString(args, "tdMode"),
2459
+ side: requireString(args, "side"),
2460
+ posSide: readString(args, "posSide"),
2461
+ ordType: "move_order_stop",
2462
+ sz: requireString(args, "sz"),
2463
+ callBackRatio: readString(args, "callbackRatio"),
2464
+ callBackSpread: readString(args, "callbackSpread"),
2465
+ activePx: readString(args, "activePx"),
2466
+ reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
2467
+ clOrdId: readString(args, "clOrdId")
2468
+ }),
2469
+ privateRateLimit("futures_place_move_stop_order", 20)
2470
+ );
2471
+ return normalizeResponse(response);
2472
+ }
2473
+ },
2474
+ {
2475
+ name: "futures_amend_algo_order",
2476
+ module: "futures",
2477
+ description: "Amend a pending FUTURES delivery algo order (modify TP/SL prices or size).",
2478
+ isWrite: true,
2479
+ inputSchema: {
2480
+ type: "object",
2481
+ properties: {
2482
+ instId: { type: "string", description: "e.g. BTC-USDT-240329" },
2483
+ algoId: { type: "string", description: "Algo order ID" },
2484
+ newSz: { type: "string", description: "New number of contracts" },
2485
+ newTpTriggerPx: { type: "string", description: "New TP trigger price" },
2486
+ newTpOrdPx: { type: "string", description: "New TP order price; -1=market" },
2487
+ newSlTriggerPx: { type: "string", description: "New SL trigger price" },
2488
+ newSlOrdPx: { type: "string", description: "New SL order price; -1=market" }
2489
+ },
2490
+ required: ["instId", "algoId"]
2491
+ },
2492
+ handler: async (rawArgs, context) => {
2493
+ const args = asRecord(rawArgs);
2494
+ const response = await context.client.privatePost(
2495
+ "/api/v5/trade/amend-algos",
2496
+ compactObject({
2497
+ instId: requireString(args, "instId"),
2498
+ algoId: requireString(args, "algoId"),
2499
+ newSz: readString(args, "newSz"),
2500
+ newTpTriggerPx: readString(args, "newTpTriggerPx"),
2501
+ newTpOrdPx: readString(args, "newTpOrdPx"),
2502
+ newSlTriggerPx: readString(args, "newSlTriggerPx"),
2503
+ newSlOrdPx: readString(args, "newSlOrdPx")
2504
+ }),
2505
+ privateRateLimit("futures_amend_algo_order", 20)
2506
+ );
2507
+ return normalizeResponse(response);
2508
+ }
2509
+ },
2510
+ {
2511
+ name: "futures_cancel_algo_orders",
2512
+ module: "futures",
2513
+ description: "Cancel one or more pending FUTURES delivery algo orders (TP/SL). Accepts a list of {algoId, instId} objects.",
2514
+ isWrite: true,
2515
+ inputSchema: {
2516
+ type: "object",
2517
+ properties: {
2518
+ orders: {
2519
+ type: "array",
2520
+ description: "List of algo orders to cancel. Each item: {algoId, instId}.",
2521
+ items: {
2522
+ type: "object",
2523
+ properties: {
2524
+ algoId: { type: "string", description: "Algo order ID" },
2525
+ instId: { type: "string", description: "e.g. BTC-USDT-240329" }
2526
+ },
2527
+ required: ["algoId", "instId"]
2528
+ }
2529
+ }
2530
+ },
2531
+ required: ["orders"]
2532
+ },
2533
+ handler: async (rawArgs, context) => {
2534
+ const args = asRecord(rawArgs);
2535
+ const orders = args.orders;
2536
+ if (!Array.isArray(orders) || orders.length === 0) {
2537
+ throw new Error("orders must be a non-empty array.");
2538
+ }
2539
+ const response = await context.client.privatePost(
2540
+ "/api/v5/trade/cancel-algos",
2541
+ orders,
2542
+ privateRateLimit("futures_cancel_algo_orders", 20)
2543
+ );
2544
+ return normalizeResponse(response);
2545
+ }
2546
+ },
2547
+ {
2548
+ name: "futures_get_algo_orders",
2549
+ module: "futures",
2550
+ description: "Query pending or completed FUTURES delivery algo orders (TP/SL, OCO, trailing stop).",
2551
+ isWrite: false,
2552
+ inputSchema: {
2553
+ type: "object",
2554
+ properties: {
2555
+ status: {
2556
+ type: "string",
2557
+ enum: ["pending", "history"],
2558
+ description: "pending=active (default); history=completed"
2559
+ },
2560
+ ordType: {
2561
+ type: "string",
2562
+ enum: ["conditional", "oco", "move_order_stop"],
2563
+ description: "Filter by type; omit for all"
2564
+ },
2565
+ instId: {
2566
+ type: "string",
2567
+ description: "Instrument ID filter"
2568
+ },
2569
+ algoId: {
2570
+ type: "string",
2571
+ description: "Filter by algo order ID"
2572
+ },
2573
+ after: {
2574
+ type: "string",
2575
+ description: "Pagination: before this algo ID"
2576
+ },
2577
+ before: {
2578
+ type: "string",
2579
+ description: "Pagination: after this algo ID"
2580
+ },
2581
+ limit: {
2582
+ type: "number",
2583
+ description: "Max results (default 100)"
2584
+ },
2585
+ state: {
2586
+ type: "string",
2587
+ enum: ["effective", "canceled", "order_failed"],
2588
+ description: "Required when status=history. effective=triggered, canceled, order_failed. Defaults to effective."
2589
+ }
2590
+ }
2591
+ },
2592
+ handler: async (rawArgs, context) => {
2593
+ const args = asRecord(rawArgs);
2594
+ const status = readString(args, "status") ?? "pending";
2595
+ const isHistory = status === "history";
2596
+ const path4 = isHistory ? "/api/v5/trade/orders-algo-history" : "/api/v5/trade/orders-algo-pending";
2597
+ const ordType = readString(args, "ordType");
2598
+ const state = isHistory ? readString(args, "state") ?? "effective" : void 0;
2599
+ const baseParams = compactObject({
2600
+ instType: "FUTURES",
2601
+ instId: readString(args, "instId"),
2602
+ algoId: readString(args, "algoId"),
2603
+ after: readString(args, "after"),
2604
+ before: readString(args, "before"),
2605
+ limit: readNumber(args, "limit"),
2606
+ state
2607
+ });
2608
+ if (ordType) {
2609
+ const response = await context.client.privateGet(
2610
+ path4,
2611
+ { ...baseParams, ordType },
2612
+ privateRateLimit("futures_get_algo_orders", 20)
2613
+ );
2614
+ return normalizeResponse(response);
2615
+ }
2616
+ const [r1, r2, r3] = await Promise.all([
2617
+ context.client.privateGet(path4, { ...baseParams, ordType: "conditional" }, privateRateLimit("futures_get_algo_orders", 20)),
2618
+ context.client.privateGet(path4, { ...baseParams, ordType: "oco" }, privateRateLimit("futures_get_algo_orders", 20)),
2619
+ context.client.privateGet(path4, { ...baseParams, ordType: "move_order_stop" }, privateRateLimit("futures_get_algo_orders", 20))
2620
+ ]);
2621
+ const merged = [
2622
+ ...r1.data ?? [],
2623
+ ...r2.data ?? [],
2624
+ ...r3.data ?? []
2625
+ ];
2626
+ return { endpoint: r1.endpoint, requestTime: r1.requestTime, data: merged };
2627
+ }
2628
+ }
2629
+ ];
2630
+ }
2631
+ var DEFAULT_LOG_DIR = path.join(os.homedir(), ".okx", "logs");
2632
+ function getLogPaths(logDir, days = 7) {
2633
+ const paths = [];
2634
+ const now = /* @__PURE__ */ new Date();
2635
+ for (let i = 0; i < days; i++) {
2636
+ const d = new Date(now);
2637
+ d.setUTCDate(now.getUTCDate() - i);
2638
+ const yyyy = d.getUTCFullYear();
2639
+ const mm = String(d.getUTCMonth() + 1).padStart(2, "0");
2640
+ const dd = String(d.getUTCDate()).padStart(2, "0");
2641
+ paths.push(path.join(logDir, `trade-${yyyy}-${mm}-${dd}.log`));
2642
+ }
2643
+ return paths;
2644
+ }
2645
+ function readEntries(logDir) {
2646
+ const entries = [];
2647
+ for (const filePath of getLogPaths(logDir)) {
2648
+ let content;
2649
+ try {
2650
+ content = fs.readFileSync(filePath, "utf8");
2651
+ } catch {
2652
+ continue;
2653
+ }
2654
+ for (const line of content.split("\n")) {
2655
+ const trimmed = line.trim();
2656
+ if (!trimmed) continue;
2657
+ try {
2658
+ entries.push(JSON.parse(trimmed));
2659
+ } catch {
2660
+ }
2661
+ }
2662
+ }
2663
+ return entries;
2664
+ }
2665
+ function registerAuditTools() {
2666
+ return [
2667
+ {
2668
+ name: "trade_get_history",
2669
+ module: "account",
2670
+ description: "Query local audit log of tool calls made through this MCP server. Returns recent operations with timestamps, duration, params, and results. Use to review what trades or queries were executed in this session or past sessions.",
2671
+ isWrite: false,
2672
+ inputSchema: {
2673
+ type: "object",
2674
+ properties: {
2675
+ limit: {
2676
+ type: "number",
2677
+ description: "Max results (default 20)"
2678
+ },
2679
+ tool: {
2680
+ type: "string",
2681
+ description: "e.g. swap_place_order"
2682
+ },
2683
+ level: {
2684
+ type: "string",
2685
+ enum: ["INFO", "WARN", "ERROR", "DEBUG"]
2686
+ },
2687
+ since: {
2688
+ type: "string",
2689
+ description: "ISO 8601 timestamp lower bound"
2690
+ }
2691
+ }
2692
+ },
2693
+ handler: async (rawArgs) => {
2694
+ const args = asRecord(rawArgs);
2695
+ const limit = Math.min(readNumber(args, "limit") ?? 20, 100);
2696
+ const toolFilter = readString(args, "tool");
2697
+ const levelFilter = readString(args, "level")?.toUpperCase();
2698
+ const since = readString(args, "since");
2699
+ const sinceTime = since ? new Date(since).getTime() : void 0;
2700
+ let entries = readEntries(DEFAULT_LOG_DIR);
2701
+ if (toolFilter) {
2702
+ entries = entries.filter((e) => e.tool === toolFilter);
2703
+ }
2704
+ if (levelFilter) {
2705
+ entries = entries.filter((e) => e.level === levelFilter);
2706
+ }
2707
+ if (sinceTime !== void 0) {
2708
+ entries = entries.filter((e) => new Date(e.timestamp).getTime() >= sinceTime);
2709
+ }
2710
+ entries.sort(
2711
+ (a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
2712
+ );
2713
+ entries = entries.slice(0, limit);
2714
+ return { entries, total: entries.length };
2715
+ }
2716
+ }
2717
+ ];
2718
+ }
2719
+ function normalizeWrite(response) {
2720
+ const data = response.data;
2721
+ if (Array.isArray(data) && data.length > 0) {
2722
+ const failed = data.filter(
2723
+ (item) => item !== null && typeof item === "object" && "sCode" in item && item["sCode"] !== "0"
2724
+ );
2725
+ if (failed.length > 0) {
2726
+ const messages2 = failed.map(
2727
+ (item) => `[${item["sCode"]}] ${item["sMsg"] ?? "Operation failed"}`
2728
+ );
2729
+ throw new OkxApiError(messages2.join("; "), {
2730
+ code: String(failed[0]["sCode"] ?? ""),
2731
+ endpoint: response.endpoint
2732
+ });
2733
+ }
2734
+ }
2735
+ return {
2736
+ endpoint: response.endpoint,
2737
+ requestTime: response.requestTime,
2738
+ data
2739
+ };
2740
+ }
2741
+ function registerGridTools() {
2742
+ return [
2743
+ {
2744
+ name: "grid_get_orders",
2745
+ module: "bot.grid",
2746
+ description: "Query grid trading bot list. status='active' for running bots; status='history' for completed/stopped. Covers Spot Grid, Contract Grid, and Moon Grid.",
2747
+ isWrite: false,
2748
+ inputSchema: {
2749
+ type: "object",
2750
+ properties: {
2751
+ algoOrdType: {
2752
+ type: "string",
2753
+ enum: ["grid", "contract_grid", "moon_grid"],
2754
+ description: "Grid bot type. grid=Spot, contract_grid=Contract, moon_grid=Moon. Must match the bot's actual type when filtering by algoId."
2755
+ },
2756
+ status: {
2757
+ type: "string",
2758
+ enum: ["active", "history"],
2759
+ description: "active=running (default); history=stopped"
2760
+ },
2761
+ instId: {
2762
+ type: "string",
2763
+ description: "e.g. BTC-USDT"
2764
+ },
2765
+ algoId: {
2766
+ type: "string",
2767
+ description: "Grid bot algo order ID (returned by grid_create_order or grid_get_orders). This is NOT a normal trade order ID."
2768
+ },
2769
+ after: {
2770
+ type: "string",
2771
+ description: "Pagination: before this algo ID"
2772
+ },
2773
+ before: {
2774
+ type: "string",
2775
+ description: "Pagination: after this algo ID"
2776
+ },
2777
+ limit: {
2778
+ type: "number",
2779
+ description: "Max results (default 100)"
2780
+ }
2781
+ },
2782
+ required: ["algoOrdType"]
2783
+ },
2784
+ handler: async (rawArgs, context) => {
2785
+ const args = asRecord(rawArgs);
2786
+ const algoOrdType = requireString(args, "algoOrdType");
2787
+ const status = readString(args, "status") ?? "active";
2788
+ const path4 = status === "history" ? "/api/v5/tradingBot/grid/orders-algo-history" : "/api/v5/tradingBot/grid/orders-algo-pending";
2789
+ const response = await context.client.privateGet(
2790
+ path4,
2791
+ compactObject({
2792
+ algoOrdType,
2793
+ instId: readString(args, "instId"),
2794
+ algoId: readString(args, "algoId"),
2795
+ after: readString(args, "after"),
2796
+ before: readString(args, "before"),
2797
+ limit: readNumber(args, "limit")
2798
+ }),
2799
+ privateRateLimit("grid_get_orders", 20)
2800
+ );
2801
+ return normalizeResponse(response);
2802
+ }
2803
+ },
2804
+ {
2805
+ name: "grid_get_order_details",
2806
+ module: "bot.grid",
2807
+ description: "Query details of a single grid trading bot by its algo ID. Returns configuration, current status, PnL, and position info.",
2808
+ isWrite: false,
2809
+ inputSchema: {
2810
+ type: "object",
2452
2811
  properties: {
2453
2812
  algoOrdType: {
2454
2813
  type: "string",
@@ -2472,13 +2831,13 @@ function registerGridTools() {
2472
2831
  },
2473
2832
  privateRateLimit("grid_get_order_details", 20)
2474
2833
  );
2475
- return normalize3(response);
2834
+ return normalizeResponse(response);
2476
2835
  }
2477
2836
  },
2478
2837
  {
2479
2838
  name: "grid_get_sub_orders",
2480
2839
  module: "bot.grid",
2481
- description: "Query individual sub-orders (grid trades) generated by a grid bot. Use type='filled' for executed trades, type='live' for pending orders. Private endpoint. Rate limit: 20 req/2s per UID.",
2840
+ description: "Query individual sub-orders (grid trades) generated by a grid bot. type='filled' for executed trades; type='live' for pending orders.",
2482
2841
  isWrite: false,
2483
2842
  inputSchema: {
2484
2843
  type: "object",
@@ -2531,13 +2890,13 @@ function registerGridTools() {
2531
2890
  }),
2532
2891
  privateRateLimit("grid_get_sub_orders", 20)
2533
2892
  );
2534
- return normalize3(response);
2893
+ return normalizeResponse(response);
2535
2894
  }
2536
2895
  },
2537
2896
  {
2538
2897
  name: "grid_create_order",
2539
2898
  module: "bot.grid",
2540
- description: "Create a new grid trading bot. [CAUTION] Executes real trades and locks funds. Supports Spot Grid ('grid') and Contract Grid ('contract_grid'). For spot grid, provide quoteSz (invest in quote currency) or baseSz (invest in base currency). For contract grids, provide direction, lever, and sz (investment amount in margin currency, e.g. USDT for USDT-margined contracts). Private endpoint. Rate limit: 20 req/2s per UID.",
2899
+ description: "Create a new grid trading bot. [CAUTION] Executes real trades and locks funds. Supports Spot Grid ('grid') and Contract Grid ('contract_grid'). For spot: provide quoteSz or baseSz. For contract: provide direction, lever, and sz.",
2541
2900
  isWrite: true,
2542
2901
  inputSchema: {
2543
2902
  type: "object",
@@ -2628,7 +2987,7 @@ function registerGridTools() {
2628
2987
  {
2629
2988
  name: "grid_stop_order",
2630
2989
  module: "bot.grid",
2631
- description: "Stop a running grid trading bot. [CAUTION] This will close or cancel the bot's orders. For contract grids, stopType controls whether open positions are closed ('1') or only orders are cancelled ('2'). Private endpoint. Rate limit: 20 req/2s per UID.",
2990
+ description: "Stop a running grid trading bot. [CAUTION] This will close or cancel the bot's orders. For contract grids, stopType controls whether positions are closed ('1') or only orders cancelled ('2').",
2632
2991
  isWrite: true,
2633
2992
  inputSchema: {
2634
2993
  type: "object",
@@ -2672,13 +3031,6 @@ function registerGridTools() {
2672
3031
  ];
2673
3032
  }
2674
3033
  var BASE = "/api/v5/tradingBot/dca";
2675
- function normalize4(response) {
2676
- return {
2677
- endpoint: response.endpoint,
2678
- requestTime: response.requestTime,
2679
- data: response.data
2680
- };
2681
- }
2682
3034
  function normalizeWrite2(response) {
2683
3035
  const data = response.data;
2684
3036
  if (Array.isArray(data) && data.length > 0) {
@@ -2706,7 +3058,7 @@ function registerDcaTools() {
2706
3058
  {
2707
3059
  name: "dca_create_order",
2708
3060
  module: "bot.dca",
2709
- description: "Create a Contract DCA (Martingale) bot order with leverage on futures/swaps. Required: instId, lever, direction, initOrdAmt, maxSafetyOrds, tpPct. Conditionally required (when maxSafetyOrds > 0): safetyOrdAmt, pxSteps, pxStepsMult, volMult. Optional: slPct, slMode, allowReinvest, triggerStrategy, triggerPx. [CAUTION] Executes real trades. Private endpoint. Rate limit: 20 req/2s.",
3061
+ description: "Create a Contract DCA (Martingale) bot order with leverage on futures/swaps. Required: instId, lever, direction, initOrdAmt, maxSafetyOrds, tpPct. When maxSafetyOrds > 0: also provide safetyOrdAmt, pxSteps, pxStepsMult, volMult. [CAUTION] Executes real trades.",
2710
3062
  isWrite: true,
2711
3063
  inputSchema: {
2712
3064
  type: "object",
@@ -2767,7 +3119,7 @@ function registerDcaTools() {
2767
3119
  {
2768
3120
  name: "dca_stop_order",
2769
3121
  module: "bot.dca",
2770
- description: "Stop a running Contract DCA bot. [CAUTION] This will stop the bot. Private endpoint. Rate limit: 20 req/2s.",
3122
+ description: "Stop a running Contract DCA bot. [CAUTION] This will stop the bot.",
2771
3123
  isWrite: true,
2772
3124
  inputSchema: {
2773
3125
  type: "object",
@@ -2793,7 +3145,7 @@ function registerDcaTools() {
2793
3145
  {
2794
3146
  name: "dca_get_orders",
2795
3147
  module: "bot.dca",
2796
- description: "Query Contract DCA bot orders. Use status='active' for running bots, status='history' for completed/stopped. Private endpoint. Rate limit: 20 req/2s.",
3148
+ description: "Query Contract DCA bot orders. status='active' for running bots; status='history' for completed/stopped.",
2797
3149
  isWrite: false,
2798
3150
  inputSchema: {
2799
3151
  type: "object",
@@ -2830,13 +3182,13 @@ function registerDcaTools() {
2830
3182
  }),
2831
3183
  privateRateLimit("dca_get_orders", 20)
2832
3184
  );
2833
- return normalize4(response);
3185
+ return normalizeResponse(response);
2834
3186
  }
2835
3187
  },
2836
3188
  {
2837
3189
  name: "dca_get_order_details",
2838
3190
  module: "bot.dca",
2839
- description: "Query details of a single Contract DCA bot by algo ID. Returns current position details. Private endpoint. Rate limit: 20 req/2s.",
3191
+ description: "Query details of a single Contract DCA bot by algo ID. Returns current position details.",
2840
3192
  isWrite: false,
2841
3193
  inputSchema: {
2842
3194
  type: "object",
@@ -2856,13 +3208,13 @@ function registerDcaTools() {
2856
3208
  { algoId, algoOrdType: "contract_dca" },
2857
3209
  privateRateLimit("dca_get_order_details", 20)
2858
3210
  );
2859
- return normalize4(response);
3211
+ return normalizeResponse(response);
2860
3212
  }
2861
3213
  },
2862
3214
  {
2863
3215
  name: "dca_get_sub_orders",
2864
3216
  module: "bot.dca",
2865
- description: "Query cycles or orders within a cycle of a Contract DCA bot. Returns cycle list when cycleId is omitted; returns orders within a specific cycle when cycleId is provided. Private endpoint. Rate limit: 20 req/2s.",
3217
+ description: "Query cycles or orders within a cycle of a Contract DCA bot. Omit cycleId for cycle list; provide cycleId for orders within a cycle.",
2866
3218
  isWrite: false,
2867
3219
  inputSchema: {
2868
3220
  type: "object",
@@ -2893,7 +3245,7 @@ function registerDcaTools() {
2893
3245
  }),
2894
3246
  privateRateLimit("dca_get_sub_orders", 20)
2895
3247
  );
2896
- return normalize4(response2);
3248
+ return normalizeResponse(response2);
2897
3249
  }
2898
3250
  const response = await context.client.privateGet(
2899
3251
  `${BASE}/cycle-list`,
@@ -2906,7 +3258,7 @@ function registerDcaTools() {
2906
3258
  }),
2907
3259
  privateRateLimit("dca_get_sub_orders", 20)
2908
3260
  );
2909
- return normalize4(response);
3261
+ return normalizeResponse(response);
2910
3262
  }
2911
3263
  }
2912
3264
  ];
@@ -3712,19 +4064,12 @@ function registerAllEarnTools() {
3712
4064
  ];
3713
4065
  }
3714
4066
  var FUTURES_INST_TYPES = ["FUTURES", "SWAP"];
3715
- function normalize5(response) {
3716
- return {
3717
- endpoint: response.endpoint,
3718
- requestTime: response.requestTime,
3719
- data: response.data
3720
- };
3721
- }
3722
4067
  function registerFuturesTools() {
3723
4068
  return [
3724
4069
  {
3725
4070
  name: "futures_place_order",
3726
4071
  module: "futures",
3727
- description: "Place a FUTURES delivery contract order (e.g. instId: BTC-USDT-240329). Optionally attach TP/SL via tpTriggerPx/slTriggerPx. [CAUTION] Executes real trades. Private endpoint. Rate limit: 60 req/s.",
4072
+ description: "Place a FUTURES delivery contract order (e.g. instId: BTC-USDT-240329). Optionally attach TP/SL via tpTriggerPx/slTriggerPx. [CAUTION] Executes real trades.",
3728
4073
  isWrite: true,
3729
4074
  inputSchema: {
3730
4075
  type: "object",
@@ -3777,50 +4122,302 @@ function registerFuturesTools() {
3777
4122
  type: "string",
3778
4123
  description: "TP order price; -1=market"
3779
4124
  },
3780
- slTriggerPx: {
4125
+ slTriggerPx: {
4126
+ type: "string",
4127
+ description: "SL trigger price; places SL at slOrdPx"
4128
+ },
4129
+ slOrdPx: {
4130
+ type: "string",
4131
+ description: "SL order price; -1=market"
4132
+ }
4133
+ },
4134
+ required: ["instId", "tdMode", "side", "ordType", "sz"]
4135
+ },
4136
+ handler: async (rawArgs, context) => {
4137
+ const args = asRecord(rawArgs);
4138
+ const reduceOnly = args.reduceOnly;
4139
+ const attachAlgoOrds = buildAttachAlgoOrds(args);
4140
+ const response = await context.client.privatePost(
4141
+ "/api/v5/trade/order",
4142
+ compactObject({
4143
+ instId: requireString(args, "instId"),
4144
+ tdMode: requireString(args, "tdMode"),
4145
+ side: requireString(args, "side"),
4146
+ posSide: readString(args, "posSide"),
4147
+ ordType: requireString(args, "ordType"),
4148
+ sz: requireString(args, "sz"),
4149
+ px: readString(args, "px"),
4150
+ reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
4151
+ clOrdId: readString(args, "clOrdId"),
4152
+ tag: context.config.sourceTag,
4153
+ attachAlgoOrds
4154
+ }),
4155
+ privateRateLimit("futures_place_order", 60)
4156
+ );
4157
+ return normalizeResponse(response);
4158
+ }
4159
+ },
4160
+ {
4161
+ name: "futures_cancel_order",
4162
+ module: "futures",
4163
+ description: "Cancel an unfilled FUTURES delivery order.",
4164
+ isWrite: true,
4165
+ inputSchema: {
4166
+ type: "object",
4167
+ properties: {
4168
+ instId: {
4169
+ type: "string",
4170
+ description: "e.g. BTC-USDT-240329"
4171
+ },
4172
+ ordId: {
4173
+ type: "string"
4174
+ },
4175
+ clOrdId: {
4176
+ type: "string",
4177
+ description: "Client order ID"
4178
+ }
4179
+ },
4180
+ required: ["instId"]
4181
+ },
4182
+ handler: async (rawArgs, context) => {
4183
+ const args = asRecord(rawArgs);
4184
+ const response = await context.client.privatePost(
4185
+ "/api/v5/trade/cancel-order",
4186
+ compactObject({
4187
+ instId: requireString(args, "instId"),
4188
+ ordId: readString(args, "ordId"),
4189
+ clOrdId: readString(args, "clOrdId")
4190
+ }),
4191
+ privateRateLimit("futures_cancel_order", 60)
4192
+ );
4193
+ return normalizeResponse(response);
4194
+ }
4195
+ },
4196
+ {
4197
+ name: "futures_get_order",
4198
+ module: "futures",
4199
+ description: "Get details of a single FUTURES delivery order by ordId or clOrdId.",
4200
+ isWrite: false,
4201
+ inputSchema: {
4202
+ type: "object",
4203
+ properties: {
4204
+ instId: {
4205
+ type: "string",
4206
+ description: "e.g. BTC-USDT-240329"
4207
+ },
4208
+ ordId: {
4209
+ type: "string",
4210
+ description: "Provide ordId or clOrdId"
4211
+ },
4212
+ clOrdId: {
4213
+ type: "string",
4214
+ description: "Provide ordId or clOrdId"
4215
+ }
4216
+ },
4217
+ required: ["instId"]
4218
+ },
4219
+ handler: async (rawArgs, context) => {
4220
+ const args = asRecord(rawArgs);
4221
+ const response = await context.client.privateGet(
4222
+ "/api/v5/trade/order",
4223
+ compactObject({
4224
+ instId: requireString(args, "instId"),
4225
+ ordId: readString(args, "ordId"),
4226
+ clOrdId: readString(args, "clOrdId")
4227
+ }),
4228
+ privateRateLimit("futures_get_order", 60)
4229
+ );
4230
+ return normalizeResponse(response);
4231
+ }
4232
+ },
4233
+ {
4234
+ name: "futures_get_orders",
4235
+ module: "futures",
4236
+ description: "Query FUTURES open orders, history (last 7 days), or archive (up to 3 months).",
4237
+ isWrite: false,
4238
+ inputSchema: {
4239
+ type: "object",
4240
+ properties: {
4241
+ status: {
4242
+ type: "string",
4243
+ enum: ["open", "history", "archive"],
4244
+ description: "open=active, history=7d, archive=3mo"
4245
+ },
4246
+ instType: {
4247
+ type: "string",
4248
+ enum: [...FUTURES_INST_TYPES],
4249
+ description: "FUTURES (default) or SWAP"
4250
+ },
4251
+ instId: {
4252
+ type: "string",
4253
+ description: "e.g. BTC-USDT-240329"
4254
+ },
4255
+ ordType: {
4256
+ type: "string",
4257
+ description: "Order type filter"
4258
+ },
4259
+ state: {
4260
+ type: "string",
4261
+ description: "canceled|filled"
4262
+ },
4263
+ after: {
4264
+ type: "string",
4265
+ description: "Pagination: before this order ID"
4266
+ },
4267
+ before: {
4268
+ type: "string",
4269
+ description: "Pagination: after this order ID"
4270
+ },
4271
+ begin: {
4272
+ type: "string",
4273
+ description: "Start time (ms)"
4274
+ },
4275
+ end: {
4276
+ type: "string",
4277
+ description: "End time (ms)"
4278
+ },
4279
+ limit: {
4280
+ type: "number",
4281
+ description: "Max results (default 100)"
4282
+ }
4283
+ }
4284
+ },
4285
+ handler: async (rawArgs, context) => {
4286
+ const args = asRecord(rawArgs);
4287
+ const status = readString(args, "status") ?? "open";
4288
+ const instType = readString(args, "instType") ?? "FUTURES";
4289
+ assertEnum(instType, "instType", FUTURES_INST_TYPES);
4290
+ const path4 = status === "archive" ? "/api/v5/trade/orders-history-archive" : status === "history" ? "/api/v5/trade/orders-history" : "/api/v5/trade/orders-pending";
4291
+ const response = await context.client.privateGet(
4292
+ path4,
4293
+ compactObject({
4294
+ instType,
4295
+ instId: readString(args, "instId"),
4296
+ ordType: readString(args, "ordType"),
4297
+ state: readString(args, "state"),
4298
+ after: readString(args, "after"),
4299
+ before: readString(args, "before"),
4300
+ begin: readString(args, "begin"),
4301
+ end: readString(args, "end"),
4302
+ limit: readNumber(args, "limit")
4303
+ }),
4304
+ privateRateLimit("futures_get_orders", 20)
4305
+ );
4306
+ return normalizeResponse(response);
4307
+ }
4308
+ },
4309
+ {
4310
+ name: "futures_get_positions",
4311
+ module: "futures",
4312
+ description: "Get current FUTURES delivery contract positions.",
4313
+ isWrite: false,
4314
+ inputSchema: {
4315
+ type: "object",
4316
+ properties: {
4317
+ instType: {
4318
+ type: "string",
4319
+ enum: [...FUTURES_INST_TYPES],
4320
+ description: "FUTURES (default) or SWAP"
4321
+ },
4322
+ instId: {
4323
+ type: "string",
4324
+ description: "e.g. BTC-USDT-240329"
4325
+ },
4326
+ posId: {
4327
+ type: "string"
4328
+ }
4329
+ }
4330
+ },
4331
+ handler: async (rawArgs, context) => {
4332
+ const args = asRecord(rawArgs);
4333
+ const instType = readString(args, "instType") ?? "FUTURES";
4334
+ assertEnum(instType, "instType", FUTURES_INST_TYPES);
4335
+ const response = await context.client.privateGet(
4336
+ "/api/v5/account/positions",
4337
+ compactObject({
4338
+ instType,
4339
+ instId: readString(args, "instId"),
4340
+ posId: readString(args, "posId")
4341
+ }),
4342
+ privateRateLimit("futures_get_positions", 10)
4343
+ );
4344
+ return normalizeResponse(response);
4345
+ }
4346
+ },
4347
+ {
4348
+ name: "futures_get_fills",
4349
+ module: "futures",
4350
+ description: "Get FUTURES fill details. archive=false: last 3 days; archive=true: up to 3 months.",
4351
+ isWrite: false,
4352
+ inputSchema: {
4353
+ type: "object",
4354
+ properties: {
4355
+ archive: {
4356
+ type: "boolean",
4357
+ description: "true=up to 3 months; false=last 3 days (default)"
4358
+ },
4359
+ instType: {
4360
+ type: "string",
4361
+ enum: [...FUTURES_INST_TYPES],
4362
+ description: "FUTURES (default) or SWAP"
4363
+ },
4364
+ instId: {
4365
+ type: "string",
4366
+ description: "Instrument ID filter"
4367
+ },
4368
+ ordId: {
4369
+ type: "string",
4370
+ description: "Order ID filter"
4371
+ },
4372
+ after: {
4373
+ type: "string",
4374
+ description: "Pagination: before this bill ID"
4375
+ },
4376
+ before: {
4377
+ type: "string",
4378
+ description: "Pagination: after this bill ID"
4379
+ },
4380
+ begin: {
3781
4381
  type: "string",
3782
- description: "SL trigger price; places SL at slOrdPx"
4382
+ description: "Start time (ms)"
3783
4383
  },
3784
- slOrdPx: {
4384
+ end: {
3785
4385
  type: "string",
3786
- description: "SL order price; -1=market"
4386
+ description: "End time (ms)"
4387
+ },
4388
+ limit: {
4389
+ type: "number",
4390
+ description: "Max results (default 100 or 20 for archive)"
3787
4391
  }
3788
- },
3789
- required: ["instId", "tdMode", "side", "ordType", "sz"]
4392
+ }
3790
4393
  },
3791
4394
  handler: async (rawArgs, context) => {
3792
4395
  const args = asRecord(rawArgs);
3793
- const reduceOnly = args.reduceOnly;
3794
- const tpTriggerPx = readString(args, "tpTriggerPx");
3795
- const tpOrdPx = readString(args, "tpOrdPx");
3796
- const slTriggerPx = readString(args, "slTriggerPx");
3797
- const slOrdPx = readString(args, "slOrdPx");
3798
- const algoEntry = compactObject({ tpTriggerPx, tpOrdPx, slTriggerPx, slOrdPx });
3799
- const attachAlgoOrds = Object.keys(algoEntry).length > 0 ? [algoEntry] : void 0;
3800
- const response = await context.client.privatePost(
3801
- "/api/v5/trade/order",
4396
+ const archive = readBoolean(args, "archive") ?? false;
4397
+ const instType = readString(args, "instType") ?? "FUTURES";
4398
+ assertEnum(instType, "instType", FUTURES_INST_TYPES);
4399
+ const path4 = archive ? "/api/v5/trade/fills-history" : "/api/v5/trade/fills";
4400
+ const response = await context.client.privateGet(
4401
+ path4,
3802
4402
  compactObject({
3803
- instId: requireString(args, "instId"),
3804
- tdMode: requireString(args, "tdMode"),
3805
- side: requireString(args, "side"),
3806
- posSide: readString(args, "posSide"),
3807
- ordType: requireString(args, "ordType"),
3808
- sz: requireString(args, "sz"),
3809
- px: readString(args, "px"),
3810
- reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
3811
- clOrdId: readString(args, "clOrdId"),
3812
- tag: context.config.sourceTag,
3813
- attachAlgoOrds
4403
+ instType,
4404
+ instId: readString(args, "instId"),
4405
+ ordId: readString(args, "ordId"),
4406
+ after: readString(args, "after"),
4407
+ before: readString(args, "before"),
4408
+ begin: readString(args, "begin"),
4409
+ end: readString(args, "end"),
4410
+ limit: readNumber(args, "limit") ?? (archive ? 20 : void 0)
3814
4411
  }),
3815
- privateRateLimit("futures_place_order", 60)
4412
+ privateRateLimit("futures_get_fills", 20)
3816
4413
  );
3817
- return normalize5(response);
4414
+ return normalizeResponse(response);
3818
4415
  }
3819
4416
  },
3820
4417
  {
3821
- name: "futures_cancel_order",
4418
+ name: "futures_amend_order",
3822
4419
  module: "futures",
3823
- description: "Cancel an unfilled FUTURES delivery order. Private endpoint. Rate limit: 60 req/s.",
4420
+ description: "Amend an unfilled FUTURES delivery order (modify price and/or size).",
3824
4421
  isWrite: true,
3825
4422
  inputSchema: {
3826
4423
  type: "object",
@@ -3830,11 +4427,20 @@ function registerFuturesTools() {
3830
4427
  description: "e.g. BTC-USDT-240329"
3831
4428
  },
3832
4429
  ordId: {
3833
- type: "string"
4430
+ type: "string",
4431
+ description: "Provide ordId or clOrdId"
3834
4432
  },
3835
4433
  clOrdId: {
3836
4434
  type: "string",
3837
- description: "Client order ID"
4435
+ description: "Provide ordId or clOrdId"
4436
+ },
4437
+ newSz: {
4438
+ type: "string",
4439
+ description: "New number of contracts"
4440
+ },
4441
+ newPx: {
4442
+ type: "string",
4443
+ description: "New price"
3838
4444
  }
3839
4445
  },
3840
4446
  required: ["instId"]
@@ -3842,22 +4448,24 @@ function registerFuturesTools() {
3842
4448
  handler: async (rawArgs, context) => {
3843
4449
  const args = asRecord(rawArgs);
3844
4450
  const response = await context.client.privatePost(
3845
- "/api/v5/trade/cancel-order",
4451
+ "/api/v5/trade/amend-order",
3846
4452
  compactObject({
3847
4453
  instId: requireString(args, "instId"),
3848
4454
  ordId: readString(args, "ordId"),
3849
- clOrdId: readString(args, "clOrdId")
4455
+ clOrdId: readString(args, "clOrdId"),
4456
+ newSz: readString(args, "newSz"),
4457
+ newPx: readString(args, "newPx")
3850
4458
  }),
3851
- privateRateLimit("futures_cancel_order", 60)
4459
+ privateRateLimit("futures_amend_order", 60)
3852
4460
  );
3853
- return normalize5(response);
4461
+ return normalizeResponse(response);
3854
4462
  }
3855
4463
  },
3856
4464
  {
3857
- name: "futures_get_order",
4465
+ name: "futures_close_position",
3858
4466
  module: "futures",
3859
- description: "Get details of a single FUTURES delivery order by ordId or clOrdId. Private endpoint. Rate limit: 60 req/s.",
3860
- isWrite: false,
4467
+ description: "[CAUTION] Close an entire FUTURES delivery position at market. Private. Rate limit: 20 req/s.",
4468
+ isWrite: true,
3861
4469
  inputSchema: {
3862
4470
  type: "object",
3863
4471
  properties: {
@@ -3865,230 +4473,237 @@ function registerFuturesTools() {
3865
4473
  type: "string",
3866
4474
  description: "e.g. BTC-USDT-240329"
3867
4475
  },
3868
- ordId: {
4476
+ mgnMode: {
3869
4477
  type: "string",
3870
- description: "Provide ordId or clOrdId"
4478
+ enum: ["cross", "isolated"]
4479
+ },
4480
+ posSide: {
4481
+ type: "string",
4482
+ enum: ["long", "short", "net"],
4483
+ description: "long/short=hedge mode; omit for one-way (net)"
4484
+ },
4485
+ autoCxl: {
4486
+ type: "boolean",
4487
+ description: "Cancel pending orders for this instrument on close"
3871
4488
  },
3872
4489
  clOrdId: {
3873
4490
  type: "string",
3874
- description: "Provide ordId or clOrdId"
4491
+ description: "Client order ID for close order"
3875
4492
  }
3876
4493
  },
3877
- required: ["instId"]
4494
+ required: ["instId", "mgnMode"]
3878
4495
  },
3879
4496
  handler: async (rawArgs, context) => {
3880
4497
  const args = asRecord(rawArgs);
3881
- const response = await context.client.privateGet(
3882
- "/api/v5/trade/order",
4498
+ const autoCxl = args.autoCxl;
4499
+ const response = await context.client.privatePost(
4500
+ "/api/v5/trade/close-position",
3883
4501
  compactObject({
3884
4502
  instId: requireString(args, "instId"),
3885
- ordId: readString(args, "ordId"),
3886
- clOrdId: readString(args, "clOrdId")
4503
+ mgnMode: requireString(args, "mgnMode"),
4504
+ posSide: readString(args, "posSide"),
4505
+ autoCxl: typeof autoCxl === "boolean" ? String(autoCxl) : void 0,
4506
+ clOrdId: readString(args, "clOrdId"),
4507
+ tag: context.config.sourceTag
3887
4508
  }),
3888
- privateRateLimit("futures_get_order", 60)
4509
+ privateRateLimit("futures_close_position", 20)
3889
4510
  );
3890
- return normalize5(response);
4511
+ return normalizeResponse(response);
3891
4512
  }
3892
4513
  },
3893
4514
  {
3894
- name: "futures_get_orders",
4515
+ name: "futures_set_leverage",
3895
4516
  module: "futures",
3896
- description: "Query FUTURES open orders, history (last 7 days), or archive (up to 3 months). Private. Rate limit: 20 req/s.",
3897
- isWrite: false,
4517
+ description: "Set leverage for a FUTURES delivery instrument or position. [CAUTION] Changes risk parameters.",
4518
+ isWrite: true,
3898
4519
  inputSchema: {
3899
4520
  type: "object",
3900
4521
  properties: {
3901
- status: {
3902
- type: "string",
3903
- enum: ["open", "history", "archive"],
3904
- description: "open=active, history=7d, archive=3mo"
3905
- },
3906
- instType: {
3907
- type: "string",
3908
- enum: [...FUTURES_INST_TYPES],
3909
- description: "FUTURES (default) or SWAP"
3910
- },
3911
4522
  instId: {
3912
4523
  type: "string",
3913
4524
  description: "e.g. BTC-USDT-240329"
3914
4525
  },
3915
- ordType: {
3916
- type: "string",
3917
- description: "Order type filter"
3918
- },
3919
- state: {
3920
- type: "string",
3921
- description: "canceled|filled"
3922
- },
3923
- after: {
3924
- type: "string",
3925
- description: "Pagination: before this order ID"
3926
- },
3927
- before: {
4526
+ lever: {
3928
4527
  type: "string",
3929
- description: "Pagination: after this order ID"
4528
+ description: "Leverage, e.g. '10'"
3930
4529
  },
3931
- begin: {
4530
+ mgnMode: {
3932
4531
  type: "string",
3933
- description: "Start time (ms)"
4532
+ enum: ["cross", "isolated"]
3934
4533
  },
3935
- end: {
4534
+ posSide: {
3936
4535
  type: "string",
3937
- description: "End time (ms)"
3938
- },
3939
- limit: {
3940
- type: "number",
3941
- description: "Max results (default 100)"
4536
+ enum: ["long", "short", "net"],
4537
+ description: "Required for isolated margin in hedge mode"
3942
4538
  }
3943
- }
4539
+ },
4540
+ required: ["instId", "lever", "mgnMode"]
3944
4541
  },
3945
4542
  handler: async (rawArgs, context) => {
3946
4543
  const args = asRecord(rawArgs);
3947
- const status = readString(args, "status") ?? "open";
3948
- const instType = readString(args, "instType") ?? "FUTURES";
3949
- assertEnum(instType, "instType", FUTURES_INST_TYPES);
3950
- const path4 = status === "archive" ? "/api/v5/trade/orders-history-archive" : status === "history" ? "/api/v5/trade/orders-history" : "/api/v5/trade/orders-pending";
3951
- const response = await context.client.privateGet(
3952
- path4,
4544
+ const response = await context.client.privatePost(
4545
+ "/api/v5/account/set-leverage",
3953
4546
  compactObject({
3954
- instType,
3955
- instId: readString(args, "instId"),
3956
- ordType: readString(args, "ordType"),
3957
- state: readString(args, "state"),
3958
- after: readString(args, "after"),
3959
- before: readString(args, "before"),
3960
- begin: readString(args, "begin"),
3961
- end: readString(args, "end"),
3962
- limit: readNumber(args, "limit")
4547
+ instId: requireString(args, "instId"),
4548
+ lever: requireString(args, "lever"),
4549
+ mgnMode: requireString(args, "mgnMode"),
4550
+ posSide: readString(args, "posSide")
3963
4551
  }),
3964
- privateRateLimit("futures_get_orders", 20)
4552
+ privateRateLimit("futures_set_leverage", 20)
3965
4553
  );
3966
- return normalize5(response);
4554
+ return normalizeResponse(response);
3967
4555
  }
3968
4556
  },
3969
4557
  {
3970
- name: "futures_get_positions",
4558
+ name: "futures_get_leverage",
3971
4559
  module: "futures",
3972
- description: "Get current FUTURES delivery contract positions. Private endpoint. Rate limit: 10 req/s.",
4560
+ description: "Get current leverage for a FUTURES delivery instrument.",
3973
4561
  isWrite: false,
3974
4562
  inputSchema: {
3975
4563
  type: "object",
3976
4564
  properties: {
3977
- instType: {
3978
- type: "string",
3979
- enum: [...FUTURES_INST_TYPES],
3980
- description: "FUTURES (default) or SWAP"
3981
- },
3982
4565
  instId: {
3983
4566
  type: "string",
3984
4567
  description: "e.g. BTC-USDT-240329"
3985
4568
  },
3986
- posId: {
3987
- type: "string"
4569
+ mgnMode: {
4570
+ type: "string",
4571
+ enum: ["cross", "isolated"]
3988
4572
  }
3989
- }
4573
+ },
4574
+ required: ["instId", "mgnMode"]
3990
4575
  },
3991
4576
  handler: async (rawArgs, context) => {
3992
4577
  const args = asRecord(rawArgs);
3993
- const instType = readString(args, "instType") ?? "FUTURES";
3994
- assertEnum(instType, "instType", FUTURES_INST_TYPES);
3995
4578
  const response = await context.client.privateGet(
3996
- "/api/v5/account/positions",
4579
+ "/api/v5/account/leverage-info",
3997
4580
  compactObject({
3998
- instType,
3999
- instId: readString(args, "instId"),
4000
- posId: readString(args, "posId")
4581
+ instId: requireString(args, "instId"),
4582
+ mgnMode: requireString(args, "mgnMode")
4001
4583
  }),
4002
- privateRateLimit("futures_get_positions", 10)
4584
+ privateRateLimit("futures_get_leverage", 20)
4585
+ );
4586
+ return normalizeResponse(response);
4587
+ }
4588
+ },
4589
+ {
4590
+ name: "futures_batch_orders",
4591
+ module: "futures",
4592
+ description: "[CAUTION] Batch place up to 20 FUTURES delivery orders in one request. Private. Rate limit: 60 req/s.",
4593
+ isWrite: true,
4594
+ inputSchema: {
4595
+ type: "object",
4596
+ properties: {
4597
+ orders: {
4598
+ type: "array",
4599
+ description: "Array (max 20): {instId,tdMode,side,ordType,sz,px?,posSide?,reduceOnly?,clOrdId?,tpTriggerPx?,tpOrdPx?,slTriggerPx?,slOrdPx?}",
4600
+ items: {
4601
+ type: "object"
4602
+ }
4603
+ }
4604
+ },
4605
+ required: ["orders"]
4606
+ },
4607
+ handler: async (rawArgs, context) => {
4608
+ const args = asRecord(rawArgs);
4609
+ const orders = args.orders;
4610
+ if (!Array.isArray(orders) || orders.length === 0) {
4611
+ throw new Error("orders must be a non-empty array.");
4612
+ }
4613
+ const body = orders.map((order) => {
4614
+ const o = asRecord(order);
4615
+ const attachAlgoOrds = buildAttachAlgoOrds(o);
4616
+ const reduceOnly = o.reduceOnly;
4617
+ return compactObject({
4618
+ instId: requireString(o, "instId"),
4619
+ tdMode: requireString(o, "tdMode"),
4620
+ side: requireString(o, "side"),
4621
+ ordType: requireString(o, "ordType"),
4622
+ sz: requireString(o, "sz"),
4623
+ px: readString(o, "px"),
4624
+ posSide: readString(o, "posSide"),
4625
+ reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
4626
+ clOrdId: readString(o, "clOrdId"),
4627
+ tag: context.config.sourceTag,
4628
+ attachAlgoOrds
4629
+ });
4630
+ });
4631
+ const response = await context.client.privatePost(
4632
+ "/api/v5/trade/batch-orders",
4633
+ body,
4634
+ privateRateLimit("futures_batch_orders", 60)
4635
+ );
4636
+ return normalizeResponse(response);
4637
+ }
4638
+ },
4639
+ {
4640
+ name: "futures_batch_amend",
4641
+ module: "futures",
4642
+ description: "[CAUTION] Batch amend up to 20 unfilled FUTURES delivery orders in one request.",
4643
+ isWrite: true,
4644
+ inputSchema: {
4645
+ type: "object",
4646
+ properties: {
4647
+ orders: {
4648
+ type: "array",
4649
+ description: "Array (max 20): {instId, ordId?, clOrdId?, newSz?, newPx?}",
4650
+ items: { type: "object" }
4651
+ }
4652
+ },
4653
+ required: ["orders"]
4654
+ },
4655
+ handler: async (rawArgs, context) => {
4656
+ const args = asRecord(rawArgs);
4657
+ const orders = args.orders;
4658
+ if (!Array.isArray(orders) || orders.length === 0) {
4659
+ throw new Error("orders must be a non-empty array.");
4660
+ }
4661
+ const response = await context.client.privatePost(
4662
+ "/api/v5/trade/amend-batch-orders",
4663
+ orders,
4664
+ privateRateLimit("futures_batch_amend", 60)
4003
4665
  );
4004
- return normalize5(response);
4666
+ return normalizeResponse(response);
4005
4667
  }
4006
4668
  },
4007
4669
  {
4008
- name: "futures_get_fills",
4670
+ name: "futures_batch_cancel",
4009
4671
  module: "futures",
4010
- description: "Get FUTURES fill details. archive=false: last 3 days. archive=true: up to 3 months. Private. Rate limit: 20 req/s.",
4011
- isWrite: false,
4672
+ description: "[CAUTION] Batch cancel up to 20 FUTURES delivery orders in one request.",
4673
+ isWrite: true,
4012
4674
  inputSchema: {
4013
4675
  type: "object",
4014
4676
  properties: {
4015
- archive: {
4016
- type: "boolean",
4017
- description: "true=up to 3 months; false=last 3 days (default)"
4018
- },
4019
- instType: {
4020
- type: "string",
4021
- enum: [...FUTURES_INST_TYPES],
4022
- description: "FUTURES (default) or SWAP"
4023
- },
4024
- instId: {
4025
- type: "string",
4026
- description: "Instrument ID filter"
4027
- },
4028
- ordId: {
4029
- type: "string",
4030
- description: "Order ID filter"
4031
- },
4032
- after: {
4033
- type: "string",
4034
- description: "Pagination: before this bill ID"
4035
- },
4036
- before: {
4037
- type: "string",
4038
- description: "Pagination: after this bill ID"
4039
- },
4040
- begin: {
4041
- type: "string",
4042
- description: "Start time (ms)"
4043
- },
4044
- end: {
4045
- type: "string",
4046
- description: "End time (ms)"
4047
- },
4048
- limit: {
4049
- type: "number",
4050
- description: "Max results (default 100 or 20 for archive)"
4677
+ orders: {
4678
+ type: "array",
4679
+ description: "Array (max 20): {instId, ordId?, clOrdId?}",
4680
+ items: { type: "object" }
4051
4681
  }
4052
- }
4682
+ },
4683
+ required: ["orders"]
4053
4684
  },
4054
4685
  handler: async (rawArgs, context) => {
4055
4686
  const args = asRecord(rawArgs);
4056
- const archive = readBoolean(args, "archive") ?? false;
4057
- const instType = readString(args, "instType") ?? "FUTURES";
4058
- assertEnum(instType, "instType", FUTURES_INST_TYPES);
4059
- const path4 = archive ? "/api/v5/trade/fills-history" : "/api/v5/trade/fills";
4060
- const response = await context.client.privateGet(
4061
- path4,
4062
- compactObject({
4063
- instType,
4064
- instId: readString(args, "instId"),
4065
- ordId: readString(args, "ordId"),
4066
- after: readString(args, "after"),
4067
- before: readString(args, "before"),
4068
- begin: readString(args, "begin"),
4069
- end: readString(args, "end"),
4070
- limit: readNumber(args, "limit") ?? (archive ? 20 : void 0)
4071
- }),
4072
- privateRateLimit("futures_get_fills", 20)
4687
+ const orders = args.orders;
4688
+ if (!Array.isArray(orders) || orders.length === 0) {
4689
+ throw new Error("orders must be a non-empty array.");
4690
+ }
4691
+ const response = await context.client.privatePost(
4692
+ "/api/v5/trade/cancel-batch-orders",
4693
+ orders,
4694
+ privateRateLimit("futures_batch_cancel", 60)
4073
4695
  );
4074
- return normalize5(response);
4696
+ return normalizeResponse(response);
4075
4697
  }
4076
4698
  }
4077
4699
  ];
4078
4700
  }
4079
- function normalize6(response) {
4080
- return {
4081
- endpoint: response.endpoint,
4082
- requestTime: response.requestTime,
4083
- data: response.data
4084
- };
4085
- }
4086
4701
  function registerMarketTools() {
4087
4702
  return [
4088
4703
  {
4089
4704
  name: "market_get_ticker",
4090
4705
  module: "market",
4091
- description: "Get ticker data for a single instrument. Public endpoint, no authentication required. Rate limit: 20 req/s.",
4706
+ description: "Get ticker data for a single instrument.",
4092
4707
  isWrite: false,
4093
4708
  inputSchema: {
4094
4709
  type: "object",
@@ -4107,13 +4722,13 @@ function registerMarketTools() {
4107
4722
  { instId: requireString(args, "instId") },
4108
4723
  publicRateLimit("market_get_ticker", 20)
4109
4724
  );
4110
- return normalize6(response);
4725
+ return normalizeResponse(response);
4111
4726
  }
4112
4727
  },
4113
4728
  {
4114
4729
  name: "market_get_tickers",
4115
4730
  module: "market",
4116
- description: "Get ticker data for all instruments of a given type. Public endpoint, no authentication required. Rate limit: 20 req/s.",
4731
+ description: "Get ticker data for all instruments of a given type.",
4117
4732
  isWrite: false,
4118
4733
  inputSchema: {
4119
4734
  type: "object",
@@ -4144,13 +4759,13 @@ function registerMarketTools() {
4144
4759
  }),
4145
4760
  publicRateLimit("market_get_tickers", 20)
4146
4761
  );
4147
- return normalize6(response);
4762
+ return normalizeResponse(response);
4148
4763
  }
4149
4764
  },
4150
4765
  {
4151
4766
  name: "market_get_orderbook",
4152
4767
  module: "market",
4153
- description: "Get the order book (bids/asks) for an instrument. Public endpoint, no authentication required. Rate limit: 20 req/s.",
4768
+ description: "Get the order book (bids/asks) for an instrument.",
4154
4769
  isWrite: false,
4155
4770
  inputSchema: {
4156
4771
  type: "object",
@@ -4176,13 +4791,13 @@ function registerMarketTools() {
4176
4791
  }),
4177
4792
  publicRateLimit("market_get_orderbook", 20)
4178
4793
  );
4179
- return normalize6(response);
4794
+ return normalizeResponse(response);
4180
4795
  }
4181
4796
  },
4182
4797
  {
4183
4798
  name: "market_get_candles",
4184
4799
  module: "market",
4185
- description: "Get candlestick (OHLCV) data for an instrument. history=false (default): recent candles up to 1440 bars. history=true: older historical data beyond the recent window. Public endpoint, no authentication required. Rate limit: 40 req/s.",
4800
+ description: "Get candlestick (OHLCV) data for an instrument. history=false (default): recent candles up to 1440 bars; history=true: older historical data.",
4186
4801
  isWrite: false,
4187
4802
  inputSchema: {
4188
4803
  type: "object",
@@ -4230,13 +4845,13 @@ function registerMarketTools() {
4230
4845
  }),
4231
4846
  publicRateLimit("market_get_candles", 40)
4232
4847
  );
4233
- return normalize6(response);
4848
+ return normalizeResponse(response);
4234
4849
  }
4235
4850
  },
4236
4851
  {
4237
4852
  name: "market_get_instruments",
4238
4853
  module: "market",
4239
- description: "Get tradable instruments for a given type. Returns contract specs: min order size, lot size, tick size, contract value, settlement currency, listing/expiry time. Essential before placing orders. Public endpoint. Rate limit: 20 req/s.",
4854
+ description: "Get tradable instruments for a given type. Returns contract specs: min order size, lot size, tick size, contract value, settlement currency, listing/expiry time. Essential before placing orders.",
4240
4855
  isWrite: false,
4241
4856
  inputSchema: {
4242
4857
  type: "object",
@@ -4272,13 +4887,13 @@ function registerMarketTools() {
4272
4887
  }),
4273
4888
  publicRateLimit("market_get_instruments", 20)
4274
4889
  );
4275
- return normalize6(response);
4890
+ return normalizeResponse(response);
4276
4891
  }
4277
4892
  },
4278
4893
  {
4279
4894
  name: "market_get_funding_rate",
4280
4895
  module: "market",
4281
- description: "Get funding rate for a SWAP instrument. history=false (default): current rate and estimated next rate + settlement time. history=true: historical rates, default 20 records, max 100. Public endpoint. Rate limit: 20 req/s.",
4896
+ description: "Get funding rate for a SWAP instrument. history=false (default): current rate + next estimated rate; history=true: historical rates.",
4282
4897
  isWrite: false,
4283
4898
  inputSchema: {
4284
4899
  type: "object",
@@ -4320,20 +4935,20 @@ function registerMarketTools() {
4320
4935
  }),
4321
4936
  publicRateLimit("market_get_funding_rate", 20)
4322
4937
  );
4323
- return normalize6(response2);
4938
+ return normalizeResponse(response2);
4324
4939
  }
4325
4940
  const response = await context.client.publicGet(
4326
4941
  "/api/v5/public/funding-rate",
4327
4942
  { instId: requireString(args, "instId") },
4328
4943
  publicRateLimit("market_get_funding_rate", 20)
4329
4944
  );
4330
- return normalize6(response);
4945
+ return normalizeResponse(response);
4331
4946
  }
4332
4947
  },
4333
4948
  {
4334
4949
  name: "market_get_mark_price",
4335
4950
  module: "market",
4336
- description: "Get mark price for SWAP, FUTURES, or MARGIN instruments. Mark price is used for liquidation calculations and unrealized PnL. Public endpoint. Rate limit: 10 req/s.",
4951
+ description: "Get mark price for SWAP, FUTURES, or MARGIN instruments. Used for liquidation calculations and unrealized PnL.",
4337
4952
  isWrite: false,
4338
4953
  inputSchema: {
4339
4954
  type: "object",
@@ -4368,13 +4983,13 @@ function registerMarketTools() {
4368
4983
  }),
4369
4984
  publicRateLimit("market_get_mark_price", 10)
4370
4985
  );
4371
- return normalize6(response);
4986
+ return normalizeResponse(response);
4372
4987
  }
4373
4988
  },
4374
4989
  {
4375
4990
  name: "market_get_trades",
4376
4991
  module: "market",
4377
- description: "Get recent trades for an instrument. Default 20 records, max 500. Public endpoint, no authentication required. Rate limit: 20 req/s.",
4992
+ description: "Get recent trades for an instrument. Default 20 records, max 500.",
4378
4993
  isWrite: false,
4379
4994
  inputSchema: {
4380
4995
  type: "object",
@@ -4400,13 +5015,13 @@ function registerMarketTools() {
4400
5015
  }),
4401
5016
  publicRateLimit("market_get_trades", 20)
4402
5017
  );
4403
- return normalize6(response);
5018
+ return normalizeResponse(response);
4404
5019
  }
4405
5020
  },
4406
5021
  {
4407
5022
  name: "market_get_index_ticker",
4408
5023
  module: "market",
4409
- description: "Get index ticker data (e.g. BTC-USD, ETH-USD index prices). Index prices are used for mark price calculation and are independent of any single exchange. Public endpoint. Rate limit: 20 req/s.",
5024
+ description: "Get index ticker data (e.g. BTC-USD, ETH-USD index prices). Independent of any single exchange.",
4410
5025
  isWrite: false,
4411
5026
  inputSchema: {
4412
5027
  type: "object",
@@ -4431,178 +5046,428 @@ function registerMarketTools() {
4431
5046
  }),
4432
5047
  publicRateLimit("market_get_index_ticker", 20)
4433
5048
  );
4434
- return normalize6(response);
5049
+ return normalizeResponse(response);
4435
5050
  }
4436
5051
  },
4437
5052
  {
4438
5053
  name: "market_get_index_candles",
4439
5054
  module: "market",
4440
- description: "Get candlestick data for an index (e.g. BTC-USD index). history=false (default): recent candles up to 1440 bars. history=true: older historical data beyond the recent window. Public endpoint. Rate limit: 20 req/s.",
5055
+ description: "Get candlestick data for an index (e.g. BTC-USD index). history=false: recent up to 1440 bars; history=true: older data.",
5056
+ isWrite: false,
5057
+ inputSchema: {
5058
+ type: "object",
5059
+ properties: {
5060
+ instId: {
5061
+ type: "string",
5062
+ description: "Index ID, e.g. BTC-USD"
5063
+ },
5064
+ bar: {
5065
+ type: "string",
5066
+ enum: [...OKX_CANDLE_BARS],
5067
+ description: "Default 1m"
5068
+ },
5069
+ after: {
5070
+ type: "string",
5071
+ description: "Pagination: before this timestamp (ms)"
5072
+ },
5073
+ before: {
5074
+ type: "string",
5075
+ description: "Pagination: after this timestamp (ms)"
5076
+ },
5077
+ limit: {
5078
+ type: "number",
5079
+ description: "Max results (default 100)"
5080
+ },
5081
+ history: {
5082
+ type: "boolean",
5083
+ description: "true=older historical data"
5084
+ }
5085
+ },
5086
+ required: ["instId"]
5087
+ },
5088
+ handler: async (rawArgs, context) => {
5089
+ const args = asRecord(rawArgs);
5090
+ const isHistory = readBoolean(args, "history") ?? false;
5091
+ const path4 = isHistory ? "/api/v5/market/history-index-candles" : "/api/v5/market/index-candles";
5092
+ const response = await context.client.publicGet(
5093
+ path4,
5094
+ compactObject({
5095
+ instId: requireString(args, "instId"),
5096
+ bar: readString(args, "bar"),
5097
+ after: readString(args, "after"),
5098
+ before: readString(args, "before"),
5099
+ limit: readNumber(args, "limit")
5100
+ }),
5101
+ publicRateLimit("market_get_index_candles", 20)
5102
+ );
5103
+ return normalizeResponse(response);
5104
+ }
5105
+ },
5106
+ {
5107
+ name: "market_get_price_limit",
5108
+ module: "market",
5109
+ description: "Get the current price limit (upper and lower bands) for a SWAP or FUTURES instrument. Orders outside these limits will be rejected.",
5110
+ isWrite: false,
5111
+ inputSchema: {
5112
+ type: "object",
5113
+ properties: {
5114
+ instId: {
5115
+ type: "string",
5116
+ description: "SWAP or FUTURES ID, e.g. BTC-USDT-SWAP"
5117
+ }
5118
+ },
5119
+ required: ["instId"]
5120
+ },
5121
+ handler: async (rawArgs, context) => {
5122
+ const args = asRecord(rawArgs);
5123
+ const response = await context.client.publicGet(
5124
+ "/api/v5/public/price-limit",
5125
+ { instId: requireString(args, "instId") },
5126
+ publicRateLimit("market_get_price_limit", 20)
5127
+ );
5128
+ return normalizeResponse(response);
5129
+ }
5130
+ },
5131
+ {
5132
+ name: "market_get_open_interest",
5133
+ module: "market",
5134
+ description: "Get open interest for SWAP, FUTURES, or OPTION instruments. Useful for gauging market sentiment and positioning.",
5135
+ isWrite: false,
5136
+ inputSchema: {
5137
+ type: "object",
5138
+ properties: {
5139
+ instType: {
5140
+ type: "string",
5141
+ enum: ["SWAP", "FUTURES", "OPTION"]
5142
+ },
5143
+ instId: {
5144
+ type: "string",
5145
+ description: "e.g. BTC-USDT-SWAP"
5146
+ },
5147
+ uly: {
5148
+ type: "string",
5149
+ description: "e.g. BTC-USD"
5150
+ },
5151
+ instFamily: {
5152
+ type: "string"
5153
+ }
5154
+ },
5155
+ required: ["instType"]
5156
+ },
5157
+ handler: async (rawArgs, context) => {
5158
+ const args = asRecord(rawArgs);
5159
+ const response = await context.client.publicGet(
5160
+ "/api/v5/public/open-interest",
5161
+ compactObject({
5162
+ instType: requireString(args, "instType"),
5163
+ instId: readString(args, "instId"),
5164
+ uly: readString(args, "uly"),
5165
+ instFamily: readString(args, "instFamily")
5166
+ }),
5167
+ publicRateLimit("market_get_open_interest", 20)
5168
+ );
5169
+ return normalizeResponse(response);
5170
+ }
5171
+ },
5172
+ {
5173
+ name: "market_get_stock_tokens",
5174
+ module: "market",
5175
+ description: "Get all stock token instruments (instCategory=3). Stock tokens track real-world stock prices on OKX (e.g. AAPL-USDT-SWAP). Filters client-side by instCategory=3.",
4441
5176
  isWrite: false,
5177
+ inputSchema: {
5178
+ type: "object",
5179
+ properties: {
5180
+ instType: {
5181
+ type: "string",
5182
+ enum: ["SPOT", "SWAP"],
5183
+ description: "Instrument type. Default: SWAP"
5184
+ },
5185
+ instId: {
5186
+ type: "string",
5187
+ description: "Optional: filter by specific instrument ID, e.g. AAPL-USDT-SWAP"
5188
+ }
5189
+ },
5190
+ required: []
5191
+ },
5192
+ handler: async (rawArgs, context) => {
5193
+ const args = asRecord(rawArgs);
5194
+ const instType = readString(args, "instType") ?? "SWAP";
5195
+ const instId = readString(args, "instId");
5196
+ const response = await context.client.publicGet(
5197
+ "/api/v5/public/instruments",
5198
+ compactObject({ instType, instId }),
5199
+ publicRateLimit("market_get_stock_tokens", 20)
5200
+ );
5201
+ const data = response.data;
5202
+ const filtered = Array.isArray(data) ? data.filter((item) => item.instCategory === "3") : data;
5203
+ return normalizeResponse({ ...response, data: filtered });
5204
+ }
5205
+ }
5206
+ ];
5207
+ }
5208
+ function registerOptionAlgoTools() {
5209
+ return [
5210
+ {
5211
+ name: "option_place_algo_order",
5212
+ module: "option",
5213
+ description: "Place an OPTION algo order: TP/SL (conditional/oco). [CAUTION] Executes real trades. conditional: single TP, single SL, or both on one order. oco: TP+SL simultaneously \u2014 first trigger cancels the other. Set tpOrdPx='-1' or slOrdPx='-1' for market execution.",
5214
+ isWrite: true,
4442
5215
  inputSchema: {
4443
5216
  type: "object",
4444
5217
  properties: {
4445
5218
  instId: {
4446
5219
  type: "string",
4447
- description: "Index ID, e.g. BTC-USD"
5220
+ description: "e.g. BTC-USD-241227-50000-C"
5221
+ },
5222
+ tdMode: {
5223
+ type: "string",
5224
+ enum: ["cash", "cross", "isolated"],
5225
+ description: "cash=buyer full premium; cross/isolated=seller margin"
5226
+ },
5227
+ side: {
5228
+ type: "string",
5229
+ enum: ["buy", "sell"],
5230
+ description: "sell=close long, buy=close short"
5231
+ },
5232
+ ordType: {
5233
+ type: "string",
5234
+ enum: ["conditional", "oco"],
5235
+ description: "conditional=single TP/SL or both; oco=TP+SL pair (first trigger cancels other)"
4448
5236
  },
4449
- bar: {
5237
+ sz: {
4450
5238
  type: "string",
4451
- enum: [...OKX_CANDLE_BARS],
4452
- description: "Default 1m"
5239
+ description: "Number of contracts (NOT USDT amount). Use market_get_instruments to get ctVal for conversion."
4453
5240
  },
4454
- after: {
5241
+ tpTriggerPx: {
4455
5242
  type: "string",
4456
- description: "Pagination: before this timestamp (ms)"
5243
+ description: "TP trigger price (conditional/oco only)"
4457
5244
  },
4458
- before: {
5245
+ tpOrdPx: {
4459
5246
  type: "string",
4460
- description: "Pagination: after this timestamp (ms)"
5247
+ description: "TP order price; -1=market (conditional/oco only)"
4461
5248
  },
4462
- limit: {
4463
- type: "number",
4464
- description: "Max results (default 100)"
5249
+ tpTriggerPxType: {
5250
+ type: "string",
5251
+ enum: ["last", "index", "mark"],
5252
+ description: "last(default)|index|mark (conditional/oco only)"
4465
5253
  },
4466
- history: {
5254
+ slTriggerPx: {
5255
+ type: "string",
5256
+ description: "SL trigger price (conditional/oco only)"
5257
+ },
5258
+ slOrdPx: {
5259
+ type: "string",
5260
+ description: "SL order price; -1=market (recommended) (conditional/oco only)"
5261
+ },
5262
+ slTriggerPxType: {
5263
+ type: "string",
5264
+ enum: ["last", "index", "mark"],
5265
+ description: "last(default)|index|mark (conditional/oco only)"
5266
+ },
5267
+ reduceOnly: {
4467
5268
  type: "boolean",
4468
- description: "true=older historical data"
5269
+ description: "Ensure order only reduces position"
5270
+ },
5271
+ clOrdId: {
5272
+ type: "string",
5273
+ description: "Client order ID (max 32 chars)"
4469
5274
  }
4470
5275
  },
4471
- required: ["instId"]
5276
+ required: ["instId", "tdMode", "side", "ordType", "sz"]
4472
5277
  },
4473
5278
  handler: async (rawArgs, context) => {
4474
5279
  const args = asRecord(rawArgs);
4475
- const isHistory = readBoolean(args, "history") ?? false;
4476
- const path4 = isHistory ? "/api/v5/market/history-index-candles" : "/api/v5/market/index-candles";
4477
- const response = await context.client.publicGet(
4478
- path4,
5280
+ const reduceOnly = readBoolean(args, "reduceOnly");
5281
+ const response = await context.client.privatePost(
5282
+ "/api/v5/trade/order-algo",
4479
5283
  compactObject({
4480
5284
  instId: requireString(args, "instId"),
4481
- bar: readString(args, "bar"),
4482
- after: readString(args, "after"),
4483
- before: readString(args, "before"),
4484
- limit: readNumber(args, "limit")
5285
+ tdMode: requireString(args, "tdMode"),
5286
+ side: requireString(args, "side"),
5287
+ ordType: requireString(args, "ordType"),
5288
+ sz: requireString(args, "sz"),
5289
+ tpTriggerPx: readString(args, "tpTriggerPx"),
5290
+ tpOrdPx: readString(args, "tpOrdPx"),
5291
+ tpTriggerPxType: readString(args, "tpTriggerPxType"),
5292
+ slTriggerPx: readString(args, "slTriggerPx"),
5293
+ slOrdPx: readString(args, "slOrdPx"),
5294
+ slTriggerPxType: readString(args, "slTriggerPxType"),
5295
+ reduceOnly: reduceOnly !== void 0 ? String(reduceOnly) : void 0,
5296
+ clOrdId: readString(args, "clOrdId"),
5297
+ tag: context.config.sourceTag
4485
5298
  }),
4486
- publicRateLimit("market_get_index_candles", 20)
5299
+ privateRateLimit("option_place_algo_order", 20)
4487
5300
  );
4488
- return normalize6(response);
5301
+ return normalizeResponse(response);
4489
5302
  }
4490
5303
  },
4491
5304
  {
4492
- name: "market_get_price_limit",
4493
- module: "market",
4494
- description: "Get the current price limit (upper and lower bands) for a SWAP or FUTURES instrument. Orders placed outside these limits will be rejected by OKX. Public endpoint. Rate limit: 20 req/s.",
4495
- isWrite: false,
5305
+ name: "option_amend_algo_order",
5306
+ module: "option",
5307
+ description: "Amend a pending OPTION algo order (modify TP/SL prices or size).",
5308
+ isWrite: true,
4496
5309
  inputSchema: {
4497
5310
  type: "object",
4498
5311
  properties: {
4499
- instId: {
4500
- type: "string",
4501
- description: "SWAP or FUTURES ID, e.g. BTC-USDT-SWAP"
4502
- }
5312
+ instId: { type: "string", description: "e.g. BTC-USD-241227-50000-C" },
5313
+ algoId: { type: "string", description: "Algo order ID" },
5314
+ newSz: { type: "string", description: "New number of contracts" },
5315
+ newTpTriggerPx: { type: "string", description: "New TP trigger price" },
5316
+ newTpOrdPx: { type: "string", description: "New TP order price; -1=market" },
5317
+ newSlTriggerPx: { type: "string", description: "New SL trigger price" },
5318
+ newSlOrdPx: { type: "string", description: "New SL order price; -1=market" }
4503
5319
  },
4504
- required: ["instId"]
5320
+ required: ["instId", "algoId"]
4505
5321
  },
4506
5322
  handler: async (rawArgs, context) => {
4507
5323
  const args = asRecord(rawArgs);
4508
- const response = await context.client.publicGet(
4509
- "/api/v5/public/price-limit",
4510
- { instId: requireString(args, "instId") },
4511
- publicRateLimit("market_get_price_limit", 20)
5324
+ const response = await context.client.privatePost(
5325
+ "/api/v5/trade/amend-algos",
5326
+ compactObject({
5327
+ instId: requireString(args, "instId"),
5328
+ algoId: requireString(args, "algoId"),
5329
+ newSz: readString(args, "newSz"),
5330
+ newTpTriggerPx: readString(args, "newTpTriggerPx"),
5331
+ newTpOrdPx: readString(args, "newTpOrdPx"),
5332
+ newSlTriggerPx: readString(args, "newSlTriggerPx"),
5333
+ newSlOrdPx: readString(args, "newSlOrdPx")
5334
+ }),
5335
+ privateRateLimit("option_amend_algo_order", 20)
4512
5336
  );
4513
- return normalize6(response);
5337
+ return normalizeResponse(response);
4514
5338
  }
4515
5339
  },
4516
5340
  {
4517
- name: "market_get_open_interest",
4518
- module: "market",
4519
- description: "Get open interest for SWAP, FUTURES, or OPTION instruments. Useful for gauging market sentiment and positioning. Public endpoint. Rate limit: 20 req/s.",
4520
- isWrite: false,
5341
+ name: "option_cancel_algo_orders",
5342
+ module: "option",
5343
+ description: "Cancel one or more pending OPTION algo orders (TP/SL). Accepts a list of {algoId, instId} objects.",
5344
+ isWrite: true,
4521
5345
  inputSchema: {
4522
5346
  type: "object",
4523
5347
  properties: {
4524
- instType: {
4525
- type: "string",
4526
- enum: ["SWAP", "FUTURES", "OPTION"]
4527
- },
4528
- instId: {
4529
- type: "string",
4530
- description: "e.g. BTC-USDT-SWAP"
4531
- },
4532
- uly: {
4533
- type: "string",
4534
- description: "e.g. BTC-USD"
4535
- },
4536
- instFamily: {
4537
- type: "string"
5348
+ orders: {
5349
+ type: "array",
5350
+ description: "List of algo orders to cancel. Each item: {algoId, instId}.",
5351
+ items: {
5352
+ type: "object",
5353
+ properties: {
5354
+ algoId: {
5355
+ type: "string",
5356
+ description: "Algo order ID"
5357
+ },
5358
+ instId: {
5359
+ type: "string",
5360
+ description: "e.g. BTC-USD-241227-50000-C"
5361
+ }
5362
+ },
5363
+ required: ["algoId", "instId"]
5364
+ }
4538
5365
  }
4539
5366
  },
4540
- required: ["instType"]
5367
+ required: ["orders"]
4541
5368
  },
4542
5369
  handler: async (rawArgs, context) => {
4543
5370
  const args = asRecord(rawArgs);
4544
- const response = await context.client.publicGet(
4545
- "/api/v5/public/open-interest",
4546
- compactObject({
4547
- instType: requireString(args, "instType"),
4548
- instId: readString(args, "instId"),
4549
- uly: readString(args, "uly"),
4550
- instFamily: readString(args, "instFamily")
4551
- }),
4552
- publicRateLimit("market_get_open_interest", 20)
5371
+ const orders = args.orders;
5372
+ if (!Array.isArray(orders) || orders.length === 0) {
5373
+ throw new Error("orders must be a non-empty array.");
5374
+ }
5375
+ const response = await context.client.privatePost(
5376
+ "/api/v5/trade/cancel-algos",
5377
+ orders,
5378
+ privateRateLimit("option_cancel_algo_orders", 20)
4553
5379
  );
4554
- return normalize6(response);
5380
+ return normalizeResponse(response);
4555
5381
  }
4556
5382
  },
4557
5383
  {
4558
- name: "market_get_stock_tokens",
4559
- module: "market",
4560
- description: "Get all stock token instruments (instCategory=3). Stock tokens track real-world stock prices on OKX (e.g. AAPL-USDT-SWAP, TSLA-USDT-SWAP). Fetches all instruments of the given type and filters client-side by instCategory=3. Public endpoint. Rate limit: 20 req/s.",
5384
+ name: "option_get_algo_orders",
5385
+ module: "option",
5386
+ description: "Query pending or completed OPTION algo orders (TP/SL, OCO).",
4561
5387
  isWrite: false,
4562
5388
  inputSchema: {
4563
5389
  type: "object",
4564
5390
  properties: {
4565
- instType: {
5391
+ status: {
4566
5392
  type: "string",
4567
- enum: ["SPOT", "SWAP"],
4568
- description: "Instrument type. Default: SWAP"
5393
+ enum: ["pending", "history"],
5394
+ description: "pending=active (default); history=completed"
5395
+ },
5396
+ ordType: {
5397
+ type: "string",
5398
+ enum: ["conditional", "oco"],
5399
+ description: "Filter by type; omit for all"
4569
5400
  },
4570
5401
  instId: {
4571
5402
  type: "string",
4572
- description: "Optional: filter by specific instrument ID, e.g. AAPL-USDT-SWAP"
5403
+ description: "Instrument ID filter"
5404
+ },
5405
+ algoId: {
5406
+ type: "string",
5407
+ description: "Filter by algo order ID"
5408
+ },
5409
+ after: {
5410
+ type: "string",
5411
+ description: "Pagination: before this algo ID"
5412
+ },
5413
+ before: {
5414
+ type: "string",
5415
+ description: "Pagination: after this algo ID"
5416
+ },
5417
+ limit: {
5418
+ type: "number",
5419
+ description: "Max results (default 100)"
5420
+ },
5421
+ state: {
5422
+ type: "string",
5423
+ enum: ["effective", "canceled", "order_failed"],
5424
+ description: "Required when status=history. effective=triggered, canceled, order_failed. Defaults to effective."
4573
5425
  }
4574
- },
4575
- required: []
5426
+ }
4576
5427
  },
4577
5428
  handler: async (rawArgs, context) => {
4578
5429
  const args = asRecord(rawArgs);
4579
- const instType = readString(args, "instType") ?? "SWAP";
4580
- const instId = readString(args, "instId");
4581
- const response = await context.client.publicGet(
4582
- "/api/v5/public/instruments",
4583
- compactObject({ instType, instId }),
4584
- publicRateLimit("market_get_stock_tokens", 20)
4585
- );
4586
- const data = response.data;
4587
- const filtered = Array.isArray(data) ? data.filter((item) => item.instCategory === "3") : data;
4588
- return normalize6({ ...response, data: filtered });
5430
+ const status = readString(args, "status") ?? "pending";
5431
+ const isHistory = status === "history";
5432
+ const path4 = isHistory ? "/api/v5/trade/orders-algo-history" : "/api/v5/trade/orders-algo-pending";
5433
+ const ordType = readString(args, "ordType");
5434
+ const state = isHistory ? readString(args, "state") ?? "effective" : void 0;
5435
+ const baseParams = compactObject({
5436
+ instType: "OPTION",
5437
+ instId: readString(args, "instId"),
5438
+ algoId: readString(args, "algoId"),
5439
+ after: readString(args, "after"),
5440
+ before: readString(args, "before"),
5441
+ limit: readNumber(args, "limit"),
5442
+ state
5443
+ });
5444
+ if (ordType) {
5445
+ const response = await context.client.privateGet(
5446
+ path4,
5447
+ { ...baseParams, ordType },
5448
+ privateRateLimit("option_get_algo_orders", 20)
5449
+ );
5450
+ return normalizeResponse(response);
5451
+ }
5452
+ const [r1, r2] = await Promise.all([
5453
+ context.client.privateGet(path4, { ...baseParams, ordType: "conditional" }, privateRateLimit("option_get_algo_orders", 20)),
5454
+ context.client.privateGet(path4, { ...baseParams, ordType: "oco" }, privateRateLimit("option_get_algo_orders", 20))
5455
+ ]);
5456
+ const merged = [
5457
+ ...r1.data ?? [],
5458
+ ...r2.data ?? []
5459
+ ];
5460
+ return { endpoint: r1.endpoint, requestTime: r1.requestTime, data: merged };
4589
5461
  }
4590
5462
  }
4591
5463
  ];
4592
5464
  }
4593
- function normalize7(response) {
4594
- return {
4595
- endpoint: response.endpoint,
4596
- requestTime: response.requestTime,
4597
- data: response.data
4598
- };
4599
- }
4600
5465
  function registerOptionTools() {
4601
5466
  return [
4602
5467
  {
4603
5468
  name: "option_place_order",
4604
5469
  module: "option",
4605
- description: "Place an OPTION order (buy/sell call or put). instId format: {uly}-{expiry}-{strike}-{C|P}, e.g. BTC-USD-241227-50000-C. tdMode: cash (buyer) or cross/isolated (seller). [CAUTION] Executes real trades. Private endpoint. Rate limit: 60 req/s.",
5470
+ description: "Place an OPTION order (buy/sell call or put). instId format: {uly}-{expiry}-{strike}-{C|P}, e.g. BTC-USD-241227-50000-C. tdMode: cash (buyer) or cross/isolated (seller). [CAUTION] Executes real trades.",
4606
5471
  isWrite: true,
4607
5472
  inputSchema: {
4608
5473
  type: "object",
@@ -4640,6 +5505,22 @@ function registerOptionTools() {
4640
5505
  clOrdId: {
4641
5506
  type: "string",
4642
5507
  description: "Client order ID (max 32 chars)"
5508
+ },
5509
+ tpTriggerPx: {
5510
+ type: "string",
5511
+ description: "TP trigger price; attaches a take-profit algo order"
5512
+ },
5513
+ tpOrdPx: {
5514
+ type: "string",
5515
+ description: "TP order price; -1=market"
5516
+ },
5517
+ slTriggerPx: {
5518
+ type: "string",
5519
+ description: "SL trigger price; attaches a stop-loss algo order"
5520
+ },
5521
+ slOrdPx: {
5522
+ type: "string",
5523
+ description: "SL order price; -1=market (recommended)"
4643
5524
  }
4644
5525
  },
4645
5526
  required: ["instId", "tdMode", "side", "ordType", "sz"]
@@ -4647,6 +5528,7 @@ function registerOptionTools() {
4647
5528
  handler: async (rawArgs, context) => {
4648
5529
  const args = asRecord(rawArgs);
4649
5530
  const reduceOnly = args.reduceOnly;
5531
+ const attachAlgoOrds = buildAttachAlgoOrds(args);
4650
5532
  const response = await context.client.privatePost(
4651
5533
  "/api/v5/trade/order",
4652
5534
  compactObject({
@@ -4658,17 +5540,18 @@ function registerOptionTools() {
4658
5540
  px: readString(args, "px"),
4659
5541
  reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
4660
5542
  clOrdId: readString(args, "clOrdId"),
4661
- tag: context.config.sourceTag
5543
+ tag: context.config.sourceTag,
5544
+ attachAlgoOrds
4662
5545
  }),
4663
5546
  privateRateLimit("option_place_order", 60)
4664
5547
  );
4665
- return normalize7(response);
5548
+ return normalizeResponse(response);
4666
5549
  }
4667
5550
  },
4668
5551
  {
4669
5552
  name: "option_cancel_order",
4670
5553
  module: "option",
4671
- description: "Cancel an unfilled OPTION order. Provide ordId or clOrdId. Private endpoint. Rate limit: 60 req/s.",
5554
+ description: "Cancel an unfilled OPTION order. Provide ordId or clOrdId.",
4672
5555
  isWrite: true,
4673
5556
  inputSchema: {
4674
5557
  type: "object",
@@ -4690,13 +5573,13 @@ function registerOptionTools() {
4690
5573
  }),
4691
5574
  privateRateLimit("option_cancel_order", 60)
4692
5575
  );
4693
- return normalize7(response);
5576
+ return normalizeResponse(response);
4694
5577
  }
4695
5578
  },
4696
5579
  {
4697
5580
  name: "option_batch_cancel",
4698
5581
  module: "option",
4699
- description: "[CAUTION] Batch cancel up to 20 OPTION orders. Each item: {instId, ordId?, clOrdId?}. Private endpoint. Rate limit: 60 req/s.",
5582
+ description: "[CAUTION] Batch cancel up to 20 OPTION orders. Each item: {instId, ordId?, clOrdId?}.",
4700
5583
  isWrite: true,
4701
5584
  inputSchema: {
4702
5585
  type: "object",
@@ -4720,13 +5603,13 @@ function registerOptionTools() {
4720
5603
  orders,
4721
5604
  privateRateLimit("option_batch_cancel", 60)
4722
5605
  );
4723
- return normalize7(response);
5606
+ return normalizeResponse(response);
4724
5607
  }
4725
5608
  },
4726
5609
  {
4727
5610
  name: "option_amend_order",
4728
5611
  module: "option",
4729
- description: "Amend an unfilled OPTION order (price and/or size). Provide ordId or clOrdId. Private endpoint. Rate limit: 60 req/s.",
5612
+ description: "Amend an unfilled OPTION order (price and/or size). Provide ordId or clOrdId.",
4730
5613
  isWrite: true,
4731
5614
  inputSchema: {
4732
5615
  type: "object",
@@ -4752,13 +5635,13 @@ function registerOptionTools() {
4752
5635
  }),
4753
5636
  privateRateLimit("option_amend_order", 60)
4754
5637
  );
4755
- return normalize7(response);
5638
+ return normalizeResponse(response);
4756
5639
  }
4757
5640
  },
4758
5641
  {
4759
5642
  name: "option_get_order",
4760
5643
  module: "option",
4761
- description: "Get details of a single OPTION order by ordId or clOrdId. Private endpoint. Rate limit: 60 req/s.",
5644
+ description: "Get details of a single OPTION order by ordId or clOrdId.",
4762
5645
  isWrite: false,
4763
5646
  inputSchema: {
4764
5647
  type: "object",
@@ -4780,13 +5663,13 @@ function registerOptionTools() {
4780
5663
  }),
4781
5664
  privateRateLimit("option_get_order", 60)
4782
5665
  );
4783
- return normalize7(response);
5666
+ return normalizeResponse(response);
4784
5667
  }
4785
5668
  },
4786
5669
  {
4787
5670
  name: "option_get_orders",
4788
5671
  module: "option",
4789
- description: "List OPTION orders. status: live=pending (default), history=7d, archive=3mo. Private endpoint. Rate limit: 20 req/s.",
5672
+ description: "List OPTION orders. status: live=pending (default), history=7d, archive=3mo.",
4790
5673
  isWrite: false,
4791
5674
  inputSchema: {
4792
5675
  type: "object",
@@ -4827,13 +5710,13 @@ function registerOptionTools() {
4827
5710
  }),
4828
5711
  privateRateLimit("option_get_orders", 20)
4829
5712
  );
4830
- return normalize7(response);
5713
+ return normalizeResponse(response);
4831
5714
  }
4832
5715
  },
4833
5716
  {
4834
5717
  name: "option_get_positions",
4835
5718
  module: "option",
4836
- description: "Get current OPTION positions including Greeks (delta, gamma, theta, vega). Private endpoint. Rate limit: 10 req/s.",
5719
+ description: "Get current OPTION positions including Greeks (delta, gamma, theta, vega).",
4837
5720
  isWrite: false,
4838
5721
  inputSchema: {
4839
5722
  type: "object",
@@ -4853,13 +5736,13 @@ function registerOptionTools() {
4853
5736
  }),
4854
5737
  privateRateLimit("option_get_positions", 10)
4855
5738
  );
4856
- return normalize7(response);
5739
+ return normalizeResponse(response);
4857
5740
  }
4858
5741
  },
4859
5742
  {
4860
5743
  name: "option_get_fills",
4861
5744
  module: "option",
4862
- description: "Get OPTION fill history. archive=false: last 3 days (default). archive=true: up to 3 months. Private endpoint. Rate limit: 20 req/s.",
5745
+ description: "Get OPTION fill history. archive=false: last 3 days (default); archive=true: up to 3 months.",
4863
5746
  isWrite: false,
4864
5747
  inputSchema: {
4865
5748
  type: "object",
@@ -4895,13 +5778,13 @@ function registerOptionTools() {
4895
5778
  }),
4896
5779
  privateRateLimit("option_get_fills", 20)
4897
5780
  );
4898
- return normalize7(response);
5781
+ return normalizeResponse(response);
4899
5782
  }
4900
5783
  },
4901
5784
  {
4902
5785
  name: "option_get_instruments",
4903
5786
  module: "option",
4904
- description: "List available OPTION contracts for a given underlying (option chain). Use to find valid instIds before placing orders. Public endpoint. Rate limit: 20 req/s.",
5787
+ description: "List available OPTION contracts for a given underlying (option chain). Use to find valid instIds before placing orders.",
4905
5788
  isWrite: false,
4906
5789
  inputSchema: {
4907
5790
  type: "object",
@@ -4928,13 +5811,13 @@ function registerOptionTools() {
4928
5811
  }),
4929
5812
  privateRateLimit("option_get_instruments", 20)
4930
5813
  );
4931
- return normalize7(response);
5814
+ return normalizeResponse(response);
4932
5815
  }
4933
5816
  },
4934
5817
  {
4935
5818
  name: "option_get_greeks",
4936
5819
  module: "option",
4937
- description: "Get implied volatility and Greeks (delta, gamma, theta, vega) for OPTION contracts by underlying. Public endpoint. Rate limit: 20 req/s.",
5820
+ description: "Get implied volatility and Greeks (delta, gamma, theta, vega) for OPTION contracts by underlying.",
4938
5821
  isWrite: false,
4939
5822
  inputSchema: {
4940
5823
  type: "object",
@@ -4960,24 +5843,17 @@ function registerOptionTools() {
4960
5843
  }),
4961
5844
  privateRateLimit("option_get_greeks", 20)
4962
5845
  );
4963
- return normalize7(response);
5846
+ return normalizeResponse(response);
4964
5847
  }
4965
5848
  }
4966
5849
  ];
4967
5850
  }
4968
- function normalize8(response) {
4969
- return {
4970
- endpoint: response.endpoint,
4971
- requestTime: response.requestTime,
4972
- data: response.data
4973
- };
4974
- }
4975
5851
  function registerSpotTradeTools() {
4976
5852
  return [
4977
5853
  {
4978
5854
  name: "spot_place_order",
4979
5855
  module: "spot",
4980
- description: "Place a spot order. Optionally attach take-profit/stop-loss via tpTriggerPx/slTriggerPx (assembled into attachAlgoOrds automatically). [CAUTION] Executes real trades. Private endpoint. Rate limit: 60 req/s per UID.",
5856
+ description: "Place a spot order. Optionally attach TP/SL via tpTriggerPx/slTriggerPx (assembled into attachAlgoOrds automatically). [CAUTION] Executes real trades.",
4981
5857
  isWrite: true,
4982
5858
  inputSchema: {
4983
5859
  type: "object",
@@ -5033,12 +5909,7 @@ function registerSpotTradeTools() {
5033
5909
  },
5034
5910
  handler: async (rawArgs, context) => {
5035
5911
  const args = asRecord(rawArgs);
5036
- const tpTriggerPx = readString(args, "tpTriggerPx");
5037
- const tpOrdPx = readString(args, "tpOrdPx");
5038
- const slTriggerPx = readString(args, "slTriggerPx");
5039
- const slOrdPx = readString(args, "slOrdPx");
5040
- const algoEntry = compactObject({ tpTriggerPx, tpOrdPx, slTriggerPx, slOrdPx });
5041
- const attachAlgoOrds = Object.keys(algoEntry).length > 0 ? [algoEntry] : void 0;
5912
+ const attachAlgoOrds = buildAttachAlgoOrds(args);
5042
5913
  const response = await context.client.privatePost(
5043
5914
  "/api/v5/trade/order",
5044
5915
  compactObject({
@@ -5054,13 +5925,13 @@ function registerSpotTradeTools() {
5054
5925
  }),
5055
5926
  privateRateLimit("spot_place_order", 60)
5056
5927
  );
5057
- return normalize8(response);
5928
+ return normalizeResponse(response);
5058
5929
  }
5059
5930
  },
5060
5931
  {
5061
5932
  name: "spot_cancel_order",
5062
5933
  module: "spot",
5063
- description: "Cancel an unfilled spot order by order ID or client order ID. Private endpoint. Rate limit: 60 req/s per UID.",
5934
+ description: "Cancel an unfilled spot order by order ID or client order ID.",
5064
5935
  isWrite: true,
5065
5936
  inputSchema: {
5066
5937
  type: "object",
@@ -5090,13 +5961,13 @@ function registerSpotTradeTools() {
5090
5961
  }),
5091
5962
  privateRateLimit("spot_cancel_order", 60)
5092
5963
  );
5093
- return normalize8(response);
5964
+ return normalizeResponse(response);
5094
5965
  }
5095
5966
  },
5096
5967
  {
5097
5968
  name: "spot_amend_order",
5098
5969
  module: "spot",
5099
- description: "Amend an unfilled spot order (modify price or size). Private endpoint. Rate limit: 60 req/s per UID.",
5970
+ description: "Amend an unfilled spot order (modify price or size).",
5100
5971
  isWrite: true,
5101
5972
  inputSchema: {
5102
5973
  type: "object",
@@ -5142,13 +6013,13 @@ function registerSpotTradeTools() {
5142
6013
  }),
5143
6014
  privateRateLimit("spot_amend_order", 60)
5144
6015
  );
5145
- return normalize8(response);
6016
+ return normalizeResponse(response);
5146
6017
  }
5147
6018
  },
5148
6019
  {
5149
6020
  name: "spot_get_orders",
5150
6021
  module: "spot",
5151
- description: "Query spot open orders, order history (last 7 days), or order archive (up to 3 months). Private endpoint. Rate limit: 20 req/s.",
6022
+ description: "Query spot open orders, order history (last 7 days), or order archive (up to 3 months).",
5152
6023
  isWrite: false,
5153
6024
  inputSchema: {
5154
6025
  type: "object",
@@ -5211,13 +6082,13 @@ function registerSpotTradeTools() {
5211
6082
  }),
5212
6083
  privateRateLimit("spot_get_orders", 20)
5213
6084
  );
5214
- return normalize8(response);
6085
+ return normalizeResponse(response);
5215
6086
  }
5216
6087
  },
5217
6088
  {
5218
6089
  name: "spot_place_algo_order",
5219
6090
  module: "spot",
5220
- description: "Place a spot algo order with take-profit and/or stop-loss. [CAUTION] Executes real trades. Private endpoint. Rate limit: 20 req/s per UID.",
6091
+ description: "Place a spot algo order: TP/SL (conditional/oco) or trailing stop (move_order_stop). For conditional/oco: use tpTriggerPx, tpOrdPx, slTriggerPx, slOrdPx. For move_order_stop: use callbackRatio (e.g. '0.01'=1%) OR callbackSpread, and optionally activePx. [CAUTION] Executes real trades.",
5221
6092
  isWrite: true,
5222
6093
  inputSchema: {
5223
6094
  type: "object",
@@ -5237,8 +6108,8 @@ function registerSpotTradeTools() {
5237
6108
  },
5238
6109
  ordType: {
5239
6110
  type: "string",
5240
- enum: ["conditional", "oco"],
5241
- description: "conditional=single TP/SL; oco=TP+SL pair (one-cancels-other)"
6111
+ enum: ["conditional", "oco", "move_order_stop"],
6112
+ description: "conditional=single TP/SL; oco=TP+SL pair (one-cancels-other); move_order_stop=trailing stop"
5242
6113
  },
5243
6114
  sz: {
5244
6115
  type: "string",
@@ -5246,19 +6117,31 @@ function registerSpotTradeTools() {
5246
6117
  },
5247
6118
  tpTriggerPx: {
5248
6119
  type: "string",
5249
- description: "TP trigger price"
6120
+ description: "TP trigger price (conditional/oco only)"
5250
6121
  },
5251
6122
  tpOrdPx: {
5252
6123
  type: "string",
5253
- description: "TP order price; -1=market"
6124
+ description: "TP order price; -1=market (conditional/oco only)"
5254
6125
  },
5255
6126
  slTriggerPx: {
5256
6127
  type: "string",
5257
- description: "SL trigger price"
6128
+ description: "SL trigger price (conditional/oco only)"
5258
6129
  },
5259
6130
  slOrdPx: {
5260
6131
  type: "string",
5261
- description: "SL order price; -1=market"
6132
+ description: "SL order price; -1=market (conditional/oco only)"
6133
+ },
6134
+ callbackRatio: {
6135
+ type: "string",
6136
+ description: "Callback ratio (e.g. '0.01'=1%); provide either ratio or spread (move_order_stop only)"
6137
+ },
6138
+ callbackSpread: {
6139
+ type: "string",
6140
+ description: "Callback spread in price units; provide either ratio or spread (move_order_stop only)"
6141
+ },
6142
+ activePx: {
6143
+ type: "string",
6144
+ description: "Activation price; tracking starts after market reaches this level (move_order_stop only)"
5262
6145
  }
5263
6146
  },
5264
6147
  required: ["instId", "side", "ordType", "sz"]
@@ -5277,17 +6160,20 @@ function registerSpotTradeTools() {
5277
6160
  tpOrdPx: readString(args, "tpOrdPx"),
5278
6161
  slTriggerPx: readString(args, "slTriggerPx"),
5279
6162
  slOrdPx: readString(args, "slOrdPx"),
6163
+ callbackRatio: readString(args, "callbackRatio"),
6164
+ callbackSpread: readString(args, "callbackSpread"),
6165
+ activePx: readString(args, "activePx"),
5280
6166
  tag: context.config.sourceTag
5281
6167
  }),
5282
6168
  privateRateLimit("spot_place_algo_order", 20)
5283
6169
  );
5284
- return normalize8(response);
6170
+ return normalizeResponse(response);
5285
6171
  }
5286
6172
  },
5287
6173
  {
5288
6174
  name: "spot_amend_algo_order",
5289
6175
  module: "spot",
5290
- description: "Amend a pending spot algo order (modify TP/SL prices or size). Private endpoint. Rate limit: 20 req/s.",
6176
+ description: "Amend a pending spot algo order (modify TP/SL prices or size).",
5291
6177
  isWrite: true,
5292
6178
  inputSchema: {
5293
6179
  type: "object",
@@ -5317,13 +6203,13 @@ function registerSpotTradeTools() {
5317
6203
  }),
5318
6204
  privateRateLimit("spot_amend_algo_order", 20)
5319
6205
  );
5320
- return normalize8(response);
6206
+ return normalizeResponse(response);
5321
6207
  }
5322
6208
  },
5323
6209
  {
5324
6210
  name: "spot_cancel_algo_order",
5325
6211
  module: "spot",
5326
- description: "Cancel a spot algo order (TP/SL). Private endpoint. Rate limit: 20 req/s per UID.",
6212
+ description: "Cancel a spot algo order (TP/SL).",
5327
6213
  isWrite: true,
5328
6214
  inputSchema: {
5329
6215
  type: "object",
@@ -5351,13 +6237,13 @@ function registerSpotTradeTools() {
5351
6237
  ],
5352
6238
  privateRateLimit("spot_cancel_algo_order", 20)
5353
6239
  );
5354
- return normalize8(response);
6240
+ return normalizeResponse(response);
5355
6241
  }
5356
6242
  },
5357
6243
  {
5358
6244
  name: "spot_get_algo_orders",
5359
6245
  module: "spot",
5360
- description: "Query spot algo orders (TP/SL) \u2014 pending or history. Private endpoint. Rate limit: 20 req/s.",
6246
+ description: "Query spot algo orders (TP/SL) \u2014 pending or history.",
5361
6247
  isWrite: false,
5362
6248
  inputSchema: {
5363
6249
  type: "object",
@@ -5373,7 +6259,7 @@ function registerSpotTradeTools() {
5373
6259
  },
5374
6260
  ordType: {
5375
6261
  type: "string",
5376
- enum: ["conditional", "oco"],
6262
+ enum: ["conditional", "oco", "move_order_stop"],
5377
6263
  description: "Filter by type; omit for all"
5378
6264
  },
5379
6265
  after: {
@@ -5416,15 +6302,17 @@ function registerSpotTradeTools() {
5416
6302
  { ...baseParams, ordType },
5417
6303
  privateRateLimit("spot_get_algo_orders", 20)
5418
6304
  );
5419
- return normalize8(response);
6305
+ return normalizeResponse(response);
5420
6306
  }
5421
- const [r1, r2] = await Promise.all([
6307
+ const [r1, r2, r3] = await Promise.all([
5422
6308
  context.client.privateGet(path4, { ...baseParams, ordType: "conditional" }, privateRateLimit("spot_get_algo_orders", 20)),
5423
- context.client.privateGet(path4, { ...baseParams, ordType: "oco" }, privateRateLimit("spot_get_algo_orders", 20))
6309
+ context.client.privateGet(path4, { ...baseParams, ordType: "oco" }, privateRateLimit("spot_get_algo_orders", 20)),
6310
+ context.client.privateGet(path4, { ...baseParams, ordType: "move_order_stop" }, privateRateLimit("spot_get_algo_orders", 20))
5424
6311
  ]);
5425
6312
  const merged = [
5426
6313
  ...r1.data ?? [],
5427
- ...r2.data ?? []
6314
+ ...r2.data ?? [],
6315
+ ...r3.data ?? []
5428
6316
  ];
5429
6317
  return { endpoint: r1.endpoint, requestTime: r1.requestTime, data: merged };
5430
6318
  }
@@ -5432,7 +6320,7 @@ function registerSpotTradeTools() {
5432
6320
  {
5433
6321
  name: "spot_get_fills",
5434
6322
  module: "spot",
5435
- description: "Get spot transaction fill details. archive=false (default): last 3 days. archive=true: up to 3 months, default limit 20. Private endpoint. Rate limit: 20 req/s.",
6323
+ description: "Get spot transaction fill details. archive=false (default): last 3 days; archive=true: up to 3 months.",
5436
6324
  isWrite: false,
5437
6325
  inputSchema: {
5438
6326
  type: "object",
@@ -5489,7 +6377,7 @@ function registerSpotTradeTools() {
5489
6377
  }),
5490
6378
  privateRateLimit("spot_get_fills", 20)
5491
6379
  );
5492
- return normalize8(response);
6380
+ return normalizeResponse(response);
5493
6381
  }
5494
6382
  },
5495
6383
  {
@@ -5530,12 +6418,7 @@ function registerSpotTradeTools() {
5530
6418
  };
5531
6419
  const body = action === "place" ? orders.map((order) => {
5532
6420
  const o = asRecord(order);
5533
- const tpTriggerPx = readString(o, "tpTriggerPx");
5534
- const tpOrdPx = readString(o, "tpOrdPx");
5535
- const slTriggerPx = readString(o, "slTriggerPx");
5536
- const slOrdPx = readString(o, "slOrdPx");
5537
- const algoEntry = compactObject({ tpTriggerPx, tpOrdPx, slTriggerPx, slOrdPx });
5538
- const attachAlgoOrds = Object.keys(algoEntry).length > 0 ? [algoEntry] : void 0;
6421
+ const attachAlgoOrds = buildAttachAlgoOrds(o);
5539
6422
  return compactObject({
5540
6423
  instId: requireString(o, "instId"),
5541
6424
  tdMode: readString(o, "tdMode") ?? "cash",
@@ -5553,13 +6436,13 @@ function registerSpotTradeTools() {
5553
6436
  body,
5554
6437
  privateRateLimit("spot_batch_orders", 60)
5555
6438
  );
5556
- return normalize8(response);
6439
+ return normalizeResponse(response);
5557
6440
  }
5558
6441
  },
5559
6442
  {
5560
6443
  name: "spot_get_order",
5561
6444
  module: "spot",
5562
- description: "Get details of a single spot order by order ID or client order ID. Private endpoint. Rate limit: 60 req/s.",
6445
+ description: "Get details of a single spot order by order ID or client order ID.",
5563
6446
  isWrite: false,
5564
6447
  inputSchema: {
5565
6448
  type: "object",
@@ -5590,13 +6473,13 @@ function registerSpotTradeTools() {
5590
6473
  }),
5591
6474
  privateRateLimit("spot_get_order", 60)
5592
6475
  );
5593
- return normalize8(response);
6476
+ return normalizeResponse(response);
5594
6477
  }
5595
6478
  },
5596
6479
  {
5597
6480
  name: "spot_batch_amend",
5598
6481
  module: "spot",
5599
- description: "[CAUTION] Batch amend up to 20 unfilled spot orders in one request. Modify price and/or size per order. Private endpoint. Rate limit: 60 req/s.",
6482
+ description: "[CAUTION] Batch amend up to 20 unfilled spot orders in one request. Modify price and/or size per order.",
5600
6483
  isWrite: true,
5601
6484
  inputSchema: {
5602
6485
  type: "object",
@@ -5620,13 +6503,13 @@ function registerSpotTradeTools() {
5620
6503
  orders,
5621
6504
  privateRateLimit("spot_batch_amend", 60)
5622
6505
  );
5623
- return normalize8(response);
6506
+ return normalizeResponse(response);
5624
6507
  }
5625
6508
  },
5626
6509
  {
5627
6510
  name: "spot_batch_cancel",
5628
6511
  module: "spot",
5629
- description: "[CAUTION] Batch cancel up to 20 spot orders in one request. Provide instId plus ordId or clOrdId for each order. Private endpoint. Rate limit: 60 req/s.",
6512
+ description: "[CAUTION] Batch cancel up to 20 spot orders in one request. Provide instId plus ordId or clOrdId for each order.",
5630
6513
  isWrite: true,
5631
6514
  inputSchema: {
5632
6515
  type: "object",
@@ -5650,25 +6533,18 @@ function registerSpotTradeTools() {
5650
6533
  orders,
5651
6534
  privateRateLimit("spot_batch_cancel", 60)
5652
6535
  );
5653
- return normalize8(response);
6536
+ return normalizeResponse(response);
5654
6537
  }
5655
6538
  }
5656
6539
  ];
5657
6540
  }
5658
6541
  var SWAP_INST_TYPES = ["SWAP", "FUTURES"];
5659
- function normalize9(response) {
5660
- return {
5661
- endpoint: response.endpoint,
5662
- requestTime: response.requestTime,
5663
- data: response.data
5664
- };
5665
- }
5666
6542
  function registerSwapTradeTools() {
5667
6543
  return [
5668
6544
  {
5669
6545
  name: "swap_place_order",
5670
6546
  module: "swap",
5671
- description: "Place a SWAP or FUTURES perpetual/delivery contract order. Optionally attach take-profit/stop-loss via tpTriggerPx/slTriggerPx (assembled into attachAlgoOrds automatically). [CAUTION] Executes real trades. Private endpoint. Rate limit: 60 req/s per UID.",
6547
+ description: "Place a SWAP or FUTURES contract order. Optionally attach TP/SL via tpTriggerPx/slTriggerPx (assembled into attachAlgoOrds automatically). [CAUTION] Executes real trades.",
5672
6548
  isWrite: true,
5673
6549
  inputSchema: {
5674
6550
  type: "object",
@@ -5735,12 +6611,7 @@ function registerSwapTradeTools() {
5735
6611
  handler: async (rawArgs, context) => {
5736
6612
  const args = asRecord(rawArgs);
5737
6613
  const reduceOnly = args.reduceOnly;
5738
- const tpTriggerPx = readString(args, "tpTriggerPx");
5739
- const tpOrdPx = readString(args, "tpOrdPx");
5740
- const slTriggerPx = readString(args, "slTriggerPx");
5741
- const slOrdPx = readString(args, "slOrdPx");
5742
- const algoEntry = compactObject({ tpTriggerPx, tpOrdPx, slTriggerPx, slOrdPx });
5743
- const attachAlgoOrds = Object.keys(algoEntry).length > 0 ? [algoEntry] : void 0;
6614
+ const attachAlgoOrds = buildAttachAlgoOrds(args);
5744
6615
  const response = await context.client.privatePost(
5745
6616
  "/api/v5/trade/order",
5746
6617
  compactObject({
@@ -5758,13 +6629,13 @@ function registerSwapTradeTools() {
5758
6629
  }),
5759
6630
  privateRateLimit("swap_place_order", 60)
5760
6631
  );
5761
- return normalize9(response);
6632
+ return normalizeResponse(response);
5762
6633
  }
5763
6634
  },
5764
6635
  {
5765
6636
  name: "swap_cancel_order",
5766
6637
  module: "swap",
5767
- description: "Cancel an unfilled SWAP or FUTURES order. Private endpoint. Rate limit: 60 req/s per UID.",
6638
+ description: "Cancel an unfilled SWAP or FUTURES order.",
5768
6639
  isWrite: true,
5769
6640
  inputSchema: {
5770
6641
  type: "object",
@@ -5794,13 +6665,13 @@ function registerSwapTradeTools() {
5794
6665
  }),
5795
6666
  privateRateLimit("swap_cancel_order", 60)
5796
6667
  );
5797
- return normalize9(response);
6668
+ return normalizeResponse(response);
5798
6669
  }
5799
6670
  },
5800
6671
  {
5801
6672
  name: "swap_get_orders",
5802
6673
  module: "swap",
5803
- description: "Query SWAP or FUTURES open orders, order history (last 7 days), or order archive (up to 3 months). Private endpoint. Rate limit: 20 req/s.",
6674
+ description: "Query SWAP or FUTURES open orders, history (last 7 days), or archive (up to 3 months).",
5804
6675
  isWrite: false,
5805
6676
  inputSchema: {
5806
6677
  type: "object",
@@ -5870,13 +6741,13 @@ function registerSwapTradeTools() {
5870
6741
  }),
5871
6742
  privateRateLimit("swap_get_orders", 20)
5872
6743
  );
5873
- return normalize9(response);
6744
+ return normalizeResponse(response);
5874
6745
  }
5875
6746
  },
5876
6747
  {
5877
6748
  name: "swap_get_positions",
5878
6749
  module: "swap",
5879
- description: "Get current SWAP or FUTURES positions. Private endpoint. Rate limit: 10 req/s.",
6750
+ description: "Get current SWAP or FUTURES positions.",
5880
6751
  isWrite: false,
5881
6752
  inputSchema: {
5882
6753
  type: "object",
@@ -5908,13 +6779,13 @@ function registerSwapTradeTools() {
5908
6779
  }),
5909
6780
  privateRateLimit("swap_get_positions", 10)
5910
6781
  );
5911
- return normalize9(response);
6782
+ return normalizeResponse(response);
5912
6783
  }
5913
6784
  },
5914
6785
  {
5915
6786
  name: "swap_set_leverage",
5916
6787
  module: "swap",
5917
- description: "Set leverage for a SWAP or FUTURES instrument or position. [CAUTION] Changes risk parameters. Private endpoint. Rate limit: 20 req/s.",
6788
+ description: "Set leverage for a SWAP or FUTURES instrument or position. [CAUTION] Changes risk parameters.",
5918
6789
  isWrite: true,
5919
6790
  inputSchema: {
5920
6791
  type: "object",
@@ -5951,13 +6822,13 @@ function registerSwapTradeTools() {
5951
6822
  }),
5952
6823
  privateRateLimit("swap_set_leverage", 20)
5953
6824
  );
5954
- return normalize9(response);
6825
+ return normalizeResponse(response);
5955
6826
  }
5956
6827
  },
5957
6828
  {
5958
6829
  name: "swap_amend_algo_order",
5959
6830
  module: "swap",
5960
- description: "Amend a pending SWAP/FUTURES algo order (modify TP/SL prices or size). Private endpoint. Rate limit: 20 req/s.",
6831
+ description: "Amend a pending SWAP/FUTURES algo order (modify TP/SL prices or size).",
5961
6832
  isWrite: true,
5962
6833
  inputSchema: {
5963
6834
  type: "object",
@@ -5987,13 +6858,13 @@ function registerSwapTradeTools() {
5987
6858
  }),
5988
6859
  privateRateLimit("swap_amend_algo_order", 20)
5989
6860
  );
5990
- return normalize9(response);
6861
+ return normalizeResponse(response);
5991
6862
  }
5992
6863
  },
5993
6864
  {
5994
6865
  name: "swap_get_fills",
5995
6866
  module: "swap",
5996
- description: "Get SWAP or FUTURES transaction fill details. archive=false (default): last 3 days. archive=true: up to 3 months, default limit 20. Private endpoint. Rate limit: 20 req/s.",
6867
+ description: "Get SWAP or FUTURES fill details. archive=false (default): last 3 days; archive=true: up to 3 months.",
5997
6868
  isWrite: false,
5998
6869
  inputSchema: {
5999
6870
  type: "object",
@@ -6057,13 +6928,13 @@ function registerSwapTradeTools() {
6057
6928
  }),
6058
6929
  privateRateLimit("swap_get_fills", 20)
6059
6930
  );
6060
- return normalize9(response);
6931
+ return normalizeResponse(response);
6061
6932
  }
6062
6933
  },
6063
6934
  {
6064
6935
  name: "swap_get_order",
6065
6936
  module: "swap",
6066
- description: "Get details of a single SWAP or FUTURES order by order ID or client order ID. Private endpoint. Rate limit: 60 req/s.",
6937
+ description: "Get details of a single SWAP or FUTURES order by order ID or client order ID.",
6067
6938
  isWrite: false,
6068
6939
  inputSchema: {
6069
6940
  type: "object",
@@ -6094,7 +6965,7 @@ function registerSwapTradeTools() {
6094
6965
  }),
6095
6966
  privateRateLimit("swap_get_order", 60)
6096
6967
  );
6097
- return normalize9(response);
6968
+ return normalizeResponse(response);
6098
6969
  }
6099
6970
  },
6100
6971
  {
@@ -6144,7 +7015,7 @@ function registerSwapTradeTools() {
6144
7015
  }),
6145
7016
  privateRateLimit("swap_close_position", 20)
6146
7017
  );
6147
- return normalize9(response);
7018
+ return normalizeResponse(response);
6148
7019
  }
6149
7020
  },
6150
7021
  {
@@ -6184,12 +7055,7 @@ function registerSwapTradeTools() {
6184
7055
  };
6185
7056
  const body = action === "place" ? orders.map((order) => {
6186
7057
  const o = asRecord(order);
6187
- const tpTriggerPx = readString(o, "tpTriggerPx");
6188
- const tpOrdPx = readString(o, "tpOrdPx");
6189
- const slTriggerPx = readString(o, "slTriggerPx");
6190
- const slOrdPx = readString(o, "slOrdPx");
6191
- const algoEntry = compactObject({ tpTriggerPx, tpOrdPx, slTriggerPx, slOrdPx });
6192
- const attachAlgoOrds = Object.keys(algoEntry).length > 0 ? [algoEntry] : void 0;
7058
+ const attachAlgoOrds = buildAttachAlgoOrds(o);
6193
7059
  const reduceOnly = o.reduceOnly;
6194
7060
  return compactObject({
6195
7061
  instId: requireString(o, "instId"),
@@ -6210,13 +7076,13 @@ function registerSwapTradeTools() {
6210
7076
  body,
6211
7077
  privateRateLimit("swap_batch_orders", 60)
6212
7078
  );
6213
- return normalize9(response);
7079
+ return normalizeResponse(response);
6214
7080
  }
6215
7081
  },
6216
7082
  {
6217
7083
  name: "swap_get_leverage",
6218
7084
  module: "swap",
6219
- description: "Get current leverage for a SWAP/FUTURES instrument. Call before swap_place_order to verify leverage. Private. Rate limit: 20 req/s.",
7085
+ description: "Get current leverage for a SWAP/FUTURES instrument. Call before swap_place_order to verify leverage.",
6220
7086
  isWrite: false,
6221
7087
  inputSchema: {
6222
7088
  type: "object",
@@ -6242,13 +7108,13 @@ function registerSwapTradeTools() {
6242
7108
  }),
6243
7109
  privateRateLimit("swap_get_leverage", 20)
6244
7110
  );
6245
- return normalize9(response);
7111
+ return normalizeResponse(response);
6246
7112
  }
6247
7113
  },
6248
7114
  {
6249
7115
  name: "swap_batch_amend",
6250
7116
  module: "swap",
6251
- description: "[CAUTION] Batch amend up to 20 unfilled SWAP/FUTURES orders in one request. Modify price and/or size per order. Private endpoint. Rate limit: 60 req/s.",
7117
+ description: "[CAUTION] Batch amend up to 20 unfilled SWAP/FUTURES orders in one request. Modify price and/or size per order.",
6252
7118
  isWrite: true,
6253
7119
  inputSchema: {
6254
7120
  type: "object",
@@ -6272,13 +7138,13 @@ function registerSwapTradeTools() {
6272
7138
  orders,
6273
7139
  privateRateLimit("swap_batch_amend", 60)
6274
7140
  );
6275
- return normalize9(response);
7141
+ return normalizeResponse(response);
6276
7142
  }
6277
7143
  },
6278
7144
  {
6279
7145
  name: "swap_batch_cancel",
6280
7146
  module: "swap",
6281
- description: "[CAUTION] Batch cancel up to 20 SWAP/FUTURES orders in one request. Provide instId plus ordId or clOrdId for each order. Private endpoint. Rate limit: 60 req/s.",
7147
+ description: "[CAUTION] Batch cancel up to 20 SWAP/FUTURES orders in one request. Provide instId plus ordId or clOrdId for each order.",
6282
7148
  isWrite: true,
6283
7149
  inputSchema: {
6284
7150
  type: "object",
@@ -6302,7 +7168,7 @@ function registerSwapTradeTools() {
6302
7168
  orders,
6303
7169
  privateRateLimit("swap_batch_cancel", 60)
6304
7170
  );
6305
- return normalize9(response);
7171
+ return normalizeResponse(response);
6306
7172
  }
6307
7173
  }
6308
7174
  ];
@@ -6313,7 +7179,9 @@ function allToolSpecs() {
6313
7179
  ...registerSpotTradeTools(),
6314
7180
  ...registerSwapTradeTools(),
6315
7181
  ...registerFuturesTools(),
7182
+ ...registerFuturesAlgoTools(),
6316
7183
  ...registerOptionTools(),
7184
+ ...registerOptionAlgoTools(),
6317
7185
  ...registerAlgoTradeTools(),
6318
7186
  ...registerAccountTools(),
6319
7187
  ...registerBotTools(),
@@ -6354,11 +7222,8 @@ function writeFullConfig(config) {
6354
7222
  }
6355
7223
  writeFileSync(path4, stringify(config), "utf-8");
6356
7224
  }
6357
- var BASE_MODULES = MODULES.filter(
6358
- (m) => !BOT_SUB_MODULE_IDS.includes(m) && !EARN_SUB_MODULE_IDS.includes(m)
6359
- );
6360
7225
  function expandShorthand(moduleId) {
6361
- if (moduleId === "all") return [...BASE_MODULES, ...BOT_SUB_MODULE_IDS];
7226
+ if (moduleId === "all") return [...MODULES];
6362
7227
  if (moduleId === "earn" || moduleId === "earn.all") return [...EARN_SUB_MODULE_IDS];
6363
7228
  if (moduleId === "bot") return [...BOT_DEFAULT_SUB_MODULES];
6364
7229
  if (moduleId === "bot.all") return [...BOT_SUB_MODULE_IDS];
@@ -6369,9 +7234,6 @@ function parseModuleList(rawModules) {
6369
7234
  return [...DEFAULT_MODULES];
6370
7235
  }
6371
7236
  const trimmed = rawModules.trim().toLowerCase();
6372
- if (trimmed === "all") {
6373
- return [...BASE_MODULES, ...BOT_SUB_MODULE_IDS];
6374
- }
6375
7237
  const requested = trimmed.split(",").map((s) => s.trim()).filter(Boolean);
6376
7238
  if (requested.length === 0) {
6377
7239
  return [...DEFAULT_MODULES];
@@ -6691,7 +7553,7 @@ function readCliVersion() {
6691
7553
  return "0.0.0";
6692
7554
  }
6693
7555
  var CLI_VERSION = readCliVersion();
6694
- var GIT_HASH = true ? "1df90cc" : "dev";
7556
+ var GIT_HASH = true ? "836b2ae" : "dev";
6695
7557
  var Report = class {
6696
7558
  lines = [];
6697
7559
  add(key, value) {
@@ -7272,7 +8134,7 @@ var HELP_TREE = {
7272
8134
  }
7273
8135
  },
7274
8136
  futures: {
7275
- description: "Futures trading (orders, positions)",
8137
+ description: "Futures trading (orders, positions, algo orders, leverage)",
7276
8138
  commands: {
7277
8139
  orders: {
7278
8140
  usage: "okx futures orders [--instId <id>] [--history] [--archive]",
@@ -7294,9 +8156,56 @@ var HELP_TREE = {
7294
8156
  usage: "okx futures cancel <instId> --ordId <id>",
7295
8157
  description: "Cancel a pending futures order"
7296
8158
  },
8159
+ amend: {
8160
+ usage: "okx futures amend --instId <id> [--ordId <id>] [--clOrdId <id>] [--newSz <n>] [--newPx <price>]",
8161
+ description: "Amend a pending futures order"
8162
+ },
7297
8163
  get: {
7298
8164
  usage: "okx futures get --instId <id> --ordId <id>",
7299
8165
  description: "Get details of a specific futures order"
8166
+ },
8167
+ close: {
8168
+ usage: "okx futures close --instId <id> --mgnMode <cross|isolated> [--posSide <net|long|short>] [--autoCxl]",
8169
+ description: "Close a futures position"
8170
+ },
8171
+ "get-leverage": {
8172
+ usage: "okx futures get-leverage --instId <id> --mgnMode <cross|isolated>",
8173
+ description: "Get current leverage for a futures instrument"
8174
+ },
8175
+ leverage: {
8176
+ usage: "okx futures leverage --instId <id> --lever <n> --mgnMode <cross|isolated> [--posSide <net|long|short>]",
8177
+ description: "Set leverage for a futures instrument"
8178
+ },
8179
+ batch: {
8180
+ usage: "okx futures batch --action <place|amend|cancel> --orders '<json>'",
8181
+ description: "Batch place, amend, or cancel futures orders"
8182
+ }
8183
+ },
8184
+ subgroups: {
8185
+ algo: {
8186
+ description: "Futures algo orders (trailing stop, conditional, OCO)",
8187
+ commands: {
8188
+ orders: {
8189
+ usage: "okx futures algo orders [--instId <id>] [--history] [--ordType <conditional|oco>]",
8190
+ description: "List futures algo orders"
8191
+ },
8192
+ trail: {
8193
+ usage: "okx futures algo trail --instId <id> --side <buy|sell> --sz <n> --callbackRatio <ratio>\n [--activePx <price>] [--posSide <net|long|short>] [--tdMode <cross|isolated>] [--reduceOnly]",
8194
+ description: "Place a trailing stop algo order for futures"
8195
+ },
8196
+ place: {
8197
+ usage: "okx futures algo place --instId <id> --side <buy|sell> --sz <n> [--ordType <conditional|oco>]\n [--tpTriggerPx <price>] [--tpOrdPx <price|-1>]\n [--slTriggerPx <price>] [--slOrdPx <price|-1>]\n [--posSide <net|long|short>] [--tdMode <cross|isolated>] [--reduceOnly]",
8198
+ description: "Place a futures algo order (take-profit/stop-loss)"
8199
+ },
8200
+ amend: {
8201
+ usage: "okx futures algo amend --instId <id> --algoId <id> [--newSz <n>]\n [--newTpTriggerPx <price>] [--newTpOrdPx <price|-1>]\n [--newSlTriggerPx <price>] [--newSlOrdPx <price|-1>]",
8202
+ description: "Amend a pending futures algo order"
8203
+ },
8204
+ cancel: {
8205
+ usage: "okx futures algo cancel --instId <id> --algoId <id>",
8206
+ description: "Cancel a pending futures algo order"
8207
+ }
8208
+ }
7300
8209
  }
7301
8210
  }
7302
8211
  },
@@ -8474,6 +9383,25 @@ async function cmdSpotFills(run, opts) {
8474
9383
  }))
8475
9384
  );
8476
9385
  }
9386
+ async function cmdSpotAlgoTrailPlace(run, opts) {
9387
+ const result = await run("spot_place_algo_order", {
9388
+ instId: opts.instId,
9389
+ tdMode: opts.tdMode ?? "cash",
9390
+ side: opts.side,
9391
+ ordType: "move_order_stop",
9392
+ sz: opts.sz,
9393
+ callbackRatio: opts.callbackRatio,
9394
+ callbackSpread: opts.callbackSpread,
9395
+ activePx: opts.activePx
9396
+ });
9397
+ const data = getData3(result);
9398
+ if (opts.json) return printJson(data);
9399
+ const order = data?.[0];
9400
+ process.stdout.write(
9401
+ `Trailing stop placed: ${order?.["algoId"]} (${order?.["sCode"] === "0" ? "OK" : order?.["sMsg"]})
9402
+ `
9403
+ );
9404
+ }
8477
9405
  async function cmdSpotBatch(run, opts) {
8478
9406
  let parsed;
8479
9407
  try {
@@ -8873,40 +9801,222 @@ async function cmdFuturesPlace(run, opts) {
8873
9801
  });
8874
9802
  const data = getData5(result);
8875
9803
  if (opts.json) return printJson(data);
8876
- const order = data?.[0];
8877
- process.stdout.write(`Order placed: ${order?.["ordId"]} (${order?.["sCode"] === "0" ? "OK" : order?.["sMsg"]})
8878
- `);
9804
+ const order = data?.[0];
9805
+ process.stdout.write(`Order placed: ${order?.["ordId"]} (${order?.["sCode"] === "0" ? "OK" : order?.["sMsg"]})
9806
+ `);
9807
+ }
9808
+ async function cmdFuturesCancel(run, instId, ordId, json) {
9809
+ const result = await run("futures_cancel_order", { instId, ordId });
9810
+ const data = getData5(result);
9811
+ if (json) return printJson(data);
9812
+ const r = data?.[0];
9813
+ process.stdout.write(`Cancelled: ${r?.["ordId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
9814
+ `);
9815
+ }
9816
+ async function cmdFuturesGet(run, opts) {
9817
+ const result = await run("futures_get_order", { instId: opts.instId, ordId: opts.ordId });
9818
+ const data = getData5(result);
9819
+ if (opts.json) return printJson(data);
9820
+ const o = data?.[0];
9821
+ if (!o) {
9822
+ process.stdout.write("No data\n");
9823
+ return;
9824
+ }
9825
+ printKv({
9826
+ ordId: o["ordId"],
9827
+ instId: o["instId"],
9828
+ side: o["side"],
9829
+ posSide: o["posSide"],
9830
+ ordType: o["ordType"],
9831
+ px: o["px"],
9832
+ sz: o["sz"],
9833
+ fillSz: o["fillSz"],
9834
+ avgPx: o["avgPx"],
9835
+ state: o["state"],
9836
+ cTime: new Date(Number(o["cTime"])).toLocaleString()
9837
+ });
9838
+ }
9839
+ async function cmdFuturesAmend(run, opts) {
9840
+ const result = await run("futures_amend_order", {
9841
+ instId: opts.instId,
9842
+ ordId: opts.ordId,
9843
+ clOrdId: opts.clOrdId,
9844
+ newSz: opts.newSz,
9845
+ newPx: opts.newPx
9846
+ });
9847
+ const data = getData5(result);
9848
+ if (opts.json) return printJson(data);
9849
+ const r = data?.[0];
9850
+ process.stdout.write(`Order amended: ${r?.["ordId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
9851
+ `);
9852
+ }
9853
+ async function cmdFuturesClose(run, opts) {
9854
+ const result = await run("futures_close_position", {
9855
+ instId: opts.instId,
9856
+ mgnMode: opts.mgnMode,
9857
+ posSide: opts.posSide,
9858
+ autoCxl: opts.autoCxl
9859
+ });
9860
+ const data = getData5(result);
9861
+ if (opts.json) return printJson(data);
9862
+ const r = data?.[0];
9863
+ process.stdout.write(`Position closed: ${r?.["instId"]} ${r?.["posSide"] ?? ""}
9864
+ `);
9865
+ }
9866
+ async function cmdFuturesSetLeverage(run, opts) {
9867
+ const result = await run("futures_set_leverage", {
9868
+ instId: opts.instId,
9869
+ lever: opts.lever,
9870
+ mgnMode: opts.mgnMode,
9871
+ posSide: opts.posSide
9872
+ });
9873
+ const data = getData5(result);
9874
+ if (opts.json) return printJson(data);
9875
+ const r = data?.[0];
9876
+ process.stdout.write(`Leverage set: ${r?.["lever"]}x ${r?.["instId"]}
9877
+ `);
9878
+ }
9879
+ async function cmdFuturesGetLeverage(run, opts) {
9880
+ const result = await run("futures_get_leverage", { instId: opts.instId, mgnMode: opts.mgnMode });
9881
+ const data = getData5(result);
9882
+ if (opts.json) return printJson(data);
9883
+ printTable(
9884
+ (data ?? []).map((r) => ({
9885
+ instId: r["instId"],
9886
+ mgnMode: r["mgnMode"],
9887
+ posSide: r["posSide"],
9888
+ lever: r["lever"]
9889
+ }))
9890
+ );
9891
+ }
9892
+ async function cmdFuturesBatch(run, opts) {
9893
+ let parsed;
9894
+ try {
9895
+ parsed = JSON.parse(opts.orders);
9896
+ } catch {
9897
+ process.stderr.write("Error: --orders must be a valid JSON array\n");
9898
+ process.exitCode = 1;
9899
+ return;
9900
+ }
9901
+ if (!Array.isArray(parsed) || parsed.length === 0) {
9902
+ process.stderr.write("Error: --orders must be a non-empty JSON array\n");
9903
+ process.exitCode = 1;
9904
+ return;
9905
+ }
9906
+ const toolMap = {
9907
+ place: "futures_batch_orders",
9908
+ amend: "futures_batch_amend",
9909
+ cancel: "futures_batch_cancel"
9910
+ };
9911
+ const tool = toolMap[opts.action];
9912
+ if (!tool) {
9913
+ process.stderr.write(`Error: --action must be one of: place, amend, cancel
9914
+ `);
9915
+ process.exitCode = 1;
9916
+ return;
9917
+ }
9918
+ const result = await run(tool, tool === "futures_batch_orders" ? { orders: parsed } : { orders: parsed });
9919
+ const data = getData5(result);
9920
+ if (opts.json) return printJson(data);
9921
+ for (const r of data ?? []) {
9922
+ process.stdout.write(`${r["ordId"] ?? r["clOrdId"] ?? "?"}: ${r["sCode"] === "0" ? "OK" : r["sMsg"]}
9923
+ `);
9924
+ }
9925
+ }
9926
+ async function cmdFuturesAlgoPlace(run, opts) {
9927
+ const result = await run("futures_place_algo_order", {
9928
+ instId: opts.instId,
9929
+ tdMode: opts.tdMode,
9930
+ side: opts.side,
9931
+ ordType: opts.ordType,
9932
+ sz: opts.sz,
9933
+ posSide: opts.posSide,
9934
+ tpTriggerPx: opts.tpTriggerPx,
9935
+ tpOrdPx: opts.tpOrdPx,
9936
+ slTriggerPx: opts.slTriggerPx,
9937
+ slOrdPx: opts.slOrdPx,
9938
+ reduceOnly: opts.reduceOnly
9939
+ });
9940
+ const data = getData5(result);
9941
+ if (opts.json) return printJson(data);
9942
+ const order = data?.[0];
9943
+ process.stdout.write(
9944
+ `Algo order placed: ${order?.["algoId"]} (${order?.["sCode"] === "0" ? "OK" : order?.["sMsg"]})
9945
+ `
9946
+ );
9947
+ }
9948
+ async function cmdFuturesAlgoTrailPlace(run, opts) {
9949
+ const result = await run("futures_place_move_stop_order", {
9950
+ instId: opts.instId,
9951
+ tdMode: opts.tdMode,
9952
+ side: opts.side,
9953
+ sz: opts.sz,
9954
+ callbackRatio: opts.callbackRatio,
9955
+ callbackSpread: opts.callbackSpread,
9956
+ activePx: opts.activePx,
9957
+ posSide: opts.posSide,
9958
+ reduceOnly: opts.reduceOnly
9959
+ });
9960
+ const data = getData5(result);
9961
+ if (opts.json) return printJson(data);
9962
+ const order = data?.[0];
9963
+ process.stdout.write(
9964
+ `Trailing stop placed: ${order?.["algoId"]} (${order?.["sCode"] === "0" ? "OK" : order?.["sMsg"]})
9965
+ `
9966
+ );
9967
+ }
9968
+ async function cmdFuturesAlgoAmend(run, opts) {
9969
+ const result = await run("futures_amend_algo_order", {
9970
+ instId: opts.instId,
9971
+ algoId: opts.algoId,
9972
+ newSz: opts.newSz,
9973
+ newTpTriggerPx: opts.newTpTriggerPx,
9974
+ newTpOrdPx: opts.newTpOrdPx,
9975
+ newSlTriggerPx: opts.newSlTriggerPx,
9976
+ newSlOrdPx: opts.newSlOrdPx
9977
+ });
9978
+ const data = getData5(result);
9979
+ if (opts.json) return printJson(data);
9980
+ const r = data?.[0];
9981
+ process.stdout.write(
9982
+ `Algo order amended: ${r?.["algoId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
9983
+ `
9984
+ );
8879
9985
  }
8880
- async function cmdFuturesCancel(run, instId, ordId, json) {
8881
- const result = await run("futures_cancel_order", { instId, ordId });
9986
+ async function cmdFuturesAlgoCancel(run, instId, algoId, json) {
9987
+ const result = await run("futures_cancel_algo_orders", { orders: [{ instId, algoId }] });
8882
9988
  const data = getData5(result);
8883
9989
  if (json) return printJson(data);
8884
9990
  const r = data?.[0];
8885
- process.stdout.write(`Cancelled: ${r?.["ordId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
8886
- `);
9991
+ process.stdout.write(
9992
+ `Algo order cancelled: ${r?.["algoId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
9993
+ `
9994
+ );
8887
9995
  }
8888
- async function cmdFuturesGet(run, opts) {
8889
- const result = await run("futures_get_order", { instId: opts.instId, ordId: opts.ordId });
8890
- const data = getData5(result);
8891
- if (opts.json) return printJson(data);
8892
- const o = data?.[0];
8893
- if (!o) {
8894
- process.stdout.write("No data\n");
9996
+ async function cmdFuturesAlgoOrders(run, opts) {
9997
+ const result = await run("futures_get_algo_orders", {
9998
+ instId: opts.instId,
9999
+ status: opts.status,
10000
+ ordType: opts.ordType
10001
+ });
10002
+ const orders = getData5(result);
10003
+ if (opts.json) return printJson(orders);
10004
+ if (!(orders ?? []).length) {
10005
+ process.stdout.write("No algo orders\n");
8895
10006
  return;
8896
10007
  }
8897
- printKv({
8898
- ordId: o["ordId"],
8899
- instId: o["instId"],
8900
- side: o["side"],
8901
- posSide: o["posSide"],
8902
- ordType: o["ordType"],
8903
- px: o["px"],
8904
- sz: o["sz"],
8905
- fillSz: o["fillSz"],
8906
- avgPx: o["avgPx"],
8907
- state: o["state"],
8908
- cTime: new Date(Number(o["cTime"])).toLocaleString()
8909
- });
10008
+ printTable(
10009
+ orders.map((o) => ({
10010
+ algoId: o["algoId"],
10011
+ instId: o["instId"],
10012
+ type: o["ordType"],
10013
+ side: o["side"],
10014
+ sz: o["sz"],
10015
+ tpTrigger: o["tpTriggerPx"],
10016
+ slTrigger: o["slTriggerPx"],
10017
+ state: o["state"]
10018
+ }))
10019
+ );
8910
10020
  }
8911
10021
 
8912
10022
  // src/commands/option.ts
@@ -9050,7 +10160,11 @@ async function cmdOptionPlace(run, opts) {
9050
10160
  sz: opts.sz,
9051
10161
  px: opts.px,
9052
10162
  reduceOnly: opts.reduceOnly,
9053
- clOrdId: opts.clOrdId
10163
+ clOrdId: opts.clOrdId,
10164
+ tpTriggerPx: opts.tpTriggerPx,
10165
+ tpOrdPx: opts.tpOrdPx,
10166
+ slTriggerPx: opts.slTriggerPx,
10167
+ slOrdPx: opts.slOrdPx
9054
10168
  });
9055
10169
  const data = getData6(result);
9056
10170
  if (opts.json) return printJson(data);
@@ -9106,6 +10220,81 @@ async function cmdOptionBatchCancel(run, opts) {
9106
10220
  `);
9107
10221
  }
9108
10222
  }
10223
+ async function cmdOptionAlgoPlace(run, opts) {
10224
+ const result = await run("option_place_algo_order", {
10225
+ instId: opts.instId,
10226
+ tdMode: opts.tdMode,
10227
+ side: opts.side,
10228
+ ordType: opts.ordType,
10229
+ sz: opts.sz,
10230
+ tpTriggerPx: opts.tpTriggerPx,
10231
+ tpOrdPx: opts.tpOrdPx,
10232
+ slTriggerPx: opts.slTriggerPx,
10233
+ slOrdPx: opts.slOrdPx,
10234
+ reduceOnly: opts.reduceOnly,
10235
+ clOrdId: opts.clOrdId
10236
+ });
10237
+ const data = getData6(result);
10238
+ if (opts.json) return printJson(data);
10239
+ const order = data?.[0];
10240
+ process.stdout.write(
10241
+ `Algo order placed: ${order?.["algoId"]} (${order?.["sCode"] === "0" ? "OK" : order?.["sMsg"]})
10242
+ `
10243
+ );
10244
+ }
10245
+ async function cmdOptionAlgoAmend(run, opts) {
10246
+ const result = await run("option_amend_algo_order", {
10247
+ instId: opts.instId,
10248
+ algoId: opts.algoId,
10249
+ newSz: opts.newSz,
10250
+ newTpTriggerPx: opts.newTpTriggerPx,
10251
+ newTpOrdPx: opts.newTpOrdPx,
10252
+ newSlTriggerPx: opts.newSlTriggerPx,
10253
+ newSlOrdPx: opts.newSlOrdPx
10254
+ });
10255
+ const data = getData6(result);
10256
+ if (opts.json) return printJson(data);
10257
+ const r = data?.[0];
10258
+ process.stdout.write(
10259
+ `Algo order amended: ${r?.["algoId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
10260
+ `
10261
+ );
10262
+ }
10263
+ async function cmdOptionAlgoCancel(run, opts) {
10264
+ const result = await run("option_cancel_algo_orders", { orders: [{ instId: opts.instId, algoId: opts.algoId }] });
10265
+ const data = getData6(result);
10266
+ if (opts.json) return printJson(data);
10267
+ const r = data?.[0];
10268
+ process.stdout.write(
10269
+ `Algo order cancelled: ${r?.["algoId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
10270
+ `
10271
+ );
10272
+ }
10273
+ async function cmdOptionAlgoOrders(run, opts) {
10274
+ const result = await run("option_get_algo_orders", {
10275
+ instId: opts.instId,
10276
+ status: opts.status,
10277
+ ordType: opts.ordType
10278
+ });
10279
+ const orders = getData6(result);
10280
+ if (opts.json) return printJson(orders);
10281
+ if (!(orders ?? []).length) {
10282
+ process.stdout.write("No algo orders\n");
10283
+ return;
10284
+ }
10285
+ printTable(
10286
+ orders.map((o) => ({
10287
+ algoId: o["algoId"],
10288
+ instId: o["instId"],
10289
+ type: o["ordType"],
10290
+ side: o["side"],
10291
+ sz: o["sz"],
10292
+ tpTrigger: o["tpTriggerPx"],
10293
+ slTrigger: o["slTriggerPx"],
10294
+ state: o["state"]
10295
+ }))
10296
+ );
10297
+ }
9109
10298
 
9110
10299
  // src/config/toml.ts
9111
10300
  function writeCliConfig(config) {
@@ -10168,7 +11357,7 @@ async function cmdDcdQuoteAndBuy(run, opts) {
10168
11357
  // src/index.ts
10169
11358
  var _require2 = createRequire2(import.meta.url);
10170
11359
  var CLI_VERSION2 = _require2("../package.json").version;
10171
- var GIT_HASH2 = true ? "1df90cc" : "dev";
11360
+ var GIT_HASH2 = true ? "836b2ae" : "dev";
10172
11361
  function handleConfigCommand(action, rest, json, lang, force) {
10173
11362
  if (action === "init") return cmdConfigInit(lang === "zh" ? "zh" : "en");
10174
11363
  if (action === "show") return cmdConfigShow(json);
@@ -10280,6 +11469,17 @@ function handleAccountCommand(run, action, rest, v, json) {
10280
11469
  return handleAccountWriteCommand(run, action, v, json);
10281
11470
  }
10282
11471
  function handleSpotAlgoCommand(run, subAction, v, json) {
11472
+ if (subAction === "trail")
11473
+ return cmdSpotAlgoTrailPlace(run, {
11474
+ instId: v.instId,
11475
+ side: v.side,
11476
+ sz: v.sz,
11477
+ callbackRatio: v.callbackRatio,
11478
+ callbackSpread: v.callbackSpread,
11479
+ activePx: v.activePx,
11480
+ tdMode: v.tdMode,
11481
+ json
11482
+ });
10283
11483
  if (subAction === "place")
10284
11484
  return cmdSpotAlgoPlace(run, {
10285
11485
  instId: v.instId,
@@ -10472,7 +11672,44 @@ function handleSwapCommand(run, action, rest, v, json) {
10472
11672
  if (action === "batch")
10473
11673
  return cmdSwapBatch(run, { action: v.action, orders: v.orders, json });
10474
11674
  }
10475
- function handleOptionCommand(run, action, _rest, v, json) {
11675
+ function handleOptionAlgoCommand(run, subAction, v, json) {
11676
+ if (subAction === "place")
11677
+ return cmdOptionAlgoPlace(run, {
11678
+ instId: v.instId,
11679
+ tdMode: v.tdMode,
11680
+ side: v.side,
11681
+ ordType: v.ordType ?? "conditional",
11682
+ sz: v.sz,
11683
+ tpTriggerPx: v.tpTriggerPx,
11684
+ tpOrdPx: v.tpOrdPx,
11685
+ slTriggerPx: v.slTriggerPx,
11686
+ slOrdPx: v.slOrdPx,
11687
+ reduceOnly: v.reduceOnly,
11688
+ clOrdId: v.clOrdId,
11689
+ json
11690
+ });
11691
+ if (subAction === "amend")
11692
+ return cmdOptionAlgoAmend(run, {
11693
+ instId: v.instId,
11694
+ algoId: v.algoId,
11695
+ newSz: v.newSz,
11696
+ newTpTriggerPx: v.newTpTriggerPx,
11697
+ newTpOrdPx: v.newTpOrdPx,
11698
+ newSlTriggerPx: v.newSlTriggerPx,
11699
+ newSlOrdPx: v.newSlOrdPx,
11700
+ json
11701
+ });
11702
+ if (subAction === "cancel")
11703
+ return cmdOptionAlgoCancel(run, { instId: v.instId, algoId: v.algoId, json });
11704
+ if (subAction === "orders")
11705
+ return cmdOptionAlgoOrders(run, {
11706
+ instId: v.instId,
11707
+ status: v.history ? "history" : "pending",
11708
+ ordType: v.ordType,
11709
+ json
11710
+ });
11711
+ }
11712
+ function handleOptionCommand(run, action, rest, v, json) {
10476
11713
  if (action === "orders") {
10477
11714
  let status = "live";
10478
11715
  if (v.archive) status = "archive";
@@ -10499,6 +11736,10 @@ function handleOptionCommand(run, action, _rest, v, json) {
10499
11736
  px: v.px,
10500
11737
  reduceOnly: v.reduceOnly,
10501
11738
  clOrdId: v.clOrdId,
11739
+ tpTriggerPx: v.tpTriggerPx,
11740
+ tpOrdPx: v.tpOrdPx,
11741
+ slTriggerPx: v.slTriggerPx,
11742
+ slOrdPx: v.slOrdPx,
10502
11743
  json
10503
11744
  });
10504
11745
  if (action === "cancel")
@@ -10514,6 +11755,58 @@ function handleOptionCommand(run, action, _rest, v, json) {
10514
11755
  });
10515
11756
  if (action === "batch-cancel")
10516
11757
  return cmdOptionBatchCancel(run, { orders: v.orders, json });
11758
+ if (action === "algo")
11759
+ return handleOptionAlgoCommand(run, rest[0], v, json);
11760
+ }
11761
+ function handleFuturesAlgoCommand(run, subAction, v, json) {
11762
+ if (subAction === "trail")
11763
+ return cmdFuturesAlgoTrailPlace(run, {
11764
+ instId: v.instId,
11765
+ side: v.side,
11766
+ sz: v.sz,
11767
+ callbackRatio: v.callbackRatio,
11768
+ callbackSpread: v.callbackSpread,
11769
+ activePx: v.activePx,
11770
+ posSide: v.posSide,
11771
+ tdMode: v.tdMode ?? "cross",
11772
+ reduceOnly: v.reduceOnly,
11773
+ json
11774
+ });
11775
+ if (subAction === "place")
11776
+ return cmdFuturesAlgoPlace(run, {
11777
+ instId: v.instId,
11778
+ side: v.side,
11779
+ ordType: v.ordType ?? "conditional",
11780
+ sz: v.sz,
11781
+ posSide: v.posSide,
11782
+ tdMode: v.tdMode ?? "cross",
11783
+ tpTriggerPx: v.tpTriggerPx,
11784
+ tpOrdPx: v.tpOrdPx,
11785
+ slTriggerPx: v.slTriggerPx,
11786
+ slOrdPx: v.slOrdPx,
11787
+ reduceOnly: v.reduceOnly,
11788
+ json
11789
+ });
11790
+ if (subAction === "amend")
11791
+ return cmdFuturesAlgoAmend(run, {
11792
+ instId: v.instId,
11793
+ algoId: v.algoId,
11794
+ newSz: v.newSz,
11795
+ newTpTriggerPx: v.newTpTriggerPx,
11796
+ newTpOrdPx: v.newTpOrdPx,
11797
+ newSlTriggerPx: v.newSlTriggerPx,
11798
+ newSlOrdPx: v.newSlOrdPx,
11799
+ json
11800
+ });
11801
+ if (subAction === "cancel")
11802
+ return cmdFuturesAlgoCancel(run, v.instId, v.algoId, json);
11803
+ if (subAction === "orders")
11804
+ return cmdFuturesAlgoOrders(run, {
11805
+ instId: v.instId,
11806
+ status: v.history ? "history" : "pending",
11807
+ ordType: v.ordType,
11808
+ json
11809
+ });
10517
11810
  }
10518
11811
  function handleFuturesCommand(run, action, rest, v, json) {
10519
11812
  if (action === "orders") {
@@ -10550,6 +11843,37 @@ function handleFuturesCommand(run, action, rest, v, json) {
10550
11843
  return cmdFuturesCancel(run, rest[0] ?? v.instId, v.ordId, json);
10551
11844
  if (action === "get")
10552
11845
  return cmdFuturesGet(run, { instId: rest[0] ?? v.instId, ordId: v.ordId, json });
11846
+ if (action === "amend")
11847
+ return cmdFuturesAmend(run, {
11848
+ instId: v.instId,
11849
+ ordId: v.ordId,
11850
+ clOrdId: v.clOrdId,
11851
+ newSz: v.newSz,
11852
+ newPx: v.newPx,
11853
+ json
11854
+ });
11855
+ if (action === "close")
11856
+ return cmdFuturesClose(run, {
11857
+ instId: v.instId,
11858
+ mgnMode: v.mgnMode,
11859
+ posSide: v.posSide,
11860
+ autoCxl: v.autoCxl,
11861
+ json
11862
+ });
11863
+ if (action === "get-leverage")
11864
+ return cmdFuturesGetLeverage(run, { instId: v.instId, mgnMode: v.mgnMode, json });
11865
+ if (action === "leverage")
11866
+ return cmdFuturesSetLeverage(run, {
11867
+ instId: v.instId,
11868
+ lever: v.lever,
11869
+ mgnMode: v.mgnMode,
11870
+ posSide: v.posSide,
11871
+ json
11872
+ });
11873
+ if (action === "batch")
11874
+ return cmdFuturesBatch(run, { action: v.action, orders: v.orders, json });
11875
+ if (action === "algo")
11876
+ return handleFuturesAlgoCommand(run, rest[0], v, json);
10553
11877
  }
10554
11878
  function handleBotGridCommand(run, v, rest, json) {
10555
11879
  const subAction = rest[0];