######我在resset网站上下载了2020年1月的A股主板股票日数据Excel表,是这样的
######附上我的回测代码
```python
import backtrader as bt
import backtrader.feeds as btfeeds # 导入数据模块
import pandas as pd
import datetime
import warnings
warnings.filterwarnings("ignore")
# 实例化 cerebro
cerebro = bt.Cerebro()
# 导入daily_price
dtype={'code':str,}
data= pd.read_excel(r'C:\Users\Administrator\Desktop\data\2020-1.xls',dtype={'code':str,})
daily_price = data[["date", "code", "open", "high", "low", "close", "volume","openinterest"]]
daily_price.set_index('date', inplace=True)
# 按股票代码,依次循环传入数据
for stock in daily_price['code'].unique():
# 日期对齐
data = pd.DataFrame(index=daily_price.index.unique()) # 获取回测区间内所有交易日
df = daily_price.query(f"code=='{stock}'")[['open','high','low','close','volume','openinterest']]
data_ = pd.merge(data, df, left_index=True, right_index=True, how='left')
# 缺失值处理:日期对齐时会使得有些交易日的数据为空,所以需要对缺失数据进行填充
data_.loc[:,['volume',]] = data_.loc[:,['volume']].fillna(0)
data_.loc[:,['open','high','low','close']] = data_.loc[:,['open','high','low','close']].fillna(method='pad')
data_.loc[:,['open','high','low','close']] = data_.loc[:,['open','high','low','close']].fillna(0)
# 导入数据
datafeed = btfeeds.PandasData(dataname=data_, fromdate=datetime.datetime(2020,1,1), todate=datetime.datetime(2020,1,31))
cerebro.adddata(datafeed, name=stock) # 通过 name 实现数据集与股票的一一对应
print("Done !")
class MyStrategy(bt.Strategy):
# 策略参数
params = dict(
look_back_days=2,
printlog=False
)
def __init__(self):
self.order = None
def next(self):
#计算今日涨幅,并得出股票池
long_list=[]
for data in self.datas:
if len(data)>self.p.look_back_days:
p0=data.close[0]
pn=data.close[-1]
if pn !=0:
rate = (p0-pn)/pn
else:
rate = 0
if rate>0.097:
long_list.append([data._name])
# 得到当前的账户价值
total_value = self.broker.getvalue()
p_value = total_value*0.9/10
for data in self.datas:
#获取仓位
pos = self.getposition(data).size
if not pos and data._name in long_list:
size=int(p_value/100/data.close[0])*100
price = self.data.lines.high[0]
self.buy(data = data, size = size,price = price)
if pos!=0:
if (self.data.lines.high[0]-self.data.lines.close[0])/self.data.lines.high[0]>0.05:
price = self.data.lines.close[0]
self.sell(data = data,size = pos,price = price)
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 [order.Completed]:
if order.isbuy():
self.log(f'买入:\n价格:{order.executed.price:.2f},\
成本:{order.executed.value:.2f},\
手续费:{order.executed.comm:.2f}')
self.buyprice = order.executed.price
self.buycomm = order.executed.comm
else:
self.log(f'卖出:\n价格:{order.executed.price:.2f},\
成本: {order.executed.value:.2f},\
手续费{order.executed.comm:.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}')
# 初始资金 10,000
startcash = 10000.0
cerebro.broker.setcash(startcash)
# 佣金,双边各 0.0002
cerebro.broker.setcommission(commission=0.0002)
# 滑点:双边各 0.0001
cerebro.broker.set_slippage_perc(perc=0.0001)
# 将编写的策略添加给大脑
cerebro.addstrategy(MyStrategy,printlog=True)
# 添加策略分析指标
cerebro.addanalyzer(bt.analyzers.TimeReturn, _name='pnl') # 返回收益率时序数据
cerebro.addanalyzer(bt.analyzers.AnnualReturn, _name='_AnnualReturn') # 年化收益率
cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='_SharpeRatio') # 夏普比率
cerebro.addanalyzer(bt.analyzers.DrawDown, _name='_DrawDown') # 回撤
# 添加观测器
#cerebro.addobserver(...)
# 启动回测
result = cerebro.run()
#打印结果
portvalue = cerebro.broker.getvalue()
pnl = portvalue - startcash
print(f'总资金: {round(portvalue,2)}')
print(f'净收益: {round(pnl,2)}')
# 从返回的 result 中提取回测结果
strat = result[0]
# 返回日度收益率序列
daily_return = pd.Series(strat.analyzers.pnl.get_analysis())
# 打印评价指标
print("--------------- AnnualReturn -----------------")
print(strat.analyzers._AnnualReturn.get_analysis())
print("--------------- SharpeRatio -----------------")
print(strat.analyzers._SharpeRatio.get_analysis())
print("--------------- DrawDown -----------------")
print(strat.analyzers._DrawDown.get_analysis())