以下內容皆參考 Backtrader 官網
之前有介紹過,如果我們下單除了股價以外,還有一個很重要的因素就是要買幾股,有些時候,我們的策略可能會需要不同的買入數量,Backtrader 也有一個物件 sizer 可以提供相關的彈性,如果預設的沒有合適的,也可以自訂義一個,以下先介紹內建的一些 sizer
顧名思義就是固定的數量
參數:
cerebro.addsizer(bt.sizers.SizerFix, stake = 1000)
一樣是固定數量,只是在賣的時候,會賣出 2 倍的庫存,也就是把正的庫存賣成負的庫存
參數:
cerebro.addsizer(bt.sizers.FixedRevert, stake = 1000)
使用一定比例的帳戶餘額去買進
參數:
cerebro.addsizer(bt.sizers.PercentSizer, percents = 80)
基本上和 PercentSizer 一樣,只是預設是 100% 的帳戶餘額去買進股票,另一個差別就是 All in 聽起來比較霸氣。
這裡有一個要注意的是,AllIn 是以當天的收盤價去算要買的股數,可是在執行買入的時候,是隔天的開盤價,所以隔天是漲的話,就會造成餘額不足,買入失敗喔
cerebro.addsizer(bt.sizers.AllInSizer)
PercentSizerInt, AllInSizerInt,這兩個看說明是說在回傳數量的時候會轉成整數,不過我真正去執行的結果,兩個都是一樣的,所以暫時看不出差別
要自訂義 sizer 也很簡單
訂義一個 sizer 的 class 繼承 backtrader.Sizer
繼承後可以使用 self.strategy 和 self.broker 來取得相關資料
覆寫 _getsizing(self, comminfo, cash, data, isbuy)
例如:改寫 percent 變成可以買的最大的張數 ( 1000 股 )
import backtrader as bt
import math
class PercentBoardSizer(bt.Sizer):
params = (
('percents', 20),
)
def _getsizing(self, comminfo, cash, data, isbuy):
position = self.broker.getposition(data)
if not position:
size = cash / data.close[0] * (self.p.percents / 100)
if size < 1000:
# 小於 1000 股,就不買
size = 0
else:
size = math.floor(size / 1000) * 1000
else:
size = position.size
size = int(size)
return size
class AllInBoardSizer(PercentBoardSizer):
params = (
('percents', 100),
)
在 strategy 中:
使用 cerebro:
目前看來,如果 strategy 和 cerebro 都有設定的話,會以 cerebro 為主,cerebro 有兩個方法可以設定
cerebro = bt.Cerebro()
# 預設的 sizer
cerebro.addsizer(bt.sizers.SizerFix, stake = 1000)
# 這樣就可以針對不同的 strategy 來設定不同的 sizer
idx = cerebro.addstrategy(TestStrategy)
cerebro.addsizer_byidx(idx, bt.sizers.SizerFix, stake = 5)