失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 量化交易6-backtrader编写策略的时数据获取

量化交易6-backtrader编写策略的时数据获取

时间:2020-06-12 10:05:15

相关推荐

量化交易6-backtrader编写策略的时数据获取

上一篇文章讲到了均线的指标的运用,策略是比较简单的策略,就是使用5日均线和10均线的价格做比较,然后进行全仓的买卖,本文会继续沿用上文所使用的策略。不同的是,本文笔者会较为详细的介绍,编写策略过程中,数据的获取方式,比如指标的定义方式,backtrader而言,指标有两种方式,一种是backtrader本身就支持的定义好的指标,比如5日或者10均线,具体backtrader支持了多少指标后续笔者会为大家继续整理,另一种就是自定义指标。

以编写5日均线对比10日均线而言,编写策略中所需要的常用数据做个简单的介绍:

# 初始化时

设置初始资金,cerebro.broker.setcash( 100000000.0)

# 策略中调用

获取当前可用资金,cerebro.broker.getcash()

self.dataclose[0] # 当日的收盘价

self.dataclose[-1] # 昨天的收盘价

self.dataclose[-2] # 前天的收盘价

当前总资产self.broker.getvalue

当前持仓量, self.getposition(self.data).size

当前持仓成本, self.getposition(self.data).price

Broker 在每次交易后更新 cash 外,还会同时更新当前总资产 value 和当前持仓 position,通常在 Strategy 中调用上述方法进行查询

指标数据使用:

均线是backtrader本身就支持的指标:

# 策略参数

params = dict(

period5=5, # 5均线周期

period10=10, # 10均线周期

look_back_days=30,

printlog=False

)

self.mas[data._id] = bt.ind.SMA(data.close, period=self.p.period5) #5日均线

self.mas10[data._id] = bt.ind.SMA(data.close, period=self.p.period10) #10日均线

其中bt.ind.SMA是backtrader就已经定义好的均线的获取方式,backtrader支持的更多的指标请读者自行在backtrader查看,关于如果自定义指标,后续笔者会继续为大家整理。

通过上述的数据就能够获取指标,然后结合之前的策略构建步骤,就能实现策略:5日均线高于10均,全仓买入,反之全仓卖出。

代码如下:

import tushare as ts

import pandas as pd

import datetime # For datetime objects

import os.path # To manage paths

import sys # To find out the script name (in argv[0])

# Import the backtrader platform

import backtrader as bt

class MyStrategy(bt.Strategy):

# 策略参数

params = dict(

period5=5, # 5均线周期

period10=10, # 10均线周期

look_back_days=30,

printlog=False

)

def __init__(self):

self.mas = dict()

self.mas10 = dict()

# 遍历所有股票,计算20日均线

for data in self.datas:

self.mas[data._id] = bt.ind.SMA(data.close, period=self.p.period5)

self.mas10[data._id] = bt.ind.SMA(data.close, period=self.p.period10)

def next(self):

# 得到当前的账户价值

total_value = self.broker.getcash()

print('剩余的资金->' + str(total_value))

for data in self.datas:

# 获取仓位

pos = self.getposition(data).size

if self.mas10[data._id][0] < self.mas[data._id][0]:

p_value = total_value * 0.9 / 10

size = ((int(total_value / self.data.close[0]))) - ((int(total_value / self.data.close[0])) % 100) - 100

print('10日均线价格->' + str(self.mas10[data._id][0]) + ',5日均线价格->' + str(self.mas[data._id][0]) + \

',持仓数量->' + str(pos) + ',买入数量->' + str(size))

self.buy(data=data, size=size)

if pos > 0 and self.mas10[data._id][0] > self.mas[data._id][0]:

print('10日均线价格->' + str(self.mas10[data._id][0]) + ',5日均线价格->' + str(self.mas[data._id][0]) + \

',持仓数量->' + str(pos) + ',卖出数量->' + str(pos))

self.order = self.sell(data=data, size=pos)

def log(self, txt, dt=None, doprint=False):

if self.params.printlog or doprint:

