@okx_ai/okx-trade-cli 1.1.7 → 1.1.9

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 CHANGED
@@ -2452,7 +2452,7 @@ function registerGridTools() {
2452
2452
  {
2453
2453
  name: "grid_create_order",
2454
2454
  module: "bot.grid",
2455
- description: "Create a new grid trading bot. [CAUTION] Executes real trades and locks funds. Supports Spot Grid ('grid') and Contract Grid ('contract_grid'). For spot grid, provide quoteSz (invest in quote currency) or baseSz (invest in base currency). For contract grids, provide direction, lever, and sz (number of contracts). Private endpoint. Rate limit: 20 req/2s per UID.",
2455
+ description: "Create a new grid trading bot. [CAUTION] Executes real trades and locks funds. Supports Spot Grid ('grid') and Contract Grid ('contract_grid'). For spot grid, provide quoteSz (invest in quote currency) or baseSz (invest in base currency). For contract grids, provide direction, lever, and sz (investment amount in margin currency, e.g. USDT for USDT-margined contracts). Private endpoint. Rate limit: 20 req/2s per UID.",
2456
2456
  isWrite: true,
2457
2457
  inputSchema: {
2458
2458
  type: "object",
@@ -2502,7 +2502,11 @@ function registerGridTools() {
2502
2502
  },
2503
2503
  sz: {
2504
2504
  type: "string",
2505
- description: "Contracts to invest. Required for contract_grid."
2505
+ description: "Investment amount in margin currency (e.g. USDT for USDT-margined contracts). Required for contract_grid."
2506
+ },
2507
+ basePos: {
2508
+ type: "boolean",
2509
+ description: "Whether to open a base position for contract grid. Ignored for neutral direction and spot grid. Default: true"
2506
2510
  }
2507
2511
  },
2508
2512
  required: ["instId", "algoOrdType", "maxPx", "minPx", "gridNum"]
@@ -2525,6 +2529,7 @@ function registerGridTools() {
2525
2529
  });
2526
2530
  if (algoOrdType === "contract_grid") {
2527
2531
  body.triggerParams = [{ triggerAction: "start", triggerStrategy: "instant" }];
2532
+ body.basePos = readBoolean(args, "basePos") ?? true;
2528
2533
  }
2529
2534
  const response = await context.client.privatePost(
2530
2535
  "/api/v5/tradingBot/grid/order-algo",
@@ -6207,8 +6212,8 @@ var HELP_TREE = {
6207
6212
  description: "List sub-orders of a grid bot (filled or live)"
6208
6213
  },
6209
6214
  create: {
6210
- usage: "okx bot grid create --instId <id> --algoOrdType <grid|contract_grid> --maxPx <px> --minPx <px> --gridNum <n>\n [--runType <1|2>] [--quoteSz <n>] [--baseSz <n>]\n [--direction <long|short|neutral>] [--lever <n>] [--sz <n>]",
6211
- description: "Create a new grid bot order"
6215
+ usage: "okx bot grid create --instId <id> --algoOrdType <grid|contract_grid> --maxPx <px> --minPx <px> --gridNum <n>\n [--runType <1|2>] [--quoteSz <n>] [--baseSz <n>]\n [--direction <long|short|neutral>] [--lever <n>] [--sz <n>] [--basePos] [--no-basePos]",
6216
+ description: "Create a new grid bot order (contract grid opens base position by default)"
6212
6217
  },
6213
6218
  stop: {
6214
6219
  usage: "okx bot grid stop --algoId <id> --algoOrdType <type> --instId <id> [--stopType <1|2|3|5|6>]",
@@ -6447,6 +6452,7 @@ var CLI_OPTIONS = {
6447
6452
  quoteSz: { type: "string" },
6448
6453
  baseSz: { type: "string" },
6449
6454
  direction: { type: "string" },
6455
+ basePos: { type: "boolean", default: true },
6450
6456
  stopType: { type: "string" },
6451
6457
  live: { type: "boolean", default: false },
6452
6458
  // market extras
@@ -6488,14 +6494,30 @@ var CLI_OPTIONS = {
6488
6494
  orders: { type: "string" },
6489
6495
  // audit
6490
6496
  since: { type: "string" },
6491
- tool: { type: "string" }
6497
+ tool: { type: "string" },
6498
+ // config profile
6499
+ force: { type: "boolean", default: false }
6492
6500
  };
6493
6501
  function parseCli(argv) {
6502
+ const negated = /* @__PURE__ */ new Set();
6503
+ const filtered = argv.filter((arg) => {
6504
+ if (arg.startsWith("--no-")) {
6505
+ const key = arg.slice(5);
6506
+ if (key in CLI_OPTIONS && CLI_OPTIONS[key].type === "boolean") {
6507
+ negated.add(key);
6508
+ return false;
6509
+ }
6510
+ }
6511
+ return true;
6512
+ });
6494
6513
  const { values, positionals } = parseArgs({
6495
- args: argv,
6514
+ args: filtered,
6496
6515
  options: CLI_OPTIONS,
6497
6516
  allowPositionals: true
6498
6517
  });
6518
+ for (const key of negated) {
6519
+ values[key] = false;
6520
+ }
6499
6521
  return { values, positionals };
6500
6522
  }
6501
6523
 
@@ -7855,7 +7877,7 @@ function cmdConfigShow(json) {
7855
7877
  process.stdout.write(`[${name}]
7856
7878
  `);
7857
7879
  printKv({
7858
- api_key: profile.api_key ? "***" + profile.api_key.slice(-4) : "(not set)",
7880
+ api_key: profile.api_key ? maskSecret(profile.api_key) : "(not set)",
7859
7881
  demo: profile.demo ?? false,
7860
7882
  base_url: profile.base_url ?? "(default)"
7861
7883
  }, 2);
@@ -7876,10 +7898,24 @@ function cmdConfigSet(key, value) {
7876
7898
  }
7877
7899
  }
7878
7900
  function parseSiteKey(raw) {
7879
- if (raw === "2") return "eea";
7880
- if (raw === "3") return "us";
7901
+ const lower = raw.toLowerCase();
7902
+ if (lower === "eea" || raw === "2") return "eea";
7903
+ if (lower === "us" || raw === "3") return "us";
7904
+ if (lower === "global" || raw === "1") return "global";
7881
7905
  return "global";
7882
7906
  }
7907
+ function inferSiteFromBaseUrl(baseUrl) {
7908
+ if (!baseUrl) return "global";
7909
+ for (const id of SITE_IDS) {
7910
+ const site = OKX_SITES[id];
7911
+ if (baseUrl === site.apiBaseUrl || baseUrl === site.webUrl) return id;
7912
+ }
7913
+ return "global";
7914
+ }
7915
+ function maskSecret(value) {
7916
+ if (!value || value.length < 4) return "****";
7917
+ return "***" + value.slice(-4);
7918
+ }
7883
7919
  function buildApiUrl(siteKey, demo) {
7884
7920
  const query = demo ? "?go-demo-trading=1" : "?go-live-trading=1";
7885
7921
  return `${OKX_SITES[siteKey].webUrl}/account/my-api${query}`;
@@ -7979,6 +8015,105 @@ async function cmdConfigInit(lang = "en") {
7979
8015
  rl.close();
7980
8016
  }
7981
8017
  }
8018
+ function cmdConfigAddProfile(kvPairs, force) {
8019
+ const params = {};
8020
+ for (const pair of kvPairs) {
8021
+ const eqIdx = pair.indexOf("=");
8022
+ if (eqIdx === -1) continue;
8023
+ const key = pair.slice(0, eqIdx).trim();
8024
+ const value = pair.slice(eqIdx + 1);
8025
+ params[key.toUpperCase()] = value;
8026
+ }
8027
+ const ak = params["AK"];
8028
+ const sk = params["SK"];
8029
+ const pp = params["PP"];
8030
+ const missing = [];
8031
+ if (!ak) missing.push("AK");
8032
+ if (!sk) missing.push("SK");
8033
+ if (!pp) missing.push("PP");
8034
+ if (missing.length > 0) {
8035
+ process.stderr.write(`Error: missing required parameter(s): ${missing.join(", ")}
8036
+ `);
8037
+ process.stderr.write("Usage: okx config add-profile AK=<key> SK=<secret> PP=<passphrase> [site=global|eea|us] [demo=true|false] [name=<name>] [--force]\n");
8038
+ process.exitCode = 1;
8039
+ return;
8040
+ }
8041
+ const siteKey = parseSiteKey(params["SITE"] ?? "");
8042
+ const demo = params["DEMO"] !== void 0 ? params["DEMO"].toLowerCase() !== "false" : true;
8043
+ const defaultName = demo ? "demo" : "live";
8044
+ const profileName = params["NAME"] ?? defaultName;
8045
+ const config = readFullConfig();
8046
+ if (config.profiles[profileName] && !force) {
8047
+ process.stderr.write(`Error: profile "${profileName}" already exists. Use --force to overwrite.
8048
+ `);
8049
+ process.exitCode = 1;
8050
+ return;
8051
+ }
8052
+ const entry = buildProfileEntry(siteKey, ak, sk, pp, demo);
8053
+ entry.site = siteKey;
8054
+ config.profiles[profileName] = entry;
8055
+ config.default_profile = profileName;
8056
+ writeCliConfig(config);
8057
+ process.stdout.write(`Profile "${profileName}" saved to ${configFilePath()}
8058
+ `);
8059
+ process.stdout.write(`Default profile set to: ${profileName}
8060
+ `);
8061
+ }
8062
+ function cmdConfigListProfile() {
8063
+ const config = readFullConfig();
8064
+ const entries = Object.entries(config.profiles);
8065
+ if (entries.length === 0) {
8066
+ process.stdout.write("No profiles found. Run: okx config add-profile AK=<key> SK=<secret> PP=<passphrase>\n");
8067
+ return;
8068
+ }
8069
+ process.stdout.write(`Config: ${configFilePath()}
8070
+
8071
+ `);
8072
+ for (const [name, profile] of entries) {
8073
+ const isDefault = name === config.default_profile;
8074
+ const marker = isDefault ? " *" : "";
8075
+ const site = profile.site ?? inferSiteFromBaseUrl(profile.base_url);
8076
+ const mode = profile.demo !== false ? "demo (\u6A21\u62DF\u76D8)" : "live (\u5B9E\u76D8)";
8077
+ process.stdout.write(`[${name}]${marker}
8078
+ `);
8079
+ process.stdout.write(` api_key: ${maskSecret(profile.api_key)}
8080
+ `);
8081
+ process.stdout.write(` secret_key: ${maskSecret(profile.secret_key)}
8082
+ `);
8083
+ process.stdout.write(` passphrase: ${maskSecret(profile.passphrase)}
8084
+ `);
8085
+ process.stdout.write(` site: ${site}
8086
+ `);
8087
+ process.stdout.write(` mode: ${mode}
8088
+ `);
8089
+ process.stdout.write("\n");
8090
+ }
8091
+ }
8092
+ function cmdConfigUse(profileName) {
8093
+ if (!profileName) {
8094
+ process.stderr.write("Error: profile name is required.\nUsage: okx config use <profile-name>\n");
8095
+ process.exitCode = 1;
8096
+ return;
8097
+ }
8098
+ const config = readFullConfig();
8099
+ const available = Object.keys(config.profiles);
8100
+ if (!config.profiles[profileName]) {
8101
+ process.stderr.write(`Error: profile "${profileName}" does not exist.
8102
+ `);
8103
+ if (available.length > 0) {
8104
+ process.stderr.write(`Available profiles: ${available.join(", ")}
8105
+ `);
8106
+ } else {
8107
+ process.stderr.write("No profiles configured. Run: okx config add-profile AK=<key> SK=<secret> PP=<passphrase>\n");
8108
+ }
8109
+ process.exitCode = 1;
8110
+ return;
8111
+ }
8112
+ config.default_profile = profileName;
8113
+ writeCliConfig(config);
8114
+ process.stdout.write(`Default profile set to: "${profileName}"
8115
+ `);
8116
+ }
7982
8117
 
7983
8118
  // src/commands/bot.ts
7984
8119
  function getData7(result) {
@@ -8075,7 +8210,8 @@ async function cmdGridCreate(run, opts) {
8075
8210
  baseSz: opts.baseSz,
8076
8211
  direction: opts.direction,
8077
8212
  lever: opts.lever,
8078
- sz: opts.sz
8213
+ sz: opts.sz,
8214
+ basePos: opts.basePos
8079
8215
  });
8080
8216
  const data = getData7(result);
8081
8217
  if (opts.json) return printJson(data);
@@ -8251,12 +8387,15 @@ async function cmdDcaSubOrders(run, opts) {
8251
8387
  // src/index.ts
8252
8388
  var _require = createRequire(import.meta.url);
8253
8389
  var CLI_VERSION = _require("../package.json").version;
8254
- var GIT_HASH = true ? "b0b33d7" : "dev";
8255
- function handleConfigCommand(action, rest, json, lang) {
8390
+ var GIT_HASH = true ? "9eed480" : "dev";
8391
+ function handleConfigCommand(action, rest, json, lang, force) {
8256
8392
  if (action === "init") return cmdConfigInit(lang === "zh" ? "zh" : "en");
8257
8393
  if (action === "show") return cmdConfigShow(json);
8258
8394
  if (action === "set") return cmdConfigSet(rest[0], rest[1]);
8259
8395
  if (action === "setup-clients") return cmdSetupClients();
8396
+ if (action === "add-profile") return cmdConfigAddProfile(rest, force ?? false);
8397
+ if (action === "list-profile") return cmdConfigListProfile();
8398
+ if (action === "use") return cmdConfigUse(rest[0]);
8260
8399
  process.stderr.write(`Unknown config command: ${action}
8261
8400
  `);
8262
8401
  process.exitCode = 1;
@@ -8653,6 +8792,7 @@ function handleBotGridCommand(run, v, rest, json) {
8653
8792
  direction: v.direction,
8654
8793
  lever: v.lever,
8655
8794
  sz: v.sz,
8795
+ basePos: v.basePos,
8656
8796
  json
8657
8797
  });
8658
8798
  if (subAction === "stop")
@@ -8720,7 +8860,7 @@ async function main() {
8720
8860
  const [module, action, ...rest] = positionals;
8721
8861
  const v = values;
8722
8862
  const json = v.json ?? false;
8723
- if (module === "config") return handleConfigCommand(action, rest, json, v.lang);
8863
+ if (module === "config") return handleConfigCommand(action, rest, json, v.lang, v.force);
8724
8864
  if (module === "setup") return handleSetupCommand(v);
8725
8865
  const config = loadProfileConfig({ profile: v.profile, demo: v.demo, userAgent: `okx-trade-cli/${CLI_VERSION}` });
8726
8866
  const client = new OkxRestClient(config);