策略#
Cerebro 实例是 backtrader 的泵心和控制脑。对于平台用户来说, Strategy 也是。
策略 的生命周期表达在方法中
Conception:
__init__这在实例化时显然会被调用:在此处创建
indicators和其他所需属性。示例:def __init__(self): self.sma = btind.SimpleMovingAverage(period=15)注意
一个策略在 出生 时可能会被抛出来自
backtrader.errors模块的StrategySkipError异常中断。这将避免在回测期间执行该策略。参见
Exceptions部分。出生:
start世界(cerebro)告诉策略是时候开始行动了。存在一个默认的空方法。童年:
prenext在概念阶段声明的
indicators会对策略需要成熟的时间有一定的限制:这称为minimum period。在上面的__init__中创建了一个 SimpleMovingAverage ,其period=15。只要系统看到的数据不到
15个,就会调用prenext(默认方法为空操作)。成年期:
next一旦系统看到了
15个数据,且SimpleMovingAverage的缓冲区足够大,能够开始输出值,策略就已经足够成熟来执行了。还有一个
nextstart方法,会被调用一次,来标志着从prenext转向next的转变。nextstart的默认实现是简单地调用next。繁殖:
None好吧,策略实际上并不会繁殖。但在某种程度上它们会,因为系统会根据不同的参数多次实例化它们以进行*优化*。
死亡:
stop系统告诉策略,是时候进行重置和整理了。已经存在一个默认的空方法。
在大多数情况下,正常使用模式如下所示:
class MyStrategy(bt.Strategy):
- def __init__(self):
self.sma = btind.SimpleMovingAverage(period=15)
- def next(self):
- if self.sma > self.data.close:
# 做某事 pass
- elif self.sma < self.data.close:
# 做其他事情 pass
在这个代码段中:
在
__init__中,一个属性被赋予了一个指标默认空的
start方法没有被覆盖
prenext和nexstart没有被覆盖在
next中,将指标的值与收盘价进行比较以执行某些操作默认的空
stop方法没有被覆盖
策略就像现实世界中的交易者一样,会在事件发生时收到通知。实际上,在回测过程中每次 next 周期都会通知策略。策略会:
通过
notify_order(order)来接收订单状态的任何变化- 通过notify_trade(trade)通知任何开立/更新/关闭的交易
通过
notify_cashvalue(cash, value)通知经纪人当前的现金和投资组合通过
notify_fund(cash, value, fundvalue, shares)通知经纪人当前的现金和投资组合,以及基金价值和份额的交易通过
notify_store(msg, *args, **kwargs)通知特定实现的事件
有关 store 通知的详细说明,请参阅 Cerebro。即使这些通知已经发送到了 cerebro 实例(通过重写 notify_store 方法或通过 callback ),它们也会被发送到策略上。
和交易员一样,*策略*也有机会在 next 方法中操作市场,以试图获利
用
buy方法开多头或减少/平仓空头仓位用
sell方法开空头或减少/平仓多头仓位用
close方法关闭现有仓位用
cancel方法取消尚未执行的订单
购买/销售/关闭的方法#
Buy 和 Sell 方法会生成订单。当调用它们时,它们会返回一个 Order (或子类)实例,可以用作参考。此订单具有唯一的 ref 标识符,可用于比较。
注意
特定经纪人实现的 Order 子类可能携带经纪人提供的其他 唯一标识符 。创建订单时,请使用以下参数:
data(默认值:None)指定要创建订单的数据。如果为
None,则将使用系统中的第一个数据self.datas[0] or self.data0(也就是self.data)。size(默认值:None)指定要使用的数据单位的大小(必须为正数)。
如果为
None,则会使用通过getsizer方法检索到的sizer实例来确定大小。price(默认值:None)指定要使用的价格(如果价格不符合最低变动点要求,则活动经纪人可能会设置限制)。
对于
Market和Close订单,None是有效的(市场确定价格)。对于
Limit,Stop和StopLimit订单,此值确定触发点(对于Limit,触发点显然是订单应该匹配的价格)。 -plimit(默认值:None)仅适用于“StopLimit”订单。这是在 * Stop * 触发后(使用
price)设置隐式 * Limit * 订单的价格exectype(默认值:None)可能的值:
Order.Market或None。市价订单将以下一个可用价格执行。在回测中,它将是下一个柱状图的开盘价Order.Limit。只能以给定的price或更好的价格执行的订单Order.Stop。在price触发的订单,并像Order.Market订单一样执行Order.StopLimit。在price触发的订单,并作为由pricelimit给出的隐式 * Limit * 订单执行
valid(默认值:None)可能的值:- None : 这将生成一个不会过期的订单(也被称为 Good til cancel ),并将一直在市场上等待匹配或取消。实际上,经纪人往往会设置一个时间上限,但通常这个时间距离现在还很遥远,所以可以视为不会过期
datetime.datetime 或 datetime.date 实例:将使用该日期生成一个有效期直到给定日期的订单(也被称为 good til date )
Order.DAY 或 0 或 ` timedelta()`:将生成一个有效期直到 交易日结束 的订单(也被称为 day 订单)
numeric value :默认假设为 matplotlib 编码中的一个日期时间值( backtrader 使用的编码方式),将使用该值生成一个有效期直到该时间的订单(也被称为 good til date )
tradeid (默认值:0)
这是 backtrader 应用于跟踪同一资产上交叉交易的内部值。当订单状态发生变化时,这个 tradeid 将发送回*策略*
**kwargs :其他经纪人实施可能支持额外的参数。 backtrader 将把 kwargs 传递给已创建的订单对象
例如:如果 backtrader 直接支持的四种订单执行类型对于某些情况不足够,比如在 交互经纪商 的情况下,可以将以下内容作为 kwargs 传递:
orderType=’LIT’, lmtPrice=10.0, auxPrice=9.8
这将覆盖 backtrader 创建的设置,并生成一个带有 触发*价格为9.8和 限价 价格为10.0的 当达到指定价格时触发*订单。信息细节:
策略具有一个*长度*,它始终等于主数据( datas[0] )的长度,当然可以使用 len(self) 获取
如果数据正在重播或正在传递实时数据源,并且同一时间点(长度)的新刻度正在到达,可以在不改变*长度*的情况下调用“next”
成员属性:#
env:此策略所属的cerebro实体
datas:传递给cerebro的数据源数组
data/data0是datas[0]的别名
dataX是 datas[X] 的别名数据源 也可以通过名称访问(参见参考资料),如果已经分配了名称
dnames:通过名称(使用[name]或.name表示法)到达数据源的另一种方法例如,如果按此方式对数据进行重新取样:
… data0 = bt.feeds.YahooFinanceData(datname=’YHOO’, fromdate=…, name=’days’) cerebro.adddata(data0) cerebro.resampledata(data0, timeframe=bt.TimeFrame.Weeks, name=’weeks’) …后面在战略中可以像这样为每个指标创建指示器:
… smadays = bt.ind.SMA(self.dnames.days, period=30) # 或者 self.dnames[‘days’] smaweeks = bt.ind.SMA(self.dnames.weeks, period=10) # 或者 self.dnames[‘weeks’] …
broker:与此策略相关联的经纪人的引用(从cerebro收到的)stats:像元组一样的列表/命名元组序列,保存cerebro为此策略创建的观察者analyzers:像元组一样的列表/命名元组序列,保存cerebro为此策略创建的分析器position:实际上是一个属性,用于获取“data0”的当前持仓。可以使用一些方法来检索所有的持仓(参见参考资料)
成员属性(用于统计/观察者/分析器):#
_orderspending:在调用next之前将通知策略的订单列表-_tradespending:在调用next之前,策略将会通知的交易列表_orders:已经通知的订单列表。一个订单在该列表中可以多次出现,具有不同的状态和不同的执行位。该列表用于保留历史记录。_trades:已经通知的交易列表。一个交易在该列表中可以多次出现,就像一个订单一样。
注意
请记住,对于相同的时间点(更新每日价格的tick), prenext 、 nextstart 和 next 可能会被多次调用,当使用每日时间框架时。