diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 0000000..f5d0f85 --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,12 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "ignorePatterns": [ + "coverage/**", + "data/**", + "dist/**", + "docs/**", + "node_modules/**", + "out/**", + ".tmp/**" + ] +} diff --git a/README.md b/README.md index 213b390..1382d6e 100644 --- a/README.md +++ b/README.md @@ -226,6 +226,8 @@ EXCHANGE=binance BINANCE_MARKET_TYPE=spot BINANCE_SYMBOL=BTCUSDT bun run index.t bun run index.ts # 启动 CLI(默认入口) bun run start # 等价于运行 index.ts bun run dev # 调试模式 +bun run lint # 执行 Oxlint 检查 +bun run lint:fix # 自动修复可安全修复的问题 bun x vitest run # 执行全部测试 ``` @@ -292,6 +294,8 @@ bun run pm2:start:offset ## 测试 项目使用 Vitest: ```bash +bun run lint +bun run lint:fix bun run test bun x vitest --watch ``` diff --git a/README_en.md b/README_en.md index d05d244..4d68abc 100644 --- a/README_en.md +++ b/README_en.md @@ -222,6 +222,8 @@ Please keep these credentials safe and do not share them with anyone. bun run index.ts # Launch the CLI (default entrypoint) bun run start # Alias for bun run index.ts bun run dev # Development entrypoint +bun run lint # Run Oxlint checks +bun run lint:fix # Apply safe Oxlint fixes bun x vitest run # Execute the full Vitest suite ``` @@ -288,6 +290,8 @@ Run `pm2 save` afterwards if you want the process list to survive reboots. ## Testing Powered by Vitest: ```bash +bun run lint +bun run lint:fix bun run test bun x vitest --watch ``` diff --git a/bun.lock b/bun.lock index 99a95e6..209d2d0 100644 --- a/bun.lock +++ b/bun.lock @@ -21,6 +21,7 @@ }, "devDependencies": { "@types/bun": "^1.3.9", + "oxlint": "^1.54.0", "vitest": "^4.0.18", }, "peerDependencies": { @@ -107,6 +108,44 @@ "@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], + "@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.54.0", "", { "os": "android", "cpu": "arm" }, "sha512-khWlVXUa4CPvp4eXnj7/TUNeyiarwvTEmZggylPIPUCSWgPqUBFGElIBa9xKNCQt4pb+WSGArCNEAy22ekQQxg=="], + + "@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.54.0", "", { "os": "android", "cpu": "arm64" }, "sha512-p3qEVSDVmyducpI9ORTJNbaMyXfICidDXGaf3WwyDyiXPExyZdfc6UsPepGPxImlfFJs5kxOCPqP4ut12Ed9pg=="], + + "@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.54.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-tUQ+vn/AL2P2Rz6cl3gsFA+4pMBFMRR0e6AVePoezV9iGTSMZUXIf0YWHq203bwNDXcY04vSXDqPB6E1b9WULA=="], + + "@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.54.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-9tzH/OLGZCzVGEXW0D3I0OrQOOWciHYWV9mcxjqqQE6f1DMOXT23mWj5/OQtqhW3E1VfHf0uf2MzMbM2gboPlA=="], + + "@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.54.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-XelGa+x7vC9epF5JzXWHaQtdxqcL5R+H2WcEkr+JDkfmY3dAXVLa+51qW3+MWt7CZanakaOyhraLzdM32pWFfg=="], + + "@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.54.0", "", { "os": "linux", "cpu": "arm" }, "sha512-t5FubAU899vMF+6rBtxDewkwSAeFn8OUCKb/+jJ1XqPU0FTR+RffnTfXafVE8WXw39eN4pzUK3rkxUWlcsFuaw=="], + + "@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.54.0", "", { "os": "linux", "cpu": "arm" }, "sha512-Du6cwkoMRi9DAgITzQpzS1QaEqE+5BP3Tfgr1yPy3C034n6IHISCwf4KMB+wojg8FE/kYvrJDibT0ENdcR3jUg=="], + + "@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.54.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-R4PjJ1lfghsVBuAegW79jkvUWbN8P4F28KaKbM72dW6ZWTYMg6M0pkTilXFZ+q/mb8f0MEyR1rO16useoa6KTA=="], + + "@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.54.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-WBNFe1foIFg6ipgzjzJfDLn7C5nZpLr/UHlnlT7GI3scCD2xpJiJTGMTTpJqA8p0Q1l2NsEnAOj9PtreF0Tkzg=="], + + "@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.54.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-M+UAW76rZHHiYKKy4e7Te5MNikANiFhYWl0qYF1MTIhQczYIqWVDQ+SX0SzW8ipOB/oK3+enOvlvJuhMoA968Q=="], + + "@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.54.0", "", { "os": "linux", "cpu": "none" }, "sha512-sGassljr8TR5F1WCqOaacrp3mYi107MnjkqlSXOMHACps7U2bL4v7M3RY7P7NMcGkNhzRHF3VO5+XyPWhTVM6w=="], + + "@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.54.0", "", { "os": "linux", "cpu": "none" }, "sha512-mW5Z6XTO8QWtlUjlf6yjntarjnbrmGVSK/V6XYy2rjH8xUfv9pn9G1vO92DBBBi0eUwnVpcOY3hMkP851WZNWg=="], + + "@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.54.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-nfPmEGW9BfWEUD0PVXGaYa2RS4wVblofNih1gsyUoLSWSyliNisIWd7F+QXrDSL5SJ78BPZjDW6FainV8qRiTg=="], + + "@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.54.0", "", { "os": "linux", "cpu": "x64" }, "sha512-gybxMQx4NN1T+pa8TLwgVS4u9H9Hxwm7Sl0qvnQJF2WRhNN1oTOCzkmmCBbW/29DYLeV99WU76zh7srCamK9yw=="], + + "@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.54.0", "", { "os": "linux", "cpu": "x64" }, "sha512-EAXMh2w3pzSj/aiB67kXzcHIoKxAywC1i1IgxA1sLY7iffEaZowDTOJgirY7WxeR/WiiKwak89gPeh9wUdLnIw=="], + + "@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.54.0", "", { "os": "none", "cpu": "arm64" }, "sha512-Ih7CfITkbw86+LjgV5gDwNmNQlvz7X+51gdeLLUDwuA/9lojDxCmRQEzeMl44KStQlwzCuNIcgGMae0MllV5ww=="], + + "@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.54.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-qGQ8KIEfdgwwJd09Nc0d5hzlHQAM0EMoshMzHG/nNlMAHXrY7RFyat6VbzjflifAFb7LPAw+Yw9AB8cfzR7L8g=="], + + "@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.54.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-GXos7N5oZIcIE8hlXgtUkI+y3frIqwiztx9p4+ZrpNgASbnIsxxy8bgLJqXE2SGCAdmtjBO1mdKhGTtVrb1jbg=="], + + "@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.54.0", "", { "os": "win32", "cpu": "x64" }, "sha512-DVxSELcI72lmcODuVpO8uXkwuYPiA0hKMhBwNa8fO4+sIVxFvxugf/z6qrL+4PM8RjGWjdl8O/QqzuRWj9b5bA=="], + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.0", "", { "os": "android", "cpu": "arm" }, "sha512-VxDYCDqOaR7NXzAtvRx7G1u54d2kEHopb28YH/pKzY6y0qmogP3gG7CSiWsq9WvDFxOQMpNEyjVAHZFXfH3o/A=="], "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.52.0", "", { "os": "android", "cpu": "arm64" }, "sha512-pqDirm8koABIKvzL59YI9W9DWbRlTX7RWhN+auR8HXJxo89m4mjqbah7nJZjeKNTNYopqL+yGg+0mhCpf3xZtQ=="], @@ -307,6 +346,8 @@ "ox": ["ox@0.12.4", "", { "dependencies": { "@adraffy/ens-normalize": "^1.11.0", "@noble/ciphers": "^1.3.0", "@noble/curves": "1.9.1", "@noble/hashes": "^1.8.0", "@scure/bip32": "^1.7.0", "@scure/bip39": "^1.6.0", "abitype": "^1.2.3", "eventemitter3": "5.0.1" }, "peerDependencies": { "typescript": ">=5.4.0" }, "optionalPeers": ["typescript"] }, "sha512-+P+C7QzuwPV8lu79dOwjBKfB2CbnbEXe/hfyyrff1drrO1nOOj3Hc87svHfcW1yneRr3WXaKr6nz11nq+/DF9Q=="], + "oxlint": ["oxlint@1.54.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.54.0", "@oxlint/binding-android-arm64": "1.54.0", "@oxlint/binding-darwin-arm64": "1.54.0", "@oxlint/binding-darwin-x64": "1.54.0", "@oxlint/binding-freebsd-x64": "1.54.0", "@oxlint/binding-linux-arm-gnueabihf": "1.54.0", "@oxlint/binding-linux-arm-musleabihf": "1.54.0", "@oxlint/binding-linux-arm64-gnu": "1.54.0", "@oxlint/binding-linux-arm64-musl": "1.54.0", "@oxlint/binding-linux-ppc64-gnu": "1.54.0", "@oxlint/binding-linux-riscv64-gnu": "1.54.0", "@oxlint/binding-linux-riscv64-musl": "1.54.0", "@oxlint/binding-linux-s390x-gnu": "1.54.0", "@oxlint/binding-linux-x64-gnu": "1.54.0", "@oxlint/binding-linux-x64-musl": "1.54.0", "@oxlint/binding-openharmony-arm64": "1.54.0", "@oxlint/binding-win32-arm64-msvc": "1.54.0", "@oxlint/binding-win32-ia32-msvc": "1.54.0", "@oxlint/binding-win32-x64-msvc": "1.54.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.15.0" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-ObSjVwf0ZYA5U5Cmelj0PsCuqCJXsm2TxZ40tgUSAY7Wu0lKAsNjor6cgXHXSys8jOwv1ICjtzouoWHdKGHbZg=="], + "patch-console": ["patch-console@2.0.0", "", {}, "sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA=="], "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], diff --git a/package.json b/package.json index 9761bb7..96b9aae 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,8 @@ "scripts": { "dev": "bun run index.ts", "start": "bun run index.ts", + "lint": "oxlint", + "lint:fix": "oxlint --fix", "test": "bun x vitest run", "test:exchange-contract": "bun x vitest run tests/exchange-contract-suite.test.ts tests/exchange-factory.test.ts tests/config.test.ts", "test:watch": "bun x vitest", @@ -27,6 +29,7 @@ }, "devDependencies": { "@types/bun": "^1.3.9", + "oxlint": "^1.54.0", "vitest": "^4.0.18" }, "peerDependencies": { diff --git a/src/cli/command-parser.ts b/src/cli/command-parser.ts index 02ac8fa..c521d76 100644 --- a/src/cli/command-parser.ts +++ b/src/cli/command-parser.ts @@ -155,7 +155,7 @@ function parseExchangeCommand( options: Record, common: CommandCommonOptions & { help?: boolean } ): ParsedCliCommand { - assertAllowedOptions(options, new Set([...GLOBAL_OPTION_NAMES])); + assertAllowedOptions(options, new Set(GLOBAL_OPTION_NAMES)); if (action === "list") return { kind: "exchange-list", ...common }; if (action === "capabilities") return { kind: "exchange-capabilities", ...common }; throw new CommandParseError(`Unsupported exchange action '${action}'`); diff --git a/src/exchanges/aster/client.ts b/src/exchanges/aster/client.ts index 36b664c..1c43d9b 100644 --- a/src/exchanges/aster/client.ts +++ b/src/exchanges/aster/client.ts @@ -543,7 +543,7 @@ export class AsterSpotRestClient { } try { return JSON.parse(text) as T; - } catch (error) { + } catch { throw new Error(`[AsterSpotRestClient] 无法解析响应: ${text.slice(0, 200)}`); } } @@ -795,7 +795,7 @@ export class AsterRestClient { } try { return JSON.parse(text) as AsterFuturesExchangeInfo; - } catch (error) { + } catch { throw new Error(`[AsterRestClient] 无法解析交易规则响应: ${text.slice(0, 200)}`); } } @@ -869,7 +869,7 @@ export class AsterRestClient { try { const payload = JSON.parse(text) as any[]; return payload.map((entry) => fromRestKline(entry, interval, upper)); - } catch (error) { + } catch { throw new Error(`[AsterRestClient] 无法解析K线响应: ${text.slice(0, 200)}`); } } @@ -899,7 +899,7 @@ export class AsterRestClient { const payload = JSON.parse(text) as any; // The response shape mirrors Binance: { symbol, markPrice, indexPrice, lastFundingRate, nextFundingTime, time } return payload; - } catch (error) { + } catch { throw new Error(`[AsterRestClient] 无法解析资金费率响应: ${text.slice(0, 200)}`); } } @@ -942,7 +942,7 @@ export class AsterRestClient { } try { return JSON.parse(text) as T; - } catch (error) { + } catch { throw new Error(`[AsterRestClient] 无法解析响应: ${text.slice(0, 200)}`); } } @@ -1366,7 +1366,7 @@ export class AsterGateway { }); } - async ensureInitialized(symbol: string): Promise { + async ensureInitialized(_symbol: string): Promise { if (this.initialized) return; if (this.initializing) return this.initializing; this.initializing = (async () => { diff --git a/src/exchanges/backpack/gateway.ts b/src/exchanges/backpack/gateway.ts index 4f291c0..b10c694 100644 --- a/src/exchanges/backpack/gateway.ts +++ b/src/exchanges/backpack/gateway.ts @@ -7,7 +7,6 @@ import ccxt, { import NodeWebSocket from "ws"; import { sign, utils as edUtils, hashes as edHashes } from "@noble/ed25519"; import { sha512 } from "@noble/hashes/sha512"; -import { randomBytes } from "crypto"; import type { AsterAccountSnapshot, AsterAccountPosition, @@ -137,17 +136,16 @@ export class BackpackGateway { } private async doInitialize(symbol?: string): Promise { - try { - await this.exchange.loadMarkets(); - const requested = (symbol ?? this.symbol).toUpperCase(); - const market = this.findMarket(requested); - if (!market) { - throw new Error(`Symbol ${requested} not found in Backpack markets`); - } - this.market = market; - this.marketSymbol = market.symbol; - this.marketId = market.id; - this.isContractMarket = Boolean(market.contract); + await this.exchange.loadMarkets(); + const requested = (symbol ?? this.symbol).toUpperCase(); + const market = this.findMarket(requested); + if (!market) { + throw new Error(`Symbol ${requested} not found in Backpack markets`); + } + this.market = market; + this.marketSymbol = market.symbol; + this.marketId = market.id; + this.isContractMarket = Boolean(market.contract); if (process.env.BACKPACK_DEBUG === "1") { console.debug("[BackpackGateway] marketInfo", { userSymbol: this.symbol, @@ -155,10 +153,7 @@ export class BackpackGateway { marketId: this.marketId, }); } - this.initialized = true; - } catch (error) { - throw error; - } + this.initialized = true; } private findMarket(requested: string): any | null { @@ -774,7 +769,7 @@ export class BackpackGateway { void this.resubscribeAllTopics(); }; - private handleWsClose = (event: any): void => { + private handleWsClose = (_event: any): void => { if (this.wsCleanup) { try { this.wsCleanup(); diff --git a/src/exchanges/binance/gateway.ts b/src/exchanges/binance/gateway.ts index 569fb9e..169bafa 100644 --- a/src/exchanges/binance/gateway.ts +++ b/src/exchanges/binance/gateway.ts @@ -1,9 +1,6 @@ import ccxt, { type Balances, type Order as CcxtOrder, - type OrderBook as CcxtOrderBook, - type OHLCV as CcxtOhlcv, - type Ticker as CcxtTicker, } from "ccxt"; import axios from "axios"; import { createHash } from "crypto"; diff --git a/src/exchanges/grvt/gateway.ts b/src/exchanges/grvt/gateway.ts index 733f018..22b2ae1 100644 --- a/src/exchanges/grvt/gateway.ts +++ b/src/exchanges/grvt/gateway.ts @@ -1161,7 +1161,7 @@ function mapTicker(response: IApiTickerResponse, symbol: string): AsterTicker | }; } -function mapKlines(response: IApiCandlestickResponse, symbol: string): AsterKline[] { +function mapKlines(response: IApiCandlestickResponse, _symbol: string): AsterKline[] { return (response.result ?? []).reverse().map((entry) => ({ openTime: nsToMs(entry.open_time ?? Date.now() * ONE_SECOND_IN_NANOSECONDS), closeTime: nsToMs(entry.close_time ?? Date.now() * ONE_SECOND_IN_NANOSECONDS), diff --git a/src/exchanges/lighter/gateway.ts b/src/exchanges/lighter/gateway.ts index d8daa7a..4513b09 100644 --- a/src/exchanges/lighter/gateway.ts +++ b/src/exchanges/lighter/gateway.ts @@ -16,12 +16,10 @@ import type { AsterTicker, CreateOrderParams, } from "../types"; -import { extractMessage } from "../../utils/errors"; import type { OrderSide, OrderType } from "../types"; import { LighterHttpClient } from "./http-client"; import { HttpNonceManager } from "./nonce-manager"; import { LighterSigner, type CreateOrderSignParams } from "./signer"; -import { bytesToHex } from "./bytes"; import type { LighterAccountDetails, LighterAccountAsset, @@ -39,7 +37,6 @@ import { LIGHTER_HOSTS, LIGHTER_ORDER_TYPE, LIGHTER_TIME_IN_FORCE, - DEFAULT_ORDER_EXPIRY_PLACEHOLDER, IMMEDIATE_OR_CANCEL_EXPIRY_PLACEHOLDER, type LighterEnvironment, } from "./constants"; @@ -2210,7 +2207,7 @@ function extractJsonRequestId(message: any): string | null { function tryParseTxInfo(value: string): unknown { try { return JSON.parse(value); - } catch (_) { + } catch { return value; } } diff --git a/src/exchanges/lighter/mappers.ts b/src/exchanges/lighter/mappers.ts index 1184cd5..be8b0e8 100644 --- a/src/exchanges/lighter/mappers.ts +++ b/src/exchanges/lighter/mappers.ts @@ -128,7 +128,7 @@ function computeExecutedQty(order: LighterOrder): string { if (Number.isFinite(initial) && Number.isFinite(remaining)) { return (initial - remaining).toString(); } - } catch (_) { + } catch { // fall through } } diff --git a/src/exchanges/nado/gateway.ts b/src/exchanges/nado/gateway.ts index 3fbbbea..cdfed03 100644 --- a/src/exchanges/nado/gateway.ts +++ b/src/exchanges/nado/gateway.ts @@ -1684,7 +1684,7 @@ export class NadoGateway { try { const text = typeof data === "string" ? data : data.toString("utf8"); message = JSON.parse(text); - } catch (_error) { + } catch { return; } if (!message || typeof message !== "object") return; diff --git a/src/exchanges/paradex/gateway.ts b/src/exchanges/paradex/gateway.ts index 81578e2..518a93f 100644 --- a/src/exchanges/paradex/gateway.ts +++ b/src/exchanges/paradex/gateway.ts @@ -32,7 +32,7 @@ function loadCcxtPro(): any | null { // eslint-disable-next-line @typescript-eslint/no-var-requires const mod = require("ccxt.pro"); return mod?.default ?? mod; - } catch (_error) { + } catch { return null; } } @@ -571,7 +571,6 @@ export class ParadexGateway { const market = typeof (this.exchange as any).market === "function" ? (this.exchange as any).market(symbol) : (this.exchange.markets ?? {})[symbol]; - const precisionDigits = Number((market?.precision?.amount ?? market?.amountPrecision)); const limitMin = Number(market?.limits?.amount?.min); // Only trust explicit exchange min limit; do NOT infer 1 from precision=0 const minAmount = Number.isFinite(limitMin) && limitMin > 0 ? limitMin : undefined; @@ -593,7 +592,7 @@ export class ParadexGateway { if (typeof (this.exchange as any).amountToPrecision === "function" && Number.isFinite(Number(amount))) { amount = Number((this.exchange as any).amountToPrecision(symbol, amount)); } - } catch (_normalizeError) { + } catch { // Swallow precision normalization errors and let exchange validation surface if any } @@ -944,7 +943,7 @@ export class ParadexGateway { } } - private updateOrdersFromRemote(open: CcxtOrder[], closed: CcxtOrder[]): void { + private updateOrdersFromRemote(open: CcxtOrder[], _closed: CcxtOrder[]): void { const nextOpen = new Map(); for (const order of open) { diff --git a/src/index.tsx b/src/index.tsx index 0ab7dab..ceb4a50 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -4,7 +4,6 @@ import { App } from "./ui/App"; import { setupGlobalErrorHandlers } from "./runtime-errors"; import { parseCliArgs, printCliHelp } from "./cli/args"; import { startStrategy } from "./cli/strategy-runner"; -import { resolveExchangeId } from "./exchanges/create-adapter"; import { CommandParseError, parseCommandArgv, printCommandHelp } from "./cli/command-parser"; import { executeCliCommand, renderCommandPayload } from "./cli/command-executor"; diff --git a/src/strategy/basis-arb-engine.ts b/src/strategy/basis-arb-engine.ts index 58c8a22..448fa85 100644 --- a/src/strategy/basis-arb-engine.ts +++ b/src/strategy/basis-arb-engine.ts @@ -409,7 +409,7 @@ export class BasisArbEngine { if (!Number.isFinite(wallet) || !Number.isFinite(available)) continue; if (Math.abs(wallet) === 0 && Math.abs(available) === 0) continue; - const isTaggedFuturesAsset = /0$/.test(name); + const isTaggedFuturesAsset = name.endsWith("0"); if (isTaggedFuturesAsset) { futuresBalances.push({ asset: name.replace(/0$/, ""), wallet, available }); continue; diff --git a/src/strategy/grid-engine.ts b/src/strategy/grid-engine.ts index 5511a07..b791478 100644 --- a/src/strategy/grid-engine.ts +++ b/src/strategy/grid-engine.ts @@ -461,7 +461,7 @@ export class GridEngine { return false; } - private async haltGrid(price: number): Promise { + private async haltGrid(_price: number): Promise { if (!this.running) return; const reason = this.stopReason ?? "触发网格止损"; this.log("warn", `${reason},开始执行平仓与撤单`); diff --git a/src/strategy/maker-engine.ts b/src/strategy/maker-engine.ts index ee8178b..43c5734 100644 --- a/src/strategy/maker-engine.ts +++ b/src/strategy/maker-engine.ts @@ -3,7 +3,6 @@ import type { ExchangeAdapter } from "../exchanges/adapter"; import type { AsterAccountSnapshot, AsterDepth, - AsterKline, AsterOrder, AsterTicker, } from "../exchanges/types"; diff --git a/src/strategy/swing-engine.ts b/src/strategy/swing-engine.ts index faa1371..9e4b7a2 100644 --- a/src/strategy/swing-engine.ts +++ b/src/strategy/swing-engine.ts @@ -422,7 +422,7 @@ export class SwingEngine { : position.entryPrice * (1 + Math.max(0, this.config.stopLossPct)); const tick = Math.max(1e-9, this.config.priceTick); - const lastPrice = referencePrice ?? Number(this.tickerSnapshot?.lastPrice) ?? null; + const lastPrice = referencePrice; // Kill-switch (always-on). const triggerKill = @@ -621,4 +621,3 @@ export class SwingEngine { }); } } - diff --git a/src/strategy/trend-engine.ts b/src/strategy/trend-engine.ts index 3976435..1dd6894 100644 --- a/src/strategy/trend-engine.ts +++ b/src/strategy/trend-engine.ts @@ -386,7 +386,7 @@ export class TrendEngine { private async enforceRateLimitStop(): Promise { const position = getPosition(this.accountSnapshot, this.config.symbol); if (Math.abs(position.positionAmt) < 1e-5) return; - const price = this.getReferencePrice() ?? Number(this.tickerSnapshot?.lastPrice) ?? this.lastPrice; + const price = this.getReferencePrice(); if (!Number.isFinite(price) || price == null) return; const result = await this.handlePositionManagement(position, Number(price)); if (result.closed) { diff --git a/tests/grid-engine.test.ts b/tests/grid-engine.test.ts index 9963971..ad7a0ac 100644 --- a/tests/grid-engine.test.ts +++ b/tests/grid-engine.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, it, vi } from "vitest"; +import { describe, expect, it } from "vitest"; import type { ExchangeAdapter } from "../src/exchanges/adapter"; import type { AsterAccountSnapshot,