迭代16: 交易关联驱动持仓份额动态调整(R-018)

This commit is contained in:
2026-09-08 11:09:05 +08:00
parent 22ec732607
commit 1223e2e74b
25 changed files with 1659 additions and 405 deletions
+26 -14
View File
@@ -37,27 +37,39 @@ const dataSource = {
const runtime = { dataSource, storage, settings };
// 端点注册齐全
assert(TRADE_METHODS.has('orders/attribution-candidates'), '端点 orders/attribution-candidates 已注册');
assert(TRADE_METHODS.has('orders/set-attribution'), '端点 orders/set-attribution 已注册');
// 端点注册齐全R-018candidates/set-attribution 退役 → targets/set/segments
assert(TRADE_METHODS.has('orders/attribution-targets'), '端点 orders/attribution-targets 已注册');
assert(TRADE_METHODS.has('orders/attribution-set'), '端点 orders/attribution-set 已注册');
assert(TRADE_METHODS.has('orders/attribution-segments'), '端点 orders/attribution-segments 已注册');
assert(TRADE_METHODS.has('trades/history'), '端点 trades/history 已注册');
assert(!TRADE_METHODS.has('orders/attribution-candidates'), '端点 orders/attribution-candidates 已退役');
assert(!TRADE_METHODS.has('orders/set-attribution'), '端点 orders/set-attribution 已退役');
// 候选端点(含策略名
// attribution-targets 端点(策略级 + 策略名 + activityShares
storage.openHolding('manual-t', '300057.SZ', 1000);
const cands = await handleTrade('orders/attribution-candidates', { code: '300057.SZ' }, runtime);
assert(cands.length === 1 && cands[0].strategyName === '手动做T', '候选含策略名(手动做T');
const tgt = await handleTrade('orders/attribution-targets', { code: '300057.SZ' }, runtime);
assert(tgt.length === 2, 'targets 返回全部策略');
const tRow = tgt.find((x) => x.strategyId === 'manual-t');
assert(tRow && tRow.strategyName === '手动做T' && tRow.activityShares === 1000, 'targets 含策略名 + activityShares(手动做T 1000');
// set-attribution 端点
storage.upsertTradeOrders([{ orderId: 'X-1', tradeDate: '20260901', code: '300057.SZ', insertDate: '20260901', insertTime: '093000' }]);
const h = storage.sqlite.db.prepare('SELECT holding_id FROM strategy_holdings WHERE strategy_id=?').get('manual-t');
const setRes = await handleTrade('orders/set-attribution', { orderId: 'X-1', strategyId: 'manual-t', holdingId: h.holding_id }, runtime);
assert(setRes.ok === true, 'set-attribution 端点返回 ok');
const row = storage.sqlite.db.prepare('SELECT strategy_id FROM trade_orders WHERE order_id=?').get('X-1');
assert(row.strategy_id === 'manual-t', '归属已持久化');
// attribution-set 端点(R-018 账本写操作)
storage.upsertTradeOrders([{ orderId: 'X-1', tradeDate: '20260901', code: '300057.SZ', insertDate: '20260901', insertTime: '093000', tradedVolume: 1000 }]);
const { AttributionService } = await import('../src/trades/AttributionService.js');
const svc = new AttributionService({ store: storage.sqlite });
const rt = { ...runtime, attribution: svc };
const setRes = await handleTrade('orders/attribution-set', { orderId: 'X-1', segments: [{ strategyId: 'manual-t', volume: 1000 }] }, rt);
assert(setRes.ok === true && setRes.segments.length === 1, 'attribution-set 返回 ok + segments');
const row = storage.sqlite.db.prepare('SELECT strategy_id, holding_id FROM trade_orders WHERE order_id=?').get('X-1');
assert(row.strategy_id === 'manual-t' && row.holding_id != null, '归属已持久化(冗余列镜像)');
// trades/history 端点(策略过滤)
// attribution-segments 端点
const segs = await handleTrade('orders/attribution-segments', { orderId: 'X-1' }, rt);
assert(segs.length === 1 && segs[0].strategyName === '手动做T', 'attribution-segments 读段含策略名');
// trades/history 端点(策略过滤经段表)
const hist = await handleTrade('trades/history', { start: '20260901', end: '20260901', strategyId: 'manual-t' }, runtime);
assert(hist.orders.length === 1 && hist.orders[0].orderId === 'X-1', 'history 端点按策略过滤命中');
assert(Array.isArray(hist.orders[0].segments) && hist.orders[0].segments.length === 1, 'history orders 附加 segments');
storage.close();
rmSync(dir, { recursive: true, force: true });