策略#

Cerebro 实例是 backtrader 的泵心和控制脑。对于平台用户来说, Strategy 也是。

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

  1. Conception: __init__

    这在实例化时显然会被调用:在此处创建 indicators 和其他所需属性。示例:

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

    注意

    一个策略在 出生 时可能会被抛出来自 backtrader.errors 模块的 StrategySkipError 异常中断。

    这将避免在回测期间执行该策略。参见 Exceptions 部分。

  2. 出生: start 世界( cerebro )告诉策略是时候开始行动了。存在一个默认的空方法。

  3. 童年: prenext

    在概念阶段声明的 indicators 会对策略需要成熟的时间有一定的限制:这称为 minimum period 。在上面的 __init__ 中创建了一个 SimpleMovingAverage ,其 period=15

    只要系统看到的数据不到 15 个,就会调用 prenext (默认方法为空操作)。

  4. 成年期: next

    一旦系统看到了 15 个数据,且 SimpleMovingAverage 的缓冲区足够大,能够开始输出值,策略就已经足够成熟来执行了。

    还有一个 nextstart 方法,会被调用一次,来标志着从 prenext 转向 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:

# 做某事 pass

elif self.sma < self.data.close:

# 做其他事情 pass

在这个代码段中:

  • __init__ 中,一个属性被赋予了一个指标

  • 默认空的 start 方法没有被覆盖

  • prenextnexstart 没有被覆盖

  • 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 方法取消尚未执行的订单

购买/销售/关闭的方法#

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

注意

特定经纪人实现的 Order 子类可能携带经纪人提供的其他 唯一标识符 。创建订单时,请使用以下参数:

  • data (默认值: None

    指定要创建订单的数据。如果为 None ,则将使用系统中的第一个数据 self.datas[0] or self.data0 (也就是 self.data )。

  • size (默认值: None

    指定要使用的数据单位的大小(必须为正数)。

    如果为 None ,则会使用通过 getsizer 方法检索到的 sizer 实例来确定大小。

  • price (默认值: None

    指定要使用的价格(如果价格不符合最低变动点要求,则活动经纪人可能会设置限制)。

    对于 MarketClose 订单, None 是有效的(市场确定价格)。

    对于 LimitStopStopLimit 订单,此值确定触发点(对于 Limit ,触发点显然是订单应该匹配的价格)。 - plimit (默认值: None

    仅适用于“StopLimit”订单。这是在 * Stop * 触发后(使用 price )设置隐式 * Limit * 订单的价格

  • exectype (默认值: None

    可能的值:

    • Order.MarketNone 。市价订单将以下一个可用价格执行。在回测中,它将是下一个柱状图的开盘价

    • Order.Limit 。只能以给定的 price 或更好的价格执行的订单

    • Order.Stop 。在 price 触发的订单,并像 Order.Market 订单一样执行

    • Order.StopLimit 。在 price 触发的订单,并作为由 pricelimit 给出的隐式 * Limit * 订单执行

  • valid (默认值: None

    可能的值:- None : 这将生成一个不会过期的订单(也被称为 Good til cancel ),并将一直在市场上等待匹配或取消。实际上,经纪人往往会设置一个时间上限,但通常这个时间距离现在还很遥远,所以可以视为不会过期

  • datetime.datetimedatetime.date 实例:将使用该日期生成一个有效期直到给定日期的订单(也被称为 good til date

  • Order.DAY0 或 ` 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), prenextnextstartnext 可能会被多次调用,当使用每日时间框架时。

参考:策略#