背景
帮客户写涨停股策略时,发现选出来的股票总是跟同花顺或通达信上选出来的股票有点差异,不是少几只,就是多几只。那到底差异在哪里呢?
分析
导致数据差异的原因多方面的,例如:
情景1、价格达到涨停价,但是否完全封板了?
像同花顺等软件统计的涨停股,一般对涨停股的定义是要封死涨停板的。回想下我们常用的涨停股判断方式,像如下的掘金量化代码:收盘价==涨停价,就算是涨停了。
history_data = history(symbol=stock_list, frequency='1d', start_time=date, end_time=date, adjust=ADJUST_NONE, df= True)
symbols_info = get_symbols(sec_type1=1010, symbols=stock_list, skip_suspended=False, skip_st=False, trade_date=date, df=True)
history_data = history_data.merge(symbols_info, on=['symbol'])
zt_stock = history_data[(history_data['close']==history_data['upper_limit'])]['symbol'].tolist()
那这种方式相比软件上的统计值,肯定多了一部分:收盘价达到涨停价了,但卖一还存在委托量。
所以,最好的方式是再进一步处理:获取最后一个tick数据,通过tick数据中的5档数据进行判断,过滤掉卖一还存在委托量的股票。
当然了,为什么很多策略程序都没有做这个过滤呢?这主要是涉及到tick数据了,不同平台对tick数据的权限要求不一样,大部分平台的历史tick数据是收费的,像掘金平台比较好,最近5天是免费的,但如果要做长时间回测,这个就太少了。
另外呢,还有处于回测速度的考虑,毕竟调用tick数据进行处理的方式会大大增加回测时间。
情景2、价格的复权方式选对了吗?
什么?复权方式会导致涨停股的判断出现差异?实盘不会,但历史回测会。
掘金中的涨停价可以通过get_symbols()函数获取,但要注意:
这个涨停价是不复权的!
这个涨停价是不复权的!
这个涨停价是不复权的!
所以呢,我们使用的收盘价也要用不复权的价格。
history_data = history(symbol=stock_list, frequency='1d', start_time=date, end_time=date, adjust=ADJUST_NONE, df= True)
获取历史行情的函数中,一定要将adjust参数指定为ADJUST_NONE,采用不复权的方式。
情景3、停牌原因
解决完情景1和情景2的问题,一般算出来的涨停股就能跟同花顺等软件上算出来的一样了,但像连板股的统计可能还有些差异。
在K线上,停牌期间的K线是不显示的,同时也不会纳入统计,例如说下图中的佛塑科技,在20241031首板涨停,随后停牌,20241115复盘并涨停。但是在K线中,停牌这段时间是没有K线的,所以在停牌期间同花顺并没有将他纳入到“一板”范畴,但是在复盘涨停那天,同花顺将它纳入到“二板”的股票范畴内。
这一点呢,通达信的统计方式跟同花顺的一样。
但是在其他平台,例如韭研公社,他是有将停牌日期计算在内的:
停牌导致的遗漏在掘金中处理起来比较麻烦,数量也少,我就直接忽略了。但如果是需要统计数据的,且需要跟同花顺通达信一致的话,可以试着处理下停牌的情景。
以下是处理了情景1和情景2的程序示例:
完工,下班~
PS:策略代写/掘金研学会员优惠价,可以找我,有优惠~