扩展指标
原文: https://www.backtrader.com/blog/posts/2015-07-20-extending-an-indicator/extending-an-indicator/
在面向对象编程中,当然在 Python 本身中,现有类的扩展可以通过两种方式实现。
-
继承(或子类化)
-
合成(或嵌入)
在开发指标时,指标Trix
仅在几行代码中开发。ChartSchool-Trix参考文献中有一个Trix
,带有一条显示与 MACD 相似的信号线。
让我们使用已经开发的Trix
来“撰写”MyTrixSignal
class MyTrixSignalComposed(bt.Indicator):
lines = ('trix', 'signal')
params = (('period', 15), ('sigperiod', 9))
def __init__(self):
self.lines.trix = MyTrix(self.data, period=self.p.period)
self.lines.signal = btind.EMA(self.lines.trix, period=self.p.sigperiod)
在定义中必须重复一些内容,例如用于计算的trix
行和period
的名称。定义了新行signal
和相应的sigperiod
参数。
2-liner 是一个很好的结果。
现在让我们来看一下继承,但首先回顾一下Trix
的样子:
class MyTrix(bt.Indicator):
lines = ('trix',)
params = (('period', 15),)
def __init__(self):
ema1 = btind.EMA(self.data, period=self.p.period)
ema2 = btind.EMA(ema1, period=self.p.period)
ema3 = btind.EMA(ema2, period=self.p.period)
self.lines.trix = 100.0 * (ema3 - ema3(-1)) / ema3(-1)
使用Trix
作为基类,这是TrixSignal
的方面
class MyTrixSignalInherited(MyTrix):
lines = ('signal',)
params = (('sigperiod', 9),)
def __init__(self):
super(MyTrixSignalInherited, self).__init__()
self.lines.signal = btind.EMA(self.lines.trix, period=self.p.sigperiod)
继承的指示器最终也是一个 2 行的,但是:
-
不需要重新定义
trix
行 -
不需要重新定义
period
参数
两者都是从基类Trix
继承的。而trix
线的计算是在基类__init__
方法中完成的:
- 超级(mytrixsignalinherite,self)。初始()
组合与继承的选择是一个经典。这个例子并不是为了说明哪一个更好,而是为了说明:
笔记
继承即使在存在行和参数的元定义的情况下也可以工作,这些元定义也继承自基类的元定义
最后是两个版本的代码和图表。
- 第一个显示了继承的版本
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import backtrader as bt
import backtrader.feeds as btfeeds
from mytrix import MyTrixSignalInherited
class NoStrategy(bt.Strategy):
params = (('trixperiod', 15),
('analyzer', False),)
def __init__(self):
MyTrixSignalInherited(self.data, period=self.p.trixperiod)
if __name__ == '__main__':
# Create a cerebro entity
cerebro = bt.Cerebro()
# Add a strategy
cerebro.addstrategy(NoStrategy, trixperiod=15)
# Create a Data Feed
datapath = ('../datas/2006-day-001.txt')
data = bt.feeds.BacktraderCSVData(dataname=datapath)
# Add the Data Feed to Cerebro
cerebro.adddata(data)
# Run over everything
cerebro.run()
# Plot the result
cerebro.plot()
- 第一个显示的是合成的版本
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import backtrader as bt
import backtrader.feeds as btfeeds
from mytrix import MyTrixSignalComposed
class NoStrategy(bt.Strategy):
params = (('trixperiod', 15),
('analyzer', False),)
def __init__(self):
MyTrixSignalComposed(self.data, period=self.p.trixperiod)
if __name__ == '__main__':
# Create a cerebro entity
cerebro = bt.Cerebro()
# Add a strategy
cerebro.addstrategy(NoStrategy, trixperiod=15)
# Create a Data Feed
datapath = ('../datas/2006-day-001.txt')
data = bt.feeds.BacktraderCSVData(dataname=datapath)
# Add the Data Feed to Cerebro
cerebro.adddata(data)
# Run over everything
cerebro.run()
# Plot the result
cerebro.plot()