从图表交易
TradingLayer 是与经纪商无关的图表交易状态层:它保存规范化后的订单、持仓、成交和报价,并把用户操作以意图(TradingIntent)的形式向外输出。该层自己不发送任何东西——其中既没有传输通道,也没有账户和重试,与经纪商的通信仍由宿主负责。

引入
该层作为 @stocksharp/chart 包的一个独立入口点提供:
import { TradingLayer, TradingLayerPrimitive } from '@stocksharp/chart/trading';
不使用打包器时,同样的类可以在全局对象 SSChart 中取得(new SSChart.TradingLayer({ tickSize: 0.25 }))。
创建和更新
该层以价格网格参数创建,TradingLayerPrimitive 原语把它的状态绘制在序列之上,而 TradingOrderPlacementAdapter 把图表上的点击转换成下单意图:
import { createChart, CandlestickSeries } from '@stocksharp/chart';
import {
TradingLayer,
TradingLayerPrimitive,
TradingOrderPlacementAdapter,
type TradingIntent,
} from '@stocksharp/chart/trading';
declare const broker: { send(intent: TradingIntent): Promise<void> };
const chart = createChart(document.querySelector<HTMLElement>('#chart')!, {
timeScale: { timeVisible: true },
});
const candles = chart.addSeries(CandlestickSeries, { upColor: '#26a69a', downColor: '#ef5350' });
const layer = new TradingLayer({ tickSize: 0.25 });
chart.attachPrimitive(new TradingLayerPrimitive(layer, { showInactiveOrders: false }), {
series: candles,
});
// 经纪商的权威状态:图表只负责显示它,从不自行更改。
layer.setOrders([{
id: 'ob1',
side: 'buy',
type: 'limit',
status: 'working',
timeInForce: 'good-till-cancelled',
quantity: 2,
filledQuantity: 0,
price: 96,
revision: 1,
permissions: { canModify: true, canCancel: true },
label: 'BID',
}]);
layer.setPositions([{
id: 'pos1',
side: 'long',
quantity: 3,
averagePrice: 100,
revision: 1,
pnl: { realized: 0, unrealized: 45, currency: 'USD', markPrice: 101.5 },
permissions: { canClose: true, canReverse: true, canProtect: true },
}]);
layer.setQuote({ time: 1704326400, bidPrice: 100.75, bidSize: 5, askPrice: 101, askSize: 4 });
// 意图交给宿主,宿主再把结果回传给该层。
layer.subscribeIntents(intent => {
broker.send(intent).then(
() => layer.resolveIntent({ intentId: intent.intentId, status: 'accepted' }),
(error: Error) => layer.resolveIntent({
intentId: intent.intentId,
status: 'rejected',
reason: error.message,
}),
);
});
// Ctrl + 左键为限价买入,Ctrl + 右键为限价卖出。
new TradingOrderPlacementAdapter(chart, layer, { quantity: 1, orderType: 'limit', modifier: 'ctrl' });
setOrders、setPositions、setExecutions 和 setQuote 会整体替换相应的集合。每次调用都会先规范化再与当前状态比较:如果什么都没变,就不调用订阅者,否则发布一次变更,其中包含 added、updated(previous / current 成对)、removed 和 orderChanged 字段。报价是个例外:它的变更只有 previous 和 current。当前快照由 state() 给出——即 { version, orders, positions, executions, quote }。
规范化是严格的:价格必须落在 tickSize 网格上(带 priceOrigin 偏移),数量必须落在 quantityStep 上(如果设置了它);限价单需要 price,止损单需要 stopPrice,止损限价单则两个字段都需要。不一致的数据会以异常拒绝,而不是被悄悄修正。
意图
该层不执行用户操作,而是把它们作为意图发布:request* 方法返回一个意图对象,把它放入待处理队列,并传给 subscribeIntents 的订阅者。宿主在经纪商处执行该意图,并通过调用 resolveIntent({ intentId, status, reason }) 以 accepted 或 rejected 状态关闭它——结果会连同原始意图一起到达 subscribeIntentOutcomes。待处理的意图由 pendingIntents() 列出。
权限在发布之前就会检查:修改订单需要 permissions.canModify,撤销需要 canCancel,持仓操作需要 canClose、canReverse 和 canProtect。没有权限的订单被视为只读,调用会抛出异常。意图中会填入取自权威实体的 expectedRevision,以便经纪商可以拒绝那些基于过期数据构建的请求。
绘制与拖动
TradingLayerPrimitive 是图表原语,它在挂接时订阅该层,并绘制带标签的订单线、带 P&L 的持仓线、成交标记、bid/ask/last 线以及括号单之间的连线。显示什么、用什么颜色,由构造函数选项和 applyOptions 指定:showOrders、showInactiveOrders、showPositions、showExecutions、showExecutionLabels、showQuote、showPnl、showBrackets、autoscale、一组颜色(orderBuyColor、orderSellColor、inactiveOrderColor、longPositionColor、shortPositionColor、executionBuyColor、executionSellColor、bidColor、askColor、lastColor、bracketColor)、lineWidth、fontSize、orderLabelSpacing、zOrder,以及格式化器 priceFormatter、quantityFormatter 和 pnlFormatter。标识符 id 在创建时设置一次,之后不再改变。
当订单处于活动状态(pending、working 或 partially-filled)、不是市价单并且具有 canModify 权限时,可以用鼠标拖动它的线。拖动过程中,原语会显示对齐到网格的预览价格;松开按钮时发布 requestModifyOrder 意图,而预览会一直保持到宿主关闭该意图为止——被拒绝时线条回到权威价格。
光标命中的内容由 TradingOrderHitData、TradingPositionHitData、TradingExecutionHitData 和 TradingQuoteHitData 描述;isTradingPrimitiveHitData(value) 可以帮助在处理器中识别它们。
用鼠标下单
TradingOrderPlacementAdapter 把图表的标准下单信号与该层连接起来:它开启下单模式、监听点击并调用 requestPlaceOrder。它自己既不创建价格线,也不与经纪商通信。
选项:quantity(必填)、orderType——'limit' 或 'stop'(默认 'limit')、timeInForce(默认 'good-till-cancelled')、modifier——'ctrl'、'shift' 或 'alt'(默认 'ctrl')、color、title、enabled 和 sideResolver。默认解析器把左键当作买入、右键当作卖出,返回 null 则取消下单。适配器由方法 options()、applyOptions(patch)、setEnabled(enabled) 和 dispose() 控制。
该层的公共方法
setOrders(orders)、setPositions(positions)、setExecutions(executions)、setQuote(quote)— 替换权威状态;setQuote(null)会移除报价。state()— 带版本号的当前状态快照。normalizationOptions()— 创建该层时使用的价格网格参数。subscribeChanges(handler)、subscribeIntents(handler)、subscribeIntentOutcomes(handler)— 订阅;每个都返回一个取消订阅的函数。pendingIntents()、resolveIntent(resolution)— 待处理意图队列及其关闭。requestPlaceOrder(order)、requestModifyOrder(orderId, changes)、requestCancelOrder(orderId)— 订单操作。requestClosePosition(positionId, quantity)、requestReversePosition(positionId, quantity)— 持仓操作;不指定数量时取整个持仓。requestCreateStopLoss、requestEditStopLoss、requestRemoveStopLoss、requestCreateTakeProfit、requestEditTakeProfit、requestRemoveTakeProfit— 括号单的保护性订单。dispose()— 释放资源。
其余导出
- 模型枚举:
TradingSide、ChartOrderType、ChartOrderStatus、ChartOrderTimeInForce、ChartPositionSide、ChartBracketRole、ChartExecutionLiquidity、TradingIntentKind。 - 层与原语的枚举:
TradingLayerChangeKind、TradingIntentOutcomeStatus、TradingPrimitiveEntityKind、TradingQuoteKind。 - 数据校验与规范化:
normalizeChartOrder、normalizeChartOrders、normalizeChartPosition、normalizeChartPositions、normalizeChartExecution、normalizeChartExecutions、normalizeChartQuote、normalizeChartOrderRequest、normalizeTradingIntent、normalizeTradingModelOptions。 - 辅助计算:
quantizeTradingPrice— 把任意价格对齐到网格,chartOrderRemainingQuantity— 订单未成交的剩余量,chartPnlTotal— 已实现与未实现 P&L 之和。 - 类型
ChartOrder、ChartPosition、ChartExecution、ChartQuote、ChartOrderRequest、ChartOrderModification、TradingIntent以及由它们派生的意图接口。