VeighNa量化社区
你的开源社区量化交易平台
Member
加入于:
帖子: 158
声望: 71

最近想到个需求,针对期货CTP接口,比如持有三个合约,每个合约占用的资金比率。

这个需求分解下,就是资金占用,这个在期货中就是保证金金额。

在CTP接口中,OnRspQryTradingAccount 方法是返回查询账户资金信息,可以返回账号总保证金金额。

而onRspQryInvestorPosition方法是返回查询持仓情况,持仓情况包括对应合约的保证金金额,这里要注意的地方是,CTP 系统将持仓明细记录按合约,持仓方向,开仓日期(针对上期所,区分昨仓、今仓)进行汇总,而vnpy是只区分合约和合约方向,vnpy会将不同开仓时间返回的进行二次汇总。

这里处理流程就和明确了,首先增强PositionData和 AccountData 这两个数据类,加入保证金属性;然后增强ctp_gateway的对应方法中获取保证金数据;这两步比较简单,代码略。

第三步增强仓位报表PositionMonitor,增加保证金相关header数据列。然后除了默认的“EVENT_POSITION”, 还要订阅注册“EVENT_ACCOUNT",这里要重写父类方法regist_event;其实vnpy中事件注册时多对多关系,一个方法可以处理多个事件,虽然默认不鼓励。

def register_event(self):
    super(PositionMonitor,self).register_event()
    if self.event_type_account:
        self.signal.connect(self.process_event)
        self.event_engine.register(self.event_type_account, self.signal.emit)

然后复写父类方法process_event,来处理这两个事件,如果是Account事件,就更新总保证金数据,如果是合约事件,就计算对应保证金金额和总保证金百分比。

def process_event(self, event: Event) -> None:

    # Disable sorting to prevent unwanted error.
    if self.sorting:
        self.setSortingEnabled(False)
    # Update data into table.
    if event.type == self.event_type_account:
        self.total_margin = event.data.CurrMargin
    else:
        data = copy(event.data)
        if self.total_margin!=0:
            data.useMarginRate = '{:.2%}'.format(data.useMargin/self.total_margin)
        if not self.data_key:
            self.insert_new_row(data)
        else:
            key = data.__getattribute__(self.data_key)
            if key in self.cells:
                self.update_old_row(data)
            else:
                self.insert_new_row(data)
        # Enable sorting
        if self.sorting:
            self.setSortingEnabled(True)

其实修改逻辑很简单,就是一个方法处理多个事件要考虑下。实现效果如下图:

description

Member
加入于:
帖子: 158
声望: 71

最后补充下,如果一个事件Event被多个方法订阅处理的,每个方法最好用copy(event.data)这样处理传入对象,这样的话,对data对象处理就不会影响其他方法中的接收data; 吃过亏。。。

Administrator
avatar
加入于:
帖子: 4502
声望: 321

张国平 wrote:

最后补充下,如果一个事件Event被多个方法订阅处理的,每个方法最好用copy(event.data)这样处理传入对象,这样的话,对data对象处理就不会影响其他方法中的接收data; 吃过亏。。。

感谢分享!给你加上精华。

event.data的这个问题其实算是Python动态特性的一个双刃剑了,类似C++的shared ptr智能指针可以任意传递,同时还无法通过const来限制对入参的修改,不熟悉的时候很容易掉坑。

也是我们在CTA策略模块的DEMO策略里,几乎清一色围绕ArrayManager来进行数据缓存和计算的原因了,放到numpy.array里自然就不再会引用老的TickData/BarData等对象。

© 2015-2022 上海韦纳软件科技有限公司
备案服务号:沪ICP备18006526号

沪公网安备 31011502017034号

【用户协议】
【隐私政策】
【免责条款】