@okx_ai/okx-trade-cli 1.3.2 → 1.3.3-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 +2021 -532
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/scripts/postinstall.js +1 -1
package/dist/index.js
CHANGED
|
@@ -1988,6 +1988,16 @@ function readBoolean(args, key) {
|
|
|
1988
1988
|
}
|
|
1989
1989
|
return value;
|
|
1990
1990
|
}
|
|
1991
|
+
function readStringArray(args, key) {
|
|
1992
|
+
const value = args[key];
|
|
1993
|
+
if (value === void 0 || value === null) {
|
|
1994
|
+
return void 0;
|
|
1995
|
+
}
|
|
1996
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
|
|
1997
|
+
throw new ValidationError(`Parameter "${key}" must be an array of strings.`);
|
|
1998
|
+
}
|
|
1999
|
+
return value;
|
|
2000
|
+
}
|
|
1991
2001
|
function requireString(args, key) {
|
|
1992
2002
|
const value = readString(args, key);
|
|
1993
2003
|
if (!value || value.length === 0) {
|
|
@@ -2028,12 +2038,170 @@ function validateSwapInstId(instId) {
|
|
|
2028
2038
|
);
|
|
2029
2039
|
}
|
|
2030
2040
|
}
|
|
2041
|
+
var TP_ORD_KIND_SCHEMA = {
|
|
2042
|
+
type: "string",
|
|
2043
|
+
enum: ["condition", "limit"],
|
|
2044
|
+
description: "condition(default)=trigger-based TP; limit=immediate limit order (no trigger phase)"
|
|
2045
|
+
};
|
|
2046
|
+
var TP_TRIGGER_PX_TYPE_SCHEMA = {
|
|
2047
|
+
type: "string",
|
|
2048
|
+
enum: ["last", "index", "mark"],
|
|
2049
|
+
description: "TP trigger price source: last(default)|index|mark"
|
|
2050
|
+
};
|
|
2051
|
+
var SL_TRIGGER_PX_TYPE_SCHEMA = {
|
|
2052
|
+
type: "string",
|
|
2053
|
+
enum: ["last", "index", "mark"],
|
|
2054
|
+
description: "SL trigger price source: last(default)|index|mark"
|
|
2055
|
+
};
|
|
2056
|
+
var STP_MODE_SCHEMA = {
|
|
2057
|
+
type: "string",
|
|
2058
|
+
enum: ["cancel_maker", "cancel_taker", "cancel_both"],
|
|
2059
|
+
description: "Self-trade prevention: cancel_maker|cancel_taker|cancel_both"
|
|
2060
|
+
};
|
|
2061
|
+
var CXL_ON_CLOSE_POS_SCHEMA = {
|
|
2062
|
+
type: "boolean",
|
|
2063
|
+
description: "Auto-cancel TP/SL when associated position closes (algo only)"
|
|
2064
|
+
};
|
|
2065
|
+
var PHASE1_PLACE_FLAGS_SCHEMA = {
|
|
2066
|
+
tpOrdKind: TP_ORD_KIND_SCHEMA,
|
|
2067
|
+
tpTriggerPxType: TP_TRIGGER_PX_TYPE_SCHEMA,
|
|
2068
|
+
slTriggerPxType: SL_TRIGGER_PX_TYPE_SCHEMA,
|
|
2069
|
+
stpMode: STP_MODE_SCHEMA
|
|
2070
|
+
};
|
|
2071
|
+
var PHASE1_ALGO_FLAGS_SCHEMA = {
|
|
2072
|
+
...PHASE1_PLACE_FLAGS_SCHEMA,
|
|
2073
|
+
cxlOnClosePos: CXL_ON_CLOSE_POS_SCHEMA
|
|
2074
|
+
};
|
|
2075
|
+
var TRIGGER_FLAGS_SCHEMA = {
|
|
2076
|
+
triggerPx: {
|
|
2077
|
+
type: "string",
|
|
2078
|
+
description: "Activation price; order submits when market hits this level (trigger only)"
|
|
2079
|
+
},
|
|
2080
|
+
orderPx: {
|
|
2081
|
+
type: "string",
|
|
2082
|
+
description: "Order price submitted when trigger fires; -1=market (trigger only)"
|
|
2083
|
+
},
|
|
2084
|
+
advanceOrdType: {
|
|
2085
|
+
type: "string",
|
|
2086
|
+
enum: ["fok", "ioc"],
|
|
2087
|
+
description: "Execution qualifier for triggered order: fok=fill-or-kill, ioc=immediate-or-cancel (trigger only)"
|
|
2088
|
+
},
|
|
2089
|
+
triggerPxType: {
|
|
2090
|
+
type: "string",
|
|
2091
|
+
enum: ["last", "index", "mark"],
|
|
2092
|
+
description: "Price type used to evaluate trigger: last(default)|index|mark (trigger only)"
|
|
2093
|
+
}
|
|
2094
|
+
};
|
|
2095
|
+
var CHASE_FLAGS_SCHEMA = {
|
|
2096
|
+
chaseType: {
|
|
2097
|
+
type: "string",
|
|
2098
|
+
enum: ["distance", "ratio"],
|
|
2099
|
+
description: "Chase unit: distance=price ticks, ratio=proportion of price (chase only, default distance)"
|
|
2100
|
+
},
|
|
2101
|
+
chaseVal: {
|
|
2102
|
+
type: "string",
|
|
2103
|
+
description: "Chase amount matching chaseType (e.g. 0.5 ticks for distance, 0.001 for ratio) (chase only)"
|
|
2104
|
+
},
|
|
2105
|
+
maxChaseType: {
|
|
2106
|
+
type: "string",
|
|
2107
|
+
enum: ["distance", "ratio"],
|
|
2108
|
+
description: "Upper-bound unit for chase (chase only)"
|
|
2109
|
+
},
|
|
2110
|
+
maxChaseVal: {
|
|
2111
|
+
type: "string",
|
|
2112
|
+
description: "Upper-bound value for chase (chase only)"
|
|
2113
|
+
}
|
|
2114
|
+
};
|
|
2115
|
+
var ICEBERG_TWAP_FLAGS_SCHEMA = {
|
|
2116
|
+
pxVar: {
|
|
2117
|
+
type: "string",
|
|
2118
|
+
description: "Price variance % [0.0001, 0.01]; provide pxVar OR pxSpread (iceberg/twap only)"
|
|
2119
|
+
},
|
|
2120
|
+
pxSpread: {
|
|
2121
|
+
type: "string",
|
|
2122
|
+
description: "Price variance constant >= 0; provide pxVar OR pxSpread (iceberg/twap only)"
|
|
2123
|
+
},
|
|
2124
|
+
szLimit: {
|
|
2125
|
+
type: "string",
|
|
2126
|
+
description: "Average per-child-order size (iceberg/twap only)"
|
|
2127
|
+
},
|
|
2128
|
+
pxLimit: {
|
|
2129
|
+
type: "string",
|
|
2130
|
+
description: "Order price ceiling >= 0 (iceberg/twap only)"
|
|
2131
|
+
},
|
|
2132
|
+
timeInterval: {
|
|
2133
|
+
type: "string",
|
|
2134
|
+
description: "Seconds between child orders (iceberg/twap only)"
|
|
2135
|
+
}
|
|
2136
|
+
};
|
|
2137
|
+
function buildTriggerOrdTypeBody(args) {
|
|
2138
|
+
return compactObject({
|
|
2139
|
+
triggerPx: readString(args, "triggerPx"),
|
|
2140
|
+
orderPx: readString(args, "orderPx"),
|
|
2141
|
+
advanceOrdType: readString(args, "advanceOrdType"),
|
|
2142
|
+
triggerPxType: readString(args, "triggerPxType"),
|
|
2143
|
+
attachAlgoOrds: buildAttachAlgoOrds(args)
|
|
2144
|
+
});
|
|
2145
|
+
}
|
|
2146
|
+
function buildChaseOrdTypeBody(args) {
|
|
2147
|
+
return compactObject({
|
|
2148
|
+
chaseType: readString(args, "chaseType"),
|
|
2149
|
+
chaseVal: readString(args, "chaseVal"),
|
|
2150
|
+
maxChaseType: readString(args, "maxChaseType"),
|
|
2151
|
+
maxChaseVal: readString(args, "maxChaseVal")
|
|
2152
|
+
});
|
|
2153
|
+
}
|
|
2154
|
+
function buildIcebergTwapOrdTypeBody(args) {
|
|
2155
|
+
return compactObject({
|
|
2156
|
+
pxVar: readString(args, "pxVar"),
|
|
2157
|
+
pxSpread: readString(args, "pxSpread"),
|
|
2158
|
+
szLimit: readString(args, "szLimit"),
|
|
2159
|
+
pxLimit: readString(args, "pxLimit"),
|
|
2160
|
+
timeInterval: readString(args, "timeInterval")
|
|
2161
|
+
});
|
|
2162
|
+
}
|
|
2163
|
+
function buildAlgoConditionalCommonFields(args) {
|
|
2164
|
+
return {
|
|
2165
|
+
tpTriggerPx: readString(args, "tpTriggerPx"),
|
|
2166
|
+
tpOrdPx: readString(args, "tpOrdPx"),
|
|
2167
|
+
tpOrdKind: readString(args, "tpOrdKind"),
|
|
2168
|
+
tpTriggerPxType: readString(args, "tpTriggerPxType"),
|
|
2169
|
+
tpTriggerRatio: readString(args, "tpTriggerRatio"),
|
|
2170
|
+
slTriggerPx: readString(args, "slTriggerPx"),
|
|
2171
|
+
slOrdPx: readString(args, "slOrdPx"),
|
|
2172
|
+
slTriggerPxType: readString(args, "slTriggerPxType"),
|
|
2173
|
+
slTriggerRatio: readString(args, "slTriggerRatio"),
|
|
2174
|
+
closeFraction: readString(args, "closeFraction"),
|
|
2175
|
+
activePx: readString(args, "activePx")
|
|
2176
|
+
};
|
|
2177
|
+
}
|
|
2031
2178
|
function buildAttachAlgoOrds(source) {
|
|
2179
|
+
const tpLevels = source["tpLevels"];
|
|
2180
|
+
if (Array.isArray(tpLevels) && tpLevels.length > 0) {
|
|
2181
|
+
return tpLevels.map(
|
|
2182
|
+
(level) => compactObject(level)
|
|
2183
|
+
);
|
|
2184
|
+
}
|
|
2032
2185
|
const tpTriggerPx = readString(source, "tpTriggerPx");
|
|
2033
2186
|
const tpOrdPx = readString(source, "tpOrdPx");
|
|
2034
2187
|
const slTriggerPx = readString(source, "slTriggerPx");
|
|
2035
2188
|
const slOrdPx = readString(source, "slOrdPx");
|
|
2036
|
-
const
|
|
2189
|
+
const tpOrdKind = readString(source, "tpOrdKind");
|
|
2190
|
+
const tpTriggerPxType = readString(source, "tpTriggerPxType");
|
|
2191
|
+
const slTriggerPxType = readString(source, "slTriggerPxType");
|
|
2192
|
+
const tpTriggerRatio = readString(source, "tpTriggerRatio");
|
|
2193
|
+
const slTriggerRatio = readString(source, "slTriggerRatio");
|
|
2194
|
+
const entry = compactObject({
|
|
2195
|
+
tpTriggerPx,
|
|
2196
|
+
tpOrdPx,
|
|
2197
|
+
slTriggerPx,
|
|
2198
|
+
slOrdPx,
|
|
2199
|
+
tpOrdKind,
|
|
2200
|
+
tpTriggerPxType,
|
|
2201
|
+
slTriggerPxType,
|
|
2202
|
+
tpTriggerRatio,
|
|
2203
|
+
slTriggerRatio
|
|
2204
|
+
});
|
|
2037
2205
|
return Object.keys(entry).length > 0 ? [entry] : void 0;
|
|
2038
2206
|
}
|
|
2039
2207
|
var OKX_CANDLE_BARS = [
|
|
@@ -3108,7 +3276,7 @@ function registerAlgoTradeTools() {
|
|
|
3108
3276
|
{
|
|
3109
3277
|
name: "swap_place_algo_order",
|
|
3110
3278
|
module: "swap",
|
|
3111
|
-
description: "Place a SWAP/FUTURES algo order
|
|
3279
|
+
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 \u2014 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.",
|
|
3112
3280
|
isWrite: true,
|
|
3113
3281
|
inputSchema: {
|
|
3114
3282
|
type: "object",
|
|
@@ -3134,8 +3302,8 @@ function registerAlgoTradeTools() {
|
|
|
3134
3302
|
},
|
|
3135
3303
|
ordType: {
|
|
3136
3304
|
type: "string",
|
|
3137
|
-
enum: ["conditional", "oco", "move_order_stop"],
|
|
3138
|
-
description: "conditional=single TP/SL or both; oco=TP+SL pair
|
|
3305
|
+
enum: ["conditional", "oco", "move_order_stop", "trigger", "chase", "iceberg", "twap"],
|
|
3306
|
+
description: "conditional=single TP/SL or both; oco=TP+SL pair; move_order_stop=trailing stop; trigger=pending order; chase=follow best bid/ask; iceberg=split order; twap=time-weighted split"
|
|
3139
3307
|
},
|
|
3140
3308
|
sz: {
|
|
3141
3309
|
type: "string",
|
|
@@ -3149,11 +3317,8 @@ function registerAlgoTradeTools() {
|
|
|
3149
3317
|
type: "string",
|
|
3150
3318
|
description: "TP order price; -1=market (conditional/oco only)"
|
|
3151
3319
|
},
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
enum: ["last", "index", "mark"],
|
|
3155
|
-
description: "last(default)|index|mark (conditional/oco only)"
|
|
3156
|
-
},
|
|
3320
|
+
tpOrdKind: TP_ORD_KIND_SCHEMA,
|
|
3321
|
+
tpTriggerPxType: TP_TRIGGER_PX_TYPE_SCHEMA,
|
|
3157
3322
|
slTriggerPx: {
|
|
3158
3323
|
type: "string",
|
|
3159
3324
|
description: "SL trigger price (conditional/oco only)"
|
|
@@ -3162,11 +3327,9 @@ function registerAlgoTradeTools() {
|
|
|
3162
3327
|
type: "string",
|
|
3163
3328
|
description: "SL order price; -1=market (recommended) (conditional/oco only)"
|
|
3164
3329
|
},
|
|
3165
|
-
slTriggerPxType:
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
description: "last(default)|index|mark (conditional/oco only)"
|
|
3169
|
-
},
|
|
3330
|
+
slTriggerPxType: SL_TRIGGER_PX_TYPE_SCHEMA,
|
|
3331
|
+
stpMode: STP_MODE_SCHEMA,
|
|
3332
|
+
cxlOnClosePos: CXL_ON_CLOSE_POS_SCHEMA,
|
|
3170
3333
|
callbackRatio: {
|
|
3171
3334
|
type: "string",
|
|
3172
3335
|
description: "Callback ratio (e.g. '0.01'=1%); provide either ratio or spread (move_order_stop only)"
|
|
@@ -3179,6 +3342,9 @@ function registerAlgoTradeTools() {
|
|
|
3179
3342
|
type: "string",
|
|
3180
3343
|
description: "Activation price; tracking starts after market reaches this level (move_order_stop only)"
|
|
3181
3344
|
},
|
|
3345
|
+
...TRIGGER_FLAGS_SCHEMA,
|
|
3346
|
+
...CHASE_FLAGS_SCHEMA,
|
|
3347
|
+
...ICEBERG_TWAP_FLAGS_SCHEMA,
|
|
3182
3348
|
tgtCcy: {
|
|
3183
3349
|
type: "string",
|
|
3184
3350
|
enum: ["base_ccy", "quote_ccy", "margin"],
|
|
@@ -3198,6 +3364,8 @@ function registerAlgoTradeTools() {
|
|
|
3198
3364
|
handler: async (rawArgs, context) => {
|
|
3199
3365
|
const args = asRecord(rawArgs);
|
|
3200
3366
|
const reduceOnly = args.reduceOnly;
|
|
3367
|
+
const cxlOnClosePos = args.cxlOnClosePos;
|
|
3368
|
+
const ordType = requireString(args, "ordType");
|
|
3201
3369
|
const resolved = await resolveQuoteCcySz(
|
|
3202
3370
|
requireString(args, "instId"),
|
|
3203
3371
|
requireString(args, "sz"),
|
|
@@ -3206,29 +3374,44 @@ function registerAlgoTradeTools() {
|
|
|
3206
3374
|
context.client,
|
|
3207
3375
|
readString(args, "tdMode")
|
|
3208
3376
|
);
|
|
3377
|
+
const base = compactObject({
|
|
3378
|
+
instId: requireString(args, "instId"),
|
|
3379
|
+
tdMode: requireString(args, "tdMode"),
|
|
3380
|
+
side: requireString(args, "side"),
|
|
3381
|
+
posSide: readString(args, "posSide"),
|
|
3382
|
+
ordType,
|
|
3383
|
+
sz: resolved.sz,
|
|
3384
|
+
tgtCcy: resolved.tgtCcy,
|
|
3385
|
+
stpMode: readString(args, "stpMode"),
|
|
3386
|
+
cxlOnClosePos: typeof cxlOnClosePos === "boolean" ? String(cxlOnClosePos) : void 0,
|
|
3387
|
+
reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
|
|
3388
|
+
clOrdId: readString(args, "clOrdId"),
|
|
3389
|
+
// Phase 3a+c CLI power-user flags (issue #182, CLI-only no MCP/skill exposure)
|
|
3390
|
+
pxAmendType: readString(args, "pxAmendType"),
|
|
3391
|
+
tag: context.config.sourceTag
|
|
3392
|
+
});
|
|
3393
|
+
switch (ordType) {
|
|
3394
|
+
case "trigger":
|
|
3395
|
+
Object.assign(base, buildTriggerOrdTypeBody(args));
|
|
3396
|
+
break;
|
|
3397
|
+
case "chase":
|
|
3398
|
+
Object.assign(base, buildChaseOrdTypeBody(args));
|
|
3399
|
+
break;
|
|
3400
|
+
case "iceberg":
|
|
3401
|
+
case "twap":
|
|
3402
|
+
Object.assign(base, buildIcebergTwapOrdTypeBody(args));
|
|
3403
|
+
break;
|
|
3404
|
+
default:
|
|
3405
|
+
Object.assign(base, compactObject({
|
|
3406
|
+
...buildAlgoConditionalCommonFields(args),
|
|
3407
|
+
callBackRatio: readString(args, "callbackRatio"),
|
|
3408
|
+
callBackSpread: readString(args, "callbackSpread")
|
|
3409
|
+
}));
|
|
3410
|
+
break;
|
|
3411
|
+
}
|
|
3209
3412
|
const response = await context.client.privatePost(
|
|
3210
3413
|
"/api/v5/trade/order-algo",
|
|
3211
|
-
|
|
3212
|
-
instId: requireString(args, "instId"),
|
|
3213
|
-
tdMode: requireString(args, "tdMode"),
|
|
3214
|
-
side: requireString(args, "side"),
|
|
3215
|
-
posSide: readString(args, "posSide"),
|
|
3216
|
-
ordType: requireString(args, "ordType"),
|
|
3217
|
-
sz: resolved.sz,
|
|
3218
|
-
tgtCcy: resolved.tgtCcy,
|
|
3219
|
-
tpTriggerPx: readString(args, "tpTriggerPx"),
|
|
3220
|
-
tpOrdPx: readString(args, "tpOrdPx"),
|
|
3221
|
-
tpTriggerPxType: readString(args, "tpTriggerPxType"),
|
|
3222
|
-
slTriggerPx: readString(args, "slTriggerPx"),
|
|
3223
|
-
slOrdPx: readString(args, "slOrdPx"),
|
|
3224
|
-
slTriggerPxType: readString(args, "slTriggerPxType"),
|
|
3225
|
-
callBackRatio: readString(args, "callbackRatio"),
|
|
3226
|
-
callBackSpread: readString(args, "callbackSpread"),
|
|
3227
|
-
activePx: readString(args, "activePx"),
|
|
3228
|
-
reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
|
|
3229
|
-
clOrdId: readString(args, "clOrdId"),
|
|
3230
|
-
tag: context.config.sourceTag
|
|
3231
|
-
}),
|
|
3414
|
+
base,
|
|
3232
3415
|
privateRateLimit("swap_place_algo_order", 20)
|
|
3233
3416
|
);
|
|
3234
3417
|
const result = normalizeResponse(response);
|
|
@@ -3453,7 +3636,7 @@ function registerFuturesAlgoTools() {
|
|
|
3453
3636
|
{
|
|
3454
3637
|
name: "futures_place_algo_order",
|
|
3455
3638
|
module: "futures",
|
|
3456
|
-
description: "Place a FUTURES delivery algo order
|
|
3639
|
+
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 \u2014 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.",
|
|
3457
3640
|
isWrite: true,
|
|
3458
3641
|
inputSchema: {
|
|
3459
3642
|
type: "object",
|
|
@@ -3479,8 +3662,8 @@ function registerFuturesAlgoTools() {
|
|
|
3479
3662
|
},
|
|
3480
3663
|
ordType: {
|
|
3481
3664
|
type: "string",
|
|
3482
|
-
enum: ["conditional", "oco", "move_order_stop"],
|
|
3483
|
-
description: "conditional=single TP/SL or both; oco=TP+SL pair; move_order_stop=trailing stop"
|
|
3665
|
+
enum: ["conditional", "oco", "move_order_stop", "trigger", "chase", "iceberg", "twap"],
|
|
3666
|
+
description: "conditional=single TP/SL or both; oco=TP+SL pair; move_order_stop=trailing stop; trigger=pending order; chase=follow best bid/ask; iceberg=split order; twap=time-weighted split"
|
|
3484
3667
|
},
|
|
3485
3668
|
sz: {
|
|
3486
3669
|
type: "string",
|
|
@@ -3494,11 +3677,8 @@ function registerFuturesAlgoTools() {
|
|
|
3494
3677
|
type: "string",
|
|
3495
3678
|
description: "TP order price; -1=market (conditional/oco only)"
|
|
3496
3679
|
},
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
enum: ["last", "index", "mark"],
|
|
3500
|
-
description: "last(default)|index|mark (conditional/oco only)"
|
|
3501
|
-
},
|
|
3680
|
+
tpOrdKind: TP_ORD_KIND_SCHEMA,
|
|
3681
|
+
tpTriggerPxType: TP_TRIGGER_PX_TYPE_SCHEMA,
|
|
3502
3682
|
slTriggerPx: {
|
|
3503
3683
|
type: "string",
|
|
3504
3684
|
description: "SL trigger price (conditional/oco only)"
|
|
@@ -3507,11 +3687,9 @@ function registerFuturesAlgoTools() {
|
|
|
3507
3687
|
type: "string",
|
|
3508
3688
|
description: "SL order price; -1=market (conditional/oco only)"
|
|
3509
3689
|
},
|
|
3510
|
-
slTriggerPxType:
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
description: "last(default)|index|mark (conditional/oco only)"
|
|
3514
|
-
},
|
|
3690
|
+
slTriggerPxType: SL_TRIGGER_PX_TYPE_SCHEMA,
|
|
3691
|
+
stpMode: STP_MODE_SCHEMA,
|
|
3692
|
+
cxlOnClosePos: CXL_ON_CLOSE_POS_SCHEMA,
|
|
3515
3693
|
callbackRatio: {
|
|
3516
3694
|
type: "string",
|
|
3517
3695
|
description: "Callback ratio (e.g. '0.01'=1%); provide either ratio or spread (move_order_stop only)"
|
|
@@ -3524,6 +3702,9 @@ function registerFuturesAlgoTools() {
|
|
|
3524
3702
|
type: "string",
|
|
3525
3703
|
description: "Activation price; tracking starts after market reaches this level (move_order_stop only)"
|
|
3526
3704
|
},
|
|
3705
|
+
...TRIGGER_FLAGS_SCHEMA,
|
|
3706
|
+
...CHASE_FLAGS_SCHEMA,
|
|
3707
|
+
...ICEBERG_TWAP_FLAGS_SCHEMA,
|
|
3527
3708
|
tgtCcy: {
|
|
3528
3709
|
type: "string",
|
|
3529
3710
|
enum: ["base_ccy", "quote_ccy", "margin"],
|
|
@@ -3543,6 +3724,8 @@ function registerFuturesAlgoTools() {
|
|
|
3543
3724
|
handler: async (rawArgs, context) => {
|
|
3544
3725
|
const args = asRecord(rawArgs);
|
|
3545
3726
|
const reduceOnly = args.reduceOnly;
|
|
3727
|
+
const cxlOnClosePos = args.cxlOnClosePos;
|
|
3728
|
+
const ordType = requireString(args, "ordType");
|
|
3546
3729
|
const resolved = await resolveQuoteCcySz(
|
|
3547
3730
|
requireString(args, "instId"),
|
|
3548
3731
|
requireString(args, "sz"),
|
|
@@ -3551,29 +3734,44 @@ function registerFuturesAlgoTools() {
|
|
|
3551
3734
|
context.client,
|
|
3552
3735
|
readString(args, "tdMode")
|
|
3553
3736
|
);
|
|
3737
|
+
const base = compactObject({
|
|
3738
|
+
instId: requireString(args, "instId"),
|
|
3739
|
+
tdMode: requireString(args, "tdMode"),
|
|
3740
|
+
side: requireString(args, "side"),
|
|
3741
|
+
posSide: readString(args, "posSide"),
|
|
3742
|
+
ordType,
|
|
3743
|
+
sz: resolved.sz,
|
|
3744
|
+
tgtCcy: resolved.tgtCcy,
|
|
3745
|
+
stpMode: readString(args, "stpMode"),
|
|
3746
|
+
cxlOnClosePos: typeof cxlOnClosePos === "boolean" ? String(cxlOnClosePos) : void 0,
|
|
3747
|
+
reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
|
|
3748
|
+
clOrdId: readString(args, "clOrdId"),
|
|
3749
|
+
// Phase 3a+c CLI power-user flags (issue #182, CLI-only no MCP/skill exposure)
|
|
3750
|
+
pxAmendType: readString(args, "pxAmendType"),
|
|
3751
|
+
tag: context.config.sourceTag
|
|
3752
|
+
});
|
|
3753
|
+
switch (ordType) {
|
|
3754
|
+
case "trigger":
|
|
3755
|
+
Object.assign(base, buildTriggerOrdTypeBody(args));
|
|
3756
|
+
break;
|
|
3757
|
+
case "chase":
|
|
3758
|
+
Object.assign(base, buildChaseOrdTypeBody(args));
|
|
3759
|
+
break;
|
|
3760
|
+
case "iceberg":
|
|
3761
|
+
case "twap":
|
|
3762
|
+
Object.assign(base, buildIcebergTwapOrdTypeBody(args));
|
|
3763
|
+
break;
|
|
3764
|
+
default:
|
|
3765
|
+
Object.assign(base, compactObject({
|
|
3766
|
+
...buildAlgoConditionalCommonFields(args),
|
|
3767
|
+
callBackRatio: readString(args, "callbackRatio"),
|
|
3768
|
+
callBackSpread: readString(args, "callbackSpread")
|
|
3769
|
+
}));
|
|
3770
|
+
break;
|
|
3771
|
+
}
|
|
3554
3772
|
const response = await context.client.privatePost(
|
|
3555
3773
|
"/api/v5/trade/order-algo",
|
|
3556
|
-
|
|
3557
|
-
instId: requireString(args, "instId"),
|
|
3558
|
-
tdMode: requireString(args, "tdMode"),
|
|
3559
|
-
side: requireString(args, "side"),
|
|
3560
|
-
posSide: readString(args, "posSide"),
|
|
3561
|
-
ordType: requireString(args, "ordType"),
|
|
3562
|
-
sz: resolved.sz,
|
|
3563
|
-
tgtCcy: resolved.tgtCcy,
|
|
3564
|
-
tpTriggerPx: readString(args, "tpTriggerPx"),
|
|
3565
|
-
tpOrdPx: readString(args, "tpOrdPx"),
|
|
3566
|
-
tpTriggerPxType: readString(args, "tpTriggerPxType"),
|
|
3567
|
-
slTriggerPx: readString(args, "slTriggerPx"),
|
|
3568
|
-
slOrdPx: readString(args, "slOrdPx"),
|
|
3569
|
-
slTriggerPxType: readString(args, "slTriggerPxType"),
|
|
3570
|
-
callBackRatio: readString(args, "callbackRatio"),
|
|
3571
|
-
callBackSpread: readString(args, "callbackSpread"),
|
|
3572
|
-
activePx: readString(args, "activePx"),
|
|
3573
|
-
reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
|
|
3574
|
-
clOrdId: readString(args, "clOrdId"),
|
|
3575
|
-
tag: context.config.sourceTag
|
|
3576
|
-
}),
|
|
3774
|
+
base,
|
|
3577
3775
|
privateRateLimit("futures_place_algo_order", 20)
|
|
3578
3776
|
);
|
|
3579
3777
|
const result = normalizeResponse(response);
|
|
@@ -6156,6 +6354,23 @@ function resolveOutcome(value) {
|
|
|
6156
6354
|
}
|
|
6157
6355
|
return resolved;
|
|
6158
6356
|
}
|
|
6357
|
+
async function withConcurrency(items, maxConcurrency, fn) {
|
|
6358
|
+
const results = new Array(items.length);
|
|
6359
|
+
let nextIndex = 0;
|
|
6360
|
+
async function runNext() {
|
|
6361
|
+
while (nextIndex < items.length) {
|
|
6362
|
+
const idx = nextIndex++;
|
|
6363
|
+
try {
|
|
6364
|
+
results[idx] = { status: "fulfilled", value: await fn(items[idx]) };
|
|
6365
|
+
} catch (err) {
|
|
6366
|
+
results[idx] = { status: "rejected", reason: err };
|
|
6367
|
+
}
|
|
6368
|
+
}
|
|
6369
|
+
}
|
|
6370
|
+
const workers = Array.from({ length: Math.min(maxConcurrency, items.length) }, runNext);
|
|
6371
|
+
await Promise.all(workers);
|
|
6372
|
+
return results;
|
|
6373
|
+
}
|
|
6159
6374
|
function filterBrowseCandidates(allSeries, underlyingFilter) {
|
|
6160
6375
|
const isHumanReadable = (id) => /^(BTC|ETH|TRX|EOS|SOL|IOTA|KISHU|SUSHI|BTG|XTZ|SOLVU)-/.test(id);
|
|
6161
6376
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -6296,6 +6511,7 @@ function handlePlaceOrderError(base, rawArgs, endpoint) {
|
|
|
6296
6511
|
}
|
|
6297
6512
|
throw new OkxApiError(`[${sCode}] ${sMsg}`, { code: sCode, endpoint });
|
|
6298
6513
|
}
|
|
6514
|
+
var MAX_CONCURRENT_MARKET_FETCHES = 8;
|
|
6299
6515
|
var OUTCOME_SCHEMA = {
|
|
6300
6516
|
type: "string",
|
|
6301
6517
|
enum: ["UP", "YES", "DOWN", "NO"],
|
|
@@ -6335,10 +6551,15 @@ function registerEventContractTools() {
|
|
|
6335
6551
|
const normalizedSeries = normalizeResponse(seriesResp);
|
|
6336
6552
|
const allSeries = Array.isArray(normalizedSeries["data"]) ? normalizedSeries["data"] : [];
|
|
6337
6553
|
const candidates = filterBrowseCandidates(allSeries, underlyingFilter);
|
|
6338
|
-
const
|
|
6339
|
-
candidates
|
|
6554
|
+
const settled = await withConcurrency(
|
|
6555
|
+
candidates,
|
|
6556
|
+
MAX_CONCURRENT_MARKET_FETCHES,
|
|
6557
|
+
(s) => fetchActiveContractsForSeries(context.client, s)
|
|
6340
6558
|
);
|
|
6341
|
-
const
|
|
6559
|
+
const fulfilled = settled.filter(
|
|
6560
|
+
(r) => r.status === "fulfilled" && r.value !== null
|
|
6561
|
+
);
|
|
6562
|
+
const results = fulfilled.map((r) => r.value);
|
|
6342
6563
|
return {
|
|
6343
6564
|
data: results,
|
|
6344
6565
|
total: results.reduce((n, r) => n + (r?.contracts?.length ?? 0), 0)
|
|
@@ -6758,379 +6979,1106 @@ function registerEventContractTools() {
|
|
|
6758
6979
|
}
|
|
6759
6980
|
];
|
|
6760
6981
|
}
|
|
6982
|
+
var SMARTMONEY_RPS = 5;
|
|
6761
6983
|
var PATH_LEADERBOARD = "/api/v5/orbit/public/leaderboard";
|
|
6762
6984
|
var PATH_POSITION_CURRENT = "/api/v5/orbit/public/position-current";
|
|
6985
|
+
var PATH_POSITION_HISTORY = "/api/v5/orbit/public/position-history";
|
|
6763
6986
|
var PATH_TRADE_RECORDS = "/api/v5/orbit/public/trade-records";
|
|
6987
|
+
var PATH_TOP_TRADER_SEARCH = "/api/v5/orbit/top-trader-search";
|
|
6764
6988
|
var PATH_OVERVIEW = "/api/v5/journal/smartmoney/overview";
|
|
6765
|
-
var PATH_SIGNAL = "/api/v5/journal/smartmoney/signal";
|
|
6766
6989
|
var PATH_SIGNAL_HISTORY = "/api/v5/journal/smartmoney/signal-history";
|
|
6990
|
+
var PERIOD_DAYS = ["3", "7", "30", "90"];
|
|
6767
6991
|
var SIGNAL_POOL_FILTER_PROPS = {
|
|
6768
|
-
|
|
6992
|
+
sortBy: {
|
|
6769
6993
|
type: "string",
|
|
6770
|
-
|
|
6994
|
+
enum: ["pnl", "pnlRatio"],
|
|
6995
|
+
default: "pnl",
|
|
6996
|
+
description: "Ranking key used to pick traders into the aggregation pool. `pnl` = absolute USD profit (favors high-AUM whales); `pnlRatio` = percentage return (favors small-but-efficient traders)."
|
|
6771
6997
|
},
|
|
6772
6998
|
period: {
|
|
6773
6999
|
type: "string",
|
|
6774
|
-
|
|
7000
|
+
enum: PERIOD_DAYS,
|
|
7001
|
+
default: "7",
|
|
7002
|
+
description: 'Lookback window in days. Pass as a quoted string: `"3"` / `"7"` / `"30"` / `"90"` (NOT integer 7). Drives capability metrics (avgLongWinRate / avgShortWinRate) and the `winRateTier` filter. Does NOT affect signal fields (which always use the latest snapshot).'
|
|
6775
7003
|
},
|
|
6776
|
-
|
|
7004
|
+
pnlTier: {
|
|
6777
7005
|
type: "string",
|
|
6778
|
-
|
|
7006
|
+
enum: ["PNL_ANY", "PNL_TOP50", "PNL_TOP20", "PNL_TOP5"],
|
|
7007
|
+
default: "PNL_ANY",
|
|
7008
|
+
description: "PnL percentile gate applied on top of `sortBy`. ANY = no filter; TOP50 = PnL \u2265 P50 (median); TOP20 = \u2265 P80; TOP5 = \u2265 P95. PnL distribution is long-tailed \u2014 use percentile, not absolute thresholds."
|
|
6779
7009
|
},
|
|
6780
|
-
|
|
7010
|
+
winRateTier: {
|
|
6781
7011
|
type: "string",
|
|
6782
|
-
|
|
7012
|
+
enum: ["WR_ANY", "WR_GE_50", "WR_GE_80"],
|
|
7013
|
+
default: "WR_ANY",
|
|
7014
|
+
description: "Minimum win-rate gate (fixed thresholds). ANY = no filter; WR_GE_50 = \u2265 50%; WR_GE_80 = \u2265 80%."
|
|
6783
7015
|
},
|
|
6784
|
-
|
|
7016
|
+
maxDrawdownTier: {
|
|
6785
7017
|
type: "string",
|
|
6786
|
-
|
|
7018
|
+
enum: ["MR_ANY", "MR_LE_20", "MR_LE_50"],
|
|
7019
|
+
default: "MR_ANY",
|
|
7020
|
+
description: "Maximum-drawdown gate (fixed thresholds; smaller drawdown = lower risk). ANY = no filter; MR_LE_20 = drawdown \u2264 20%; MR_LE_50 = \u2264 50%."
|
|
6787
7021
|
},
|
|
6788
|
-
|
|
7022
|
+
aumTier: {
|
|
6789
7023
|
type: "string",
|
|
6790
|
-
|
|
7024
|
+
enum: ["AUM_ANY", "AUM_TOP50", "AUM_TOP20", "AUM_TOP5"],
|
|
7025
|
+
default: "AUM_ANY",
|
|
7026
|
+
description: "AUM (Assets Under Management) percentile gate. ANY = no filter; TOP50 = AUM \u2265 P50; TOP20 = \u2265 P80; TOP5 = \u2265 P95. AUM is long-tailed \u2014 use percentile, not absolute USD."
|
|
6791
7027
|
}
|
|
6792
7028
|
};
|
|
6793
7029
|
var LEADERBOARD_POOL_FILTER_PROPS = {
|
|
6794
|
-
|
|
7030
|
+
sortBy: {
|
|
6795
7031
|
type: "string",
|
|
6796
|
-
|
|
7032
|
+
enum: ["pnl", "pnlRatio"],
|
|
7033
|
+
default: "pnl",
|
|
7034
|
+
description: "Leaderboard sort key. `pnl` = absolute USD profit; `pnlRatio` = percentage return."
|
|
6797
7035
|
},
|
|
6798
7036
|
period: {
|
|
6799
7037
|
type: "string",
|
|
6800
|
-
|
|
7038
|
+
enum: PERIOD_DAYS,
|
|
7039
|
+
default: "90",
|
|
7040
|
+
description: 'Performance lookback window in days. Pass as a quoted string: `"3"` / `"7"` / `"30"` / `"90"` (NOT integer 90). Default `"90"` (matches leaderboard UI). Filters AND ranks traders by their PnL over that window.'
|
|
6801
7041
|
},
|
|
6802
|
-
|
|
7042
|
+
minPnl: {
|
|
6803
7043
|
type: "string",
|
|
6804
|
-
description:
|
|
7044
|
+
description: 'Minimum absolute PnL in USD. Pass as a quoted numeric string, e.g. `"10000"` (NOT integer 10000) \u2192 traders with PnL \u2265 $10,000. Numeric threshold \u2014 distinct from the signal-side `pnlTier` percentile enum.'
|
|
6805
7045
|
},
|
|
6806
|
-
|
|
7046
|
+
minWinRate: {
|
|
6807
7047
|
type: "string",
|
|
6808
|
-
description: "
|
|
7048
|
+
description: 'Minimum win-rate as decimal in 0~1 range. Pass as a quoted numeric string, e.g. `"0.8"` (NOT number 0.8) \u2192 traders with win-rate \u2265 80%. Numeric threshold \u2014 distinct from the signal-side `winRateTier` enum.'
|
|
6809
7049
|
},
|
|
6810
|
-
|
|
7050
|
+
maxDrawdown: {
|
|
6811
7051
|
type: "string",
|
|
6812
|
-
description: "
|
|
7052
|
+
description: 'Maximum drawdown as decimal. Pass as a quoted numeric string, e.g. `"0.1"` (NOT number 0.1) \u2192 traders with drawdown \u2264 10%. Lower = lower risk. Numeric threshold \u2014 distinct from the signal-side `maxDrawdownTier` enum.'
|
|
6813
7053
|
},
|
|
6814
|
-
|
|
7054
|
+
minAum: {
|
|
6815
7055
|
type: "string",
|
|
6816
|
-
description:
|
|
7056
|
+
description: 'Minimum AUM (Assets Under Management) in USD. Pass as a quoted numeric string, e.g. `"1000"` (NOT integer 1000) \u2192 traders with AUM \u2265 $1,000. Numeric threshold \u2014 distinct from the signal-side `aumTier` percentile enum.'
|
|
6817
7057
|
}
|
|
6818
7058
|
};
|
|
6819
|
-
var
|
|
7059
|
+
var LEADERBOARD_FILTER_UPSTREAM_NAMES = {
|
|
7060
|
+
sortBy: "sortBy",
|
|
7061
|
+
period: "period",
|
|
7062
|
+
minPnl: "pnl",
|
|
7063
|
+
minWinRate: "winRate",
|
|
7064
|
+
maxDrawdown: "maxDrawdown",
|
|
7065
|
+
minAum: "asset"
|
|
7066
|
+
};
|
|
6820
7067
|
function readPoolFilters(args) {
|
|
6821
7068
|
const result = {};
|
|
6822
|
-
for (const
|
|
7069
|
+
for (const [publicKey, upstreamKey] of Object.entries(LEADERBOARD_FILTER_UPSTREAM_NAMES)) {
|
|
7070
|
+
const val = readString(args, publicKey);
|
|
7071
|
+
if (val !== void 0 && val !== "") result[upstreamKey] = val;
|
|
7072
|
+
}
|
|
7073
|
+
return result;
|
|
7074
|
+
}
|
|
7075
|
+
function readSignalPoolFilters(args) {
|
|
7076
|
+
const result = {};
|
|
7077
|
+
for (const key of Object.keys(SIGNAL_POOL_FILTER_PROPS)) {
|
|
6823
7078
|
const val = readString(args, key);
|
|
6824
7079
|
if (val) result[key] = val;
|
|
6825
7080
|
}
|
|
6826
7081
|
return result;
|
|
6827
7082
|
}
|
|
6828
|
-
function
|
|
6829
|
-
if (Array.isArray(data)) return data;
|
|
7083
|
+
function extractLeaderboardEnvelope(data) {
|
|
7084
|
+
if (Array.isArray(data)) return { items: data };
|
|
6830
7085
|
if (data && typeof data === "object") {
|
|
6831
|
-
const
|
|
6832
|
-
|
|
7086
|
+
const obj = data;
|
|
7087
|
+
const inner = obj.data;
|
|
7088
|
+
const updateTime = typeof obj.updateTime === "string" ? obj.updateTime : void 0;
|
|
7089
|
+
if (Array.isArray(inner)) return { items: inner, updateTime };
|
|
7090
|
+
}
|
|
7091
|
+
return { items: [] };
|
|
7092
|
+
}
|
|
7093
|
+
function deriveDirection(posSide, pos) {
|
|
7094
|
+
if (posSide === "long") return "long";
|
|
7095
|
+
if (posSide === "short") return "short";
|
|
7096
|
+
if (posSide === "both" && typeof pos === "string" && pos !== "") {
|
|
7097
|
+
const n = Number(pos);
|
|
7098
|
+
if (Number.isFinite(n) && n !== 0) return n > 0 ? "long" : "short";
|
|
7099
|
+
}
|
|
7100
|
+
return void 0;
|
|
7101
|
+
}
|
|
7102
|
+
function extractPositionData(data) {
|
|
7103
|
+
if (!Array.isArray(data) || data.length === 0) return [];
|
|
7104
|
+
const first = data[0];
|
|
7105
|
+
if (first && typeof first === "object") {
|
|
7106
|
+
const posData = first.posData;
|
|
7107
|
+
if (Array.isArray(posData)) {
|
|
7108
|
+
return posData.map((row) => {
|
|
7109
|
+
if (!row || typeof row !== "object") return row;
|
|
7110
|
+
const r = row;
|
|
7111
|
+
const direction = deriveDirection(r.posSide, r.pos);
|
|
7112
|
+
return direction ? { ...r, direction } : r;
|
|
7113
|
+
});
|
|
7114
|
+
}
|
|
6833
7115
|
}
|
|
6834
7116
|
return [];
|
|
6835
7117
|
}
|
|
7118
|
+
function buildPagination(data, effectiveLimit, cursorField) {
|
|
7119
|
+
const hasMore = data.length >= effectiveLimit;
|
|
7120
|
+
const last = data.length > 0 ? data[data.length - 1] : void 0;
|
|
7121
|
+
const nextAfter = hasMore && last && typeof last === "object" && last !== null ? last[cursorField] : void 0;
|
|
7122
|
+
return nextAfter !== void 0 ? { hasMore, nextAfter } : { hasMore };
|
|
7123
|
+
}
|
|
7124
|
+
function extractBaseCcy(instId) {
|
|
7125
|
+
if (!instId) return void 0;
|
|
7126
|
+
const idx = instId.indexOf("-");
|
|
7127
|
+
const base = idx === -1 ? instId : instId.slice(0, idx);
|
|
7128
|
+
return base || void 0;
|
|
7129
|
+
}
|
|
7130
|
+
function actionableError(message, hint) {
|
|
7131
|
+
return new ValidationError(`${message} ${hint}`);
|
|
7132
|
+
}
|
|
7133
|
+
function readArrayAsCsv(args, key) {
|
|
7134
|
+
const arr = readStringArray(args, key);
|
|
7135
|
+
if (!arr || arr.length === 0) return void 0;
|
|
7136
|
+
return arr.join(",");
|
|
7137
|
+
}
|
|
7138
|
+
function envelope(dataSchema, extras = {}) {
|
|
7139
|
+
return {
|
|
7140
|
+
type: "object",
|
|
7141
|
+
properties: {
|
|
7142
|
+
endpoint: {
|
|
7143
|
+
type: "string",
|
|
7144
|
+
description: "Upstream API path that produced this payload (debug/audit aid)."
|
|
7145
|
+
},
|
|
7146
|
+
requestTime: { type: "string", description: "ISO-8601 timestamp when the request was issued." },
|
|
7147
|
+
data: dataSchema,
|
|
7148
|
+
...extras
|
|
7149
|
+
},
|
|
7150
|
+
required: ["endpoint", "data"]
|
|
7151
|
+
};
|
|
7152
|
+
}
|
|
7153
|
+
var PAGINATION_PROP = {
|
|
7154
|
+
type: "object",
|
|
7155
|
+
description: "Cursor pagination metadata. Only emitted on list tools that support paging.",
|
|
7156
|
+
properties: {
|
|
7157
|
+
hasMore: {
|
|
7158
|
+
type: "boolean",
|
|
7159
|
+
description: "True when `data.length` reached the requested `limit` (more pages likely). False guarantees there are no more results after this page."
|
|
7160
|
+
},
|
|
7161
|
+
nextAfter: {
|
|
7162
|
+
type: "string",
|
|
7163
|
+
description: "Cursor to pass back as `after` on the next call to fetch the following page. Absent/empty when `hasMore` is false."
|
|
7164
|
+
}
|
|
7165
|
+
}
|
|
7166
|
+
};
|
|
7167
|
+
var TRADER_ITEM_PROPS = {
|
|
7168
|
+
authorId: { type: "string", description: "Trader's unique ID \u2014 pass to other smartmoney_get_trader_* tools." },
|
|
7169
|
+
nickName: { type: "string", description: "Display nickname." },
|
|
7170
|
+
pnl: { type: "string", description: "Absolute PnL in USD over the requested `period` (numeric string)." },
|
|
7171
|
+
pnlRatio: { type: "string", description: 'PnL as a decimal ratio over the requested `period` (e.g. "0.35" = +35%).' },
|
|
7172
|
+
asset: { type: "string", description: "AUM (Assets Under Management) in USD \u2014 same field that the input `minAum` filter applies to." },
|
|
7173
|
+
winRate: { type: "string", description: "Lifetime win-rate as a decimal (0~1)." },
|
|
7174
|
+
maxDrawdown: { type: "string", description: 'Max drawdown as a decimal (e.g. "0.2" = 20%). Lower = lower risk.' },
|
|
7175
|
+
onboardDuration: { type: "string", description: "Days the trader has been onboarded on the leaderboard (numeric string)." },
|
|
7176
|
+
portrait: { type: "string", description: "Avatar image URL." },
|
|
7177
|
+
rates: {
|
|
7178
|
+
type: "array",
|
|
7179
|
+
description: "Equity-curve / PnL-rate time series (one entry per day).",
|
|
7180
|
+
items: {
|
|
7181
|
+
type: "object",
|
|
7182
|
+
properties: {
|
|
7183
|
+
statTime: { type: "string", description: 'Date stamp in `YYMMDD` (e.g. "240726" = 2024-07-26).' },
|
|
7184
|
+
value: { type: "string", description: "Cumulative PnL ratio at that day (decimal)." }
|
|
7185
|
+
}
|
|
7186
|
+
}
|
|
7187
|
+
}
|
|
7188
|
+
};
|
|
7189
|
+
var SIGNAL_ITEM_PROPS = {
|
|
7190
|
+
ccy: { type: "string", description: "Instrument ID e.g. BTC-USDT-SWAP (outer identifier; the field name is `ccy`, not `instId`)." },
|
|
7191
|
+
dataVersion: {
|
|
7192
|
+
type: "string",
|
|
7193
|
+
description: "Snapshot version key in `yyyyMMddHH` UTC (10 digits, e.g. `2026043014` = 2026-04-30 14:00 UTC; floored to the hour)."
|
|
7194
|
+
},
|
|
7195
|
+
tradersWithPosition: {
|
|
7196
|
+
type: "integer",
|
|
7197
|
+
description: "Pool traders holding this asset at latest_snap (double-sided counted once). Higher = stronger consensus."
|
|
7198
|
+
},
|
|
7199
|
+
tradersQualified: {
|
|
7200
|
+
type: "integer",
|
|
7201
|
+
description: "Pool size after applying tier filters (incl. those without positions on this instrument)."
|
|
7202
|
+
},
|
|
7203
|
+
longTraders: { type: "integer", description: "Number of pool traders currently long this asset (incl. double-sided)." },
|
|
7204
|
+
shortTraders: { type: "integer", description: "Number of pool traders currently short this asset (incl. double-sided)." },
|
|
7205
|
+
notional: {
|
|
7206
|
+
type: "object",
|
|
7207
|
+
description: "Notional / capital-flow group.",
|
|
7208
|
+
properties: {
|
|
7209
|
+
longNotionalUsdt: { type: "string", description: "Sum of long-side notional in USDT." },
|
|
7210
|
+
shortNotionalUsdt: { type: "string", description: "Sum of short-side notional in USDT." },
|
|
7211
|
+
netNotionalUsdt: { type: "string", description: "Net directional notional in USDT = long \u2212 short." },
|
|
7212
|
+
totalNotionalUsdt: { type: "string", description: "Gross notional in USDT = long + short." },
|
|
7213
|
+
totalNotionalVs24h: {
|
|
7214
|
+
type: "string",
|
|
7215
|
+
description: "Capital-flow change ratio vs 24h: (curr \u2212 hist_24h) / hist_24h. Positive = smart money adding exposure; negative = retreating. NULL when hist=0."
|
|
7216
|
+
},
|
|
7217
|
+
smartMoneyLongAvgEntry: {
|
|
7218
|
+
type: "string",
|
|
7219
|
+
description: "Long-side notional-weighted average entry price (USDT). NULL when no long. Compare to current price to judge whether following the longs is cheap/expensive now."
|
|
7220
|
+
},
|
|
7221
|
+
smartMoneyShortAvgEntry: {
|
|
7222
|
+
type: "string",
|
|
7223
|
+
description: "Short-side notional-weighted average entry price (USDT). NULL when no short."
|
|
7224
|
+
}
|
|
7225
|
+
}
|
|
7226
|
+
},
|
|
7227
|
+
longShortRatio: {
|
|
7228
|
+
type: "object",
|
|
7229
|
+
description: "Long/short ratio + historical-delta group.",
|
|
7230
|
+
properties: {
|
|
7231
|
+
longRatioVs1h: { type: "string", description: "longRatio \u2212 hist_1h.longRatio. NULL when no hist." },
|
|
7232
|
+
longRatioVs24h: { type: "string", description: "longRatio \u2212 hist_24h.longRatio. NULL when no hist." },
|
|
7233
|
+
longRatioVs7d: { type: "string", description: "longRatio \u2212 hist_7d.longRatio. NULL when no hist." },
|
|
7234
|
+
longRatio: { type: "string", description: "Headcount long ratio = longTraders / tradersWithPosition. NULL when no traders." },
|
|
7235
|
+
shortRatio: { type: "string", description: "1 \u2212 longRatio. NULL when no traders." },
|
|
7236
|
+
weightedLongRatio: {
|
|
7237
|
+
type: "string",
|
|
7238
|
+
description: "Notional-weighted long ratio = \u03A3(long_notional) / \u03A3(notional). NULL when no notional."
|
|
7239
|
+
},
|
|
7240
|
+
weightedShortRatio: {
|
|
7241
|
+
type: "string",
|
|
7242
|
+
description: "Notional-weighted short ratio = \u03A3(short_notional) / \u03A3(notional). NULL when no notional."
|
|
7243
|
+
}
|
|
7244
|
+
}
|
|
7245
|
+
},
|
|
7246
|
+
winRate: {
|
|
7247
|
+
type: "object",
|
|
7248
|
+
description: "Capability (historical performance) group; driven by the `period` window.",
|
|
7249
|
+
properties: {
|
|
7250
|
+
avgLongWinRate: {
|
|
7251
|
+
type: "string",
|
|
7252
|
+
description: "Mean closed-position win-rate (full-market) over `period` days for users currently long. NULL when closed-position sample size is below the configured minimum."
|
|
7253
|
+
},
|
|
7254
|
+
avgShortWinRate: {
|
|
7255
|
+
type: "string",
|
|
7256
|
+
description: "Mean closed-position win-rate (full-market) over `period` days for users currently short. NULL when sample is below threshold."
|
|
7257
|
+
}
|
|
7258
|
+
}
|
|
7259
|
+
}
|
|
7260
|
+
};
|
|
7261
|
+
var SIGNAL_HISTORY_ITEM_PROPS = {
|
|
7262
|
+
ccy: { type: "string", description: "Base currency / instrument key for this bucket." },
|
|
7263
|
+
longRatio: {
|
|
7264
|
+
type: "string",
|
|
7265
|
+
description: "Headcount long ratio at this bucket. Decimal 0~1."
|
|
7266
|
+
},
|
|
7267
|
+
shortRatio: {
|
|
7268
|
+
type: "string",
|
|
7269
|
+
description: "Headcount short ratio at this bucket = 1 \u2212 longRatio. Decimal 0~1."
|
|
7270
|
+
},
|
|
7271
|
+
weightedLongRatio: {
|
|
7272
|
+
type: "string",
|
|
7273
|
+
description: "Notional-weighted long ratio at this bucket. Decimal 0~1."
|
|
7274
|
+
},
|
|
7275
|
+
weightedShortRatio: {
|
|
7276
|
+
type: "string",
|
|
7277
|
+
description: "Notional-weighted short ratio at this bucket. Decimal 0~1."
|
|
7278
|
+
},
|
|
7279
|
+
longTraders: {
|
|
7280
|
+
type: "integer",
|
|
7281
|
+
description: "Number of traders with long exposure at this bucket (includes dual-side traders)."
|
|
7282
|
+
},
|
|
7283
|
+
shortTraders: {
|
|
7284
|
+
type: "integer",
|
|
7285
|
+
description: "Number of traders with short exposure at this bucket (includes dual-side traders)."
|
|
7286
|
+
},
|
|
7287
|
+
tradersWithPosition: {
|
|
7288
|
+
type: "integer",
|
|
7289
|
+
description: "Pool traders holding this asset at this bucket. Few traders = unreliable signal."
|
|
7290
|
+
},
|
|
7291
|
+
netNotionalUsdt: {
|
|
7292
|
+
type: "string",
|
|
7293
|
+
description: "Net directional notional in USDT at this bucket = long notional \u2212 short notional."
|
|
7294
|
+
},
|
|
7295
|
+
totalNotionalUsdt: {
|
|
7296
|
+
type: "string",
|
|
7297
|
+
description: "Gross notional in USDT at this bucket = long notional + short notional. Tracks total capital deployed (rising = adding, falling = retreating)."
|
|
7298
|
+
},
|
|
7299
|
+
tradersQualified: { type: "integer", description: "Pool size after applying tier filters (includes traders without a position)." },
|
|
7300
|
+
dataVersion: { type: "string", description: "Snapshot version key in `yyyyMMddHH` UTC (10-digit, e.g. `2026042820`)." }
|
|
7301
|
+
};
|
|
6836
7302
|
function registerSmartmoneyTools() {
|
|
6837
7303
|
const tools = [
|
|
6838
|
-
/*
|
|
7304
|
+
/* ===================================================== */
|
|
7305
|
+
/* Trader family (6) */
|
|
7306
|
+
/* ===================================================== */
|
|
7307
|
+
/* ---------- T1. Top traders (leaderboard rank) ---------- */
|
|
6839
7308
|
{
|
|
6840
|
-
name: "
|
|
7309
|
+
name: "smartmoney_get_traders_by_filter",
|
|
6841
7310
|
module: "smartmoney",
|
|
6842
|
-
description: "
|
|
7311
|
+
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` \u2014 do not cross-pass.",
|
|
6843
7312
|
isWrite: false,
|
|
7313
|
+
outputSchema: envelope(
|
|
7314
|
+
{ type: "array", items: { type: "object", properties: TRADER_ITEM_PROPS } },
|
|
7315
|
+
{
|
|
7316
|
+
updateTime: {
|
|
7317
|
+
type: "string",
|
|
7318
|
+
description: "Snapshot version of the leaderboard, in `yyyyMMddHHmm` (UTC+8, e.g. `202604301815`). Lives at the response top level (shared by every item in `data`), NOT inside each trader row. Refreshed approximately every 5 minutes."
|
|
7319
|
+
},
|
|
7320
|
+
pagination: PAGINATION_PROP
|
|
7321
|
+
}
|
|
7322
|
+
),
|
|
6844
7323
|
inputSchema: {
|
|
6845
7324
|
type: "object",
|
|
6846
7325
|
properties: {
|
|
6847
|
-
|
|
6848
|
-
type: "string",
|
|
6849
|
-
description: "Recommended. Timestamp ms \u2014 use Date.now() for latest."
|
|
6850
|
-
},
|
|
6851
|
-
dataVersion: {
|
|
6852
|
-
type: "string",
|
|
6853
|
-
description: "Alternative. yyyyMMddHHmm UTC for prior snapshot. If both sent, ts wins."
|
|
6854
|
-
},
|
|
6855
|
-
instType: {
|
|
6856
|
-
type: "string",
|
|
6857
|
-
description: "SPOT|MARGIN|FUTURES|SWAP|OPTION (default SWAP)"
|
|
6858
|
-
},
|
|
6859
|
-
...SIGNAL_POOL_FILTER_PROPS,
|
|
6860
|
-
lmtNum: {
|
|
7326
|
+
updateTime: {
|
|
6861
7327
|
type: "string",
|
|
6862
|
-
description:
|
|
7328
|
+
description: 'Snapshot version key. Pass as a quoted 12-digit string `yyyyMMddHHmm` (UTC+8), e.g. `"202604301815"` (NOT integer). Omit to query the latest snapshot (refreshed every ~5 min).'
|
|
6863
7329
|
},
|
|
6864
|
-
|
|
7330
|
+
...LEADERBOARD_POOL_FILTER_PROPS,
|
|
7331
|
+
after: {
|
|
6865
7332
|
type: "string",
|
|
6866
|
-
description: "
|
|
7333
|
+
description: "Cursor for paginating backwards (older page). Pass the `authorId` of the last item from the previous page verbatim as a quoted string (NOT a number). Cursor anchors on `authorId` while preserving the current `sortBy` order."
|
|
6867
7334
|
},
|
|
6868
|
-
|
|
7335
|
+
before: {
|
|
6869
7336
|
type: "string",
|
|
6870
|
-
description: "
|
|
7337
|
+
description: "Cursor for paginating forwards (newer page). Pass the `authorId` of the first item from the previous page verbatim as a quoted string. Cursor anchors on `authorId` while preserving the current `sortBy` order."
|
|
6871
7338
|
},
|
|
6872
|
-
|
|
6873
|
-
type: "
|
|
6874
|
-
|
|
7339
|
+
limit: {
|
|
7340
|
+
type: "integer",
|
|
7341
|
+
minimum: 1,
|
|
7342
|
+
maximum: 100,
|
|
7343
|
+
default: 10,
|
|
7344
|
+
description: "Max results per page (default 10, max 100)."
|
|
6875
7345
|
}
|
|
6876
7346
|
}
|
|
6877
7347
|
},
|
|
6878
7348
|
handler: async (rawArgs, context) => {
|
|
6879
7349
|
const args = asRecord(rawArgs);
|
|
6880
|
-
const
|
|
6881
|
-
const ts = readString(args, "ts");
|
|
6882
|
-
if (!dv && !ts) {
|
|
6883
|
-
throw new ValidationError('Either "dataVersion" or "ts" is required for smartmoney_get_overview.');
|
|
6884
|
-
}
|
|
7350
|
+
const limit = readNumber(args, "limit");
|
|
6885
7351
|
const response = await context.client.privateGet(
|
|
6886
|
-
|
|
7352
|
+
PATH_LEADERBOARD,
|
|
6887
7353
|
compactObject({
|
|
6888
|
-
|
|
6889
|
-
ts,
|
|
6890
|
-
instType: readString(args, "instType"),
|
|
7354
|
+
updateTime: readString(args, "updateTime"),
|
|
6891
7355
|
...readPoolFilters(args),
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
topInstruments: readString(args, "topInstruments")
|
|
7356
|
+
after: readString(args, "after"),
|
|
7357
|
+
before: readString(args, "before"),
|
|
7358
|
+
limit
|
|
6896
7359
|
}),
|
|
6897
|
-
publicRateLimit("
|
|
7360
|
+
publicRateLimit("smartmoney_get_traders_by_filter", SMARTMONEY_RPS)
|
|
6898
7361
|
);
|
|
6899
|
-
|
|
7362
|
+
const normalized = normalizeResponse(response);
|
|
7363
|
+
const { items, updateTime } = extractLeaderboardEnvelope(normalized.data);
|
|
7364
|
+
return {
|
|
7365
|
+
...normalized,
|
|
7366
|
+
data: items,
|
|
7367
|
+
...updateTime ? { updateTime } : {},
|
|
7368
|
+
pagination: buildPagination(items, limit ?? 10, "authorId")
|
|
7369
|
+
};
|
|
6900
7370
|
}
|
|
6901
7371
|
},
|
|
6902
|
-
/* ----------
|
|
7372
|
+
/* ---------- T2. Trader performance (by authorIds) ---------- */
|
|
6903
7373
|
{
|
|
6904
|
-
name: "
|
|
7374
|
+
name: "smartmoney_get_performance_by_trader",
|
|
6905
7375
|
module: "smartmoney",
|
|
6906
|
-
description: "
|
|
7376
|
+
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 \u2192 authorId), `smartmoney_get_traders_by_filter` (criteria-based discovery). Note: response `updateTime` is 12-digit `yyyyMMddHHmm` UTC+8 \u2014 do not pass to signal-side tools' `asOfTime` (10-digit UTC).",
|
|
6907
7377
|
isWrite: false,
|
|
7378
|
+
outputSchema: envelope(
|
|
7379
|
+
{ type: "array", items: { type: "object", properties: TRADER_ITEM_PROPS } },
|
|
7380
|
+
{
|
|
7381
|
+
updateTime: {
|
|
7382
|
+
type: "string",
|
|
7383
|
+
description: "Snapshot version of the leaderboard, in `yyyyMMddHHmm` (UTC+8, e.g. `202604301815`). Lives at the response top level (shared by every item in `data`), NOT inside each trader row."
|
|
7384
|
+
}
|
|
7385
|
+
}
|
|
7386
|
+
),
|
|
6908
7387
|
inputSchema: {
|
|
6909
7388
|
type: "object",
|
|
6910
7389
|
properties: {
|
|
6911
|
-
instId: {
|
|
6912
|
-
type: "string",
|
|
6913
|
-
description: "Recommended. e.g. BTC-USDT-SWAP"
|
|
6914
|
-
},
|
|
6915
|
-
instCcy: {
|
|
6916
|
-
type: "string",
|
|
6917
|
-
description: "e.g. BTC (SPOT/SWAP only); instId takes precedence if both set"
|
|
6918
|
-
},
|
|
6919
|
-
ts: {
|
|
6920
|
-
type: "string",
|
|
6921
|
-
description: "Recommended. Timestamp ms \u2014 use Date.now() for latest."
|
|
6922
|
-
},
|
|
6923
|
-
dataVersion: {
|
|
6924
|
-
type: "string",
|
|
6925
|
-
description: "Alternative. yyyyMMddHHmm UTC for prior snapshot. If both sent, ts wins."
|
|
6926
|
-
},
|
|
6927
|
-
...SIGNAL_POOL_FILTER_PROPS,
|
|
6928
|
-
lmtNum: {
|
|
6929
|
-
type: "string",
|
|
6930
|
-
description: "Trader pool size 1-500 (default 100)"
|
|
6931
|
-
},
|
|
6932
7390
|
authorIds: {
|
|
7391
|
+
type: "array",
|
|
7392
|
+
items: { type: "string" },
|
|
7393
|
+
minItems: 1,
|
|
7394
|
+
description: 'Trader IDs to look up, e.g. `["1001", "1002"]`. Required.'
|
|
7395
|
+
},
|
|
7396
|
+
period: {
|
|
6933
7397
|
type: "string",
|
|
6934
|
-
|
|
7398
|
+
enum: PERIOD_DAYS,
|
|
7399
|
+
default: "90",
|
|
7400
|
+
description: 'Performance lookback window in days. Pass as a quoted string: `"3"` / `"7"` / `"30"` / `"90"` (NOT integer). Default `"90"`.'
|
|
6935
7401
|
}
|
|
6936
|
-
}
|
|
7402
|
+
},
|
|
7403
|
+
required: ["authorIds"]
|
|
6937
7404
|
},
|
|
6938
7405
|
handler: async (rawArgs, context) => {
|
|
6939
7406
|
const args = asRecord(rawArgs);
|
|
6940
|
-
const
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
|
|
6946
|
-
const ts = readString(args, "ts");
|
|
6947
|
-
if (!dv && !ts) {
|
|
6948
|
-
throw new ValidationError('Either "dataVersion" or "ts" is required for smartmoney_get_signal.');
|
|
7407
|
+
const authorIds = readArrayAsCsv(args, "authorIds");
|
|
7408
|
+
if (!authorIds) {
|
|
7409
|
+
throw actionableError(
|
|
7410
|
+
'"authorIds" is required and must be a non-empty array.',
|
|
7411
|
+
'Discover trader IDs via `smartmoney_get_traders_by_filter`, then pass them as an array (e.g. ["1001", "1002"]).'
|
|
7412
|
+
);
|
|
6949
7413
|
}
|
|
6950
7414
|
const response = await context.client.privateGet(
|
|
6951
|
-
|
|
7415
|
+
PATH_LEADERBOARD,
|
|
6952
7416
|
compactObject({
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
dataVersion: dv,
|
|
6956
|
-
ts,
|
|
6957
|
-
...readPoolFilters(args),
|
|
6958
|
-
lmtNum: readString(args, "lmtNum"),
|
|
6959
|
-
authorIds: readString(args, "authorIds")
|
|
7417
|
+
authorIds,
|
|
7418
|
+
period: readString(args, "period")
|
|
6960
7419
|
}),
|
|
6961
|
-
publicRateLimit("
|
|
7420
|
+
publicRateLimit("smartmoney_get_performance_by_trader", SMARTMONEY_RPS)
|
|
6962
7421
|
);
|
|
6963
|
-
|
|
7422
|
+
const normalized = normalizeResponse(response);
|
|
7423
|
+
const { items, updateTime } = extractLeaderboardEnvelope(normalized.data);
|
|
7424
|
+
return {
|
|
7425
|
+
...normalized,
|
|
7426
|
+
data: items,
|
|
7427
|
+
...updateTime ? { updateTime } : {}
|
|
7428
|
+
};
|
|
6964
7429
|
}
|
|
6965
7430
|
},
|
|
6966
|
-
/* ----------
|
|
7431
|
+
/* ---------- T3. Trader current positions ---------- */
|
|
6967
7432
|
{
|
|
6968
|
-
name: "
|
|
7433
|
+
name: "smartmoney_get_trader_positions",
|
|
6969
7434
|
module: "smartmoney",
|
|
6970
|
-
description: "
|
|
7435
|
+
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 \u2192 authorId), `smartmoney_get_traders_by_filter` (discover trader).",
|
|
6971
7436
|
isWrite: false,
|
|
7437
|
+
outputSchema: envelope({
|
|
7438
|
+
type: "array",
|
|
7439
|
+
items: {
|
|
7440
|
+
type: "object",
|
|
7441
|
+
properties: {
|
|
7442
|
+
posId: { type: "string", description: "Unique position ID. Stable across the position's lifetime." },
|
|
7443
|
+
instId: { type: "string", description: "Instrument ID e.g. BTC-USDT-SWAP." },
|
|
7444
|
+
instType: {
|
|
7445
|
+
type: "string",
|
|
7446
|
+
description: "Instrument business line: `SWAP` (perpetual) | `SPOT` | `FUTURES` (delivery) | `MARGIN` | `OPTION`."
|
|
7447
|
+
},
|
|
7448
|
+
posSide: {
|
|
7449
|
+
type: "string",
|
|
7450
|
+
description: "Raw upstream position direction. `long` = long-side position (buy-to-open); `short` = short-side position (sell-to-open); `both` = net/one-way position mode where the sign of `pos` encodes direction. Prefer the derived `direction` field below for agent logic."
|
|
7451
|
+
},
|
|
7452
|
+
direction: {
|
|
7453
|
+
type: "string",
|
|
7454
|
+
enum: ["long", "short"],
|
|
7455
|
+
description: 'Derived clean direction (`long` | `short`) \u2014 handler computes this from `posSide` + sign of `pos` so agents do not have to branch on the `posSide="both"` net-mode case.'
|
|
7456
|
+
},
|
|
7457
|
+
posCcy: { type: "string", description: 'Position currency \u2014 the asset being held, e.g. "BTC".' },
|
|
7458
|
+
quoteCcy: { type: "string", description: 'Quote currency the position is priced/settled in, e.g. "USDT".' },
|
|
7459
|
+
pos: {
|
|
7460
|
+
type: "string",
|
|
7461
|
+
description: "Position size (numeric string). Unit depends on instType: coins for SPOT/MARGIN, contracts (\u5F20) for SWAP/FUTURES/OPTION."
|
|
7462
|
+
},
|
|
7463
|
+
lever: { type: "string", description: 'Leverage multiplier (numeric string; "1" for spot).' },
|
|
7464
|
+
avgPx: { type: "string", description: "Volume-weighted average entry price (numeric string)." },
|
|
7465
|
+
last: { type: "string", description: "Latest market/mark price for the instrument (numeric string)." },
|
|
7466
|
+
notionalUsd: { type: "string", description: "Current position notional value in USD." },
|
|
7467
|
+
upl: { type: "string", description: "Unrealized (floating) PnL, denominated in `quoteCcy`." },
|
|
7468
|
+
pnl: { type: "string", description: "Realized PnL accrued on this position so far, denominated in `quoteCcy`." },
|
|
7469
|
+
cTime: { type: "string", description: "Position open time as Unix milliseconds (numeric string)." },
|
|
7470
|
+
positionIntensity: {
|
|
7471
|
+
type: "string",
|
|
7472
|
+
description: "Conviction metric = notionalUsd / trader.asset (this position's notional as a share of the trader's AUM). Higher = the trader is betting a larger fraction of their book on this position."
|
|
7473
|
+
}
|
|
7474
|
+
}
|
|
7475
|
+
}
|
|
7476
|
+
}),
|
|
6972
7477
|
inputSchema: {
|
|
6973
7478
|
type: "object",
|
|
6974
7479
|
properties: {
|
|
6975
|
-
|
|
7480
|
+
authorId: {
|
|
6976
7481
|
type: "string",
|
|
6977
|
-
description: "
|
|
7482
|
+
description: "Trader's unique ID (obtain from `smartmoney_get_traders_by_filter`)."
|
|
6978
7483
|
},
|
|
6979
|
-
|
|
7484
|
+
instId: {
|
|
7485
|
+
type: "string",
|
|
7486
|
+
description: 'Optional instrument filter. Accepts either full instId (e.g. "BTC-USDT-SWAP") or bare base currency (e.g. "BTC") \u2014 the handler extracts the base currency for the upstream filter.'
|
|
7487
|
+
}
|
|
7488
|
+
},
|
|
7489
|
+
required: ["authorId"]
|
|
7490
|
+
},
|
|
7491
|
+
handler: async (rawArgs, context) => {
|
|
7492
|
+
const args = asRecord(rawArgs);
|
|
7493
|
+
const authorId = readString(args, "authorId");
|
|
7494
|
+
if (!authorId) {
|
|
7495
|
+
throw actionableError(
|
|
7496
|
+
'"authorId" is required.',
|
|
7497
|
+
"Discover trader IDs via `smartmoney_get_traders_by_filter` and pass one ID here."
|
|
7498
|
+
);
|
|
7499
|
+
}
|
|
7500
|
+
const response = await context.client.privateGet(
|
|
7501
|
+
PATH_POSITION_CURRENT,
|
|
7502
|
+
compactObject({
|
|
7503
|
+
authorId,
|
|
7504
|
+
instCcy: extractBaseCcy(readString(args, "instId"))
|
|
7505
|
+
}),
|
|
7506
|
+
publicRateLimit("smartmoney_get_trader_positions", SMARTMONEY_RPS)
|
|
7507
|
+
);
|
|
7508
|
+
const normalized = normalizeResponse(response);
|
|
7509
|
+
return { ...normalized, data: extractPositionData(normalized.data) };
|
|
7510
|
+
}
|
|
7511
|
+
},
|
|
7512
|
+
/* ---------- T4. Trader closed-position history ---------- */
|
|
7513
|
+
{
|
|
7514
|
+
name: "smartmoney_get_trader_positions_history",
|
|
7515
|
+
module: "smartmoney",
|
|
7516
|
+
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 \u2192 authorId), `smartmoney_get_traders_by_filter` (discover trader).",
|
|
7517
|
+
isWrite: false,
|
|
7518
|
+
outputSchema: envelope(
|
|
7519
|
+
{
|
|
7520
|
+
type: "array",
|
|
7521
|
+
items: {
|
|
7522
|
+
type: "object",
|
|
7523
|
+
properties: {
|
|
7524
|
+
posId: { type: "string", description: "Unique closed-position ID. Use as the `after` / `before` cursor when paginating." },
|
|
7525
|
+
instId: { type: "string", description: "Instrument ID e.g. BTC-USDT-SWAP." },
|
|
7526
|
+
instType: {
|
|
7527
|
+
type: "string",
|
|
7528
|
+
description: "Instrument business line: `SWAP` (perpetual) | `FUTURES` (delivery) | `MARGIN` | `SPOT`."
|
|
7529
|
+
},
|
|
7530
|
+
ctVal: {
|
|
7531
|
+
type: "string",
|
|
7532
|
+
description: "Contract face value \u2014 USD value of a single contract (\u5F20). Numeric string. Empty/0 for non-contract instruments."
|
|
7533
|
+
},
|
|
7534
|
+
posSide: {
|
|
7535
|
+
type: "string",
|
|
7536
|
+
description: "Position direction at close. `long` = was long-side; `short` = was short-side."
|
|
7537
|
+
},
|
|
7538
|
+
lever: { type: "string", description: "Leverage multiplier used for this position (numeric string)." },
|
|
7539
|
+
mgnMode: {
|
|
7540
|
+
type: "string",
|
|
7541
|
+
description: "Margin mode used for this position. `cross` = cross-margin (shared collateral pool); `isolated` = isolated-margin (per-position collateral)."
|
|
7542
|
+
},
|
|
7543
|
+
marginCcy: {
|
|
7544
|
+
type: "string",
|
|
7545
|
+
description: 'Margin currency held as collateral for this position, e.g. "BTC" or "USDT".'
|
|
7546
|
+
},
|
|
7547
|
+
quoteCcy: { type: "string", description: 'Quote currency the position settled in, e.g. "USDT".' },
|
|
7548
|
+
openAvgPx: { type: "string", description: "Volume-weighted average price across all open fills (numeric string)." },
|
|
7549
|
+
closeAvgPx: { type: "string", description: "Volume-weighted average price across all close fills (numeric string)." },
|
|
7550
|
+
openMaxAmount: {
|
|
7551
|
+
type: "string",
|
|
7552
|
+
description: "Peak position size held during the position's lifetime, in contracts (\u5F20)."
|
|
7553
|
+
},
|
|
7554
|
+
closeAmount: {
|
|
7555
|
+
type: "string",
|
|
7556
|
+
description: "Total amount closed across all close fills, in contracts for SWAP/FUTURES or in base currency for SPOT/MARGIN (numeric string)."
|
|
7557
|
+
},
|
|
7558
|
+
realizedPnl: { type: "string", description: "Cumulative realized PnL during the position's lifetime, in `quoteCcy` units." },
|
|
7559
|
+
pnl: {
|
|
7560
|
+
type: "string",
|
|
7561
|
+
description: "Total realized PnL for this position including fees and funding, denominated in quoteCcy (numeric string). Differs from `realizedPnl` which may exclude fees."
|
|
7562
|
+
},
|
|
7563
|
+
pnlRatio: {
|
|
7564
|
+
type: "string",
|
|
7565
|
+
description: 'Realized PnL as a decimal ratio of cost basis (e.g. "0.15" = +15%, "-0.20" = \u221220%).'
|
|
7566
|
+
},
|
|
7567
|
+
fee: {
|
|
7568
|
+
type: "string",
|
|
7569
|
+
description: "Cumulative trading fee paid over the position's lifetime, denominated in quoteCcy (numeric string, negative = cost)."
|
|
7570
|
+
},
|
|
7571
|
+
fundingFee: {
|
|
7572
|
+
type: "string",
|
|
7573
|
+
description: "Cumulative funding fee paid or received over the position's lifetime, denominated in quoteCcy (numeric string; negative = paid, positive = received)."
|
|
7574
|
+
},
|
|
7575
|
+
liquidationStatus: {
|
|
7576
|
+
type: "string",
|
|
7577
|
+
description: 'Whether the position was liquidated. `"0"` = normal close (not liquidated); `"1"` = liquidated. Use this dedicated field for liquidation checks; `closeType` may also encode liquidation via the `liquidateClose` / `liquidateReceive` / `adl` values.'
|
|
7578
|
+
},
|
|
7579
|
+
closeType: {
|
|
7580
|
+
type: "string",
|
|
7581
|
+
description: "How the position was closed. `allClose` = entire position closed in one action; `partClose` = partially closed (position reduced but not fully exited); `liquidateClose` = forced liquidation; `liquidateReceive` = received liquidation transfer; `adl` = auto-deleveraging."
|
|
7582
|
+
},
|
|
7583
|
+
cTime: { type: "string", description: "Position open time as Unix milliseconds (numeric string)." },
|
|
7584
|
+
uTime: { type: "string", description: "Position close time as Unix milliseconds (numeric string)." }
|
|
7585
|
+
}
|
|
7586
|
+
}
|
|
7587
|
+
},
|
|
7588
|
+
{ pagination: PAGINATION_PROP }
|
|
7589
|
+
),
|
|
7590
|
+
inputSchema: {
|
|
7591
|
+
type: "object",
|
|
7592
|
+
properties: {
|
|
7593
|
+
authorId: {
|
|
6980
7594
|
type: "string",
|
|
6981
|
-
description: "
|
|
7595
|
+
description: "Trader's unique ID (obtain from `smartmoney_get_traders_by_filter`)."
|
|
6982
7596
|
},
|
|
6983
|
-
|
|
7597
|
+
instId: {
|
|
6984
7598
|
type: "string",
|
|
6985
|
-
description:
|
|
7599
|
+
description: 'Optional instrument filter. Accepts either full instId (e.g. "BTC-USDT-SWAP") or bare base currency (e.g. "BTC") \u2014 the handler extracts the base currency for the upstream filter.'
|
|
6986
7600
|
},
|
|
6987
|
-
|
|
7601
|
+
after: {
|
|
6988
7602
|
type: "string",
|
|
6989
|
-
description: "
|
|
7603
|
+
description: "Cursor: returns positions with `posId` smaller than this value (older \u2014 paginate backwards). Pass as quoted string (the `posId` value verbatim, NOT a number \u2014 `posId` is a 19-digit ID and number coercion can lose precision)."
|
|
6990
7604
|
},
|
|
6991
|
-
|
|
7605
|
+
before: {
|
|
6992
7606
|
type: "string",
|
|
6993
|
-
description: "
|
|
7607
|
+
description: "Cursor: returns positions with `posId` greater than this value (newer \u2014 paginate forwards). Pass as quoted string."
|
|
6994
7608
|
},
|
|
6995
|
-
|
|
7609
|
+
limit: {
|
|
7610
|
+
type: "integer",
|
|
7611
|
+
minimum: 1,
|
|
7612
|
+
maximum: 100,
|
|
7613
|
+
default: 10,
|
|
7614
|
+
description: "Max positions per page (default 10, max 100)."
|
|
7615
|
+
}
|
|
6996
7616
|
},
|
|
6997
|
-
required: ["
|
|
7617
|
+
required: ["authorId"]
|
|
6998
7618
|
},
|
|
6999
7619
|
handler: async (rawArgs, context) => {
|
|
7000
7620
|
const args = asRecord(rawArgs);
|
|
7001
|
-
const
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7621
|
+
const authorId = readString(args, "authorId");
|
|
7622
|
+
if (!authorId) {
|
|
7623
|
+
throw actionableError(
|
|
7624
|
+
'"authorId" is required.',
|
|
7625
|
+
"Discover trader IDs via `smartmoney_get_traders_by_filter`."
|
|
7626
|
+
);
|
|
7005
7627
|
}
|
|
7628
|
+
const limit = readNumber(args, "limit");
|
|
7006
7629
|
const response = await context.client.privateGet(
|
|
7007
|
-
|
|
7630
|
+
PATH_POSITION_HISTORY,
|
|
7008
7631
|
compactObject({
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
limit
|
|
7014
|
-
...readPoolFilters(args)
|
|
7632
|
+
authorId,
|
|
7633
|
+
instCcy: extractBaseCcy(readString(args, "instId")),
|
|
7634
|
+
after: readString(args, "after"),
|
|
7635
|
+
before: readString(args, "before"),
|
|
7636
|
+
limit
|
|
7015
7637
|
}),
|
|
7016
|
-
publicRateLimit("
|
|
7638
|
+
publicRateLimit("smartmoney_get_trader_positions_history", SMARTMONEY_RPS)
|
|
7017
7639
|
);
|
|
7018
|
-
|
|
7640
|
+
const normalized = normalizeResponse(response);
|
|
7641
|
+
const data = Array.isArray(normalized.data) ? normalized.data : [];
|
|
7642
|
+
return {
|
|
7643
|
+
...normalized,
|
|
7644
|
+
data,
|
|
7645
|
+
pagination: buildPagination(data, limit ?? 10, "posId")
|
|
7646
|
+
};
|
|
7019
7647
|
}
|
|
7020
7648
|
},
|
|
7021
|
-
/* ----------
|
|
7649
|
+
/* ---------- T5. Trader order history ---------- */
|
|
7022
7650
|
{
|
|
7023
|
-
name: "
|
|
7651
|
+
name: "smartmoney_get_trader_orders_history",
|
|
7024
7652
|
module: "smartmoney",
|
|
7025
|
-
description: "
|
|
7653
|
+
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 \u2192 authorId), `smartmoney_get_traders_by_filter` (discover trader).",
|
|
7026
7654
|
isWrite: false,
|
|
7655
|
+
outputSchema: envelope(
|
|
7656
|
+
{
|
|
7657
|
+
type: "array",
|
|
7658
|
+
items: {
|
|
7659
|
+
type: "object",
|
|
7660
|
+
properties: {
|
|
7661
|
+
ordId: { type: "string", description: "Unique order ID. Use as the `after` / `before` cursor when paginating." },
|
|
7662
|
+
instId: { type: "string", description: "Instrument ID e.g. BTC-USDT-SWAP." },
|
|
7663
|
+
displayId: { type: "string", description: "Display-form instrument ID used in OKX UI." },
|
|
7664
|
+
instType: {
|
|
7665
|
+
type: "string",
|
|
7666
|
+
description: "Instrument business line: `SWAP` (perpetual contract) | `SPOT`."
|
|
7667
|
+
},
|
|
7668
|
+
baseName: { type: "string", description: 'Base currency symbol, e.g. "BTC".' },
|
|
7669
|
+
quoteName: { type: "string", description: 'Quote currency symbol, e.g. "USD".' },
|
|
7670
|
+
tradeQuoteCcy: { type: "string", description: "Quote currency the fill actually settled in." },
|
|
7671
|
+
side: {
|
|
7672
|
+
type: "string",
|
|
7673
|
+
description: "Order side. `buy` = open long / close short; `sell` = open short / close long."
|
|
7674
|
+
},
|
|
7675
|
+
posSide: {
|
|
7676
|
+
type: "string",
|
|
7677
|
+
description: "Position direction the order applies to: `long` | `short`. Indicates whether the trader was opening/closing a long-side or short-side position."
|
|
7678
|
+
},
|
|
7679
|
+
ordType: {
|
|
7680
|
+
type: "string",
|
|
7681
|
+
description: "Order type. `limit` = price-protected limit order; `market` = immediate at best available price."
|
|
7682
|
+
},
|
|
7683
|
+
lever: { type: "string", description: 'Leverage multiplier used for this order (numeric string; "1" for spot).' },
|
|
7684
|
+
px: { type: "string", description: "Submitted order price (numeric string). For market orders this may be empty/0." },
|
|
7685
|
+
avgPx: { type: "string", description: "Volume-weighted average fill price (numeric string)." },
|
|
7686
|
+
sz: {
|
|
7687
|
+
type: "string",
|
|
7688
|
+
description: "Order size. Unit depends on instType: coins (\u5E01) for SPOT, contracts (\u5F20) for SWAP/FUTURES."
|
|
7689
|
+
},
|
|
7690
|
+
value: {
|
|
7691
|
+
type: "string",
|
|
7692
|
+
description: "Order notional value, denominated in `quoteName` units."
|
|
7693
|
+
},
|
|
7694
|
+
cTime: { type: "string", description: "Order creation time as Unix milliseconds (numeric string)." },
|
|
7695
|
+
fillTime: {
|
|
7696
|
+
type: "string",
|
|
7697
|
+
description: "Timestamp when the order was last filled, as Unix milliseconds (numeric string)."
|
|
7698
|
+
},
|
|
7699
|
+
uTime: {
|
|
7700
|
+
type: "string",
|
|
7701
|
+
description: "Timestamp when the order record was last updated, as Unix milliseconds (numeric string)."
|
|
7702
|
+
}
|
|
7703
|
+
}
|
|
7704
|
+
}
|
|
7705
|
+
},
|
|
7706
|
+
{ pagination: PAGINATION_PROP }
|
|
7707
|
+
),
|
|
7027
7708
|
inputSchema: {
|
|
7028
7709
|
type: "object",
|
|
7029
7710
|
properties: {
|
|
7030
|
-
|
|
7711
|
+
authorId: {
|
|
7031
7712
|
type: "string",
|
|
7032
|
-
description: "
|
|
7713
|
+
description: "Trader's unique ID (obtain from `smartmoney_get_traders_by_filter`)."
|
|
7033
7714
|
},
|
|
7034
|
-
|
|
7035
|
-
authorIds: {
|
|
7715
|
+
instId: {
|
|
7036
7716
|
type: "string",
|
|
7037
|
-
description: "
|
|
7717
|
+
description: 'Optional instrument filter. Accepts either full instId (e.g. "BTC-USDT-SWAP") or bare base currency (e.g. "BTC") \u2014 the handler extracts the base currency for the upstream filter.'
|
|
7038
7718
|
},
|
|
7039
7719
|
after: {
|
|
7040
7720
|
type: "string",
|
|
7041
|
-
description: "Cursor
|
|
7721
|
+
description: "Cursor: returns trades with `ordId` smaller than this value (older \u2014 paginate backwards). Pass as quoted string (the `ordId` value verbatim, NOT a number \u2014 `ordId` is a 19-digit ID and number coercion can lose precision)."
|
|
7042
7722
|
},
|
|
7043
7723
|
before: {
|
|
7044
7724
|
type: "string",
|
|
7045
|
-
description: "Cursor
|
|
7725
|
+
description: "Cursor: returns trades with `ordId` greater than this value (newer \u2014 paginate forwards). Pass as quoted string."
|
|
7046
7726
|
},
|
|
7047
7727
|
limit: {
|
|
7048
|
-
type: "
|
|
7049
|
-
|
|
7728
|
+
type: "integer",
|
|
7729
|
+
minimum: 1,
|
|
7730
|
+
maximum: 100,
|
|
7731
|
+
default: 10,
|
|
7732
|
+
description: "Max trades per page (default 10, max 100)."
|
|
7050
7733
|
}
|
|
7051
|
-
}
|
|
7734
|
+
},
|
|
7735
|
+
required: ["authorId"]
|
|
7052
7736
|
},
|
|
7053
7737
|
handler: async (rawArgs, context) => {
|
|
7054
7738
|
const args = asRecord(rawArgs);
|
|
7739
|
+
const authorId = readString(args, "authorId");
|
|
7740
|
+
if (!authorId) {
|
|
7741
|
+
throw actionableError(
|
|
7742
|
+
'"authorId" is required.',
|
|
7743
|
+
"Discover trader IDs via `smartmoney_get_traders_by_filter`."
|
|
7744
|
+
);
|
|
7745
|
+
}
|
|
7746
|
+
const limit = readNumber(args, "limit");
|
|
7055
7747
|
const response = await context.client.privateGet(
|
|
7056
|
-
|
|
7748
|
+
PATH_TRADE_RECORDS,
|
|
7057
7749
|
compactObject({
|
|
7058
|
-
|
|
7059
|
-
|
|
7060
|
-
authorIds: readString(args, "authorIds"),
|
|
7750
|
+
authorId,
|
|
7751
|
+
instCcy: extractBaseCcy(readString(args, "instId")),
|
|
7061
7752
|
after: readString(args, "after"),
|
|
7062
7753
|
before: readString(args, "before"),
|
|
7063
|
-
limit
|
|
7754
|
+
limit
|
|
7064
7755
|
}),
|
|
7065
|
-
publicRateLimit("
|
|
7756
|
+
publicRateLimit("smartmoney_get_trader_orders_history", SMARTMONEY_RPS)
|
|
7066
7757
|
);
|
|
7067
7758
|
const normalized = normalizeResponse(response);
|
|
7068
|
-
|
|
7759
|
+
const data = Array.isArray(normalized.data) ? normalized.data : [];
|
|
7760
|
+
return {
|
|
7761
|
+
...normalized,
|
|
7762
|
+
data,
|
|
7763
|
+
pagination: buildPagination(data, limit ?? 10, "ordId")
|
|
7764
|
+
};
|
|
7069
7765
|
}
|
|
7070
7766
|
},
|
|
7071
|
-
/* ----------
|
|
7767
|
+
/* ---------- T6. Search top traders by nickname keyword ---------- */
|
|
7072
7768
|
{
|
|
7073
|
-
name: "
|
|
7769
|
+
name: "smartmoney_search_trader",
|
|
7074
7770
|
module: "smartmoney",
|
|
7075
|
-
description: "Trader
|
|
7771
|
+
description: "Search Top Traders by nickname keyword, ranked by OKX-platform follower count DESC. Returns up to 10 matches; intersects KOL full-text recall with the Top Trader set. Use when: resolving a nickname or partial name to `authorId`(s) before calling other `smartmoney_get_trader_*` tools. See also: `smartmoney_get_traders_by_filter` (discover top performers by criteria), `smartmoney_get_performance_by_trader` (lookup by known authorId).",
|
|
7076
7772
|
isWrite: false,
|
|
7773
|
+
outputSchema: envelope({
|
|
7774
|
+
type: "array",
|
|
7775
|
+
description: "Matched Top Traders (\u226410), sorted by `followerCount` DESC. Empty array when no recall intersects the Top Trader set.",
|
|
7776
|
+
items: {
|
|
7777
|
+
type: "object",
|
|
7778
|
+
properties: {
|
|
7779
|
+
authorId: { type: "string", description: "Trader's unique ID \u2014 pass to other `smartmoney_get_trader_*` tools." },
|
|
7780
|
+
nickName: { type: "string", description: "Display nickname matched against the keyword." },
|
|
7781
|
+
followerCount: { type: "string", description: "OKX-platform follower count (numeric string; Twitter followers excluded). Sort key." }
|
|
7782
|
+
}
|
|
7783
|
+
}
|
|
7784
|
+
}),
|
|
7077
7785
|
inputSchema: {
|
|
7078
7786
|
type: "object",
|
|
7079
7787
|
properties: {
|
|
7080
|
-
|
|
7788
|
+
keyword: {
|
|
7081
7789
|
type: "string",
|
|
7082
|
-
description: "Trader
|
|
7790
|
+
description: "Nickname search keyword. Required, must be non-empty / non-whitespace. Matched candidates are intersected with the Top Trader set."
|
|
7791
|
+
}
|
|
7792
|
+
},
|
|
7793
|
+
required: ["keyword"]
|
|
7794
|
+
},
|
|
7795
|
+
handler: async (rawArgs, context) => {
|
|
7796
|
+
const args = asRecord(rawArgs);
|
|
7797
|
+
const keyword = readString(args, "keyword");
|
|
7798
|
+
if (!keyword || keyword.trim() === "") {
|
|
7799
|
+
throw actionableError(
|
|
7800
|
+
'"keyword" is required and must be non-empty.',
|
|
7801
|
+
'Pass a nickname fragment (e.g. "alice", "\u5C0F\u660E"). For known author IDs use `smartmoney_get_performance_by_trader` instead.'
|
|
7802
|
+
);
|
|
7803
|
+
}
|
|
7804
|
+
const response = await context.client.privateGet(
|
|
7805
|
+
PATH_TOP_TRADER_SEARCH,
|
|
7806
|
+
compactObject({ keyword }),
|
|
7807
|
+
publicRateLimit("smartmoney_search_trader", SMARTMONEY_RPS)
|
|
7808
|
+
);
|
|
7809
|
+
const normalized = normalizeResponse(response);
|
|
7810
|
+
const data = Array.isArray(normalized.data) ? normalized.data : [];
|
|
7811
|
+
return { ...normalized, data };
|
|
7812
|
+
}
|
|
7813
|
+
},
|
|
7814
|
+
/* ===================================================== */
|
|
7815
|
+
/* Signal/Coin family (4) */
|
|
7816
|
+
/* ===================================================== */
|
|
7817
|
+
/* ---------- S1. Signal overview by filter (multi-asset, tier-filtered pool) ---------- */
|
|
7818
|
+
{
|
|
7819
|
+
name: "smartmoney_get_signal_overview_by_filter",
|
|
7820
|
+
module: "smartmoney",
|
|
7821
|
+
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` \u2014 exactly one. Snapshot time auto-resolved to current hour. 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).",
|
|
7822
|
+
isWrite: false,
|
|
7823
|
+
outputSchema: envelope({
|
|
7824
|
+
type: "array",
|
|
7825
|
+
description: "Per-instrument snapshot, one element per requested coin.",
|
|
7826
|
+
items: { type: "object", properties: SIGNAL_ITEM_PROPS }
|
|
7827
|
+
}),
|
|
7828
|
+
inputSchema: {
|
|
7829
|
+
type: "object",
|
|
7830
|
+
properties: {
|
|
7831
|
+
topInstruments: {
|
|
7832
|
+
type: "integer",
|
|
7833
|
+
minimum: 1,
|
|
7834
|
+
maximum: 100,
|
|
7835
|
+
default: 20,
|
|
7836
|
+
description: "Top-N hottest instruments to aggregate (sorted by `tradersWithPosition` DESC). Mutually exclusive with `instCcyList`; one of the two is required (default 20 if neither provided)."
|
|
7083
7837
|
},
|
|
7084
|
-
|
|
7085
|
-
type: "
|
|
7086
|
-
|
|
7838
|
+
instCcyList: {
|
|
7839
|
+
type: "array",
|
|
7840
|
+
items: { type: "string" },
|
|
7841
|
+
minItems: 1,
|
|
7842
|
+
description: 'Base currencies to aggregate, e.g. `["BTC", "ETH", "SOL"]`. Mutually exclusive with `topInstruments`.'
|
|
7843
|
+
},
|
|
7844
|
+
...SIGNAL_POOL_FILTER_PROPS,
|
|
7845
|
+
lmtNum: {
|
|
7846
|
+
type: "integer",
|
|
7847
|
+
minimum: 1,
|
|
7848
|
+
maximum: 2e3,
|
|
7849
|
+
default: 100,
|
|
7850
|
+
description: "Top-N traders to pull into the aggregation pool, ranked by `sortBy` (DESC). Larger pool = stronger signal but slower. Default 100 is fine for most cases."
|
|
7851
|
+
}
|
|
7852
|
+
}
|
|
7853
|
+
},
|
|
7854
|
+
handler: async (rawArgs, context) => {
|
|
7855
|
+
const args = asRecord(rawArgs);
|
|
7856
|
+
const instCcyList = readArrayAsCsv(args, "instCcyList");
|
|
7857
|
+
const topInstrumentsRaw = readNumber(args, "topInstruments");
|
|
7858
|
+
if (instCcyList && topInstrumentsRaw !== void 0) {
|
|
7859
|
+
throw actionableError(
|
|
7860
|
+
'"topInstruments" and "instCcyList" are mutually exclusive.',
|
|
7861
|
+
"Pass exactly one \u2014 `topInstruments` for top-N hottest coins, or `instCcyList` for specific coins."
|
|
7862
|
+
);
|
|
7863
|
+
}
|
|
7864
|
+
const response = await context.client.privateGet(
|
|
7865
|
+
PATH_OVERVIEW,
|
|
7866
|
+
compactObject({
|
|
7867
|
+
...instCcyList ? { instCcyList } : { topInstruments: topInstrumentsRaw ?? 20 },
|
|
7868
|
+
...readSignalPoolFilters(args),
|
|
7869
|
+
lmtNum: readNumber(args, "lmtNum")
|
|
7870
|
+
}),
|
|
7871
|
+
publicRateLimit("smartmoney_get_signal_overview_by_filter", SMARTMONEY_RPS)
|
|
7872
|
+
);
|
|
7873
|
+
return normalizeResponse(response);
|
|
7874
|
+
}
|
|
7875
|
+
},
|
|
7876
|
+
/* ---------- S2. Signal overview by trader (multi-asset, authorIds-restricted) ---------- */
|
|
7877
|
+
{
|
|
7878
|
+
name: "smartmoney_get_signal_overview_by_trader",
|
|
7879
|
+
module: "smartmoney",
|
|
7880
|
+
description: "Multi-asset smart-money signals aggregated over a hand-picked set of traders (`authorIds`). Pick instruments via `topInstruments` OR `instCcyList`. Pool sizing / ranking / capability filters not exposed \u2014 backend uses defaults for direct-lookup scenarios. 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).",
|
|
7881
|
+
isWrite: false,
|
|
7882
|
+
outputSchema: envelope({
|
|
7883
|
+
type: "array",
|
|
7884
|
+
description: "Per-instrument snapshot, one element per requested coin.",
|
|
7885
|
+
items: { type: "object", properties: SIGNAL_ITEM_PROPS }
|
|
7886
|
+
}),
|
|
7887
|
+
inputSchema: {
|
|
7888
|
+
type: "object",
|
|
7889
|
+
properties: {
|
|
7890
|
+
authorIds: {
|
|
7891
|
+
type: "array",
|
|
7892
|
+
items: { type: "string" },
|
|
7893
|
+
minItems: 1,
|
|
7894
|
+
description: 'Trader IDs to aggregate over, e.g. `["1001", "1002"]`. Required.'
|
|
7895
|
+
},
|
|
7896
|
+
topInstruments: {
|
|
7897
|
+
type: "integer",
|
|
7898
|
+
minimum: 1,
|
|
7899
|
+
maximum: 100,
|
|
7900
|
+
default: 20,
|
|
7901
|
+
description: "Top-N hottest instruments held by the given traders (sorted by `tradersWithPosition` DESC). Mutually exclusive with `instCcyList`; one of the two is required (default 20 if neither provided)."
|
|
7087
7902
|
},
|
|
7903
|
+
instCcyList: {
|
|
7904
|
+
type: "array",
|
|
7905
|
+
items: { type: "string" },
|
|
7906
|
+
minItems: 1,
|
|
7907
|
+
description: 'Base currencies to aggregate, e.g. `["BTC", "ETH", "SOL"]`. Mutually exclusive with `topInstruments`.'
|
|
7908
|
+
}
|
|
7909
|
+
},
|
|
7910
|
+
required: ["authorIds"]
|
|
7911
|
+
},
|
|
7912
|
+
handler: async (rawArgs, context) => {
|
|
7913
|
+
const args = asRecord(rawArgs);
|
|
7914
|
+
const authorIds = readArrayAsCsv(args, "authorIds");
|
|
7915
|
+
if (!authorIds) {
|
|
7916
|
+
throw actionableError(
|
|
7917
|
+
'"authorIds" is required and must be a non-empty array.',
|
|
7918
|
+
'Pass IDs from `smartmoney_get_traders_by_filter` as an array (e.g. ["1001", "1002"]).'
|
|
7919
|
+
);
|
|
7920
|
+
}
|
|
7921
|
+
const instCcyList = readArrayAsCsv(args, "instCcyList");
|
|
7922
|
+
const topInstrumentsRaw = readNumber(args, "topInstruments");
|
|
7923
|
+
if (instCcyList && topInstrumentsRaw !== void 0) {
|
|
7924
|
+
throw actionableError(
|
|
7925
|
+
'"topInstruments" and "instCcyList" are mutually exclusive.',
|
|
7926
|
+
"Pass exactly one \u2014 `topInstruments` for top-N hottest coins, or `instCcyList` for specific coins."
|
|
7927
|
+
);
|
|
7928
|
+
}
|
|
7929
|
+
const response = await context.client.privateGet(
|
|
7930
|
+
PATH_OVERVIEW,
|
|
7931
|
+
compactObject({
|
|
7932
|
+
authorIds,
|
|
7933
|
+
...instCcyList ? { instCcyList } : { topInstruments: topInstrumentsRaw ?? 20 }
|
|
7934
|
+
}),
|
|
7935
|
+
publicRateLimit("smartmoney_get_signal_overview_by_trader", SMARTMONEY_RPS)
|
|
7936
|
+
);
|
|
7937
|
+
return normalizeResponse(response);
|
|
7938
|
+
}
|
|
7939
|
+
},
|
|
7940
|
+
/* ---------- S3. Signal trend by filter (single-asset, tier-filtered pool, asOfTime anchor) ---------- */
|
|
7941
|
+
{
|
|
7942
|
+
name: "smartmoney_get_signal_trend_by_filter",
|
|
7943
|
+
module: "smartmoney",
|
|
7944
|
+
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). 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` \u2014 do not cross-pass.",
|
|
7945
|
+
isWrite: false,
|
|
7946
|
+
outputSchema: envelope({
|
|
7947
|
+
type: "array",
|
|
7948
|
+
description: "Time-bucket series for the requested instrument, sorted by time DESC (newest first).",
|
|
7949
|
+
items: { type: "object", properties: SIGNAL_HISTORY_ITEM_PROPS }
|
|
7950
|
+
}),
|
|
7951
|
+
inputSchema: {
|
|
7952
|
+
type: "object",
|
|
7953
|
+
properties: {
|
|
7088
7954
|
instCcy: {
|
|
7089
7955
|
type: "string",
|
|
7090
|
-
description:
|
|
7956
|
+
description: 'Base currency to scope the time-series, e.g. "BTC". Required.'
|
|
7091
7957
|
},
|
|
7092
|
-
|
|
7958
|
+
asOfTime: {
|
|
7093
7959
|
type: "string",
|
|
7094
|
-
description:
|
|
7960
|
+
description: 'Anchor snapshot time. Pass as a quoted 10-digit string `yyyyMMddHH` UTC, e.g. `"2026050100"` (NOT integer 2026050100). Returns the latest `limit` buckets ending at this anchor. Omit to use the current UTC hour.'
|
|
7961
|
+
},
|
|
7962
|
+
granularity: {
|
|
7963
|
+
type: "string",
|
|
7964
|
+
enum: ["1h", "1d"],
|
|
7965
|
+
default: "1h",
|
|
7966
|
+
description: "Time-bucket size. `1h` = hourly snapshots (intraday/short-term trend), `1d` = daily snapshots (multi-day trend)."
|
|
7967
|
+
},
|
|
7968
|
+
limit: {
|
|
7969
|
+
type: "integer",
|
|
7970
|
+
minimum: 1,
|
|
7971
|
+
maximum: 500,
|
|
7972
|
+
default: 24,
|
|
7973
|
+
description: "Number of buckets to return (newest first), ending at `asOfTime`. Default 24, max 500."
|
|
7974
|
+
},
|
|
7975
|
+
...SIGNAL_POOL_FILTER_PROPS,
|
|
7976
|
+
lmtNum: {
|
|
7977
|
+
type: "integer",
|
|
7978
|
+
minimum: 1,
|
|
7979
|
+
maximum: 2e3,
|
|
7980
|
+
default: 100,
|
|
7981
|
+
description: "Top-N traders to pull into the aggregation pool, ranked by `sortBy` (DESC). Default 100, max 2000."
|
|
7095
7982
|
}
|
|
7096
7983
|
},
|
|
7097
|
-
required: ["
|
|
7984
|
+
required: ["instCcy"]
|
|
7098
7985
|
},
|
|
7099
7986
|
handler: async (rawArgs, context) => {
|
|
7100
7987
|
const args = asRecord(rawArgs);
|
|
7101
|
-
const authorId = requireString(args, "authorId");
|
|
7102
|
-
const period = readString(args, "period");
|
|
7103
7988
|
const instCcy = readString(args, "instCcy");
|
|
7104
|
-
|
|
7105
|
-
|
|
7106
|
-
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7111
|
-
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
)
|
|
7121
|
-
|
|
7122
|
-
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7989
|
+
if (!instCcy) {
|
|
7990
|
+
throw actionableError(
|
|
7991
|
+
'"instCcy" is required.',
|
|
7992
|
+
'Pass a base currency, e.g. "BTC".'
|
|
7993
|
+
);
|
|
7994
|
+
}
|
|
7995
|
+
const response = await context.client.privateGet(
|
|
7996
|
+
PATH_SIGNAL_HISTORY,
|
|
7997
|
+
compactObject({
|
|
7998
|
+
instCcy,
|
|
7999
|
+
asOfTime: readString(args, "asOfTime"),
|
|
8000
|
+
granularity: readString(args, "granularity"),
|
|
8001
|
+
limit: readNumber(args, "limit"),
|
|
8002
|
+
...readSignalPoolFilters(args),
|
|
8003
|
+
lmtNum: readNumber(args, "lmtNum")
|
|
8004
|
+
}),
|
|
8005
|
+
publicRateLimit("smartmoney_get_signal_trend_by_filter", SMARTMONEY_RPS)
|
|
8006
|
+
);
|
|
8007
|
+
return normalizeResponse(response);
|
|
8008
|
+
}
|
|
8009
|
+
},
|
|
8010
|
+
/* ---------- S4. Signal trend by trader (single-asset, authorIds-restricted) ---------- */
|
|
8011
|
+
{
|
|
8012
|
+
name: "smartmoney_get_signal_trend_by_trader",
|
|
8013
|
+
module: "smartmoney",
|
|
8014
|
+
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). Pool sizing / ranking / capability filters not exposed \u2014 backend uses defaults for direct-lookup scenarios. 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` \u2014 do not cross-pass.",
|
|
8015
|
+
isWrite: false,
|
|
8016
|
+
outputSchema: envelope({
|
|
8017
|
+
type: "array",
|
|
8018
|
+
description: "Time-bucket series for the requested instrument, sorted by time DESC (newest first).",
|
|
8019
|
+
items: { type: "object", properties: SIGNAL_HISTORY_ITEM_PROPS }
|
|
8020
|
+
}),
|
|
8021
|
+
inputSchema: {
|
|
8022
|
+
type: "object",
|
|
8023
|
+
properties: {
|
|
8024
|
+
authorIds: {
|
|
8025
|
+
type: "array",
|
|
8026
|
+
items: { type: "string" },
|
|
8027
|
+
minItems: 1,
|
|
8028
|
+
description: 'Trader IDs to aggregate over, e.g. `["1001", "1002"]`. Required.'
|
|
8029
|
+
},
|
|
8030
|
+
instCcy: {
|
|
8031
|
+
type: "string",
|
|
8032
|
+
description: 'Base currency to scope the time-series, e.g. "BTC". Required.'
|
|
8033
|
+
},
|
|
8034
|
+
asOfTime: {
|
|
8035
|
+
type: "string",
|
|
8036
|
+
description: 'Anchor snapshot time. Pass as a quoted 10-digit string `yyyyMMddHH` UTC, e.g. `"2026050100"` (NOT integer 2026050100). Returns the latest `limit` buckets ending at this anchor. Omit to use the current UTC hour.'
|
|
8037
|
+
},
|
|
8038
|
+
granularity: {
|
|
8039
|
+
type: "string",
|
|
8040
|
+
enum: ["1h", "1d"],
|
|
8041
|
+
default: "1h",
|
|
8042
|
+
description: "Time-bucket size. `1h` = hourly snapshots (intraday/short-term trend), `1d` = daily snapshots (multi-day trend)."
|
|
8043
|
+
},
|
|
8044
|
+
limit: {
|
|
8045
|
+
type: "integer",
|
|
8046
|
+
minimum: 1,
|
|
8047
|
+
maximum: 500,
|
|
8048
|
+
default: 24,
|
|
8049
|
+
description: "Number of buckets to return (newest first), ending at `asOfTime`. Default 24, max 500."
|
|
7132
8050
|
}
|
|
7133
|
-
}
|
|
8051
|
+
},
|
|
8052
|
+
required: ["authorIds", "instCcy"]
|
|
8053
|
+
},
|
|
8054
|
+
handler: async (rawArgs, context) => {
|
|
8055
|
+
const args = asRecord(rawArgs);
|
|
8056
|
+
const authorIds = readArrayAsCsv(args, "authorIds");
|
|
8057
|
+
const instCcy = readString(args, "instCcy");
|
|
8058
|
+
if (!authorIds) {
|
|
8059
|
+
throw actionableError(
|
|
8060
|
+
'"authorIds" is required and must be a non-empty array.',
|
|
8061
|
+
'Pass IDs from `smartmoney_get_traders_by_filter` as an array (e.g. ["1001", "1002"]).'
|
|
8062
|
+
);
|
|
8063
|
+
}
|
|
8064
|
+
if (!instCcy) {
|
|
8065
|
+
throw actionableError(
|
|
8066
|
+
'"instCcy" is required.',
|
|
8067
|
+
'Pass a base currency, e.g. "BTC".'
|
|
8068
|
+
);
|
|
8069
|
+
}
|
|
8070
|
+
const response = await context.client.privateGet(
|
|
8071
|
+
PATH_SIGNAL_HISTORY,
|
|
8072
|
+
compactObject({
|
|
8073
|
+
authorIds,
|
|
8074
|
+
instCcy,
|
|
8075
|
+
asOfTime: readString(args, "asOfTime"),
|
|
8076
|
+
granularity: readString(args, "granularity"),
|
|
8077
|
+
limit: readNumber(args, "limit")
|
|
8078
|
+
}),
|
|
8079
|
+
publicRateLimit("smartmoney_get_signal_trend_by_trader", SMARTMONEY_RPS)
|
|
8080
|
+
);
|
|
8081
|
+
return normalizeResponse(response);
|
|
7134
8082
|
}
|
|
7135
8083
|
}
|
|
7136
8084
|
];
|
|
@@ -7189,8 +8137,12 @@ function buildContractTradeTools(cfg) {
|
|
|
7189
8137
|
clOrdId: { type: "string", description: "Client order ID (max 32 chars)" },
|
|
7190
8138
|
tpTriggerPx: { type: "string", description: "TP trigger price" },
|
|
7191
8139
|
tpOrdPx: { type: "string", description: "TP order price; -1=market" },
|
|
8140
|
+
tpOrdKind: TP_ORD_KIND_SCHEMA,
|
|
8141
|
+
tpTriggerPxType: TP_TRIGGER_PX_TYPE_SCHEMA,
|
|
7192
8142
|
slTriggerPx: { type: "string", description: "SL trigger price" },
|
|
7193
|
-
slOrdPx: { type: "string", description: "SL order price; -1=market" }
|
|
8143
|
+
slOrdPx: { type: "string", description: "SL order price; -1=market" },
|
|
8144
|
+
slTriggerPxType: SL_TRIGGER_PX_TYPE_SCHEMA,
|
|
8145
|
+
stpMode: STP_MODE_SCHEMA
|
|
7194
8146
|
},
|
|
7195
8147
|
required: ["instId", "tdMode", "side", "ordType", "sz"]
|
|
7196
8148
|
},
|
|
@@ -7219,6 +8171,9 @@ function buildContractTradeTools(cfg) {
|
|
|
7219
8171
|
px: readString(args, "px"),
|
|
7220
8172
|
reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
|
|
7221
8173
|
clOrdId: readString(args, "clOrdId"),
|
|
8174
|
+
stpMode: readString(args, "stpMode"),
|
|
8175
|
+
// Phase 3c CLI power-user flag (issue #182, CLI-only no MCP/skill exposure)
|
|
8176
|
+
pxAmendType: readString(args, "pxAmendType"),
|
|
7222
8177
|
tag: context.config.sourceTag,
|
|
7223
8178
|
attachAlgoOrds
|
|
7224
8179
|
}),
|
|
@@ -9218,6 +10173,8 @@ function registerOptionTools() {
|
|
|
9218
10173
|
type: "string",
|
|
9219
10174
|
description: "TP order price; -1=market"
|
|
9220
10175
|
},
|
|
10176
|
+
tpOrdKind: TP_ORD_KIND_SCHEMA,
|
|
10177
|
+
tpTriggerPxType: TP_TRIGGER_PX_TYPE_SCHEMA,
|
|
9221
10178
|
slTriggerPx: {
|
|
9222
10179
|
type: "string",
|
|
9223
10180
|
description: "SL trigger price"
|
|
@@ -9225,7 +10182,9 @@ function registerOptionTools() {
|
|
|
9225
10182
|
slOrdPx: {
|
|
9226
10183
|
type: "string",
|
|
9227
10184
|
description: "SL order price; -1=market"
|
|
9228
|
-
}
|
|
10185
|
+
},
|
|
10186
|
+
slTriggerPxType: SL_TRIGGER_PX_TYPE_SCHEMA,
|
|
10187
|
+
stpMode: STP_MODE_SCHEMA
|
|
9229
10188
|
},
|
|
9230
10189
|
required: ["instId", "tdMode", "side", "ordType", "sz"]
|
|
9231
10190
|
},
|
|
@@ -9253,6 +10212,7 @@ function registerOptionTools() {
|
|
|
9253
10212
|
px: readString(args, "px"),
|
|
9254
10213
|
reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
|
|
9255
10214
|
clOrdId: readString(args, "clOrdId"),
|
|
10215
|
+
stpMode: readString(args, "stpMode"),
|
|
9256
10216
|
tag: context.config.sourceTag,
|
|
9257
10217
|
attachAlgoOrds
|
|
9258
10218
|
}),
|
|
@@ -9621,6 +10581,8 @@ function registerSpotTradeTools() {
|
|
|
9621
10581
|
type: "string",
|
|
9622
10582
|
description: "TP order price, -1=market"
|
|
9623
10583
|
},
|
|
10584
|
+
tpOrdKind: TP_ORD_KIND_SCHEMA,
|
|
10585
|
+
tpTriggerPxType: TP_TRIGGER_PX_TYPE_SCHEMA,
|
|
9624
10586
|
slTriggerPx: {
|
|
9625
10587
|
type: "string",
|
|
9626
10588
|
description: "SL trigger price"
|
|
@@ -9628,13 +10590,16 @@ function registerSpotTradeTools() {
|
|
|
9628
10590
|
slOrdPx: {
|
|
9629
10591
|
type: "string",
|
|
9630
10592
|
description: "SL order price, -1=market"
|
|
9631
|
-
}
|
|
10593
|
+
},
|
|
10594
|
+
slTriggerPxType: SL_TRIGGER_PX_TYPE_SCHEMA,
|
|
10595
|
+
stpMode: STP_MODE_SCHEMA
|
|
9632
10596
|
},
|
|
9633
10597
|
required: ["instId", "tdMode", "side", "ordType", "sz"]
|
|
9634
10598
|
},
|
|
9635
10599
|
handler: async (rawArgs, context) => {
|
|
9636
10600
|
const args = asRecord(rawArgs);
|
|
9637
10601
|
const attachAlgoOrds = buildAttachAlgoOrds(args);
|
|
10602
|
+
const banAmend = args.banAmend;
|
|
9638
10603
|
const response = await context.client.privatePost(
|
|
9639
10604
|
"/api/v5/trade/order",
|
|
9640
10605
|
compactObject({
|
|
@@ -9646,6 +10611,11 @@ function registerSpotTradeTools() {
|
|
|
9646
10611
|
tgtCcy: readString(args, "tgtCcy"),
|
|
9647
10612
|
px: readString(args, "px"),
|
|
9648
10613
|
clOrdId: readString(args, "clOrdId"),
|
|
10614
|
+
stpMode: readString(args, "stpMode"),
|
|
10615
|
+
// Phase 3c CLI power-user flags (issue #182, CLI-only no MCP/skill exposure)
|
|
10616
|
+
tradeQuoteCcy: readString(args, "tradeQuoteCcy"),
|
|
10617
|
+
banAmend: typeof banAmend === "boolean" ? String(banAmend) : void 0,
|
|
10618
|
+
pxAmendType: readString(args, "pxAmendType"),
|
|
9649
10619
|
tag: context.config.sourceTag,
|
|
9650
10620
|
attachAlgoOrds
|
|
9651
10621
|
}),
|
|
@@ -9810,7 +10780,7 @@ function registerSpotTradeTools() {
|
|
|
9810
10780
|
{
|
|
9811
10781
|
name: "spot_place_algo_order",
|
|
9812
10782
|
module: "spot",
|
|
9813
|
-
description: "Place a spot algo order: TP/SL
|
|
10783
|
+
description: "Place a spot algo order. [CAUTION] Executes real trades. conditional: single TP/SL. oco: TP+SL pair. move_order_stop: trailing stop. trigger: pending order at triggerPx. chase: follow best bid/ask. iceberg: split large order into child orders. twap: time-weighted split.",
|
|
9814
10784
|
isWrite: true,
|
|
9815
10785
|
inputSchema: {
|
|
9816
10786
|
type: "object",
|
|
@@ -9830,8 +10800,8 @@ function registerSpotTradeTools() {
|
|
|
9830
10800
|
},
|
|
9831
10801
|
ordType: {
|
|
9832
10802
|
type: "string",
|
|
9833
|
-
enum: ["conditional", "oco", "move_order_stop"],
|
|
9834
|
-
description: "conditional=single TP/SL, oco=TP+SL pair, move_order_stop=trailing stop"
|
|
10803
|
+
enum: ["conditional", "oco", "move_order_stop", "trigger", "chase", "iceberg", "twap"],
|
|
10804
|
+
description: "conditional=single TP/SL, oco=TP+SL pair, move_order_stop=trailing stop, trigger=pending order, chase=follow best bid/ask, iceberg=split order, twap=time-weighted split"
|
|
9835
10805
|
},
|
|
9836
10806
|
sz: {
|
|
9837
10807
|
type: "string",
|
|
@@ -9845,6 +10815,8 @@ function registerSpotTradeTools() {
|
|
|
9845
10815
|
type: "string",
|
|
9846
10816
|
description: "TP order price, -1=market (conditional/oco only)"
|
|
9847
10817
|
},
|
|
10818
|
+
tpOrdKind: TP_ORD_KIND_SCHEMA,
|
|
10819
|
+
tpTriggerPxType: TP_TRIGGER_PX_TYPE_SCHEMA,
|
|
9848
10820
|
slTriggerPx: {
|
|
9849
10821
|
type: "string",
|
|
9850
10822
|
description: "SL trigger price (conditional/oco only)"
|
|
@@ -9853,6 +10825,8 @@ function registerSpotTradeTools() {
|
|
|
9853
10825
|
type: "string",
|
|
9854
10826
|
description: "SL order price, -1=market (conditional/oco only)"
|
|
9855
10827
|
},
|
|
10828
|
+
slTriggerPxType: SL_TRIGGER_PX_TYPE_SCHEMA,
|
|
10829
|
+
stpMode: STP_MODE_SCHEMA,
|
|
9856
10830
|
tgtCcy: {
|
|
9857
10831
|
type: "string",
|
|
9858
10832
|
enum: ["base_ccy", "quote_ccy"],
|
|
@@ -9869,30 +10843,50 @@ function registerSpotTradeTools() {
|
|
|
9869
10843
|
activePx: {
|
|
9870
10844
|
type: "string",
|
|
9871
10845
|
description: "Activation price, trailing starts when market hits this (move_order_stop only)"
|
|
9872
|
-
}
|
|
10846
|
+
},
|
|
10847
|
+
...TRIGGER_FLAGS_SCHEMA,
|
|
10848
|
+
...CHASE_FLAGS_SCHEMA,
|
|
10849
|
+
...ICEBERG_TWAP_FLAGS_SCHEMA
|
|
9873
10850
|
},
|
|
9874
10851
|
required: ["instId", "side", "ordType", "sz"]
|
|
9875
10852
|
},
|
|
9876
10853
|
handler: async (rawArgs, context) => {
|
|
9877
10854
|
const args = asRecord(rawArgs);
|
|
9878
|
-
const
|
|
9879
|
-
|
|
9880
|
-
|
|
9881
|
-
|
|
9882
|
-
|
|
9883
|
-
|
|
9884
|
-
|
|
9885
|
-
|
|
9886
|
-
|
|
9887
|
-
|
|
9888
|
-
|
|
9889
|
-
|
|
9890
|
-
|
|
9891
|
-
|
|
9892
|
-
|
|
9893
|
-
|
|
9894
|
-
|
|
9895
|
-
|
|
10855
|
+
const ordType = requireString(args, "ordType");
|
|
10856
|
+
const base = compactObject({
|
|
10857
|
+
instId: requireString(args, "instId"),
|
|
10858
|
+
tdMode: readString(args, "tdMode") ?? "cash",
|
|
10859
|
+
side: requireString(args, "side"),
|
|
10860
|
+
ordType,
|
|
10861
|
+
sz: requireString(args, "sz"),
|
|
10862
|
+
tgtCcy: readString(args, "tgtCcy"),
|
|
10863
|
+
stpMode: readString(args, "stpMode"),
|
|
10864
|
+
// Phase 3a+c CLI power-user flags (issue #182, CLI-only no MCP/skill exposure)
|
|
10865
|
+
pxAmendType: readString(args, "pxAmendType"),
|
|
10866
|
+
tag: context.config.sourceTag
|
|
10867
|
+
});
|
|
10868
|
+
switch (ordType) {
|
|
10869
|
+
case "trigger":
|
|
10870
|
+
Object.assign(base, buildTriggerOrdTypeBody(args));
|
|
10871
|
+
break;
|
|
10872
|
+
case "chase":
|
|
10873
|
+
Object.assign(base, buildChaseOrdTypeBody(args));
|
|
10874
|
+
break;
|
|
10875
|
+
case "iceberg":
|
|
10876
|
+
case "twap":
|
|
10877
|
+
Object.assign(base, buildIcebergTwapOrdTypeBody(args));
|
|
10878
|
+
break;
|
|
10879
|
+
default:
|
|
10880
|
+
Object.assign(base, compactObject({
|
|
10881
|
+
...buildAlgoConditionalCommonFields(args),
|
|
10882
|
+
callbackRatio: readString(args, "callbackRatio"),
|
|
10883
|
+
callbackSpread: readString(args, "callbackSpread")
|
|
10884
|
+
}));
|
|
10885
|
+
break;
|
|
10886
|
+
}
|
|
10887
|
+
const response = await context.client.privatePost(
|
|
10888
|
+
"/api/v5/trade/order-algo",
|
|
10889
|
+
base,
|
|
9896
10890
|
privateRateLimit("spot_place_algo_order", 20)
|
|
9897
10891
|
);
|
|
9898
10892
|
return normalizeResponse(response);
|
|
@@ -10941,7 +11935,7 @@ var DOWNLOAD_TIMEOUT_MS = 3e4;
|
|
|
10941
11935
|
var PLATFORM_MAP = {
|
|
10942
11936
|
"darwin-arm64": "darwin-arm64",
|
|
10943
11937
|
"darwin-x64": "darwin-x64",
|
|
10944
|
-
"linux-arm64": "linux-
|
|
11938
|
+
"linux-arm64": "linux-arm64",
|
|
10945
11939
|
"linux-x64": "linux-x64",
|
|
10946
11940
|
"win32-arm64": "win32-arm64",
|
|
10947
11941
|
"win32-x64": "win32-x64"
|
|
@@ -12374,7 +13368,7 @@ async function cmdDiagnoseMcp(options = {}) {
|
|
|
12374
13368
|
|
|
12375
13369
|
// src/commands/diagnose.ts
|
|
12376
13370
|
var CLI_VERSION = readCliVersion();
|
|
12377
|
-
var GIT_HASH = true ? "
|
|
13371
|
+
var GIT_HASH = true ? "d0f8ad6" : "dev";
|
|
12378
13372
|
function maskKey2(key) {
|
|
12379
13373
|
if (!key) return "(not set)";
|
|
12380
13374
|
if (key.length <= 8) return "****";
|
|
@@ -13066,7 +14060,7 @@ var CLI_REGISTRY = {
|
|
|
13066
14060
|
},
|
|
13067
14061
|
place: {
|
|
13068
14062
|
toolName: "spot_place_order",
|
|
13069
|
-
usage:
|
|
14063
|
+
usage: 'okx spot place --instId <id> --side <buy|sell> --ordType <type> --sz <n> [--px <price>] [--tdMode <cash|cross|isolated>]\n [--tgtCcy <base_ccy|quote_ccy>] [--clOrdId <id>]\n [--tpTriggerPx <price>] [--tpOrdPx <price|-1>] [--tpOrdKind <condition|limit>] [--tpTriggerPxType <last|index|mark>]\n [--slTriggerPx <price>] [--slOrdPx <price|-1>] [--slTriggerPxType <last|index|mark>]\n [--stpMode <cancel_maker|cancel_taker|cancel_both>]\n power-user (CLI-only): [--tradeQuoteCcy <USDT|USDC|BTC>] [--banAmend] [--pxAmendType <0|1>]\n power-user (CLI-only): [--tpLevel "px:78000,sz:0.5,kind:limit"] [--tpLevel "px:81000,sz:0.5"] (repeatable; split multi-tier take-profit; mutually exclusive with --tpTriggerPx/--tpOrdPx)',
|
|
13070
14064
|
description: "Place a new spot order (supports attached TP/SL)"
|
|
13071
14065
|
},
|
|
13072
14066
|
amend: {
|
|
@@ -13102,8 +14096,8 @@ var CLI_REGISTRY = {
|
|
|
13102
14096
|
},
|
|
13103
14097
|
place: {
|
|
13104
14098
|
toolName: "spot_place_algo_order",
|
|
13105
|
-
usage:
|
|
13106
|
-
description: "Place a spot algo order (
|
|
14099
|
+
usage: 'okx spot algo place --instId <id> --side <buy|sell> --sz <n> [--ordType <conditional|oco|move_order_stop|trigger|chase|iceberg|twap>]\n [--tpTriggerPx <price>] [--tpOrdPx <price|-1>] [--tpOrdKind <condition|limit>] [--tpTriggerPxType <last|index|mark>]\n [--slTriggerPx <price>] [--slOrdPx <price|-1>] [--slTriggerPxType <last|index|mark>]\n [--stpMode <cancel_maker|cancel_taker|cancel_both>] [--tdMode <cash|cross|isolated>]\n trigger: [--triggerPx <price>] [--orderPx <price|-1>] [--advanceOrdType <fok|ioc>] [--triggerPxType <last|index|mark>]\n chase: [--chaseType <distance|ratio>] [--chaseVal <n>] [--maxChaseType <distance|ratio>] [--maxChaseVal <n>]\n iceberg/twap: [--pxVar <n>|--pxSpread <n>] [--szLimit <n>] [--pxLimit <price>] [--timeInterval <secs>]\n power-user (CLI-only): [--tpTriggerRatio <ratio>] [--slTriggerRatio <ratio>] [--closeFraction <frac>] [--pxAmendType <0|1>]\n power-user (CLI-only): [--tpLevel "px:78000,sz:0.5,kind:limit"] [--tpLevel "px:81000,sz:0.5"] (repeatable; split multi-tier take-profit)',
|
|
14100
|
+
description: "Place a spot algo order (TP/SL, pending order, chase, iceberg, twap)"
|
|
13107
14101
|
},
|
|
13108
14102
|
trail: {
|
|
13109
14103
|
toolName: "spot_place_algo_order",
|
|
@@ -13150,7 +14144,7 @@ var CLI_REGISTRY = {
|
|
|
13150
14144
|
},
|
|
13151
14145
|
place: {
|
|
13152
14146
|
toolName: "swap_place_order",
|
|
13153
|
-
usage:
|
|
14147
|
+
usage: 'okx swap place --instId <id> --side <buy|sell> --ordType <type> --sz <n> [--posSide <side>] [--px <price>]\n [--tdMode <cross|isolated>] [--tgtCcy <base_ccy|quote_ccy|margin>] [--reduceOnly] [--clOrdId <id>]\n [--tpTriggerPx <price>] [--tpOrdPx <price|-1>] [--tpOrdKind <condition|limit>] [--tpTriggerPxType <last|index|mark>]\n [--slTriggerPx <price>] [--slOrdPx <price|-1>] [--slTriggerPxType <last|index|mark>]\n [--stpMode <cancel_maker|cancel_taker|cancel_both>]\n power-user (CLI-only): [--pxAmendType <0|1>]\n power-user (CLI-only): [--tpLevel "px:78000,sz:0.5,kind:limit"] [--tpLevel "px:81000,sz:0.5"] (repeatable; split multi-tier take-profit; mutually exclusive with --tpTriggerPx/--tpOrdPx)',
|
|
13154
14148
|
description: "Place a new perpetual swap order (supports attached TP/SL)"
|
|
13155
14149
|
},
|
|
13156
14150
|
cancel: {
|
|
@@ -13202,8 +14196,8 @@ var CLI_REGISTRY = {
|
|
|
13202
14196
|
},
|
|
13203
14197
|
place: {
|
|
13204
14198
|
toolName: "swap_place_algo_order",
|
|
13205
|
-
usage:
|
|
13206
|
-
description: "Place a swap algo order (
|
|
14199
|
+
usage: 'okx swap algo place --instId <id> --side <buy|sell> --sz <n> [--ordType <conditional|oco|move_order_stop|trigger|chase|iceberg|twap>]\n [--tpTriggerPx <price>] [--tpOrdPx <price|-1>] [--tpOrdKind <condition|limit>] [--tpTriggerPxType <last|index|mark>]\n [--slTriggerPx <price>] [--slOrdPx <price|-1>] [--slTriggerPxType <last|index|mark>]\n [--stpMode <cancel_maker|cancel_taker|cancel_both>] [--cxlOnClosePos]\n [--posSide <net|long|short>] [--tdMode <cross|isolated>] [--reduceOnly]\n trigger: [--triggerPx <price>] [--orderPx <price|-1>] [--advanceOrdType <fok|ioc>] [--triggerPxType <last|index|mark>]\n chase: [--chaseType <distance|ratio>] [--chaseVal <n>] [--maxChaseType <distance|ratio>] [--maxChaseVal <n>]\n iceberg/twap: [--pxVar <n>|--pxSpread <n>] [--szLimit <n>] [--pxLimit <price>] [--timeInterval <secs>]\n power-user (CLI-only): [--tpTriggerRatio <ratio>] [--slTriggerRatio <ratio>] [--closeFraction <frac>] [--pxAmendType <0|1>]\n power-user (CLI-only): [--tpLevel "px:78000,sz:0.5,kind:limit"] [--tpLevel "px:81000,sz:0.5"] (repeatable; split multi-tier take-profit)',
|
|
14200
|
+
description: "Place a swap algo order (TP/SL, pending order, chase, iceberg, twap)"
|
|
13207
14201
|
},
|
|
13208
14202
|
amend: {
|
|
13209
14203
|
toolName: "swap_amend_algo_order",
|
|
@@ -13240,7 +14234,7 @@ var CLI_REGISTRY = {
|
|
|
13240
14234
|
},
|
|
13241
14235
|
place: {
|
|
13242
14236
|
toolName: "futures_place_order",
|
|
13243
|
-
usage:
|
|
14237
|
+
usage: 'okx futures place --instId <id> --side <buy|sell> --ordType <type> --sz <n>\n [--tdMode <cross|isolated>] [--posSide <net|long|short>] [--px <price>] [--reduceOnly]\n [--tgtCcy <base_ccy|quote_ccy|margin>] [--clOrdId <id>]\n [--tpTriggerPx <price>] [--tpOrdPx <price|-1>] [--tpOrdKind <condition|limit>] [--tpTriggerPxType <last|index|mark>]\n [--slTriggerPx <price>] [--slOrdPx <price|-1>] [--slTriggerPxType <last|index|mark>]\n [--stpMode <cancel_maker|cancel_taker|cancel_both>]\n power-user (CLI-only): [--pxAmendType <0|1>]\n power-user (CLI-only): [--tpLevel "px:78000,sz:0.5,kind:limit"] [--tpLevel "px:81000,sz:0.5"] (repeatable; split multi-tier take-profit; mutually exclusive with --tpTriggerPx/--tpOrdPx)',
|
|
13244
14238
|
description: "Place a new futures order (supports attached TP/SL)"
|
|
13245
14239
|
},
|
|
13246
14240
|
cancel: {
|
|
@@ -13296,7 +14290,7 @@ var CLI_REGISTRY = {
|
|
|
13296
14290
|
},
|
|
13297
14291
|
place: {
|
|
13298
14292
|
toolName: "futures_place_algo_order",
|
|
13299
|
-
usage:
|
|
14293
|
+
usage: 'okx futures algo place --instId <id> --side <buy|sell> --sz <n> [--ordType <conditional|oco|move_order_stop|trigger|chase|iceberg|twap>]\n [--tpTriggerPx <price>] [--tpOrdPx <price|-1>] [--tpOrdKind <condition|limit>] [--tpTriggerPxType <last|index|mark>]\n [--slTriggerPx <price>] [--slOrdPx <price|-1>] [--slTriggerPxType <last|index|mark>]\n [--stpMode <cancel_maker|cancel_taker|cancel_both>] [--cxlOnClosePos]\n [--posSide <net|long|short>] [--tdMode <cross|isolated>] [--reduceOnly]\n trigger: [--triggerPx <price>] [--orderPx <price|-1>] [--advanceOrdType <fok|ioc>] [--triggerPxType <last|index|mark>]\n chase: [--chaseType <distance|ratio>] [--chaseVal <n>] [--maxChaseType <distance|ratio>] [--maxChaseVal <n>]\n iceberg/twap: [--pxVar <n>|--pxSpread <n>] [--szLimit <n>] [--pxLimit <price>] [--timeInterval <secs>]\n power-user (CLI-only): [--tpTriggerRatio <ratio>] [--slTriggerRatio <ratio>] [--closeFraction <frac>] [--pxAmendType <0|1>]\n power-user (CLI-only): [--tpLevel "px:78000,sz:0.5,kind:limit"] [--tpLevel "px:81000,sz:0.5"] (repeatable; split multi-tier take-profit)',
|
|
13300
14294
|
description: "Place a futures algo order (take-profit/stop-loss)"
|
|
13301
14295
|
},
|
|
13302
14296
|
amend: {
|
|
@@ -13349,7 +14343,7 @@ var CLI_REGISTRY = {
|
|
|
13349
14343
|
},
|
|
13350
14344
|
place: {
|
|
13351
14345
|
toolName: "option_place_order",
|
|
13352
|
-
usage: "okx option place --instId <id> --tdMode <cash|cross|isolated> --side <buy|sell> --ordType <type> --sz <n>\n [--px <price>] [--tgtCcy <base_ccy|quote_ccy|margin>] [--reduceOnly] [--clOrdId <id>]\n [--tpTriggerPx <price>] [--tpOrdPx <price|-1>] [--slTriggerPx <price>] [--slOrdPx <price|-1>]",
|
|
14346
|
+
usage: "okx option place --instId <id> --tdMode <cash|cross|isolated> --side <buy|sell> --ordType <type> --sz <n>\n [--px <price>] [--tgtCcy <base_ccy|quote_ccy|margin>] [--reduceOnly] [--clOrdId <id>]\n [--tpTriggerPx <price>] [--tpOrdPx <price|-1>] [--tpOrdKind <condition|limit>] [--tpTriggerPxType <last|index|mark>]\n [--slTriggerPx <price>] [--slOrdPx <price|-1>] [--slTriggerPxType <last|index|mark>]\n [--stpMode <cancel_maker|cancel_taker|cancel_both>]",
|
|
13353
14347
|
description: "Place a new option order"
|
|
13354
14348
|
},
|
|
13355
14349
|
cancel: {
|
|
@@ -13379,7 +14373,7 @@ var CLI_REGISTRY = {
|
|
|
13379
14373
|
},
|
|
13380
14374
|
place: {
|
|
13381
14375
|
toolName: "option_place_algo_order",
|
|
13382
|
-
usage: "okx option algo place --instId <id> --tdMode <cash|cross|isolated> --side <buy|sell> --sz <n>\n [--ordType <conditional|oco>] [--tpTriggerPx <price>] [--tpOrdPx <price|-1>]\n [--slTriggerPx <price>] [--slOrdPx <price|-1>] [--reduceOnly] [--clOrdId <id>]",
|
|
14376
|
+
usage: "okx option algo place --instId <id> --tdMode <cash|cross|isolated> --side <buy|sell> --sz <n>\n [--ordType <conditional|oco>] [--tpTriggerPx <price>] [--tpOrdPx <price|-1>] [--tpTriggerPxType <last|index|mark>]\n [--slTriggerPx <price>] [--slOrdPx <price|-1>] [--slTriggerPxType <last|index|mark>]\n [--reduceOnly] [--clOrdId <id>]",
|
|
13383
14377
|
description: "Place an option algo order (take-profit/stop-loss)"
|
|
13384
14378
|
},
|
|
13385
14379
|
amend: {
|
|
@@ -13678,32 +14672,57 @@ var CLI_REGISTRY = {
|
|
|
13678
14672
|
},
|
|
13679
14673
|
// ── smartmoney ─────────────────────────────────────────────────────────────
|
|
13680
14674
|
smartmoney: {
|
|
13681
|
-
description: "Smart money
|
|
14675
|
+
description: "Smart money analytics \u2014 trader leaderboard, consensus signals, and position analysis",
|
|
13682
14676
|
commands: {
|
|
13683
|
-
|
|
13684
|
-
toolName: "
|
|
13685
|
-
usage: "okx smartmoney
|
|
13686
|
-
description: "
|
|
13687
|
-
},
|
|
13688
|
-
|
|
13689
|
-
toolName: "
|
|
13690
|
-
usage: "okx smartmoney
|
|
13691
|
-
description: "
|
|
13692
|
-
},
|
|
13693
|
-
"
|
|
13694
|
-
toolName: "
|
|
13695
|
-
usage: "okx smartmoney
|
|
13696
|
-
description: "
|
|
13697
|
-
},
|
|
13698
|
-
|
|
13699
|
-
toolName: "
|
|
13700
|
-
usage:
|
|
13701
|
-
description: "
|
|
13702
|
-
},
|
|
13703
|
-
trader: {
|
|
13704
|
-
toolName: "
|
|
13705
|
-
usage: "okx smartmoney trader --authorId <id> [--
|
|
13706
|
-
description: "
|
|
14677
|
+
"traders-by-filter": {
|
|
14678
|
+
toolName: "smartmoney_get_traders_by_filter",
|
|
14679
|
+
usage: "okx smartmoney traders-by-filter [--updateTime <ts>] [--sortBy <pnl|pnlRatio>] [--period <3|7|30|90>] [--minPnl <n>] [--minWinRate <r>] [--maxDrawdown <r>] [--minAum <n>] [--after <id>] [--before <id>] [--limit <n>] [--json]",
|
|
14680
|
+
description: "Leaderboard of top smart-money traders, ranked and filtered by pool conditions"
|
|
14681
|
+
},
|
|
14682
|
+
"performance-by-trader": {
|
|
14683
|
+
toolName: "smartmoney_get_performance_by_trader",
|
|
14684
|
+
usage: "okx smartmoney performance-by-trader --authorIds <id1,id2> [--period <3|7|30|90>] [--json]",
|
|
14685
|
+
description: "PnL / win-rate / drawdown profile for one or more traders by authorIds"
|
|
14686
|
+
},
|
|
14687
|
+
"trader-positions": {
|
|
14688
|
+
toolName: "smartmoney_get_trader_positions",
|
|
14689
|
+
usage: "okx smartmoney trader-positions --authorId <id> [--instId <id>] [--json]",
|
|
14690
|
+
description: "Currently-open positions held by a single trader"
|
|
14691
|
+
},
|
|
14692
|
+
"trader-positions-history": {
|
|
14693
|
+
toolName: "smartmoney_get_trader_positions_history",
|
|
14694
|
+
usage: "okx smartmoney trader-positions-history --authorId <id> [--instId <id>] [--after <posId>] [--before <posId>] [--limit <n>] [--json]",
|
|
14695
|
+
description: "Closed-position history of a single trader (paginated)"
|
|
14696
|
+
},
|
|
14697
|
+
"trader-orders-history": {
|
|
14698
|
+
toolName: "smartmoney_get_trader_orders_history",
|
|
14699
|
+
usage: "okx smartmoney trader-orders-history --authorId <id> [--instId <id>] [--after <ordId>] [--before <ordId>] [--limit <n>] [--json]",
|
|
14700
|
+
description: "Recent orders/fills placed by a single trader (paginated)"
|
|
14701
|
+
},
|
|
14702
|
+
"search-trader": {
|
|
14703
|
+
toolName: "smartmoney_search_trader",
|
|
14704
|
+
usage: "okx smartmoney search-trader --keyword <name> [--json]",
|
|
14705
|
+
description: "Search Top Traders by nickname keyword (\u226410 results, ranked by follower count)"
|
|
14706
|
+
},
|
|
14707
|
+
"signal-overview-by-filter": {
|
|
14708
|
+
toolName: "smartmoney_get_signal_overview_by_filter",
|
|
14709
|
+
usage: "okx smartmoney signal-overview-by-filter [--topInstruments <n> | --instCcyList <BTC,ETH,...>] [--sortBy <pnl|pnlRatio>] [--period <3|7|30|90>] [--pnlTier <tier>] [--winRateTier <tier>] [--maxDrawdownTier <tier>] [--aumTier <tier>] [--lmtNum <n>] [--json]",
|
|
14710
|
+
description: "Multi-asset smart-money consensus signal aggregated over a tier-filtered pool"
|
|
14711
|
+
},
|
|
14712
|
+
"signal-overview-by-trader": {
|
|
14713
|
+
toolName: "smartmoney_get_signal_overview_by_trader",
|
|
14714
|
+
usage: "okx smartmoney signal-overview-by-trader --authorIds <id1,id2> [--topInstruments <n> | --instCcyList <BTC,ETH,...>] [--json]",
|
|
14715
|
+
description: "Multi-asset smart-money signal aggregated over a hand-picked set of traders (authorIds-direct-lookup; pool filters not exposed)"
|
|
14716
|
+
},
|
|
14717
|
+
"signal-trend-by-filter": {
|
|
14718
|
+
toolName: "smartmoney_get_signal_trend_by_filter",
|
|
14719
|
+
usage: "okx smartmoney signal-trend-by-filter --instCcy <ccy> [--asOfTime <yyyyMMddHH>] [--granularity <1h|1d>] [--limit <n>] [--sortBy <pnl|pnlRatio>] [--period <3|7|30|90>] [--pnlTier <tier>] [--winRateTier <tier>] [--maxDrawdownTier <tier>] [--aumTier <tier>] [--lmtNum <n>] [--json]",
|
|
14720
|
+
description: "Single-coin smart-money signal time-series aggregated over a tier-filtered pool, anchored at asOfTime"
|
|
14721
|
+
},
|
|
14722
|
+
"signal-trend-by-trader": {
|
|
14723
|
+
toolName: "smartmoney_get_signal_trend_by_trader",
|
|
14724
|
+
usage: "okx smartmoney signal-trend-by-trader --authorIds <id1,id2> --instCcy <ccy> [--asOfTime <yyyyMMddHH>] [--granularity <1h|1d>] [--limit <n>] [--json]",
|
|
14725
|
+
description: "Single-coin smart-money signal time-series aggregated over a hand-picked set of traders (authorIds-direct-lookup; pool filters not exposed)"
|
|
13707
14726
|
}
|
|
13708
14727
|
}
|
|
13709
14728
|
},
|
|
@@ -14407,6 +15426,33 @@ var CLI_OPTIONS = {
|
|
|
14407
15426
|
tpOrdPx: { type: "string" },
|
|
14408
15427
|
slTriggerPx: { type: "string" },
|
|
14409
15428
|
slOrdPx: { type: "string" },
|
|
15429
|
+
// Phase 1 algo order flags (issue #178)
|
|
15430
|
+
tpOrdKind: { type: "string" },
|
|
15431
|
+
tpTriggerPxType: { type: "string" },
|
|
15432
|
+
slTriggerPxType: { type: "string" },
|
|
15433
|
+
stpMode: { type: "string" },
|
|
15434
|
+
cxlOnClosePos: { type: "boolean", default: false },
|
|
15435
|
+
// Phase 3a+c CLI power-user flags (issue #182, CLI-only no MCP/skill exposure)
|
|
15436
|
+
tpTriggerRatio: { type: "string" },
|
|
15437
|
+
slTriggerRatio: { type: "string" },
|
|
15438
|
+
closeFraction: { type: "string" },
|
|
15439
|
+
banAmend: { type: "boolean", default: false },
|
|
15440
|
+
pxAmendType: { type: "string" },
|
|
15441
|
+
// Phase 3b CLI power-user flag (issue #183, CLI-only no MCP/skill exposure)
|
|
15442
|
+
tpLevel: { type: "string", multiple: true },
|
|
15443
|
+
// Phase 2 algo ordType flags (issue #181)
|
|
15444
|
+
orderPx: { type: "string" },
|
|
15445
|
+
advanceOrdType: { type: "string" },
|
|
15446
|
+
triggerPxType: { type: "string" },
|
|
15447
|
+
chaseType: { type: "string" },
|
|
15448
|
+
chaseVal: { type: "string" },
|
|
15449
|
+
maxChaseType: { type: "string" },
|
|
15450
|
+
maxChaseVal: { type: "string" },
|
|
15451
|
+
pxVar: { type: "string" },
|
|
15452
|
+
pxSpread: { type: "string" },
|
|
15453
|
+
szLimit: { type: "string" },
|
|
15454
|
+
pxLimit: { type: "string" },
|
|
15455
|
+
timeInterval: { type: "string" },
|
|
14410
15456
|
algoId: { type: "string" },
|
|
14411
15457
|
reduceOnly: { type: "boolean", default: false },
|
|
14412
15458
|
// algo amend
|
|
@@ -14494,19 +15540,23 @@ var CLI_OPTIONS = {
|
|
|
14494
15540
|
// smartmoney
|
|
14495
15541
|
authorId: { type: "string" },
|
|
14496
15542
|
authorIds: { type: "string" },
|
|
14497
|
-
|
|
14498
|
-
sortType: { type: "string" },
|
|
15543
|
+
updateTime: { type: "string" },
|
|
14499
15544
|
granularity: { type: "string" },
|
|
14500
15545
|
lmtNum: { type: "string" },
|
|
14501
15546
|
instCcy: { type: "string" },
|
|
14502
15547
|
instCcyList: { type: "string" },
|
|
14503
15548
|
topInstruments: { type: "string" },
|
|
14504
|
-
|
|
14505
|
-
// smartmoney pool filters
|
|
14506
|
-
|
|
14507
|
-
|
|
14508
|
-
|
|
14509
|
-
|
|
15549
|
+
asOfTime: { type: "string" },
|
|
15550
|
+
// smartmoney pool filters — leaderboard (numeric thresholds)
|
|
15551
|
+
minPnl: { type: "string" },
|
|
15552
|
+
minWinRate: { type: "string" },
|
|
15553
|
+
maxDrawdown: { type: "string" },
|
|
15554
|
+
minAum: { type: "string" },
|
|
15555
|
+
// smartmoney pool filters — signal endpoints (enum tiers)
|
|
15556
|
+
pnlTier: { type: "string" },
|
|
15557
|
+
winRateTier: { type: "string" },
|
|
15558
|
+
maxDrawdownTier: { type: "string" },
|
|
15559
|
+
aumTier: { type: "string" },
|
|
14510
15560
|
// upgrade
|
|
14511
15561
|
beta: { type: "boolean", default: false },
|
|
14512
15562
|
check: { type: "boolean", default: false },
|
|
@@ -14593,6 +15643,42 @@ var CLI_OPTIONS = {
|
|
|
14593
15643
|
output: { type: "string" }
|
|
14594
15644
|
// diagnose --output only: save report to file
|
|
14595
15645
|
};
|
|
15646
|
+
var TP_LEVEL_KEY_MAP = {
|
|
15647
|
+
px: "tpOrdPx",
|
|
15648
|
+
sz: "sz",
|
|
15649
|
+
kind: "tpOrdKind",
|
|
15650
|
+
triggerPx: "tpTriggerPx",
|
|
15651
|
+
triggerPxType: "tpTriggerPxType",
|
|
15652
|
+
amendPxOnTrigger: "amendPxOnTriggerType",
|
|
15653
|
+
clOrdId: "attachAlgoClOrdId"
|
|
15654
|
+
};
|
|
15655
|
+
function parseTpLevel(s) {
|
|
15656
|
+
if (!s || !s.includes(":")) {
|
|
15657
|
+
throw new Error(
|
|
15658
|
+
`Invalid --tpLevel format: "${s}". Expected "key:value,key:value,..." (e.g. "px:78000,sz:0.5,kind:limit")`
|
|
15659
|
+
);
|
|
15660
|
+
}
|
|
15661
|
+
const result = {};
|
|
15662
|
+
const pairs = s.split(",");
|
|
15663
|
+
for (const pair of pairs) {
|
|
15664
|
+
const colonIdx = pair.indexOf(":");
|
|
15665
|
+
if (colonIdx < 1) {
|
|
15666
|
+
throw new Error(
|
|
15667
|
+
`Invalid --tpLevel format: "${pair}". Each entry must be "key:value", not "${pair}". Valid keys: ${Object.keys(TP_LEVEL_KEY_MAP).join(", ")}`
|
|
15668
|
+
);
|
|
15669
|
+
}
|
|
15670
|
+
const key = pair.slice(0, colonIdx).trim();
|
|
15671
|
+
const value = pair.slice(colonIdx + 1).trim();
|
|
15672
|
+
const mapped = TP_LEVEL_KEY_MAP[key];
|
|
15673
|
+
if (!mapped) {
|
|
15674
|
+
throw new Error(
|
|
15675
|
+
`Unknown --tpLevel key: "${key}". Valid keys: ${Object.keys(TP_LEVEL_KEY_MAP).join(", ")}`
|
|
15676
|
+
);
|
|
15677
|
+
}
|
|
15678
|
+
result[mapped] = value;
|
|
15679
|
+
}
|
|
15680
|
+
return result;
|
|
15681
|
+
}
|
|
14596
15682
|
function parseCli(argv) {
|
|
14597
15683
|
const negated = /* @__PURE__ */ new Set();
|
|
14598
15684
|
const filtered = argv.filter((arg) => {
|
|
@@ -15338,8 +16424,16 @@ async function cmdSpotPlace(run, opts) {
|
|
|
15338
16424
|
clOrdId: opts.clOrdId,
|
|
15339
16425
|
tpTriggerPx: opts.tpTriggerPx,
|
|
15340
16426
|
tpOrdPx: opts.tpOrdPx,
|
|
16427
|
+
tpOrdKind: opts.tpOrdKind,
|
|
16428
|
+
tpTriggerPxType: opts.tpTriggerPxType,
|
|
15341
16429
|
slTriggerPx: opts.slTriggerPx,
|
|
15342
|
-
slOrdPx: opts.slOrdPx
|
|
16430
|
+
slOrdPx: opts.slOrdPx,
|
|
16431
|
+
slTriggerPxType: opts.slTriggerPxType,
|
|
16432
|
+
stpMode: opts.stpMode,
|
|
16433
|
+
tradeQuoteCcy: opts.tradeQuoteCcy,
|
|
16434
|
+
banAmend: opts.banAmend,
|
|
16435
|
+
pxAmendType: opts.pxAmendType,
|
|
16436
|
+
tpLevels: opts.tpLevels
|
|
15343
16437
|
});
|
|
15344
16438
|
const data = getData4(result);
|
|
15345
16439
|
if (opts.json) return printJson(data);
|
|
@@ -15364,11 +16458,33 @@ async function cmdSpotAlgoPlace(run, opts) {
|
|
|
15364
16458
|
tgtCcy: opts.tgtCcy,
|
|
15365
16459
|
tpTriggerPx: opts.tpTriggerPx,
|
|
15366
16460
|
tpOrdPx: opts.tpOrdPx,
|
|
16461
|
+
tpOrdKind: opts.tpOrdKind,
|
|
16462
|
+
tpTriggerPxType: opts.tpTriggerPxType,
|
|
15367
16463
|
slTriggerPx: opts.slTriggerPx,
|
|
15368
16464
|
slOrdPx: opts.slOrdPx,
|
|
16465
|
+
slTriggerPxType: opts.slTriggerPxType,
|
|
16466
|
+
stpMode: opts.stpMode,
|
|
15369
16467
|
callbackRatio: opts.callbackRatio,
|
|
15370
16468
|
callbackSpread: opts.callbackSpread,
|
|
15371
|
-
activePx: opts.activePx
|
|
16469
|
+
activePx: opts.activePx,
|
|
16470
|
+
triggerPx: opts.triggerPx,
|
|
16471
|
+
orderPx: opts.orderPx,
|
|
16472
|
+
advanceOrdType: opts.advanceOrdType,
|
|
16473
|
+
triggerPxType: opts.triggerPxType,
|
|
16474
|
+
chaseType: opts.chaseType,
|
|
16475
|
+
chaseVal: opts.chaseVal,
|
|
16476
|
+
maxChaseType: opts.maxChaseType,
|
|
16477
|
+
maxChaseVal: opts.maxChaseVal,
|
|
16478
|
+
pxVar: opts.pxVar,
|
|
16479
|
+
pxSpread: opts.pxSpread,
|
|
16480
|
+
szLimit: opts.szLimit,
|
|
16481
|
+
pxLimit: opts.pxLimit,
|
|
16482
|
+
timeInterval: opts.timeInterval,
|
|
16483
|
+
tpTriggerRatio: opts.tpTriggerRatio,
|
|
16484
|
+
slTriggerRatio: opts.slTriggerRatio,
|
|
16485
|
+
closeFraction: opts.closeFraction,
|
|
16486
|
+
pxAmendType: opts.pxAmendType,
|
|
16487
|
+
tpLevels: opts.tpLevels
|
|
15372
16488
|
});
|
|
15373
16489
|
const data = getData4(result);
|
|
15374
16490
|
if (opts.json) return printJson(data);
|
|
@@ -15602,8 +16718,14 @@ async function cmdSwapPlace(run, opts) {
|
|
|
15602
16718
|
clOrdId: opts.clOrdId,
|
|
15603
16719
|
tpTriggerPx: opts.tpTriggerPx,
|
|
15604
16720
|
tpOrdPx: opts.tpOrdPx,
|
|
16721
|
+
tpOrdKind: opts.tpOrdKind,
|
|
16722
|
+
tpTriggerPxType: opts.tpTriggerPxType,
|
|
15605
16723
|
slTriggerPx: opts.slTriggerPx,
|
|
15606
|
-
slOrdPx: opts.slOrdPx
|
|
16724
|
+
slOrdPx: opts.slOrdPx,
|
|
16725
|
+
slTriggerPxType: opts.slTriggerPxType,
|
|
16726
|
+
stpMode: opts.stpMode,
|
|
16727
|
+
pxAmendType: opts.pxAmendType,
|
|
16728
|
+
tpLevels: opts.tpLevels
|
|
15607
16729
|
});
|
|
15608
16730
|
const data = getData5(result);
|
|
15609
16731
|
if (opts.json) return printJson(data);
|
|
@@ -15629,12 +16751,35 @@ async function cmdSwapAlgoPlace(run, opts) {
|
|
|
15629
16751
|
posSide: opts.posSide,
|
|
15630
16752
|
tpTriggerPx: opts.tpTriggerPx,
|
|
15631
16753
|
tpOrdPx: opts.tpOrdPx,
|
|
16754
|
+
tpOrdKind: opts.tpOrdKind,
|
|
16755
|
+
tpTriggerPxType: opts.tpTriggerPxType,
|
|
15632
16756
|
slTriggerPx: opts.slTriggerPx,
|
|
15633
16757
|
slOrdPx: opts.slOrdPx,
|
|
16758
|
+
slTriggerPxType: opts.slTriggerPxType,
|
|
16759
|
+
stpMode: opts.stpMode,
|
|
16760
|
+
cxlOnClosePos: opts.cxlOnClosePos,
|
|
15634
16761
|
reduceOnly: opts.reduceOnly,
|
|
15635
16762
|
callbackRatio: opts.callbackRatio,
|
|
15636
16763
|
callbackSpread: opts.callbackSpread,
|
|
15637
|
-
activePx: opts.activePx
|
|
16764
|
+
activePx: opts.activePx,
|
|
16765
|
+
triggerPx: opts.triggerPx,
|
|
16766
|
+
orderPx: opts.orderPx,
|
|
16767
|
+
advanceOrdType: opts.advanceOrdType,
|
|
16768
|
+
triggerPxType: opts.triggerPxType,
|
|
16769
|
+
chaseType: opts.chaseType,
|
|
16770
|
+
chaseVal: opts.chaseVal,
|
|
16771
|
+
maxChaseType: opts.maxChaseType,
|
|
16772
|
+
maxChaseVal: opts.maxChaseVal,
|
|
16773
|
+
pxVar: opts.pxVar,
|
|
16774
|
+
pxSpread: opts.pxSpread,
|
|
16775
|
+
szLimit: opts.szLimit,
|
|
16776
|
+
pxLimit: opts.pxLimit,
|
|
16777
|
+
timeInterval: opts.timeInterval,
|
|
16778
|
+
tpTriggerRatio: opts.tpTriggerRatio,
|
|
16779
|
+
slTriggerRatio: opts.slTriggerRatio,
|
|
16780
|
+
closeFraction: opts.closeFraction,
|
|
16781
|
+
pxAmendType: opts.pxAmendType,
|
|
16782
|
+
tpLevels: opts.tpLevels
|
|
15638
16783
|
});
|
|
15639
16784
|
const data = getData5(result);
|
|
15640
16785
|
if (opts.json) return printJson(data);
|
|
@@ -15908,8 +17053,14 @@ async function cmdFuturesPlace(run, opts) {
|
|
|
15908
17053
|
clOrdId: opts.clOrdId,
|
|
15909
17054
|
tpTriggerPx: opts.tpTriggerPx,
|
|
15910
17055
|
tpOrdPx: opts.tpOrdPx,
|
|
17056
|
+
tpOrdKind: opts.tpOrdKind,
|
|
17057
|
+
tpTriggerPxType: opts.tpTriggerPxType,
|
|
15911
17058
|
slTriggerPx: opts.slTriggerPx,
|
|
15912
|
-
slOrdPx: opts.slOrdPx
|
|
17059
|
+
slOrdPx: opts.slOrdPx,
|
|
17060
|
+
slTriggerPxType: opts.slTriggerPxType,
|
|
17061
|
+
stpMode: opts.stpMode,
|
|
17062
|
+
pxAmendType: opts.pxAmendType,
|
|
17063
|
+
tpLevels: opts.tpLevels
|
|
15913
17064
|
});
|
|
15914
17065
|
const data = getData6(result);
|
|
15915
17066
|
if (opts.json) return printJson(data);
|
|
@@ -16037,12 +17188,35 @@ async function cmdFuturesAlgoPlace(run, opts) {
|
|
|
16037
17188
|
posSide: opts.posSide,
|
|
16038
17189
|
tpTriggerPx: opts.tpTriggerPx,
|
|
16039
17190
|
tpOrdPx: opts.tpOrdPx,
|
|
17191
|
+
tpOrdKind: opts.tpOrdKind,
|
|
17192
|
+
tpTriggerPxType: opts.tpTriggerPxType,
|
|
16040
17193
|
slTriggerPx: opts.slTriggerPx,
|
|
16041
17194
|
slOrdPx: opts.slOrdPx,
|
|
17195
|
+
slTriggerPxType: opts.slTriggerPxType,
|
|
17196
|
+
stpMode: opts.stpMode,
|
|
17197
|
+
cxlOnClosePos: opts.cxlOnClosePos,
|
|
16042
17198
|
reduceOnly: opts.reduceOnly,
|
|
16043
17199
|
callbackRatio: opts.callbackRatio,
|
|
16044
17200
|
callbackSpread: opts.callbackSpread,
|
|
16045
|
-
activePx: opts.activePx
|
|
17201
|
+
activePx: opts.activePx,
|
|
17202
|
+
triggerPx: opts.triggerPx,
|
|
17203
|
+
orderPx: opts.orderPx,
|
|
17204
|
+
advanceOrdType: opts.advanceOrdType,
|
|
17205
|
+
triggerPxType: opts.triggerPxType,
|
|
17206
|
+
chaseType: opts.chaseType,
|
|
17207
|
+
chaseVal: opts.chaseVal,
|
|
17208
|
+
maxChaseType: opts.maxChaseType,
|
|
17209
|
+
maxChaseVal: opts.maxChaseVal,
|
|
17210
|
+
pxVar: opts.pxVar,
|
|
17211
|
+
pxSpread: opts.pxSpread,
|
|
17212
|
+
szLimit: opts.szLimit,
|
|
17213
|
+
pxLimit: opts.pxLimit,
|
|
17214
|
+
timeInterval: opts.timeInterval,
|
|
17215
|
+
tpTriggerRatio: opts.tpTriggerRatio,
|
|
17216
|
+
slTriggerRatio: opts.slTriggerRatio,
|
|
17217
|
+
closeFraction: opts.closeFraction,
|
|
17218
|
+
pxAmendType: opts.pxAmendType,
|
|
17219
|
+
tpLevels: opts.tpLevels
|
|
16046
17220
|
});
|
|
16047
17221
|
const data = getData6(result);
|
|
16048
17222
|
if (opts.json) return printJson(data);
|
|
@@ -16274,8 +17448,12 @@ async function cmdOptionPlace(run, opts) {
|
|
|
16274
17448
|
clOrdId: opts.clOrdId,
|
|
16275
17449
|
tpTriggerPx: opts.tpTriggerPx,
|
|
16276
17450
|
tpOrdPx: opts.tpOrdPx,
|
|
17451
|
+
tpOrdKind: opts.tpOrdKind,
|
|
17452
|
+
tpTriggerPxType: opts.tpTriggerPxType,
|
|
16277
17453
|
slTriggerPx: opts.slTriggerPx,
|
|
16278
|
-
slOrdPx: opts.slOrdPx
|
|
17454
|
+
slOrdPx: opts.slOrdPx,
|
|
17455
|
+
slTriggerPxType: opts.slTriggerPxType,
|
|
17456
|
+
stpMode: opts.stpMode
|
|
16279
17457
|
});
|
|
16280
17458
|
const data = getData7(result);
|
|
16281
17459
|
if (opts.json) return printJson(data);
|
|
@@ -16894,175 +18072,267 @@ function extractFixedOffers(result) {
|
|
|
16894
18072
|
}
|
|
16895
18073
|
|
|
16896
18074
|
// src/commands/smartmoney.ts
|
|
16897
|
-
function
|
|
16898
|
-
if (json) {
|
|
16899
|
-
printJson(data);
|
|
16900
|
-
return;
|
|
16901
|
-
}
|
|
18075
|
+
function printDataTable(data, emptyMsg, mapper) {
|
|
16902
18076
|
if (!data.length) {
|
|
16903
18077
|
outputLine(emptyMsg);
|
|
16904
18078
|
return;
|
|
16905
18079
|
}
|
|
16906
18080
|
printTable(data.map(mapper));
|
|
16907
18081
|
}
|
|
16908
|
-
function
|
|
18082
|
+
function csvToArray(value) {
|
|
18083
|
+
if (!value) return void 0;
|
|
18084
|
+
const arr = value.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
18085
|
+
return arr.length > 0 ? arr : void 0;
|
|
18086
|
+
}
|
|
18087
|
+
function printPaginationHint(result) {
|
|
18088
|
+
if (!result || typeof result !== "object") return;
|
|
18089
|
+
const pagination = result.pagination;
|
|
18090
|
+
if (!pagination || typeof pagination !== "object") return;
|
|
18091
|
+
const { hasMore, nextAfter } = pagination;
|
|
18092
|
+
if (hasMore !== true) return;
|
|
18093
|
+
const cursor = typeof nextAfter === "string" || typeof nextAfter === "number" ? String(nextAfter) : "";
|
|
18094
|
+
errorLine(cursor ? `more results \u2014 pass --after ${cursor} for next page` : "more results \u2014 pass --after <cursor> for next page");
|
|
18095
|
+
}
|
|
18096
|
+
function signalPoolFilterArgs(o) {
|
|
16909
18097
|
const result = {};
|
|
16910
|
-
if (o.
|
|
18098
|
+
if (o.sortBy) result.sortBy = o.sortBy;
|
|
16911
18099
|
if (o.period) result.period = o.period;
|
|
16912
|
-
if (o.
|
|
16913
|
-
if (o.
|
|
16914
|
-
if (o.
|
|
16915
|
-
if (o.
|
|
18100
|
+
if (o.pnlTier) result.pnlTier = o.pnlTier;
|
|
18101
|
+
if (o.winRateTier) result.winRateTier = o.winRateTier;
|
|
18102
|
+
if (o.maxDrawdownTier) result.maxDrawdownTier = o.maxDrawdownTier;
|
|
18103
|
+
if (o.aumTier) result.aumTier = o.aumTier;
|
|
16916
18104
|
return result;
|
|
16917
18105
|
}
|
|
16918
|
-
|
|
16919
|
-
const result =
|
|
16920
|
-
|
|
16921
|
-
|
|
16922
|
-
|
|
16923
|
-
|
|
16924
|
-
|
|
16925
|
-
|
|
16926
|
-
|
|
16927
|
-
|
|
18106
|
+
function leaderboardPoolFilterArgs(o) {
|
|
18107
|
+
const result = {};
|
|
18108
|
+
if (o.sortBy) result.sortBy = o.sortBy;
|
|
18109
|
+
if (o.period) result.period = o.period;
|
|
18110
|
+
if (o.minPnl) result.minPnl = o.minPnl;
|
|
18111
|
+
if (o.minWinRate) result.minWinRate = o.minWinRate;
|
|
18112
|
+
if (o.maxDrawdown) result.maxDrawdown = o.maxDrawdown;
|
|
18113
|
+
if (o.minAum) result.minAum = o.minAum;
|
|
18114
|
+
return result;
|
|
18115
|
+
}
|
|
18116
|
+
async function cmdSmartmoneyTradersByFilter(run, opts) {
|
|
18117
|
+
const result = await run("smartmoney_get_traders_by_filter", {
|
|
18118
|
+
updateTime: opts.updateTime,
|
|
18119
|
+
...leaderboardPoolFilterArgs(opts),
|
|
18120
|
+
after: opts.after,
|
|
18121
|
+
before: opts.before,
|
|
18122
|
+
limit: opts.limit
|
|
16928
18123
|
});
|
|
18124
|
+
if (opts.json) {
|
|
18125
|
+
printJson(result);
|
|
18126
|
+
return;
|
|
18127
|
+
}
|
|
16929
18128
|
const data = extractData(result);
|
|
16930
|
-
|
|
16931
|
-
|
|
16932
|
-
|
|
16933
|
-
|
|
16934
|
-
|
|
16935
|
-
|
|
16936
|
-
|
|
18129
|
+
printDataTable(data, "No traders found", (r) => ({
|
|
18130
|
+
authorId: r["authorId"],
|
|
18131
|
+
nickName: r["nickName"],
|
|
18132
|
+
pnl: r["pnl"],
|
|
18133
|
+
pnlRatio: r["pnlRatio"],
|
|
18134
|
+
winRate: r["winRate"],
|
|
18135
|
+
maxDrawdown: r["maxDrawdown"],
|
|
18136
|
+
asset: r["asset"]
|
|
16937
18137
|
}));
|
|
18138
|
+
printPaginationHint(result);
|
|
16938
18139
|
}
|
|
16939
|
-
async function
|
|
16940
|
-
const result = await run("
|
|
16941
|
-
|
|
16942
|
-
|
|
16943
|
-
dataVersion: opts.dataVersion,
|
|
16944
|
-
ts: opts.ts,
|
|
16945
|
-
...poolFilterArgs(opts),
|
|
16946
|
-
lmtNum: opts.lmtNum,
|
|
16947
|
-
authorIds: opts.authorIds
|
|
18140
|
+
async function cmdSmartmoneyPerformanceByTrader(run, opts) {
|
|
18141
|
+
const result = await run("smartmoney_get_performance_by_trader", {
|
|
18142
|
+
authorIds: csvToArray(opts.authorIds),
|
|
18143
|
+
period: opts.period
|
|
16948
18144
|
});
|
|
16949
|
-
const data = extractData(result);
|
|
16950
|
-
const signal = data[0];
|
|
16951
18145
|
if (opts.json) {
|
|
16952
|
-
printJson(
|
|
18146
|
+
printJson(result);
|
|
16953
18147
|
return;
|
|
16954
18148
|
}
|
|
16955
|
-
|
|
16956
|
-
|
|
18149
|
+
const data = extractData(result);
|
|
18150
|
+
printDataTable(data, "No traders found", (r) => ({
|
|
18151
|
+
authorId: r["authorId"],
|
|
18152
|
+
nickName: r["nickName"],
|
|
18153
|
+
pnl: r["pnl"],
|
|
18154
|
+
pnlRatio: r["pnlRatio"],
|
|
18155
|
+
winRate: r["winRate"],
|
|
18156
|
+
maxDrawdown: r["maxDrawdown"],
|
|
18157
|
+
asset: r["asset"]
|
|
18158
|
+
}));
|
|
18159
|
+
}
|
|
18160
|
+
async function cmdSmartmoneyTraderPositions(run, opts) {
|
|
18161
|
+
const result = await run("smartmoney_get_trader_positions", {
|
|
18162
|
+
authorId: opts.authorId,
|
|
18163
|
+
instId: opts.instId
|
|
18164
|
+
});
|
|
18165
|
+
if (opts.json) {
|
|
18166
|
+
printJson(result);
|
|
16957
18167
|
return;
|
|
16958
18168
|
}
|
|
16959
|
-
|
|
16960
|
-
|
|
16961
|
-
|
|
16962
|
-
|
|
16963
|
-
|
|
16964
|
-
|
|
16965
|
-
|
|
16966
|
-
|
|
16967
|
-
|
|
16968
|
-
|
|
16969
|
-
|
|
16970
|
-
|
|
16971
|
-
|
|
16972
|
-
shortTraders: signal["shortTraders"],
|
|
16973
|
-
vs1h: signal["vs1h"],
|
|
16974
|
-
vs24h: signal["vs24h"],
|
|
16975
|
-
vs7d: signal["vs7d"],
|
|
16976
|
-
smartMoneyLongAvgEntry: signal["smartMoneyLongAvgEntry"],
|
|
16977
|
-
smartMoneyShortAvgEntry: signal["smartMoneyShortAvgEntry"],
|
|
16978
|
-
totalNotionalVs24h: signal["totalNotionalVs24h"],
|
|
16979
|
-
currentPrice: signal["currentPrice"],
|
|
16980
|
-
priceChange24h: signal["priceChange24h"],
|
|
16981
|
-
fundingRate: signal["fundingRate"],
|
|
16982
|
-
openInterest: signal["openInterest"],
|
|
16983
|
-
longShortAccountRatio: signal["longShortAccountRatio"]
|
|
16984
|
-
});
|
|
18169
|
+
const data = extractData(result);
|
|
18170
|
+
printDataTable(data, "No open positions", (r) => ({
|
|
18171
|
+
instId: r["instId"],
|
|
18172
|
+
direction: r["direction"] ?? r["posSide"],
|
|
18173
|
+
pos: r["pos"],
|
|
18174
|
+
lever: r["lever"],
|
|
18175
|
+
avgPx: r["avgPx"],
|
|
18176
|
+
last: r["last"],
|
|
18177
|
+
notionalUsd: r["notionalUsd"],
|
|
18178
|
+
upl: r["upl"],
|
|
18179
|
+
pnl: r["pnl"],
|
|
18180
|
+
positionIntensity: r["positionIntensity"]
|
|
18181
|
+
}));
|
|
16985
18182
|
}
|
|
16986
|
-
async function
|
|
16987
|
-
const result = await run("
|
|
18183
|
+
async function cmdSmartmoneyTraderPositionsHistory(run, opts) {
|
|
18184
|
+
const result = await run("smartmoney_get_trader_positions_history", {
|
|
18185
|
+
authorId: opts.authorId,
|
|
16988
18186
|
instId: opts.instId,
|
|
16989
|
-
|
|
16990
|
-
|
|
16991
|
-
|
|
16992
|
-
limit: opts.limit,
|
|
16993
|
-
...poolFilterArgs(opts)
|
|
18187
|
+
after: opts.after,
|
|
18188
|
+
before: opts.before,
|
|
18189
|
+
limit: opts.limit
|
|
16994
18190
|
});
|
|
18191
|
+
if (opts.json) {
|
|
18192
|
+
printJson(result);
|
|
18193
|
+
return;
|
|
18194
|
+
}
|
|
16995
18195
|
const data = extractData(result);
|
|
16996
|
-
|
|
16997
|
-
|
|
16998
|
-
|
|
16999
|
-
|
|
17000
|
-
|
|
17001
|
-
|
|
17002
|
-
|
|
17003
|
-
|
|
18196
|
+
printDataTable(data, "No closed positions", (r) => ({
|
|
18197
|
+
cTime: r["cTime"],
|
|
18198
|
+
uTime: r["uTime"],
|
|
18199
|
+
instId: r["instId"],
|
|
18200
|
+
posSide: r["posSide"],
|
|
18201
|
+
openAvgPx: r["openAvgPx"],
|
|
18202
|
+
closeAvgPx: r["closeAvgPx"],
|
|
18203
|
+
pnl: r["pnl"],
|
|
18204
|
+
pnlRatio: r["pnlRatio"],
|
|
18205
|
+
closeType: r["closeType"]
|
|
17004
18206
|
}));
|
|
18207
|
+
printPaginationHint(result);
|
|
17005
18208
|
}
|
|
17006
|
-
async function
|
|
17007
|
-
const
|
|
17008
|
-
|
|
17009
|
-
|
|
17010
|
-
authorIds: opts.authorIds,
|
|
18209
|
+
async function cmdSmartmoneyTraderOrdersHistory(run, opts) {
|
|
18210
|
+
const result = await run("smartmoney_get_trader_orders_history", {
|
|
18211
|
+
authorId: opts.authorId,
|
|
18212
|
+
instId: opts.instId,
|
|
17011
18213
|
after: opts.after,
|
|
17012
18214
|
before: opts.before,
|
|
17013
18215
|
limit: opts.limit
|
|
18216
|
+
});
|
|
18217
|
+
if (opts.json) {
|
|
18218
|
+
printJson(result);
|
|
18219
|
+
return;
|
|
18220
|
+
}
|
|
18221
|
+
const data = extractData(result);
|
|
18222
|
+
printDataTable(data, "No order history", (r) => ({
|
|
18223
|
+
cTime: r["cTime"],
|
|
18224
|
+
instId: r["instId"],
|
|
18225
|
+
side: r["side"],
|
|
18226
|
+
posSide: r["posSide"],
|
|
18227
|
+
ordType: r["ordType"],
|
|
18228
|
+
avgPx: r["avgPx"],
|
|
18229
|
+
sz: r["sz"],
|
|
18230
|
+
value: r["value"]
|
|
17014
18231
|
}));
|
|
17015
|
-
|
|
18232
|
+
printPaginationHint(result);
|
|
18233
|
+
}
|
|
18234
|
+
async function cmdSmartmoneySearchTrader(run, opts) {
|
|
18235
|
+
const result = await run("smartmoney_search_trader", {
|
|
18236
|
+
keyword: opts.keyword
|
|
18237
|
+
});
|
|
18238
|
+
if (opts.json) {
|
|
18239
|
+
printJson(result);
|
|
18240
|
+
return;
|
|
18241
|
+
}
|
|
18242
|
+
const data = extractData(result);
|
|
18243
|
+
printDataTable(data, "No matching top traders", (r) => ({
|
|
17016
18244
|
authorId: r["authorId"],
|
|
17017
18245
|
nickName: r["nickName"],
|
|
17018
|
-
|
|
17019
|
-
pnlRatio: r["pnlRatio"],
|
|
17020
|
-
winRatio: r["winRatio"],
|
|
17021
|
-
asset: r["asset"]
|
|
18246
|
+
followerCount: r["followerCount"]
|
|
17022
18247
|
}));
|
|
17023
18248
|
}
|
|
17024
|
-
|
|
17025
|
-
const
|
|
17026
|
-
|
|
17027
|
-
|
|
17028
|
-
|
|
17029
|
-
|
|
18249
|
+
var signalRowMapper = (r) => {
|
|
18250
|
+
const lsr = r["longShortRatio"] ?? {};
|
|
18251
|
+
const notional = r["notional"] ?? {};
|
|
18252
|
+
return {
|
|
18253
|
+
ccy: r["ccy"],
|
|
18254
|
+
tradersWithPosition: r["tradersWithPosition"],
|
|
18255
|
+
longRatio: lsr["longRatio"],
|
|
18256
|
+
weightedLongRatio: lsr["weightedLongRatio"],
|
|
18257
|
+
longTraders: r["longTraders"],
|
|
18258
|
+
shortTraders: r["shortTraders"],
|
|
18259
|
+
netNotionalUsdt: notional["netNotionalUsdt"],
|
|
18260
|
+
longRatioVs1h: lsr["longRatioVs1h"],
|
|
18261
|
+
longRatioVs24h: lsr["longRatioVs24h"],
|
|
18262
|
+
longRatioVs7d: lsr["longRatioVs7d"]
|
|
18263
|
+
};
|
|
18264
|
+
};
|
|
18265
|
+
async function cmdSmartmoneySignalOverviewByFilter(run, opts) {
|
|
18266
|
+
const result = await run("smartmoney_get_signal_overview_by_filter", {
|
|
18267
|
+
topInstruments: opts.topInstruments,
|
|
18268
|
+
instCcyList: csvToArray(opts.instCcyList),
|
|
18269
|
+
...signalPoolFilterArgs(opts),
|
|
18270
|
+
lmtNum: opts.lmtNum
|
|
17030
18271
|
});
|
|
17031
|
-
const data = result;
|
|
17032
|
-
const inner = data["data"];
|
|
17033
18272
|
if (opts.json) {
|
|
17034
|
-
printJson(
|
|
18273
|
+
printJson(result);
|
|
17035
18274
|
return;
|
|
17036
18275
|
}
|
|
17037
|
-
|
|
17038
|
-
|
|
18276
|
+
const data = extractData(result);
|
|
18277
|
+
printDataTable(data, "No signal data", signalRowMapper);
|
|
18278
|
+
}
|
|
18279
|
+
async function cmdSmartmoneySignalOverviewByTrader(run, opts) {
|
|
18280
|
+
const result = await run("smartmoney_get_signal_overview_by_trader", {
|
|
18281
|
+
authorIds: csvToArray(opts.authorIds),
|
|
18282
|
+
topInstruments: opts.topInstruments,
|
|
18283
|
+
instCcyList: csvToArray(opts.instCcyList)
|
|
18284
|
+
});
|
|
18285
|
+
if (opts.json) {
|
|
18286
|
+
printJson(result);
|
|
17039
18287
|
return;
|
|
17040
18288
|
}
|
|
17041
|
-
const
|
|
17042
|
-
|
|
17043
|
-
|
|
17044
|
-
|
|
17045
|
-
|
|
17046
|
-
|
|
17047
|
-
|
|
17048
|
-
|
|
17049
|
-
|
|
17050
|
-
|
|
17051
|
-
|
|
17052
|
-
|
|
17053
|
-
|
|
17054
|
-
|
|
17055
|
-
|
|
17056
|
-
|
|
17057
|
-
|
|
17058
|
-
|
|
17059
|
-
|
|
18289
|
+
const data = extractData(result);
|
|
18290
|
+
printDataTable(data, "No signal data", signalRowMapper);
|
|
18291
|
+
}
|
|
18292
|
+
var trendRowMapper = (r) => ({
|
|
18293
|
+
dataVersion: r["dataVersion"],
|
|
18294
|
+
ccy: r["ccy"],
|
|
18295
|
+
longRatio: r["longRatio"],
|
|
18296
|
+
shortRatio: r["shortRatio"],
|
|
18297
|
+
weightedLongRatio: r["weightedLongRatio"],
|
|
18298
|
+
weightedShortRatio: r["weightedShortRatio"],
|
|
18299
|
+
longTraders: r["longTraders"],
|
|
18300
|
+
shortTraders: r["shortTraders"],
|
|
18301
|
+
tradersWithPosition: r["tradersWithPosition"],
|
|
18302
|
+
tradersQualified: r["tradersQualified"],
|
|
18303
|
+
netNotionalUsdt: r["netNotionalUsdt"],
|
|
18304
|
+
totalNotionalUsdt: r["totalNotionalUsdt"]
|
|
18305
|
+
});
|
|
18306
|
+
async function cmdSmartmoneySignalTrendByFilter(run, opts) {
|
|
18307
|
+
const result = await run("smartmoney_get_signal_trend_by_filter", {
|
|
18308
|
+
instCcy: opts.instCcy,
|
|
18309
|
+
asOfTime: opts.asOfTime,
|
|
18310
|
+
granularity: opts.granularity,
|
|
18311
|
+
limit: opts.limit,
|
|
18312
|
+
...signalPoolFilterArgs(opts),
|
|
18313
|
+
lmtNum: opts.lmtNum
|
|
18314
|
+
});
|
|
18315
|
+
if (opts.json) {
|
|
18316
|
+
printJson(result);
|
|
18317
|
+
return;
|
|
17060
18318
|
}
|
|
17061
|
-
const
|
|
17062
|
-
|
|
17063
|
-
|
|
17064
|
-
|
|
18319
|
+
const data = extractData(result);
|
|
18320
|
+
printDataTable(data, "No signal trend data", trendRowMapper);
|
|
18321
|
+
}
|
|
18322
|
+
async function cmdSmartmoneySignalTrendByTrader(run, opts) {
|
|
18323
|
+
const result = await run("smartmoney_get_signal_trend_by_trader", {
|
|
18324
|
+
authorIds: csvToArray(opts.authorIds),
|
|
18325
|
+
instCcy: opts.instCcy,
|
|
18326
|
+
asOfTime: opts.asOfTime,
|
|
18327
|
+
granularity: opts.granularity,
|
|
18328
|
+
limit: opts.limit
|
|
18329
|
+
});
|
|
18330
|
+
if (opts.json) {
|
|
18331
|
+
printJson(result);
|
|
18332
|
+
return;
|
|
17065
18333
|
}
|
|
18334
|
+
const data = extractData(result);
|
|
18335
|
+
printDataTable(data, "No signal trend data", trendRowMapper);
|
|
17066
18336
|
}
|
|
17067
18337
|
|
|
17068
18338
|
// src/commands/auto-earn.ts
|
|
@@ -18579,7 +19849,7 @@ async function cmdEventCancel(run, opts) {
|
|
|
18579
19849
|
// src/index.ts
|
|
18580
19850
|
var _require3 = createRequire3(import.meta.url);
|
|
18581
19851
|
var CLI_VERSION2 = _require3("../package.json").version;
|
|
18582
|
-
var GIT_HASH2 = true ? "
|
|
19852
|
+
var GIT_HASH2 = true ? "d0f8ad6" : "dev";
|
|
18583
19853
|
function handlePilotCommand(action, json, force, binaryPath) {
|
|
18584
19854
|
if (action === "status") return cmdPilotStatus(json, binaryPath);
|
|
18585
19855
|
if (action === "install") return cmdPilotInstall(json, binaryPath);
|
|
@@ -18809,7 +20079,8 @@ function handleSpotAlgoCommand(run, subAction, v, json) {
|
|
|
18809
20079
|
tdMode: v.tdMode,
|
|
18810
20080
|
json
|
|
18811
20081
|
});
|
|
18812
|
-
if (subAction === "place")
|
|
20082
|
+
if (subAction === "place") {
|
|
20083
|
+
assertNoTpConflict(v.tpLevel, { tpTriggerPx: v.tpTriggerPx, tpOrdPx: v.tpOrdPx });
|
|
18813
20084
|
return cmdSpotAlgoPlace(run, {
|
|
18814
20085
|
instId: v.instId,
|
|
18815
20086
|
tdMode: v.tdMode,
|
|
@@ -18820,13 +20091,38 @@ function handleSpotAlgoCommand(run, subAction, v, json) {
|
|
|
18820
20091
|
tgtCcy: v.tgtCcy,
|
|
18821
20092
|
tpTriggerPx: v.tpTriggerPx,
|
|
18822
20093
|
tpOrdPx: v.tpOrdPx,
|
|
20094
|
+
tpOrdKind: v.tpOrdKind,
|
|
20095
|
+
tpTriggerPxType: v.tpTriggerPxType,
|
|
18823
20096
|
slTriggerPx: v.slTriggerPx,
|
|
18824
20097
|
slOrdPx: v.slOrdPx,
|
|
20098
|
+
slTriggerPxType: v.slTriggerPxType,
|
|
20099
|
+
stpMode: v.stpMode,
|
|
18825
20100
|
callbackRatio: v.callbackRatio,
|
|
18826
20101
|
callbackSpread: v.callbackSpread,
|
|
18827
20102
|
activePx: v.activePx,
|
|
20103
|
+
triggerPx: v.triggerPx,
|
|
20104
|
+
orderPx: v.orderPx,
|
|
20105
|
+
advanceOrdType: v.advanceOrdType,
|
|
20106
|
+
triggerPxType: v.triggerPxType,
|
|
20107
|
+
chaseType: v.chaseType,
|
|
20108
|
+
chaseVal: v.chaseVal,
|
|
20109
|
+
maxChaseType: v.maxChaseType,
|
|
20110
|
+
maxChaseVal: v.maxChaseVal,
|
|
20111
|
+
pxVar: v.pxVar,
|
|
20112
|
+
pxSpread: v.pxSpread,
|
|
20113
|
+
szLimit: v.szLimit,
|
|
20114
|
+
pxLimit: v.pxLimit,
|
|
20115
|
+
timeInterval: v.timeInterval,
|
|
20116
|
+
// Phase 3a+c CLI power-user flags (issue #182, CLI-only no MCP/skill exposure)
|
|
20117
|
+
tpTriggerRatio: v.tpTriggerRatio,
|
|
20118
|
+
slTriggerRatio: v.slTriggerRatio,
|
|
20119
|
+
closeFraction: v.closeFraction,
|
|
20120
|
+
pxAmendType: v.pxAmendType,
|
|
20121
|
+
// Phase 3b CLI power-user flag (issue #183, CLI-only no MCP/skill exposure)
|
|
20122
|
+
tpLevels: v.tpLevel?.map(parseTpLevel),
|
|
18828
20123
|
json
|
|
18829
20124
|
});
|
|
20125
|
+
}
|
|
18830
20126
|
if (subAction === "amend")
|
|
18831
20127
|
return cmdSpotAlgoAmend(run, {
|
|
18832
20128
|
instId: v.instId,
|
|
@@ -18849,6 +20145,16 @@ function handleSpotAlgoCommand(run, subAction, v, json) {
|
|
|
18849
20145
|
});
|
|
18850
20146
|
unknownSubcommand("spot algo", subAction, ["trail", "place", "amend", "cancel", "orders"]);
|
|
18851
20147
|
}
|
|
20148
|
+
function assertNoTpConflict(tpLevel, singleFields) {
|
|
20149
|
+
if (!tpLevel || tpLevel.length === 0) return;
|
|
20150
|
+
const conflicting = ["tpTriggerPx", "tpOrdPx"].filter((k) => singleFields[k] !== void 0);
|
|
20151
|
+
if (conflicting.length > 0) {
|
|
20152
|
+
const flagNames = conflicting.map((k) => `--${k}`).join(", ");
|
|
20153
|
+
throw new Error(
|
|
20154
|
+
`Cannot use --tpLevel together with ${flagNames}. Use --tpLevel for split multi-tier take-profit, or single-TP flags for a single TP \u2014 not both.`
|
|
20155
|
+
);
|
|
20156
|
+
}
|
|
20157
|
+
}
|
|
18852
20158
|
function handleSpotCommand(run, action, rest, v, json) {
|
|
18853
20159
|
if (action === "orders")
|
|
18854
20160
|
return cmdSpotOrders(run, {
|
|
@@ -18869,7 +20175,8 @@ function handleSpotCommand(run, action, rest, v, json) {
|
|
|
18869
20175
|
newPx: v.newPx,
|
|
18870
20176
|
json
|
|
18871
20177
|
});
|
|
18872
|
-
if (action === "place")
|
|
20178
|
+
if (action === "place") {
|
|
20179
|
+
assertNoTpConflict(v.tpLevel, { tpTriggerPx: v.tpTriggerPx, tpOrdPx: v.tpOrdPx });
|
|
18873
20180
|
return cmdSpotPlace(run, {
|
|
18874
20181
|
instId: v.instId,
|
|
18875
20182
|
tdMode: v.tdMode,
|
|
@@ -18881,10 +20188,21 @@ function handleSpotCommand(run, action, rest, v, json) {
|
|
|
18881
20188
|
clOrdId: v.clOrdId,
|
|
18882
20189
|
tpTriggerPx: v.tpTriggerPx,
|
|
18883
20190
|
tpOrdPx: v.tpOrdPx,
|
|
20191
|
+
tpOrdKind: v.tpOrdKind,
|
|
20192
|
+
tpTriggerPxType: v.tpTriggerPxType,
|
|
18884
20193
|
slTriggerPx: v.slTriggerPx,
|
|
18885
20194
|
slOrdPx: v.slOrdPx,
|
|
20195
|
+
slTriggerPxType: v.slTriggerPxType,
|
|
20196
|
+
stpMode: v.stpMode,
|
|
20197
|
+
// Phase 3c CLI power-user flags (issue #182, CLI-only no MCP/skill exposure)
|
|
20198
|
+
tradeQuoteCcy: v.tradeQuoteCcy,
|
|
20199
|
+
banAmend: v.banAmend,
|
|
20200
|
+
pxAmendType: v.pxAmendType,
|
|
20201
|
+
// Phase 3b CLI power-user flag (issue #183, CLI-only no MCP/skill exposure)
|
|
20202
|
+
tpLevels: v.tpLevel?.map(parseTpLevel),
|
|
18886
20203
|
json
|
|
18887
20204
|
});
|
|
20205
|
+
}
|
|
18888
20206
|
if (action === "cancel")
|
|
18889
20207
|
return cmdSpotCancel(run, { instId: v.instId ?? rest[0], ordId: v.ordId, clOrdId: v.clOrdId, json });
|
|
18890
20208
|
if (action === "algo")
|
|
@@ -18925,7 +20243,8 @@ function handleSwapAlgoCommand(run, subAction, v, json) {
|
|
|
18925
20243
|
reduceOnly: v.reduceOnly,
|
|
18926
20244
|
json
|
|
18927
20245
|
});
|
|
18928
|
-
if (subAction === "place")
|
|
20246
|
+
if (subAction === "place") {
|
|
20247
|
+
assertNoTpConflict(v.tpLevel, { tpTriggerPx: v.tpTriggerPx, tpOrdPx: v.tpOrdPx });
|
|
18929
20248
|
return cmdSwapAlgoPlace(run, {
|
|
18930
20249
|
instId: v.instId,
|
|
18931
20250
|
side: v.side,
|
|
@@ -18937,14 +20256,40 @@ function handleSwapAlgoCommand(run, subAction, v, json) {
|
|
|
18937
20256
|
tgtCcy: v.tgtCcy,
|
|
18938
20257
|
tpTriggerPx: v.tpTriggerPx,
|
|
18939
20258
|
tpOrdPx: v.tpOrdPx,
|
|
20259
|
+
tpOrdKind: v.tpOrdKind,
|
|
20260
|
+
tpTriggerPxType: v.tpTriggerPxType,
|
|
18940
20261
|
slTriggerPx: v.slTriggerPx,
|
|
18941
20262
|
slOrdPx: v.slOrdPx,
|
|
20263
|
+
slTriggerPxType: v.slTriggerPxType,
|
|
20264
|
+
stpMode: v.stpMode,
|
|
20265
|
+
cxlOnClosePos: v.cxlOnClosePos,
|
|
18942
20266
|
reduceOnly: v.reduceOnly,
|
|
18943
20267
|
callbackRatio: v.callbackRatio,
|
|
18944
20268
|
callbackSpread: v.callbackSpread,
|
|
18945
20269
|
activePx: v.activePx,
|
|
20270
|
+
triggerPx: v.triggerPx,
|
|
20271
|
+
orderPx: v.orderPx,
|
|
20272
|
+
advanceOrdType: v.advanceOrdType,
|
|
20273
|
+
triggerPxType: v.triggerPxType,
|
|
20274
|
+
chaseType: v.chaseType,
|
|
20275
|
+
chaseVal: v.chaseVal,
|
|
20276
|
+
maxChaseType: v.maxChaseType,
|
|
20277
|
+
maxChaseVal: v.maxChaseVal,
|
|
20278
|
+
pxVar: v.pxVar,
|
|
20279
|
+
pxSpread: v.pxSpread,
|
|
20280
|
+
szLimit: v.szLimit,
|
|
20281
|
+
pxLimit: v.pxLimit,
|
|
20282
|
+
timeInterval: v.timeInterval,
|
|
20283
|
+
// Phase 3a+c CLI power-user flags (issue #182, CLI-only no MCP/skill exposure)
|
|
20284
|
+
tpTriggerRatio: v.tpTriggerRatio,
|
|
20285
|
+
slTriggerRatio: v.slTriggerRatio,
|
|
20286
|
+
closeFraction: v.closeFraction,
|
|
20287
|
+
pxAmendType: v.pxAmendType,
|
|
20288
|
+
// Phase 3b CLI power-user flag (issue #183, CLI-only no MCP/skill exposure)
|
|
20289
|
+
tpLevels: v.tpLevel?.map(parseTpLevel),
|
|
18946
20290
|
json
|
|
18947
20291
|
});
|
|
20292
|
+
}
|
|
18948
20293
|
if (subAction === "amend")
|
|
18949
20294
|
return cmdSwapAlgoAmend(run, {
|
|
18950
20295
|
instId: v.instId,
|
|
@@ -19000,7 +20345,8 @@ function handleSwapCommand(run, action, rest, v, json) {
|
|
|
19000
20345
|
autoCxl: v.autoCxl,
|
|
19001
20346
|
json
|
|
19002
20347
|
});
|
|
19003
|
-
if (action === "place")
|
|
20348
|
+
if (action === "place") {
|
|
20349
|
+
assertNoTpConflict(v.tpLevel, { tpTriggerPx: v.tpTriggerPx, tpOrdPx: v.tpOrdPx });
|
|
19004
20350
|
return cmdSwapPlace(run, {
|
|
19005
20351
|
instId: v.instId,
|
|
19006
20352
|
side: v.side,
|
|
@@ -19014,10 +20360,19 @@ function handleSwapCommand(run, action, rest, v, json) {
|
|
|
19014
20360
|
clOrdId: v.clOrdId,
|
|
19015
20361
|
tpTriggerPx: v.tpTriggerPx,
|
|
19016
20362
|
tpOrdPx: v.tpOrdPx,
|
|
20363
|
+
tpOrdKind: v.tpOrdKind,
|
|
20364
|
+
tpTriggerPxType: v.tpTriggerPxType,
|
|
19017
20365
|
slTriggerPx: v.slTriggerPx,
|
|
19018
20366
|
slOrdPx: v.slOrdPx,
|
|
20367
|
+
slTriggerPxType: v.slTriggerPxType,
|
|
20368
|
+
stpMode: v.stpMode,
|
|
20369
|
+
// Phase 3c CLI power-user flag (issue #182, CLI-only no MCP/skill exposure)
|
|
20370
|
+
pxAmendType: v.pxAmendType,
|
|
20371
|
+
// Phase 3b CLI power-user flag (issue #183, CLI-only no MCP/skill exposure)
|
|
20372
|
+
tpLevels: v.tpLevel?.map(parseTpLevel),
|
|
19019
20373
|
json
|
|
19020
20374
|
});
|
|
20375
|
+
}
|
|
19021
20376
|
if (action === "cancel")
|
|
19022
20377
|
return cmdSwapCancel(run, { instId: v.instId ?? rest[0], ordId: v.ordId, clOrdId: v.clOrdId, json });
|
|
19023
20378
|
if (action === "amend")
|
|
@@ -19125,8 +20480,12 @@ function handleOptionCommand(run, action, rest, v, json) {
|
|
|
19125
20480
|
clOrdId: v.clOrdId,
|
|
19126
20481
|
tpTriggerPx: v.tpTriggerPx,
|
|
19127
20482
|
tpOrdPx: v.tpOrdPx,
|
|
20483
|
+
tpOrdKind: v.tpOrdKind,
|
|
20484
|
+
tpTriggerPxType: v.tpTriggerPxType,
|
|
19128
20485
|
slTriggerPx: v.slTriggerPx,
|
|
19129
20486
|
slOrdPx: v.slOrdPx,
|
|
20487
|
+
slTriggerPxType: v.slTriggerPxType,
|
|
20488
|
+
stpMode: v.stpMode,
|
|
19130
20489
|
json
|
|
19131
20490
|
});
|
|
19132
20491
|
if (action === "cancel")
|
|
@@ -19172,7 +20531,8 @@ function handleFuturesAlgoCommand(run, subAction, v, json) {
|
|
|
19172
20531
|
reduceOnly: v.reduceOnly,
|
|
19173
20532
|
json
|
|
19174
20533
|
});
|
|
19175
|
-
if (subAction === "place")
|
|
20534
|
+
if (subAction === "place") {
|
|
20535
|
+
assertNoTpConflict(v.tpLevel, { tpTriggerPx: v.tpTriggerPx, tpOrdPx: v.tpOrdPx });
|
|
19176
20536
|
return cmdFuturesAlgoPlace(run, {
|
|
19177
20537
|
instId: v.instId,
|
|
19178
20538
|
side: v.side,
|
|
@@ -19184,14 +20544,40 @@ function handleFuturesAlgoCommand(run, subAction, v, json) {
|
|
|
19184
20544
|
tgtCcy: v.tgtCcy,
|
|
19185
20545
|
tpTriggerPx: v.tpTriggerPx,
|
|
19186
20546
|
tpOrdPx: v.tpOrdPx,
|
|
20547
|
+
tpOrdKind: v.tpOrdKind,
|
|
20548
|
+
tpTriggerPxType: v.tpTriggerPxType,
|
|
19187
20549
|
slTriggerPx: v.slTriggerPx,
|
|
19188
20550
|
slOrdPx: v.slOrdPx,
|
|
20551
|
+
slTriggerPxType: v.slTriggerPxType,
|
|
20552
|
+
stpMode: v.stpMode,
|
|
20553
|
+
cxlOnClosePos: v.cxlOnClosePos,
|
|
19189
20554
|
reduceOnly: v.reduceOnly,
|
|
19190
20555
|
callbackRatio: v.callbackRatio,
|
|
19191
20556
|
callbackSpread: v.callbackSpread,
|
|
19192
20557
|
activePx: v.activePx,
|
|
20558
|
+
triggerPx: v.triggerPx,
|
|
20559
|
+
orderPx: v.orderPx,
|
|
20560
|
+
advanceOrdType: v.advanceOrdType,
|
|
20561
|
+
triggerPxType: v.triggerPxType,
|
|
20562
|
+
chaseType: v.chaseType,
|
|
20563
|
+
chaseVal: v.chaseVal,
|
|
20564
|
+
maxChaseType: v.maxChaseType,
|
|
20565
|
+
maxChaseVal: v.maxChaseVal,
|
|
20566
|
+
pxVar: v.pxVar,
|
|
20567
|
+
pxSpread: v.pxSpread,
|
|
20568
|
+
szLimit: v.szLimit,
|
|
20569
|
+
pxLimit: v.pxLimit,
|
|
20570
|
+
timeInterval: v.timeInterval,
|
|
20571
|
+
// Phase 3a+c CLI power-user flags (issue #182, CLI-only no MCP/skill exposure)
|
|
20572
|
+
tpTriggerRatio: v.tpTriggerRatio,
|
|
20573
|
+
slTriggerRatio: v.slTriggerRatio,
|
|
20574
|
+
closeFraction: v.closeFraction,
|
|
20575
|
+
pxAmendType: v.pxAmendType,
|
|
20576
|
+
// Phase 3b CLI power-user flag (issue #183, CLI-only no MCP/skill exposure)
|
|
20577
|
+
tpLevels: v.tpLevel?.map(parseTpLevel),
|
|
19193
20578
|
json
|
|
19194
20579
|
});
|
|
20580
|
+
}
|
|
19195
20581
|
if (subAction === "amend")
|
|
19196
20582
|
return cmdFuturesAlgoAmend(run, {
|
|
19197
20583
|
instId: v.instId,
|
|
@@ -19239,7 +20625,8 @@ function handleFuturesQuery(run, action, v, json) {
|
|
|
19239
20625
|
function handleFuturesCommand(run, action, rest, v, json) {
|
|
19240
20626
|
const queryResult = handleFuturesQuery(run, action, v, json);
|
|
19241
20627
|
if (queryResult !== void 0) return queryResult;
|
|
19242
|
-
if (action === "place")
|
|
20628
|
+
if (action === "place") {
|
|
20629
|
+
assertNoTpConflict(v.tpLevel, { tpTriggerPx: v.tpTriggerPx, tpOrdPx: v.tpOrdPx });
|
|
19243
20630
|
return cmdFuturesPlace(run, {
|
|
19244
20631
|
instId: v.instId,
|
|
19245
20632
|
side: v.side,
|
|
@@ -19253,10 +20640,19 @@ function handleFuturesCommand(run, action, rest, v, json) {
|
|
|
19253
20640
|
clOrdId: v.clOrdId,
|
|
19254
20641
|
tpTriggerPx: v.tpTriggerPx,
|
|
19255
20642
|
tpOrdPx: v.tpOrdPx,
|
|
20643
|
+
tpOrdKind: v.tpOrdKind,
|
|
20644
|
+
tpTriggerPxType: v.tpTriggerPxType,
|
|
19256
20645
|
slTriggerPx: v.slTriggerPx,
|
|
19257
20646
|
slOrdPx: v.slOrdPx,
|
|
20647
|
+
slTriggerPxType: v.slTriggerPxType,
|
|
20648
|
+
stpMode: v.stpMode,
|
|
20649
|
+
// Phase 3c CLI power-user flag (issue #182, CLI-only no MCP/skill exposure)
|
|
20650
|
+
pxAmendType: v.pxAmendType,
|
|
20651
|
+
// Phase 3b CLI power-user flag (issue #183, CLI-only no MCP/skill exposure)
|
|
20652
|
+
tpLevels: v.tpLevel?.map(parseTpLevel),
|
|
19258
20653
|
json
|
|
19259
20654
|
});
|
|
20655
|
+
}
|
|
19260
20656
|
if (action === "cancel")
|
|
19261
20657
|
return cmdFuturesCancel(run, { instId: v.instId ?? rest[0], ordId: v.ordId, clOrdId: v.clOrdId, json });
|
|
19262
20658
|
if (action === "amend")
|
|
@@ -19457,79 +20853,171 @@ function handleEarnFlashEarnCommand(run, action, v, json) {
|
|
|
19457
20853
|
process.exitCode = 1;
|
|
19458
20854
|
}
|
|
19459
20855
|
function handleSmartmoneyCommand(run, action, rest, v, json) {
|
|
19460
|
-
|
|
19461
|
-
|
|
20856
|
+
void rest;
|
|
20857
|
+
const signalPoolFilters = {
|
|
20858
|
+
sortBy: v.sortBy,
|
|
19462
20859
|
period: v.period,
|
|
19463
|
-
|
|
19464
|
-
|
|
19465
|
-
|
|
19466
|
-
|
|
20860
|
+
pnlTier: v.pnlTier,
|
|
20861
|
+
winRateTier: v.winRateTier,
|
|
20862
|
+
maxDrawdownTier: v.maxDrawdownTier,
|
|
20863
|
+
aumTier: v.aumTier
|
|
19467
20864
|
};
|
|
19468
|
-
|
|
19469
|
-
|
|
19470
|
-
|
|
19471
|
-
|
|
19472
|
-
|
|
19473
|
-
|
|
19474
|
-
|
|
19475
|
-
|
|
19476
|
-
|
|
19477
|
-
|
|
20865
|
+
const leaderboardPoolFilters = {
|
|
20866
|
+
sortBy: v.sortBy,
|
|
20867
|
+
period: v.period,
|
|
20868
|
+
minPnl: v.minPnl,
|
|
20869
|
+
minWinRate: v.minWinRate,
|
|
20870
|
+
maxDrawdown: v.maxDrawdown,
|
|
20871
|
+
minAum: v.minAum
|
|
20872
|
+
};
|
|
20873
|
+
if (action === "traders-by-filter")
|
|
20874
|
+
return cmdSmartmoneyTradersByFilter(run, {
|
|
20875
|
+
updateTime: v.updateTime,
|
|
20876
|
+
...leaderboardPoolFilters,
|
|
20877
|
+
after: v.after,
|
|
20878
|
+
before: v.before,
|
|
20879
|
+
limit: v.limit,
|
|
19478
20880
|
json
|
|
19479
20881
|
});
|
|
19480
|
-
if (action === "
|
|
19481
|
-
|
|
19482
|
-
|
|
19483
|
-
|
|
19484
|
-
|
|
19485
|
-
|
|
19486
|
-
|
|
19487
|
-
lmtNum: v.lmtNum,
|
|
20882
|
+
if (action === "performance-by-trader") {
|
|
20883
|
+
if (!v.authorIds) {
|
|
20884
|
+
errorLine("Missing required --authorIds: okx smartmoney performance-by-trader --authorIds <id1,id2> [--period <3|7|30|90>]");
|
|
20885
|
+
process.exitCode = 1;
|
|
20886
|
+
return;
|
|
20887
|
+
}
|
|
20888
|
+
return cmdSmartmoneyPerformanceByTrader(run, {
|
|
19488
20889
|
authorIds: v.authorIds,
|
|
20890
|
+
period: v.period,
|
|
19489
20891
|
json
|
|
19490
20892
|
});
|
|
19491
|
-
|
|
19492
|
-
|
|
19493
|
-
|
|
20893
|
+
}
|
|
20894
|
+
if (action === "trader-positions") {
|
|
20895
|
+
if (!v.authorId) {
|
|
20896
|
+
errorLine("Missing required --authorId: okx smartmoney trader-positions --authorId <id> [--instId <id>]");
|
|
19494
20897
|
process.exitCode = 1;
|
|
19495
20898
|
return;
|
|
19496
20899
|
}
|
|
19497
|
-
return
|
|
20900
|
+
return cmdSmartmoneyTraderPositions(run, {
|
|
20901
|
+
authorId: v.authorId,
|
|
19498
20902
|
instId: v.instId,
|
|
19499
|
-
dataVersion: v.dataVersion,
|
|
19500
|
-
ts: v.ts,
|
|
19501
|
-
granularity: v.granularity,
|
|
19502
|
-
limit: v.limit,
|
|
19503
|
-
...poolFilters,
|
|
19504
20903
|
json
|
|
19505
20904
|
});
|
|
19506
20905
|
}
|
|
19507
|
-
if (action === "
|
|
19508
|
-
|
|
19509
|
-
|
|
19510
|
-
|
|
19511
|
-
|
|
20906
|
+
if (action === "trader-positions-history") {
|
|
20907
|
+
if (!v.authorId) {
|
|
20908
|
+
errorLine("Missing required --authorId: okx smartmoney trader-positions-history --authorId <id> [--instId <id>] [--limit <n>]");
|
|
20909
|
+
process.exitCode = 1;
|
|
20910
|
+
return;
|
|
20911
|
+
}
|
|
20912
|
+
return cmdSmartmoneyTraderPositionsHistory(run, {
|
|
20913
|
+
authorId: v.authorId,
|
|
20914
|
+
instId: v.instId,
|
|
19512
20915
|
after: v.after,
|
|
19513
20916
|
before: v.before,
|
|
19514
20917
|
limit: v.limit,
|
|
19515
20918
|
json
|
|
19516
20919
|
});
|
|
19517
|
-
|
|
20920
|
+
}
|
|
20921
|
+
if (action === "trader-orders-history") {
|
|
19518
20922
|
if (!v.authorId) {
|
|
19519
|
-
errorLine("Missing required --authorId: okx smartmoney trader --authorId <id>");
|
|
20923
|
+
errorLine("Missing required --authorId: okx smartmoney trader-orders-history --authorId <id> [--instId <id>] [--limit <n>]");
|
|
19520
20924
|
process.exitCode = 1;
|
|
19521
20925
|
return;
|
|
19522
20926
|
}
|
|
19523
|
-
return
|
|
20927
|
+
return cmdSmartmoneyTraderOrdersHistory(run, {
|
|
19524
20928
|
authorId: v.authorId,
|
|
19525
|
-
|
|
20929
|
+
instId: v.instId,
|
|
20930
|
+
after: v.after,
|
|
20931
|
+
before: v.before,
|
|
20932
|
+
limit: v.limit,
|
|
20933
|
+
json
|
|
20934
|
+
});
|
|
20935
|
+
}
|
|
20936
|
+
if (action === "search-trader") {
|
|
20937
|
+
if (!v.keyword || v.keyword.trim() === "") {
|
|
20938
|
+
errorLine("Missing required --keyword: okx smartmoney search-trader --keyword <name>");
|
|
20939
|
+
process.exitCode = 1;
|
|
20940
|
+
return;
|
|
20941
|
+
}
|
|
20942
|
+
return cmdSmartmoneySearchTrader(run, {
|
|
20943
|
+
keyword: v.keyword,
|
|
20944
|
+
json
|
|
20945
|
+
});
|
|
20946
|
+
}
|
|
20947
|
+
if (action === "signal-overview-by-filter") {
|
|
20948
|
+
if (v.topInstruments && v.instCcyList) {
|
|
20949
|
+
errorLine(
|
|
20950
|
+
"--topInstruments and --instCcyList are mutually exclusive. Pass exactly one \u2014 `--topInstruments` for top-N hottest coins, or `--instCcyList` for specific coins."
|
|
20951
|
+
);
|
|
20952
|
+
process.exitCode = 1;
|
|
20953
|
+
return;
|
|
20954
|
+
}
|
|
20955
|
+
return cmdSmartmoneySignalOverviewByFilter(run, {
|
|
20956
|
+
topInstruments: v.topInstruments,
|
|
20957
|
+
instCcyList: v.instCcyList,
|
|
20958
|
+
...signalPoolFilters,
|
|
20959
|
+
lmtNum: v.lmtNum,
|
|
20960
|
+
json
|
|
20961
|
+
});
|
|
20962
|
+
}
|
|
20963
|
+
if (action === "signal-overview-by-trader") {
|
|
20964
|
+
if (!v.authorIds) {
|
|
20965
|
+
errorLine("Missing required --authorIds: okx smartmoney signal-overview-by-trader --authorIds <id1,id2> [--topInstruments <n> | --instCcyList <BTC,ETH>]");
|
|
20966
|
+
process.exitCode = 1;
|
|
20967
|
+
return;
|
|
20968
|
+
}
|
|
20969
|
+
if (v.topInstruments && v.instCcyList) {
|
|
20970
|
+
errorLine(
|
|
20971
|
+
"--topInstruments and --instCcyList are mutually exclusive. Pass exactly one \u2014 `--topInstruments` for top-N hottest coins, or `--instCcyList` for specific coins."
|
|
20972
|
+
);
|
|
20973
|
+
process.exitCode = 1;
|
|
20974
|
+
return;
|
|
20975
|
+
}
|
|
20976
|
+
return cmdSmartmoneySignalOverviewByTrader(run, {
|
|
20977
|
+
authorIds: v.authorIds,
|
|
20978
|
+
topInstruments: v.topInstruments,
|
|
20979
|
+
instCcyList: v.instCcyList,
|
|
20980
|
+
json
|
|
20981
|
+
});
|
|
20982
|
+
}
|
|
20983
|
+
if (action === "signal-trend-by-filter") {
|
|
20984
|
+
if (!v.instCcy) {
|
|
20985
|
+
errorLine("Missing required --instCcy: okx smartmoney signal-trend-by-filter --instCcy <ccy> [--asOfTime <yyyyMMddHH>] [--granularity <1h|1d>] [--limit <n>]");
|
|
20986
|
+
process.exitCode = 1;
|
|
20987
|
+
return;
|
|
20988
|
+
}
|
|
20989
|
+
return cmdSmartmoneySignalTrendByFilter(run, {
|
|
19526
20990
|
instCcy: v.instCcy,
|
|
19527
|
-
|
|
20991
|
+
asOfTime: v.asOfTime,
|
|
20992
|
+
granularity: v.granularity,
|
|
20993
|
+
limit: v.limit,
|
|
20994
|
+
...signalPoolFilters,
|
|
20995
|
+
lmtNum: v.lmtNum,
|
|
20996
|
+
json
|
|
20997
|
+
});
|
|
20998
|
+
}
|
|
20999
|
+
if (action === "signal-trend-by-trader") {
|
|
21000
|
+
if (!v.authorIds) {
|
|
21001
|
+
errorLine("Missing required --authorIds: okx smartmoney signal-trend-by-trader --authorIds <id1,id2> --instCcy <ccy> [--asOfTime <yyyyMMddHH>]");
|
|
21002
|
+
process.exitCode = 1;
|
|
21003
|
+
return;
|
|
21004
|
+
}
|
|
21005
|
+
if (!v.instCcy) {
|
|
21006
|
+
errorLine("Missing required --instCcy: okx smartmoney signal-trend-by-trader --authorIds <id1,id2> --instCcy <ccy> [--asOfTime <yyyyMMddHH>]");
|
|
21007
|
+
process.exitCode = 1;
|
|
21008
|
+
return;
|
|
21009
|
+
}
|
|
21010
|
+
return cmdSmartmoneySignalTrendByTrader(run, {
|
|
21011
|
+
authorIds: v.authorIds,
|
|
21012
|
+
instCcy: v.instCcy,
|
|
21013
|
+
asOfTime: v.asOfTime,
|
|
21014
|
+
granularity: v.granularity,
|
|
21015
|
+
limit: v.limit,
|
|
19528
21016
|
json
|
|
19529
21017
|
});
|
|
19530
21018
|
}
|
|
19531
21019
|
errorLine(`Unknown smartmoney command: ${action}`);
|
|
19532
|
-
errorLine("Valid:
|
|
21020
|
+
errorLine("Valid: traders-by-filter, performance-by-trader, trader-positions, trader-positions-history, trader-orders-history, search-trader, signal-overview-by-filter, signal-overview-by-trader, signal-trend-by-filter, signal-trend-by-trader");
|
|
19533
21021
|
process.exitCode = 1;
|
|
19534
21022
|
}
|
|
19535
21023
|
function handleEarnSavingsCommand(run, action, rest, v, json) {
|
|
@@ -19860,6 +21348,7 @@ main().catch((error) => {
|
|
|
19860
21348
|
process.exitCode = 1;
|
|
19861
21349
|
});
|
|
19862
21350
|
export {
|
|
21351
|
+
assertNoTpConflict,
|
|
19863
21352
|
handleAccountWriteCommand,
|
|
19864
21353
|
handleBotCommand,
|
|
19865
21354
|
handleBotDcaCommand,
|