跳转到内容

接收成交详情

execDetails() 每次返回一条成交记录,execDetailsEnd() 表示这批成交详情已经返回完毕。

def execDetails(self, reqId, contract, execution) -> None:
print("成交请求 ID:", reqId)
print("合约:", contract.symbol, contract.secType, contract.currency)
print("成交 ID:", execution.execId)
print("成交时间:", execution.time)
print("方向:", execution.side)
print("数量:", execution.shares)
print("价格:", execution.price)
print("订单 ID:", execution.orderId)
print("永久订单 ID:", execution.permId)
def execDetailsEnd(self, reqId: int) -> None:
print("成交详情结束", reqId)

reqId 用来识别这是哪一次 reqExecutions() 请求返回的数据。contract 负责说明成交的合约,execution 负责说明成交本身。

字段
成交表execIdtimesymbolsidesharespriceorderIdpermId
费用表execIdcommissionAndFeescurrencyrealizedPNL

成交和费用可以通过 execId 合并。

def execDetails(self, reqId, contract, execution) -> None:
save_execution(
exec_id=execution.execId,
order_id=execution.orderId,
perm_id=execution.permId,
symbol=contract.symbol,
side=execution.side,
shares=float(execution.shares),
price=execution.price,
time=execution.time,
)
def commissionAndFeesReport(self, report) -> None:
update_execution_fee(
exec_id=report.execId,
commission_and_fees=report.commissionAndFees,
currency=report.currency,
realized_pnl=report.realizedPNL,
)

上面的 save_execution()update_execution_fee() 是业务系统里的保存函数名。实际项目可以写入 MySQL、SQLite、CSV 或日志系统,关键是用 execId 把两类数据合并。

EXEC_ROWS=0
COMMISSION_ROWS=0

空结果不代表错误。没有真实成交、过滤条件太窄、或该 clientId 看不到成交,都可能返回 0 行。

如果订单只是提交后撤单,例如模拟账户里用远离市价的限价单检查下单和撤单流程,就会有订单状态和已完成订单记录,但不会有 execDetails()

  • execDetails() 可能返回多次,一次一笔成交。
  • commissionAndFeesReport() 可能在成交回调后到达,不要依赖固定顺序。
  • execDetailsEnd() 表示成交详情批次结束,但费用报告是否已经全部到齐要根据程序实际收到的数据处理。
  • 程序重连后再次查询,可能会读到已经保存过的成交,因此成交表要做去重。