@pionex/pionex-trade-mcp 0.2.36 → 0.2.38
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/README.md +1 -0
- package/dist/index.js +383 -27
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -39,6 +39,7 @@ Credentials are read from `~/.pionex/config.toml` when the server starts; the cl
|
|
|
39
39
|
- **Account** (auth): `pionex_account_get_balance`
|
|
40
40
|
- **Orders** (auth): `pionex_orders_new_order`, `pionex_orders_get_order`, `pionex_orders_get_order_by_client_order_id`, `pionex_orders_get_open_orders`, `pionex_orders_get_all_orders`, `pionex_orders_cancel_order`, `pionex_orders_get_fills`, `pionex_orders_get_fills_by_order_id`, `pionex_orders_cancel_all_orders`
|
|
41
41
|
- **Bot / Futures Grid** (auth): `pionex_bot_futures_grid_get_order`, `pionex_bot_futures_grid_create`, `pionex_bot_futures_grid_adjust_params`, `pionex_bot_futures_grid_reduce`, `pionex_bot_futures_grid_cancel`
|
|
42
|
+
- **Bot / Spot Grid** (auth): `pionex_bot_spot_grid_get_order`, `pionex_bot_spot_grid_get_ai_strategy`, `pionex_bot_spot_grid_create`, `pionex_bot_spot_grid_adjust_params`, `pionex_bot_spot_grid_invest_in`, `pionex_bot_spot_grid_cancel`, `pionex_bot_spot_grid_profit`
|
|
42
43
|
|
|
43
44
|
### `pionex_bot_futures_grid_create` (strict OpenAPI)
|
|
44
45
|
|
package/dist/index.js
CHANGED
|
@@ -1536,6 +1536,24 @@ var createFuturesGridCreateToolInputSchema = {
|
|
|
1536
1536
|
__dryRun: { type: "boolean", description: "Internal: when true, return resolved body without POST" }
|
|
1537
1537
|
}
|
|
1538
1538
|
};
|
|
1539
|
+
var CREATE_SPOT_GRID_ORDER_DATA_KEYS = [
|
|
1540
|
+
"top",
|
|
1541
|
+
"bottom",
|
|
1542
|
+
"row",
|
|
1543
|
+
"gridType",
|
|
1544
|
+
"quoteTotalInvestment",
|
|
1545
|
+
"lossStopType",
|
|
1546
|
+
"lossStop",
|
|
1547
|
+
"lossStopDelay",
|
|
1548
|
+
"profitStopType",
|
|
1549
|
+
"profitStop",
|
|
1550
|
+
"profitStopDelay",
|
|
1551
|
+
"condition",
|
|
1552
|
+
"conditionDirection",
|
|
1553
|
+
"slippage",
|
|
1554
|
+
"closeSellModel"
|
|
1555
|
+
];
|
|
1556
|
+
var ORDER_DATA_KEY_SET2 = new Set(CREATE_SPOT_GRID_ORDER_DATA_KEYS);
|
|
1539
1557
|
function asNonEmptyString2(value, field) {
|
|
1540
1558
|
if (typeof value !== "string" || value.trim().length === 0) {
|
|
1541
1559
|
throw new Error(`Invalid "${field}": expected non-empty string.`);
|
|
@@ -1560,13 +1578,181 @@ function asPositiveInteger2(value, field) {
|
|
|
1560
1578
|
}
|
|
1561
1579
|
return n;
|
|
1562
1580
|
}
|
|
1581
|
+
function asNonNegativeInteger(value, field) {
|
|
1582
|
+
const n = asFiniteNumber2(value, field);
|
|
1583
|
+
if (n < 0 || !Number.isInteger(n)) {
|
|
1584
|
+
throw new Error(`Invalid "${field}": expected non-negative integer.`);
|
|
1585
|
+
}
|
|
1586
|
+
return n;
|
|
1587
|
+
}
|
|
1588
|
+
function assertEnum2(value, field, allowed) {
|
|
1589
|
+
if (!allowed.includes(value)) {
|
|
1590
|
+
throw new Error(`Invalid "${field}": expected one of ${allowed.join(", ")}.`);
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
function asPositiveDecimalStringLoose2(value, field) {
|
|
1594
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0) {
|
|
1595
|
+
return String(value);
|
|
1596
|
+
}
|
|
1597
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
1598
|
+
throw new Error(`Invalid "${field}": expected positive decimal string.`);
|
|
1599
|
+
}
|
|
1600
|
+
const s = value.trim();
|
|
1601
|
+
if (!/^\d+(\.\d+)?$/.test(s)) {
|
|
1602
|
+
throw new Error(`Invalid "${field}": expected positive decimal string.`);
|
|
1603
|
+
}
|
|
1604
|
+
const n = Number(s);
|
|
1605
|
+
if (!Number.isFinite(n) || n <= 0) {
|
|
1606
|
+
throw new Error(`Invalid "${field}": expected positive decimal string.`);
|
|
1607
|
+
}
|
|
1608
|
+
return s;
|
|
1609
|
+
}
|
|
1610
|
+
function asOptionalString2(value, field) {
|
|
1611
|
+
if (typeof value !== "string") {
|
|
1612
|
+
throw new Error(`Invalid "${field}": expected string.`);
|
|
1613
|
+
}
|
|
1614
|
+
return value;
|
|
1615
|
+
}
|
|
1616
|
+
function parseAndValidateCreateSpotGridBuOrderData(raw) {
|
|
1617
|
+
const data = { ...raw };
|
|
1618
|
+
for (const k of Object.keys(data)) {
|
|
1619
|
+
if (!ORDER_DATA_KEY_SET2.has(k)) {
|
|
1620
|
+
throw new Error(`Unknown buOrderData property "${k}". Allowed keys: ${CREATE_SPOT_GRID_ORDER_DATA_KEYS.join(", ")}.`);
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
const top = asPositiveDecimalStringLoose2(data.top, "buOrderData.top");
|
|
1624
|
+
const bottom = asPositiveDecimalStringLoose2(data.bottom, "buOrderData.bottom");
|
|
1625
|
+
if (Number(top) <= Number(bottom)) {
|
|
1626
|
+
throw new Error('Invalid "buOrderData.top": expected top > bottom.');
|
|
1627
|
+
}
|
|
1628
|
+
const row = asPositiveInteger2(data.row, "buOrderData.row");
|
|
1629
|
+
if (row < 2 || row > 200) {
|
|
1630
|
+
throw new Error('Invalid "buOrderData.row": expected integer between 2 and 200.');
|
|
1631
|
+
}
|
|
1632
|
+
const gridType = asNonEmptyString2(data.gridType, "buOrderData.gridType");
|
|
1633
|
+
assertEnum2(gridType, "buOrderData.gridType", ["arithmetic", "geometric"]);
|
|
1634
|
+
const quoteTotalInvestment = asPositiveDecimalStringLoose2(data.quoteTotalInvestment, "buOrderData.quoteTotalInvestment");
|
|
1635
|
+
const out = {
|
|
1636
|
+
top,
|
|
1637
|
+
bottom,
|
|
1638
|
+
row,
|
|
1639
|
+
gridType,
|
|
1640
|
+
quoteTotalInvestment
|
|
1641
|
+
};
|
|
1642
|
+
if (data.lossStopType != null) {
|
|
1643
|
+
const v = asNonEmptyString2(data.lossStopType, "buOrderData.lossStopType");
|
|
1644
|
+
assertEnum2(v, "buOrderData.lossStopType", ["price", "profit_amount", "profit_ratio"]);
|
|
1645
|
+
out.lossStopType = v;
|
|
1646
|
+
}
|
|
1647
|
+
if (data.lossStop != null) out.lossStop = asOptionalString2(data.lossStop, "buOrderData.lossStop");
|
|
1648
|
+
if (data.lossStopDelay != null) out.lossStopDelay = asNonNegativeInteger(data.lossStopDelay, "buOrderData.lossStopDelay");
|
|
1649
|
+
if (data.profitStopType != null) {
|
|
1650
|
+
const v = asNonEmptyString2(data.profitStopType, "buOrderData.profitStopType");
|
|
1651
|
+
assertEnum2(v, "buOrderData.profitStopType", ["price", "profit_amount", "profit_ratio"]);
|
|
1652
|
+
out.profitStopType = v;
|
|
1653
|
+
}
|
|
1654
|
+
if (data.profitStop != null) out.profitStop = asOptionalString2(data.profitStop, "buOrderData.profitStop");
|
|
1655
|
+
if (data.profitStopDelay != null) out.profitStopDelay = asNonNegativeInteger(data.profitStopDelay, "buOrderData.profitStopDelay");
|
|
1656
|
+
if (data.condition != null) out.condition = asOptionalString2(data.condition, "buOrderData.condition");
|
|
1657
|
+
if (data.conditionDirection != null) {
|
|
1658
|
+
const v = asNonEmptyString2(data.conditionDirection, "buOrderData.conditionDirection");
|
|
1659
|
+
assertEnum2(v, "buOrderData.conditionDirection", ["-1", "1"]);
|
|
1660
|
+
out.conditionDirection = v;
|
|
1661
|
+
}
|
|
1662
|
+
if (data.slippage != null) out.slippage = asOptionalString2(data.slippage, "buOrderData.slippage");
|
|
1663
|
+
if (data.closeSellModel != null) {
|
|
1664
|
+
const v = asNonEmptyString2(data.closeSellModel, "buOrderData.closeSellModel");
|
|
1665
|
+
assertEnum2(v, "buOrderData.closeSellModel", ["NOT_SELL", "TO_QUOTE", "TO_USDT"]);
|
|
1666
|
+
out.closeSellModel = v;
|
|
1667
|
+
}
|
|
1668
|
+
return out;
|
|
1669
|
+
}
|
|
1670
|
+
var createSpotGridOrderDataJsonSchema = {
|
|
1671
|
+
type: "object",
|
|
1672
|
+
additionalProperties: false,
|
|
1673
|
+
description: "CreateSpotGridOrderData (openapi_bot.yaml PR #7). Required: top, bottom, row, gridType, quoteTotalInvestment.",
|
|
1674
|
+
required: ["top", "bottom", "row", "gridType", "quoteTotalInvestment"],
|
|
1675
|
+
properties: {
|
|
1676
|
+
top: { type: "string", description: "Grid upper price" },
|
|
1677
|
+
bottom: { type: "string", description: "Grid lower price" },
|
|
1678
|
+
row: { type: "number", description: "Number of grid levels (2\u2013200)" },
|
|
1679
|
+
gridType: {
|
|
1680
|
+
type: "string",
|
|
1681
|
+
enum: ["arithmetic", "geometric"],
|
|
1682
|
+
description: "Grid spacing: arithmetic (equal difference) or geometric (equal ratio)"
|
|
1683
|
+
},
|
|
1684
|
+
quoteTotalInvestment: { type: "string", description: "Total quote currency investment amount" },
|
|
1685
|
+
lossStopType: {
|
|
1686
|
+
type: "string",
|
|
1687
|
+
enum: ["price", "profit_amount", "profit_ratio"],
|
|
1688
|
+
description: "Stop loss type"
|
|
1689
|
+
},
|
|
1690
|
+
lossStop: { type: "string", description: "Stop loss threshold value" },
|
|
1691
|
+
lossStopDelay: { type: "number", description: "Seconds before executing stop loss (0=immediate)" },
|
|
1692
|
+
profitStopType: {
|
|
1693
|
+
type: "string",
|
|
1694
|
+
enum: ["price", "profit_amount", "profit_ratio"],
|
|
1695
|
+
description: "Take profit type"
|
|
1696
|
+
},
|
|
1697
|
+
profitStop: { type: "string", description: "Take profit threshold value" },
|
|
1698
|
+
profitStopDelay: { type: "number", description: "Seconds before executing take profit (0=immediate)" },
|
|
1699
|
+
condition: { type: "string", description: "Trigger price for conditional start" },
|
|
1700
|
+
conditionDirection: {
|
|
1701
|
+
type: "string",
|
|
1702
|
+
enum: ["-1", "1"],
|
|
1703
|
+
description: 'Trigger direction: "-1" drop below, "1" rise above'
|
|
1704
|
+
},
|
|
1705
|
+
slippage: { type: "string", description: "Slippage tolerance e.g. 0.01 = 1%" },
|
|
1706
|
+
closeSellModel: {
|
|
1707
|
+
type: "string",
|
|
1708
|
+
enum: ["NOT_SELL", "TO_QUOTE", "TO_USDT"],
|
|
1709
|
+
description: "Close sell model (default: NOT_SELL)"
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
};
|
|
1713
|
+
var createSpotGridCreateToolInputSchema = {
|
|
1714
|
+
type: "object",
|
|
1715
|
+
additionalProperties: false,
|
|
1716
|
+
required: ["base", "quote", "buOrderData"],
|
|
1717
|
+
properties: {
|
|
1718
|
+
base: { type: "string", description: "Base currency (e.g. BTC)" },
|
|
1719
|
+
quote: { type: "string", description: "Quote currency (e.g. USDT)" },
|
|
1720
|
+
note: { type: "string", description: "Optional order note" },
|
|
1721
|
+
buOrderData: createSpotGridOrderDataJsonSchema,
|
|
1722
|
+
__dryRun: { type: "boolean", description: "Internal: when true, return resolved body without POST" }
|
|
1723
|
+
}
|
|
1724
|
+
};
|
|
1725
|
+
function asNonEmptyString3(value, field) {
|
|
1726
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
1727
|
+
throw new Error(`Invalid "${field}": expected non-empty string.`);
|
|
1728
|
+
}
|
|
1729
|
+
return value.trim();
|
|
1730
|
+
}
|
|
1731
|
+
function asFiniteNumber3(value, field) {
|
|
1732
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
1733
|
+
throw new Error(`Invalid "${field}": expected finite number.`);
|
|
1734
|
+
}
|
|
1735
|
+
return value;
|
|
1736
|
+
}
|
|
1737
|
+
function asPositiveNumber3(value, field) {
|
|
1738
|
+
const n = asFiniteNumber3(value, field);
|
|
1739
|
+
if (n <= 0) throw new Error(`Invalid "${field}": expected number > 0.`);
|
|
1740
|
+
return n;
|
|
1741
|
+
}
|
|
1742
|
+
function asPositiveInteger3(value, field) {
|
|
1743
|
+
const n = asPositiveNumber3(value, field);
|
|
1744
|
+
if (!Number.isInteger(n)) {
|
|
1745
|
+
throw new Error(`Invalid "${field}": expected positive integer.`);
|
|
1746
|
+
}
|
|
1747
|
+
return n;
|
|
1748
|
+
}
|
|
1563
1749
|
function asBoolean2(value, field) {
|
|
1564
1750
|
if (typeof value !== "boolean") {
|
|
1565
1751
|
throw new Error(`Invalid "${field}": expected boolean.`);
|
|
1566
1752
|
}
|
|
1567
1753
|
return value;
|
|
1568
1754
|
}
|
|
1569
|
-
function
|
|
1755
|
+
function assertEnum3(value, field, allowed) {
|
|
1570
1756
|
if (!allowed.includes(value)) {
|
|
1571
1757
|
throw new Error(`Invalid "${field}": expected one of ${allowed.join(", ")}.`);
|
|
1572
1758
|
}
|
|
@@ -1578,7 +1764,7 @@ function asObject(value, field) {
|
|
|
1578
1764
|
return value;
|
|
1579
1765
|
}
|
|
1580
1766
|
function asPositiveDecimalString2(value, field) {
|
|
1581
|
-
const s =
|
|
1767
|
+
const s = asNonEmptyString3(value, field);
|
|
1582
1768
|
if (!/^\d+(\.\d+)?$/.test(s)) {
|
|
1583
1769
|
throw new Error(`Invalid "${field}": expected positive decimal string.`);
|
|
1584
1770
|
}
|
|
@@ -1624,9 +1810,9 @@ function registerBotTools() {
|
|
|
1624
1810
|
if (config.readOnly) {
|
|
1625
1811
|
throw new Error("Server is running in --read-only mode; bot futures_grid create is disabled.");
|
|
1626
1812
|
}
|
|
1627
|
-
const rawBase =
|
|
1813
|
+
const rawBase = asNonEmptyString3(args.base, "base");
|
|
1628
1814
|
const base = normalizePerpBase(rawBase);
|
|
1629
|
-
const quote =
|
|
1815
|
+
const quote = asNonEmptyString3(args.quote, "quote");
|
|
1630
1816
|
const buOrderDataOut = parseAndValidateCreateFuturesGridBuOrderData(asObject(args.buOrderData, "buOrderData"));
|
|
1631
1817
|
const row = buOrderDataOut.row;
|
|
1632
1818
|
const gridType = buOrderDataOut.grid_type;
|
|
@@ -1686,12 +1872,12 @@ function registerBotTools() {
|
|
|
1686
1872
|
if (config.readOnly) {
|
|
1687
1873
|
throw new Error("Server is running in --read-only mode; bot futures_grid adjust_params is disabled.");
|
|
1688
1874
|
}
|
|
1689
|
-
const buOrderId =
|
|
1690
|
-
const type =
|
|
1691
|
-
|
|
1875
|
+
const buOrderId = asNonEmptyString3(args.buOrderId, "buOrderId");
|
|
1876
|
+
const type = asNonEmptyString3(args.type, "type");
|
|
1877
|
+
assertEnum3(type, "type", ["invest_in", "adjust_params", "invest_in_trigger"]);
|
|
1692
1878
|
const extraMargin = asBoolean2(args.extraMargin, "extraMargin");
|
|
1693
1879
|
if (type === "invest_in" && args.quoteInvestment != null) {
|
|
1694
|
-
|
|
1880
|
+
asPositiveNumber3(args.quoteInvestment, "quoteInvestment");
|
|
1695
1881
|
}
|
|
1696
1882
|
if (type === "adjust_params") {
|
|
1697
1883
|
const bottom = asPositiveDecimalString2(args.bottom, "bottom");
|
|
@@ -1699,35 +1885,35 @@ function registerBotTools() {
|
|
|
1699
1885
|
if (Number(top) <= Number(bottom)) {
|
|
1700
1886
|
throw new Error('Invalid "top": expected top > bottom.');
|
|
1701
1887
|
}
|
|
1702
|
-
|
|
1888
|
+
asPositiveInteger3(args.row, "row");
|
|
1703
1889
|
}
|
|
1704
1890
|
if (type === "invest_in_trigger") {
|
|
1705
1891
|
asPositiveDecimalString2(args.condition, "condition");
|
|
1706
|
-
const conditionDirection =
|
|
1707
|
-
|
|
1892
|
+
const conditionDirection = asNonEmptyString3(args.conditionDirection, "conditionDirection");
|
|
1893
|
+
assertEnum3(conditionDirection, "conditionDirection", ["1", "-1"]);
|
|
1708
1894
|
}
|
|
1709
1895
|
const body = {
|
|
1710
1896
|
buOrderId,
|
|
1711
1897
|
type,
|
|
1712
1898
|
extraMargin
|
|
1713
1899
|
};
|
|
1714
|
-
if (args.quoteInvestment != null) body.quoteInvestment =
|
|
1900
|
+
if (args.quoteInvestment != null) body.quoteInvestment = asFiniteNumber3(args.quoteInvestment, "quoteInvestment");
|
|
1715
1901
|
if (args.bottom != null) body.bottom = asPositiveDecimalString2(args.bottom, "bottom");
|
|
1716
1902
|
if (args.top != null) body.top = asPositiveDecimalString2(args.top, "top");
|
|
1717
|
-
if (args.row != null) body.row =
|
|
1718
|
-
if (args.extraMarginAmount != null) body.extraMarginAmount =
|
|
1903
|
+
if (args.row != null) body.row = asPositiveInteger3(args.row, "row");
|
|
1904
|
+
if (args.extraMarginAmount != null) body.extraMarginAmount = asFiniteNumber3(args.extraMarginAmount, "extraMarginAmount");
|
|
1719
1905
|
if (args.isRecommend != null) body.isRecommend = asBoolean2(args.isRecommend, "isRecommend");
|
|
1720
1906
|
if (args.isReinvest != null) body.isReinvest = asBoolean2(args.isReinvest, "isReinvest");
|
|
1721
1907
|
if (args.investCoin != null) body.investCoin = String(args.investCoin);
|
|
1722
1908
|
if (args.investmentFrom != null) {
|
|
1723
|
-
const investmentFrom =
|
|
1724
|
-
|
|
1909
|
+
const investmentFrom = asNonEmptyString3(args.investmentFrom, "investmentFrom");
|
|
1910
|
+
assertEnum3(investmentFrom, "investmentFrom", ["USER", "LOCK_ACTIVITY"]);
|
|
1725
1911
|
body.investmentFrom = investmentFrom;
|
|
1726
1912
|
}
|
|
1727
1913
|
if (args.condition != null) body.condition = asPositiveDecimalString2(args.condition, "condition");
|
|
1728
1914
|
if (args.conditionDirection != null) {
|
|
1729
|
-
const conditionDirection =
|
|
1730
|
-
|
|
1915
|
+
const conditionDirection = asNonEmptyString3(args.conditionDirection, "conditionDirection");
|
|
1916
|
+
assertEnum3(conditionDirection, "conditionDirection", ["1", "-1"]);
|
|
1731
1917
|
body.conditionDirection = conditionDirection;
|
|
1732
1918
|
}
|
|
1733
1919
|
if (args.slippage != null) body.slippage = String(args.slippage);
|
|
@@ -1756,8 +1942,8 @@ function registerBotTools() {
|
|
|
1756
1942
|
if (config.readOnly) {
|
|
1757
1943
|
throw new Error("Server is running in --read-only mode; bot futures_grid reduce is disabled.");
|
|
1758
1944
|
}
|
|
1759
|
-
const buOrderId =
|
|
1760
|
-
const reduceNum =
|
|
1945
|
+
const buOrderId = asNonEmptyString3(args.buOrderId, "buOrderId");
|
|
1946
|
+
const reduceNum = asPositiveInteger3(args.reduceNum, "reduceNum");
|
|
1761
1947
|
const body = {
|
|
1762
1948
|
buOrderId,
|
|
1763
1949
|
reduceNum
|
|
@@ -1765,8 +1951,8 @@ function registerBotTools() {
|
|
|
1765
1951
|
if (args.slippage != null) body.slippage = String(args.slippage);
|
|
1766
1952
|
if (args.condition != null) body.condition = String(args.condition);
|
|
1767
1953
|
if (args.conditionDirection != null) {
|
|
1768
|
-
const conditionDirection =
|
|
1769
|
-
|
|
1954
|
+
const conditionDirection = asNonEmptyString3(args.conditionDirection, "conditionDirection");
|
|
1955
|
+
assertEnum3(conditionDirection, "conditionDirection", ["1", "-1"]);
|
|
1770
1956
|
body.conditionDirection = conditionDirection;
|
|
1771
1957
|
}
|
|
1772
1958
|
return (await client.signedPost("/api/v1/bot/orders/futuresGrid/reduce", body)).data;
|
|
@@ -1776,14 +1962,14 @@ function registerBotTools() {
|
|
|
1776
1962
|
name: "pionex_bot_order_list",
|
|
1777
1963
|
module: "bot",
|
|
1778
1964
|
isWrite: false,
|
|
1779
|
-
description: "List bot orders with optional filters and pagination. status: 'running' (default) or '
|
|
1965
|
+
description: "List bot orders with optional filters and pagination. status: 'running' (default) or 'finished'. buOrderTypes: one or more of futures_grid, spot_grid, smart_copy. Endpoint: GET /api/v1/bot/orders",
|
|
1780
1966
|
inputSchema: {
|
|
1781
1967
|
type: "object",
|
|
1782
1968
|
additionalProperties: false,
|
|
1783
1969
|
properties: {
|
|
1784
1970
|
status: {
|
|
1785
1971
|
type: "string",
|
|
1786
|
-
enum: ["running", "
|
|
1972
|
+
enum: ["running", "finished"],
|
|
1787
1973
|
description: "Filter by order status. Default: 'running'."
|
|
1788
1974
|
},
|
|
1789
1975
|
base: { type: "string", description: "Base currency filter (e.g. BTC)." },
|
|
@@ -1830,18 +2016,188 @@ function registerBotTools() {
|
|
|
1830
2016
|
if (config.readOnly) {
|
|
1831
2017
|
throw new Error("Server is running in --read-only mode; bot futures_grid cancel is disabled.");
|
|
1832
2018
|
}
|
|
1833
|
-
const buOrderId =
|
|
2019
|
+
const buOrderId = asNonEmptyString3(args.buOrderId, "buOrderId");
|
|
1834
2020
|
const body = { buOrderId };
|
|
1835
2021
|
if (args.closeNote != null) body.closeNote = String(args.closeNote);
|
|
1836
2022
|
if (args.closeSellModel != null) {
|
|
1837
|
-
const closeSellModel =
|
|
1838
|
-
|
|
2023
|
+
const closeSellModel = asNonEmptyString3(args.closeSellModel, "closeSellModel");
|
|
2024
|
+
assertEnum3(closeSellModel, "closeSellModel", ["TO_QUOTE", "TO_USDT"]);
|
|
1839
2025
|
body.closeSellModel = closeSellModel;
|
|
1840
2026
|
}
|
|
1841
2027
|
if (args.immediate != null) body.immediate = asBoolean2(args.immediate, "immediate");
|
|
1842
2028
|
if (args.closeSlippage != null) body.closeSlippage = String(args.closeSlippage);
|
|
1843
2029
|
return (await client.signedPost("/api/v1/bot/orders/futuresGrid/cancel", body)).data;
|
|
1844
2030
|
}
|
|
2031
|
+
},
|
|
2032
|
+
{
|
|
2033
|
+
name: "pionex_bot_spot_grid_get_order",
|
|
2034
|
+
module: "bot",
|
|
2035
|
+
isWrite: false,
|
|
2036
|
+
description: "Get one spot grid bot order by buOrderId.",
|
|
2037
|
+
inputSchema: {
|
|
2038
|
+
type: "object",
|
|
2039
|
+
additionalProperties: false,
|
|
2040
|
+
properties: {
|
|
2041
|
+
buOrderId: { type: "string", description: "Spot grid bot order id." }
|
|
2042
|
+
},
|
|
2043
|
+
required: ["buOrderId"]
|
|
2044
|
+
},
|
|
2045
|
+
async handler(args, { client }) {
|
|
2046
|
+
const buOrderId = asNonEmptyString3(args.buOrderId, "buOrderId");
|
|
2047
|
+
const q = { buOrderId };
|
|
2048
|
+
return (await client.signedGet("/api/v1/bot/orders/spotGrid/order", q)).data;
|
|
2049
|
+
}
|
|
2050
|
+
},
|
|
2051
|
+
{
|
|
2052
|
+
name: "pionex_bot_spot_grid_get_ai_strategy",
|
|
2053
|
+
module: "bot",
|
|
2054
|
+
isWrite: false,
|
|
2055
|
+
description: "Retrieve AI-recommended spot grid strategy parameters for a trading pair.",
|
|
2056
|
+
inputSchema: {
|
|
2057
|
+
type: "object",
|
|
2058
|
+
additionalProperties: false,
|
|
2059
|
+
properties: {
|
|
2060
|
+
base: { type: "string", description: "Base currency (e.g. BTC)" },
|
|
2061
|
+
quote: { type: "string", description: "Quote currency (e.g. USDT)" }
|
|
2062
|
+
},
|
|
2063
|
+
required: ["base", "quote"]
|
|
2064
|
+
},
|
|
2065
|
+
async handler(args, { client }) {
|
|
2066
|
+
const base = asNonEmptyString3(args.base, "base");
|
|
2067
|
+
const quote = asNonEmptyString3(args.quote, "quote");
|
|
2068
|
+
return (await client.signedGet("/api/v1/bot/orders/spotGrid/aiStrategy", { base, quote })).data;
|
|
2069
|
+
}
|
|
2070
|
+
},
|
|
2071
|
+
{
|
|
2072
|
+
name: "pionex_bot_spot_grid_create",
|
|
2073
|
+
module: "bot",
|
|
2074
|
+
isWrite: true,
|
|
2075
|
+
description: "Create a spot grid bot order (openapi_bot.yaml CreateSpotGridRequest / CreateSpotGridOrderData). Required: base, quote, buOrderData. Optional: note. buOrderData required: top, bottom, row, gridType, quoteTotalInvestment; unknown keys rejected.",
|
|
2076
|
+
inputSchema: createSpotGridCreateToolInputSchema,
|
|
2077
|
+
async handler(args, { client, config }) {
|
|
2078
|
+
if (config.readOnly) {
|
|
2079
|
+
throw new Error("Server is running in --read-only mode; bot spot_grid create is disabled.");
|
|
2080
|
+
}
|
|
2081
|
+
const base = asNonEmptyString3(args.base, "base");
|
|
2082
|
+
const quote = asNonEmptyString3(args.quote, "quote");
|
|
2083
|
+
const buOrderDataOut = parseAndValidateCreateSpotGridBuOrderData(asObject(args.buOrderData, "buOrderData"));
|
|
2084
|
+
const body = { base, quote, buOrderData: buOrderDataOut };
|
|
2085
|
+
if (args.note != null) body.note = String(args.note);
|
|
2086
|
+
if (args.__dryRun === true) {
|
|
2087
|
+
return {
|
|
2088
|
+
dryRun: true,
|
|
2089
|
+
note: "No order was sent. Body matches openapi_bot.yaml CreateSpotGridRequest.",
|
|
2090
|
+
resolvedBody: body
|
|
2091
|
+
};
|
|
2092
|
+
}
|
|
2093
|
+
return (await client.signedPost("/api/v1/bot/orders/spotGrid/create", body)).data;
|
|
2094
|
+
}
|
|
2095
|
+
},
|
|
2096
|
+
{
|
|
2097
|
+
name: "pionex_bot_spot_grid_adjust_params",
|
|
2098
|
+
module: "bot",
|
|
2099
|
+
isWrite: true,
|
|
2100
|
+
description: "Adjust spot grid bot range or investment parameters.",
|
|
2101
|
+
inputSchema: {
|
|
2102
|
+
type: "object",
|
|
2103
|
+
additionalProperties: false,
|
|
2104
|
+
properties: {
|
|
2105
|
+
buOrderId: { type: "string" },
|
|
2106
|
+
top: { type: "string", description: "New upper price" },
|
|
2107
|
+
bottom: { type: "string", description: "New lower price" },
|
|
2108
|
+
row: { type: "number", description: "New number of grid levels" },
|
|
2109
|
+
quoteInvest: { type: "string", description: "Additional quote investment amount" }
|
|
2110
|
+
},
|
|
2111
|
+
required: ["buOrderId"]
|
|
2112
|
+
},
|
|
2113
|
+
async handler(args, { client, config }) {
|
|
2114
|
+
if (config.readOnly) {
|
|
2115
|
+
throw new Error("Server is running in --read-only mode; bot spot_grid adjust_params is disabled.");
|
|
2116
|
+
}
|
|
2117
|
+
const buOrderId = asNonEmptyString3(args.buOrderId, "buOrderId");
|
|
2118
|
+
const body = { buOrderId };
|
|
2119
|
+
if (args.top != null) body.top = asPositiveDecimalString2(args.top, "top");
|
|
2120
|
+
if (args.bottom != null) body.bottom = asPositiveDecimalString2(args.bottom, "bottom");
|
|
2121
|
+
if (args.row != null) body.row = asPositiveInteger3(args.row, "row");
|
|
2122
|
+
if (args.quoteInvest != null) body.quoteInvest = asPositiveDecimalString2(args.quoteInvest, "quoteInvest");
|
|
2123
|
+
return (await client.signedPost("/api/v1/bot/orders/spotGrid/adjustParams", body)).data;
|
|
2124
|
+
}
|
|
2125
|
+
},
|
|
2126
|
+
{
|
|
2127
|
+
name: "pionex_bot_spot_grid_invest_in",
|
|
2128
|
+
module: "bot",
|
|
2129
|
+
isWrite: true,
|
|
2130
|
+
description: "Add additional quote investment to a running spot grid bot.",
|
|
2131
|
+
inputSchema: {
|
|
2132
|
+
type: "object",
|
|
2133
|
+
additionalProperties: false,
|
|
2134
|
+
properties: {
|
|
2135
|
+
buOrderId: { type: "string" },
|
|
2136
|
+
quoteInvest: { type: "string", description: "Quote amount to invest" }
|
|
2137
|
+
},
|
|
2138
|
+
required: ["buOrderId", "quoteInvest"]
|
|
2139
|
+
},
|
|
2140
|
+
async handler(args, { client, config }) {
|
|
2141
|
+
if (config.readOnly) {
|
|
2142
|
+
throw new Error("Server is running in --read-only mode; bot spot_grid invest_in is disabled.");
|
|
2143
|
+
}
|
|
2144
|
+
const buOrderId = asNonEmptyString3(args.buOrderId, "buOrderId");
|
|
2145
|
+
const quoteInvest = asPositiveDecimalString2(args.quoteInvest, "quoteInvest");
|
|
2146
|
+
return (await client.signedPost("/api/v1/bot/orders/spotGrid/investIn", { buOrderId, quoteInvest })).data;
|
|
2147
|
+
}
|
|
2148
|
+
},
|
|
2149
|
+
{
|
|
2150
|
+
name: "pionex_bot_spot_grid_cancel",
|
|
2151
|
+
module: "bot",
|
|
2152
|
+
isWrite: true,
|
|
2153
|
+
description: "Cancel and close a spot grid bot order.",
|
|
2154
|
+
inputSchema: {
|
|
2155
|
+
type: "object",
|
|
2156
|
+
additionalProperties: false,
|
|
2157
|
+
properties: {
|
|
2158
|
+
buOrderId: { type: "string" },
|
|
2159
|
+
closeSellModel: { type: "string", enum: ["NOT_SELL", "TO_QUOTE", "TO_USDT"] },
|
|
2160
|
+
slippage: { type: "string" }
|
|
2161
|
+
},
|
|
2162
|
+
required: ["buOrderId"]
|
|
2163
|
+
},
|
|
2164
|
+
async handler(args, { client, config }) {
|
|
2165
|
+
if (config.readOnly) {
|
|
2166
|
+
throw new Error("Server is running in --read-only mode; bot spot_grid cancel is disabled.");
|
|
2167
|
+
}
|
|
2168
|
+
const buOrderId = asNonEmptyString3(args.buOrderId, "buOrderId");
|
|
2169
|
+
const body = { buOrderId };
|
|
2170
|
+
if (args.closeSellModel != null) {
|
|
2171
|
+
const closeSellModel = asNonEmptyString3(args.closeSellModel, "closeSellModel");
|
|
2172
|
+
assertEnum3(closeSellModel, "closeSellModel", ["NOT_SELL", "TO_QUOTE", "TO_USDT"]);
|
|
2173
|
+
body.closeSellModel = closeSellModel;
|
|
2174
|
+
}
|
|
2175
|
+
if (args.slippage != null) body.slippage = String(args.slippage);
|
|
2176
|
+
return (await client.signedPost("/api/v1/bot/orders/spotGrid/cancel", body)).data;
|
|
2177
|
+
}
|
|
2178
|
+
},
|
|
2179
|
+
{
|
|
2180
|
+
name: "pionex_bot_spot_grid_profit",
|
|
2181
|
+
module: "bot",
|
|
2182
|
+
isWrite: true,
|
|
2183
|
+
description: "Extract accumulated grid profit from a spot grid bot order.",
|
|
2184
|
+
inputSchema: {
|
|
2185
|
+
type: "object",
|
|
2186
|
+
additionalProperties: false,
|
|
2187
|
+
properties: {
|
|
2188
|
+
buOrderId: { type: "string" },
|
|
2189
|
+
amount: { type: "string", description: "Amount of profit to extract" }
|
|
2190
|
+
},
|
|
2191
|
+
required: ["buOrderId", "amount"]
|
|
2192
|
+
},
|
|
2193
|
+
async handler(args, { client, config }) {
|
|
2194
|
+
if (config.readOnly) {
|
|
2195
|
+
throw new Error("Server is running in --read-only mode; bot spot_grid profit is disabled.");
|
|
2196
|
+
}
|
|
2197
|
+
const buOrderId = asNonEmptyString3(args.buOrderId, "buOrderId");
|
|
2198
|
+
const amount = asPositiveDecimalString2(args.amount, "amount");
|
|
2199
|
+
return (await client.signedPost("/api/v1/bot/orders/spotGrid/profit", { buOrderId, amount })).data;
|
|
2200
|
+
}
|
|
1845
2201
|
}
|
|
1846
2202
|
];
|
|
1847
2203
|
}
|