跳转到内容

接收单个持仓盈亏

reqPnLSingle() 的返回结果通过 pnlSingle() 接收。

def pnlSingle(self, reqId, pos, dailyPnL, unrealizedPnL, realizedPnL, value):
...

它返回的是单个持仓维度的盈亏和市值,不包含完整合约对象。因此程序通常要把 reqId 与请求时的 conIdaccount 保存起来,才能知道回调属于哪个合约。

字段中文含义说明
reqId请求编号对应 reqPnLSingle() 的请求编号
pos持仓数量可能是 Decimal,建议保存为字符串
dailyPnL当日盈亏按 TWS 的 PnL 重置规则计算
unrealizedPnL未实现盈亏未平仓部分的盈亏
realizedPnL已实现盈亏已平仓或已实现部分的盈亏
value市值持仓的市场价值

这些都是敏感交易数据。公开日志中不建议直接展示真实金额。

pending_single_pnl = {
9302: {
"account": "ACCOUNT_1",
"conid": 265598,
"modelCode": "",
}
}
def pnlSingle(self, reqId, pos, dailyPnL, unrealizedPnL, realizedPnL, value):
request = pending_single_pnl.get(reqId)
row = {
"reqId": reqId,
"account": request["account"],
"conid": request["conid"],
"position": str(pos),
"dailyPnL": dailyPnL,
"unrealizedPnL": unrealizedPnL,
"realizedPnL": realizedPnL,
"value": value,
}

如果要把结果展示到页面上,建议在后端完成账户号脱敏和字段筛选,再返回给前端。

TWS 模拟账户请求 AAPL conId=265598 的单持仓 PnL,结果为:

SINGLE_PNL_CALLBACK_RECEIVED=False
SINGLE_PNL_ROW_COUNT=0
SINGLE_PNL_REQID_COUNTS=NONE
SINGLE_PNL_VALUE_TYPE_COUNTS=NONE
INFO_CODES=2104,2106,2158
NON_INFO_ERROR_COUNT=0

没有该合约持仓时,pnlSingle() 可能不会被调用。程序应设置超时,不要无限等待。

为什么 pnlSingle() 没有 accountconId

Section titled “为什么 pnlSingle() 没有 account 和 conId?”

因为回调只返回 reqId 和 PnL 数值。账户、模型和合约 ID 需要由程序在请求时自己保存映射关系。

dailyPnLunrealizedPnL 一定一样吗?

Section titled “dailyPnL 和 unrealizedPnL 一定一样吗?”

不一定。dailyPnL 受当日重置规则影响,unrealizedPnL 表示未平仓部分的盈亏。

value 是持仓的市场价值,不是平均成本。