- 智能质押
策略提供了交易方法,即:buy
和 sell
close
。让我们看看签名 buy
:
def buy(self, data=None, size=None, price=None, plimit=None, exectype=None, valid=None, tradeid=0, **kwargs):
请注意,size
如果调用方未指定默认值,则具有默认值 None
。这是 Sizers 发挥重要作用的地方:
size=None
要求「战略」询问其实际赌注的Sizer
这显然意味着策略有一个 Sizer:是的,确实如此!后台机制将缺省 sizer 添加到策略中,如果用户尚未添加一个。添加到策略的缺省 Sizer 为SizerFix
。定义的初始 lines :
class SizerFix(SizerBase): params = (('stake', 1),)
很容易猜到,这个Sizer只是使用一个stake
1
单位(无论是股票,合约等)购买/出售。
使用 Sizers
从 Cerebro
Sizers 可以通过2种不同的方法通过 Cerebro 添加:
-
addsizer(sizercls, *args, **kwargs)
添加一个 Sizer ,该将应用于添加到 cerebro的任何策略。可以说,这是缺省 Sizer。例:
cerebro = bt.Cerebro() cerebro.addsizer(bt.sizers.SizerFix, stake=20) # default sizer for strategies
-
addsizer_byidx(idx, sizercls, *args, **kwargs)
Sizer将仅添加到
idx
这可以
idx
作为返回值从addstrategy
获取。如:cerebro = bt.Cerebro() cerebro.addsizer(bt.sizers.SizerFix, stake=20) # default sizer for strategies idx = cerebro.addstrategy(MyStrategy, myparam=myvalue) cerebro.addsizer_byidx(idx, bt.sizers.SizerFix, stake=5) cerebro.addstrategy(MyOtherStrategy)
在这里范例中:
-
默认 Sizer 已添加到系统中。这适用于没有分配特定 Sizer 的所有策略
-
对于 MyStrategy,在收集其插入 idx 后,将添加特定的 sizer (更改
stake
参数) -
第二个策略MyOtherStrategy被添加到系统中。没有为其添加特定的Sizer
-
这意味着:
-
MyStrategy最终将有一个内部特定的 Sizer
-
MyOtherStrategy将获得缺省 sizer
-
-
注意
默认并不意味着策略共用单个Sizer实例。每个策略接收缺省sizer的不同实例
若要共用单个实例,要共用 sizer 应为单例类。如何定义一个超出了 backtrader
从战略
策略类提供了一个 API:setsizer
和(和 getsizer
一个属性 sizer
)来管理 Sizer。签章:
-
def setsizer(self, sizer)
:它需要一个已经实例化的 Sizer -
def getsizer(self)
:返回当前 Sizer 实例 -
sizer
它是可以直接获取/设置的属性
在这种情况下, Sizer 可以是例如:
-
作为参数传递给策略
-
在使用属性
sizer
时__init__
进行设置,或setsizer
如:class MyStrategy(bt.Strategy): params = (('sizer', None),) def __init__(self): if self.p.sizer is not None: self.sizer = self.p.sizer
例如,这将允许在cerebro调用发生的同一级别创建Sizer,并将其作为参数传递给系统中的所有策略,从而有效地允许共用Sizer
Sizer 开发
这很容易:
-
子类从
backtrader.Sizer
这使您可以访问
self.strategy
并且self.broker
在大多数情况下不需要它。可以使用broker
-
数据的位置
self.strategy.getposition(data)
-
完整的投资组合价值通过以下方式
self.broker.getvalue()
请注意,这当然也可以通过以下方式完成
self.strategy.broker.getvalue()
其他一些事情已经在下面作为论据
-
-
重写方法
_getsizing(self, comminfo, cash, data, isbuy)
-
comminfo
:佣金信息实例,包含有关数据佣金的信息,并允许计算位置值,运营成本,操作佣金 -
cash
:经纪人的当前可用现金 -
data
:操作的目标 -
isbuy
:将True
用于买入操作和False
卖出操作
此方法返回
size
买入/卖出操作所需的值返回的符号不相关,即:如果操作是卖出操作(
isbuy
将是False
),则方法可能返回5
或-5
。卖出操作将仅使用绝对值。Sizer
已经转到broker
并要求委员会提供给定数据,实际现金水准的信息,并提供对作为操作目标的数据的直接参考 -
让我们来看看sizer的定义FixedSize
:
import backtrader as bt class FixedSize(bt.Sizer): params = (('stake', 1),) def _getsizing(self, comminfo, cash, data, isbuy): return self.params.stake
这很简单,因为 Sizer 不进行计算,参数就在那里。
但该机制应该允许构建复杂的尺寸(又名定位)系统,以管理进入/退出市场时的赌注。
另一个例子:位置反转器:
class FixedRerverser(bt.FixedSize): def _getsizing(self, comminfo, cash, data, isbuy): position = self.broker.getposition(data) size = self.p.stake * (1 + (position.size != 0)) return size
这个创建在现有FixedSize
的基础上,继承 params
并覆盖 _getsizing
:
-
position
通过属性获取数据broker
-
用于
position.size
决定是否将固定赌注翻倍 -
返回计算值
这将消除《战略》的负担,即决定是否必须逆转或开仓, Sizer 处于控制之中,可以随时更换而不影响逻辑。
实用 Sizer 适用性
考虑到复杂的大小调整算法,可以使用两种不同的sizers将策略从仅做多转换为多空。只需改变cerebro运行中的Sizer,策略就会改变行为。一个非常简单的close
交叉SMA
算法:
class CloseSMA(bt.Strategy): params = (('period', 15),) def __init__(self): sma = bt.indicators.SMA(self.data, period=self.p.period) self.crossover = bt.indicators.CrossOver(self.data, sma) def next(self): if self.crossover > 0: self.buy() elif self.crossover < 0: self.sell()
请注意,该策略如何不考虑当前头寸(通过查看self.position
)来决定是否必须实际完成买入或卖出。仅考虑来自的 CrossOver
信号。 Sizers 将负责一切。
此 sizer 将负责在卖出时仅返回非零大小,如果仓位已经 open:
class LongOnly(bt.Sizer): params = (('stake', 1),) def _getsizing(self, comminfo, cash, data, isbuy): if isbuy: return self.p.stake # Sell situation position = self.broker.getposition(data) if not position.size: return 0 # do not sell if nothing is open return self.p.stake
将它们放在一起(并假设已经导入 backtrader 并且数据已添加到系统中):
... cerebro.addstrategy(CloseSMA) cerebro.addsizer(LongOnly) ... cerebro.run() ...
图表(从源中包含的范例中对此进行测试)。
长短版本只是将SizerFixedReverser
更改为如上所示:
... cerebro.addstrategy(CloseSMA) cerebro.addsizer(FixedReverser) ... cerebro.run() ...
输出图表。
请注意差异:
-
重复的交易数量
-
现金水平永远不会回到价值,因为策略总是在市场上
这两种方法都是负面的,但这只是一个例子。
Sizer 参考
backtrader类 .Sizer()
这是 Sizers的基类。任何 sizer 都应对此进行子类化并重写该_getsizing
方法
成员单位:
-
strategy
:将由 sizer 正在工作的策略设置允许访问策略的整个 API,例如,如果需要以下位置
_getsizing
的实际数据位置:position = self.strategy.getposition(data)
-
broker
:将由 sizer 正在工作的策略设置提供对信息的访问,一些复杂的 sizers 可能需要,如投资组合价值,..
_getsizing(通信信息、现金、数据、购买)
此方法必须由 Sizer 的子类覆盖,以提供大小调整功能
参数:
* `comminfo`: The CommissionInfo instance that contains information about the commission for the data and allows calculation of position value, operation cost, commision for the operation * `cash`: current available cash in the *broker* * `data`: target of the operation * `isbuy`: will be `True` for *buy* operations and `False` for *sell* operations
该方法必须返回要运行的实际大小(整型)。如果0
返回,则不会运行任何内容。
将使用返回值的绝对值