最近,backtrader通過實現line覆蓋來執行從 ohlc-land 逃逸,這允許重新定義整個層次結構,例如,具有僅具有 bid,ask 和 datetime lines的data feeds。
(這裡到原來的逃離OHLC土地)
這就提出了如何可視化此類數據的問題,這是以OHLC
格式(無論是a還是a bar
candlestick
)最有效地完成的。
所需步驟:
-
定義一個可以讀取給定
bid/ask
格式的Data Feed載入程式 -
確定要將值分配給哪些字段,即:
open
,high
,low
和close
(也許volume
-
確定重採樣方案
源數據(10 行買賣數據):
Date,Time,Symbol,Status,Bid,Ask,Bid Vol,Ask Vol 01/03/16,23:43:11,EUR/JPY,D,,130.520,,1000000 01/03/16,23:43:27,EUR/JPY,D,,130.520,,2000000 01/03/16,23:49:19,EUR/JPY,D,,130.510,,500000 01/03/16,23:49:22,EUR/JPY,D,,130.530,,1500000 01/03/16,23:49:25,EUR/JPY,D,,130.540,,750000 01/03/16,23:49:27,EUR/JPY,D,,130.550,,900000 01/03/16,23:51:25,EUR/JPY,D,,130.500,,1200000 01/03/16,23:52:27,EUR/JPY,D,,130.495,,1100000 01/03/16,23:53:25,EUR/JPY,D,,130.480,,600000 01/03/16,23:54:27,EUR/JPY,D,,130.470,,900000
之後:
-
讀取數據不會是一個主要問題,因為最終結果必須是OHLC,這就是內置 data feeds 解析后提供的內容。因為它是csv的另一個變體。我們甚至可以重用
GenericCSVData
現有的源。感謝上帝,它是通用的 -
每個line只有一個價格元素和一個volume元素,價格分配很清楚:將價格分配給四個價格元素,將volume分配給volume
-
當涉及到重採樣時,而不是上採樣到更大的時間範圍,關鍵將是柱的數量,即:壓縮
內置的重採樣器已經可以提供相同的時間範圍,但經過壓縮
使用以下命令將資料轉換為 OHLC 格式GenericCSVData
:
data = btfeeds.GenericCSVData( dataname=args.data, dtformat='%d/%m/%y', # tmformat='%H%M%S', # already the default value # datetime=0, # position at default time=1, # position of time open=5, # position of open high=5, low=5, close=5, volume=7, openinterest=-1, # -1 for not present timeframe=bt.TimeFrame.Ticks)
有些參數甚至不需要改變,即:
-
tmformat
:因為源中的時間已與預設格式匹配 -
datetime
:因為日期位於 csv 流中的第一個位置
其他:
-
time=1
:表示時間不在單個字段中,並且date
它具有哪個位置 -
open=5
(與high
, 、low
相同close
) :流中的哪個欄位將用作價格的來源 -
volume=7
:同上 -
openinterest=-1
:負值表示此欄位不存在
一旦數據進入板載,只需對其進行重新採樣:
cerebro.resampledata(data, timeframe=bt.TimeFrame.Ticks, compression=args.compression)
我們提供與數據相同的timeframe
數據 TimeFrame.Ticks
,以確保數據不會被上採樣。並且 從 compression
命令 line中取出 ,因此: compression=args.compression
範例執行:
$ ./bidask-to-ohlc.py --compression 2 2016-03-01 23:43:27,130.52,130.52,130.52,130.52,3000000.0 2016-03-01 23:49:22,130.51,130.53,130.53,130.53,2000000.0 2016-03-01 23:49:27,130.54,130.55,130.55,130.55,1650000.0 2016-03-01 23:52:27,130.5,130.5,130.5,130.495,2300000.0 2016-03-01 23:54:27,130.48,130.48,130.48,130.47,1500000.0
不出所料,由於2
分配給壓縮,我們已經從買入價/賣出價格式變成了OHLC格式,並從10
5
數據行變成了數據行。
同樣不足為奇的是,backtrader
它不能創造奇跡,並且壓縮因數不是原始行總數的除數,它將提供 rows / compression + 1
新的行:
$ ./bidask-to-ohlc.py --compression 3 2016-03-01 23:49:19,130.52,130.52,130.52,130.51,3500000.0 2016-03-01 23:49:27,130.53,130.55,130.55,130.55,3150000.0 2016-03-01 23:53:25,130.5,130.5,130.5,130.48,2900000.0 2016-03-01 23:54:27,130.47,130.47,130.47,130.47,900000.0
在這種情況下10 / 3 = 3.33333
,這就是傳遞行的原因 4
。
當然,現在手OHLC
裡可以繪製結果。由於數據量 low ,數據方差 low 以及 matplotlib
內部如何處理這種情況,因此圖表並不是很好。
範例代碼(包含在原始程式碼backtrader
中)
from __future__ import (absolute_import, division, print_function,) # unicode_literals) import argparse import datetime import backtrader as bt import backtrader.feeds as btfeeds class St(bt.Strategy): def next(self): print(','.join(str(x) for x in [ self.data.datetime.datetime(), self.data.open[0], self.data.high[0], self.data.high[0], self.data.close[0], self.data.volume[0]])) def runstrat(): args = parse_args() cerebro = bt.Cerebro() data = btfeeds.GenericCSVData( dataname=args.data, dtformat='%d/%m/%y', # tmformat='%H%M%S', # already the default value # datetime=0, # position at default time=1, # position of time open=5, # position of open high=5, low=5, close=5, volume=7, openinterest=-1, # -1 for not present timeframe=bt.TimeFrame.Ticks) cerebro.resampledata(data, timeframe=bt.TimeFrame.Ticks, compression=args.compression) cerebro.addstrategy(St) cerebro.run() if args.plot: cerebro.plot(style='bar') def parse_args(): parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter, description='BidAsk to OHLC') parser.add_argument('--data', required=False, default='../../datas/bidask2.csv', help='Data file to be read in') parser.add_argument('--compression', required=False, default=2, type=int, help='How much to compress the bars') parser.add_argument('--plot', required=False, action='store_true', help='Plot the vars') return parser.parse_args() if __name__ == '__main__': runstrat()