feat: 迭代03-05 交易记录接入、行情实时、QMT连接配置、data store 标准化
- R-004 QMT连接配置:多配置管理 + 会话头部快捷切换(03-QMT连接配置) - R-005 WS盘中价格实时更新:服务端中转+缓存+前端轮询(04-WS盘中价格实时更新) - R-006 策略数据 JSON data store 标准化(store.json/market.json/schema.json) - R-007 交易记录接入:当日订单+成交单表合并(委托主行+展开成交明细)、时间段查询(今日/本周/本月+手动起止)、费用计算(佣金费率万m_dCommission+最低5元、印花税卖出万5、过户费双向万0.1) - 架构治理:api 按领域拆分、component 目录、QmtHealthMonitor
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* 服务端 HTTP API 入口(2026-08-31 从 api.js 按领域拆分)
|
||||
*
|
||||
* 结构:
|
||||
* src/api/
|
||||
* ├── index.js # 路由入口:合并各领域 + 公共处理(405/404/500)
|
||||
* ├── common.js # 公共工具(writeJson/readJsonBody/resolveActiveBaseUrl)
|
||||
* ├── positions.js # 持仓域(positions)
|
||||
* ├── strategies.js # 策略/份额/tabs 域
|
||||
* ├── qmt-connections.js # QMT 连接配置域(含热切换编排)
|
||||
* └── market.js # 行情域(market-snapshot)
|
||||
*
|
||||
* 端点(POST /odl/api/<method>,body = { args: {...} }):
|
||||
* positions → 全量持仓
|
||||
* strategies → 策略列表(含 visible)
|
||||
* strategies/update → 更新策略列表(整表)
|
||||
* strategies/add → 新增策略 { name }
|
||||
* strategies/remove → 删除策略 { strategyId },联动清份额
|
||||
* strategies/move → 排序 { strategyId, dir }
|
||||
* strategy-positions → 某策略持仓 { strategyId }
|
||||
* unallocated → 未分配持仓
|
||||
* summary → 分仓摘要
|
||||
* add-shares → 添加份额 { code, strategyId, shares }
|
||||
* move-all-shares → 全部移入 { code, strategyId }
|
||||
* remove-shares → 移出份额 { code, strategyId, shares }
|
||||
* remove-all-shares → 一键清零 { strategyId }
|
||||
* tabs / tabs/update → 通用 tab 显隐配置
|
||||
* qmt-connections → QMT 连接配置(R-004)
|
||||
* qmt-connections/* → 增删改/激活/默认/测试/active-host/订阅代理
|
||||
* market-snapshot → 按 code 查询行情缓存(R-005)
|
||||
*/
|
||||
|
||||
import { API_PREFIX, writeJson, readJsonBody } from './common.js';
|
||||
import { POSITION_METHODS, handlePosition } from './positions.js';
|
||||
import { STRATEGY_METHODS, handleStrategy } from './strategies.js';
|
||||
import { QMT_METHODS, handleQmt } from './qmt-connections.js';
|
||||
import { MARKET_METHODS, handleMarket } from './market.js';
|
||||
import { TRADE_METHODS, handleTrade } from './trades.js';
|
||||
|
||||
/** 全部端点方法表(合并各领域) */
|
||||
const METHODS = new Set([
|
||||
...POSITION_METHODS,
|
||||
...STRATEGY_METHODS,
|
||||
...QMT_METHODS,
|
||||
...MARKET_METHODS,
|
||||
...TRADE_METHODS,
|
||||
]);
|
||||
|
||||
/** 领域分发:method → handler */
|
||||
const HANDLERS = [
|
||||
{ set: POSITION_METHODS, handle: handlePosition },
|
||||
{ set: STRATEGY_METHODS, handle: handleStrategy },
|
||||
{ set: QMT_METHODS, handle: handleQmt },
|
||||
{ set: MARKET_METHODS, handle: handleMarket },
|
||||
{ set: TRADE_METHODS, handle: handleTrade },
|
||||
];
|
||||
|
||||
/**
|
||||
* 注册 HTTP API
|
||||
* @param {import('@deepseek-ai/cordis').Context} ctx
|
||||
* @param {object} runtime { manager, settings, dataSource, marketCache }
|
||||
*/
|
||||
export function registerApi(ctx, { manager, settings, dataSource, marketHub, marketFeed, qmtHealthMonitor }) {
|
||||
const runtime = { ctx, manager, settings, dataSource, marketHub, marketFeed, qmtHealthMonitor };
|
||||
|
||||
ctx.effect(() => ctx.webServer.register({
|
||||
kind: 'prefix',
|
||||
path: '/odl/api',
|
||||
handler: async (req, res) => {
|
||||
if (req.method !== 'POST') {
|
||||
writeJson(res, 405, { ok: false, error: { code: 'method-error', message: 'method not allowed' } });
|
||||
return;
|
||||
}
|
||||
const pathname = new URL(req.url ?? '/', 'http://dsh.internal').pathname;
|
||||
const method = pathname.startsWith(API_PREFIX) ? pathname.slice(API_PREFIX.length) : void 0;
|
||||
if (!method || !METHODS.has(method)) {
|
||||
writeJson(res, 404, { ok: false, error: { code: 'not-found', message: 'unknown method: ' + method } });
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const body = await readJsonBody(req);
|
||||
const args = body?.args ?? {};
|
||||
// 按领域分发
|
||||
let value;
|
||||
for (const { set, handle } of HANDLERS) {
|
||||
if (set.has(method)) {
|
||||
value = await handle(method, args, runtime);
|
||||
break;
|
||||
}
|
||||
}
|
||||
writeJson(res, 200, { ok: true, value });
|
||||
} catch (error) {
|
||||
writeJson(res, 500, {
|
||||
ok: false,
|
||||
error: { code: error?.code ?? 'internal', message: error?.message ?? String(error), details: {} },
|
||||
});
|
||||
}
|
||||
},
|
||||
}), 'one-divine-lot.api');
|
||||
|
||||
ctx.logger?.info('[one-divine-lot] HTTP API 已注册 (/odl/api/*)');
|
||||
}
|
||||
Reference in New Issue
Block a user