@okx_ai/okx-trade-cli 1.3.8-beta.1 → 1.3.8-beta.4
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/LICENSE +21 -0
- package/dist/index.js +433 -1231
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
- package/scripts/postinstall-download.js +152 -0
package/dist/index.js
CHANGED
|
@@ -2650,7 +2650,6 @@ var MODULES = [
|
|
|
2650
2650
|
"event",
|
|
2651
2651
|
"news",
|
|
2652
2652
|
"smartmoney",
|
|
2653
|
-
"outcomes",
|
|
2654
2653
|
...EARN_SUB_MODULE_IDS,
|
|
2655
2654
|
...BOT_SUB_MODULE_IDS,
|
|
2656
2655
|
"skills"
|
|
@@ -2674,7 +2673,6 @@ var MODULE_DESCRIPTIONS = {
|
|
|
2674
2673
|
"bot.dca": "DCA (Martingale) bot - spot or contract recurring buys",
|
|
2675
2674
|
news: "Crypto news, sentiment analysis, and coin trend tracking",
|
|
2676
2675
|
smartmoney: "Smart money signals - trader leaderboard, consensus signals, and position analysis",
|
|
2677
|
-
outcomes: "Prediction markets - binary YES/NO event contracts (browse, search, CLOB, account)",
|
|
2678
2676
|
skills: SKILLS_MARKETPLACE_DESC,
|
|
2679
2677
|
earn: "Earn products - Simple Earn, On-chain Earn, DCD, Flash Earn, and Auto-Earn",
|
|
2680
2678
|
bot: "Trading bot strategies (grid, dca)",
|
|
@@ -2685,6 +2683,203 @@ var MODULE_DESCRIPTIONS = {
|
|
|
2685
2683
|
upgrade: "Upgrade okx CLI and MCP server to the latest stable version",
|
|
2686
2684
|
skill: SKILLS_MARKETPLACE_DESC
|
|
2687
2685
|
};
|
|
2686
|
+
var AGGREGATE_ENDPOINT = "/api/v5/aigc/forward/balance-aggregate";
|
|
2687
|
+
var TRADING_ENDPOINT = "/api/v5/account/balance";
|
|
2688
|
+
var FUNDING_ENDPOINT = "/api/v5/asset/balances";
|
|
2689
|
+
var VALUATION_ENDPOINT = "/api/v5/asset/asset-valuation";
|
|
2690
|
+
function parseParams(rawArgs) {
|
|
2691
|
+
const args = asRecord(rawArgs);
|
|
2692
|
+
const accounts = readString(args, "accounts") ?? "trading,funding";
|
|
2693
|
+
return {
|
|
2694
|
+
ccy: readString(args, "ccy"),
|
|
2695
|
+
accounts,
|
|
2696
|
+
requestedAccounts: accounts.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean),
|
|
2697
|
+
showValuation: readBoolean(args, "showValuation") ?? true,
|
|
2698
|
+
valuationCcy: readString(args, "valuationCcy") ?? "USDT",
|
|
2699
|
+
preferParallel: readBoolean(args, "preferParallel") ?? false
|
|
2700
|
+
};
|
|
2701
|
+
}
|
|
2702
|
+
function normalizeSubError(error) {
|
|
2703
|
+
if (!error || typeof error !== "object") {
|
|
2704
|
+
return void 0;
|
|
2705
|
+
}
|
|
2706
|
+
const e = error;
|
|
2707
|
+
return {
|
|
2708
|
+
code: e["code"] === void 0 || e["code"] === null ? "UNKNOWN" : String(e["code"]),
|
|
2709
|
+
msg: typeof e["msg"] === "string" ? e["msg"] : String(e["msg"] ?? "")
|
|
2710
|
+
};
|
|
2711
|
+
}
|
|
2712
|
+
function toIsoTimestamp(value, fallbackMs) {
|
|
2713
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2714
|
+
return new Date(value).toISOString();
|
|
2715
|
+
}
|
|
2716
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
2717
|
+
return value;
|
|
2718
|
+
}
|
|
2719
|
+
return new Date(fallbackMs).toISOString();
|
|
2720
|
+
}
|
|
2721
|
+
function normalizeAggregate(agg, params, startTime) {
|
|
2722
|
+
const result = {};
|
|
2723
|
+
const trading = agg["trading"];
|
|
2724
|
+
if (trading) {
|
|
2725
|
+
result.trading = compactObject({
|
|
2726
|
+
available: trading["available"] ?? false,
|
|
2727
|
+
totalEq: trading["totalEq"],
|
|
2728
|
+
adjEq: trading["adjEq"],
|
|
2729
|
+
details: Array.isArray(trading["details"]) ? trading["details"] : [],
|
|
2730
|
+
error: normalizeSubError(trading["error"])
|
|
2731
|
+
});
|
|
2732
|
+
}
|
|
2733
|
+
const funding = agg["funding"];
|
|
2734
|
+
if (funding) {
|
|
2735
|
+
result.funding = compactObject({
|
|
2736
|
+
available: funding["available"] ?? false,
|
|
2737
|
+
details: Array.isArray(funding["details"]) ? funding["details"] : [],
|
|
2738
|
+
error: normalizeSubError(funding["error"])
|
|
2739
|
+
});
|
|
2740
|
+
}
|
|
2741
|
+
const valuation = agg["valuation"];
|
|
2742
|
+
if (valuation) {
|
|
2743
|
+
result.valuation = compactObject({
|
|
2744
|
+
available: valuation["available"] ?? false,
|
|
2745
|
+
valuationCcy: valuation["valuationCcy"] ?? params.valuationCcy,
|
|
2746
|
+
totalBal: valuation["totalBal"] ?? "0",
|
|
2747
|
+
details: Array.isArray(valuation["details"]) ? valuation["details"] : [],
|
|
2748
|
+
error: normalizeSubError(valuation["error"])
|
|
2749
|
+
});
|
|
2750
|
+
}
|
|
2751
|
+
const meta = agg["meta"] ?? {};
|
|
2752
|
+
result.meta = compactObject({
|
|
2753
|
+
requestedAt: toIsoTimestamp(meta["requestedAt"], startTime),
|
|
2754
|
+
elapsedMs: typeof meta["elapsedMs"] === "number" ? meta["elapsedMs"] : Date.now() - startTime,
|
|
2755
|
+
partialFailure: Boolean(meta["partialFailure"]),
|
|
2756
|
+
site: typeof meta["site"] === "string" ? meta["site"] : void 0,
|
|
2757
|
+
source: "aggregate"
|
|
2758
|
+
});
|
|
2759
|
+
return result;
|
|
2760
|
+
}
|
|
2761
|
+
async function queryAggregate(context, params, startTime) {
|
|
2762
|
+
const resp = await context.client.privateGet(
|
|
2763
|
+
AGGREGATE_ENDPOINT,
|
|
2764
|
+
compactObject({
|
|
2765
|
+
ccy: params.ccy,
|
|
2766
|
+
accounts: params.accounts,
|
|
2767
|
+
showValuation: params.showValuation,
|
|
2768
|
+
valuationCcy: params.valuationCcy
|
|
2769
|
+
}),
|
|
2770
|
+
privateRateLimit("account_get_balance_all", 5)
|
|
2771
|
+
);
|
|
2772
|
+
const data = resp.data;
|
|
2773
|
+
const agg = Array.isArray(data) ? data[0] : void 0;
|
|
2774
|
+
if (!agg || agg["trading"] === void 0 && agg["funding"] === void 0) {
|
|
2775
|
+
throw new OkxApiError("Aggregate endpoint returned no usable data", {
|
|
2776
|
+
code: "AGG_EMPTY",
|
|
2777
|
+
endpoint: `GET ${AGGREGATE_ENDPOINT}`
|
|
2778
|
+
});
|
|
2779
|
+
}
|
|
2780
|
+
return normalizeAggregate(agg, params, startTime);
|
|
2781
|
+
}
|
|
2782
|
+
var REQUESTED_KEYS = /* @__PURE__ */ new Set(["trading", "funding"]);
|
|
2783
|
+
function buildBalanceTasks(context, params) {
|
|
2784
|
+
const { ccy, requestedAccounts, showValuation, valuationCcy } = params;
|
|
2785
|
+
const tasks = [];
|
|
2786
|
+
if (requestedAccounts.includes("trading")) {
|
|
2787
|
+
tasks.push({
|
|
2788
|
+
key: "trading",
|
|
2789
|
+
run: () => context.client.privateGet(TRADING_ENDPOINT, compactObject({ ccy }), privateRateLimit("account_get_balance", 10)).then((resp) => resp.data)
|
|
2790
|
+
});
|
|
2791
|
+
}
|
|
2792
|
+
if (requestedAccounts.includes("funding")) {
|
|
2793
|
+
tasks.push({
|
|
2794
|
+
key: "funding",
|
|
2795
|
+
run: () => context.client.privateGet(FUNDING_ENDPOINT, compactObject({ ccy }), privateRateLimit("account_get_asset_balance", 6)).then((resp) => resp.data)
|
|
2796
|
+
});
|
|
2797
|
+
}
|
|
2798
|
+
if (showValuation) {
|
|
2799
|
+
tasks.push({
|
|
2800
|
+
key: "valuation",
|
|
2801
|
+
run: () => context.client.privateGet(VALUATION_ENDPOINT, { ccy: valuationCcy }, privateRateLimit("account_get_asset_valuation", 1)).then((resp) => resp.data)
|
|
2802
|
+
});
|
|
2803
|
+
}
|
|
2804
|
+
return tasks;
|
|
2805
|
+
}
|
|
2806
|
+
async function settleBalanceTasks(tasks) {
|
|
2807
|
+
return Promise.all(
|
|
2808
|
+
tasks.map(async (task) => {
|
|
2809
|
+
try {
|
|
2810
|
+
return { key: task.key, data: await task.run() };
|
|
2811
|
+
} catch (error) {
|
|
2812
|
+
return { key: task.key, error };
|
|
2813
|
+
}
|
|
2814
|
+
})
|
|
2815
|
+
);
|
|
2816
|
+
}
|
|
2817
|
+
function buildSuccessSection(key, data, valuationCcy) {
|
|
2818
|
+
const rows = Array.isArray(data) ? data : [];
|
|
2819
|
+
const first = rows[0];
|
|
2820
|
+
if (key === "funding") {
|
|
2821
|
+
return { available: true, details: rows };
|
|
2822
|
+
}
|
|
2823
|
+
if (key === "valuation") {
|
|
2824
|
+
return { available: true, valuationCcy, totalBal: first?.["totalBal"] ?? "0", details: rows };
|
|
2825
|
+
}
|
|
2826
|
+
return {
|
|
2827
|
+
available: true,
|
|
2828
|
+
totalEq: first?.["totalEq"] ?? "0",
|
|
2829
|
+
adjEq: first?.["adjEq"] ?? "0",
|
|
2830
|
+
details: first && Array.isArray(first["details"]) ? first["details"] : []
|
|
2831
|
+
};
|
|
2832
|
+
}
|
|
2833
|
+
function buildErrorSection(error) {
|
|
2834
|
+
return {
|
|
2835
|
+
available: false,
|
|
2836
|
+
error: {
|
|
2837
|
+
code: error instanceof OkxApiError ? error.code ?? "UNKNOWN" : "UNKNOWN",
|
|
2838
|
+
msg: error.message
|
|
2839
|
+
}
|
|
2840
|
+
};
|
|
2841
|
+
}
|
|
2842
|
+
async function queryParallel(context, params, startTime) {
|
|
2843
|
+
const tasks = buildBalanceTasks(context, params);
|
|
2844
|
+
const outcomes = await settleBalanceTasks(tasks);
|
|
2845
|
+
const authFailure = outcomes.find((o) => o.error instanceof AuthenticationError);
|
|
2846
|
+
if (authFailure?.error) {
|
|
2847
|
+
throw authFailure.error;
|
|
2848
|
+
}
|
|
2849
|
+
const result = {};
|
|
2850
|
+
for (const outcome of outcomes) {
|
|
2851
|
+
result[outcome.key] = outcome.error ? buildErrorSection(outcome.error) : buildSuccessSection(outcome.key, outcome.data, params.valuationCcy);
|
|
2852
|
+
}
|
|
2853
|
+
const requestedCount = tasks.filter((t) => REQUESTED_KEYS.has(t.key)).length;
|
|
2854
|
+
const requestedFailures = outcomes.filter((o) => o.error && REQUESTED_KEYS.has(o.key)).length;
|
|
2855
|
+
if (requestedCount > 0 && requestedFailures >= requestedCount) {
|
|
2856
|
+
throw new OkxApiError("Both balance queries failed", { code: "-30001" });
|
|
2857
|
+
}
|
|
2858
|
+
const site = typeof context.config?.site === "string" ? context.config.site : void 0;
|
|
2859
|
+
result.meta = compactObject({
|
|
2860
|
+
requestedAt: new Date(startTime).toISOString(),
|
|
2861
|
+
elapsedMs: Date.now() - startTime,
|
|
2862
|
+
partialFailure: requestedFailures > 0,
|
|
2863
|
+
site,
|
|
2864
|
+
source: "fallback"
|
|
2865
|
+
});
|
|
2866
|
+
return result;
|
|
2867
|
+
}
|
|
2868
|
+
async function buildBalanceAll(rawArgs, context) {
|
|
2869
|
+
const params = parseParams(rawArgs);
|
|
2870
|
+
const startTime = Date.now();
|
|
2871
|
+
if (params.preferParallel) {
|
|
2872
|
+
return queryParallel(context, params, startTime);
|
|
2873
|
+
}
|
|
2874
|
+
try {
|
|
2875
|
+
return await queryAggregate(context, params, startTime);
|
|
2876
|
+
} catch (error) {
|
|
2877
|
+
if (error instanceof AuthenticationError) {
|
|
2878
|
+
throw error;
|
|
2879
|
+
}
|
|
2880
|
+
return queryParallel(context, params, startTime);
|
|
2881
|
+
}
|
|
2882
|
+
}
|
|
2688
2883
|
function registerAccountTools() {
|
|
2689
2884
|
return [
|
|
2690
2885
|
{
|
|
@@ -3264,6 +3459,39 @@ function registerAccountTools() {
|
|
|
3264
3459
|
);
|
|
3265
3460
|
return normalizeResponse(response);
|
|
3266
3461
|
}
|
|
3462
|
+
},
|
|
3463
|
+
{
|
|
3464
|
+
name: "account_get_balance_all",
|
|
3465
|
+
title: "Get Aggregate Balance Snapshot",
|
|
3466
|
+
module: "account",
|
|
3467
|
+
description: "One-shot snapshot of all OKX assets: trading-account equity + funding-account balances + optional cross-account valuation. Use when the user asks for total assets / net worth / \u603B\u8D44\u4EA7 / all balances. Prefer this over calling account_get_balance + account_get_asset_balance separately. Returns {trading, funding, valuation, meta} with per-section error so partial failures don't block the rest.",
|
|
3468
|
+
isWrite: false,
|
|
3469
|
+
inputSchema: {
|
|
3470
|
+
type: "object",
|
|
3471
|
+
properties: {
|
|
3472
|
+
ccy: {
|
|
3473
|
+
type: "string",
|
|
3474
|
+
description: "Filter by currency, comma-separated (e.g. BTC,ETH). Omit for all. Applied to trading + funding queries only."
|
|
3475
|
+
},
|
|
3476
|
+
accounts: {
|
|
3477
|
+
type: "string",
|
|
3478
|
+
description: "Comma-separated accounts to query: 'trading','funding'. Default 'trading,funding'."
|
|
3479
|
+
},
|
|
3480
|
+
showValuation: {
|
|
3481
|
+
type: "boolean",
|
|
3482
|
+
description: "Include cross-account asset valuation. Default true."
|
|
3483
|
+
},
|
|
3484
|
+
valuationCcy: {
|
|
3485
|
+
type: "string",
|
|
3486
|
+
description: "Currency for valuation (e.g. USDT, BTC). Default USDT. Only effective when showValuation=true."
|
|
3487
|
+
},
|
|
3488
|
+
preferParallel: {
|
|
3489
|
+
type: "boolean",
|
|
3490
|
+
description: "Skip the server-side aggregate endpoint and query trading/funding/valuation directly in parallel. Default false. Use when you need the per-account valuation breakdown or a non-USD valuation currency."
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
},
|
|
3494
|
+
handler: (rawArgs, context) => buildBalanceAll(rawArgs, context)
|
|
3267
3495
|
}
|
|
3268
3496
|
];
|
|
3269
3497
|
}
|
|
@@ -8523,830 +8751,130 @@ function registerSmartmoneyTools() {
|
|
|
8523
8751
|
...SIGNAL_POOL_FILTER_PROPS,
|
|
8524
8752
|
lmtNum: {
|
|
8525
8753
|
type: "integer",
|
|
8526
|
-
minimum: 1,
|
|
8527
|
-
maximum: 2e3,
|
|
8528
|
-
default: 100,
|
|
8529
|
-
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)."
|
|
8530
|
-
}
|
|
8531
|
-
},
|
|
8532
|
-
required: ["instCcy", "granularity", "sortBy", "period"]
|
|
8533
|
-
},
|
|
8534
|
-
handler: async (rawArgs, context) => {
|
|
8535
|
-
const args = asRecord(rawArgs);
|
|
8536
|
-
assertEnum2(args, "granularity", ["1h", "1d"]);
|
|
8537
|
-
const instCcy = readString(args, "instCcy");
|
|
8538
|
-
if (!instCcy) {
|
|
8539
|
-
throw actionableError(
|
|
8540
|
-
'"instCcy" is required.',
|
|
8541
|
-
'Pass a base currency, e.g. "BTC".'
|
|
8542
|
-
);
|
|
8543
|
-
}
|
|
8544
|
-
const response = await context.client.privateGet(
|
|
8545
|
-
PATH_SIGNAL_HISTORY,
|
|
8546
|
-
compactObject({
|
|
8547
|
-
instCcy,
|
|
8548
|
-
asOfTime: readString(args, "asOfTime"),
|
|
8549
|
-
// Apply schema default explicitly (CLI bypasses MCP `required` validation).
|
|
8550
|
-
granularity: readString(args, "granularity") ?? "1h",
|
|
8551
|
-
limit: readNumber(args, "limit"),
|
|
8552
|
-
...readSignalPoolFilters(args),
|
|
8553
|
-
lmtNum: readNumber(args, "lmtNum")
|
|
8554
|
-
}),
|
|
8555
|
-
publicRateLimit("smartmoney_get_signal_trend_by_filter", SMARTMONEY_RPS)
|
|
8556
|
-
);
|
|
8557
|
-
return normalizeResponse(response);
|
|
8558
|
-
}
|
|
8559
|
-
},
|
|
8560
|
-
/* ---------- S4. Signal trend by trader (single-asset, authorIds-restricted) ---------- */
|
|
8561
|
-
{
|
|
8562
|
-
name: "smartmoney_get_signal_trend_by_trader",
|
|
8563
|
-
title: "Smart Money Signal Trend by Trader",
|
|
8564
|
-
module: "smartmoney",
|
|
8565
|
-
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.",
|
|
8566
|
-
isWrite: false,
|
|
8567
|
-
outputSchema: envelope({
|
|
8568
|
-
type: "array",
|
|
8569
|
-
description: "Time-bucket series for the requested instrument, sorted by time DESC (newest first).",
|
|
8570
|
-
items: { type: "object", properties: SIGNAL_HISTORY_ITEM_PROPS }
|
|
8571
|
-
}),
|
|
8572
|
-
inputSchema: {
|
|
8573
|
-
type: "object",
|
|
8574
|
-
properties: {
|
|
8575
|
-
authorIds: {
|
|
8576
|
-
type: "array",
|
|
8577
|
-
items: { type: "string" },
|
|
8578
|
-
minItems: 1,
|
|
8579
|
-
description: 'Trader IDs to aggregate over, e.g. `["1001", "1002"]`. Required.'
|
|
8580
|
-
},
|
|
8581
|
-
instCcy: {
|
|
8582
|
-
type: "string",
|
|
8583
|
-
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.'
|
|
8584
|
-
},
|
|
8585
|
-
asOfTime: {
|
|
8586
|
-
type: "string",
|
|
8587
|
-
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.'
|
|
8588
|
-
},
|
|
8589
|
-
granularity: {
|
|
8590
|
-
type: "string",
|
|
8591
|
-
enum: ["1h", "1d"],
|
|
8592
|
-
default: "1h",
|
|
8593
|
-
description: "Time-bucket size. `1h` = hourly snapshots (intraday/short-term trend), `1d` = daily snapshots (multi-day trend)."
|
|
8594
|
-
},
|
|
8595
|
-
limit: {
|
|
8596
|
-
type: "integer",
|
|
8597
|
-
minimum: 1,
|
|
8598
|
-
maximum: 500,
|
|
8599
|
-
default: 24,
|
|
8600
|
-
description: "Number of buckets to return (newest first), ending at `asOfTime`. Default 24, max 500."
|
|
8601
|
-
},
|
|
8602
|
-
sortBy: {
|
|
8603
|
-
type: "string",
|
|
8604
|
-
enum: ["pnl", "pnlRatio"],
|
|
8605
|
-
default: "pnl",
|
|
8606
|
-
description: 'Required. Ranking key for the trader set. `pnl` = absolute USD profit; `pnlRatio` = percentage return. Default `"pnl"`.'
|
|
8607
|
-
},
|
|
8608
|
-
period: {
|
|
8609
|
-
type: "string",
|
|
8610
|
-
enum: PERIOD_DAYS,
|
|
8611
|
-
default: "7",
|
|
8612
|
-
description: 'Required. Lookback window in days. One of `"3"` / `"7"` / `"30"` / `"90"`. Default `"7"`. Does NOT affect signal fields (which always use the latest snapshot).'
|
|
8613
|
-
}
|
|
8614
|
-
},
|
|
8615
|
-
required: ["authorIds", "instCcy", "granularity", "sortBy", "period"]
|
|
8616
|
-
},
|
|
8617
|
-
handler: async (rawArgs, context) => {
|
|
8618
|
-
const args = asRecord(rawArgs);
|
|
8619
|
-
assertEnum2(args, "granularity", ["1h", "1d"]);
|
|
8620
|
-
assertEnum2(args, "sortBy", ["pnl", "pnlRatio"]);
|
|
8621
|
-
assertEnum2(args, "period", PERIOD_DAYS);
|
|
8622
|
-
const authorIds = readArrayAsCsv(args, "authorIds");
|
|
8623
|
-
const instCcy = readString(args, "instCcy");
|
|
8624
|
-
if (!authorIds) {
|
|
8625
|
-
throw actionableError(
|
|
8626
|
-
'"authorIds" is required and must be a non-empty array.',
|
|
8627
|
-
'Pass IDs from `smartmoney_get_traders_by_filter` as an array (e.g. ["1001", "1002"]).'
|
|
8628
|
-
);
|
|
8629
|
-
}
|
|
8630
|
-
if (!instCcy) {
|
|
8631
|
-
throw actionableError(
|
|
8632
|
-
'"instCcy" is required.',
|
|
8633
|
-
'Pass a base currency, e.g. "BTC".'
|
|
8634
|
-
);
|
|
8635
|
-
}
|
|
8636
|
-
const response = await context.client.privateGet(
|
|
8637
|
-
PATH_SIGNAL_HISTORY,
|
|
8638
|
-
compactObject({
|
|
8639
|
-
authorIds,
|
|
8640
|
-
instCcy,
|
|
8641
|
-
asOfTime: readString(args, "asOfTime"),
|
|
8642
|
-
// Apply schema defaults explicitly so behavior does not depend on backend defaults
|
|
8643
|
-
// (CLI bypasses MCP `required` validation, so handler is the only deterministic layer).
|
|
8644
|
-
granularity: readString(args, "granularity") ?? "1h",
|
|
8645
|
-
limit: readNumber(args, "limit"),
|
|
8646
|
-
sortBy: readString(args, "sortBy") ?? "pnl",
|
|
8647
|
-
period: readString(args, "period") ?? "7"
|
|
8648
|
-
}),
|
|
8649
|
-
publicRateLimit("smartmoney_get_signal_trend_by_trader", SMARTMONEY_RPS)
|
|
8650
|
-
);
|
|
8651
|
-
return normalizeResponse(response);
|
|
8652
|
-
}
|
|
8653
|
-
}
|
|
8654
|
-
];
|
|
8655
|
-
return tools;
|
|
8656
|
-
}
|
|
8657
|
-
function toNum(v) {
|
|
8658
|
-
if (v === void 0 || v === null || v === "") return void 0;
|
|
8659
|
-
const n = Number(v);
|
|
8660
|
-
return Number.isFinite(n) ? n : void 0;
|
|
8661
|
-
}
|
|
8662
|
-
function decimalPlaces(v) {
|
|
8663
|
-
if (v === void 0 || v === null || v === "") return 0;
|
|
8664
|
-
const s = String(v);
|
|
8665
|
-
const dot = s.indexOf(".");
|
|
8666
|
-
return dot < 0 ? 0 : s.length - dot - 1;
|
|
8667
|
-
}
|
|
8668
|
-
function fmtFixed(n, places) {
|
|
8669
|
-
return n.toFixed(places);
|
|
8670
|
-
}
|
|
8671
|
-
function deriveTickerView(ticker, outcome) {
|
|
8672
|
-
const bidNum = toNum(ticker.bidPx);
|
|
8673
|
-
const askNum = toNum(ticker.askPx);
|
|
8674
|
-
const lastStr = ticker.last !== void 0 ? String(ticker.last) : void 0;
|
|
8675
|
-
const bidPlaces = decimalPlaces(ticker.bidPx);
|
|
8676
|
-
const askPlaces = decimalPlaces(ticker.askPx);
|
|
8677
|
-
const maxPlaces = Math.max(bidPlaces, askPlaces);
|
|
8678
|
-
const bidStr = bidNum !== void 0 ? fmtFixed(bidNum, bidPlaces) : void 0;
|
|
8679
|
-
const askStr = askNum !== void 0 ? fmtFixed(askNum, askPlaces) : void 0;
|
|
8680
|
-
const view = { last: lastStr, bidPx: bidStr, askPx: askStr };
|
|
8681
|
-
if (bidNum !== void 0 && askNum !== void 0) {
|
|
8682
|
-
view.midpoint = fmtFixed((bidNum + askNum) / 2, maxPlaces);
|
|
8683
|
-
view.spread = fmtFixed(askNum - bidNum, maxPlaces);
|
|
8684
|
-
}
|
|
8685
|
-
if (outcome !== void 0 && askNum !== void 0) {
|
|
8686
|
-
const outcomeLower = outcome.toLowerCase();
|
|
8687
|
-
if (outcomeLower === "yes") {
|
|
8688
|
-
view.derivedPrice = fmtFixed(askNum, askPlaces);
|
|
8689
|
-
} else if (outcomeLower === "no") {
|
|
8690
|
-
view.derivedPrice = fmtFixed(1 - askNum, askPlaces);
|
|
8691
|
-
}
|
|
8692
|
-
}
|
|
8693
|
-
return view;
|
|
8694
|
-
}
|
|
8695
|
-
var PATH_EVENTS = "/api/v5/predictions/events";
|
|
8696
|
-
var PATH_EVENTS_SEARCH = "/api/v5/predictions/events/search";
|
|
8697
|
-
var PATH_MARKETS = "/api/v5/predictions/markets";
|
|
8698
|
-
var PATH_BALANCE = "/api/v5/predictions/balance";
|
|
8699
|
-
var PATH_ORDERS = "/api/v5/predictions/orders";
|
|
8700
|
-
var PATH_POSITIONS = "/api/v5/predictions/positions";
|
|
8701
|
-
var PATH_TRADES = "/api/v5/predictions/trades";
|
|
8702
|
-
var PATH_TICKER = "/api/v5/market/ticker";
|
|
8703
|
-
var PATH_CANDLES = "/api/v5/market/candles";
|
|
8704
|
-
var PATH_PM_BOOKS = "/api/v5/market/pm-books";
|
|
8705
|
-
var OUTCOMES_RPS = 10;
|
|
8706
|
-
function requireString2(args, key, label) {
|
|
8707
|
-
const v = readString(args, key);
|
|
8708
|
-
if (!v) throw new Error(`${label} is required`);
|
|
8709
|
-
return v;
|
|
8710
|
-
}
|
|
8711
|
-
function pathSegment(id) {
|
|
8712
|
-
return encodeURIComponent(id);
|
|
8713
|
-
}
|
|
8714
|
-
async function runBatchQuery(ids, fn) {
|
|
8715
|
-
if (ids.length === 0) {
|
|
8716
|
-
throw new Error("At least one ID is required");
|
|
8717
|
-
}
|
|
8718
|
-
const results = await Promise.allSettled(ids.map((id) => fn(id)));
|
|
8719
|
-
return results.map((result, i) => {
|
|
8720
|
-
const id = ids[i];
|
|
8721
|
-
if (result.status === "fulfilled") {
|
|
8722
|
-
return { id, data: result.value };
|
|
8723
|
-
}
|
|
8724
|
-
const errMsg = result.reason instanceof Error ? result.reason.message : String(result.reason);
|
|
8725
|
-
return { id, error: errMsg };
|
|
8726
|
-
});
|
|
8727
|
-
}
|
|
8728
|
-
function registerOutcomesTools() {
|
|
8729
|
-
const tools = [
|
|
8730
|
-
/* ================================================================ */
|
|
8731
|
-
/* DATA MODULE (7) */
|
|
8732
|
-
/* ================================================================ */
|
|
8733
|
-
/* D1. List events */
|
|
8734
|
-
{
|
|
8735
|
-
name: "outcomes_get_events",
|
|
8736
|
-
title: "List Prediction Events",
|
|
8737
|
-
module: "outcomes",
|
|
8738
|
-
description: "List available prediction (binary outcomes) events on OKX, optionally filtered by status, category, tag, league, sort, or cursor. Use when: discovering events to trade on. Default limit 20. See also: `outcomes_get_trending_events` (no args, server-chosen trending events), `outcomes_search_events` (keyword search).",
|
|
8739
|
-
isWrite: false,
|
|
8740
|
-
inputSchema: {
|
|
8741
|
-
type: "object",
|
|
8742
|
-
properties: {
|
|
8743
|
-
status: { type: "string", description: "Filter by event status, e.g. `active` | `closed` | `settled`." },
|
|
8744
|
-
category: { type: "string", description: "Event category, e.g. `crypto` | `sports` | `politics`." },
|
|
8745
|
-
tag: { type: "string", description: "Event tag for further classification." },
|
|
8746
|
-
league: { type: "string", description: "League / competition name for sports events." },
|
|
8747
|
-
sort: { type: "string", description: "Sort key, e.g. `trending` | `newest`." },
|
|
8748
|
-
cursor: { type: "string", description: "Pagination cursor from previous response." },
|
|
8749
|
-
limit: { type: "integer", minimum: 1, maximum: 100, default: 20, description: "Max results (default 20)." }
|
|
8750
|
-
}
|
|
8751
|
-
},
|
|
8752
|
-
handler: async (rawArgs, context) => {
|
|
8753
|
-
const args = asRecord(rawArgs);
|
|
8754
|
-
const response = await context.client.privateGet(
|
|
8755
|
-
PATH_EVENTS,
|
|
8756
|
-
compactObject({
|
|
8757
|
-
status: readString(args, "status"),
|
|
8758
|
-
category: readString(args, "category"),
|
|
8759
|
-
tag: readString(args, "tag"),
|
|
8760
|
-
league: readString(args, "league"),
|
|
8761
|
-
sort: readString(args, "sort"),
|
|
8762
|
-
cursor: readString(args, "cursor"),
|
|
8763
|
-
limit: readNumber(args, "limit") ?? 20
|
|
8764
|
-
}),
|
|
8765
|
-
privateRateLimit("outcomes_get_events", OUTCOMES_RPS)
|
|
8766
|
-
);
|
|
8767
|
-
return normalizeResponse(response);
|
|
8768
|
-
}
|
|
8769
|
-
},
|
|
8770
|
-
/* D2. Get event detail */
|
|
8771
|
-
{
|
|
8772
|
-
name: "outcomes_get_event_detail",
|
|
8773
|
-
title: "Get Prediction Event Detail",
|
|
8774
|
-
module: "outcomes",
|
|
8775
|
-
description: "Get full detail of a single prediction event by its ID, including description, resolution criteria, and linked markets. Use when: inspecting a specific event before trading.",
|
|
8776
|
-
isWrite: false,
|
|
8777
|
-
inputSchema: {
|
|
8778
|
-
type: "object",
|
|
8779
|
-
properties: {
|
|
8780
|
-
id: { type: "string", description: "Event ID, e.g. from `outcomes_get_events` results." }
|
|
8781
|
-
},
|
|
8782
|
-
required: ["id"]
|
|
8783
|
-
},
|
|
8784
|
-
handler: async (rawArgs, context) => {
|
|
8785
|
-
const args = asRecord(rawArgs);
|
|
8786
|
-
const id = requireString2(args, "id", "Event ID");
|
|
8787
|
-
const response = await context.client.privateGet(
|
|
8788
|
-
`${PATH_EVENTS}/${pathSegment(id)}`,
|
|
8789
|
-
{},
|
|
8790
|
-
privateRateLimit("outcomes_get_event_detail", OUTCOMES_RPS)
|
|
8791
|
-
);
|
|
8792
|
-
return normalizeResponse(response);
|
|
8793
|
-
}
|
|
8794
|
-
},
|
|
8795
|
-
/* D3. Get event markets */
|
|
8796
|
-
{
|
|
8797
|
-
name: "outcomes_get_event_markets",
|
|
8798
|
-
title: "Get Markets for a Prediction Event",
|
|
8799
|
-
module: "outcomes",
|
|
8800
|
-
description: "Get all tradable markets for a prediction event. Each market corresponds to a binary outcome (YES/NO). Use when: listing which outcomes are available to trade for an event. See also: `outcomes_get_market_detail` (single market by market ID).",
|
|
8801
|
-
isWrite: false,
|
|
8802
|
-
inputSchema: {
|
|
8803
|
-
type: "object",
|
|
8804
|
-
properties: {
|
|
8805
|
-
id: { type: "string", description: "Event ID." }
|
|
8806
|
-
},
|
|
8807
|
-
required: ["id"]
|
|
8808
|
-
},
|
|
8809
|
-
handler: async (rawArgs, context) => {
|
|
8810
|
-
const args = asRecord(rawArgs);
|
|
8811
|
-
const id = requireString2(args, "id", "Event ID");
|
|
8812
|
-
const response = await context.client.privateGet(
|
|
8813
|
-
`${PATH_EVENTS}/${pathSegment(id)}/markets`,
|
|
8814
|
-
{},
|
|
8815
|
-
privateRateLimit("outcomes_get_event_markets", OUTCOMES_RPS)
|
|
8816
|
-
);
|
|
8817
|
-
return normalizeResponse(response);
|
|
8818
|
-
}
|
|
8819
|
-
},
|
|
8820
|
-
/* D4. Get market detail */
|
|
8821
|
-
{
|
|
8822
|
-
name: "outcomes_get_market_detail",
|
|
8823
|
-
title: "Get Prediction Market Detail",
|
|
8824
|
-
module: "outcomes",
|
|
8825
|
-
description: "Get full detail of a single prediction market by its market ID (e.g. current probability, settlement info, linked event). Use when: inspecting a specific binary market before placing an order.",
|
|
8826
|
-
isWrite: false,
|
|
8827
|
-
inputSchema: {
|
|
8828
|
-
type: "object",
|
|
8829
|
-
properties: {
|
|
8830
|
-
id: { type: "string", description: "Market ID." }
|
|
8831
|
-
},
|
|
8832
|
-
required: ["id"]
|
|
8833
|
-
},
|
|
8834
|
-
handler: async (rawArgs, context) => {
|
|
8835
|
-
const args = asRecord(rawArgs);
|
|
8836
|
-
const id = requireString2(args, "id", "Market ID");
|
|
8837
|
-
const response = await context.client.privateGet(
|
|
8838
|
-
`${PATH_MARKETS}/${pathSegment(id)}`,
|
|
8839
|
-
{},
|
|
8840
|
-
privateRateLimit("outcomes_get_market_detail", OUTCOMES_RPS)
|
|
8841
|
-
);
|
|
8842
|
-
return normalizeResponse(response);
|
|
8843
|
-
}
|
|
8844
|
-
},
|
|
8845
|
-
/* D5. Trending events (alias of events, server defaults sort) */
|
|
8846
|
-
{
|
|
8847
|
-
name: "outcomes_get_trending_events",
|
|
8848
|
-
title: "Get Trending Prediction Events",
|
|
8849
|
-
module: "outcomes",
|
|
8850
|
-
description: "Get trending prediction events \u2014 server-selected, most-active events. Equivalent to `outcomes_get_events` with no sort parameter; the server applies its trending algorithm. Use when: user asks for 'what's hot / trending' in predictions. See also: `outcomes_get_events` (full filter support).",
|
|
8851
|
-
isWrite: false,
|
|
8852
|
-
inputSchema: {
|
|
8853
|
-
type: "object",
|
|
8854
|
-
properties: {
|
|
8855
|
-
cursor: { type: "string", description: "Pagination cursor." },
|
|
8856
|
-
limit: { type: "integer", minimum: 1, maximum: 100, default: 20, description: "Max results (default 20)." }
|
|
8857
|
-
}
|
|
8858
|
-
},
|
|
8859
|
-
handler: async (rawArgs, context) => {
|
|
8860
|
-
const args = asRecord(rawArgs);
|
|
8861
|
-
const response = await context.client.privateGet(
|
|
8862
|
-
PATH_EVENTS,
|
|
8863
|
-
compactObject({
|
|
8864
|
-
cursor: readString(args, "cursor"),
|
|
8865
|
-
limit: readNumber(args, "limit") ?? 20
|
|
8866
|
-
}),
|
|
8867
|
-
privateRateLimit("outcomes_get_trending_events", OUTCOMES_RPS)
|
|
8868
|
-
);
|
|
8869
|
-
return normalizeResponse(response);
|
|
8870
|
-
}
|
|
8871
|
-
},
|
|
8872
|
-
/* D6. Get ticker */
|
|
8873
|
-
{
|
|
8874
|
-
name: "outcomes_get_ticker",
|
|
8875
|
-
title: "Get Prediction Asset Ticker",
|
|
8876
|
-
module: "outcomes",
|
|
8877
|
-
description: "Get the current ticker (last traded price, best bid/ask, volume) for a prediction market asset ID. Use when: checking the latest price for a prediction market instrument. Returns the full raw ticker \u2014 use `outcomes_get_market_price` for outcome-derived pricing.",
|
|
8878
|
-
isWrite: false,
|
|
8879
|
-
inputSchema: {
|
|
8880
|
-
type: "object",
|
|
8881
|
-
properties: {
|
|
8882
|
-
assetId: { type: "string", description: "Prediction asset instrument ID, e.g. `BTC-USD-PRED`." }
|
|
8883
|
-
},
|
|
8884
|
-
required: ["assetId"]
|
|
8885
|
-
},
|
|
8886
|
-
handler: async (rawArgs, context) => {
|
|
8887
|
-
const args = asRecord(rawArgs);
|
|
8888
|
-
const assetId = readString(args, "assetId") ?? "";
|
|
8889
|
-
const response = await context.client.privateGet(
|
|
8890
|
-
PATH_TICKER,
|
|
8891
|
-
{ instId: assetId },
|
|
8892
|
-
privateRateLimit("outcomes_get_ticker", OUTCOMES_RPS)
|
|
8893
|
-
);
|
|
8894
|
-
return normalizeResponse(response);
|
|
8895
|
-
}
|
|
8896
|
-
},
|
|
8897
|
-
/* D7. Get candles */
|
|
8898
|
-
{
|
|
8899
|
-
name: "outcomes_get_candles",
|
|
8900
|
-
title: "Get Prediction Asset Candles",
|
|
8901
|
-
module: "outcomes",
|
|
8902
|
-
description: "Get OHLCV candlestick data for a prediction asset. OKX pagination convention: `after` returns candles with timestamp BEFORE the cursor; `before` returns candles AFTER. Use when: charting or analysing price history of a prediction market instrument.",
|
|
8903
|
-
isWrite: false,
|
|
8904
|
-
inputSchema: {
|
|
8905
|
-
type: "object",
|
|
8906
|
-
properties: {
|
|
8907
|
-
assetId: { type: "string", description: "Prediction asset instrument ID." },
|
|
8908
|
-
bar: { type: "string", enum: ["1m", "5m", "15m", "30m", "1H", "4H", "1D"], description: "Candlestick bar size (default `1m`)." },
|
|
8909
|
-
after: { type: "string", description: "Pagination cursor \u2014 returns candles with ts BEFORE this value." },
|
|
8910
|
-
before: { type: "string", description: "Pagination cursor \u2014 returns candles with ts AFTER this value." },
|
|
8911
|
-
limit: { type: "integer", minimum: 1, maximum: 300, default: 100, description: "Max candles (default 100)." }
|
|
8912
|
-
},
|
|
8913
|
-
required: ["assetId"]
|
|
8914
|
-
},
|
|
8915
|
-
handler: async (rawArgs, context) => {
|
|
8916
|
-
const args = asRecord(rawArgs);
|
|
8917
|
-
const assetId = readString(args, "assetId") ?? "";
|
|
8918
|
-
const response = await context.client.privateGet(
|
|
8919
|
-
PATH_CANDLES,
|
|
8920
|
-
compactObject({
|
|
8921
|
-
instId: assetId,
|
|
8922
|
-
bar: readString(args, "bar"),
|
|
8923
|
-
after: readString(args, "after"),
|
|
8924
|
-
before: readString(args, "before"),
|
|
8925
|
-
limit: readNumber(args, "limit") ?? 100
|
|
8926
|
-
}),
|
|
8927
|
-
privateRateLimit("outcomes_get_candles", OUTCOMES_RPS)
|
|
8928
|
-
);
|
|
8929
|
-
return normalizeResponse(response);
|
|
8930
|
-
}
|
|
8931
|
-
},
|
|
8932
|
-
/* ================================================================ */
|
|
8933
|
-
/* SEARCH MODULE (1) */
|
|
8934
|
-
/* ================================================================ */
|
|
8935
|
-
/* S1. Search events */
|
|
8936
|
-
{
|
|
8937
|
-
name: "outcomes_search_events",
|
|
8938
|
-
title: "Search Prediction Events",
|
|
8939
|
-
module: "outcomes",
|
|
8940
|
-
description: "Search prediction events by keyword. Returns events matching the keyword in title, description, or tags. Use when: user asks about a specific topic (e.g. 'Will BTC hit 100k?', 'US election'). See also: `outcomes_get_events` (full browse), `outcomes_get_trending_events` (trending).",
|
|
8941
|
-
isWrite: false,
|
|
8942
|
-
inputSchema: {
|
|
8943
|
-
type: "object",
|
|
8944
|
-
properties: {
|
|
8945
|
-
keyword: { type: "string", description: "Search keyword." },
|
|
8946
|
-
cursor: { type: "string", description: "Pagination cursor." },
|
|
8947
|
-
limit: { type: "integer", minimum: 1, maximum: 100, default: 20, description: "Max results (default 20)." }
|
|
8948
|
-
},
|
|
8949
|
-
required: ["keyword"]
|
|
8950
|
-
},
|
|
8951
|
-
handler: async (rawArgs, context) => {
|
|
8952
|
-
const args = asRecord(rawArgs);
|
|
8953
|
-
const response = await context.client.privateGet(
|
|
8954
|
-
PATH_EVENTS_SEARCH,
|
|
8955
|
-
compactObject({
|
|
8956
|
-
keyword: readString(args, "keyword"),
|
|
8957
|
-
cursor: readString(args, "cursor"),
|
|
8958
|
-
limit: readNumber(args, "limit") ?? 20
|
|
8959
|
-
}),
|
|
8960
|
-
privateRateLimit("outcomes_search_events", OUTCOMES_RPS)
|
|
8961
|
-
);
|
|
8962
|
-
return normalizeResponse(response);
|
|
8963
|
-
}
|
|
8964
|
-
},
|
|
8965
|
-
/* ================================================================ */
|
|
8966
|
-
/* CLOB MODULE (8) */
|
|
8967
|
-
/* 6 of these call /api/v5/market/ticker with client-side derive. */
|
|
8968
|
-
/* 2 (book/books) call /api/v5/market/pm-books. */
|
|
8969
|
-
/* ================================================================ */
|
|
8970
|
-
/* C1. Market price (single) */
|
|
8971
|
-
{
|
|
8972
|
-
name: "outcomes_get_market_price",
|
|
8973
|
-
title: "Get Prediction Market Price",
|
|
8974
|
-
module: "outcomes",
|
|
8975
|
-
description: "Get the derived trading price for a binary prediction market outcome (YES or NO side). Internally fetches the ticker and derives the best-ask for the specified outcome. Use `outcome=yes` for YES side, `outcome=no` for NO side. See also: `outcomes_get_market_prices` (batch), `outcomes_get_market_midpoint` (mid price).",
|
|
8976
|
-
isWrite: false,
|
|
8977
|
-
inputSchema: {
|
|
8978
|
-
type: "object",
|
|
8979
|
-
properties: {
|
|
8980
|
-
mktId: { type: "string", description: "Market instrument ID." },
|
|
8981
|
-
outcome: { type: "string", enum: ["yes", "no"], description: "Which outcome side: `yes` or `no`." }
|
|
8982
|
-
},
|
|
8983
|
-
required: ["mktId"]
|
|
8984
|
-
},
|
|
8985
|
-
handler: async (rawArgs, context) => {
|
|
8986
|
-
const args = asRecord(rawArgs);
|
|
8987
|
-
const mktId = readString(args, "mktId") ?? "";
|
|
8988
|
-
const outcome = readString(args, "outcome");
|
|
8989
|
-
const response = await context.client.privateGet(
|
|
8990
|
-
PATH_TICKER,
|
|
8991
|
-
{ instId: mktId },
|
|
8992
|
-
privateRateLimit("outcomes_get_market_price", OUTCOMES_RPS)
|
|
8993
|
-
);
|
|
8994
|
-
const normalized = normalizeResponse(response);
|
|
8995
|
-
const ticker = Array.isArray(normalized.data) && normalized.data.length > 0 ? normalized.data[0] : {};
|
|
8996
|
-
const view = deriveTickerView(ticker, outcome);
|
|
8997
|
-
return { ...normalized, data: { ...ticker, ...view } };
|
|
8998
|
-
}
|
|
8999
|
-
},
|
|
9000
|
-
/* C2. Market prices (batch) */
|
|
9001
|
-
{
|
|
9002
|
-
name: "outcomes_get_market_prices",
|
|
9003
|
-
title: "Get Prediction Market Prices (Batch)",
|
|
9004
|
-
module: "outcomes",
|
|
9005
|
-
description: "Get derived trading prices for multiple prediction market IDs in parallel. Per-row error isolation: if any single market fails, only that row has an `error` field; the rest succeed normally. See also: `outcomes_get_market_price` (single market), `outcomes_get_market_midpoints` (batch midpoints).",
|
|
9006
|
-
isWrite: false,
|
|
9007
|
-
inputSchema: {
|
|
9008
|
-
type: "object",
|
|
9009
|
-
properties: {
|
|
9010
|
-
ids: { type: "array", items: { type: "string" }, description: "List of market instrument IDs." },
|
|
9011
|
-
outcome: { type: "string", enum: ["yes", "no"], description: "Outcome side for price derivation." }
|
|
9012
|
-
},
|
|
9013
|
-
required: ["ids"]
|
|
9014
|
-
},
|
|
9015
|
-
handler: async (rawArgs, context) => {
|
|
9016
|
-
const args = asRecord(rawArgs);
|
|
9017
|
-
const ids = Array.isArray(args["ids"]) ? args["ids"] : [];
|
|
9018
|
-
const outcome = readString(args, "outcome");
|
|
9019
|
-
const rows = await runBatchQuery(ids, async (id) => {
|
|
9020
|
-
const response = await context.client.privateGet(
|
|
9021
|
-
PATH_TICKER,
|
|
9022
|
-
{ instId: id },
|
|
9023
|
-
privateRateLimit("outcomes_get_market_prices", OUTCOMES_RPS)
|
|
9024
|
-
);
|
|
9025
|
-
const normalized = normalizeResponse(response);
|
|
9026
|
-
const ticker = Array.isArray(normalized.data) && normalized.data.length > 0 ? normalized.data[0] : {};
|
|
9027
|
-
return { ...ticker, ...deriveTickerView(ticker, outcome) };
|
|
9028
|
-
});
|
|
9029
|
-
return {
|
|
9030
|
-
endpoint: PATH_TICKER,
|
|
9031
|
-
requestTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9032
|
-
data: rows
|
|
9033
|
-
};
|
|
9034
|
-
}
|
|
9035
|
-
},
|
|
9036
|
-
/* C3. Market midpoint (single) */
|
|
9037
|
-
{
|
|
9038
|
-
name: "outcomes_get_market_midpoint",
|
|
9039
|
-
title: "Get Prediction Market Midpoint",
|
|
9040
|
-
module: "outcomes",
|
|
9041
|
-
description: "Get the midpoint price for a prediction market: (bidPx + askPx) / 2. Use when: estimating the fair mid-market price. See also: `outcomes_get_market_midpoints` (batch), `outcomes_get_market_spread` (bid-ask spread).",
|
|
9042
|
-
isWrite: false,
|
|
9043
|
-
inputSchema: {
|
|
9044
|
-
type: "object",
|
|
9045
|
-
properties: {
|
|
9046
|
-
mktId: { type: "string", description: "Market instrument ID." }
|
|
9047
|
-
},
|
|
9048
|
-
required: ["mktId"]
|
|
9049
|
-
},
|
|
9050
|
-
handler: async (rawArgs, context) => {
|
|
9051
|
-
const args = asRecord(rawArgs);
|
|
9052
|
-
const mktId = readString(args, "mktId") ?? "";
|
|
9053
|
-
const response = await context.client.privateGet(
|
|
9054
|
-
PATH_TICKER,
|
|
9055
|
-
{ instId: mktId },
|
|
9056
|
-
privateRateLimit("outcomes_get_market_midpoint", OUTCOMES_RPS)
|
|
9057
|
-
);
|
|
9058
|
-
const normalized = normalizeResponse(response);
|
|
9059
|
-
const ticker = Array.isArray(normalized.data) && normalized.data.length > 0 ? normalized.data[0] : {};
|
|
9060
|
-
const view = deriveTickerView(ticker, void 0);
|
|
9061
|
-
return { ...normalized, data: { ...ticker, ...view } };
|
|
9062
|
-
}
|
|
9063
|
-
},
|
|
9064
|
-
/* C4. Market midpoints (batch) */
|
|
9065
|
-
{
|
|
9066
|
-
name: "outcomes_get_market_midpoints",
|
|
9067
|
-
title: "Get Prediction Market Midpoints (Batch)",
|
|
9068
|
-
module: "outcomes",
|
|
9069
|
-
description: "Get midpoint prices for multiple prediction markets in parallel. Per-row error isolation. See also: `outcomes_get_market_midpoint` (single), `outcomes_get_market_spreads` (batch spreads).",
|
|
9070
|
-
isWrite: false,
|
|
9071
|
-
inputSchema: {
|
|
9072
|
-
type: "object",
|
|
9073
|
-
properties: {
|
|
9074
|
-
ids: { type: "array", items: { type: "string" }, description: "List of market instrument IDs." }
|
|
9075
|
-
},
|
|
9076
|
-
required: ["ids"]
|
|
9077
|
-
},
|
|
9078
|
-
handler: async (rawArgs, context) => {
|
|
9079
|
-
const args = asRecord(rawArgs);
|
|
9080
|
-
const ids = Array.isArray(args["ids"]) ? args["ids"] : [];
|
|
9081
|
-
const rows = await runBatchQuery(ids, async (id) => {
|
|
9082
|
-
const response = await context.client.privateGet(
|
|
9083
|
-
PATH_TICKER,
|
|
9084
|
-
{ instId: id },
|
|
9085
|
-
privateRateLimit("outcomes_get_market_midpoints", OUTCOMES_RPS)
|
|
9086
|
-
);
|
|
9087
|
-
const normalized = normalizeResponse(response);
|
|
9088
|
-
const ticker = Array.isArray(normalized.data) && normalized.data.length > 0 ? normalized.data[0] : {};
|
|
9089
|
-
return { ...ticker, ...deriveTickerView(ticker, void 0) };
|
|
9090
|
-
});
|
|
9091
|
-
return {
|
|
9092
|
-
endpoint: PATH_TICKER,
|
|
9093
|
-
requestTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9094
|
-
data: rows
|
|
9095
|
-
};
|
|
9096
|
-
}
|
|
9097
|
-
},
|
|
9098
|
-
/* C5. Market spread (single) */
|
|
9099
|
-
{
|
|
9100
|
-
name: "outcomes_get_market_spread",
|
|
9101
|
-
title: "Get Prediction Market Spread",
|
|
9102
|
-
module: "outcomes",
|
|
9103
|
-
description: "Get the bid-ask spread for a prediction market: askPx - bidPx. Use when: assessing liquidity or trading cost. See also: `outcomes_get_market_spreads` (batch), `outcomes_get_market_midpoint` (midpoint price).",
|
|
9104
|
-
isWrite: false,
|
|
9105
|
-
inputSchema: {
|
|
9106
|
-
type: "object",
|
|
9107
|
-
properties: {
|
|
9108
|
-
mktId: { type: "string", description: "Market instrument ID." }
|
|
9109
|
-
},
|
|
9110
|
-
required: ["mktId"]
|
|
9111
|
-
},
|
|
9112
|
-
handler: async (rawArgs, context) => {
|
|
9113
|
-
const args = asRecord(rawArgs);
|
|
9114
|
-
const mktId = readString(args, "mktId") ?? "";
|
|
9115
|
-
const response = await context.client.privateGet(
|
|
9116
|
-
PATH_TICKER,
|
|
9117
|
-
{ instId: mktId },
|
|
9118
|
-
privateRateLimit("outcomes_get_market_spread", OUTCOMES_RPS)
|
|
9119
|
-
);
|
|
9120
|
-
const normalized = normalizeResponse(response);
|
|
9121
|
-
const ticker = Array.isArray(normalized.data) && normalized.data.length > 0 ? normalized.data[0] : {};
|
|
9122
|
-
const view = deriveTickerView(ticker, void 0);
|
|
9123
|
-
return { ...normalized, data: { ...ticker, ...view } };
|
|
9124
|
-
}
|
|
9125
|
-
},
|
|
9126
|
-
/* C6. Market spreads (batch) */
|
|
9127
|
-
{
|
|
9128
|
-
name: "outcomes_get_market_spreads",
|
|
9129
|
-
title: "Get Prediction Market Spreads (Batch)",
|
|
9130
|
-
module: "outcomes",
|
|
9131
|
-
description: "Get bid-ask spreads for multiple prediction markets in parallel. Per-row error isolation. See also: `outcomes_get_market_spread` (single), `outcomes_get_market_midpoints` (batch midpoints).",
|
|
9132
|
-
isWrite: false,
|
|
9133
|
-
inputSchema: {
|
|
9134
|
-
type: "object",
|
|
9135
|
-
properties: {
|
|
9136
|
-
ids: { type: "array", items: { type: "string" }, description: "List of market instrument IDs." }
|
|
9137
|
-
},
|
|
9138
|
-
required: ["ids"]
|
|
9139
|
-
},
|
|
9140
|
-
handler: async (rawArgs, context) => {
|
|
9141
|
-
const args = asRecord(rawArgs);
|
|
9142
|
-
const ids = Array.isArray(args["ids"]) ? args["ids"] : [];
|
|
9143
|
-
const rows = await runBatchQuery(ids, async (id) => {
|
|
9144
|
-
const response = await context.client.privateGet(
|
|
9145
|
-
PATH_TICKER,
|
|
9146
|
-
{ instId: id },
|
|
9147
|
-
privateRateLimit("outcomes_get_market_spreads", OUTCOMES_RPS)
|
|
9148
|
-
);
|
|
9149
|
-
const normalized = normalizeResponse(response);
|
|
9150
|
-
const ticker = Array.isArray(normalized.data) && normalized.data.length > 0 ? normalized.data[0] : {};
|
|
9151
|
-
return { ...ticker, ...deriveTickerView(ticker, void 0) };
|
|
9152
|
-
});
|
|
9153
|
-
return {
|
|
9154
|
-
endpoint: PATH_TICKER,
|
|
9155
|
-
requestTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9156
|
-
data: rows
|
|
9157
|
-
};
|
|
9158
|
-
}
|
|
9159
|
-
},
|
|
9160
|
-
/* C7. Order book (single) */
|
|
9161
|
-
{
|
|
9162
|
-
name: "outcomes_get_order_book",
|
|
9163
|
-
title: "Get Prediction Market Order Book",
|
|
9164
|
-
module: "outcomes",
|
|
9165
|
-
description: "Get the CLOB order book (bids and asks) for a prediction market. Use when: examining market depth before a limit order. See also: `outcomes_get_order_books` (batch).",
|
|
9166
|
-
isWrite: false,
|
|
9167
|
-
inputSchema: {
|
|
9168
|
-
type: "object",
|
|
9169
|
-
properties: {
|
|
9170
|
-
mktId: { type: "string", description: "Market instrument ID." },
|
|
9171
|
-
sz: { type: "integer", minimum: 1, maximum: 400, description: "Order book depth (levels to return)." }
|
|
9172
|
-
},
|
|
9173
|
-
required: ["mktId"]
|
|
9174
|
-
},
|
|
9175
|
-
handler: async (rawArgs, context) => {
|
|
9176
|
-
const args = asRecord(rawArgs);
|
|
9177
|
-
const mktId = readString(args, "mktId") ?? "";
|
|
9178
|
-
const sz = readNumber(args, "sz");
|
|
9179
|
-
const response = await context.client.privateGet(
|
|
9180
|
-
PATH_PM_BOOKS,
|
|
9181
|
-
compactObject({ instId: mktId, sz }),
|
|
9182
|
-
privateRateLimit("outcomes_get_order_book", OUTCOMES_RPS)
|
|
9183
|
-
);
|
|
9184
|
-
return normalizeResponse(response);
|
|
9185
|
-
}
|
|
9186
|
-
},
|
|
9187
|
-
/* C8. Order books (batch) */
|
|
9188
|
-
{
|
|
9189
|
-
name: "outcomes_get_order_books",
|
|
9190
|
-
title: "Get Prediction Market Order Books (Batch)",
|
|
9191
|
-
module: "outcomes",
|
|
9192
|
-
description: "Get CLOB order books for multiple prediction markets in parallel. Per-row error isolation. See also: `outcomes_get_order_book` (single).",
|
|
9193
|
-
isWrite: false,
|
|
9194
|
-
inputSchema: {
|
|
9195
|
-
type: "object",
|
|
9196
|
-
properties: {
|
|
9197
|
-
ids: { type: "array", items: { type: "string" }, description: "List of market instrument IDs." },
|
|
9198
|
-
sz: { type: "integer", minimum: 1, maximum: 400, description: "Order book depth per market." }
|
|
9199
|
-
},
|
|
9200
|
-
required: ["ids"]
|
|
9201
|
-
},
|
|
9202
|
-
handler: async (rawArgs, context) => {
|
|
9203
|
-
const args = asRecord(rawArgs);
|
|
9204
|
-
const ids = Array.isArray(args["ids"]) ? args["ids"] : [];
|
|
9205
|
-
const sz = readNumber(args, "sz");
|
|
9206
|
-
const rows = await runBatchQuery(ids, async (id) => {
|
|
9207
|
-
const response = await context.client.privateGet(
|
|
9208
|
-
PATH_PM_BOOKS,
|
|
9209
|
-
compactObject({ instId: id, sz }),
|
|
9210
|
-
privateRateLimit("outcomes_get_order_books", OUTCOMES_RPS)
|
|
9211
|
-
);
|
|
9212
|
-
const normalized = normalizeResponse(response);
|
|
9213
|
-
return Array.isArray(normalized.data) && normalized.data.length > 0 ? normalized.data[0] : normalized.data;
|
|
9214
|
-
});
|
|
9215
|
-
return {
|
|
9216
|
-
endpoint: PATH_PM_BOOKS,
|
|
9217
|
-
requestTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9218
|
-
data: rows
|
|
9219
|
-
};
|
|
9220
|
-
}
|
|
9221
|
-
},
|
|
9222
|
-
/* ================================================================ */
|
|
9223
|
-
/* ACCOUNT MODULE (5) */
|
|
9224
|
-
/* ================================================================ */
|
|
9225
|
-
/* A1. Account balance */
|
|
9226
|
-
{
|
|
9227
|
-
name: "outcomes_get_account_balance",
|
|
9228
|
-
title: "Get Predictions Account Balance",
|
|
9229
|
-
module: "outcomes",
|
|
9230
|
-
description: "Get the balance of the user's predictions account (collateral available for trading binary outcomes). Use when: checking how much is available to bet on prediction markets.",
|
|
9231
|
-
isWrite: false,
|
|
9232
|
-
inputSchema: { type: "object", properties: {} },
|
|
9233
|
-
handler: async (_rawArgs, context) => {
|
|
9234
|
-
const response = await context.client.privateGet(
|
|
9235
|
-
PATH_BALANCE,
|
|
9236
|
-
{},
|
|
9237
|
-
privateRateLimit("outcomes_get_account_balance", OUTCOMES_RPS)
|
|
9238
|
-
);
|
|
9239
|
-
return normalizeResponse(response);
|
|
9240
|
-
}
|
|
9241
|
-
},
|
|
9242
|
-
/* A2. Order detail */
|
|
9243
|
-
{
|
|
9244
|
-
name: "outcomes_get_order_detail",
|
|
9245
|
-
title: "Get Prediction Order Detail",
|
|
9246
|
-
module: "outcomes",
|
|
9247
|
-
description: "Get full detail of a single prediction order by order ID (status, fill info, timestamps). Use when: checking whether a specific order was filled. Also reachable via `okx outcomes clob order {ID}` (CLI alias).",
|
|
9248
|
-
isWrite: false,
|
|
9249
|
-
inputSchema: {
|
|
9250
|
-
type: "object",
|
|
9251
|
-
properties: {
|
|
9252
|
-
id: { type: "string", description: "Order ID." }
|
|
9253
|
-
},
|
|
9254
|
-
required: ["id"]
|
|
9255
|
-
},
|
|
9256
|
-
handler: async (rawArgs, context) => {
|
|
9257
|
-
const args = asRecord(rawArgs);
|
|
9258
|
-
const id = requireString2(args, "id", "Order ID");
|
|
9259
|
-
const response = await context.client.privateGet(
|
|
9260
|
-
`${PATH_ORDERS}/${pathSegment(id)}`,
|
|
9261
|
-
{},
|
|
9262
|
-
privateRateLimit("outcomes_get_order_detail", OUTCOMES_RPS)
|
|
9263
|
-
);
|
|
9264
|
-
return normalizeResponse(response);
|
|
9265
|
-
}
|
|
9266
|
-
},
|
|
9267
|
-
/* A3. Account orders */
|
|
9268
|
-
{
|
|
9269
|
-
name: "outcomes_get_account_orders",
|
|
9270
|
-
title: "List Prediction Account Orders",
|
|
9271
|
-
module: "outcomes",
|
|
9272
|
-
description: "List the user's prediction orders, optionally filtered by status (`open` | `closed`, default `open`) and paginated. Use when: reviewing pending or historical orders. Also reachable via `okx outcomes clob orders` (CLI alias).",
|
|
9273
|
-
isWrite: false,
|
|
9274
|
-
inputSchema: {
|
|
9275
|
-
type: "object",
|
|
9276
|
-
properties: {
|
|
9277
|
-
status: { type: "string", enum: ["open", "closed"], default: "open", description: "Order status filter (default `open`)." },
|
|
9278
|
-
cursor: { type: "string", description: "Pagination cursor." },
|
|
9279
|
-
limit: { type: "integer", minimum: 1, maximum: 100, default: 20, description: "Max results (default 20)." }
|
|
9280
|
-
}
|
|
8754
|
+
minimum: 1,
|
|
8755
|
+
maximum: 2e3,
|
|
8756
|
+
default: 100,
|
|
8757
|
+
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)."
|
|
8758
|
+
}
|
|
8759
|
+
},
|
|
8760
|
+
required: ["instCcy", "granularity", "sortBy", "period"]
|
|
9281
8761
|
},
|
|
9282
8762
|
handler: async (rawArgs, context) => {
|
|
9283
8763
|
const args = asRecord(rawArgs);
|
|
9284
|
-
|
|
9285
|
-
|
|
9286
|
-
|
|
9287
|
-
|
|
9288
|
-
|
|
9289
|
-
|
|
9290
|
-
|
|
9291
|
-
privateRateLimit("outcomes_get_account_orders", OUTCOMES_RPS)
|
|
9292
|
-
);
|
|
9293
|
-
return normalizeResponse(response);
|
|
9294
|
-
}
|
|
9295
|
-
},
|
|
9296
|
-
/* A4. Account positions */
|
|
9297
|
-
{
|
|
9298
|
-
name: "outcomes_get_account_positions",
|
|
9299
|
-
title: "List Prediction Account Positions",
|
|
9300
|
-
module: "outcomes",
|
|
9301
|
-
description: "List the user's prediction positions, optionally filtered by status (`open` | `closed`, default `open`), market ID, or limit. The MCP schema enum enforces valid status values at the boundary; server-side mapping of unknown values to `open` is a defensive fallback only. Use when: checking which prediction markets the user currently holds positions in.",
|
|
9302
|
-
isWrite: false,
|
|
9303
|
-
inputSchema: {
|
|
9304
|
-
type: "object",
|
|
9305
|
-
properties: {
|
|
9306
|
-
status: { type: "string", enum: ["open", "closed"], default: "open", description: "Position status filter (default `open`)." },
|
|
9307
|
-
market: { type: "string", description: "Optional market instrument ID to filter by." },
|
|
9308
|
-
cursor: { type: "string", description: "Pagination cursor." },
|
|
9309
|
-
limit: { type: "integer", minimum: 1, maximum: 100, default: 20, description: "Max results (default 20)." }
|
|
8764
|
+
assertEnum2(args, "granularity", ["1h", "1d"]);
|
|
8765
|
+
const instCcy = readString(args, "instCcy");
|
|
8766
|
+
if (!instCcy) {
|
|
8767
|
+
throw actionableError(
|
|
8768
|
+
'"instCcy" is required.',
|
|
8769
|
+
'Pass a base currency, e.g. "BTC".'
|
|
8770
|
+
);
|
|
9310
8771
|
}
|
|
9311
|
-
},
|
|
9312
|
-
handler: async (rawArgs, context) => {
|
|
9313
|
-
const args = asRecord(rawArgs);
|
|
9314
8772
|
const response = await context.client.privateGet(
|
|
9315
|
-
|
|
8773
|
+
PATH_SIGNAL_HISTORY,
|
|
9316
8774
|
compactObject({
|
|
9317
|
-
|
|
9318
|
-
|
|
9319
|
-
|
|
9320
|
-
|
|
8775
|
+
instCcy,
|
|
8776
|
+
asOfTime: readString(args, "asOfTime"),
|
|
8777
|
+
// Apply schema default explicitly (CLI bypasses MCP `required` validation).
|
|
8778
|
+
granularity: readString(args, "granularity") ?? "1h",
|
|
8779
|
+
limit: readNumber(args, "limit"),
|
|
8780
|
+
...readSignalPoolFilters(args),
|
|
8781
|
+
lmtNum: readNumber(args, "lmtNum")
|
|
9321
8782
|
}),
|
|
9322
|
-
|
|
8783
|
+
publicRateLimit("smartmoney_get_signal_trend_by_filter", SMARTMONEY_RPS)
|
|
9323
8784
|
);
|
|
9324
8785
|
return normalizeResponse(response);
|
|
9325
8786
|
}
|
|
9326
8787
|
},
|
|
9327
|
-
/*
|
|
8788
|
+
/* ---------- S4. Signal trend by trader (single-asset, authorIds-restricted) ---------- */
|
|
9328
8789
|
{
|
|
9329
|
-
name: "
|
|
9330
|
-
title: "
|
|
9331
|
-
module: "
|
|
9332
|
-
description: "
|
|
8790
|
+
name: "smartmoney_get_signal_trend_by_trader",
|
|
8791
|
+
title: "Smart Money Signal Trend by Trader",
|
|
8792
|
+
module: "smartmoney",
|
|
8793
|
+
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.",
|
|
9333
8794
|
isWrite: false,
|
|
8795
|
+
outputSchema: envelope({
|
|
8796
|
+
type: "array",
|
|
8797
|
+
description: "Time-bucket series for the requested instrument, sorted by time DESC (newest first).",
|
|
8798
|
+
items: { type: "object", properties: SIGNAL_HISTORY_ITEM_PROPS }
|
|
8799
|
+
}),
|
|
9334
8800
|
inputSchema: {
|
|
9335
8801
|
type: "object",
|
|
9336
8802
|
properties: {
|
|
9337
|
-
|
|
9338
|
-
|
|
9339
|
-
|
|
8803
|
+
authorIds: {
|
|
8804
|
+
type: "array",
|
|
8805
|
+
items: { type: "string" },
|
|
8806
|
+
minItems: 1,
|
|
8807
|
+
description: 'Trader IDs to aggregate over, e.g. `["1001", "1002"]`. Required.'
|
|
8808
|
+
},
|
|
8809
|
+
instCcy: {
|
|
8810
|
+
type: "string",
|
|
8811
|
+
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.'
|
|
8812
|
+
},
|
|
8813
|
+
asOfTime: {
|
|
8814
|
+
type: "string",
|
|
8815
|
+
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.'
|
|
8816
|
+
},
|
|
8817
|
+
granularity: {
|
|
8818
|
+
type: "string",
|
|
8819
|
+
enum: ["1h", "1d"],
|
|
8820
|
+
default: "1h",
|
|
8821
|
+
description: "Time-bucket size. `1h` = hourly snapshots (intraday/short-term trend), `1d` = daily snapshots (multi-day trend)."
|
|
8822
|
+
},
|
|
8823
|
+
limit: {
|
|
8824
|
+
type: "integer",
|
|
8825
|
+
minimum: 1,
|
|
8826
|
+
maximum: 500,
|
|
8827
|
+
default: 24,
|
|
8828
|
+
description: "Number of buckets to return (newest first), ending at `asOfTime`. Default 24, max 500."
|
|
8829
|
+
},
|
|
8830
|
+
sortBy: {
|
|
8831
|
+
type: "string",
|
|
8832
|
+
enum: ["pnl", "pnlRatio"],
|
|
8833
|
+
default: "pnl",
|
|
8834
|
+
description: 'Required. Ranking key for the trader set. `pnl` = absolute USD profit; `pnlRatio` = percentage return. Default `"pnl"`.'
|
|
8835
|
+
},
|
|
8836
|
+
period: {
|
|
8837
|
+
type: "string",
|
|
8838
|
+
enum: PERIOD_DAYS,
|
|
8839
|
+
default: "7",
|
|
8840
|
+
description: 'Required. Lookback window in days. One of `"3"` / `"7"` / `"30"` / `"90"`. Default `"7"`. Does NOT affect signal fields (which always use the latest snapshot).'
|
|
8841
|
+
}
|
|
8842
|
+
},
|
|
8843
|
+
required: ["authorIds", "instCcy", "granularity", "sortBy", "period"]
|
|
9340
8844
|
},
|
|
9341
8845
|
handler: async (rawArgs, context) => {
|
|
9342
8846
|
const args = asRecord(rawArgs);
|
|
8847
|
+
assertEnum2(args, "granularity", ["1h", "1d"]);
|
|
8848
|
+
assertEnum2(args, "sortBy", ["pnl", "pnlRatio"]);
|
|
8849
|
+
assertEnum2(args, "period", PERIOD_DAYS);
|
|
8850
|
+
const authorIds = readArrayAsCsv(args, "authorIds");
|
|
8851
|
+
const instCcy = readString(args, "instCcy");
|
|
8852
|
+
if (!authorIds) {
|
|
8853
|
+
throw actionableError(
|
|
8854
|
+
'"authorIds" is required and must be a non-empty array.',
|
|
8855
|
+
'Pass IDs from `smartmoney_get_traders_by_filter` as an array (e.g. ["1001", "1002"]).'
|
|
8856
|
+
);
|
|
8857
|
+
}
|
|
8858
|
+
if (!instCcy) {
|
|
8859
|
+
throw actionableError(
|
|
8860
|
+
'"instCcy" is required.',
|
|
8861
|
+
'Pass a base currency, e.g. "BTC".'
|
|
8862
|
+
);
|
|
8863
|
+
}
|
|
9343
8864
|
const response = await context.client.privateGet(
|
|
9344
|
-
|
|
8865
|
+
PATH_SIGNAL_HISTORY,
|
|
9345
8866
|
compactObject({
|
|
9346
|
-
|
|
9347
|
-
|
|
8867
|
+
authorIds,
|
|
8868
|
+
instCcy,
|
|
8869
|
+
asOfTime: readString(args, "asOfTime"),
|
|
8870
|
+
// Apply schema defaults explicitly so behavior does not depend on backend defaults
|
|
8871
|
+
// (CLI bypasses MCP `required` validation, so handler is the only deterministic layer).
|
|
8872
|
+
granularity: readString(args, "granularity") ?? "1h",
|
|
8873
|
+
limit: readNumber(args, "limit"),
|
|
8874
|
+
sortBy: readString(args, "sortBy") ?? "pnl",
|
|
8875
|
+
period: readString(args, "period") ?? "7"
|
|
9348
8876
|
}),
|
|
9349
|
-
|
|
8877
|
+
publicRateLimit("smartmoney_get_signal_trend_by_trader", SMARTMONEY_RPS)
|
|
9350
8878
|
);
|
|
9351
8879
|
return normalizeResponse(response);
|
|
9352
8880
|
}
|
|
@@ -13144,7 +12672,6 @@ function allToolSpecs() {
|
|
|
13144
12672
|
...registerBotTools(),
|
|
13145
12673
|
...registerAllEarnTools(),
|
|
13146
12674
|
...registerSmartmoneyTools(),
|
|
13147
|
-
...registerOutcomesTools(),
|
|
13148
12675
|
...registerAuditTools(),
|
|
13149
12676
|
...registerSkillsTools()
|
|
13150
12677
|
];
|
|
@@ -15144,7 +14671,7 @@ async function cmdDiagnoseMcp(options = {}) {
|
|
|
15144
14671
|
|
|
15145
14672
|
// src/commands/diagnose.ts
|
|
15146
14673
|
var CLI_VERSION = readCliVersion();
|
|
15147
|
-
var GIT_HASH = true ? "
|
|
14674
|
+
var GIT_HASH = true ? "9beb3ee8" : "dev";
|
|
15148
14675
|
function maskKey2(key) {
|
|
15149
14676
|
if (!key) return "(not set)";
|
|
15150
14677
|
if (key.length <= 8) return "****";
|
|
@@ -15754,6 +15281,11 @@ var CLI_REGISTRY = {
|
|
|
15754
15281
|
usage: "okx account balance [<ccy>]",
|
|
15755
15282
|
description: "Get trading account balance"
|
|
15756
15283
|
},
|
|
15284
|
+
"balance-all": {
|
|
15285
|
+
toolName: "account_get_balance_all",
|
|
15286
|
+
usage: "okx account balance-all [<ccy>] [--accounts trading,funding] [--no-valuation] [--no-aggregate] [--valuationCcy <ccy>]",
|
|
15287
|
+
description: "One-shot snapshot: trading + funding (+ valuation) via server aggregate, auto-fallback to parallel"
|
|
15288
|
+
},
|
|
15757
15289
|
"asset-balance": {
|
|
15758
15290
|
toolName: "account_get_asset_balance",
|
|
15759
15291
|
usage: "okx account asset-balance [--ccy <ccy>]",
|
|
@@ -16512,152 +16044,6 @@ var CLI_REGISTRY = {
|
|
|
16512
16044
|
}
|
|
16513
16045
|
}
|
|
16514
16046
|
},
|
|
16515
|
-
// ── outcomes ────────────────────────────────────────────────────────────────
|
|
16516
|
-
outcomes: {
|
|
16517
|
-
description: "Prediction markets - binary YES/NO event contracts (browse, search, CLOB, account)",
|
|
16518
|
-
subgroups: {
|
|
16519
|
-
data: {
|
|
16520
|
-
description: "Browse and query prediction market events and markets",
|
|
16521
|
-
commands: {
|
|
16522
|
-
events: {
|
|
16523
|
-
toolName: "outcomes_get_events",
|
|
16524
|
-
usage: "okx outcomes data events [--status <status>] [--category <cat>] [--tag <tag>] [--league <lg>] [--sortBy <sort>] [--after <cursor>] [--limit <n>] [--json]",
|
|
16525
|
-
description: "List prediction market events"
|
|
16526
|
-
},
|
|
16527
|
-
event: {
|
|
16528
|
-
toolName: "outcomes_get_event_detail",
|
|
16529
|
-
usage: "okx outcomes data event <id> [--json]",
|
|
16530
|
-
description: "Get details of a specific prediction market event"
|
|
16531
|
-
},
|
|
16532
|
-
"event-markets": {
|
|
16533
|
-
toolName: "outcomes_get_event_markets",
|
|
16534
|
-
usage: "okx outcomes data event-markets <id> [--json]",
|
|
16535
|
-
description: "Get markets for a prediction market event"
|
|
16536
|
-
},
|
|
16537
|
-
market: {
|
|
16538
|
-
toolName: "outcomes_get_market_detail",
|
|
16539
|
-
usage: "okx outcomes data market <id> [--json]",
|
|
16540
|
-
description: "Get details of a specific prediction market"
|
|
16541
|
-
},
|
|
16542
|
-
trending: {
|
|
16543
|
-
toolName: "outcomes_get_trending_events",
|
|
16544
|
-
usage: "okx outcomes data trending [--after <cursor>] [--limit <n>] [--json]",
|
|
16545
|
-
description: "Get trending prediction market events"
|
|
16546
|
-
},
|
|
16547
|
-
ticker: {
|
|
16548
|
-
toolName: "outcomes_get_ticker",
|
|
16549
|
-
usage: "okx outcomes data ticker <assetId> [--json]",
|
|
16550
|
-
description: "Get ticker for a prediction market asset"
|
|
16551
|
-
},
|
|
16552
|
-
candles: {
|
|
16553
|
-
toolName: "outcomes_get_candles",
|
|
16554
|
-
usage: "okx outcomes data candles <assetId> [--bar <bar>] [--after <ts>] [--before <ts>] [--limit <n>] [--json]",
|
|
16555
|
-
description: "Get candlestick data for a prediction market asset"
|
|
16556
|
-
}
|
|
16557
|
-
}
|
|
16558
|
-
},
|
|
16559
|
-
search: {
|
|
16560
|
-
description: "Search prediction market events",
|
|
16561
|
-
commands: {
|
|
16562
|
-
"<keyword>": {
|
|
16563
|
-
toolName: "outcomes_search_events",
|
|
16564
|
-
usage: "okx outcomes search <keyword> [--after <cursor>] [--limit <n>] [--json]",
|
|
16565
|
-
description: "Search prediction market events by keyword"
|
|
16566
|
-
}
|
|
16567
|
-
}
|
|
16568
|
-
},
|
|
16569
|
-
clob: {
|
|
16570
|
-
description: "CLOB price, order book, and account actions",
|
|
16571
|
-
commands: {
|
|
16572
|
-
price: {
|
|
16573
|
-
toolName: "outcomes_get_market_price",
|
|
16574
|
-
usage: "okx outcomes clob price <mktId> [--outcome <yes|no>] [--json]",
|
|
16575
|
-
description: "Get price for a market (optionally for a specific outcome)"
|
|
16576
|
-
},
|
|
16577
|
-
prices: {
|
|
16578
|
-
toolName: "outcomes_get_market_prices",
|
|
16579
|
-
usage: "okx outcomes clob prices <id1,id2,...> [--outcome <yes|no>] [--json]",
|
|
16580
|
-
description: "Get prices for multiple markets (batch)"
|
|
16581
|
-
},
|
|
16582
|
-
midpoint: {
|
|
16583
|
-
toolName: "outcomes_get_market_midpoint",
|
|
16584
|
-
usage: "okx outcomes clob midpoint <mktId> [--json]",
|
|
16585
|
-
description: "Get midpoint price for a market"
|
|
16586
|
-
},
|
|
16587
|
-
midpoints: {
|
|
16588
|
-
toolName: "outcomes_get_market_midpoints",
|
|
16589
|
-
usage: "okx outcomes clob midpoints <id1,id2,...> [--json]",
|
|
16590
|
-
description: "Get midpoint prices for multiple markets (batch)"
|
|
16591
|
-
},
|
|
16592
|
-
spread: {
|
|
16593
|
-
toolName: "outcomes_get_market_spread",
|
|
16594
|
-
usage: "okx outcomes clob spread <mktId> [--json]",
|
|
16595
|
-
description: "Get bid-ask spread for a market"
|
|
16596
|
-
},
|
|
16597
|
-
spreads: {
|
|
16598
|
-
toolName: "outcomes_get_market_spreads",
|
|
16599
|
-
usage: "okx outcomes clob spreads <id1,id2,...> [--json]",
|
|
16600
|
-
description: "Get bid-ask spreads for multiple markets (batch)"
|
|
16601
|
-
},
|
|
16602
|
-
book: {
|
|
16603
|
-
toolName: "outcomes_get_order_book",
|
|
16604
|
-
usage: "okx outcomes clob book <mktId> [--sz <depth>] [--json]",
|
|
16605
|
-
description: "Get order book for a prediction market"
|
|
16606
|
-
},
|
|
16607
|
-
books: {
|
|
16608
|
-
toolName: "outcomes_get_order_books",
|
|
16609
|
-
usage: "okx outcomes clob books <id1,id2,...> [--sz <depth>] [--json]",
|
|
16610
|
-
description: "Get order books for multiple markets (batch)"
|
|
16611
|
-
},
|
|
16612
|
-
order: {
|
|
16613
|
-
toolName: "outcomes_get_order_detail",
|
|
16614
|
-
usage: "okx outcomes clob order <id> [--json]",
|
|
16615
|
-
description: "Get details of a specific prediction market order (alias for account order)"
|
|
16616
|
-
},
|
|
16617
|
-
orders: {
|
|
16618
|
-
toolName: "outcomes_get_account_orders",
|
|
16619
|
-
usage: "okx outcomes clob orders [--status <open|closed>] [--after <cursor>] [--limit <n>] [--json]",
|
|
16620
|
-
description: "List prediction market orders (alias for account orders)"
|
|
16621
|
-
},
|
|
16622
|
-
trades: {
|
|
16623
|
-
toolName: "outcomes_get_account_trades",
|
|
16624
|
-
usage: "okx outcomes clob trades [--after <cursor>] [--limit <n>] [--json]",
|
|
16625
|
-
description: "List prediction market trades (alias for account trades)"
|
|
16626
|
-
}
|
|
16627
|
-
}
|
|
16628
|
-
},
|
|
16629
|
-
account: {
|
|
16630
|
-
description: "Prediction market account balance, orders, positions, and trades",
|
|
16631
|
-
commands: {
|
|
16632
|
-
balance: {
|
|
16633
|
-
toolName: "outcomes_get_account_balance",
|
|
16634
|
-
usage: "okx outcomes account balance [--json]",
|
|
16635
|
-
description: "Get prediction market account balance"
|
|
16636
|
-
},
|
|
16637
|
-
order: {
|
|
16638
|
-
toolName: "outcomes_get_order_detail",
|
|
16639
|
-
usage: "okx outcomes account order <id> [--json]",
|
|
16640
|
-
description: "Get details of a specific prediction market order"
|
|
16641
|
-
},
|
|
16642
|
-
orders: {
|
|
16643
|
-
toolName: "outcomes_get_account_orders",
|
|
16644
|
-
usage: "okx outcomes account orders [--status <open|closed>] [--after <cursor>] [--limit <n>] [--json]",
|
|
16645
|
-
description: "List prediction market orders"
|
|
16646
|
-
},
|
|
16647
|
-
positions: {
|
|
16648
|
-
toolName: "outcomes_get_account_positions",
|
|
16649
|
-
usage: "okx outcomes account positions [--status <open|closed>] [--instId <mktId>] [--after <cursor>] [--limit <n>] [--json]",
|
|
16650
|
-
description: "List prediction market positions"
|
|
16651
|
-
},
|
|
16652
|
-
trades: {
|
|
16653
|
-
toolName: "outcomes_get_account_trades",
|
|
16654
|
-
usage: "okx outcomes account trades [--after <cursor>] [--limit <n>] [--json]",
|
|
16655
|
-
description: "List prediction market account trades"
|
|
16656
|
-
}
|
|
16657
|
-
}
|
|
16658
|
-
}
|
|
16659
|
-
}
|
|
16660
|
-
},
|
|
16661
16047
|
// ── config ─────────────────────────────────────────────────────────────────
|
|
16662
16048
|
config: {
|
|
16663
16049
|
description: "Manage CLI configuration profiles",
|
|
@@ -17478,8 +16864,10 @@ var CLI_OPTIONS = {
|
|
|
17478
16864
|
quoteCcy: { type: "string" },
|
|
17479
16865
|
// account extras
|
|
17480
16866
|
archive: { type: "boolean", default: false },
|
|
17481
|
-
valuation: { type: "boolean"
|
|
16867
|
+
valuation: { type: "boolean" },
|
|
16868
|
+
aggregate: { type: "boolean" },
|
|
17482
16869
|
valuationCcy: { type: "string" },
|
|
16870
|
+
accounts: { type: "string" },
|
|
17483
16871
|
posMode: { type: "string" },
|
|
17484
16872
|
ccy: { type: "string" },
|
|
17485
16873
|
from: { type: "string" },
|
|
@@ -17626,9 +17014,6 @@ var CLI_OPTIONS = {
|
|
|
17626
17014
|
settleCcy: { type: "string" },
|
|
17627
17015
|
ts: { type: "string" },
|
|
17628
17016
|
minAbsOiDeltaPct: { type: "string" },
|
|
17629
|
-
// outcomes module
|
|
17630
|
-
category: { type: "string" },
|
|
17631
|
-
league: { type: "string" },
|
|
17632
17017
|
// diagnostics - cli/mcp/all/output are diagnose-specific; verbose is shared
|
|
17633
17018
|
verbose: { type: "boolean", default: false },
|
|
17634
17019
|
mcp: { type: "boolean", default: false },
|
|
@@ -18351,6 +17736,88 @@ async function cmdAccountTransfer(run, opts) {
|
|
|
18351
17736
|
const r = data?.[0];
|
|
18352
17737
|
outputLine(`Transfer: ${r?.["transId"]} (${r?.["ccy"]} ${r?.["amt"]})`);
|
|
18353
17738
|
}
|
|
17739
|
+
async function cmdAccountBalanceAll(run, ccy, opts) {
|
|
17740
|
+
const result = await run("account_get_balance_all", {
|
|
17741
|
+
...ccy ? { ccy } : {},
|
|
17742
|
+
...opts.accounts ? { accounts: opts.accounts } : {},
|
|
17743
|
+
showValuation: !opts.noValuation,
|
|
17744
|
+
...opts.preferParallel ? { preferParallel: true } : {},
|
|
17745
|
+
...opts.valuationCcy ? { valuationCcy: opts.valuationCcy } : {}
|
|
17746
|
+
});
|
|
17747
|
+
if (opts.json) return printJson(result);
|
|
17748
|
+
const meta = result.meta;
|
|
17749
|
+
if (meta?.partialFailure) {
|
|
17750
|
+
outputLine("[PARTIAL] Some balance queries failed \u2014 results may be incomplete.");
|
|
17751
|
+
outputLine("");
|
|
17752
|
+
}
|
|
17753
|
+
const trading = result.trading;
|
|
17754
|
+
if (trading) {
|
|
17755
|
+
if (trading.available) {
|
|
17756
|
+
outputLine("=== Trading Account ===");
|
|
17757
|
+
outputLine(`Total Equity: ${String(trading["totalEq"] ?? "0")}`);
|
|
17758
|
+
const details = trading.details ?? [];
|
|
17759
|
+
const rows = details.filter((d) => Number(d["eq"] ?? d["bal"] ?? 0) > 0).map((d) => ({
|
|
17760
|
+
ccy: d["ccy"],
|
|
17761
|
+
equity: d["eq"] ?? d["bal"],
|
|
17762
|
+
available: d["availEq"] ?? d["availBal"],
|
|
17763
|
+
frozen: d["frozenBal"]
|
|
17764
|
+
}));
|
|
17765
|
+
if (rows.length > 0) printTable(rows);
|
|
17766
|
+
} else {
|
|
17767
|
+
const error = trading.error;
|
|
17768
|
+
outputLine(`=== Trading Account === [ERROR: ${error?.msg ?? "unavailable"}]`);
|
|
17769
|
+
}
|
|
17770
|
+
outputLine("");
|
|
17771
|
+
}
|
|
17772
|
+
const funding = result.funding;
|
|
17773
|
+
if (funding) {
|
|
17774
|
+
if (funding.available) {
|
|
17775
|
+
outputLine("=== Funding Account ===");
|
|
17776
|
+
const details = funding.details ?? [];
|
|
17777
|
+
const rows = details.filter((d) => Number(d["bal"] ?? 0) > 0).map((d) => ({
|
|
17778
|
+
ccy: d["ccy"],
|
|
17779
|
+
balance: d["bal"],
|
|
17780
|
+
available: d["availBal"],
|
|
17781
|
+
frozen: d["frozenBal"]
|
|
17782
|
+
}));
|
|
17783
|
+
if (rows.length > 0) printTable(rows);
|
|
17784
|
+
else outputLine("(no non-zero balances)");
|
|
17785
|
+
} else {
|
|
17786
|
+
const error = funding.error;
|
|
17787
|
+
outputLine(`=== Funding Account === [ERROR: ${error?.msg ?? "unavailable"}]`);
|
|
17788
|
+
}
|
|
17789
|
+
outputLine("");
|
|
17790
|
+
}
|
|
17791
|
+
const valuation = result.valuation;
|
|
17792
|
+
if (valuation) {
|
|
17793
|
+
if (valuation.available) {
|
|
17794
|
+
outputLine(`=== Valuation (${String(valuation.valuationCcy ?? "USDT")}) ===`);
|
|
17795
|
+
printKv({ totalBal: valuation.totalBal });
|
|
17796
|
+
const details = valuation.details ?? [];
|
|
17797
|
+
if (details.length > 0) {
|
|
17798
|
+
const first = details[0];
|
|
17799
|
+
const breakdown = first?.["details"] ?? {};
|
|
17800
|
+
if (Object.keys(breakdown).length > 0) {
|
|
17801
|
+
printKv(breakdown);
|
|
17802
|
+
}
|
|
17803
|
+
}
|
|
17804
|
+
} else {
|
|
17805
|
+
const error = valuation.error;
|
|
17806
|
+
outputLine(`=== Valuation === [ERROR: ${error?.msg ?? "unavailable"}]`);
|
|
17807
|
+
}
|
|
17808
|
+
}
|
|
17809
|
+
const source = meta?.source;
|
|
17810
|
+
if (source) {
|
|
17811
|
+
const site = meta?.site;
|
|
17812
|
+
const elapsed = meta?.elapsedMs;
|
|
17813
|
+
let line = `[source: ${source}`;
|
|
17814
|
+
if (site) line += `, site: ${site}`;
|
|
17815
|
+
if (elapsed !== void 0) line += `, ${String(elapsed)}ms`;
|
|
17816
|
+
line += "]";
|
|
17817
|
+
outputLine("");
|
|
17818
|
+
outputLine(line);
|
|
17819
|
+
}
|
|
17820
|
+
}
|
|
18354
17821
|
function readAuditLogs(logDir, days = 7) {
|
|
18355
17822
|
const entries = [];
|
|
18356
17823
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -21997,186 +21464,10 @@ async function cmdEventCancel(run, opts) {
|
|
|
21997
21464
|
`);
|
|
21998
21465
|
}
|
|
21999
21466
|
|
|
22000
|
-
// src/commands/outcomes.ts
|
|
22001
|
-
function getData10(result) {
|
|
22002
|
-
return result.data;
|
|
22003
|
-
}
|
|
22004
|
-
async function cmdOutcomesEvents(run, opts) {
|
|
22005
|
-
const result = await run("outcomes_get_events", {
|
|
22006
|
-
status: opts.status,
|
|
22007
|
-
category: opts.category,
|
|
22008
|
-
tag: opts.tag,
|
|
22009
|
-
league: opts.league,
|
|
22010
|
-
sort: opts.sort,
|
|
22011
|
-
cursor: opts.cursor,
|
|
22012
|
-
limit: opts.limit
|
|
22013
|
-
});
|
|
22014
|
-
const data = getData10(result);
|
|
22015
|
-
if (opts.json) return printJson(data);
|
|
22016
|
-
printTable(Array.isArray(data) ? data : []);
|
|
22017
|
-
}
|
|
22018
|
-
async function cmdOutcomesEventDetail(run, id, opts) {
|
|
22019
|
-
const result = await run("outcomes_get_event_detail", { id });
|
|
22020
|
-
const data = getData10(result);
|
|
22021
|
-
if (opts.json) return printJson(data);
|
|
22022
|
-
printTable(Array.isArray(data) ? data : [data]);
|
|
22023
|
-
}
|
|
22024
|
-
async function cmdOutcomesEventMarkets(run, id, opts) {
|
|
22025
|
-
const result = await run("outcomes_get_event_markets", { id });
|
|
22026
|
-
const data = getData10(result);
|
|
22027
|
-
if (opts.json) return printJson(data);
|
|
22028
|
-
printTable(Array.isArray(data) ? data : []);
|
|
22029
|
-
}
|
|
22030
|
-
async function cmdOutcomesMarketDetail(run, id, opts) {
|
|
22031
|
-
const result = await run("outcomes_get_market_detail", { id });
|
|
22032
|
-
const data = getData10(result);
|
|
22033
|
-
if (opts.json) return printJson(data);
|
|
22034
|
-
printTable(Array.isArray(data) ? data : [data]);
|
|
22035
|
-
}
|
|
22036
|
-
async function cmdOutcomesTrending(run, opts) {
|
|
22037
|
-
const result = await run("outcomes_get_trending_events", {
|
|
22038
|
-
cursor: opts.cursor,
|
|
22039
|
-
limit: opts.limit
|
|
22040
|
-
});
|
|
22041
|
-
const data = getData10(result);
|
|
22042
|
-
if (opts.json) return printJson(data);
|
|
22043
|
-
printTable(Array.isArray(data) ? data : []);
|
|
22044
|
-
}
|
|
22045
|
-
async function cmdOutcomesTicker(run, assetId, opts) {
|
|
22046
|
-
const result = await run("outcomes_get_ticker", { assetId });
|
|
22047
|
-
const data = getData10(result);
|
|
22048
|
-
if (opts.json) return printJson(data);
|
|
22049
|
-
printTable(Array.isArray(data) ? data : [data]);
|
|
22050
|
-
}
|
|
22051
|
-
async function cmdOutcomesCandles(run, assetId, opts) {
|
|
22052
|
-
const result = await run("outcomes_get_candles", {
|
|
22053
|
-
assetId,
|
|
22054
|
-
bar: opts.bar,
|
|
22055
|
-
after: opts.after,
|
|
22056
|
-
before: opts.before,
|
|
22057
|
-
limit: opts.limit
|
|
22058
|
-
});
|
|
22059
|
-
const data = getData10(result);
|
|
22060
|
-
if (opts.json) return printJson(data);
|
|
22061
|
-
printTable(Array.isArray(data) ? data : []);
|
|
22062
|
-
}
|
|
22063
|
-
async function cmdOutcomesSearch(run, keyword, opts) {
|
|
22064
|
-
const result = await run("outcomes_search_events", {
|
|
22065
|
-
keyword,
|
|
22066
|
-
cursor: opts.cursor,
|
|
22067
|
-
limit: opts.limit
|
|
22068
|
-
});
|
|
22069
|
-
const data = getData10(result);
|
|
22070
|
-
if (opts.json) return printJson(data);
|
|
22071
|
-
printTable(Array.isArray(data) ? data : []);
|
|
22072
|
-
}
|
|
22073
|
-
async function cmdOutcomesClobPrice(run, mktId, opts) {
|
|
22074
|
-
const result = await run("outcomes_get_market_price", {
|
|
22075
|
-
mktId,
|
|
22076
|
-
outcome: opts.outcome
|
|
22077
|
-
});
|
|
22078
|
-
const data = getData10(result);
|
|
22079
|
-
if (opts.json) return printJson(data);
|
|
22080
|
-
printTable(data ? [data] : []);
|
|
22081
|
-
}
|
|
22082
|
-
async function cmdOutcomesClobPrices(run, ids, opts) {
|
|
22083
|
-
const result = await run("outcomes_get_market_prices", {
|
|
22084
|
-
ids,
|
|
22085
|
-
outcome: opts.outcome
|
|
22086
|
-
});
|
|
22087
|
-
const data = getData10(result);
|
|
22088
|
-
if (opts.json) return printJson(data);
|
|
22089
|
-
printTable(Array.isArray(data) ? data : []);
|
|
22090
|
-
}
|
|
22091
|
-
async function cmdOutcomesClobMidpoint(run, mktId, opts) {
|
|
22092
|
-
const result = await run("outcomes_get_market_midpoint", { mktId });
|
|
22093
|
-
const data = getData10(result);
|
|
22094
|
-
if (opts.json) return printJson(data);
|
|
22095
|
-
printTable(data ? [data] : []);
|
|
22096
|
-
}
|
|
22097
|
-
async function cmdOutcomesClobMidpoints(run, ids, opts) {
|
|
22098
|
-
const result = await run("outcomes_get_market_midpoints", { ids });
|
|
22099
|
-
const data = getData10(result);
|
|
22100
|
-
if (opts.json) return printJson(data);
|
|
22101
|
-
printTable(Array.isArray(data) ? data : []);
|
|
22102
|
-
}
|
|
22103
|
-
async function cmdOutcomesClobSpread(run, mktId, opts) {
|
|
22104
|
-
const result = await run("outcomes_get_market_spread", { mktId });
|
|
22105
|
-
const data = getData10(result);
|
|
22106
|
-
if (opts.json) return printJson(data);
|
|
22107
|
-
printTable(data ? [data] : []);
|
|
22108
|
-
}
|
|
22109
|
-
async function cmdOutcomesClobSpreads(run, ids, opts) {
|
|
22110
|
-
const result = await run("outcomes_get_market_spreads", { ids });
|
|
22111
|
-
const data = getData10(result);
|
|
22112
|
-
if (opts.json) return printJson(data);
|
|
22113
|
-
printTable(Array.isArray(data) ? data : []);
|
|
22114
|
-
}
|
|
22115
|
-
async function cmdOutcomesClobBook(run, mktId, opts) {
|
|
22116
|
-
const result = await run("outcomes_get_order_book", {
|
|
22117
|
-
mktId,
|
|
22118
|
-
sz: opts.sz
|
|
22119
|
-
});
|
|
22120
|
-
const data = getData10(result);
|
|
22121
|
-
if (opts.json) return printJson(data);
|
|
22122
|
-
printTable(Array.isArray(data) ? data : [data]);
|
|
22123
|
-
}
|
|
22124
|
-
async function cmdOutcomesClobBooks(run, ids, opts) {
|
|
22125
|
-
const result = await run("outcomes_get_order_books", {
|
|
22126
|
-
ids,
|
|
22127
|
-
sz: opts.sz
|
|
22128
|
-
});
|
|
22129
|
-
const data = getData10(result);
|
|
22130
|
-
if (opts.json) return printJson(data);
|
|
22131
|
-
printTable(Array.isArray(data) ? data : []);
|
|
22132
|
-
}
|
|
22133
|
-
async function cmdOutcomesAccountBalance(run, opts) {
|
|
22134
|
-
const result = await run("outcomes_get_account_balance", {});
|
|
22135
|
-
const data = getData10(result);
|
|
22136
|
-
if (opts.json) return printJson(data);
|
|
22137
|
-
printTable(Array.isArray(data) ? data : [data]);
|
|
22138
|
-
}
|
|
22139
|
-
async function cmdOutcomesAccountOrderDetail(run, id, opts) {
|
|
22140
|
-
const result = await run("outcomes_get_order_detail", { id });
|
|
22141
|
-
const data = getData10(result);
|
|
22142
|
-
if (opts.json) return printJson(data);
|
|
22143
|
-
printTable(Array.isArray(data) ? data : [data]);
|
|
22144
|
-
}
|
|
22145
|
-
async function cmdOutcomesAccountOrders(run, opts) {
|
|
22146
|
-
const result = await run("outcomes_get_account_orders", {
|
|
22147
|
-
status: opts.status,
|
|
22148
|
-
cursor: opts.cursor,
|
|
22149
|
-
limit: opts.limit
|
|
22150
|
-
});
|
|
22151
|
-
const data = getData10(result);
|
|
22152
|
-
if (opts.json) return printJson(data);
|
|
22153
|
-
printTable(Array.isArray(data) ? data : []);
|
|
22154
|
-
}
|
|
22155
|
-
async function cmdOutcomesAccountPositions(run, opts) {
|
|
22156
|
-
const result = await run("outcomes_get_account_positions", {
|
|
22157
|
-
status: opts.status,
|
|
22158
|
-
market: opts.market,
|
|
22159
|
-
cursor: opts.cursor,
|
|
22160
|
-
limit: opts.limit
|
|
22161
|
-
});
|
|
22162
|
-
const data = getData10(result);
|
|
22163
|
-
if (opts.json) return printJson(data);
|
|
22164
|
-
printTable(Array.isArray(data) ? data : []);
|
|
22165
|
-
}
|
|
22166
|
-
async function cmdOutcomesAccountTrades(run, opts) {
|
|
22167
|
-
const result = await run("outcomes_get_account_trades", {
|
|
22168
|
-
cursor: opts.cursor,
|
|
22169
|
-
limit: opts.limit
|
|
22170
|
-
});
|
|
22171
|
-
const data = getData10(result);
|
|
22172
|
-
if (opts.json) return printJson(data);
|
|
22173
|
-
printTable(Array.isArray(data) ? data : []);
|
|
22174
|
-
}
|
|
22175
|
-
|
|
22176
21467
|
// src/index.ts
|
|
22177
21468
|
var _require3 = createRequire3(import.meta.url);
|
|
22178
21469
|
var CLI_VERSION2 = _require3("../package.json").version;
|
|
22179
|
-
var GIT_HASH2 = true ? "
|
|
21470
|
+
var GIT_HASH2 = true ? "9beb3ee8" : "dev";
|
|
22180
21471
|
function handlePilotCommand(action, json, force, binaryPath) {
|
|
22181
21472
|
if (action === "status") return cmdPilotStatus(json, binaryPath);
|
|
22182
21473
|
if (action === "install") return cmdPilotInstall(json, binaryPath);
|
|
@@ -22363,6 +21654,7 @@ function handleAccountWriteCommand(run, action, v, json) {
|
|
|
22363
21654
|
unknownSubcommand("account", action, [
|
|
22364
21655
|
"audit",
|
|
22365
21656
|
"balance",
|
|
21657
|
+
"balance-all",
|
|
22366
21658
|
"asset-balance",
|
|
22367
21659
|
"positions",
|
|
22368
21660
|
"positions-history",
|
|
@@ -22381,6 +21673,14 @@ function handleAccountCommand(run, action, rest, v, json) {
|
|
|
22381
21673
|
return cmdAccountAudit({ limit: v.limit, tool: v.tool, since: v.since, json });
|
|
22382
21674
|
const limit = v.limit !== void 0 ? Number(v.limit) : void 0;
|
|
22383
21675
|
if (action === "balance") return cmdAccountBalance(run, rest[0], json);
|
|
21676
|
+
if (action === "balance-all")
|
|
21677
|
+
return cmdAccountBalanceAll(run, v.ccy ?? rest[0], {
|
|
21678
|
+
accounts: v.accounts,
|
|
21679
|
+
noValuation: v.valuation === false,
|
|
21680
|
+
preferParallel: v.aggregate === false,
|
|
21681
|
+
valuationCcy: v.valuationCcy,
|
|
21682
|
+
json
|
|
21683
|
+
});
|
|
22384
21684
|
if (action === "asset-balance") return cmdAccountAssetBalance(run, v.ccy, json, v.valuation, v.valuationCcy);
|
|
22385
21685
|
if (action === "positions")
|
|
22386
21686
|
return cmdAccountPositions(run, { instType: v.instType, instId: v.instId, json });
|
|
@@ -23570,102 +22870,6 @@ function handleEventCommand(run, action, rest, v, json) {
|
|
|
23570
22870
|
`);
|
|
23571
22871
|
process.exitCode = 1;
|
|
23572
22872
|
}
|
|
23573
|
-
function handleOutcomesCommand(run, module, rest, v, json) {
|
|
23574
|
-
const sub = rest[0];
|
|
23575
|
-
const subRest = rest.slice(1);
|
|
23576
|
-
const limit = v.limit !== void 0 ? Number(v.limit) : void 0;
|
|
23577
|
-
if (module === "data") {
|
|
23578
|
-
if (sub === "events")
|
|
23579
|
-
return cmdOutcomesEvents(run, {
|
|
23580
|
-
status: v.status,
|
|
23581
|
-
category: v.category,
|
|
23582
|
-
tag: v.tag,
|
|
23583
|
-
league: v.league,
|
|
23584
|
-
sort: v.sortBy,
|
|
23585
|
-
cursor: v.after,
|
|
23586
|
-
limit,
|
|
23587
|
-
json
|
|
23588
|
-
});
|
|
23589
|
-
if (sub === "event")
|
|
23590
|
-
return cmdOutcomesEventDetail(run, subRest[0] ?? "", { json });
|
|
23591
|
-
if (sub === "event-markets")
|
|
23592
|
-
return cmdOutcomesEventMarkets(run, subRest[0] ?? "", { json });
|
|
23593
|
-
if (sub === "market")
|
|
23594
|
-
return cmdOutcomesMarketDetail(run, subRest[0] ?? "", { json });
|
|
23595
|
-
if (sub === "trending")
|
|
23596
|
-
return cmdOutcomesTrending(run, { cursor: v.after, limit, json });
|
|
23597
|
-
if (sub === "ticker")
|
|
23598
|
-
return cmdOutcomesTicker(run, subRest[0] ?? "", { json });
|
|
23599
|
-
if (sub === "candles")
|
|
23600
|
-
return cmdOutcomesCandles(run, subRest[0] ?? "", {
|
|
23601
|
-
bar: v.bar,
|
|
23602
|
-
after: v.after,
|
|
23603
|
-
before: v.before,
|
|
23604
|
-
limit,
|
|
23605
|
-
json
|
|
23606
|
-
});
|
|
23607
|
-
errorLine(`Unknown outcomes data command: ${sub ?? "(none)"}`);
|
|
23608
|
-
errorLine("Valid: events, event, event-markets, market, trending, ticker, candles");
|
|
23609
|
-
process.exitCode = 1;
|
|
23610
|
-
return;
|
|
23611
|
-
}
|
|
23612
|
-
if (module === "search") {
|
|
23613
|
-
const keyword = sub ?? "";
|
|
23614
|
-
return cmdOutcomesSearch(run, keyword, { cursor: v.after, limit, json });
|
|
23615
|
-
}
|
|
23616
|
-
if (module === "clob") {
|
|
23617
|
-
const mktId = subRest[0] ?? "";
|
|
23618
|
-
const parseIds = (raw) => raw.split(",").map((s) => s.trim()).filter(Boolean);
|
|
23619
|
-
if (sub === "price")
|
|
23620
|
-
return cmdOutcomesClobPrice(run, mktId, { outcome: v.outcome, json });
|
|
23621
|
-
if (sub === "prices")
|
|
23622
|
-
return cmdOutcomesClobPrices(run, parseIds(subRest[0] ?? ""), { outcome: v.outcome, json });
|
|
23623
|
-
if (sub === "midpoint")
|
|
23624
|
-
return cmdOutcomesClobMidpoint(run, mktId, { json });
|
|
23625
|
-
if (sub === "midpoints")
|
|
23626
|
-
return cmdOutcomesClobMidpoints(run, parseIds(subRest[0] ?? ""), { json });
|
|
23627
|
-
if (sub === "spread")
|
|
23628
|
-
return cmdOutcomesClobSpread(run, mktId, { json });
|
|
23629
|
-
if (sub === "spreads")
|
|
23630
|
-
return cmdOutcomesClobSpreads(run, parseIds(subRest[0] ?? ""), { json });
|
|
23631
|
-
if (sub === "book")
|
|
23632
|
-
return cmdOutcomesClobBook(run, mktId, { sz: v.sz !== void 0 ? Number(v.sz) : void 0, json });
|
|
23633
|
-
if (sub === "books")
|
|
23634
|
-
return cmdOutcomesClobBooks(run, parseIds(subRest[0] ?? ""), { sz: v.sz !== void 0 ? Number(v.sz) : void 0, json });
|
|
23635
|
-
if (sub === "order")
|
|
23636
|
-
return cmdOutcomesAccountOrderDetail(run, subRest[0] ?? "", { json });
|
|
23637
|
-
if (sub === "orders")
|
|
23638
|
-
return cmdOutcomesAccountOrders(run, { status: v.status, cursor: v.after, limit, json });
|
|
23639
|
-
if (sub === "trades")
|
|
23640
|
-
return cmdOutcomesAccountTrades(run, { cursor: v.after, limit, json });
|
|
23641
|
-
errorLine(`Unknown outcomes clob command: ${sub ?? "(none)"}`);
|
|
23642
|
-
errorLine("Valid: price, prices, midpoint, midpoints, spread, spreads, book, books, order, orders, trades");
|
|
23643
|
-
process.exitCode = 1;
|
|
23644
|
-
return;
|
|
23645
|
-
}
|
|
23646
|
-
if (module === "account") {
|
|
23647
|
-
if (sub === "balance")
|
|
23648
|
-
return cmdOutcomesAccountBalance(run, { json });
|
|
23649
|
-
if (sub === "order")
|
|
23650
|
-
return cmdOutcomesAccountOrderDetail(run, subRest[0] ?? "", { json });
|
|
23651
|
-
if (sub === "orders")
|
|
23652
|
-
return cmdOutcomesAccountOrders(run, { status: v.status, cursor: v.after, limit, json });
|
|
23653
|
-
if (sub === "positions")
|
|
23654
|
-
return cmdOutcomesAccountPositions(run, { status: v.status, market: v.instId, cursor: v.after, limit, json });
|
|
23655
|
-
if (sub === "trades")
|
|
23656
|
-
return cmdOutcomesAccountTrades(run, { cursor: v.after, limit, json });
|
|
23657
|
-
errorLine(`Unknown outcomes account command: ${sub ?? "(none)"}`);
|
|
23658
|
-
errorLine("Valid: balance, order, orders, positions, trades");
|
|
23659
|
-
process.exitCode = 1;
|
|
23660
|
-
return;
|
|
23661
|
-
}
|
|
23662
|
-
if (module === "wallet") {
|
|
23663
|
-
throw new Error("Coming in Phase 2");
|
|
23664
|
-
}
|
|
23665
|
-
errorLine(`Unknown outcomes module: ${module}`);
|
|
23666
|
-
errorLine("Valid: data, search, clob, account, wallet");
|
|
23667
|
-
process.exitCode = 1;
|
|
23668
|
-
}
|
|
23669
22873
|
function outputResult(result, json) {
|
|
23670
22874
|
if (json) {
|
|
23671
22875
|
outputLine(JSON.stringify(result, null, 2));
|
|
@@ -23778,7 +22982,6 @@ async function main() {
|
|
|
23778
22982
|
bot: () => handleBotCommand(run, action, rest, v, json),
|
|
23779
22983
|
earn: () => handleEarnCommand(run, action, rest, v, json),
|
|
23780
22984
|
smartmoney: () => handleSmartmoneyCommand(run, action, rest, v, json),
|
|
23781
|
-
outcomes: () => handleOutcomesCommand(run, action, rest, v, json),
|
|
23782
22985
|
skill: () => handleSkillCommand(run, action, rest, v, json, config)
|
|
23783
22986
|
};
|
|
23784
22987
|
const handler = moduleHandlers[module];
|
|
@@ -23812,7 +23015,6 @@ export {
|
|
|
23812
23015
|
handleNewsCommand,
|
|
23813
23016
|
handleOptionAlgoCommand,
|
|
23814
23017
|
handleOptionCommand,
|
|
23815
|
-
handleOutcomesCommand,
|
|
23816
23018
|
handlePilotCommand,
|
|
23817
23019
|
handleSetupCommand,
|
|
23818
23020
|
handleSkillCommand,
|