前言:
在前面学了点机器学习知识后,发现自己还没有一个回测框架,找了短时间学习资料,还是决定使用backtrader,至于聚宽优米那些平台感觉使用起来好像没那么自由,还是先学习下backtrader,学完后再把自己学到的知识理顺下,然后再整理个符合自己使用的框架来,东学西学,学得越多就越乱,得重新审视下自己的需求。以下是我学习backtrader的一些笔记,主要是直接拿tushaer的数据来用,就不用先本地CSV数据化了,方便快捷,代码如下:
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import datetime
import pandas as pd
import backtrader as bt
import tushare as ts
import numpy as np
# 创建策略类
class TestStrategy(bt.Strategy):
# 设置简单均线周期,以备后面调用
params = (
('maperiod21', 21),
('maperiod55', 55)
)
def log(self, txt, dt=None):
# 日记记录输出
dt = dt or self.datas[0].datetime.date(0)
print('%s, %s' % (dt.isoformat(), txt))
def __init__(self):
# 初始化数据参数
# 设置当前收盘价为dataclose
self.dataclose = self.datas[0].close
self.order = None
self.buyprice = None
self.buycomm = None
# 添加简单均线
self.sma21 = bt.indicators.SimpleMovingAverage(
self.datas[0], period=self.params.maperiod21)
self.sma55 = bt.indicators.SimpleMovingAverage(
self.datas[0], period=self.params.maperiod55)
def notify_order(self, order):
if order.status in [order.Submitted, order.Accepted]:
# 如果有订单提交或者已经接受的订单,返回退出
return
# 主要是检查有没有成交的订单,如果有则日志记录输出价格,金额,手续费。注意,如果资金不足是不会成交订单的
if order.status in [order.Completed]:
if order.isbuy():
self.log(
'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
(order.executed.price,
order.executed.value,
order.executed.comm))
self.buyprice = order.executed.price
self.buycomm = order.executed.comm
else: # Sell
self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
(order.executed.price,
order.executed.value,
order.executed.comm))
# len(self)是指获取截至当前数据一共有多少根bar
# 以下代码就是指当交易发生时立刻记录下了当天有多少根bar
# 如果要表示当成交后过了5天卖,则可以这样写 if len(self) >= (self.bar_executed + 5):
self.bar_executed = len(self)
elif order.status in [order.Canceled, order.Margin, order.Rejected]:
self.log('Order Canceled/Margin/Rejected')
self.order = None
def notify_trade(self, trade):
if not trade.isclosed: # 如果交易还没有关闭,则退出不输出显示盈利跟手续费
return
self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
(trade.pnl, trade.pnlcomm))
def next(self):
# 输出显示收盘价
self.log('Close, %.2f' % self.dataclose[0])
# 检查是否有订单发送当中,如果有则不再发送第二个订单
if self.order:
return
# 检查是否已经有仓位
if not self.position:
# 如果没有则可以执行一下策略了
if self.sma21[0] > self.sma55[0]:
# 记录输出买入价格
self.log('BUY CREATE, %.2f' % self.dataclose[0])
# 跟踪已经创建好的订单避免重复第二次交易
self.order = self.buy()
else:
if self.sma21[0] < self.sma55[0]:
self.log('SELL CREATE, %.2f' % self.dataclose[0])
self.order = self.sell()
if __name__ == '__main__':
# 创建策略容器
cerebro = bt.Cerebro()
# 添加自定义的策略TestStrategy
cerebro.addstrategy(TestStrategy)
pro = ts.pro_api('要到tushare官网注册个账户然后将token复制到这里,可以的话请帮个忙用文章末我分享的链接注册,谢谢')
stock_code = '000001.SZ'
df = pro.daily(ts_code=stock_code, start_date='20200101', end_date='20200828')
df['trade_date'] = pd.to_datetime(df['trade_date'])
# df = df.drop(['change', 'pre_close', 'pct_chg', 'amount'], axis=1)
df = df.rename(columns={'vol': 'volume'})
df.set_index('trade_date', inplace=True) # 设置索引覆盖原来的数据
df = df.sort_index(ascending=True) # 将时间顺序升序,符合时间序列
dataframe = df
dataframe['openinterest'] = 0
data = bt.feeds.PandasData(dataname=dataframe,
fromdate=datetime.datetime(2020, 1, 1),
todate=datetime.datetime(2020, 8, 20)
)
# 添加数据
cerebro.adddata(data)
# 设置资金
cerebro.broker.setcash(10000.0)
# 设置每笔交易交易的股票数量
cerebro.addsizer(bt.sizers.FixedSize, stake=100)
# 设置手续费
cerebro.broker.setcommission(commission=0.01)
# 输出初始资金
print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
# 运行策略
cerebro.run()
# 输出结果
print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
cerebro.plot()
tushare注册链接:link