The time is gone and testing a strategy against a fully formed and closed bar is good, but it could be better.
時間一去不復返了,針對一個完全成形的封閉式bar測試一種策略是好的,但也可能更好
This is where Data Replay comes in to help. If:
這就是數據重放的作用。如果:
- The strategy operates on data with a timeframe X (example: daily)
- 該策略在一個時間框架X上操作數據(例如:每日)
and
- Data for a smaller timeframe Y (example: 1 minute) is available
操作數據和更小的時間框架Y(1分鍾)數據可用
Data replay does exactly what the name implies:
數據回放顧名思義:
- Replay a daily bar using the 1 minute data
- 用1分鍾的數據重放一天的bar
This is of course not exactly how the market developed, but it is far better than looking at the daily fully formed and closed bar in isolation:
當然,這並不完全是市場發展的方式,但它遠比孤立地觀察每日bar的收盤價要好得多:
If the strategy operates in realtime during the formation of the daily bar, the approximation of the formation of the bar gives a chance to replicate the actual behavior of the strategy under real conditions
如果策略在日條形成過程中是實時運行的,那么對條形成的近似值就有機會在實際條件下復制策略的實際行為
Putting Data Replay into action follows the regular usage patterns of backtrader
按照交易者的常規操作模式進行數據回放
-
Load a data feed
- 讀取數據傳輸
-
Pass the data to cerebro with
replaydata
- 通過replaydata將數據傳遞給cerebro
-
Add a strategy
- 添加一個策略
Note
Preloading is not supported when data is being replayed because each bar is actually built in real-time. It will automatically disabled in any Cerebro
instance.
數據回放時不支持預加載,因為每個bar實際上是實時構建的。它會在任何Cerebro
實例中自動禁用。
Parameters which can be passed to replaydata
:
可傳遞給replaydata的參數:
-
timeframe
(default: bt.TimeFrame.Days)Destination timeframe which to be useful has to be equal or larger than the source
- 目標時間框架必須等於或大於源時間框架
-
compression
(default: 1)Compress the selected value “n” to 1 bar
- 壓縮可以是1或者n
Extended parameters (do not touch if not really needed):
-
bar2edge
(default: True)replays using time boundaries as the target of the closed bar. For example with a “ticks -> 5 seconds” the resulting 5 seconds bars will be aligned to xx:00, xx:05, xx:10 …
- 使用時間邊界作為目標重新采樣。例如,對於“ticks-> 5秒”,得到的5秒bars將對齊到xx:00、xx:05、xx:10…
-
adjbartime
(default: False)Use the time at the boundary to adjust the time of the delivered resampled bar instead of the last seen timestamp. If resampling to “5 seconds” the time of the bar will be adjusted for example to hh:mm:05 even if the last seen timestamp was hh:mm:04.33
- 使用邊界處的時間來調整交付的重采樣條的時間,而不是最后看到的時間戳。如果重新采樣到“5秒”,則條的時間將調整為hh:mm:05,即使最后看到的時間戳是hh:mm:04.3
-
NOTE: Time will only be adjusted if “bar2edge” is True. It wouldn’t make sense to adjust the time if the bar has not been aligned to a boundary
- 只有當“bar2edge”正確時,時間才會調整。如果工具條沒有對齊到邊界,那么調整時間就沒有意義了
-
rightedge
(default: True)Use the right edge of the time boundaries to set the time.
- 使用時間邊界的右邊界來設置時間。
-
If False and compressing to 5 seconds the time of a resampled bar for seconds between hh:mm:00 and hh:mm:04 will be hh:mm:00 (the starting boundary
- 如果為假,壓縮到5秒,則重新采樣的時間條在hh:mm:00和hh:mm:04之間的秒將為hh:mm:00(起始邊界)
-
If True the used boundary for the time will be hh:mm:05 (the ending boundary)
- 如果為真,使用的時間邊界將是hh:mm:05(結束邊界)
For the sake of working with a example the standard 2006 daily data will be replayed on a weekly basis. Which means:
為了舉例說明,標准的2006年每日數據將每周重播一次。也就是說:
-
There will finally be 52 bars, one for each week
- 最后會有52個bars,每周一個
-
Cerebro will call
prenext
andnext
a total of 255 times, which is the original count of daily bars - Cerebro將調用prenext和next共255次,這是每日bar的原始計數
The trick:
訣竅
-
When a weekly bar is forming, the length (
len(self)
) of the strategy will remain unchanged. - 當一個周線形成時,策略的長度(len(self))將保持不變。
-
With each new week the length will increase by one
- 每過一個星期,長度就會增加一個
Some examples below, but first the sauce of the test script in which the data is loaded and passed to cerebro with replaydata
… and then run
.
下面是一些例子,但是首先是測試腳本的准備,在這個腳本中,數據被加載並用replaydata傳遞給cerebro…然后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)
Example - Replay Daily to Weekly
The invocation of the script:
$ ./replay-example.py --timeframe weekly --compression 1
The chart cannot unfortunately show us the real thing happening in the background, so let’s have a look at the console output:
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
As we see the internal self.counter
variable is keeping track of each call to either prenext
or next
. The former being called before the applied Simple Moving Average produces a value. The latter called when the Simple Moving Average is producing values.
正如我們看到的內部self.counter
變量跟蹤對prenext或next的每個調用。在應用簡單移動平均值生成值之前調用前者。后者在簡單移動平均值產生值時調用。
The key:
關鍵是:
- The length (len(self)) of the strategy changes every 5 bars (5 trading days in the week)
- 策略的長度(len(self))每5個交易日(每周5個交易日)變化一次
The strategy is effectively seeing:
該策略有效的看到:
-
How the weekly bar developed in 5 shots.
-
每周bar是如何在5次擊中發展起來的。
This, again, doesn’t replicate the actual tick-by-tick (and not even minute, hour) development of the market, but it is better than actually seeing a bar.
- 同樣,這並不能復制市場每時每刻(甚至不是每分,每小時)的發展,但這比真正的bar還好
The visual output is that of the weekly chart which is the final outcome the system is being tested again.
視覺輸出是周線圖,這是系統再次測試的最終結果。
Example 2 - Daily to Daily with Compression
Of course “Replaying” can be applied to the same timeframe but with a compression.
當然,“回放”也可以應用於同一時間段,但需要壓縮。
The console:
$ ./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
This time we got half the bars as expected because of the factor 2 requested compression.
這一次我們得到了一半的bars,因為系數2要求壓縮。
The chart:
Conclusion
A reconstruction of the market development is possible. Usually a smaller timeframe set of data is available and can be used to discretely replay the timeframe which the system operates on.
重建市場發展是可能的。通常一個較小的時間框架數據集是可用的,可以用來離散地重播系統運行的時間框架。
The test script.
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()
這里有關於Replay的相關答疑:
https://community.backtrader.com/topic/1329/how-to-determine-if-the-data-is-being-replayed-in-strategy/2
就我自己的理解,在Replay中,你在next中讀取的數據還是傳入的元素數據,但replay可以創建一些指標線。
這樣的話可以通過原始數據去處理一些跨邏輯的信號。
比較日線跳上周線的5日平均線,書中的demo也沒有具體演示功能,我覺的replay可能就這么點用?還是就畫圖用?還是誇時間區域進行操作?但說真的,跨時間區域操作有用嗎?