Skip to content

策略

原文: https://www.backtrader.com/docu/strategy/

一个Cerebro实例是backtrader的心脏泵送和大脑控制。Strategy对于平台用户也是一样的。

策略的以方法表示生命周期

笔记

出生期间,可以通过从模块backtrader.errors引发StrategySkipError异常来中断策略

这将避免在回溯测试期间执行策略。见Exceptions一节

  1. 概念:__init__

    这显然是在实例化过程中调用的:indicators将在此处创建,并且需要其他属性。例子:

    py 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方法,准确地称为一次,用于标记从prenextnext的切换。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方法不被覆盖

  • 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)

    有关商店通知的说明,请参见脑波。即使它们也已被传递到cerebro实例(使用覆盖的notify_store方法或通过回调传递),也会被传递到策略中

策略也像交易者一样,在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

    使用价格(如果实际格式不符合最小刻度大小要求,实时经纪人可能会对其进行限制)

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

    对于LimitStopStopLimit订单,该值确定触发点(在Limit的情况下,触发点显然是订单应匹配的价格)

  • plimit(默认为None

    仅适用于StopLimit订单。这是在触发停止后(已使用price时)设置隐含限制订单的价格

  • exectype(默认为None

    可能值:

    • Order.MarketNone。市场订单将以下一个可用价格执行。在回溯测试中,它将是下一个酒吧的开盘价

    • Order.Limit。只能在给定的price或更好的条件下执行的命令

    • Order.Stop。在price触发并像Order.Market指令一样执行的指令

    • Order.StopLimit。在price触发并作为隐含限额订单执行的订单,价格由pricelimit给出

  • valid(默认为None

    可能值:

    • None:这将生成一个不会过期的订单(也称为在取消之前有效),并在匹配或取消之前保持在市场中。在现实中,经纪人倾向于施加时间限制,但通常情况下,在时间上远不及考虑到期。

    • datetime.datetimedatetime.date实例:该日期将用于生成在给定日期时间之前有效的订单(又名good til date

    • Order.DAY0timedelta():生成有效期至会话结束的一天(又名订单)

    • numeric value:假设该值对应于matplotlib编码中的日期时间(由backtrader使用的日期时间),并将用于生成在该时间之前有效的订单(截止日期

  • tradeid(默认为0

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

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

    示例:如果backtrader直接支持的 4 种订单执行类型不够,例如交互经纪人的情况下,以下可以传递为kwargs

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

    这将覆盖backtrader创建的设置并生成LIMIT IF TOUCHED订单,其中触摸价格为 9.8,限制价格为 10.0。

信息位:

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

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

成员属性:

  • env:此策略所在的大脑实体

  • datas:已传递给大脑的数据馈送数组

    • data/data0是数据[0]的别名

    • dataX是数据[X]的别名

    数据源也可以通过名称访问(参见参考资料),如果已经为其分配了名称

  • dnames:通过名称(使用[name].name符号)访问数据源的替代方法

    例如,如果像这样对数据重新采样:

    py ... data0 = bt.feeds.YahooFinanceData(datname='YHOO', fromdate=..., name='days') cerebro.adddata(data0) cerebro.resampledata(data0, timeframe=bt.TimeFrame.Weeks, name='weeks') ...

    在战略的后面部分,我们可以创建如下各项指标:

    py ... 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:对与该策略相关的经纪人的引用(从 Cerbero 收到)

  • stats:列出/命名的元组序列,其中包含大脑为此策略创建的观察者

  • analyzers:列出/命名类似元组的序列,其中包含由 Cerbero 为此策略创建的分析器

  • position:实际上是给出data0当前位置的属性。

    检索所有 position 的方法都可用(请参阅参考资料)

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

  • _orderspending:调用next前会通知策略的订单列表

  • _tradespending:在调用next之前将通知策略的交易列表

  • _orders:已经通知的订单列表。一个订单可以在列表中多次使用不同的状态和不同的执行位。该列表是用来保存历史记录的。

  • _trades:已经通知的订单列表。一笔交易可以像一笔订单一样多次出现在列表中。

笔记

请记住,对于同一时间点,prenextnextstartnext可以多次调用(当使用每日时间段时,勾号会更新每日酒吧的价格)

参考:战略

类 backtrader.Strategy(args,*kwargs)

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

下一个()

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

nextstart()

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

prenext()

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

开始()

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

停止()

在回溯测试即将停止之前调用

通知订单(订单)

在订单发生变化时接收订单

通知贸易部(贸易部)

每当一项交易发生变化时,接受一项交易

通知现金价值(现金、价值)

接收当前基金价值、战略经纪人的价值状态

通知基金(现金、价值、基金价值、股份)

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

通知门店(消息,args,*kwargs)

接收来自存储提供商的通知

购买(数据=None,大小=None,价格=None,plimit=None,exectype=None,valid=None,tradeid=0,oco=None,trailamount=None,trailpercent=None,父项=None,传输=True,**kwargs)

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

  • data(默认为None

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

  • size(默认为None

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

    如果None将使用getsizer检索的sizer实例来确定大小。

  • price(默认为None

    使用价格(如果实际格式不符合最小刻度大小要求,实时经纪人可能会对其进行限制)

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

    对于LimitStopStopLimit订单,该值确定触发点(在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.StopTrail。在price减去trailamount(或trailpercent时触发的订单,如果价格偏离止损点,则更新该订单

    • Order.StopTrailLimit。在price减去trailamount(或trailpercent时触发的订单,如果价格偏离止损点,则更新该订单

  • valid(默认为None

    可能值:

    • None:这将生成一个不会过期的订单(也称为在取消之前有效),并在匹配或取消之前保持在市场中。在现实中,经纪人倾向于施加时间限制,但通常情况下,在时间上远不及考虑到期。

    • datetime.datetimedatetime.date实例:该日期将用于生成有效期至给定日期时间的订单(又名有效期至日期

    • Order.DAY0timedelta():生成有效期至会话结束的一天(又名订单)

    • numeric value:假设该值对应于matplotlib编码中的日期时间(由backtrader使用的日期时间),并将用于生成在此时间之前有效的订单(截止日期

  • tradeid(默认为0

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

  • oco(默认为None

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

  • parent(默认为None

    控制一组订单的关系,例如,由高端限售和低端停售括起的买入。在父订单被执行(激活)或取消/到期(子订单也被取消)之前,高端/低端订单保持非活动状态。括号订单具有相同的大小

  • transmit(默认为True

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

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

    示例:如果backtrader直接支持的 4 种订单执行类型不够,例如交互经纪人的情况下,以下可以传递为kwargs

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

    这将覆盖backtrader创建的设置并生成LIMIT IF TOUCHED订单,其中触摸价格为 9.8,限制价格为 10.0。

  • 返回

    • 提交的订单

销售(数据=None,大小=None,价格=None,plimit=None,exectype=None,valid=None,tradeid=0,oco=None,trailamount=None,trailpercent=None,父项=None,传输=True,**kwargs)

创建销售(短期)订单并将其发送给经纪人

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

返回:提交的订单

关闭(数据=无,大小=无,**kwargs)

冲销多头/空头头寸并将其关闭

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

笔记

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

返回:提交的订单

取消(订单)

取消代理中的订单

buy_ 括号(data=None,size=None,price=None,plimit=None,exectype=2,valid=None,tradeid=0,trailamount=None,trailpercent=None,oargs={},stopperice=None,stoppexec=3,stoppergs={},limitprice=None,limitexec=2,limitargs={},**kwargs)

创建括号订单组(低端-采购订单-高端)。默认行为如下所示:

  • 发出购买订单并执行Limit

  • 下发低端括号卖出订单并执行Stop

  • 发出高端括号卖出订单,执行Limit

有关不同的参数,请参见下文

  • data(默认为None

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

  • size(默认为None

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

    如果None将使用getsizer检索的sizer实例来确定大小。

    笔记

    相同的大小应用于括号的所有 3 个订单

  • price(默认为None

    使用价格(如果实际格式不符合最小刻度大小要求,实时经纪人可能会对其进行限制)

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

    对于LimitStopStopLimit订单,该值确定触发点(在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中)传递到主端顺序。来自默认值**kwargs的参数将应用于此参数之上。

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

    可能值:(方法buy见文档)

    笔记

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

  • stopprice(默认为None

    低端停单具体价格

  • stopexec(默认为bt.Order.Stop

    低端订单的具体执行类型

  • stopargs(默认为{}

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

  • limitprice(默认为None

    高端停单具体价格

  • stopexec(默认为bt.Order.Limit

    高端订单的具体执行类型

  • limitargs(默认为{}

    要传递到高端顺序的特定关键字参数(在dict中)。来自默认值**kwargs的参数将应用于此参数之上。

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

  • limitexec=None抑制高侧

  • stopexec=None抑制低端

  • 返回

    • 包含 3 个订单[订单、停止端、限制端]的列表

    • 如果高/低订单已被抑制,返回值仍将包含 3 个订单,但被抑制的订单的值将为None

sell_ 括号(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

订单\目标\大小(数据=无,目标=0,**kwargs)

下订单重新平衡位置,使最终尺寸为target

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

  • 如果target>pos.size->买入target - pos.size

  • 如果target<pos.size->卖出pos.size - target

它返回以下任一项:

  • 生成的订单

  • None如果没有发出订单(target == position.size

订单\目标\价值(数据=无,目标=0.0,价格=无,**kwargs)

下订单重新平衡位置,使最终值为target

考虑电流value作为实现target的起点

  • 如果没有target,则关闭数据上的位置

  • 如果target>value则按数据买入

  • target<value则按数据卖出

它返回以下任一项:

  • 生成的订单

  • None如果没有发出订单

订单\目标\百分比(数据=无,目标=0.0,**kwargs)

下订单重新平衡头寸,使其最终价值达到当前投资组合valuetarget百分比

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

它使用order_target_value执行订单。

示例

  • target=0.05且投资组合价值为100

  • 要到达的value0.05 * 100 = 5

  • 5作为target值传递给order_target_value

考虑电流value作为实现target的起点

position.size用于确定位置是否为long/short

  • 如果target>value

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

    • 如果pos.size >= 0卖出(减少多头头寸)

    • 如果pos.size < 0买入(减少空头头寸)

它返回以下任一项:

  • 生成的订单

  • None如果没有发出订单(target == position.size

getsizer()

如果使用自动桩计算,则返回正在使用的尺寸器

也可作为sizer提供

设定器(施胶器)

替换默认(固定桩)尺寸测量器

getsizing(数据=None,isbuy=True)

返回 sizer 实例为当前情况计算的桩号

getposition(数据=无,代理=无)

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

如果两者都为无,则将使用主数据和默认代理

还提供了一个属性position

getpositionbyname(name=None,broker=None)

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

如果两者都为无,则将使用主数据和默认代理

还提供了一个属性positionbyname

getpositionsbyname(代理=无)

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

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

还提供了一个属性positionsbyname

getdatanames()

返回现有数据名的列表

getdatabyname(名称)

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

添加计时器(当,offset=datetime.timedelta(0),repeat=datetime.timedelta(0),weekdays=[],weekcarry=False,monthdays=[],monthcarry=True,allow=None,tzdata=None,cheat=False,args,*kwargs)

笔记

可在__init__start期间调用

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

  • 参数

    -)–可以

    • datetime.time实例(见下文tzdata

    • bt.timer.SESSION_START引用会话开始

    • bt.timer.SESSION_END引用会话结束

    • offset必须是datetime.timedelta实例

    用于偏移值when。它与SESSION_STARTSESSION_END结合使用,有意义地表示在会话开始后调用15 minutes计时器之类的事情。

    • repeat必须是datetime.timedelta实例

      指示在 1st呼叫后,是否会在同一会话中以预定的repeat增量安排更多呼叫

      一旦计时器在会话结束后被重置为when的原始值

    • weekdays:一个排序的iterable,带有整数,表示可以实际调用计时器的日期(iso 代码,周一是 1,周日是 7)

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

    • weekcarry(默认为False)。如果True和工作日不可见(例如:交易假日),计时器将在第二天执行(即使在新的一周内)

    • monthdays:一个排序的iterable,整数表示计时器必须在月份的哪几天执行。例如,始终在当月的第15

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

    • monthcarry(默认为True)。如果看不到该日(周末、交易日),计时器将在下一个可用日执行。

    • allow(默认为None)。接收 datetime.date实例并返回True的回调,如果允许计时器使用该日期,则返回False`

    • tzdata可以是None(默认)、一个pytz实例或一个data feed实例。

      Nonewhen按面值解释(这意味着即使不是 UTC,也要像对待 UTC 一样处理)

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

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

      笔记

      如果whenSESSION_STARTSESSION_ENDtzdataNone,则系统中的 1st数据馈送(又名self.data0)将作为查询会话时间的参考。

    • cheat(默认False)如果True计时器将在经纪人有机会评估订单之前调用。这样就有机会根据开盘价发出订单,例如在会议开始之前

    • *args:任何额外参数都将传递给notify_timer

    • **kwargs:任何额外的 KWARG 将传递给notify_timer

返回值:

  • 创建的计时器

通知计时器(计时器,时间,args,*kwargs)

接收定时器通知,timeradd_timer返回的定时器,when为呼叫时间。argskwargs是传递给add_timer的任何附加参数

实际的when时间可以晚一点,但系统之前可能无法调用计时器。该值为计时器值,不代表系统时间。


我们一直在努力

apachecn/AiLearning

【布客】中文翻译组