有時投資決策是使用不同的時間框架做出的:
-
每周評估趨勢
-
每天執行條目
或者5分鐘對60分鐘。
這意味著需要將多個時間幀的數據組合在 backtrader 中以支援此類組合。
對它的本機支持已經內置。最終使用者只能遵循以下規則:
-
具有最小時間幀(因此柱數較大的數據)必須是要添加到Cerebro實例中的第1個數據
-
數據必須正確對齊日期時間,以便平臺從中產生任何意義
除此之外,最終使用者可以自由地在較短/較長的時間範圍內按預期應用指標。答案是肯定的:
- 應用於較大時間幀的指標將產生較少的柱線
該平臺還將考慮以下因素
- 較大時間幀的最小週期
最小週期,這可能會產生副作用,即在將策略添加到 Cerebro 開始行動之前,必須消耗幾個數量級的較小時間幀柱。
內置DataResampler
的將用於創建更大的時間範圍。
下面是一些示例,但首先是測試腳本的醬汁。
# Load the Data datapath = args.dataname or '../datas/sample/2006-day-001.txt' data = btfeeds.BacktraderCSVData( dataname=datapath) tframes = dict( daily=bt.TimeFrame.Days, weekly=bt.TimeFrame.Weeks, monthly=bt.TimeFrame.Months) # Handy dictionary for the argument timeframe conversion # Resample the data if args.noresample: datapath = args.dataname2 or '../datas/sample/2006-week-001.txt' data2 = btfeeds.BacktraderCSVData( dataname=datapath) else: data2 = bt.DataResampler( dataname=data, timeframe=tframes[args.timeframe], compression=args.compression)
步驟:
-
載入數據
-
根據使用者指定的參數對其進行重新採樣
該腳本還允許載入第 2 個 數據
-
將資料新增到 cerebro
-
將重新採樣的數據(更大的時間幀)添加到 cerebro
-
跑
示例 1 - 每日和每周
文稿的呼叫:
$ ./data-multitimeframe.py --timeframe weekly --compression 1
和輸出圖表:
範例 2 - 每日和每日壓縮(2 個 bar 到 1)
文稿的呼叫:
$ ./data-multitimeframe.py --timeframe daily --compression 2
和輸出圖表:
範例 3 - 使用 SMA 的策略
雖然繪圖很好,但這裡的關鍵問題是顯示更大的時間框架如何影響系統,特別是當它歸結為起點時。
該腳本可以添加--indicators
一個策略,該策略在較小和較大的時間幀數據上創建 週期為10 的簡單移動平均線。
如果只考慮較小的時間範圍:
-
next
將在10根柱線後首先調用,這是簡單移動平均線產生值所需的時間注意
請記住,Strategy 監控已創建的指標,並且僅在所有指標都生成值時才調用
next
。基本原理是最終使用者已添加指標以在邏輯中使用它們,因此,如果指標未生成任何值,則不應發生任何邏輯。
但是在這種情況下,較大的時間幀(每周)延遲調用next
,直到每周數據產生一個值的簡單移動平均線,這需要...10周。
該腳本將nextstart
覆蓋僅調用一次且預設為調用 next
以顯示首次調用時的腳本。
呼叫 1:
只有較小的時間幀,每天,得到一個簡單的移動平均線
命令 line 和輸出
$ ./data-multitimeframe.py --timeframe weekly --compression 1 --indicators --onlydaily -------------------------------------------------- nextstart called with len 10 --------------------------------------------------
和圖表。
呼叫 2:
兩個時間幀都得到一個簡單的移動平均線
命令 line:
$ ./data-multitimeframe.py --timeframe weekly --compression 1 --indicators -------------------------------------------------- nextstart called with len 50 -------------------------------------------------- -------------------------------------------------- nextstart called with len 51 -------------------------------------------------- -------------------------------------------------- nextstart called with len 52 -------------------------------------------------- -------------------------------------------------- nextstart called with len 53 -------------------------------------------------- -------------------------------------------------- nextstart called with len 54 --------------------------------------------------
這裡要注意兩件事:
-
該策略不是在10 個週期后調用,而是在50個週期后調用1st 。
之所以如此,是因為應用於較大(每周)時間幀的簡單移動平均線在10周後產生一個值......那就是10周* 5天/周...50 天
-
nextstart
被調用 5 次,而不僅僅是 1 次。這是混合時間幀並將指標(在本例中只有一個)應用於較大時間幀的自然副作用。
較大的時間幀簡單移動平均線產生相同值的 5 倍,而 5 個日柱線被消耗。
而且由於周期的開始被較大的時間幀
nextstart
控制,因此被調用了5次。
和圖表。
結論
多個時間幀數據可以在沒有特殊物件或調整的情況下使用backtrader
:只需先添加較小的時間幀即可。
測試腳本。
from __future__ import (absolute_import, division, print_function, unicode_literals) import argparse import backtrader as bt import backtrader.feeds as btfeeds import backtrader.indicators as btind class SMAStrategy(bt.Strategy): params = ( ('period', 10), ('onlydaily', False), ) def __init__(self): self.sma_small_tf = btind.SMA(self.data, period=self.p.period) if not self.p.onlydaily: self.sma_large_tf = btind.SMA(self.data1, period=self.p.period) def nextstart(self): print('--------------------------------------------------') print('nextstart called with len', len(self)) print('--------------------------------------------------') super(SMAStrategy, self).nextstart() def runstrat(): args = parse_args() # Create a cerebro entity cerebro = bt.Cerebro(stdstats=False) # Add a strategy if not args.indicators: cerebro.addstrategy(bt.Strategy) else: cerebro.addstrategy( SMAStrategy, # args for the strategy period=args.period, onlydaily=args.onlydaily, ) # Load the Data datapath = args.dataname or '../datas/sample/2006-day-001.txt' data = btfeeds.BacktraderCSVData( dataname=datapath) tframes = dict( daily=bt.TimeFrame.Days, weekly=bt.TimeFrame.Weeks, monthly=bt.TimeFrame.Months) # Handy dictionary for the argument timeframe conversion # Resample the data if args.noresample: datapath = args.dataname2 or '../datas/sample/2006-week-001.txt' data2 = btfeeds.BacktraderCSVData( dataname=datapath) else: data2 = bt.DataResampler( dataname=data, timeframe=tframes[args.timeframe], compression=args.compression) # First add the original data - smaller timeframe cerebro.adddata(data) # And then the large timeframe cerebro.adddata(data2) # Run over everything cerebro.run() # Plot the result cerebro.plot(style='bar') def parse_args(): parser = argparse.ArgumentParser( description='Pandas test script') parser.add_argument('--dataname', default='', required=False, help='File Data to Load') parser.add_argument('--dataname2', default='', required=False, help='Larger timeframe file to load') parser.add_argument('--noresample', action='store_true', help='Do not resample, rather load larger timeframe') parser.add_argument('--timeframe', default='weekly', required=False, choices=['daily', 'weekly', 'monhtly'], help='Timeframe to resample to') parser.add_argument('--compression', default=1, required=False, type=int, help='Compress n bars into 1') parser.add_argument('--indicators', action='store_true', help='Wether to apply Strategy with indicators') parser.add_argument('--onlydaily', action='store_true', help='Indicator only to be applied to daily timeframe') parser.add_argument('--period', default=10, required=False, type=int, help='Period to apply to indicator') return parser.parse_args() if __name__ == '__main__': runstrat()