技术分析,指标为王:详解backtrader的指标体系与扩展

原创文章第71篇,专注“个人成长与财富自由、世界运作的逻辑, AI量化投资”。

李笑来竟然写了一本关于微信视频号的书。

里面谈及了长期价值的理念,确实,很多事情难在“长期”。需要长时间才能显现出来,越往后复利越高,而在初期甚至可能感觉不到进展。这是大多数人终生䘵䘵无为根本原因。

今天继续说backtrader,按传统的量化投资,需要用指标来建立量化规则,所以指标计算很重要。

01 backtrader的指标

技术分析,指标为王:详解backtrader的指标体系与扩展_第1张图片

指标是基于基础数据来进行“衍生”计算。基础数据包含是宏观数据,基本面财务数据,基于交易时间序列的OHLCV数据以及另类数据,比如港口的船只数量,商超的人数等等。

这些指标可以是“已经计算”好的,比如昨天说的PE/PB,那么我们直接通过PandasData引入即可。

而像布林带,唐奇安通道这种通过Indicators来“临时计算”。

指标在__init__计算,在next里使用。

import backtrader as bt
import backtrader.indicators as ind # 导入策略分析模块
class MyStrategy(bt.Strategy):
  # 先在 __init__ 中提前算好指标
    def __init__(self):
        sma1 = ind.SimpleMovingAverage(self.data)
        ema1 = ind.ExponentialMovingAverage()
        close_over_sma = self.data.close > sma1
        close_over_ema = self.data.close > ema1
        sma_ema_diff = sma1 - ema1
        # 生成交易信号
        self.buy_sig = bt.And(close_over_sma, close_over_ema, sma_ema_diff > 0)
    # 在 next 中直接调用计算好的指标
    def next(self):
        if self.buy_sig:
            self.buy()

Sma1, ema1, sma_ema_diff,buy_sig都是line对象,(类似pandas里的series),另外指标全称一般比较长,可以简化写为alias:

ind.SimpleMovingAverage=ind.SMA

计算指标或编写策略逻辑时,离不开算术运算、关系运算、逻辑运算、条件运算等等,Bt封装的运算符,是针对line对象进行,返回的结果也是line。bt.And、bt.Or、bt.If、bt.All、bt.Any、bt.Max、bt.Min、bt.Sum 计算返回的结果与在next()中对当前时点通过常规 python 运算语法返回的结果是一致的。 

class MyStrategy2(bt.Strategy):
    def __init__(self):
        self.sma5 = ind.SimpleMovingAverage(period=5)  # 5日均线
        self.sma10 = ind.SimpleMovingAverage(period=10)  # 10日均线
        # bt.And 中所有条件都满足时返回 1;有一个条件不满足就返回 0
        self.And = bt.And(self.data > self.sma5, self.data > self.sma10, self.sma5 > self.sma10)
        # bt.Or 中有一个条件满足时就返回 1;所有条件都不满足时返回 0
        self.Or = bt.Or(self.data > self.sma5, self.data > self.sma10, self.sma5 > self.sma10)
        # bt.If(a, b, c) 如果满足条件 a,就返回 b,否则返回 c
        self.If = bt.If(self.data > self.sma5, 1000, 5000)
        # bt.All,同 bt.And
        self.All = bt.All(self.data > self.sma5, self.data > self.sma10, self.sma5 > self.sma10)
        # bt.Any,同 bt.Or
        self.Any = bt.Any(self.data > self.sma5, self.data > self.sma10, self.sma5 > self.sma10)
        # bt.Max,返回同一时刻所有指标中的最大值
        self.Max = bt.Max(self.data, self.sma10, self.sma5)
        # bt.Min,返回同一时刻所有指标中的最小值
        self.Min = bt.Min(self.data, self.sma10, self.sma5)
        # bt.Sum,对同一时刻所有指标进行求和
        self.Sum = bt.Sum(self.data, self.sma10, self.sma5)
        # bt.Cmp(a,b), 如果 a>b ,返回 1;否则返回 -1
        self.Cmp = bt.Cmp(self.data, self.sma5)

关于不同周期的指标

都是“日频”,但有些数据,如财务指标是“季度”频度。比如seelf.data1是月度数据,那么self.month也是月度数据。这时可以有两种做法:使用self.month[0](),或者对齐整个指标对象:self.month_ = self.month(),然后使用就一样的。

推荐第二种。

在bt框架中使用talib,整合得很好,bt里叫period,而talib里通常叫timeperiod。

class TALibStrategy(bt.Strategy):
    def __init__(self):
        # 计算 5 日均线
        bt.talib.SMA(self.data.close, timeperiod=5)
        bt.indicators.SMA(self.data, period=5)
        # 计算布林带
        bt.talib.BBANDS(self.data, timeperiod=25)
        bt.indicators.BollingerBands(self.data, period=25)

02 自定义自己的指标

内置140多个指标及运算符,外加talib的扩展,仍然不够,比如RSRS指标。

继承自bt.Indicator,lines里定义我们这个指标有几个line, params是参数,在init里做一次性的“向量”运算,在next里按元素计算。

import backtrader as bt
import numpy as np
import statsmodels.api as sm


class RSRS(bt.Indicator):
    lines = ('rsrs', 'R2')

    params = (('N', 18), ('value', 5))

    def __init__(self):
        self.high = self.data.high
        self.low = self.data.low

    def next(self):
        high_N = self.high.get(ago=0, size=self.p.N)
        low_N = self.low.get(ago=0, size=self.p.N)

        try:
            X = sm.add_constant(np.array(low_N))
            model = sm.OLS(np.array(high_N), X)
            results = model.fit()
            self.lines.rsrs[0] = results.params[1]
            self.lines.R2[0] = results.rsquared
        except:

self.lines.rsrs[0] = 0

class RSRS_Norm(bt.Indicator):
lines = ('rsrs_norm','rsrs_r2','beta_right')
params = (('N', 18), ('M', 600))

def __init__(self):
self.rsrs = RSRS(self.data)
self.lines.rsrs_norm = (self.rsrs - bt.ind.Average(self.rsrs, period=self.p.M))/bt.ind.StandardDeviation(self.rsrs, period= self.p.M)
self.lines.rsrs_r2 = self.lines.rsrs_norm * self.rsrs.R2
self.lines.beta_right = self.rsrs * self.lines.rsrs_r2

  02 小结

Backtrader的指标模块 Indicator 侧重的是技术分析,提供了各式各样的技术指标计算函数,考虑到大家技术指标的计算习惯,还内接了 TA-Lib 指标库,bt的line还可以自动匹配时间,对齐周期,这个着实非常方便。

指标都是标准的bt的lines对象。

尽管这里我们说的是“技术指标”,但针对机器学习的因子计算,这里的公式依然有效。

明天可以正式进行“交易”环节了。

 

你可能感兴趣的:(建立自己的算法交易事业,python,开发语言)