From 6a96e469943dfc5156fe1705303deceb0fcc602b Mon Sep 17 00:00:00 2001 From: LiZhenhai-MBP14 <5935568+jackhai9@users.noreply.github.com> Date: Sun, 30 Aug 2026 18:34:46 +0800 Subject: [PATCH] fix: preserve ladder replacement options --- scripts/binance-orderbook-trade.user.js | 7 +++++-- src/binance-orderbook-trade/index.user.js | 9 ++++++++- .../binance-orderbook-trade/source-regressions.test.js | 6 +++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/scripts/binance-orderbook-trade.user.js b/scripts/binance-orderbook-trade.user.js index f5a86a7..289de4c 100644 --- a/scripts/binance-orderbook-trade.user.js +++ b/scripts/binance-orderbook-trade.user.js @@ -3,7 +3,7 @@ // @namespace binance.orderbook.trade // @icon data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2064%2064%22%3E%3Crect%20width%3D%2264%22%20height%3D%2264%22%20rx%3D%2214%22%20fill%3D%22%23f0b90b%22%2F%3E%3Ctext%20x%3D%2232%22%20y%3D%2249%22%20text-anchor%3D%22middle%22%20font-family%3D%22Arial%2C%20sans-serif%22%20font-size%3D%2242%22%20font-weight%3D%22800%22%20fill%3D%22%23111827%22%3EJ%3C%2Ftext%3E%3C%2Fsvg%3E // @icon64 data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2064%2064%22%3E%3Crect%20width%3D%2264%22%20height%3D%2264%22%20rx%3D%2214%22%20fill%3D%22%23f0b90b%22%2F%3E%3Ctext%20x%3D%2232%22%20y%3D%2249%22%20text-anchor%3D%22middle%22%20font-family%3D%22Arial%2C%20sans-serif%22%20font-size%3D%2242%22%20font-weight%3D%22800%22%20fill%3D%22%23111827%22%3EJ%3C%2Ftext%3E%3C%2Fsvg%3E -// @version 2.7.163 +// @version 2.7.164 // @author jackhai9 // @description 单击订单簿价格,按当前开仓/平仓 tab 自动填数量并执行下单,内置数量倍率面板 // @match https://www.binance.com/*/futures/* @@ -4376,6 +4376,7 @@ baseQty, percent, levels, + optionContext, minimumPercent: autoFit.minimumPercent, maxAutoFitPercent: autoFit.maxPercent, replacementTotalQty: spec.mode === "OPEN" ? multiplyDecimalByInt(minRequiredQty, levels) : null @@ -4411,6 +4412,7 @@ minRequiredQty, percent, levels, + optionContext, minimumPercent, maxAutoFitPercent, replacementTotalQty @@ -4429,6 +4431,7 @@ spec, symbol, precision, + optionContext, totalQty: replacementTotalQty }; } @@ -6753,7 +6756,7 @@ } function getOpenLadderMinimumQtyReplacementPlan(error) { const plan = error?.openOrdersReplacementPlan; - if (plan?.spec?.mode === "OPEN" && plan.symbol && plan.precision && plan.totalQty && isPositiveDecimalString(plan.totalQty)) { + if (plan?.spec?.mode === "OPEN" && plan.symbol && plan.precision && plan.optionContext && plan.optionContext.percent != null && Number.isInteger(plan.optionContext.levels) && Number.isInteger(plan.optionContext.ladderStep) && plan.totalQty && isPositiveDecimalString(plan.totalQty)) { return plan; } return null; diff --git a/src/binance-orderbook-trade/index.user.js b/src/binance-orderbook-trade/index.user.js index 07f89f2..7d49241 100644 --- a/src/binance-orderbook-trade/index.user.js +++ b/src/binance-orderbook-trade/index.user.js @@ -3,7 +3,7 @@ // @namespace binance.orderbook.trade // @icon data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2064%2064%22%3E%3Crect%20width%3D%2264%22%20height%3D%2264%22%20rx%3D%2214%22%20fill%3D%22%23f0b90b%22%2F%3E%3Ctext%20x%3D%2232%22%20y%3D%2249%22%20text-anchor%3D%22middle%22%20font-family%3D%22Arial%2C%20sans-serif%22%20font-size%3D%2242%22%20font-weight%3D%22800%22%20fill%3D%22%23111827%22%3EJ%3C%2Ftext%3E%3C%2Fsvg%3E // @icon64 data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2064%2064%22%3E%3Crect%20width%3D%2264%22%20height%3D%2264%22%20rx%3D%2214%22%20fill%3D%22%23f0b90b%22%2F%3E%3Ctext%20x%3D%2232%22%20y%3D%2249%22%20text-anchor%3D%22middle%22%20font-family%3D%22Arial%2C%20sans-serif%22%20font-size%3D%2242%22%20font-weight%3D%22800%22%20fill%3D%22%23111827%22%3EJ%3C%2Ftext%3E%3C%2Fsvg%3E -// @version 2.7.163 +// @version 2.7.164 // @author jackhai9 // @description 单击订单簿价格,按当前开仓/平仓 tab 自动填数量并执行下单,内置数量倍率面板 // @match https://www.binance.com/*/futures/* @@ -2262,6 +2262,7 @@ import { baseQty, percent, levels, + optionContext, minimumPercent: autoFit.minimumPercent, maxAutoFitPercent: autoFit.maxPercent, replacementTotalQty: spec.mode === 'OPEN' ? multiplyDecimalByInt(minRequiredQty, levels) : null, @@ -2299,6 +2300,7 @@ import { minRequiredQty, percent, levels, + optionContext, minimumPercent, maxAutoFitPercent, replacementTotalQty, @@ -2328,6 +2330,7 @@ import { spec, symbol, precision, + optionContext, totalQty: replacementTotalQty, }; } @@ -5022,6 +5025,10 @@ import { plan?.spec?.mode === 'OPEN' && plan.symbol && plan.precision && + plan.optionContext && + plan.optionContext.percent != null && + Number.isInteger(plan.optionContext.levels) && + Number.isInteger(plan.optionContext.ladderStep) && plan.totalQty && isPositiveDecimalString(plan.totalQty) ) { diff --git a/test/unit/binance-orderbook-trade/source-regressions.test.js b/test/unit/binance-orderbook-trade/source-regressions.test.js index 6445e2e..1569944 100644 --- a/test/unit/binance-orderbook-trade/source-regressions.test.js +++ b/test/unit/binance-orderbook-trade/source-regressions.test.js @@ -554,7 +554,7 @@ test('ladder minimum quantity failure explains safe manual options', () => { assert.match(buildBody, /autoFitLevels = autoFit\.levels/); assert.match(buildBody, /autoFitPercent: autoFitPercent/); assert.match(buildBody, /autoFitLevels/); - assert.match(buildBody, /createLadderMinimumQtyFailure\(\{\s*spec,\s*symbol: startSymbol,\s*precision: startPrecision,\s*mode: spec\.mode,\s*minRequiredQty,\s*baseQty,\s*percent,\s*levels,\s*minimumPercent: autoFit\.minimumPercent,\s*maxAutoFitPercent: autoFit\.maxPercent,\s*replacementTotalQty: spec\.mode === 'OPEN' \? multiplyDecimalByInt\(minRequiredQty,\s*levels\) : null,\s*\}\)/); + assert.match(buildBody, /createLadderMinimumQtyFailure\(\{\s*spec,\s*symbol: startSymbol,\s*precision: startPrecision,\s*mode: spec\.mode,\s*minRequiredQty,\s*baseQty,\s*percent,\s*levels,\s*optionContext,\s*minimumPercent: autoFit\.minimumPercent,\s*maxAutoFitPercent: autoFit\.maxPercent,\s*replacementTotalQty: spec\.mode === 'OPEN' \? multiplyDecimalByInt\(minRequiredQty,\s*levels\) : null,\s*\}\)/); const errorBody = readFunctionBody('createLadderMinimumQtyFailure'); assert.match(errorBody, /数量低于最小下单量/); @@ -568,12 +568,16 @@ test('ladder minimum quantity failure explains safe manual options', () => { assert.match(errorBody, /自动提高比例/); assert.match(errorBody, /自动降档/); assert.match(errorBody, /openOrdersReplacementPlan/); + assert.match(errorBody, /precision,\s*optionContext,\s*totalQty: replacementTotalQty/); assert.match(errorBody, /replacementTotalQty/); assert.doesNotMatch(errorBody, /allowPartialReplacement/); assert.match(errorBody, /脚本只会尝试替换当前交易对的同向开仓基础单,不会自动全撤/); assert.match(errorBody, /脚本不会自动撤单/); assert.doesNotMatch(errorBody, /将自动撤单/); + const replacementPlanBody = readFunctionBody('getOpenLadderMinimumQtyReplacementPlan'); + assert.match(replacementPlanBody, /plan\.optionContext/); + const percentBody = readFunctionBody('computeMinimumLadderPercent', ladderPlanSource); assert.match(percentBody, /parseDecimalString\(baseQty\)/); assert.match(percentBody, /decimalToStepCount\(minRequiredQty,\s*stepSize,\s*'ceil'\)/);