All checks were successful
deploy / deploy (push) Successful in 59s
Proof: added persisted quote_lifecycle_stat_subjects snapshots, refreshed statistics from retained per-quote subjects, preserved completed/attributed execution evidence during lifecycle retention, and wired successful lifecycle evidence into the dashboard trade funnel; verified with targeted lifecycle/dashboard tests, full npm test, and operator dashboard bundle build. Assumptions: detailed successful trade rows already deleted by prior retention cannot be reconstructed from aggregate rollups without faking quote-level settlement evidence; the new subject table starts preserving surviving and future quote evidence after deployment. Still fake: fee-aware realized PnL and venue-native fill truth beyond retained settlement/inventory evidence remain out of scope; already-pruned detailed success rows remain unrecoverable.
128 lines
4.6 KiB
JavaScript
128 lines
4.6 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
|
|
import {
|
|
buildQuoteLifecycleStatistics,
|
|
classifyQuoteLifecycleStatisticsBucket,
|
|
quoteLifecycleStatisticWindow,
|
|
} from '../src/core/quote-lifecycle-statistics.mjs';
|
|
|
|
test('quote lifecycle statistics classify states without upgrading submitted-only rows to success', () => {
|
|
assert.equal(classifyQuoteLifecycleStatisticsBucket({
|
|
lifecycle_state: 'submitted',
|
|
execution: { status: 'submitted', result_code: 'quote_response_ok' },
|
|
}), 'submitted_no_reply');
|
|
assert.equal(classifyQuoteLifecycleStatisticsBucket({
|
|
lifecycle_state: 'failed',
|
|
execution: { status: 'failed', failure_category: 'quote_not_found_or_finished' },
|
|
}), 'submission_failed');
|
|
assert.equal(classifyQuoteLifecycleStatisticsBucket({
|
|
lifecycle_state: 'command_emitted',
|
|
}), 'awaiting_executor');
|
|
assert.equal(classifyQuoteLifecycleStatisticsBucket({
|
|
lifecycle_state: 'completed',
|
|
outcome_status: 'completed',
|
|
has_settlement_evidence: true,
|
|
}), 'success');
|
|
});
|
|
|
|
test('quote lifecycle statistics can aggregate retained quote subject buckets', () => {
|
|
const rows = buildQuoteLifecycleStatistics({
|
|
computedAt: '2026-06-12T14:20:00.000Z',
|
|
lifecycleRows: [{
|
|
quote_id: 'quote-retained-success',
|
|
quote_activity_at: '2026-06-12T14:11:01.000Z',
|
|
latest_stage_at: '2026-06-12T14:11:10.000Z',
|
|
statistics_bucket: 'success',
|
|
}],
|
|
});
|
|
|
|
const allTime = rows.find((row) => row.grain === 'all_time');
|
|
const fiveMinute = rows.find((row) => (
|
|
row.grain === 'five_minute'
|
|
&& row.window_start === '2026-06-12T14:10:00.000Z'
|
|
));
|
|
assert.equal(allTime.quote_count, 1);
|
|
assert.equal(allTime.bucket_counts.success, 1);
|
|
assert.equal(fiveMinute.quote_count, 1);
|
|
assert.equal(fiveMinute.bucket_counts.success, 1);
|
|
});
|
|
|
|
test('quote lifecycle statistics use UTC grain boundaries with Monday UTC weeks', () => {
|
|
assert.deepEqual(quoteLifecycleStatisticWindow('2026-06-12T17:34:44.123Z', 'five_minute'), {
|
|
grain: 'five_minute',
|
|
window_start: '2026-06-12T17:30:00.000Z',
|
|
window_end: '2026-06-12T17:35:00.000Z',
|
|
});
|
|
assert.deepEqual(quoteLifecycleStatisticWindow('2026-06-14T23:59:00.000Z', 'week'), {
|
|
grain: 'week',
|
|
window_start: '2026-06-08T00:00:00.000Z',
|
|
window_end: '2026-06-15T00:00:00.000Z',
|
|
});
|
|
assert.deepEqual(quoteLifecycleStatisticWindow('2026-06-01T00:00:00.000Z', 'month'), {
|
|
grain: 'month',
|
|
window_start: '2026-06-01T00:00:00.000Z',
|
|
window_end: '2026-07-01T00:00:00.000Z',
|
|
});
|
|
});
|
|
|
|
test('quote lifecycle statistics dedupe quotes and refresh later results in the original quote window', () => {
|
|
const rows = [
|
|
{
|
|
quote_id: 'quote-follow',
|
|
lifecycle_state: 'command_emitted',
|
|
quote_activity_at: '2026-06-12T17:31:01.000Z',
|
|
latest_stage_at: '2026-06-12T17:31:03.000Z',
|
|
},
|
|
{
|
|
quote_id: 'quote-follow',
|
|
lifecycle_state: 'failed',
|
|
quote_activity_at: '2026-06-12T17:31:01.000Z',
|
|
latest_stage_at: '2026-06-12T17:36:10.000Z',
|
|
execution: {
|
|
status: 'failed',
|
|
failure_category: 'quote_not_found_or_finished',
|
|
},
|
|
},
|
|
];
|
|
|
|
const statistics = buildQuoteLifecycleStatistics({
|
|
lifecycleRows: rows,
|
|
computedAt: '2026-06-12T17:40:00.000Z',
|
|
});
|
|
const allTime = statistics.find((row) => row.grain === 'all_time');
|
|
const fiveMinute = statistics.find((row) => (
|
|
row.grain === 'five_minute'
|
|
&& row.window_start === '2026-06-12T17:30:00.000Z'
|
|
));
|
|
const laterFiveMinute = statistics.find((row) => (
|
|
row.grain === 'five_minute'
|
|
&& row.window_start === '2026-06-12T17:35:00.000Z'
|
|
));
|
|
|
|
assert.equal(allTime.quote_count, 1);
|
|
assert.equal(allTime.bucket_counts.submission_failed, 1);
|
|
assert.equal(allTime.bucket_counts.awaiting_executor, 0);
|
|
assert.equal(fiveMinute.quote_count, 1);
|
|
assert.equal(fiveMinute.bucket_counts.submission_failed, 1);
|
|
assert.equal(laterFiveMinute, undefined);
|
|
});
|
|
|
|
test('quote lifecycle statistics preserve missing identifiers as unavailable evidence', () => {
|
|
const statistics = buildQuoteLifecycleStatistics({
|
|
lifecycleRows: [{
|
|
quote_id: null,
|
|
lifecycle_state: 'observed',
|
|
quote_activity_at: '2026-06-12T17:31:01.000Z',
|
|
}],
|
|
computedAt: '2026-06-12T17:40:00.000Z',
|
|
});
|
|
const allTime = statistics.find((row) => row.grain === 'all_time');
|
|
const fiveMinute = statistics.find((row) => row.grain === 'five_minute');
|
|
|
|
assert.equal(allTime.quote_count, 0);
|
|
assert.equal(allTime.missing_identifier_count, 1);
|
|
assert.equal(allTime.bucket_counts.unavailable, 1);
|
|
assert.equal(fiveMinute.quote_count, 0);
|
|
assert.equal(fiveMinute.missing_identifier_count, 1);
|
|
});
|