Cerebro 实例是backtrader的心脏和大脑。 策略对于用户来说是相同的。

策略在方法中表达的生命周期:

Tips:可以通过从模块中引发 异常StrategySkipError来中断策略backtrader.errors

  1. 概念:__init__

    这显然是在实例化期间调用的:indicators将在此处创建和其他需要的属性。例子:

    def __init__(self):
        self.sma = btind.SimpleMovingAverage(period=15)
  2. 出生:start

    世界 ( cerebro) 告诉策略是时候开始踢了。存在默认的空方法。

  3. 童年:prenext

    indicators在构想期间宣布将限制策略需要多长时间才能成熟:这称为minimum period. 上面__init__创建了一个 带有period=15.

    只要系统看到不到15吧,prenext就会被调用(默认实现是no-op)

  4. 成年:next

    一旦系统看到15柱并且SimpleMovingAverage有足够大的缓冲区开始产生值,该策略就足够成熟以真正执行。

    有一种nextstart方法只调用一次,用于标记从prenextto的切换next。的默认实现 nextstart是简单地调用next

  5. 再生产:None

    好吧,策略并没有真正复制。但从某种意义上说,它们确实如此,因为如果优化(使用不同的参数),系统将多次实例化它们

  6. 死亡:stop

    系统告诉策略该重置并整理好东西的时间已经到来。存在默认的空方法。

在大多数情况下,对于常规使用模式,这将如下所示:

class MyStrategy(bt.Strategy):

    def __init__(self):
        self.sma = btind.SimpleMovingAverage(period=15)

    def next(self):
        if self.sma > self.data.close:
            # Do something
            pass

        elif self.sma < self.data.close:
            # Do something else
            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)

    有关商店通知的说明,请参阅 Cerebro。即使它们也已交付给 cerebro实例(使用覆盖notify_store方法或通过 回调) ,它们也会交付给策略

并且策略也像交易者一样有机会在市场操作过程中next尝试以获取利润的方法

  • buy做多或减少/关闭空头头寸的方法
  • sell做空或减少/关闭多头头寸的方法
  • close明显平仓的方法
  • cancel取消尚未执行的订单的方法

如何购买/出售/关闭

和方法Buy生成Sell订单。当被调用时,它们返回一个 Order(或子类)实例,可以用作参考。此订单具有唯一ref标识符,可用于比较

Tips:特定代理实现的子类Order可以携带代理提供的额外唯一标识符。

