diff --git a/docs/binance-strategy27-events-development.md b/docs/binance-strategy27-events-development.md index c491e72..fb9b8d6 100644 --- a/docs/binance-strategy27-events-development.md +++ b/docs/binance-strategy27-events-development.md @@ -44,6 +44,11 @@ removed and visualization stops with an alignment error. `trigger_snapshot.bucket_start_ms` to equal it; the bucket end remains the exclusive end of that same measurement interval. +For a closed event, `latest_snapshot` is the last eligible event bucket retained +before closure. `event_closed.event_time_ms` carries `active_end_at_ms` and can +be later than that snapshot's end when an ineligible bucket advances the event +to its lifecycle deadline without joining the event. + The script stores only its own returned entity IDs. Route, symbol, interval, epoch, cursor, or sequence discontinuities abort the request and remove only those transient entities. Event count and age are bounded in memory and on the diff --git a/scripts/binance-strategy27-events.user.js b/scripts/binance-strategy27-events.user.js index 55a6697..eddb859 100644 --- a/scripts/binance-strategy27-events.user.js +++ b/scripts/binance-strategy27-events.user.js @@ -3,7 +3,7 @@ // @namespace binance.strategy27.events // @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 0.1.1 +// @version 0.1.2 // @author jackhai9 // @description 在 Binance 一秒图表标注 VPS Strategy 27 的实时订单流事件和后续结果 // @match https://www.binance.com/*/futures/* @@ -165,7 +165,6 @@ "universe_removed", "monitor_stopped" ].includes(value.close_reason), "closed event close_reason is invalid"); - assertCondition(value.latest_snapshot.bucket_end_ms === value.active_end_at_ms, "closed latest snapshot must end at active_end_at_ms"); } } function validateOutcome(value) { diff --git a/src/binance-strategy27-events/core/live-event-contract.js b/src/binance-strategy27-events/core/live-event-contract.js index 872bc5f..3b2a9ad 100644 --- a/src/binance-strategy27-events/core/live-event-contract.js +++ b/src/binance-strategy27-events/core/live-event-contract.js @@ -154,7 +154,6 @@ function validateEvent(value) { 'universe_removed', 'monitor_stopped', ].includes(value.close_reason), 'closed event close_reason is invalid'); - assertCondition(value.latest_snapshot.bucket_end_ms === value.active_end_at_ms, 'closed latest snapshot must end at active_end_at_ms'); } } diff --git a/src/binance-strategy27-events/index.user.js b/src/binance-strategy27-events/index.user.js index b25941c..5f47de2 100644 --- a/src/binance-strategy27-events/index.user.js +++ b/src/binance-strategy27-events/index.user.js @@ -3,7 +3,7 @@ // @namespace binance.strategy27.events // @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 0.1.1 +// @version 0.1.2 // @author jackhai9 // @description 在 Binance 一秒图表标注 VPS Strategy 27 的实时订单流事件和后续结果 // @match https://www.binance.com/*/futures/* diff --git a/test/unit/binance-strategy27-events/live-event-contract.test.js b/test/unit/binance-strategy27-events/live-event-contract.test.js index ae23393..df26ed9 100644 --- a/test/unit/binance-strategy27-events/live-event-contract.test.js +++ b/test/unit/binance-strategy27-events/live-event-contract.test.js @@ -167,6 +167,25 @@ test('validates live envelopes without coercing decimal strings or extra keys', ); }); +test('allows a closed event to retain the last eligible snapshot before its lifecycle boundary', () => { + const closedEvent = { + ...event({ status: 'complete', activeEnd: 2_000 }), + latest_snapshot: snapshot({ start: 1_500, end: 1_750 }), + }; + const closedEnvelope = envelope({ + kind: 'event_closed', + payload: { event: closedEvent }, + status: 'complete', + eventTime: 2_000, + }); + + assert.equal(validateLiveEnvelope(closedEnvelope), closedEnvelope); + assert.throws( + () => validateLiveEnvelope({ ...closedEnvelope, event_time_ms: 1_999 }), + /event_closed time is invalid/, + ); +}); + test('tracks exact sequence and event lifecycle while allowing reset rehydration', () => { const lifecycle = new LiveEventLifecycle('BTR/USDT:USDT', lifecycleOptions); const opened = lifecycle.apply(envelope()); diff --git a/test/unit/userscript-release-contract.test.js b/test/unit/userscript-release-contract.test.js index 96aed57..4ca515e 100644 --- a/test/unit/userscript-release-contract.test.js +++ b/test/unit/userscript-release-contract.test.js @@ -37,7 +37,7 @@ test('release contract identifies the generated Strategy 27 annotation artifact' assert.equal(contract.name, '【自写】Binance Strategy 27 事件标注'); assert.equal(contract.namespace, 'binance.strategy27.events'); - assert.equal(contract.version, '0.1.1'); + assert.equal(contract.version, '0.1.2'); assert.equal(contract.runAt, 'document-idle'); assert.equal(contract.updateURL, contract.downloadURL); assert.deepEqual(contract.matches, [