diff --git a/scripts/binance-orderbook-trade.user.js b/scripts/binance-orderbook-trade.user.js index 84ef243..1ea0ad0 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.153 +// @version 2.7.154 // @author jackhai9 // @description 单击订单簿价格,按当前开仓/平仓 tab 自动填数量并执行下单,内置数量倍率面板 // @match https://www.binance.com/*/futures/* @@ -906,7 +906,9 @@ function formatFailedLadderProgress(label, message, progress) { assertLadderLabel(label); assertLadderMessage(message); - return appendLadderProgressCounts(`${label}失败:${message}`, progress); + const counts = formatLadderProgressCounts(progress); + const details = counts.length > 0 ? `${counts.join(" · ")} · ${message}` : message; + return `${label}失败:${details}`; } function formatCompletedLadderProgress(label, completedOrders, totalOrders, progress) { assertLadderLabel(label); @@ -2504,7 +2506,8 @@ const LADDER_CONTROL_BUTTON_FONT_SIZE = 14; const PANEL_BOTTOM_TOOLTIP_GAP = 12; const TRADE_UI_STATE_TIMEOUT_MS = 1e3; - const TRADE_ACTION_BUTTON_READY_TIMEOUT_MS = 2e3; + const TRADE_ACTION_BUTTON_READY_TIMEOUT_SECONDS = 3; + const TRADE_ACTION_BUTTON_READY_TIMEOUT_MS = TRADE_ACTION_BUTTON_READY_TIMEOUT_SECONDS * 1e3; const ROUTE_WATCHDOG_MS = 5e3; let lastTs = 0; let isEditingMultiplier = false; @@ -4177,12 +4180,12 @@ if (button) return button; const currentButton = plan.spec.buttonGetter(); if (!currentButton || !currentButton.isConnected || !isVisibleElement(currentButton)) { - throw new Error(`${plan.spec.label}按钮尚未渲染完成,已停止`); + throw new Error(`下单按钮 ${TRADE_ACTION_BUTTON_READY_TIMEOUT_SECONDS} 秒内未渲染完成`); } if (isSubmitButtonBusy(currentButton)) { - throw new Error(`${plan.spec.label}按钮持续处理中,已停止`); + throw new Error(`下单按钮 ${TRADE_ACTION_BUTTON_READY_TIMEOUT_SECONDS} 秒内未恢复可点击`); } - throw new Error(`${plan.spec.label}按钮当前不可点击,已停止`); + throw new Error(`下单按钮 ${TRADE_ACTION_BUTTON_READY_TIMEOUT_SECONDS} 秒内未达到可点击状态`); } function readVisibleOrderFeedbackEntries() { const selectors = [ diff --git a/src/binance-orderbook-trade/core/ladder-progress.js b/src/binance-orderbook-trade/core/ladder-progress.js index 018dfbb..eba2328 100644 --- a/src/binance-orderbook-trade/core/ladder-progress.js +++ b/src/binance-orderbook-trade/core/ladder-progress.js @@ -102,7 +102,9 @@ export function formatInterruptedLadderProgress(label, reason, progress) { export function formatFailedLadderProgress(label, message, progress) { assertLadderLabel(label); assertLadderMessage(message); - return appendLadderProgressCounts(`${label}失败:${message}`, progress); + const counts = formatLadderProgressCounts(progress); + const details = counts.length > 0 ? `${counts.join(' · ')} · ${message}` : message; + return `${label}失败:${details}`; } export function formatCompletedLadderProgress(label, completedOrders, totalOrders, progress) { diff --git a/src/binance-orderbook-trade/index.user.js b/src/binance-orderbook-trade/index.user.js index f17ea73..eb0a4d7 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.153 +// @version 2.7.154 // @author jackhai9 // @description 单击订单簿价格,按当前开仓/平仓 tab 自动填数量并执行下单,内置数量倍率面板 // @match https://www.binance.com/*/futures/* @@ -339,7 +339,8 @@ import { const LADDER_CONTROL_BUTTON_FONT_SIZE = 14; const PANEL_BOTTOM_TOOLTIP_GAP = 12; const TRADE_UI_STATE_TIMEOUT_MS = 1000; - const TRADE_ACTION_BUTTON_READY_TIMEOUT_MS = 2000; + const TRADE_ACTION_BUTTON_READY_TIMEOUT_SECONDS = 3; + const TRADE_ACTION_BUTTON_READY_TIMEOUT_MS = TRADE_ACTION_BUTTON_READY_TIMEOUT_SECONDS * 1000; const ROUTE_WATCHDOG_MS = 5000; let lastTs = 0; @@ -2416,12 +2417,12 @@ import { const currentButton = plan.spec.buttonGetter(); if (!currentButton || !currentButton.isConnected || !isVisibleElement(currentButton)) { - throw new Error(`${plan.spec.label}按钮尚未渲染完成,已停止`); + throw new Error(`下单按钮 ${TRADE_ACTION_BUTTON_READY_TIMEOUT_SECONDS} 秒内未渲染完成`); } if (isSubmitButtonBusy(currentButton)) { - throw new Error(`${plan.spec.label}按钮持续处理中,已停止`); + throw new Error(`下单按钮 ${TRADE_ACTION_BUTTON_READY_TIMEOUT_SECONDS} 秒内未恢复可点击`); } - throw new Error(`${plan.spec.label}按钮当前不可点击,已停止`); + throw new Error(`下单按钮 ${TRADE_ACTION_BUTTON_READY_TIMEOUT_SECONDS} 秒内未达到可点击状态`); } function readVisibleOrderFeedbackEntries() { diff --git a/test/unit/binance-orderbook-trade/ladder-progress.test.js b/test/unit/binance-orderbook-trade/ladder-progress.test.js index 5326f2e..a6c0cd4 100644 --- a/test/unit/binance-orderbook-trade/ladder-progress.test.js +++ b/test/unit/binance-orderbook-trade/ladder-progress.test.js @@ -89,7 +89,7 @@ test('failed and interrupted ladder statuses retain confirmed progress', () => { assert.equal( formatFailedLadderProgress('阶梯开多', '数量框状态未稳定', progress), - '阶梯开多失败:数量框状态未稳定 · 已挂 1/5 笔 · 已撤 1 笔', + '阶梯开多失败:已挂 1/5 笔 · 已撤 1 笔 · 数量框状态未稳定', ); assert.equal( formatInterruptedLadderProgress('阶梯开多', '交易对已切换', progress), @@ -104,6 +104,18 @@ test('failed and interrupted ladder statuses retain confirmed progress', () => { formatInterruptedLadderProgress('阶梯平多', '交易对已切换', createLadderProgress()), '阶梯平多已中止:交易对已切换', ); + + const buttonNotReady = createLadderProgress(); + setLadderPlannedOrders(buttonNotReady, 2); + recordLadderSubmittedOrder(buttonNotReady); + assert.equal( + formatFailedLadderProgress( + '阶梯开空', + '下单按钮 3 秒内未恢复可点击', + buttonNotReady, + ), + '阶梯开空失败:已挂 1/2 笔 · 下单按钮 3 秒内未恢复可点击', + ); }); test('ladder progress rejects invalid counters instead of masking them', () => { diff --git a/test/unit/binance-orderbook-trade/source-regressions.test.js b/test/unit/binance-orderbook-trade/source-regressions.test.js index f61a8ba..2abc891 100644 --- a/test/unit/binance-orderbook-trade/source-regressions.test.js +++ b/test/unit/binance-orderbook-trade/source-regressions.test.js @@ -154,6 +154,10 @@ test('ladder execution waits for the current semantic action button before every assert.match(readyButtonBody, /await waitForTradeActionButtonFrameState/); assert.match(readyButtonBody, /plan\.spec\.buttonGetter/); + assert.match(source, /const TRADE_ACTION_BUTTON_READY_TIMEOUT_SECONDS = 3;/); + assert.match(source, /const TRADE_ACTION_BUTTON_READY_TIMEOUT_MS = TRADE_ACTION_BUTTON_READY_TIMEOUT_SECONDS \* 1000;/); + assert.match(readyButtonBody, /下单按钮 \$\{TRADE_ACTION_BUTTON_READY_TIMEOUT_SECONDS\} 秒内未恢复可点击/); + assert.doesNotMatch(readyButtonBody, /持续处理中/); assert.doesNotMatch(executeBody, /const button = plan\.spec\.buttonGetter\(\);\s*if/); assert.match(readyButtonBody, /isSubmitButtonBusy/); assert.doesNotMatch(source, /LADDER_ORDER_DELAY_MS/);