Backtrader中文筆記之Sizers


Sizers

  • Smart Staking

A Strategy offers methods to trade, namely: buy, sell and close. Let’s see the signature of buy:

策略提供了交易的方法,即:買入、賣出和成交。讓我們看看buy的簽名:

def buy(self, data=None,
        size=None, price=None, plimit=None,
        exectype=None, valid=None, tradeid=0, **kwargs):

 Notice that size has a default value of None if the caller does not specify it. This is where Sizers play an important role:

請注意,如果調用方未指定大小,則size的默認值為None。這就是Sizers發揮重要作用的地方:

  • size=None requests that the Strategy asks its Sizer for the actual stake
  • size=None請求策略向其Sizer請求實際的股份

This obviously implies that Strategies have a Sizer: Yes, indeed!. The background machinery adds a default sizer to a Strategy if the user has not added one. The default Sizer added to a strategy is SizerFix. The initial lines of the definition:

這顯然意味着策略里面有Sizer:是的,確實如此!。如果用戶沒有添加,則后台機制將默認的大小寫器添加到策略中。添加到策略中的默認Sizer是SizerFix。定義的初始行:

class SizerFix(SizerBase):
    params = (('stake', 1),)

 It is easy to guess that this Sizer simply buys/sells using a stake of 1 units (be it shares, contracts, …)

很容易猜測,這個規模的Sizer只是用1個單位的股份進行買賣(無論是股票、合同等)

 

Using Sizers

From Cerebro

Sizers can be added via Cerebro with 2 different methods:

Sizers有兩個不同的方法通過Cerebro添加

addsizer(sizercls, *args, **kwargs)

Adds a Sizer that will be applied to any strategy added to cerebro. This is, so to to say, the default Sizer. Example:

添加一個Sizer,它將應用於添加到大腦的任何策略。可以說,這是默認的Sizer。例子:

cerebro = bt.Cerebro()
cerebro.addsizer(bt.sizers.SizerFix, stake=20)  # default sizer for strategies

addsizer_byidx(idx, sizercls, *args, **kwargs)

The Sizer will only be added to the Strategy referenced by idx

Sizer只能通過策略返回的參考idx被添加

This idx can be gotten as return value from addstrategy. As in:

這個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)

 

In this example:

  • A default Sizer has been added to the system. This one applies to all strategies which don’t have a specific Sizer assigned

  • 系統中已添加了一個默認的Sizer。這一條適用於所有沒有指定特定尺寸的策略。
  • For MyStrategy and after collecting its insertion idx, a specific sizer (changing the stake param) is added

  • 對於MyStrategy,在收集其插入idx之后,將添加一個特定的sizer(更改stake param)
  • A 2nd strategy, MyOtherStrategy, is added to the system. No specific Sizer is added for it

  • 第二個策略,MyOtherStrategy,被添加到系統中。沒有為它添加特定的Sizer
  • This means that:

  • 這意味着
  •  

    • MyStrategy will finally have an internal specific Sizer

    • MyStrategy最終會有一個內部特定的Sizer
    • MyOtherStrategy will get the default sizer

    • MyOtherStrategy將獲得默認Sizer

Note

default doesn’t mean that that the strategies share a single Sizer instance. Each strategy receives a different instance of the default sizer

默認並不意味着這些策略共享一個Sizer實例。每個策略都會收到一個不同的默認sizer實例

To share a single instance, the sizer to be shared should be a singleton class. How to define one is outside of the scope of backtrader

要共享單個實例,要共享的sizer應該是一個singleton類(單例)。如何定義一個超出了backtrader的范圍

 

From Strategy

The Strategy class offers an API: setsizer and getsizer (and a property sizer) to manage the Sizer. The signatures:

Strategy類提供了一個API: setzer和getsizer(以及一個屬性sizer)來管理sizer。簽名:

  • def setsizer(self, sizer): it takes an already instantiated Sizer

  • def setzer(self,sizer):它需要一個已經實例化的sizer
  • def getsizer(self): returns the current Sizer instance

  • def getsizer(self):返回當前的Sizer實例
  • sizer it is the property which can be directly get/set

  • sizer它是可以直接獲取/設置的屬性

