在最近的Canonical vs Non-Canonical 帖子中 MFI
,开发了(aka MoneyFlowIndicator
)。
尽管它是以规范的方式开发的,但它仍然提供了一些改进和成为通用的空间。
让我们关注实现的第一lines,即创建典型价格的那些
class MFI_Canonical(bt.Indicator): lines = ('mfi',) params = dict(period=14) def __init__(self): tprice = (self.data.close + self.data.low + self.data.high) / 3.0 mfraw = tprice * self.data.volume ...
典型的实例化如下所示
class MyMFIStrategy(bt.Strategy): def __init__(self): mfi = bt.MFI_Canonical(self.data)
这里的问题应该是显而易见的:“人们需要一个指针的输入,low
high
其中的特征close
和volume
组件(又名*lines在backtrader生态系统中)”*
当然,可能的情况是,人们希望从不同的数据源(lines来自data feeds或来自其他指针lines)创建一MoneyFlowIndicator
个使用组件,就像想要赋予close
更多的权重一样简单,而不必开发一个特定的指针。考虑到行业标准OHLCV
的字段排序,多个输入,额外的权重,close
实例化可能看起来像这样
class MyMFIStrategy2(bt.Strategy): def __init__(self): wclose = self.data.close * 5.0 mfi = bt.MFI_Canonical(self.data.high, self.data.low, wclose, self.data.volume)
或者因为用户以前使用ta-lib
过并幻想过多输入样式。
支持多种输入
backtrader 尝试尽可能的pythonic,self.datas
并且可以查找包含系统中 data feeds 清单的数字(并且自动神奇地提供给您的策略)的长度。让我们用它来区分调用方想要什么,并正确计算 tprice
和 mfraw
class MFI_MultipleInputs(bt.Indicator): lines = ('mfi',) params = dict(period=14) def __init__(self): if len(self.datas) == 1: # 1 data feed passed, must have components tprice = (self.data.close + self.data.low + self.data.high) / 3.0 mfraw = tprice * self.data.volume else: # if more than 1 data feed, individual components in OHLCV order tprice = (self.data0 + self.data1 + self.data2) / 3.0 mfraw = tprice * self.data3 # No changes with regards to previous implementation flowpos = bt.ind.SumN(mfraw * (tprice > tprice(-1)), period=self.p.period) flowneg = bt.ind.SumN(mfraw * (tprice < tprice(-1)), period=self.p.period) mfiratio = bt.ind.DivByZero(flowpos, flowneg, zero=100.0) self.l.mfi = 100.0 - 100.0 / (1.0 + mfiratio)
注意
请注意各个组件的参考方式(self.dataX
如 self.data0
、 self.data1
)
这与使用self.datas[x]
相同,如 self.datas[0]
...
让我们以图形方式看到,此指针产生的结果与规范指针相同,当多个输入对应于 data feed的原始分量时,产生相同的结果。为此,它将在策略中运行,如下所示
class MyMFIStrategy2(bt.Strategy): def __init__(self): MFI_Canonical(self.data) MFI_MultipleInputs(self.data, plotname='MFI Single Input') MFI_MultipleInputs(self.data.high, self.data.low, self.data.close, self.data.volume, plotname='MFI Multiple Inputs')
无需检查每个值,从图片中可以明显看出,三者的结果相同。
让我们最终看看如果把更多的权重放在上面close
会发生什么。让我们这样运行。
class MyMFIStrategy2(bt.Strategy): def __init__(self): MFI_MultipleInputs(self.data) MFI_MultipleInputs(self.data.high, self.data.low, self.data.close * 5.0, self.data.volume, plotname='MFI Close * 5.0')
这是否有意义留给读者,但人们可以清楚地看到,增加重量close
已经改变了模式。
结论
通过简单地使用pythoniclen
,可以将使用具有多个组件(和固定名称)的 data feed 的指针转换为接受多个通用输入的指针。