关注持续行动1期 53/100,“AI技术应用于量化投资研究”。
继续backtrader系列。backtrader会深入一个系列,这里有一个核心原因,backtrader是产品级的。而qlib只是一个lib,一个更适合机器学习/深度学习的lib,但距离实盘还有距离,如它的版本号0.8.6。
今天重点说说bt的指标体系以及如何自定义指标。
对于一个策略而言,核心要素就是指标。比如均线,MACD或者动量,K线形态之类的。这个定义好了,策略就是指标的规则表达式,或者机器模型罢了。
01 指标
指标有两处用途:在策略里用和在其他指标里用。
打开源代码,看到indicators下边有几十个内置的指标。(对于开源框架的使用,直接看代码是效率最高的方式)。
bt内置的动量有4种:
它给出了公式roc = (data-data_period) / data_period,比如N天的价格变化率。roc本身也是“lines”复合了“减法”和“除法”的结果,同样得到一个“lines”。
class RateOfChange(Indicator): ''' Measures the ratio of change in prices over a period Formula: - roc = (data - data_period) / data_period See: - http://en.wikipedia.org/wiki/Momentum_(technical_analysis) ''' alias = ('ROC',) # Named output lines lines = ('roc',) # Accepted parameters (and defaults) - params = (('period', 12),) def __init__(self): dperiod = self.data(-self.p.period) self.l.roc = (self.data - dperiod) / dperiod super(RateOfChange, self).__init__()
照猫画虎,自定义一个空指标,这个指标每个值实际上都是5。
class DummyInd(bt.Indicator): lines = ('dummyline',) params = (('value', 5),) def __init__(self): self.lines.dummyline = bt.Max(0.0, self.params.value)
调用也非常简单:
class MyStrategy(bt.Strategy): params = dict( period=20, # 动量周期 ) def __init__(self): self.sma1 = bt.ind.ROC(period=self.p.period) # fast moving average self.dummy = DummyInd()
这里带出一个问题,bt.ind.ROC并未指定对哪个data序列进行计算,比如我们的策略是多标的轮动呢?这里就是bt框架有大量约定的范式。
Strategy里的属于self.datas是所有添加的PandasData的list。默认self.data=self.datas[0]。而bt.ind.ROC未指定data的时候,默认等价于使用self.data。
完整的写法如下:
self.roc1 = bt.ind.ROC(self.data,period=self.p.period) # fast moving average self.roc2 = bt.ind.ROC(self.datas[1],period=self.p.period)
我们没有写策略,只是定义了指标,可以看到,下图可以把两个指数的ROC指标(20日变化率的动量指标)画出来。
02 talib支持
bt对于talib的支持也是内置的,不过需要本地安装talib包。
pip安装无法成功的话,需要网上下载安装包。
self.sma = bt.talib.SMA(self.data, timeperiod=self.p.period)
后面使用基本类似,只不过talib的参数通常叫timeperiod。
bt内置的指标外加ta-lib,基本上所有技术分析上需要用的指标,都有了。
qlib的指标体系,更向统计学,并不全是传统技术分析。
传统的技术指标也可以输入到机器学习模型里去训练,这个没有优与劣。
03 多证券的策略轮动
qlib里的topK只有排序规则,就是得分高的持有,而得分低的清仓。
但我们还需要买卖信号规则,比如动量>0.02才可能买入,动量<0则卖出,然后才按照动量大小排序。
to_buy_list = [动量>0.02],hold_list=[当前已持仓],to_sell_list=[动量<0]
to_buy+hold-to_sell得到最终持仓,然后先清仓to_sell,然后按平均仓位买入。
self.getposition(self.data).size > 0
可以判断当前data是否为已经持仓。
明天我们要完成动量轮动策略的1.0版本。
重点还是如何构造策略,如何优化策略,建立社群,共创共享,真正创造价值。
反思反省:
吾日三省吾身。
其实从15年左右就开始关注量化投资,接触的第一个框架是pyalgotrade。
demo都没有run起来吧,因为涉及到陌生的概念,第一反应是先看它的代码,把它的代码改造成为自己的。这样做好处当然是知其然知其所以然。后发现pyalgotrade使用数据结构不是dataframe(bt也不是),只有qlib充分使用了pandas的dataframe。
当时一直停留在回测框架本身,尤其是数据准备——主要是tushare+mongo,反复折腾。
现在想来,大可不必,因为用csv准备一些静态数据就好了。数据如何动态、增量更新,这些属于工程上的事情。重点是有没有好的策略。
后来还接触了一段时间外汇,折腾C++的MQL,无果。
后开始折腾深度学习,NLP,NLTK,django/flask/fastapi等框架。到底是建设数据中心,分析平台还是量化框架来回摇摆。
若要说反思的话,专注目标而去,就是策略,那前提就是熟悉一个框架,可以执行策略与想法即可。pyalgotrade也好,backtrader也罢,用熟。
多关注前沿,新鲜的东西是好的,但不必所有事情都亲力亲为,太发散导致都没有结果。(还折腾过ionic, angular,vue3前后端分离的开发,css,大数据kafka+spark/flink等等)
专注结果就是策略甚至实盘。然后准备好必要的东西,比如数据就是csv搞定,框架就是backtrader,用熟。然后就是专注指标、因子,机器学习模型lightGBM,强化学习也可以,但要循序渐进,有些太前沿无法落地。然后就是如何找到好的策略,如何优化策略等。