Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/binance-strategy27-events-development.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ Every created entity uses the second obtained by flooring the projection's
update. If TradingView shifts the point to a different bar, the entity is
removed and visualization stops with an alignment error.

`triggered_at_ms` is the trigger bucket's start boundary. The browser requires
`trigger_snapshot.bucket_start_ms` to equal it; the bucket end remains the
exclusive end of that same measurement interval.

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
Expand All @@ -62,4 +66,3 @@ Live validation must confirm the current Binance main-world chart API, exact
`1S` resolution, exact route symbol, successful create/readback/remove behavior,
Tampermonkey source readback, and the actually loaded source after a hard
reload. A source-level method name alone is not end-to-end proof.

4 changes: 2 additions & 2 deletions scripts/binance-strategy27-events.user.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.0
// @version 0.1.1
// @author jackhai9
// @description 在 Binance 一秒图表标注 VPS Strategy 27 的实时订单流事件和后续结果
// @match https://www.binance.com/*/futures/*
Expand Down Expand Up @@ -152,7 +152,7 @@
assertSortedUniqueStrings(value.trigger_reasons, "payload.event.trigger_reasons", { nonEmpty: true });
validateSnapshot(value.trigger_snapshot, "payload.event.trigger_snapshot");
validateSnapshot(value.latest_snapshot, "payload.event.latest_snapshot");
assertCondition(value.trigger_snapshot.bucket_end_ms === value.triggered_at_ms, "trigger snapshot must end at triggered_at_ms");
assertCondition(value.trigger_snapshot.bucket_start_ms === value.triggered_at_ms, "trigger snapshot must start at triggered_at_ms");
if (value.event_status === "active") {
assertCondition(value.active_end_at_ms === null && value.close_reason === null, "active event close fields must be null");
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/binance-strategy27-events/core/live-event-contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ function validateEvent(value) {
assertSortedUniqueStrings(value.trigger_reasons, 'payload.event.trigger_reasons', { nonEmpty: true });
validateSnapshot(value.trigger_snapshot, 'payload.event.trigger_snapshot');
validateSnapshot(value.latest_snapshot, 'payload.event.latest_snapshot');
assertCondition(value.trigger_snapshot.bucket_end_ms === value.triggered_at_ms, 'trigger snapshot must end at triggered_at_ms');
assertCondition(value.trigger_snapshot.bucket_start_ms === value.triggered_at_ms, 'trigger snapshot must start at triggered_at_ms');
if (value.event_status === 'active') {
assertCondition(value.active_end_at_ms === null && value.close_reason === null, 'active event close fields must be null');
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/binance-strategy27-events/index.user.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.0
// @version 0.1.1
// @author jackhai9
// @description 在 Binance 一秒图表标注 VPS Strategy 27 的实时订单流事件和后续结果
// @match https://www.binance.com/*/futures/*
Expand Down
20 changes: 16 additions & 4 deletions test/unit/binance-strategy27-events/live-event-contract.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const epoch = '0123456789abcdef0123456789abcdef';
const eventId = 'a'.repeat(64);
const lifecycleOptions = { maxEvents: 80, maxAgeMs: 2 * 60 * 60 * 1_000 };

function snapshot({ start = 750, end = 1_000, mid = '1.25' } = {}) {
function snapshot({ start = 1_000, end = 1_250, mid = '1.25' } = {}) {
return {
bucket_start_ms: start,
bucket_end_ms: end,
Expand Down Expand Up @@ -153,6 +153,18 @@ test('validates live envelopes without coercing decimal strings or extra keys',
}),
/canonical decimal string/,
);
assert.throws(
() => validateLiveEnvelope({
...opened,
payload: {
event: {
...opened.payload.event,
trigger_snapshot: snapshot({ start: 750, end: 1_000 }),
},
},
}),
/trigger snapshot must start at triggered_at_ms/,
);
});

test('tracks exact sequence and event lifecycle while allowing reset rehydration', () => {
Expand Down Expand Up @@ -215,7 +227,7 @@ test('tracks exact sequence and event lifecycle while allowing reset rehydration
test('rejects unknown lifecycle transitions without a reset', () => {
const lifecycle = new LiveEventLifecycle('BTR/USDT:USDT', lifecycleOptions);
lifecycle.apply(envelope());
const lateSnapshot = snapshot({ start: 2_750, end: 3_000 });
const lateSnapshot = snapshot({ start: 3_000, end: 3_250 });
const lateEvent = {
...event(),
triggered_at_ms: 3_000,
Expand All @@ -228,7 +240,7 @@ test('rejects unknown lifecycle transitions without a reset', () => {
id: 'b'.repeat(64),
kind: 'event_updated',
payload: { event: lateEvent },
eventTime: 3_000,
eventTime: 3_250,
})),
/unknown event/,
);
Expand Down Expand Up @@ -268,7 +280,7 @@ test('bounds retained lifecycle events and reports exact count and age evictions
id: eventB,
sequence: 4,
kind: 'event_updated',
eventTime: 1_000,
eventTime: 1_250,
}));
assert.equal(ignored.type, 'event_evicted');
assert.equal(lifecycle.size, 0);
Expand Down
2 changes: 1 addition & 1 deletion test/unit/userscript-release-contract.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.0');
assert.equal(contract.version, '0.1.1');
assert.equal(contract.runAt, 'document-idle');
assert.equal(contract.updateURL, contract.downloadURL);
assert.deepEqual(contract.matches, [
Expand Down
Loading