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

2020-12-15 22:54:08,446 INFO: vetusdt: 策略启动
2020-12-15 22:54:08,446 INFO: yfiusdt: 策略启动
2020-12-15 23:20:46,077 INFO: vetusdt: 开多98608.6手,时间2020-12-15 22:00:00,订单['STOP.1']
2020-12-16 09:39:45,236 INFO: yfiusdt: 开空0.164手,时间2020-12-15 22:00:00,订单['STOP.2']

self.write_log("开多{}手,时间{},订单{}".format(self.lots, bar.datetime, self.buy_vt_orderids))

策略具体的开仓逻辑是在1小时Bar上触发的,按理来说发单的时间节点肯定应该都是整数小时点之后的很近的时间,但是从上面打印的日志显示, 第一个停止单发单时的那根1小时Bar是在22:00:00,对应的合成完的时间应该是在23点初,但实际触发信号时的本地时间是23:20分钟,前后的时间间隔足足差距了20分钟。第二个停止单就更夸张了,停止单发单时的那根1小时Bar依然是在22:00:00, 但是开仓停止单的本地时间是第二天09:39,两者的时间间隔差了十几个小时。

不是合约流动性的问题,流动性好的合约也同样出现上面的问题,我的Bar合成逻辑也没有自己修改过。这个情况多出现在每个策略重启的时候的第一个信号,之后的信号Bar的时间和本地时间基本上是一致的,但是每个信号依然比合成好的那1小时Bar滞后了1-2分钟。

2020-12-15 23:02:23,384 INFO: xrpusdt: 平空26204.3手,时间2020-12-15 22:00:00,订单['STOP.1']
2020-12-16 04:01:41,404 INFO: btcusdt: 平多0.5手,时间2020-12-16 03:00:00,订单['STOP.7']
上面这两个都是非常活跃的合约了,从本地打印出来的时间可以看出,发单的时间是在上一个小时结束之后的1-2分钟之后了,我每个进程下运行的策略数量不大,计算逻辑也不复杂,没有发现有tick阻塞的情况。

我的交易服务器的物理地址在新加坡,据说币安的服务器在日本,虽然差距了一个时区,但也不应该出现上面的这个问题吧? 从时间戳看起来合成出来的Bar有比较久的滞后,这样很容易影响到回测和实盘的一致性的。 回测的逻辑是这一根1小时Bar走完就立刻推送出来了,但是现在实盘却观察到的是1小时Bar合成好出来信号的时候,已经滞后了1-2分钟了。请问大家有遇到我说的这个情况吗?感觉问题还是比较严重的。

Member
avatar
加入于:
帖子: 2038
声望: 134
  1. 币安永续应该是用的本地停止单,本地停止单只是在本地缓存了信息,触发条件时才会以涨停跌停价或者盘口五档价格发出下单。
  2. 可以去vnpy.trader.utility下去看bg的update_bar函数,合成小时线的时候的判断是上一个合成的bar的小时和这一个合成的bar的小时不一致,才合成一根小时线。那么,以三点举例,应该要三点整走完到三点零一分,合成了三点整的K线了再去与两点五十九分的K线比较才生成这根小时线。如果想要别的合成方法,可以自己进行个性化修改
Member
avatar
加入于:
帖子: 31
声望: 0
  1. 我知道币安是本地停止单啊,但本地停止单开仓发在本地缓存的信息,也肯定是应该在整数小时走完很短的一个延迟发单才对,我上面说全部都是本地停止单发到到本地缓存的时间延迟。
  2. ”以三点举例,应该要三点整走完到三点零一分,合成了三点整的K线了再去与两点五十九分的K线比较才生成这根小时线。“
    这个合成逻辑我理解,底层代码也都看过了,即使是这样,也不应该有超过几秒的延迟才对,最多也就两个tick推送间隔时长的延迟而已,你看我上面的信息,现在合成小时Bar延迟已经超过了1分钟多钟了,期间tick推送的间隔也就0.5秒-几秒之内的,所以现在肯定是哪里有点问题。
Member
avatar
加入于:
帖子: 31
声望: 0

我拿了个最活跃的币安永续BTCUSDT合约交易做合成K线的测试。
在on_bar和合成1小时的on_hour_bar函数里面,将服务器的本地时间和合成Bar的时间打印了出来:

self.write_log('当前时间{},合成分钟Bar时间{}'.format(datetime.now(), bar.datetime))
self.write_log('当前时间{},合成小时Bar时间{}'.format(datetime.now(), bar.datetime))

description

从图中可以发现,在分钟Bar合成的时候,时间上存在很大的不确定性,有的Bar是在下一分钟的前几秒合成的,有的Bar是在下一分钟的几十秒之后才合成出来,有的合成出来的Bar居然已经延迟了1分钟多钟。币安永续BTCUSDT是流动性非常好的,tick几乎每秒都有更新,上述问题肯定不是没有tick推送过来导致的。
从时间戳上可以看出,这个合成K先的滞后性问题很大,这样也会导致实盘和回测绩效有比较大的差异了。