dt = dt or self.datas[0].datetime.date(0)

print(f'{dt.isoformat()},{txt}')

# 记录交易执行情况(可省略,默认不输出结果)

def notify_order(self, order):

# 如果order为submitted/accepted,返回空

if order.status in [order.Submitted, order.Accepted]:

return

# 如果order为buy/sell executed,报告价格结果

if order.status in [pleted]:

if order.isbuy():

self.log(f'买入:\n价格:{order.executed.price:.2f},\

成本:{order.executed.value:.2f},\

数量:{order.executed.size:.2f},\

手续费:{m:.2f}')

self.buyprice = order.executed.price

self.buycomm = m

else:

self.log(f'卖出:\n价格:{order.executed.price:.2f},\

成本: {order.executed.value:.2f},\

数量:{order.executed.size:.2f},\

手续费{m:.2f}')

self.bar_executed = len(self)

# 如果指令取消/交易失败, 报告结果

elif order.status in [order.Canceled, order.Margin, order.Rejected]:

self.log('交易失败')

self.order = None

# 记录交易收益情况(可省略,默认不输出结果)

def notify_trade(self, trade):

if not trade.isclosed:

return

self.log(f'策略收益:\n毛收益 {trade.pnl:.2f}, 净收益 {trade.pnlcomm:.2f}')

pro = ts.pro_api('cbb257058b7cb228769b4949437c27c27e5132e882747dc80f01a5a5')

def ts_get_daily_stock(code, start_dt, end_dt):

start_dt = start_dt.replace("'", "", 3);

end_dt = end_dt.replace("'", "", 3);

# start_dt = '0101'

# end_dt=''

print(code, start_dt, end_dt)

data = pro.daily(ts_code=code, start_date=start_dt, end_date=end_dt)

data['trade_date'] = pd.to_datetime(data['trade_date'])

data['trade_date'] = pd.to_datetime(data['trade_date'])

data = data.sort_values(by='trade_date')

data.index = data['trade_date']

data['openinterest'] = 0

data['volume'] = data['vol']

data = data[

['open', 'close', 'high', 'low', 'volume']

]

return data

# 读取选股的结果

df = pd.read_csv('stock_alpha.csv')

df.columns = ['ts_code', 'name', 'alpha', 'start_dt', 'end_dt']

min_a = df.sort_values(by='alpha')

min_a = min_a.iloc[:10, :]

code = []

code = min_a['ts_code'] # 股票代码

start_dts = []

start_dts = min_a['start_dt'] # 股票代码起始时间

end_dts = []

end_dts = min_a['end_dt'] # 股票代码结束时间

for i in range(len(code)):

data = ts_get_daily_stock(code.iloc[i], start_dts.iloc[i], end_dts.iloc[i]) # 字段分别为股票代码、开始日期、结束日期

data.to_csv(code.iloc[i] + '.csv')

cerebro = bt.Cerebro()

for i in range(len(code)): # 循环获取股票历史数据

dataframe = pd.read_csv(code.iloc[i] + '.csv', index_col=0, parse_dates=True)

dataframe['openinterest'] = 0

data = bt.feeds.PandasData(dataname=dataframe,

fromdate=datetime.datetime(, 8, 18),

todate=datetime.datetime(, 3, 22)

)

cerebro.adddata(data)

# 回测设置

startcash = 100000.0

cerebro.broker.setcash(startcash)

# 设置佣金为千分之一

cerebro.broker.setcommission(commission=0.001)

# 添加策略

cerebro.addstrategy(MyStrategy, printlog=True)

cerebro.run()

# 获取回测结束后的总资金

portvalue = cerebro.broker.getvalue()

pnl = portvalue - startcash

# 打印结果

print(f'总资金: {round(portvalue,2)}')

print(f'净收益: {round(pnl,2)}')

cerebro.plot()

其中用到的csv文件还是从上一章的地址获取

结果为:

总资金: 136632.34

净收益: 36632.34

执行图为:

如果觉得《量化交易6-backtrader编写策略的时数据获取》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。