learning_ai_invt_trdg/backend/testStateMergeCoverage.ts

157 lines
4.8 KiB
TypeScript

import assert from 'node:assert/strict';
import { mergeOrderSnapshots, mergePositionSnapshots } from '../src/services/stateMerge.js';
const testMergePositionSnapshots = () => {
const merged = mergePositionSnapshots([
[
{
id: 'p-global-1',
symbol: 'BTC/USD',
side: 'BUY',
size: 0.5,
entryPrice: 50000,
currentPrice: 50500,
stopLoss: 49000,
takeProfit: 52000,
unrealizedPnl: 250,
unrealizedPnlPercent: 1,
marketValue: 25250,
tradeId: 'TRD-abc-1'
}
],
[
{
id: 'p-profile-1',
symbol: 'BTC/USD',
side: 'BUY',
size: 0.5,
entryPrice: 50000,
currentPrice: 50600,
stopLoss: 49100,
takeProfit: 52100,
unrealizedPnl: 300,
unrealizedPnlPercent: 1.2,
marketValue: 25300,
userId: 'user-1',
profileId: 'profile-1',
profileName: 'High Risk',
tradeId: 'TRD-abc-1'
}
]
]);
assert.equal(merged.length, 1, 'stable trade_id duplicates should collapse');
assert.equal(merged[0].profileId, 'profile-1', 'profile should be preserved from richer position');
assert.equal(merged[0].userId, 'user-1', 'user should be preserved from richer position');
assert.equal(merged[0].tradeId, 'TRD-abc-1');
};
const testMergePositionFallbackReduction = () => {
const merged = mergePositionSnapshots([
[
{
id: 'fallback-1',
symbol: 'ETH/USD',
side: 'BUY',
size: 1,
entryPrice: 2000,
currentPrice: 2010,
stopLoss: 1900,
takeProfit: 2200,
unrealizedPnl: 10,
unrealizedPnlPercent: 0.5,
marketValue: 2010,
profileId: 'profile-1',
tradeId: 'TRD-SYNC-profile-1-ETHUSD'
},
{
id: 'fallback-2',
symbol: 'ETH/USD',
side: 'BUY',
size: 1,
entryPrice: 2000,
currentPrice: 2020,
stopLoss: 1890,
takeProfit: 2210,
unrealizedPnl: 20,
unrealizedPnlPercent: 1,
marketValue: 2020,
profileId: 'profile-1'
}
]
]);
assert.equal(merged.length, 1, 'fallback same owner+symbol+side should reduce to one row');
assert.equal(merged[0].profileId, 'profile-1');
assert.equal(merged[0].symbol, 'ETH/USD');
};
const testMergeOrderSnapshots = () => {
const merged = mergeOrderSnapshots([
[
{
id: 'ord-1',
symbol: 'BTC/USD',
type: 'Market',
side: 'BUY',
qty: 0.25,
price: 50000,
status: 'pending_new',
timestamp: 1000
}
],
[
{
id: 'ord-1',
symbol: 'BTC/USD',
type: 'Market',
side: 'BUY',
qty: 0.25,
price: 50010,
status: 'filled',
timestamp: 1050,
profileId: 'profile-2',
trade_id: 'TRD-ord-1',
action: 'ENTRY',
source: 'BOT'
},
{
id: 'ord-2',
symbol: 'ETH/USD',
type: 'Market',
side: 'SELL',
qty: 1,
price: 2000,
status: 'rejected',
timestamp: 900,
profileId: 'profile-2',
trade_id: 'TRD-ord-2',
action: 'EXIT',
source: 'BOT'
}
]
]);
assert.equal(merged.length, 2, 'orders should be merged by order id');
const ord1 = merged.find((order) => order.id === 'ord-1');
assert.ok(ord1, 'ord-1 should exist');
assert.equal(ord1?.status, 'filled', 'terminal status should not be downgraded');
assert.equal(ord1?.profileId, 'profile-2');
assert.equal(ord1?.trade_id, 'TRD-ord-1');
assert.equal(ord1?.source, 'BOT');
assert.equal(ord1?.action, 'ENTRY');
const ord2 = merged.find((order) => order.id === 'ord-2');
assert.equal(ord2?.status, 'rejected');
};
const run = () => {
testMergePositionSnapshots();
testMergePositionFallbackReduction();
testMergeOrderSnapshots();
console.log('[state-merge-coverage] OK: position/order snapshot merge behavior validated');
};
run();