hvip-mcp-server 0.2.44 → 0.2.45
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 +1893 -174
- package/package.json +64 -61
package/dist/index.js
CHANGED
|
@@ -25320,6 +25320,57 @@ function classifyError(msg) {
|
|
|
25320
25320
|
if (msg.includes("API Key")) return { errorCode: "AUTH_REQUIRED", errorCategory: "AUTH" };
|
|
25321
25321
|
return { errorCode: "UNKNOWN_ERROR", errorCategory: "BUSINESS" };
|
|
25322
25322
|
}
|
|
25323
|
+
function classifyRisk(toolName) {
|
|
25324
|
+
const admin = ["okx_set_account_mode", "okx_set_position_mode", "okx_set_settle_currency"];
|
|
25325
|
+
if (admin.includes(toolName)) return "ADMIN";
|
|
25326
|
+
const fund = ["okx_withdrawal"];
|
|
25327
|
+
if (fund.some((p) => toolName.startsWith(p))) return "FUND_TRANSFER";
|
|
25328
|
+
const writePrefixes = [
|
|
25329
|
+
"okx_place_",
|
|
25330
|
+
"okx_cancel_",
|
|
25331
|
+
"okx_amend_",
|
|
25332
|
+
"okx_create_",
|
|
25333
|
+
"okx_stop_",
|
|
25334
|
+
"okx_close_",
|
|
25335
|
+
"okx_batch_",
|
|
25336
|
+
"okx_set_",
|
|
25337
|
+
"okx_transfer",
|
|
25338
|
+
"okx_borrow",
|
|
25339
|
+
"okx_repay",
|
|
25340
|
+
"okx_convert_trade",
|
|
25341
|
+
"okx_preset_",
|
|
25342
|
+
"okx_activate_",
|
|
25343
|
+
"okx_move_",
|
|
25344
|
+
"okx_copy_",
|
|
25345
|
+
"okx_first_",
|
|
25346
|
+
"okx_one_click_",
|
|
25347
|
+
"okx_easy_convert",
|
|
25348
|
+
"agent_quick_trade"
|
|
25349
|
+
];
|
|
25350
|
+
if (writePrefixes.some((p) => toolName.startsWith(p))) return "WRITE";
|
|
25351
|
+
const readSpecials = [
|
|
25352
|
+
"agent_simulate_order",
|
|
25353
|
+
"okx_preflight_check",
|
|
25354
|
+
"okx_agent_feedback",
|
|
25355
|
+
"agent_catalog",
|
|
25356
|
+
"agent_catalog_detail",
|
|
25357
|
+
"agent_hub_status",
|
|
25358
|
+
"agent_hub_dispatch",
|
|
25359
|
+
"agent_hub_review",
|
|
25360
|
+
"agent_room_send",
|
|
25361
|
+
"agent_room_view",
|
|
25362
|
+
"okx_ws_subscribe",
|
|
25363
|
+
"okx_ws_events",
|
|
25364
|
+
"okx_ws_status",
|
|
25365
|
+
"okx_ws_close",
|
|
25366
|
+
"xlayer_subscribe",
|
|
25367
|
+
"xlayer_get_events",
|
|
25368
|
+
"xlayer_unsubscribe"
|
|
25369
|
+
];
|
|
25370
|
+
if (readSpecials.includes(toolName)) return "READ";
|
|
25371
|
+
if (toolName.startsWith("xlayer_call")) return "WRITE";
|
|
25372
|
+
return "READ";
|
|
25373
|
+
}
|
|
25323
25374
|
function toError(e) {
|
|
25324
25375
|
const msg = e instanceof Error ? e.message : String(e);
|
|
25325
25376
|
const { errorCode, errorCategory } = classifyError(msg);
|
|
@@ -31343,6 +31394,59 @@ function registerFiatTools(server, auth) {
|
|
|
31343
31394
|
var fs = __toESM(require("node:fs"));
|
|
31344
31395
|
var path = __toESM(require("node:path"));
|
|
31345
31396
|
var os = __toESM(require("node:os"));
|
|
31397
|
+
async function fetchAllSettled(fetchers) {
|
|
31398
|
+
const entries = Object.entries(fetchers);
|
|
31399
|
+
const keys = entries.map((e) => e[0]);
|
|
31400
|
+
const results = await Promise.allSettled(entries.map((e) => e[1]));
|
|
31401
|
+
const errors = [];
|
|
31402
|
+
for (let i = 0; i < results.length; i++) {
|
|
31403
|
+
if (results[i].status === "rejected") {
|
|
31404
|
+
const r = results[i];
|
|
31405
|
+
if (r.status === "rejected") {
|
|
31406
|
+
errors.push(`${keys[i]}: ${r.reason?.message ?? String(r.reason)}`);
|
|
31407
|
+
}
|
|
31408
|
+
}
|
|
31409
|
+
}
|
|
31410
|
+
const get = (name) => {
|
|
31411
|
+
const idx = keys.indexOf(name);
|
|
31412
|
+
if (idx < 0) return null;
|
|
31413
|
+
const r = results[idx];
|
|
31414
|
+
if (r.status === "rejected") return null;
|
|
31415
|
+
return r.value;
|
|
31416
|
+
};
|
|
31417
|
+
return { get, errors };
|
|
31418
|
+
}
|
|
31419
|
+
function inferInstType(instId) {
|
|
31420
|
+
const upper = instId.toUpperCase();
|
|
31421
|
+
if (upper.includes("-SWAP")) return "SWAP";
|
|
31422
|
+
if (upper.includes("-OPTION") || /-[\d]+-[CP]$/.test(upper)) return "OPTION";
|
|
31423
|
+
if (upper.includes("-FUTURES")) return "FUTURES";
|
|
31424
|
+
if (upper.includes("MARGIN")) return "MARGIN";
|
|
31425
|
+
if (/-[\d]{6,}/.test(upper)) return "FUTURES";
|
|
31426
|
+
return "SPOT";
|
|
31427
|
+
}
|
|
31428
|
+
function inferFeeCcy(instId, tdMode) {
|
|
31429
|
+
if (tdMode === "cash") {
|
|
31430
|
+
const parts = instId.split("-");
|
|
31431
|
+
return parts[1] || "USDT";
|
|
31432
|
+
}
|
|
31433
|
+
return "USDT";
|
|
31434
|
+
}
|
|
31435
|
+
function parseNumeric(val, label) {
|
|
31436
|
+
const n = parseFloat(val);
|
|
31437
|
+
if (isNaN(n) || !isFinite(n)) {
|
|
31438
|
+
return { ok: false, error: `\u53C2\u6570 ${label}="${val}" \u4E0D\u662F\u6709\u6548\u6570\u5B57\uFF0CAgent \u8BF7\u68C0\u67E5\u7528\u6237\u8F93\u5165\u540E\u91CD\u8BD5` };
|
|
31439
|
+
}
|
|
31440
|
+
return { ok: true, value: n };
|
|
31441
|
+
}
|
|
31442
|
+
function extractOrderbook(raw) {
|
|
31443
|
+
const item = Array.isArray(raw) ? raw[0] : raw;
|
|
31444
|
+
if (!item) return { asks: [], bids: [] };
|
|
31445
|
+
return {
|
|
31446
|
+
asks: item.asks ?? [],
|
|
31447
|
+
bids: item.bids ?? []
|
|
31448
|
+
};
|
|
31449
|
+
}
|
|
31346
31450
|
function registerAgentUtils(server, auth) {
|
|
31347
31451
|
server.tool(
|
|
31348
31452
|
"okx_account_overview",
|
|
@@ -31351,13 +31455,13 @@ function registerAgentUtils(server, auth) {
|
|
|
31351
31455
|
async () => {
|
|
31352
31456
|
if (!auth) return toError(AUTH_REQUIRED);
|
|
31353
31457
|
try {
|
|
31354
|
-
const
|
|
31355
|
-
privateApi.getBalance(auth),
|
|
31356
|
-
privateApi.getPositions(auth),
|
|
31357
|
-
privateApi.getAccountConfig(auth),
|
|
31358
|
-
privateApi.getAssetValuation(auth)
|
|
31359
|
-
|
|
31360
|
-
const balanceData = balance
|
|
31458
|
+
const { get, errors } = await fetchAllSettled({
|
|
31459
|
+
balance: privateApi.getBalance(auth),
|
|
31460
|
+
positions: privateApi.getPositions(auth),
|
|
31461
|
+
config: privateApi.getAccountConfig(auth),
|
|
31462
|
+
valuation: privateApi.getAssetValuation(auth)
|
|
31463
|
+
});
|
|
31464
|
+
const balanceData = get("balance") ?? [];
|
|
31361
31465
|
const totalEq = balanceData.length > 0 ? balanceData[0]?.totalEq : "N/A";
|
|
31362
31466
|
const details = balanceData.length > 0 ? balanceData[0]?.details ?? [] : [];
|
|
31363
31467
|
const nonZero = details.filter((d) => parseFloat(d.availBal || d.cashBal || "0") > 0);
|
|
@@ -31368,7 +31472,7 @@ function registerAgentUtils(server, auth) {
|
|
|
31368
31472
|
frozen: d.frozenBal ?? "0",
|
|
31369
31473
|
upl: d.upl
|
|
31370
31474
|
}));
|
|
31371
|
-
const posData = positions
|
|
31475
|
+
const posData = get("positions") ?? [];
|
|
31372
31476
|
const activePositions = posData.filter(
|
|
31373
31477
|
(p) => parseFloat(p.avgPx || "0") > 0 || parseFloat(p.pos || "0") !== 0
|
|
31374
31478
|
);
|
|
@@ -31384,9 +31488,12 @@ function registerAgentUtils(server, auth) {
|
|
|
31384
31488
|
margin: p.margin,
|
|
31385
31489
|
liqPx: p.liqPx
|
|
31386
31490
|
}));
|
|
31387
|
-
const
|
|
31388
|
-
const
|
|
31491
|
+
const cfgArr = get("config") ?? [];
|
|
31492
|
+
const cfg = cfgArr[0] ?? {};
|
|
31493
|
+
const valArr = get("valuation") ?? [];
|
|
31494
|
+
const val = valArr[0] ?? {};
|
|
31389
31495
|
const overview = {
|
|
31496
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
31390
31497
|
totalEquity: totalEq,
|
|
31391
31498
|
totalValue: val.totalBal ?? "N/A",
|
|
31392
31499
|
valuationCurrency: val.ccy ?? "USD",
|
|
@@ -31405,12 +31512,7 @@ function registerAgentUtils(server, auth) {
|
|
|
31405
31512
|
posMode: cfg.posMode,
|
|
31406
31513
|
autoLoan: cfg.autoLoan
|
|
31407
31514
|
},
|
|
31408
|
-
errors
|
|
31409
|
-
balance.status === "rejected" ? `\u4F59\u989D\u67E5\u8BE2\u5931\u8D25: ${balance.reason?.message}` : null,
|
|
31410
|
-
positions.status === "rejected" ? `\u6301\u4ED3\u67E5\u8BE2\u5931\u8D25: ${positions.reason?.message}` : null,
|
|
31411
|
-
config2.status === "rejected" ? `\u914D\u7F6E\u67E5\u8BE2\u5931\u8D25: ${config2.reason?.message}` : null,
|
|
31412
|
-
valuation.status === "rejected" ? `\u4F30\u503C\u67E5\u8BE2\u5931\u8D25: ${valuation.reason?.message}` : null
|
|
31413
|
-
].filter(Boolean)
|
|
31515
|
+
errors
|
|
31414
31516
|
};
|
|
31415
31517
|
return toResult(overview);
|
|
31416
31518
|
} catch (e) {
|
|
@@ -31427,36 +31529,31 @@ function registerAgentUtils(server, auth) {
|
|
|
31427
31529
|
async ({ instId }) => {
|
|
31428
31530
|
try {
|
|
31429
31531
|
const isSwap = instId.toUpperCase().includes("-SWAP");
|
|
31430
|
-
const
|
|
31431
|
-
|
|
31432
|
-
|
|
31433
|
-
|
|
31434
|
-
];
|
|
31532
|
+
const fetchers = {
|
|
31533
|
+
ticker: publicApi.getTicker(instId),
|
|
31534
|
+
orderbook: publicApi.getOrderbook(instId, 5)
|
|
31535
|
+
};
|
|
31435
31536
|
if (isSwap) {
|
|
31436
|
-
fetchers.
|
|
31437
|
-
}
|
|
31438
|
-
const
|
|
31439
|
-
const
|
|
31440
|
-
const
|
|
31441
|
-
const
|
|
31442
|
-
const
|
|
31443
|
-
const obIdx = keys.indexOf("orderbook");
|
|
31444
|
-
const obRaw = results[obIdx]?.status === "fulfilled" ? results[obIdx].value : null;
|
|
31445
|
-
const obData = obRaw?.data?.[0] ?? obRaw;
|
|
31446
|
-
const asks = (obData?.asks ?? []).slice(0, 5);
|
|
31447
|
-
const bids = (obData?.bids ?? []).slice(0, 5);
|
|
31537
|
+
fetchers.fundingRate = publicApi.getFundingRate(instId);
|
|
31538
|
+
}
|
|
31539
|
+
const { get, errors } = await fetchAllSettled(fetchers);
|
|
31540
|
+
const tickerArr = get("ticker") ?? [];
|
|
31541
|
+
const tk = tickerArr[0] ?? {};
|
|
31542
|
+
const obRaw = get("orderbook");
|
|
31543
|
+
const { asks, bids } = extractOrderbook(obRaw);
|
|
31448
31544
|
const spread = asks.length > 0 && bids.length > 0 ? (parseFloat(asks[0]?.[0] ?? "0") - parseFloat(bids[0]?.[0] ?? "0")).toFixed(2) : "N/A";
|
|
31449
31545
|
let fundingRate = null;
|
|
31450
31546
|
if (isSwap) {
|
|
31451
|
-
const
|
|
31452
|
-
const
|
|
31453
|
-
const fr = frRaw.length > 0 ? frRaw[0] : {};
|
|
31547
|
+
const frArr = get("fundingRate") ?? [];
|
|
31548
|
+
const fr = frArr[0] ?? {};
|
|
31454
31549
|
fundingRate = {
|
|
31455
31550
|
fundingRate: fr.fundingRate,
|
|
31456
31551
|
nextFundingTime: fr.nextFundingTime ? new Date(parseInt(fr.nextFundingTime)).toISOString() : void 0
|
|
31457
31552
|
};
|
|
31458
31553
|
}
|
|
31554
|
+
const isMargin = instId.toUpperCase().includes("MARGIN");
|
|
31459
31555
|
const summary = {
|
|
31556
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
31460
31557
|
instId,
|
|
31461
31558
|
productType: isSwap ? "\u6C38\u7EED\u5408\u7EA6" : isMargin ? "\u6760\u6746" : "\u73B0\u8D27/\u5176\u4ED6",
|
|
31462
31559
|
ticker: {
|
|
@@ -31470,11 +31567,11 @@ function registerAgentUtils(server, auth) {
|
|
|
31470
31567
|
},
|
|
31471
31568
|
depth: {
|
|
31472
31569
|
spread,
|
|
31473
|
-
top5Asks: asks.map((a) => ({ px: a[0], sz: a[1], orders: a[3] })),
|
|
31474
|
-
top5Bids: bids.map((b) => ({ px: b[0], sz: b[1], orders: b[3] }))
|
|
31570
|
+
top5Asks: asks.slice(0, 5).map((a) => ({ px: a[0], sz: a[1], orders: a[3] })),
|
|
31571
|
+
top5Bids: bids.slice(0, 5).map((b) => ({ px: b[0], sz: b[1], orders: b[3] }))
|
|
31475
31572
|
},
|
|
31476
31573
|
fundingRate,
|
|
31477
|
-
errors
|
|
31574
|
+
errors
|
|
31478
31575
|
};
|
|
31479
31576
|
return toResult(summary);
|
|
31480
31577
|
} catch (e) {
|
|
@@ -31496,28 +31593,30 @@ function registerAgentUtils(server, auth) {
|
|
|
31496
31593
|
async ({ instId, tdMode, sz, px, side, ordType }) => {
|
|
31497
31594
|
if (!auth) return toError(AUTH_REQUIRED);
|
|
31498
31595
|
try {
|
|
31499
|
-
const
|
|
31500
|
-
|
|
31501
|
-
|
|
31502
|
-
|
|
31503
|
-
|
|
31504
|
-
|
|
31505
|
-
|
|
31506
|
-
|
|
31507
|
-
const get = (
|
|
31508
|
-
|
|
31509
|
-
|
|
31510
|
-
|
|
31511
|
-
|
|
31512
|
-
|
|
31513
|
-
const
|
|
31514
|
-
const
|
|
31515
|
-
const
|
|
31516
|
-
const
|
|
31517
|
-
const
|
|
31518
|
-
const
|
|
31519
|
-
const
|
|
31596
|
+
const szParsed = parseNumeric(sz, "sz(\u6570\u91CF)");
|
|
31597
|
+
if (!szParsed.ok) return toError(szParsed.error);
|
|
31598
|
+
if (szParsed.value <= 0) return toError(`\u6570\u91CF sz=${sz} \u5FC5\u987B\u5927\u4E8E 0\uFF0CAgent \u8BF7\u8C03\u6574\u540E\u91CD\u8BD5`);
|
|
31599
|
+
if (px !== void 0) {
|
|
31600
|
+
const pxParsed = parseNumeric(px, "px(\u4EF7\u683C)");
|
|
31601
|
+
if (!pxParsed.ok) return toError(pxParsed.error);
|
|
31602
|
+
if (pxParsed.value <= 0) return toError(`\u4EF7\u683C px=${px} \u5FC5\u987B\u5927\u4E8E 0\uFF0CAgent \u8BF7\u8C03\u6574\u540E\u91CD\u8BD5`);
|
|
31603
|
+
}
|
|
31604
|
+
const { get, errors } = await fetchAllSettled({
|
|
31605
|
+
maxSize: privateApi.getMaxSize(auth, instId, tdMode),
|
|
31606
|
+
priceLimit: publicApi.getPriceLimitBatch("", void 0, instId),
|
|
31607
|
+
convertCoin: publicApi.convertContractCoin(instId, sz, "coin", "open"),
|
|
31608
|
+
ticker: publicApi.getTicker(instId)
|
|
31609
|
+
});
|
|
31610
|
+
const maxSizeArr = get("maxSize") ?? [];
|
|
31611
|
+
const maxSz = maxSizeArr[0];
|
|
31612
|
+
const limitArr = get("priceLimit") ?? [];
|
|
31613
|
+
const limit = limitArr[0];
|
|
31614
|
+
const convertArr = get("convertCoin") ?? [];
|
|
31615
|
+
const converted = convertArr[0];
|
|
31616
|
+
const tickerArr = get("ticker") ?? [];
|
|
31617
|
+
const tk = tickerArr[0] ?? {};
|
|
31520
31618
|
const checks = {
|
|
31619
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
31521
31620
|
instId,
|
|
31522
31621
|
tdMode,
|
|
31523
31622
|
userInput: { sz, px, side, ordType },
|
|
@@ -31534,7 +31633,7 @@ function registerAgentUtils(server, auth) {
|
|
|
31534
31633
|
priceLimit: limit ? {
|
|
31535
31634
|
highest: limit.highest,
|
|
31536
31635
|
lowest: limit.lowest,
|
|
31537
|
-
pxWithinLimit: px ? parseFloat(px) >= parseFloat(limit.lowest ?? "0") && parseFloat(px) <= parseFloat(limit.highest ?? "Infinity") : null
|
|
31636
|
+
pxWithinLimit: px ? szParsed.ok && parseFloat(px) >= parseFloat(limit.lowest ?? "0") && parseFloat(px) <= parseFloat(limit.highest ?? "Infinity") : null
|
|
31538
31637
|
} : null,
|
|
31539
31638
|
contractConversion: converted ? {
|
|
31540
31639
|
fromCoin: sz,
|
|
@@ -31542,25 +31641,30 @@ function registerAgentUtils(server, auth) {
|
|
|
31542
31641
|
unit: "contracts"
|
|
31543
31642
|
} : null,
|
|
31544
31643
|
warnings: [],
|
|
31545
|
-
errors
|
|
31644
|
+
errors
|
|
31546
31645
|
};
|
|
31547
|
-
if (limit && px) {
|
|
31646
|
+
if (limit && px !== void 0) {
|
|
31548
31647
|
const lowest = parseFloat(limit.lowest ?? "0");
|
|
31549
31648
|
const highest = parseFloat(limit.highest ?? "Infinity");
|
|
31550
31649
|
const price = parseFloat(px);
|
|
31551
|
-
if (price
|
|
31552
|
-
|
|
31650
|
+
if (!isNaN(price) && price < lowest)
|
|
31651
|
+
checks.warnings.push(`\u4EF7\u683C ${px} \u4F4E\u4E8E\u4E0B\u9650 ${limit.lowest}\uFF0CAgent \u8BF7\u964D\u4F4E\u4EF7\u683C\u81F3 \u2265${lowest}`);
|
|
31652
|
+
if (!isNaN(price) && price > highest)
|
|
31653
|
+
checks.warnings.push(`\u4EF7\u683C ${px} \u9AD8\u4E8E\u4E0A\u9650 ${limit.highest}\uFF0CAgent \u8BF7\u63D0\u9AD8\u4EF7\u683C\u81F3 \u2264${highest}`);
|
|
31553
31654
|
}
|
|
31554
31655
|
if (maxSz && side) {
|
|
31555
31656
|
const maxBuy = parseFloat(maxSz.maxBuy ?? "0");
|
|
31556
31657
|
const maxSell = parseFloat(maxSz.maxSell ?? "0");
|
|
31557
|
-
const qty =
|
|
31558
|
-
if (side === "buy" && qty > maxBuy)
|
|
31559
|
-
|
|
31658
|
+
const qty = szParsed.value;
|
|
31659
|
+
if (side === "buy" && qty > maxBuy)
|
|
31660
|
+
checks.warnings.push(`\u6570\u91CF ${sz} \u8D85\u8FC7\u6700\u5927\u53EF\u4E70 ${maxSz.maxBuy}\uFF0CAgent \u8BF7\u51CF\u81F3 \u2264${maxBuy}`);
|
|
31661
|
+
if (side === "sell" && qty > maxSell)
|
|
31662
|
+
checks.warnings.push(`\u6570\u91CF ${sz} \u8D85\u8FC7\u6700\u5927\u53EF\u5356 ${maxSz.maxSell}\uFF0CAgent \u8BF7\u51CF\u81F3 \u2264${maxSell}`);
|
|
31560
31663
|
}
|
|
31561
31664
|
if (converted) {
|
|
31562
31665
|
const contractSz = converted.sz;
|
|
31563
|
-
if (parseFloat(contractSz ?? "0") < 1)
|
|
31666
|
+
if (parseFloat(contractSz ?? "0") < 1)
|
|
31667
|
+
checks.warnings.push(`\u6362\u7B97\u540E\u5F20\u6570 ${contractSz} < 1\uFF0C\u53EF\u80FD\u65E0\u6CD5\u4E0B\u5355\uFF0CAgent \u8BF7\u589E\u52A0\u6570\u91CF`);
|
|
31564
31668
|
}
|
|
31565
31669
|
checks.passed = checks.warnings.length === 0 && checks.errors.length === 0;
|
|
31566
31670
|
return toResult(checks);
|
|
@@ -31606,14 +31710,15 @@ function registerAgentUtils(server, auth) {
|
|
|
31606
31710
|
async () => {
|
|
31607
31711
|
if (!auth) return toError(AUTH_REQUIRED);
|
|
31608
31712
|
try {
|
|
31609
|
-
const
|
|
31610
|
-
privateApi.getBalance(auth),
|
|
31611
|
-
privateApi.getPositions(auth),
|
|
31612
|
-
privateApi.getAccountConfig(auth)
|
|
31613
|
-
|
|
31614
|
-
const balOk = balance
|
|
31615
|
-
const posOk = positions
|
|
31616
|
-
const
|
|
31713
|
+
const { get, errors } = await fetchAllSettled({
|
|
31714
|
+
balance: privateApi.getBalance(auth),
|
|
31715
|
+
positions: privateApi.getPositions(auth),
|
|
31716
|
+
config: privateApi.getAccountConfig(auth)
|
|
31717
|
+
});
|
|
31718
|
+
const balOk = get("balance") ?? [];
|
|
31719
|
+
const posOk = get("positions") ?? [];
|
|
31720
|
+
const cfgArr = get("config") ?? [];
|
|
31721
|
+
const cfgOk = cfgArr[0] ?? {};
|
|
31617
31722
|
const totalEq = balOk.length > 0 ? parseFloat(balOk[0]?.totalEq ?? "0") : 0;
|
|
31618
31723
|
const details = balOk.length > 0 ? balOk[0]?.details ?? [] : [];
|
|
31619
31724
|
const activePos = posOk.filter((p) => parseFloat(p.pos || "0") !== 0);
|
|
@@ -31628,6 +31733,7 @@ function registerAgentUtils(server, auth) {
|
|
|
31628
31733
|
if (liqPx > 0 && markPx > 0) {
|
|
31629
31734
|
liqDistance = p.posSide === "long" ? (markPx - liqPx) / markPx * 100 : (liqPx - markPx) / markPx * 100;
|
|
31630
31735
|
}
|
|
31736
|
+
const mgnMode = p.mgnMode || "unknown";
|
|
31631
31737
|
return {
|
|
31632
31738
|
instId: p.instId,
|
|
31633
31739
|
posSide: p.posSide,
|
|
@@ -31644,12 +31750,13 @@ function registerAgentUtils(server, auth) {
|
|
|
31644
31750
|
// 附操作上下文,让 Agent 不再二次查
|
|
31645
31751
|
instFamily: p.instFamily,
|
|
31646
31752
|
instType: p.instType,
|
|
31647
|
-
mgnMode
|
|
31753
|
+
mgnMode
|
|
31648
31754
|
};
|
|
31649
31755
|
}).sort((a, b) => parseFloat(a.mgnRatio) - parseFloat(b.mgnRatio));
|
|
31650
31756
|
const totalMargin = posRisks.reduce((s, p) => s + parseFloat(p.margin), 0);
|
|
31651
31757
|
const dangerCount = posRisks.filter((p) => p.riskLevel === "\u{1F534} \u5371\u9669").length;
|
|
31652
31758
|
const warnCount = posRisks.filter((p) => p.riskLevel === "\u{1F7E1} \u8B66\u544A").length;
|
|
31759
|
+
const unknownMgnCount = posRisks.filter((p) => p.mgnMode === "unknown").length;
|
|
31653
31760
|
const totalMgnRatio = totalEq > 0 ? (totalMargin / totalEq * 100).toFixed(1) : "N/A";
|
|
31654
31761
|
const usdtDetail = details.find((d) => d.ccy === "USDT");
|
|
31655
31762
|
const availBalance = usdtDetail ? parseFloat(usdtDetail.availBal ?? "0") : 0;
|
|
@@ -31672,11 +31779,9 @@ function registerAgentUtils(server, auth) {
|
|
|
31672
31779
|
acctLv: cfgOk.acctLv,
|
|
31673
31780
|
autoLoan: cfgOk.autoLoan
|
|
31674
31781
|
},
|
|
31675
|
-
errors
|
|
31676
|
-
|
|
31677
|
-
|
|
31678
|
-
config2.status === "rejected" ? `\u914D\u7F6E: ${config2.reason?.message}` : null
|
|
31679
|
-
].filter(Boolean)
|
|
31782
|
+
errors,
|
|
31783
|
+
_notes: unknownMgnCount > 0 ? `\u26A0\uFE0F ${unknownMgnCount} \u4E2A\u4ED3\u4F4D\u672A\u8FD4\u56DE mgnMode\uFF0C\u5E73\u4ED3\u65F6 Agent \u9700\u5355\u72EC\u786E\u8BA4\u4FDD\u8BC1\u91D1\u6A21\u5F0F` : void 0,
|
|
31784
|
+
_summary: `\u5F53\u524D${posRisks.length}\u4E2A\u6301\u4ED3\uFF0C\u4FDD\u8BC1\u91D1${totalMargin.toFixed(2)} USD\uFF0C\u603B\u6743\u76CA${totalEq.toFixed(2)} USD\u3002${dangerCount > 0 ? `\u{1F534} ${dangerCount}\u4E2A\u4ED3\u4F4D\u63A5\u8FD1\u5F3A\u5E73\uFF01` : warnCount > 0 ? `\u26A1 ${warnCount}\u4E2A\u9700\u5173\u6CE8` : posRisks.length > 0 ? `\u2705 \u6240\u6709\u4ED3\u4F4D\u5B89\u5168` : `\u65E0\u6301\u4ED3`}`
|
|
31680
31785
|
};
|
|
31681
31786
|
return toResult(overview);
|
|
31682
31787
|
} catch (e) {
|
|
@@ -31698,47 +31803,57 @@ function registerAgentUtils(server, auth) {
|
|
|
31698
31803
|
async ({ instId, side, sz, tdMode, px, ordType }) => {
|
|
31699
31804
|
if (!auth) return toError(AUTH_REQUIRED);
|
|
31700
31805
|
try {
|
|
31701
|
-
const
|
|
31702
|
-
|
|
31703
|
-
|
|
31704
|
-
|
|
31705
|
-
|
|
31706
|
-
|
|
31707
|
-
|
|
31708
|
-
|
|
31709
|
-
const
|
|
31710
|
-
const
|
|
31711
|
-
const get = (
|
|
31712
|
-
|
|
31713
|
-
|
|
31714
|
-
|
|
31715
|
-
|
|
31716
|
-
|
|
31717
|
-
|
|
31718
|
-
const
|
|
31719
|
-
const
|
|
31806
|
+
const szParsed = parseNumeric(sz, "sz(\u6570\u91CF)");
|
|
31807
|
+
if (!szParsed.ok) return toError(szParsed.error);
|
|
31808
|
+
if (szParsed.value <= 0) return toError(`\u6570\u91CF sz=${sz} \u5FC5\u987B\u5927\u4E8E 0\uFF0CAgent \u8BF7\u8C03\u6574\u540E\u91CD\u8BD5`);
|
|
31809
|
+
if (px !== void 0) {
|
|
31810
|
+
const pxParsed = parseNumeric(px, "px(\u4EF7\u683C)");
|
|
31811
|
+
if (!pxParsed.ok) return toError(pxParsed.error);
|
|
31812
|
+
if (pxParsed.value <= 0) return toError(`\u4EF7\u683C px=${px} \u5FC5\u987B\u5927\u4E8E 0\uFF0CAgent \u8BF7\u8C03\u6574\u540E\u91CD\u8BD5`);
|
|
31813
|
+
}
|
|
31814
|
+
const instType = inferInstType(instId);
|
|
31815
|
+
const feeCcy = inferFeeCcy(instId, tdMode);
|
|
31816
|
+
const { get, errors: precheckErrors } = await fetchAllSettled({
|
|
31817
|
+
balance: privateApi.getBalance(auth),
|
|
31818
|
+
maxSize: privateApi.getMaxSize(auth, instId, tdMode),
|
|
31819
|
+
feeRates: privateApi.getFeeRates(auth, instType, instId),
|
|
31820
|
+
ticker: publicApi.getTicker(instId),
|
|
31821
|
+
priceLimit: publicApi.getPriceLimitBatch("", void 0, instId)
|
|
31822
|
+
});
|
|
31823
|
+
const balArr = get("balance") ?? [];
|
|
31824
|
+
const balDetails = balArr[0]?.details ?? [];
|
|
31825
|
+
const availBal = parseFloat(balDetails.find((d) => d.ccy === feeCcy)?.availBal ?? "0");
|
|
31826
|
+
const maxArr = get("maxSize") ?? [];
|
|
31827
|
+
const maxData = maxArr[0];
|
|
31720
31828
|
const maxBuy = parseFloat(maxData?.maxBuy ?? "0");
|
|
31721
31829
|
const maxSell = parseFloat(maxData?.maxSell ?? "0");
|
|
31722
31830
|
const maxSz = side === "buy" ? maxBuy : maxSell;
|
|
31723
|
-
const
|
|
31831
|
+
const feeArr = get("feeRates") ?? [];
|
|
31832
|
+
const feeData = feeArr[0] ?? {};
|
|
31724
31833
|
const makerFee = parseFloat(feeData?.maker ?? "0");
|
|
31725
31834
|
const takerFee = parseFloat(feeData?.taker ?? "0");
|
|
31726
31835
|
const feeRate = ordType === "market" ? takerFee : makerFee;
|
|
31727
|
-
const
|
|
31836
|
+
const tkArr = get("ticker") ?? [];
|
|
31837
|
+
const tkData = tkArr[0] ?? {};
|
|
31728
31838
|
const lastPx = parseFloat(tkData?.last ?? "0");
|
|
31729
31839
|
const orderPx = px ? parseFloat(px) : lastPx;
|
|
31730
|
-
const estCost =
|
|
31840
|
+
const estCost = szParsed.value * orderPx;
|
|
31731
31841
|
const estFee = estCost * feeRate;
|
|
31732
|
-
const
|
|
31842
|
+
const limitArr = get("priceLimit") ?? [];
|
|
31843
|
+
const limitData = limitArr[0];
|
|
31733
31844
|
const lowest = parseFloat(limitData?.lowest ?? "0");
|
|
31734
31845
|
const highest = parseFloat(limitData?.highest ?? "999999");
|
|
31735
31846
|
const warnings = [];
|
|
31736
|
-
const qty =
|
|
31737
|
-
if (
|
|
31738
|
-
|
|
31739
|
-
if (
|
|
31740
|
-
|
|
31847
|
+
const qty = szParsed.value;
|
|
31848
|
+
if (maxSz > 0 && qty > maxSz)
|
|
31849
|
+
warnings.push(`\u6570\u91CF ${sz} \u8D85\u8FC7\u6700\u5927\u53EF${side === "buy" ? "\u4E70" : "\u5356"} ${maxSz}\uFF0CAgent \u8BF7\u51CF\u81F3 \u2264${maxSz}`);
|
|
31850
|
+
if (availBal > 0 && availBal < estCost + estFee)
|
|
31851
|
+
warnings.push(`\u4F59\u989D\u4E0D\u8DB3\uFF1A\u9700\u8981 $${(estCost + estFee).toFixed(2)}\uFF0C\u53EF\u7528 $${availBal.toFixed(2)}\uFF0CAgent \u8BF7\u51CF\u5C11\u6570\u91CF\u6216\u5145\u503C`);
|
|
31852
|
+
if (orderPx > 0 && (orderPx < lowest || orderPx > highest))
|
|
31853
|
+
warnings.push(`\u4EF7\u683C ${orderPx} \u8D85\u51FA\u9650\u4EF7\u8303\u56F4 [${lowest}, ${highest}]\uFF0CAgent \u8BF7\u8C03\u6574\u4EF7\u683C`);
|
|
31854
|
+
if (warnings.length > 0 || precheckErrors.length > 0) {
|
|
31741
31855
|
return toResult({
|
|
31856
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
31742
31857
|
executed: false,
|
|
31743
31858
|
precheck: {
|
|
31744
31859
|
balance: availBal.toFixed(2),
|
|
@@ -31748,9 +31863,8 @@ function registerAgentUtils(server, auth) {
|
|
|
31748
31863
|
estFee: estFee.toFixed(4),
|
|
31749
31864
|
priceCheck: { orderPx, lowest, highest, within: orderPx >= lowest && orderPx <= highest }
|
|
31750
31865
|
},
|
|
31751
|
-
warnings,
|
|
31752
|
-
tip: "\u9884\u68C0\u672A\u901A\u8FC7\uFF0C\u8BF7\u8C03\u6574\u53C2\u6570\u540E\u91CD\u8BD5"
|
|
31753
|
-
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
31866
|
+
warnings: [...warnings, ...precheckErrors],
|
|
31867
|
+
tip: "\u9884\u68C0\u672A\u901A\u8FC7\uFF0C\u8BF7 Agent \u6839\u636E\u4EE5\u4E0A warnings \u8C03\u6574\u53C2\u6570\u540E\u91CD\u8BD5"
|
|
31754
31868
|
});
|
|
31755
31869
|
}
|
|
31756
31870
|
const body = { instId, side, sz, tdMode };
|
|
@@ -31758,6 +31872,7 @@ function registerAgentUtils(server, auth) {
|
|
|
31758
31872
|
if (px) body.px = px;
|
|
31759
31873
|
const orderResult = await privateApi.placeOrder(auth, body);
|
|
31760
31874
|
return toResult({
|
|
31875
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
31761
31876
|
executed: true,
|
|
31762
31877
|
order: orderResult?.[0] ?? orderResult,
|
|
31763
31878
|
precheck: {
|
|
@@ -31768,10 +31883,10 @@ function registerAgentUtils(server, auth) {
|
|
|
31768
31883
|
estFee: estFee.toFixed(4)
|
|
31769
31884
|
},
|
|
31770
31885
|
risk: {
|
|
31771
|
-
marginUsed: (estCost / availBal * 100).toFixed(1) + "%",
|
|
31772
|
-
warning: estCost / availBal > 0.3 ? "\u6B64\u5355\u4F7F\u7528\u8D85\u8FC730%\u53EF\u7528\u4F59\u989D" : null
|
|
31886
|
+
marginUsed: availBal > 0 ? (estCost / availBal * 100).toFixed(1) + "%" : "N/A",
|
|
31887
|
+
warning: availBal > 0 && estCost / availBal > 0.3 ? "\u6B64\u5355\u4F7F\u7528\u8D85\u8FC730%\u53EF\u7528\u4F59\u989D" : null
|
|
31773
31888
|
},
|
|
31774
|
-
|
|
31889
|
+
_summary: `${side === "buy" ? "\u4E70\u5165" : "\u5356\u51FA"} ${sz} ${instId} \u5DF2\u6210\u4EA4\uFF0C\u9884\u4F30\u6210\u672C $${(estCost + estFee).toFixed(2)}\uFF0C\u624B\u7EED\u8D39 $${estFee.toFixed(4)}\u3002\u4FDD\u8BC1\u91D1\u5360\u7528 ${availBal > 0 ? (estCost / availBal * 100).toFixed(1) + "%" : "N/A"}`
|
|
31775
31890
|
});
|
|
31776
31891
|
} catch (e) {
|
|
31777
31892
|
return toError(e);
|
|
@@ -31800,40 +31915,61 @@ function registerAgentUtils(server, auth) {
|
|
|
31800
31915
|
high24h: parseFloat(t.high24h ?? "0"),
|
|
31801
31916
|
low24h: parseFloat(t.low24h ?? "0"),
|
|
31802
31917
|
bid: parseFloat(t.bidPx ?? "0"),
|
|
31803
|
-
ask: parseFloat(t.askPx ?? "0")
|
|
31918
|
+
ask: parseFloat(t.askPx ?? "0"),
|
|
31919
|
+
fundingRate: 0
|
|
31920
|
+
// 稍后填充
|
|
31804
31921
|
})).filter((t) => t.last > 0 && t.vol24h > 0);
|
|
31805
|
-
if (sb === "vol")
|
|
31806
|
-
|
|
31807
|
-
else
|
|
31922
|
+
if (sb === "vol") {
|
|
31923
|
+
arr.sort((a, b) => b.vol24h - a.vol24h);
|
|
31924
|
+
} else if (sb === "change") {
|
|
31925
|
+
arr.sort((a, b) => Math.abs(b.change24h) - Math.abs(a.change24h));
|
|
31926
|
+
} else if (sb === "fundingRate") {
|
|
31927
|
+
const candidates = [...arr].sort((a, b) => Math.abs(b.change24h) - Math.abs(a.change24h)).slice(0, 20);
|
|
31928
|
+
const frFetchers = {};
|
|
31929
|
+
for (const c of candidates) {
|
|
31930
|
+
frFetchers[c.instId] = publicApi.getFundingRate(c.instId);
|
|
31931
|
+
}
|
|
31932
|
+
const { get: frGet } = await fetchAllSettled(frFetchers);
|
|
31933
|
+
for (const c of candidates) {
|
|
31934
|
+
const frArr = frGet(c.instId) ?? [];
|
|
31935
|
+
c.fundingRate = parseFloat(frArr[0]?.fundingRate ?? "0");
|
|
31936
|
+
}
|
|
31937
|
+
const frMap = new Map(candidates.map((c) => [c.instId, c.fundingRate]));
|
|
31938
|
+
arr.forEach((t) => {
|
|
31939
|
+
t.fundingRate = frMap.get(t.instId) ?? 0;
|
|
31940
|
+
});
|
|
31941
|
+
arr.sort((a, b) => Math.abs(b.fundingRate) - Math.abs(a.fundingRate));
|
|
31942
|
+
}
|
|
31808
31943
|
const top = arr.slice(0, n);
|
|
31809
31944
|
const gainers = top.filter((t) => t.change24h > 0).sort((a, b) => b.change24h - a.change24h);
|
|
31810
31945
|
const losers = top.filter((t) => t.change24h < 0).sort((a, b) => a.change24h - b.change24h);
|
|
31811
|
-
const volumeLeader = arr.
|
|
31946
|
+
const volumeLeader = [...arr].sort((a, b) => b.vol24h - a.vol24h).slice(0, 5);
|
|
31812
31947
|
let fundingAlerts = [];
|
|
31813
31948
|
if (it === "SWAP") {
|
|
31814
|
-
|
|
31815
|
-
|
|
31816
|
-
|
|
31817
|
-
|
|
31818
|
-
|
|
31819
|
-
|
|
31820
|
-
|
|
31821
|
-
|
|
31822
|
-
|
|
31949
|
+
const toFetch = top.filter((t) => t.fundingRate === 0);
|
|
31950
|
+
if (toFetch.length > 0) {
|
|
31951
|
+
const frFetchers = {};
|
|
31952
|
+
for (const t of toFetch) {
|
|
31953
|
+
frFetchers[t.instId] = publicApi.getFundingRate(t.instId);
|
|
31954
|
+
}
|
|
31955
|
+
const { get: frGet } = await fetchAllSettled(frFetchers);
|
|
31956
|
+
for (const t of toFetch) {
|
|
31957
|
+
const frArr = frGet(t.instId) ?? [];
|
|
31958
|
+
t.fundingRate = parseFloat(frArr[0]?.fundingRate ?? "0");
|
|
31823
31959
|
}
|
|
31824
|
-
fundingAlerts = Object.entries(fr).filter(([, r]) => Math.abs(r) > 1e-3).map(([instId, rate]) => ({ instId, fundingRate: (rate * 100).toFixed(4) + "%" }));
|
|
31825
|
-
} catch {
|
|
31826
31960
|
}
|
|
31961
|
+
fundingAlerts = top.filter((t) => Math.abs(t.fundingRate) > 1e-3).map((t) => ({ instId: t.instId, fundingRate: (t.fundingRate * 100).toFixed(4) + "%" }));
|
|
31827
31962
|
}
|
|
31828
31963
|
return toResult({
|
|
31829
|
-
|
|
31964
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
31965
|
+
scanType: sb === "fundingRate" ? "\u8D44\u91D1\u8D39\u7387\u6392\u884C" : sb === "vol" ? "\u6210\u4EA4\u91CF\u6392\u884C" : "\u6DA8\u8DCC\u5E45\u5F02\u52A8",
|
|
31830
31966
|
instType: it,
|
|
31831
31967
|
top: top.slice(0, n),
|
|
31832
31968
|
gainers: gainers.slice(0, 5),
|
|
31833
31969
|
losers: losers.slice(0, 5),
|
|
31834
31970
|
volumeLeader,
|
|
31835
31971
|
fundingAlerts,
|
|
31836
|
-
|
|
31972
|
+
_summary: `\u5171\u626B\u63CF${arr.length}\u4E2A${it}\u54C1\u79CD\u3002${sb === "fundingRate" ? `\u8D44\u91D1\u8D39\u7387\u524D${n}: ${top.slice(0, 3).map((t) => `${t.instId}(${(t.fundingRate * 100).toFixed(3)}%)`).join("\u3001")}` : `\u6DA8\u5E45\u524D5: ${gainers.slice(0, 3).map((g) => g.instId).join("\u3001") || "\u65E0"}\u3002\u8DCC\u5E45\u524D5: ${losers.slice(0, 3).map((l) => l.instId).join("\u3001") || "\u65E0"}`}\u3002${fundingAlerts.length > 0 ? `\u26A0\uFE0F ${fundingAlerts.length}\u4E2A\u54C1\u79CD\u8D44\u91D1\u8D39\u7387\u5F02\u5E38\u3002` : ""}`,
|
|
31837
31973
|
tip: "\u626B\u63CF\u7ED3\u679C\u4E3A\u5FEB\u7167\u3002\u5177\u4F53\u54C1\u79CD\u7528 okx_quick_market \u6DF1\u5165\u5206\u6790\u3002"
|
|
31838
31974
|
});
|
|
31839
31975
|
} catch (e) {
|
|
@@ -31851,14 +31987,15 @@ function registerAgentUtils(server, auth) {
|
|
|
31851
31987
|
if (!auth) return toError(AUTH_REQUIRED);
|
|
31852
31988
|
try {
|
|
31853
31989
|
const d = days || 7;
|
|
31854
|
-
const
|
|
31855
|
-
privateApi.getBalance(auth),
|
|
31856
|
-
privateApi.getPositions(auth),
|
|
31857
|
-
privateApi.getFillsHistory(auth, void 0, void 0, Math.min(d * 10, 100))
|
|
31858
|
-
|
|
31859
|
-
const balOk = balance
|
|
31860
|
-
const
|
|
31861
|
-
const
|
|
31990
|
+
const { get, errors } = await fetchAllSettled({
|
|
31991
|
+
balance: privateApi.getBalance(auth),
|
|
31992
|
+
positions: privateApi.getPositions(auth),
|
|
31993
|
+
fills: privateApi.getFillsHistory(auth, void 0, void 0, Math.min(d * 10, 100))
|
|
31994
|
+
});
|
|
31995
|
+
const balOk = get("balance") ?? [];
|
|
31996
|
+
const balFirst = balOk[0] ?? {};
|
|
31997
|
+
const posOk = get("positions") ?? [];
|
|
31998
|
+
const fillsOk = get("fills") ?? [];
|
|
31862
31999
|
const totalUpl = posOk.reduce((s, p) => s + parseFloat(p.upl ?? "0"), 0).toFixed(2);
|
|
31863
32000
|
const activePos = posOk.filter((p) => parseFloat(p.pos || "0") !== 0);
|
|
31864
32001
|
const posPnL = activePos.map((p) => ({
|
|
@@ -31885,7 +32022,7 @@ function registerAgentUtils(server, auth) {
|
|
|
31885
32022
|
dailyPnL[day] = (dailyPnL[day] || 0) + pnl;
|
|
31886
32023
|
totalRealized += pnl;
|
|
31887
32024
|
}
|
|
31888
|
-
const totalEq = parseFloat(
|
|
32025
|
+
const totalEq = parseFloat(balFirst.totalEq ?? "0");
|
|
31889
32026
|
return toResult({
|
|
31890
32027
|
tsIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
31891
32028
|
period: `\u8FD1${d}\u65E5`,
|
|
@@ -31901,11 +32038,1544 @@ function registerAgentUtils(server, auth) {
|
|
|
31901
32038
|
positions: posPnL,
|
|
31902
32039
|
positionCount: activePos.length,
|
|
31903
32040
|
tradesAnalyzed: recentFills.length,
|
|
31904
|
-
errors
|
|
31905
|
-
|
|
31906
|
-
|
|
31907
|
-
|
|
31908
|
-
|
|
32041
|
+
errors,
|
|
32042
|
+
_summary: `\u8FD1${d}\u65E5\u6D6E\u52A8\u76C8\u4E8F $${totalUpl}\uFF08${totalEq > 0 ? (parseFloat(totalUpl) / totalEq * 100).toFixed(2) : "N/A"}%\uFF09\uFF0C\u5DF2\u5B9E\u73B0\u76C8\u4E8F $${totalRealized.toFixed(2)}\u3002${activePos.length}\u4E2A\u6301\u4ED3\uFF0C\u5206\u6790${recentFills.length}\u7B14\u6210\u4EA4\u3002`
|
|
32043
|
+
});
|
|
32044
|
+
} catch (e) {
|
|
32045
|
+
return toError(e);
|
|
32046
|
+
}
|
|
32047
|
+
}
|
|
32048
|
+
);
|
|
32049
|
+
server.tool(
|
|
32050
|
+
"agent_simulate_order",
|
|
32051
|
+
'CAT:[\u7CFB\u7EDF] | ## \u529F\u80FD\uFF1A\u6A21\u62DF\u4E0B\u5355\u2014\u2014\u4E0D\u4EA7\u751F\u771F\u5B9E\u8BA2\u5355\uFF0C\u8FD4\u56DE\u9884\u4F30\u6210\u4EA4\u4EF7\u3001\u6ED1\u70B9\u3001\u624B\u7EED\u8D39\u3001\u8D44\u91D1\u5360\u7528\n## \u573A\u666F\uFF1AAgent \u56DE\u7B54"\u5982\u679C\u6211\u73B0\u5728\u4E70\u51650.1 BTC\u4F1A\u600E\u6837"\u65F6\u4F7F\u7528\uFF0C\u8BA9\u7528\u6237\u5728\u4E0D\u5192\u98CE\u9669\u7684\u60C5\u51B5\u4E0B\u4E86\u89E3\u4EA4\u6613\u6210\u672C\n## \u5173\u952E\u8BCD\uFF1A\u6A21\u62DF\u4EA4\u6613, \u6C99\u76D2, simulate, \u9884\u4F30, \u6ED1\u70B9, \u624B\u7EED\u8D39, \u8D44\u91D1\u9884\u4F30\n## \u53C2\u6570\uFF1A\n## - instId: \u4EA7\u54C1ID\n## - side: buy=\u4E70\u5165, sell=\u5356\u51FA\n## - sz: \u4E0B\u5355\u6570\u91CF\n## - tdMode: \u4EA4\u6613\u6A21\u5F0F\n## - px: \u9650\u4EF7\uFF08\u9009\u586B\uFF0C\u7528\u4E8E\u8BA1\u7B97\u9650\u4EF7\u5355\u9884\u4F30\uFF09\n## \u9274\u6743\uFF1A\u26A0\uFE0F \u9700\u8981 API Key\uFF08\u53EA\u8BFB\uFF0C\u4E0D\u4EA7\u751F\u8BA2\u5355\uFF09\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u67E5\u8BE2+\u8BA1\u7B97\uFF0C\u4E0D\u4EA7\u751F\u771F\u5B9E\u8BA2\u5355\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~1KB\n## \u5173\u8054\uFF1A\u672C\u5DE5\u5177\u6A21\u62DF \u2192 \u7528\u6237\u786E\u8BA4 \u2192 agent_quick_trade \u771F\u5B9E\u4E0B\u5355',
|
|
32052
|
+
{
|
|
32053
|
+
instId: external_exports.string().describe("\u4EA7\u54C1ID\uFF0C\u5982 BTC-USDT-SWAP"),
|
|
32054
|
+
side: external_exports.enum(["buy", "sell"]).describe("\u4E70\u5356\u65B9\u5411"),
|
|
32055
|
+
sz: external_exports.string().describe("\u4E0B\u5355\u6570\u91CF"),
|
|
32056
|
+
tdMode: external_exports.enum(["cash", "cross", "isolated"]).describe("\u4EA4\u6613\u6A21\u5F0F"),
|
|
32057
|
+
px: external_exports.string().optional().describe("\u9650\u4EF7\uFF08\u9009\u586B\uFF0C\u7528\u4E8E\u8BA1\u7B97\u9650\u4EF7\u5355\u9884\u4F30\uFF09")
|
|
32058
|
+
},
|
|
32059
|
+
async ({ instId, side, sz, tdMode, px }) => {
|
|
32060
|
+
if (!auth) return toError(AUTH_REQUIRED);
|
|
32061
|
+
try {
|
|
32062
|
+
const szParsed = parseNumeric(sz, "sz(\u6570\u91CF)");
|
|
32063
|
+
if (!szParsed.ok) return toError(szParsed.error);
|
|
32064
|
+
if (szParsed.value <= 0) return toError(`\u6570\u91CF sz=${sz} \u5FC5\u987B\u5927\u4E8E 0\uFF0CAgent \u8BF7\u8C03\u6574\u540E\u91CD\u8BD5`);
|
|
32065
|
+
if (px !== void 0) {
|
|
32066
|
+
const pxParsed = parseNumeric(px, "px(\u4EF7\u683C)");
|
|
32067
|
+
if (!pxParsed.ok) return toError(pxParsed.error);
|
|
32068
|
+
}
|
|
32069
|
+
const qty = szParsed.value;
|
|
32070
|
+
const instType = inferInstType(instId);
|
|
32071
|
+
const { get, errors } = await fetchAllSettled({
|
|
32072
|
+
ticker: publicApi.getTicker(instId),
|
|
32073
|
+
orderbook: publicApi.getOrderbook(instId, 10),
|
|
32074
|
+
feeRates: privateApi.getFeeRates(auth, instType, instId),
|
|
32075
|
+
priceLimit: publicApi.getPriceLimitBatch("", void 0, instId)
|
|
32076
|
+
});
|
|
32077
|
+
const tkArr = get("ticker") ?? [];
|
|
32078
|
+
const tk = tkArr[0] ?? {};
|
|
32079
|
+
const lastPx = parseFloat(tk?.last ?? "0");
|
|
32080
|
+
const bidPx = parseFloat(tk?.bidPx ?? "0");
|
|
32081
|
+
const askPx = parseFloat(tk?.askPx ?? "0");
|
|
32082
|
+
const markPx = lastPx || bidPx || askPx;
|
|
32083
|
+
const obRaw = get("orderbook");
|
|
32084
|
+
const { asks, bids } = extractOrderbook(obRaw);
|
|
32085
|
+
let slippage = 0;
|
|
32086
|
+
if (side === "buy" && asks.length > 0) {
|
|
32087
|
+
let remaining = qty;
|
|
32088
|
+
let cost = 0;
|
|
32089
|
+
for (const a of asks) {
|
|
32090
|
+
const px_a = parseFloat(a[0] || "0");
|
|
32091
|
+
const sz_a = parseFloat(a[1] || "0");
|
|
32092
|
+
const fill = Math.min(remaining, sz_a);
|
|
32093
|
+
cost += fill * px_a;
|
|
32094
|
+
remaining -= fill;
|
|
32095
|
+
if (remaining <= 0) break;
|
|
32096
|
+
}
|
|
32097
|
+
const avgPx = cost / qty;
|
|
32098
|
+
slippage = markPx > 0 ? (avgPx - markPx) / markPx * 100 : 0;
|
|
32099
|
+
} else if (side === "sell" && bids.length > 0) {
|
|
32100
|
+
let remaining = qty;
|
|
32101
|
+
let revenue = 0;
|
|
32102
|
+
for (const b of bids) {
|
|
32103
|
+
const px_b = parseFloat(b[0] || "0");
|
|
32104
|
+
const sz_b = parseFloat(b[1] || "0");
|
|
32105
|
+
const fill = Math.min(remaining, sz_b);
|
|
32106
|
+
revenue += fill * px_b;
|
|
32107
|
+
remaining -= fill;
|
|
32108
|
+
if (remaining <= 0) break;
|
|
32109
|
+
}
|
|
32110
|
+
const avgPx = revenue / qty;
|
|
32111
|
+
slippage = markPx > 0 ? (markPx - avgPx) / markPx * 100 : 0;
|
|
32112
|
+
}
|
|
32113
|
+
const feeArr = get("feeRates") ?? [];
|
|
32114
|
+
const feeData = feeArr[0] ?? {};
|
|
32115
|
+
const takerFee = parseFloat(feeData?.taker ?? "0");
|
|
32116
|
+
const feeRate = takerFee;
|
|
32117
|
+
const limitArr = get("priceLimit") ?? [];
|
|
32118
|
+
const limitData = limitArr[0];
|
|
32119
|
+
const lowest = parseFloat(limitData?.lowest ?? "0");
|
|
32120
|
+
const highest = parseFloat(limitData?.highest ?? "999999");
|
|
32121
|
+
const orderPx = px ? parseFloat(px) : side === "buy" ? askPx : bidPx;
|
|
32122
|
+
const estCost = qty * orderPx;
|
|
32123
|
+
const estFee = estCost * feeRate;
|
|
32124
|
+
const pxWithinLimit = orderPx >= lowest && orderPx <= highest;
|
|
32125
|
+
return toResult({
|
|
32126
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
32127
|
+
simulated: true,
|
|
32128
|
+
instId,
|
|
32129
|
+
side,
|
|
32130
|
+
sz,
|
|
32131
|
+
tdMode,
|
|
32132
|
+
orderPx: orderPx.toFixed(4),
|
|
32133
|
+
currentPrice: { last: lastPx, bid: bidPx, ask: askPx },
|
|
32134
|
+
estimate: {
|
|
32135
|
+
estCost: estCost.toFixed(2) + " USD",
|
|
32136
|
+
estFee: estFee.toFixed(4) + " USD",
|
|
32137
|
+
estTotal: (estCost + estFee).toFixed(2) + " USD",
|
|
32138
|
+
feeRate: (feeRate * 100).toFixed(4) + "%",
|
|
32139
|
+
slippage: slippage.toFixed(4) + "%"
|
|
32140
|
+
},
|
|
32141
|
+
priceCheck: {
|
|
32142
|
+
withinLimit: pxWithinLimit,
|
|
32143
|
+
range: `${lowest} ~ ${highest}`
|
|
32144
|
+
},
|
|
32145
|
+
errors,
|
|
32146
|
+
_summary: `\u6A21\u62DF${side === "buy" ? "\u4E70\u5165" : "\u5356\u51FA"} ${sz} ${instId}\uFF1A\u9884\u4F30\u6210\u4EA4\u4EF7 $${orderPx.toFixed(2)}\uFF0C\u624B\u7EED\u8D39 $${estFee.toFixed(4)}\uFF0C\u5408\u8BA1 $${(estCost + estFee).toFixed(2)}\uFF0C\u6ED1\u70B9 ${slippage.toFixed(2)}%\u3002${pxWithinLimit ? "\u4EF7\u683C\u5728\u9650\u4EF7\u8303\u56F4\u5185\u3002" : "\u26A0\uFE0F \u4EF7\u683C\u8D85\u51FA\u9650\u4EF7\u8303\u56F4\uFF0CAgent \u8BF7\u8C03\u6574\u3002"}`,
|
|
32147
|
+
tip: "\u4EE5\u4E0A\u4E3A\u6A21\u62DF\u7ED3\u679C\uFF0C\u4E0D\u4EA7\u751F\u771F\u5B9E\u8BA2\u5355\u3002\u786E\u8BA4\u540E\u53EF\u7528 agent_quick_trade \u771F\u5B9E\u4E0B\u5355\u3002"
|
|
32148
|
+
});
|
|
32149
|
+
} catch (e) {
|
|
32150
|
+
return toError(e);
|
|
32151
|
+
}
|
|
32152
|
+
}
|
|
32153
|
+
);
|
|
32154
|
+
server.tool(
|
|
32155
|
+
"agent_get_preference",
|
|
32156
|
+
'CAT:[\u7CFB\u7EDF] | ## \u529F\u80FD\uFF1A\u8BFB\u53D6 Agent \u6301\u4E45\u5316\u504F\u597D\uFF0C\u8DE8\u4F1A\u8BDD\u4FDD\u7559\n## \u573A\u666F\uFF1AAgent \u5728\u65B0\u4F1A\u8BDD\u4E2D\u6062\u590D\u7528\u6237\u504F\u597D\uFF08\u5982"\u53EA\u505A\u73B0\u8D27""\u9ED8\u8BA4\u4EA4\u6613\u5BF9BTC-USDT""\u98CE\u9669\u504F\u597D\u4F4E"\uFF09\n## \u5173\u952E\u8BCD\uFF1A\u504F\u597D, preference, \u8BB0\u5FC6, \u6301\u4E45\u5316, \u7528\u6237\u753B\u50CF\n## \u53C2\u6570\uFF1A\n## - key: \u504F\u597D\u952E\u540D\u3002\u4E0D\u586B\u8FD4\u56DE\u5168\u90E8\u504F\u597D\n## \u9274\u6743\uFF1APUBLIC \u2014 \u672C\u5730\u8BFB\u53D6\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~300B\n## \u5173\u8054\uFF1Aagent_set_preference \u8BBE\u7F6E\u504F\u597D \u2192 \u672C\u5DE5\u5177 \u2192 Agent \u6839\u636E\u504F\u597D\u8C03\u6574\u7B56\u7565',
|
|
32157
|
+
{
|
|
32158
|
+
key: external_exports.string().optional().describe("\u504F\u597D\u952E\u540D\uFF0C\u4E0D\u586B\u8FD4\u56DE\u5168\u90E8")
|
|
32159
|
+
},
|
|
32160
|
+
async ({ key }) => {
|
|
32161
|
+
try {
|
|
32162
|
+
const prefPath = path.join(os.homedir(), ".hvip", "preferences.json");
|
|
32163
|
+
let prefs = {};
|
|
32164
|
+
try {
|
|
32165
|
+
if (fs.existsSync(prefPath)) {
|
|
32166
|
+
prefs = JSON.parse(fs.readFileSync(prefPath, "utf-8"));
|
|
32167
|
+
}
|
|
32168
|
+
} catch {
|
|
32169
|
+
}
|
|
32170
|
+
const result = key ? { key, value: prefs[key] ?? null, found: key in prefs } : { all: prefs, count: Object.keys(prefs).length };
|
|
32171
|
+
return toResult({
|
|
32172
|
+
...result,
|
|
32173
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
32174
|
+
_summary: key ? `\u504F\u597D "${key}" = ${prefs[key] ? `"${prefs[key]}"` : "\u672A\u8BBE\u7F6E"}` : `\u5DF2\u5B58\u50A8 ${Object.keys(prefs).length} \u6761\u504F\u597D`
|
|
32175
|
+
});
|
|
32176
|
+
} catch (e) {
|
|
32177
|
+
return toError(e);
|
|
32178
|
+
}
|
|
32179
|
+
}
|
|
32180
|
+
);
|
|
32181
|
+
server.tool(
|
|
32182
|
+
"agent_set_preference",
|
|
32183
|
+
'CAT:[\u7CFB\u7EDF] | ## \u529F\u80FD\uFF1A\u8BBE\u7F6E Agent \u6301\u4E45\u5316\u504F\u597D\uFF0C\u8DE8\u4F1A\u8BDD\u4FDD\u7559\n## \u573A\u666F\uFF1A\u7528\u6237\u8BF4"\u4EE5\u540E\u9ED8\u8BA4\u4EA4\u6613\u5BF9\u7528BTC-USDT"\u65F6\uFF0CAgent \u4FDD\u5B58\u504F\u597D\uFF0C\u4E0B\u6B21\u4F1A\u8BDD\u81EA\u52A8\u6062\u590D\n## \u5173\u952E\u8BCD\uFF1A\u504F\u597D, preference, \u8BBE\u7F6E, \u8BB0\u5FC6, \u6301\u4E45\u5316, \u7528\u6237\u753B\u50CF\n## \u53C2\u6570\uFF1A\n## - key: \u504F\u597D\u952E\u540D\n## - value: \u504F\u597D\u503C\n## \u9274\u6743\uFF1APUBLIC \u2014 \u672C\u5730\u5199\u5165\n## \u98CE\u9669\uFF1AREAD \u2014 \u672C\u5730\u6587\u4EF6\u5199\u5165\uFF0C\u65E0\u8D44\u91D1\u98CE\u9669\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~200B\n## \u5173\u8054\uFF1A\u672C\u5DE5\u5177\u8BBE\u7F6E\u504F\u597D \u2192 agent_get_preference \u8BFB\u53D6 \u2192 Agent \u6309\u504F\u597D\u51B3\u7B56\n## \u5E38\u7528\u952E\u540D\u53C2\u8003:\n## - default_instId: \u9ED8\u8BA4\u4EA4\u6613\u5BF9\uFF0C\u5982 BTC-USDT-SWAP\n## - default_tdMode: \u9ED8\u8BA4\u4EA4\u6613\u6A21\u5F0F (cross/isolated/cash)\n## - risk_level: \u98CE\u9669\u504F\u597D (low/medium/high)\n## - trade_mode: \u4EA4\u6613\u6A21\u5F0F (spot_only/swap_permitted/margin_permitted)\n## - position_size_pct: \u5355\u7B14\u4ED3\u4F4D\u5360\u6BD4\uFF0C\u5982 0.1 (10%)',
|
|
32184
|
+
{
|
|
32185
|
+
key: external_exports.string().describe("\u504F\u597D\u952E\u540D\u3002\u5E38\u7528: default_instId, default_tdMode, risk_level, trade_mode, position_size_pct"),
|
|
32186
|
+
value: external_exports.string().describe("\u504F\u597D\u503C")
|
|
32187
|
+
},
|
|
32188
|
+
async ({ key, value }) => {
|
|
32189
|
+
try {
|
|
32190
|
+
const dir = path.join(os.homedir(), ".hvip");
|
|
32191
|
+
const prefPath = path.join(dir, "preferences.json");
|
|
32192
|
+
let prefs = {};
|
|
32193
|
+
try {
|
|
32194
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
32195
|
+
if (fs.existsSync(prefPath)) {
|
|
32196
|
+
prefs = JSON.parse(fs.readFileSync(prefPath, "utf-8"));
|
|
32197
|
+
}
|
|
32198
|
+
} catch {
|
|
32199
|
+
}
|
|
32200
|
+
prefs[key] = value;
|
|
32201
|
+
fs.writeFileSync(prefPath, JSON.stringify(prefs, null, 2), "utf-8");
|
|
32202
|
+
return toResult({
|
|
32203
|
+
ok: true,
|
|
32204
|
+
key,
|
|
32205
|
+
value,
|
|
32206
|
+
stored: Object.keys(prefs).length,
|
|
32207
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
32208
|
+
_summary: `\u5DF2\u4FDD\u5B58\u504F\u597D: "${key}" = "${value}"\uFF08\u5171 ${Object.keys(prefs).length} \u6761\u504F\u597D\uFF09`
|
|
32209
|
+
});
|
|
32210
|
+
} catch (e) {
|
|
32211
|
+
return toError(e);
|
|
32212
|
+
}
|
|
32213
|
+
}
|
|
32214
|
+
);
|
|
32215
|
+
const CATALOG = {
|
|
32216
|
+
_instruction: [
|
|
32217
|
+
"\u4F60\u662F hvip MCP Server \u7684 Agent\u3002\u672C\u76EE\u5F55\u5E2E\u4F60\u6309\u7528\u6237\u610F\u56FE\u5FEB\u901F\u5B9A\u4F4D\u5DE5\u5177\uFF0C\u65E0\u9700\u626B\u63CF\u5168\u90E8 350+ \u4E2A\u5DE5\u5177\u63CF\u8FF0\u3002",
|
|
32218
|
+
"\u7528\u6CD5: 1) \u6839\u636E\u7528\u6237\u8BF4\u7684\u8BDD\u5339\u914D\u4E0B\u65B9\u67D0\u4E2A\u57DF\u7684 when \u89E6\u53D1\u8BCD \u2192 2) \u8C03\u7528\u8BE5\u57DF\u7684 go_to \u5DE5\u5177 \u2192 3) \u5982\u9700\u6DF1\u5165\u518D\u8C03\u7528 also \u5217\u8868\u4E2D\u7684\u5DE5\u5177\u3002",
|
|
32219
|
+
"\u4E0D\u786E\u5B9A\u57DF\u65F6\u8C03\u7528 agent_catalog_detail { domain } \u67E5\u770B\u8BE5\u57DF\u7684\u8BE6\u7EC6\u5DE5\u5177\u6E05\u5355\u3002",
|
|
32220
|
+
"\u6CE8\u610F: \u6240\u6709 WRITE/ADMIN \u7EA7\u522B\u7684\u5DE5\u5177\u9700\u7528\u6237\u786E\u8BA4\u540E\u624D\u80FD\u8C03\u7528\u3002"
|
|
32221
|
+
].join(" "),
|
|
32222
|
+
domains: [
|
|
32223
|
+
{
|
|
32224
|
+
domain: "\u8D26\u6237\u8D44\u4EA7",
|
|
32225
|
+
what: "\u67E5\u770B\u8D26\u6237\u4F59\u989D\u3001\u6301\u4ED3\u3001\u914D\u7F6E\u3001\u624B\u7EED\u8D39\u3001\u4F30\u503C",
|
|
32226
|
+
when: ["\u6211\u7684\u8D26\u6237", "\u6301\u4ED3", "\u4F59\u989D", "\u4FDD\u8BC1\u91D1", "\u6760\u6746\u500D\u6570", "\u8D44\u4EA7\u4F30\u503C", "\u624B\u7EED\u8D39\u7387", "\u8D26\u6237\u914D\u7F6E"],
|
|
32227
|
+
go_to: "okx_account_overview",
|
|
32228
|
+
also: [
|
|
32229
|
+
"okx_get_balance \u2014 \u5404\u5E01\u79CD\u4F59\u989D\u660E\u7EC6",
|
|
32230
|
+
"okx_get_positions \u2014 \u6301\u4ED3\u8BE6\u60C5\uFF08\u542B\u5E73\u4ED3\u4E0A\u4E0B\u6587 _actionContext\uFF09",
|
|
32231
|
+
"okx_get_account_config \u2014 \u8D26\u6237\u6A21\u5F0F/\u6301\u4ED3\u6A21\u5F0F",
|
|
32232
|
+
"okx_get_asset_valuation \u2014 \u603B\u8D44\u4EA7\u4F30\u503C",
|
|
32233
|
+
"okx_get_fee_rates \u2014 \u624B\u7EED\u8D39\u7387",
|
|
32234
|
+
"okx_get_leverage_info \u2014 \u5F53\u524D\u6760\u6746\u500D\u6570",
|
|
32235
|
+
"okx_get_max_size \u2014 \u6700\u5927\u53EF\u5F00\u6570\u91CF",
|
|
32236
|
+
"okx_set_leverage \u2014 \u8C03\u6574\u6760\u6746\uFF08WRITE\uFF0C\u9700\u786E\u8BA4\uFF09"
|
|
32237
|
+
],
|
|
32238
|
+
risk: "READ"
|
|
32239
|
+
},
|
|
32240
|
+
{
|
|
32241
|
+
domain: "\u884C\u60C5\u770B\u76D8",
|
|
32242
|
+
what: "\u67E5\u770B\u4EA7\u54C1\u4EF7\u683C\u3001K\u7EBF\u3001\u6DF1\u5EA6\u3001\u6210\u4EA4\u8BB0\u5F55",
|
|
32243
|
+
when: ["BTC\u4EF7\u683C", "ETH\u884C\u60C5", "K\u7EBF", "\u6DA8\u8DCC", "\u6DF1\u5EA6", "\u76D8\u53E3", "\u6210\u4EA4\u8BB0\u5F55", "\u8D70\u52BF"],
|
|
32244
|
+
go_to: "okx_quick_market",
|
|
32245
|
+
also: [
|
|
32246
|
+
"okx_get_ticker \u2014 \u5355\u4E2A\u4EA7\u54C1\u5B9E\u65F6\u884C\u60C5",
|
|
32247
|
+
"okx_get_tickers \u2014 \u67D0\u7C7B\u578B\u5168\u90E8\u4EA7\u54C1\u884C\u60C5",
|
|
32248
|
+
"okx_get_orderbook \u2014 \u5B8C\u6574\u6DF1\u5EA6/\u76D8\u53E3",
|
|
32249
|
+
"okx_get_candles \u2014 K\u7EBF\u6570\u636E",
|
|
32250
|
+
"okx_get_trades \u2014 \u6700\u65B0\u6210\u4EA4\u8BB0\u5F55",
|
|
32251
|
+
"okx_get_history_candles \u2014 \u5386\u53F2K\u7EBF",
|
|
32252
|
+
"okx_get_index_candles \u2014 \u6307\u6570K\u7EBF",
|
|
32253
|
+
"okx_get_mark_price_candles \u2014 \u6807\u8BB0\u4EF7K\u7EBF"
|
|
32254
|
+
],
|
|
32255
|
+
risk: "READ"
|
|
32256
|
+
},
|
|
32257
|
+
{
|
|
32258
|
+
domain: "\u4E0B\u5355\u4EA4\u6613",
|
|
32259
|
+
what: "\u4E0B\u5355\u3001\u64A4\u5355\u3001\u6539\u5355\u3001\u5E73\u4ED3",
|
|
32260
|
+
when: ["\u4E70\u5165", "\u5356\u51FA", "\u4E0B\u5355", "\u5F00\u4ED3", "\u5E73\u4ED3", "\u64A4\u5355", "\u6539\u5355", "\u6302\u5355"],
|
|
32261
|
+
go_to: "agent_quick_trade",
|
|
32262
|
+
also: [
|
|
32263
|
+
"okx_preflight_check \u2014 \u4E0B\u5355\u524D\u9884\u68C0\uFF08\u6570\u91CF/\u9650\u4EF7/\u5408\u7EA6\u6362\u7B97\uFF09",
|
|
32264
|
+
"agent_simulate_order \u2014 \u6A21\u62DF\u4E0B\u5355\uFF08\u4E0D\u4EA7\u751F\u771F\u5B9E\u8BA2\u5355\uFF09",
|
|
32265
|
+
"okx_place_order \u2014 \u6807\u51C6\u4E0B\u5355\uFF08WRITE\uFF0C\u9700\u786E\u8BA4\uFF09",
|
|
32266
|
+
"okx_cancel_order \u2014 \u64A4\u5355\uFF08WRITE\uFF09",
|
|
32267
|
+
"okx_amend_order \u2014 \u6539\u5355\uFF08WRITE\uFF09",
|
|
32268
|
+
"okx_close_position \u2014 \u5E73\u4ED3\uFF08WRITE\uFF0C\u9700\u786E\u8BA4\uFF09",
|
|
32269
|
+
"okx_get_order \u2014 \u67E5\u8BE2\u8BA2\u5355\u72B6\u6001",
|
|
32270
|
+
"okx_get_orders_pending \u2014 \u5F53\u524D\u6302\u5355",
|
|
32271
|
+
"okx_get_orders_history \u2014 \u5386\u53F2\u8BA2\u5355",
|
|
32272
|
+
"okx_batch_orders \u2014 \u6279\u91CF\u4E0B\u5355\uFF08WRITE\uFF09",
|
|
32273
|
+
"okx_batch_cancel_orders \u2014 \u6279\u91CF\u64A4\u5355\uFF08WRITE\uFF09",
|
|
32274
|
+
"okx_amend_batch_orders \u2014 \u6279\u91CF\u6539\u5355\uFF08WRITE\uFF09"
|
|
32275
|
+
],
|
|
32276
|
+
risk: "WRITE"
|
|
32277
|
+
},
|
|
32278
|
+
{
|
|
32279
|
+
domain: "\u98CE\u9669\u98CE\u63A7",
|
|
32280
|
+
what: "\u6301\u4ED3\u98CE\u9669\u8BC4\u4F30\u3001\u5F3A\u5E73\u9884\u8B66\u3001\u4FDD\u8BC1\u91D1\u7387",
|
|
32281
|
+
when: ["\u98CE\u9669", "\u7206\u4ED3", "\u5F3A\u5E73", "\u4FDD\u8BC1\u91D1\u7387", "\u5065\u5EB7\u5EA6", "\u98CE\u63A7", "\u4F1A\u4E0D\u4F1A\u7206"],
|
|
32282
|
+
go_to: "agent_risk_overview",
|
|
32283
|
+
also: [
|
|
32284
|
+
"okx_get_account_position_risk \u2014 \u8D26\u6237\u6301\u4ED3\u98CE\u9669\u8BE6\u60C5",
|
|
32285
|
+
"okx_get_risk_state \u2014 \u8D26\u6237\u98CE\u63A7\u72B6\u6001",
|
|
32286
|
+
"okx_get_positions \u2014 \u6301\u4ED3\u4E2D\u7684 mgnRatio/liqPx",
|
|
32287
|
+
"okx_get_margin_balance \u2014 \u4FDD\u8BC1\u91D1\u4F59\u989D",
|
|
32288
|
+
"agent_quick_trade \u2014 \u98CE\u63A7\u544A\u8B66\u540E\u5E73\u4ED3\uFF08WRITE\uFF09"
|
|
32289
|
+
],
|
|
32290
|
+
risk: "READ"
|
|
32291
|
+
},
|
|
32292
|
+
{
|
|
32293
|
+
domain: "\u5E02\u573A\u626B\u63CF",
|
|
32294
|
+
what: "\u53D1\u73B0\u5E02\u573A\u673A\u4F1A\u3001\u6DA8\u5E45\u699C\u3001\u8DCC\u5E45\u699C\u3001\u8D44\u91D1\u8D39\u7387\u5F02\u5E38",
|
|
32295
|
+
when: ["\u4ECA\u5929\u6709\u4EC0\u4E48\u673A\u4F1A", "\u6DA8\u5E45\u699C", "\u8DCC\u5E45\u699C", "\u4EC0\u4E48\u5728\u6DA8", "\u4EC0\u4E48\u5728\u8DCC", "\u5F02\u52A8", "\u626B\u63CF"],
|
|
32296
|
+
go_to: "agent_market_scan",
|
|
32297
|
+
also: [
|
|
32298
|
+
"okx_quick_market \u2014 \u6DF1\u5165\u770B\u67D0\u4E2A\u54C1\u79CD",
|
|
32299
|
+
"okx_get_funding_rate \u2014 \u6C38\u7EED\u5408\u7EA6\u8D44\u91D1\u8D39\u7387",
|
|
32300
|
+
"okx_get_tickers \u2014 \u5168\u5E02\u573A\u884C\u60C5"
|
|
32301
|
+
],
|
|
32302
|
+
risk: "READ"
|
|
32303
|
+
},
|
|
32304
|
+
{
|
|
32305
|
+
domain: "\u76C8\u4E8F\u590D\u76D8",
|
|
32306
|
+
what: "\u8BA1\u7B97\u5DF2\u5B9E\u73B0/\u672A\u5B9E\u73B0\u76C8\u4E8F\u3001\u4EA4\u6613\u7EE9\u6548",
|
|
32307
|
+
when: ["\u8D5A\u4E86\u591A\u5C11", "\u4E8F\u4E86\u591A\u5C11", "\u76C8\u4E8F", "\u7EE9\u6548", "\u590D\u76D8", "PnL", "\u6536\u76CA"],
|
|
32308
|
+
go_to: "agent_pnl_report",
|
|
32309
|
+
also: [
|
|
32310
|
+
"okx_get_positions \u2014 \u5F53\u524D\u6D6E\u52A8\u76C8\u4E8F",
|
|
32311
|
+
"okx_get_orders_history \u2014 \u5386\u53F2\u8BA2\u5355\u76C8\u4E8F",
|
|
32312
|
+
"okx_get_positions_history \u2014 \u5386\u53F2\u5E73\u4ED3\u76C8\u4E8F",
|
|
32313
|
+
"okx_get_fills \u2014 \u6210\u4EA4\u660E\u7EC6"
|
|
32314
|
+
],
|
|
32315
|
+
risk: "READ"
|
|
32316
|
+
},
|
|
32317
|
+
{
|
|
32318
|
+
domain: "\u8D44\u91D1\u7BA1\u7406",
|
|
32319
|
+
what: "\u5212\u8F6C\u3001\u63D0\u73B0\u3001\u5145\u503C\u3001\u5151\u6362",
|
|
32320
|
+
when: ["\u5212\u8F6C", "\u63D0\u73B0", "\u5145\u503C", "\u8F6C\u8D26", "\u5151\u6362", "\u95EA\u5151", "\u51FA\u5165\u91D1", "deposit", "withdraw"],
|
|
32321
|
+
go_to: "okx_get_balance",
|
|
32322
|
+
also: [
|
|
32323
|
+
"okx_transfer \u2014 \u8D44\u91D1\u5212\u8F6C\uFF08WRITE\uFF0C\u9700\u786E\u8BA4\uFF09",
|
|
32324
|
+
"okx_withdrawal \u2014 \u63D0\u73B0\uFF08WRITE\uFF0C\u9700\u786E\u8BA4\uFF09",
|
|
32325
|
+
"okx_get_deposit_address \u2014 \u83B7\u53D6\u5145\u503C\u5730\u5740",
|
|
32326
|
+
"okx_get_deposit_history \u2014 \u5145\u503C\u8BB0\u5F55",
|
|
32327
|
+
"okx_get_withdrawal_history \u2014 \u63D0\u73B0\u8BB0\u5F55",
|
|
32328
|
+
"okx_convert_trade \u2014 \u4E00\u952E\u5151\u6362\uFF08WRITE\uFF0C\u9700\u786E\u8BA4\uFF09",
|
|
32329
|
+
"okx_get_convert_currencies \u2014 \u53EF\u5151\u6362\u5E01\u79CD",
|
|
32330
|
+
"okx_get_currencies \u2014 \u94FE\u4E0A\u5E01\u79CD\u4FE1\u606F",
|
|
32331
|
+
"okx_get_funding_balance \u2014 \u8D44\u91D1\u8D26\u6237\u4F59\u989D"
|
|
32332
|
+
],
|
|
32333
|
+
risk: "FUND_TRANSFER"
|
|
32334
|
+
},
|
|
32335
|
+
{
|
|
32336
|
+
domain: "\u7B56\u7565\u4EA4\u6613",
|
|
32337
|
+
what: "\u7F51\u683C\u3001\u8DDF\u5355\u3001\u4FE1\u53F7\u3001\u7B56\u7565\u59D4\u6258\u3001\u4EF7\u5DEE\u3001RFQ",
|
|
32338
|
+
when: ["\u7F51\u683C", "\u8DDF\u5355", "\u4FE1\u53F7", "\u7B56\u7565", "\u5B9A\u6295", "\u4EF7\u5DEE", "\u5927\u5B97", "RFQ"],
|
|
32339
|
+
go_to: "okx_get_grid_ai_param",
|
|
32340
|
+
also: [
|
|
32341
|
+
"okx_create_grid_order \u2014 \u521B\u5EFA\u7F51\u683C\uFF08WRITE\uFF0C\u9700\u786E\u8BA4\uFF09",
|
|
32342
|
+
"okx_stop_grid_order \u2014 \u505C\u6B62\u7F51\u683C",
|
|
32343
|
+
"okx_get_grid_positions \u2014 \u7F51\u683C\u6301\u4ED3",
|
|
32344
|
+
"okx_create_recurring_plan \u2014 \u521B\u5EFA\u5B9A\u6295\u8BA1\u5212\uFF08WRITE\uFF09",
|
|
32345
|
+
"okx_copy_trader \u2014 \u5F00\u59CB\u8DDF\u5355\uFF08WRITE\uFF0C\u9700\u786E\u8BA4\uFF09",
|
|
32346
|
+
"okx_get_lead_trader_positions \u2014 \u4EA4\u6613\u5458\u6301\u4ED3",
|
|
32347
|
+
"okx_get_lead_trader_stats \u2014 \u4EA4\u6613\u5458\u7EDF\u8BA1",
|
|
32348
|
+
"okx_place_algo_order \u2014 \u7B56\u7565\u59D4\u6258\u4E0B\u5355\uFF08WRITE\uFF09",
|
|
32349
|
+
"okx_get_algo_orders \u2014 \u7B56\u7565\u59D4\u6258\u5217\u8868",
|
|
32350
|
+
"okx_create_rfq \u2014 \u521B\u5EFA\u5927\u5B97\u8BE2\u4EF7\uFF08WRITE\uFF09"
|
|
32351
|
+
],
|
|
32352
|
+
risk: "WRITE"
|
|
32353
|
+
},
|
|
32354
|
+
{
|
|
32355
|
+
domain: "\u9884\u6D4B\u5E02\u573A",
|
|
32356
|
+
what: "\u4E8B\u4EF6\u5408\u7EA6\u3001\u9884\u6D4B\u5E02\u573A\u4EA4\u6613",
|
|
32357
|
+
when: ["\u9884\u6D4B\u5E02\u573A", "\u4E8B\u4EF6\u5408\u7EA6", "outcomes", "predictions", "\u5BF9\u8D4C"],
|
|
32358
|
+
go_to: "okx_event_instruments",
|
|
32359
|
+
also: [
|
|
32360
|
+
"okx_event_place_order \u2014 \u4E8B\u4EF6\u5408\u7EA6\u4E0B\u5355\uFF08WRITE\uFF09",
|
|
32361
|
+
"okx_event_fills \u2014 \u4E8B\u4EF6\u5408\u7EA6\u6210\u4EA4",
|
|
32362
|
+
"okx_predictions_positions \u2014 \u9884\u6D4B\u5E02\u573A\u6301\u4ED3",
|
|
32363
|
+
"okx_predictions_order_list \u2014 \u9884\u6D4B\u5E02\u573A\u8BA2\u5355",
|
|
32364
|
+
"okx_predictions_redeem \u2014 \u9884\u6D4B\u5E02\u573A\u8D4E\u56DE\uFF08WRITE\uFF09"
|
|
32365
|
+
],
|
|
32366
|
+
risk: "READ"
|
|
32367
|
+
},
|
|
32368
|
+
{
|
|
32369
|
+
domain: "\u6280\u672F\u6307\u6807",
|
|
32370
|
+
what: "\u6280\u672F\u5206\u6790\u6307\u6807\u8BA1\u7B97\uFF1ARSI\u3001MACD\u3001\u5E03\u6797\u5E26\u3001ADX\u3001Supertrend \u7B49 17 \u79CD\u6307\u6807",
|
|
32371
|
+
when: ["RSI", "MACD", "\u5E03\u6797\u5E26", "KDJ", "ADX", "\u8D85\u4E70", "\u8D85\u5356", "\u91D1\u53C9", "\u6B7B\u53C9", "\u6280\u672F\u6307\u6807", "\u6307\u6807\u5206\u6790"],
|
|
32372
|
+
go_to: "okx_indicator",
|
|
32373
|
+
also: [
|
|
32374
|
+
"okx_indicator \u2014 \u5355\u6307\u6807\u8BA1\u7B97+\u4FE1\u53F7\u89E3\u8BFB",
|
|
32375
|
+
"okx_indicator_batch \u2014 \u591A\u6307\u6807\u6279\u91CF+\u7EFC\u5408\u4FE1\u53F7",
|
|
32376
|
+
"okx_get_candles \u2014 \u539F\u59CBK\u7EBF\u6570\u636E"
|
|
32377
|
+
],
|
|
32378
|
+
risk: "READ"
|
|
32379
|
+
},
|
|
32380
|
+
{
|
|
32381
|
+
domain: "\u806A\u660E\u94B1",
|
|
32382
|
+
what: "\u4EA4\u6613\u5458\u6392\u884C\u699C\u3001\u806A\u660E\u94B1\u6D41\u5411\u3001\u5E02\u573A\u60C5\u7EEA\u5206\u6790",
|
|
32383
|
+
when: ["\u4EA4\u6613\u5458", "\u6392\u884C\u699C", "\u806A\u660E\u94B1", "\u8DDF\u8C01\u8D5A\u94B1", "\u60C5\u7EEA", "\u591A\u7A7A\u6BD4", "\u6050\u614C", "smart money"],
|
|
32384
|
+
go_to: "okx_smart_leaderboard",
|
|
32385
|
+
also: [
|
|
32386
|
+
"okx_smart_leaderboard \u2014 \u4EA4\u6613\u5458\u6392\u884C\u699C",
|
|
32387
|
+
"okx_smart_trader_detail \u2014 \u5355\u4EA4\u6613\u5458\u6DF1\u5EA6\u5206\u6790",
|
|
32388
|
+
"okx_smart_sentiment \u2014 \u5E02\u573A\u60C5\u7EEA\u4EEA\u8868\u76D8",
|
|
32389
|
+
"okx_get_lead_trader_positions \u2014 \u4EA4\u6613\u5458\u5F53\u524D\u6301\u4ED3",
|
|
32390
|
+
"okx_get_lead_trader_stats \u2014 \u4EA4\u6613\u5458\u5386\u53F2\u7EDF\u8BA1"
|
|
32391
|
+
],
|
|
32392
|
+
risk: "READ"
|
|
32393
|
+
},
|
|
32394
|
+
{
|
|
32395
|
+
domain: "WebSocket \u5B9E\u65F6",
|
|
32396
|
+
what: "\u5B9E\u65F6\u884C\u60C5\u63A8\u9001\u3001\u6210\u4EA4\u63A8\u9001",
|
|
32397
|
+
when: ["\u5B9E\u65F6", "\u8BA2\u9605", "\u63A8\u9001", "websocket", "ws", "\u76D1\u542C"],
|
|
32398
|
+
go_to: "okx_ws_subscribe",
|
|
32399
|
+
also: [
|
|
32400
|
+
"okx_ws_events \u2014 \u83B7\u53D6\u63A8\u9001\u4E8B\u4EF6",
|
|
32401
|
+
"okx_ws_status \u2014 \u8BA2\u9605\u72B6\u6001",
|
|
32402
|
+
"okx_ws_close \u2014 \u5173\u95ED\u8BA2\u9605"
|
|
32403
|
+
],
|
|
32404
|
+
risk: "READ"
|
|
32405
|
+
},
|
|
32406
|
+
{
|
|
32407
|
+
domain: "\u6A21\u62DF\u4F30\u7B97",
|
|
32408
|
+
what: "\u4E0D\u4EA7\u751F\u771F\u5B9E\u8BA2\u5355\uFF0C\u9884\u4F30\u6210\u4EA4\u4EF7\u3001\u6ED1\u70B9\u3001\u624B\u7EED\u8D39",
|
|
32409
|
+
when: ["\u5982\u679C\u4E70\u5165", "\u5982\u679C\u5356\u51FA", "\u6A21\u62DF", "\u9884\u4F30", "\u6C99\u76D2", "\u8BD5\u7B97", "\u4F1A\u600E\u6837"],
|
|
32410
|
+
go_to: "agent_simulate_order",
|
|
32411
|
+
also: [
|
|
32412
|
+
"agent_quick_trade \u2014 \u786E\u8BA4\u540E\u771F\u5B9E\u4E0B\u5355\uFF08WRITE\uFF09",
|
|
32413
|
+
"okx_preflight_check \u2014 \u4E0B\u5355\u524D\u53C2\u6570\u6821\u9A8C",
|
|
32414
|
+
"okx_position_builder \u2014 \u7EC4\u5408\u4FDD\u8BC1\u91D1\u8BD5\u7B97"
|
|
32415
|
+
],
|
|
32416
|
+
risk: "READ"
|
|
32417
|
+
},
|
|
32418
|
+
{
|
|
32419
|
+
domain: "\u7CFB\u7EDF\u5DE5\u5177",
|
|
32420
|
+
what: "\u504F\u597D\u8BBE\u7F6E\u3001\u53CD\u9988\u7559\u8A00\u3001Agent\u96C6\u7FA4\u7BA1\u7406",
|
|
32421
|
+
when: ["\u504F\u597D", "\u8BBE\u7F6E\u9ED8\u8BA4", "\u8BB0\u4F4F", "\u53CD\u9988", "\u5EFA\u8BAE", "Agent Hub", "\u96C6\u7FA4"],
|
|
32422
|
+
go_to: "agent_get_preference",
|
|
32423
|
+
also: [
|
|
32424
|
+
"agent_set_preference \u2014 \u4FDD\u5B58\u504F\u597D",
|
|
32425
|
+
"okx_agent_feedback \u2014 \u63D0\u4EA4\u4F7F\u7528\u53CD\u9988",
|
|
32426
|
+
"agent_hub_status \u2014 Agent \u96C6\u7FA4\u72B6\u6001",
|
|
32427
|
+
"agent_hub_dispatch \u2014 \u6D3E\u53D1\u4EFB\u52A1",
|
|
32428
|
+
"agent_room_send \u2014 \u623F\u95F4\u6D88\u606F",
|
|
32429
|
+
"xlayer_subscribe \u2014 X Layer \u94FE\u4E0A\u4E8B\u4EF6",
|
|
32430
|
+
"xlayer_call \u2014 X Layer \u5408\u7EA6\u8C03\u7528\uFF08WRITE\uFF09"
|
|
32431
|
+
],
|
|
32432
|
+
risk: "READ"
|
|
32433
|
+
}
|
|
32434
|
+
],
|
|
32435
|
+
_tips: [
|
|
32436
|
+
"Agent \u6700\u4F73\u5B9E\u8DF5\uFF1A\u6BCF\u4E2A\u65B0\u4F1A\u8BDD\u5148\u8C03 agent_get_preference \u6062\u590D\u7528\u6237\u504F\u597D",
|
|
32437
|
+
"\u9700\u8981 API Key \u7684\u5DE5\u5177\uFF08\u8D26\u6237/\u4EA4\u6613\u7C7B\uFF09\u9700\u7528\u6237\u5148\u914D\u7F6E OKX_API_KEY / OKX_SECRET_KEY / OKX_PASSPHRASE \u73AF\u5883\u53D8\u91CF",
|
|
32438
|
+
"WRITE \u7EA7\u522B\u5DE5\u5177\u4F1A\u4FEE\u6539\u7528\u6237\u8D26\u6237\uFF0C\u8C03\u7528\u524D Agent \u5FC5\u987B\u5411\u7528\u6237\u786E\u8BA4",
|
|
32439
|
+
"\u6DF1\u5EA6\u8C03\u7814\u67D0\u4E2A\u57DF\u65F6\u8C03 agent_catalog_detail { domain } \u83B7\u53D6\u8BE5\u57DF\u5168\u90E8\u5DE5\u5177\u8BE6\u60C5",
|
|
32440
|
+
"\u6280\u672F\u6307\u6807\u7528 okx_indicator \u5355\u4E2A\u8BA1\u7B97\u6216 okx_indicator_batch \u6279\u91CF\uFF0C\u652F\u6301 RSI/MACD/\u5E03\u6797\u5E26\u7B49 17 \u79CD",
|
|
32441
|
+
"\u806A\u660E\u94B1\u5206\u6790\u7528 okx_smart_leaderboard \u627E\u9876\u5C16\u4EA4\u6613\u5458 \u2192 okx_smart_sentiment \u770B\u5E02\u573A\u60C5\u7EEA"
|
|
32442
|
+
]
|
|
32443
|
+
};
|
|
32444
|
+
server.tool(
|
|
32445
|
+
"agent_catalog",
|
|
32446
|
+
"CAT:[\u7CFB\u7EDF] | ## \u529F\u80FD\uFF1A\u5168\u5C40\u5DE5\u5177\u5BFC\u822A\u2014\u2014Agent \u9996\u6B21\u8FDE\u63A5 hvip MCP \u540E\u7B2C\u4E00\u4E2A\u5E94\u8C03\u7528\u7684\u5DE5\u5177\u3002\u8FD4\u56DE\u6309\u7528\u6237\u610F\u56FE\u5206\u7EC4\u7684\u5DE5\u5177\u5730\u56FE\n## \u573A\u666F\uFF1AAgent \u9996\u6B21\u8FDE\u63A5\u3001\u4E0D\u786E\u5B9A\u8BE5\u7528\u4EC0\u4E48\u5DE5\u5177\u3001\u60F3\u4E86\u89E3 hvip \u80FD\u505A\u4EC0\u4E48\u3002\u770B\u5B8C\u76EE\u5F55\u540E Agent \u6309\u57DF\u76F4\u8FBE\u76EE\u6807\u5DE5\u5177\uFF0C\u65E0\u9700\u9605\u8BFB\u5168\u90E8 350+ \u5DE5\u5177\u63CF\u8FF0\n## \u5173\u952E\u8BCD\uFF1A\u5BFC\u822A, catalog, \u76EE\u5F55, \u5730\u56FE, \u5165\u53E3, \u9996\u6B21\u8FDE\u63A5, \u5DE5\u5177\u53D1\u73B0, \u7D22\u5F15, \u8DEF\u7531\n## \u53C2\u6570\uFF1A\u65E0\n## \u9274\u6743\uFF1APUBLIC \u2014 \u7EAF\u7D22\u5F15\uFF0C\u4E0D\u67E5\u4EFB\u4F55 API\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~5KB \u2014 12 \u4E2A\u57DF\u7684\u7ED3\u6784\u5316\u7D22\u5F15\n## \u5173\u8054\uFF1A\u672C\u5DE5\u5177\u770B\u5168\u5C40 \u2192 agent_catalog_detail { domain } \u770B\u57DF\u8BE6\u60C5 \u2192 \u76F4\u63A5\u8C03\u7528\u76EE\u6807\u5DE5\u5177",
|
|
32447
|
+
{},
|
|
32448
|
+
async () => {
|
|
32449
|
+
try {
|
|
32450
|
+
return toResult({
|
|
32451
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
32452
|
+
...CATALOG
|
|
32453
|
+
});
|
|
32454
|
+
} catch (e) {
|
|
32455
|
+
return toError(e);
|
|
32456
|
+
}
|
|
32457
|
+
}
|
|
32458
|
+
);
|
|
32459
|
+
const DOMAIN_DETAILS = {
|
|
32460
|
+
"\u8D26\u6237\u8D44\u4EA7": {
|
|
32461
|
+
workflow: "okx_account_overview\uFF08\u5168\u666F\uFF09\u2192 \u67E5\u770B\u5177\u4F53\u9879 \u2192 okx_get_balance / okx_get_positions \u7EC6\u5316",
|
|
32462
|
+
tools: [
|
|
32463
|
+
{ name: "okx_account_overview", auth: "API Key", params: "\u65E0", what: "\u8D26\u6237\u5168\u666F\uFF1A\u4F59\u989D+\u6301\u4ED3+\u914D\u7F6E+\u4F30\u503C \u56DB\u5408\u4E00\u4E00\u952E\u67E5\u8BE2" },
|
|
32464
|
+
{ name: "okx_get_balance", auth: "API Key", params: "ccy? (\u5E01\u79CD\uFF0C\u4E0D\u586B\u5168\u90E8)", what: "\u4EA4\u6613\u8D26\u6237\u5404\u5E01\u79CD\u4F59\u989D" },
|
|
32465
|
+
{ name: "okx_get_positions", auth: "API Key", params: "instType? (\u4E0D\u586B\u5168\u90E8)", what: "\u6301\u4ED3\u8BE6\u60C5\uFF0C\u542B _actionContext \u53EF\u76F4\u63A5\u7528\u4E8E\u5E73\u4ED3" },
|
|
32466
|
+
{ name: "okx_get_account_config", auth: "API Key", params: "\u65E0", what: "\u8D26\u6237\u6A21\u5F0F/\u6301\u4ED3\u6A21\u5F0F/UID" },
|
|
32467
|
+
{ name: "okx_get_asset_valuation", auth: "API Key", params: "ccy? (\u8BA1\u4EF7\u5E01\u79CD)", what: "\u603B\u8D44\u4EA7\u4F30\u503C" },
|
|
32468
|
+
{ name: "okx_get_fee_rates", auth: "API Key", params: "instType?, instId?", what: "\u624B\u7EED\u8D39\u7387" },
|
|
32469
|
+
{ name: "okx_get_leverage_info", auth: "API Key", params: "instId, mgnMode", what: "\u5F53\u524D\u6760\u6746\u500D\u6570" },
|
|
32470
|
+
{ name: "okx_get_max_size", auth: "API Key", params: "instId, tdMode", what: "\u6700\u5927\u53EF\u5F00\u4ED3\u6570\u91CF" },
|
|
32471
|
+
{ name: "okx_set_leverage", auth: "API Key (\u4EA4\u6613)", params: "instId, lever, mgnMode", what: "\u8C03\u6574\u6760\u6746 \u2014 WRITE\uFF0C\u9700\u786E\u8BA4" },
|
|
32472
|
+
{ name: "okx_get_max_loan", auth: "API Key", params: "instId, mgnMode", what: "\u6700\u5927\u53EF\u501F\u6570\u91CF" },
|
|
32473
|
+
{ name: "okx_get_margin_balance", auth: "API Key", params: "instId, mgnMode", what: "\u4FDD\u8BC1\u91D1\u4F59\u989D\u8BE6\u60C5" },
|
|
32474
|
+
{ name: "okx_set_position_mode", auth: "API Key (\u4EA4\u6613)", params: "posMode", what: "\u5207\u6362\u6301\u4ED3\u6A21\u5F0F \u2014 ADMIN\uFF0C\u9700\u786E\u8BA4" },
|
|
32475
|
+
{ name: "okx_get_account_bills", auth: "API Key", params: "instType?, ccy?, limit?", what: "\u8D26\u6237\u8D44\u91D1\u6D41\u6C34" },
|
|
32476
|
+
{ name: "okx_get_interest_accrued", auth: "API Key", params: "instId?, ccy?", what: "\u501F\u5E01\u5229\u606F\u7D2F\u8BA1" },
|
|
32477
|
+
{ name: "okx_get_interest_rates", auth: "API Key", params: "ccy?", what: "\u5404\u5E01\u79CD\u501F\u5E01\u5229\u7387" },
|
|
32478
|
+
{ name: "okx_get_interest_limits", auth: "API Key", params: "\u65E0", what: "\u5229\u606F\u9650\u989D" },
|
|
32479
|
+
{ name: "okx_get_max_withdrawal", auth: "API Key", params: "ccy?", what: "\u6700\u5927\u53EF\u63D0\u73B0\u6570\u91CF" },
|
|
32480
|
+
{ name: "okx_get_account_position_risk", auth: "API Key", params: "\u65E0", what: "\u6301\u4ED3\u98CE\u9669\u8BC4\u4F30" },
|
|
32481
|
+
{ name: "okx_get_risk_state", auth: "API Key", params: "\u65E0", what: "\u8D26\u6237\u98CE\u63A7\u72B6\u6001" },
|
|
32482
|
+
{ name: "okx_get_account_greeks", auth: "API Key", params: "instType?, instFamily?", what: "\u671F\u6743 Greeks \u98CE\u9669\u53C2\u6570" },
|
|
32483
|
+
{ name: "okx_get_trade_fee", auth: "API Key", params: "instType?, instId?", what: "\u6309\u4EA7\u54C1\u7EF4\u5EA6\u67E5\u8BE2\u624B\u7EED\u8D39" },
|
|
32484
|
+
{ name: "okx_get_convert_currencies", auth: "API Key", params: "\u65E0", what: "\u652F\u6301\u4E00\u952E\u5151\u6362\u7684\u5E01\u79CD\u5217\u8868" },
|
|
32485
|
+
{ name: "okx_convert_trade", auth: "API Key (\u4EA4\u6613)", params: "fromCcy, toCcy, sz", what: "\u6267\u884C\u8D44\u4EA7\u5151\u6362 \u2014 FUND_TRANSFER\uFF0C\u9700\u786E\u8BA4" },
|
|
32486
|
+
{ name: "okx_get_bills", auth: "API Key", params: "instType?, ccy?", what: "\u8D26\u6237\u8D26\u5355\u6D41\u6C34" },
|
|
32487
|
+
{ name: "okx_get_positions_history", auth: "API Key", params: "instType?, instId?", what: "\u5386\u53F2\u6301\u4ED3\uFF08\u5DF2\u5E73\u4ED3\uFF09" },
|
|
32488
|
+
{ name: "okx_get_account_bills_archive", auth: "API Key", params: "\u65E0", what: "\u5F52\u6863\u8D26\u5355\uFF083\u4E2A\u6708\u524D\uFF09" },
|
|
32489
|
+
{ name: "okx_borrow_repay", auth: "API Key (\u4EA4\u6613)", params: "ccy, side(borrow|repay), amt", what: "\u501F\u5E01/\u8FD8\u6B3E \u2014 FUND_TRANSFER\uFF0C\u9700\u786E\u8BA4" },
|
|
32490
|
+
{ name: "okx_get_borrow_repay_history", auth: "API Key", params: "\u65E0", what: "\u501F\u8D37\u5386\u53F2\u8BB0\u5F55" },
|
|
32491
|
+
{ name: "okx_activate_option", auth: "API Key (\u4EA4\u6613)", params: "\u65E0", what: "\u6FC0\u6D3B\u671F\u6743\u4EA4\u6613 \u2014 ADMIN\uFF0C\u9700\u786E\u8BA4" },
|
|
32492
|
+
{ name: "okx_set_account_mode", auth: "API Key (\u4EA4\u6613)", params: "acctLv(1|2|3|4)", what: "\u8BBE\u7F6E\u8D26\u6237\u5C42\u7EA7 \u2014 ADMIN\uFF0C\u9700\u786E\u8BA4" }
|
|
32493
|
+
]
|
|
32494
|
+
},
|
|
32495
|
+
"\u884C\u60C5\u770B\u76D8": {
|
|
32496
|
+
workflow: "okx_quick_market\uFF08\u901F\u89C8\uFF09\u2192 \u9700\u8981K\u7EBF\u65F6\u8C03 okx_get_candles \u2192 \u9700\u8981\u5168\u6DF1\u5EA6\u65F6\u8C03 okx_get_orderbook",
|
|
32497
|
+
tools: [
|
|
32498
|
+
{ name: "okx_quick_market", auth: "\u516C\u5F00", params: "instId", what: "\u884C\u60C5+5\u6863\u6DF1\u5EA6+\u8D44\u91D1\u8D39\u7387 \u4E09\u5408\u4E00\u901F\u89C8" },
|
|
32499
|
+
{ name: "okx_get_ticker", auth: "\u516C\u5F00", params: "instId", what: "\u5355\u4E2A\u4EA7\u54C1\u6700\u65B0\u884C\u60C5" },
|
|
32500
|
+
{ name: "okx_get_tickers", auth: "\u516C\u5F00", params: "instType", what: "\u67D0\u7C7B\u578B\u5168\u90E8\u4EA7\u54C1\u884C\u60C5" },
|
|
32501
|
+
{ name: "okx_get_orderbook", auth: "\u516C\u5F00", params: "instId, sz?", what: "\u8BA2\u5355\u7C3F\u6DF1\u5EA6\uFF08\u9ED8\u8BA41\u6863\uFF0C\u6700\u5927400\u6863\uFF09" },
|
|
32502
|
+
{ name: "okx_get_books_full", auth: "\u516C\u5F00", params: "instId", what: "\u5168\u91CF\u8BA2\u5355\u7C3F" },
|
|
32503
|
+
{ name: "okx_get_candles", auth: "\u516C\u5F00", params: "instId, bar, limit?", what: "K\u7EBF\u6570\u636E" },
|
|
32504
|
+
{ name: "okx_get_history_candles", auth: "\u516C\u5F00", params: "instId, bar, after?", what: "\u5386\u53F2K\u7EBF\uFF08\u66F4\u65E9\u7684\uFF09" },
|
|
32505
|
+
{ name: "okx_get_index_candles", auth: "\u516C\u5F00", params: "instId, bar", what: "\u6307\u6570K\u7EBF" },
|
|
32506
|
+
{ name: "okx_get_mark_price_candles", auth: "\u516C\u5F00", params: "instId, bar", what: "\u6807\u8BB0\u4EF7K\u7EBF" },
|
|
32507
|
+
{ name: "okx_get_trades", auth: "\u516C\u5F00", params: "instId, limit?", what: "\u6700\u65B0\u6210\u4EA4\u8BB0\u5F55" },
|
|
32508
|
+
{ name: "okx_get_history_trades", auth: "\u516C\u5F00", params: "instId, after?", what: "\u5386\u53F2\u6210\u4EA4\u8BB0\u5F55" },
|
|
32509
|
+
{ name: "okx_get_index_tickers", auth: "\u516C\u5F00", params: "quoteCcy?", what: "\u6307\u6570\u884C\u60C5" },
|
|
32510
|
+
{ name: "okx_get_block_tickers", auth: "\u516C\u5F00", params: "instType", what: "\u6279\u91CF\u4EA7\u54C1\u884C\u60C5\uFF08Tickers\uFF09" },
|
|
32511
|
+
{ name: "okx_get_mark_price", auth: "\u516C\u5F00", params: "instType?, instId?", what: "\u6807\u8BB0\u4EF7\u683C" },
|
|
32512
|
+
{ name: "okx_get_funding_rate", auth: "\u516C\u5F00", params: "instId", what: "\u6C38\u7EED\u5408\u7EA6\u5F53\u524D\u8D44\u91D1\u8D39\u7387" },
|
|
32513
|
+
{ name: "okx_get_funding_rate_history", auth: "\u516C\u5F00", params: "instId, before?, after?", what: "\u8D44\u91D1\u8D39\u7387\u5386\u53F2" }
|
|
32514
|
+
]
|
|
32515
|
+
},
|
|
32516
|
+
"\u4E0B\u5355\u4EA4\u6613": {
|
|
32517
|
+
workflow: "\u5148\u8C03 agent_simulate_order \u9884\u4F30 \u2192 \u518D\u8C03 okx_preflight_check \u6821\u9A8C \u2192 \u6700\u540E agent_quick_trade \u4E0B\u5355",
|
|
32518
|
+
tools: [
|
|
32519
|
+
{ name: "agent_quick_trade", auth: "API Key (\u4EA4\u6613)", params: "instId, side, sz, tdMode, px?, ordType?", what: "\u4E00\u952E\u4E0B\u5355\u5168\u6D41\u7A0B \u2014 WRITE\uFF0C\u9700\u786E\u8BA4" },
|
|
32520
|
+
{ name: "agent_simulate_order", auth: "API Key (\u53EA\u8BFB)", params: "instId, side, sz, tdMode, px?", what: "\u6A21\u62DF\u4E0B\u5355\uFF1A\u6ED1\u70B9/\u624B\u7EED\u8D39/\u6210\u672C\u9884\u4F30\uFF08\u65E0\u771F\u5B9E\u8BA2\u5355\uFF09" },
|
|
32521
|
+
{ name: "okx_preflight_check", auth: "API Key (\u53EA\u8BFB)", params: "instId, tdMode, sz, px?, side?, ordType?", what: "\u4E0B\u5355\u524D\u9884\u68C0\uFF1A\u6570\u91CF/\u9650\u4EF7/\u5408\u7EA6\u6362\u7B97" },
|
|
32522
|
+
{ name: "okx_place_order", auth: "API Key (\u4EA4\u6613)", params: "instId, tdMode, side, sz, ordType, px?", what: "\u6807\u51C6\u4E0B\u5355 \u2014 WRITE\uFF0C\u9700\u786E\u8BA4" },
|
|
32523
|
+
{ name: "okx_batch_orders", auth: "API Key (\u4EA4\u6613)", params: "orders[]", what: "\u6279\u91CF\u4E0B\u5355 \u2014 WRITE" },
|
|
32524
|
+
{ name: "okx_cancel_order", auth: "API Key (\u4EA4\u6613)", params: "instId, ordId", what: "\u64A4\u9500\u5355\u7B14\u8BA2\u5355 \u2014 WRITE" },
|
|
32525
|
+
{ name: "okx_batch_cancel_orders", auth: "API Key (\u4EA4\u6613)", params: "orders[]", what: "\u6279\u91CF\u64A4\u5355 \u2014 WRITE" },
|
|
32526
|
+
{ name: "okx_amend_order", auth: "API Key (\u4EA4\u6613)", params: "instId, ordId, newSz?, newPx?", what: "\u4FEE\u6539\u672A\u6210\u4EA4\u8BA2\u5355 \u2014 WRITE" },
|
|
32527
|
+
{ name: "okx_amend_batch_orders", auth: "API Key (\u4EA4\u6613)", params: "orders[]", what: "\u6279\u91CF\u6539\u5355 \u2014 WRITE" },
|
|
32528
|
+
{ name: "okx_close_position", auth: "API Key (\u4EA4\u6613)", params: "instId, posSide, mgnMode", what: "\u5E73\u4ED3\uFF08\u7528 _actionContext \u4E2D\u53C2\u6570\uFF09\u2014 WRITE\uFF0C\u9700\u786E\u8BA4" },
|
|
32529
|
+
{ name: "okx_get_order", auth: "API Key", params: "instId, ordId", what: "\u67E5\u8BE2\u5355\u7B14\u8BA2\u5355\u72B6\u6001" },
|
|
32530
|
+
{ name: "okx_get_orders_pending", auth: "API Key", params: "instType?, instId?", what: "\u5F53\u524D\u6302\u5355\u5217\u8868" },
|
|
32531
|
+
{ name: "okx_get_orders_history", auth: "API Key", params: "instType, limit?", what: "\u5386\u53F2\u8BA2\u5355\uFF08\u8FD13\u4E2A\u6708\uFF09" },
|
|
32532
|
+
{ name: "okx_get_fills", auth: "API Key", params: "instType?, instId?, ordId?", what: "\u6700\u8FD1\u6210\u4EA4\u660E\u7EC6" },
|
|
32533
|
+
{ name: "okx_get_fills_history", auth: "API Key", params: "instType?, instId?, limit?", what: "\u5386\u53F2\u6210\u4EA4\u660E\u7EC6" }
|
|
32534
|
+
]
|
|
32535
|
+
},
|
|
32536
|
+
"\u98CE\u9669\u98CE\u63A7": {
|
|
32537
|
+
workflow: "agent_risk_overview\uFF08\u5168\u666F\uFF09\u2192 \u53D1\u73B0\u98CE\u9669\u4ED3\u4F4D \u2192 agent_quick_trade \u5E73\u4ED3",
|
|
32538
|
+
tools: [
|
|
32539
|
+
{ name: "agent_risk_overview", auth: "API Key", params: "\u65E0", what: "\u5168\u4ED3\u98CE\u9669\u4EEA\u8868\u76D8\uFF1A\u98CE\u9669\u6392\u5E8F+\u5F3A\u5E73\u9884\u8B66+\u4FDD\u8BC1\u91D1\u7387" },
|
|
32540
|
+
{ name: "okx_get_account_position_risk", auth: "API Key", params: "\u65E0", what: "\u8D26\u6237\u6301\u4ED3\u98CE\u9669\u8BE6\u60C5" },
|
|
32541
|
+
{ name: "okx_get_risk_state", auth: "API Key", params: "\u65E0", what: "\u8D26\u6237\u98CE\u63A7\u72B6\u6001" },
|
|
32542
|
+
{ name: "okx_get_margin_balance", auth: "API Key", params: "instId, mgnMode", what: "\u67D0\u4EA7\u54C1\u7684\u4FDD\u8BC1\u91D1\u4F59\u989D" },
|
|
32543
|
+
{ name: "okx_get_positions", auth: "API Key", params: "instType?", what: "\u6301\u4ED3\u4E2D\u7684 liqPx/mgnRatio \u5B57\u6BB5\u53EF\u76F4\u63A5\u8BC4\u4F30\u98CE\u9669" },
|
|
32544
|
+
{ name: "okx_get_max_withdrawal", auth: "API Key", params: "ccy?", what: "\u6700\u5927\u53EF\u63D0\u73B0\u989D\u5EA6" }
|
|
32545
|
+
]
|
|
32546
|
+
},
|
|
32547
|
+
"\u5E02\u573A\u626B\u63CF": {
|
|
32548
|
+
workflow: "agent_market_scan\uFF08\u5F02\u52A8\uFF09\u2192 okx_quick_market\uFF08\u6DF1\u5165\uFF09\u2192 \u4E0B\u5355",
|
|
32549
|
+
tools: [
|
|
32550
|
+
{ name: "agent_market_scan", auth: "\u516C\u5F00", params: "instType?, topN?, sortBy?", what: "\u6DA8\u5E45\u699C/\u8DCC\u5E45\u699C/\u6210\u4EA4\u91CF/\u8D44\u91D1\u8D39\u7387\u5F02\u5E38\u4E00\u952E\u626B\u63CF" },
|
|
32551
|
+
{ name: "okx_get_tickers", auth: "\u516C\u5F00", params: "instType", what: "\u67D0\u7C7B\u578B\u5168\u90E8\u4EA7\u54C1\u884C\u60C5\uFF08\u53EF\u81EA\u884C\u6392\u5E8F\u8FC7\u6EE4\uFF09" },
|
|
32552
|
+
{ name: "okx_get_funding_rate", auth: "\u516C\u5F00", params: "instId", what: "\u5355\u4EA7\u54C1\u8D44\u91D1\u8D39\u7387" },
|
|
32553
|
+
{ name: "okx_get_funding_rate_history", auth: "\u516C\u5F00", params: "instId", what: "\u8D44\u91D1\u8D39\u7387\u5386\u53F2\u8D8B\u52BF" }
|
|
32554
|
+
]
|
|
32555
|
+
},
|
|
32556
|
+
"\u76C8\u4E8F\u590D\u76D8": {
|
|
32557
|
+
workflow: "agent_pnl_report\uFF08\u76C8\u4E8F\u62A5\u544A\uFF09\u2192 \u9700\u8981\u65F6\u67E5 okx_get_fills \u660E\u7EC6",
|
|
32558
|
+
tools: [
|
|
32559
|
+
{ name: "agent_pnl_report", auth: "API Key", params: "days?", what: "\u6D6E\u52A8\u76C8\u4E8F+\u5DF2\u5B9E\u73B0\u76C8\u4E8F \u53CC\u7EF4\u65E5\u62A5" },
|
|
32560
|
+
{ name: "okx_get_positions", auth: "API Key", params: "instType?", what: "\u5F53\u524D\u6301\u4ED3\u6D6E\u52A8\u76C8\u4E8F" },
|
|
32561
|
+
{ name: "okx_get_positions_history", auth: "API Key", params: "instType?, instId?", what: "\u5386\u53F2\u5E73\u4ED3\u76C8\u4E8F" },
|
|
32562
|
+
{ name: "okx_get_orders_history", auth: "API Key", params: "instType", what: "\u5386\u53F2\u8BA2\u5355\u76C8\u4E8F" },
|
|
32563
|
+
{ name: "okx_get_fills", auth: "API Key", params: "instType?, instId?", what: "\u9010\u7B14\u6210\u4EA4\u660E\u7EC6\uFF08\u53EF\u6309 pnl \u5B57\u6BB5\u6C42\u548C\uFF09" }
|
|
32564
|
+
]
|
|
32565
|
+
},
|
|
32566
|
+
"\u8D44\u91D1\u7BA1\u7406": {
|
|
32567
|
+
workflow: "\u5148\u770B\u4F59\u989D \u2192 \u518D\u51B3\u5B9A\u5212\u8F6C/\u63D0\u73B0/\u5145\u503C",
|
|
32568
|
+
tools: [
|
|
32569
|
+
{ name: "okx_get_balance", auth: "API Key", params: "ccy?", what: "\u4EA4\u6613\u8D26\u6237\u4F59\u989D" },
|
|
32570
|
+
{ name: "okx_get_funding_balance", auth: "API Key", params: "ccy?", what: "\u8D44\u91D1\u8D26\u6237\u4F59\u989D" },
|
|
32571
|
+
{ name: "okx_transfer", auth: "API Key (\u4EA4\u6613)", params: "ccy, amt, from, to", what: "\u8D44\u91D1\u5212\u8F6C \u2014 FUND_TRANSFER\uFF0C\u9700\u786E\u8BA4" },
|
|
32572
|
+
{ name: "okx_get_transfer_state", auth: "API Key", params: "transId?", what: "\u5212\u8F6C\u72B6\u6001\u67E5\u8BE2" },
|
|
32573
|
+
{ name: "okx_withdrawal", auth: "API Key (\u4EA4\u6613)", params: "ccy, amt, dest, toAddr", what: "\u63D0\u73B0 \u2014 FUND_TRANSFER\uFF0C\u9700\u786E\u8BA4" },
|
|
32574
|
+
{ name: "okx_get_deposit_address", auth: "API Key", params: "ccy", what: "\u83B7\u53D6\u5145\u503C\u5730\u5740" },
|
|
32575
|
+
{ name: "okx_get_deposit_history", auth: "API Key", params: "ccy?, limit?", what: "\u5145\u503C\u8BB0\u5F55" },
|
|
32576
|
+
{ name: "okx_get_withdrawal_history", auth: "API Key", params: "ccy?, limit?", what: "\u63D0\u73B0\u8BB0\u5F55" },
|
|
32577
|
+
{ name: "okx_get_currencies", auth: "API Key", params: "ccy?", what: "\u94FE\u4E0A\u5E01\u79CD\u4FE1\u606F" },
|
|
32578
|
+
{ name: "okx_convert_trade", auth: "API Key (\u4EA4\u6613)", params: "fromCcy, toCcy, sz", what: "\u4E00\u952E\u5151\u6362 \u2014 FUND_TRANSFER\uFF0C\u9700\u786E\u8BA4" },
|
|
32579
|
+
{ name: "okx_get_convert_currencies", auth: "API Key", params: "\u65E0", what: "\u53EF\u5151\u6362\u5E01\u79CD\u5217\u8868" },
|
|
32580
|
+
{ name: "okx_get_max_withdrawal", auth: "API Key", params: "ccy?", what: "\u6700\u5927\u53EF\u63D0\u73B0\u6570\u91CF" },
|
|
32581
|
+
{ name: "okx_get_non_tradable_assets", auth: "API Key", params: "ccy?", what: "\u4E0D\u53EF\u4EA4\u6613\u8D44\u4EA7" },
|
|
32582
|
+
{ name: "okx_get_exchange_list", auth: "API Key", params: "\u65E0", what: "\u4EA4\u6613\u6240\u5217\u8868" },
|
|
32583
|
+
{ name: "okx_get_deposit_withdraw_status", auth: "API Key", params: "\u65E0", what: "\u5145\u63D0\u72B6\u6001" }
|
|
32584
|
+
]
|
|
32585
|
+
},
|
|
32586
|
+
"\u7B56\u7565\u4EA4\u6613": {
|
|
32587
|
+
workflow: "\u7F51\u683C/\u8DDF\u5355/\u4FE1\u53F7/\u7B56\u7565\u59D4\u6258 \u5404\u81EA\u72EC\u7ACB\uFF0C\u6309\u9700\u8C03\u7528",
|
|
32588
|
+
tools: [
|
|
32589
|
+
{ name: "okx_get_grid_ai_param", auth: "API Key", params: "instType, algoOrdType", what: "\u7F51\u683CAI\u53C2\u6570\u63A8\u8350" },
|
|
32590
|
+
{ name: "okx_create_grid_order", auth: "API Key (\u4EA4\u6613)", params: "instId, algoOrdType, maxPx, minPx, gridNum, sz", what: "\u521B\u5EFA\u7F51\u683C \u2014 WRITE" },
|
|
32591
|
+
{ name: "okx_stop_grid_order", auth: "API Key (\u4EA4\u6613)", params: "algoId, instId, algoOrdType, stopType", what: "\u505C\u6B62\u7F51\u683C" },
|
|
32592
|
+
{ name: "okx_close_grid_position", auth: "API Key (\u4EA4\u6613)", params: "algoId, mktClose", what: "\u5E73\u4ED3\u7F51\u683C\u6240\u6709\u6301\u4ED3" },
|
|
32593
|
+
{ name: "okx_get_grid_positions", auth: "API Key (\u4EA4\u6613)", params: "algoOrdType, algoId?", what: "\u7F51\u683C\u6301\u4ED3" },
|
|
32594
|
+
{ name: "okx_get_grid_sub_orders", auth: "API Key", params: "algoId, algoOrdType, type", what: "\u7F51\u683C\u5B50\u8BA2\u5355" },
|
|
32595
|
+
{ name: "okx_get_grid_orders_pending", auth: "API Key", params: "algoOrdType, algoId?", what: "\u8FD0\u884C\u4E2D\u7684\u7F51\u683C" },
|
|
32596
|
+
{ name: "okx_get_grid_orders_history", auth: "API Key", params: "algoOrdType, algoId?", what: "\u5386\u53F2\u7F51\u683C" },
|
|
32597
|
+
{ name: "okx_create_recurring_plan", auth: "API Key (\u4EA4\u6613)", params: "instId, sz, period, recurringList", what: "\u5B9A\u6295\u8BA1\u5212 \u2014 WRITE" },
|
|
32598
|
+
{ name: "okx_stop_recurring_plan", auth: "API Key (\u4EA4\u6613)", params: "algoId", what: "\u505C\u6B62\u5B9A\u6295" },
|
|
32599
|
+
{ name: "okx_copy_trader", auth: "API Key (\u4EA4\u6613)", params: "uniqueCode, copyTotalAmt, instType", what: "\u5F00\u59CB\u8DDF\u5355 \u2014 WRITE\uFF0C\u9700\u786E\u8BA4" },
|
|
32600
|
+
{ name: "okx_get_copy_traders", auth: "API Key", params: "\u65E0", what: "\u6211\u5173\u6CE8\u7684\u4EA4\u6613\u5458" },
|
|
32601
|
+
{ name: "okx_get_public_lead_traders", auth: "\u516C\u5F00", params: "instType, sortType?", what: "\u516C\u5F00\u4EA4\u6613\u5458\u5217\u8868" },
|
|
32602
|
+
{ name: "okx_get_lead_trader_positions", auth: "API Key", params: "uniqueCode", what: "\u4EA4\u6613\u5458\u5F53\u524D\u6301\u4ED3" },
|
|
32603
|
+
{ name: "okx_get_lead_trader_stats", auth: "API Key", params: "uniqueCode", what: "\u4EA4\u6613\u5458\u4E1A\u7EE9\u7EDF\u8BA1" },
|
|
32604
|
+
{ name: "okx_place_algo_order", auth: "API Key (\u4EA4\u6613)", params: "instId, tdMode, side, ordType, sz, triggerPx", what: "\u7B56\u7565\u59D4\u6258\u4E0B\u5355 \u2014 WRITE" },
|
|
32605
|
+
{ name: "okx_get_algo_orders", auth: "API Key", params: "ordType?, algoId?", what: "\u7B56\u7565\u59D4\u6258\u5217\u8868" },
|
|
32606
|
+
{ name: "okx_cancel_algo_order", auth: "API Key (\u4EA4\u6613)", params: "algoId, instId", what: "\u64A4\u9500\u7B56\u7565\u59D4\u6258 \u2014 WRITE" }
|
|
32607
|
+
]
|
|
32608
|
+
},
|
|
32609
|
+
"\u9884\u6D4B\u5E02\u573A": {
|
|
32610
|
+
workflow: "okx_event_instruments \u770B\u5E02\u573A \u2192 okx_event_place_order \u4E0B\u5355",
|
|
32611
|
+
tools: [
|
|
32612
|
+
{ name: "okx_event_instruments", auth: "\u516C\u5F00", params: "eventType?", what: "\u4E8B\u4EF6\u5408\u7EA6\u4EA7\u54C1\u5217\u8868" },
|
|
32613
|
+
{ name: "okx_event_place_order", auth: "API Key (\u4EA4\u6613)", params: "instId, side, sz, ordType?", what: "\u4E8B\u4EF6\u5408\u7EA6\u4E0B\u5355 \u2014 WRITE" },
|
|
32614
|
+
{ name: "okx_event_cancel_order", auth: "API Key (\u4EA4\u6613)", params: "instId, ordId", what: "\u4E8B\u4EF6\u5408\u7EA6\u64A4\u5355 \u2014 WRITE" },
|
|
32615
|
+
{ name: "okx_event_amend_order", auth: "API Key (\u4EA4\u6613)", params: "instId, ordId, newSz?", what: "\u4E8B\u4EF6\u5408\u7EA6\u6539\u5355 \u2014 WRITE" },
|
|
32616
|
+
{ name: "okx_event_fills", auth: "API Key", params: "instId?", what: "\u4E8B\u4EF6\u5408\u7EA6\u6210\u4EA4\u8BB0\u5F55" },
|
|
32617
|
+
{ name: "okx_predictions_place_order", auth: "API Key (\u4EA4\u6613)", params: "marketId, side, price, size", what: "\u9884\u6D4B\u5E02\u573A\u4E0B\u5355 \u2014 WRITE" },
|
|
32618
|
+
{ name: "okx_predictions_positions", auth: "API Key", params: "marketId?", what: "\u9884\u6D4B\u5E02\u573A\u6301\u4ED3" },
|
|
32619
|
+
{ name: "okx_predictions_order_list", auth: "API Key", params: "marketId?, status?", what: "\u9884\u6D4B\u5E02\u573A\u8BA2\u5355\u5217\u8868" },
|
|
32620
|
+
{ name: "okx_predictions_redeem", auth: "API Key (\u4EA4\u6613)", params: "marketId, outcome", what: "\u9884\u6D4B\u5E02\u573A\u8D4E\u56DE \u2014 WRITE" },
|
|
32621
|
+
{ name: "okx_predictions_balance", auth: "API Key", params: "\u65E0", what: "\u9884\u6D4B\u5E02\u573A\u4F59\u989D" }
|
|
32622
|
+
]
|
|
32623
|
+
},
|
|
32624
|
+
"\u6280\u672F\u6307\u6807": {
|
|
32625
|
+
workflow: "okx_indicator \u5355\u6307\u6807\u8BA1\u7B97 \u2192 \u9700\u8981\u7EFC\u5408\u5224\u65AD\u65F6 okx_indicator_batch \u6279\u91CF\u8BA1\u7B97",
|
|
32626
|
+
tools: [
|
|
32627
|
+
{ name: "okx_indicator", auth: "\u516C\u5F00", params: "instId, indicator, period?, bar?", what: "\u5355\u6307\u6807\u8BA1\u7B97+Agent\u4FE1\u53F7\u89E3\u8BFB\uFF0817\u79CD\u6307\u6807\u542BRSI/MACD/BB/ATR/ADX\u7B49\uFF09" },
|
|
32628
|
+
{ name: "okx_indicator_batch", auth: "\u516C\u5F00", params: "instId, indicators(\u9017\u53F7\u5206\u9694), bar?", what: "\u591A\u6307\u6807\u6279\u91CF\u8BA1\u7B97+\u7EFC\u5408\u4FE1\u53F7\u5171\u8BC6\uFF08\u6700\u591A10\u4E2A\u6307\u6807\uFF09" }
|
|
32629
|
+
]
|
|
32630
|
+
},
|
|
32631
|
+
"\u806A\u660E\u94B1": {
|
|
32632
|
+
workflow: "okx_smart_leaderboard \u770B\u6392\u884C \u2192 okx_smart_trader_detail \u6DF1\u6316 \u2192 okx_smart_sentiment \u770B\u60C5\u7EEA",
|
|
32633
|
+
tools: [
|
|
32634
|
+
{ name: "okx_smart_leaderboard", auth: "\u516C\u5F00", params: "instType?, sortBy?, topN?", what: "\u4EA4\u6613\u5458\u6392\u884C\u699C\uFF08\u6309\u6536\u76CA\u7387/\u603B\u6536\u76CA/\u8DDF\u5355\u4EBA\u6570\u6392\u5E8F\uFF09" },
|
|
32635
|
+
{ name: "okx_smart_trader_detail", auth: "\u516C\u5F00", params: "uniqueCode, instType?", what: "\u5355\u4EA4\u6613\u5458\u5168\u666F\uFF1A\u6536\u76CA\u7387+\u80DC\u7387+\u56DE\u64A4+\u6301\u4ED3+PnL\u66F2\u7EBF" },
|
|
32636
|
+
{ name: "okx_smart_sentiment", auth: "\u516C\u5F00", params: "instFamily?", what: "\u5E02\u573A\u60C5\u7EEA\u4EEA\u8868\u76D8\uFF1A\u591A\u7A7A\u6BD4+PCR+\u8D44\u91D1\u8D39\u7387 \u2192 \u91CF\u5316\u8BC4\u5206(0-100)" }
|
|
32637
|
+
]
|
|
32638
|
+
},
|
|
32639
|
+
"WebSocket \u5B9E\u65F6": {
|
|
32640
|
+
workflow: "okx_ws_subscribe \u8BA2\u9605\u9891\u9053 \u2192 okx_ws_events \u62C9\u53D6\u4E8B\u4EF6",
|
|
32641
|
+
tools: [
|
|
32642
|
+
{ name: "okx_ws_subscribe", auth: "\u516C\u5F00", params: "channels[]", what: "\u8BA2\u9605\u5B9E\u65F6\u9891\u9053\uFF08tickers/trades/books/candles/fundingRate \u7B49\uFF09" },
|
|
32643
|
+
{ name: "okx_ws_events", auth: "\u516C\u5F00", params: "channel?", what: "\u6536\u53D6\u8BA2\u9605\u7684\u5B9E\u65F6\u63A8\u9001\u4E8B\u4EF6" },
|
|
32644
|
+
{ name: "okx_ws_status", auth: "\u516C\u5F00", params: "\u65E0", what: "\u5F53\u524D\u8BA2\u9605\u72B6\u6001" },
|
|
32645
|
+
{ name: "okx_ws_close", auth: "\u516C\u5F00", params: "channel?", what: "\u53D6\u6D88\u8BA2\u9605" }
|
|
32646
|
+
]
|
|
32647
|
+
},
|
|
32648
|
+
"\u6A21\u62DF\u4F30\u7B97": {
|
|
32649
|
+
workflow: "agent_simulate_order\uFF08\u9884\u4F30\uFF09\u2192 \u7528\u6237\u786E\u8BA4 \u2192 agent_quick_trade\uFF08\u771F\u5B9E\u4E0B\u5355\uFF09",
|
|
32650
|
+
tools: [
|
|
32651
|
+
{ name: "agent_simulate_order", auth: "API Key (\u53EA\u8BFB)", params: "instId, side, sz, tdMode, px?", what: "\u6A21\u62DF\u4E0B\u5355\uFF1A\u6210\u4EA4\u4EF7/\u6ED1\u70B9/\u624B\u7EED\u8D39/\u8D44\u91D1\u5360\u7528 \u5168\u9884\u4F30" },
|
|
32652
|
+
{ name: "okx_preflight_check", auth: "API Key (\u53EA\u8BFB)", params: "instId, tdMode, sz, px?, side?, ordType?", what: "\u4E0B\u5355\u9884\u68C0\uFF1A\u6700\u5927\u53EF\u5F00/\u9650\u4EF7/\u5408\u7EA6\u6362\u7B97" },
|
|
32653
|
+
{ name: "okx_position_builder", auth: "API Key (\u4EA4\u6613)", params: "body(JSON)", what: "\u7EC4\u5408\u4FDD\u8BC1\u91D1\u8BD5\u7B97 \u2014 WRITE" }
|
|
32654
|
+
]
|
|
32655
|
+
},
|
|
32656
|
+
"\u7CFB\u7EDF\u5DE5\u5177": {
|
|
32657
|
+
workflow: "\u6309\u9700\u8C03\u7528\uFF0C\u5404\u5DE5\u5177\u72EC\u7ACB",
|
|
32658
|
+
tools: [
|
|
32659
|
+
{ name: "agent_catalog", auth: "\u516C\u5F00", params: "\u65E0", what: "\u4F60\u6B63\u5728\u770B\u7684\u8FD9\u4E2A" },
|
|
32660
|
+
{ name: "agent_catalog_detail", auth: "\u516C\u5F00", params: "domain", what: "\u67E5\u770B\u67D0\u4E2A\u57DF\u7684\u8BE6\u7EC6\u5DE5\u5177\u6E05\u5355" },
|
|
32661
|
+
{ name: "agent_get_preference", auth: "\u516C\u5F00", params: "key?", what: "\u8BFB\u53D6 Agent \u6301\u4E45\u5316\u504F\u597D" },
|
|
32662
|
+
{ name: "agent_set_preference", auth: "\u516C\u5F00", params: "key, value", what: "\u4FDD\u5B58 Agent \u504F\u597D" },
|
|
32663
|
+
{ name: "okx_agent_feedback", auth: "\u516C\u5F00", params: "title, what, tools, pain, suggestion", what: "\u63D0\u4EA4\u4F7F\u7528\u53CD\u9988" },
|
|
32664
|
+
{ name: "agent_hub_status", auth: "\u516C\u5F00", params: "\u65E0", what: "Agent \u96C6\u7FA4\u72B6\u6001" },
|
|
32665
|
+
{ name: "agent_hub_dispatch", auth: "\u516C\u5F00", params: "taskId, agentId?", what: "\u6D3E\u53D1\u4EFB\u52A1\u7ED9 Agent" },
|
|
32666
|
+
{ name: "agent_hub_review", auth: "\u516C\u5F00", params: "taskId, verdict, feedback?", what: "\u5BA1\u6838 Agent \u63D0\u4EA4\u7ED3\u679C" },
|
|
32667
|
+
{ name: "agent_room_send", auth: "\u516C\u5F00", params: "roomId, text", what: "\u53D1\u9001\u623F\u95F4\u6D88\u606F" },
|
|
32668
|
+
{ name: "agent_room_view", auth: "\u516C\u5F00", params: "roomId?, limit?", what: "\u67E5\u770B\u623F\u95F4\u6D88\u606F\u5386\u53F2" },
|
|
32669
|
+
{ name: "xlayer_subscribe", auth: "\u516C\u5F00", params: "channel, address?", what: "X Layer \u94FE\u4E0A\u4E8B\u4EF6\u8BA2\u9605" },
|
|
32670
|
+
{ name: "xlayer_call", auth: "\u516C\u5F00", params: "to, data, value?", what: "X Layer \u5408\u7EA6\u8C03\u7528 \u2014 WRITE" },
|
|
32671
|
+
{ name: "xlayer_get_events", auth: "\u516C\u5F00", params: "channel?", what: "X Layer \u94FE\u4E0A\u4E8B\u4EF6" },
|
|
32672
|
+
{ name: "okx_get_system_status", auth: "\u516C\u5F00", params: "\u65E0", what: "OKX \u7CFB\u7EDF\u72B6\u6001" },
|
|
32673
|
+
{ name: "okx_get_instruments", auth: "\u516C\u5F00", params: "instType, instId?", what: "\u4EA7\u54C1\u5217\u8868/\u8BE6\u60C5" }
|
|
32674
|
+
]
|
|
32675
|
+
}
|
|
32676
|
+
};
|
|
32677
|
+
server.tool(
|
|
32678
|
+
"agent_catalog_detail",
|
|
32679
|
+
"CAT:[\u7CFB\u7EDF] | ## \u529F\u80FD\uFF1A\u67E5\u770B\u67D0\u4E2A\u4E1A\u52A1\u57DF\u7684\u8BE6\u7EC6\u5DE5\u5177\u6E05\u5355\u2014\u2014\u542B\u6BCF\u4E2A\u5DE5\u5177\u7684\u53C2\u6570\u63D0\u793A\u3001\u9274\u6743\u8981\u6C42\u3001\u63A8\u8350\u8C03\u7528\u987A\u5E8F\n## \u573A\u666F\uFF1AAgent \u5728 agent_catalog \u786E\u5B9A\u57DF\u540E\uFF0C\u8C03\u7528\u6B64\u5DE5\u5177\u83B7\u53D6\u8BE5\u57DF\u6240\u6709\u5DE5\u5177\u7684\u7CBE\u51C6\u4FE1\u606F\u3001\u53C2\u6570\u63D0\u793A\u548C\u5178\u578B workflow\n## \u5173\u952E\u8BCD\uFF1A\u76EE\u5F55\u8BE6\u60C5, catalog detail, \u5DE5\u5177\u6E05\u5355, \u57DF\u8BE6\u60C5, workflow\n## \u53C2\u6570\uFF1A\n## - domain: \u57DF\u540D\u79F0\u3002\u53EF\u53D6\u503C: \u8D26\u6237\u8D44\u4EA7 | \u884C\u60C5\u770B\u76D8 | \u4E0B\u5355\u4EA4\u6613 | \u98CE\u9669\u98CE\u63A7 | \u5E02\u573A\u626B\u63CF | \u76C8\u4E8F\u590D\u76D8 | \u8D44\u91D1\u7BA1\u7406 | \u7B56\u7565\u4EA4\u6613 | \u9884\u6D4B\u5E02\u573A | WebSocket \u5B9E\u65F6 | \u6A21\u62DF\u4F30\u7B97 | \u7CFB\u7EDF\u5DE5\u5177\n## \u9274\u6743\uFF1APUBLIC \u2014 \u7EAF\u7D22\u5F15\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~2KB \u2014 \u5355\u57DF\u8BE6\u60C5\n## \u5173\u8054\uFF1Aagent_catalog \u9009\u57DF \u2192 \u672C\u5DE5\u5177\u83B7\u53D6\u8BE6\u60C5 \u2192 \u76F4\u63A5\u8C03\u7528\u76EE\u6807\u5DE5\u5177",
|
|
32680
|
+
{
|
|
32681
|
+
domain: external_exports.string().describe("\u57DF\u540D\u79F0\u3002\u53EF\u9009: \u8D26\u6237\u8D44\u4EA7, \u884C\u60C5\u770B\u76D8, \u6280\u672F\u6307\u6807, \u4E0B\u5355\u4EA4\u6613, \u98CE\u9669\u98CE\u63A7, \u5E02\u573A\u626B\u63CF, \u806A\u660E\u94B1, \u76C8\u4E8F\u590D\u76D8, \u8D44\u91D1\u7BA1\u7406, \u7B56\u7565\u4EA4\u6613, \u9884\u6D4B\u5E02\u573A, WebSocket \u5B9E\u65F6, \u6A21\u62DF\u4F30\u7B97, \u7CFB\u7EDF\u5DE5\u5177")
|
|
32682
|
+
},
|
|
32683
|
+
async ({ domain }) => {
|
|
32684
|
+
try {
|
|
32685
|
+
const detail = DOMAIN_DETAILS[domain];
|
|
32686
|
+
if (!detail) {
|
|
32687
|
+
return toResult({
|
|
32688
|
+
found: false,
|
|
32689
|
+
domain,
|
|
32690
|
+
availableDomains: Object.keys(DOMAIN_DETAILS),
|
|
32691
|
+
hint: "\u8BF7\u4ECE availableDomains \u4E2D\u9009\u62E9\u4E00\u4E2A\u57DF\uFF0C\u6216\u8C03 agent_catalog \u67E5\u770B\u5B8C\u6574\u5BFC\u822A",
|
|
32692
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
32693
|
+
});
|
|
32694
|
+
}
|
|
32695
|
+
return toResult({
|
|
32696
|
+
found: true,
|
|
32697
|
+
domain,
|
|
32698
|
+
...detail,
|
|
32699
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
32700
|
+
});
|
|
32701
|
+
} catch (e) {
|
|
32702
|
+
return toError(e);
|
|
32703
|
+
}
|
|
32704
|
+
}
|
|
32705
|
+
);
|
|
32706
|
+
}
|
|
32707
|
+
|
|
32708
|
+
// src/tools/indicators.ts
|
|
32709
|
+
async function fetchCandles(instId, bar, minBars) {
|
|
32710
|
+
const limit = Math.min(300, Math.max(minBars + 50, 100));
|
|
32711
|
+
const raw = await publicApi.getCandles(instId, bar, limit);
|
|
32712
|
+
if (!raw || raw.length === 0) return [];
|
|
32713
|
+
return raw.map((r) => ({
|
|
32714
|
+
ts: parseInt(r[0]),
|
|
32715
|
+
o: parseFloat(r[1]),
|
|
32716
|
+
h: parseFloat(r[2]),
|
|
32717
|
+
l: parseFloat(r[3]),
|
|
32718
|
+
c: parseFloat(r[4]),
|
|
32719
|
+
vol: parseFloat(r[5])
|
|
32720
|
+
})).reverse();
|
|
32721
|
+
}
|
|
32722
|
+
function calcSMA(data, period) {
|
|
32723
|
+
const result = [];
|
|
32724
|
+
for (let i = period - 1; i < data.length; i++) {
|
|
32725
|
+
let sum = 0;
|
|
32726
|
+
for (let j = 0; j < period; j++) sum += data[i - j];
|
|
32727
|
+
result.push(sum / period);
|
|
32728
|
+
}
|
|
32729
|
+
return result;
|
|
32730
|
+
}
|
|
32731
|
+
function calcEMA(data, period) {
|
|
32732
|
+
const result = [];
|
|
32733
|
+
const k = 2 / (period + 1);
|
|
32734
|
+
let ema = data[0];
|
|
32735
|
+
result.push(ema);
|
|
32736
|
+
for (let i = 1; i < data.length; i++) {
|
|
32737
|
+
ema = data[i] * k + ema * (1 - k);
|
|
32738
|
+
result.push(ema);
|
|
32739
|
+
}
|
|
32740
|
+
return result.slice(period - 1);
|
|
32741
|
+
}
|
|
32742
|
+
function calcRSI(closes, period = 14) {
|
|
32743
|
+
const rsi = [];
|
|
32744
|
+
const gains = [], losses = [];
|
|
32745
|
+
for (let i = 1; i < closes.length; i++) {
|
|
32746
|
+
const diff = closes[i] - closes[i - 1];
|
|
32747
|
+
gains.push(diff > 0 ? diff : 0);
|
|
32748
|
+
losses.push(diff < 0 ? -diff : 0);
|
|
32749
|
+
}
|
|
32750
|
+
for (let i = period; i < gains.length; i++) {
|
|
32751
|
+
const avgGain = gains.slice(i - period, i).reduce((a, b) => a + b, 0) / period;
|
|
32752
|
+
const avgLoss = losses.slice(i - period, i).reduce((a, b) => a + b, 0) / period;
|
|
32753
|
+
rsi.push(avgLoss === 0 ? 100 : 100 - 100 / (1 + avgGain / avgLoss));
|
|
32754
|
+
}
|
|
32755
|
+
return rsi;
|
|
32756
|
+
}
|
|
32757
|
+
function calcMACD(closes, fast = 12, slow = 26, signal = 9) {
|
|
32758
|
+
const emaFast = calcEMA(closes, fast);
|
|
32759
|
+
const emaSlow = calcEMA(closes, slow);
|
|
32760
|
+
const offset = emaFast.length - emaSlow.length;
|
|
32761
|
+
const macd = [];
|
|
32762
|
+
for (let i = 0; i < emaSlow.length; i++) macd.push(emaFast[i + offset] - emaSlow[i]);
|
|
32763
|
+
const sigLine = calcEMA(macd, signal);
|
|
32764
|
+
const histOffset = macd.length - sigLine.length;
|
|
32765
|
+
const histogram = [];
|
|
32766
|
+
for (let i = 0; i < sigLine.length; i++) histogram.push(macd[i + histOffset] - sigLine[i]);
|
|
32767
|
+
return { macd: macd.slice(-sigLine.length), signal: sigLine, histogram };
|
|
32768
|
+
}
|
|
32769
|
+
function calcBollinger(closes, period = 20, mult = 2) {
|
|
32770
|
+
const sma = calcSMA(closes, period);
|
|
32771
|
+
const upper = [], lower = [], bandwidth = [], pctB = [];
|
|
32772
|
+
for (let i = 0; i < sma.length; i++) {
|
|
32773
|
+
const idx = i + period - 1;
|
|
32774
|
+
let sumSq = 0;
|
|
32775
|
+
for (let j = 0; j < period; j++) sumSq += (closes[idx - j] - sma[i]) ** 2;
|
|
32776
|
+
const std = Math.sqrt(sumSq / period);
|
|
32777
|
+
const up = sma[i] + mult * std;
|
|
32778
|
+
const lo = sma[i] - mult * std;
|
|
32779
|
+
upper.push(up);
|
|
32780
|
+
lower.push(lo);
|
|
32781
|
+
bandwidth.push((up - lo) / sma[i] * 100);
|
|
32782
|
+
pctB.push((closes[idx] - lo) / (up - lo));
|
|
32783
|
+
}
|
|
32784
|
+
return { upper, middle: sma, lower, bandwidth, pctB };
|
|
32785
|
+
}
|
|
32786
|
+
function calcATR(candles, period = 14) {
|
|
32787
|
+
const tr = [];
|
|
32788
|
+
for (let i = 1; i < candles.length; i++) {
|
|
32789
|
+
const h = candles[i].h, l = candles[i].l, pc = candles[i - 1].c;
|
|
32790
|
+
tr.push(Math.max(h - l, Math.abs(h - pc), Math.abs(l - pc)));
|
|
32791
|
+
}
|
|
32792
|
+
return calcSMA(tr, period);
|
|
32793
|
+
}
|
|
32794
|
+
function calcStoch(candles, kPeriod = 14, dPeriod = 3) {
|
|
32795
|
+
const k = [];
|
|
32796
|
+
for (let i = kPeriod - 1; i < candles.length; i++) {
|
|
32797
|
+
let highest = -Infinity, lowest = Infinity;
|
|
32798
|
+
for (let j = 0; j < kPeriod; j++) {
|
|
32799
|
+
highest = Math.max(highest, candles[i - j].h);
|
|
32800
|
+
lowest = Math.min(lowest, candles[i - j].l);
|
|
32801
|
+
}
|
|
32802
|
+
k.push((candles[i].c - lowest) / (highest - lowest) * 100);
|
|
32803
|
+
}
|
|
32804
|
+
const d = calcSMA(k, dPeriod);
|
|
32805
|
+
return { k: k.slice(dPeriod - 1), d };
|
|
32806
|
+
}
|
|
32807
|
+
function calcMFI(candles, period = 14) {
|
|
32808
|
+
const mfi = [];
|
|
32809
|
+
for (let i = period; i < candles.length; i++) {
|
|
32810
|
+
let posFlow = 0, negFlow = 0;
|
|
32811
|
+
for (let j = 0; j < period; j++) {
|
|
32812
|
+
const idx = i - j;
|
|
32813
|
+
const tp = (candles[idx].h + candles[idx].l + candles[idx].c) / 3;
|
|
32814
|
+
const prevTp = (candles[idx - 1].h + candles[idx - 1].l + candles[idx - 1].c) / 3;
|
|
32815
|
+
const rmf = tp * candles[idx].vol;
|
|
32816
|
+
if (tp > prevTp) posFlow += rmf;
|
|
32817
|
+
else negFlow += rmf;
|
|
32818
|
+
}
|
|
32819
|
+
mfi.push(negFlow === 0 ? 100 : 100 - 100 / (1 + posFlow / negFlow));
|
|
32820
|
+
}
|
|
32821
|
+
return mfi;
|
|
32822
|
+
}
|
|
32823
|
+
function calcWR(candles, period = 14) {
|
|
32824
|
+
const wr = [];
|
|
32825
|
+
for (let i = period - 1; i < candles.length; i++) {
|
|
32826
|
+
let highest = -Infinity, lowest = Infinity;
|
|
32827
|
+
for (let j = 0; j < period; j++) {
|
|
32828
|
+
highest = Math.max(highest, candles[i - j].h);
|
|
32829
|
+
lowest = Math.min(lowest, candles[i - j].l);
|
|
32830
|
+
}
|
|
32831
|
+
wr.push((highest - candles[i].c) / (highest - lowest) * -100);
|
|
32832
|
+
}
|
|
32833
|
+
return wr;
|
|
32834
|
+
}
|
|
32835
|
+
function calcCCI(candles, period = 20) {
|
|
32836
|
+
const tp = candles.map((c) => (c.h + c.l + c.c) / 3);
|
|
32837
|
+
const sma = calcSMA(tp, period);
|
|
32838
|
+
const cci = [];
|
|
32839
|
+
for (let i = 0; i < sma.length; i++) {
|
|
32840
|
+
const idx = i + period - 1;
|
|
32841
|
+
let sumDev = 0;
|
|
32842
|
+
for (let j = 0; j < period; j++) sumDev += Math.abs(tp[idx - j] - sma[i]);
|
|
32843
|
+
const mad = sumDev / period;
|
|
32844
|
+
cci.push(mad === 0 ? 0 : (tp[idx] - sma[i]) / (0.015 * mad));
|
|
32845
|
+
}
|
|
32846
|
+
return cci;
|
|
32847
|
+
}
|
|
32848
|
+
function calcOBV(candles) {
|
|
32849
|
+
const obv = [candles[0].vol];
|
|
32850
|
+
for (let i = 1; i < candles.length; i++) {
|
|
32851
|
+
if (candles[i].c > candles[i - 1].c) obv.push(obv[i - 1] + candles[i].vol);
|
|
32852
|
+
else if (candles[i].c < candles[i - 1].c) obv.push(obv[i - 1] - candles[i].vol);
|
|
32853
|
+
else obv.push(obv[i - 1]);
|
|
32854
|
+
}
|
|
32855
|
+
return obv;
|
|
32856
|
+
}
|
|
32857
|
+
function calcVWAP(candles) {
|
|
32858
|
+
const vwap = [];
|
|
32859
|
+
let cumPV = 0, cumV = 0;
|
|
32860
|
+
for (const c of candles) {
|
|
32861
|
+
const tp = (c.h + c.l + c.c) / 3;
|
|
32862
|
+
cumPV += tp * c.vol;
|
|
32863
|
+
cumV += c.vol;
|
|
32864
|
+
vwap.push(cumV === 0 ? c.c : cumPV / cumV);
|
|
32865
|
+
}
|
|
32866
|
+
return vwap;
|
|
32867
|
+
}
|
|
32868
|
+
function calcADX(candles, period = 14) {
|
|
32869
|
+
const tr = [], plusDM = [], minusDM = [];
|
|
32870
|
+
for (let i = 1; i < candles.length; i++) {
|
|
32871
|
+
const up = candles[i].h - candles[i - 1].h;
|
|
32872
|
+
const down = candles[i - 1].l - candles[i].l;
|
|
32873
|
+
tr.push(Math.max(candles[i].h - candles[i].l, Math.abs(candles[i].h - candles[i - 1].c), Math.abs(candles[i].l - candles[i - 1].c)));
|
|
32874
|
+
plusDM.push(up > down && up > 0 ? up : 0);
|
|
32875
|
+
minusDM.push(down > up && down > 0 ? down : 0);
|
|
32876
|
+
}
|
|
32877
|
+
const atrSm = calcEMASmooth(tr, period);
|
|
32878
|
+
const plusDISM = calcEMASmooth(plusDM, period);
|
|
32879
|
+
const minusDISM = calcEMASmooth(minusDM, period);
|
|
32880
|
+
const adx = [], pDI = [], mDI = [];
|
|
32881
|
+
for (let i = 0; i < atrSm.length; i++) {
|
|
32882
|
+
pDI.push(atrSm[i] === 0 ? 0 : plusDISM[i] / atrSm[i] * 100);
|
|
32883
|
+
mDI.push(atrSm[i] === 0 ? 0 : minusDISM[i] / atrSm[i] * 100);
|
|
32884
|
+
}
|
|
32885
|
+
const dx = [];
|
|
32886
|
+
for (let i = 0; i < pDI.length; i++) {
|
|
32887
|
+
const sum = pDI[i] + mDI[i];
|
|
32888
|
+
dx.push(sum === 0 ? 0 : Math.abs(pDI[i] - mDI[i]) / sum * 100);
|
|
32889
|
+
}
|
|
32890
|
+
const adxRaw = calcEMASmooth(dx, period);
|
|
32891
|
+
const offset2 = pDI.length - adxRaw.length;
|
|
32892
|
+
for (let i = 0; i < adxRaw.length; i++) {
|
|
32893
|
+
adx.push(adxRaw[i]);
|
|
32894
|
+
}
|
|
32895
|
+
return { adx, plusDI: pDI.slice(offset2), minusDI: mDI.slice(offset2) };
|
|
32896
|
+
}
|
|
32897
|
+
function calcEMASmooth(data, period) {
|
|
32898
|
+
if (data.length === 0) return [];
|
|
32899
|
+
const result = [data[0]];
|
|
32900
|
+
const k = 2 / (period + 1);
|
|
32901
|
+
for (let i = 1; i < data.length; i++) result.push(data[i] * k + result[i - 1] * (1 - k));
|
|
32902
|
+
return result.slice(period - 1);
|
|
32903
|
+
}
|
|
32904
|
+
function calcSupertrend(candles, period = 10, mult = 3) {
|
|
32905
|
+
const atr = calcATR(candles, period);
|
|
32906
|
+
const upper = [], lower = [], trend = [];
|
|
32907
|
+
const direction = [];
|
|
32908
|
+
for (let i = 0; i < atr.length; i++) {
|
|
32909
|
+
const idx = i + period - 1;
|
|
32910
|
+
const mid = (candles[idx].h + candles[idx].l) / 2;
|
|
32911
|
+
const up = mid - mult * atr[i];
|
|
32912
|
+
const lo = mid + mult * atr[i];
|
|
32913
|
+
if (i === 0) {
|
|
32914
|
+
upper.push(up);
|
|
32915
|
+
lower.push(lo);
|
|
32916
|
+
direction.push(candles[idx].c > lo ? 1 : -1);
|
|
32917
|
+
trend.push(candles[idx].c > lo ? lo : up);
|
|
32918
|
+
} else {
|
|
32919
|
+
const prevLo = lower[i - 1], prevUp = upper[i - 1];
|
|
32920
|
+
const newUp = mid - mult * atr[i];
|
|
32921
|
+
const newLo = mid + mult * atr[i];
|
|
32922
|
+
upper.push(candles[idx - 1].c > prevLo ? Math.max(newUp, upper[i - 1]) : newUp);
|
|
32923
|
+
lower.push(candles[idx - 1].c < prevUp ? Math.min(newLo, lower[i - 1]) : newLo);
|
|
32924
|
+
if (direction[i - 1] === 1) {
|
|
32925
|
+
direction.push(candles[idx].c > lower[i] ? 1 : -1);
|
|
32926
|
+
} else {
|
|
32927
|
+
direction.push(candles[idx].c < upper[i] ? -1 : 1);
|
|
32928
|
+
}
|
|
32929
|
+
trend.push(direction[i] === 1 ? lower[i] : upper[i]);
|
|
32930
|
+
}
|
|
32931
|
+
}
|
|
32932
|
+
return { trend, direction };
|
|
32933
|
+
}
|
|
32934
|
+
function calcCMF(candles, period = 20) {
|
|
32935
|
+
const cmf = [];
|
|
32936
|
+
for (let i = period - 1; i < candles.length; i++) {
|
|
32937
|
+
let mfVol = 0, totalVol = 0;
|
|
32938
|
+
for (let j = 0; j < period; j++) {
|
|
32939
|
+
const c = candles[i - j];
|
|
32940
|
+
const mf = (c.c - c.l - (c.h - c.c)) / (c.h - c.l || 1);
|
|
32941
|
+
mfVol += mf * c.vol;
|
|
32942
|
+
totalVol += c.vol;
|
|
32943
|
+
}
|
|
32944
|
+
cmf.push(totalVol === 0 ? 0 : mfVol / totalVol);
|
|
32945
|
+
}
|
|
32946
|
+
return cmf;
|
|
32947
|
+
}
|
|
32948
|
+
function calcKeltner(candles, period = 20, mult = 2) {
|
|
32949
|
+
const tp = candles.map((c) => (c.h + c.l + c.c) / 3);
|
|
32950
|
+
const middle = calcEMA(tp, period);
|
|
32951
|
+
const atr = calcATR(candles, period);
|
|
32952
|
+
const minLen = Math.min(middle.length, atr.length);
|
|
32953
|
+
const upper = [], lower = [];
|
|
32954
|
+
for (let i = 0; i < minLen; i++) {
|
|
32955
|
+
upper.push(middle[middle.length - minLen + i] + mult * atr[atr.length - minLen + i]);
|
|
32956
|
+
lower.push(middle[middle.length - minLen + i] - mult * atr[atr.length - minLen + i]);
|
|
32957
|
+
}
|
|
32958
|
+
return { upper, middle: middle.slice(-minLen), lower };
|
|
32959
|
+
}
|
|
32960
|
+
function detectDoji(candle) {
|
|
32961
|
+
const body = Math.abs(candle.c - candle.o);
|
|
32962
|
+
const range = candle.h - candle.l;
|
|
32963
|
+
return range > 0 && body / range < 0.1;
|
|
32964
|
+
}
|
|
32965
|
+
function detectHammer(candle) {
|
|
32966
|
+
const body = Math.abs(candle.c - candle.o);
|
|
32967
|
+
const upperWick = candle.h - Math.max(candle.o, candle.c);
|
|
32968
|
+
const lowerWick = Math.min(candle.o, candle.c) - candle.l;
|
|
32969
|
+
return body > 0 && lowerWick > body * 2 && upperWick < body * 0.5;
|
|
32970
|
+
}
|
|
32971
|
+
function detectEngulfing(prev, curr) {
|
|
32972
|
+
const prevBody = Math.abs(prev.c - prev.o);
|
|
32973
|
+
const currBody = Math.abs(curr.c - curr.o);
|
|
32974
|
+
if (currBody < prevBody * 1.2) return null;
|
|
32975
|
+
if (curr.c > curr.o && prev.c < prev.o) return "bullish";
|
|
32976
|
+
if (curr.c < curr.o && prev.c > prev.o) return "bearish";
|
|
32977
|
+
return null;
|
|
32978
|
+
}
|
|
32979
|
+
function rsiSignal(rsi) {
|
|
32980
|
+
if (rsi > 70) return { signal: "bearish", message: `RSI \u8D85\u4E70 (${rsi.toFixed(1)} > 70)\uFF0C\u8FD1\u671F\u6709\u56DE\u8C03\u98CE\u9669\uFF0C\u4E0D\u5B9C\u8FFD\u591A` };
|
|
32981
|
+
if (rsi < 30) return { signal: "bullish", message: `RSI \u8D85\u5356 (${rsi.toFixed(1)} < 30)\uFF0C\u53EF\u80FD\u51FA\u73B0\u6280\u672F\u6027\u53CD\u5F39\uFF0C\u4E0D\u5B9C\u8FFD\u7A7A` };
|
|
32982
|
+
if (rsi > 60) return { signal: "bullish", message: `RSI \u504F\u5F3A (${rsi.toFixed(1)})\uFF0C\u591A\u5934\u52A8\u80FD\u6301\u7EED` };
|
|
32983
|
+
if (rsi < 40) return { signal: "bearish", message: `RSI \u504F\u5F31 (${rsi.toFixed(1)})\uFF0C\u7A7A\u5934\u52A8\u80FD\u6301\u7EED` };
|
|
32984
|
+
return { signal: "neutral", message: `RSI \u4E2D\u6027 (${rsi.toFixed(1)})\uFF0C\u65E0\u660E\u663E\u8D85\u4E70\u8D85\u5356\u4FE1\u53F7` };
|
|
32985
|
+
}
|
|
32986
|
+
function macdSignal(hist, prevHist) {
|
|
32987
|
+
if (hist > 0 && prevHist <= 0) return { signal: "bullish", message: "MACD \u91D1\u53C9\uFF0C\u591A\u5934\u4FE1\u53F7\u542F\u52A8" };
|
|
32988
|
+
if (hist < 0 && prevHist >= 0) return { signal: "bearish", message: "MACD \u6B7B\u53C9\uFF0C\u7A7A\u5934\u4FE1\u53F7\u542F\u52A8" };
|
|
32989
|
+
if (hist > 0) return { signal: "bullish", message: `MACD \u67F1 ${hist.toFixed(4)}\uFF0C\u591A\u5934\u533A\u57DF\u8FD0\u884C` };
|
|
32990
|
+
return { signal: "bearish", message: `MACD \u67F1 ${hist.toFixed(4)}\uFF0C\u7A7A\u5934\u533A\u57DF\u8FD0\u884C` };
|
|
32991
|
+
}
|
|
32992
|
+
function stochSignal(k, d) {
|
|
32993
|
+
if (k > 80 && d > 80) return { signal: "bearish", message: `KD \u8D85\u4E70 (K:${k.toFixed(1)}, D:${d.toFixed(1)})\uFF0C\u5173\u6CE8\u6B7B\u53C9` };
|
|
32994
|
+
if (k < 20 && d < 20) return { signal: "bullish", message: `KD \u8D85\u5356 (K:${k.toFixed(1)}, D:${d.toFixed(1)})\uFF0C\u5173\u6CE8\u91D1\u53C9` };
|
|
32995
|
+
return { signal: "neutral", message: `KD \u4E2D\u6027\u533A\u57DF (K:${k.toFixed(1)}, D:${d.toFixed(1)})` };
|
|
32996
|
+
}
|
|
32997
|
+
function adxSignal(adx, plusDI, minusDI) {
|
|
32998
|
+
if (adx > 40) {
|
|
32999
|
+
if (plusDI > minusDI) return { signal: "bullish", message: `ADX \u5F3A\u52BF\u8D8B\u52BF (${adx.toFixed(1)})\uFF0C+DI \u4E3B\u5BFC\uFF0C\u591A\u5934\u8D8B\u52BF\u5F3A\u52B2` };
|
|
33000
|
+
return { signal: "bearish", message: `ADX \u5F3A\u52BF\u8D8B\u52BF (${adx.toFixed(1)})\uFF0C-DI \u4E3B\u5BFC\uFF0C\u7A7A\u5934\u8D8B\u52BF\u5F3A\u52B2` };
|
|
33001
|
+
}
|
|
33002
|
+
if (adx > 25) {
|
|
33003
|
+
if (plusDI > minusDI) return { signal: "bullish", message: `ADX \u8D8B\u52BF\u786E\u7ACB (${adx.toFixed(1)})\uFF0C\u65B9\u5411\u504F\u591A` };
|
|
33004
|
+
return { signal: "bearish", message: `ADX \u8D8B\u52BF\u786E\u7ACB (${adx.toFixed(1)})\uFF0C\u65B9\u5411\u504F\u7A7A` };
|
|
33005
|
+
}
|
|
33006
|
+
return { signal: "neutral", message: `ADX \u4F4E\u6CE2\u52A8 (${adx.toFixed(1)} < 25)\uFF0C\u9707\u8361\u884C\u60C5\uFF0C\u8D8B\u52BF\u7B56\u7565\u9700\u8C28\u614E` };
|
|
33007
|
+
}
|
|
33008
|
+
function registerIndicatorTools(server) {
|
|
33009
|
+
server.tool(
|
|
33010
|
+
"okx_indicator",
|
|
33011
|
+
"CAT:[\u884C\u60C5] | ## \u529F\u80FD\uFF1A\u8BA1\u7B97\u6307\u5B9A\u4EA7\u54C1\u7684\u5355\u4E2A\u6280\u672F\u6307\u6807\uFF0C\u8FD4\u56DE\u539F\u59CB\u503C + \u4E2D\u6587Agent\u4FE1\u53F7\u89E3\u8BFB\uFF08\u8D85\u4E70/\u8D85\u5356/\u91D1\u53C9/\u6B7B\u53C9/\u8D8B\u52BF\u65B9\u5411\uFF09\n## \u573A\u666F\uFF1AAgent \u56DE\u7B54\u300CRSI \u591A\u5C11\u300D\u300CMACD \u91D1\u53C9\u4E86\u5417\u300D\u300C\u5E03\u6797\u5E26\u4EC0\u4E48\u4F4D\u7F6E\u300D\u7B49\u6307\u6807\u95EE\u9898\u65F6\u8C03\u7528\uFF0C\u4E00\u6B21\u62FF\u5230\u8BA1\u7B97\u7ED3\u679C\u548C\u64CD\u4F5C\u5EFA\u8BAE\n## \u5173\u952E\u8BCD\uFF1A\u6280\u672F\u6307\u6807, indicator, RSI, MACD, \u5E03\u6797\u5E26, KDJ, ADX, \u8D85\u4E70, \u8D85\u5356, \u91D1\u53C9, \u6B7B\u53C9, \u5747\u7EBF\n## \u53C2\u6570\uFF1A\n## - instId: \u4EA7\u54C1ID\uFF0C\u5982 BTC-USDT\n## - indicator: \u6307\u6807\u540D (sma/ema/rsi/macd/bb/atr/stoch/wr/cci/obv/vwap/adx/mfi/cmf/supertrend/keltner/pattern)\n## - period: \u5468\u671F\u53C2\u6570\uFF0C\u9ED8\u8BA4\u503C\u56E0\u6307\u6807\u800C\u5F02\uFF08RSI=14\uFF0CMACD=12/26/9 \u7B49\uFF09\n## - bar: K\u7EBF\u7C92\u5EA6\uFF0C\u9ED8\u8BA4 1H\u3002\u652F\u6301 1m/5m/15m/30m/1H/2H/4H/6H/12H/1D\n## \u9274\u6743\uFF1APUBLIC \u2014 \u516C\u5F00\u63A5\u53E3\uFF08\u57FA\u4E8E okx_get_candles\uFF09\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BA1\u7B97\u4E0D\u4EA4\u6613\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~1KB\n## \u5173\u8054\uFF1A\u672C\u5DE5\u5177\u8BA1\u7B97\u6307\u6807 \u2192 okx_quick_market \u770B\u76D8\u53E3 \u2192 agent_quick_trade \u4E0B\u5355",
|
|
33012
|
+
{
|
|
33013
|
+
instId: external_exports.string().describe("\u4EA7\u54C1ID\uFF0C\u5982 BTC-USDT\u3001ETH-USDT-SWAP"),
|
|
33014
|
+
indicator: external_exports.enum(["sma", "ema", "rsi", "macd", "bb", "atr", "stoch", "wr", "cci", "obv", "vwap", "adx", "mfi", "cmf", "supertrend", "keltner", "pattern"]).describe("\u6307\u6807\u540D"),
|
|
33015
|
+
period: external_exports.number().int().min(2).max(200).optional().describe("\u5468\u671F\uFF08\u9ED8\u8BA4\u503C\u56E0\u6307\u6807\u800C\u5F02\uFF0C\u5982 RSI \u9ED8\u8BA414\uFF09"),
|
|
33016
|
+
bar: external_exports.enum(["1m", "5m", "15m", "30m", "1H", "2H", "4H", "6H", "12H", "1D"]).optional().describe("K\u7EBF\u7C92\u5EA6\uFF0C\u9ED8\u8BA41H")
|
|
33017
|
+
},
|
|
33018
|
+
async ({ instId, indicator, period, bar }) => {
|
|
33019
|
+
try {
|
|
33020
|
+
const b = bar || "1H";
|
|
33021
|
+
const p = period || ({ sma: 20, ema: 20, rsi: 14, macd: 12, bb: 20, atr: 14, stoch: 14, wr: 14, cci: 20, obv: 0, vwap: 0, adx: 14, mfi: 14, cmf: 20, supertrend: 10, keltner: 20, pattern: 0 }[indicator] || 14);
|
|
33022
|
+
const minBars = indicator === "pattern" ? 5 : p * 3 + 50;
|
|
33023
|
+
const candles = await fetchCandles(instId, b, minBars);
|
|
33024
|
+
if (candles.length < p + 2) {
|
|
33025
|
+
return toResult({
|
|
33026
|
+
instId,
|
|
33027
|
+
indicator,
|
|
33028
|
+
bar: b,
|
|
33029
|
+
error: `\u6570\u636E\u4E0D\u8DB3\uFF1A\u4EC5\u83B7\u53D6 ${candles.length} \u6839K\u7EBF\uFF0C\u9700\u8981\u81F3\u5C11 ${p + 2} \u6839`,
|
|
33030
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
33031
|
+
});
|
|
33032
|
+
}
|
|
33033
|
+
const closes = candles.map((c) => c.c);
|
|
33034
|
+
const latest = candles[candles.length - 1];
|
|
33035
|
+
let result = { instId, indicator, bar: b, period: p, tsIso: (/* @__PURE__ */ new Date()).toISOString() };
|
|
33036
|
+
switch (indicator) {
|
|
33037
|
+
case "sma": {
|
|
33038
|
+
const sma = calcSMA(closes, p);
|
|
33039
|
+
const v = sma[sma.length - 1];
|
|
33040
|
+
const prev = sma[sma.length - 2];
|
|
33041
|
+
result.value = v.toFixed(4);
|
|
33042
|
+
result.signal = latest.c > v ? "bullish" : "bearish";
|
|
33043
|
+
result.message = `SMA(${p}) = ${v.toFixed(2)}\u3002\u4EF7\u683C${latest.c > v ? "\u9AD8\u4E8E" : "\u4F4E\u4E8E"}\u5747\u7EBF\uFF0C${latest.c > v ? "\u591A\u5934\u6392\u5217" : "\u7A7A\u5934\u6392\u5217"}${latest.c > v !== prev > 0 ? "\uFF08\u521A\u521A\u7A7F\u8D8A\uFF0C\u53EF\u80FD\u662F\u53D8\u76D8\u4FE1\u53F7\uFF09" : ""}`;
|
|
33044
|
+
break;
|
|
33045
|
+
}
|
|
33046
|
+
case "ema": {
|
|
33047
|
+
const ema = calcEMA(closes, p);
|
|
33048
|
+
const v = ema[ema.length - 1];
|
|
33049
|
+
const prev = ema[ema.length - 2];
|
|
33050
|
+
result.value = v.toFixed(4);
|
|
33051
|
+
result.signal = latest.c > v ? "bullish" : "bearish";
|
|
33052
|
+
result.message = `EMA(${p}) = ${v.toFixed(2)}\u3002\u4EF7\u683C${latest.c > v ? "\u9AD8\u4E8E" : "\u4F4E\u4E8E"}\u6307\u6570\u5747\u7EBF\uFF0C${latest.c > v ? "\u77ED\u671F\u8D8B\u52BF\u504F\u591A" : "\u77ED\u671F\u8D8B\u52BF\u504F\u7A7A"}`;
|
|
33053
|
+
break;
|
|
33054
|
+
}
|
|
33055
|
+
case "rsi": {
|
|
33056
|
+
const rsi = calcRSI(closes, p);
|
|
33057
|
+
const v = rsi[rsi.length - 1];
|
|
33058
|
+
result.value = v.toFixed(2);
|
|
33059
|
+
const sig = rsiSignal(v);
|
|
33060
|
+
result.signal = sig.signal;
|
|
33061
|
+
result.message = sig.message;
|
|
33062
|
+
break;
|
|
33063
|
+
}
|
|
33064
|
+
case "macd": {
|
|
33065
|
+
const { macd, signal: sigLine, histogram } = calcMACD(closes, 12, 26, 9);
|
|
33066
|
+
const m = macd[macd.length - 1], s = sigLine[sigLine.length - 1], h = histogram[histogram.length - 1];
|
|
33067
|
+
const prevH = histogram[histogram.length - 2] || 0;
|
|
33068
|
+
result.value = { macd: m.toFixed(4), signal: s.toFixed(4), histogram: h.toFixed(4) };
|
|
33069
|
+
const sig = macdSignal(h, prevH);
|
|
33070
|
+
result.signal = sig.signal;
|
|
33071
|
+
result.message = `MACD(12,26,9): DIF=${m.toFixed(4)}, DEA=${s.toFixed(4)}, \u67F1=${h.toFixed(4)}\u3002${sig.message}`;
|
|
33072
|
+
break;
|
|
33073
|
+
}
|
|
33074
|
+
case "bb": {
|
|
33075
|
+
const bb = calcBollinger(closes, p, 2);
|
|
33076
|
+
const up = bb.upper[bb.upper.length - 1], mid = bb.middle[bb.middle.length - 1];
|
|
33077
|
+
const lo = bb.lower[bb.lower.length - 1], pct = bb.pctB[bb.pctB.length - 1];
|
|
33078
|
+
result.value = { upper: up.toFixed(2), middle: mid.toFixed(2), lower: lo.toFixed(2), pctB: pct.toFixed(3), bandwidth: bb.bandwidth[bb.bandwidth.length - 1].toFixed(2) + "%" };
|
|
33079
|
+
if (pct > 1) result = { ...result, signal: "bearish", message: `\u5E03\u6797\u5E26(${p},2): \u4EF7\u683C ${latest.c.toFixed(2)} \u7A81\u7834\u4E0A\u8F68 ${up.toFixed(2)}\uFF0C\u8D85\u4E70\u72B6\u6001\uFF0C\u53EF\u80FD\u56DE\u8C03` };
|
|
33080
|
+
else if (pct < 0) result = { ...result, signal: "bullish", message: `\u5E03\u6797\u5E26(${p},2): \u4EF7\u683C ${latest.c.toFixed(2)} \u8DCC\u7834\u4E0B\u8F68 ${lo.toFixed(2)}\uFF0C\u8D85\u5356\u72B6\u6001\uFF0C\u53EF\u80FD\u53CD\u5F39` };
|
|
33081
|
+
else if (pct > 0.8) result = { ...result, signal: "bullish", message: `\u5E03\u6797\u5E26(${p},2): \u4EF7\u683C ${latest.c.toFixed(2)} \u504F\u4E0A\u8F68 ${up.toFixed(2)}\uFF0C\u5F3A\u52BF\u533A\u57DF` };
|
|
33082
|
+
else if (pct < 0.2) result = { ...result, signal: "bearish", message: `\u5E03\u6797\u5E26(${p},2): \u4EF7\u683C ${latest.c.toFixed(2)} \u504F\u4E0B\u8F68 ${lo.toFixed(2)}\uFF0C\u5F31\u52BF\u533A\u57DF` };
|
|
33083
|
+
else result = { ...result, signal: "neutral", message: `\u5E03\u6797\u5E26(${p},2): \u4EF7\u683C ${latest.c.toFixed(2)} \u5728\u4E2D\u8F68 ${mid.toFixed(2)} \u9644\u8FD1\uFF0C\u9707\u8361\u6574\u7406` };
|
|
33084
|
+
break;
|
|
33085
|
+
}
|
|
33086
|
+
case "atr": {
|
|
33087
|
+
const atr = calcATR(candles, p);
|
|
33088
|
+
const v = atr[atr.length - 1];
|
|
33089
|
+
const pctOfPrice = v / latest.c * 100;
|
|
33090
|
+
result.value = v.toFixed(4);
|
|
33091
|
+
result.message = `ATR(${p}) = ${v.toFixed(4)}\uFF08\u4E3A\u5F53\u524D\u4EF7\u683C\u7684 ${pctOfPrice.toFixed(2)}%\uFF09\u3002\u6CE2\u52A8\u7387${pctOfPrice > 3 ? "\u8F83\u9AD8" : pctOfPrice > 1 ? "\u6B63\u5E38" : "\u8F83\u4F4E"}\uFF0C\u6B62\u635F\u5EFA\u8BAE\u8BBE\u7F6E\u5728 ${(latest.c - v * 1.5).toFixed(2)} ~ ${(latest.c - v * 2).toFixed(2)}`;
|
|
33092
|
+
result.signal = "neutral";
|
|
33093
|
+
break;
|
|
33094
|
+
}
|
|
33095
|
+
case "stoch": {
|
|
33096
|
+
const st = calcStoch(candles, p, 3);
|
|
33097
|
+
const k = st.k[st.k.length - 1], d = st.d[st.d.length - 1];
|
|
33098
|
+
result.value = { k: k.toFixed(2), d: d.toFixed(2) };
|
|
33099
|
+
const sig = stochSignal(k, d);
|
|
33100
|
+
result.signal = sig.signal;
|
|
33101
|
+
result.message = sig.message;
|
|
33102
|
+
break;
|
|
33103
|
+
}
|
|
33104
|
+
case "wr": {
|
|
33105
|
+
const wr = calcWR(candles, p);
|
|
33106
|
+
const v = wr[wr.length - 1];
|
|
33107
|
+
result.value = v.toFixed(2);
|
|
33108
|
+
if (v > -20) result = { ...result, signal: "bearish", message: `W%R(${p}) = ${v.toFixed(1)}\uFF0C\u8D85\u4E70\u533A\uFF08>-20\uFF09\uFF0C\u77ED\u671F\u56DE\u8C03\u98CE\u9669` };
|
|
33109
|
+
else if (v < -80) result = { ...result, signal: "bullish", message: `W%R(${p}) = ${v.toFixed(1)}\uFF0C\u8D85\u5356\u533A\uFF08<-80\uFF09\uFF0C\u77ED\u671F\u53CD\u5F39\u673A\u4F1A` };
|
|
33110
|
+
else result = { ...result, signal: "neutral", message: `W%R(${p}) = ${v.toFixed(1)}\uFF0C\u4E2D\u6027\u533A\u57DF` };
|
|
33111
|
+
break;
|
|
33112
|
+
}
|
|
33113
|
+
case "cci": {
|
|
33114
|
+
const cci = calcCCI(candles, p);
|
|
33115
|
+
const v = cci[cci.length - 1];
|
|
33116
|
+
result.value = v.toFixed(2);
|
|
33117
|
+
if (v > 200) result = { ...result, signal: "bearish", message: `CCI(${p}) = ${v.toFixed(1)}\uFF0C\u6781\u5EA6\u8D85\u4E70\uFF08>200\uFF09\uFF0C\u5F3A\u56DE\u8C03\u4FE1\u53F7` };
|
|
33118
|
+
else if (v > 100) result = { ...result, signal: "bullish", message: `CCI(${p}) = ${v.toFixed(1)}\uFF0C\u8D85\u4E70\u533A\u57DF\uFF08>100\uFF09\uFF0C\u8D8B\u52BF\u504F\u5F3A\u4F46\u6CE8\u610F\u56DE\u8C03` };
|
|
33119
|
+
else if (v < -200) result = { ...result, signal: "bullish", message: `CCI(${p}) = ${v.toFixed(1)}\uFF0C\u6781\u5EA6\u8D85\u5356\uFF08<-200\uFF09\uFF0C\u5F3A\u53CD\u5F39\u4FE1\u53F7` };
|
|
33120
|
+
else if (v < -100) result = { ...result, signal: "bearish", message: `CCI(${p}) = ${v.toFixed(1)}\uFF0C\u8D85\u5356\u533A\u57DF\uFF08<-100\uFF09\uFF0C\u8D8B\u52BF\u504F\u5F31\u4F46\u6CE8\u610F\u53CD\u5F39` };
|
|
33121
|
+
else result = { ...result, signal: "neutral", message: `CCI(${p}) = ${v.toFixed(1)}\uFF0C\u6B63\u5E38\u8303\u56F4\uFF08-100~100\uFF09\uFF0C\u65E0\u660E\u663E\u6781\u7AEF\u4FE1\u53F7` };
|
|
33122
|
+
break;
|
|
33123
|
+
}
|
|
33124
|
+
case "obv": {
|
|
33125
|
+
const obv = calcOBV(candles);
|
|
33126
|
+
const v = obv[obv.length - 1];
|
|
33127
|
+
const prevV = obv[obv.length - 2];
|
|
33128
|
+
const trend = v > obv[obv.length - Math.min(20, obv.length)] ? "\u4E0A\u5347" : "\u4E0B\u964D";
|
|
33129
|
+
result.value = v.toFixed(0);
|
|
33130
|
+
result.signal = trend === "\u4E0A\u5347" ? "bullish" : "bearish";
|
|
33131
|
+
result.message = `OBV \u5F53\u524D ${v.toFixed(0)}\uFF08${v > prevV ? "+" : ""}${(v - prevV).toFixed(0)}\uFF09\uFF0C\u8FD1\u671F\u8D8B\u52BF${trend}\u3002${trend === "\u4E0A\u5347" ? "\u91CF\u4EF7\u914D\u5408\uFF0C\u4E0A\u6DA8\u6709\u8D44\u91D1\u652F\u6491" : "\u6210\u4EA4\u91CF\u4E0D\u914D\u5408\uFF0C\u4E0A\u6DA8\u52A8\u529B\u4E0D\u8DB3"}`;
|
|
33132
|
+
break;
|
|
33133
|
+
}
|
|
33134
|
+
case "vwap": {
|
|
33135
|
+
const vwap = calcVWAP(candles);
|
|
33136
|
+
const v = vwap[vwap.length - 1];
|
|
33137
|
+
result.value = v.toFixed(4);
|
|
33138
|
+
result.signal = latest.c > v ? "bullish" : "bearish";
|
|
33139
|
+
result.message = `VWAP = ${v.toFixed(2)}\u3002\u4EF7\u683C${latest.c > v ? "\u9AD8\u4E8E" : "\u4F4E\u4E8E"}\u6210\u4EA4\u91CF\u52A0\u6743\u5747\u4EF7\uFF0C${latest.c > v ? "\u4E70\u65B9\u4E3B\u5BFC" : "\u5356\u65B9\u4E3B\u5BFC"}`;
|
|
33140
|
+
break;
|
|
33141
|
+
}
|
|
33142
|
+
case "adx": {
|
|
33143
|
+
const { adx, plusDI, minusDI } = calcADX(candles, p);
|
|
33144
|
+
const a = adx[adx.length - 1], pDI = plusDI[plusDI.length - 1], mDI = minusDI[minusDI.length - 1];
|
|
33145
|
+
result.value = { adx: a.toFixed(2), plusDI: pDI.toFixed(2), minusDI: mDI.toFixed(2) };
|
|
33146
|
+
const sig = adxSignal(a, pDI, mDI);
|
|
33147
|
+
result.signal = sig.signal;
|
|
33148
|
+
result.message = sig.message;
|
|
33149
|
+
break;
|
|
33150
|
+
}
|
|
33151
|
+
case "mfi": {
|
|
33152
|
+
const mfi = calcMFI(candles, p);
|
|
33153
|
+
const v = mfi[mfi.length - 1];
|
|
33154
|
+
result.value = v.toFixed(2);
|
|
33155
|
+
if (v > 80) result = { ...result, signal: "bearish", message: `MFI(${p}) = ${v.toFixed(1)}\uFF0C\u8D44\u91D1\u4E25\u91CD\u8D85\u4E70\uFF08>80\uFF09\uFF0C\u53EF\u80FD\u89C1\u9876` };
|
|
33156
|
+
else if (v < 20) result = { ...result, signal: "bullish", message: `MFI(${p}) = ${v.toFixed(1)}\uFF0C\u8D44\u91D1\u4E25\u91CD\u8D85\u5356\uFF08<20\uFF09\uFF0C\u53EF\u80FD\u89C1\u5E95` };
|
|
33157
|
+
else if (v > 60) result = { ...result, signal: "bullish", message: `MFI(${p}) = ${v.toFixed(1)}\uFF0C\u8D44\u91D1\u6301\u7EED\u6D41\u5165` };
|
|
33158
|
+
else if (v < 40) result = { ...result, signal: "bearish", message: `MFI(${p}) = ${v.toFixed(1)}\uFF0C\u8D44\u91D1\u6301\u7EED\u6D41\u51FA` };
|
|
33159
|
+
else result = { ...result, signal: "neutral", message: `MFI(${p}) = ${v.toFixed(1)}\uFF0C\u8D44\u91D1\u9762\u4E2D\u6027` };
|
|
33160
|
+
break;
|
|
33161
|
+
}
|
|
33162
|
+
case "cmf": {
|
|
33163
|
+
const cmf = calcCMF(candles, p);
|
|
33164
|
+
const v = cmf[cmf.length - 1];
|
|
33165
|
+
result.value = v.toFixed(4);
|
|
33166
|
+
if (v > 0.1) result = { ...result, signal: "bullish", message: `CMF(${p}) = ${v.toFixed(3)}\uFF0C\u663E\u8457\u51C0\u6D41\u5165\uFF08>0.1\uFF09\uFF0C\u4E70\u65B9\u4E3B\u5BFC` };
|
|
33167
|
+
else if (v < -0.1) result = { ...result, signal: "bearish", message: `CMF(${p}) = ${v.toFixed(3)}\uFF0C\u663E\u8457\u51C0\u6D41\u51FA\uFF08<-0.1\uFF09\uFF0C\u5356\u65B9\u4E3B\u5BFC` };
|
|
33168
|
+
else if (v > 0) result = { ...result, signal: "bullish", message: `CMF(${p}) = ${v.toFixed(3)}\uFF0C\u8F7B\u5FAE\u51C0\u6D41\u5165` };
|
|
33169
|
+
else result = { ...result, signal: "bearish", message: `CMF(${p}) = ${v.toFixed(3)}\uFF0C\u8F7B\u5FAE\u51C0\u6D41\u51FA` };
|
|
33170
|
+
break;
|
|
33171
|
+
}
|
|
33172
|
+
case "supertrend": {
|
|
33173
|
+
const st = calcSupertrend(candles, p, 3);
|
|
33174
|
+
const trend = st.trend[st.trend.length - 1];
|
|
33175
|
+
const dir = st.direction[st.direction.length - 1];
|
|
33176
|
+
result.value = { trend: trend.toFixed(2), direction: dir };
|
|
33177
|
+
result.signal = dir === 1 ? "bullish" : "bearish";
|
|
33178
|
+
result.message = `Supertrend(${p},3): ${dir === 1 ? "\u{1F7E2} \u591A\u5934" : "\u{1F534} \u7A7A\u5934"}\uFF0C\u6B62\u635F\u7EBF ${trend.toFixed(2)}\u3002${dir === 1 ? "\u8D8B\u52BF\u504F\u591A\uFF0C\u4E0D\u5EFA\u8BAE\u505A\u7A7A" : "\u8D8B\u52BF\u504F\u7A7A\uFF0C\u4E0D\u5EFA\u8BAE\u505A\u591A"}`;
|
|
33179
|
+
break;
|
|
33180
|
+
}
|
|
33181
|
+
case "keltner": {
|
|
33182
|
+
const kc = calcKeltner(candles, p, 2);
|
|
33183
|
+
const up = kc.upper[kc.upper.length - 1], mid = kc.middle[kc.middle.length - 1];
|
|
33184
|
+
const lo = kc.lower[kc.lower.length - 1];
|
|
33185
|
+
result.value = { upper: up.toFixed(2), middle: mid.toFixed(2), lower: lo.toFixed(2) };
|
|
33186
|
+
if (latest.c > up) result = { ...result, signal: "bullish", message: `\u80AF\u7279\u7EB3(${p},2): \u4EF7\u683C\u7A81\u7834\u4E0A\u8F68 ${up.toFixed(2)}\uFF0C\u5F3A\u52BF\u7A81\u7834\u4FE1\u53F7` };
|
|
33187
|
+
else if (latest.c < lo) result = { ...result, signal: "bearish", message: `\u80AF\u7279\u7EB3(${p},2): \u4EF7\u683C\u8DCC\u7834\u4E0B\u8F68 ${lo.toFixed(2)}\uFF0C\u5F31\u52BF\u8DCC\u7834\u4FE1\u53F7` };
|
|
33188
|
+
else result = { ...result, signal: "neutral", message: `\u80AF\u7279\u7EB3(${p},2): \u4EF7\u683C\u5728\u901A\u9053\u5185 [${lo.toFixed(2)}, ${up.toFixed(2)}]\uFF0C\u9707\u8361\u8FD0\u884C` };
|
|
33189
|
+
break;
|
|
33190
|
+
}
|
|
33191
|
+
case "pattern": {
|
|
33192
|
+
const patterns = [];
|
|
33193
|
+
const last = candles[candles.length - 1], prev = candles[candles.length - 2];
|
|
33194
|
+
if (detectDoji(last)) patterns.push("\u5341\u5B57\u661F (Doji) \u2014 \u591A\u7A7A\u5747\u8861\uFF0C\u53D8\u76D8\u524D\u5146");
|
|
33195
|
+
if (detectHammer(last)) patterns.push("\u9524\u5B50\u7EBF (Hammer) \u2014 \u5E95\u90E8\u53CD\u8F6C\u4FE1\u53F7\uFF0C\u770B\u6DA8");
|
|
33196
|
+
const eng = detectEngulfing(prev, last);
|
|
33197
|
+
if (eng === "bullish") patterns.push("\u770B\u6DA8\u541E\u6CA1 (Bullish Engulfing) \u2014 \u5F3A\u5E95\u90E8\u53CD\u8F6C\u4FE1\u53F7");
|
|
33198
|
+
if (eng === "bearish") patterns.push("\u770B\u8DCC\u541E\u6CA1 (Bearish Engulfing) \u2014 \u5F3A\u9876\u90E8\u53CD\u8F6C\u4FE1\u53F7");
|
|
33199
|
+
if (candles.length >= 5) {
|
|
33200
|
+
const last5 = candles.slice(-5);
|
|
33201
|
+
if (last5.every((c) => c.c < c.o) && last.c > last.o) patterns.push("\u6668\u661F (Morning Star) \u2014 \u5E95\u90E8\u4E09\u7EBF\u53CD\u8F6C\uFF0C\u770B\u6DA8");
|
|
33202
|
+
if (last5.every((c) => c.c > c.o) && last.c < last.o) patterns.push("\u9EC4\u660F\u661F (Evening Star) \u2014 \u9876\u90E8\u4E09\u7EBF\u53CD\u8F6C\uFF0C\u770B\u8DCC");
|
|
33203
|
+
}
|
|
33204
|
+
result.value = patterns;
|
|
33205
|
+
result.signal = patterns.length > 0 ? patterns[0].includes("Bullish") || patterns[0].includes("Hammer") || patterns[0].includes("Morning") ? "bullish" : "bearish" : "neutral";
|
|
33206
|
+
result.message = patterns.length > 0 ? patterns.join("\uFF1B") : "\u6700\u8FD1\u4E24\u6839K\u7EBF\u672A\u68C0\u6D4B\u5230\u7ECF\u5178\u53CD\u8F6C\u5F62\u6001";
|
|
33207
|
+
break;
|
|
33208
|
+
}
|
|
33209
|
+
}
|
|
33210
|
+
result._summary = `[${instId} ${b}] ${indicator.toUpperCase()}: ${result.message}`;
|
|
33211
|
+
return toResult(result);
|
|
33212
|
+
} catch (e) {
|
|
33213
|
+
return toError(e);
|
|
33214
|
+
}
|
|
33215
|
+
}
|
|
33216
|
+
);
|
|
33217
|
+
server.tool(
|
|
33218
|
+
"okx_indicator_batch",
|
|
33219
|
+
"CAT:[\u884C\u60C5] | ## \u529F\u80FD\uFF1A\u6279\u91CF\u8BA1\u7B97\u591A\u4E2A\u6280\u672F\u6307\u6807\uFF0C\u4E00\u6B21\u6027\u8FD4\u56DE\u5168\u90E8\u6307\u6807\u503C\u548C\u7EFC\u5408\u4EA4\u6613\u4FE1\u53F7\u603B\u7ED3\n## \u573A\u666F\uFF1AAgent \u9700\u8981\u7EFC\u5408\u5206\u6790\u591A\u4E2A\u6307\u6807\uFF08\u5982\u540C\u65F6\u770BRSI+MACD+\u5E03\u6797\u5E26\uFF09\u65F6\u8C03\u7528\uFF0C\u4E00\u6B21\u62FF\u5230\u6240\u6709\u7ED3\u679C\u548C\u7EFC\u5408\u5224\u65AD\n## \u5173\u952E\u8BCD\uFF1A\u6279\u91CF\u6307\u6807, indicator batch, \u591A\u6307\u6807, \u7EFC\u5408\u4FE1\u53F7, \u6280\u672F\u5206\u6790, \u6307\u6807\u7EC4\u5408\n## \u53C2\u6570\uFF1A\n## - instId: \u4EA7\u54C1ID\n## - indicators: \u6307\u6807\u540D\u5217\u8868\uFF0C\u7528\u9017\u53F7\u5206\u9694\u3002\u5982 RSI,MACD,BB,ATR\n## - bar: K\u7EBF\u7C92\u5EA6\uFF0C\u9ED8\u8BA4 1H\n## \u9274\u6743\uFF1APUBLIC\n## \u98CE\u9669\uFF1AREAD\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~3KB\n## \u5173\u8054\uFF1A\u672C\u5DE5\u5177\u6279\u91CF \u2192 \u5355\u6307\u6807\u6DF1\u5165\u7528 okx_indicator \u2192 agent_quick_trade \u4E0B\u5355",
|
|
33220
|
+
{
|
|
33221
|
+
instId: external_exports.string().describe("\u4EA7\u54C1ID\uFF0C\u5982 BTC-USDT"),
|
|
33222
|
+
indicators: external_exports.string().describe("\u6307\u6807\u540D\u5217\u8868\uFF0C\u9017\u53F7\u5206\u9694\u3002\u53EF\u9009: sma,ema,rsi,macd,bb,atr,stoch,wr,cci,obv,vwap,adx,mfi,cmf,supertrend,keltner,pattern"),
|
|
33223
|
+
bar: external_exports.enum(["1m", "5m", "15m", "30m", "1H", "2H", "4H", "6H", "12H", "1D"]).optional().describe("K\u7EBF\u7C92\u5EA6\uFF0C\u9ED8\u8BA41H")
|
|
33224
|
+
},
|
|
33225
|
+
async ({ instId, indicators, bar }) => {
|
|
33226
|
+
try {
|
|
33227
|
+
const b = bar || "1H";
|
|
33228
|
+
const list = indicators.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
|
|
33229
|
+
if (list.length === 0) return toError("indicators \u53C2\u6570\u4E0D\u80FD\u4E3A\u7A7A\uFF0CAgent \u8BF7\u6307\u5B9A\u81F3\u5C11\u4E00\u4E2A\u6307\u6807\u540D");
|
|
33230
|
+
if (list.length > 10) return toError("\u6700\u591A\u540C\u65F6\u8BA1\u7B97 10 \u4E2A\u6307\u6807\uFF0CAgent \u8BF7\u51CF\u5C11\u6570\u91CF");
|
|
33231
|
+
const candles = await fetchCandles(instId, b, 300);
|
|
33232
|
+
if (candles.length < 20) {
|
|
33233
|
+
return toResult({
|
|
33234
|
+
instId,
|
|
33235
|
+
bar: b,
|
|
33236
|
+
error: `\u6570\u636E\u4E0D\u8DB3\uFF1A\u4EC5\u83B7\u53D6 ${candles.length} \u6839K\u7EBF`,
|
|
33237
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
33238
|
+
});
|
|
33239
|
+
}
|
|
33240
|
+
const closes = candles.map((c) => c.c);
|
|
33241
|
+
let bullCount = 0, bearCount = 0;
|
|
33242
|
+
const results = [];
|
|
33243
|
+
for (const ind of list) {
|
|
33244
|
+
const p = { sma: 20, ema: 20, rsi: 14, macd: 12, bb: 20, atr: 14, stoch: 14, wr: 14, cci: 20, obv: 0, vwap: 0, adx: 14, mfi: 14, cmf: 20, supertrend: 10, keltner: 20, pattern: 0 }[ind] || 14;
|
|
33245
|
+
let item = { indicator: ind };
|
|
33246
|
+
try {
|
|
33247
|
+
switch (ind) {
|
|
33248
|
+
case "rsi": {
|
|
33249
|
+
const v = calcRSI(closes, p);
|
|
33250
|
+
item.value = v[v.length - 1].toFixed(2);
|
|
33251
|
+
const sig = rsiSignal(v[v.length - 1]);
|
|
33252
|
+
item.signal = sig.signal;
|
|
33253
|
+
item.message = sig.message;
|
|
33254
|
+
break;
|
|
33255
|
+
}
|
|
33256
|
+
case "macd": {
|
|
33257
|
+
const m = calcMACD(closes, 12, 26, 9);
|
|
33258
|
+
const h = m.histogram[m.histogram.length - 1];
|
|
33259
|
+
item.value = `${h.toFixed(4)}`;
|
|
33260
|
+
const prevH = m.histogram[m.histogram.length - 2] || 0;
|
|
33261
|
+
const sig = macdSignal(h, prevH);
|
|
33262
|
+
item.signal = sig.signal;
|
|
33263
|
+
item.message = sig.message;
|
|
33264
|
+
break;
|
|
33265
|
+
}
|
|
33266
|
+
case "bb": {
|
|
33267
|
+
const bb = calcBollinger(closes, p, 2);
|
|
33268
|
+
const pct = bb.pctB[bb.pctB.length - 1];
|
|
33269
|
+
item.value = `pctB:${pct.toFixed(2)}`;
|
|
33270
|
+
if (pct > 1) {
|
|
33271
|
+
item.signal = "bearish";
|
|
33272
|
+
item.message = "\u7A81\u7834\u4E0A\u8F68";
|
|
33273
|
+
} else if (pct < 0) {
|
|
33274
|
+
item.signal = "bullish";
|
|
33275
|
+
item.message = "\u8DCC\u7834\u4E0B\u8F68";
|
|
33276
|
+
} else {
|
|
33277
|
+
item.signal = "neutral";
|
|
33278
|
+
item.message = "\u901A\u9053\u5185";
|
|
33279
|
+
}
|
|
33280
|
+
;
|
|
33281
|
+
break;
|
|
33282
|
+
}
|
|
33283
|
+
case "atr": {
|
|
33284
|
+
const a = calcATR(candles, p);
|
|
33285
|
+
item.value = a[a.length - 1].toFixed(4);
|
|
33286
|
+
item.signal = "neutral";
|
|
33287
|
+
item.message = `\u6CE2\u52A8\u7387: ${(a[a.length - 1] / candles[candles.length - 1].c * 100).toFixed(2)}%`;
|
|
33288
|
+
break;
|
|
33289
|
+
}
|
|
33290
|
+
case "stoch": {
|
|
33291
|
+
const s = calcStoch(candles, p, 3);
|
|
33292
|
+
item.value = `K:${s.k[s.k.length - 1].toFixed(1)},D:${s.d[s.d.length - 1].toFixed(1)}`;
|
|
33293
|
+
const sig = stochSignal(s.k[s.k.length - 1], s.d[s.d.length - 1]);
|
|
33294
|
+
item.signal = sig.signal;
|
|
33295
|
+
item.message = sig.message;
|
|
33296
|
+
break;
|
|
33297
|
+
}
|
|
33298
|
+
case "wr": {
|
|
33299
|
+
const w = calcWR(candles, p);
|
|
33300
|
+
item.value = w[w.length - 1].toFixed(1);
|
|
33301
|
+
item.signal = w[w.length - 1] > -20 ? "bearish" : w[w.length - 1] < -80 ? "bullish" : "neutral";
|
|
33302
|
+
item.message = `W%R=${item.value}`;
|
|
33303
|
+
break;
|
|
33304
|
+
}
|
|
33305
|
+
case "cci": {
|
|
33306
|
+
const c = calcCCI(candles, p);
|
|
33307
|
+
item.value = c[c.length - 1].toFixed(1);
|
|
33308
|
+
item.signal = Math.abs(c[c.length - 1]) > 100 ? c[c.length - 1] > 0 ? "bearish" : "bullish" : "neutral";
|
|
33309
|
+
item.message = `CCI=${item.value}`;
|
|
33310
|
+
break;
|
|
33311
|
+
}
|
|
33312
|
+
case "obv": {
|
|
33313
|
+
const o = calcOBV(candles);
|
|
33314
|
+
item.value = o[o.length - 1].toFixed(0);
|
|
33315
|
+
item.signal = o[o.length - 1] > o[o.length - 20] ? "bullish" : "bearish";
|
|
33316
|
+
item.message = "\u91CF\u4EF7\u5206\u6790";
|
|
33317
|
+
break;
|
|
33318
|
+
}
|
|
33319
|
+
case "vwap": {
|
|
33320
|
+
const vw = calcVWAP(candles);
|
|
33321
|
+
item.value = vw[vw.length - 1].toFixed(2);
|
|
33322
|
+
item.signal = candles[candles.length - 1].c > vw[vw.length - 1] ? "bullish" : "bearish";
|
|
33323
|
+
item.message = "\u6210\u4EA4\u91CF\u52A0\u6743\u5747\u4EF7";
|
|
33324
|
+
break;
|
|
33325
|
+
}
|
|
33326
|
+
case "adx": {
|
|
33327
|
+
const ax = calcADX(candles, p);
|
|
33328
|
+
const a = ax.adx[ax.adx.length - 1] ?? 0;
|
|
33329
|
+
const pd = ax.plusDI[ax.plusDI.length - 1] ?? 0;
|
|
33330
|
+
const md = ax.minusDI[ax.minusDI.length - 1] ?? 0;
|
|
33331
|
+
item.value = `${a.toFixed(1)}`;
|
|
33332
|
+
const sig = adxSignal(a, pd, md);
|
|
33333
|
+
item.signal = sig.signal;
|
|
33334
|
+
item.message = sig.message;
|
|
33335
|
+
break;
|
|
33336
|
+
}
|
|
33337
|
+
case "mfi": {
|
|
33338
|
+
const mf = calcMFI(candles, p);
|
|
33339
|
+
const v = mf[mf.length - 1] ?? 50;
|
|
33340
|
+
item.value = v.toFixed(1);
|
|
33341
|
+
item.signal = v > 80 ? "bearish" : v < 20 ? "bullish" : "neutral";
|
|
33342
|
+
item.message = `MFI=${item.value}`;
|
|
33343
|
+
break;
|
|
33344
|
+
}
|
|
33345
|
+
case "cmf": {
|
|
33346
|
+
const cm = calcCMF(candles, p);
|
|
33347
|
+
const v = cm[cm.length - 1] ?? 0;
|
|
33348
|
+
item.value = v.toFixed(3);
|
|
33349
|
+
item.signal = v > 0 ? "bullish" : "bearish";
|
|
33350
|
+
item.message = `CMF=${item.value}`;
|
|
33351
|
+
break;
|
|
33352
|
+
}
|
|
33353
|
+
case "supertrend": {
|
|
33354
|
+
const st = calcSupertrend(candles, p, 3);
|
|
33355
|
+
const trend = st.trend[st.trend.length - 1] ?? 0;
|
|
33356
|
+
const dir = st.direction[st.direction.length - 1] ?? 0;
|
|
33357
|
+
item.value = trend.toFixed(2);
|
|
33358
|
+
item.signal = dir === 1 ? "bullish" : "bearish";
|
|
33359
|
+
item.message = `${item.signal === "bullish" ? "\u591A\u5934" : "\u7A7A\u5934"}`;
|
|
33360
|
+
break;
|
|
33361
|
+
}
|
|
33362
|
+
default: {
|
|
33363
|
+
item.value = "N/A";
|
|
33364
|
+
item.signal = "neutral";
|
|
33365
|
+
item.message = `\u6307\u6807 ${ind} \u6682\u4E0D\u652F\u6301\u6279\u91CF\u8BA1\u7B97\uFF0C\u8BF7\u7528 okx_indicator \u5355\u72EC\u67E5\u8BE2`;
|
|
33366
|
+
break;
|
|
33367
|
+
}
|
|
33368
|
+
}
|
|
33369
|
+
} catch {
|
|
33370
|
+
item.value = "error";
|
|
33371
|
+
item.signal = "neutral";
|
|
33372
|
+
item.message = "\u8BA1\u7B97\u5931\u8D25";
|
|
33373
|
+
}
|
|
33374
|
+
if (item.signal === "bullish") bullCount++;
|
|
33375
|
+
else if (item.signal === "bearish") bearCount++;
|
|
33376
|
+
results.push(item);
|
|
33377
|
+
}
|
|
33378
|
+
const consensus = bullCount > bearCount + 2 ? "bullish" : bearCount > bullCount + 2 ? "bearish" : "neutral";
|
|
33379
|
+
const consensusMsg = consensus === "bullish" ? `\u{1F7E2} \u7EFC\u5408\u504F\u591A\uFF08${bullCount}\u4E2A\u770B\u6DA8 vs ${bearCount}\u4E2A\u770B\u8DCC\uFF09\uFF0C\u591A\u4E2A\u6307\u6807\u786E\u8BA4\u591A\u5934\u4FE1\u53F7` : consensus === "bearish" ? `\u{1F534} \u7EFC\u5408\u504F\u7A7A\uFF08${bearCount}\u4E2A\u770B\u8DCC vs ${bullCount}\u4E2A\u770B\u6DA8\uFF09\uFF0C\u591A\u4E2A\u6307\u6807\u786E\u8BA4\u7A7A\u5934\u4FE1\u53F7` : `\u{1F7E1} \u4FE1\u53F7\u5206\u6B67\uFF08${bullCount}\u591A ${bearCount}\u7A7A\uFF09\uFF0C\u65B9\u5411\u4E0D\u660E\u786E\uFF0C\u5EFA\u8BAE\u89C2\u671B`;
|
|
33380
|
+
return toResult({
|
|
33381
|
+
instId,
|
|
33382
|
+
bar: b,
|
|
33383
|
+
indicators: results,
|
|
33384
|
+
consensus: { signal: consensus, bullCount, bearCount, neutralCount: results.length - bullCount - bearCount, message: consensusMsg },
|
|
33385
|
+
_summary: `[${instId} ${b}] \u5171 ${results.length} \u4E2A\u6307\u6807\u3002${consensusMsg}`,
|
|
33386
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
33387
|
+
});
|
|
33388
|
+
} catch (e) {
|
|
33389
|
+
return toError(e);
|
|
33390
|
+
}
|
|
33391
|
+
}
|
|
33392
|
+
);
|
|
33393
|
+
}
|
|
33394
|
+
|
|
33395
|
+
// src/tools/smartmoney.ts
|
|
33396
|
+
function registerSmartMoneyTools(server, auth) {
|
|
33397
|
+
server.tool(
|
|
33398
|
+
"okx_smart_leaderboard",
|
|
33399
|
+
"CAT:[Smart Money] | ## \u529F\u80FD\uFF1A\u4EA4\u6613\u5458\u6392\u884C\u699C\u2014\u2014\u6309\u6536\u76CA\u7387/\u603B\u6536\u76CA\u6392\u5E8F\uFF0C\u542B\u8FD1N\u65E5\u80DC\u7387\u3001\u6700\u5927\u56DE\u64A4\u3001\u8DDF\u5355\u4EBA\u6570\n## \u573A\u666F\uFF1AAgent \u56DE\u7B54\u300C\u54EA\u4E9B\u4EA4\u6613\u5458\u5389\u5BB3\u300D\u300C\u8DDF\u8C01\u8D5A\u94B1\u300D\u3001\u5BFB\u627E\u4F18\u8D28\u4EA4\u6613\u5458\u3001\u5206\u6790\u806A\u660E\u94B1\u6D41\u5411\n## \u5173\u952E\u8BCD\uFF1A\u4EA4\u6613\u5458, \u6392\u884C\u699C, leaderboard, \u806A\u660E\u94B1, smart money, \u8DDF\u5355, \u6536\u76CA\u6392\u540D\n## \u53C2\u6570\uFF1A\n## - instType: \u4EA7\u54C1\u7C7B\u578B\u3002SPOT=\u73B0\u8D27, SWAP=\u6C38\u7EED\u3002\u9ED8\u8BA4SPOT\n## - sortBy: \u6392\u5E8F\u5B57\u6BB5\u3002pnl=\u6536\u76CA\u7387, totalPnl=\u603B\u6536\u76CA, followers=\u8DDF\u5355\u4EBA\u6570\n## - topN: \u8FD4\u56DE\u6761\u6570\uFF0C\u9ED8\u8BA410\n## \u9274\u6743\uFF1APUBLIC \u2014 \u516C\u5F00\u63A5\u53E3\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~3KB\n## \u5173\u8054\uFF1A\u672C\u5DE5\u5177\u6392\u884C \u2192 okx_smart_trader_detail \u770B\u8BE6\u60C5 \u2192 okx_copy_trader \u8DDF\u5355\uFF08\u9700\u786E\u8BA4\uFF09",
|
|
33400
|
+
{
|
|
33401
|
+
instType: external_exports.enum(["SPOT", "SWAP"]).optional().describe("\u4EA7\u54C1\u7C7B\u578B\uFF0C\u9ED8\u8BA4SPOT"),
|
|
33402
|
+
sortBy: external_exports.enum(["pnl", "totalPnl", "followers"]).optional().describe("\u6392\u5E8F\u3002pnl=\u6536\u76CA\u7387, totalPnl=\u603B\u6536\u76CA, followers=\u8DDF\u5355\u4EBA\u6570"),
|
|
33403
|
+
topN: external_exports.number().int().min(3).max(50).optional().describe("\u8FD4\u56DE\u6761\u6570\uFF0C\u9ED8\u8BA410")
|
|
33404
|
+
},
|
|
33405
|
+
async ({ instType, sortBy, topN }) => {
|
|
33406
|
+
try {
|
|
33407
|
+
const it = instType || "SPOT";
|
|
33408
|
+
const n = topN || 10;
|
|
33409
|
+
const sb = sortBy || "pnl";
|
|
33410
|
+
const raw = await publicApi.getPublicLeadTraders();
|
|
33411
|
+
if (!raw || raw.length === 0) {
|
|
33412
|
+
return toResult({ leaderboard: [], count: 0, message: "\u6682\u65E0\u4EA4\u6613\u5458\u6570\u636E", tsIso: (/* @__PURE__ */ new Date()).toISOString() });
|
|
33413
|
+
}
|
|
33414
|
+
const traders = raw.map((t) => ({
|
|
33415
|
+
uniqueCode: t.uniqueCode,
|
|
33416
|
+
nickName: t.nickName,
|
|
33417
|
+
instType: it,
|
|
33418
|
+
pnl: parseFloat(t.pnl ?? "0"),
|
|
33419
|
+
totalPnl: parseFloat(t.totalPnl ?? "0"),
|
|
33420
|
+
winRate: parseFloat(t.winRate ?? "0"),
|
|
33421
|
+
drawdown: t.maxDrawdown,
|
|
33422
|
+
followers: parseInt(t.followerCount ?? "0"),
|
|
33423
|
+
sharpeRatio: t.sharpeRatio,
|
|
33424
|
+
profitSharingRatio: t.profitSharingRatio,
|
|
33425
|
+
filledPnL: parseFloat(t.filledPnl ?? "0"),
|
|
33426
|
+
beginTs: t.beginTs ? new Date(parseInt(t.beginTs)).toISOString() : void 0
|
|
33427
|
+
})).filter((t) => t.pnl > 0 || t.totalPnl > 0);
|
|
33428
|
+
if (sb === "pnl") traders.sort((a, b) => b.pnl - a.pnl);
|
|
33429
|
+
else if (sb === "totalPnl") traders.sort((a, b) => b.totalPnl - a.totalPnl);
|
|
33430
|
+
else traders.sort((a, b) => b.followers - a.followers);
|
|
33431
|
+
const top = traders.slice(0, n);
|
|
33432
|
+
return toResult({
|
|
33433
|
+
leaderboard: top.map((t, i) => ({ rank: i + 1, ...t, pnl: t.pnl.toFixed(2) + "%", totalPnl: "$" + t.totalPnl.toFixed(2) })),
|
|
33434
|
+
total: traders.length,
|
|
33435
|
+
sortBy: sb,
|
|
33436
|
+
_summary: `\u{1F3C6} ${it} \u4EA4\u6613\u5458\u6392\u884C\u699C Top${n}: ${top.slice(0, 3).map((t) => `${t.nickName}(${t.pnl.toFixed(1)}%)`).join(" | ")}\u3002\u5171 ${traders.length} \u4F4D\u4EA4\u6613\u5458\u3002`,
|
|
33437
|
+
tip: "\u60F3\u770B\u67D0\u4F4D\u4EA4\u6613\u5458\u7684\u8BE6\u7EC6\u6570\u636E\uFF0C\u7528 okx_smart_trader_detail { uniqueCode }",
|
|
33438
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
33439
|
+
});
|
|
33440
|
+
} catch (e) {
|
|
33441
|
+
return toError(e);
|
|
33442
|
+
}
|
|
33443
|
+
}
|
|
33444
|
+
);
|
|
33445
|
+
server.tool(
|
|
33446
|
+
"okx_smart_trader_detail",
|
|
33447
|
+
"CAT:[Smart Money] | ## \u529F\u80FD\uFF1A\u5355\u4EA4\u6613\u5458\u5168\u666F\u5206\u6790\u2014\u2014\u6536\u76CA\u7387+\u80DC\u7387+\u56DE\u64A4+\u5F53\u524D\u6301\u4ED3+\u8FD130\u5929PnL\u66F2\u7EBF\n## \u573A\u666F\uFF1AAgent \u6DF1\u5165\u4E86\u89E3\u67D0\u4F4D\u4EA4\u6613\u5458\uFF08\u4ECE\u6392\u884C\u699C\u70B9\u51FB\u8FDB\u5165\uFF09\u3001\u5224\u65AD\u662F\u5426\u503C\u5F97\u8DDF\u5355\n## \u5173\u952E\u8BCD\uFF1A\u4EA4\u6613\u5458\u8BE6\u60C5, trader detail, \u8DDF\u5355\u5206\u6790, \u6301\u4ED3\u67E5\u770B, \u4E1A\u7EE9\u5206\u6790\n## \u53C2\u6570\uFF1A\n## - uniqueCode: \u4EA4\u6613\u5458\u552F\u4E00\u7801\uFF08\u4ECE\u6392\u884C\u699C\u4E2D\u83B7\u53D6\uFF09\n## - instType: \u4EA7\u54C1\u7C7B\u578B\u3002SPOT=\u73B0\u8D27, SWAP=\u6C38\u7EED\n## \u9274\u6743\uFF1APUBLIC \u2014 \u516C\u5F00\u63A5\u53E3\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~3KB\n## \u5173\u8054\uFF1Aokx_smart_leaderboard \u6392\u884C \u2192 \u672C\u5DE5\u5177\u8BE6\u60C5 \u2192 okx_copy_trader \u8DDF\u5355",
|
|
33448
|
+
{
|
|
33449
|
+
uniqueCode: external_exports.string().describe("\u4EA4\u6613\u5458\u552F\u4E00\u7801\uFF08\u5982 A12345678\uFF09"),
|
|
33450
|
+
instType: external_exports.enum(["SPOT", "SWAP"]).optional().describe("\u4EA7\u54C1\u7C7B\u578B\uFF0C\u9ED8\u8BA4SPOT")
|
|
33451
|
+
},
|
|
33452
|
+
async ({ uniqueCode, instType }) => {
|
|
33453
|
+
try {
|
|
33454
|
+
const it = instType || "SPOT";
|
|
33455
|
+
const [stats, pnl, positions] = await Promise.allSettled([
|
|
33456
|
+
publicApi.getPublicLeadTraderStats(uniqueCode, it, "30"),
|
|
33457
|
+
publicApi.getPublicLeadTraderPnl(uniqueCode, "30"),
|
|
33458
|
+
publicApi.getLeadTraderPositions(uniqueCode, it)
|
|
33459
|
+
]);
|
|
33460
|
+
const sOk = stats.status === "fulfilled" ? stats.value?.[0] ?? {} : {};
|
|
33461
|
+
const pOk = pnl.status === "fulfilled" ? pnl.value ?? [] : [];
|
|
33462
|
+
const posOk = positions.status === "fulfilled" ? positions.value ?? [] : [];
|
|
33463
|
+
const currentPos = posOk.filter((p) => parseFloat(p.pos || "0") !== 0).map((p) => ({
|
|
33464
|
+
instId: p.instId,
|
|
33465
|
+
posSide: p.posSide,
|
|
33466
|
+
pos: p.pos,
|
|
33467
|
+
avgPx: p.avgOpenPx,
|
|
33468
|
+
markPx: p.markPx,
|
|
33469
|
+
upl: p.upl,
|
|
33470
|
+
uplRatio: p.uplRatio,
|
|
33471
|
+
lever: p.lever
|
|
33472
|
+
}));
|
|
33473
|
+
const pnlCurve = pOk.slice(0, 30).map((p) => ({
|
|
33474
|
+
date: p.ts ? new Date(parseInt(p.ts)).toISOString().slice(0, 10) : void 0,
|
|
33475
|
+
pnl: parseFloat(p.pnl ?? "0").toFixed(2)
|
|
33476
|
+
}));
|
|
33477
|
+
return toResult({
|
|
33478
|
+
uniqueCode,
|
|
33479
|
+
profile: {
|
|
33480
|
+
nickName: sOk.nickName,
|
|
33481
|
+
pnl: parseFloat(sOk.pnl ?? "0").toFixed(2) + "%",
|
|
33482
|
+
totalPnl: "$" + parseFloat(sOk.totalPnl ?? "0").toFixed(2),
|
|
33483
|
+
winRate: parseFloat(sOk.winRate ?? "0").toFixed(1) + "%",
|
|
33484
|
+
maxDrawdown: sOk.maxDrawdown,
|
|
33485
|
+
sharpeRatio: sOk.sharpeRatio,
|
|
33486
|
+
totalEquity: sOk.totalEquity,
|
|
33487
|
+
followerCount: sOk.followerCount,
|
|
33488
|
+
tradesPerDay: sOk.tradesPerDay,
|
|
33489
|
+
avgHoldingHours: sOk.avgHoldingHours
|
|
33490
|
+
},
|
|
33491
|
+
positions: {
|
|
33492
|
+
activeCount: currentPos.length,
|
|
33493
|
+
list: currentPos
|
|
33494
|
+
},
|
|
33495
|
+
pnlTimeline: pnlCurve,
|
|
33496
|
+
_summary: `${sOk.nickName || uniqueCode}: ${sOk.pnl || "?"}% \u6536\u76CA\u7387\uFF0C${sOk.winRate || "?"}% \u80DC\u7387\uFF0C${currentPos.length} \u4E2A\u5F53\u524D\u6301\u4ED3\u3002\u6700\u5927\u56DE\u64A4 ${sOk.maxDrawdown || "?"}\u3002`,
|
|
33497
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
33498
|
+
});
|
|
33499
|
+
} catch (e) {
|
|
33500
|
+
return toError(e);
|
|
33501
|
+
}
|
|
33502
|
+
}
|
|
33503
|
+
);
|
|
33504
|
+
server.tool(
|
|
33505
|
+
"okx_smart_sentiment",
|
|
33506
|
+
"CAT:[Smart Money] | ## \u529F\u80FD\uFF1A\u5E02\u573A\u60C5\u7EEA\u4EEA\u8868\u76D8\u2014\u2014\u7EFC\u5408\u591A\u7A7A\u6BD4\u3001\u671F\u6743PCR\u3001\u8D44\u91D1\u8D39\u7387\u3001\u6210\u4EA4\u91CF\uFF0C\u7ED9\u51FA\u91CF\u5316\u60C5\u7EEA\u8BC4\u5206\n## \u573A\u666F\uFF1AAgent \u56DE\u7B54\u300C\u73B0\u5728\u5E02\u573A\u60C5\u7EEA\u600E\u4E48\u6837\u300D\u300C\u6563\u6237\u548C\u806A\u660E\u94B1\u5728\u505A\u4EC0\u4E48\u300D\u300C\u8BE5\u8FFD\u591A\u8FD8\u662F\u89C2\u671B\u300D\n## \u5173\u952E\u8BCD\uFF1A\u5E02\u573A\u60C5\u7EEA, sentiment, \u591A\u7A7A\u6BD4, PCR, \u8D44\u91D1\u8D39\u7387, \u6050\u614C\u8D2A\u5A6A, \u60C5\u7EEA\u6307\u6807\n## \u53C2\u6570\uFF1A\n## - instFamily: \u4EA7\u54C1\u65CF\uFF0C\u5982 BTC-USD\u3002\u9ED8\u8BA4 BTC-USD\n## \u9274\u6743\uFF1APUBLIC \u2014 \u516C\u5F00\u63A5\u53E3\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~2KB\n## \u5173\u8054\uFF1A\u672C\u5DE5\u5177\u770B\u60C5\u7EEA \u2192 agent_market_scan \u770B\u5F02\u52A8 \u2192 agent_quick_trade \u4E0B\u5355",
|
|
33507
|
+
{
|
|
33508
|
+
instFamily: external_exports.string().optional().describe("\u4EA7\u54C1\u65CF\uFF0C\u5982 BTC-USD\u3001ETH-USD\u3002\u9ED8\u8BA4 BTC-USD")
|
|
33509
|
+
},
|
|
33510
|
+
async ({ instFamily }) => {
|
|
33511
|
+
try {
|
|
33512
|
+
const family = instFamily || "BTC-USD";
|
|
33513
|
+
const instId = family.replace("-", "-") + "-SWAP";
|
|
33514
|
+
const ccy = family.split("-")[0];
|
|
33515
|
+
const fetchers = {
|
|
33516
|
+
lsRatio: publicApi.getLongShortRatio(ccy),
|
|
33517
|
+
pcr: publicApi.getOptionPutCallRatio(ccy),
|
|
33518
|
+
fundingRate: publicApi.getFundingRate(instId),
|
|
33519
|
+
topLSRatio: publicApi.getTopTraderLongShortRatio(instId)
|
|
33520
|
+
};
|
|
33521
|
+
const entries = Object.entries(fetchers);
|
|
33522
|
+
const keys = entries.map((e) => e[0]);
|
|
33523
|
+
const results = await Promise.allSettled(entries.map((e) => e[1]));
|
|
33524
|
+
const get = (name) => {
|
|
33525
|
+
const idx = keys.indexOf(name);
|
|
33526
|
+
if (idx < 0) return null;
|
|
33527
|
+
if (results[idx].status === "rejected") return null;
|
|
33528
|
+
return results[idx].value;
|
|
33529
|
+
};
|
|
33530
|
+
const lsArr = get("lsRatio") ?? [];
|
|
33531
|
+
const ls = lsArr[0];
|
|
33532
|
+
const lsRatio = parseFloat(ls?.lsRatio ?? "0");
|
|
33533
|
+
const lsRatioPrev = parseFloat(ls?.lsRatioPrev ?? lsRatio);
|
|
33534
|
+
const pcrArr = get("pcr") ?? [];
|
|
33535
|
+
const pcr = pcrArr[0];
|
|
33536
|
+
const pcrRatio = parseFloat(pcr?.pcrRatio ?? "0");
|
|
33537
|
+
const frArr = get("fundingRate") ?? [];
|
|
33538
|
+
const fr = frArr[0];
|
|
33539
|
+
const fundingRate = parseFloat(fr?.fundingRate ?? "0");
|
|
33540
|
+
const topLSArr = get("topLSRatio") ?? [];
|
|
33541
|
+
const topLS = topLSArr[0];
|
|
33542
|
+
const topLsRatio = parseFloat(topLS?.lsRatio ?? "0");
|
|
33543
|
+
let score = 50;
|
|
33544
|
+
if (lsRatio > 1.5) score += 15;
|
|
33545
|
+
else if (lsRatio > 1.2) score += 8;
|
|
33546
|
+
else if (lsRatio < 0.8) score -= 8;
|
|
33547
|
+
else if (lsRatio < 0.5) score -= 15;
|
|
33548
|
+
if (topLsRatio > 1.2 && lsRatio < 1) score += 10;
|
|
33549
|
+
if (pcrRatio > 1.2) score -= 12;
|
|
33550
|
+
else if (pcrRatio > 0.8) score -= 5;
|
|
33551
|
+
else if (pcrRatio < 0.5) score += 5;
|
|
33552
|
+
else if (pcrRatio < 0.3) score += 10;
|
|
33553
|
+
if (fundingRate > 1e-3) score -= 10;
|
|
33554
|
+
else if (fundingRate > 5e-4) score -= 5;
|
|
33555
|
+
else if (fundingRate < -5e-4) score += 5;
|
|
33556
|
+
score = Math.max(0, Math.min(100, score));
|
|
33557
|
+
const sentiment = score >= 70 ? "\u{1F7E2} \u6781\u5EA6\u770B\u591A" : score >= 55 ? "\u{1F7E2} \u504F\u591A" : score >= 45 ? "\u{1F7E1} \u4E2D\u6027" : score <= 30 ? "\u{1F534} \u6781\u5EA6\u770B\u7A7A" : "\u{1F534} \u504F\u7A7A";
|
|
33558
|
+
const signals = [];
|
|
33559
|
+
if (lsRatio > 1.5) signals.push(`\u591A\u7A7A\u6BD4 ${lsRatio.toFixed(2)} \u6781\u9AD8\uFF0C\u6563\u6237\u9AD8\u5EA6\u770B\u591A\uFF08\u8B66\u60D5\u53CD\u8F6C\uFF09`);
|
|
33560
|
+
else if (lsRatio > 1.2) signals.push(`\u591A\u7A7A\u6BD4 ${lsRatio.toFixed(2)}\uFF0C\u6563\u6237\u504F\u591A`);
|
|
33561
|
+
else if (lsRatio < 0.8) signals.push(`\u591A\u7A7A\u6BD4 ${lsRatio.toFixed(2)}\uFF0C\u6563\u6237\u504F\u7A7A`);
|
|
33562
|
+
if (topLsRatio > 1.2 && lsRatio < 1) signals.push("\u806A\u660E\u94B1\uFF08Top\u4EA4\u6613\u5458\uFF09\u4E0E\u6563\u6237\u65B9\u5411\u5206\u6B67\uFF1A\u806A\u660E\u94B1\u770B\u591A\uFF0C\u6563\u6237\u770B\u7A7A");
|
|
33563
|
+
if (pcrRatio > 1) signals.push(`PCR ${pcrRatio.toFixed(2)}\uFF0C\u671F\u6743\u5E02\u573A\u907F\u9669\u60C5\u7EEA\u91CD\uFF08\u66F4\u591A\u4EBA\u4E70Put\uFF09`);
|
|
33564
|
+
else if (pcrRatio < 0.5) signals.push(`PCR ${pcrRatio.toFixed(2)}\uFF0C\u671F\u6743\u5E02\u573A\u770B\u6DA8\u60C5\u7EEA\u6D53\uFF08\u4E70Call\u4E3A\u4E3B\uFF09`);
|
|
33565
|
+
if (Math.abs(fundingRate) > 1e-3) signals.push(`\u8D44\u91D1\u8D39\u7387 ${(fundingRate * 100).toFixed(3)}%\uFF0C${fundingRate > 0 ? "\u591A\u5934\u62E5\u6324\uFF0C\u6CE8\u610F\u56DE\u8C03" : "\u7A7A\u5934\u62E5\u6324\uFF0C\u6CE8\u610F\u8F67\u7A7A"}`);
|
|
33566
|
+
return toResult({
|
|
33567
|
+
instFamily,
|
|
33568
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
33569
|
+
sentiment: { score, label: sentiment },
|
|
33570
|
+
metrics: {
|
|
33571
|
+
lsRatio: { value: lsRatio.toFixed(2), change: (lsRatio - lsRatioPrev).toFixed(2), label: "\u591A\u7A7A\u6BD4\uFF08\u6563\u6237\uFF09" },
|
|
33572
|
+
topLsRatio: { value: topLsRatio.toFixed(2), label: "\u591A\u7A7A\u6BD4\uFF08Top\u4EA4\u6613\u5458\uFF09" },
|
|
33573
|
+
pcr: { value: pcrRatio.toFixed(2), label: "Put/Call Ratio" },
|
|
33574
|
+
fundingRate: { value: (fundingRate * 100).toFixed(4) + "%", label: "\u8D44\u91D1\u8D39\u7387" }
|
|
33575
|
+
},
|
|
33576
|
+
signals,
|
|
33577
|
+
_summary: `${family} \u5E02\u573A\u60C5\u7EEA: ${sentiment}\uFF08\u8BC4\u5206 ${score}/100\uFF09\u3002${signals.slice(0, 2).join("\u3002")}`,
|
|
33578
|
+
tip: "\u60C5\u7EEA\u8BC4\u5206\u4EC5\u4F5C\u53C2\u8003\uFF0C\u4E0D\u6784\u6210\u6295\u8D44\u5EFA\u8BAE\u3002\u7ED3\u5408\u6280\u672F\u6307\u6807\u548C\u98CE\u9669\u7BA1\u7406\u51B3\u7B56\u3002"
|
|
31909
33579
|
});
|
|
31910
33580
|
} catch (e) {
|
|
31911
33581
|
return toError(e);
|
|
@@ -32992,36 +34662,85 @@ function registerAgentHubTools(server) {
|
|
|
32992
34662
|
|
|
32993
34663
|
// src/index.ts
|
|
32994
34664
|
async function main() {
|
|
32995
|
-
const VERSION = "0.2.
|
|
34665
|
+
const VERSION = "0.2.45";
|
|
32996
34666
|
const server = new McpServer({
|
|
32997
34667
|
name: "hvip-mcp",
|
|
32998
34668
|
version: VERSION,
|
|
32999
|
-
description: "hvip MCP Server \u2014
|
|
34669
|
+
description: "hvip MCP Server \u2014 362 \u5DE5\u5177\u8986\u76D6 97.7% OKX REST API\uFF0C\u542B\u4EA4\u6613/\u884C\u60C5/\u8D44\u91D1/\u7B56\u7565/\u9884\u6D4B\u5E02\u573A/\u6280\u672F\u6307\u6807/Smart Money\uFF08\u975E OKX \u5B98\u65B9\u4EA7\u54C1\uFF09\u3002\u4ED3\u5E93: https://github.com/okx-wallet-H/hvip-mcp"
|
|
33000
34670
|
});
|
|
33001
34671
|
const auth = getAuth();
|
|
33002
|
-
|
|
33003
|
-
|
|
33004
|
-
|
|
33005
|
-
|
|
33006
|
-
|
|
33007
|
-
|
|
33008
|
-
|
|
33009
|
-
|
|
33010
|
-
|
|
33011
|
-
|
|
33012
|
-
|
|
33013
|
-
|
|
33014
|
-
|
|
33015
|
-
|
|
33016
|
-
|
|
33017
|
-
|
|
33018
|
-
|
|
33019
|
-
|
|
33020
|
-
|
|
33021
|
-
|
|
33022
|
-
|
|
33023
|
-
|
|
34672
|
+
const READ_ONLY = process.env.OKX_READ_ONLY === "true";
|
|
34673
|
+
let skipped = 0;
|
|
34674
|
+
const skipLog = [];
|
|
34675
|
+
function createReadOnlyProxy(s) {
|
|
34676
|
+
const orig = s.tool?.bind?.(s) ?? s.tool.bind(s);
|
|
34677
|
+
s.tool = function(name, ...args) {
|
|
34678
|
+
const risk = classifyRisk(name);
|
|
34679
|
+
if (risk !== "READ") {
|
|
34680
|
+
skipped++;
|
|
34681
|
+
skipLog.push(`${name} (${risk})`);
|
|
34682
|
+
return;
|
|
34683
|
+
}
|
|
34684
|
+
return orig(name, ...args);
|
|
34685
|
+
};
|
|
34686
|
+
return s;
|
|
34687
|
+
}
|
|
34688
|
+
const effectiveServer = READ_ONLY ? createReadOnlyProxy(server) : server;
|
|
34689
|
+
registerMarketTools(effectiveServer);
|
|
34690
|
+
registerPublicTools(effectiveServer, auth);
|
|
34691
|
+
registerStatsTools(effectiveServer);
|
|
34692
|
+
registerSpreadTools(effectiveServer, auth);
|
|
34693
|
+
registerOutcomesTools(effectiveServer);
|
|
34694
|
+
registerAccountTools(effectiveServer, auth);
|
|
34695
|
+
registerTradingTools(effectiveServer, auth);
|
|
34696
|
+
registerAlgoTools(effectiveServer, auth);
|
|
34697
|
+
registerBotTools(effectiveServer, auth);
|
|
34698
|
+
registerCopyTools(effectiveServer, auth);
|
|
34699
|
+
registerSignalTools(effectiveServer, auth);
|
|
34700
|
+
registerFundingTools(effectiveServer, auth);
|
|
34701
|
+
registerSubAccountTools(effectiveServer, auth);
|
|
34702
|
+
registerFinanceTools(effectiveServer, auth);
|
|
34703
|
+
registerAffiliateTools(effectiveServer, auth);
|
|
34704
|
+
registerFiatTools(effectiveServer, auth);
|
|
34705
|
+
registerRfqTools(effectiveServer, auth);
|
|
34706
|
+
registerAgentUtils(effectiveServer, auth);
|
|
34707
|
+
registerIndicatorTools(effectiveServer);
|
|
34708
|
+
registerSmartMoneyTools(effectiveServer, auth);
|
|
34709
|
+
registerXLayerWSTools(effectiveServer);
|
|
34710
|
+
registerWsTools(effectiveServer);
|
|
34711
|
+
registerAgentHubTools(effectiveServer);
|
|
34712
|
+
if (READ_ONLY) {
|
|
34713
|
+
let authStatus = "\u672A\u914D\u7F6E";
|
|
34714
|
+
if (auth) {
|
|
34715
|
+
try {
|
|
34716
|
+
authStatus = "\u5DF2\u914D\u7F6E\uFF08\u53EA\u8BFB\u6A21\u5F0F\uFF0C\u4EC5\u66B4\u9732 READ \u7EA7\u522B\u5DE5\u5177\uFF09";
|
|
34717
|
+
} catch {
|
|
34718
|
+
authStatus = "\u5DF2\u914D\u7F6E";
|
|
34719
|
+
}
|
|
34720
|
+
}
|
|
34721
|
+
process.stderr.write(`[hvip] \u53EA\u8BFB\u6A21\u5F0F\u5DF2\u542F\u7528 | API Key: ${authStatus} | \u5199\u5165\u5DE5\u5177\u5DF2\u8DF3\u8FC7: ${skipped}
|
|
34722
|
+
`);
|
|
34723
|
+
if (skipLog.length > 0 && process.env.NODE_ENV !== "production") {
|
|
34724
|
+
const sample = skipLog.slice(0, 8).join(", ");
|
|
34725
|
+
process.stderr.write(`[hvip] \u8DF3\u8FC7\u793A\u4F8B: ${sample}${skipLog.length > 8 ? ` +${skipLog.length - 8} \u4E2A` : ""}
|
|
34726
|
+
`);
|
|
34727
|
+
}
|
|
34728
|
+
} else if (auth) {
|
|
34729
|
+
try {
|
|
34730
|
+
const cfg = await privateApi.getAccountConfig(auth);
|
|
34731
|
+
const uid = cfg?.[0]?.uid ?? "?";
|
|
34732
|
+
process.stderr.write(`[hvip] API Key \u5DF2\u9A8C\u8BC1 | UID: ${uid} | \u5B8C\u6574\u6A21\u5F0F\uFF08\u5168\u90E8 357 \u5DE5\u5177\uFF09
|
|
34733
|
+
`);
|
|
34734
|
+
} catch {
|
|
34735
|
+
process.stderr.write(`[hvip] API Key \u9A8C\u8BC1\u5931\u8D25 | \u5C06\u4EE5\u672A\u8BA4\u8BC1\u6A21\u5F0F\u542F\u52A8\uFF08\u516C\u5F00\u5DE5\u5177\u53EF\u7528\uFF09
|
|
34736
|
+
`);
|
|
34737
|
+
}
|
|
34738
|
+
} else {
|
|
34739
|
+
process.stderr.write(`[hvip] \u672A\u914D\u7F6E API Key | \u4EC5\u516C\u5F00\u5DE5\u5177\u53EF\u7528
|
|
34740
|
+
`);
|
|
34741
|
+
}
|
|
34742
|
+
startAgentHub(parseInt(process.env.WS_AGENT_PORT || "9321"), "0.2.45.0", VERSION);
|
|
33024
34743
|
const transport = new StdioServerTransport();
|
|
33025
|
-
await
|
|
34744
|
+
await effectiveServer.connect(transport);
|
|
33026
34745
|
}
|
|
33027
34746
|
main();
|