最近,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格式,并从105数据行变成了数据行。
同样不足为奇的是,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()