要创建订单,请使用以下参数:

  • data(默认None

    必须为哪些数据创建订单。如果None那么系统中的第一个数据,self.datas[0] or self.data0(又名 self.data)将被使用

  • size(默认None

    用于订单的数据单位的大小(正)。

    如果通过检索None的实例将用于确定大小。sizergetsizer

  • price(默认None

    使用价格(如果实际格式不符合最小报价大小要求,实时经纪人可能会对实际格式施加限制)

    NoneMarketClose订单有效(市场决定价格)

    For LimitStopand StopLimitorders 这个值决定了触发点(在触发的情况下Limit明显是在哪个价格下单应该匹配)

  • plimit(默认None

    仅适用于StopLimit订单。这是设置隐含限价单的价格,一旦触发止损price(已使用)

  • exectype(默认None

    可能的值:

    • Order.MarketNone。市价单将以下一个可用价格执行。在回测中,它将是下一个柱的开盘价
    • Order.Limit. 只能在给定 price或更好的条件下执行的订单
    • Order.Stop. 像订单一样触发price和执行的Order.Market订单
    • Order.StopLimit. 触发price并作为隐式限价订单执行的订单,价格为 pricelimit
  • valid(默认None

    可能的值:

    • None:这会生成一个不会过期的订单(又名 Good til cancel)并保留在市场中直到匹配或取消。实际上,经纪人倾向于施加时间限制,但这通常在时间上很遥远,以至于认为它不会过期
    • datetime.datetimedatetime.date实例:日期将用于生成在给定日期时间之前有效的订单(也就是好日期
    • Order.DAY0timedelta():将生成在会话结束前有效的一天(又名日订单)
    • numeric valuematplotlib:这被假定为与编码 中的日期时间相对应的值(由 使用的那个backtrader),并将用于生成在该时间之前有效的订单(良好的直到日期
  • tradeid(默认0

    这是一个内部值,用于backtrader跟踪同一资产的重叠交易。当通知订单状态的变化时,这tradeid将被发送回策略。

  • **kwargs: 额外的代理实现可能支持额外的参数。backtraderkwargs传递给创建的订单对象

    示例:如果直接支持的 4 种订单执行类型 backtrader不够用,例如 Interactive Brokers,可以将以下内容作为kwargs传递:

orderType='LIT', lmtPrice=10.0, auxPrice=9.8
  • 这将覆盖由创建的设置backtrader并生成一个触及价格为 9.8 和限价为 10.0的LIMIT IF TOUCHED订单。

信息位:

  • 策略的长度始终等于主数据的长度 ( datas[0]),当然可以通过len(self)

    next如果正在重播数据或正在传递实时提要并且同一时间点(长度)的新滴答声到达,则可以在不改变长度的情况下调用

会员属性:

  • env:这个策略所在的大脑实体
  • 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)  # or self.dnames['days']
smaweeks = bt.ind.SMA(self.dnames.weeks, period=10)  # or self.dnames['weeks']
...
  • broker: 引用与该策略相关的经纪人(来自 cerebro)
  • stats: list/named tuple-like sequence 保存 cerebro 为此策略创建的观察者
  • analyzers: list/named tuple-like 序列,包含 cerebro 为此策略创建的分析器
  • position: 实际上是一个属性,它给出了 data0.

    可以使用检索所有位置的方法(请参阅参考资料)

成员属性(用于统计/观察员/分析员):

  • _orderspending:  next被调用之前会通知策略的订单列表
  • _tradespending:  next被调用之前将被通知到策略的交易列表
  • _orders: 已经通知的订单列表。一个订单可以在列表中多次出现,具有不同的状态和不同的执行位。该列表是用来保存历史的。
  • _trades: 已经通知的订单列表。就像订单一样,一笔交易可以在列表中多次出现。

Tips:请记住prenext,nextstartnext可以在同一时间点多次调用(当使用每日时间框架时,更新每日柱的价格的刻度)

参考:策略

class backtrader.Strategy(*args, **kwargs)

要为用户定义的策略子类化的基类。

next()

当满足所有数据/指标的最短周期时,将为所有剩余的数据点调用此方法。

nextstart()

此方法将被调用一次,恰好在所有数据/指标的最小周期都已满足时。默认行为是调用 next

prenext()

此方法将在满足策略开始执行的所有数据/指标的最短周期之前调用

start()

在即将开始回测之前调用。

stop()

在回测即将停止之前调用

notify_order(order)

每当有一个变化时收到一个订单

notify_trade(trade)

每当有变化时接收交易

notify_cashvalue(cash, value)

接收当前基金价值,策略经纪商的价值状态

notify_fund(cash, value, fundvalue, shares)

收到当前现金、价值、基金价值和基金份额

notify_store(msg, *args, **kwargs)

收到来自商店提供商的通知

buy(data=None, size=None, price=None, plimit=None, exectype=None, valid=None, tradeid=0, oco=None, trailamount=None, trailpercent=None, parent=None, transmit=True, **kwargs)

创建买入(多头)订单并将其发送给经纪人

  • data(默认None

    必须为哪些数据创建订单。如果None那么系统中的第一个数据,self.datas[0] or self.data0(又名 self.data)将被使用

  • size(默认None

    用于订单的数据单位的大小(正)。

    如果通过检索None的实例将用于确定大小。sizergetsizer

  • price(默认None

    使用价格(如果实际格式不符合最小报价大小要求,实时经纪人可能会对实际格式施加限制)

    NoneMarketClose订单有效(市场决定价格)

    For LimitStopand StopLimitorders 这个值决定了触发点(在触发的情况下Limit明显是在哪个价格下单应该匹配)

  • plimit(默认None

    仅适用于StopLimit订单。这是设置隐含限价单的价格,一旦触发止损price(已使用)

  • trailamount(默认None

    如果订单类型是 StopTrail 或 StopTrailLimit,这是一个绝对数量,它决定了与价格的距离(低于卖出订单,高于买入订单)以保持追踪止损

  • trailpercent(默认None

    如果订单类型是 StopTrail 或 StopTrailLimit,这是一个百分比量,它决定了与价格的距离(低于卖出订单,高于买入订单)以保持追踪止损(如果trailamount也指定它将被使用)

  • exectype(默认None

    可能的值:

    • Order.MarketNone。市价单将以下一个可用价格执行。在回测中,它将是下一个柱的开盘价
    • Order.Limit. 只能在给定 price或更好的条件下执行的订单
    • Order.Stop. 像订单一样触发price和执行的Order.Market订单
    • Order.StopLimit. 触发price并作为隐式限价订单执行的订单,价格为 pricelimit
    • Order.Close. 只能以时段收盘价执行的订单(通常在收盘竞价期间)
    • Order.StopTrailprice 在减号trailamount(或)触发的订单,trailpercent如果价格远离止损,则更新订单
    • Order.StopTrailLimitprice在减号trailamount(或)触发的订单, trailpercent如果价格远离止损,则更新订单
  • valid(默认None

    可能的值:

    • None:这会生成一个不会过期的订单(又名 Good until cancel)并保留在市场中直到匹配或取消。实际上,经纪人倾向于施加时间限制,但这通常在时间上很遥远,以至于认为它不会过期
    • datetime.datetimedatetime.date实例:日期将用于生成在给定日期时间之前有效的订单(又名有效期至日期
    • Order.DAY0timedelta():将生成在会话结束前有效的一天(又名日订单)
    • numeric valuematplotlib:这被假定为与编码 中的日期时间相对应的值(由 使用的那个backtrader),并将用于生成在该时间之前有效的订单(直到日期有效)
  • tradeid(默认0

    这是一个内部值,用于backtrader跟踪同一资产的重叠交易。当通知订单状态的变化时,这tradeid将被发送回策略。

  • oco(默认None

    另一个order例子。此订单将成为 OCO(订单取消其他)组的一部分。执行其中一个订单,立即取消同一组中的所有其他订单

  • parent(默认None

    控制一组订单之间的关系,例如由高端限价卖出和低端止损卖出包围的买入。高位/低位订单保持无效,直到父订单被执行(它们变为有效)或被取消/到期(子订单也被取消)括号订单具有相同的大小

  • transmit(默认True

    指示是否必须传输订单,即:不仅放置在经纪人中,而且还发出。这意味着例如控制括号顺序,其中禁用父级和第一组子级的传输并最后一个子级激活它,这会触发所有括号顺序的完全放置。

  • **kwargs: 额外的代理实现可能支持额外的参数。backtraderkwargs传递给创建的订单对象

    示例:如果直接支持的 4 种订单执行类型 backtrader不够用,例如 Interactive Brokers,可以将以下内容作为kwargs传递:

    orderType='LIT', lmtPrice=10.0, auxPrice=9.8

    这将覆盖由创建的设置backtrader并生成一个触及价格为 9.8 和限价为 10.0的LIMIT IF TOUCHED订单。

  • 退货
    • 提交的订单

sell(data=None, size=None, price=None, plimit=None, exectype=None, valid=None, tradeid=0, oco=None, trailamount=None, trailpercent=None, parent=None, transmit=True, **kwargs)

创建卖出(空头)订单并将其发送给经纪人

buy有关参数的说明,请参阅文档

返回:提交的订单

close(data=None, size=None, **kwargs)

多头/空头头寸的平仓

buy有关参数的说明,请参阅文档

  • size:如果None调用者未提供(默认值:),则从现有位置自动计算

返回:提交的订单

cancel(order)

取消经纪商的订单

buy_bracket(data=None, size=None, price=None, plimit=None, exectype=2, valid=None, tradeid=0, trailamount=None, trailpercent=None, oargs={}, stopprice=None, stopexec=3 , stopargs={}, limitprice=None, limitexec=2, limitargs={}, **kwargs)

创建一个括号定单组(低端 – 买入定单 – 高端)。默认行为如下:

  • 发出带有执行的买单Limit
  • 发出低边括号单并执行Stop
  • 发出带有执行的高边括号单 Limit

请参阅下面的不同参数

  • data(默认None

    必须为哪些数据创建订单。如果None那么系统中的第一个数据,self.datas[0] or self.data0(又名 self.data)将被使用

  • size(默认None

    用于订单的数据单位的大小(正)。

    如果通过检索None的实例将用于确定大小。sizergetsizer

    笔记

    相同尺寸适用于支架的所有 3 个订单

  • price(默认None

    使用价格(如果实际格式不符合最小报价大小要求,实时经纪人可能会对实际格式施加限制)

    NoneMarketClose订单有效(市场决定价格)

    For LimitStopand StopLimitorders 这个值决定了触发点(在触发的情况下Limit明显是在哪个价格下单应该匹配)

  • plimit(默认None

    仅适用于StopLimit订单。这是设置隐含限价单的价格,一旦触发止损price(已使用)

  • trailamount(默认None

    如果订单类型是 StopTrail 或 StopTrailLimit,这是一个绝对数量,它决定了与价格的距离(低于卖出订单,高于买入订单)以保持追踪止损

  • trailpercent(默认None

    如果订单类型是 StopTrail 或 StopTrailLimit,这是一个百分比量,它决定了与价格的距离(低于卖出订单,高于买入订单)以保持追踪止损(如果trailamount也指定它将被使用)

  • exectype(默认bt.Order.Limit

    可能的值:(请参阅该方法的文档buy

  • valid(默认None

    可能的值:(请参阅该方法的文档buy

  • tradeid(默认0

    可能的值:(请参阅该方法的文档buy

  • oargs(默认{}

    dict要传递给主侧顺序的特定关键字参数(在 a 中)。默认的参数**kwargs将在此之上应用。

  • **kwargs: 额外的代理实现可能支持额外的参数。backtraderkwargs传递给创建的订单对象

    可能的值:(请参阅该方法的文档buy

    笔记

    kwargs将应用于括号的 3 个订单。请参阅下文,了解低端和高端订单的特定关键字参数

  • stopprice(默认None

    低位止损单的具体价格

  • stopexec(默认bt.Order.Stop

    低边订单的特定执行类型

  • stopargs(默认{}

    dict要传递给低端顺序的特定关键字参数(在 a 中)。默认的参数**kwargs将在此之上应用。

  • limitprice(默认None

    高位止损单的具体价格

  • stopexec(默认bt.Order.Limit

    高端订单的特定执行类型

  • limitargs(默认{}

    dict要传递给高端订单的特定关键字参数(在 a 中)。默认的参数**kwargs将在此之上应用。

可以使用以下方法抑制高/低侧订单:

  • limitexec=None压制高端
  • stopexec=None抑制低端
  • 退货
    • 包含 3 个订单的列表 [订单、止损边、限价边]
    • 如果高/低订单已被抑制,则返回值仍将包含 3 个订单,但那些被抑制的订单的值为 None

sell_bracket(data=None, size=None, price=None, plimit=None, exectype=2, valid=None, tradeid=0, trailamount=None, trailpercent=None, oargs={}, stopprice=None, stopexec=3 , stopargs={}, limitprice=None, limitexec=2, limitargs={}, **kwargs)

创建一个括号定单组(低端 – 买入定单 – 高端)。默认行为如下:

  • 发出带执行的卖单Limit
  • 发出高边括号买单并执行Stop
  • 发出带有执行的低边括号买单Limit

bracket_buy参数含义见

可以使用以下方法抑制高/低侧订单:

  • stopexec=None压制高端
  • limitexec=None抑制低端
  • 退货
    • 包含 3 个订单的列表 [订单、止损边、限价边]
    • 如果高/低订单已被抑制,则返回值仍将包含 3 个订单,但那些被抑制的订单的值为 None

order_target_size(data=None, target=0, **kwargs)

下订单以重新平衡头寸,使其最终大小为target

以当前position大小为起点实现target

  • 如果targetpos.size-> 购买target - pos.size
  • 如果targetpos.size-> 卖出pos.size - target

它返回:

  • 生成的订单

或者

  • None如果没有发出命令 ( target == position.size)

order_target_value(data=None, target=0.0, price=None, **kwargs)

下订单以重新平衡头寸以获得最终价值 target

以电流value为起点实现target

  • 如果没有target,则关闭数据
  • 如果target>value则购买数据
  • 如果target<value则出售数据

它返回:

  • 生成的订单

或者

  • None如果没有下达命令

order_target_percent(data=None, target=0.0, **kwargs)

下订单以重新平衡头寸以获得 target当前投资组合百分比的最终值value

target以十进制表示:0.05->5%

它用于order_target_value执行订单。

例子

  • target=0.05和投资组合价值是100
  • value要达到的是0.05 * 100 = 5
  • 5作为target值传递给order_target_value

以电流value为起点实现target

position.size用于确定位置是否为longshort

  • 如果target>value
    • 买如果pos.size >= 0(增加多头头寸)
    • 卖出如果pos.size < 0(增加空头头寸)
  • 如果target<value
    • 卖出如果pos.size >= 0(减少多头头寸)
    • 买如果pos.size < 0(减少空头头寸)

它返回:

  • 生成的订单

或者

  • None如果没有发出命令 ( target == position.size)

getsizer()

如果使用自动 statke 计算,则返回正在使用的 sizer

也可作为sizer

setsizer(sizer)

替换默认(固定赌注)sizer

getsizing(data=None, isbuy=True)

返回由 sizer 实例针对当前情况计算的权益

getposition(data=None, broker=None)

返回给定代理中给定数据的当前位置。

如果两者都是None,将使用主要数据和默认代理

position也有房源

getpositionbyname(name=None, broker=None)

返回给定代理中给定名称的当前位置。

如果两者都是None,将使用主要数据和默认代理

属性 positionbyname 也可用

getpositionsbyname(broker=None)

直接从代理返回当前的按名称位置

如果给定broker为无,将使用默认代理

positionsbyname也有房源

getdatanames()

返回现有数据名称的列表

getdatabyname(name)

使用环境 (cerebro) 按名称返回给定数据

add_timer(when, offset=datetime.timedelta(0), repeat=datetime.timedelta(0), weekdays=[], weekcarry=False, monthdays=[], monthcarry=True, allow=None, tzdata=None, cheat=False, *args, **kwargs)

Tips:可以在__init__或期间调用start

安排一个计时器来调用指定的回调或 notify_timer一个或多个策略。

  • 参数

     ) – 可以

    • datetime.time实例(见下文tzdata
    • bt.timer.SESSION_START引用会话开始
    • bt.timer.SESSION_END引用会话结束
    • offset这必须是一个datetime.timedelta实例

    用于偏移值whenSESSION_START它与和结合使用具有有意义的用途,以指示在会话开始后SESSION_END调用计时器之类的事情。15 minutes

    • repeat这必须是一个datetime.timedelta实例

      指示在第一次通话后,是否将在同一会话中以预定的repeat增量安排进一步的通话

      一旦计时器超过会话结束,它将重置为原始值when

    • weekdays: 一个排序的迭代器,带有整数,指示在哪些天(iso 代码,星期一是 1,星期日是 7)可以实际调用计时器

      如果未指定,计时器将在所有日子都处于活动状态

    • weekcarry(默认值:False。如果True没有看到工作日(例如:交易假期),计时器将在第二天执行(即使在新的一周)
    • monthdays:一个排序的迭代器,带有整数,指示必须在每月的哪几天执行计时器。例如总是在每月的第15天

      如果未指定,计时器将在所有日子都处于活动状态

    • monthcarry(默认值:True。如果没有看到这一天(周末、交易假日),则计时器将在下一个可用日期执行。
    • allow(默认值:None。一个回调,它接收一个 datetime.date` 实例,True如果计时器允许该日期,则返回,否则返回False
    • tzdata可以是None(默认)、pytz 实例或data feed实例。

      None:when以面值解释(这意味着将其视为 UTC 处理,即使它不是)

      pytz实例:when将被解释为在时区实例指定的本地时间中指定。

      data feed实例:将被解释为在数据馈送实例when的参数指定的本地时间中指定。tz

      笔记

      如果whenisSESSION_STARTSESSION_END并且tzdata is None,系统中的第一个数据 馈送(aka self.data0)将用作查找会话时间的参考。

    • cheat(默认False)如果True在经纪人有机会评估订单之前调用计时器。这打开了基于开盘价发出订单的机会,例如在会话开始之前
    • *args: 任何额外的参数都将传递给notify_timer
    • **kwargs: 任何额外的 kwargs 将被传递给notify_timer

返回值:

  • 创建的计时器

notify_timer(timer, when, *args, **kwargs)

收到定时器通知,timer返回的定时器在哪里add_timerwhen是调用时间。args 并且kwargs是传递给add_timer

实际when时间可以晚一些,但系统可能之前无法调用定时器。该值是定时器值,不是系统时间。