Administrator
avatar
加入于:
帖子: 4607
声望: 264
  1. BarGenerator合成的分钟线时间戳,是该分钟的开始点,而非结束点,所以和当前时间天然应该差1分钟
  2. 你的本机时间和交易所的服务器时间,可能存在一定的偏差
  3. 币圈交易所的WS推送并不那么稳定,如果不是用同区域的托管云服务器(尤其是翻墙情况下),网络抖动可能很大
  4. 小时线合成,之前的写法会延时1分钟生成,新版本2.1.8已经修改了

请照着上述几条检查下问题吧

Member
avatar
加入于:
帖子: 31
声望: 0

用Python的交易员 wrote:

  1. BarGenerator合成的分钟线时间戳,是该分钟的开始点,而非结束点,所以和当前时间天然应该差1分钟
  2. 你的本机时间和交易所的服务器时间,可能存在一定的偏差
  3. 币圈交易所的WS推送并不那么稳定,如果不是用同区域的托管云服务器(尤其是翻墙情况下),网络抖动可能很大
  4. 小时线合成,之前的写法会延时1分钟生成,新版本2.1.8已经修改了

请照着上述几条检查下问题吧

  1. 你的本机时间和交易所的服务器时间,可能存在一定的偏差
    请问这个问题,应该如何校对呢? 调试的时候,我只能输出tick推送过来的时间,但是无法确切的知道交易所服务器此时的精确时间。

  2. 如果要保证同区域的托管云服务器的话,比如交易币安的话,币安的交易服务器在日本的AWS对吧? 那就是需要把云服务器放到日本(东九区时区)?
    我现在的云服务器放在了新加坡(东八区时区),之前在环球时区那个帖子里面有看到,币安的接口时区就是东八区时区,所以现在就很疑惑,为了保持同区域,到底应该是把服务器放在日本(东九区时区)还是香港或者新加坡(东八区时区)?

Member
avatar
加入于:
帖子: 31
声望: 0

新版本2.1.8 在合成一小时Bar的时候,从逻辑上看,好像是会出现仅一根分钟Bar就合成了1小时Bar的情况:

新版本的update_bar代码如下:

    elif self.interval == Interval.HOUR:
        if self.last_bar:
            new_hour = bar.datetime.hour != self.last_bar.datetime.hour
            last_minute = bar.datetime.minute == 59
    ....

    # Cache last bar object
    self.last_bar = bar

比如当根Bar是59分钟的时候,表示1小时内最后一分钟Bar已经走完了,此时合成1小时Bar, 合成逻辑正确。
但在下一根0分钟的Bar时, 因为 bar.datetime.hour != self.last_bar.datetime.hour,结果会再次触发一次1小时Bar合成, 合成逻辑错误。

Administrator
avatar
加入于:
帖子: 4607
声望: 264
  1. 没法准确校准,只能每天定时和Windows服务器做一次对时,这是能做的最好的操作了
  2. 保持东8就好
  3. 这个问题我们来修复下
Member
avatar
加入于:
帖子: 31
声望: 0

description

交易的是币安永续USDT合约,将合成的分钟Bar和小时Bar打印出来之后,发现合成的Bar所对应的时间,与服务器本地时间延迟很大。比如标黄线的地方,在本地时间是 02:52:57的时候,才合成了02:36:00的Bar,时间滞后了十几分钟。 紧接着在合成1小时Bar的时候,也已经延迟到了 03:07:31, 6分钟以上的延迟。 而且从最右侧输出来的合成的分钟Bar数据可以看出,从02:35:00到03:13:00 合成的分钟Bar居然不足20个,分钟Bar的合成都严重缺失。我是阿里云服务器,物理地址在新加坡,即使有网络抖动,也不可能有这么大延迟,感觉是币安永续USDT合约有比较大的问题。

Member
avatar
加入于:
帖子: 31
声望: 0

今天发现的另外一个重大问题,就是我放在服务器上的策略,其实连合成分钟级别的操作也早就停止了。上图是我25日从服务器上的输出截图,但是最后一根分钟Bar合成时间戳,还是在22日几天之前输出的。 我在图形界面上有订阅BTCUSDT的币安永续合约,发现订阅的合约是有Tick不断推送过来的,图形界面的盘口价格也一直是在正常跳动,且与币安网站上的显示的实时价格是同步的。 策略程序没有任何报错,现在在图上界面上也是正常显示,要不是我把每次合成的分钟Bar打印出来了,根本发现不了Bar数据已经停止合成的问题。

Member
avatar
加入于:
帖子: 31
声望: 0

最后一个重大的问题,可能是与上面发现的问题有关,就是关于策略跟踪记录进场后的最高价和最低价的记录严重不准确。