In this scenario the Sizer can be for example:

在這種情況下,Sizer可以是:

  • Passed to the strategy as a parameter

  • 作為參數傳遞給策略
  • Be set during __init__ using the property sizer or setsizer as in:

  • 在初始化期間使用屬性sizer或setsizer進行設置,如下所示:
class MyStrategy(bt.Strategy):
    params = (('sizer', None),)

    def __init__(self):
        if self.p.sizer is not None:
        # 通過property進行設置 self.sizer = self.p.sizer

 This would for example allow to create a Sizer at the same level as the cerebro calls are happening and pass it as a parameter to all strategies that go in the system, which effectevily allows sharing a Sizer

例如,這將在發生大腦調用的同一時間級別創建一個Sizer,並將其作為參數傳遞給系統中的所有策略,從而有效地允許共享一個Sizer。

 

Sizer Development

Doing it is easy:

這樣做很容易:

  1. Subclass from backtrader.Sizer

  2. 子類來自於backtrader.Sizer

     

    This gives you access to self.strategy and self.broker although it shouldn’t be needed in most cases. Things that can be accessed with the broker

  3. 這樣你就可以訪問self.strategy以及self.broker雖然在大多數情況下不需要它。這個可以讓你訪問broker

     

    • data’s position with self.strategy.getposition(data)

    • 數據的position通過self.strategy.getposition取到(數據)
    • complete portfolio value through self.broker.getvalue()

    • 完整的投資價值通過self.broker.getvalue()

       

      Notice this could of course also be done with self.strategy.broker.getvalue()

    • 注意這當然也可以用self.strategy.broker.getvalue()

    Some of the other things are already below as arguments

  4. 其他一些事情已經作為論據在下面了
  5. Override the method _getsizing(self, comminfo, cash, data, isbuy)

  6. 重寫方法_getsizing(self, comminfo, cash, data, isbuy)

     

    • 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

    • comminfo:包含數據佣金信息的CommissionInfo實例,允許計算頭寸值、操作成本、操作佣金
    • cash: current available cash in the broker

    • cash:當前經紀人可用的現金
    • data: target of the operation

    • data:操作的目標
    • isbuy: will be True for buy operations and False for sell operations

    • isbuy:對於buy操作為True,對於sell操作為False

    This method returns the desired size for the buy/sell operation

  7. 此方法返回buy/sell操作所需的大小

    The returned sign is not relevant, ie: if the operation is a sell operation (isbuy will be False) the method may return 5 or -5. Only the absolute value will be used by the sell operation.

  8. 返回的符號與此無關,即:如果操作是sell操作(isbuy將為False),則該方法可能返回5或-5。只有絕對值將被sell操作使用。
  9. Sizer has already gone to the broker and requested the commission information for the given data, the actual cash level and provides a direct reference to the data which is the target of the operation

  10. Sizer已經去找經紀人,要求提供給定數據的佣金信息、實際現金水平,並提供直接參考數據,這是操作的目標

Let’s go for the definition of the FixedSize sizer:

讓我們定一個FixedSize

import backtrader as bt

class FixedSize(bt.Sizer):
    params = (('stake', 1),)

    def _getsizing(self, comminfo, cash, data, isbuy):
        return self.params.stake

 

This is pretty simple in that the Sizer makes no calculations and the parameters are just there.

這很簡單,因為Sizer不進行計算,參數就在那里。

But the mechanism should allow the construction of complex sizing (aka positioning) systems to manage the stakes when entering/exiting the market.

但該機制應允許構建復雜的規模(又名定位)系統,以便在進入/退出市場時管理股權。

Another example: A position rerverser:

另一個例子:位置變換器:

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

 This one builds on the existing FixedSize to inherit the params and overrides _getsizing to:

