Backtrader知识储备
框架的概念还挺多:Cerebro,Data Feeds,Strategy,Indicators,Orders,Broker,Analyzers,Observers,Sizers。逐个来看看大概的功能和角色。对学习框架好处多多。
- Cerebro :翻译过来是大脑的意思。可以说是backtrader的基石,有点类似cpu的感觉,处理收集所有数据、运行策略,执行回溯测试,操作交易,绘图等等。
- Data Feeds:交易数据,这个没什么好说的,都是各种金融平台的交易数据,开盘价,收盘价啥的。
- Strategy:策略,根据定义的策略会处理或者说遍历数据,来判定具体的买卖等动作。
- Indicators:指标,用股市打比方,比如相对强弱指标(RSI)、随机指标(KD)、趋向指标(DMI)、平滑异同平均线(MACD)、能量潮(OBV)等等这些都已经实现好的,不用咱们自己实现,拿来使用即可。当然也支持自定义指标。
- Orders:下单员,可以理解具体交易订单执行单元,触发了对应的策略,发出订单信号,具体交给orders处理订单操作。
- Broker:经纪人,可以理解为交易所,收取手续费,管理账户资金。
- Analyzers:看样子辅助分析执行的流程,协助改进和修正问题的角色(暂且这么理解)
- Observers:看样子辅助分析执行的流程,协助改进和修正问题的角色(暂且这么理解)
- Sizers:这个比较好理解,不同的交易所,交易的单位不一样,比如,1手是100股,交易都是以100为单位。通过这个来设置交易的基本单位。
看了下官方给出的:Quickstart Guide。由于官网举得例子都是国外的数据。要是想掌握这个必须把源头先搞定,就是提供交易数据(Data Feeds ),还好官方支持按照规范自己实现自己的数据。所以还是从这里开始研究。
第一弹:Data Feeds(交易数据)
背景
因为数据的获取,我使用的是tushare。tushare返回的是pandas的dataframe格式。所以我就主攻pandas-datafeed这块。
原理
参考官方文档pandas-datafeed:
class PandasData(feed.DataBase):
'''
The ``dataname`` parameter inherited from ``feed.DataBase`` is the pandas
DataFrame
'''
params = (
# Possible values for datetime (must always be present)
# None : datetime is the "index" in the Pandas Dataframe
# -1 : autodetect position or case-wise equal name
# >= 0 : numeric index to the colum in the pandas dataframe
# string : column name (as index) in the pandas dataframe
('datetime', None),
# Possible values below:
# None : column not present
# -1 : autodetect position or case-wise equal name
# >= 0 : numeric index to the colum in the pandas dataframe
# string : column name (as index) in the pandas dataframe
('open', -1),
('high', -1),
('low', -1),
('close', -1),
('volume', -1),
('openinterest', -1),
)
PandasData类继承feed.DataBase类,初始化数据需要7列数据 分别为:datetime、open、high、low、close、volume、openinterest,其中datetime是索引列。经过实践送过去的数据按照这个顺序排列,不包含header部分即可。
实践(Data Feeds 使用pandas数据)
使用的是601668 中国建筑的股票数据,csv文件我放到github上了。可以自行去下载,按照官方文档的源码改了下数据元,正常执行。
# -*- coding: utf-8 -*-
"""
搞定自定义的数据送给backtrader
"""
#############################################################
#import
#############################################################
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import os,sys
import pandas as pd
import backtrader as bt
#############################################################
#global const values
#############################################################
#############################################################
#static function
#############################################################
#############################################################
#class
#############################################################
#############################################################
#global values
#############################################################
#############################################################
#global function
#############################################################
def G_get_dataframe():
# Get a pandas dataframe
datapath = './data/stockinfo.csv'
tmpdatapath = './data/stockinfo_tmp.csv'
print('-----------------------read csv---------------------------')
dataframe = pd.read_csv(datapath,
skiprows=0,
header=0,
parse_dates=True,
index_col=0)
print(dataframe)
print('--------------------------------------------------')
print('-----------------------change time------------------------')
dataframe.trade_date = pd.to_datetime(dataframe.trade_date, format="%Y%m%d")
print(dataframe)
print('--------------------------------------------------')
print('-----------------------add openinterest-------------------')
dataframe['openinterest'] = '0'
print(dataframe)
print('--------------------------------------------------')
print('-----------------------make feedsdf-----------------------')
feedsdf = dataframe[['trade_date', 'open', 'high', 'low', 'close', 'vol', 'openinterest']]
print(feedsdf)
print('--------------------------------------------------')
print('-----------------------change columns---------------------')
feedsdf.columns =['datetime', 'open', 'high', 'low', 'close', 'volume', 'openinterest']
print(feedsdf)
print('--------------------------------------------------')
print('-----------------------change index-----------------------')
feedsdf.set_index(keys='datetime', inplace =True)
print(feedsdf)
print('--------------------------------------------------')
feedsdf.iloc[::-1].to_csv(tmpdatapath)
feedsdf = pd.read_csv(tmpdatapath, skiprows=0, header=0, parse_dates=True, index_col=0)
if os.path.isfile(tmpdatapath):
os.remove(tmpdatapath)
print(tmpdatapath+" removed!")
return feedsdf
########################################################################
#main
########################################################################
if __name__ == '__main__':
# Create a cerebro entity
cerebro = bt.Cerebro(stdstats=False)
# Add a strategy
cerebro.addstrategy(bt.Strategy)
# Get a pandas dataframe
feedsdf = G_get_dataframe()
# Pass it to the backtrader datafeed and add it to the cerebro
data = bt.feeds.PandasData(dataname=feedsdf)
print(data)
cerebro.adddata(data)
# Run over everything
cerebro.run()
# Plot the result
cerebro.plot(style='bar')
输出图形
源码:
qtbt