策略用于跟踪进场后的最高价和最低价的写法如下:
在on_hour_bar函数里面的写法如下:

if self.pos > 0.0:
self.HighestAfterEntry = max(self.HighestAfterEntry, bar.high_price)
elif self.pos < 0.0:
self.LowestAfterEntry = min(self.LowestAfterEntry, bar.low_price)
...
self.sync_data()
self.put_event()

当策略按照信号正常进场后,我对比图形界面上显示的HighestAfterEntry 和 LowestAfterEntry 发现,
变量记录的价格,比如HighestAfterEntry 虽然确实是在逐步抬高,但是依然与进场后真实的最高价(与币安网站上历史行对比)有比较大的差距。

比如策略是在BTCUSDT合约19000点进场的,进场后该合约的最高价曾到过24281.61,结果图形界面上显示的self.HighestAfterEntry只有23808,
进而导致策略的跟踪止损计算错误。

而且是每个策略里面的记录,都有一个比较大的差异,导致实盘的跟踪止损与回测时严重不一致。
图形界面的刷新,我是在on_hour_bar函数里面调用的self.put_event(), 每小时会更新一次,
按理来说只要合成的1小时Bar数据没问题的话,跟踪记录的最高价和最低价就应该是准确无误的。

综合上述三点重大问题,感觉现在至少币安永续USDT接口可能存在重大问题,问题可能来源于几个方面:

  1. 币安永续USDT接口推送的Tick延迟很大,导致合成分钟Bar的时间严重滞后,进而导致了大量的分钟Bar数据合成缺失。
  2. 即使成功订阅合约行情,但是在策略里面的回调函数on_bar和on_tick,会在实盘交易的某个时间之后,
    无法有新的tick和bar数据推送,进而导致后续没有任何分钟Bar和小时Bar的合成。
  3. 可能存在tick数据推送严重丢失的情况,不然不可能策略进场后记录的最高价和最低价与币安网站提供的历史行情差异巨大。
Member
avatar
加入于:
帖子: 31
声望: 0

description

币安永续USDT行情,实盘运行中的策略,将每个策略最新的一小时合成Bar打印的图形界面上,在同一个时间节点,不同策略最新的一小时合成Bar时间戳差异巨大,此刻正常的合成1小时Bar的时间戳应该为 2020-12-27 10:00,但是发现很多策略合成的1小时Bar时间戳均没有更新,有些策略的时间戳甚至还在昨天,说明很多策略长达几个小时以上的时间内,都没有合成1根一小时Bar来更新数据。而且这个情况,不仅仅出现在实盘连接交易过程中,甚至在策略初始化的过程中,在从交易所接口把最新的分钟数据拉下来合成的时候,也是有很多策略合成的1小时Bar是几个小时甚至十几个小时之前的小时Bar数据,差异巨大,肯定是行情接口或者Bar合成逻辑哪里出现了巨大问题,还请官方重点关注我上面提到的这些问题。 我是用的新加坡阿里云服务器实盘交易的,网络再怎么延迟或者抖动,都不应该出现这种情况的。

在on_hour_bar函数里面的写法如下,该回调函数应该每个整数小时运行一次:

def on_hour_bar(self, bar: BarData):

   self.BarTime = str(bar.datetime)

   am = self.am
    am.update_bar(bar)
    if not am.inited:
        return
 ...
 self.sync_data()
 self.put_event()
Administrator
avatar
加入于:
帖子: 4607
声望: 264

请贴下您的完整策略代码,我们让同事来测试下

Member
avatar
加入于:
帖子: 31
声望: 0

用Python的交易员 wrote:

请贴下您的完整策略代码,我们让同事来测试下

任何一个1小时的策略,只要需要用到合成1小时Bar的逻辑,都可以测试出来的。
这个问题与策略逻辑是无关的,您官方的那些1小时的Demo策略就可以做这个测试的。

Member
avatar
加入于:
帖子: 4
声望: 0

我实盘跑的策略也是中频1小时,托管在aws伦敦,目前运行没有问题,准点发单。时区设置在上海,服务器时区也要设置一致

Member
avatar
加入于:
帖子: 31
声望: 0

问题已找到,是2.1.7版本里面,数字货币行情底层的tick过滤有问题:https://github.com/vnpy/vnpy/issues/2741。
目前2.1.8 master版本里面,虽然把这个问题修正了,但是当选择interval.Hour时,合成Hour Bar的逻辑依然有问题,不知道当前的2.1.8 dev分支下的utility的最终的版本吗?

另外提个建议,希望每次Github更新的时候,都把到底哪些地方更新了可以列的详细一些。
就拿2.1.7版本里面的tick过滤写法来说,本来之前的版本写的应该是正确的,不知道从哪个版本之后给改错了,又是哪个版本正确的改回来了。如果能有一个比较清晰的文档记录,用户在自己排查问题的时候也会方便很多。

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

沪公网安备 31011502017034号