它基於現有的FixedSize來繼承參數,並重寫_getsizing以:

  • Get the position of the data via the attribute broker

  • 通過data的屬性broker來獲取持倉情況
  • Use position.size to decide if to double the fixed stake

  • 使用position.size來計算是否需要兩倍的量
  • Return the calculated value

  • 返回計算好的值

This would remove the burden from the Strategy to decide if a position has to be reversed or opened, the Sizer is in control and can at any time be replaced without affecting the logic.

這將減輕策略的負擔,以決定是否必須逆轉或打開頭寸,規模大小是在控制之中,可以隨時替換而不影響邏輯。

 

Practical Sizer Applicability

實際Sizer的適用性

Wihtout considering complex sizing algorithms, two different sizers can be used to turn a strategy from Long-Only to Long-Short. Simply by changing the Sizer in the cerebro execution, the strategy will change behavior. A very simple close crosses SMA algorithm:

在不考慮復雜的大小調整算法的情況下,可以使用兩種不同的大小sizers來將策略從“僅多單”轉換為“多空單”。通過改變執行策略,大腦的行為會改變。一種非常簡單的收盤價超越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()

 Notice how the strategy doesn’t consider the current position (by looking at self.position) to decide whether a buy or sell has to actually be done. Only the signal from the CrossOver is considered. The Sizers will be in charge of everything.

注意策略是不考慮當前倉位(通過查看自我定位)決定到底是買還是賣。只考慮來自交叉口的信號。所有的事都由Sizers負責。

This sizer will take care of only returning a non-zero size when selling if a position is already open:

如果倉位已經打開,則在賣出時,此sizer只負責返回非零大小:

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

 Putting it all together (and assuming backtrader has already been imported and a data has been added to the system):

 把它們放在一起(假設backtrader已經導入,並且數據已經添加到系統中):

...
cerebro.addstrategy(CloseSMA)
cerebro.addsizer(LongOnly)
...
cerebro.run()
...

 The chart (from the sample included in the sources to test this).

圖表(源代碼中包含的樣本)。

 

 

 The Long-Short version simply changes the Sizer to be the FixedReverser shown above:

 長短版只需將Sizer更改為上面顯示的FixedReverser:

 

...
cerebro.addstrategy(CloseSMA)
cerebro.addsizer(FixedReverser)
...
cerebro.run()
...

 The output chart.

 

 

Notice the differences:

注意區別:

  • The number of trades has duplicated

  • 交易數量重復了
  • The cash level never goes back to be the value because the strategy is always in the market

  • 現金水平永遠不會回到價值,因為策略總是在市場上

Both approaches are anyhow negative, but this is only an example.

這兩種方法都是消極的,但這只是一個例子。

 

bt.Sizer Reference

class backtrader.Sizer()

This is the base class for Sizers. Any sizer should subclass this and override the _getsizing method

這是sizer的基類。任何sizer都應將其子類化並重寫_getsizing方法

Member Attribs:

成員屬性:

strategy: will be set by the strategy in which the sizer is working

策略:在任意一個sizer的工作狀態都可以設置策略

Gives access to the entire api of the strategy, for example if the actual data position would be needed in_getsizing:

提供對策略的整個api的訪問權限,例如,如果需要實際的數據倉位就可以通過_getsizing方法

position = self.strategy.getposition(data)

 

  • broker: will be set by the strategy in which the sizer is working

  • broker:在任意一個sizer的工作狀態都可以設置broker
  •  

    Gives access to information some complex sizers may need like portfolio value, ..

  • 提供對一些復雜規模公司可能需要的信息的訪問,如投資組合價值。。

_getsizing(comminfo, cash, data, isbuy)

This method has to be overriden by subclasses of Sizer to provide the sizing functionality

此方法必須由Sizer的子類重寫才能提供調整功能

Params:

參數:

* `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

 

The method has to return the actual size (an int) to be executed. If 0 is returned nothing will be executed.

該方法必須返回要執行的實際大小(int)。如果返回的是0,則不執行任何操作。

The absolute value of the returned value will be used

將使用返回值的絕對值

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM