VeighNa量化社区
你的开源社区量化交易平台 | vn.py | vnpy
Member
avatar
加入于:
帖子: 1
声望: 0

CtpTdApi 未提供数据,需要修改onRspQryInvestorPosition接口实现
实现方案:

  1. 新增CtpTdApiVNPY类,继承CtpTdApi, 重载onRspQryInvestorPosition,在onRspQryInvestorPosition中计算开仓均价和逐笔浮盈
  2. 新增CtpVNPY类,继承CtpGateway,重载__init__接口,使用CtpTdApiVNPY初始化td_api
  3. 修改程序初始化,使用CtpVNPY类初始化。

具体代码:

  1. 新增CtpTdApiVNPY类
class CtpTdApiVNPY(CtpTdApi):

    def __init__(self, gateway: CtpGateway) -> None:
        """构造函数"""
        super().__init__(gateway)

    def onRspQryInvestorPosition(self, data: dict, error: dict, reqid: int, last: bool) -> None:
        """持仓查询回报"""
        if not data:
            return

        # 必须已经收到了合约信息后才能处理
        symbol: str = data["InstrumentID"]
        contract = symbol_contract_map.get(symbol, None)

        if contract:
            # 获取之前缓存的持仓数据缓存
            key: str = f"{data['InstrumentID'], data['PosiDirection']}"
            position = self.positions.get(key, None)
            if not position:
                position = PositionData(
                    symbol=data["InstrumentID"],
                    exchange=contract.exchange,
                    direction=DIRECTION_CTP2VT[data["PosiDirection"]],
                    gateway_name=self.gateway_name
                )
                self.positions[key] = position

            # 对于上期所昨仓需要特殊处理
            if position.exchange in {Exchange.SHFE, Exchange.INE}:
                if data["YdPosition"] and not data["TodayPosition"]:
                    position.yd_volume = data["Position"]
            # 对于其他交易所昨仓的计算
            else:
                position.yd_volume = data["Position"] - data["TodayPosition"]

            # 获取合约的乘数信息
            size: int = contract.size

            # 计算之前已有仓位的持仓总成本
            cost: float = position.price * position.volume * size

            position.opencost = data["OpenCost"]
            position.openprice = 0
            # 累加更新持仓数量和盈亏
            position.volume += data["Position"]
            position.pnl += data["PositionProfit"]

            # 计算更新后的持仓总成本和均价
            if position.volume and size:
                cost += data["PositionCost"]
                position.price = cost / (position.volume * size)
                # 计算开仓均价
                position.openprice = position.opencost / (position.volume * size)

                # 更新仓位冻结数量
            if position.direction == Direction.LONG:
                position.frozen += data["ShortFrozen"]
            else:
                position.frozen += data["LongFrozen"]

            # 计算浮盈
            position.settlementPrice = data["SettlementPrice"]
            floatprofit = position.settlementPrice * position.volume * size - position.opencost
            if position.direction == Direction.LONG:
                position.floatProfit = floatprofit
            else:
                position.floatProfit = -floatprofit

        if last:
            for position in self.positions.values():
                self.gateway.on_position(position)

            self.positions.clear()
  1. 新增CtpVNPY类
class CtpVNPY(CtpGateway):

    def __init__(self, event_engine: EventEngine, gateway_name: str) -> None:
        super().__init__(event_engine, gateway_name)
        self.td_api: "CtpTdApi" = CtpTdApiVNPY(self)
  1. 修改程序初始化
init_cli_trading([CtpVNPY])
Member
avatar
加入于:
帖子: 1991
声望: 159

感谢分享!