策略需求
监控即将涨停的股票数据,只提醒,辅助我做交易。
考虑到全市场订阅要付费,而且我关注的只是一小部分的,所以设计如下:
每一段时间更新股票池,轮换着订阅,触发条件时发出声音提醒我。
想得挺好的,实际中发现监控得条件出现了问题,也就引出了本篇文章的主题:行情堵塞。
难题:行情堵塞
行情堵塞,简单点说明就是程序处理不过来,本来100只股票要在3秒内处理完,程序却要4秒才能处理完,导致你处理第二遍数据的时候晚了1秒,处理第三遍数据的时候晚了2秒钟......这个延迟的时间越来越大。
回来需求设计上来,每隔一段时间更新股票池采用掘金的timer()定时器,在定时器中通过current()获取全市场数据,以筛选目标股票池进行tick级行情订阅;在行情订阅中,实时计算涨速和当日涨幅,满足条件就进行文字和声音提醒;其中涨速是通过context.data()获取历史数据来计算的。
设计看起来没问题,但实操起来,问题一大堆:延迟 延迟 延迟在累积增加。
途中第一个是datetime.now()的时间,第二个是tick数据的tick['created_at']时间,第三个是二者的时间差。
发现没有,时间差一直在累积,说明程序堵塞了,3秒时间处理不过来。
逐项功能查询耗时,发现原来是声音,那我先取消声音,后续是用了多线程的方式解决了,这个后期再讲。
取消了声音后,发现还是有很大的延迟。
问题出在每分钟的监控标的池更新,current()这个函数延迟太大了,全市场的数据一次性获取延迟低的时候有六七秒左右,高的三四十秒....这可能是我电脑内存不足或者网络延迟问题,但整体来说波动延迟很大。
那没办法了,这延迟波动有点接受不了。
新方案:全市场订阅
推倒重来:只在第一次运行时才调用current()数据,后续数据的更新通过tick级的行情订阅来实现,也就是说采用全市场订阅的方式,更新监控标的池后,在tick()行情中加一道过滤,判断是不是监控目标,是监控目标才进一步判断监控的条件是否满足。
新方法实测下来,股票池的更新基本都是毫秒级的延迟,但因为订阅数量从原本的200只股票提升到全市场,行情处理会有些延迟,但低于1个tick时间,整体还可以接受哈哈哈。
结果
总结来看,行情堵塞时,就需要在在行情事件中逐个代码功能进行排查,排查的方式也很简单,可以直接在代码块中前后添加时间戳,记录这两个时间的差,就是该代码运行所耗费的时间,具体代码如下:
time1 = datetime.now()
"""要测试的代码"""
time2 = datetime.now()
print(time2-time1)
tips:如何查看行情是否堵塞?
另外,如何查看行情是否堵塞了呢?
首先可以对比下提醒的时间和实际走势图的触发时间是否一致,一般有拥堵的话,延迟时间会越来越大,那运行一段时间,很容易就会发现程序发出的实际时间晚了很多;
发现信号晚了之后,就可以在代码里进行精细的查询了,这里就是用实际时间跟行情数据自带的时间戳进行比较,不能用context.now哈,这个也是实际时间。
下面这个created_at就是tick数据中自带的时间戳,bar数据的话可以用bar[0]['eob']。
print(datetime.now()-tick['created_at'].replace(tzinfo=None))
PS:掘金研学会员优惠价/策略代写,可以找我,有优惠~