Files

77 lines
3.9 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* API 层集成测试:handleTrade 各端点(含 settings 依赖的 candidates 端点)
* 独立数据目录,mock dataSource + 真实 storage/settings
*/
import { mkdtempSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { DataStore } from '../src/storage/DataStore.js';
import { handleTrade, TRADE_METHODS } from '../src/api/trades.js';
const dir = mkdtempSync(join(tmpdir(), 'odl-api-test-'));
process.env.ODL_TEST_DATA_DIR = dir;
let pass = 0, fail = 0;
function assert(cond, msg) {
if (cond) { pass++; console.log(' ✅ ' + msg); }
else { fail++; console.log(' ❌ ' + msg); }
}
const storage = new DataStore({ dataDir: dir });
await storage._ensure();
// mock settings(含策略名)
const settings = {
get: () => ({ strategies: [
{ id: 'grid-supermarket', name: '网格超市' },
{ id: 'manual-t', name: '手动做T' },
]}),
};
// mock dataSource
const dataSource = {
async getOrders() { return []; },
async getTrades() { return []; },
async getTradingDates() { return { market: '', dates: [] }; },
};
const runtime = { dataSource, storage, settings };
// 端点注册齐全(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 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');
// 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, '归属已持久化(冗余列镜像)');
// 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 });
console.log('\n结果: ' + pass + ' 通过, ' + fail + ' 失败');
process.exit(fail > 0 ? 1 : 0);