《backtrader》的发布1.9.27.105
纠正了一个疏忽。这是一个疏忽,因为拼图的所有部分都已到位,但启动并不是在所有角落都进行的。
该机制使用一个名为的属性_mindatas
,因此让我们将其称为: mindatas
。
社区问了这个问题,答案并不是很到位。请参阅此处的对话:
即使谈话是关于其他事情的,这个问题也可以很快得到回答:「嘿,它实际上应该有效!但是,这些天谁有时间考虑一个适当而周到的答案。
让我们考虑一个交叉一个普通的旧数字参数的用例。类似的东西
mycrossover = bt.ind.CrossOver(bt.ind.RSI(), 50.0)
哪个会像
Traceback (most recent call last): File "./cross-over-num.py", line 114, in <module> runstrat() File "./cross-over-num.py", line 70, in runstrat cerebro.run(**eval('dict(' + args.cerebro + ')')) File "d:\dro\01-docs\01-home\src\backtrader\backtrader\cerebro.py", line 810, in run runstrat = self.runstrategies(iterstrat) File "d:\dro\01-docs\01-home\src\backtrader\backtrader\cerebro.py", line 878, in runstrategies strat = stratcls(*sargs, **skwargs) File "d:\dro\01-docs\01-home\src\backtrader\backtrader\metabase.py", line 87, in __call__ _obj, args, kwargs = cls.doinit(_obj, *args, **kwargs) File "d:\dro\01-docs\01-home\src\backtrader\backtrader\metabase.py", line 77, in doinit _obj.__init__(*args, **kwargs) File "./cross-over-num.py", line 35, in __init__ bt.ind.CrossOver(bt.ind.RSI(), 50) File "d:\dro\01-docs\01-home\src\backtrader\backtrader\indicator.py", line 53, in __call__ return super(MetaIndicator, cls).__call__(*args, **kwargs) File "d:\dro\01-docs\01-home\src\backtrader\backtrader\metabase.py", line 87, in __call__ _obj, args, kwargs = cls.doinit(_obj, *args, **kwargs) File "d:\dro\01-docs\01-home\src\backtrader\backtrader\metabase.py", line 77, in doinit _obj.__init__(*args, **kwargs) Typeerror: __init__() takes exactly 1 argument (2 given)
作为 last line 最翔实的,因为它告诉我们,有些东西有太多的论据。这意味着他们正在50.0
伤害我们。
为了解决手头的问题,给出了一个数字包装器作为答案。
class ConstantValue(bt.Indicator): lines = ('constant',) params = (('constant', float('NaN')),) def next(self): self.lines.constant[0] = self.p.constant ... mycrossover = bt.ind.CrossOver(bt.ind.RSI(), ConstantValue(50.0))
问题解决了。但是等等,解决方案已经在船上了。有一个内部帮手,要解决问题,就完全忘记了:LineNum
它做了这个名字试图暗示的事情:取一个数字,并使其成为一个 line。问题解决方案就在那里,解决方案可能看起来像这样:
mycrossover = bt.ind.CrossOver(bt.ind.RSI(), bt.LineNum(50.0))
通常的背景线程无论如何都在滴答作响,告诉某些东西仍然不是100%清晰,解决方案应该是显而易见的,而无需用户指定包装器。
这就是疏忽。即使该mindatas
机制存在并应用于回声系统的某些部分,它也没有应用于 CrossOver
。它尝试过,但人类有时会失败得很惨,认为他们做了一些事情只是为了发现,他们没有进一步向下滚动。事实也的确如此。一个 line 添加,如下所示:
class CrossOver(Indicator): ... _mindatas = 2 ...
现在,这个问题的解决方案很简单:
mycrossover = bt.ind.CrossOver(bt.ind.RSI(), 50.0)
它应该一直处于第1位 的方式(请参阅下面的范例和图表)
mindatas
在工作中
这是一个方便的属性,旨在用于特定情况,因此是前导_
,以指示应非常谨慎地使用它。指针的默认值为:
-
_mindatas = 1
这告诉系统,如果没有数据源 传递给指针,系统应从父级拷贝第 1个 数据源。如果没有这个,例如实例化应该
RelativeStrengthIndicator
像这样完成:class Strategy(bt.Indicator): def __init__(self): rsi = bt.ind.RSI(self.data0)
但是,使用 给出
_mindatas
的缺省指示,以下情况是可能的:class Strategy(bt.Indicator): def __init__(self): rsi = bt.ind.RSI()
结果完全相同,因为策略
self.data0
中的第1个数据源被传递给RSI
像这样的CrossOver
指针需要 2 data feeds,因为它正在检查一个事物是否正在交叉另一个事物。在本例中,如上所示,默认值已设置为:
_mindatas = 2
这告诉系统如下内容:
-
如果未传递任何数据,则从父级拷贝 2 data feeds (如果可能)
-
如果仅传递了 1 个数据,请尝试将下一个传入参数转换为 lines 对象,以便有 2 个 data feeds 可用。Usseful用于 line 穿越普通旧花车的用例。再次供参考:
mycrossover = bt.ind.CrossOver(bt.ind.RSI(), 50.0)
-
如果传递到
CrossOver
2 个或更多data feeds,则不运行任何操作并继续进行
在社区中,该机制最近已被应用于例如1st 草图以实现 KalmanFilter
对交易。当谈论配对时,需要2个 data feeds 并使用它: _mindatas = 2
一个小样本(尽管有完整的骨架)来测试完整的解决方案:
$ ./cross-over-num.py --plot
哪个输出这个。
示例用法
$ ./cross-over-num.py --help usage: cross-over-num.py [-h] [--data0 DATA0] [--fromdate FROMDATE] [--todate TODATE] [--cerebro kwargs] [--broker kwargs] [--sizer kwargs] [--strat kwargs] [--plot [kwargs]] Sample Skeleton optional arguments: -h, --help show this help message and exit --data0 DATA0 Data to read in (default: ../../datas/2005-2006-day-001.txt) --fromdate FROMDATE Date[time] in YYYY-MM-DD[THH:MM:SS] format (default: ) --todate TODATE Date[time] in YYYY-MM-DD[THH:MM:SS] format (default: ) --cerebro kwargs kwargs in key=value format (default: ) --broker kwargs kwargs in key=value format (default: ) --sizer kwargs kwargs in key=value format (default: ) --strat kwargs kwargs in key=value format (default: ) --plot [kwargs] kwargs in key=value format (default: )
示例代码
from __future__ import (absolute_import, division, print_function, unicode_literals) import argparse import datetime import backtrader as bt class St(bt.Strategy): params = () def __init__(self): bt.ind.CrossOver(bt.ind.RSI(), 50) def next(self): pass def runstrat(args=None): args = parse_args(args) cerebro = bt.Cerebro() # Data feed kwargs kwargs = dict() # Parse from/to-date dtfmt, tmfmt = '%Y-%m-%d', 'T%H:%M:%S' for a, d in ((getattr(args, x), x) for x in ['fromdate', 'todate']): if a: strpfmt = dtfmt + tmfmt * ('T' in a) kwargs[d] = datetime.datetime.strptime(a, strpfmt) # Data feed data0 = bt.feeds.BacktraderCSVData(dataname=args.data0, **kwargs) cerebro.adddata(data0) # Broker cerebro.broker = bt.brokers.BackBroker(**eval('dict(' + args.broker + ')')) # Sizer cerebro.addsizer(bt.sizers.FixedSize, **eval('dict(' + args.sizer + ')')) # Strategy cerebro.addstrategy(St, **eval('dict(' + args.strat + ')')) # Execute cerebro.run(**eval('dict(' + args.cerebro + ')')) if args.plot: # Plot if requested to cerebro.plot(**eval('dict(' + args.plot + ')')) def parse_args(pargs=None): parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter, description=( 'Sample Skeleton' ) ) parser.add_argument('--data0', default='../../datas/2005-2006-day-001.txt', required=False, help='Data to read in') # Defaults for dates parser.add_argument('--fromdate', required=False, default='', help='Date[time] in YYYY-MM-DD[THH:MM:SS] format') parser.add_argument('--todate', required=False, default='', help='Date[time] in YYYY-MM-DD[THH:MM:SS] format') parser.add_argument('--cerebro', required=False, default='', metavar='kwargs', help='kwargs in key=value format') parser.add_argument('--broker', required=False, default='', metavar='kwargs', help='kwargs in key=value format') parser.add_argument('--sizer', required=False, default='', metavar='kwargs', help='kwargs in key=value format') parser.add_argument('--strat', required=False, default='', metavar='kwargs', help='kwargs in key=value format') parser.add_argument('--plot', required=False, default='', nargs='?', const='{}', metavar='kwargs', help='kwargs in key=value format') return parser.parse_args(pargs) if __name__ == '__main__': runstrat()