有時投資決策是使用不同的時間框架做出的:
-
每周評估趨勢
-
每天執行條目
或者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()