時間已經過去,針對完全形成和封閉的柱線測試策略是好的,但它可能會更好。
這就是 Data Replay 的用武之地。如果:
- 該策略對時間範圍 X 的數據進行操作(例如:每日)
和
- 更小時間範圍 Y(例如:1 分鐘)的數據可用
數據重放正如其名稱所暗示的那樣:
- 使用 1 分鐘數據重播每日柱
這當然不完全是市場的發展方式,但它比孤立地查看每日完全形成和封閉的柱線要好得多:
如果策略在每日柱形的形成過程中實時運行,則柱形的近似值提供了在真實條件下複製策略的實際行為的機會
將數據重放付諸行動遵循backtrader
的常規使用模式
加載數據饋送
使用
replaydata
將數據傳遞給cerebro添加策略
筆記
重播數據時不支持預加載,因為每個條實際上都是實時構建的。它會在任何Cerebro
實例中自動禁用。
可以傳遞給replaydata
的參數:
timeframe
(默認:bt.TimeFrame.Days)有用的目標時間範圍必須等於或大於源
compression
(默認值:1)將所選值“n”壓縮為 1 bar
擴展參數(如果不是真的需要,請勿觸摸):
bar2edge
(默認值: True )使用時間邊界作為封閉柱的目標重播。例如,使用“ticks -> 5 seconds”,生成的 5 秒條將對齊到 xx:00、xx:05、xx:10 …
adjbartime
(默認值: False )使用邊界處的時間來調整交付的重採樣柱的時間,而不是最後看到的時間戳。如果重新採樣到“5 秒”,則柱的時間將調整為例如 hh:mm:05,即使最後看到的時間戳是 hh:mm:04.33
注意:僅當“bar2edge”為True時才會調整時間。如果條未與邊界對齊,則調整時間沒有意義
rightedge
(默認值: True )使用時間邊界的右邊緣設置時間。
如果False並壓縮到 5 秒,則在 hh:mm:00 和 hh:mm:04 之間重新採樣的條形的時間將是 hh:mm:00(起始邊界
如果為True ,則使用的時間邊界將是 hh:mm:05(結束邊界)
為了使用示例,將每週重播標準的 2006 年每日數據。意思是:
最終將有 52 個酒吧,每週一個
Cerebro將調用
prenext
和next
共 255 次,這是每日柱的原始計數
訣竅:
當周柱形成時,策略的長度 (
len(self)
) 將保持不變。每個新的一周,長度將增加一
下面是一些示例,但首先是測試腳本的調味汁,其中數據被加載並使用replaydata
......然後run
.
# Load the Data datapath = args.dataname or '../../datas/2006-day-001.txt' data = btfeeds.BacktraderCSVData(dataname=datapath) # Handy dictionary for the argument timeframe conversion tframes = dict( daily=bt.TimeFrame.Days, weekly=bt.TimeFrame.Weeks, monthly=bt.TimeFrame.Months) # First add the original data - smaller timeframe cerebro.replaydata(data, timeframe=tframes[args.timeframe], compression=args.compression)
示例 - 每天到每週重播
腳本的調用:
$ ./replay-example.py --timeframe weekly --compression 1
不幸的是,圖表無法向我們展示後台發生的真實情況,所以讓我們看一下控制台輸出:
prenext len 1 - counter 1 prenext len 1 - counter 2 prenext len 1 - counter 3 prenext len 1 - counter 4 prenext len 1 - counter 5 prenext len 2 - counter 6 ... ... prenext len 9 - counter 44 prenext len 9 - counter 45 ---next len 10 - counter 46 ---next len 10 - counter 47 ---next len 10 - counter 48 ---next len 10 - counter 49 ---next len 10 - counter 50 ---next len 11 - counter 51 ---next len 11 - counter 52 ---next len 11 - counter 53 ... ... ---next len 51 - counter 248 ---next len 51 - counter 249 ---next len 51 - counter 250 ---next len 51 - counter 251 ---next len 51 - counter 252 ---next len 52 - counter 253 ---next len 52 - counter 254 ---next len 52 - counter 255
正如我們所見,內部self.counter
變量正在跟踪對prenext
或next
的每次調用。前者在應用的簡單移動平均線產生一個值之前被調用。後者在簡單移動平均線產生值時調用。
鑰匙:
- 策略的長度 (len(self)) 每 5 個柱變化一次(一周中的 5 個交易日)
該策略有效地看到:
每週欄如何在 5 次拍攝中發展。
同樣,這並不能複制市場的實際逐筆交易(甚至不是一分鐘、一小時)的發展,但它比實際看到一根柱線要好。
視覺輸出是每週圖表的輸出,這是系統再次測試的最終結果。
示例 2 - 每天到每天都有壓縮
當然,“重播”可以應用於相同的時間範圍,但需要進行壓縮。
控制台:
$ ./replay-example.py --timeframe daily --compression 2 prenext len 1 - counter 1 prenext len 1 - counter 2 prenext len 2 - counter 3 prenext len 2 - counter 4 prenext len 3 - counter 5 prenext len 3 - counter 6 prenext len 4 - counter 7 ... ... ---next len 125 - counter 250 ---next len 126 - counter 251 ---next len 126 - counter 252 ---next len 127 - counter 253 ---next len 127 - counter 254 ---next len 128 - counter 255
這次我們得到了預期的一半,因為因素 2 要求壓縮。
圖表:
結論
重建市場發展是可能的。通常可以使用較小的時間範圍數據集,並可用於離散地重放系統運行的時間範圍。
測試腳本。
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 = btind.SMA(self.data, period=self.p.period) def start(self): self.counter = 0 def prenext(self): self.counter += 1 print('prenext len %d - counter %d' % (len(self), self.counter)) def next(self): self.counter += 1 print('---next len %d - counter %d' % (len(self), self.counter)) def runstrat(): args = parse_args() # Create a cerebro entity cerebro = bt.Cerebro(stdstats=False) cerebro.addstrategy( SMAStrategy, # args for the strategy period=args.period, ) # Load the Data datapath = args.dataname or '../../datas/2006-day-001.txt' data = btfeeds.BacktraderCSVData(dataname=datapath) # Handy dictionary for the argument timeframe conversion tframes = dict( daily=bt.TimeFrame.Days, weekly=bt.TimeFrame.Weeks, monthly=bt.TimeFrame.Months) # First add the original data - smaller timeframe cerebro.replaydata(data, timeframe=tframes[args.timeframe], compression=args.compression) # 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('--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('--period', default=10, required=False, type=int, help='Period to apply to indicator') return parser.parse_args() if __name__ == '__main__': runstrat()