時間已經過去,針對完全形成和封閉的柱線測試策略是好的,但它可能會更好。
這就是 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()