@okx_ai/okx-trade-cli 1.3.4 → 1.3.5-beta.1
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 +406 -236
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/scripts/postinstall-download.js +152 -0
package/dist/index.js
CHANGED
|
@@ -1157,8 +1157,8 @@ var PilotManager = class {
|
|
|
1157
1157
|
* Apply a Pilot node: set up the custom Agent + base URL.
|
|
1158
1158
|
*
|
|
1159
1159
|
* node.ip may be a real IP or a domain (CNAME like *.aliyunddos1021.com).
|
|
1160
|
-
* - Real IP
|
|
1161
|
-
* - Domain
|
|
1160
|
+
* - Real IP -> use directly in lookup callback
|
|
1161
|
+
* - Domain -> dns.lookup on every connection to get a fresh IP
|
|
1162
1162
|
*/
|
|
1163
1163
|
applyNode(node, protocol) {
|
|
1164
1164
|
this.pilotNode = node;
|
|
@@ -1508,29 +1508,29 @@ var RateLimiter = class {
|
|
|
1508
1508
|
}
|
|
1509
1509
|
};
|
|
1510
1510
|
var OKX_CODE_BEHAVIORS = {
|
|
1511
|
-
// Rate limit
|
|
1511
|
+
// Rate limit -> throw RateLimitError
|
|
1512
1512
|
"50011": { retry: true, suggestion: "Rate limited. Back off and retry after a delay." },
|
|
1513
1513
|
"50061": { retry: true, suggestion: "Too many connections. Reduce request frequency and retry." },
|
|
1514
|
-
// Server temporarily unavailable
|
|
1514
|
+
// Server temporarily unavailable -> retryable
|
|
1515
1515
|
"50001": { retry: true, suggestion: "Service temporarily unavailable. Retry in a few minutes." },
|
|
1516
1516
|
"50004": { retry: true, suggestion: "Endpoint request timeout. Retry later." },
|
|
1517
1517
|
"50013": { retry: true, suggestion: "System busy. Retry after 1-2 seconds." },
|
|
1518
1518
|
"50026": { retry: true, suggestion: "System error. Retry in a few minutes." },
|
|
1519
|
-
// Region / compliance restriction
|
|
1519
|
+
// Region / compliance restriction -> do not retry
|
|
1520
1520
|
"51155": { retry: false, suggestion: "Feature unavailable in your region (site: {site}). Verify your site setting matches your account registration region. Available sites: global, eea, us. Do not retry." },
|
|
1521
1521
|
"51734": { retry: false, suggestion: "Feature not supported for your KYC country (site: {site}). Verify your site setting matches your account registration region. Available sites: global, eea, us. Do not retry." },
|
|
1522
|
-
// Account issues
|
|
1522
|
+
// Account issues -> do not retry
|
|
1523
1523
|
"50007": { retry: false, suggestion: "Account suspended. Contact OKX support. Do not retry." },
|
|
1524
1524
|
"50009": { retry: false, suggestion: "Account blocked by risk control. Contact OKX support. Do not retry." },
|
|
1525
1525
|
"51009": { retry: false, suggestion: "Account mode not supported for this operation. Check account settings." },
|
|
1526
|
-
// API key permission / expiry
|
|
1526
|
+
// API key permission / expiry -> do not retry
|
|
1527
1527
|
"50100": { retry: false, suggestion: "API key lacks required permissions. Update API key permissions." },
|
|
1528
1528
|
"50110": { retry: false, suggestion: "API key expired. Generate a new API key." },
|
|
1529
|
-
// Insufficient funds / margin
|
|
1530
|
-
"51008": { retry: false, suggestion: "Insufficient balance in trading account. Check funding account via account_get_asset_balance
|
|
1529
|
+
// Insufficient funds / margin -> do not retry
|
|
1530
|
+
"51008": { retry: false, suggestion: "Insufficient balance in trading account. Check funding account via account_get_asset_balance - funds may be there. Use account_transfer (from=18, to=6) to move funds to trading account, then retry." },
|
|
1531
1531
|
"51119": { retry: false, suggestion: "Insufficient margin. Add margin or check funding account (account_get_asset_balance). Transfer via account_transfer (from=18, to=6) if needed." },
|
|
1532
1532
|
"51127": { retry: false, suggestion: "Insufficient available margin. Reduce position, add margin, or transfer from funding account (account_transfer from=18 to=6)." },
|
|
1533
|
-
// Instrument unavailable
|
|
1533
|
+
// Instrument unavailable -> do not retry
|
|
1534
1534
|
"51021": { retry: false, suggestion: "Instrument does not exist. Check instId." },
|
|
1535
1535
|
"51022": { retry: false, suggestion: "Instrument not available for trading." },
|
|
1536
1536
|
"51027": { retry: false, suggestion: "Contract has expired." }
|
|
@@ -1614,11 +1614,11 @@ var OkxRestClient = class _OkxRestClient {
|
|
|
1614
1614
|
}
|
|
1615
1615
|
}
|
|
1616
1616
|
/**
|
|
1617
|
-
* Dynamic auth
|
|
1617
|
+
* Dynamic auth - determines auth method per request.
|
|
1618
1618
|
*
|
|
1619
|
-
* 1. API key in config
|
|
1620
|
-
* 2. OAuth token via okx-auth binary
|
|
1621
|
-
* 3. Neither
|
|
1619
|
+
* 1. API key in config -> HMAC signing (no OAuth fallback)
|
|
1620
|
+
* 2. OAuth token via okx-auth binary -> Bearer token
|
|
1621
|
+
* 3. Neither -> throw ConfigError
|
|
1622
1622
|
*/
|
|
1623
1623
|
async applyAuth(headers, method, requestPath, bodyJson, timestamp) {
|
|
1624
1624
|
if (this.config.apiKey && this.config.secretKey && this.config.passphrase) {
|
|
@@ -1772,7 +1772,7 @@ var OkxRestClient = class _OkxRestClient {
|
|
|
1772
1772
|
};
|
|
1773
1773
|
}
|
|
1774
1774
|
// ---------------------------------------------------------------------------
|
|
1775
|
-
// Binary (non-JSON) download
|
|
1775
|
+
// Binary (non-JSON) download - reuses auth, proxy, rate-limit, verbose
|
|
1776
1776
|
// ---------------------------------------------------------------------------
|
|
1777
1777
|
static DEFAULT_MAX_BYTES = 50 * 1024 * 1024;
|
|
1778
1778
|
// 50 MB
|
|
@@ -2384,7 +2384,7 @@ var INDICATOR_CODE_OVERRIDES = {
|
|
|
2384
2384
|
// default: NVI_PVI
|
|
2385
2385
|
"top-long-short": "TOPLONGSHORT"
|
|
2386
2386
|
// default: TOP_LONG_SHORT
|
|
2387
|
-
// Note: range-filter
|
|
2387
|
+
// Note: range-filter -> RANGE_FILTER is correct via the default rule; no override needed.
|
|
2388
2388
|
};
|
|
2389
2389
|
var KNOWN_INDICATORS = [
|
|
2390
2390
|
// Moving Averages
|
|
@@ -2633,7 +2633,7 @@ var MODULES = [
|
|
|
2633
2633
|
"skills"
|
|
2634
2634
|
];
|
|
2635
2635
|
var DEFAULT_MODULES = ["spot", "swap", "option", "account", ...BOT_DEFAULT_SUB_MODULES, "skills"];
|
|
2636
|
-
var SKILLS_MARKETPLACE_DESC = "OKX Skills Marketplace
|
|
2636
|
+
var SKILLS_MARKETPLACE_DESC = "OKX Skills Marketplace - search, install, and manage agent skills";
|
|
2637
2637
|
var MODULE_DESCRIPTIONS = {
|
|
2638
2638
|
market: "Market data (ticker, orderbook, candles, trades)",
|
|
2639
2639
|
spot: "Spot trading (orders, algo orders)",
|
|
@@ -2641,18 +2641,18 @@ var MODULE_DESCRIPTIONS = {
|
|
|
2641
2641
|
futures: "Futures trading (orders, positions, algo orders, leverage)",
|
|
2642
2642
|
option: "Options trading (orders, positions, greeks)",
|
|
2643
2643
|
account: "Account balance, positions, bills, and configuration",
|
|
2644
|
-
"earn.savings": "Simple Earn
|
|
2645
|
-
"earn.onchain": "On-chain Earn
|
|
2646
|
-
"earn.dcd": "DCD (Dual Currency Deposit)
|
|
2647
|
-
"earn.autoearn": "Auto-earn
|
|
2648
|
-
"earn.flash": "Flash Earn
|
|
2649
|
-
event: "Event contracts
|
|
2650
|
-
"bot.grid": "Grid trading bot
|
|
2651
|
-
"bot.dca": "DCA (Martingale) bot
|
|
2644
|
+
"earn.savings": "Simple Earn - flexible savings, fixed-term, and lending",
|
|
2645
|
+
"earn.onchain": "On-chain Earn - staking and DeFi products",
|
|
2646
|
+
"earn.dcd": "DCD (Dual Currency Deposit) - structured products with fixed yield",
|
|
2647
|
+
"earn.autoearn": "Auto-earn - automatically lend, stake, or earn on idle assets",
|
|
2648
|
+
"earn.flash": "Flash Earn - short-window high-yield earn projects",
|
|
2649
|
+
event: "Event contracts - binary prediction markets (YES/NO, UP/DOWN)",
|
|
2650
|
+
"bot.grid": "Grid trading bot - create, monitor, and stop grid orders",
|
|
2651
|
+
"bot.dca": "DCA (Martingale) bot - spot or contract recurring buys",
|
|
2652
2652
|
news: "Crypto news, sentiment analysis, and coin trend tracking",
|
|
2653
|
-
smartmoney: "Smart money signals
|
|
2653
|
+
smartmoney: "Smart money signals - trader leaderboard, consensus signals, and position analysis",
|
|
2654
2654
|
skills: SKILLS_MARKETPLACE_DESC,
|
|
2655
|
-
earn: "Earn products
|
|
2655
|
+
earn: "Earn products - Simple Earn, On-chain Earn, DCD, Flash Earn, and Auto-Earn",
|
|
2656
2656
|
bot: "Trading bot strategies (grid, dca)",
|
|
2657
2657
|
config: "Manage CLI configuration profiles",
|
|
2658
2658
|
setup: "Set up client integrations (Cursor, Windsurf, Claude, etc.)",
|
|
@@ -2713,7 +2713,7 @@ function registerAccountTools() {
|
|
|
2713
2713
|
},
|
|
2714
2714
|
type: {
|
|
2715
2715
|
type: "string",
|
|
2716
|
-
description: "0=main account (default), 1=main
|
|
2716
|
+
description: "0=main account (default), 1=main->sub, 2=sub->main, 3=sub->sub"
|
|
2717
2717
|
},
|
|
2718
2718
|
subAcct: {
|
|
2719
2719
|
type: "string",
|
|
@@ -3297,7 +3297,7 @@ function computeContracts(p) {
|
|
|
3297
3297
|
);
|
|
3298
3298
|
}
|
|
3299
3299
|
const contractsStr = contractsRounded.toFixed(lotSzDecimals);
|
|
3300
|
-
const conversionNote = isMarginMode ? `Converting ${sz} USDT margin (${leverStr}x leverage)
|
|
3300
|
+
const conversionNote = isMarginMode ? `Converting ${sz} USDT margin (${leverStr}x leverage) -> ${contractsStr} contracts (notional value \u2248 ${(contractsRounded * contractValue).toFixed(2)} USDT, ctVal=${ctValStr}, lastPx=${lastStr}, lever=${leverStr}, minSz=${minSzStr}, lotSz=${lotSzStr})` : `Converting ${sz} USDT -> ${contractsStr} contracts (ctVal=${ctValStr}, lastPx=${lastStr}, minSz=${minSzStr}, lotSz=${lotSzStr})`;
|
|
3301
3301
|
return { contractsStr, conversionNote };
|
|
3302
3302
|
}
|
|
3303
3303
|
async function resolveQuoteCcySz(instId, sz, tgtCcy, instType, client, tdMode) {
|
|
@@ -3345,7 +3345,7 @@ function registerAlgoTradeTools() {
|
|
|
3345
3345
|
{
|
|
3346
3346
|
name: "swap_place_algo_order",
|
|
3347
3347
|
module: "swap",
|
|
3348
|
-
description: "Place a SWAP/FUTURES algo order. [CAUTION] Executes real trades. conditional: single TP, single SL, or both on one order. oco: TP+SL simultaneously
|
|
3348
|
+
description: "Place a SWAP/FUTURES algo order. [CAUTION] Executes real trades. conditional: single TP, single SL, or both on one order. oco: TP+SL simultaneously - first trigger cancels the other. move_order_stop: trailing stop (callbackRatio or callbackSpread). trigger: pending order activated when triggerPx is hit (provide triggerPx + orderPx). chase: smart-follow best bid/ask. iceberg: split large order into child orders at intervals. twap: time-weighted average price order splitting.",
|
|
3349
3349
|
isWrite: true,
|
|
3350
3350
|
inputSchema: {
|
|
3351
3351
|
type: "object",
|
|
@@ -3705,7 +3705,7 @@ function registerFuturesAlgoTools() {
|
|
|
3705
3705
|
{
|
|
3706
3706
|
name: "futures_place_algo_order",
|
|
3707
3707
|
module: "futures",
|
|
3708
|
-
description: "Place a FUTURES delivery algo order. [CAUTION] Executes real trades. conditional: single TP, single SL, or both on one order. oco: TP+SL simultaneously
|
|
3708
|
+
description: "Place a FUTURES delivery algo order. [CAUTION] Executes real trades. conditional: single TP, single SL, or both on one order. oco: TP+SL simultaneously - first trigger cancels the other. move_order_stop: trailing stop (callbackRatio or callbackSpread). trigger: pending order activated when triggerPx is hit (provide triggerPx + orderPx). chase: smart-follow best bid/ask. iceberg: split large order into child orders at intervals. twap: time-weighted average price order splitting.",
|
|
3709
3709
|
isWrite: true,
|
|
3710
3710
|
inputSchema: {
|
|
3711
3711
|
type: "object",
|
|
@@ -3930,7 +3930,7 @@ function registerFuturesAlgoTools() {
|
|
|
3930
3930
|
{
|
|
3931
3931
|
name: "futures_amend_algo_order",
|
|
3932
3932
|
module: "futures",
|
|
3933
|
-
description: "Amend a pending FUTURES delivery algo order (modify TP/SL prices or size). Also covers TP/SL orders attached when placing the main order
|
|
3933
|
+
description: "Amend a pending FUTURES delivery algo order (modify TP/SL prices or size). Also covers TP/SL orders attached when placing the main order - look up algoId via futures_get_algo_orders first.",
|
|
3934
3934
|
isWrite: true,
|
|
3935
3935
|
inputSchema: {
|
|
3936
3936
|
type: "object",
|
|
@@ -4383,7 +4383,7 @@ function registerSkillsTools() {
|
|
|
4383
4383
|
{
|
|
4384
4384
|
name: "skills_get_categories",
|
|
4385
4385
|
module: "skills",
|
|
4386
|
-
description: "List all available skill categories in OKX Skills Marketplace. Use the returned categoryId as input to skills_search for category filtering. Do NOT use for searching or downloading skills
|
|
4386
|
+
description: "List all available skill categories in OKX Skills Marketplace. Use the returned categoryId as input to skills_search for category filtering. Do NOT use for searching or downloading skills - use skills_search or skills_download.",
|
|
4387
4387
|
inputSchema: {
|
|
4388
4388
|
type: "object",
|
|
4389
4389
|
properties: {},
|
|
@@ -4395,7 +4395,7 @@ function registerSkillsTools() {
|
|
|
4395
4395
|
{
|
|
4396
4396
|
name: "skills_search",
|
|
4397
4397
|
module: "skills",
|
|
4398
|
-
description: "Search for skills in OKX Skills Marketplace by keyword or category. To get valid category IDs, call skills_get_categories first. Returns skill names for use with skills_download. Do NOT use for downloading
|
|
4398
|
+
description: "Search for skills in OKX Skills Marketplace by keyword or category. To get valid category IDs, call skills_get_categories first. Returns skill names for use with skills_download. Do NOT use for downloading - use skills_download.",
|
|
4399
4399
|
inputSchema: {
|
|
4400
4400
|
type: "object",
|
|
4401
4401
|
properties: {
|
|
@@ -4424,7 +4424,7 @@ function registerSkillsTools() {
|
|
|
4424
4424
|
{
|
|
4425
4425
|
name: "skills_download",
|
|
4426
4426
|
module: "skills",
|
|
4427
|
-
description: "Download a skill package from OKX Skills Marketplace to a local directory. Always call skills_search first to confirm the skill name exists. Downloads the latest approved version. NOTE: Downloads third-party developer content
|
|
4427
|
+
description: "Download a skill package from OKX Skills Marketplace to a local directory. Always call skills_search first to confirm the skill name exists. Downloads the latest approved version. NOTE: Downloads third-party developer content - does NOT install to agents. For full installation use CLI: okx skill add <name>. Use when the user wants to inspect or manually install a skill package.",
|
|
4428
4428
|
inputSchema: {
|
|
4429
4429
|
type: "object",
|
|
4430
4430
|
properties: {
|
|
@@ -4705,7 +4705,7 @@ function registerGridTools() {
|
|
|
4705
4705
|
{
|
|
4706
4706
|
name: "grid_amend_order",
|
|
4707
4707
|
module: "bot.grid",
|
|
4708
|
-
description: "Amend a running grid bot. [CAUTION] Modifies a running bot. Use grid_list_orders to confirm the bot is running and obtain the algoId before calling.\nSupports two modes, which can be combined in a single call:\n\u2022 Price-range mode (maxPx+minPx+gridNum): change upper/lower price boundary and grid count. Contract grid: if new range requires more margin, pass topUpAmt; omit to auto-use the minimum required. Spot grid: topUpAmt is not supported.\n\u2022 TP/SL mode (instId + any of tpTriggerPx/slTriggerPx/tpRatio/slRatio): update take-profit and/or stop-loss. Pass '-1' to explicitly clear an existing TP or SL. tpTriggerPx/slTriggerPx are absolute prices; tpRatio/slRatio are profit ratios (e.g. '0.1' = 10%).\nWhen both sets of params are provided, both APIs are called sequentially.\nDo NOT use to create a new grid bot
|
|
4708
|
+
description: "Amend a running grid bot. [CAUTION] Modifies a running bot. Use grid_list_orders to confirm the bot is running and obtain the algoId before calling.\nSupports two modes, which can be combined in a single call:\n\u2022 Price-range mode (maxPx+minPx+gridNum): change upper/lower price boundary and grid count. Contract grid: if new range requires more margin, pass topUpAmt; omit to auto-use the minimum required. Spot grid: topUpAmt is not supported.\n\u2022 TP/SL mode (instId + any of tpTriggerPx/slTriggerPx/tpRatio/slRatio): update take-profit and/or stop-loss. Pass '-1' to explicitly clear an existing TP or SL. tpTriggerPx/slTriggerPx are absolute prices; tpRatio/slRatio are profit ratios (e.g. '0.1' = 10%).\nWhen both sets of params are provided, both APIs are called sequentially.\nDo NOT use to create a new grid bot - use grid_create_order instead. Do NOT use to stop a grid bot - use grid_stop_order instead.",
|
|
4709
4709
|
isWrite: true,
|
|
4710
4710
|
inputSchema: {
|
|
4711
4711
|
type: "object",
|
|
@@ -4783,7 +4783,7 @@ function registerGridTools() {
|
|
|
4783
4783
|
maxPx,
|
|
4784
4784
|
minPx: requireString(args, "minPx"),
|
|
4785
4785
|
gridNum: requireString(args, "gridNum"),
|
|
4786
|
-
// API field is "topupAmount" (lowercase u)
|
|
4786
|
+
// API field is "topupAmount" (lowercase u) - different from TP/SL mode's "topUpAmt"
|
|
4787
4787
|
// Contract grid only; omitting lets the API use the minimum required
|
|
4788
4788
|
topupAmount: readString(args, "topUpAmt")
|
|
4789
4789
|
}),
|
|
@@ -4804,7 +4804,7 @@ function registerGridTools() {
|
|
|
4804
4804
|
tpRatio: readString(args, "tpRatio"),
|
|
4805
4805
|
slRatio: readString(args, "slRatio"),
|
|
4806
4806
|
topUpAmt: readString(args, "topUpAmt")
|
|
4807
|
-
// API field is "topUpAmt" (uppercase U)
|
|
4807
|
+
// API field is "topUpAmt" (uppercase U) - different from price-range mode's "topupAmount"
|
|
4808
4808
|
}),
|
|
4809
4809
|
privateRateLimit("grid_amend_order", 20),
|
|
4810
4810
|
true
|
|
@@ -4828,7 +4828,7 @@ function registerGridTools() {
|
|
|
4828
4828
|
{
|
|
4829
4829
|
name: "grid_stop_order",
|
|
4830
4830
|
module: "bot.grid",
|
|
4831
|
-
description: "Stop a
|
|
4831
|
+
description: "[CAUTION] Stop a grid bot or close its remaining open position \u2014 real trades, irreversible. Workflow: (1) If the user has not specified which bot to stop, call grid_get_orders first and ask the user to confirm which bot before proceeding. (2) Call grid_get_order_details to check the current 'state' field. (3) If state='running' \u2192 call this tool: stopType='1' (default, clean exit) \u2014 spot grid sells all base assets back to quote; contract grid market-closes all positions. stopType='2' (keep assets) \u2014 spot grid keeps base assets as-is; contract grid cancels grid orders but leaves the position open. (4) If state='no_close_position' \u2192 call this tool with stopType='1' to close the remaining open position.",
|
|
4832
4832
|
isWrite: true,
|
|
4833
4833
|
inputSchema: {
|
|
4834
4834
|
type: "object",
|
|
@@ -4843,7 +4843,7 @@ function registerGridTools() {
|
|
|
4843
4843
|
stopType: {
|
|
4844
4844
|
type: "string",
|
|
4845
4845
|
enum: ["1", "2"],
|
|
4846
|
-
description: "'1' (default): stop strategy and sell
|
|
4846
|
+
description: "'1' (default): stop strategy and sell - spot grid sells all base assets back to quote; contract grid market-closes all positions. '2': stop strategy without selling - spot grid keeps base assets as-is; contract grid cancels all grid orders but leaves the position open. After stopType='2', the remaining position can be closed manually from the Positions page."
|
|
4847
4847
|
}
|
|
4848
4848
|
},
|
|
4849
4849
|
required: ["algoId", "algoOrdType", "instId"]
|
|
@@ -4860,7 +4860,7 @@ function registerGridTools() {
|
|
|
4860
4860
|
})],
|
|
4861
4861
|
privateRateLimit("grid_stop_order", 20),
|
|
4862
4862
|
true
|
|
4863
|
-
// retryOnNetworkError: safe to retry
|
|
4863
|
+
// retryOnNetworkError: safe to retry - already-stopped returns an error but does not harm state
|
|
4864
4864
|
);
|
|
4865
4865
|
return normalizeWrite(response);
|
|
4866
4866
|
}
|
|
@@ -5006,7 +5006,7 @@ function registerDcaTools() {
|
|
|
5006
5006
|
{
|
|
5007
5007
|
name: "dca_stop_order",
|
|
5008
5008
|
module: "bot.dca",
|
|
5009
|
-
description: "Stop a
|
|
5009
|
+
description: "[CAUTION] Stop a DCA bot or close its remaining open position \u2014 real trades, irreversible. Workflow: (1) If the user has not specified which bot to stop, call dca_get_orders first and ask the user to confirm which bot before proceeding. (2) Call dca_get_order_details to check the current 'state' field. (3) If state='running' \u2192 call this tool. (4) If state='no_close_position' \u2192 call this tool with stopType='1' to close the remaining open position. spot_dca requires stopType: 1=sell all tokens, 2=keep tokens.",
|
|
5010
5010
|
isWrite: true,
|
|
5011
5011
|
inputSchema: {
|
|
5012
5012
|
type: "object",
|
|
@@ -5161,7 +5161,7 @@ function registerEarnTools() {
|
|
|
5161
5161
|
{
|
|
5162
5162
|
name: "earn_get_savings_balance",
|
|
5163
5163
|
module: "earn.savings",
|
|
5164
|
-
description: "Get Simple Earn (savings/flexible earn) balance. Returns current holdings for all currencies or a specific one. To show market rates alongside balance (\u5E02\u573A\u5747\u5229\u7387), call earn_get_lending_rate_history. earn_get_lending_rate_history also returns fixed-term (\u5B9A\u671F) product offers, so one call gives a complete view of both flexible and fixed options. Do NOT use for fixed-term (\u5B9A\u671F) order queries
|
|
5164
|
+
description: "Get Simple Earn (savings/flexible earn) balance. Returns current holdings for all currencies or a specific one. To show market rates alongside balance (\u5E02\u573A\u5747\u5229\u7387), call earn_get_lending_rate_history. earn_get_lending_rate_history also returns fixed-term (\u5B9A\u671F) product offers, so one call gives a complete view of both flexible and fixed options. Do NOT use for fixed-term (\u5B9A\u671F) order queries - use earn_get_fixed_order_list instead.",
|
|
5165
5165
|
isWrite: false,
|
|
5166
5166
|
inputSchema: {
|
|
5167
5167
|
type: "object",
|
|
@@ -5185,7 +5185,7 @@ function registerEarnTools() {
|
|
|
5185
5185
|
{
|
|
5186
5186
|
name: "earn_get_fixed_order_list",
|
|
5187
5187
|
module: "earn.savings",
|
|
5188
|
-
description: "Get Simple Earn Fixed (\u5B9A\u671F\u8D5A\u5E01) lending order list. Returns orders sorted by creation time descending. Use this to check status of fixed-term lending orders (pending/earning/expired/settled/cancelled). Do NOT use for flexible earn balance
|
|
5188
|
+
description: "Get Simple Earn Fixed (\u5B9A\u671F\u8D5A\u5E01) lending order list. Returns orders sorted by creation time descending. Use this to check status of fixed-term lending orders (pending/earning/expired/settled/cancelled). Do NOT use for flexible earn balance - use earn_get_savings_balance instead. If the result is empty, do NOT display any fixed-term section in the output.",
|
|
5189
5189
|
isWrite: false,
|
|
5190
5190
|
inputSchema: {
|
|
5191
5191
|
type: "object",
|
|
@@ -5237,7 +5237,7 @@ function registerEarnTools() {
|
|
|
5237
5237
|
},
|
|
5238
5238
|
rate: {
|
|
5239
5239
|
type: "string",
|
|
5240
|
-
description: "Minimum lending rate threshold (annual, decimal). e.g. 0.01 = 1%. Only matched when market rate \u2265 this value. Defaults to 0.01. Keep at 0.01 to maximize matching probability
|
|
5240
|
+
description: "Minimum lending rate threshold (annual, decimal). e.g. 0.01 = 1%. Only matched when market rate \u2265 this value. Defaults to 0.01. Keep at 0.01 to maximize matching probability - do NOT raise this to increase yield, as actual yield (lendingRate) is determined by market supply/demand, not this setting."
|
|
5241
5241
|
}
|
|
5242
5242
|
},
|
|
5243
5243
|
required: ["ccy", "amt"]
|
|
@@ -5304,7 +5304,7 @@ function registerEarnTools() {
|
|
|
5304
5304
|
},
|
|
5305
5305
|
rate: {
|
|
5306
5306
|
type: "string",
|
|
5307
|
-
description: "Minimum lending rate threshold (annual, decimal). e.g. 0.01 = 1%. Only matched when market rate \u2265 this value. Keep at 0.01 to maximize matching probability
|
|
5307
|
+
description: "Minimum lending rate threshold (annual, decimal). e.g. 0.01 = 1%. Only matched when market rate \u2265 this value. Keep at 0.01 to maximize matching probability - do NOT raise this to increase yield, as actual yield (lendingRate) is determined by market supply/demand, not this setting."
|
|
5308
5308
|
}
|
|
5309
5309
|
},
|
|
5310
5310
|
required: ["ccy", "rate"]
|
|
@@ -5366,7 +5366,7 @@ function registerEarnTools() {
|
|
|
5366
5366
|
{
|
|
5367
5367
|
name: "earn_fixed_purchase",
|
|
5368
5368
|
module: "earn.savings",
|
|
5369
|
-
description: "Purchase Simple Earn Fixed (\u5B9A\u671F) product, two-step flow. First call (confirm omitted or false): returns purchase preview with product details and risk warning. Preview offer fields: lendQuota = remaining quota (\u5269\u4F59\u989D\u5EA6), soldOut = whether product is sold out (lendQuota is 0). YOU MUST display the 'warning' field from the preview response to the user VERBATIM before asking for confirmation
|
|
5369
|
+
description: "Purchase Simple Earn Fixed (\u5B9A\u671F) product, two-step flow. First call (confirm omitted or false): returns purchase preview with product details and risk warning. Preview offer fields: lendQuota = remaining quota (\u5269\u4F59\u989D\u5EA6), soldOut = whether product is sold out (lendQuota is 0). YOU MUST display the 'warning' field from the preview response to the user VERBATIM before asking for confirmation - do NOT omit or summarize it. Second call (confirm=true): executes the purchase. Only proceed after the user explicitly confirms. IMPORTANT: Orders in 'pending' (\u5339\u914D\u4E2D) state can still be cancelled via earn_fixed_redeem; once the status changes to 'earning' (\u8D5A\u5E01\u4E2D), funds are LOCKED until maturity - no early redemption allowed.",
|
|
5370
5370
|
isWrite: true,
|
|
5371
5371
|
inputSchema: {
|
|
5372
5372
|
type: "object",
|
|
@@ -5425,7 +5425,7 @@ function registerEarnTools() {
|
|
|
5425
5425
|
term,
|
|
5426
5426
|
offer: offerWithSoldOut,
|
|
5427
5427
|
currentFlexibleRate: rateArr[0]?.["lendingRate"] ?? null,
|
|
5428
|
-
warning: "\u26A0\uFE0F Orders still in 'pending' state can be cancelled before matching completes. Once the status changes to 'earning', funds are LOCKED until maturity
|
|
5428
|
+
warning: "\u26A0\uFE0F Orders still in 'pending' state can be cancelled before matching completes. Once the status changes to 'earning', funds are LOCKED until maturity - early redemption is NOT allowed. Please call again with confirm=true to proceed."
|
|
5429
5429
|
};
|
|
5430
5430
|
}
|
|
5431
5431
|
assertNotDemo(context.config, "earn_fixed_purchase");
|
|
@@ -5440,7 +5440,7 @@ function registerEarnTools() {
|
|
|
5440
5440
|
{
|
|
5441
5441
|
name: "earn_fixed_redeem",
|
|
5442
5442
|
module: "earn.savings",
|
|
5443
|
-
description: "Redeem Simple Earn Fixed (\u5B9A\u671F\u8D5A\u5E01) order. [CAUTION] Redeems a fixed-term lending order. Always redeems the full order amount. Only orders in 'pending' (\u5339\u914D\u4E2D) state can be redeemed
|
|
5443
|
+
description: "Redeem Simple Earn Fixed (\u5B9A\u671F\u8D5A\u5E01) order. [CAUTION] Redeems a fixed-term lending order. Always redeems the full order amount. Only orders in 'pending' (\u5339\u914D\u4E2D) state can be redeemed - orders in 'earning' state are locked until maturity and cannot be redeemed early. Do NOT use for flexible earn redemption - use earn_savings_redeem instead.",
|
|
5444
5444
|
isWrite: true,
|
|
5445
5445
|
inputSchema: {
|
|
5446
5446
|
type: "object",
|
|
@@ -5468,7 +5468,7 @@ function registerEarnTools() {
|
|
|
5468
5468
|
{
|
|
5469
5469
|
name: "earn_get_lending_rate_history",
|
|
5470
5470
|
module: "earn.savings",
|
|
5471
|
-
description: "Query Simple Earn lending rates and fixed-term offers. Use this tool when the user asks about Simple Earn products, current or historical lending rates, or when displaying savings balance with market rate context (\u5E02\u573A\u5747\u5229\u7387). Returns lending rate history (lendingRate field, newest-first) AND available fixed-term (\u5B9A\u671F) offers with APR, term, min amount, and quota
|
|
5471
|
+
description: "Query Simple Earn lending rates and fixed-term offers. Use this tool when the user asks about Simple Earn products, current or historical lending rates, or when displaying savings balance with market rate context (\u5E02\u573A\u5747\u5229\u7387). Returns lending rate history (lendingRate field, newest-first) AND available fixed-term (\u5B9A\u671F) offers with APR, term, min amount, and quota - one call gives a complete view of both flexible and fixed options. In fixedOffers: lendQuota = remaining quota (\u5269\u4F59\u989D\u5EA6), soldOut = whether product is sold out (lendQuota is 0). To get current flexible APY: use limit=1 and read lendingRate.",
|
|
5472
5472
|
isWrite: false,
|
|
5473
5473
|
inputSchema: {
|
|
5474
5474
|
type: "object",
|
|
@@ -5801,7 +5801,7 @@ function registerOnchainEarnTools() {
|
|
|
5801
5801
|
}
|
|
5802
5802
|
var DCD_CODE_BEHAVIORS = {
|
|
5803
5803
|
"50001": { retry: true, suggestion: "Service temporarily unavailable. Retry in a few minutes." },
|
|
5804
|
-
"50002": { retry: false, suggestion: "Invalid JSON in request body. This is likely a bug
|
|
5804
|
+
"50002": { retry: false, suggestion: "Invalid JSON in request body. This is likely a bug - check request parameters." },
|
|
5805
5805
|
"50014": { retry: false, suggestion: "Missing required parameter. Check that all required fields are provided." },
|
|
5806
5806
|
"50016": { retry: false, suggestion: "notionalCcy does not match productId option type. Use baseCcy for CALL, quoteCcy for PUT." },
|
|
5807
5807
|
"50026": { retry: true, suggestion: "DCD system error. Retry in a few minutes." },
|
|
@@ -6176,7 +6176,7 @@ function registerFlashEarnTools() {
|
|
|
6176
6176
|
{
|
|
6177
6177
|
name: "earn_get_flash_earn_projects",
|
|
6178
6178
|
module: "earn.flash",
|
|
6179
|
-
description: "Get Flash Earn projects. Use this to browse upcoming or in-progress Flash Earn opportunities. Do NOT use for purchase or redeem actions
|
|
6179
|
+
description: "Get Flash Earn projects. Use this to browse upcoming or in-progress Flash Earn opportunities. Do NOT use for purchase or redeem actions - Flash Earn is query-only in this module.",
|
|
6180
6180
|
isWrite: false,
|
|
6181
6181
|
inputSchema: {
|
|
6182
6182
|
type: "object",
|
|
@@ -6572,7 +6572,7 @@ function handlePlaceOrderError(base, rawArgs, endpoint) {
|
|
|
6572
6572
|
const seriesId = extractSeriesId(instId);
|
|
6573
6573
|
const expiryMs = inferExpiryMsFromInstId(instId);
|
|
6574
6574
|
const isExpired = expiryMs !== null && expiryMs < Date.now();
|
|
6575
|
-
const reason = isExpired ? `The contract (${instId}) has expired.` : `The contract (${instId}) was not found
|
|
6575
|
+
const reason = isExpired ? `The contract (${instId}) has expired.` : `The contract (${instId}) was not found - it may not exist or has not started yet.`;
|
|
6576
6576
|
throw new OkxApiError(
|
|
6577
6577
|
`${reason} Ask the user if they'd like to place the same order on the next session. If yes, call event_get_markets with seriesId=${seriesId} and state=live to find available contracts.`,
|
|
6578
6578
|
{ code: sCode, endpoint }
|
|
@@ -6588,17 +6588,17 @@ var OUTCOME_SCHEMA = {
|
|
|
6588
6588
|
UP/DOWN direction contracts: UP (price rises during the period) or DOWN (price falls).
|
|
6589
6589
|
YES/NO price-target or touch contracts: YES (condition met) or NO (condition not met).
|
|
6590
6590
|
Check the series type from event_get_series to determine which applies.
|
|
6591
|
-
NOTE: px is the event contract price (0.01
|
|
6591
|
+
NOTE: px is the event contract price (0.01-0.99), NOT the underlying asset price. It reflects market-implied probability when actively trading.`
|
|
6592
6592
|
};
|
|
6593
6593
|
function registerEventContractTools() {
|
|
6594
6594
|
return [
|
|
6595
6595
|
// -----------------------------------------------------------------------
|
|
6596
|
-
// Read-only
|
|
6596
|
+
// Read-only - browse (user-facing) + series / events / markets (internal)
|
|
6597
6597
|
// -----------------------------------------------------------------------
|
|
6598
6598
|
{
|
|
6599
6599
|
name: "event_browse",
|
|
6600
6600
|
module: "event",
|
|
6601
|
-
description: "Browse currently active (in-progress) event contracts. Call when user asks what event contracts are available to trade. Returns only in-progress contracts (floorStrike set). If a live quote field px is present, it is the event contract price (0.01
|
|
6601
|
+
description: "Browse currently active (in-progress) event contracts. Call when user asks what event contracts are available to trade. Returns only in-progress contracts (floorStrike set). If a live quote field px is present, it is the event contract price (0.01-0.99), not the underlying asset price; it reflects the market-implied probability when actively trading. Grouped by settlement type and underlying. Do NOT use for querying contracts within a specific series - use event_get_markets with seriesId instead.",
|
|
6602
6602
|
isWrite: false,
|
|
6603
6603
|
inputSchema: {
|
|
6604
6604
|
type: "object",
|
|
@@ -6717,7 +6717,7 @@ function registerEventContractTools() {
|
|
|
6717
6717
|
{
|
|
6718
6718
|
name: "event_get_markets",
|
|
6719
6719
|
module: "event",
|
|
6720
|
-
description: "List tradeable contracts within a series. state=live for active contracts, state=expired for settlement results. floorStrike=strike price; px (when present) is the event contract price (0.01
|
|
6720
|
+
description: "List tradeable contracts within a series. state=live for active contracts, state=expired for settlement results. floorStrike=strike price; px (when present) is the event contract price (0.01-0.99), not the underlying asset price - reflects the market-implied probability when actively trading; outcome pre-translated (pending/YES/NO/UP/DOWN); timestamps UTC+8. Do NOT use for discovering what series are available across all underlyings - use event_browse instead.",
|
|
6721
6721
|
isWrite: false,
|
|
6722
6722
|
inputSchema: {
|
|
6723
6723
|
type: "object",
|
|
@@ -6798,7 +6798,7 @@ function registerEventContractTools() {
|
|
|
6798
6798
|
{
|
|
6799
6799
|
name: "event_get_orders",
|
|
6800
6800
|
module: "event",
|
|
6801
|
-
description: "Query event contract orders (open, 7d history, or 3-month archive). outcome pre-translated (YES/NO/UP/DOWN). Do NOT use for trade executions
|
|
6801
|
+
description: "Query event contract orders (open, 7d history, or 3-month archive). outcome pre-translated (YES/NO/UP/DOWN). Do NOT use for trade executions - use event_get_fills for fill records and settlement outcomes.",
|
|
6802
6802
|
isWrite: false,
|
|
6803
6803
|
inputSchema: {
|
|
6804
6804
|
type: "object",
|
|
@@ -6856,7 +6856,7 @@ function registerEventContractTools() {
|
|
|
6856
6856
|
{
|
|
6857
6857
|
name: "event_get_fills",
|
|
6858
6858
|
module: "event",
|
|
6859
|
-
description: "Get event contract fill history (trade executions and settlement payouts). archive=true for up to 3mo, false (default) for last 3d. outcome pre-translated (YES/NO/UP/DOWN). Each record includes a 'type' field: 'fill' (opening trade) or 'settlement' (expiry payout with settlementResult win/loss and pnl). Do NOT use for order status
|
|
6859
|
+
description: "Get event contract fill history (trade executions and settlement payouts). archive=true for up to 3mo, false (default) for last 3d. outcome pre-translated (YES/NO/UP/DOWN). Each record includes a 'type' field: 'fill' (opening trade) or 'settlement' (expiry payout with settlementResult win/loss and pnl). Do NOT use for order status - use event_get_orders instead.",
|
|
6860
6860
|
isWrite: false,
|
|
6861
6861
|
inputSchema: {
|
|
6862
6862
|
type: "object",
|
|
@@ -6898,15 +6898,15 @@ function registerEventContractTools() {
|
|
|
6898
6898
|
}
|
|
6899
6899
|
},
|
|
6900
6900
|
// -----------------------------------------------------------------------
|
|
6901
|
-
// Private
|
|
6901
|
+
// Private - write
|
|
6902
6902
|
// -----------------------------------------------------------------------
|
|
6903
6903
|
{
|
|
6904
6904
|
name: "event_place_order",
|
|
6905
6905
|
module: "event",
|
|
6906
6906
|
description: `Place an event contract order. [CAUTION] Places a real order. Before placing, call event_get_markets(seriesId, state=live) to obtain the instId of the target contract.
|
|
6907
6907
|
- outcome: UP/YES (bet price goes up/condition met) or DOWN/NO (bet price goes down/condition not met)
|
|
6908
|
-
- For limit orders: px is the event contract price (0.01
|
|
6909
|
-
- tdMode is always isolated; speedBump is auto-set per exchange requirement
|
|
6908
|
+
- For limit orders: px is the event contract price (0.01-0.99), NOT the underlying asset price. It reflects market-implied probability when actively trading
|
|
6909
|
+
- tdMode is always isolated; speedBump is auto-set per exchange requirement - do not pass either`,
|
|
6910
6910
|
isWrite: true,
|
|
6911
6911
|
inputSchema: {
|
|
6912
6912
|
type: "object",
|
|
@@ -6932,7 +6932,7 @@ function registerEventContractTools() {
|
|
|
6932
6932
|
},
|
|
6933
6933
|
px: {
|
|
6934
6934
|
type: "string",
|
|
6935
|
-
description: "Event contract price (0.01
|
|
6935
|
+
description: "Event contract price (0.01-0.99). Required when ordType=limit. Do NOT use for market orders."
|
|
6936
6936
|
}
|
|
6937
6937
|
},
|
|
6938
6938
|
required: ["instId", "side", "outcome", "sz"]
|
|
@@ -6985,7 +6985,7 @@ function registerEventContractTools() {
|
|
|
6985
6985
|
properties: {
|
|
6986
6986
|
instId: { type: "string", description: "Event contract instrument ID" },
|
|
6987
6987
|
ordId: { type: "string", description: "Order ID to amend" },
|
|
6988
|
-
newPx: { type: "string", description: "New event contract price (0.01
|
|
6988
|
+
newPx: { type: "string", description: "New event contract price (0.01-0.99). Omit to keep current." },
|
|
6989
6989
|
newSz: { type: "string", description: "New size in contracts (omit to keep current)" }
|
|
6990
6990
|
},
|
|
6991
6991
|
required: ["instId", "ordId"]
|
|
@@ -7039,7 +7039,7 @@ function registerEventContractTools() {
|
|
|
7039
7039
|
if (sCode === "51001") {
|
|
7040
7040
|
const expiryMs = inferExpiryMsFromInstId(instId);
|
|
7041
7041
|
const isExpired = expiryMs !== null && expiryMs < Date.now();
|
|
7042
|
-
const reason = isExpired ? `The contract (${instId}) has already expired
|
|
7042
|
+
const reason = isExpired ? `The contract (${instId}) has already expired - the order was auto-cancelled at settlement. Check event_get_fills to confirm the outcome.` : `Instrument (${instId}) not found. Verify the instId with event_get_markets before retrying.`;
|
|
7043
7043
|
throw new OkxApiError(reason, { code: sCode, endpoint: response.endpoint });
|
|
7044
7044
|
}
|
|
7045
7045
|
}
|
|
@@ -7074,25 +7074,25 @@ var SIGNAL_POOL_FILTER_PROPS = {
|
|
|
7074
7074
|
type: "string",
|
|
7075
7075
|
enum: ["PNL_ANY", "PNL_TOP50", "PNL_TOP20", "PNL_TOP5"],
|
|
7076
7076
|
default: "PNL_ANY",
|
|
7077
|
-
description: "PnL percentile gate
|
|
7077
|
+
description: "PnL percentile gate. Naming: `TOP{N}` = top N% percentile (NOT an absolute PnL value). PNL_ANY = no filter; PNL_TOP50 = PnL \u2265 P50 (median); PNL_TOP20 = \u2265 P80; PNL_TOP5 = \u2265 P95. PnL distribution is long-tailed - use percentile, not absolute thresholds."
|
|
7078
7078
|
},
|
|
7079
7079
|
winRateTier: {
|
|
7080
7080
|
type: "string",
|
|
7081
7081
|
enum: ["WR_ANY", "WR_GE_50", "WR_GE_80"],
|
|
7082
7082
|
default: "WR_ANY",
|
|
7083
|
-
description: "Minimum win-rate gate (absolute thresholds, NOT percentile). Naming: `GE_{N}` = career win-rate \u2265 N%
|
|
7083
|
+
description: "Minimum win-rate gate (absolute thresholds, NOT percentile). Naming: `GE_{N}` = career win-rate \u2265 N% - distinct from `pnlTier`/`aumTier` `TOP{N}` which are percentiles. WR_ANY = no filter; WR_GE_50 = \u2265 50%; WR_GE_80 = \u2265 80%."
|
|
7084
7084
|
},
|
|
7085
7085
|
maxDrawdownTier: {
|
|
7086
7086
|
type: "string",
|
|
7087
7087
|
enum: ["MR_ANY", "MR_LE_20", "MR_LE_50"],
|
|
7088
7088
|
default: "MR_ANY",
|
|
7089
|
-
description: "Maximum-drawdown gate (absolute thresholds, NOT percentile; smaller drawdown = lower risk). Naming: `LE_{N}` = drawdown \u2264 N%
|
|
7089
|
+
description: "Maximum-drawdown gate (absolute thresholds, NOT percentile; smaller drawdown = lower risk). Naming: `LE_{N}` = drawdown \u2264 N% - distinct from `pnlTier`/`aumTier` `TOP{N}` which are percentiles. MR_ANY = no filter; MR_LE_20 = drawdown \u2264 20%; MR_LE_50 = \u2264 50%."
|
|
7090
7090
|
},
|
|
7091
7091
|
aumTier: {
|
|
7092
7092
|
type: "string",
|
|
7093
7093
|
enum: ["AUM_ANY", "AUM_TOP50", "AUM_TOP20", "AUM_TOP5"],
|
|
7094
7094
|
default: "AUM_ANY",
|
|
7095
|
-
description: "AUM (Assets Under Management) percentile gate. Naming: `TOP{N}` = top N% percentile (NOT an absolute USD amount). AUM_ANY = no filter; AUM_TOP50 = AUM \u2265 P50; AUM_TOP20 = \u2265 P80; AUM_TOP5 = \u2265 P95. AUM is long-tailed
|
|
7095
|
+
description: "AUM (Assets Under Management) percentile gate. Naming: `TOP{N}` = top N% percentile (NOT an absolute USD amount). AUM_ANY = no filter; AUM_TOP50 = AUM \u2265 P50; AUM_TOP20 = \u2265 P80; AUM_TOP5 = \u2265 P95. AUM is long-tailed - use percentile, not absolute USD."
|
|
7096
7096
|
}
|
|
7097
7097
|
};
|
|
7098
7098
|
var LEADERBOARD_POOL_FILTER_PROPS = {
|
|
@@ -7110,19 +7110,19 @@ var LEADERBOARD_POOL_FILTER_PROPS = {
|
|
|
7110
7110
|
},
|
|
7111
7111
|
minPnl: {
|
|
7112
7112
|
type: "string",
|
|
7113
|
-
description: 'Minimum absolute PnL in USD as a string, e.g. `"10000"`
|
|
7113
|
+
description: 'Minimum absolute PnL in USD as a string, e.g. `"10000"` -> traders with PnL \u2265 $10,000. Numeric threshold - distinct from the signal-side `pnlTier` percentile enum.'
|
|
7114
7114
|
},
|
|
7115
7115
|
minWinRate: {
|
|
7116
7116
|
type: "string",
|
|
7117
|
-
description: 'Minimum win-rate as a decimal in 0~1 range, passed as a string, e.g. `"0.8"`
|
|
7117
|
+
description: 'Minimum win-rate as a decimal in 0~1 range, passed as a string, e.g. `"0.8"` -> traders with win-rate \u2265 80%. Numeric threshold - distinct from the signal-side `winRateTier` enum.'
|
|
7118
7118
|
},
|
|
7119
7119
|
maxDrawdown: {
|
|
7120
7120
|
type: "string",
|
|
7121
|
-
description: 'Maximum drawdown as a decimal, passed as a string, e.g. `"0.1"`
|
|
7121
|
+
description: 'Maximum drawdown as a decimal, passed as a string, e.g. `"0.1"` -> traders with drawdown \u2264 10%. Lower = lower risk. Numeric threshold - distinct from the signal-side `maxDrawdownTier` enum.'
|
|
7122
7122
|
},
|
|
7123
7123
|
minAum: {
|
|
7124
7124
|
type: "string",
|
|
7125
|
-
description: 'Minimum AUM (Assets Under Management) in USD as a string, e.g. `"1000"`
|
|
7125
|
+
description: 'Minimum AUM (Assets Under Management) in USD as a string, e.g. `"1000"` -> traders with AUM \u2265 $1,000. Numeric threshold - distinct from the signal-side `aumTier` percentile enum.'
|
|
7126
7126
|
}
|
|
7127
7127
|
};
|
|
7128
7128
|
var LEADERBOARD_FILTER_UPSTREAM_NAMES = {
|
|
@@ -7256,11 +7256,11 @@ var PAGINATION_PROP = {
|
|
|
7256
7256
|
}
|
|
7257
7257
|
};
|
|
7258
7258
|
var TRADER_ITEM_PROPS = {
|
|
7259
|
-
authorId: { type: "string", description: "Trader's unique ID
|
|
7259
|
+
authorId: { type: "string", description: "Trader's unique ID - pass to other smartmoney_get_trader_* tools." },
|
|
7260
7260
|
nickName: { type: "string", description: "Display nickname." },
|
|
7261
7261
|
pnl: { type: "string", description: "Absolute PnL in USD over the requested `period` (numeric string)." },
|
|
7262
7262
|
pnlRatio: { type: "string", description: 'PnL as a decimal ratio over the requested `period` (e.g. "0.35" = +35%).' },
|
|
7263
|
-
asset: { type: "string", description: "AUM (Assets Under Management) in USD
|
|
7263
|
+
asset: { type: "string", description: "AUM (Assets Under Management) in USD - same field that the input `minAum` filter applies to." },
|
|
7264
7264
|
winRate: { type: "string", description: "Lifetime win-rate as a decimal (0~1)." },
|
|
7265
7265
|
maxDrawdown: { type: "string", description: 'Max drawdown as a decimal (e.g. "0.2" = 20%). Lower = lower risk.' },
|
|
7266
7266
|
onboardDuration: { type: "string", description: "Days the trader has been onboarded on the leaderboard (numeric string)." },
|
|
@@ -7289,7 +7289,7 @@ var SIGNAL_ITEM_PROPS = {
|
|
|
7289
7289
|
},
|
|
7290
7290
|
tradersQualified: {
|
|
7291
7291
|
type: "integer",
|
|
7292
|
-
description: "
|
|
7292
|
+
description: "Final aggregation pool size after tier filters + top-N truncation by `sortBy`. Bounded by the request's pool size limit (`lmtNum` for `_by_filter` variants, `authorIds.length` for `_by_trader` variants). Smaller than the bound only when the upstream candidate pool (traders passing all tier filters) contains fewer entries than the bound \u2014 typical for low-volume instruments or very strict tier combos."
|
|
7293
7293
|
},
|
|
7294
7294
|
longTraders: { type: "integer", description: "Number of pool traders currently long this asset (incl. double-sided)." },
|
|
7295
7295
|
shortTraders: { type: "integer", description: "Number of pool traders currently short this asset (incl. double-sided)." },
|
|
@@ -7299,19 +7299,19 @@ var SIGNAL_ITEM_PROPS = {
|
|
|
7299
7299
|
properties: {
|
|
7300
7300
|
longNotionalUsdt: {
|
|
7301
7301
|
type: "string",
|
|
7302
|
-
description: "Sum of long-side notional in USDT, weighted by each trader's ENTRY PRICE (price_avg), not mark price. Moves only when positions are opened / closed / scaled
|
|
7302
|
+
description: "Sum of long-side notional in USDT, weighted by each trader's ENTRY PRICE (price_avg), not mark price. Moves only when positions are opened / closed / scaled - stays constant when positions are unchanged."
|
|
7303
7303
|
},
|
|
7304
7304
|
shortNotionalUsdt: {
|
|
7305
7305
|
type: "string",
|
|
7306
|
-
description: "Sum of short-side notional in USDT, weighted by each trader's ENTRY PRICE (price_avg), not mark price. Moves only when positions are opened / closed / scaled
|
|
7306
|
+
description: "Sum of short-side notional in USDT, weighted by each trader's ENTRY PRICE (price_avg), not mark price. Moves only when positions are opened / closed / scaled - stays constant when positions are unchanged."
|
|
7307
7307
|
},
|
|
7308
7308
|
netNotionalUsdt: {
|
|
7309
7309
|
type: "string",
|
|
7310
|
-
description: "Net directional notional in USDT = long \u2212 short. Weighted by each trader's ENTRY PRICE (price_avg), not mark price
|
|
7310
|
+
description: "Net directional notional in USDT = long \u2212 short. Weighted by each trader's ENTRY PRICE (price_avg), not mark price - reflects position scaling, not underlying price movement."
|
|
7311
7311
|
},
|
|
7312
7312
|
totalNotionalUsdt: {
|
|
7313
7313
|
type: "string",
|
|
7314
|
-
description: "Gross notional in USDT = long + short. Weighted by each trader's ENTRY PRICE (price_avg), not mark price
|
|
7314
|
+
description: "Gross notional in USDT = long + short. Weighted by each trader's ENTRY PRICE (price_avg), not mark price - reflects position scaling (open / close / add), not underlying price movement. Stays constant across buckets when traders hold positions unchanged."
|
|
7315
7315
|
},
|
|
7316
7316
|
totalNotionalVs24h: {
|
|
7317
7317
|
type: "string",
|
|
@@ -7341,7 +7341,7 @@ var SIGNAL_ITEM_PROPS = {
|
|
|
7341
7341
|
},
|
|
7342
7342
|
weightedLongRatio: {
|
|
7343
7343
|
type: "string",
|
|
7344
|
-
description: "Notional-weighted long ratio = \u03A3(long_notional) / \u03A3(notional). Notional uses each trader's ENTRY PRICE (price_avg), not mark price
|
|
7344
|
+
description: "Notional-weighted long ratio = \u03A3(long_notional) / \u03A3(notional). Notional uses each trader's ENTRY PRICE (price_avg), not mark price - ratio shifts only when positions are scaled. NULL when no notional."
|
|
7345
7345
|
},
|
|
7346
7346
|
weightedShortRatio: {
|
|
7347
7347
|
type: "string",
|
|
@@ -7376,7 +7376,7 @@ var SIGNAL_HISTORY_ITEM_PROPS = {
|
|
|
7376
7376
|
},
|
|
7377
7377
|
weightedLongRatio: {
|
|
7378
7378
|
type: "string",
|
|
7379
|
-
description: "Notional-weighted long ratio at this bucket = \u03A3(long_notional) / \u03A3(notional). Decimal 0~1. Notional uses each trader's ENTRY PRICE (price_avg), not mark price
|
|
7379
|
+
description: "Notional-weighted long ratio at this bucket = \u03A3(long_notional) / \u03A3(notional). Decimal 0~1. Notional uses each trader's ENTRY PRICE (price_avg), not mark price - ratio shifts only when positions are scaled."
|
|
7380
7380
|
},
|
|
7381
7381
|
weightedShortRatio: {
|
|
7382
7382
|
type: "string",
|
|
@@ -7396,13 +7396,16 @@ var SIGNAL_HISTORY_ITEM_PROPS = {
|
|
|
7396
7396
|
},
|
|
7397
7397
|
netNotionalUsdt: {
|
|
7398
7398
|
type: "string",
|
|
7399
|
-
description: "Net directional notional in USDT at this bucket = long notional \u2212 short notional. Weighted by each trader's ENTRY PRICE (price_avg), not mark price
|
|
7399
|
+
description: "Net directional notional in USDT at this bucket = long notional \u2212 short notional. Weighted by each trader's ENTRY PRICE (price_avg), not mark price - reflects position scaling, not underlying price movement."
|
|
7400
7400
|
},
|
|
7401
7401
|
totalNotionalUsdt: {
|
|
7402
7402
|
type: "string",
|
|
7403
|
-
description: "Gross notional in USDT at this bucket = long notional + short notional. Weighted by each trader's ENTRY PRICE (price_avg), not mark price
|
|
7403
|
+
description: "Gross notional in USDT at this bucket = long notional + short notional. Weighted by each trader's ENTRY PRICE (price_avg), not mark price - tracks capital deployed (rising = adding, falling = retreating). Stays constant across buckets when traders hold positions unchanged."
|
|
7404
|
+
},
|
|
7405
|
+
tradersQualified: {
|
|
7406
|
+
type: "integer",
|
|
7407
|
+
description: "Final aggregation pool size in this bucket after tier filters + top-N truncation by `sortBy`. Bounded by the request's pool size limit (`lmtNum` for `_by_filter` variants, `authorIds.length` for `_by_trader` variants). The funnel + top-N selection runs once per query (not per bucket); each bucket reuses the same selected pool for position aggregation. Smaller than the bound only when the upstream candidate pool underflows."
|
|
7404
7408
|
},
|
|
7405
|
-
tradersQualified: { type: "integer", description: "Pool size after applying tier filters (includes traders without a position)." },
|
|
7406
7409
|
dataVersion: { type: "string", description: "Snapshot version key in `yyyyMMddHH` UTC (10-digit, e.g. `2026042820`)." }
|
|
7407
7410
|
};
|
|
7408
7411
|
function registerSmartmoneyTools() {
|
|
@@ -7414,7 +7417,7 @@ function registerSmartmoneyTools() {
|
|
|
7414
7417
|
{
|
|
7415
7418
|
name: "smartmoney_get_traders_by_filter",
|
|
7416
7419
|
module: "smartmoney",
|
|
7417
|
-
description: "Leaderboard ranking of OKX smart-money traders, filtered by pool conditions and ranked by `sortBy`. Use when: discovering top performers by criteria (PnL / win-rate / drawdown / AUM). See also: `smartmoney_get_performance_by_trader` (lookup by ID), `smartmoney_search_trader` (lookup by nickname). Note: `updateTime` is 12-digit `yyyyMMddHHmm` UTC+8, different from signal tools' 10-digit UTC `asOfTime`/`dataVersion`
|
|
7420
|
+
description: "Leaderboard ranking of OKX smart-money traders, filtered by pool conditions and ranked by `sortBy`. Use when: discovering top performers by criteria (PnL / win-rate / drawdown / AUM). See also: `smartmoney_get_performance_by_trader` (lookup by ID), `smartmoney_search_trader` (lookup by nickname). Note: `updateTime` is 12-digit `yyyyMMddHHmm` UTC+8, different from signal tools' 10-digit UTC `asOfTime`/`dataVersion` - do not cross-pass.",
|
|
7418
7421
|
isWrite: false,
|
|
7419
7422
|
outputSchema: envelope(
|
|
7420
7423
|
{ type: "array", items: { type: "object", properties: TRADER_ITEM_PROPS } },
|
|
@@ -7431,16 +7434,16 @@ function registerSmartmoneyTools() {
|
|
|
7431
7434
|
properties: {
|
|
7432
7435
|
updateTime: {
|
|
7433
7436
|
type: "string",
|
|
7434
|
-
description: 'Snapshot version key
|
|
7437
|
+
description: 'Snapshot version key - 12-digit `yyyyMMddHHmm` (UTC+8) as a string, e.g. `"202604301815"`. Omit to query the latest snapshot (refreshed every ~5 min).'
|
|
7435
7438
|
},
|
|
7436
7439
|
...LEADERBOARD_POOL_FILTER_PROPS,
|
|
7437
7440
|
after: {
|
|
7438
7441
|
type: "string",
|
|
7439
|
-
description: 'Pagination cursor (older page)
|
|
7442
|
+
description: 'Pagination cursor (older page) - pass the `authorId` of the last item from the previous page as a string, e.g. `"872913470357110787"`. Cursor anchors on `authorId` while preserving the current `sortBy` order.'
|
|
7440
7443
|
},
|
|
7441
7444
|
before: {
|
|
7442
7445
|
type: "string",
|
|
7443
|
-
description: 'Pagination cursor (newer page)
|
|
7446
|
+
description: 'Pagination cursor (newer page) - pass the `authorId` of the first item from the previous page as a string, e.g. `"872913470357110787"`. Cursor anchors on `authorId` while preserving the current `sortBy` order.'
|
|
7444
7447
|
},
|
|
7445
7448
|
limit: {
|
|
7446
7449
|
type: "integer",
|
|
@@ -7480,7 +7483,7 @@ function registerSmartmoneyTools() {
|
|
|
7480
7483
|
{
|
|
7481
7484
|
name: "smartmoney_get_performance_by_trader",
|
|
7482
7485
|
module: "smartmoney",
|
|
7483
|
-
description: "PnL / win-rate / drawdown profile for one or more traders looked up by `authorIds`. Use when: caller already has trader IDs and needs their performance metrics. See also: `smartmoney_search_trader` (resolve nickname
|
|
7486
|
+
description: "PnL / win-rate / drawdown profile for one or more traders looked up by `authorIds`. Use when: caller already has trader IDs and needs their performance metrics. See also: `smartmoney_search_trader` (resolve nickname -> authorId), `smartmoney_get_traders_by_filter` (criteria-based discovery). Note: response `updateTime` is 12-digit `yyyyMMddHHmm` UTC+8 - do not pass to signal-side tools' `asOfTime` (10-digit UTC).",
|
|
7484
7487
|
isWrite: false,
|
|
7485
7488
|
outputSchema: envelope(
|
|
7486
7489
|
{ type: "array", items: { type: "object", properties: TRADER_ITEM_PROPS } },
|
|
@@ -7550,7 +7553,7 @@ function registerSmartmoneyTools() {
|
|
|
7550
7553
|
{
|
|
7551
7554
|
name: "smartmoney_get_trader_positions",
|
|
7552
7555
|
module: "smartmoney",
|
|
7553
|
-
description: "Currently-open positions held by a single trader (direction, size, leverage, entry, conviction). Use when: inspecting what a top trader is holding RIGHT NOW. See also: `smartmoney_get_trader_positions_history` (closed positions), `smartmoney_search_trader` (nickname
|
|
7556
|
+
description: "Currently-open positions held by a single trader (direction, size, leverage, entry, conviction). Use when: inspecting what a top trader is holding RIGHT NOW. See also: `smartmoney_get_trader_positions_history` (closed positions), `smartmoney_search_trader` (nickname -> authorId), `smartmoney_get_traders_by_filter` (discover trader).",
|
|
7554
7557
|
isWrite: false,
|
|
7555
7558
|
outputSchema: envelope({
|
|
7556
7559
|
type: "array",
|
|
@@ -7570,9 +7573,9 @@ function registerSmartmoneyTools() {
|
|
|
7570
7573
|
direction: {
|
|
7571
7574
|
type: "string",
|
|
7572
7575
|
enum: ["long", "short"],
|
|
7573
|
-
description: 'Derived clean direction (`long` | `short`)
|
|
7576
|
+
description: 'Derived clean direction (`long` | `short`) - handler computes this from `posSide` + sign of `pos` so agents do not have to branch on the `posSide="net"` net-mode case.'
|
|
7574
7577
|
},
|
|
7575
|
-
posCcy: { type: "string", description: 'Position currency
|
|
7578
|
+
posCcy: { type: "string", description: 'Position currency - the asset being held, e.g. "BTC".' },
|
|
7576
7579
|
quoteCcy: { type: "string", description: 'Quote currency the position is priced/settled in, e.g. "USDT".' },
|
|
7577
7580
|
pos: {
|
|
7578
7581
|
type: "string",
|
|
@@ -7601,7 +7604,7 @@ function registerSmartmoneyTools() {
|
|
|
7601
7604
|
},
|
|
7602
7605
|
instId: {
|
|
7603
7606
|
type: "string",
|
|
7604
|
-
description: 'Optional instrument filter. Accepts either full instId (e.g. "BTC-USDT-SWAP") or bare base currency (e.g. "BTC")
|
|
7607
|
+
description: 'Optional instrument filter. Accepts either full instId (e.g. "BTC-USDT-SWAP") or bare base currency (e.g. "BTC") - the handler extracts the base currency for the upstream filter.'
|
|
7605
7608
|
}
|
|
7606
7609
|
},
|
|
7607
7610
|
required: ["authorId"]
|
|
@@ -7631,7 +7634,7 @@ function registerSmartmoneyTools() {
|
|
|
7631
7634
|
{
|
|
7632
7635
|
name: "smartmoney_get_trader_positions_history",
|
|
7633
7636
|
module: "smartmoney",
|
|
7634
|
-
description: "Closed-position history of a single trader, paginated by `posId` cursor. Use when: studying realized PnL pattern, holding duration, win/loss streaks, or how positions ended (closed vs liquidated). See also: `smartmoney_get_trader_positions` (currently-open), `smartmoney_search_trader` (nickname
|
|
7637
|
+
description: "Closed-position history of a single trader, paginated by `posId` cursor. Use when: studying realized PnL pattern, holding duration, win/loss streaks, or how positions ended (closed vs liquidated). See also: `smartmoney_get_trader_positions` (currently-open), `smartmoney_search_trader` (nickname -> authorId), `smartmoney_get_traders_by_filter` (discover trader).",
|
|
7635
7638
|
isWrite: false,
|
|
7636
7639
|
outputSchema: envelope(
|
|
7637
7640
|
{
|
|
@@ -7647,7 +7650,7 @@ function registerSmartmoneyTools() {
|
|
|
7647
7650
|
},
|
|
7648
7651
|
ctVal: {
|
|
7649
7652
|
type: "string",
|
|
7650
|
-
description: "Contract face value
|
|
7653
|
+
description: "Contract face value - USD value of a single contract (\u5F20). Numeric string. Empty/0 for non-contract instruments."
|
|
7651
7654
|
},
|
|
7652
7655
|
posSide: {
|
|
7653
7656
|
type: "string",
|
|
@@ -7714,15 +7717,15 @@ function registerSmartmoneyTools() {
|
|
|
7714
7717
|
},
|
|
7715
7718
|
instId: {
|
|
7716
7719
|
type: "string",
|
|
7717
|
-
description: 'Optional instrument filter. Accepts either full instId (e.g. "BTC-USDT-SWAP") or bare base currency (e.g. "BTC")
|
|
7720
|
+
description: 'Optional instrument filter. Accepts either full instId (e.g. "BTC-USDT-SWAP") or bare base currency (e.g. "BTC") - the handler extracts the base currency for the upstream filter.'
|
|
7718
7721
|
},
|
|
7719
7722
|
after: {
|
|
7720
7723
|
type: "string",
|
|
7721
|
-
description: 'Pagination cursor (older)
|
|
7724
|
+
description: 'Pagination cursor (older) - returns positions with `posId` smaller than this value. Pass the `posId` as a string, e.g. `"872913470357110787"`.'
|
|
7722
7725
|
},
|
|
7723
7726
|
before: {
|
|
7724
7727
|
type: "string",
|
|
7725
|
-
description: 'Pagination cursor (newer)
|
|
7728
|
+
description: 'Pagination cursor (newer) - returns positions with `posId` greater than this value. Pass the `posId` as a string, e.g. `"872913470357110787"`.'
|
|
7726
7729
|
},
|
|
7727
7730
|
limit: {
|
|
7728
7731
|
type: "integer",
|
|
@@ -7768,7 +7771,7 @@ function registerSmartmoneyTools() {
|
|
|
7768
7771
|
{
|
|
7769
7772
|
name: "smartmoney_get_trader_orders_history",
|
|
7770
7773
|
module: "smartmoney",
|
|
7771
|
-
description: "Recent orders/fills placed by a single trader (direction, size, price, leverage), paginated by `ordId` cursor. Aligned with the cross-module `*_get_orders` family. Use when: tracking a top trader's latest trade activity. See also: `smartmoney_search_trader` (nickname
|
|
7774
|
+
description: "Recent orders/fills placed by a single trader (direction, size, price, leverage), paginated by `ordId` cursor. Aligned with the cross-module `*_get_orders` family. Use when: tracking a top trader's latest trade activity. See also: `smartmoney_search_trader` (nickname -> authorId), `smartmoney_get_traders_by_filter` (discover trader).",
|
|
7772
7775
|
isWrite: false,
|
|
7773
7776
|
outputSchema: envelope(
|
|
7774
7777
|
{
|
|
@@ -7832,15 +7835,15 @@ function registerSmartmoneyTools() {
|
|
|
7832
7835
|
},
|
|
7833
7836
|
instId: {
|
|
7834
7837
|
type: "string",
|
|
7835
|
-
description: 'Optional instrument filter. Accepts either full instId (e.g. "BTC-USDT-SWAP") or bare base currency (e.g. "BTC")
|
|
7838
|
+
description: 'Optional instrument filter. Accepts either full instId (e.g. "BTC-USDT-SWAP") or bare base currency (e.g. "BTC") - the handler extracts the base currency for the upstream filter.'
|
|
7836
7839
|
},
|
|
7837
7840
|
after: {
|
|
7838
7841
|
type: "string",
|
|
7839
|
-
description: 'Pagination cursor (older)
|
|
7842
|
+
description: 'Pagination cursor (older) - returns trades with `ordId` smaller than this value. Pass the `ordId` as a string, e.g. `"872913470357110787"`.'
|
|
7840
7843
|
},
|
|
7841
7844
|
before: {
|
|
7842
7845
|
type: "string",
|
|
7843
|
-
description: 'Pagination cursor (newer)
|
|
7846
|
+
description: 'Pagination cursor (newer) - returns trades with `ordId` greater than this value. Pass the `ordId` as a string, e.g. `"872913470357110787"`.'
|
|
7844
7847
|
},
|
|
7845
7848
|
limit: {
|
|
7846
7849
|
type: "integer",
|
|
@@ -7894,7 +7897,7 @@ function registerSmartmoneyTools() {
|
|
|
7894
7897
|
items: {
|
|
7895
7898
|
type: "object",
|
|
7896
7899
|
properties: {
|
|
7897
|
-
authorId: { type: "string", description: "Trader's unique ID
|
|
7900
|
+
authorId: { type: "string", description: "Trader's unique ID - pass to other `smartmoney_get_trader_*` tools." },
|
|
7898
7901
|
nickName: { type: "string", description: "Display nickname matched against the keyword." },
|
|
7899
7902
|
followerCount: { type: "string", description: "OKX-platform follower count (numeric string; Twitter followers excluded). Sort key." }
|
|
7900
7903
|
}
|
|
@@ -7936,7 +7939,7 @@ function registerSmartmoneyTools() {
|
|
|
7936
7939
|
{
|
|
7937
7940
|
name: "smartmoney_get_signal_overview_by_filter",
|
|
7938
7941
|
module: "smartmoney",
|
|
7939
|
-
description: "Multi-asset smart-money consensus signals (long/short ratio, weighted entry, capital flow, deltas vs 1h/24h/7d), aggregated over a tier-filtered trader pool (PnL / win-rate / drawdown / AUM). Pick instruments via `topInstruments` OR `instCcyList`
|
|
7942
|
+
description: "Multi-asset smart-money consensus signals (long/short ratio, weighted entry, capital flow, deltas vs 1h/24h/7d), aggregated over a tier-filtered trader pool (PnL / win-rate / drawdown / AUM). Pick instruments via `topInstruments` OR `instCcyList` - exactly one. Snapshot time auto-resolved to current hour. **Linear (USDT/USDS-margined) contracts only - coin-margined (`-USD-SWAP` / `-USD-DELIVERY`) positions are excluded by upstream and silently omitted from the aggregation.** Use when: latest cross-asset consensus from a criteria-defined pool. See also: `smartmoney_get_signal_overview_by_trader` (restrict pool to specific traders), `smartmoney_get_signal_trend_by_filter` (time-series instead of latest snapshot).",
|
|
7940
7943
|
isWrite: false,
|
|
7941
7944
|
outputSchema: envelope({
|
|
7942
7945
|
type: "array",
|
|
@@ -7957,7 +7960,7 @@ function registerSmartmoneyTools() {
|
|
|
7957
7960
|
type: "array",
|
|
7958
7961
|
items: { type: "string" },
|
|
7959
7962
|
minItems: 1,
|
|
7960
|
-
description: 'Base currencies to aggregate, e.g. `["BTC", "ETH", "SOL"]`. Mutually exclusive with `topInstruments`. Scope: only USDT-margined and USDS-margined (linear) instruments
|
|
7963
|
+
description: 'Base currencies to aggregate, e.g. `["BTC", "ETH", "SOL"]`. Mutually exclusive with `topInstruments`. Scope: only USDT-margined and USDS-margined (linear) instruments - e.g. `BTC` covers `BTC-USDT-SWAP` + `BTC-USDS-SWAP`. Coin-margined contracts (`BTC-USD-SWAP`, `BTC-USD-DELIVERY`) are NOT included; positions a trader holds in those instruments are silently dropped from the aggregation.'
|
|
7961
7964
|
},
|
|
7962
7965
|
...SIGNAL_POOL_FILTER_PROPS,
|
|
7963
7966
|
lmtNum: {
|
|
@@ -7965,7 +7968,7 @@ function registerSmartmoneyTools() {
|
|
|
7965
7968
|
minimum: 1,
|
|
7966
7969
|
maximum: 2e3,
|
|
7967
7970
|
default: 100,
|
|
7968
|
-
description: "
|
|
7971
|
+
description: "Upper bound on `tradersQualified` (final aggregation pool size). Candidates pass through tier filters (`pnlTier` / `winRateTier` / `aumTier` / `maxDrawdownTier`), then are truncated to top-N by `sortBy` (DESC). `tradersQualified` \u2264 `lmtNum` always; equals `lmtNum` unless candidate pool underflows (rare ccy / strict tier combos). Default 100; values above ~1500 add latency without benefit (exceeds typical candidate pool size)."
|
|
7969
7972
|
}
|
|
7970
7973
|
},
|
|
7971
7974
|
required: ["sortBy", "period"]
|
|
@@ -7977,7 +7980,7 @@ function registerSmartmoneyTools() {
|
|
|
7977
7980
|
if (instCcyList && topInstrumentsRaw !== void 0) {
|
|
7978
7981
|
throw actionableError(
|
|
7979
7982
|
'"topInstruments" and "instCcyList" are mutually exclusive.',
|
|
7980
|
-
"Pass exactly one
|
|
7983
|
+
"Pass exactly one - `topInstruments` for top-N hottest coins, or `instCcyList` for specific coins."
|
|
7981
7984
|
);
|
|
7982
7985
|
}
|
|
7983
7986
|
const response = await context.client.privateGet(
|
|
@@ -7996,7 +7999,7 @@ function registerSmartmoneyTools() {
|
|
|
7996
7999
|
{
|
|
7997
8000
|
name: "smartmoney_get_signal_overview_by_trader",
|
|
7998
8001
|
module: "smartmoney",
|
|
7999
|
-
description: "Multi-asset smart-money signals aggregated over a hand-picked set of traders (`authorIds`). Pick instruments via `topInstruments` OR `instCcyList`. Capability tier filters (pnlTier / winRateTier / etc.) not exposed
|
|
8002
|
+
description: "Multi-asset smart-money signals aggregated over a hand-picked set of traders (`authorIds`). Pick instruments via `topInstruments` OR `instCcyList`. Capability tier filters (pnlTier / winRateTier / etc.) not exposed - backend uses defaults for direct-lookup scenarios. **Linear (USDT/USDS-margined) contracts only - a trader's coin-margined (`-USD-SWAP` / `-USD-DELIVERY`) positions are silently excluded from the aggregation, even when those positions are large.** Use `smartmoney_get_trader_positions` if the full position book is needed. Use when: caller already knows which traders to follow and wants their cross-asset consensus at the latest hour. See also: `smartmoney_get_signal_overview_by_filter` (criteria-defined pool), `smartmoney_get_signal_trend_by_trader` (time-series), `smartmoney_get_traders_by_filter` / `smartmoney_search_trader` (discover authorIds).",
|
|
8000
8003
|
isWrite: false,
|
|
8001
8004
|
outputSchema: envelope({
|
|
8002
8005
|
type: "array",
|
|
@@ -8023,7 +8026,7 @@ function registerSmartmoneyTools() {
|
|
|
8023
8026
|
type: "array",
|
|
8024
8027
|
items: { type: "string" },
|
|
8025
8028
|
minItems: 1,
|
|
8026
|
-
description: 'Base currencies to aggregate, e.g. `["BTC", "ETH", "SOL"]`. Mutually exclusive with `topInstruments`. Scope: only USDT-margined and USDS-margined (linear) instruments
|
|
8029
|
+
description: 'Base currencies to aggregate, e.g. `["BTC", "ETH", "SOL"]`. Mutually exclusive with `topInstruments`. Scope: only USDT-margined and USDS-margined (linear) instruments - e.g. `BTC` covers `BTC-USDT-SWAP` + `BTC-USDS-SWAP`. Coin-margined contracts (`BTC-USD-SWAP`, `BTC-USD-DELIVERY`) are NOT included; the trader\'s positions in those instruments are silently dropped.'
|
|
8027
8030
|
},
|
|
8028
8031
|
sortBy: {
|
|
8029
8032
|
type: "string",
|
|
@@ -8056,7 +8059,7 @@ function registerSmartmoneyTools() {
|
|
|
8056
8059
|
if (instCcyList && topInstrumentsRaw !== void 0) {
|
|
8057
8060
|
throw actionableError(
|
|
8058
8061
|
'"topInstruments" and "instCcyList" are mutually exclusive.',
|
|
8059
|
-
"Pass exactly one
|
|
8062
|
+
"Pass exactly one - `topInstruments` for top-N hottest coins, or `instCcyList` for specific coins."
|
|
8060
8063
|
);
|
|
8061
8064
|
}
|
|
8062
8065
|
const response = await context.client.privateGet(
|
|
@@ -8078,7 +8081,7 @@ function registerSmartmoneyTools() {
|
|
|
8078
8081
|
{
|
|
8079
8082
|
name: "smartmoney_get_signal_trend_by_filter",
|
|
8080
8083
|
module: "smartmoney",
|
|
8081
|
-
description: "Time-series of single-asset smart-money signal across hourly/daily buckets, aggregated over a tier-filtered trader pool. Returns the latest `limit` buckets ending at `asOfTime` (defaults to current UTC hour). **Linear (USDT/USDS-margined) contracts only
|
|
8084
|
+
description: "Time-series of single-asset smart-money signal across hourly/daily buckets, aggregated over a tier-filtered trader pool. Returns the latest `limit` buckets ending at `asOfTime` (defaults to current UTC hour). **Linear (USDT/USDS-margined) contracts only - coin-margined (`-USD-SWAP` / `-USD-DELIVERY`) positions are excluded by upstream and silently omitted.** Use when: tracking how long/short conviction and capital evolve over time (smart money adding exposure or retreating). See also: `smartmoney_get_signal_overview_by_filter` (latest snapshot only), `smartmoney_get_signal_trend_by_trader` (restrict to specific traders). Note: `asOfTime` is 10-digit `yyyyMMddHH` UTC, different from leaderboard tools' 12-digit UTC+8 `updateTime` - do not cross-pass.",
|
|
8082
8085
|
isWrite: false,
|
|
8083
8086
|
outputSchema: envelope({
|
|
8084
8087
|
type: "array",
|
|
@@ -8090,11 +8093,11 @@ function registerSmartmoneyTools() {
|
|
|
8090
8093
|
properties: {
|
|
8091
8094
|
instCcy: {
|
|
8092
8095
|
type: "string",
|
|
8093
|
-
description: 'Base currency to scope the time-series, e.g. "BTC". Required. Scope: USDT-margined and USDS-margined (linear) instruments only
|
|
8096
|
+
description: 'Base currency to scope the time-series, e.g. "BTC". Required. Scope: USDT-margined and USDS-margined (linear) instruments only - coin-margined (`-USD-SWAP` / `-USD-DELIVERY`) positions are NOT included.'
|
|
8094
8097
|
},
|
|
8095
8098
|
asOfTime: {
|
|
8096
8099
|
type: "string",
|
|
8097
|
-
description: 'Anchor snapshot time
|
|
8100
|
+
description: 'Anchor snapshot time - 10-digit `yyyyMMddHH` UTC as a string, e.g. `"2026050100"`. Returns the latest `limit` buckets ending at this anchor. Omit to use the current UTC hour.'
|
|
8098
8101
|
},
|
|
8099
8102
|
granularity: {
|
|
8100
8103
|
type: "string",
|
|
@@ -8115,7 +8118,7 @@ function registerSmartmoneyTools() {
|
|
|
8115
8118
|
minimum: 1,
|
|
8116
8119
|
maximum: 2e3,
|
|
8117
8120
|
default: 100,
|
|
8118
|
-
description: "
|
|
8121
|
+
description: "Upper bound on `tradersQualified` per bucket (final aggregation pool size). Candidates pass through tier filters (`pnlTier` / `winRateTier` / `aumTier` / `maxDrawdownTier`), then are truncated to top-N by `sortBy` (DESC). `tradersQualified` \u2264 `lmtNum` always; equals `lmtNum` unless candidate pool underflows (rare ccy / strict tier combos). Default 100; values above ~1500 add latency without benefit (exceeds typical candidate pool size)."
|
|
8119
8122
|
}
|
|
8120
8123
|
},
|
|
8121
8124
|
required: ["instCcy", "granularity", "sortBy", "period"]
|
|
@@ -8150,7 +8153,7 @@ function registerSmartmoneyTools() {
|
|
|
8150
8153
|
{
|
|
8151
8154
|
name: "smartmoney_get_signal_trend_by_trader",
|
|
8152
8155
|
module: "smartmoney",
|
|
8153
|
-
description: "Time-series of single-asset smart-money signal aggregated over a hand-picked set of traders (`authorIds`). Returns the latest `limit` buckets ending at `asOfTime` (defaults to current UTC hour). Capability tier filters (pnlTier / winRateTier / etc.) not exposed
|
|
8156
|
+
description: "Time-series of single-asset smart-money signal aggregated over a hand-picked set of traders (`authorIds`). Returns the latest `limit` buckets ending at `asOfTime` (defaults to current UTC hour). Capability tier filters (pnlTier / winRateTier / etc.) not exposed - backend uses defaults for direct-lookup scenarios. **Linear (USDT/USDS-margined) contracts only - a trader's coin-margined (`-USD-SWAP` / `-USD-DELIVERY`) positions on the requested base ccy are silently excluded from each bucket.** Use `smartmoney_get_trader_positions` to inspect the full position book. Use when: tracking how a specific group of traders has evolved their long/short consensus over time on one coin. See also: `smartmoney_get_signal_trend_by_filter` (criteria-defined pool), `smartmoney_get_signal_overview_by_trader` (latest snapshot only), `smartmoney_get_traders_by_filter` / `smartmoney_search_trader` (discover authorIds). Note: `asOfTime` is 10-digit `yyyyMMddHH` UTC, different from leaderboard tools' 12-digit UTC+8 `updateTime` - do not cross-pass.",
|
|
8154
8157
|
isWrite: false,
|
|
8155
8158
|
outputSchema: envelope({
|
|
8156
8159
|
type: "array",
|
|
@@ -8168,11 +8171,11 @@ function registerSmartmoneyTools() {
|
|
|
8168
8171
|
},
|
|
8169
8172
|
instCcy: {
|
|
8170
8173
|
type: "string",
|
|
8171
|
-
description: 'Base currency to scope the time-series, e.g. "BTC". Required. Scope: USDT-margined and USDS-margined (linear) instruments only
|
|
8174
|
+
description: 'Base currency to scope the time-series, e.g. "BTC". Required. Scope: USDT-margined and USDS-margined (linear) instruments only - coin-margined (`-USD-SWAP` / `-USD-DELIVERY`) positions held by the trader set are NOT included.'
|
|
8172
8175
|
},
|
|
8173
8176
|
asOfTime: {
|
|
8174
8177
|
type: "string",
|
|
8175
|
-
description: 'Anchor snapshot time
|
|
8178
|
+
description: 'Anchor snapshot time - 10-digit `yyyyMMddHH` UTC as a string, e.g. `"2026050100"`. Returns the latest `limit` buckets ending at this anchor. Omit to use the current UTC hour.'
|
|
8176
8179
|
},
|
|
8177
8180
|
granularity: {
|
|
8178
8181
|
type: "string",
|
|
@@ -8252,7 +8255,7 @@ function buildContractTradeTools(cfg) {
|
|
|
8252
8255
|
{
|
|
8253
8256
|
name: n("place_order"),
|
|
8254
8257
|
module,
|
|
8255
|
-
description: `Place ${label} order. Attach TP/SL via tpTriggerPx/slTriggerPx. Before placing, use market_get_instruments to get ctVal (contract face value)
|
|
8258
|
+
description: `Place ${label} order. Attach TP/SL via tpTriggerPx/slTriggerPx. Before placing, use market_get_instruments to get ctVal (contract face value) - do NOT assume contract sizes. [CAUTION] Executes real trades.`,
|
|
8256
8259
|
isWrite: true,
|
|
8257
8260
|
inputSchema: {
|
|
8258
8261
|
type: "object",
|
|
@@ -8592,10 +8595,10 @@ function buildContractTradeTools(cfg) {
|
|
|
8592
8595
|
module,
|
|
8593
8596
|
description: `Set leverage for a ${label} instrument or position. [CAUTION] Changes risk parameters.
|
|
8594
8597
|
Scenarios (SWAP/FUTURES only):
|
|
8595
|
-
\u2022 cross + any instId under the index
|
|
8596
|
-
\u2022 isolated + buy-sell (net) posMode
|
|
8597
|
-
\u2022 isolated + long-short (hedge) posMode
|
|
8598
|
-
Not supported: PORTFOLIO MARGIN accounts cannot adjust cross leverage for SWAP/FUTURES
|
|
8598
|
+
\u2022 cross + any instId under the index -> sets leverage at the index level
|
|
8599
|
+
\u2022 isolated + buy-sell (net) posMode -> instId only
|
|
8600
|
+
\u2022 isolated + long-short (hedge) posMode -> instId + posSide=long|short (BOTH directions must be set separately)
|
|
8601
|
+
Not supported: PORTFOLIO MARGIN accounts cannot adjust cross leverage for SWAP/FUTURES - the request will be rejected by OKX. Use account_get_config first if unsure of the account's margin mode.`,
|
|
8599
8602
|
isWrite: true,
|
|
8600
8603
|
inputSchema: {
|
|
8601
8604
|
type: "object",
|
|
@@ -8603,13 +8606,13 @@ Not supported: PORTFOLIO MARGIN accounts cannot adjust cross leverage for SWAP/F
|
|
|
8603
8606
|
instId: { type: "string", description: instIdExample },
|
|
8604
8607
|
lever: {
|
|
8605
8608
|
type: "string",
|
|
8606
|
-
description: "Leverage multiplier as a positive number string, e.g. '10'. Max value depends on the instrument (query market_get_instruments
|
|
8609
|
+
description: "Leverage multiplier as a positive number string, e.g. '10'. Max value depends on the instrument (query market_get_instruments -> lever)."
|
|
8607
8610
|
},
|
|
8608
8611
|
mgnMode: { type: "string", enum: ["cross", "isolated"] },
|
|
8609
8612
|
posSide: {
|
|
8610
8613
|
type: "string",
|
|
8611
8614
|
enum: ["long", "short"],
|
|
8612
|
-
description: "REQUIRED when mgnMode=isolated AND the account is in hedge (long/short) position mode. Use 'long' or 'short'
|
|
8615
|
+
description: "REQUIRED when mgnMode=isolated AND the account is in hedge (long/short) position mode. Use 'long' or 'short' - setting one side does NOT auto-apply to the other. Omit entirely for one-way (net) position mode or for cross margin."
|
|
8613
8616
|
}
|
|
8614
8617
|
},
|
|
8615
8618
|
required: ["instId", "lever", "mgnMode"]
|
|
@@ -9425,12 +9428,12 @@ var OI_BARS = ["5m", "15m", "1H", "4H", "1D"];
|
|
|
9425
9428
|
function registerMarketFilterTools() {
|
|
9426
9429
|
return [
|
|
9427
9430
|
// ─────────────────────────────────────────────────────────────────────────
|
|
9428
|
-
// market_filter
|
|
9431
|
+
// market_filter - /api/v5/aigc/mcp/market-filter
|
|
9429
9432
|
// ─────────────────────────────────────────────────────────────────────────
|
|
9430
9433
|
{
|
|
9431
9434
|
name: "market_filter",
|
|
9432
9435
|
module: "market",
|
|
9433
|
-
description: "Screen / rank instruments across SPOT, SWAP, or FUTURES by multi-dimensional criteria: price range, 24h change %, market cap, 24h volume (USD), funding rate (SWAP), open interest (USD), listing time. Returns ranked rows with full ticker snapshot. Use to find top movers, high-OI contracts, newly listed tokens, etc. No credentials required. Do NOT use to get OI change rankings across contracts
|
|
9436
|
+
description: "Screen / rank instruments across SPOT, SWAP, or FUTURES by multi-dimensional criteria: price range, 24h change %, market cap, 24h volume (USD), funding rate (SWAP), open interest (USD), listing time. Returns ranked rows with full ticker snapshot. Use to find top movers, high-OI contracts, newly listed tokens, etc. No credentials required. Do NOT use to get OI change rankings across contracts - use market_filter_oi_change instead. Do NOT use to get OI time series for a single instrument - use market_get_oi_history instead.",
|
|
9434
9437
|
isWrite: false,
|
|
9435
9438
|
inputSchema: {
|
|
9436
9439
|
type: "object",
|
|
@@ -9514,7 +9517,7 @@ function registerMarketFilterTools() {
|
|
|
9514
9517
|
sortBy: {
|
|
9515
9518
|
type: "string",
|
|
9516
9519
|
enum: ["last", "chg24hPct", "marketCapUsd", "volUsd24h", "fundingRate", "oiUsd", "listTime"],
|
|
9517
|
-
description: "Sort field. Default: volUsd24h. Note: marketCapUsd is only meaningful for SPOT (null for SWAP/FUTURES). To rank by OI *change* (oiDeltaPct / absOiDeltaPct), use market_filter_oi_change
|
|
9520
|
+
description: "Sort field. Default: volUsd24h. Note: marketCapUsd is only meaningful for SPOT (null for SWAP/FUTURES). To rank by OI *change* (oiDeltaPct / absOiDeltaPct), use market_filter_oi_change - market_filter only sorts by the current snapshot."
|
|
9518
9521
|
},
|
|
9519
9522
|
sortOrder: {
|
|
9520
9523
|
type: "string",
|
|
@@ -9562,12 +9565,12 @@ function registerMarketFilterTools() {
|
|
|
9562
9565
|
}
|
|
9563
9566
|
},
|
|
9564
9567
|
// ─────────────────────────────────────────────────────────────────────────
|
|
9565
|
-
// market_get_oi_history
|
|
9568
|
+
// market_get_oi_history - /api/v5/aigc/mcp/oi-history
|
|
9566
9569
|
// ─────────────────────────────────────────────────────────────────────────
|
|
9567
9570
|
{
|
|
9568
9571
|
name: "market_get_oi_history",
|
|
9569
9572
|
module: "market",
|
|
9570
|
-
description: "Get open interest (OI) history time series for a single SWAP or FUTURES instrument. Returns per-bar OI in contracts, base currency and USD, plus bar-over-bar delta and delta %. Useful for tracking how OI evolves around price moves. No credentials required. Do NOT use to compare OI changes across multiple contracts
|
|
9573
|
+
description: "Get open interest (OI) history time series for a single SWAP or FUTURES instrument. Returns per-bar OI in contracts, base currency and USD, plus bar-over-bar delta and delta %. Useful for tracking how OI evolves around price moves. No credentials required. Do NOT use to compare OI changes across multiple contracts - use market_filter_oi_change instead. Do NOT use to screen instruments by current OI level - use market_filter instead.",
|
|
9571
9574
|
isWrite: false,
|
|
9572
9575
|
inputSchema: {
|
|
9573
9576
|
type: "object",
|
|
@@ -9609,12 +9612,12 @@ function registerMarketFilterTools() {
|
|
|
9609
9612
|
}
|
|
9610
9613
|
},
|
|
9611
9614
|
// ─────────────────────────────────────────────────────────────────────────
|
|
9612
|
-
// market_filter_oi_change
|
|
9615
|
+
// market_filter_oi_change - /api/v5/aigc/mcp/oi-change-filter
|
|
9613
9616
|
// ─────────────────────────────────────────────────────────────────────────
|
|
9614
9617
|
{
|
|
9615
9618
|
name: "market_filter_oi_change",
|
|
9616
9619
|
module: "market",
|
|
9617
|
-
description: "Find SWAP or FUTURES instruments with significant open interest changes over a given bar window. Returns ranked rows with current OI (USD), previous OI (USD), OI delta (USD and %), price change %, 24h volume and funding rate. Ideal for spotting unusual accumulation/distribution or confirming trend momentum. No credentials required. Do NOT use to get OI time series for a single instrument
|
|
9620
|
+
description: "Find SWAP or FUTURES instruments with significant open interest changes over a given bar window. Returns ranked rows with current OI (USD), previous OI (USD), OI delta (USD and %), price change %, 24h volume and funding rate. Ideal for spotting unusual accumulation/distribution or confirming trend momentum. No credentials required. Do NOT use to get OI time series for a single instrument - use market_get_oi_history instead. Do NOT use to screen by current OI absolute level or other non-OI metrics - use market_filter instead.",
|
|
9618
9621
|
isWrite: false,
|
|
9619
9622
|
inputSchema: {
|
|
9620
9623
|
type: "object",
|
|
@@ -9646,7 +9649,7 @@ function registerMarketFilterTools() {
|
|
|
9646
9649
|
sortBy: {
|
|
9647
9650
|
type: "string",
|
|
9648
9651
|
enum: ["oiUsd", "oiDeltaUsd", "oiDeltaPct", "absOiDeltaPct", "volUsd24h", "fundingRate", "last"],
|
|
9649
|
-
description: "Sort field. Default: oiDeltaPct (largest movers first, signed
|
|
9652
|
+
description: "Sort field. Default: oiDeltaPct (largest movers first, signed - longs and shorts separate). Use absOiDeltaPct to sort by |oiDeltaPct| (largest-magnitude moves regardless of direction). fundingRate is also supported for SWAP. Do NOT use the market_filter tool's sort fields (chg24hPct, marketCapUsd, listTime) here - they are not in the OI-change Row."
|
|
9650
9653
|
},
|
|
9651
9654
|
sortOrder: {
|
|
9652
9655
|
type: "string",
|
|
@@ -9679,6 +9682,58 @@ function registerMarketFilterTools() {
|
|
|
9679
9682
|
);
|
|
9680
9683
|
return normalizeResponse(response);
|
|
9681
9684
|
}
|
|
9685
|
+
},
|
|
9686
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
9687
|
+
// market_get_pair_spread - /api/v5/aigc/mcp/pair-spread
|
|
9688
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
9689
|
+
{
|
|
9690
|
+
name: "market_get_pair_spread",
|
|
9691
|
+
module: "market",
|
|
9692
|
+
description: "Compute spread statistics between two instruments over a lookback window. Returns absolute and ratio spread (mean / stdDev / median / min / max) plus an optional realtime spread snapshot. Use to size pairs trades, detect mean-reversion setups, or compare cross-listed contracts. Results are cached ~60s per (pair, bar, window) tuple. Read-only, no credentials required.\nDo NOT use to fetch raw candles (use market_get_candles) or single-instrument OI/funding (use market_get_oi_history / market_filter_oi_change).",
|
|
9693
|
+
isWrite: false,
|
|
9694
|
+
inputSchema: {
|
|
9695
|
+
type: "object",
|
|
9696
|
+
properties: {
|
|
9697
|
+
instIdA: {
|
|
9698
|
+
type: "string",
|
|
9699
|
+
description: "First instrument ID, e.g. BTC-USDT-SWAP"
|
|
9700
|
+
},
|
|
9701
|
+
instIdB: {
|
|
9702
|
+
type: "string",
|
|
9703
|
+
description: "Second instrument ID; must differ from instIdA"
|
|
9704
|
+
},
|
|
9705
|
+
bar: {
|
|
9706
|
+
type: "string",
|
|
9707
|
+
enum: ["5m", "15m"],
|
|
9708
|
+
description: "Bar size for the spread series. Default 15m. 1m is not supported."
|
|
9709
|
+
},
|
|
9710
|
+
window: {
|
|
9711
|
+
type: "string",
|
|
9712
|
+
description: "Lookback window. Format <n><unit>, units m/H/D/W (case-sensitive), max 1W. Default 1W."
|
|
9713
|
+
},
|
|
9714
|
+
backtestTime: {
|
|
9715
|
+
type: "number",
|
|
9716
|
+
description: "Anchor timestamp (ms epoch) for backtest mode. When provided, realtime is omitted."
|
|
9717
|
+
}
|
|
9718
|
+
},
|
|
9719
|
+
required: ["instIdA", "instIdB"]
|
|
9720
|
+
},
|
|
9721
|
+
handler: async (rawArgs, context) => {
|
|
9722
|
+
const args = asRecord(rawArgs);
|
|
9723
|
+
const body = compactObject({
|
|
9724
|
+
instIdA: requireString(args, "instIdA"),
|
|
9725
|
+
instIdB: requireString(args, "instIdB"),
|
|
9726
|
+
bar: readString(args, "bar"),
|
|
9727
|
+
window: readString(args, "window"),
|
|
9728
|
+
backtestTime: readNumber(args, "backtestTime")
|
|
9729
|
+
});
|
|
9730
|
+
const response = await context.client.publicPost(
|
|
9731
|
+
"/api/v5/aigc/mcp/pair-spread",
|
|
9732
|
+
body,
|
|
9733
|
+
publicRateLimit("market_get_pair_spread", 5)
|
|
9734
|
+
);
|
|
9735
|
+
return normalizeResponse(response);
|
|
9736
|
+
}
|
|
9682
9737
|
}
|
|
9683
9738
|
];
|
|
9684
9739
|
}
|
|
@@ -9915,7 +9970,7 @@ var D_COINS_SENTIMENT = 'Comma-separated uppercase ticker symbols, max 20 (e.g.
|
|
|
9915
9970
|
var D_LANGUAGE = "Content language: zh-CN or en-US. Infer from user's message. No server default.";
|
|
9916
9971
|
var D_BEGIN = "Start time, Unix epoch milliseconds. API defaults to 72 hours ago when omitted. Pass explicitly for older topics (e.g. 'last 30 days'). Max range: 180 days. Parse relative time if given.";
|
|
9917
9972
|
var D_END = "End time, Unix epoch milliseconds. Parse relative time if given. Omit for no upper bound.";
|
|
9918
|
-
var D_IMPORTANCE = "Importance filter: 'low' returns all news (both low and high importance); 'high' narrows to major/breaking news only. Omitted
|
|
9973
|
+
var D_IMPORTANCE = "Importance filter: 'low' returns all news (both low and high importance); 'high' narrows to major/breaking news only. Omitted -> server default (high-only). Default to 'low' for broad browsing; pass 'high' only when the user explicitly asks for major news.";
|
|
9919
9974
|
var D_PLATFORM = "Filter by news source. Use values from news_get_domains (e.g. blockbeats, odaily_flash). Omit for all sources.";
|
|
9920
9975
|
var D_LIMIT = "Number of results (default 10, max 50).";
|
|
9921
9976
|
function registerNewsTools() {
|
|
@@ -10014,7 +10069,7 @@ function registerNewsTools() {
|
|
|
10014
10069
|
{
|
|
10015
10070
|
name: "news_search",
|
|
10016
10071
|
module: "news",
|
|
10017
|
-
description: "Search crypto news by keyword with optional filters. Use when user provides specific search terms: 'SEC ETF news', 'stablecoin regulation'. Keyword is optional
|
|
10072
|
+
description: "Search crypto news by keyword with optional filters. Use when user provides specific search terms: 'SEC ETF news', 'stablecoin regulation'. Keyword is optional - pass sentiment alone to browse by sentiment direction. For coin-only queries prefer news_get_by_coin.",
|
|
10018
10073
|
isWrite: false,
|
|
10019
10074
|
inputSchema: {
|
|
10020
10075
|
type: "object",
|
|
@@ -10124,7 +10179,7 @@ function registerNewsTools() {
|
|
|
10124
10179
|
{
|
|
10125
10180
|
name: "news_get_coin_sentiment",
|
|
10126
10181
|
module: "news",
|
|
10127
|
-
description: "Get sentiment snapshot or time-series trend for coins. Returns bullish/bearish ratios and mention counts. Pass trendPoints for trend data (1h
|
|
10182
|
+
description: "Get sentiment snapshot or time-series trend for coins. Returns bullish/bearish ratios and mention counts. Pass trendPoints for trend data (1h->24 points, 4h->6, 24h->7). Use when user asks about coin sentiment, sentiment trend, or how bullish/bearish a coin is. For ranking all coins by sentiment, use news_get_sentiment_ranking instead.",
|
|
10128
10183
|
isWrite: false,
|
|
10129
10184
|
inputSchema: {
|
|
10130
10185
|
type: "object",
|
|
@@ -10137,7 +10192,7 @@ function registerNewsTools() {
|
|
|
10137
10192
|
},
|
|
10138
10193
|
trendPoints: {
|
|
10139
10194
|
type: "number",
|
|
10140
|
-
description: "Trend data points. Pass for time-series trend; omit for snapshot. Guide: 1h
|
|
10195
|
+
description: "Trend data points. Pass for time-series trend; omit for snapshot. Guide: 1h->24, 4h->6, 24h->7."
|
|
10141
10196
|
}
|
|
10142
10197
|
},
|
|
10143
10198
|
required: ["coins"]
|
|
@@ -10204,7 +10259,7 @@ function registerNewsTools() {
|
|
|
10204
10259
|
{
|
|
10205
10260
|
name: "news_list_calendar_regions",
|
|
10206
10261
|
module: "news",
|
|
10207
|
-
description: "List all valid region values for the economic calendar. Returns a string array of snake_case region codes. Call this when economic-calendar returns empty results to verify the region value, or to help the user pick a valid region. Do NOT use to list news source platforms
|
|
10262
|
+
description: "List all valid region values for the economic calendar. Returns a string array of snake_case region codes. Call this when economic-calendar returns empty results to verify the region value, or to help the user pick a valid region. Do NOT use to list news source platforms - use news_get_domains instead.",
|
|
10208
10263
|
isWrite: false,
|
|
10209
10264
|
inputSchema: { type: "object", properties: {}, required: [] },
|
|
10210
10265
|
handler: async () => ({ data: CALENDAR_REGIONS })
|
|
@@ -10212,15 +10267,15 @@ function registerNewsTools() {
|
|
|
10212
10267
|
{
|
|
10213
10268
|
name: "news_get_economic_calendar",
|
|
10214
10269
|
module: "news",
|
|
10215
|
-
description: "Get macro-economic calendar data (GDP, CPI, NFP, interest rate decisions, PMI, etc.). Returns scheduled and released economic events with forecast, previous, and actual values. Use when user asks about economic calendar, macro data, or specific indicators like NFP/CPI/GDP/FOMC. Do NOT use for news articles or sentiment
|
|
10270
|
+
description: "Get macro-economic calendar data (GDP, CPI, NFP, interest rate decisions, PMI, etc.). Returns scheduled and released economic events with forecast, previous, and actual values. Use when user asks about economic calendar, macro data, or specific indicators like NFP/CPI/GDP/FOMC. Do NOT use for news articles or sentiment - use news_get_latest or news_search instead.",
|
|
10216
10271
|
isWrite: false,
|
|
10217
10272
|
inputSchema: {
|
|
10218
10273
|
type: "object",
|
|
10219
10274
|
properties: {
|
|
10220
10275
|
region: { type: "string", description: "Country/region filter in snake_case (e.g. united_states, euro_area, japan). Invalid values return empty results silently. If empty results, call news_list_calendar_regions to verify the value." },
|
|
10221
10276
|
importance: { type: "string", enum: ["1", "2", "3"], description: "Importance level: 1=low, 2=medium, 3=high. Omit for all levels." },
|
|
10222
|
-
before: { type: "string", description: "Lower time bound
|
|
10223
|
-
after: { type: "string", description: "Upper time bound
|
|
10277
|
+
before: { type: "string", description: "Lower time bound - returns events NEWER than this timestamp (reversed semantics). Pair with 'after' for future-event windows. Unix ms." },
|
|
10278
|
+
after: { type: "string", description: "Upper time bound - returns events OLDER than this timestamp (reversed semantics). Default=now (returns past events). Pair with 'before' for a bounded window. Unix ms." },
|
|
10224
10279
|
limit: { type: "number", minimum: 1, maximum: 100, description: "Number of results (default 100, max 100)." }
|
|
10225
10280
|
},
|
|
10226
10281
|
required: []
|
|
@@ -10378,7 +10433,7 @@ function registerOptionAlgoTools() {
|
|
|
10378
10433
|
{
|
|
10379
10434
|
name: "option_amend_algo_order",
|
|
10380
10435
|
module: "option",
|
|
10381
|
-
description: "Amend a pending OPTION algo order (modify TP/SL prices or size). Also covers TP/SL orders attached when placing the main order
|
|
10436
|
+
description: "Amend a pending OPTION algo order (modify TP/SL prices or size). Also covers TP/SL orders attached when placing the main order - look up algoId via option_get_algo_orders first.",
|
|
10382
10437
|
isWrite: true,
|
|
10383
10438
|
inputSchema: {
|
|
10384
10439
|
type: "object",
|
|
@@ -10541,7 +10596,7 @@ function registerOptionTools() {
|
|
|
10541
10596
|
{
|
|
10542
10597
|
name: "option_place_order",
|
|
10543
10598
|
module: "option",
|
|
10544
|
-
description: "Place OPTION order. instId: {uly}-{expiry}-{strike}-C/P, e.g. BTC-USD-241227-50000-C. Before placing, use market_get_instruments to get ctVal (contract face value)
|
|
10599
|
+
description: "Place OPTION order. instId: {uly}-{expiry}-{strike}-C/P, e.g. BTC-USD-241227-50000-C. Before placing, use market_get_instruments to get ctVal (contract face value) - do NOT assume contract sizes. [CAUTION] Executes real trades.",
|
|
10545
10600
|
isWrite: true,
|
|
10546
10601
|
inputSchema: {
|
|
10547
10602
|
type: "object",
|
|
@@ -11315,7 +11370,7 @@ function registerSpotTradeTools() {
|
|
|
11315
11370
|
{
|
|
11316
11371
|
name: "spot_amend_algo_order",
|
|
11317
11372
|
module: "spot",
|
|
11318
|
-
description: "Amend a pending spot algo order (modify TP/SL prices or size). Also covers TP/SL orders attached when placing the main order
|
|
11373
|
+
description: "Amend a pending spot algo order (modify TP/SL prices or size). Also covers TP/SL orders attached when placing the main order - look up algoId via spot_get_algo_orders first.",
|
|
11319
11374
|
isWrite: true,
|
|
11320
11375
|
inputSchema: {
|
|
11321
11376
|
type: "object",
|
|
@@ -11384,7 +11439,7 @@ function registerSpotTradeTools() {
|
|
|
11384
11439
|
{
|
|
11385
11440
|
name: "spot_get_algo_orders",
|
|
11386
11441
|
module: "spot",
|
|
11387
|
-
description: "Query spot algo orders (TP/SL)
|
|
11442
|
+
description: "Query spot algo orders (TP/SL) - pending or history.",
|
|
11388
11443
|
isWrite: false,
|
|
11389
11444
|
inputSchema: {
|
|
11390
11445
|
type: "object",
|
|
@@ -11677,16 +11732,16 @@ function registerSpotTradeTools() {
|
|
|
11677
11732
|
}
|
|
11678
11733
|
},
|
|
11679
11734
|
// ── set_leverage (SPOT margin: instId-level isolated OR ccy-level cross) ──
|
|
11680
|
-
// Covers OKX scenarios 1
|
|
11735
|
+
// Covers OKX scenarios 1-5 (everything except SWAP/FUTURES, which are in
|
|
11681
11736
|
// contract-trade.ts). Callers supply exactly one of {instId, ccy}:
|
|
11682
|
-
// • instId + isolated
|
|
11683
|
-
// • instId + cross
|
|
11684
|
-
// • ccy + cross
|
|
11737
|
+
// • instId + isolated -> scenario 1 (pair-level margin)
|
|
11738
|
+
// • instId + cross -> scenario 3 (contract-mode pair-level cross margin)
|
|
11739
|
+
// • ccy + cross -> scenarios 2 / 4 / 5 (spot/multi-ccy/PM currency-level cross)
|
|
11685
11740
|
// Not applicable: posSide (spot has no long/short hedge).
|
|
11686
11741
|
{
|
|
11687
11742
|
name: "spot_set_leverage",
|
|
11688
11743
|
module: "spot",
|
|
11689
|
-
description: "Set leverage for SPOT margin trading. Provide exactly ONE of instId (pair-level) or ccy (currency-level cross, requires borrow-enabled account / multi-ccy / portfolio margin). [CAUTION] Changes risk parameters.\nScenarios:\n \u2022 instId + mgnMode=isolated
|
|
11744
|
+
description: "Set leverage for SPOT margin trading. Provide exactly ONE of instId (pair-level) or ccy (currency-level cross, requires borrow-enabled account / multi-ccy / portfolio margin). [CAUTION] Changes risk parameters.\nScenarios:\n \u2022 instId + mgnMode=isolated -> pair-level isolated margin\n \u2022 instId + mgnMode=cross -> pair-level cross margin (contract-mode account)\n \u2022 ccy + mgnMode=cross -> currency-level cross margin (spot-with-borrow / multi-ccy / portfolio margin)\nWhen ccy is supplied, mgnMode MUST be cross. posSide is never applicable to spot margin.",
|
|
11690
11745
|
isWrite: true,
|
|
11691
11746
|
inputSchema: {
|
|
11692
11747
|
type: "object",
|
|
@@ -11701,7 +11756,7 @@ function registerSpotTradeTools() {
|
|
|
11701
11756
|
},
|
|
11702
11757
|
lever: {
|
|
11703
11758
|
type: "string",
|
|
11704
|
-
description: "Leverage multiplier as a positive number string, e.g. '3'. Max depends on the pair (query market_get_instruments
|
|
11759
|
+
description: "Leverage multiplier as a positive number string, e.g. '3'. Max depends on the pair (query market_get_instruments -> lever) or the account policy for ccy-level."
|
|
11705
11760
|
},
|
|
11706
11761
|
mgnMode: {
|
|
11707
11762
|
type: "string",
|
|
@@ -11722,7 +11777,7 @@ function registerSpotTradeTools() {
|
|
|
11722
11777
|
}
|
|
11723
11778
|
if (instId && ccy) {
|
|
11724
11779
|
throw new ValidationError(
|
|
11725
|
-
`Parameters "instId" and "ccy" are mutually exclusive
|
|
11780
|
+
`Parameters "instId" and "ccy" are mutually exclusive - provide only one. instId sets pair-level leverage; ccy sets currency-level cross margin leverage.`
|
|
11726
11781
|
);
|
|
11727
11782
|
}
|
|
11728
11783
|
const leverRaw = requireString(args, "lever");
|
|
@@ -11769,7 +11824,7 @@ function registerSwapTradeTools() {
|
|
|
11769
11824
|
{
|
|
11770
11825
|
name: "swap_amend_algo_order",
|
|
11771
11826
|
module: "swap",
|
|
11772
|
-
description: "Amend a pending SWAP/FUTURES algo order (modify TP/SL prices or size). Also covers TP/SL orders attached when placing the main order
|
|
11827
|
+
description: "Amend a pending SWAP/FUTURES algo order (modify TP/SL prices or size). Also covers TP/SL orders attached when placing the main order - look up algoId via swap_get_algo_orders first.",
|
|
11773
11828
|
isWrite: true,
|
|
11774
11829
|
inputSchema: {
|
|
11775
11830
|
type: "object",
|
|
@@ -11911,9 +11966,9 @@ function readFullConfig() {
|
|
|
11911
11966
|
throw new ConfigError(
|
|
11912
11967
|
`Failed to parse ${path42}: ${err instanceof Error ? err.message : String(err)}`,
|
|
11913
11968
|
`If your passphrase or keys contain special characters:
|
|
11914
|
-
- Contains # \\ "
|
|
11915
|
-
- Contains '
|
|
11916
|
-
- Contains both
|
|
11969
|
+
- Contains # \\ " -> use single quotes: passphrase = 'your#pass'
|
|
11970
|
+
- Contains ' -> use double quotes: passphrase = "your'pass"
|
|
11971
|
+
- Contains both -> use triple quotes: passphrase = '''your'#pass'''
|
|
11917
11972
|
Or re-run: okx config init`
|
|
11918
11973
|
);
|
|
11919
11974
|
}
|
|
@@ -12056,6 +12111,9 @@ async function loadConfig(cli) {
|
|
|
12056
12111
|
}
|
|
12057
12112
|
var CACHE_FILE = join8(homedir6(), ".okx", "update-check.json");
|
|
12058
12113
|
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
12114
|
+
var NEGATIVE_CHECK_INTERVAL_MS = 60 * 60 * 1e3;
|
|
12115
|
+
var DEFAULT_REGISTRY = "https://registry.npmjs.org/";
|
|
12116
|
+
var FETCH_TIMEOUT_MS = 3e3;
|
|
12059
12117
|
function readCache2() {
|
|
12060
12118
|
try {
|
|
12061
12119
|
if (existsSync4(CACHE_FILE)) {
|
|
@@ -12072,7 +12130,73 @@ function writeCache2(cache) {
|
|
|
12072
12130
|
} catch {
|
|
12073
12131
|
}
|
|
12074
12132
|
}
|
|
12133
|
+
function resolveNpmRegistry() {
|
|
12134
|
+
const envRegistry = process.env.npm_config_registry;
|
|
12135
|
+
if (envRegistry) {
|
|
12136
|
+
return envRegistry.endsWith("/") ? envRegistry : `${envRegistry}/`;
|
|
12137
|
+
}
|
|
12138
|
+
for (const filePath of buildNpmrcCandidates()) {
|
|
12139
|
+
const registry = readNpmrcRegistry(filePath);
|
|
12140
|
+
if (registry) {
|
|
12141
|
+
return registry.endsWith("/") ? registry : `${registry}/`;
|
|
12142
|
+
}
|
|
12143
|
+
}
|
|
12144
|
+
return DEFAULT_REGISTRY;
|
|
12145
|
+
}
|
|
12146
|
+
function buildNpmrcCandidates() {
|
|
12147
|
+
const paths = [];
|
|
12148
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12149
|
+
const add = (p) => {
|
|
12150
|
+
if (!seen.has(p)) {
|
|
12151
|
+
seen.add(p);
|
|
12152
|
+
paths.push(p);
|
|
12153
|
+
}
|
|
12154
|
+
};
|
|
12155
|
+
let dir = process.cwd();
|
|
12156
|
+
const root = dir.startsWith("/") ? "/" : dir.slice(0, 3);
|
|
12157
|
+
while (true) {
|
|
12158
|
+
add(join8(dir, ".npmrc"));
|
|
12159
|
+
if (dir === root) break;
|
|
12160
|
+
const parent = join8(dir, "..");
|
|
12161
|
+
if (parent === dir) break;
|
|
12162
|
+
dir = parent;
|
|
12163
|
+
}
|
|
12164
|
+
add(join8(homedir6(), ".npmrc"));
|
|
12165
|
+
if (process.platform !== "win32") {
|
|
12166
|
+
add("/etc/npmrc");
|
|
12167
|
+
}
|
|
12168
|
+
return paths;
|
|
12169
|
+
}
|
|
12170
|
+
function readNpmrcRegistry(filePath) {
|
|
12171
|
+
try {
|
|
12172
|
+
if (!existsSync4(filePath)) return null;
|
|
12173
|
+
const lines = readFileSync5(filePath, "utf-8").split(/\r?\n/);
|
|
12174
|
+
for (const line of lines) {
|
|
12175
|
+
const trimmed = line.trim();
|
|
12176
|
+
if (trimmed.startsWith("#") || !trimmed.includes("=")) continue;
|
|
12177
|
+
const eqIdx = trimmed.indexOf("=");
|
|
12178
|
+
const key = trimmed.slice(0, eqIdx).trim();
|
|
12179
|
+
const value = trimmed.slice(eqIdx + 1).trim();
|
|
12180
|
+
if (key === "registry" && value) return value;
|
|
12181
|
+
}
|
|
12182
|
+
} catch {
|
|
12183
|
+
}
|
|
12184
|
+
return null;
|
|
12185
|
+
}
|
|
12186
|
+
async function fetchFromRegistry(packageName, suffix = "") {
|
|
12187
|
+
const registry = resolveNpmRegistry();
|
|
12188
|
+
const url = `${registry}${encodeURIComponent(packageName)}${suffix}`;
|
|
12189
|
+
try {
|
|
12190
|
+
return await fetch(url, {
|
|
12191
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
12192
|
+
headers: { accept: "application/json" }
|
|
12193
|
+
});
|
|
12194
|
+
} catch {
|
|
12195
|
+
return null;
|
|
12196
|
+
}
|
|
12197
|
+
}
|
|
12075
12198
|
function isNewerVersion(current, latest) {
|
|
12199
|
+
if (!latest) return false;
|
|
12076
12200
|
const parse2 = (v) => v.replace(/^v/, "").split(".").map((n) => parseInt(n, 10));
|
|
12077
12201
|
const [cMaj, cMin, cPat] = parse2(current);
|
|
12078
12202
|
const [lMaj, lMin, lPat] = parse2(latest);
|
|
@@ -12082,14 +12206,8 @@ function isNewerVersion(current, latest) {
|
|
|
12082
12206
|
}
|
|
12083
12207
|
async function fetchDistTags(packageName) {
|
|
12084
12208
|
try {
|
|
12085
|
-
const
|
|
12086
|
-
|
|
12087
|
-
const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}`, {
|
|
12088
|
-
signal: controller.signal,
|
|
12089
|
-
headers: { accept: "application/json" }
|
|
12090
|
-
});
|
|
12091
|
-
clearTimeout(timeout);
|
|
12092
|
-
if (!res.ok) return null;
|
|
12209
|
+
const res = await fetchFromRegistry(packageName);
|
|
12210
|
+
if (!res || !res.ok) return null;
|
|
12093
12211
|
const data = await res.json();
|
|
12094
12212
|
return data["dist-tags"] ?? null;
|
|
12095
12213
|
} catch {
|
|
@@ -12098,14 +12216,8 @@ async function fetchDistTags(packageName) {
|
|
|
12098
12216
|
}
|
|
12099
12217
|
async function fetchLatestVersion(packageName) {
|
|
12100
12218
|
try {
|
|
12101
|
-
const
|
|
12102
|
-
|
|
12103
|
-
const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`, {
|
|
12104
|
-
signal: controller.signal,
|
|
12105
|
-
headers: { accept: "application/json" }
|
|
12106
|
-
});
|
|
12107
|
-
clearTimeout(timeout);
|
|
12108
|
-
if (!res.ok) return null;
|
|
12219
|
+
const res = await fetchFromRegistry(packageName, "/latest");
|
|
12220
|
+
if (!res || !res.ok) return null;
|
|
12109
12221
|
const data = await res.json();
|
|
12110
12222
|
return data.version ?? null;
|
|
12111
12223
|
} catch {
|
|
@@ -12114,26 +12226,31 @@ async function fetchLatestVersion(packageName) {
|
|
|
12114
12226
|
}
|
|
12115
12227
|
function refreshCacheInBackground(packageName) {
|
|
12116
12228
|
fetchLatestVersion(packageName).then((latest) => {
|
|
12117
|
-
if (!latest) return;
|
|
12118
12229
|
const cache = readCache2();
|
|
12119
|
-
|
|
12230
|
+
if (latest) {
|
|
12231
|
+
cache[packageName] = { latestVersion: latest, checkedAt: Date.now() };
|
|
12232
|
+
} else {
|
|
12233
|
+
cache[packageName] = { latestVersion: null, checkedAt: Date.now(), failed: true };
|
|
12234
|
+
}
|
|
12120
12235
|
writeCache2(cache);
|
|
12121
12236
|
}).catch(() => {
|
|
12122
12237
|
});
|
|
12123
12238
|
}
|
|
12124
12239
|
function checkForUpdates(packageName, currentVersion) {
|
|
12240
|
+
if (process.env.OKX_UPDATE_CHECK === "false") return;
|
|
12125
12241
|
const cache = readCache2();
|
|
12126
12242
|
const entry = cache[packageName];
|
|
12127
|
-
if (entry && isNewerVersion(currentVersion, entry.latestVersion)) {
|
|
12243
|
+
if (entry && entry.latestVersion && isNewerVersion(currentVersion, entry.latestVersion)) {
|
|
12128
12244
|
process.stderr.write(
|
|
12129
12245
|
`
|
|
12130
|
-
Update available for ${packageName}: ${currentVersion}
|
|
12246
|
+
Update available for ${packageName}: ${currentVersion} -> ${entry.latestVersion}
|
|
12131
12247
|
Run: npm install -g ${packageName}
|
|
12132
12248
|
|
|
12133
12249
|
`
|
|
12134
12250
|
);
|
|
12135
12251
|
}
|
|
12136
|
-
|
|
12252
|
+
const ttl = entry?.failed ? NEGATIVE_CHECK_INTERVAL_MS : CHECK_INTERVAL_MS;
|
|
12253
|
+
if (!entry || Date.now() - entry.checkedAt > ttl) {
|
|
12137
12254
|
refreshCacheInBackground(packageName);
|
|
12138
12255
|
}
|
|
12139
12256
|
}
|
|
@@ -12318,7 +12435,7 @@ function mergeJsonConfig(configPath, serverName, entry) {
|
|
|
12318
12435
|
}
|
|
12319
12436
|
const backupPath = configPath + ".bak";
|
|
12320
12437
|
fs3.copyFileSync(configPath, backupPath);
|
|
12321
|
-
process.stdout.write(` Backup
|
|
12438
|
+
process.stdout.write(` Backup -> ${backupPath}
|
|
12322
12439
|
`);
|
|
12323
12440
|
}
|
|
12324
12441
|
if (typeof data.mcpServers !== "object" || data.mcpServers === null) {
|
|
@@ -12389,7 +12506,7 @@ function validateRedirect(res, requestUrl, redirectCount, maxRedirects) {
|
|
|
12389
12506
|
}
|
|
12390
12507
|
const location = res.headers.location;
|
|
12391
12508
|
if (requestUrl.startsWith("https") && !location.startsWith("https")) {
|
|
12392
|
-
throw new Error("Refused HTTPS
|
|
12509
|
+
throw new Error("Refused HTTPS -> HTTP redirect downgrade");
|
|
12393
12510
|
}
|
|
12394
12511
|
return location;
|
|
12395
12512
|
}
|
|
@@ -12987,10 +13104,10 @@ async function cmdAuthLogin(args) {
|
|
|
12987
13104
|
status: "skipped",
|
|
12988
13105
|
reason: "api_key_configured",
|
|
12989
13106
|
profile: apiKeyProfile,
|
|
12990
|
-
message: `API key already configured (profile: ${apiKeyProfile}). OAuth login skipped
|
|
13107
|
+
message: `API key already configured (profile: ${apiKeyProfile}). OAuth login skipped - API key will be used automatically.`
|
|
12991
13108
|
}));
|
|
12992
13109
|
} else {
|
|
12993
|
-
outputLine(`API key already configured (profile: ${apiKeyProfile}). OAuth login skipped
|
|
13110
|
+
outputLine(`API key already configured (profile: ${apiKeyProfile}). OAuth login skipped - API key will be used automatically.`);
|
|
12994
13111
|
}
|
|
12995
13112
|
return;
|
|
12996
13113
|
}
|
|
@@ -13509,7 +13626,7 @@ function checkToolCount(report, configuredClients, getSpecs = allToolSpecs) {
|
|
|
13509
13626
|
if (totalCount > limits.total) {
|
|
13510
13627
|
warn(
|
|
13511
13628
|
"tool count",
|
|
13512
|
-
`${totalCount} tools loaded
|
|
13629
|
+
`${totalCount} tools loaded - exceeds ${name} limit (${limits.total} total / ${limits.perServer} per server)`,
|
|
13513
13630
|
[
|
|
13514
13631
|
`Use --modules to reduce: okx-trade-mcp --modules ${defaultModulesArg} (${defaultCount} tools)`
|
|
13515
13632
|
]
|
|
@@ -13519,7 +13636,7 @@ function checkToolCount(report, configuredClients, getSpecs = allToolSpecs) {
|
|
|
13519
13636
|
} else if (totalCount > limits.perServer) {
|
|
13520
13637
|
warn(
|
|
13521
13638
|
"tool count",
|
|
13522
|
-
`${totalCount} tools loaded
|
|
13639
|
+
`${totalCount} tools loaded - exceeds ${name} per-server limit (${limits.perServer})`,
|
|
13523
13640
|
[
|
|
13524
13641
|
`Use --modules to reduce: okx-trade-mcp --modules ${defaultModulesArg} (${defaultCount} tools)`
|
|
13525
13642
|
]
|
|
@@ -13586,7 +13703,7 @@ function checkMcpLogs(report) {
|
|
|
13586
13703
|
} catch (_e) {
|
|
13587
13704
|
}
|
|
13588
13705
|
}
|
|
13589
|
-
ok("log file", "(not found
|
|
13706
|
+
ok("log file", "(not found - logs only appear after MCP server has been started)");
|
|
13590
13707
|
report.add("mcp_log", "not_found");
|
|
13591
13708
|
}
|
|
13592
13709
|
function parseHandshakeResponse(line) {
|
|
@@ -13662,7 +13779,7 @@ async function checkStdioHandshake(entryPath, report) {
|
|
|
13662
13779
|
const parsed = parseHandshakeResponse(line);
|
|
13663
13780
|
if (!parsed) continue;
|
|
13664
13781
|
if (parsed.ok) {
|
|
13665
|
-
ok("handshake", `OK
|
|
13782
|
+
ok("handshake", `OK - ${parsed.serverName} v${parsed.serverVer}`);
|
|
13666
13783
|
report.add("handshake", `OK ${parsed.serverName}@${parsed.serverVer}`);
|
|
13667
13784
|
} else {
|
|
13668
13785
|
fail("handshake", `JSON-RPC error: ${parsed.errMsg}`, [
|
|
@@ -13689,7 +13806,7 @@ async function checkStdioHandshake(entryPath, report) {
|
|
|
13689
13806
|
function checkModuleLoading(entryPath, report) {
|
|
13690
13807
|
section("Module Loading");
|
|
13691
13808
|
if (!entryPath) {
|
|
13692
|
-
ok("module load", "(skipped
|
|
13809
|
+
ok("module load", "(skipped - entry point not found)");
|
|
13693
13810
|
report.add("module_load", "skipped");
|
|
13694
13811
|
return true;
|
|
13695
13812
|
}
|
|
@@ -13732,7 +13849,7 @@ async function cmdDiagnoseMcp(options = {}) {
|
|
|
13732
13849
|
handshakePassed = await checkStdioHandshake(entryPath, report);
|
|
13733
13850
|
} else {
|
|
13734
13851
|
section("stdio Handshake");
|
|
13735
|
-
ok("handshake", "(skipped
|
|
13852
|
+
ok("handshake", "(skipped - entry point not available)");
|
|
13736
13853
|
report.add("handshake", "skipped");
|
|
13737
13854
|
handshakePassed = true;
|
|
13738
13855
|
}
|
|
@@ -13751,7 +13868,7 @@ async function cmdDiagnoseMcp(options = {}) {
|
|
|
13751
13868
|
|
|
13752
13869
|
// src/commands/diagnose.ts
|
|
13753
13870
|
var CLI_VERSION = readCliVersion();
|
|
13754
|
-
var GIT_HASH = true ? "
|
|
13871
|
+
var GIT_HASH = true ? "ce35abd7" : "dev";
|
|
13755
13872
|
function maskKey2(key) {
|
|
13756
13873
|
if (!key) return "(not set)";
|
|
13757
13874
|
if (key.length <= 8) return "****";
|
|
@@ -14008,13 +14125,13 @@ async function checkPilot(report) {
|
|
|
14008
14125
|
report.add("pilot_binary", `installed (${local.platform ?? "unknown"})`);
|
|
14009
14126
|
const cdnChecksum = await fetchCdnChecksum(void 0, 5e3);
|
|
14010
14127
|
if (!cdnChecksum) {
|
|
14011
|
-
warn("Pilot checksum", "CDN unreachable
|
|
14128
|
+
warn("Pilot checksum", "CDN unreachable - cannot verify");
|
|
14012
14129
|
report.add("pilot_checksum", "CDN unreachable");
|
|
14013
14130
|
} else if (cdnChecksum.sha256 === local.sha256) {
|
|
14014
14131
|
ok("Pilot checksum", `match (${cdnChecksum.source})`);
|
|
14015
14132
|
report.add("pilot_checksum", `match (${cdnChecksum.source})`);
|
|
14016
14133
|
} else {
|
|
14017
|
-
warn("Pilot checksum", "mismatch
|
|
14134
|
+
warn("Pilot checksum", "mismatch - update available", ["Run: okx pilot install"]);
|
|
14018
14135
|
report.add("pilot_checksum", "mismatch");
|
|
14019
14136
|
}
|
|
14020
14137
|
try {
|
|
@@ -14043,9 +14160,9 @@ function checkConfigFile(report) {
|
|
|
14043
14160
|
const msg = e instanceof Error ? e.message : String(e);
|
|
14044
14161
|
fail("Config parse", msg, [
|
|
14045
14162
|
`If passphrase contains special characters (# \\ " '), wrap in quotes:`,
|
|
14046
|
-
` Contains # \\ "
|
|
14047
|
-
` Contains '
|
|
14048
|
-
" Contains both
|
|
14163
|
+
` Contains # \\ " -> passphrase = 'value'`,
|
|
14164
|
+
` Contains ' -> passphrase = "value"`,
|
|
14165
|
+
" Contains both -> passphrase = '''value'''",
|
|
14049
14166
|
"Or re-run: okx config init"
|
|
14050
14167
|
]);
|
|
14051
14168
|
report.add("config_parse", `FAIL ${msg}`);
|
|
@@ -14144,13 +14261,13 @@ function printResult(result, json) {
|
|
|
14144
14261
|
break;
|
|
14145
14262
|
case "update-available":
|
|
14146
14263
|
process.stderr.write(
|
|
14147
|
-
`[info] Update available: ${result.currentVersion}
|
|
14264
|
+
`[info] Update available: ${result.currentVersion} -> ${result.latestVersion}
|
|
14148
14265
|
Run: okx upgrade
|
|
14149
14266
|
`
|
|
14150
14267
|
);
|
|
14151
14268
|
break;
|
|
14152
14269
|
case "updated":
|
|
14153
|
-
process.stderr.write(`[ok] Upgraded: ${result.currentVersion}
|
|
14270
|
+
process.stderr.write(`[ok] Upgraded: ${result.currentVersion} -> ${result.latestVersion}
|
|
14154
14271
|
`);
|
|
14155
14272
|
break;
|
|
14156
14273
|
case "error":
|
|
@@ -14327,6 +14444,11 @@ var CLI_REGISTRY = {
|
|
|
14327
14444
|
toolName: "market_filter_oi_change",
|
|
14328
14445
|
usage: "okx market oi-change --instType <SWAP|FUTURES> [--bar <5m|15m|1H|4H|1D>] [--sortBy <oiUsd|oiDeltaUsd|oiDeltaPct|absOiDeltaPct|volUsd24h|fundingRate|last>] [--sortOrder <asc|desc>] [--limit <1-100>] [--minOiUsd <n>] [--minVolUsd24h <n>] [--minAbsOiDeltaPct <n>]",
|
|
14329
14446
|
description: "Find instruments with largest OI changes over a bar window (accumulation/distribution scanner)"
|
|
14447
|
+
},
|
|
14448
|
+
"pair-spread": {
|
|
14449
|
+
toolName: "market_get_pair_spread",
|
|
14450
|
+
usage: "okx market pair-spread <instIdA> <instIdB> [--bar <5m|15m>] [--window <window>] [--backtest-time <ms>] [--json]",
|
|
14451
|
+
description: "Compute spread statistics (abs + ratio) between two instruments over a lookback window"
|
|
14330
14452
|
}
|
|
14331
14453
|
},
|
|
14332
14454
|
subgroups: {
|
|
@@ -14549,7 +14671,7 @@ var CLI_REGISTRY = {
|
|
|
14549
14671
|
leverage: {
|
|
14550
14672
|
toolName: "swap_set_leverage",
|
|
14551
14673
|
usage: "okx swap leverage --instId <id> --lever <positive-number> --mgnMode <cross|isolated> [--posSide <long|short>]",
|
|
14552
|
-
description: "Set leverage for a swap instrument. posSide is REQUIRED when mgnMode=isolated and account is in hedge mode
|
|
14674
|
+
description: "Set leverage for a swap instrument. posSide is REQUIRED when mgnMode=isolated and account is in hedge mode - must be set for BOTH long and short separately. Not supported for portfolio margin + cross."
|
|
14553
14675
|
},
|
|
14554
14676
|
"get-leverage": {
|
|
14555
14677
|
toolName: "swap_get_leverage",
|
|
@@ -14648,7 +14770,7 @@ var CLI_REGISTRY = {
|
|
|
14648
14770
|
leverage: {
|
|
14649
14771
|
toolName: "futures_set_leverage",
|
|
14650
14772
|
usage: "okx futures leverage --instId <id> --lever <positive-number> --mgnMode <cross|isolated> [--posSide <long|short>]",
|
|
14651
|
-
description: "Set leverage for a futures instrument. posSide is REQUIRED when mgnMode=isolated and account is in hedge mode
|
|
14773
|
+
description: "Set leverage for a futures instrument. posSide is REQUIRED when mgnMode=isolated and account is in hedge mode - must be set for BOTH long and short separately. Not supported for portfolio margin + cross."
|
|
14652
14774
|
},
|
|
14653
14775
|
batch: {
|
|
14654
14776
|
toolName: "futures_batch_orders",
|
|
@@ -14775,10 +14897,10 @@ var CLI_REGISTRY = {
|
|
|
14775
14897
|
},
|
|
14776
14898
|
// ── earn ───────────────────────────────────────────────────────────────────
|
|
14777
14899
|
earn: {
|
|
14778
|
-
description: "Earn products
|
|
14900
|
+
description: "Earn products - Simple Earn, On-chain Earn, DCD, Flash Earn, and Auto-Earn",
|
|
14779
14901
|
subgroups: {
|
|
14780
14902
|
savings: {
|
|
14781
|
-
description: "Simple Earn
|
|
14903
|
+
description: "Simple Earn - flexible savings, fixed-term, and lending",
|
|
14782
14904
|
commands: {
|
|
14783
14905
|
balance: {
|
|
14784
14906
|
toolName: "earn_get_savings_balance",
|
|
@@ -14828,7 +14950,7 @@ var CLI_REGISTRY = {
|
|
|
14828
14950
|
}
|
|
14829
14951
|
},
|
|
14830
14952
|
onchain: {
|
|
14831
|
-
description: "On-chain Earn
|
|
14953
|
+
description: "On-chain Earn - staking and DeFi products",
|
|
14832
14954
|
commands: {
|
|
14833
14955
|
offers: {
|
|
14834
14956
|
toolName: "onchain_earn_get_offers",
|
|
@@ -14863,7 +14985,7 @@ var CLI_REGISTRY = {
|
|
|
14863
14985
|
}
|
|
14864
14986
|
},
|
|
14865
14987
|
"auto-earn": {
|
|
14866
|
-
description: "Auto-earn
|
|
14988
|
+
description: "Auto-earn - automatically lend, stake, or earn on idle assets",
|
|
14867
14989
|
commands: {
|
|
14868
14990
|
status: {
|
|
14869
14991
|
// CLI reads from account_get_balance; earn_auto_set is covered by 'on' command below
|
|
@@ -14885,7 +15007,7 @@ var CLI_REGISTRY = {
|
|
|
14885
15007
|
}
|
|
14886
15008
|
},
|
|
14887
15009
|
"flash-earn": {
|
|
14888
|
-
description: "Flash Earn
|
|
15010
|
+
description: "Flash Earn - browse short-window earn projects by status",
|
|
14889
15011
|
commands: {
|
|
14890
15012
|
projects: {
|
|
14891
15013
|
toolName: "earn_get_flash_earn_projects",
|
|
@@ -14895,7 +15017,7 @@ var CLI_REGISTRY = {
|
|
|
14895
15017
|
}
|
|
14896
15018
|
},
|
|
14897
15019
|
dcd: {
|
|
14898
|
-
description: "DCD (Dual Currency Deposit)
|
|
15020
|
+
description: "DCD (Dual Currency Deposit) - structured products with fixed yield",
|
|
14899
15021
|
commands: {
|
|
14900
15022
|
pairs: {
|
|
14901
15023
|
toolName: "dcd_get_currency_pairs",
|
|
@@ -14936,7 +15058,7 @@ var CLI_REGISTRY = {
|
|
|
14936
15058
|
description: "Trading bot strategies (grid, dca)",
|
|
14937
15059
|
subgroups: {
|
|
14938
15060
|
grid: {
|
|
14939
|
-
description: "Grid trading bot
|
|
15061
|
+
description: "Grid trading bot - create, monitor, and stop grid orders",
|
|
14940
15062
|
commands: {
|
|
14941
15063
|
orders: {
|
|
14942
15064
|
toolName: "grid_get_orders",
|
|
@@ -14971,7 +15093,7 @@ var CLI_REGISTRY = {
|
|
|
14971
15093
|
}
|
|
14972
15094
|
},
|
|
14973
15095
|
dca: {
|
|
14974
|
-
description: "DCA (Martingale) bot
|
|
15096
|
+
description: "DCA (Martingale) bot - spot or contract recurring buys",
|
|
14975
15097
|
commands: {
|
|
14976
15098
|
orders: {
|
|
14977
15099
|
toolName: "dca_get_orders",
|
|
@@ -15004,7 +15126,7 @@ var CLI_REGISTRY = {
|
|
|
15004
15126
|
},
|
|
15005
15127
|
// ── event ──────────────────────────────────────────────────────────────────
|
|
15006
15128
|
event: {
|
|
15007
|
-
description: "Event contracts
|
|
15129
|
+
description: "Event contracts - binary prediction markets (YES/NO, UP/DOWN)",
|
|
15008
15130
|
commands: {
|
|
15009
15131
|
browse: {
|
|
15010
15132
|
toolName: "event_browse",
|
|
@@ -15055,7 +15177,7 @@ var CLI_REGISTRY = {
|
|
|
15055
15177
|
},
|
|
15056
15178
|
// ── smartmoney ─────────────────────────────────────────────────────────────
|
|
15057
15179
|
smartmoney: {
|
|
15058
|
-
description: "Smart money analytics
|
|
15180
|
+
description: "Smart money analytics - trader leaderboard, consensus signals, and position analysis",
|
|
15059
15181
|
commands: {
|
|
15060
15182
|
"traders-by-filter": {
|
|
15061
15183
|
toolName: "smartmoney_get_traders_by_filter",
|
|
@@ -15227,7 +15349,7 @@ var CLI_REGISTRY = {
|
|
|
15227
15349
|
},
|
|
15228
15350
|
// ── skill ──────────────────────────────────────────────────────────────────
|
|
15229
15351
|
skill: {
|
|
15230
|
-
description: "OKX Skills Marketplace
|
|
15352
|
+
description: "OKX Skills Marketplace - search, install, and manage agent skills",
|
|
15231
15353
|
commands: {
|
|
15232
15354
|
search: {
|
|
15233
15355
|
toolName: "skills_search",
|
|
@@ -15393,7 +15515,7 @@ function cmdListTools(json) {
|
|
|
15393
15515
|
}
|
|
15394
15516
|
const lines = [
|
|
15395
15517
|
"",
|
|
15396
|
-
`OKX CLI v${data.version}
|
|
15518
|
+
`OKX CLI v${data.version} - ${data.totalTools} tool-backed commands across ${data.modules.length} modules`,
|
|
15397
15519
|
"",
|
|
15398
15520
|
"Modules:"
|
|
15399
15521
|
];
|
|
@@ -15989,12 +16111,12 @@ var CLI_OPTIONS = {
|
|
|
15989
16111
|
instCcyList: { type: "string" },
|
|
15990
16112
|
topInstruments: { type: "string" },
|
|
15991
16113
|
asOfTime: { type: "string" },
|
|
15992
|
-
// smartmoney pool filters
|
|
16114
|
+
// smartmoney pool filters - leaderboard (numeric thresholds)
|
|
15993
16115
|
minPnl: { type: "string" },
|
|
15994
16116
|
minWinRate: { type: "string" },
|
|
15995
16117
|
maxDrawdown: { type: "string" },
|
|
15996
16118
|
minAum: { type: "string" },
|
|
15997
|
-
// smartmoney pool filters
|
|
16119
|
+
// smartmoney pool filters - signal endpoints (enum tiers)
|
|
15998
16120
|
pnlTier: { type: "string" },
|
|
15999
16121
|
winRateTier: { type: "string" },
|
|
16000
16122
|
maxDrawdownTier: { type: "string" },
|
|
@@ -16031,6 +16153,8 @@ var CLI_OPTIONS = {
|
|
|
16031
16153
|
params: { type: "string" },
|
|
16032
16154
|
list: { type: "boolean", default: false },
|
|
16033
16155
|
"backtest-time": { type: "string" },
|
|
16156
|
+
// pair-spread
|
|
16157
|
+
window: { type: "string" },
|
|
16034
16158
|
// news
|
|
16035
16159
|
coins: { type: "string" },
|
|
16036
16160
|
sentiment: { type: "string" },
|
|
@@ -16075,7 +16199,7 @@ var CLI_OPTIONS = {
|
|
|
16075
16199
|
settleCcy: { type: "string" },
|
|
16076
16200
|
ts: { type: "string" },
|
|
16077
16201
|
minAbsOiDeltaPct: { type: "string" },
|
|
16078
|
-
// diagnostics
|
|
16202
|
+
// diagnostics - cli/mcp/all/output are diagnose-specific; verbose is shared
|
|
16079
16203
|
verbose: { type: "boolean", default: false },
|
|
16080
16204
|
mcp: { type: "boolean", default: false },
|
|
16081
16205
|
// diagnose --mcp only: MCP server checks
|
|
@@ -16415,7 +16539,7 @@ async function cmdMarketInstrumentsByCategory(run, opts) {
|
|
|
16415
16539
|
"7": "Bonds"
|
|
16416
16540
|
};
|
|
16417
16541
|
const label = CATEGORY_LABELS[opts.instCategory] ?? opts.instCategory;
|
|
16418
|
-
process.stdout.write(`instCategory=${opts.instCategory} (${label})
|
|
16542
|
+
process.stdout.write(`instCategory=${opts.instCategory} (${label}) - ${items?.length ?? 0} instruments
|
|
16419
16543
|
|
|
16420
16544
|
`);
|
|
16421
16545
|
printTable(
|
|
@@ -16554,6 +16678,42 @@ async function cmdMarketOiChangeFilter(run, opts) {
|
|
|
16554
16678
|
}))
|
|
16555
16679
|
);
|
|
16556
16680
|
}
|
|
16681
|
+
async function cmdMarketPairSpread(run, instIdA, instIdB, opts) {
|
|
16682
|
+
const result = await run("market_get_pair_spread", {
|
|
16683
|
+
instIdA,
|
|
16684
|
+
instIdB,
|
|
16685
|
+
bar: opts.bar,
|
|
16686
|
+
window: opts.window,
|
|
16687
|
+
backtestTime: opts.backtestTime
|
|
16688
|
+
});
|
|
16689
|
+
const data = getData2(result);
|
|
16690
|
+
if (opts.json) return printJson(data);
|
|
16691
|
+
const bar = data?.["bar"] ?? "15m";
|
|
16692
|
+
const win = data?.["window"] ?? "1W";
|
|
16693
|
+
const mode = data?.["mode"] ?? "live";
|
|
16694
|
+
outputLine(`${instIdA} / ${instIdB} bar=${bar} window=${win} mode=${mode}`);
|
|
16695
|
+
const rt = data?.["realtime"];
|
|
16696
|
+
if (rt) {
|
|
16697
|
+
outputLine(`realtime lastA=${rt["lastPriceA"]} lastB=${rt["lastPriceB"]} abs=${rt["spreadAbs"]} ratio=${rt["spreadRatio"]}`);
|
|
16698
|
+
}
|
|
16699
|
+
const stats = data?.["statistics"];
|
|
16700
|
+
if (stats) {
|
|
16701
|
+
const abs = stats["absolute"];
|
|
16702
|
+
const ratio = stats["ratio"];
|
|
16703
|
+
const meta = data?.["meta"];
|
|
16704
|
+
outputLine(`samples count=${meta?.["alignedBars"] ?? "?"} start=${stats?.["windowStartTs"] ?? "?"} end=${stats?.["windowEndTs"] ?? "?"}`);
|
|
16705
|
+
printTable([
|
|
16706
|
+
{ stat: "mean", absolute: abs?.["mean"], ratio: ratio?.["mean"] },
|
|
16707
|
+
{ stat: "stdDev", absolute: abs?.["stdDev"], ratio: ratio?.["stdDev"] },
|
|
16708
|
+
{ stat: "median", absolute: abs?.["median"], ratio: ratio?.["median"] },
|
|
16709
|
+
{ stat: "min", absolute: abs?.["min"], ratio: ratio?.["min"] },
|
|
16710
|
+
{ stat: "max", absolute: abs?.["max"], ratio: ratio?.["max"] }
|
|
16711
|
+
]);
|
|
16712
|
+
if (meta) {
|
|
16713
|
+
outputLine(`meta requested=${meta["requestedBars"]} aligned=${meta["alignedBars"]} dropped=${meta["droppedBars"]} truncated=${meta["truncated"]}`);
|
|
16714
|
+
}
|
|
16715
|
+
}
|
|
16716
|
+
}
|
|
16557
16717
|
|
|
16558
16718
|
// src/commands/account.ts
|
|
16559
16719
|
import * as fs7 from "fs";
|
|
@@ -18018,7 +18178,7 @@ import { createInterface } from "readline";
|
|
|
18018
18178
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
18019
18179
|
var messages = {
|
|
18020
18180
|
en: {
|
|
18021
|
-
title: "OKX Trade CLI
|
|
18181
|
+
title: "OKX Trade CLI - Configuration Wizard",
|
|
18022
18182
|
selectSite: "Select site:",
|
|
18023
18183
|
sitePrompt: "Site (1/2/3, default: 1): ",
|
|
18024
18184
|
demoPrompt: "Use demo trading? (Y/n) ",
|
|
@@ -18052,7 +18212,7 @@ Config saved to ${p}
|
|
|
18052
18212
|
`
|
|
18053
18213
|
},
|
|
18054
18214
|
zh: {
|
|
18055
|
-
title: "OKX Trade CLI
|
|
18215
|
+
title: "OKX Trade CLI - \u914D\u7F6E\u5411\u5BFC",
|
|
18056
18216
|
selectSite: "\u8BF7\u9009\u62E9\u7AD9\u70B9:",
|
|
18057
18217
|
sitePrompt: "\u7AD9\u70B9 (1/2/3, \u9ED8\u8BA4: 1): ",
|
|
18058
18218
|
demoPrompt: "\u4F7F\u7528\u6A21\u62DF\u76D8\uFF1F(Y/n) ",
|
|
@@ -18399,7 +18559,7 @@ async function cmdEarnSetLendingRate(run, opts) {
|
|
|
18399
18559
|
return;
|
|
18400
18560
|
}
|
|
18401
18561
|
const r = data[0];
|
|
18402
|
-
outputLine(`Lending rate set: ${r?.["ccy"]}
|
|
18562
|
+
outputLine(`Lending rate set: ${r?.["ccy"]} -> ${r?.["rate"]}`);
|
|
18403
18563
|
}
|
|
18404
18564
|
async function cmdEarnLendingHistory(run, opts) {
|
|
18405
18565
|
const data = extractData(await run("earn_get_lending_history", { ccy: opts.ccy, limit: opts.limit }));
|
|
@@ -18534,7 +18694,7 @@ function printPaginationHint(result) {
|
|
|
18534
18694
|
const { hasMore, nextAfter } = pagination;
|
|
18535
18695
|
if (hasMore !== true) return;
|
|
18536
18696
|
const cursor = typeof nextAfter === "string" || typeof nextAfter === "number" ? String(nextAfter) : "";
|
|
18537
|
-
errorLine(cursor ? `more results
|
|
18697
|
+
errorLine(cursor ? `more results - pass --after ${cursor} for next page` : "more results - pass --after <cursor> for next page");
|
|
18538
18698
|
}
|
|
18539
18699
|
function signalPoolFilterArgs(o) {
|
|
18540
18700
|
const result = {};
|
|
@@ -19349,8 +19509,8 @@ async function cmdDcdProducts(run, opts) {
|
|
|
19349
19509
|
quoteCcy: r["quoteCcy"],
|
|
19350
19510
|
optType: r["optType"],
|
|
19351
19511
|
strike: r["strike"],
|
|
19352
|
-
// products endpoint returns decimal (e.g. 0.3423 = 34.23%)
|
|
19353
|
-
annualizedYield: r["annualizedYield"] ? `${(parseFloat(r["annualizedYield"]) * 100).toFixed(2)}%` : "
|
|
19512
|
+
// products endpoint returns decimal (e.g. 0.3423 = 34.23%) - multiply by 100
|
|
19513
|
+
annualizedYield: r["annualizedYield"] ? `${(parseFloat(r["annualizedYield"]) * 100).toFixed(2)}%` : "-",
|
|
19354
19514
|
minSize: r["minSize"],
|
|
19355
19515
|
expTime: r["expTime"] ? new Date(Number(r["expTime"])).toLocaleDateString() : ""
|
|
19356
19516
|
})));
|
|
@@ -19380,8 +19540,8 @@ async function cmdDcdRedeemExecute(run, opts) {
|
|
|
19380
19540
|
printKv({
|
|
19381
19541
|
ordId: r["ordId"],
|
|
19382
19542
|
state: r["state"],
|
|
19383
|
-
redeemSz: q["redeemSz"] ? `${parseFloat(q["redeemSz"]).toFixed(8)} ${q["redeemCcy"]}` : "
|
|
19384
|
-
termRate: q["termRate"] ? `${(parseFloat(q["termRate"]) * 100).toFixed(2)}%` : "
|
|
19543
|
+
redeemSz: q["redeemSz"] ? `${parseFloat(q["redeemSz"]).toFixed(8)} ${q["redeemCcy"]}` : "-",
|
|
19544
|
+
termRate: q["termRate"] ? `${(parseFloat(q["termRate"]) * 100).toFixed(2)}%` : "-"
|
|
19385
19545
|
});
|
|
19386
19546
|
}
|
|
19387
19547
|
async function cmdDcdOrderState(run, opts) {
|
|
@@ -19434,7 +19594,7 @@ async function cmdDcdOrders(run, opts) {
|
|
|
19434
19594
|
quoteCcy: r["quoteCcy"],
|
|
19435
19595
|
strike: r["strike"],
|
|
19436
19596
|
notionalSz: r["notionalSz"],
|
|
19437
|
-
annualizedYield: r["annualizedYield"] ? `${(parseFloat(r["annualizedYield"]) * 100).toFixed(2)}%` : "
|
|
19597
|
+
annualizedYield: r["annualizedYield"] ? `${(parseFloat(r["annualizedYield"]) * 100).toFixed(2)}%` : "-",
|
|
19438
19598
|
yieldSz: r["yieldSz"],
|
|
19439
19599
|
settleTime: r["settleTime"] ? new Date(Number(r["settleTime"])).toLocaleDateString() : "",
|
|
19440
19600
|
// scheduled settlement time
|
|
@@ -19474,7 +19634,7 @@ async function cmdDcdQuoteAndBuy(run, opts) {
|
|
|
19474
19634
|
outputLine("Quote:");
|
|
19475
19635
|
printKv({
|
|
19476
19636
|
quoteId: q["quoteId"],
|
|
19477
|
-
annualizedYield: q["annualizedYield"] ? `${(parseFloat(q["annualizedYield"]) * 100).toFixed(2)}%` : "
|
|
19637
|
+
annualizedYield: q["annualizedYield"] ? `${(parseFloat(q["annualizedYield"]) * 100).toFixed(2)}%` : "-",
|
|
19478
19638
|
absYield: q["absYield"],
|
|
19479
19639
|
notionalSz: q["notionalSz"],
|
|
19480
19640
|
notionalCcy: q["notionalCcy"]
|
|
@@ -19649,9 +19809,9 @@ async function cmdSkillCheck(run, name, json) {
|
|
|
19649
19809
|
upToDate
|
|
19650
19810
|
}, null, 2));
|
|
19651
19811
|
} else if (upToDate) {
|
|
19652
|
-
outputLine(`${name}: installed v${local.version}
|
|
19812
|
+
outputLine(`${name}: installed v${local.version} -> latest v${remote.latestVersion} (up to date)`);
|
|
19653
19813
|
} else {
|
|
19654
|
-
outputLine(`${name}: installed v${local.version}
|
|
19814
|
+
outputLine(`${name}: installed v${local.version} -> latest v${remote.latestVersion} (update available)`);
|
|
19655
19815
|
outputLine(` Use \`okx skill add ${name}\` to update.`);
|
|
19656
19816
|
}
|
|
19657
19817
|
}
|
|
@@ -19928,9 +20088,9 @@ async function cmdEventBrowse(run, opts) {
|
|
|
19928
20088
|
contracts.map((c) => ({
|
|
19929
20089
|
"Contract": formatDisplayTitle(String(c["instId"] ?? "")),
|
|
19930
20090
|
"Expiry": c["expTime"] ?? "",
|
|
19931
|
-
"Target Price": c["floorStrike"] ? String(c["floorStrike"]) : "
|
|
20091
|
+
"Target Price": c["floorStrike"] ? String(c["floorStrike"]) : "-",
|
|
19932
20092
|
"Probability": fmtProbability(c["px"]),
|
|
19933
|
-
"Outcome": fmtOutcome(c["outcome"]) || "
|
|
20093
|
+
"Outcome": fmtOutcome(c["outcome"]) || "-",
|
|
19934
20094
|
"instId": c["instId"]
|
|
19935
20095
|
}))
|
|
19936
20096
|
);
|
|
@@ -20067,7 +20227,7 @@ async function cmdEventMarkets(run, opts) {
|
|
|
20067
20227
|
expTime: m["expTime"] ?? "",
|
|
20068
20228
|
targetPrice: m["floorStrike"] ?? "",
|
|
20069
20229
|
probability: fmtProbability(m["px"]),
|
|
20070
|
-
outcome: outcome.toLowerCase() === "pending" ? "
|
|
20230
|
+
outcome: outcome.toLowerCase() === "pending" ? "-" : outcome,
|
|
20071
20231
|
settleValue: m["settleValue"] ?? "",
|
|
20072
20232
|
instId: id
|
|
20073
20233
|
};
|
|
@@ -20120,7 +20280,7 @@ async function cmdEventFills(run, opts) {
|
|
|
20120
20280
|
const side = String(f["side"] ?? "").toUpperCase();
|
|
20121
20281
|
const outcome = fmtOrderOutcome(f["instId"], f["outcome"]).toUpperCase();
|
|
20122
20282
|
const dir = `${side} ${outcome}`.trim();
|
|
20123
|
-
return dir || "
|
|
20283
|
+
return dir || "-";
|
|
20124
20284
|
})(),
|
|
20125
20285
|
"Fill Price": f["fillPx"],
|
|
20126
20286
|
"Fill Size": f["fillSz"],
|
|
@@ -20222,7 +20382,7 @@ async function cmdEventPlace(run, opts) {
|
|
|
20222
20382
|
const data = getData9(result);
|
|
20223
20383
|
if (opts.json) return printJson(data);
|
|
20224
20384
|
const order = data?.[0];
|
|
20225
|
-
const stateHint = ordType === "market" ? "market order
|
|
20385
|
+
const stateHint = ordType === "market" ? "market order - typically fills immediately" : `${ordType} order - may still be live; verify with: okx event orders --instId ${opts.instId} --state live`;
|
|
20226
20386
|
const period = fmtPeriodFromInstId(opts.instId);
|
|
20227
20387
|
const pxPart = opts.px ? ` px: ${opts.px}` : "";
|
|
20228
20388
|
process.stdout.write(
|
|
@@ -20268,7 +20428,7 @@ function handleCancelCatchError(instId, ordId, err) {
|
|
|
20268
20428
|
if (isExpired) {
|
|
20269
20429
|
process.stdout.write(
|
|
20270
20430
|
`Cannot cancel: contract ${instId} has already expired.
|
|
20271
|
-
The order was auto-cancelled at settlement
|
|
20431
|
+
The order was auto-cancelled at settlement - no action needed.
|
|
20272
20432
|
`
|
|
20273
20433
|
);
|
|
20274
20434
|
} else {
|
|
@@ -20297,7 +20457,7 @@ async function cmdEventCancel(run, opts) {
|
|
|
20297
20457
|
// src/index.ts
|
|
20298
20458
|
var _require3 = createRequire3(import.meta.url);
|
|
20299
20459
|
var CLI_VERSION2 = _require3("../package.json").version;
|
|
20300
|
-
var GIT_HASH2 = true ? "
|
|
20460
|
+
var GIT_HASH2 = true ? "ce35abd7" : "dev";
|
|
20301
20461
|
function handlePilotCommand(action, json, force, binaryPath) {
|
|
20302
20462
|
if (action === "status") return cmdPilotStatus(json, binaryPath);
|
|
20303
20463
|
if (action === "install") return cmdPilotInstall(json, binaryPath);
|
|
@@ -20402,6 +20562,15 @@ function handleMarketFilterCommand(run, action, rest, v, json) {
|
|
|
20402
20562
|
limit,
|
|
20403
20563
|
json
|
|
20404
20564
|
});
|
|
20565
|
+
if (action === "pair-spread") {
|
|
20566
|
+
const backtestTime = v["backtest-time"] !== void 0 ? Number(v["backtest-time"]) : void 0;
|
|
20567
|
+
return cmdMarketPairSpread(run, rest[0], rest[1], {
|
|
20568
|
+
bar: v.bar,
|
|
20569
|
+
window: v.window,
|
|
20570
|
+
backtestTime,
|
|
20571
|
+
json
|
|
20572
|
+
});
|
|
20573
|
+
}
|
|
20405
20574
|
}
|
|
20406
20575
|
function handleIndicatorAction(run, rest, v, json) {
|
|
20407
20576
|
if (rest[0] === "list") return cmdMarketIndicatorList(json);
|
|
@@ -20450,7 +20619,8 @@ function handleMarketCommand(run, action, rest, v, json) {
|
|
|
20450
20619
|
"filter",
|
|
20451
20620
|
"oi-history",
|
|
20452
20621
|
"oi-change",
|
|
20453
|
-
"index-candles"
|
|
20622
|
+
"index-candles",
|
|
20623
|
+
"pair-spread"
|
|
20454
20624
|
]);
|
|
20455
20625
|
}
|
|
20456
20626
|
function handleAccountWriteCommand(run, action, v, json) {
|
|
@@ -20599,7 +20769,7 @@ function assertNoTpConflict(tpLevel, singleFields) {
|
|
|
20599
20769
|
if (conflicting.length > 0) {
|
|
20600
20770
|
const flagNames = conflicting.map((k) => `--${k}`).join(", ");
|
|
20601
20771
|
throw new Error(
|
|
20602
|
-
`Cannot use --tpLevel together with ${flagNames}. Use --tpLevel for split multi-tier take-profit, or single-TP flags for a single TP
|
|
20772
|
+
`Cannot use --tpLevel together with ${flagNames}. Use --tpLevel for split multi-tier take-profit, or single-TP flags for a single TP - not both.`
|
|
20603
20773
|
);
|
|
20604
20774
|
}
|
|
20605
20775
|
}
|
|
@@ -21396,7 +21566,7 @@ function handleSmartmoneyCommand(run, action, rest, v, json) {
|
|
|
21396
21566
|
if (action === "signal-overview-by-filter") {
|
|
21397
21567
|
if (v.topInstruments && v.instCcyList) {
|
|
21398
21568
|
errorLine(
|
|
21399
|
-
"--topInstruments and --instCcyList are mutually exclusive. Pass exactly one
|
|
21569
|
+
"--topInstruments and --instCcyList are mutually exclusive. Pass exactly one - `--topInstruments` for top-N hottest coins, or `--instCcyList` for specific coins."
|
|
21400
21570
|
);
|
|
21401
21571
|
process.exitCode = 1;
|
|
21402
21572
|
return;
|
|
@@ -21417,7 +21587,7 @@ function handleSmartmoneyCommand(run, action, rest, v, json) {
|
|
|
21417
21587
|
}
|
|
21418
21588
|
if (v.topInstruments && v.instCcyList) {
|
|
21419
21589
|
errorLine(
|
|
21420
|
-
"--topInstruments and --instCcyList are mutually exclusive. Pass exactly one
|
|
21590
|
+
"--topInstruments and --instCcyList are mutually exclusive. Pass exactly one - `--topInstruments` for top-N hottest coins, or `--instCcyList` for specific coins."
|
|
21421
21591
|
);
|
|
21422
21592
|
process.exitCode = 1;
|
|
21423
21593
|
return;
|