vn.py量化社区
By Traders, For Traders.
Member
avatar
加入于:
帖子: 22
声望: 2

最近策略研究方向中要使用到成交总金额(turnover),在这里中已经讲解了在实时的tickdata中加入成交总金额的方法。我沿着这个思路,增加修改的几个地方,实现在bardata中加入成交总金额。

注意一点是要先确保在tickdata中已成功加入成交总金额,再修改下面几个地方才能实现BarData中加入成交总金额。

1、object.py (为了上下文统一,所有的turnover改为小写,tickdata中也是)

class BarData(BaseData):
    ******省略
    interval: Interval = None
    volume: float = 0
    turnover: float = 0  ##增加,turnover小写
    open_interest: float = 0
    open_price: float = 0
    ******省略

2、database_sql.py(database_sql.py主要用于保存与读取数据库,也作修改,保证整个VNPY都能使用turnover)

def init_models(db: Database, driver: Driver):
    class DbBarData(ModelBase):
       ******省略
        volume: float = DoubleField()
        turnover: float = DoubleField()  ##增加,volume、turnover、open_interest改了Field类型,后面会说明原因
        open_interest: float = DoubleField()
        open_price: float = FloatField()
        high_price: float = FloatField()
        low_price: float = FloatField()
        close_price: float = FloatField()

        def from_bar(bar: BarData):
           ******省略
            db_bar.volume = bar.volume
            db_bar.turnover = bar.turnover  ##增加
            db_bar.open_interest = bar.open_interest
            db_bar.open_price = bar.open_price
            db_bar.high_price = bar.high_price
            db_bar.low_price = bar.low_price
            db_bar.close_price = bar.close_price

            return db_bar

        def to_bar(self):
            ******省略
                volume=self.volume,
                turnover=self.turnover,  ##增加
                open_price=self.open_price,
                high_price=self.high_price,
                open_interest=self.open_interest,
                low_price=self.low_price,
                close_price=self.close_price,
                gateway_name="DB",
            )
            return bar

3、utility.py(修改了合成1分钟Bar的update_tick(),update_bar()中window_bar.volume不知道为什么要对bar.volume整型处理,也先统一吧)

    def update_tick(self, tick: TickData):
        ******省略
        if self.last_tick:
            volume_change = tick.volume - self.last_tick.volume
            turnover_change = tick.turnover - self.last_tick.turnover  ##增加,对照volume
            self.bar.volume += max(volume_change, 0)
            self.bar.turnover += max(turnover_change, 0)   ##增加,对照volume
            # print(self.bar.turnover)
        self.last_tick = tick

    def update_bar(self, bar: BarData):
       ******省略
        # Update close price/volume into window bar
        self.window_bar.close_price = bar.close_price
        self.window_bar.volume += int(bar.volume)
        self.window_bar.turnover += int(bar.turnover)      ## 增加,对照window_bar.volume,不知道int()作用,int的范围更大?
        self.window_bar.open_interest = bar.open_interest

删除原来保存的bar数据库 database.db(会同时删掉dbtickdata表,或者可以直接删库下的dbbardata表),再重启VNPY,bardata中就加入了成交金额turnover。

完成上面的步骤后,输出bardata中的turnover,结果正确。我启动了datarecorder连接MySQL数据库,开始实时记录数据。发现turnover能够写入到MySQL中,但是后几位数字全是0。我在VNPY内各流程模块中打印出turnover,都是精确无误的,由此确定了问题应该出在本地的MySQL上。

查阅了peewee的文档,得知peewee的FloatField相当于MySQL的Real。MySQL中的Real一般是Float类型,在64位电脑上不设置长度、小数位,默认的Float精度只能到6位数,turnover存入时就溢出了。鉴于大于6位数挺常见的,所以将database_sql.py建表时的volume、turnover、open_interest改了Field类型为DoubleField(),问题解决。

还有几个注意要点:
①. VNPY的tick数据是CTP的源数据,turnover字段在郑商所中处理有点不太一样,turnover要乘以合约乘数才是真正的成交总金额。
②. 跟turnover相关还有一个是当日均价,这时郑商所是正确的,另外两商品交易所的要除以合约乘数。

Administrator
avatar
加入于:
帖子: 4028
声望: 221

给你加个精华

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